@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,366 @@
1
+ /**
2
+ * TlSeatMap Stencil Component
3
+ *
4
+ * An iframe wrapper for embedding the Ticketlayer seat map.
5
+ * The actual seat map is rendered by HBO at /embed/seats and this component
6
+ * handles communication via postMessage.
7
+ *
8
+ * @element tl-seat-map
9
+ * @slot - No slots
10
+ *
11
+ * @fires tlReady - Fired when the seat map iframe is ready
12
+ * @fires tlLoad - Fired when the seat map has loaded, includes seatMapId
13
+ * @fires tlError - Fired when an error occurs
14
+ * @fires tlSeatAdded - Fired when a seat is added to cart
15
+ * @fires tlSeatRemoved - Fired when a seat is removed from cart
16
+ * @fires tlCartChange - Fired when cart seats change
17
+ */
18
+ import { h } from "@stencil/core";
19
+ import { getSDK, hasSDK } from "../../utils/sdk-connector";
20
+ export class TlSeatMap {
21
+ constructor() {
22
+ /** Base URL for the hosted seat map (HBO URL) */
23
+ this.hboUrl = 'https://checkout.ticketlayer.com';
24
+ /** API URL for the seat map data */
25
+ this.apiUrl = 'https://api.ticketlayer.com';
26
+ /** Height of the seat map */
27
+ this.height = '600px';
28
+ /** Width of the seat map */
29
+ this.width = '100%';
30
+ // -------------------------------------------------------------------------
31
+ // State
32
+ // -------------------------------------------------------------------------
33
+ this.isReady = false;
34
+ this.isLoading = true;
35
+ this.error = null;
36
+ this.seatsInCart = [];
37
+ // -------------------------------------------------------------------------
38
+ // Methods
39
+ // -------------------------------------------------------------------------
40
+ this.postToIframe = (type, data = {}) => {
41
+ if (this.iframeRef?.contentWindow) {
42
+ this.iframeRef.contentWindow.postMessage({ type, ...data }, '*');
43
+ }
44
+ };
45
+ this.handleMessage = (event) => {
46
+ if (!event.data || !event.data.type)
47
+ return;
48
+ switch (event.data.type) {
49
+ case 'seatmap:ready':
50
+ this.isReady = true;
51
+ this.isLoading = false;
52
+ this.tlReady.emit();
53
+ // Send initial cart seats
54
+ this.postToIframe('seatmap:set-cart-seats', { seatIds: this.seatsInCart });
55
+ break;
56
+ case 'seatmap:loaded':
57
+ this.tlLoad.emit({ seatMapId: event.data.seatMapId });
58
+ break;
59
+ case 'seatmap:error':
60
+ this.error = event.data.error;
61
+ this.isLoading = false;
62
+ this.tlError.emit({ error: event.data.error });
63
+ break;
64
+ case 'seatmap:add-seat':
65
+ this.handleAddSeat(event.data.seatId, event.data.ticketTypeId);
66
+ break;
67
+ case 'seatmap:remove-seat':
68
+ this.handleRemoveSeat(event.data.seatId);
69
+ break;
70
+ }
71
+ };
72
+ this.handleAddSeat = async (seatId, ticketTypeId) => {
73
+ if (!hasSDK()) {
74
+ console.warn('[tl-seat-map] SDK not available, cannot add seat');
75
+ this.postToIframe('seatmap:add-seat-failed', { seatId, error: 'SDK not available' });
76
+ return;
77
+ }
78
+ try {
79
+ const sdk = getSDK();
80
+ await sdk.getCartManager().addSeat(seatId, ticketTypeId, this.occurrenceId);
81
+ this.postToIframe('seatmap:add-seat-confirmed', { seatId });
82
+ this.seatsInCart = [...this.seatsInCart, seatId];
83
+ this.tlSeatAdded.emit({ seatId, ticketTypeId });
84
+ this.tlCartChange.emit({ seatIds: this.seatsInCart });
85
+ }
86
+ catch (err) {
87
+ console.error('[tl-seat-map] Failed to add seat:', err);
88
+ this.postToIframe('seatmap:add-seat-failed', { seatId, error: 'Failed to add seat' });
89
+ }
90
+ };
91
+ this.handleRemoveSeat = async (seatId) => {
92
+ if (!hasSDK()) {
93
+ console.warn('[tl-seat-map] SDK not available, cannot remove seat');
94
+ this.postToIframe('seatmap:remove-seat-failed', { seatId, error: 'SDK not available' });
95
+ return;
96
+ }
97
+ try {
98
+ const sdk = getSDK();
99
+ await sdk.getCartManager().removeSeat(seatId, this.occurrenceId);
100
+ this.postToIframe('seatmap:remove-seat-confirmed', { seatId });
101
+ this.seatsInCart = this.seatsInCart.filter(id => id !== seatId);
102
+ this.tlSeatRemoved.emit({ seatId });
103
+ this.tlCartChange.emit({ seatIds: this.seatsInCart });
104
+ }
105
+ catch (err) {
106
+ console.error('[tl-seat-map] Failed to remove seat:', err);
107
+ this.postToIframe('seatmap:remove-seat-failed', { seatId, error: 'Failed to remove seat' });
108
+ }
109
+ };
110
+ }
111
+ // -------------------------------------------------------------------------
112
+ // Lifecycle
113
+ // -------------------------------------------------------------------------
114
+ componentWillLoad() {
115
+ // Add message listener
116
+ window.addEventListener('message', this.handleMessage);
117
+ }
118
+ disconnectedCallback() {
119
+ // Clean up message listener
120
+ window.removeEventListener('message', this.handleMessage);
121
+ }
122
+ watchOccurrenceId() {
123
+ // Reset state when occurrence changes
124
+ this.isReady = false;
125
+ this.isLoading = true;
126
+ this.error = null;
127
+ }
128
+ getIframeSrc() {
129
+ return `${this.hboUrl}/embed/seats?occurrenceId=${encodeURIComponent(this.occurrenceId)}&apiUrl=${encodeURIComponent(this.apiUrl)}`;
130
+ }
131
+ // -------------------------------------------------------------------------
132
+ // Render
133
+ // -------------------------------------------------------------------------
134
+ render() {
135
+ return (h("div", { key: 'f1efda6053825bdeb72aa277ad9fb5533fc56881', class: "seat-map-container", style: {
136
+ width: this.width,
137
+ height: this.height,
138
+ } }, this.isLoading && (h("div", { key: 'd6017235cb2e06fcc27184b382747dc8bcae5b6c', class: "loading" }, h("div", { key: '63618e07b6f4a2822418283fc83ab08aaec054a2', class: "spinner" }), h("p", { key: '0de2e4f71f78c5e662b03f5c0217ae43a2c4c1df' }, "Loading seat map..."))), this.error && (h("div", { key: 'a2b45dc5a66e18109cd4cf8677989e669117dcc0', class: "error" }, h("p", { key: 'c50b5527a2f6308b53e0389f94cacb2ebeef7262', class: "error-title" }, "Error"), h("p", { key: '1625a73993cbac40bfefb7913e0b735c0082a23f', class: "error-message" }, this.error))), h("iframe", { key: 'c7fc0441b436086d4717a87723108b1471c941ad', ref: (el) => (this.iframeRef = el), src: this.getIframeSrc(), class: {
139
+ 'seat-map-iframe': true,
140
+ hidden: this.isLoading || !!this.error,
141
+ }, title: "Ticketlayer Seat Map", allow: "fullscreen" })));
142
+ }
143
+ static get is() { return "tl-seat-map"; }
144
+ static get encapsulation() { return "shadow"; }
145
+ static get originalStyleUrls() {
146
+ return {
147
+ "$": ["tl-seat-map.css"]
148
+ };
149
+ }
150
+ static get styleUrls() {
151
+ return {
152
+ "$": ["tl-seat-map.css"]
153
+ };
154
+ }
155
+ static get properties() {
156
+ return {
157
+ "occurrenceId": {
158
+ "type": "string",
159
+ "mutable": false,
160
+ "complexType": {
161
+ "original": "string",
162
+ "resolved": "string",
163
+ "references": {}
164
+ },
165
+ "required": true,
166
+ "optional": false,
167
+ "docs": {
168
+ "tags": [],
169
+ "text": "Occurrence ID to show seat map for"
170
+ },
171
+ "getter": false,
172
+ "setter": false,
173
+ "reflect": false,
174
+ "attribute": "occurrence-id"
175
+ },
176
+ "hboUrl": {
177
+ "type": "string",
178
+ "mutable": false,
179
+ "complexType": {
180
+ "original": "string",
181
+ "resolved": "string",
182
+ "references": {}
183
+ },
184
+ "required": false,
185
+ "optional": false,
186
+ "docs": {
187
+ "tags": [],
188
+ "text": "Base URL for the hosted seat map (HBO URL)"
189
+ },
190
+ "getter": false,
191
+ "setter": false,
192
+ "reflect": false,
193
+ "attribute": "hbo-url",
194
+ "defaultValue": "'https://checkout.ticketlayer.com'"
195
+ },
196
+ "apiUrl": {
197
+ "type": "string",
198
+ "mutable": false,
199
+ "complexType": {
200
+ "original": "string",
201
+ "resolved": "string",
202
+ "references": {}
203
+ },
204
+ "required": false,
205
+ "optional": false,
206
+ "docs": {
207
+ "tags": [],
208
+ "text": "API URL for the seat map data"
209
+ },
210
+ "getter": false,
211
+ "setter": false,
212
+ "reflect": false,
213
+ "attribute": "api-url",
214
+ "defaultValue": "'https://api.ticketlayer.com'"
215
+ },
216
+ "height": {
217
+ "type": "string",
218
+ "mutable": false,
219
+ "complexType": {
220
+ "original": "string",
221
+ "resolved": "string",
222
+ "references": {}
223
+ },
224
+ "required": false,
225
+ "optional": false,
226
+ "docs": {
227
+ "tags": [],
228
+ "text": "Height of the seat map"
229
+ },
230
+ "getter": false,
231
+ "setter": false,
232
+ "reflect": false,
233
+ "attribute": "height",
234
+ "defaultValue": "'600px'"
235
+ },
236
+ "width": {
237
+ "type": "string",
238
+ "mutable": false,
239
+ "complexType": {
240
+ "original": "string",
241
+ "resolved": "string",
242
+ "references": {}
243
+ },
244
+ "required": false,
245
+ "optional": false,
246
+ "docs": {
247
+ "tags": [],
248
+ "text": "Width of the seat map"
249
+ },
250
+ "getter": false,
251
+ "setter": false,
252
+ "reflect": false,
253
+ "attribute": "width",
254
+ "defaultValue": "'100%'"
255
+ }
256
+ };
257
+ }
258
+ static get states() {
259
+ return {
260
+ "isReady": {},
261
+ "isLoading": {},
262
+ "error": {},
263
+ "seatsInCart": {}
264
+ };
265
+ }
266
+ static get events() {
267
+ return [{
268
+ "method": "tlReady",
269
+ "name": "tlReady",
270
+ "bubbles": true,
271
+ "cancelable": true,
272
+ "composed": true,
273
+ "docs": {
274
+ "tags": [],
275
+ "text": "Emitted when seat map is ready"
276
+ },
277
+ "complexType": {
278
+ "original": "void",
279
+ "resolved": "void",
280
+ "references": {}
281
+ }
282
+ }, {
283
+ "method": "tlLoad",
284
+ "name": "tlLoad",
285
+ "bubbles": true,
286
+ "cancelable": true,
287
+ "composed": true,
288
+ "docs": {
289
+ "tags": [],
290
+ "text": "Emitted when seat map is loaded"
291
+ },
292
+ "complexType": {
293
+ "original": "{ seatMapId: string }",
294
+ "resolved": "{ seatMapId: string; }",
295
+ "references": {}
296
+ }
297
+ }, {
298
+ "method": "tlError",
299
+ "name": "tlError",
300
+ "bubbles": true,
301
+ "cancelable": true,
302
+ "composed": true,
303
+ "docs": {
304
+ "tags": [],
305
+ "text": "Emitted when an error occurs"
306
+ },
307
+ "complexType": {
308
+ "original": "{ error: string }",
309
+ "resolved": "{ error: string; }",
310
+ "references": {}
311
+ }
312
+ }, {
313
+ "method": "tlSeatAdded",
314
+ "name": "tlSeatAdded",
315
+ "bubbles": true,
316
+ "cancelable": true,
317
+ "composed": true,
318
+ "docs": {
319
+ "tags": [],
320
+ "text": "Emitted when a seat is added to cart"
321
+ },
322
+ "complexType": {
323
+ "original": "{ seatId: string; ticketTypeId: string }",
324
+ "resolved": "{ seatId: string; ticketTypeId: string; }",
325
+ "references": {}
326
+ }
327
+ }, {
328
+ "method": "tlSeatRemoved",
329
+ "name": "tlSeatRemoved",
330
+ "bubbles": true,
331
+ "cancelable": true,
332
+ "composed": true,
333
+ "docs": {
334
+ "tags": [],
335
+ "text": "Emitted when a seat is removed from cart"
336
+ },
337
+ "complexType": {
338
+ "original": "{ seatId: string }",
339
+ "resolved": "{ seatId: string; }",
340
+ "references": {}
341
+ }
342
+ }, {
343
+ "method": "tlCartChange",
344
+ "name": "tlCartChange",
345
+ "bubbles": true,
346
+ "cancelable": true,
347
+ "composed": true,
348
+ "docs": {
349
+ "tags": [],
350
+ "text": "Emitted when cart seats change"
351
+ },
352
+ "complexType": {
353
+ "original": "{ seatIds: string[] }",
354
+ "resolved": "{ seatIds: string[]; }",
355
+ "references": {}
356
+ }
357
+ }];
358
+ }
359
+ static get elementRef() { return "el"; }
360
+ static get watchers() {
361
+ return [{
362
+ "propName": "occurrenceId",
363
+ "methodName": "watchOccurrenceId"
364
+ }];
365
+ }
366
+ }
@@ -0,0 +1,90 @@
1
+ :host {
2
+ display: block;
3
+ font-family: var(--tl-font-family, system-ui, sans-serif);
4
+ }
5
+
6
+ .ticket {
7
+ border: 1px solid var(--tl-border, #e5e7eb);
8
+ border-radius: var(--tl-radius-lg, 0.75rem);
9
+ background: var(--tl-card, #ffffff);
10
+ padding: var(--tl-spacing-5, 1.25rem);
11
+ text-align: center;
12
+ }
13
+
14
+ .qr-wrap {
15
+ position: relative;
16
+ width: 160px;
17
+ height: 160px;
18
+ margin: 0 auto;
19
+ }
20
+
21
+ .qr {
22
+ width: 160px;
23
+ height: 160px;
24
+ }
25
+
26
+ .qr svg {
27
+ width: 100%;
28
+ height: 100%;
29
+ display: block;
30
+ }
31
+
32
+ .qr.inactive {
33
+ opacity: 0.3;
34
+ }
35
+
36
+ .stamp {
37
+ position: absolute;
38
+ top: 50%;
39
+ left: 50%;
40
+ transform: translate(-50%, -50%);
41
+ padding: 0.25rem 0.5rem;
42
+ border-radius: var(--tl-radius-sm, 0.25rem);
43
+ background: rgba(17, 24, 39, 0.85);
44
+ color: #ffffff;
45
+ font-size: 0.7rem;
46
+ font-weight: 700;
47
+ text-transform: uppercase;
48
+ letter-spacing: 0.05em;
49
+ }
50
+
51
+ .name {
52
+ margin: 1rem 0 0;
53
+ font-weight: 600;
54
+ color: var(--tl-foreground, #111827);
55
+ }
56
+
57
+ .meta {
58
+ margin: 0.125rem 0 0;
59
+ font-size: 0.875rem;
60
+ color: var(--tl-muted-foreground, #6b7280);
61
+ }
62
+
63
+ .barcode {
64
+ margin: 0.25rem 0 0;
65
+ font-family: ui-monospace, monospace;
66
+ font-size: 0.625rem;
67
+ color: var(--tl-muted-foreground, #9ca3af);
68
+ word-break: break-all;
69
+ }
70
+
71
+ .download {
72
+ margin-top: 0.75rem;
73
+ padding: 0.375rem 0.75rem;
74
+ border: 1px solid var(--tl-border, #e5e7eb);
75
+ border-radius: var(--tl-radius-md, 0.5rem);
76
+ background: transparent;
77
+ color: var(--tl-foreground, #111827);
78
+ font-size: 0.875rem;
79
+ font-weight: 500;
80
+ cursor: pointer;
81
+ }
82
+
83
+ .download:hover {
84
+ background: var(--tl-muted, #f3f4f6);
85
+ }
86
+
87
+ .download:disabled {
88
+ opacity: 0.5;
89
+ cursor: default;
90
+ }
@@ -0,0 +1,129 @@
1
+ import { h } from "@stencil/core";
2
+ import QRCode from "qrcode";
3
+ import { whenSDK } from "../../utils/sdk-connector";
4
+ /**
5
+ * tl-ticket - a single event ticket: a scannable QR (the redemption token),
6
+ * ticket name / seat / holder, and a PDF download. Greys out + stamps
7
+ * Used/Void when redeemed or cancelled.
8
+ */
9
+ export class TlTicket {
10
+ constructor() {
11
+ this.qrSvg = '';
12
+ this.downloading = false;
13
+ }
14
+ async generateQr() {
15
+ if (this.ticket?.barcode) {
16
+ this.qrSvg = await QRCode.toString(this.ticket.barcode, {
17
+ type: 'svg',
18
+ margin: 0,
19
+ errorCorrectionLevel: 'M',
20
+ });
21
+ }
22
+ }
23
+ async componentWillLoad() {
24
+ await this.generateQr();
25
+ }
26
+ async download() {
27
+ try {
28
+ this.downloading = true;
29
+ const sdk = await whenSDK();
30
+ const orders = sdk.getOrdersManager?.();
31
+ if (!orders)
32
+ throw new Error('Ticket downloads are not available');
33
+ const blob = await orders.ticketPdf(this.orderId, this.ticket.id);
34
+ const url = URL.createObjectURL(blob);
35
+ const a = document.createElement('a');
36
+ a.href = url;
37
+ a.download = `ticket-${this.ticket.id}.pdf`;
38
+ document.body.appendChild(a);
39
+ a.click();
40
+ a.remove();
41
+ URL.revokeObjectURL(url);
42
+ }
43
+ catch (err) {
44
+ console.error('[tl-ticket] download failed', err);
45
+ }
46
+ finally {
47
+ this.downloading = false;
48
+ }
49
+ }
50
+ render() {
51
+ const t = this.ticket;
52
+ if (!t)
53
+ return null;
54
+ const used = t.admissionStatus === 'fully_redeemed';
55
+ const voided = ['cancelled', 'expired'].includes(t.status);
56
+ const inactive = used || voided;
57
+ return (h("div", { class: "ticket" }, h("div", { class: "qr-wrap" }, h("div", { class: { qr: true, inactive }, innerHTML: this.qrSvg }), inactive && h("span", { class: "stamp" }, used ? 'Used' : 'Void')), h("p", { class: "name" }, t.name), t.seatLabel && h("p", { class: "meta" }, "Seat ", t.seatLabel), t.holderName && h("p", { class: "meta" }, t.holderName), h("p", { class: "barcode" }, t.barcode), h("button", { class: "download", disabled: this.downloading, onClick: () => this.download() }, this.downloading ? 'Preparing…' : 'Download PDF')));
58
+ }
59
+ static get is() { return "tl-ticket"; }
60
+ static get encapsulation() { return "shadow"; }
61
+ static get originalStyleUrls() {
62
+ return {
63
+ "$": ["tl-ticket.css"]
64
+ };
65
+ }
66
+ static get styleUrls() {
67
+ return {
68
+ "$": ["tl-ticket.css"]
69
+ };
70
+ }
71
+ static get properties() {
72
+ return {
73
+ "ticket": {
74
+ "type": "unknown",
75
+ "mutable": false,
76
+ "complexType": {
77
+ "original": "TlTicketData",
78
+ "resolved": "TlTicketData",
79
+ "references": {
80
+ "TlTicketData": {
81
+ "location": "local",
82
+ "path": "/home/runner/work/live-elements/live-elements/src/components/tl-ticket/tl-ticket.tsx",
83
+ "id": "src/components/tl-ticket/tl-ticket.tsx::TlTicketData"
84
+ }
85
+ }
86
+ },
87
+ "required": true,
88
+ "optional": false,
89
+ "docs": {
90
+ "tags": [],
91
+ "text": "The ticket to render."
92
+ },
93
+ "getter": false,
94
+ "setter": false
95
+ },
96
+ "orderId": {
97
+ "type": "string",
98
+ "mutable": false,
99
+ "complexType": {
100
+ "original": "string",
101
+ "resolved": "string",
102
+ "references": {}
103
+ },
104
+ "required": true,
105
+ "optional": false,
106
+ "docs": {
107
+ "tags": [],
108
+ "text": "Order id this ticket belongs to (for the PDF download)."
109
+ },
110
+ "getter": false,
111
+ "setter": false,
112
+ "reflect": false,
113
+ "attribute": "order-id"
114
+ }
115
+ };
116
+ }
117
+ static get states() {
118
+ return {
119
+ "qrSvg": {},
120
+ "downloading": {}
121
+ };
122
+ }
123
+ static get watchers() {
124
+ return [{
125
+ "propName": "ticket",
126
+ "methodName": "generateQr"
127
+ }];
128
+ }
129
+ }