@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,217 @@
1
+ import { h } from "@stencil/core";
2
+ import { whenSDK } from "../../utils/sdk-connector";
3
+ // Storage key for persisted cart count
4
+ const CART_COUNT_KEY = 'tl_cart_count';
5
+ export class TlCartBadge {
6
+ constructor() {
7
+ /**
8
+ * Show the badge even when count is 0
9
+ */
10
+ this.showEmpty = false;
11
+ /**
12
+ * Size variant
13
+ */
14
+ this.size = 'md';
15
+ /**
16
+ * Badge only mode - only shows the count bubble, no icon or button
17
+ */
18
+ this.badgeOnly = false;
19
+ this.itemCount = 0;
20
+ this.handleClick = () => {
21
+ this.tlClick.emit({ itemCount: this.itemCount });
22
+ };
23
+ }
24
+ componentWillLoad() {
25
+ // Initialize with persisted count to prevent FOUC
26
+ this.itemCount = this.getPersistedCartCount();
27
+ }
28
+ componentDidLoad() {
29
+ this.subscribeToCartUpdates();
30
+ }
31
+ disconnectedCallback() {
32
+ if (this.unsubscribe) {
33
+ this.unsubscribe();
34
+ }
35
+ }
36
+ getPersistedCartCount() {
37
+ if (typeof window === 'undefined')
38
+ return 0;
39
+ try {
40
+ const stored = localStorage.getItem(CART_COUNT_KEY);
41
+ return stored ? parseInt(stored, 10) || 0 : 0;
42
+ }
43
+ catch {
44
+ return 0;
45
+ }
46
+ }
47
+ persistCartCount(count) {
48
+ if (typeof window === 'undefined')
49
+ return;
50
+ try {
51
+ localStorage.setItem(CART_COUNT_KEY, count.toString());
52
+ }
53
+ catch {
54
+ // localStorage may be unavailable
55
+ }
56
+ }
57
+ async subscribeToCartUpdates() {
58
+ const sdk = await whenSDK().catch(() => null);
59
+ if (!sdk)
60
+ return;
61
+ const cartManager = sdk.getCartManager?.();
62
+ if (!cartManager)
63
+ return;
64
+ // Subscribe to cart updates
65
+ this.unsubscribe = cartManager.on?.('cart:updated', (cart) => {
66
+ const newCount = cart?.itemCount || 0;
67
+ console.log('[tl-cart-badge] Cart updated:', newCount);
68
+ this.itemCount = newCount;
69
+ this.persistCartCount(newCount);
70
+ });
71
+ // Load initial cart
72
+ cartManager.get?.().then((cart) => {
73
+ const newCount = cart?.itemCount || 0;
74
+ this.itemCount = newCount;
75
+ this.persistCartCount(newCount);
76
+ }).catch(() => {
77
+ // Cart may not exist yet - keep persisted value
78
+ });
79
+ }
80
+ renderIcon() {
81
+ if (this.icon) {
82
+ return h("span", { class: "icon-text" }, this.icon);
83
+ }
84
+ return (h("svg", { class: "icon-svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor" }, h("path", { "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "2", d: "M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" })));
85
+ }
86
+ render() {
87
+ const showBadge = this.itemCount > 0 || this.showEmpty;
88
+ const displayCount = this.itemCount > 99 ? '99+' : this.itemCount.toString();
89
+ // Badge only mode - just show the count bubble
90
+ if (this.badgeOnly) {
91
+ if (this.itemCount === 0) {
92
+ return null;
93
+ }
94
+ return (h("span", { class: `badge-only size-${this.size}` }, displayCount));
95
+ }
96
+ // Full mode with icon and badge
97
+ return (h("button", { class: `cart-badge size-${this.size}`, onClick: this.handleClick, "aria-label": `Cart with ${this.itemCount} items` }, this.renderIcon(), showBadge && this.itemCount > 0 && (h("span", { class: "badge-count" }, displayCount))));
98
+ }
99
+ static get is() { return "tl-cart-badge"; }
100
+ static get encapsulation() { return "shadow"; }
101
+ static get originalStyleUrls() {
102
+ return {
103
+ "$": ["tl-cart-badge.css"]
104
+ };
105
+ }
106
+ static get styleUrls() {
107
+ return {
108
+ "$": ["tl-cart-badge.css"]
109
+ };
110
+ }
111
+ static get properties() {
112
+ return {
113
+ "showEmpty": {
114
+ "type": "boolean",
115
+ "mutable": false,
116
+ "complexType": {
117
+ "original": "boolean",
118
+ "resolved": "boolean",
119
+ "references": {}
120
+ },
121
+ "required": false,
122
+ "optional": false,
123
+ "docs": {
124
+ "tags": [],
125
+ "text": "Show the badge even when count is 0"
126
+ },
127
+ "getter": false,
128
+ "setter": false,
129
+ "reflect": false,
130
+ "attribute": "show-empty",
131
+ "defaultValue": "false"
132
+ },
133
+ "icon": {
134
+ "type": "string",
135
+ "mutable": false,
136
+ "complexType": {
137
+ "original": "string",
138
+ "resolved": "string | undefined",
139
+ "references": {}
140
+ },
141
+ "required": false,
142
+ "optional": true,
143
+ "docs": {
144
+ "tags": [],
145
+ "text": "Custom icon (emoji or text). If not provided, uses cart SVG"
146
+ },
147
+ "getter": false,
148
+ "setter": false,
149
+ "reflect": false,
150
+ "attribute": "icon"
151
+ },
152
+ "size": {
153
+ "type": "string",
154
+ "mutable": false,
155
+ "complexType": {
156
+ "original": "'sm' | 'md' | 'lg'",
157
+ "resolved": "\"lg\" | \"md\" | \"sm\"",
158
+ "references": {}
159
+ },
160
+ "required": false,
161
+ "optional": false,
162
+ "docs": {
163
+ "tags": [],
164
+ "text": "Size variant"
165
+ },
166
+ "getter": false,
167
+ "setter": false,
168
+ "reflect": false,
169
+ "attribute": "size",
170
+ "defaultValue": "'md'"
171
+ },
172
+ "badgeOnly": {
173
+ "type": "boolean",
174
+ "mutable": false,
175
+ "complexType": {
176
+ "original": "boolean",
177
+ "resolved": "boolean",
178
+ "references": {}
179
+ },
180
+ "required": false,
181
+ "optional": false,
182
+ "docs": {
183
+ "tags": [],
184
+ "text": "Badge only mode - only shows the count bubble, no icon or button"
185
+ },
186
+ "getter": false,
187
+ "setter": false,
188
+ "reflect": false,
189
+ "attribute": "badge-only",
190
+ "defaultValue": "false"
191
+ }
192
+ };
193
+ }
194
+ static get states() {
195
+ return {
196
+ "itemCount": {}
197
+ };
198
+ }
199
+ static get events() {
200
+ return [{
201
+ "method": "tlClick",
202
+ "name": "tlClick",
203
+ "bubbles": true,
204
+ "cancelable": true,
205
+ "composed": true,
206
+ "docs": {
207
+ "tags": [],
208
+ "text": "Emitted when the badge is clicked"
209
+ },
210
+ "complexType": {
211
+ "original": "{ itemCount: number }",
212
+ "resolved": "{ itemCount: number; }",
213
+ "references": {}
214
+ }
215
+ }];
216
+ }
217
+ }
@@ -0,0 +1,98 @@
1
+ :host {
2
+ --_bg: var(--tl-background, #ffffff);
3
+ --_fg: var(--tl-foreground, #111827);
4
+ --_muted-fg: var(--tl-muted-foreground, #6b7280);
5
+ --_muted: var(--tl-muted, #f3f4f6);
6
+ --_border: var(--tl-border, #e5e7eb);
7
+ --_font: var(--tl-font-family, system-ui, -apple-system, sans-serif);
8
+ font-family: var(--_font);
9
+ }
10
+
11
+ .overlay {
12
+ position: fixed;
13
+ inset: 0;
14
+ z-index: 2147483640;
15
+ background: rgba(8, 8, 16, 0.6);
16
+ backdrop-filter: blur(2px);
17
+ opacity: 0;
18
+ pointer-events: none;
19
+ transition: opacity 0.25s ease;
20
+ }
21
+
22
+ .overlay.is-open {
23
+ opacity: 1;
24
+ pointer-events: auto;
25
+ }
26
+
27
+ .panel {
28
+ position: fixed;
29
+ top: 0;
30
+ bottom: 0;
31
+ width: min(420px, 100%);
32
+ display: flex;
33
+ flex-direction: column;
34
+ background: var(--_bg);
35
+ color: var(--_fg);
36
+ box-shadow: 0 0 48px rgba(0, 0, 0, 0.5);
37
+ transition: transform 0.28s cubic-bezier(0.16, 1, 0.3, 1);
38
+ will-change: transform;
39
+ }
40
+
41
+ .panel--right {
42
+ right: 0;
43
+ border-left: 1px solid var(--_border);
44
+ transform: translateX(100%);
45
+ }
46
+
47
+ .panel--left {
48
+ left: 0;
49
+ border-right: 1px solid var(--_border);
50
+ transform: translateX(-100%);
51
+ }
52
+
53
+ .panel.is-open {
54
+ transform: translateX(0);
55
+ }
56
+
57
+ .drawer-header {
58
+ display: flex;
59
+ align-items: center;
60
+ justify-content: space-between;
61
+ padding: 18px 20px;
62
+ border-bottom: 1px solid var(--_border);
63
+ }
64
+
65
+ .drawer-title {
66
+ margin: 0;
67
+ font-size: 1.1rem;
68
+ font-weight: 700;
69
+ }
70
+
71
+ .close-btn {
72
+ display: inline-flex;
73
+ align-items: center;
74
+ justify-content: center;
75
+ width: 34px;
76
+ height: 34px;
77
+ border: 0;
78
+ border-radius: 999px;
79
+ background: var(--_muted);
80
+ color: var(--_muted-fg);
81
+ cursor: pointer;
82
+ transition: color 0.15s;
83
+ }
84
+
85
+ .close-btn:hover {
86
+ color: var(--_fg);
87
+ }
88
+
89
+ .close-btn svg {
90
+ width: 16px;
91
+ height: 16px;
92
+ }
93
+
94
+ .drawer-body {
95
+ flex: 1;
96
+ overflow-y: auto;
97
+ padding: 18px 20px;
98
+ }
@@ -0,0 +1,185 @@
1
+ import { h, Host } from "@stencil/core";
2
+ import { onSDKEvent } from "../../utils/sdk-connector";
3
+ /**
4
+ * @component tl-cart-drawer
5
+ *
6
+ * A slide-in cart panel (off-canvas) showing the current cart. It opens when
7
+ * anything raises the `ui:cart-requested` bus intent - e.g. wire a
8
+ * `tl-cart-badge`'s click to emit it - and closes on the backdrop, the close
9
+ * button, Escape, or `ui:modal-close-requested`. The panel embeds `<tl-cart>`,
10
+ * so the actual cart rendering / remove / checkout is shared with the inline
11
+ * cart; the drawer only adds the off-canvas chrome.
12
+ *
13
+ * @prop side - which edge the panel slides from (default 'right')
14
+ * @event tlOpen - the drawer opened
15
+ * @event tlClose - the drawer closed
16
+ */
17
+ export class TlCartDrawer {
18
+ constructor() {
19
+ /** Edge the panel slides in from. */
20
+ this.side = 'right';
21
+ /** Heading shown at the top of the panel. */
22
+ this.heading = 'Your cart';
23
+ /** Controlled open state (also driven by the `ui:cart-requested` intent). */
24
+ this.open = false;
25
+ this.visible = false;
26
+ this.onKey = (e) => {
27
+ if (e.key === 'Escape' && this.visible)
28
+ this.setOpen(false);
29
+ };
30
+ this.close = () => this.setOpen(false);
31
+ }
32
+ connectedCallback() {
33
+ this.visible = this.open;
34
+ // Open on the cart intent; close on the shared modal-close intent.
35
+ this.offCart = onSDKEvent('ui:cart-requested', () => this.setOpen(true));
36
+ this.offClose = onSDKEvent('ui:modal-close-requested', () => this.setOpen(false));
37
+ if (typeof document !== 'undefined')
38
+ document.addEventListener('keydown', this.onKey);
39
+ }
40
+ disconnectedCallback() {
41
+ this.offCart?.();
42
+ this.offClose?.();
43
+ if (typeof document !== 'undefined')
44
+ document.removeEventListener('keydown', this.onKey);
45
+ }
46
+ onOpenProp(v) {
47
+ this.visible = v;
48
+ }
49
+ setOpen(v) {
50
+ if (this.visible === v)
51
+ return;
52
+ this.open = v;
53
+ this.visible = v;
54
+ if (v)
55
+ this.tlOpen.emit();
56
+ else
57
+ this.tlClose.emit();
58
+ }
59
+ render() {
60
+ return (h(Host, { key: '5b4dbc69206ef19bcf3b0ba619a67728c8e35e68' }, h("div", { key: '0312918752eb5eebb86206be7094c1024dbd3457', class: { overlay: true, 'is-open': this.visible }, onClick: (e) => {
61
+ if (e.target === e.currentTarget)
62
+ this.close();
63
+ } }, h("aside", { key: '8c50e6b0cfacf3a881e4ec1ab272ef8da13cd796', class: { panel: true, [`panel--${this.side}`]: true, 'is-open': this.visible }, role: "dialog", "aria-modal": "true", "aria-label": this.heading, "aria-hidden": this.visible ? 'false' : 'true' }, h("header", { key: 'ee7efe3700ff05c921f6ace97f39f957ebf6670e', class: "drawer-header" }, h("h2", { key: '07841a92eea5bca5db0ebf64df91a14eaa5ecffc', class: "drawer-title" }, this.heading), h("button", { key: 'c2099831dfaf89b44b7228c1ee5634d61c5af919', class: "close-btn", onClick: this.close, "aria-label": "Close cart" }, h("svg", { key: 'a2c8e0ecf42e4fe43ca1d6b6ccc6f4687e6af483', viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, h("path", { key: 'de07e2ce6b0b60a137d8b534826963a03421af7b', d: "M6 6l12 12M18 6L6 18", "stroke-linecap": "round" })))), h("div", { key: 'f67798d0e026cce074bf15b246cdd3b726be98f6', class: "drawer-body" }, h("tl-cart", { key: '1b2a5a44e1862a3b4754bd36e17de063d012453e' }))))));
64
+ }
65
+ static get is() { return "tl-cart-drawer"; }
66
+ static get encapsulation() { return "shadow"; }
67
+ static get originalStyleUrls() {
68
+ return {
69
+ "$": ["tl-cart-drawer.css"]
70
+ };
71
+ }
72
+ static get styleUrls() {
73
+ return {
74
+ "$": ["tl-cart-drawer.css"]
75
+ };
76
+ }
77
+ static get properties() {
78
+ return {
79
+ "side": {
80
+ "type": "string",
81
+ "mutable": false,
82
+ "complexType": {
83
+ "original": "'right' | 'left'",
84
+ "resolved": "\"left\" | \"right\"",
85
+ "references": {}
86
+ },
87
+ "required": false,
88
+ "optional": false,
89
+ "docs": {
90
+ "tags": [],
91
+ "text": "Edge the panel slides in from."
92
+ },
93
+ "getter": false,
94
+ "setter": false,
95
+ "reflect": false,
96
+ "attribute": "side",
97
+ "defaultValue": "'right'"
98
+ },
99
+ "heading": {
100
+ "type": "string",
101
+ "mutable": false,
102
+ "complexType": {
103
+ "original": "string",
104
+ "resolved": "string",
105
+ "references": {}
106
+ },
107
+ "required": false,
108
+ "optional": false,
109
+ "docs": {
110
+ "tags": [],
111
+ "text": "Heading shown at the top of the panel."
112
+ },
113
+ "getter": false,
114
+ "setter": false,
115
+ "reflect": false,
116
+ "attribute": "heading",
117
+ "defaultValue": "'Your cart'"
118
+ },
119
+ "open": {
120
+ "type": "boolean",
121
+ "mutable": true,
122
+ "complexType": {
123
+ "original": "boolean",
124
+ "resolved": "boolean",
125
+ "references": {}
126
+ },
127
+ "required": false,
128
+ "optional": false,
129
+ "docs": {
130
+ "tags": [],
131
+ "text": "Controlled open state (also driven by the `ui:cart-requested` intent)."
132
+ },
133
+ "getter": false,
134
+ "setter": false,
135
+ "reflect": false,
136
+ "attribute": "open",
137
+ "defaultValue": "false"
138
+ }
139
+ };
140
+ }
141
+ static get states() {
142
+ return {
143
+ "visible": {}
144
+ };
145
+ }
146
+ static get events() {
147
+ return [{
148
+ "method": "tlOpen",
149
+ "name": "tlOpen",
150
+ "bubbles": true,
151
+ "cancelable": true,
152
+ "composed": true,
153
+ "docs": {
154
+ "tags": [],
155
+ "text": ""
156
+ },
157
+ "complexType": {
158
+ "original": "void",
159
+ "resolved": "void",
160
+ "references": {}
161
+ }
162
+ }, {
163
+ "method": "tlClose",
164
+ "name": "tlClose",
165
+ "bubbles": true,
166
+ "cancelable": true,
167
+ "composed": true,
168
+ "docs": {
169
+ "tags": [],
170
+ "text": ""
171
+ },
172
+ "complexType": {
173
+ "original": "void",
174
+ "resolved": "void",
175
+ "references": {}
176
+ }
177
+ }];
178
+ }
179
+ static get watchers() {
180
+ return [{
181
+ "propName": "open",
182
+ "methodName": "onOpenProp"
183
+ }];
184
+ }
185
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * tl-checkout-wrapper styles
3
+ */
4
+
5
+ tl-checkout-wrapper,
6
+ .tl-checkout-wrapper {
7
+ display: inline-block;
8
+ cursor: pointer;
9
+ }
10
+
11
+ tl-checkout-wrapper:focus,
12
+ .tl-checkout-wrapper:focus {
13
+ outline: 2px solid var(--tl-ring, #3b82f6);
14
+ outline-offset: 2px;
15
+ border-radius: var(--tl-radius-sm, 0.25rem);
16
+ }
17
+
18
+ tl-checkout-wrapper[disabled],
19
+ tl-checkout-wrapper.tl-checkout-wrapper--disabled,
20
+ .tl-checkout-wrapper--disabled {
21
+ cursor: not-allowed;
22
+ opacity: 0.5;
23
+ }
@@ -0,0 +1,148 @@
1
+ import { h, Host } from "@stencil/core";
2
+ import { getSDK, hasSDK } from "../../utils/sdk-connector";
3
+ /**
4
+ * @component tl-checkout-wrapper
5
+ *
6
+ * Wraps any content and opens the Ticketlayer checkout modal when clicked.
7
+ * Uses the SDK's modal manager which handles the iframe overlay.
8
+ *
9
+ * @slot - Content to display (typically a checkout button)
10
+ *
11
+ * @example
12
+ * <tl-checkout-wrapper>
13
+ * <button>Proceed to Checkout</button>
14
+ * </tl-checkout-wrapper>
15
+ */
16
+ export class TlCheckoutWrapper {
17
+ constructor() {
18
+ /**
19
+ * Whether the wrapper is disabled
20
+ */
21
+ this.disabled = false;
22
+ this.handleClick = () => {
23
+ if (this.disabled)
24
+ return;
25
+ if (!hasSDK()) {
26
+ console.error('[tl-checkout-wrapper] SDK not initialized. Call setSDK(ticketlayer) first.');
27
+ this.tlError.emit({ message: 'SDK not initialized' });
28
+ return;
29
+ }
30
+ const sdk = getSDK();
31
+ // Open the checkout modal via SDK
32
+ sdk.checkout.openModal({
33
+ onComplete: (order) => {
34
+ this.tlComplete.emit(order);
35
+ },
36
+ onError: (err) => {
37
+ this.tlError.emit({ message: err.message });
38
+ },
39
+ onClose: () => {
40
+ this.tlClose.emit();
41
+ },
42
+ });
43
+ };
44
+ this.handleKeyDown = (e) => {
45
+ if (e.key === 'Enter' || e.key === ' ') {
46
+ e.preventDefault();
47
+ this.handleClick();
48
+ }
49
+ };
50
+ }
51
+ render() {
52
+ return (h(Host, { key: 'ebaae5dd6710ffc5353ece4327012df0332fdbb7', class: {
53
+ 'tl-checkout-wrapper': true,
54
+ 'tl-checkout-wrapper--disabled': this.disabled,
55
+ }, onClick: this.handleClick, onKeyDown: this.handleKeyDown, role: "button", tabindex: this.disabled ? -1 : 0, "aria-disabled": this.disabled ? 'true' : null }, h("slot", { key: '0118d9921df5af1ae2376fd4135bac487aac7ebd' })));
56
+ }
57
+ static get is() { return "tl-checkout-wrapper"; }
58
+ static get originalStyleUrls() {
59
+ return {
60
+ "$": ["tl-checkout-wrapper.css"]
61
+ };
62
+ }
63
+ static get styleUrls() {
64
+ return {
65
+ "$": ["tl-checkout-wrapper.css"]
66
+ };
67
+ }
68
+ static get properties() {
69
+ return {
70
+ "disabled": {
71
+ "type": "boolean",
72
+ "mutable": false,
73
+ "complexType": {
74
+ "original": "boolean",
75
+ "resolved": "boolean",
76
+ "references": {}
77
+ },
78
+ "required": false,
79
+ "optional": false,
80
+ "docs": {
81
+ "tags": [],
82
+ "text": "Whether the wrapper is disabled"
83
+ },
84
+ "getter": false,
85
+ "setter": false,
86
+ "reflect": false,
87
+ "attribute": "disabled",
88
+ "defaultValue": "false"
89
+ }
90
+ };
91
+ }
92
+ static get events() {
93
+ return [{
94
+ "method": "tlComplete",
95
+ "name": "tl-complete",
96
+ "bubbles": true,
97
+ "cancelable": true,
98
+ "composed": true,
99
+ "docs": {
100
+ "tags": [],
101
+ "text": "Emitted when checkout completes successfully"
102
+ },
103
+ "complexType": {
104
+ "original": "OrderResult",
105
+ "resolved": "OrderResult",
106
+ "references": {
107
+ "OrderResult": {
108
+ "location": "import",
109
+ "path": "../../utils/sdk-connector",
110
+ "id": "src/utils/sdk-connector.ts::OrderResult",
111
+ "referenceLocation": "OrderResult"
112
+ }
113
+ }
114
+ }
115
+ }, {
116
+ "method": "tlError",
117
+ "name": "tl-error",
118
+ "bubbles": true,
119
+ "cancelable": true,
120
+ "composed": true,
121
+ "docs": {
122
+ "tags": [],
123
+ "text": "Emitted when an error occurs"
124
+ },
125
+ "complexType": {
126
+ "original": "{ message: string }",
127
+ "resolved": "{ message: string; }",
128
+ "references": {}
129
+ }
130
+ }, {
131
+ "method": "tlClose",
132
+ "name": "tl-close",
133
+ "bubbles": true,
134
+ "cancelable": true,
135
+ "composed": true,
136
+ "docs": {
137
+ "tags": [],
138
+ "text": "Emitted when the modal closes"
139
+ },
140
+ "complexType": {
141
+ "original": "void",
142
+ "resolved": "void",
143
+ "references": {}
144
+ }
145
+ }];
146
+ }
147
+ static get elementRef() { return "el"; }
148
+ }
@@ -0,0 +1,23 @@
1
+ /** Adapt an event detail to the card shape (the list adapter lives in the SDK connector). */
2
+ export function toEventCardEvent(detail) {
3
+ const occurrences = detail.occurrences ?? [];
4
+ const starts = occurrences
5
+ .map((o) => o.startsAt)
6
+ .filter((s) => !!s)
7
+ .sort();
8
+ const now = Date.now();
9
+ const next = starts.find((s) => new Date(s).getTime() >= now) ?? starts[0];
10
+ const soldOut = detail.status === 'sold_out' ||
11
+ (occurrences.length > 0 && occurrences.every((o) => o.status === 'sold_out'));
12
+ return {
13
+ id: detail.id,
14
+ name: detail.name,
15
+ ...(detail.shortDescription ? { shortDescription: detail.shortDescription } : {}),
16
+ ...(detail.imageUrl ? { imageUrl: detail.imageUrl } : {}),
17
+ ...(detail.venueName
18
+ ? { venue: { id: detail.venueId ?? '', name: detail.venueName, city: detail.venueCity ?? '' } }
19
+ : {}),
20
+ ...(next ? { nextOccurrence: { startsAt: next } } : {}),
21
+ availabilityStatus: soldOut ? 'sold_out' : 'available',
22
+ };
23
+ }