@ticketlayer/elements 0.2.0

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 (195) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +55 -0
  3. package/dist/cjs/index-DfzcrE9-.js +3598 -0
  4. package/dist/cjs/index.cjs.js +16 -0
  5. package/dist/cjs/loader.cjs.js +12 -0
  6. package/dist/cjs/order-summary-ZMkJ5bez.js +116 -0
  7. package/dist/cjs/sdk-connector-ClDF3013.js +108 -0
  8. package/dist/cjs/ticketlayer-elements.cjs.js +24 -0
  9. package/dist/cjs/tl-buy-modal.cjs.entry.js +127 -0
  10. package/dist/cjs/tl-buy-tickets-button.cjs.entry.js +131 -0
  11. package/dist/cjs/tl-buy-tickets-wrapper.cjs.entry.js +58 -0
  12. package/dist/cjs/tl-cart-badge.cjs.entry.js +109 -0
  13. package/dist/cjs/tl-cart-drawer.cjs.entry.js +67 -0
  14. package/dist/cjs/tl-cart.cjs.entry.js +148 -0
  15. package/dist/cjs/tl-checkout-wrapper.cjs.entry.js +57 -0
  16. package/dist/cjs/tl-event-card.cjs.entry.js +140 -0
  17. package/dist/cjs/tl-event-list.cjs.entry.js +80 -0
  18. package/dist/cjs/tl-login.cjs.entry.js +184 -0
  19. package/dist/cjs/tl-my-orders.cjs.entry.js +123 -0
  20. package/dist/cjs/tl-occurrence-selector_2.cjs.entry.js +754 -0
  21. package/dist/cjs/tl-order-confirmation.cjs.entry.js +146 -0
  22. package/dist/cjs/tl-order-tickets_2.cjs.entry.js +3198 -0
  23. package/dist/cjs/tl-promo-code.cjs.entry.js +75 -0
  24. package/dist/cjs/tl-seat-map.cjs.entry.js +147 -0
  25. package/dist/collection/collection-manifest.json +29 -0
  26. package/dist/collection/components/tl-buy-modal/tl-buy-modal.css +264 -0
  27. package/dist/collection/components/tl-buy-modal/tl-buy-modal.js +249 -0
  28. package/dist/collection/components/tl-buy-tickets-button/tl-buy-tickets-button.css +120 -0
  29. package/dist/collection/components/tl-buy-tickets-button/tl-buy-tickets-button.js +412 -0
  30. package/dist/collection/components/tl-buy-tickets-wrapper/tl-buy-tickets-wrapper.css +23 -0
  31. package/dist/collection/components/tl-buy-tickets-wrapper/tl-buy-tickets-wrapper.js +192 -0
  32. package/dist/collection/components/tl-cart/tl-cart.css +251 -0
  33. package/dist/collection/components/tl-cart/tl-cart.js +314 -0
  34. package/dist/collection/components/tl-cart-badge/tl-cart-badge.css +138 -0
  35. package/dist/collection/components/tl-cart-badge/tl-cart-badge.js +217 -0
  36. package/dist/collection/components/tl-cart-drawer/tl-cart-drawer.css +98 -0
  37. package/dist/collection/components/tl-cart-drawer/tl-cart-drawer.js +185 -0
  38. package/dist/collection/components/tl-checkout-wrapper/tl-checkout-wrapper.css +23 -0
  39. package/dist/collection/components/tl-checkout-wrapper/tl-checkout-wrapper.js +148 -0
  40. package/dist/collection/components/tl-event-card/event-card-adapter.js +23 -0
  41. package/dist/collection/components/tl-event-card/tl-event-card.css +175 -0
  42. package/dist/collection/components/tl-event-card/tl-event-card.js +205 -0
  43. package/dist/collection/components/tl-event-list/tl-event-list.css +134 -0
  44. package/dist/collection/components/tl-event-list/tl-event-list.js +171 -0
  45. package/dist/collection/components/tl-login/tl-login.css +133 -0
  46. package/dist/collection/components/tl-login/tl-login.js +309 -0
  47. package/dist/collection/components/tl-my-orders/tl-my-orders.css +204 -0
  48. package/dist/collection/components/tl-my-orders/tl-my-orders.js +221 -0
  49. package/dist/collection/components/tl-occurrence-selector/tl-occurrence-selector.css +658 -0
  50. package/dist/collection/components/tl-occurrence-selector/tl-occurrence-selector.js +707 -0
  51. package/dist/collection/components/tl-order-confirmation/tl-order-confirmation.css +176 -0
  52. package/dist/collection/components/tl-order-confirmation/tl-order-confirmation.js +298 -0
  53. package/dist/collection/components/tl-order-tickets/tl-order-tickets.css +30 -0
  54. package/dist/collection/components/tl-order-tickets/tl-order-tickets.js +122 -0
  55. package/dist/collection/components/tl-promo-code/tl-promo-code.css +106 -0
  56. package/dist/collection/components/tl-promo-code/tl-promo-code.js +181 -0
  57. package/dist/collection/components/tl-seat-map/tl-seat-map.css +85 -0
  58. package/dist/collection/components/tl-seat-map/tl-seat-map.js +366 -0
  59. package/dist/collection/components/tl-ticket/tl-ticket.css +90 -0
  60. package/dist/collection/components/tl-ticket/tl-ticket.js +129 -0
  61. package/dist/collection/components/tl-ticket-selector/tl-ticket-selector.css +205 -0
  62. package/dist/collection/components/tl-ticket-selector/tl-ticket-selector.js +332 -0
  63. package/dist/collection/index.js +10 -0
  64. package/dist/collection/utils/order-summary.js +101 -0
  65. package/dist/collection/utils/sdk-connector.js +100 -0
  66. package/dist/collection/utils/testing/mock-sdk.js +95 -0
  67. package/dist/components/index.d.ts +35 -0
  68. package/dist/components/index.js +1 -0
  69. package/dist/components/order-summary.js +1 -0
  70. package/dist/components/sdk-connector.js +1 -0
  71. package/dist/components/tl-buy-modal.d.ts +11 -0
  72. package/dist/components/tl-buy-modal.js +1 -0
  73. package/dist/components/tl-buy-tickets-button.d.ts +11 -0
  74. package/dist/components/tl-buy-tickets-button.js +1 -0
  75. package/dist/components/tl-buy-tickets-wrapper.d.ts +11 -0
  76. package/dist/components/tl-buy-tickets-wrapper.js +1 -0
  77. package/dist/components/tl-buy-tickets-wrapper2.js +1 -0
  78. package/dist/components/tl-cart-badge.d.ts +11 -0
  79. package/dist/components/tl-cart-badge.js +1 -0
  80. package/dist/components/tl-cart-drawer.d.ts +11 -0
  81. package/dist/components/tl-cart-drawer.js +1 -0
  82. package/dist/components/tl-cart.d.ts +11 -0
  83. package/dist/components/tl-cart.js +1 -0
  84. package/dist/components/tl-cart2.js +1 -0
  85. package/dist/components/tl-checkout-wrapper.d.ts +11 -0
  86. package/dist/components/tl-checkout-wrapper.js +1 -0
  87. package/dist/components/tl-checkout-wrapper2.js +1 -0
  88. package/dist/components/tl-event-card.d.ts +11 -0
  89. package/dist/components/tl-event-card.js +1 -0
  90. package/dist/components/tl-event-card2.js +1 -0
  91. package/dist/components/tl-event-list.d.ts +11 -0
  92. package/dist/components/tl-event-list.js +1 -0
  93. package/dist/components/tl-login.d.ts +11 -0
  94. package/dist/components/tl-login.js +1 -0
  95. package/dist/components/tl-login2.js +1 -0
  96. package/dist/components/tl-my-orders.d.ts +11 -0
  97. package/dist/components/tl-my-orders.js +1 -0
  98. package/dist/components/tl-occurrence-selector.d.ts +11 -0
  99. package/dist/components/tl-occurrence-selector.js +1 -0
  100. package/dist/components/tl-occurrence-selector2.js +1 -0
  101. package/dist/components/tl-order-confirmation.d.ts +11 -0
  102. package/dist/components/tl-order-confirmation.js +1 -0
  103. package/dist/components/tl-order-tickets.d.ts +11 -0
  104. package/dist/components/tl-order-tickets.js +1 -0
  105. package/dist/components/tl-order-tickets2.js +1 -0
  106. package/dist/components/tl-promo-code.d.ts +11 -0
  107. package/dist/components/tl-promo-code.js +1 -0
  108. package/dist/components/tl-seat-map.d.ts +11 -0
  109. package/dist/components/tl-seat-map.js +1 -0
  110. package/dist/components/tl-ticket-selector.d.ts +11 -0
  111. package/dist/components/tl-ticket-selector.js +1 -0
  112. package/dist/components/tl-ticket-selector2.js +1 -0
  113. package/dist/components/tl-ticket.d.ts +11 -0
  114. package/dist/components/tl-ticket.js +1 -0
  115. package/dist/components/tl-ticket2.js +1 -0
  116. package/dist/elements.docs.d.ts +454 -0
  117. package/dist/elements.docs.json +3008 -0
  118. package/dist/esm/index-Ba-RZTFI.js +3588 -0
  119. package/dist/esm/index.js +4 -0
  120. package/dist/esm/loader.js +10 -0
  121. package/dist/esm/order-summary-BGekdjN9.js +103 -0
  122. package/dist/esm/sdk-connector-CqhvfyKV.js +102 -0
  123. package/dist/esm/ticketlayer-elements.js +20 -0
  124. package/dist/esm/tl-buy-modal.entry.js +125 -0
  125. package/dist/esm/tl-buy-tickets-button.entry.js +129 -0
  126. package/dist/esm/tl-buy-tickets-wrapper.entry.js +56 -0
  127. package/dist/esm/tl-cart-badge.entry.js +107 -0
  128. package/dist/esm/tl-cart-drawer.entry.js +65 -0
  129. package/dist/esm/tl-cart.entry.js +146 -0
  130. package/dist/esm/tl-checkout-wrapper.entry.js +55 -0
  131. package/dist/esm/tl-event-card.entry.js +138 -0
  132. package/dist/esm/tl-event-list.entry.js +78 -0
  133. package/dist/esm/tl-login.entry.js +182 -0
  134. package/dist/esm/tl-my-orders.entry.js +121 -0
  135. package/dist/esm/tl-occurrence-selector_2.entry.js +751 -0
  136. package/dist/esm/tl-order-confirmation.entry.js +144 -0
  137. package/dist/esm/tl-order-tickets_2.entry.js +3195 -0
  138. package/dist/esm/tl-promo-code.entry.js +73 -0
  139. package/dist/esm/tl-seat-map.entry.js +145 -0
  140. package/dist/index.cjs.js +1 -0
  141. package/dist/index.js +1 -0
  142. package/dist/ticketlayer-elements/index.esm.js +1 -0
  143. package/dist/ticketlayer-elements/p-0291df4c.entry.js +1 -0
  144. package/dist/ticketlayer-elements/p-10f01a1f.entry.js +1 -0
  145. package/dist/ticketlayer-elements/p-11273f8f.entry.js +1 -0
  146. package/dist/ticketlayer-elements/p-340ab4f5.entry.js +1 -0
  147. package/dist/ticketlayer-elements/p-41d22d7c.entry.js +1 -0
  148. package/dist/ticketlayer-elements/p-82752e3b.entry.js +1 -0
  149. package/dist/ticketlayer-elements/p-976770f3.entry.js +1 -0
  150. package/dist/ticketlayer-elements/p-9a903ff6.entry.js +1 -0
  151. package/dist/ticketlayer-elements/p-9c9072c8.entry.js +1 -0
  152. package/dist/ticketlayer-elements/p-9d8163d6.entry.js +1 -0
  153. package/dist/ticketlayer-elements/p-BGekdjN9.js +1 -0
  154. package/dist/ticketlayer-elements/p-Ba-RZTFI.js +2 -0
  155. package/dist/ticketlayer-elements/p-CqhvfyKV.js +1 -0
  156. package/dist/ticketlayer-elements/p-a5c90b68.entry.js +1 -0
  157. package/dist/ticketlayer-elements/p-b6d479ad.entry.js +1 -0
  158. package/dist/ticketlayer-elements/p-dd43f015.entry.js +1 -0
  159. package/dist/ticketlayer-elements/p-eb640760.entry.js +1 -0
  160. package/dist/ticketlayer-elements/p-ee3aa227.entry.js +1 -0
  161. package/dist/ticketlayer-elements/p-fb9444c4.entry.js +1 -0
  162. package/dist/ticketlayer-elements/ticketlayer-elements.css +1 -0
  163. package/dist/ticketlayer-elements/ticketlayer-elements.esm.js +1 -0
  164. package/dist/types/components/tl-buy-modal/tl-buy-modal.d.ts +54 -0
  165. package/dist/types/components/tl-buy-tickets-button/tl-buy-tickets-button.d.ts +61 -0
  166. package/dist/types/components/tl-buy-tickets-wrapper/tl-buy-tickets-wrapper.d.ts +52 -0
  167. package/dist/types/components/tl-cart/tl-cart.d.ts +80 -0
  168. package/dist/types/components/tl-cart-badge/tl-cart-badge.d.ts +36 -0
  169. package/dist/types/components/tl-cart-drawer/tl-cart-drawer.d.ts +35 -0
  170. package/dist/types/components/tl-checkout-wrapper/tl-checkout-wrapper.d.ts +39 -0
  171. package/dist/types/components/tl-event-card/event-card-adapter.d.ts +23 -0
  172. package/dist/types/components/tl-event-card/tl-event-card.d.ts +55 -0
  173. package/dist/types/components/tl-event-list/tl-event-list.d.ts +30 -0
  174. package/dist/types/components/tl-login/tl-login.d.ts +59 -0
  175. package/dist/types/components/tl-my-orders/tl-my-orders.d.ts +39 -0
  176. package/dist/types/components/tl-occurrence-selector/tl-occurrence-selector.d.ts +208 -0
  177. package/dist/types/components/tl-order-confirmation/tl-order-confirmation.d.ts +54 -0
  178. package/dist/types/components/tl-order-tickets/tl-order-tickets.d.ts +21 -0
  179. package/dist/types/components/tl-promo-code/tl-promo-code.d.ts +39 -0
  180. package/dist/types/components/tl-seat-map/tl-seat-map.d.ts +68 -0
  181. package/dist/types/components/tl-ticket/tl-ticket.d.ts +28 -0
  182. package/dist/types/components/tl-ticket-selector/tl-ticket-selector.d.ts +78 -0
  183. package/dist/types/components.d.ts +1629 -0
  184. package/dist/types/index.d.ts +14 -0
  185. package/dist/types/stencil-public-runtime.d.ts +1839 -0
  186. package/dist/types/utils/order-summary.d.ts +67 -0
  187. package/dist/types/utils/sdk-connector.d.ts +113 -0
  188. package/dist/types/utils/testing/mock-sdk.d.ts +36 -0
  189. package/elements.catalogue.json +968 -0
  190. package/loader/cdn.js +1 -0
  191. package/loader/index.cjs.js +1 -0
  192. package/loader/index.d.ts +24 -0
  193. package/loader/index.es2017.js +1 -0
  194. package/loader/index.js +2 -0
  195. package/package.json +101 -0
