{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ticket-tier-select",
  "version": "4.1.0",
  "category": "events",
  "meta": {
    "preview": "https://ui.manifest.build/previews/ticket-tier-select.png",
    "version": "4.1.0",
    "changelog": {
      "1.0.0": "Initial release with ticket tier cards, quantity controls, price breakdown, and order summary sidebar",
      "1.1.0": "Added optional event image above order summary. Order summary now always visible with fixed width.",
      "2.0.0": "BREAKING: Refactored to use nested event object (event.title, event.date, event.image, event.currency) instead of flat props",
      "2.0.2": "Added comprehensive JSDoc documentation",
      "2.0.3": "Updated Props interface with decorative header and sub-parameter JSDoc documentation",
      "3.0.0": "BREAKING: Removed id from TicketTier interface, made name and price optional.",
      "3.0.1": "Simplified TicketSelection interface by removing tierIndex",
      "4.0.0": "BREAKING: Removed onSelectionChange action. Tier quantity changes are now internal.",
      "4.0.1": "Removed default content data - component only renders explicitly provided data",
      "4.1.0": "Added demo data defaults - component renders demo content when no data prop is provided"
    }
  },
  "changelog": {
    "1.0.0": "Initial release with ticket tier cards, quantity controls, price breakdown, and order summary sidebar",
    "1.1.0": "Added optional event image above order summary. Order summary now always visible with fixed width.",
    "2.0.0": "BREAKING: Refactored to use nested event object (event.title, event.date, event.image, event.currency) instead of flat props",
    "2.0.2": "Added comprehensive JSDoc documentation",
    "2.0.3": "Updated Props interface with decorative header and sub-parameter JSDoc documentation",
    "3.0.0": "BREAKING: Removed id from TicketTier interface, made name and price optional.",
    "3.0.1": "Simplified TicketSelection interface by removing tierIndex",
    "4.0.0": "BREAKING: Removed onSelectionChange action. Tier quantity changes are now internal.",
    "4.0.1": "Removed default content data - component only renders explicitly provided data",
    "4.1.0": "Added demo data defaults - component renders demo content when no data prop is provided"
  },
  "title": "Ticket Tier Select",
  "author": "MNFST, Inc",
  "description": "Ticket tier selection with quantity controls and order summary. Shows price breakdown with fees.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "button"
  ],
  "files": [
    {
      "path": "registry/events/ticket-tier-select.tsx",
      "content": "'use client'\n\nimport { Button } from '@/components/ui/button'\nimport { cn } from '@/lib/utils'\nimport { Minus, Plus, Info } from 'lucide-react'\nimport { useState } from 'react'\nimport { demoTicketTiers } from './demo/events'\n\n/**\n * Formats a currency amount.\n * @param {number} amount - Amount to format\n * @param {string} currency - Currency code\n * @returns {string} Formatted currency string\n */\nfunction formatCurrency(amount: number, currency: string = 'USD'): string {\n  return new Intl.NumberFormat('en-US', {\n    style: 'currency',\n    currency,\n    minimumFractionDigits: 2\n  }).format(amount)\n}\n\n/**\n * Represents a ticket tier option.\n * @interface TicketTier\n * @property {string} [name] - Tier name (e.g., \"General Admission\", \"VIP\")\n * @property {number} [price] - Base price\n * @property {number} [fee] - Service fee\n * @property {number} [available] - Number available\n * @property {string} [salesEndDate] - When sales end\n * @property {string} [description] - Tier description\n * @property {number} [maxPerOrder] - Maximum tickets per order\n */\nexport interface TicketTier {\n  name?: string\n  price?: number\n  fee?: number\n  available?: number\n  salesEndDate?: string\n  description?: string\n  maxPerOrder?: number\n}\n\n/**\n * Represents a selected ticket with quantity.\n * @interface TicketSelection\n * @property {string} tierName - Tier name for display\n * @property {number} quantity - Number of tickets\n * @property {number} price - Base price per ticket\n * @property {number} fee - Fee per ticket\n */\nexport interface TicketSelection {\n  tierName?: string\n  quantity: number\n  price?: number\n  fee?: number\n}\n\nexport interface TicketTierEvent {\n  title?: string\n  date?: string\n  image?: string\n  currency?: string\n}\n\n/**\n * ═══════════════════════════════════════════════════════════════════════════\n * TicketTierSelectProps\n * ═══════════════════════════════════════════════════════════════════════════\n *\n * Props for the TicketTierSelect component. Allows selection of multiple\n * ticket tiers with quantity pickers and displays an order summary.\n */\nexport interface TicketTierSelectProps {\n  data?: {\n    /** Event information including title, date, and currency. */\n    event?: TicketTierEvent\n    /** Available ticket tiers with pricing and availability. */\n    tiers?: TicketTier[]\n  }\n  actions?: {\n    /** Called when checkout button is clicked with selections and total. */\n    onCheckout?: (selections: TicketSelection[], total: number) => void\n  }\n  appearance?: {\n    /**\n     * Whether to show the order summary sidebar.\n     * @default true\n     */\n    showOrderSummary?: boolean\n  }\n  control?: {\n    /** Initial ticket selections as a map of tier index to quantity. */\n    selections?: Record<number, number>\n  }\n}\n\n/**\n * A ticket tier selection component with quantity pickers and order summary.\n * Allows users to select quantities for multiple ticket tiers.\n *\n * Features:\n * - Multiple tier selection with quantities\n * - Price and fee breakdown\n * - Sales end date display\n * - Tier descriptions\n * - Order summary sidebar\n * - Checkout button\n *\n * @component\n * @example\n * ```tsx\n * <TicketTierSelect\n *   data={{\n *     event: {\n *       title: \"Concert Night\",\n *       date: \"Friday, Feb 6 · 8pm\",\n *       currency: \"USD\"\n *     },\n *     tiers: [\n *       { name: \"General Admission\", price: 45, fee: 5, available: 100 },\n *       { name: \"VIP\", price: 120, fee: 10, available: 50 }\n *     ]\n *   }}\n *   actions={{\n *     onCheckout: (selections, total) => console.log(\"Checkout:\", total),\n *     onSelectionChange: (selections) => console.log(\"Selections:\", selections)\n *   }}\n *   appearance={{ showOrderSummary: true }}\n * />\n * ```\n */\nexport function TicketTierSelect({ data, actions, appearance, control }: TicketTierSelectProps) {\n  const resolved: NonNullable<TicketTierSelectProps['data']> = data ?? { tiers: demoTicketTiers }\n  const event = resolved.event\n  const tiers = resolved.tiers ?? []\n  const currency = event?.currency ?? 'USD'\n  const { onCheckout } = actions ?? {}\n  const { showOrderSummary = true } = appearance ?? {}\n\n  const [selections, setSelections] = useState<Record<number, number>>(\n    control?.selections ?? {}\n  )\n\n  const updateQuantity = (tierIndex: number, delta: number) => {\n    const tier = tiers[tierIndex]\n    if (!tier) return\n\n    const currentQty = selections[tierIndex] || 0\n    const newQty = Math.max(0, Math.min(currentQty + delta, tier.maxPerOrder ?? 10, tier.available ?? 100))\n\n    const newSelections = { ...selections, [tierIndex]: newQty }\n    if (newQty === 0) {\n      delete newSelections[tierIndex]\n    }\n    setSelections(newSelections)\n  }\n\n  const getSelectionsList = (sels: Record<number, number> = selections): TicketSelection[] => {\n    return Object.entries(sels)\n      .filter(([_, qty]) => qty > 0)\n      .map(([indexStr, qty]) => {\n        const tierIndex = parseInt(indexStr, 10)\n        const tier = tiers[tierIndex]\n        return {\n          tierName: tier?.name,\n          quantity: qty,\n          price: tier?.price,\n          fee: tier?.fee ?? 0\n        }\n      })\n  }\n\n  const selectionsList = getSelectionsList()\n  const hasSelections = selectionsList.length > 0\n\n  const subtotal = selectionsList.reduce((sum, s) => sum + (s.price ?? 0) * s.quantity, 0)\n  const totalFees = selectionsList.reduce((sum, s) => sum + (s.fee ?? 0) * s.quantity, 0)\n  const total = subtotal + totalFees\n\n  const handleCheckout = () => {\n    onCheckout?.(selectionsList, total)\n  }\n\n  return (\n    <div className=\"rounded-xl border bg-card p-6\">\n      <div className=\"flex flex-col lg:flex-row gap-6\">\n        {/* Left side - Tier selection */}\n        <div className=\"flex-1\">\n        {/* Header */}\n        {(event?.title || event?.date) && (\n          <div className=\"text-center mb-6\">\n            {event?.title && <h2 className=\"text-xl font-semibold\">{event.title}</h2>}\n            {event?.date && <p className=\"text-sm text-muted-foreground mt-1\">{event.date}</p>}\n          </div>\n        )}\n\n        {/* Tiers */}\n        <div className=\"space-y-4\">\n          {tiers.map((tier, index) => {\n            const qty = selections[index] || 0\n            const isSelected = qty > 0\n            const totalPrice = (tier.price ?? 0) + (tier.fee ?? 0)\n\n            return (\n              <div\n                key={index}\n                className={cn(\n                  'rounded-lg border p-4 transition-colors',\n                  isSelected && 'border-primary ring-1 ring-primary'\n                )}\n              >\n                {/* Tier header */}\n                <div className=\"flex items-center justify-between\">\n                  {tier.name && <h3 className=\"font-medium\">{tier.name}</h3>}\n                  <div className=\"flex items-center gap-3\">\n                    <Button\n                      variant=\"outline\"\n                      size=\"icon\"\n                      className={cn(\n                        'h-8 w-8 rounded-full',\n                        qty === 0 && 'opacity-50'\n                      )}\n                      onClick={() => updateQuantity(index, -1)}\n                      disabled={qty === 0}\n                    >\n                      <Minus className=\"h-4 w-4\" />\n                    </Button>\n                    <span className=\"w-6 text-center font-medium\">{qty}</span>\n                    <Button\n                      size=\"icon\"\n                      className=\"h-8 w-8 rounded-full\"\n                      onClick={() => updateQuantity(index, 1)}\n                      disabled={qty >= (tier.maxPerOrder ?? 10) || qty >= (tier.available ?? 100)}\n                    >\n                      <Plus className=\"h-4 w-4\" />\n                    </Button>\n                  </div>\n                </div>\n\n                {/* Price info */}\n                {tier.price !== undefined && (\n                  <div className=\"mt-3\">\n                    <div className=\"flex items-baseline gap-2\">\n                      <span className=\"font-semibold\">{formatCurrency(totalPrice, currency)}</span>\n                      {(tier.fee ?? 0) > 0 && (\n                        <span className=\"text-sm text-muted-foreground\">\n                          incl. {formatCurrency(tier.fee ?? 0, currency)} Fee\n                        </span>\n                      )}\n                    </div>\n                    {tier.salesEndDate && (\n                      <p className=\"text-sm text-muted-foreground mt-1\">\n                        Sales end on {tier.salesEndDate}\n                      </p>\n                    )}\n                  </div>\n                )}\n\n                {/* Description */}\n                {tier.description && (\n                  <p className=\"text-sm text-muted-foreground mt-3\">\n                    {tier.description}\n                  </p>\n                )}\n              </div>\n            )\n          })}\n        </div>\n\n        {/* Checkout button */}\n        <div className=\"mt-6\">\n          <Button\n            className=\"w-full\"\n            size=\"lg\"\n            onClick={handleCheckout}\n            disabled={!hasSelections}\n          >\n            Check out\n          </Button>\n        </div>\n      </div>\n\n        {/* Right side - Order summary */}\n        {showOrderSummary && (\n          <div className=\"w-full lg:w-80 shrink-0\">\n            {/* Event image */}\n            {event?.image && (\n              <img\n                src={event.image}\n                alt={event?.title || 'Event image'}\n                className=\"w-full h-40 object-cover rounded-lg mb-4\"\n              />\n            )}\n\n            <div className=\"rounded-lg border bg-muted/30 p-4\">\n              <h3 className=\"font-semibold mb-4\">Order summary</h3>\n\n              {hasSelections ? (\n                <>\n                  {/* Line items */}\n                  <div className=\"space-y-2\">\n                    {selectionsList.map((selection, index) => (\n                      <div key={index} className=\"flex justify-between text-sm\">\n                        <span>{selection.quantity} x {selection.tierName ?? 'Ticket'}</span>\n                        <span>{formatCurrency((selection.price ?? 0) * selection.quantity, currency)}</span>\n                      </div>\n                    ))}\n                  </div>\n\n                  {/* Totals */}\n                  <div className=\"mt-4 pt-4 border-t space-y-2\">\n                    <div className=\"flex justify-between text-sm\">\n                      <span>Subtotal</span>\n                      <span>{formatCurrency(subtotal, currency)}</span>\n                    </div>\n                    <div className=\"flex justify-between text-sm\">\n                      <span className=\"flex items-center gap-1\">\n                        Fees\n                        <Info className=\"h-3 w-3 text-muted-foreground\" />\n                      </span>\n                      <span>{formatCurrency(totalFees, currency)}</span>\n                    </div>\n                  </div>\n\n                  <div className=\"mt-4 pt-4 border-t\">\n                    <div className=\"flex justify-between font-semibold\">\n                      <span>Total</span>\n                      <span>{formatCurrency(total, currency)}</span>\n                    </div>\n                  </div>\n                </>\n              ) : (\n                <p className=\"text-sm text-muted-foreground\">No tickets selected</p>\n              )}\n            </div>\n          </div>\n        )}\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:block",
      "target": "components/ui/ticket-tier-select.tsx"
    },
    {
      "path": "registry/events/demo/events.ts",
      "content": "// Demo data for Events category components\n// This file contains sample data used for component previews and documentation\n\nimport type { Event, EventDetails } from '../types'\n\n// Helper to generate dates relative to today\nfunction getDateAt(daysFromNow: number, hour: number): string {\n  const date = new Date()\n  date.setDate(date.getDate() + daysFromNow)\n  date.setHours(hour, 0, 0, 0)\n  return date.toISOString()\n}\n\n// Single event for EventCard default\nexport const demoEvent: Event = {\n  title: 'NEON Vol. 9',\n  category: 'Music',\n  venue: 'Echoplex',\n  neighborhood: 'Echo Park',\n  city: 'Los Angeles',\n  dateTime: 'Tonight 9:00 PM - 3:00 AM',\n  priceRange: '$45 - $150',\n  image: 'https://images.unsplash.com/photo-1470225620780-dba8ba36b745?w=800',\n  vibeTags: ['High energy', 'Late night', 'Dressy'],\n  vibeDescription:\n    'Immersive electronic experience with world-class DJs and stunning visuals.',\n  aiSummary:\n    \"Immersive electronic night with world-class DJs and stunning visuals at LA's top-rated venue.\",\n  lineup: ['DJ Shadow', 'Bonobo', 'Four Tet', 'Caribou'],\n  ticketTiers: [\n    'General Admission $45',\n    'VIP Access $120',\n    'Backstage Pass $150'\n  ],\n  eventSignal: 'going-fast',\n  organizerRating: 4.8,\n  reviewCount: 12453,\n  venueRating: 4.8,\n  ageRestriction: '21+',\n  hasMultipleDates: true\n}\n\n// 15 events for EventList default\nexport const demoEvents: Event[] = [\n  {\n    title: 'NEON Vol. 9',\n    category: 'Music',\n    venue: 'Echoplex',\n    neighborhood: 'Echo Park',\n    city: 'Los Angeles',\n    dateTime: 'Tonight 9:00 PM - 3:00 AM',\n    priceRange: '$45 - $150',\n    image: 'https://images.unsplash.com/photo-1470225620780-dba8ba36b745?w=800',\n    coordinates: { lat: 34.0781, lng: -118.2606 },\n    vibeTags: ['High energy', 'Late night'],\n    eventSignal: 'going-fast',\n    organizerRating: 4.8,\n    reviewCount: 12453,\n    ageRestriction: '21+'\n  },\n  {\n    title: 'The Midnight Show',\n    category: 'Comedy',\n    venue: 'The Comedy Underground',\n    neighborhood: 'Santa Monica',\n    city: 'Los Angeles',\n    dateTime: 'Tonight 10:00 PM - 12:00 AM',\n    priceRange: '$15 - $35',\n    image: 'https://images.unsplash.com/photo-1585699324551-f6c309eedeca?w=800',\n    coordinates: { lat: 34.0195, lng: -118.4912 },\n    vibeTags: ['Social', 'Late night'],\n    eventSignal: 'popular',\n    organizerRating: 4.7,\n    reviewCount: 3241,\n    discount: 'TONIGHT ONLY - 40% OFF'\n  },\n  {\n    title: 'Salsa Sundays @ Echo Park',\n    category: 'Classes',\n    venue: 'Echo Park Lake',\n    neighborhood: 'Echo Park',\n    city: 'Los Angeles',\n    dateTime: 'Saturday 6:00 PM - 10:00 PM',\n    priceRange: 'Free',\n    image: 'https://images.unsplash.com/photo-1504609813442-a8924e83f76e?w=800',\n    coordinates: { lat: 34.0731, lng: -118.2608 },\n    vibeTags: ['High energy', 'Social'],\n    eventSignal: 'just-added',\n    organizerRating: 4.9,\n    reviewCount: 8764\n  },\n  {\n    title: 'Dawn Flow: Griffith Park',\n    category: 'Classes',\n    venue: 'Griffith Park',\n    neighborhood: 'Los Feliz',\n    city: 'Los Angeles',\n    dateTime: 'Tomorrow 6:00 AM - 8:00 AM',\n    priceRange: 'Free',\n    image: 'https://images.unsplash.com/photo-1545205597-3d9d02c29597?w=800',\n    coordinates: { lat: 34.1365, lng: -118.2943 },\n    vibeTags: ['Chill', 'Wellness', 'Outdoor'],\n    organizerRating: 4.9,\n    reviewCount: 8764,\n    discount: 'FREE - First 50 Only'\n  },\n  {\n    title: 'Lakers vs Celtics',\n    category: 'Sports',\n    venue: 'Crypto.com Arena',\n    neighborhood: 'Downtown',\n    city: 'Los Angeles',\n    dateTime: 'Friday 7:30 PM - 10:30 PM',\n    priceRange: '$125 - $850',\n    image: 'https://images.unsplash.com/photo-1546519638-68e109498ffc?w=800',\n    coordinates: { lat: 34.0430, lng: -118.2673 },\n    vibeTags: ['High energy', 'Social', 'Premium'],\n    eventSignal: 'sales-end-soon',\n    organizerRating: 4.5,\n    reviewCount: 2341\n  },\n  {\n    title: 'Smorgasburg LA: Sunday Market',\n    category: 'Food & Drink',\n    venue: 'ROW DTLA',\n    neighborhood: 'Arts District',\n    city: 'Los Angeles',\n    dateTime: 'Sunday 10:00 AM - 4:00 PM',\n    priceRange: 'Free',\n    image: 'https://images.unsplash.com/photo-1555939594-58d7cb561ad1?w=800',\n    coordinates: { lat: 34.0341, lng: -118.2324 },\n    vibeTags: ['Family-friendly', 'Outdoor', 'Social'],\n    organizerRating: 4.8,\n    reviewCount: 5632\n  },\n  {\n    title: 'LACMA After Hours',\n    category: 'Arts',\n    venue: 'LACMA',\n    neighborhood: 'Miracle Mile',\n    city: 'Los Angeles',\n    dateTime: 'Friday 7:00 PM - 11:00 PM',\n    priceRange: '$35 - $75',\n    image: 'https://images.unsplash.com/photo-1531243269054-5ebf6f34081e?w=800',\n    coordinates: { lat: 34.0639, lng: -118.3592 },\n    vibeTags: ['Chill', 'Date night', 'Sophisticated'],\n    organizerRating: 4.7,\n    reviewCount: 1234,\n    ageRestriction: '21+',\n    discount: 'MEMBER PRICE'\n  },\n  {\n    title: 'Blue Note Under Stars',\n    category: 'Music',\n    venue: 'Hollywood Bowl',\n    neighborhood: 'Hollywood Hills',\n    city: 'Los Angeles',\n    dateTime: 'Saturday 8:00 PM - 11:00 PM',\n    priceRange: '$45 - $200',\n    image: 'https://images.unsplash.com/photo-1514320291840-2e0a9bf2a9ae?w=800',\n    coordinates: { lat: 34.1122, lng: -118.3391 },\n    vibeTags: ['Chill', 'Date night', 'Outdoor'],\n    lineup: ['Kamasi Washington', 'Thundercat', 'Terrace Martin'],\n    organizerRating: 4.8,\n    reviewCount: 12453\n  },\n  {\n    title: 'Meraki: Seth Troxler',\n    category: 'Nightlife',\n    venue: 'Sound Nightclub',\n    neighborhood: 'Hollywood',\n    city: 'Los Angeles',\n    dateTime: 'Saturday 10:00 PM - 4:00 AM',\n    priceRange: '$35 - $65',\n    image: 'https://images.unsplash.com/photo-1571266028243-e4733b0f0bb0?w=800',\n    coordinates: { lat: 34.0928, lng: -118.3287 },\n    vibeTags: ['High energy', 'Late night', 'Underground'],\n    lineup: ['Amelie Lens', 'I Hate Models', 'FJAAK'],\n    organizerRating: 4.6,\n    reviewCount: 1876,\n    ageRestriction: '21+'\n  },\n  {\n    title: 'Whitney Cummings + Friends',\n    category: 'Comedy',\n    venue: 'The Laugh Factory',\n    neighborhood: 'Hollywood',\n    city: 'Los Angeles',\n    dateTime: 'In 2 days 8:00 PM - 11:00 PM',\n    priceRange: '$25 - $55',\n    image: 'https://images.unsplash.com/photo-1527224538127-2104bb71c51b?w=800',\n    coordinates: { lat: 34.0901, lng: -118.3615 },\n    vibeTags: ['Chill', 'Social', 'Date night'],\n    organizerRating: 4.7,\n    reviewCount: 3241,\n    ageRestriction: '18+'\n  },\n  {\n    title: 'Venice Beach Drum Circle',\n    category: 'Music',\n    venue: 'Venice Beach Boardwalk',\n    neighborhood: 'Venice',\n    city: 'Los Angeles',\n    dateTime: 'Sunday 4:00 PM - 8:00 PM',\n    priceRange: 'Free',\n    image: 'https://images.unsplash.com/photo-1506157786151-b8491531f063?w=800',\n    coordinates: { lat: 33.9850, lng: -118.4695 },\n    vibeTags: ['Outdoor', 'Social', 'Chill'],\n    eventSignal: 'popular',\n    organizerRating: 4.6,\n    reviewCount: 2145\n  },\n  {\n    title: 'Rooftop Cinema: Blade Runner',\n    category: 'Film',\n    venue: 'Rooftop Cinema Club',\n    neighborhood: 'DTLA',\n    city: 'Los Angeles',\n    dateTime: 'Friday 8:30 PM - 11:00 PM',\n    priceRange: '$25 - $45',\n    image: 'https://images.unsplash.com/photo-1489599849927-2ee91cede3ba?w=800',\n    coordinates: { lat: 34.0407, lng: -118.2468 },\n    vibeTags: ['Date night', 'Views', 'Chill'],\n    organizerRating: 4.8,\n    reviewCount: 892\n  },\n  {\n    title: 'Dodgers vs Giants',\n    category: 'Sports',\n    venue: 'Dodger Stadium',\n    neighborhood: 'Elysian Park',\n    city: 'Los Angeles',\n    dateTime: 'Saturday 1:10 PM - 4:30 PM',\n    priceRange: '$35 - $350',\n    image: 'https://images.unsplash.com/photo-1566577739112-5180d4bf9390?w=800',\n    coordinates: { lat: 34.0739, lng: -118.2400 },\n    vibeTags: ['Family-friendly', 'Social', 'High energy'],\n    eventSignal: 'few-tickets-left',\n    organizerRating: 4.7,\n    reviewCount: 15678\n  },\n  {\n    title: 'Natural Wine Fair',\n    category: 'Food & Drink',\n    venue: 'Grand Central Market',\n    neighborhood: 'Downtown',\n    city: 'Los Angeles',\n    dateTime: 'Sunday 12:00 PM - 6:00 PM',\n    priceRange: '$45 - $85',\n    image: 'https://images.unsplash.com/photo-1510812431401-41d2bd2722f3?w=800',\n    coordinates: { lat: 34.0508, lng: -118.2490 },\n    vibeTags: ['Tasting', 'Social', 'Sophisticated'],\n    eventSignal: 'just-added',\n    organizerRating: 4.5,\n    reviewCount: 567,\n    ageRestriction: '21+'\n  },\n  {\n    title: 'Meditation in the Gardens',\n    category: 'Wellness',\n    venue: 'The Getty Center',\n    neighborhood: 'Brentwood',\n    city: 'Los Angeles',\n    dateTime: 'Sunday 7:00 AM - 9:00 AM',\n    priceRange: 'Free',\n    image: 'https://images.unsplash.com/photo-1506126613408-eca07ce68773?w=800',\n    coordinates: { lat: 34.0780, lng: -118.4741 },\n    vibeTags: ['Wellness', 'Outdoor', 'Chill'],\n    organizerRating: 4.9,\n    reviewCount: 1234\n  }\n]\n\n// Detailed event for EventDetail default\nexport const demoEventDetails: EventDetails = {\n  title: 'Sunglasses at Night: Underground Techno',\n  category: 'Nightlife',\n  venue: 'The White Rabbit',\n  neighborhood: 'The Woodlands',\n  city: 'Houston, TX',\n  startDateTime: getDateAt(2, 22),\n  endDateTime: getDateAt(3, 4),\n  priceRange: '$15 - $30',\n  images: [\n    'https://images.unsplash.com/photo-1470225620780-dba8ba36b745?w=800',\n    'https://images.unsplash.com/photo-1514525253161-7a46d19cd819?w=800',\n    'https://images.unsplash.com/photo-1533174072545-7a4b6ad7a6c3?w=800'\n  ],\n  vibeTags: ['High energy', 'Late night', 'Underground'],\n  eventSignal: 'going-fast',\n  aiSummary: 'Raw, unfiltered techno in an authentic warehouse setting.',\n  description:\n    'Experience the raw energy of underground techno. Industrial beats, immersive visuals, and a crowd that lives for the music.',\n  lineup: ['Amelie Lens', 'I Hate Models', 'FJAAK'],\n  attendeesCount: 537,\n  friendsGoing: [\n    { name: 'Alex', avatar: 'https://i.pravatar.cc/40?u=alex' },\n    { name: 'Sam', avatar: 'https://i.pravatar.cc/40?u=sam' }\n  ],\n  organizer: {\n    name: 'Midnight Lovers',\n    image: 'https://i.pravatar.cc/80?u=midnight',\n    rating: 4.5,\n    reviewCount: 1067,\n    verified: true,\n    followers: 1200,\n    eventsCount: 154,\n    hostingYears: 8,\n    trackRecord: 'great',\n    responseRate: 'very responsive'\n  },\n  venue_details: {\n    name: 'The White Rabbit',\n    address: '8827 Nasher Ave',\n    city: 'Houston TX',\n    coordinates: { lat: 29.7604, lng: -95.3698 }\n  },\n  tiers: [\n    { name: 'General Admission', price: 15, available: 50 },\n    {\n      name: 'VIP Access',\n      price: 30,\n      available: 20,\n      benefits: ['Skip the line', 'Exclusive lounge']\n    }\n  ],\n  goodToKnow: {\n    duration: '2 hours',\n    doorsOpen: '7:00 PM',\n    showtime: '7:30 PM',\n    ageRestriction: '21+',\n    dressCode: 'Casual',\n    parking: 'Limited, leave early to avoid long queues'\n  },\n  policies: {\n    refund: 'No refunds. Tickets are transferable.',\n    entry: 'Open 2 hours before event',\n    idRequired: true,\n    securityOnSite: true\n  },\n  faq: [\n    {\n      question: 'What is the refund policy?',\n      answer: 'No refunds. Tickets are transferable.'\n    },\n    {\n      question: 'When do doors open?',\n      answer: 'Open 2 hours before event.'\n    },\n    {\n      question: 'Is there parking?',\n      answer: 'Limited, leave early to avoid long queues.'\n    }\n  ],\n  relatedTags: ['Houston Events', 'Texas Nightlife', 'Techno Parties']\n}\n\n// Ticket tiers for TicketTierSelect\nexport const demoTicketTiers = [\n  {\n    id: '1',\n    name: 'General Admission',\n    price: 45,\n    fee: 5,\n    available: 100,\n    maxPerOrder: 10,\n  },\n  {\n    id: '2',\n    name: 'VIP',\n    price: 150,\n    fee: 15,\n    available: 20,\n    maxPerOrder: 4,\n    description: 'Includes backstage access',\n  },\n]\n\n// Event confirmation data\nexport const demoEventConfirmation = {\n  orderNumber: 'EVT-12345',\n  eventTitle: 'Summer Music Festival',\n  ticketCount: 2,\n  recipientEmail: 'customer@example.com',\n  eventDate: 'Jan 20, 2024',\n  eventLocation: 'Central Park, New York',\n  organizer: {\n    name: 'Live Nation',\n  },\n}\n",
      "type": "registry:lib",
      "target": "components/ui/demo/events.ts"
    }
  ],
  "categories": [
    "events"
  ],
  "type": "registry:block"
}