@getmicdrop/venue-calendar 4.0.109 → 4.0.110

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/CartView-bMHSoj75.js +2475 -0
  2. package/dist/CartView-bMHSoj75.js.map +1 -0
  3. package/dist/{Checkout-CMEf_qnp.js → Checkout-DDXZc-yj.js} +323 -333
  4. package/dist/Checkout-DDXZc-yj.js.map +1 -0
  5. package/dist/{Checkout-Chki2df_.js → Checkout-DG2iHmHC.js} +206 -205
  6. package/dist/Checkout-DG2iHmHC.js.map +1 -0
  7. package/dist/{CheckoutTimer-BAaY_60w.js → CheckoutTimer-Bwq6a_Hl.js} +5 -5
  8. package/dist/{CheckoutTimer-BAaY_60w.js.map → CheckoutTimer-Bwq6a_Hl.js.map} +1 -1
  9. package/dist/{ClockIcon-Dbbj_qur.js → ClockIcon-ZgeMNNI1.js} +2 -2
  10. package/dist/{ClockIcon-Dbbj_qur.js.map → ClockIcon-ZgeMNNI1.js.map} +1 -1
  11. package/dist/{CollectionView-RM30YPOJ.js → CollectionView-1pf2C4kX.js} +78 -77
  12. package/dist/CollectionView-1pf2C4kX.js.map +1 -0
  13. package/dist/{Event-kdxMa6OT.js → Event-D3o0fguY.js} +659 -657
  14. package/dist/Event-D3o0fguY.js.map +1 -0
  15. package/dist/{EventPage-BRBByBHe.js → EventPage-DqO-AV8i.js} +300 -306
  16. package/dist/EventPage-DqO-AV8i.js.map +1 -0
  17. package/dist/{Heading-CSDFD80h.js → Heading-pURRwiIC.js} +2 -2
  18. package/dist/{Heading-CSDFD80h.js.map → Heading-pURRwiIC.js.map} +1 -1
  19. package/dist/{ScarcityBadge-B0ca48su.js → ScarcityBadge-ykz32KS9.js} +11 -11
  20. package/dist/{ScarcityBadge-B0ca48su.js.map → ScarcityBadge-ykz32KS9.js.map} +1 -1
  21. package/dist/SeriesPage-BmNk80cF.js +34 -0
  22. package/dist/SeriesPage-BmNk80cF.js.map +1 -0
  23. package/dist/{Spinner--TOwvv9A.js → Spinner-OGA1hrc5.js} +2 -2
  24. package/dist/{Spinner--TOwvv9A.js.map → Spinner-OGA1hrc5.js.map} +1 -1
  25. package/dist/Success-DLlQ54_-.js +896 -0
  26. package/dist/Success-DLlQ54_-.js.map +1 -0
  27. package/dist/{Text-WLl_ELy9.js → Text-DMpMLgcU.js} +19 -19
  28. package/dist/Text-DMpMLgcU.js.map +1 -0
  29. package/dist/VenueCalendar-ClSRsS6u.js +16474 -0
  30. package/dist/VenueCalendar-ClSRsS6u.js.map +1 -0
  31. package/dist/{ViewTicketsEmbed-BOukxQIF.js → ViewTicketsEmbed-5LMG2xwn.js} +86 -85
  32. package/dist/{ViewTicketsEmbed-BOukxQIF.js.map → ViewTicketsEmbed-5LMG2xwn.js.map} +1 -1
  33. package/dist/__SKIP_PATHS__-BtJ0tS93.js +10 -0
  34. package/dist/__SKIP_PATHS__-BtJ0tS93.js.map +1 -0
  35. package/dist/api/api.cjs +1 -1
  36. package/dist/api/api.cjs.map +1 -1
  37. package/dist/api/api.mjs +336 -333
  38. package/dist/api/api.mjs.map +1 -1
  39. package/dist/{labels-DXGieQXs.js → labels-Ws4MJjH5.js} +154 -149
  40. package/dist/labels-Ws4MJjH5.js.map +1 -0
  41. package/dist/{modalManager.svelte-Dbd1xgTQ.js → modalManager.svelte-BPA2JF6c.js} +2 -2
  42. package/dist/{modalManager.svelte-Dbd1xgTQ.js.map → modalManager.svelte-BPA2JF6c.js.map} +1 -1
  43. package/dist/navigation--gZASiSa.js +19 -0
  44. package/dist/navigation--gZASiSa.js.map +1 -0
  45. package/dist/{promo-oWi_MKmY.js → promo-vXx1bxQm.js} +2 -2
  46. package/dist/{promo-oWi_MKmY.js.map → promo-vXx1bxQm.js.map} +1 -1
  47. package/dist/seo/seo.cjs +1 -1
  48. package/dist/seo/seo.cjs.map +1 -1
  49. package/dist/seo/seo.mjs +438 -291
  50. package/dist/seo/seo.mjs.map +1 -1
  51. package/dist/seo/types.d.ts +0 -1
  52. package/dist/{showcase-state-options-DJJdjxvZ.js → showcase-state-options-9SoS5WuT.js} +21 -21
  53. package/dist/showcase-state-options-9SoS5WuT.js.map +1 -0
  54. package/dist/{transform-Bgqwj9i-.js → transform-BD9xXAq7.js} +81 -77
  55. package/dist/transform-BD9xXAq7.js.map +1 -0
  56. package/dist/types/index.d.ts +18 -14
  57. package/dist/utm-rT0TPh8G.js +288 -0
  58. package/dist/utm-rT0TPh8G.js.map +1 -0
  59. package/dist/venue-calendar.css +1 -1
  60. package/dist/venue-calendar.es.js +2 -2
  61. package/dist/venue-calendar.iife.js +49 -49
  62. package/dist/venue-calendar.iife.js.map +1 -1
  63. package/dist/venue-calendar.umd.js +44 -44
  64. package/dist/venue-calendar.umd.js.map +1 -1
  65. package/package.json +4 -4
  66. package/dist/CartView-C3N5pw89.js +0 -2381
  67. package/dist/CartView-C3N5pw89.js.map +0 -1
  68. package/dist/Checkout-CMEf_qnp.js.map +0 -1
  69. package/dist/Checkout-Chki2df_.js.map +0 -1
  70. package/dist/CollectionView-RM30YPOJ.js.map +0 -1
  71. package/dist/Event-kdxMa6OT.js.map +0 -1
  72. package/dist/EventPage-BRBByBHe.js.map +0 -1
  73. package/dist/SeriesPage-CczfbUKO.js +0 -33
  74. package/dist/SeriesPage-CczfbUKO.js.map +0 -1
  75. package/dist/Success-DIWUGUPs.js +0 -886
  76. package/dist/Success-DIWUGUPs.js.map +0 -1
  77. package/dist/Text-WLl_ELy9.js.map +0 -1
  78. package/dist/VenueCalendar-CU5N9klc.js +0 -16579
  79. package/dist/VenueCalendar-CU5N9klc.js.map +0 -1
  80. package/dist/labels-DXGieQXs.js.map +0 -1
  81. package/dist/showcase-state-options-DJJdjxvZ.js.map +0 -1
  82. package/dist/transform-Bgqwj9i-.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"labels-DXGieQXs.js","sources":["../node_modules/@getmicdrop/svelte-components/dist/primitives/Icons/phosphor/CalendarIcon.svelte","../src/lib/api/cta.ts","../src/lib/public-calendar-flow/defaults.ts","../src/lib/public-calendar-flow/OrderSummary.svelte","../src/lib/public-calendar-flow/i18n/labels.js"],"sourcesContent":["<script lang=\"ts\">\r\n /**\r\n * Calendar — Phosphor icon (canonical Micdrop icon family).\r\n * Outline by default; pass `weight=\"fill\"` for solid, or let a stateful parent\r\n * (NavItem / Tabs / BottomNav / status badge) drive it via icon-weight context.\r\n */\r\n import { useIconWeight, type IconWeight } from './iconWeight.js';\r\n\r\n interface Props {\r\n /** Pixel size (width + height). */\r\n size?: string;\r\n /** Icon color; defaults to `currentColor` (inherits text color). */\r\n color?: string;\r\n /** Extra classes. */\r\n class?: string;\r\n /** `regular` (outline) or `fill` (solid). Overrides ambient state weight. */\r\n weight?: IconWeight;\r\n }\r\n\r\n let { size = '24', color = 'currentColor', class: className = '', weight }: Props = $props();\r\n\r\n const ctx = useIconWeight();\r\n let resolved: IconWeight = $derived(weight ?? ctx?.weight ?? 'regular');\r\n</script>\r\n\r\n<svg\r\n class={className}\r\n aria-hidden=\"true\"\r\n width={size}\r\n height={size}\r\n viewBox=\"0 0 256 256\"\r\n fill=\"currentColor\"\r\n style:color={color}\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n>\r\n {#if resolved === 'fill'}<path d=\"M208,32H184V24a8,8,0,0,0-16,0v8H88V24a8,8,0,0,0-16,0v8H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM112,184a8,8,0,0,1-16,0V132.94l-4.42,2.22a8,8,0,0,1-7.16-14.32l16-8A8,8,0,0,1,112,120Zm56-8a8,8,0,0,1,0,16H136a8,8,0,0,1-6.4-12.8l28.78-38.37A8,8,0,1,0,145.07,132a8,8,0,1,1-13.85-8A24,24,0,0,1,176,136a23.76,23.76,0,0,1-4.84,14.45L152,176ZM48,80V48H72v8a8,8,0,0,0,16,0V48h80v8a8,8,0,0,0,16,0V48h24V80Z\"/>{:else}<rect x=\"40\" y=\"40\" width=\"176\" height=\"176\" rx=\"8\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><line x1=\"176\" y1=\"24\" x2=\"176\" y2=\"56\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><line x1=\"80\" y1=\"24\" x2=\"80\" y2=\"56\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><line x1=\"40\" y1=\"88\" x2=\"216\" y2=\"88\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><polyline points=\"88 128 104 120 104 184\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><path d=\"M138.14,128a16,16,0,1,1,26.64,17.63L136,184h32\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/>{/if}\r\n</svg>\r\n","/**\r\n * CTA state computation.\r\n *\r\n * Pure function (no I/O) — derives the buy-button state from an event and\r\n * its ticket list. Lives in `api/` because it is the canonical, single\r\n * source of truth that replaces the duplicate implementations previously\r\n * scattered across utils/api.js, core/api-client.js, and a few components.\r\n */\r\n\r\n// Import from the specific subpath (not the bare entry) so the api/\r\n// bundle doesn't pull in the entire SC component graph (Accordion etc.)\r\n// and break `npm run build:api`. `formatLocal` is the sanctioned browser-local\r\n// (no-timezone) Intl label home — these \"On sale …\" countdown labels render in\r\n// the viewer's own clock, so no venue timezone applies. The datetime subpath is\r\n// leaf/component-free; only `formatLocal` (→ Intl) is pulled, no date-fns.\r\nimport { browserNow, formatLocal } from '@getmicdrop/svelte-components/datetime';\r\n// Hidden-ticket predicate from the `/transforms` leaf subpath (no component\r\n// graph, so `npm run build:api` stays clean). SC's copy was pinned FROM this\r\n// body (dedup #392) and additionally honours the backend-resolved\r\n// `effectiveSales*` window for relative-offset tickets (#388). Imported (not\r\n// just re-exported) so it stays in local scope for `computeCtaState` below.\r\nimport { isHiddenTicketPurchasable } from '@getmicdrop/svelte-components/transforms';\r\n\r\nexport interface CtaStateOptions {\r\n cancelled?: boolean;\r\n isRegistration?: boolean;\r\n waitlistEnabled?: boolean;\r\n}\r\n\r\nexport interface CtaState {\r\n text: string;\r\n disabled: boolean;\r\n reason:\r\n | 'cancelled'\r\n | 'event_past'\r\n | 'no_tickets'\r\n | 'available'\r\n | 'coming_soon'\r\n | 'sold_out_waitlist'\r\n | 'sold_out'\r\n | 'sales_ended'\r\n | 'hidden_only';\r\n}\r\n\r\ninterface CtaEvent {\r\n startDateTime?: string | null;\r\n endDateTime?: string | null;\r\n hasPurchasableHiddenTickets?: boolean;\r\n}\r\n\r\ninterface CtaTicket {\r\n salesChannel?: number;\r\n salesBegin?: string | null;\r\n salesStart?: string | null;\r\n saleBegin?: string | null;\r\n onSaleStart?: string | null;\r\n salesEnd?: string | null;\r\n saleEnd?: string | null;\r\n onSaleEnd?: string | null;\r\n remainingCapacity?: number | null;\r\n quantityRemaining?: number | null;\r\n quantity?: number | null;\r\n soldOut?: boolean;\r\n isHidden?: boolean;\r\n visibility?: number;\r\n}\r\n\r\n// A hidden ticket (visibility>=2 or isHidden) that's still on sale drives the\r\n// \"Sales ended\" / \"Sold out\" / \"No tickets\" → \"Get tickets\" override. The user\r\n// just needs the promo code to see it. Re-exported from the SC canonical so\r\n// existing consumers (cta.test.ts, computeCtaState) keep their import path while\r\n// the single-source body lives in SC (dedup #392).\r\nexport { isHiddenTicketPurchasable };\r\n\r\nexport function computeCtaState(\r\n event: CtaEvent,\r\n tickets: CtaTicket[] | undefined,\r\n options: CtaStateOptions = {}\r\n): CtaState {\r\n const {\r\n cancelled = false,\r\n isRegistration = false,\r\n waitlistEnabled = false,\r\n } = options;\r\n const now = browserNow();\r\n\r\n if (cancelled)\r\n return { text: 'Cancelled', disabled: true, reason: 'cancelled' };\r\n\r\n const eventEnd = event.endDateTime || event.startDateTime;\r\n // @datetime-escape: absolute-instant compare of a UTC-Z field vs now — tz-independent\r\n if (eventEnd && new Date(eventEnd) < now) {\r\n return { text: 'Sales ended', disabled: true, reason: 'event_past' };\r\n }\r\n\r\n const hiddenAvailable =\r\n event?.hasPurchasableHiddenTickets === true ||\r\n (Array.isArray(tickets) && tickets.some(isHiddenTicketPurchasable));\r\n\r\n const publicTickets = (tickets || []).filter(\r\n t =>\r\n t.salesChannel !== 2 &&\r\n !t.isHidden &&\r\n !(typeof t.visibility === 'number' && t.visibility >= 2)\r\n );\r\n if (publicTickets.length === 0) {\r\n if (hiddenAvailable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'hidden_only',\r\n };\r\n }\r\n return {\r\n text: 'No tickets available',\r\n disabled: true,\r\n reason: 'no_tickets',\r\n };\r\n }\r\n\r\n let hasPurchasable = false;\r\n let allSoldOut = true;\r\n let allComingSoon = true;\r\n let earliestSalesStart: Date | null = null;\r\n\r\n for (const ticket of publicTickets) {\r\n const salesBegin =\r\n ticket.salesBegin ||\r\n ticket.salesStart ||\r\n ticket.saleBegin ||\r\n ticket.onSaleStart;\r\n const salesEnd = ticket.salesEnd || ticket.saleEnd || ticket.onSaleEnd;\r\n const remaining =\r\n ticket.remainingCapacity ?? ticket.quantityRemaining ?? ticket.quantity;\r\n const isSoldOut =\r\n ticket.soldOut ||\r\n (remaining !== null && remaining !== undefined && remaining <= 0);\r\n\r\n const isScheduled = salesBegin ? new Date(salesBegin) > now : false; // @datetime-escape: absolute-instant compare of a UTC-Z field vs now — tz-independent\r\n const hasSalesEnded = salesEnd ? new Date(salesEnd) < now : false; // @datetime-escape: absolute-instant compare of a UTC-Z field vs now — tz-independent\r\n const isPurchasable = !isSoldOut && !isScheduled && !hasSalesEnded;\r\n\r\n if (isPurchasable) hasPurchasable = true;\r\n if (!isSoldOut) allSoldOut = false;\r\n if (!isScheduled) allComingSoon = false;\r\n\r\n if (isScheduled && salesBegin && !isSoldOut && !hasSalesEnded) {\r\n const startDate = new Date(salesBegin); // @datetime-escape: absolute-instant compare of a UTC-Z field vs now — tz-independent\r\n if (!earliestSalesStart || startDate < earliestSalesStart) {\r\n earliestSalesStart = startDate;\r\n }\r\n }\r\n }\r\n\r\n if (hasPurchasable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'available',\r\n };\r\n }\r\n\r\n if (allComingSoon && earliestSalesStart) {\r\n if (hiddenAvailable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'hidden_only',\r\n };\r\n }\r\n const diffMs = earliestSalesStart.getTime() - now.getTime();\r\n const diffHours = diffMs / (1000 * 60 * 60);\r\n const diffDays = diffMs / (1000 * 60 * 60 * 24);\r\n // Viewer-local time label (\"8:00 PM\") — the shape shared by the <24h branch\r\n // and the >7d composite. Matches the deprecated `formatTime(d,{hour12:true})`\r\n // defaults-merge exactly.\r\n const timeLabel = (d: Date) =>\r\n formatLocal(\r\n d,\r\n { hour: 'numeric', minute: '2-digit', hour12: true },\r\n 'en-US'\r\n );\r\n let dateText: string;\r\n if (diffHours < 24) {\r\n dateText = timeLabel(earliestSalesStart);\r\n } else if (diffDays <= 7) {\r\n dateText = formatLocal(\r\n earliestSalesStart,\r\n { weekday: 'short', hour: 'numeric', minute: '2-digit', hour12: true },\r\n 'en-US'\r\n );\r\n } else {\r\n const d = formatLocal(\r\n earliestSalesStart,\r\n { month: 'short', day: 'numeric' },\r\n 'en-US'\r\n );\r\n dateText = `${d} ${timeLabel(earliestSalesStart)}`;\r\n }\r\n return {\r\n text: `On sale ${dateText}`,\r\n disabled: true,\r\n reason: 'coming_soon',\r\n };\r\n }\r\n\r\n if (allSoldOut) {\r\n if (hiddenAvailable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'hidden_only',\r\n };\r\n }\r\n if (waitlistEnabled) {\r\n return {\r\n text: 'Join Waitlist',\r\n disabled: false,\r\n reason: 'sold_out_waitlist',\r\n };\r\n }\r\n return { text: 'Sold out', disabled: true, reason: 'sold_out' };\r\n }\r\n\r\n if (hiddenAvailable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'hidden_only',\r\n };\r\n }\r\n\r\n return { text: 'Sales ended', disabled: true, reason: 'sales_ended' };\r\n}\r\n","// @currency-escape: feeCents / 100 in calculateServiceFee is arithmetic,\r\n// not display. Produces a dollar-magnitude number used in the fee formula\r\n// `price * (feePercentage / 100) + feeCents / 100`. Per Atlas\r\n// utility-currency convergence record; the no-handrolled-currency\r\n// ESLint rule's divideByHundred detector treats variable-name `Cents`\r\n// as drift but here it's real math.\r\n\r\n// Premium Ticket Experience — Constants & Defaults\r\n// Used by all design variants. DO NOT MODIFY per-variant.\r\n\r\n// This file is the canonical formatter module for public-calendar-flow: it\r\n// wraps + re-exports the timezone-aware production date/time formatters, plus\r\n// the shared sales-countdown formatter (formatSmartSalesDate) hoisted into\r\n// svelte-components (SC #471). No raw Intl date formatting lives here anymore.\r\n\r\nimport type {\r\n EventData,\r\n TicketTypeData,\r\n ScarcityLevel,\r\n CtaConfig,\r\n PromoCodeState,\r\n} from './types';\r\nimport { computeCtaState } from '$lib/api';\r\nimport {\r\n computeScarcityLevel,\r\n SCARCITY_THRESHOLDS,\r\n} from '$lib/constants/scarcity';\r\nimport type { Cents } from '@getmicdrop/svelte-components';\r\nimport { roundCurrency } from '@getmicdrop/svelte-components';\r\nimport { formatSmartSalesDate } from '@getmicdrop/svelte-components/utils/formatters';\r\nimport {\r\n formatFullDate,\r\n formatFullDateCompact,\r\n formatEventTime,\r\n formatTimeRange,\r\n formatDoorsTime,\r\n formatSalesDate,\r\n formatBrowseDate,\r\n formatEventDate,\r\n formatCleanTimeRange,\r\n getDateParts,\r\n} from '$lib/utils/datetime.js';\r\n\r\n// --- Re-export production date/time formatters (timezone-aware) ---\r\nexport {\r\n formatFullDate,\r\n formatFullDateCompact,\r\n formatEventTime,\r\n formatTimeRange,\r\n formatDoorsTime,\r\n formatSalesDate,\r\n formatBrowseDate,\r\n formatEventDate,\r\n formatCleanTimeRange,\r\n getDateParts,\r\n};\r\n\r\n// Shared sales-countdown formatter, adopted from svelte-components (SC #471).\r\n// Kept as a re-export so public-calendar-flow consumers import it from this\r\n// module unchanged. English defaults match VC's prior copy; the clock time\r\n// renders in UTC (matching the production TicketBlock origin) rather than the\r\n// old copy's viewer-local time.\r\nexport { formatSmartSalesDate };\r\n\r\n// --- Scarcity Badge Rules ---\r\n// Threshold logic lives in the ONE canonical computeScarcityLevel\r\n// ($lib/constants/scarcity) — including the sliding floor/cap that keeps a\r\n// 1,000-seat show from flagging \"Selling fast\" at 200 left. This module only\r\n// adapts the canon's tier enum ('sold-out'/'plenty') to public-calendar-flow's\r\n// display enum ('sold_out'/'none') and renders the copy.\r\nexport function getScarcityLevel(\r\n remaining: number,\r\n total: number\r\n): ScarcityLevel {\r\n const level = computeScarcityLevel(remaining, total);\r\n if (level === 'sold-out') return 'sold_out';\r\n if (level === 'plenty') return 'none';\r\n return level; // 'urgent' | 'low' — identical between the two enums\r\n}\r\n\r\nexport function getScarcityText(\r\n level: ScarcityLevel,\r\n remaining: number,\r\n context: 'browse' | 'event' | 'ticket',\r\n options?: { isFree?: boolean }\r\n): string | null {\r\n if (level === 'none') return null;\r\n if (level === 'sold_out') return 'Sold out';\r\n // No scarcity badges on free events/tickets — nothing to lose = no urgency\r\n if (options?.isFree) return null;\r\n if (\r\n level === 'urgent' &&\r\n context !== 'browse' &&\r\n remaining <= SCARCITY_THRESHOLDS.MAX_EXACT_COUNT\r\n ) {\r\n return `Only ${remaining} left`;\r\n }\r\n if (level === 'low' || level === 'urgent') return 'Selling fast';\r\n return null;\r\n}\r\n\r\n// --- CTA Rules ---\r\n// Delegates to production computeCtaState() but adapts our EventData shape.\r\n// Components keep calling getCtaConfig(event) — internal logic is production-aligned.\r\nexport function getCtaConfig(event: EventData): CtaConfig {\r\n // Map our EventData tickets to the shape computeCtaState expects.\r\n // `isHidden` flows through so computeCtaState can apply the hidden-only\r\n // \"Sales ended\" → \"Get tickets\" override (MIC-1039).\r\n const apiTickets = event.tickets.map(t => ({\r\n salesBegin: t.salesStartDate,\r\n salesEnd: t.salesEndDate,\r\n remainingCapacity: t.quantityAvailable,\r\n totalCapacity: t.quantityTotal,\r\n soldOut: t.status === 'sold_out',\r\n salesChannel: 1, // All our tickets are online (not \"at the door only\")\r\n isHidden: t.isHidden,\r\n }));\r\n\r\n // Handle statuses that computeCtaState doesn't compute from tickets\r\n if (event.status === 'cancelled') {\r\n return {\r\n text: 'Cancelled',\r\n disabled: true,\r\n reason: 'This event has been cancelled',\r\n };\r\n }\r\n if (event.status === 'past') {\r\n return {\r\n text: 'Event ended',\r\n disabled: true,\r\n reason: 'This event has ended',\r\n };\r\n }\r\n\r\n const result = computeCtaState(\r\n { startDateTime: event.startDateTime, endDateTime: event.endDateTime },\r\n apiTickets,\r\n {\r\n cancelled: false,\r\n isRegistration: event.isRegistrationEvent,\r\n waitlistEnabled: false,\r\n }\r\n );\r\n\r\n return {\r\n text: result.text,\r\n disabled: result.disabled,\r\n reason: result.disabled ? toFriendlyReason(result.reason) : undefined,\r\n };\r\n}\r\n\r\n/**\r\n * computeCtaState() returns machine-enum reasons ('event_past', 'sold_out',\r\n * 'coming_soon', etc) intended for branching, not display. The BookingWidget\r\n * and MobileCta render `reason` directly as supplementary copy below the\r\n * button text — which leaks raw enum strings to users.\r\n *\r\n * Map each enum to a friendly sentence, OR return undefined when the button\r\n * `text` already says everything (\"Sales ended\" / \"Sold out\" — no need for\r\n * a second line repeating it).\r\n */\r\nfunction toFriendlyReason(reason: string | undefined): string | undefined {\r\n if (!reason) return undefined;\r\n switch (reason) {\r\n case 'cancelled':\r\n return 'This event has been cancelled.';\r\n case 'event_past':\r\n return 'This event has already happened.';\r\n case 'no_tickets':\r\n return 'There are no tickets configured for this event.';\r\n case 'coming_soon':\r\n return undefined; // text already shows \"On sale <date>\"\r\n case 'sold_out':\r\n return undefined; // text already shows \"Sold out\"\r\n case 'sold_out_waitlist':\r\n return 'All tickets are claimed. Join the waitlist to be notified.';\r\n case 'sales_ended':\r\n return undefined; // text already shows \"Sales ended\"\r\n default:\r\n return undefined; // unknown enum — never leak it\r\n }\r\n}\r\n\r\n// --- Price Display Rules (from DECISIONS.md #1) ---\r\nexport function getPriceDisplay(event: EventData): string | null {\r\n const visibleTickets = event.tickets.filter(\r\n t => t.status === 'on_sale' && !t.isHidden\r\n );\r\n if (visibleTickets.length === 0) return null;\r\n\r\n const hasDonation = visibleTickets.some(\r\n t => t.isDonation || t.ticketType === 2\r\n );\r\n const paidTickets = visibleTickets.filter(\r\n t => !t.isDonation && t.ticketType !== 2\r\n );\r\n const hasFree = paidTickets.some(t => t.price === 0);\r\n const pricedTickets = paidTickets.filter(t => t.price > 0);\r\n\r\n // Only donation tickets → \"Donation\"\r\n if (pricedTickets.length === 0 && !hasFree && hasDonation) return 'Donation';\r\n\r\n // Only free tickets (no paid, no donation) → null (BookingWidget shows \"Free\" via isFreeEvent)\r\n if (pricedTickets.length === 0 && hasFree) return null;\r\n\r\n const minPrice = Math.min(...pricedTickets.map(t => t.price));\r\n\r\n // Free + paid → \"Free\" (free dominates the display). Non-donation free tickets\r\n // outrank the paid options in the headline, matching the shared \"Free\" label\r\n // every other price surface uses. Returning null here left the widget blank.\r\n if (hasFree) return 'Free';\r\n\r\n // Donation + paid → \"From $X\" (donation is an alternative option)\r\n if (hasDonation) return `From $${minPrice}`;\r\n\r\n // Single paid ticket type → \"$X\"\r\n if (pricedTickets.length === 1) return `$${minPrice}`;\r\n\r\n // Multiple paid ticket types → \"From $X\"\r\n return `From $${minPrice}`;\r\n}\r\n\r\n// --- Fee Calculation ---\r\nexport function calculateFee(\r\n price: number,\r\n feePercentage: number,\r\n feeCents: Cents\r\n): number {\r\n return roundCurrency(price * (feePercentage / 100) + feeCents / 100);\r\n}\r\n\r\nexport function calculateTax(amount: number, taxPercentage: number): number {\r\n return roundCurrency(amount * (taxPercentage / 100));\r\n}\r\n\r\n// --- Date Formatting ---\r\n// PREFERRED: Use the timezone-aware production formatters re-exported above:\r\n// formatBrowseDate(iso, tz) → \"Fri, Feb 20\"\r\n// formatFullDateCompact(iso, tz) → \"Friday, February 20\"\r\n// formatEventTime(iso, tz) → \"8:00 PM\"\r\n// formatTimeRange(start, end, tz) → \"8:00 PM - 10:00 PM\"\r\n// formatDoorsTime(doors, tz) → \"7:00 PM\"\r\n\r\n// --- Animation Durations ---\r\nexport const DURATION = {\r\n instant: 100,\r\n micro: 150,\r\n fast: 200,\r\n normal: 300,\r\n slow: 400,\r\n elaborate: 600,\r\n} as const;\r\n\r\n// --- Promo Code State Factory ---\r\nexport function createDefaultPromoState(): PromoCodeState {\r\n return {\r\n code: '',\r\n isApplied: false,\r\n isValidating: false,\r\n error: '',\r\n hint: '',\r\n discountAmount: 0,\r\n discountType: '',\r\n discountTicketIds: [],\r\n revealHiddenTickets: false,\r\n revealTicketIds: [],\r\n };\r\n}\r\n\r\n// --- Ticket helpers ---\r\nexport function getAvailableTickets(\r\n tickets: TicketTypeData[]\r\n): TicketTypeData[] {\r\n return tickets.filter(t => !t.isHidden && t.status === 'on_sale');\r\n}\r\n","<!-- @style-escape: widget-intentional. -->\r\n<script lang=\"ts\">\r\n import type { USD } from '@getmicdrop/svelte-components';\r\n import { Text, formatCurrency } from '@getmicdrop/svelte-components';\r\n import type { OrderTotals } from '$lib/public-calendar-flow/types';\r\n import { formatPriceOrFree } from '$lib/core';\r\n import { DURATION } from '$lib/public-calendar-flow/defaults';\r\n\r\n interface Props {\r\n orderTotals: OrderTotals;\r\n labels?: Record<string, string>;\r\n /**\r\n * Which section to render.\r\n * - `full` (default): ticket lines + totals stacked together.\r\n * - `lines` : ticket-line items only. Use when the parent scrolls\r\n * this section in a flex column.\r\n * - `totals` : subtotal/fees/taxes/promo/total only. Use in a fixed\r\n * footer alongside the action button.\r\n *\r\n * Splitting via `lines` / `totals` lets the sticky sidebars scroll\r\n * just the variable-length ticket list while keeping the summary\r\n * block and CTA always visible.\r\n */\r\n mode?: 'full' | 'lines' | 'totals';\r\n }\r\n\r\n let { orderTotals, labels = {}, mode = 'full' }: Props = $props();\r\n</script>\r\n\r\n<div class=\"space-y-2\" style=\"transition-duration: {DURATION.normal}ms;\">\r\n {#if mode !== 'totals'}\r\n <!-- Line items -->\r\n {#each orderTotals.lines as line (line.ticketId)}\r\n <div class=\"flex justify-between\">\r\n <Text size=\"sm\">{line.quantity}x {line.ticketName}</Text>\r\n <Text size=\"sm\"\r\n >{line.isDonation\r\n ? formatCurrency(line.subtotal as USD)\r\n : formatPriceOrFree(line.subtotal, labels)}</Text\r\n >\r\n </div>\r\n {/each}\r\n {/if}\r\n\r\n {#if mode !== 'lines'}\r\n <!-- Subtotal. In `totals` mode the parent supplies the separator above\r\n\t\t this block (BookingWidget wraps the totals block in border-t); a\r\n\t\t second internal border would render as a double line. Only show\r\n\t\t the internal border-t in `full` mode where lines + totals stack\r\n\t\t in one container with no external separator. -->\r\n {#if mode === 'full' && orderTotals.lines.length > 1}\r\n <div class=\"flex justify-between pt-1 border-t border-default\">\r\n <Text size=\"sm\" color=\"muted\">{labels.subtotal || 'Subtotal'}</Text>\r\n <Text size=\"sm\" color=\"muted\"\r\n >{formatCurrency(orderTotals.subtotal as USD)}</Text\r\n >\r\n </div>\r\n {:else if orderTotals.lines.length > 1}\r\n <div class=\"flex justify-between\">\r\n <Text size=\"sm\" color=\"muted\">{labels.subtotal || 'Subtotal'}</Text>\r\n <Text size=\"sm\" color=\"muted\"\r\n >{formatCurrency(orderTotals.subtotal as USD)}</Text\r\n >\r\n </div>\r\n {/if}\r\n\r\n <!-- Fees -->\r\n {#if orderTotals.fees > 0}\r\n <div class=\"flex justify-between\">\r\n <Text size=\"sm\" color=\"muted\"\r\n >{labels.serviceFees || 'Service fees'}</Text\r\n >\r\n <Text size=\"sm\" color=\"muted\"\r\n >{formatCurrency(orderTotals.fees as USD)}</Text\r\n >\r\n </div>\r\n {/if}\r\n\r\n <!-- Taxes -->\r\n {#if orderTotals.taxes > 0}\r\n <div class=\"flex justify-between\">\r\n <Text size=\"sm\" color=\"muted\">{labels.taxes || 'Taxes'}</Text>\r\n <Text size=\"sm\" color=\"muted\"\r\n >{formatCurrency(orderTotals.taxes as USD)}</Text\r\n >\r\n </div>\r\n {/if}\r\n\r\n <!-- Promo discount -->\r\n {#if orderTotals.promoDiscount > 0}\r\n <div class=\"flex justify-between\">\r\n <Text size=\"sm\" color=\"success\"\r\n >{labels.promoDiscount || 'Promo discount'}</Text\r\n >\r\n <Text size=\"sm\" color=\"success\"\r\n >-{formatCurrency(orderTotals.promoDiscount as USD)}</Text\r\n >\r\n </div>\r\n {/if}\r\n\r\n <!-- Gift card — deduction from the amount due; `total` already reflects it -->\r\n {#if orderTotals.giftCardAmount > 0}\r\n <div class=\"flex justify-between\">\r\n <Text size=\"sm\" color=\"success\">{labels.giftCard || 'Gift card'}</Text>\r\n <Text size=\"sm\" color=\"success\"\r\n >-{formatCurrency(orderTotals.giftCardAmount as USD)}</Text\r\n >\r\n </div>\r\n {/if}\r\n\r\n <!-- Total -->\r\n <div class=\"flex justify-between pt-2 border-t border-default\">\r\n <Text size=\"base\" weight=\"semibold\">{labels.total || 'Total'}</Text>\r\n <Text size=\"base\" weight=\"semibold\"\r\n >{formatCurrency(orderTotals.total as USD)}</Text\r\n >\r\n </div>\r\n {/if}\r\n</div>\r\n","/**\r\n * Default English labels for public-calendar-flow components.\r\n * Consumers override via the `labels` prop on any *Main component.\r\n *\r\n * Label keys use flat camelCase. For composed strings (e.g. aria-labels),\r\n * components build them from atomic label parts.\r\n */\r\nexport const defaultLabels = {\r\n // ── Ticket quantity controls ──────────────────────────────────────\r\n // Stepper aria-labels compose these into \"Increase <name> quantity\" etc.\r\n // `quantityNoun` is deliberately its OWN key (not the main i18n's `quantity`,\r\n // whose value is the sr-only display PREFIX 'Quantity:') so the main-i18n\r\n // merge can't leak a capital-Q + trailing colon into the button labels.\r\n // Overridable, same as increase/decrease, which main i18n also doesn't define.\r\n decrease: 'Decrease',\r\n increase: 'Increase',\r\n quantityNoun: 'quantity',\r\n\r\n // ── Ticket states ─────────────────────────────────────────────────\r\n soldOut: 'Sold out',\r\n free: 'Free',\r\n unavailable: 'Unavailable',\r\n eventSoldOut: 'This event is sold out',\r\n\r\n // ── Price display ─────────────────────────────────────────────────\r\n includesFees: 'Includes',\r\n fees: 'fees',\r\n fee: 'fee',\r\n\r\n // ── Checkout CTAs ─────────────────────────────────────────────────\r\n checkout: 'Checkout',\r\n getTickets: 'Get tickets',\r\n selectTickets: 'Select tickets',\r\n selectTicketsBelow: 'Select tickets below',\r\n selectTicketsToContinue: 'Select tickets to continue',\r\n reserveASpot: 'Reserve a spot',\r\n\r\n // ── Password modal / gate ─────────────────────────────────────────\r\n enterPassword: 'Enter password',\r\n enterEventPassword: 'Enter event password',\r\n passwordRequired: 'Password required',\r\n passwordRequiredShort: 'Password required',\r\n eventRequiresPassword: 'This event requires a password to purchase tickets.',\r\n eventRequiresPasswordAccess:\r\n 'This event requires a password to access tickets.',\r\n enterEventPasswordToView: 'Enter the event password to view tickets.',\r\n enterEventPasswordToViewAvailable:\r\n 'Enter the event password to view available tickets.',\r\n eventPassword: 'Event password',\r\n password: 'Password',\r\n pleaseEnterPassword: 'Please enter the event password',\r\n pleaseEnterAPassword: 'Please enter a password',\r\n eventRequiresPasswordShort: 'This event requires a password',\r\n unlockTickets: 'Unlock tickets',\r\n cancel: 'Cancel',\r\n continue: 'Continue',\r\n submit: 'Submit',\r\n\r\n // ── Order summary ─────────────────────────────────────────────────\r\n subtotal: 'Subtotal',\r\n serviceFees: 'Service fees',\r\n taxes: 'Taxes',\r\n tax: 'Tax',\r\n promoDiscount: 'Promo discount',\r\n giftCard: 'Gift card',\r\n total: 'Total',\r\n orderSummary: 'Order summary',\r\n yourOrder: 'Your order',\r\n\r\n // ── Ticket counts (used in CTA buttons) ───────────────────────────\r\n ticket: 'ticket',\r\n tickets: 'tickets',\r\n\r\n // ── Checkout form (public-calendar-flow) ───────────────────────────────\r\n yourDetails: 'Your details',\r\n attendeeDetails: 'Attendee details',\r\n attendee: 'Attendee',\r\n sameAsPurchaser: 'Same as purchaser',\r\n payment: 'Payment',\r\n noPaymentRequired: 'No payment required',\r\n freeEventMessage:\r\n 'This is a free event. Complete the form above to reserve your spot.',\r\n firstName: 'First name',\r\n lastName: 'Last name',\r\n emailAddress: 'Email address',\r\n email: 'Email',\r\n emailPlaceholder: 'you@example.com',\r\n attendeeEmailPlaceholder: 'attendee@example.com',\r\n cardNumber: 'Card number',\r\n cardPlaceholder: '4242 4242 4242 4242',\r\n expiryDate: 'Expiry date',\r\n expiryPlaceholder: 'MM / YY',\r\n cvc: 'CVC',\r\n cvcPlaceholder: '123',\r\n keepMeUpdated: 'Keep me updated about this event and similar events',\r\n agreeToTerms: 'I agree to the terms and conditions',\r\n goBack: 'Go back',\r\n loadingPaymentForm: 'Loading secure payment form...',\r\n\r\n // ── Checkout form validation ──────────────────────────────────────\r\n firstNameRequired: 'First name is required',\r\n lastNameRequired: 'Last name is required',\r\n emailRequired: 'Email is required',\r\n emailInvalid: 'Enter a valid email address',\r\n emailInvalidShort: 'Enter a valid email',\r\n cardNumberRequired: 'Card number is required',\r\n expiryRequired: 'Expiry date is required',\r\n cvcRequired: 'CVC is required',\r\n mustAgreeTerms: 'You must agree to the terms',\r\n\r\n // ── Place order CTAs ──────────────────────────────────────────────\r\n placeOrder: 'Place order',\r\n completeOrder: 'Complete order',\r\n placingOrder: 'Placing order...',\r\n\r\n // ── Promo code ────────────────────────────────────────────────────\r\n havePromoCode: 'Have a promo code?',\r\n promoCode: 'Promo code',\r\n enterCode: 'Enter code',\r\n apply: 'Apply',\r\n remove: 'Remove',\r\n removePromoCode: 'Remove promo code',\r\n applyPromoCode: 'Apply promo code',\r\n checkingPromoCode: 'Checking promo code',\r\n checking: 'Checking...',\r\n promoApplied: 'Promo applied',\r\n\r\n // ── Navigation tabs (app-segments) ────────────────────────────────\r\n about: 'About',\r\n ticketsTab: 'Tickets',\r\n eventSections: 'Event sections',\r\n\r\n // ── Event details ─────────────────────────────────────────────────\r\n eventDetails: 'Event details',\r\n performers: 'Performers',\r\n faq: 'FAQ',\r\n frequentlyAskedQuestions: 'Frequently asked questions',\r\n doors: 'Doors',\r\n doorsOpenAt: 'Doors open at',\r\n\r\n // ── Series occurrences ────────────────────────────────────────────\r\n upcomingDates: 'Upcoming dates',\r\n\r\n // ── Close / dismiss ───────────────────────────────────────────────\r\n closeTicketSelection: 'Close ticket selection',\r\n closeTicketSelector: 'Close ticket selector',\r\n\r\n // ── Accessibility ─────────────────────────────────────────────────\r\n ticketSelection: 'ticket selection',\r\n ticketsSelected: 'tickets selected',\r\n view: 'View',\r\n\r\n // ── Success page (public-calendar-flow) ────────────────────────────────\r\n youreIn: \"You're in\",\r\n youreRegistered: \"You're registered\",\r\n confirmed: 'confirmed',\r\n viewTickets: 'View tickets',\r\n order: 'Order',\r\n confirmationSentTo: 'Confirmation sent to',\r\n addToCalendar: 'Add to calendar',\r\n googleCalendar: 'Google Calendar',\r\n appleCalendar: 'Apple Calendar (.ics)',\r\n share: 'Share',\r\n map: 'Map',\r\n backToEvent: 'Back to event',\r\n needHelp: 'Need help?',\r\n linkCopied: 'Link copied to clipboard',\r\n copyLink: 'Copy this link:',\r\n addToAppleWallet: 'Add to Apple Wallet',\r\n saveToGoogleWallet: 'Save to Google Wallet',\r\n\r\n // ── Session timer / expiration modals ─────────────────────────────\r\n sessionExpiringSoon: 'Session expiring soon',\r\n sessionExpiringSoonMessage:\r\n 'Your checkout session will expire in {time}. Your selected tickets will be released back to inventory.',\r\n extensionsRemaining: '{count} extension{plural} remaining',\r\n continueCheckout: 'Continue checkout',\r\n okIllHurry: \"OK, I'll hurry\",\r\n maxExtensionsReached: 'Maximum extensions reached',\r\n wantToKeepTickets: 'Want to keep your tickets?',\r\n sessionExpiredMessage:\r\n 'Your checkout session has expired and your selected tickets have been released.',\r\n sessionExpired: 'Session expired',\r\n reservationTimedOut:\r\n 'Your reservation has timed out. Please select your tickets again to continue.',\r\n keepMyTickets: 'Keep my tickets',\r\n selectTicketsAgain: 'Select tickets again',\r\n extendingSession: 'Extending...',\r\n\r\n // ── MobileCta ─────────────────────────────────────────────────────\r\n selectTicketsLabel: 'Select tickets',\r\n\r\n // ── Waitlist (sold-out gating + tokenized unlock) ─────────────────\r\n joinWaitlist: 'Join waitlist',\r\n getNotifiedWhenAvailable: 'Get notified when tickets are available',\r\n // Tokenized-link unlock outcomes (decisions #3/#22/#36). Mapped from the\r\n // server's failure enum; shown as a small dismissible notice near the CTA.\r\n waitlistLinkInvalid:\r\n \"This link isn't valid. You're still on the waitlist — we'll email you if tickets free up.\",\r\n waitlistLinkExpired: \"This link has expired. You're still on the waitlist.\",\r\n waitlistLinkUsed:\r\n \"This link has already been used. You're still on the waitlist.\",\r\n waitlistLinkEmailMismatch:\r\n \"This link was sent to a different email address. You're still on the waitlist.\",\r\n waitlistLinkInventoryExhausted:\r\n \"Those tickets were just claimed. You're still on the waitlist — we'll email you if more free up.\",\r\n dismiss: 'Dismiss',\r\n};\r\n\r\n/**\r\n * Merge user-provided label overrides with the defaults.\r\n * Shallow merge — any key provided by the consumer wins.\r\n *\r\n * @param {Record<string, string>} [userLabels] - Partial label overrides\r\n * @returns {Record<string, string>} Merged labels object\r\n */\r\nexport function mergeLabels(userLabels = {}) {\r\n return { ...defaultLabels, ...userLabels };\r\n}\r\n"],"names":["size","$","$$props","color","className","ctx","useIconWeight","resolved","svg","root_2","path","root","$$render","consequent","alternate","styles","computeCtaState","event","tickets","options","cancelled","isRegistration","waitlistEnabled","now","browserNow","eventEnd","hiddenAvailable","isHiddenTicketPurchasable","publicTickets","t","hasPurchasable","allSoldOut","allComingSoon","earliestSalesStart","ticket","salesBegin","salesEnd","remaining","isSoldOut","isScheduled","hasSalesEnded","startDate","diffMs","diffHours","diffDays","timeLabel","d","formatLocal","dateText","getScarcityLevel","total","level","computeScarcityLevel","getScarcityText","context","SCARCITY_THRESHOLDS","getCtaConfig","apiTickets","result","toFriendlyReason","reason","getPriceDisplay","visibleTickets","hasDonation","paidTickets","hasFree","pricedTickets","minPrice","calculateTax","amount","taxPercentage","roundCurrency","DURATION","createDefaultPromoState","labels","mode","div","root_3","node_1","line","div_1","Text","node_2","text","node_3","formatCurrency","formatPriceOrFree","div_2","root_1","node_6","node_7","$0","text_3","div_3","node_8","node_9","text_5","consequent_1","consequent_2","div_4","node_11","node_12","text_7","consequent_3","div_5","node_14","node_15","text_9","consequent_4","div_6","node_17","node_18","text_11","consequent_5","div_7","node_20","node_21","text_13","consequent_6","div_8","node_19","node_22","node_23","text_15","consequent_7","defaultLabels","mergeLabels","userLabels"],"mappings":"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","x_google_ignoreList":[0]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"showcase-state-options-DJJdjxvZ.js","sources":["../src/lib/public-calendar-flow/mock-data.ts","../src/lib/public-calendar-flow/data-toggle-store.svelte.ts","../src/lib/public-calendar-flow/showcase-state-options.ts"],"sourcesContent":["import { getDefaultTimezone } from '@getmicdrop/svelte-components/utils/timezones';\r\n// Premium Ticket Experience — Mock Data\r\n// Realistic event data for all design variants. DO NOT MODIFY per-variant.\r\n\r\nimport type {\r\n EventData,\r\n PerformerData,\r\n FAQItem,\r\n VenueData,\r\n TicketTypeData,\r\n} from './types';\r\n\r\n// All dates here are anchored to \"the upcoming Friday at 8pm\" so the showcase\r\n// stays in the future regardless of when it's loaded. Hardcoded calendar dates\r\n// rot every few months and cause `event_past` CTAs even when status === 'on_sale'.\r\nfunction showcaseDate(\r\n daysFromFriday: number,\r\n hour: number,\r\n minute = 0\r\n): string {\r\n const now = new Date(); // @datetime-escape: mock/demo fixture data — not a live datetime path\r\n const day = now.getUTCDay(); // 0=Sun..6=Sat\r\n const daysToFriday = (5 - day + 7) % 7 || 7; // always the NEXT Friday (never today)\r\n // @datetime-escape: mock/demo fixture data — not a live datetime path\r\n const base = new Date(\r\n Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())\r\n );\r\n base.setUTCDate(base.getUTCDate() + daysToFriday + daysFromFriday);\r\n const y = base.getUTCFullYear();\r\n const m = String(base.getUTCMonth() + 1).padStart(2, '0');\r\n const d = String(base.getUTCDate()).padStart(2, '0');\r\n const hh = String(hour).padStart(2, '0');\r\n const mm = String(minute).padStart(2, '0');\r\n return `${y}-${m}-${d}T${hh}:${mm}:00-08:00`;\r\n}\r\n\r\nfunction showcaseDateOnly(daysFromFriday: number): string {\r\n return showcaseDate(daysFromFriday, 0).slice(0, 10);\r\n}\r\n\r\n// --- Venue ---\r\nexport const mockVenue: VenueData = {\r\n id: 101,\r\n name: 'The Laugh Factory',\r\n address: '8001 Sunset Blvd, Los Angeles, CA 90046',\r\n timezone: getDefaultTimezone(),\r\n serviceFeePercentage: 10,\r\n serviceFeeCents: 0,\r\n taxPercentage: 9.5,\r\n contactEmail: 'help@thelaughfactory.com',\r\n};\r\n\r\n// --- Performers ---\r\nexport const mockPerformers: PerformerData[] = [\r\n {\r\n id: 1,\r\n displayName: 'Dave Martinez',\r\n profileImage:\r\n 'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?w=200&h=200&fit=crop',\r\n },\r\n {\r\n id: 2,\r\n displayName: 'Sarah Chen',\r\n profileImage:\r\n 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200&h=200&fit=crop',\r\n },\r\n {\r\n id: 3,\r\n displayName: 'Mike Thompson',\r\n profileImage:\r\n 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=200&h=200&fit=crop',\r\n },\r\n];\r\n\r\n// --- FAQs ---\r\nexport const mockFaqs: FAQItem[] = [\r\n {\r\n question: 'What time do doors open?',\r\n answer:\r\n 'Doors open at 7:00 PM, one hour before showtime. We recommend arriving early to get the best seats.',\r\n },\r\n {\r\n question: 'Is there a drink minimum?',\r\n answer:\r\n 'Yes, there is a 2-drink minimum per person. Both alcoholic and non-alcoholic beverages count toward the minimum.',\r\n },\r\n {\r\n question: 'Can I get a refund?',\r\n answer:\r\n 'Tickets are non-refundable but can be transferred to another person up to 24 hours before the show. Contact us for transfers.',\r\n },\r\n {\r\n question: 'Is the venue accessible?',\r\n answer:\r\n 'Yes, the venue is fully wheelchair accessible with ADA-compliant seating available. Please contact us to reserve accessible seating.',\r\n },\r\n];\r\n\r\n// --- Ticket Types ---\r\nexport const mockTickets: TicketTypeData[] = [\r\n\t{\r\n\t\tid: 101,\r\n\t\tname: 'General Admission',\r\n\t\tdescription: 'Standard seating in the main room',\r\n\t\tprice: 25,\r\n\t\tfee: 2.5,\r\n\t\tquantityAvailable: 12,\r\n\t\tquantityTotal: 150,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 8,\r\n\t\tstatus: 'on_sale',\r\n\t\tsalesEndDate: '2026-02-20T20:00:00-08:00',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 102,\r\n\t\tname: 'VIP Front Row',\r\n\t\tdescription: 'Premium seats in the first two rows with a complimentary drink',\r\n\t\tprice: 55,\r\n\t\tfee: 5.5,\r\n\t\tquantityAvailable: 3,\r\n\t\tquantityTotal: 20,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 4,\r\n\t\tstatus: 'on_sale',\r\n\t\tsalesEndDate: '2026-02-20T20:00:00-08:00',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 103,\r\n\t\tname: 'Table for 4',\r\n\t\tdescription: 'Reserved table for four guests with bottle service',\r\n\t\tprice: 180,\r\n\t\tfee: 18,\r\n\t\tquantityAvailable: 8,\r\n\t\tquantityTotal: 15,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 3,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 104,\r\n\t\tname: 'Student Discount',\r\n\t\tdescription: 'Valid student ID required at the door',\r\n\t\tprice: 15,\r\n\t\tfee: 1.5,\r\n\t\tquantityAvailable: 45,\r\n\t\tquantityTotal: 50,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 2,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 105,\r\n\t\tname: 'Early Bird Special',\r\n\t\tdescription: 'Limited early bird pricing — first come, first served',\r\n\t\tprice: 20,\r\n\t\tfee: 2,\r\n\t\tquantityAvailable: 15,\r\n\t\tquantityTotal: 30,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 4,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 106,\r\n\t\tname: 'Senior (65+)',\r\n\t\tdescription: 'Senior discount with valid ID at the door',\r\n\t\tprice: 18,\r\n\t\tfee: 1.8,\r\n\t\tquantityAvailable: 30,\r\n\t\tquantityTotal: 40,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 4,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 107,\r\n\t\tname: 'Industry Comp',\r\n\t\tdescription: 'Discount for industry professionals — credentials required',\r\n\t\tprice: 12,\r\n\t\tfee: 1.2,\r\n\t\tquantityAvailable: 25,\r\n\t\tquantityTotal: 30,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 2,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 108,\r\n\t\tname: 'Group of 6',\r\n\t\tdescription: 'Reserved booth for six guests with priority seating',\r\n\t\tprice: 240,\r\n\t\tfee: 24,\r\n\t\tquantityAvailable: 5,\r\n\t\tquantityTotal: 8,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 2,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 109,\r\n\t\tname: 'Standing Room',\r\n\t\tdescription: 'Standing room only at the back of the venue',\r\n\t\tprice: 12,\r\n\t\tfee: 1.2,\r\n\t\tquantityAvailable: 50,\r\n\t\tquantityTotal: 60,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 6,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 110,\r\n\t\tname: 'Day-of Door',\r\n\t\tdescription: 'Day-of pricing for walk-ins — limited availability',\r\n\t\tprice: 35,\r\n\t\tfee: 3.5,\r\n\t\tquantityAvailable: 20,\r\n\t\tquantityTotal: 25,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 4,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t}\r\n];\r\n\r\n// --- Main Event (on sale, multiple ticket types, scarcity on VIP) ---\r\n// Computed relative to today (showcase use): always lands ~21 days in the\r\n// future so the BookingWidget renders the on-sale state, not \"Sales ended\".\r\n// Memory: [[user_mastermind_date_awareness]] — never hardcode showcase dates.\r\nconst _now = new Date(); // @datetime-escape: mock/demo fixture data — not a live datetime path\r\nconst _evDate = new Date(_now.getFullYear(), _now.getMonth(), _now.getDate() + 21); // @datetime-escape: mock/demo fixture data — not a live datetime path\r\nconst _ymd = `${_evDate.getFullYear()}-${String(_evDate.getMonth() + 1).padStart(2, '0')}-${String(_evDate.getDate()).padStart(2, '0')}`;\r\n\r\nexport const mockEvent: EventData = {\r\n id: 2405,\r\n title: 'Friday Night Comedy Throwdown',\r\n slug: 'friday-night-comedy-throwdown',\r\n description: `Get ready for the funniest night of the week! The Friday Night Comedy Throwdown brings together three of LA's hottest stand-up comics for two hours of non-stop laughs.\r\n\r\nHeadliner Dave Martinez (as seen on Netflix's \"Comedy Knockout\") brings his signature high-energy style, while Sarah Chen delivers her razor-sharp observational humor that's earned her a devoted following. Host Mike Thompson keeps the energy up between sets with crowd work that'll have you crying laughing.\r\n\r\nWhether you're a comedy regular or a first-timer, this show delivers. Grab your crew, grab some drinks, and prepare to laugh until your abs hurt.`,\r\n\tdate: _ymd,\r\n\tstartDateTime: `${_ymd}T20:00:00-08:00`,\r\n\tendDateTime: `${_ymd}T22:00:00-08:00`,\r\n\tdoorsOpenTime: `${_ymd}T19:00:00-08:00`,\r\n\ttimezone: 'America/Los_Angeles',\r\n\timageUrl: '/posters/Friday Night Showdown.jpg', // wide landscape 800×400\r\n\tvenue: mockVenue,\r\n\tperformers: mockPerformers,\r\n\ttickets: mockTickets,\r\n\tfaqs: mockFaqs,\r\n\tdisclaimer: '',\r\n\tstatus: 'on_sale',\r\n\tisPasswordProtected: false,\r\n\tisRegistrationEvent: false,\r\n\ttotalTicketsRemaining: 68,\r\n\ttotalTicketsCapacity: 265,\r\n\tdisplayStartTime: true,\r\n\tdisplayEndTime: true,\r\n\tdisplayDoorsTime: true\r\n};\r\n\r\n// --- Sold Out Event (no end time shown) ---\r\nexport const mockSoldOutEvent: EventData = {\r\n ...mockEvent,\r\n id: 2406,\r\n title: 'Saturday Night Special',\r\n slug: 'saturday-night-special',\r\n imageUrl: '/posters/the-duel-square.webp', // square 3000×3000\r\n date: showcaseDateOnly(1),\r\n startDateTime: showcaseDate(1, 21),\r\n endDateTime: showcaseDate(1, 23),\r\n displayEndTime: false,\r\n status: 'sold_out',\r\n totalTicketsRemaining: 0,\r\n tickets: mockTickets.map(t => ({\r\n ...t,\r\n quantityAvailable: 0,\r\n status: 'sold_out' as const,\r\n })),\r\n};\r\n\r\n// --- Free Event (no doors time shown) ---\r\nexport const mockFreeEvent: EventData = {\r\n ...mockEvent,\r\n id: 2407,\r\n title: 'Open Mic Night',\r\n slug: 'open-mic-night',\r\n imageUrl: '/posters/OpenMic-Twitter.jpg', // wide landscape 2127×1075\r\n date: showcaseDateOnly(-2),\r\n startDateTime: showcaseDate(-2, 19),\r\n endDateTime: showcaseDate(-2, 21),\r\n displayDoorsTime: false,\r\n description:\r\n 'Free open mic night! Sign up at the door. All skill levels welcome.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 201,\r\n name: 'Free Entry',\r\n description: 'Sign up at the door for a 5-minute set',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 40,\r\n quantityTotal: 50,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n ],\r\n totalTicketsRemaining: 40,\r\n totalTicketsCapacity: 50,\r\n};\r\n\r\n// --- Series Event (with occurrences) ---\r\nexport const mockSeriesEvent: EventData = {\r\n ...mockEvent,\r\n id: 2410,\r\n title: 'Improv Throwdown',\r\n slug: 'improv-throwdown',\r\n imageUrl: '/posters/laughlab-tall.webp', // tall portrait 2550×3300\r\n eventSeriesId: 42,\r\n description:\r\n 'Weekly improv comedy show featuring rotating guest performers and audience participation games.',\r\n seriesOccurrences: [\r\n // Same-day shows (Fri Feb 20 — 7pm, 8pm, 9:30pm)\r\n {\r\n id: 2410,\r\n slug: 'improv-throwdown-feb-20-7pm',\r\n startDateTime: showcaseDate(0, 19),\r\n endDateTime: showcaseDate(0, 20, 30),\r\n status: 'sold_out',\r\n ctaText: 'Sold out',\r\n ctaDisabled: true,\r\n },\r\n {\r\n id: 2414,\r\n slug: 'improv-throwdown-feb-20-8pm',\r\n startDateTime: showcaseDate(0, 20),\r\n endDateTime: showcaseDate(0, 21, 30),\r\n status: 'on_sale',\r\n ctaText: 'Get tickets',\r\n ctaDisabled: false,\r\n },\r\n {\r\n id: 2415,\r\n slug: 'improv-throwdown-feb-20-930pm',\r\n startDateTime: showcaseDate(0, 21, 30),\r\n endDateTime: showcaseDate(0, 23),\r\n status: 'on_sale',\r\n ctaText: 'Get tickets',\r\n ctaDisabled: false,\r\n },\r\n // Single show days\r\n {\r\n id: 2411,\r\n slug: 'improv-throwdown-feb-27',\r\n startDateTime: showcaseDate(7, 20),\r\n endDateTime: showcaseDate(7, 22),\r\n status: 'sold_out',\r\n ctaText: 'Sold out',\r\n ctaDisabled: true,\r\n },\r\n {\r\n id: 2412,\r\n slug: 'improv-throwdown-mar-06',\r\n startDateTime: showcaseDate(14, 20),\r\n endDateTime: showcaseDate(14, 22),\r\n status: 'on_sale',\r\n ctaText: 'Get tickets',\r\n ctaDisabled: false,\r\n },\r\n {\r\n id: 2413,\r\n slug: 'improv-throwdown-mar-13',\r\n startDateTime: showcaseDate(21, 20),\r\n endDateTime: showcaseDate(21, 22),\r\n status: 'coming_soon',\r\n ctaText: 'Coming soon',\r\n ctaDisabled: true,\r\n },\r\n ],\r\n};\r\n\r\n// --- Series Instance (one specific occurrence of the series — regular event page with series link) ---\r\nexport const mockSeriesInstanceEvent: EventData = {\r\n ...mockEvent,\r\n id: 2414,\r\n title: 'Improv Throwdown',\r\n slug: 'improv-throwdown-feb-20-8pm',\r\n imageUrl: '/posters/laughlab-tall.webp',\r\n eventSeriesId: 42,\r\n startDateTime: showcaseDate(0, 20),\r\n endDateTime: showcaseDate(0, 21, 30),\r\n description:\r\n 'Weekly improv comedy show featuring rotating guest performers and audience participation games.',\r\n // No seriesOccurrences — this is a single instance, not the series home\r\n};\r\n\r\n// --- Collection Home (loose grouping of different events with widgets) ---\r\nexport const mockCollectionEvent: EventData = {\r\n ...mockEvent,\r\n id: 3000,\r\n title: 'February Comedy Festival',\r\n slug: 'february-comedy-festival',\r\n imageUrl: '/posters/Friday Night Showdown.jpg',\r\n description:\r\n \"A curated collection of the best comedy shows this February. From improv to stand-up, sketch to open mic — there's something for every comedy fan.\",\r\n collectionId: 7,\r\n collectionEvents: [\r\n {\r\n id: 2401,\r\n name: 'Friday Night Comedy Throwdown',\r\n slug: 'friday-night-comedy-throwdown',\r\n image: '/posters/Friday Night Showdown.jpg',\r\n startDateTime: showcaseDate(0, 20),\r\n status: 'on_sale',\r\n ticketsRemaining: 42,\r\n ticketsTotal: 200,\r\n },\r\n {\r\n id: 2402,\r\n name: 'Saturday Night Special',\r\n slug: 'saturday-night-special',\r\n image: '/posters/the-duel-square.webp',\r\n startDateTime: showcaseDate(1, 21),\r\n status: 'on_sale',\r\n ticketsRemaining: 8,\r\n ticketsTotal: 150,\r\n },\r\n {\r\n id: 2403,\r\n name: 'Stand-Up Comedy Workshop',\r\n slug: 'standup-comedy-workshop',\r\n image: '/posters/stand up 101.png',\r\n startDateTime: showcaseDate(2, 14),\r\n status: 'on_sale',\r\n ticketsRemaining: 15,\r\n ticketsTotal: 30,\r\n },\r\n {\r\n id: 2410,\r\n name: 'Improv Throwdown',\r\n slug: 'improv-throwdown',\r\n image: '/posters/laughlab-tall.webp',\r\n startDateTime: showcaseDate(7, 20),\r\n status: 'on_sale',\r\n ticketsRemaining: 65,\r\n ticketsTotal: 200,\r\n },\r\n {\r\n id: 2404,\r\n name: 'Open Mic Night',\r\n slug: 'open-mic-night',\r\n image: '/posters/OpenMic-Twitter.jpg',\r\n startDateTime: showcaseDate(8, 19),\r\n status: 'on_sale',\r\n ticketsRemaining: 100,\r\n ticketsTotal: 100,\r\n },\r\n {\r\n id: 2405,\r\n name: 'Late Night Comedy Underground',\r\n slug: 'late-night-comedy-underground',\r\n image: '/posters/standup-portrait.webp',\r\n startDateTime: showcaseDate(8, 22),\r\n status: 'sold_out',\r\n ticketsRemaining: 0,\r\n ticketsTotal: 80,\r\n },\r\n ],\r\n};\r\n\r\n// --- Registration Event (workshop — no time shown, just date + doors) ---\r\nexport const mockRegistrationEvent: EventData = {\r\n ...mockEvent,\r\n id: 2408,\r\n title: 'Stand-Up Comedy Workshop',\r\n slug: 'standup-comedy-workshop',\r\n imageUrl: '/posters/stand up 101.png', // 16:9 landscape 1920×1080\r\n description:\r\n 'Learn the fundamentals of stand-up comedy in this 3-hour intensive workshop. Write, refine, and perform your first 5-minute set.',\r\n isRegistrationEvent: true,\r\n displayStartTime: false,\r\n displayEndTime: false,\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 301,\r\n name: 'Workshop Seat',\r\n description: 'Includes materials and performance slot',\r\n price: 75,\r\n fee: 7.5,\r\n quantityAvailable: 8,\r\n quantityTotal: 12,\r\n minPerOrder: 1,\r\n maxPerOrder: 1,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n ],\r\n totalTicketsRemaining: 8,\r\n totalTicketsCapacity: 12,\r\n};\r\n\r\n// --- Donation Event ---\r\nexport const mockDonationEvent: EventData = {\r\n ...mockEvent,\r\n id: 2414,\r\n title: 'Charity Comedy Benefit',\r\n slug: 'charity-comedy-benefit',\r\n imageUrl: '/posters/Friday Night Showdown.jpg',\r\n description:\r\n 'All proceeds go to the LA Comedy Relief Fund. Choose your own donation amount or grab a standard ticket.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 401,\r\n name: 'Donation',\r\n description: 'Support the cause — choose your amount',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 200,\r\n quantityTotal: 200,\r\n minPerOrder: 1,\r\n maxPerOrder: 10,\r\n status: 'on_sale',\r\n isDonation: true,\r\n isHidden: false,\r\n ticketType: 2,\r\n },\r\n {\r\n id: 402,\r\n name: 'Standard Admission',\r\n description: 'Includes one drink ticket',\r\n price: 30,\r\n fee: 3,\r\n quantityAvailable: 80,\r\n quantityTotal: 100,\r\n minPerOrder: 1,\r\n maxPerOrder: 6,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n ],\r\n totalTicketsRemaining: 280,\r\n totalTicketsCapacity: 300,\r\n};\r\n\r\n// --- Mixed Event (ALL ticket states in one event) ---\r\nexport const mockMixedEvent: EventData = {\r\n ...mockEvent,\r\n id: 2415,\r\n title: 'The Everything Show',\r\n slug: 'the-everything-show',\r\n imageUrl: '/posters/the-duel-square.webp',\r\n description:\r\n 'A showcase event with every ticket state possible — for testing all edge cases.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 501,\r\n name: 'General Admission',\r\n description: 'Standard seating in the main room',\r\n price: 25,\r\n fee: 2.5,\r\n quantityAvailable: 45,\r\n quantityTotal: 150,\r\n minPerOrder: 1,\r\n maxPerOrder: 8,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 502,\r\n name: 'Basic Entry',\r\n price: 15,\r\n fee: 1.5,\r\n quantityAvailable: 60,\r\n quantityTotal: 80,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 503,\r\n name: 'VIP Front Row',\r\n description: 'Premium seats with complimentary drink',\r\n price: 75,\r\n fee: 7.5,\r\n quantityAvailable: 2,\r\n quantityTotal: 20,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 504,\r\n name: 'Early Bird',\r\n description: 'Limited early bird pricing',\r\n price: 20,\r\n fee: 2,\r\n quantityAvailable: 0,\r\n quantityTotal: 30,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'sold_out',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 505,\r\n name: 'Late Night Add-On',\r\n description: 'Access to the after-party at midnight',\r\n price: 40,\r\n fee: 4,\r\n quantityAvailable: 50,\r\n quantityTotal: 50,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'coming_soon',\r\n salesStartDate: showcaseDate(9, 10),\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 506,\r\n name: 'Weekend Bundle',\r\n description: 'Includes Saturday + Sunday shows',\r\n price: 45,\r\n fee: 4.5,\r\n quantityAvailable: 0,\r\n quantityTotal: 25,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'sales_ended',\r\n salesEndDate: showcaseDate(-10, 23, 59),\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 507,\r\n name: 'Donation',\r\n description: 'Support the performers directly',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 100,\r\n quantityTotal: 100,\r\n minPerOrder: 1,\r\n maxPerOrder: 5,\r\n status: 'on_sale',\r\n isDonation: true,\r\n isHidden: false,\r\n ticketType: 2,\r\n },\r\n {\r\n id: 508,\r\n name: 'Secret VIP Lounge',\r\n description: 'Backstage access with meet & greet',\r\n price: 150,\r\n fee: 15,\r\n quantityAvailable: 10,\r\n quantityTotal: 10,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n {\r\n id: 509,\r\n name: 'Industry Comp',\r\n description: 'Complimentary ticket for industry professionals',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 20,\r\n quantityTotal: 20,\r\n minPerOrder: 1,\r\n maxPerOrder: 1,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n ],\r\n totalTicketsRemaining: 287,\r\n totalTicketsCapacity: 485,\r\n};\r\n\r\n// --- Sectioned Event (tickets grouped by section) ---\r\nexport const mockSectionedEvent: EventData = {\r\n ...mockEvent,\r\n id: 2416,\r\n title: 'Multi-Stage Festival',\r\n slug: 'multi-stage-festival',\r\n imageUrl: '/posters/OpenMic-Twitter.jpg',\r\n description:\r\n 'Three stages, one incredible night. Choose your zone and enjoy performances across the venue.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 601,\r\n name: 'Floor Standing',\r\n description: 'Standing room on the main floor',\r\n price: 35,\r\n fee: 3.5,\r\n quantityAvailable: 100,\r\n quantityTotal: 200,\r\n minPerOrder: 1,\r\n maxPerOrder: 8,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n sectionName: 'Floor',\r\n },\r\n {\r\n id: 602,\r\n name: 'Floor Reserved',\r\n description: 'Reserved seat on the main floor',\r\n price: 50,\r\n fee: 5,\r\n quantityAvailable: 30,\r\n quantityTotal: 80,\r\n minPerOrder: 1,\r\n maxPerOrder: 6,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n sectionName: 'Floor',\r\n },\r\n {\r\n id: 603,\r\n name: 'Balcony Standard',\r\n description: 'Standard balcony seating with great views',\r\n price: 40,\r\n fee: 4,\r\n quantityAvailable: 50,\r\n quantityTotal: 60,\r\n minPerOrder: 1,\r\n maxPerOrder: 6,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n sectionName: 'Balcony',\r\n },\r\n {\r\n id: 604,\r\n name: 'Balcony Premium',\r\n description: 'Front-row balcony seats',\r\n price: 60,\r\n fee: 6,\r\n quantityAvailable: 5,\r\n quantityTotal: 20,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n sectionName: 'Balcony',\r\n },\r\n {\r\n id: 605,\r\n name: 'VIP Lounge Table',\r\n description:\r\n 'Private table for 4 with bottle service and backstage access',\r\n price: 250,\r\n fee: 25,\r\n quantityAvailable: 3,\r\n quantityTotal: 8,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n sectionName: 'VIP Lounge',\r\n },\r\n ],\r\n totalTicketsRemaining: 188,\r\n totalTicketsCapacity: 368,\r\n};\r\n\r\n// --- Promo Event (hidden tickets for promo reveal testing) ---\r\nexport const mockPromoEvent: EventData = {\r\n ...mockEvent,\r\n id: 2417,\r\n title: 'Secret Show',\r\n slug: 'secret-show',\r\n imageUrl: '/posters/luke-null-tall.webp',\r\n description:\r\n 'An intimate comedy experience. Some tickets are only available with a promo code.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 701,\r\n name: 'General Admission',\r\n price: 30,\r\n fee: 3,\r\n quantityAvailable: 40,\r\n quantityTotal: 60,\r\n minPerOrder: 1,\r\n maxPerOrder: 6,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 702,\r\n name: 'Premium Seat',\r\n description: 'Reserved seating in rows 1-5',\r\n price: 50,\r\n fee: 5,\r\n quantityAvailable: 15,\r\n quantityTotal: 30,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 703,\r\n name: 'Artist Meet & Greet',\r\n description:\r\n 'Backstage pass with photo opportunity — promo code required',\r\n price: 100,\r\n fee: 10,\r\n quantityAvailable: 8,\r\n quantityTotal: 10,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n {\r\n id: 704,\r\n name: 'Industry Comp',\r\n description: 'Complimentary entry for industry professionals',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 10,\r\n quantityTotal: 10,\r\n minPerOrder: 1,\r\n maxPerOrder: 1,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n ],\r\n totalTicketsRemaining: 73,\r\n totalTicketsCapacity: 110,\r\n};\r\n\r\n// --- Hidden-Only Event (MIC-1039) — no visible tickets, only hidden remain ---\r\n// Lands the user on a page where the only purchasable seats are gated behind\r\n// a promo code. With zero visible tickets the page should suppress the ticket\r\n// list entirely and render only the PromoCodeInput.\r\nexport const mockHiddenOnlyEvent: EventData = {\r\n ...mockEvent,\r\n id: 2419,\r\n title: 'Industry Showcase',\r\n slug: 'industry-showcase',\r\n description:\r\n 'A private comedy showcase. Tickets are only available with a promo code.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 902,\r\n name: 'Industry Comp',\r\n description:\r\n 'Complimentary entry for industry professionals — promo code required',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 15,\r\n quantityTotal: 20,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n {\r\n id: 903,\r\n name: 'Artist Hold',\r\n description: 'Held for artist guests — promo code required',\r\n price: 50,\r\n fee: 5,\r\n quantityAvailable: 5,\r\n quantityTotal: 10,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n ],\r\n totalTicketsRemaining: 0,\r\n totalTicketsCapacity: 0,\r\n};\r\n\r\n// --- Multi-Stage Event (stage name + age restriction) ---\r\nexport const mockMultiStageEvent: EventData = {\r\n ...mockEvent,\r\n id: 2418,\r\n title: 'Late Night Comedy Underground',\r\n slug: 'late-night-comedy-underground',\r\n imageUrl: '/posters/laughlab-tall.webp',\r\n description:\r\n 'The raunchiest, most unfiltered comedy night in LA. Side stage, no holds barred.',\r\n status: 'on_sale',\r\n stageName: 'Side Stage',\r\n ageRestriction: 21,\r\n displayAgeRestriction: true,\r\n tickets: [\r\n {\r\n id: 801,\r\n name: 'General Admission',\r\n price: 20,\r\n fee: 2,\r\n quantityAvailable: 25,\r\n quantityTotal: 40,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 802,\r\n name: 'VIP Booth',\r\n description: 'Reserved booth for 2 with drinks included',\r\n price: 80,\r\n fee: 8,\r\n quantityAvailable: 4,\r\n quantityTotal: 6,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n ],\r\n totalTicketsRemaining: 29,\r\n totalTicketsCapacity: 46,\r\n};\r\n\r\n// --- Long Name Event (Laugh Factory-style: all performers in the title) ---\r\nexport const mockLongNameEvent: EventData = {\r\n ...mockEvent,\r\n id: 2420,\r\n title:\r\n 'The Friday Night All-Star Comedy Throwdown featuring Dave Martinez, Sarah Chen, Mike Thompson, Bobby Lee, Andrew Santino, Hasan Minhaj, and Very Special Guests from Netflix, Comedy Central, HBO, and Amazon Prime',\r\n slug: 'the-friday-night-all-star-comedy-throwdown',\r\n imageUrl: '/posters/laughlab-tall.webp',\r\n description: `The biggest lineup of the year! Seven of the hottest comics in LA on one stage for one unforgettable night. This is the show comedy fans have been waiting for — a stacked bill from top to bottom with headliners you've seen on every major streaming platform.\r\n\r\nDave Martinez (Netflix's \"Comedy Knockout\") headlines with his signature high-energy style. Sarah Chen brings her razor-sharp observational humor. Mike Thompson keeps the energy sky-high between sets. Bobby Lee delivers his unhinged brilliance. Andrew Santino roasts everything in sight. Hasan Minhaj brings the political heat. Plus surprise guests you won't want to miss.\r\n\r\nTwo-drink minimum. No photography or recording. Arrive early — seating is first come, first served.`,\r\n ageRestriction: 18,\r\n displayAgeRestriction: true,\r\n displayStartTime: true,\r\n displayEndTime: true,\r\n displayDoorsTime: true,\r\n performers: [\r\n ...mockPerformers,\r\n {\r\n id: 4,\r\n displayName: 'Bobby Lee',\r\n profileImage:\r\n 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=200&h=200&fit=crop',\r\n },\r\n {\r\n id: 5,\r\n displayName: 'Andrew Santino',\r\n profileImage:\r\n 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=200&h=200&fit=crop',\r\n },\r\n {\r\n id: 6,\r\n displayName: 'Hasan Minhaj',\r\n profileImage:\r\n 'https://images.unsplash.com/photo-1519085360753-af0119f7cbe7?w=200&h=200&fit=crop',\r\n },\r\n ],\r\n};\r\n\r\n// --- Wide/Panoramic Image Event (tests min-height behavior) ---\r\nexport const mockWideImageEvent: EventData = {\r\n ...mockEvent,\r\n id: 2421,\r\n title: 'Sunset Sessions: Rooftop Jazz & Cocktails',\r\n slug: 'sunset-sessions-rooftop-jazz',\r\n imageUrl: '/posters/Wide.jpg',\r\n description: `Join us on the rooftop for an evening of smooth jazz, craft cocktails, and stunning sunset views over the city. Featuring a rotating cast of LA's finest jazz musicians in an intimate outdoor setting.\r\n\r\nFull bar available with specialty cocktails curated for the evening. Light bites and small plates from our kitchen. Dress code: smart casual.`,\r\n displayStartTime: true,\r\n displayEndTime: true,\r\n displayDoorsTime: true,\r\n};\r\n\r\n// --- Password Protected Event ---\r\nexport const mockPasswordEvent: EventData = {\r\n ...mockEvent,\r\n id: 2409,\r\n title: 'Secret Comedy Club',\r\n slug: 'secret-comedy-club',\r\n imageUrl: '/posters/luke-null-tall.webp', // tall portrait 625×937\r\n description: 'An exclusive underground comedy experience. Password required.',\r\n isPasswordProtected: true,\r\n status: 'on_sale',\r\n};\r\n","export type DataVariant =\r\n\t| 'default'\r\n\t| 'sold_out'\r\n\t| 'free'\r\n\t| 'registration'\r\n\t| 'series'\r\n\t| 'series_instance'\r\n\t| 'collection'\r\n\t| 'donation'\r\n\t| 'mixed'\r\n\t| 'sections'\r\n\t| 'promo'\r\n\t| 'multi_stage'\r\n\t| 'long'\r\n\t| 'wide';\r\n\r\nexport interface ToggleOption {\r\n\tvalue: string;\r\n\tlabel: string;\r\n\tcolor: string;\r\n}\r\n\r\nclass DataToggleStore {\r\n\tcurrent = $state<string>('default');\r\n\toptions = $state<ToggleOption[]>([]);\r\n\tisActive = $state(false);\r\n}\r\n\r\nexport const dataToggleStore = new DataToggleStore();\r\n","/**\r\n * Canonical state-option sets for the public-calendar-flow showcase.\r\n *\r\n * Per R-PATTERN-01 (canonicals-golden-rules.md): function form is the source,\r\n * static snapshots derive at module init. Every showcase surface that drives\r\n * `dataToggleStore` reads its option set from here — Checkout, Success and\r\n * ShowcaseEvent each used to inline their own array beside the variant union\r\n * they switch on, so the same `{ default, free, registration, donation }` core\r\n * lived in three places and could drift silently.\r\n *\r\n * Ordering is per-surface and deliberate: Checkout lists donation before\r\n * registration, Success lists registration before donation. The sets stay\r\n * distinct rather than merged so no surface's toggle order changes.\r\n */\r\nimport type { ToggleOption } from '$lib/public-calendar-flow/data-toggle-store.svelte';\r\n\r\n/**\r\n * Categorical hues for the showcase toggle dots — keyed by hue role, not by\r\n * state, so each class is named once and reused across every set.\r\n *\r\n * `info` is raw Tailwind palette (`bg-sky-500`) rather than an SC semantic\r\n * token, carried over verbatim from the arrays this module absorbed. It is the\r\n * one non-token hue here; replacing it is a color-category call, not an\r\n * options-array one.\r\n */\r\nconst HUE = {\r\n\tsuccess: 'bg-accent-success',\r\n\tneutral: 'bg-muted-foreground',\r\n\tinfo: 'bg-sky-500',\r\n\tbrand: 'bg-brand-primary',\r\n\tdanger: 'bg-accent-danger',\r\n\twarning: 'bg-accent-warning',\r\n\twarningSubtle: 'bg-status-warning-bg0',\r\n} as const;\r\n\r\nexport function getShowcaseBrowseStates(): ToggleOption[] {\r\n\treturn [\r\n\t\t{ value: 'default', label: 'Default', color: HUE.success },\r\n\t\t{ value: 'empty', label: 'Empty', color: HUE.neutral },\r\n\t\t{ value: 'sparse', label: '2 events', color: HUE.info },\r\n\t\t{ value: 'busy', label: 'Many events', color: HUE.brand },\r\n\t];\r\n}\r\n\r\nexport function getShowcaseCalendarStates(): ToggleOption[] {\r\n\treturn [\r\n\t\t{ value: 'default', label: 'Default', color: HUE.success },\r\n\t\t{ value: 'empty', label: 'Empty month', color: HUE.neutral },\r\n\t\t{ value: 'busy', label: 'Busy month', color: HUE.brand },\r\n\t];\r\n}\r\n\r\nexport function getShowcaseCheckoutStates(): ToggleOption[] {\r\n\treturn [\r\n\t\t{ value: 'default', label: 'Standard', color: HUE.success },\r\n\t\t{ value: 'free', label: 'Free', color: HUE.info },\r\n\t\t{ value: 'donation', label: 'Donation', color: HUE.danger },\r\n\t\t{ value: 'registration', label: 'Registration', color: HUE.brand },\r\n\t\t{ value: 'timer_warning', label: 'Timer warning', color: HUE.warningSubtle },\r\n\t\t{ value: 'expired', label: 'Expired', color: HUE.danger },\r\n\t\t{ value: 'promo', label: 'Promo discount', color: HUE.success },\r\n\t];\r\n}\r\n\r\nexport function getShowcaseSuccessStates(): ToggleOption[] {\r\n\treturn [\r\n\t\t{ value: 'default', label: 'Standard', color: HUE.success },\r\n\t\t{ value: 'free', label: 'Free', color: HUE.info },\r\n\t\t{ value: 'registration', label: 'Registration', color: HUE.brand },\r\n\t\t{ value: 'donation', label: 'Donation', color: HUE.danger },\r\n\t];\r\n}\r\n\r\n/**\r\n * Event showcase picker — five hues cover 14 variants; the label disambiguates.\r\n * `default` reads \"On sale\" and `free` is brand-hued here, unlike Checkout and\r\n * Success: an event is on sale, a checkout is standard.\r\n */\r\nexport function getShowcaseEventStates(): ToggleOption[] {\r\n\treturn [\r\n\t\t{ value: 'default', label: 'On sale', color: HUE.success },\r\n\t\t{ value: 'sold_out', label: 'Sold out', color: HUE.neutral },\r\n\t\t{ value: 'free', label: 'Free', color: HUE.brand },\r\n\t\t{ value: 'registration', label: 'Registration', color: HUE.brand },\r\n\t\t{ value: 'series', label: 'Series', color: HUE.brand },\r\n\t\t{ value: 'series_instance', label: 'Instance', color: HUE.warning },\r\n\t\t{ value: 'collection', label: 'Collection', color: HUE.danger },\r\n\t\t{ value: 'donation', label: 'Donation', color: HUE.danger },\r\n\t\t{ value: 'mixed', label: 'Mixed', color: HUE.warning },\r\n\t\t{ value: 'sections', label: 'Sections', color: HUE.brand },\r\n\t\t{ value: 'promo', label: 'Promo codes', color: HUE.success },\r\n\t\t{ value: 'multi_stage', label: 'Multi-stage', color: HUE.danger },\r\n\t\t{ value: 'long', label: 'Long name', color: HUE.warning },\r\n\t\t{ value: 'wide', label: 'Wide image', color: HUE.neutral },\r\n\t];\r\n}\r\n\r\n/** Static snapshots derived from the functions above — for non-reactive consumers. */\r\nexport const SHOWCASE_BROWSE_STATES = getShowcaseBrowseStates();\r\nexport const SHOWCASE_CALENDAR_STATES = getShowcaseCalendarStates();\r\n"],"names":["showcaseDate","daysFromFriday","hour","minute","now","daysToFriday","base","y","m","d","hh","mm","showcaseDateOnly","mockVenue","getDefaultTimezone","mockPerformers","mockFaqs","mockTickets","_now","_evDate","_ymd","mockEvent","t","mockFreeEvent","mockRegistrationEvent","mockDonationEvent","DataToggleStore","#current","$","#isActive","dataToggleStore","HUE","getShowcaseCheckoutStates","getShowcaseSuccessStates"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"transform-Bgqwj9i-.js","sources":["../node_modules/@getmicdrop/svelte-components/dist/primitives/Icons/phosphor/ExportIcon.svelte","../node_modules/@getmicdrop/svelte-components/dist/primitives/Icons/phosphor/LocationIcon.svelte","../node_modules/@getmicdrop/svelte-components/dist/utils/copyToClipboard.js","../src/lib/api/transformers/address.ts","../src/lib/api/transformers/series.ts","../src/lib/api/transformers/collection.ts","../src/lib/public-calendar-flow/shareEventLink.ts","../src/lib/public-calendar-flow/shareCopyFeedback.svelte.ts","../src/lib/public-calendar-flow/transform.ts"],"sourcesContent":["<script lang=\"ts\">\r\n /**\r\n * Export — Phosphor icon (canonical Micdrop icon family).\r\n * Outline by default; pass `weight=\"fill\"` for solid, or let a stateful parent\r\n * (NavItem / Tabs / BottomNav / status badge) drive it via icon-weight context.\r\n */\r\n import { useIconWeight, type IconWeight } from './iconWeight.js';\r\n\r\n interface Props {\r\n /** Pixel size (width + height). */\r\n size?: string;\r\n /** Icon color; defaults to `currentColor` (inherits text color). */\r\n color?: string;\r\n /** Extra classes. */\r\n class?: string;\r\n /** `regular` (outline) or `fill` (solid). Overrides ambient state weight. */\r\n weight?: IconWeight;\r\n }\r\n\r\n let { size = '24', color = 'currentColor', class: className = '', weight }: Props = $props();\r\n\r\n const ctx = useIconWeight();\r\n let resolved: IconWeight = $derived(weight ?? ctx?.weight ?? 'regular');\r\n</script>\r\n\r\n<svg\r\n class={className}\r\n aria-hidden=\"true\"\r\n width={size}\r\n height={size}\r\n viewBox=\"0 0 256 256\"\r\n fill=\"currentColor\"\r\n style:color={color}\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n>\r\n {#if resolved === 'fill'}<path d=\"M216,112v96a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V112A16,16,0,0,1,56,96h64v48a8,8,0,0,0,16,0V96h64A16,16,0,0,1,216,112ZM136,43.31l26.34,26.35a8,8,0,0,0,11.32-11.32l-40-40a8,8,0,0,0-11.32,0l-40,40A8,8,0,0,0,93.66,69.66L120,43.31V96h16Z\"/>{:else}<path d=\"M176,104h24a8,8,0,0,1,8,8v96a8,8,0,0,1-8,8H56a8,8,0,0,1-8-8V112a8,8,0,0,1,8-8H80\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><polyline points=\"88 64 128 24 168 64\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><line x1=\"128\" y1=\"24\" x2=\"128\" y2=\"136\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/>{/if}\r\n</svg>\r\n","<script lang=\"ts\">\r\n /**\r\n * Location — Phosphor icon (canonical Micdrop icon family).\r\n * Outline by default; pass `weight=\"fill\"` for solid, or let a stateful parent\r\n * (NavItem / Tabs / BottomNav / status badge) drive it via icon-weight context.\r\n */\r\n import { useIconWeight, type IconWeight } from './iconWeight.js';\r\n\r\n interface Props {\r\n /** Pixel size (width + height). */\r\n size?: string;\r\n /** Icon color; defaults to `currentColor` (inherits text color). */\r\n color?: string;\r\n /** Extra classes. */\r\n class?: string;\r\n /** `regular` (outline) or `fill` (solid). Overrides ambient state weight. */\r\n weight?: IconWeight;\r\n }\r\n\r\n let { size = '24', color = 'currentColor', class: className = '', weight }: Props = $props();\r\n\r\n const ctx = useIconWeight();\r\n let resolved: IconWeight = $derived(weight ?? ctx?.weight ?? 'regular');\r\n</script>\r\n\r\n<svg\r\n class={className}\r\n aria-hidden=\"true\"\r\n width={size}\r\n height={size}\r\n viewBox=\"0 0 256 256\"\r\n fill=\"currentColor\"\r\n style:color={color}\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n>\r\n {#if resolved === 'fill'}<path d=\"M128,16a88.1,88.1,0,0,0-88,88c0,75.3,80,132.17,83.41,134.55a8,8,0,0,0,9.18,0C136,236.17,216,179.3,216,104A88.1,88.1,0,0,0,128,16Zm0,56a32,32,0,1,1-32,32A32,32,0,0,1,128,72Z\"/>{:else}<circle cx=\"128\" cy=\"104\" r=\"32\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><path d=\"M208,104c0,72-80,128-80,128S48,176,48,104a80,80,0,0,1,160,0Z\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/>{/if}\r\n</svg>\r\n","/**\n * Copy-to-clipboard utility — resolves `true` ONLY on a real successful write.\n *\n * The whole point of this canonical: callers fire their own \"Copied!\" toast\n * ONLY when this resolves `true`. It NEVER resolves `true` unless the text\n * actually landed on the clipboard, so a permission-denied / insecure-context /\n * no-API failure can no longer masquerade as success — killing the \"lying\n * toast\" bug where a button claimed it copied when nothing was copied.\n *\n * Strategy (best → fallback, never throws):\n * 1. Async Clipboard API (`navigator.clipboard.writeText`) when available\n * (secure context, granted permission) — AWAITED; resolves `true` only\n * when that promise resolves. On rejection it falls through (2) rather\n * than reporting success.\n * 2. Legacy `document.execCommand('copy')` for older / insecure (non-HTTPS)\n * contexts — returns its REAL success boolean.\n * 3. `false` on any failure (rejected write, no clipboard API, no DOM,\n * thrown exception).\n *\n * @param text - The text to place on the clipboard.\n * @returns Promise resolving `true` iff the write actually succeeded, else `false`.\n *\n * @example\n * if (await copyToClipboard(shareUrl)) toast.success('Link copied');\n * else toast.error(\"Couldn't copy — try selecting and copying manually\");\n */\nexport async function copyToClipboard(text) {\n // 1. Async Clipboard API — preferred; only present in secure contexts.\n if (typeof navigator !== 'undefined' &&\n navigator.clipboard &&\n typeof navigator.clipboard.writeText === 'function') {\n try {\n await navigator.clipboard.writeText(text);\n return true;\n }\n catch {\n // Permission denied / insecure context / transient failure — do NOT\n // report success. Fall through to the legacy path and let it decide.\n }\n }\n // 2. Legacy execCommand fallback — older browsers / insecure (non-HTTPS).\n return copyViaExecCommand(text);\n}\n/**\n * Legacy `document.execCommand('copy')` path. Returns its real success boolean\n * and never throws. Used when the async Clipboard API is unavailable or its\n * write rejected.\n *\n * @param text - The text to copy.\n * @returns `true` iff `execCommand('copy')` reported success.\n */\nfunction copyViaExecCommand(text) {\n if (typeof document === 'undefined' ||\n typeof document.execCommand !== 'function') {\n return false;\n }\n // Preserve what the user had selected/focused — selecting our textarea would\n // otherwise blow away their current selection (e.g. text they were copying by hand).\n const prevActive = document.activeElement;\n const selection = document.getSelection();\n const savedRanges = selection\n ? Array.from({ length: selection.rangeCount }, (_, i) => selection.getRangeAt(i).cloneRange())\n : [];\n const textarea = document.createElement('textarea');\n try {\n textarea.value = text;\n // Read-only + off-screen so it never flashes, scrolls, or steals focus.\n textarea.setAttribute('readonly', '');\n textarea.style.position = 'fixed';\n textarea.style.top = '-9999px';\n textarea.style.left = '-9999px';\n textarea.style.opacity = '0';\n document.body.appendChild(textarea);\n textarea.select();\n textarea.setSelectionRange(0, text.length);\n return document.execCommand('copy');\n }\n catch {\n return false;\n }\n finally {\n textarea.remove();\n // Restore the user's prior selection + focus, on success AND failure.\n if (selection) {\n selection.removeAllRanges();\n for (const range of savedRanges)\n selection.addRange(range);\n }\n prevActive?.focus?.();\n }\n}\n","/**\r\n * Address helpers — shared between the event, series and collection page\r\n * transformers.\r\n *\r\n * Lifted verbatim from public-calendar-flow/transform.ts so the series and\r\n * collection canonicals (and the in-place transformApiEvent) read a single\r\n * source instead of each carrying a private copy. Behavior is byte-identical\r\n * to the previous module-private versions.\r\n */\r\n\r\n/**\r\n * Parse a single-line address string into display lines.\r\n * E.g. \"123 Main St, Los Angeles, CA 90012\" -> [\"123 Main St\", \"Los Angeles, CA 90012\"]\r\n */\r\nexport function parseAddress(addressStr: string): string[] {\r\n if (!addressStr) return [];\r\n const parts = addressStr.split(',').map(p => p.trim());\r\n if (parts.length < 2) return [addressStr];\r\n const lastPart = parts[parts.length - 1];\r\n const stateZipMatch = lastPart.match(/^([A-Z]{2})\\s+(\\d{5}(-\\d{4})?)$/);\r\n if (stateZipMatch && parts.length >= 3) {\r\n const state = stateZipMatch[1];\r\n const zip = stateZipMatch[2];\r\n const city = parts[parts.length - 2];\r\n const lines = parts.slice(0, -2);\r\n lines.push(`${city}, ${state} ${zip}`);\r\n return lines;\r\n }\r\n return [parts[0], parts.slice(1).join(', ')];\r\n}\r\n\r\n/**\r\n * Build a Google Maps search URL from an address string.\r\n */\r\nexport function buildGoogleMapsUrl(address: string): string {\r\n if (!address) return '';\r\n return `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(address)}`;\r\n}\r\n","/**\r\n * Series Page Transformer\r\n *\r\n * Wire->domain boundary for the public series page. Maps a SeriesPageData\r\n * payload (from the series API) into the clean EventData shape consumed by\r\n * SeriesPage.svelte / EventExperience (full-width series mode, set via\r\n * eventSeriesId).\r\n *\r\n * Lifted byte-identically from public-calendar-flow/transform.ts's\r\n * transformSeriesPageData. Every ||/?? fallthrough is preserved exactly;\r\n * characterization tests pin the output. transformSeriesPageData now delegates\r\n * here.\r\n *\r\n * COMPOSITION NOTE — why this does NOT reuse parseVenue:\r\n * The api `parseVenue` returns the api-domain `Venue` (raw timezone string,\r\n * fee fields read from the payload). The series page needs the pcf `VenueData`\r\n * shape: timezone is the IANA-RESOLVED zone (getIANATimezone) and the fee\r\n * fields are hard-zeroed (the series payload carries no venue fees). Those\r\n * shapes are not byte-compatible, so the venue sub-shape stays local.\r\n */\r\n\r\nimport { getIANATimezone } from '@getmicdrop/svelte-components';\r\nimport { resolveImageUrl } from '@getmicdrop/svelte-components';\r\nimport { formatDateKey } from '$lib/utils/datetime.js';\r\nimport { parseAddress, buildGoogleMapsUrl } from './address.js';\r\nimport type { SeriesPageData } from '../types.js';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n PerformerData,\r\n FAQItem,\r\n SeriesOccurrence,\r\n} from '$lib/public-calendar-flow/types';\r\n\r\n/**\r\n * Transform SeriesPageData (from the series API) into our clean EventData interface.\r\n * Sets eventSeriesId so EventExperience renders in full-width series mode.\r\n */\r\nexport function parseSeries(series: SeriesPageData): EventData {\r\n // Mirror the event transform: raw series carry lowercase `timezone`\r\n // (some PascalCase `timeZone` / snake `time_zone`). Read all casings so a\r\n // non-UTC series doesn't silently fall back to UTC.\r\n const seriesAny = series as SeriesPageData & {\r\n timezone?: string;\r\n time_zone?: string;\r\n };\r\n const timezone = getIANATimezone(\r\n series.timeZone || seriesAny.timezone || seriesAny.time_zone || 'UTC'\r\n );\r\n\r\n // Build image URL — SC resolveImageUrl already passes absolute URLs through,\r\n // so no local startsWith('http') guard is needed.\r\n const imageUrl = resolveImageUrl(series.image || '', { cdn: true });\r\n\r\n // Map occurrences to SeriesOccurrence[]\r\n const seriesOccurrences: SeriesOccurrence[] = (series.occurrences || []).map(\r\n occ => ({\r\n id: occ.id,\r\n slug: occ.slug || '',\r\n startDateTime: occ.startDateTime,\r\n endDateTime: occ.endDateTime || '',\r\n status: (occ.ctaState?.reason === 'sold_out'\r\n ? 'sold_out'\r\n : 'on_sale') as EventStatus,\r\n ctaText: occ.ctaState?.text || 'Get Tickets',\r\n ctaDisabled: occ.ctaState?.disabled || false,\r\n })\r\n );\r\n\r\n // Use first occurrence for date fields\r\n const firstOcc = series.occurrences?.[0];\r\n const date = firstOcc?.startDateTime\r\n ? formatDateKey(firstOcc.startDateTime, timezone)\r\n : '';\r\n\r\n // Map FAQs\r\n const rawFaq = series.venue?.faq;\r\n let faqs: FAQItem[] = [];\r\n if (Array.isArray(rawFaq)) {\r\n faqs = rawFaq.map(f => ({\r\n question: f.question || '',\r\n answer: f.answer || '',\r\n }));\r\n } else if (typeof rawFaq === 'string' && rawFaq) {\r\n faqs = [{ question: 'FAQ', answer: rawFaq }];\r\n }\r\n\r\n // Map performers\r\n const performers: PerformerData[] = (series.performers || []).map(\r\n (p, index) => ({\r\n id: index + 1,\r\n displayName:\r\n p.displayName || [p.firstName, p.lastName].filter(Boolean).join(' '),\r\n profileImage: p.profileImage || undefined,\r\n })\r\n );\r\n\r\n // Venue address\r\n const venueAddress =\r\n series.venue?.location || series.venue?.googleLocationNameCache || '';\r\n\r\n return {\r\n id: series.id,\r\n title: series.title || '',\r\n slug: '',\r\n description: series.description || series.eventSummary || '',\r\n date,\r\n startDateTime: firstOcc?.startDateTime || '',\r\n endDateTime: firstOcc?.endDateTime || '',\r\n doorsOpenTime: '',\r\n timezone,\r\n imageUrl,\r\n venue: {\r\n id: series.venue?.id || 0,\r\n name: series.venue?.name || '',\r\n address: venueAddress,\r\n timezone,\r\n serviceFeePercentage: 0,\r\n serviceFeeCents: 0,\r\n taxPercentage: 0,\r\n },\r\n performers,\r\n tickets: [],\r\n faqs,\r\n disclaimer: series.venue?.disclaimer || undefined,\r\n status: 'on_sale',\r\n eventSeriesId: series.id,\r\n seriesOccurrences,\r\n isPasswordProtected: false,\r\n isRegistrationEvent: false,\r\n totalTicketsRemaining: 0,\r\n totalTicketsCapacity: 0,\r\n venueAddressLines: parseAddress(venueAddress),\r\n googleMapsUrl: buildGoogleMapsUrl(venueAddress),\r\n };\r\n}\r\n\r\n/**\r\n * Back-compat alias — the public-calendar-flow shaper name. Existing call\r\n * sites importing transformSeriesPageData continue to work unchanged.\r\n */\r\nexport const transformSeriesPageData = parseSeries;\r\n","/**\r\n * Collection Page Transformer\r\n *\r\n * Wire->domain boundary for the public collection page. Maps a\r\n * PublicCollectionData payload (from the collection API) into the clean\r\n * EventData shape consumed by CollectionView.svelte / EventExperience\r\n * (full-width collection mode, set via collectionId).\r\n *\r\n * Lifted byte-identically from public-calendar-flow/transform.ts's\r\n * transformCollectionData. Every ||/?? fallthrough is preserved exactly;\r\n * characterization tests pin the output. transformCollectionData now delegates\r\n * here.\r\n *\r\n * COMPOSITION NOTE — why this does NOT reuse parseVenue/parseEvent:\r\n * The collection payload has no venue and no timezone; the EventData it\r\n * produces hard-codes an empty venue and 'UTC'. The per-event mapping is a\r\n * tiny CollectionEvent card shape (id/name/slug/image/startDateTime/status),\r\n * not the full Event domain — reusing parseEvent would change the output.\r\n * Both stay local.\r\n */\r\n\r\nimport { resolveImageUrl } from '@getmicdrop/svelte-components';\r\nimport type { PublicCollectionData } from '../types.js';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n CollectionEvent,\r\n} from '$lib/public-calendar-flow/types';\r\n\r\n/**\r\n * Transform PublicCollectionData (from the collection API) into our clean EventData interface.\r\n * Sets collectionId so EventExperience renders in full-width collection mode.\r\n */\r\nexport function parseCollection(collection: PublicCollectionData): EventData {\r\n // Map collection events to CollectionEvent[]\r\n const collectionEvents: CollectionEvent[] = (collection.events || []).map(\r\n ev => {\r\n return {\r\n id: ev.id,\r\n name: ev.title || '',\r\n slug: ev.slug || '',\r\n // SC's resolveImageUrl passes absolute http(s)/data/blob URLs through\r\n // untouched, so no local startsWith('http') guard is needed.\r\n image: resolveImageUrl(ev.image || '', { cdn: true }),\r\n startDateTime: ev.startDateTime || '',\r\n status: (ev.status || 'on_sale') as EventStatus,\r\n };\r\n }\r\n );\r\n\r\n // Cover image — SC resolveImageUrl already passes absolute URLs through.\r\n const imageUrl = resolveImageUrl(collection.coverImage || '', { cdn: true });\r\n\r\n return {\r\n id: collection.id,\r\n title: collection.collectionTitle || '',\r\n slug: '',\r\n description: collection.description || collection.summary || '',\r\n date: '',\r\n startDateTime: '',\r\n endDateTime: '',\r\n doorsOpenTime: '',\r\n timezone: 'UTC',\r\n imageUrl,\r\n venue: {\r\n id: 0,\r\n name: '',\r\n address: '',\r\n timezone: 'UTC',\r\n serviceFeePercentage: 0,\r\n serviceFeeCents: 0,\r\n taxPercentage: 0,\r\n },\r\n performers: [],\r\n tickets: [],\r\n faqs: [],\r\n status: 'on_sale',\r\n collectionId: collection.id,\r\n collectionEvents,\r\n isPasswordProtected: false,\r\n isRegistrationEvent: false,\r\n totalTicketsRemaining: 0,\r\n totalTicketsCapacity: 0,\r\n };\r\n}\r\n\r\n/**\r\n * Back-compat alias — the public-calendar-flow shaper name. Existing call\r\n * sites importing transformCollectionData continue to work unchanged.\r\n */\r\nexport const transformCollectionData = parseCollection;\r\n","import { copyToClipboard } from '@getmicdrop/svelte-components';\r\n\r\n/**\r\n * Outcome of a share attempt, mapped by the caller to its own inline feedback.\r\n *\r\n * - `shared` — the native share sheet handled it (or the user cancelled). No\r\n * inline feedback: the OS UI already spoke, and a cancel must stay quiet.\r\n * - `copied` — the link landed on the clipboard via the SC canonical.\r\n * - `failed` — the clipboard write was blocked; surface the URL for manual copy.\r\n */\r\nexport type ShareLinkResult = 'shared' | 'copied' | 'failed';\r\n\r\n/**\r\n * Share-link decision — the ONE copy of the native-share/clipboard logic that\r\n * used to be duplicated across the event header and the confirmation sidebar.\r\n *\r\n * 1. Native share sheet when the browser exposes `navigator.share`. A user\r\n * cancel (AbortError) ends quietly — returns `shared`, no fallback.\r\n * 2. Otherwise (no share API, or a non-cancel share failure) copy the URL via\r\n * the SC canonical `copyToClipboard`, which resolves `true` ONLY on a real\r\n * write and falls back to `execCommand` on the insecure (http embed) hosts\r\n * where the async Clipboard API is unavailable — the exact context the old\r\n * raw `navigator.clipboard.writeText` threw in.\r\n *\r\n * VC has no toasts (standalone embeddable widget, no Toaster mounted), so this\r\n * returns a result the caller renders inline rather than firing feedback here.\r\n *\r\n * @param url - The link to share.\r\n */\r\nexport async function shareEventLink(url: string): Promise<ShareLinkResult> {\r\n if (\r\n typeof navigator !== 'undefined' &&\r\n typeof navigator.share === 'function'\r\n ) {\r\n try {\r\n await navigator.share({ url });\r\n return 'shared';\r\n } catch (err: unknown) {\r\n // User dismissed the share sheet — leave it there, no fallback. Browsers\r\n // reject with a DOMException named 'AbortError', and DOMException is NOT\r\n // `instanceof Error`, so match on the name alone (not the prototype).\r\n if ((err as { name?: string } | null)?.name === 'AbortError') {\r\n return 'shared';\r\n }\r\n // Any other failure falls through to the clipboard fallback below.\r\n }\r\n }\r\n\r\n return (await copyToClipboard(url)) ? 'copied' : 'failed';\r\n}\r\n","import { shareEventLink } from '$lib/public-calendar-flow/shareEventLink';\r\n\r\n/**\r\n * Share-link copy feedback — the ONE copy of the inline state machine that used\r\n * to be hand-rolled identically in the event header and the confirmation\r\n * sidebar. It owns the reactive `copyState`/`copyFailedUrl` and the reset timer,\r\n * delegating the native-share/clipboard decision to `shareEventLink`.\r\n *\r\n * VC has no toasts, so feedback is inline: `copied` briefly swaps the button\r\n * label, `failed` reveals the URL for manual copy. Native share (or a user\r\n * cancel) leaves the state untouched — the OS UI already spoke.\r\n *\r\n * Call `dispose()` from the consumer's `onDestroy` to clear the pending timer.\r\n */\r\nexport function createShareCopyFeedback() {\r\n let copyState = $state<'idle' | 'copied' | 'failed'>('idle');\r\n let copyFailedUrl = $state('');\r\n let resetTimer: ReturnType<typeof setTimeout> | undefined;\r\n\r\n async function share(url: string) {\r\n const result = await shareEventLink(url);\r\n if (result === 'copied') {\r\n copyFailedUrl = '';\r\n copyState = 'copied';\r\n clearTimeout(resetTimer);\r\n resetTimer = setTimeout(() => (copyState = 'idle'), 2500);\r\n } else if (result === 'failed') {\r\n // Copy blocked — reveal the URL inline so the buyer can select it manually.\r\n clearTimeout(resetTimer);\r\n copyState = 'failed';\r\n copyFailedUrl = url;\r\n }\r\n // 'shared' → native sheet handled it (or user cancelled); no inline feedback.\r\n }\r\n\r\n function dispose() {\r\n clearTimeout(resetTimer);\r\n }\r\n\r\n return {\r\n get copyState() {\r\n return copyState;\r\n },\r\n get copyFailedUrl() {\r\n return copyFailedUrl;\r\n },\r\n share,\r\n dispose,\r\n };\r\n}\r\n","import { getIANATimezone } from '@getmicdrop/svelte-components';\r\nimport { browserNow } from '@getmicdrop/svelte-components/datetime';\r\nimport { formatDateKey } from '$lib/utils/datetime.js';\r\n// Premium Ticket Experience — API → EventData Transformer\r\n// Maps raw API event responses to our clean EventData interface.\r\n// Used when plugging in real API data. The showcase continues using mock-data.ts directly.\r\n\r\nimport { resolveImageUrl } from '@getmicdrop/svelte-components';\r\nimport {\r\n parseAddress,\r\n buildGoogleMapsUrl,\r\n} from '$lib/api/transformers/address';\r\n// Canonical wire→domain boundary — all event-level scalar reads go through it.\r\nimport { parseEvent } from '$lib/api/transformers/event';\r\nimport { parseSeries } from '$lib/api/transformers/series';\r\nimport { parseCollection } from '$lib/api/transformers/collection';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n TicketTypeData,\r\n TicketStatus,\r\n VenueData,\r\n PerformerData,\r\n FAQItem,\r\n SeriesOccurrence,\r\n} from './types';\r\nimport type { SeriesPageData, PublicCollectionData } from '$lib/api/types';\r\n\r\n/**\r\n * Map a raw API ticket status/state to our TicketStatus union.\r\n */\r\nfunction mapTicketStatus(ticket: any): TicketStatus {\r\n const now = browserNow();\r\n const remaining =\r\n ticket.remainingCapacity ??\r\n ticket.quantityRemaining ??\r\n ticket.quantity ??\r\n 0;\r\n const salesBegin =\r\n ticket.salesBegin ||\r\n ticket.salesStart ||\r\n ticket.saleBegin ||\r\n ticket.onSaleStart;\r\n const salesEnd = ticket.salesEnd || ticket.saleEnd || ticket.onSaleEnd;\r\n\r\n if (remaining <= 0) return 'sold_out';\r\n if (salesEnd && new Date(salesEnd) < now) return 'sales_ended'; // @datetime-escape: absolute-instant compare of a UTC-Z field vs now — tz-independent\r\n if (salesBegin && new Date(salesBegin) > now) return 'coming_soon'; // @datetime-escape: absolute-instant compare of a UTC-Z field vs now — tz-independent\r\n return 'on_sale';\r\n}\r\n\r\n/**\r\n * Map a raw API event status string to our EventStatus union.\r\n */\r\nfunction mapEventStatus(\r\n rawStatus: string,\r\n tickets: TicketTypeData[]\r\n): EventStatus {\r\n const s = (rawStatus || '').toLowerCase().replace(/\\s+/g, '_');\r\n\r\n if (s === 'cancelled' || s === 'canceled') return 'cancelled';\r\n\r\n // Check if event is past based on end time (handled by caller if needed)\r\n if (s === 'past' || s === 'ended') return 'past';\r\n\r\n // MIC-1039: if any hidden ticket is still on sale, the event is \"on_sale\"\r\n // regardless of visible-ticket states — the user just needs a promo code.\r\n // NOTE: this operates on the pcf DOMAIN ticket shape (post-transform, with a\r\n // computed `status` string), NOT the wire shape SC's\r\n // `isHiddenTicketPurchasable` reads (raw visibility/salesChannel/sale-window\r\n // fields). The sale-window math already happened in `mapTicketStatus`, so the\r\n // SC predicate can't honestly serve this site — kept deliberately local.\r\n const hasPurchasableHiddenTickets = tickets.some(\r\n t => t.isHidden && t.status === 'on_sale'\r\n );\r\n if (hasPurchasableHiddenTickets) return 'on_sale';\r\n\r\n // Derive from ticket states\r\n const publicTickets = tickets.filter(t => !t.isHidden);\r\n if (publicTickets.length > 0) {\r\n if (publicTickets.every(t => t.status === 'sold_out')) return 'sold_out';\r\n if (publicTickets.every(t => t.status === 'coming_soon'))\r\n return 'coming_soon';\r\n if (\r\n publicTickets.every(\r\n t => t.status === 'sales_ended' || t.status === 'sold_out'\r\n )\r\n )\r\n return 'sales_ended';\r\n }\r\n\r\n if (s === 'sold_out' || s === 'soldout') return 'sold_out';\r\n if (s === 'coming_soon' || s === 'comingsoon') return 'coming_soon';\r\n if (s === 'sales_ended' || s === 'salesended') return 'sales_ended';\r\n\r\n return 'on_sale';\r\n}\r\n\r\n/**\r\n * Transform a raw API event response into our clean EventData interface.\r\n * This is the bridge between the API and our premium ticket experience components.\r\n *\r\n * COMPOSITION NOTE (events convergence): the wire is parsed ONCE through the\r\n * canonical parseEvent ($lib/api/transformers/event); every event-level\r\n * scalar below projects off the domain Event. Three deliberate wire seams\r\n * remain, characterization-pinned in\r\n * utils/event-shapers.characterization.test.js:\r\n * 1. TICKETS — the TicketTypeData map uses `??` (nullish) semantics over\r\n * raw ticket fields (remainingCapacity/visibility/fee/…) that\r\n * parseTicket's `||`-folding AvailableTicket neither carries nor\r\n * preserves; routing through parseTicket would change rendered output.\r\n * 2. IMAGE — image→imageUrl→image_url precedence intentionally differs\r\n * from the canonical resolver's (imageUrl-first); see the note in\r\n * api/transformers/event.ts.\r\n * 3. VENUE/PERFORMERS — mapped from the raw passthrough objects\r\n * (domain.venue / domain.performers) with B-specific `??` fee/tax\r\n * semantics; the performer canonical lands in PR #260 and should\r\n * absorb the performer map then.\r\n */\r\nexport function transformApiEvent(rawEvent: any): EventData {\r\n // Wire→domain ONCE (see composition note).\r\n const domain = parseEvent(rawEvent);\r\n const rawVenue = domain.venue || {};\r\n // Event-level timeZone is an OPTIONAL per-event override; when absent/blank it\r\n // must inherit the venue timezone. Falling straight to 'UTC' here rendered\r\n // venue-local times (e.g. a Fri 10pm Central show) in UTC (\"Sat 3:00 AM\"),\r\n // which made already-ended events look like future ones.\r\n // (domain.timeZone is the verbatim PascalCase passthrough; domain.timezone\r\n // folds lowercase + snake_case — same chain as before.)\r\n const timezone = getIANATimezone(\r\n domain.timeZone ||\r\n domain.timezone ||\r\n rawVenue.timeZone ||\r\n rawVenue.timezone ||\r\n 'UTC'\r\n );\r\n\r\n // Transform tickets — TICKET SEAM: raw wire tickets by contract (see note).\r\n const rawTickets = rawEvent.availableTickets || [];\r\n const tickets: TicketTypeData[] = rawTickets.map((t: any) => ({\r\n id: t.id || t.ID,\r\n name: t.name || t.title || '',\r\n description: t.description || undefined,\r\n price: t.price ?? 0,\r\n fee: t.fee ?? 0,\r\n quantityAvailable:\r\n t.remainingCapacity ?? t.quantityRemaining ?? t.quantity ?? 0,\r\n quantityTotal: t.totalCapacity ?? t.quantity ?? 0,\r\n minPerOrder: t.minPerOrder ?? t.minQuantity ?? 1,\r\n maxPerOrder: t.maxPerOrder ?? t.maxQuantity ?? 10,\r\n status: mapTicketStatus(t),\r\n salesStartDate:\r\n t.salesBegin || t.salesStart || t.saleBegin || t.onSaleStart || undefined,\r\n salesEndDate: t.salesEnd || t.saleEnd || t.onSaleEnd || undefined,\r\n isDonation: t.type === 2 || t.ticketType === 2 || t.isDonation === true,\r\n isHidden: t.visibility === 2 || t.isHidden === true,\r\n ticketType: t.type || t.ticketType || undefined,\r\n sectionName: t.sectionName || t.section || undefined,\r\n }));\r\n\r\n // Calculate totals from public tickets\r\n const publicTickets = tickets.filter(t => !t.isHidden && !t.isDonation);\r\n const totalRemaining = publicTickets.reduce(\r\n (sum, t) => sum + t.quantityAvailable,\r\n 0\r\n );\r\n const totalCapacity = publicTickets.reduce(\r\n (sum, t) => sum + t.quantityTotal,\r\n 0\r\n );\r\n\r\n // Determine event status\r\n const status = mapEventStatus(domain.status as string, tickets);\r\n\r\n // Build image URL — IMAGE SEAM: image-first precedence (see note).\r\n const rawImage =\r\n rawEvent.image || rawEvent.imageUrl || rawEvent.image_url || '';\r\n const imageUrl = rawImage.startsWith('http')\r\n ? rawImage\r\n : resolveImageUrl(rawImage, { cdn: true });\r\n\r\n // Venue\r\n const venue: VenueData = {\r\n id: rawVenue.id || rawVenue.ID || 0,\r\n name: rawVenue.name || rawVenue.googleLocationNameCache || '',\r\n address: rawVenue.address || rawVenue.googleLocationNameCache || '',\r\n timezone,\r\n serviceFeePercentage: rawVenue.serviceFeePercentage ?? rawVenue.fee ?? 0,\r\n serviceFeeCents: rawVenue.serviceFeeCents ?? 0,\r\n taxPercentage: rawVenue.taxPercentage ?? rawVenue.tax ?? 0,\r\n contactEmail: rawVenue.contactEmail || rawVenue.email || undefined,\r\n };\r\n\r\n // Performers — VENUE/PERFORMERS SEAM: raw passthrough map (see note).\r\n const rawPerformers = domain.performers || [];\r\n const performers: PerformerData[] = rawPerformers.map((p: any) => ({\r\n id: p.id || p.ID,\r\n displayName: p.displayName || p.name || '',\r\n profileImage: p.avatar || p.profileImage || undefined,\r\n role: p.role || undefined,\r\n }));\r\n\r\n // FAQs (may not be in API response)\r\n const faqs: FAQItem[] = (domain.faqs || []).map((f: any) => ({\r\n question: f.question || '',\r\n answer: f.answer || '',\r\n }));\r\n\r\n // Series showtimes → occurrences. A single series-event detail carries a\r\n // `showtimes` array; the v2 <ShowtimeDesigns> renders event.seriesOccurrences\r\n // under \"Upcoming Shows\". Without this map the section is always empty.\r\n const seriesOccurrences: SeriesOccurrence[] = (domain.showtimes || [])\r\n .filter((s: any) => s.published !== false)\r\n .map((s: any, i: number) => ({\r\n id: s.id ?? s.eventId ?? i + 1,\r\n slug: s.slug || '',\r\n startDateTime: s.startDateTime || s.startTime || '',\r\n endDateTime: s.endDateTime || s.endTime || '',\r\n status: (s.ctaState?.reason === 'sold_out'\r\n ? 'sold_out'\r\n : 'on_sale') as EventStatus,\r\n ctaText: s.ctaState?.text || 'Get tickets',\r\n ctaDisabled: s.ctaState?.disabled || false,\r\n }));\r\n\r\n // Date in venue timezone\r\n const date = domain.startDateTime\r\n ? formatDateKey(domain.startDateTime, timezone)\r\n : '';\r\n\r\n return {\r\n id: domain.id,\r\n title: domain.title || '',\r\n slug: domain.slug || '',\r\n description: domain.description || domain.eventSummary || '',\r\n date,\r\n startDateTime: domain.startDateTime || '',\r\n endDateTime: domain.endDateTime || '',\r\n doorsOpenTime: domain.doorsOpenTime || '',\r\n timezone,\r\n imageUrl,\r\n venue,\r\n performers,\r\n tickets,\r\n faqs,\r\n disclaimer: domain.disclaimer || undefined,\r\n status,\r\n eventSeriesId: domain.eventSeriesId || undefined,\r\n seriesOccurrences: seriesOccurrences.length ? seriesOccurrences : undefined,\r\n // Public API hides the actual password (json:\"-\") and exposes a boolean\r\n // `hasPassword` flag instead; fall back to a populated `password` for\r\n // admin-shaped payloads.\r\n isPasswordProtected: domain.hasPassword === true || !!domain.password,\r\n isRegistrationEvent:\r\n domain.ticketType === 1 || domain.eventTicketingType === 1,\r\n totalTicketsRemaining: totalRemaining,\r\n totalTicketsCapacity: totalCapacity,\r\n stageName: domain.stage?.name || domain.stageName || undefined,\r\n ageRestriction: domain.ageRestriction || undefined,\r\n displayAgeRestriction: domain.displayAgeRestriction ?? false,\r\n displayStartTime: domain.displayStartTime ?? true,\r\n displayEndTime: domain.displayEndTime ?? true,\r\n displayDoorsTime: domain.displayDoorsTime ?? true,\r\n collectionId: domain.collectionId || undefined, // domain folds collection_id\r\n venueAddressLines: parseAddress(\r\n rawVenue.address || rawVenue.googleLocationNameCache || ''\r\n ),\r\n googleMapsUrl: buildGoogleMapsUrl(\r\n rawVenue.address || rawVenue.googleLocationNameCache || ''\r\n ),\r\n };\r\n}\r\n\r\n/**\r\n * Transform SeriesPageData (from the series API) into our clean EventData interface.\r\n * Sets eventSeriesId so EventExperience renders in full-width series mode.\r\n */\r\nexport function transformSeriesPageData(series: SeriesPageData): EventData {\r\n // Implementation moved to the canonical transformer home\r\n // (`$lib/api/transformers/series.ts`). This export stays as a thin delegate\r\n // so SeriesPage.svelte and other consumers don't churn.\r\n return parseSeries(series);\r\n}\r\n\r\n/**\r\n * Transform PublicCollectionData (from the collection API) into our clean EventData interface.\r\n * Sets collectionId so EventExperience renders in full-width collection mode.\r\n */\r\nexport function transformCollectionData(\r\n collection: PublicCollectionData\r\n): EventData {\r\n // Implementation moved to the canonical transformer home\r\n // (`$lib/api/transformers/collection.ts`). This export stays as a thin\r\n // delegate so CollectionView.svelte and other consumers don't churn.\r\n return parseCollection(collection);\r\n}\r\n"],"names":["size","$","$$props","color","className","ctx","useIconWeight","resolved","svg","root_2","path","root","$$render","consequent","alternate","styles","copyToClipboard","text","copyViaExecCommand","prevActive","selection","savedRanges","_","i","textarea","range","parseAddress","addressStr","parts","p","stateZipMatch","state","zip","city","lines","buildGoogleMapsUrl","address","parseSeries","series","seriesAny","timezone","getIANATimezone","imageUrl","resolveImageUrl","seriesOccurrences","occ","firstOcc","date","formatDateKey","rawFaq","faqs","f","performers","index","venueAddress","parseCollection","collection","collectionEvents","ev","shareEventLink","url","err","createShareCopyFeedback","copyState","copyFailedUrl","resetTimer","share","result","dispose","mapTicketStatus","ticket","now","browserNow","remaining","salesBegin","salesEnd","mapEventStatus","rawStatus","tickets","s","t","publicTickets","transformApiEvent","rawEvent","domain","parseEvent","rawVenue","totalRemaining","sum","totalCapacity","status","rawImage","venue","transformSeriesPageData","transformCollectionData"],"mappings":"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","x_google_ignoreList":[0,1,2]}