@@ -0,0 +1,4 @@
1
+ export { g as getSDK, h as hasSDK, o as onSDKEvent, s as setSDK, w as whenSDK } from './sdk-connector-CqhvfyKV.js';
2
+ export { tl_buy_tickets_wrapper as TlBuyTicketsWrapper } from './tl-buy-tickets-wrapper.entry.js';
3
+ export { tl_checkout_wrapper as TlCheckoutWrapper } from './tl-checkout-wrapper.entry.js';
4
+ import './index-Ba-RZTFI.js';
@@ -0,0 +1,10 @@
1
+ import { g as globalScripts, b as bootstrapLazy } from './index-Ba-RZTFI.js';
2
+ export { s as setNonce } from './index-Ba-RZTFI.js';
3
+
4
+ const defineCustomElements = async (win, options) => {
5
+ if (typeof window === 'undefined') return undefined;
6
+ await globalScripts();
7
+ return bootstrapLazy([["tl-my-orders",[[1,"tl-my-orders",{"emptyMessage":[1,"empty-message"],"columns":[2],"orders":[32],"authenticated":[32],"loading":[32],"error":[32],"expandedId":[32]}]]],["tl-buy-modal",[[1,"tl-buy-modal",{"eventId":[1,"event-id"],"occurrenceId":[1,"occurrence-id"],"step":[32],"eventName":[32],"imageUrl":[32],"venueLabel":[32],"dateSummary":[32],"selectedOccurrenceId":[32],"occurrenceCount":[32],"occurrenceLabel":[32],"error":[32]}]]],["tl-order-confirmation",[[1,"tl-order-confirmation",{"orderId":[1,"order-id"],"customerEmail":[1,"customer-email"],"showTickets":[4,"show-tickets"],"columns":[2],"order":[32],"resolvedOrderId":[32],"loading":[32],"error":[32],"paymentFailed":[32],"occurrence":[32],"signedInCustomer":[32]},null,{"orderId":[{"watchOrderId":0}]}]]],["tl-cart-drawer",[[1,"tl-cart-drawer",{"side":[1],"heading":[1],"open":[1028],"visible":[32]},null,{"open":[{"onOpenProp":0}]}]]],["tl-event-list",[[1,"tl-event-list",{"limit":[2],"category":[1],"columns":[2],"events":[32],"loading":[32],"error":[32]},null,{"limit":[{"watchFiltersChange":0}],"category":[{"watchFiltersChange":0}]}]]],["tl-buy-tickets-button",[[1,"tl-buy-tickets-button",{"eventId":[1,"event-id"],"occurrenceId":[1,"occurrence-id"],"state":[1],"label":[1],"variant":[1],"size":[1],"fullWidth":[4,"full-width"],"price":[2],"currency":[1],"pricePrefix":[1,"price-prefix"],"disabled":[4],"isHovered":[32]}]]],["tl-buy-tickets-wrapper",[[260,"tl-buy-tickets-wrapper",{"eventId":[1,"event-id"],"occurrenceId":[1,"occurrence-id"],"disabled":[4]}]]],["tl-cart-badge",[[1,"tl-cart-badge",{"showEmpty":[4,"show-empty"],"icon":[1],"size":[1],"badgeOnly":[4,"badge-only"],"itemCount":[32]}]]],["tl-checkout-wrapper",[[260,"tl-checkout-wrapper",{"disabled":[4]}]]],["tl-promo-code",[[1,"tl-promo-code",{"placeholder":[1],"buttonLabel":[1,"button-label"],"code":[32],"applying":[32],"applied":[32],"error":[32]}]]],["tl-seat-map",[[1,"tl-seat-map",{"occurrenceId":[1,"occurrence-id"],"hboUrl":[1,"hbo-url"],"apiUrl":[1,"api-url"],"height":[1],"width":[1],"isReady":[32],"isLoading":[32],"error":[32],"seatsInCart":[32]},null,{"occurrenceId":[{"watchOccurrenceId":0}]}]]],["tl-cart",[[1,"tl-cart",{"showCheckoutButton":[4,"show-checkout-button"],"checkoutLabel":[1,"checkout-label"],"showRemoveButtons":[4,"show-remove-buttons"],"compact":[4],"cart":[32],"loading":[32],"error":[32],"removingItemId":[32]}]]],["tl-event-card",[[1,"tl-event-card",{"event":[16],"eventId":[1,"event-id"],"loadedEvent":[32],"loading":[32],"error":[32]},null,{"eventId":[{"watchEventId":0}]}]]],["tl-login",[[1,"tl-login",{"heading":[1],"allowCodeEntry":[4,"allow-code-entry"],"phase":[32],"email":[32],"code":[32],"busy":[32],"error":[32],"notice":[32],"customer":[32]}]]],["tl-occurrence-selector_2",[[1,"tl-occurrence-selector",{"eventId":[1,"event-id"],"displayMode":[1,"display-mode"],"orientation":[1],"theme":[16],"loading":[32],"error":[32],"occurrences":[32],"currentMonth":[32],"selectedDate":[32],"computedDisplayMode":[32],"containerWidth":[32]},null,{"eventId":[{"onEventIdChange":0}]}],[1,"tl-ticket-selector",{"eventId":[1,"event-id"],"occurrenceId":[1,"occurrence-id"],"showButton":[4,"show-button"],"buttonLabel":[1,"button-label"],"ticketTypes":[32],"quantities":[32],"loading":[32],"error":[32],"adding":[32],"addSuccess":[32]},null,{"eventId":[{"watchPropsChange":0}],"occurrenceId":[{"watchPropsChange":0}]}]]],["tl-order-tickets_2",[[1,"tl-order-tickets",{"orderId":[1,"order-id"],"columns":[2],"tickets":[32],"loading":[32],"error":[32]},null,{"orderId":[{"watchOrder":0}]}],[1,"tl-ticket",{"ticket":[16],"orderId":[1,"order-id"],"qrSvg":[32],"downloading":[32]},null,{"ticket":[{"generateQr":0}]}]]]], options);
8
+ };
9
+
10
+ export { defineCustomElements };
@@ -0,0 +1,103 @@
1
+ /** Money arrives as minor-unit integers or decimal strings ("50.00"). */
2
+ function formatPrice(value, currency = 'GBP') {
3
+ if (value === null || value === undefined || value === '')
4
+ return '';
5
+ const fmt = new Intl.NumberFormat('en-GB', { style: 'currency', currency });
6
+ if (typeof value === 'number')
7
+ return fmt.format(value / 100);
8
+ const n = Number(value);
9
+ return Number.isNaN(n) ? String(value) : fmt.format(n);
10
+ }
11
+ function formatDateTime(iso) {
12
+ return new Date(iso).toLocaleDateString('en-GB', {
13
+ weekday: 'short',
14
+ day: 'numeric',
15
+ month: 'short',
16
+ year: 'numeric',
17
+ hour: '2-digit',
18
+ minute: '2-digit',
19
+ });
20
+ }
21
+ function formatDate(iso) {
22
+ return new Date(iso).toLocaleDateString('en-GB', {
23
+ day: 'numeric',
24
+ month: 'short',
25
+ year: 'numeric',
26
+ });
27
+ }
28
+ /** Line items that are tickets (fees, taxes and discounts have their own type). */
29
+ function ticketItems(order) {
30
+ return (order.items ?? []).filter((i) => !i.type || i.type === 'ticket');
31
+ }
32
+ function ticketCount(order) {
33
+ const fromItems = ticketItems(order).reduce((sum, i) => sum + (Number(i.quantity) || 0), 0);
34
+ return fromItems || order.tickets?.length || 0;
35
+ }
36
+ /** Event name as the order view exposes it: the first ticket line's name. */
37
+ function orderEventName(order) {
38
+ return order.eventName || ticketItems(order)[0]?.name || order.items?.[0]?.name || null;
39
+ }
40
+ function orderCustomerEmail(order, customer) {
41
+ const fromOrder = order?.customerEmail || order?.customer?.email;
42
+ if (fromOrder)
43
+ return fromOrder;
44
+ const c = customer;
45
+ return c?.email || null;
46
+ }
47
+ function statusLabel(status) {
48
+ if (!status)
49
+ return '';
50
+ return status.replace(/_/g, ' ').replace(/^\w/, (m) => m.toUpperCase());
51
+ }
52
+ function statusTone(status) {
53
+ switch (status) {
54
+ case 'confirmed':
55
+ return 'success';
56
+ case 'completed':
57
+ case 'fulfilled':
58
+ return 'info';
59
+ case 'pending':
60
+ case 'processing':
61
+ return 'warning';
62
+ case 'cancelled':
63
+ case 'expired':
64
+ case 'failed':
65
+ return 'error';
66
+ default:
67
+ return 'muted';
68
+ }
69
+ }
70
+ function errorMessage(err, fallback) {
71
+ return err instanceof Error && err.message ? err.message : fallback;
72
+ }
73
+ /** True for the "not signed in" family of API errors (401/403, NO_SESSION, NOT_AUTHENTICATED). */
74
+ function isAuthError(err) {
75
+ const e = err;
76
+ if (!e || typeof e !== 'object')
77
+ return false;
78
+ return e.status === 401 || e.status === 403 || e.code === 'NO_SESSION' || e.code === 'NOT_AUTHENTICATED';
79
+ }
80
+ /**
81
+ * Find the event and start time for an occurrence id. The order view only
82
+ * carries the occurrence id, so this walks the channel's listings (cached by
83
+ * live-api) until one owns the occurrence. Best effort: null when not found.
84
+ */
85
+ async function resolveOccurrence(sdk, occurrenceId, maxEvents = 12) {
86
+ const events = sdk.getEventsManager();
87
+ const listing = await events.list({ limit: maxEvents });
88
+ const candidates = listing.items.slice(0, maxEvents);
89
+ for (const candidate of candidates) {
90
+ const detail = (await events.get(candidate.id).catch(() => null));
91
+ const occ = detail?.occurrences?.find((o) => o.id === occurrenceId);
92
+ if (occ) {
93
+ return {
94
+ eventId: detail?.id ?? candidate.id,
95
+ eventName: detail?.name ?? candidate.name ?? '',
96
+ startsAt: occ.startsAt ?? null,
97
+ };
98
+ }
99
+ }
100
+ return null;
101
+ }
102
+
103
+ export { formatPrice as a, statusLabel as b, formatDateTime as c, orderCustomerEmail as d, errorMessage as e, formatDate as f, ticketItems as g, isAuthError as i, orderEventName as o, resolveOccurrence as r, statusTone as s, ticketCount as t };
@@ -0,0 +1,102 @@
1
+ /**
2
+ * SDK Connector
3
+ *
4
+ * Utility to connect external SDK instances to Elements components.
5
+ */
6
+ // The SDK is shared between bundles via the `window.Ticketlayer` registry that
7
+ // @ticketlayer/live publishes (createLiveClient → publishClient). Elements never
8
+ // import the SDK; they read this global and bind to its connector view.
9
+ const READY_EVENT = 'ticketlayer:ready';
10
+ // Back-compat slot for hosts that install a connector manually via setSDK().
11
+ const MANUAL_SLOT = '__TICKETLAYER_SDK__';
12
+ function readGlobalSDK() {
13
+ if (typeof window === 'undefined')
14
+ return null;
15
+ const win = window;
16
+ const reg = win.Ticketlayer;
17
+ return (reg?.getSDK?.() ?? reg?.sdk ?? win[MANUAL_SLOT]) || null;
18
+ }
19
+ /**
20
+ * Manually install an SDK/connector instance (escape hatch). The normal path is
21
+ * for the host to call createLiveClient(), which auto-publishes on the registry.
22
+ */
23
+ function setSDK(sdk) {
24
+ if (typeof window === 'undefined')
25
+ return;
26
+ window[MANUAL_SLOT] = sdk;
27
+ // Wake any components already awaiting whenSDK().
28
+ window.dispatchEvent(new CustomEvent(READY_EVENT, { detail: sdk }));
29
+ }
30
+ /**
31
+ * Get the SDK instance synchronously. Throws if not yet available - prefer
32
+ * whenSDK() in lifecycle methods so mounting before Live is ready isn't an error.
33
+ */
34
+ function getSDK() {
35
+ const sdk = readGlobalSDK();
36
+ if (!sdk) {
37
+ throw new Error('[Ticketlayer Elements] SDK not ready. Create a Live client (createLiveClient) ' +
38
+ 'or await whenSDK() before using Elements.');
39
+ }
40
+ return sdk;
41
+ }
42
+ /** True if a client is currently registered. */
43
+ function hasSDK() {
44
+ return readGlobalSDK() !== null;
45
+ }
46
+ /**
47
+ * Resolve when the SDK is available - immediately if Live is already up, else
48
+ * on the `ticketlayer:ready` event. Replaces busy-wait polling in components.
49
+ */
50
+ function whenSDK(timeoutMs = 15000) {
51
+ const existing = readGlobalSDK();
52
+ if (existing)
53
+ return Promise.resolve(existing);
54
+ if (typeof window === 'undefined') {
55
+ return Promise.reject(new Error('[Ticketlayer Elements] No window; SDK unavailable.'));
56
+ }
57
+ return new Promise((resolve, reject) => {
58
+ let settled = false;
59
+ const finish = () => {
60
+ const sdk = readGlobalSDK();
61
+ if (sdk && !settled) {
62
+ settled = true;
63
+ cleanup();
64
+ resolve(sdk);
65
+ }
66
+ };
67
+ const cleanup = () => {
68
+ window.removeEventListener(READY_EVENT, finish);
69
+ clearTimeout(timer);
70
+ };
71
+ const timer = setTimeout(() => {
72
+ if (settled)
73
+ return;
74
+ settled = true;
75
+ cleanup();
76
+ reject(new Error('[Ticketlayer Elements] SDK not initialized. Create a Live client before using Elements.'));
77
+ }, timeoutMs);
78
+ window.addEventListener(READY_EVENT, finish);
79
+ // Late-publish race guard: re-check once listener is attached.
80
+ finish();
81
+ });
82
+ }
83
+ /**
84
+ * Subscribe to SDK events (waits for the SDK, returns an unsubscribe function).
85
+ */
86
+ function onSDKEvent(event, callback) {
87
+ let off = null;
88
+ let cancelled = false;
89
+ whenSDK()
90
+ .then((sdk) => {
91
+ if (cancelled)
92
+ return;
93
+ off = sdk.on(event, callback);
94
+ })
95
+ .catch(() => undefined);
96
+ return () => {
97
+ cancelled = true;
98
+ off?.();
99
+ };
100
+ }
101
+
102
+ export { getSDK as g, hasSDK as h, onSDKEvent as o, setSDK as s, whenSDK as w };
@@ -0,0 +1,20 @@
1
+ import { p as promiseResolve, g as globalScripts, b as bootstrapLazy } from './index-Ba-RZTFI.js';
2
+ export { s as setNonce } from './index-Ba-RZTFI.js';
3
+
4
+ /*
5
+ Stencil Client Patch Browser v4.41.1 | MIT Licensed | https://stenciljs.com
6
+ */
7
+
8
+ var patchBrowser = () => {
9
+ const importMeta = import.meta.url;
10
+ const opts = {};
11
+ if (importMeta !== "") {
12
+ opts.resourcesUrl = new URL(".", importMeta).href;
13
+ }
14
+ return promiseResolve(opts);
15
+ };
16
+
17
+ patchBrowser().then(async (options) => {
18
+ await globalScripts();
19
+ return bootstrapLazy([["tl-my-orders",[[1,"tl-my-orders",{"emptyMessage":[1,"empty-message"],"columns":[2],"orders":[32],"authenticated":[32],"loading":[32],"error":[32],"expandedId":[32]}]]],["tl-buy-modal",[[1,"tl-buy-modal",{"eventId":[1,"event-id"],"occurrenceId":[1,"occurrence-id"],"step":[32],"eventName":[32],"imageUrl":[32],"venueLabel":[32],"dateSummary":[32],"selectedOccurrenceId":[32],"occurrenceCount":[32],"occurrenceLabel":[32],"error":[32]}]]],["tl-order-confirmation",[[1,"tl-order-confirmation",{"orderId":[1,"order-id"],"customerEmail":[1,"customer-email"],"showTickets":[4,"show-tickets"],"columns":[2],"order":[32],"resolvedOrderId":[32],"loading":[32],"error":[32],"paymentFailed":[32],"occurrence":[32],"signedInCustomer":[32]},null,{"orderId":[{"watchOrderId":0}]}]]],["tl-cart-drawer",[[1,"tl-cart-drawer",{"side":[1],"heading":[1],"open":[1028],"visible":[32]},null,{"open":[{"onOpenProp":0}]}]]],["tl-event-list",[[1,"tl-event-list",{"limit":[2],"category":[1],"columns":[2],"events":[32],"loading":[32],"error":[32]},null,{"limit":[{"watchFiltersChange":0}],"category":[{"watchFiltersChange":0}]}]]],["tl-buy-tickets-button",[[1,"tl-buy-tickets-button",{"eventId":[1,"event-id"],"occurrenceId":[1,"occurrence-id"],"state":[1],"label":[1],"variant":[1],"size":[1],"fullWidth":[4,"full-width"],"price":[2],"currency":[1],"pricePrefix":[1,"price-prefix"],"disabled":[4],"isHovered":[32]}]]],["tl-buy-tickets-wrapper",[[260,"tl-buy-tickets-wrapper",{"eventId":[1,"event-id"],"occurrenceId":[1,"occurrence-id"],"disabled":[4]}]]],["tl-cart-badge",[[1,"tl-cart-badge",{"showEmpty":[4,"show-empty"],"icon":[1],"size":[1],"badgeOnly":[4,"badge-only"],"itemCount":[32]}]]],["tl-checkout-wrapper",[[260,"tl-checkout-wrapper",{"disabled":[4]}]]],["tl-promo-code",[[1,"tl-promo-code",{"placeholder":[1],"buttonLabel":[1,"button-label"],"code":[32],"applying":[32],"applied":[32],"error":[32]}]]],["tl-seat-map",[[1,"tl-seat-map",{"occurrenceId":[1,"occurrence-id"],"hboUrl":[1,"hbo-url"],"apiUrl":[1,"api-url"],"height":[1],"width":[1],"isReady":[32],"isLoading":[32],"error":[32],"seatsInCart":[32]},null,{"occurrenceId":[{"watchOccurrenceId":0}]}]]],["tl-cart",[[1,"tl-cart",{"showCheckoutButton":[4,"show-checkout-button"],"checkoutLabel":[1,"checkout-label"],"showRemoveButtons":[4,"show-remove-buttons"],"compact":[4],"cart":[32],"loading":[32],"error":[32],"removingItemId":[32]}]]],["tl-event-card",[[1,"tl-event-card",{"event":[16],"eventId":[1,"event-id"],"loadedEvent":[32],"loading":[32],"error":[32]},null,{"eventId":[{"watchEventId":0}]}]]],["tl-login",[[1,"tl-login",{"heading":[1],"allowCodeEntry":[4,"allow-code-entry"],"phase":[32],"email":[32],"code":[32],"busy":[32],"error":[32],"notice":[32],"customer":[32]}]]],["tl-occurrence-selector_2",[[1,"tl-occurrence-selector",{"eventId":[1,"event-id"],"displayMode":[1,"display-mode"],"orientation":[1],"theme":[16],"loading":[32],"error":[32],"occurrences":[32],"currentMonth":[32],"selectedDate":[32],"computedDisplayMode":[32],"containerWidth":[32]},null,{"eventId":[{"onEventIdChange":0}]}],[1,"tl-ticket-selector",{"eventId":[1,"event-id"],"occurrenceId":[1,"occurrence-id"],"showButton":[4,"show-button"],"buttonLabel":[1,"button-label"],"ticketTypes":[32],"quantities":[32],"loading":[32],"error":[32],"adding":[32],"addSuccess":[32]},null,{"eventId":[{"watchPropsChange":0}],"occurrenceId":[{"watchPropsChange":0}]}]]],["tl-order-tickets_2",[[1,"tl-order-tickets",{"orderId":[1,"order-id"],"columns":[2],"tickets":[32],"loading":[32],"error":[32]},null,{"orderId":[{"watchOrder":0}]}],[1,"tl-ticket",{"ticket":[16],"orderId":[1,"order-id"],"qrSvg":[32],"downloading":[32]},null,{"ticket":[{"generateQr":0}]}]]]], options);
20
+ });
@@ -0,0 +1,125 @@
1
+ import { r as registerInstance, c as createEvent, h, H as Host } from './index-Ba-RZTFI.js';
2
+ import { w as whenSDK, g as getSDK } from './sdk-connector-CqhvfyKV.js';
3
+
4
+ const tlBuyModalCss = () => `:host{--_bg:var(--tl-background, #ffffff);--_fg:var(--tl-foreground, #111827);--_muted:var(--tl-muted, #f3f4f6);--_muted-fg:var(--tl-muted-foreground, #6b7280);--_border:var(--tl-border, #e5e7eb);--_primary:var(--tl-primary, #6366f1);--_primary-fg:var(--tl-primary-foreground, #ffffff);--_radius:var(--tl-radius-lg, var(--tl-radius, 0.75rem));--_font:var(--tl-font-family, system-ui, -apple-system, sans-serif);font-family:var(--_font)}.overlay{position:fixed;inset:0;z-index:2147483646;display:flex;align-items:center;justify-content:center;padding:16px;background:rgba(8, 8, 16, 0.72);backdrop-filter:blur(4px);animation:tl-fade 0.18s ease-out}.panel{width:100%;max-width:460px;max-height:90vh;display:flex;flex-direction:column;overflow:hidden;background:var(--_bg);color:var(--_fg);border:1px solid var(--_border);border-radius:var(--_radius);box-shadow:0 24px 64px rgba(0, 0, 0, 0.45);animation:tl-rise 0.22s cubic-bezier(0.16, 1, 0.3, 1);transition:max-width 0.25s cubic-bezier(0.16, 1, 0.3, 1)}.panel--wide{max-width:720px}.panel-header{display:flex;align-items:center;gap:14px;padding:16px 18px;border-bottom:1px solid var(--_border)}.event-thumb{flex:none;width:56px;height:56px;border-radius:12px;background-size:cover;background-position:center;background-color:var(--_muted);border:1px solid var(--_border)}.titles{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}.event-meta{margin:0;font-size:0.8rem;color:var(--_muted-fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kicker{font-size:0.72rem;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;color:var(--_primary)}.event-name{margin:0;font-size:1.18rem;font-weight:700;line-height:1.25;color:var(--_fg);overflow:hidden;text-overflow:ellipsis}.close-btn{flex:none;display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border:0;border-radius:999px;background:var(--_muted);color:var(--_muted-fg);cursor:pointer;transition:color 0.15s, background 0.15s}.close-btn:hover{color:var(--_fg)}.close-btn svg{width:16px;height:16px}.panel-body{padding:18px 22px 22px;overflow-y:auto}.state-msg{display:flex;align-items:center;justify-content:center;gap:10px;padding:40px 0;color:var(--_muted-fg)}.state-msg.error{color:#b91c1c}.spinner{width:16px;height:16px;border:2px solid var(--_border);border-top-color:var(--_primary);border-radius:999px;animation:tl-spin 0.7s linear infinite}.tickets-step{display:flex;flex-direction:column;gap:6px}.back-link{align-self:flex-start;padding:0;border:0;background:none;color:var(--_primary);font-size:0.85rem;font-weight:500;cursor:pointer}.back-link:hover{text-decoration:underline}.occ-label{margin:2px 0 8px;font-size:0.9rem;font-weight:600;color:var(--_fg)}.done-step{display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;padding:16px 0 4px}.done-mark{font-size:2.4rem;line-height:1;margin-bottom:6px}.done-title{margin:0;font-size:1.1rem;font-weight:700;color:var(--_fg)}.done-sub{margin:0 0 14px;font-size:0.9rem;color:var(--_muted-fg)}.primary-btn{width:100%;padding:13px;border:0;border-radius:var(--tl-radius-md, 0.5rem);background:var(--_primary);color:var(--_primary-fg);font-size:0.98rem;font-weight:600;cursor:pointer;transition:opacity 0.15s}.primary-btn:hover{opacity:0.9}.ghost-btn{width:100%;margin-top:8px;padding:12px;border:1px solid var(--_border);border-radius:var(--tl-radius-md, 0.5rem);background:transparent;color:var(--_fg);font-size:0.95rem;font-weight:500;cursor:pointer;transition:background 0.15s}.ghost-btn:hover{background:var(--_muted)}@keyframes tl-fade{from{opacity:0}}@keyframes tl-rise{from{opacity:0;transform:translateY(12px) scale(0.98)}}@keyframes tl-spin{to{transform:rotate(360deg)}}`;
5
+
6
+ const TlBuyModal = class {
7
+ constructor(hostRef) {
8
+ registerInstance(this, hostRef);
9
+ this.tlClose = createEvent(this, "tlClose");
10
+ this.tlCheckout = createEvent(this, "tlCheckout");
11
+ this.tlError = createEvent(this, "tlError");
12
+ this.step = 'loading';
13
+ this.eventName = '';
14
+ this.imageUrl = '';
15
+ this.venueLabel = '';
16
+ this.dateSummary = '';
17
+ this.selectedOccurrenceId = null;
18
+ this.occurrenceCount = 0;
19
+ this.occurrenceLabel = '';
20
+ this.error = null;
21
+ this.handleOccurrenceSelect = (e) => {
22
+ const occ = e.detail.occurrence;
23
+ this.selectedOccurrenceId = occ.id;
24
+ this.occurrenceLabel = this.labelFor(occ);
25
+ this.step = 'tickets';
26
+ };
27
+ this.handleAdded = () => {
28
+ this.step = 'done';
29
+ };
30
+ this.backToDates = () => {
31
+ this.selectedOccurrenceId = null;
32
+ this.step = 'occurrence';
33
+ };
34
+ this.close = () => this.tlClose.emit();
35
+ this.goCheckout = () => this.tlCheckout.emit();
36
+ }
37
+ async componentWillLoad() {
38
+ if (!this.eventId) {
39
+ this.fail('No event specified');
40
+ return;
41
+ }
42
+ try {
43
+ await whenSDK();
44
+ const ev = (await getSDK().getEventsManager().get(this.eventId));
45
+ this.eventName = ev?.name ?? 'Tickets';
46
+ this.imageUrl = ev?.imageUrl || ev?.heroImageUrl || '';
47
+ this.venueLabel = [ev?.venueName, ev?.venueCity].filter(Boolean).join(', ');
48
+ const occs = ev?.occurrences ?? [];
49
+ this.occurrenceCount = occs.length;
50
+ this.dateSummary = this.summariseDates(occs);
51
+ // Skip the date step when one was preselected or there's only one date.
52
+ const initial = this.occurrenceId ?? (occs.length === 1 ? occs[0]?.id : null);
53
+ if (initial) {
54
+ this.selectedOccurrenceId = initial;
55
+ this.occurrenceLabel = this.labelFor(occs.find((o) => o.id === initial));
56
+ this.step = 'tickets';
57
+ }
58
+ else {
59
+ this.step = 'occurrence';
60
+ }
61
+ }
62
+ catch (err) {
63
+ this.fail(err instanceof Error ? err.message : 'Could not load this event');
64
+ }
65
+ }
66
+ fail(message) {
67
+ this.error = message;
68
+ this.step = 'error';
69
+ this.tlError.emit({ message });
70
+ }
71
+ /** A compact date line for the header: a single date, or a range across many. */
72
+ summariseDates(occs) {
73
+ const times = occs
74
+ .map((o) => o.startsAt)
75
+ .filter((s) => !!s)
76
+ .sort();
77
+ if (times.length === 0)
78
+ return '';
79
+ const day = (s) => new Date(s).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' });
80
+ if (times.length === 1) {
81
+ return new Date(times[0]).toLocaleDateString('en-GB', {
82
+ weekday: 'short',
83
+ day: 'numeric',
84
+ month: 'short',
85
+ year: 'numeric',
86
+ });
87
+ }
88
+ const first = day(times[0]);
89
+ const last = day(times[times.length - 1]);
90
+ const range = first === last ? first : `${first} – ${last}`;
91
+ return `${range} · ${times.length} dates`;
92
+ }
93
+ labelFor(occ) {
94
+ if (!occ?.startsAt)
95
+ return '';
96
+ return new Date(occ.startsAt).toLocaleString('en-GB', {
97
+ weekday: 'short',
98
+ day: 'numeric',
99
+ month: 'short',
100
+ hour: '2-digit',
101
+ minute: '2-digit',
102
+ });
103
+ }
104
+ stepKicker() {
105
+ switch (this.step) {
106
+ case 'occurrence':
107
+ return 'Choose a date';
108
+ case 'tickets':
109
+ return 'Select tickets';
110
+ case 'done':
111
+ return 'Nice one';
112
+ default:
113
+ return 'Tickets';
114
+ }
115
+ }
116
+ render() {
117
+ return (h(Host, { key: '1245e518c2b5232f4d9dba091cf808cd3867fbef' }, h("div", { key: '4e770fccdd785444f1cc87df4adab5a5dc1bf58a', class: "overlay", onClick: (e) => {
118
+ if (e.target === e.currentTarget)
119
+ this.close();
120
+ } }, h("div", { key: '57b13dac690028aeebd6a601acfba07f00854c40', class: { panel: true, 'panel--wide': this.step === 'occurrence' }, role: "dialog", "aria-modal": "true", "aria-label": this.eventName }, h("header", { key: '881e9cc70a0ca25947f272b9ebcb2e6d4b4268f2', class: "panel-header" }, this.imageUrl && (h("div", { key: '753f7df1b5118dfacbbc6b89b4e5d7ba114f6cdf', class: "event-thumb", style: { backgroundImage: `url(${this.imageUrl})` } })), h("div", { key: '9aaa32d1add90fabd1b0ea0c100f198962f4e6a5', class: "titles" }, h("span", { key: '538032bdf2338206ad763417386852ff97cc472f', class: "kicker" }, this.stepKicker()), h("h2", { key: '71429804179e7fbbea1fa90a2937a065517092f5', class: "event-name" }, this.eventName), this.venueLabel && h("p", { key: 'dd968b397deab890df3a4fbdff33226e82bd9660', class: "event-meta" }, this.venueLabel), this.dateSummary && h("p", { key: 'f40e6049d09b06c9f599e7d14d6fbb43b39b22fd', class: "event-meta" }, this.dateSummary)), h("button", { key: 'dbe0908f8cd8544654b627921f68cc4961802b77', class: "close-btn", "aria-label": "Close", onClick: this.close }, h("svg", { key: '23a750830e6e16d28cbcd5025507d25848aaadf7', viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, h("path", { key: 'e81b8763a5c781f72c1ca8a2113482948e3ba8cc', d: "M6 6l12 12M18 6L6 18", "stroke-linecap": "round" })))), h("div", { key: 'da71e610f907cf53e78246d2065aaf526d5ceffd', class: "panel-body" }, this.step === 'loading' && (h("div", { key: '28cbb9a98c7b08fa8dcb9d8d5dfbf3bec93fe38d', class: "state-msg" }, h("span", { key: '915c8de87cbdc7da1ccf0622ce6c0f02fccf2cad', class: "spinner" }), " Loading\u2026")), this.step === 'error' && h("div", { key: '5785578bfef6f1ee81d938d91ffd3ded975f8c12', class: "state-msg error" }, this.error), this.step === 'occurrence' && (h("tl-occurrence-selector", { key: 'eeb853eab141c3c103015e82d221a140f6a3a109', eventId: this.eventId, onTlSelect: this.handleOccurrenceSelect })), this.step === 'tickets' && this.selectedOccurrenceId && (h("div", { key: 'f608f592ba651eb431375433eb4ff9393863ade5', class: "tickets-step" }, this.occurrenceCount > 1 && (h("button", { key: '84adfbdbeaceb2cf4238c6ffd09558b4499ca940', class: "back-link", onClick: this.backToDates }, "\u2190 Change date")), this.occurrenceLabel && h("p", { key: '0317e9194049608711e8c622142c3ad2c0a5dc12', class: "occ-label" }, this.occurrenceLabel), h("tl-ticket-selector", { key: '27b1e05d9d92fb8d519375e2b27d4b5ea0a4890a', eventId: this.eventId, occurrenceId: this.selectedOccurrenceId, onTlAddToCart: this.handleAdded }))), this.step === 'done' && (h("div", { key: '0853088206988c66d489f8804df7899821d49e64', class: "done-step" }, h("div", { key: 'c2955b893c4dffaadcdfd27bee96ef2724a131a6', class: "done-mark" }, "\uD83C\uDF9F\uFE0F"), h("p", { key: '370c30dfcbc0c25b4794d984dd261a3a5779a9dc', class: "done-title" }, "Added to your cart"), h("p", { key: 'c462f3c9292740e2fd2c74b173484f80a5dc1a30', class: "done-sub" }, "Held for you while you check out."), h("button", { key: '484991f79572e3213ad6413a1af87599880c3643', class: "primary-btn", onClick: this.goCheckout }, "Go to checkout"), h("button", { key: '5b4ba5a472b794e8f5af0f131dad1c8c11b869f5', class: "ghost-btn", onClick: this.close }, "Keep browsing"))))))));
121
+ }
122
+ };
123
+ TlBuyModal.style = tlBuyModalCss();
124
+
125
+ export { TlBuyModal as tl_buy_modal };
@@ -0,0 +1,129 @@
1
+ import { r as registerInstance, c as createEvent, h, H as Host } from './index-Ba-RZTFI.js';
2
+ import { h as hasSDK, g as getSDK } from './sdk-connector-CqhvfyKV.js';
3
+
4
+ const tlBuyTicketsButtonCss = () => `:host{display:inline-block;font-family:var(--tl-font-family, system-ui, -apple-system, sans-serif)}:host(.full-width){display:block;width:100%}:host(.full-width) .buy-button{width:100%}.buy-button{display:inline-flex;align-items:center;justify-content:center;gap:0.5rem;font-weight:600;border:none;cursor:pointer;text-decoration:none;outline:none;transition:all 0.2s ease;white-space:nowrap}.buy-button.variant-primary{background:var(--button-color);color:var(--button-foreground)}.buy-button.variant-secondary{background:color-mix(in srgb, var(--button-color) 15%, transparent);color:var(--button-color)}.buy-button.variant-outline{background:transparent;color:var(--button-color);border:2px solid var(--button-color)}.buy-button.size-sm{padding:0.5rem 1rem;font-size:0.875rem;border-radius:var(--tl-radius-sm, 0.375rem)}.buy-button.size-md{padding:0.75rem 1.5rem;font-size:1rem;border-radius:var(--tl-radius-md, 0.5rem)}.buy-button.size-lg{padding:1rem 2rem;font-size:1.125rem;border-radius:var(--tl-radius-lg, 0.625rem);min-height:51px}.buy-button.hovered:not(.disabled){opacity:0.9;transform:translateY(-1px)}.buy-button.hovered.variant-primary{background:var(--button-hover-color)}.buy-button.disabled{opacity:0.7;cursor:not-allowed}.icon{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.icon svg{width:1em;height:1em}.label{flex-shrink:0}.price{display:inline-flex;align-items:center;gap:0.25rem;margin-left:0.5rem;white-space:nowrap;opacity:0.9}.price-prefix{opacity:0.7}.price-value{font-weight:700}`;
5
+
6
+ // State configurations
7
+ const STATE_CONFIGS = {
8
+ available: {
9
+ defaultLabel: 'Buy Tickets',
10
+ color: 'var(--tl-primary, #e64b12)',
11
+ hoverColor: 'var(--tl-primary, #d4440f)',
12
+ foreground: 'var(--tl-primary-foreground, #ffffff)',
13
+ },
14
+ soldOut: {
15
+ defaultLabel: 'Sold Out',
16
+ color: '#dc2626',
17
+ hoverColor: '#b91c1c',
18
+ foreground: '#ffffff',
19
+ },
20
+ waitlist: {
21
+ defaultLabel: 'Join Waitlist',
22
+ color: '#2563eb',
23
+ hoverColor: '#1d4ed8',
24
+ foreground: '#ffffff',
25
+ },
26
+ comingSoon: {
27
+ defaultLabel: 'On Sale Soon',
28
+ color: '#d97706',
29
+ hoverColor: '#b45309',
30
+ foreground: '#ffffff',
31
+ },
32
+ };
33
+ const TlBuyTicketsButton = class {
34
+ constructor(hostRef) {
35
+ registerInstance(this, hostRef);
36
+ this.tlClick = createEvent(this, "tlClick");
37
+ /** Button state - determines colour, label, and icon */
38
+ this.state = 'available';
39
+ /** Button variant */
40
+ this.variant = 'primary';
41
+ /** Button size */
42
+ this.size = 'md';
43
+ /** Full width button */
44
+ this.fullWidth = false;
45
+ /** Currency code for price formatting */
46
+ this.currency = 'GBP';
47
+ /** Show price prefix text */
48
+ this.pricePrefix = 'From';
49
+ /** Disabled state */
50
+ this.disabled = false;
51
+ // -------------------------------------------------------------------------
52
+ // State
53
+ // -------------------------------------------------------------------------
54
+ this.isHovered = false;
55
+ // -------------------------------------------------------------------------
56
+ // Methods
57
+ // -------------------------------------------------------------------------
58
+ this.handleClick = () => {
59
+ // Check if button should be interactive
60
+ if (this.disabled || this.state === 'soldOut' || this.state === 'comingSoon') {
61
+ return;
62
+ }
63
+ // Emit click event
64
+ this.tlClick.emit({ eventId: this.eventId, occurrenceId: this.occurrenceId });
65
+ // Open modal via SDK if available
66
+ if (hasSDK()) {
67
+ try {
68
+ const sdk = getSDK();
69
+ sdk.event(this.eventId).openModal({
70
+ occurrenceId: this.occurrenceId,
71
+ });
72
+ }
73
+ catch (err) {
74
+ console.error('[tl-buy-tickets-button] Failed to open modal:', err);
75
+ }
76
+ }
77
+ };
78
+ }
79
+ formatPrice(priceInMinorUnits) {
80
+ const amount = priceInMinorUnits / 100;
81
+ const hasDecimals = amount % 1 !== 0;
82
+ return new Intl.NumberFormat('en-GB', {
83
+ style: 'currency',
84
+ currency: this.currency,
85
+ minimumFractionDigits: hasDecimals ? 2 : 0,
86
+ maximumFractionDigits: hasDecimals ? 2 : 0,
87
+ }).format(amount);
88
+ }
89
+ getStateConfig() {
90
+ return STATE_CONFIGS[this.state];
91
+ }
92
+ isInteractive() {
93
+ return !this.disabled && this.state !== 'soldOut' && this.state !== 'comingSoon';
94
+ }
95
+ // -------------------------------------------------------------------------
96
+ // Render
97
+ // -------------------------------------------------------------------------
98
+ render() {
99
+ const config = this.getStateConfig();
100
+ const buttonLabel = this.label || config.defaultLabel;
101
+ const isInteractive = this.isInteractive();
102
+ return (h(Host, { key: '10c8c36d12223afcfd13c9807c2ef6b0f4c34266', class: { 'full-width': this.fullWidth } }, h("button", { key: 'c7f6a39a837c90ced0176b5d017687afabf99a5a', type: "button", class: {
103
+ 'buy-button': true,
104
+ [`variant-${this.variant}`]: true,
105
+ [`size-${this.size}`]: true,
106
+ 'disabled': !isInteractive,
107
+ 'hovered': this.isHovered && isInteractive,
108
+ }, style: {
109
+ '--button-color': config.color,
110
+ '--button-hover-color': config.hoverColor,
111
+ '--button-foreground': config.foreground,
112
+ }, disabled: !isInteractive, onClick: this.handleClick, onMouseEnter: () => (this.isHovered = true), onMouseLeave: () => (this.isHovered = false) }, h("span", { key: 'e2bc1edc9fbd2a9c81da8cc3293170b1c4275125', class: "icon" }, this.state === 'soldOut' && this.renderSoldOutIcon(), this.state === 'waitlist' && this.renderWaitlistIcon(), this.state === 'comingSoon' && this.renderComingSoonIcon(), this.state === 'available' && this.renderTicketIcon()), h("span", { key: '8371c85dcc24c5ac040744edefe80618421025ef', class: "label" }, buttonLabel), this.price !== undefined && (h("span", { key: 'c02cb5b646ade8866deafb9b3e698115abec5708', class: "price" }, h("span", { key: 'cb0ab272460115a5edebd674362c83711735a70d', class: "price-prefix" }, this.pricePrefix), h("span", { key: 'e28ba56d3928076b624513de95682351f3e0d92b', class: "price-value" }, this.formatPrice(this.price)))))));
113
+ }
114
+ renderTicketIcon() {
115
+ return (h("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z" }), h("path", { d: "M13 5v2" }), h("path", { d: "M13 17v2" }), h("path", { d: "M13 11v2" })));
116
+ }
117
+ renderSoldOutIcon() {
118
+ return (h("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("circle", { cx: "12", cy: "12", r: "10" }), h("path", { d: "m15 9-6 6" }), h("path", { d: "m9 9 6 6" })));
119
+ }
120
+ renderWaitlistIcon() {
121
+ return (h("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("circle", { cx: "12", cy: "12", r: "10" }), h("polyline", { points: "12 6 12 12 16 14" })));
122
+ }
123
+ renderComingSoonIcon() {
124
+ return (h("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "M12 2v4" }), h("path", { d: "m16.2 7.8 2.9-2.9" }), h("path", { d: "M18 12h4" }), h("path", { d: "m16.2 16.2 2.9 2.9" }), h("path", { d: "M12 18v4" }), h("path", { d: "m4.9 19.1 2.9-2.9" }), h("path", { d: "M2 12h4" }), h("path", { d: "m4.9 4.9 2.9 2.9" })));
125
+ }
126
+ };
127
+ TlBuyTicketsButton.style = tlBuyTicketsButtonCss();
128
+
129
+ export { TlBuyTicketsButton as tl_buy_tickets_button };
@@ -0,0 +1,56 @@
1
+ import { r as registerInstance, c as createEvent, h, H as Host, a as getElement } from './index-Ba-RZTFI.js';
2
+ import { h as hasSDK, g as getSDK } from './sdk-connector-CqhvfyKV.js';
3
+
4
+ const tlBuyTicketsWrapperCss = () => `tl-buy-tickets-wrapper,.tl-buy-tickets-wrapper{display:inline-block;cursor:pointer}tl-buy-tickets-wrapper:focus,.tl-buy-tickets-wrapper:focus{outline:2px solid var(--tl-ring, #3b82f6);outline-offset:2px;border-radius:var(--tl-radius-sm, 0.25rem)}tl-buy-tickets-wrapper[disabled],tl-buy-tickets-wrapper.tl-buy-tickets-wrapper--disabled,.tl-buy-tickets-wrapper--disabled{cursor:not-allowed;opacity:0.5}`;
5
+
6
+ const TlBuyTicketsWrapper = class {
7
+ constructor(hostRef) {
8
+ registerInstance(this, hostRef);
9
+ this.tlComplete = createEvent(this, "tl-complete");
10
+ this.tlError = createEvent(this, "tl-error");
11
+ this.tlClose = createEvent(this, "tl-close");
12
+ /**
13
+ * Whether the wrapper is disabled
14
+ */
15
+ this.disabled = false;
16
+ this.handleClick = () => {
17
+ if (this.disabled)
18
+ return;
19
+ if (!hasSDK()) {
20
+ console.error('[tl-buy-tickets-wrapper] SDK not initialized. Call setSDK(ticketlayer) first.');
21
+ this.tlError.emit({ message: 'SDK not initialized' });
22
+ return;
23
+ }
24
+ const sdk = getSDK();
25
+ // Open the modal via SDK
26
+ sdk.event(this.eventId).openModal({
27
+ occurrenceId: this.occurrenceId,
28
+ onComplete: (order) => {
29
+ this.tlComplete.emit(order);
30
+ },
31
+ onError: (err) => {
32
+ this.tlError.emit({ message: err.message });
33
+ },
34
+ onClose: () => {
35
+ this.tlClose.emit();
36
+ },
37
+ });
38
+ };
39
+ this.handleKeyDown = (e) => {
40
+ if (e.key === 'Enter' || e.key === ' ') {
41
+ e.preventDefault();
42
+ this.handleClick();
43
+ }
44
+ };
45
+ }
46
+ render() {
47
+ return (h(Host, { key: 'd6ef81ac9bc1a1194eda1603cbb2a75b355a212e', class: {
48
+ 'tl-buy-tickets-wrapper': true,
49
+ 'tl-buy-tickets-wrapper--disabled': this.disabled,
50
+ }, onClick: this.handleClick, onKeyDown: this.handleKeyDown, role: "button", tabindex: this.disabled ? -1 : 0, "aria-disabled": this.disabled ? 'true' : null }, h("slot", { key: 'faef5aaad20deaf5e442d688c69105e45f9ee26f' })));
51
+ }
52
+ get el() { return getElement(this); }
53
+ };
54
+ TlBuyTicketsWrapper.style = tlBuyTicketsWrapperCss();
55
+
56
+ export { TlBuyTicketsWrapper as tl_buy_tickets_wrapper };