@ticketlayer/elements 0.3.3 → 1.0.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 (179) hide show
  1. package/README.md +3 -2
  2. package/dist/cjs/{index-BpfoKd9Q.js → index-DanPUX0s.js} +1 -1
  3. package/dist/cjs/index.cjs.js +2 -1
  4. package/dist/cjs/loader.cjs.js +2 -2
  5. package/dist/cjs/ticket-selector-BYVL13k_.js +3623 -0
  6. package/dist/cjs/ticketlayer-elements.cjs.js +2 -2
  7. package/dist/cjs/tl-buy-modal.cjs.entry.js +4 -4
  8. package/dist/cjs/tl-buy-tickets-button.cjs.entry.js +89 -71
  9. package/dist/cjs/tl-buy-tickets-wrapper.cjs.entry.js +62 -31
  10. package/dist/cjs/tl-cart-badge.cjs.entry.js +75 -62
  11. package/dist/cjs/tl-cart-drawer.cjs.entry.js +52 -24
  12. package/dist/cjs/tl-cart.cjs.entry.js +72 -98
  13. package/dist/cjs/tl-checkout-wrapper.cjs.entry.js +52 -30
  14. package/dist/cjs/tl-event-card.cjs.entry.js +44 -105
  15. package/dist/cjs/tl-event-list.cjs.entry.js +73 -36
  16. package/dist/cjs/tl-login.cjs.entry.js +75 -141
  17. package/dist/cjs/tl-my-orders.cjs.entry.js +53 -92
  18. package/dist/cjs/tl-occurrence-selector_2.cjs.entry.js +205 -641
  19. package/dist/cjs/tl-order-confirmation.cjs.entry.js +72 -105
  20. package/dist/cjs/tl-order-tickets_2.cjs.entry.js +50 -76
  21. package/dist/cjs/tl-promo-code.cjs.entry.js +51 -47
  22. package/dist/cjs/tl-seat-map.cjs.entry.js +4 -4
  23. package/dist/cjs/web-query-Ce73jB4k.js +16 -0
  24. package/dist/collection/components/tl-buy-modal/tl-buy-modal.css +12 -19
  25. package/dist/collection/components/tl-buy-modal/tl-buy-modal.js +2 -2
  26. package/dist/collection/components/tl-buy-tickets-button/tl-buy-tickets-button.css +41 -4
  27. package/dist/collection/components/tl-buy-tickets-button/tl-buy-tickets-button.js +105 -76
  28. package/dist/collection/components/tl-buy-tickets-wrapper/tl-buy-tickets-wrapper.css +2 -2
  29. package/dist/collection/components/tl-buy-tickets-wrapper/tl-buy-tickets-wrapper.js +73 -30
  30. package/dist/collection/components/tl-cart/tl-cart.css +52 -51
  31. package/dist/collection/components/tl-cart/tl-cart.js +82 -101
  32. package/dist/collection/components/tl-cart-badge/tl-cart-badge.css +11 -11
  33. package/dist/collection/components/tl-cart-badge/tl-cart-badge.js +62 -62
  34. package/dist/collection/components/tl-cart-drawer/tl-cart-drawer.css +6 -6
  35. package/dist/collection/components/tl-cart-drawer/tl-cart-drawer.js +56 -24
  36. package/dist/collection/components/tl-checkout-wrapper/tl-checkout-wrapper.css +2 -2
  37. package/dist/collection/components/tl-checkout-wrapper/tl-checkout-wrapper.js +61 -29
  38. package/dist/collection/components/tl-event-card/event-card-adapter.js +11 -23
  39. package/dist/collection/components/tl-event-card/tl-event-card.css +22 -22
  40. package/dist/collection/components/tl-event-card/tl-event-card.js +51 -84
  41. package/dist/collection/components/tl-event-list/tl-event-list.css +17 -17
  42. package/dist/collection/components/tl-event-list/tl-event-list.js +82 -38
  43. package/dist/collection/components/tl-login/tl-login.css +26 -26
  44. package/dist/collection/components/tl-login/tl-login.js +83 -147
  45. package/dist/collection/components/tl-my-orders/tl-my-orders.css +40 -40
  46. package/dist/collection/components/tl-my-orders/tl-my-orders.js +58 -96
  47. package/dist/collection/components/tl-occurrence-selector/tl-occurrence-selector.css +54 -65
  48. package/dist/collection/components/tl-occurrence-selector/tl-occurrence-selector.js +137 -516
  49. package/dist/collection/components/tl-order-confirmation/tl-order-confirmation.css +38 -38
  50. package/dist/collection/components/tl-order-confirmation/tl-order-confirmation.js +81 -113
  51. package/dist/collection/components/tl-order-tickets/tl-order-tickets.css +9 -9
  52. package/dist/collection/components/tl-order-tickets/tl-order-tickets.js +57 -92
  53. package/dist/collection/components/tl-promo-code/tl-promo-code.css +25 -25
  54. package/dist/collection/components/tl-promo-code/tl-promo-code.js +55 -50
  55. package/dist/collection/components/tl-seat-map/tl-seat-map.css +10 -10
  56. package/dist/collection/components/tl-seat-map/tl-seat-map.js +2 -2
  57. package/dist/collection/components/tl-ticket/tl-ticket.css +13 -13
  58. package/dist/collection/components/tl-ticket-selector/tl-ticket-selector.css +74 -49
  59. package/dist/collection/components/tl-ticket-selector/tl-ticket-selector.js +95 -135
  60. package/dist/collection/utils/cart-totals.js +9 -0
  61. package/dist/collection/utils/order-summary.js +15 -99
  62. package/dist/collection/utils/testing/deep-text.js +29 -0
  63. package/dist/collection/utils/testing/fixtures.js +290 -0
  64. package/dist/collection/utils/testing/mock-sdk.js +13 -2
  65. package/dist/collection/utils/web-query.js +12 -0
  66. package/dist/collection/utils/web-storage.js +22 -0
  67. package/dist/components/ticket-selector.js +1 -0
  68. package/dist/components/tl-buy-modal.js +1 -1
  69. package/dist/components/tl-buy-tickets-button.js +1 -1
  70. package/dist/components/tl-buy-tickets-wrapper2.js +1 -1
  71. package/dist/components/tl-cart-badge.js +1 -1
  72. package/dist/components/tl-cart-drawer.js +1 -1
  73. package/dist/components/tl-cart2.js +1 -1
  74. package/dist/components/tl-checkout-wrapper2.js +1 -1
  75. package/dist/components/tl-event-card2.js +1 -1
  76. package/dist/components/tl-event-list.js +1 -1
  77. package/dist/components/tl-login2.js +1 -1
  78. package/dist/components/tl-my-orders.js +1 -1
  79. package/dist/components/tl-occurrence-selector2.js +1 -1
  80. package/dist/components/tl-order-confirmation.js +1 -1
  81. package/dist/components/tl-order-tickets2.js +1 -1
  82. package/dist/components/tl-promo-code.js +1 -1
  83. package/dist/components/tl-seat-map.js +1 -1
  84. package/dist/components/tl-ticket-selector2.js +1 -1
  85. package/dist/components/tl-ticket2.js +1 -1
  86. package/dist/components/web-query.js +1 -0
  87. package/dist/elements.docs.json +36 -36
  88. package/dist/esm/{index-CNX8hZa8.js → index-imfxp765.js} +1 -1
  89. package/dist/esm/index.js +2 -1
  90. package/dist/esm/loader.js +3 -3
  91. package/dist/esm/ticket-selector-BwChnHVC.js +3606 -0
  92. package/dist/esm/ticketlayer-elements.js +3 -3
  93. package/dist/esm/tl-buy-modal.entry.js +4 -4
  94. package/dist/esm/tl-buy-tickets-button.entry.js +90 -72
  95. package/dist/esm/tl-buy-tickets-wrapper.entry.js +63 -32
  96. package/dist/esm/tl-cart-badge.entry.js +76 -63
  97. package/dist/esm/tl-cart-drawer.entry.js +53 -25
  98. package/dist/esm/tl-cart.entry.js +73 -99
  99. package/dist/esm/tl-checkout-wrapper.entry.js +53 -31
  100. package/dist/esm/tl-event-card.entry.js +45 -106
  101. package/dist/esm/tl-event-list.entry.js +74 -37
  102. package/dist/esm/tl-login.entry.js +76 -142
  103. package/dist/esm/tl-my-orders.entry.js +54 -93
  104. package/dist/esm/tl-occurrence-selector_2.entry.js +206 -642
  105. package/dist/esm/tl-order-confirmation.entry.js +73 -106
  106. package/dist/esm/tl-order-tickets_2.entry.js +51 -77
  107. package/dist/esm/tl-promo-code.entry.js +52 -48
  108. package/dist/esm/tl-seat-map.entry.js +4 -4
  109. package/dist/esm/web-query-Bdbb2lk5.js +14 -0
  110. package/dist/ticketlayer-elements/index.esm.js +1 -1
  111. package/dist/ticketlayer-elements/p-45923d2c.entry.js +1 -0
  112. package/dist/ticketlayer-elements/p-492adc77.entry.js +1 -0
  113. package/dist/ticketlayer-elements/p-4cfc9e53.entry.js +1 -0
  114. package/dist/ticketlayer-elements/p-5135630e.entry.js +1 -0
  115. package/dist/ticketlayer-elements/p-5bbce3b5.entry.js +1 -0
  116. package/dist/ticketlayer-elements/p-7d547721.entry.js +1 -0
  117. package/dist/ticketlayer-elements/p-7fe7b6ba.entry.js +1 -0
  118. package/dist/ticketlayer-elements/p-8122f0c1.entry.js +1 -0
  119. package/dist/ticketlayer-elements/p-98d40869.entry.js +1 -0
  120. package/dist/ticketlayer-elements/p-Bdbb2lk5.js +1 -0
  121. package/dist/ticketlayer-elements/p-BwChnHVC.js +1 -0
  122. package/dist/ticketlayer-elements/p-abec290a.entry.js +1 -0
  123. package/dist/ticketlayer-elements/p-ac79a3f6.entry.js +1 -0
  124. package/dist/ticketlayer-elements/p-d01f4429.entry.js +1 -0
  125. package/dist/ticketlayer-elements/p-d7ffaf46.entry.js +1 -0
  126. package/dist/ticketlayer-elements/p-e7170f3c.entry.js +1 -0
  127. package/dist/ticketlayer-elements/p-e787e862.entry.js +1 -0
  128. package/dist/ticketlayer-elements/p-f1ff931f.entry.js +1 -0
  129. package/dist/ticketlayer-elements/p-imfxp765.js +3 -0
  130. package/dist/ticketlayer-elements/ticketlayer-elements.css +1 -1
  131. package/dist/ticketlayer-elements/ticketlayer-elements.esm.js +1 -1
  132. package/dist/types/components/tl-buy-tickets-button/tl-buy-tickets-button.d.ts +40 -8
  133. package/dist/types/components/tl-buy-tickets-wrapper/tl-buy-tickets-wrapper.d.ts +20 -1
  134. package/dist/types/components/tl-cart/tl-cart.d.ts +40 -32
  135. package/dist/types/components/tl-cart-badge/tl-cart-badge.d.ts +22 -7
  136. package/dist/types/components/tl-cart-drawer/tl-cart-drawer.d.ts +28 -5
  137. package/dist/types/components/tl-checkout-wrapper/tl-checkout-wrapper.d.ts +18 -1
  138. package/dist/types/components/tl-event-card/event-card-adapter.d.ts +9 -20
  139. package/dist/types/components/tl-event-card/tl-event-card.d.ts +25 -28
  140. package/dist/types/components/tl-event-list/tl-event-list.d.ts +46 -6
  141. package/dist/types/components/tl-login/tl-login.d.ts +68 -22
  142. package/dist/types/components/tl-my-orders/tl-my-orders.d.ts +30 -12
  143. package/dist/types/components/tl-occurrence-selector/tl-occurrence-selector.d.ts +73 -161
  144. package/dist/types/components/tl-order-confirmation/tl-order-confirmation.d.ts +48 -15
  145. package/dist/types/components/tl-order-tickets/tl-order-tickets.d.ts +29 -31
  146. package/dist/types/components/tl-promo-code/tl-promo-code.d.ts +28 -10
  147. package/dist/types/components/tl-ticket/tl-ticket.d.ts +2 -11
  148. package/dist/types/components/tl-ticket-selector/tl-ticket-selector.d.ts +61 -32
  149. package/dist/types/components.d.ts +302 -62
  150. package/dist/types/utils/cart-totals.d.ts +10 -0
  151. package/dist/types/utils/order-summary.d.ts +16 -65
  152. package/dist/types/utils/testing/deep-text.d.ts +13 -0
  153. package/dist/types/utils/testing/fixtures.d.ts +225 -0
  154. package/dist/types/utils/testing/mock-sdk.d.ts +14 -1
  155. package/dist/types/utils/web-query.d.ts +18 -0
  156. package/dist/types/utils/web-storage.d.ts +16 -0
  157. package/elements.catalogue.json +676 -55
  158. package/package.json +14 -6
  159. package/dist/cjs/order-summary-ZMkJ5bez.js +0 -116
  160. package/dist/components/order-summary.js +0 -1
  161. package/dist/esm/order-summary-BGekdjN9.js +0 -103
  162. package/dist/ticketlayer-elements/p-0b1d16f8.entry.js +0 -1
  163. package/dist/ticketlayer-elements/p-1471f6d8.entry.js +0 -1
  164. package/dist/ticketlayer-elements/p-1c51cbc1.entry.js +0 -1
  165. package/dist/ticketlayer-elements/p-5169f68b.entry.js +0 -1
  166. package/dist/ticketlayer-elements/p-895ba1f3.entry.js +0 -1
  167. package/dist/ticketlayer-elements/p-8d5722e1.entry.js +0 -1
  168. package/dist/ticketlayer-elements/p-917d8e09.entry.js +0 -1
  169. package/dist/ticketlayer-elements/p-9629029a.entry.js +0 -1
  170. package/dist/ticketlayer-elements/p-BGekdjN9.js +0 -1
  171. package/dist/ticketlayer-elements/p-CNX8hZa8.js +0 -3
  172. package/dist/ticketlayer-elements/p-a22714d0.entry.js +0 -1
  173. package/dist/ticketlayer-elements/p-bf73044b.entry.js +0 -1
  174. package/dist/ticketlayer-elements/p-e02079fa.entry.js +0 -1
  175. package/dist/ticketlayer-elements/p-e04ace15.entry.js +0 -1
  176. package/dist/ticketlayer-elements/p-e6fab1d5.entry.js +0 -1
  177. package/dist/ticketlayer-elements/p-f826b753.entry.js +0 -1
  178. package/dist/ticketlayer-elements/p-fa639d88.entry.js +0 -1
  179. package/dist/ticketlayer-elements/p-fbaca948.entry.js +0 -1
@@ -1,25 +1,25 @@
1
1
  :host {
2
2
  display: block;
3
- font-family: var(--tl-font-family, system-ui, sans-serif);
3
+ font-family: var(--tl-font-family);
4
4
  }
5
5
 
6
6
  /* Skeleton loading */
7
7
  .skeleton-container {
8
- padding: var(--tl-spacing-4, 1rem);
8
+ padding: var(--tl-spacing-4);
9
9
  }
10
10
 
11
11
  .skeleton-item {
12
12
  height: 70px;
13
- background: var(--tl-color-muted, #f3f4f6);
14
- border-radius: var(--tl-radius-md, 0.5rem);
15
- margin-bottom: var(--tl-spacing-3, 0.75rem);
13
+ background: var(--tl-color-muted);
14
+ border-radius: var(--tl-radius-md);
15
+ margin-bottom: var(--tl-spacing-3);
16
16
  animation: pulse 1.5s ease-in-out infinite;
17
17
  }
18
18
 
19
19
  .skeleton-totals {
20
20
  height: 100px;
21
- background: var(--tl-color-muted, #f3f4f6);
22
- border-radius: var(--tl-radius-md, 0.5rem);
21
+ background: var(--tl-color-muted);
22
+ border-radius: var(--tl-radius-md);
23
23
  animation: pulse 1.5s ease-in-out infinite;
24
24
  }
25
25
 
@@ -34,50 +34,50 @@
34
34
  flex-direction: column;
35
35
  align-items: center;
36
36
  justify-content: center;
37
- padding: var(--tl-spacing-8, 2rem);
37
+ padding: var(--tl-spacing-8);
38
38
  text-align: center;
39
39
  }
40
40
 
41
41
  .empty-icon {
42
42
  width: 48px;
43
43
  height: 48px;
44
- color: var(--tl-color-muted-foreground, #9ca3af);
45
- margin-bottom: var(--tl-spacing-4, 1rem);
44
+ color: var(--tl-color-muted-foreground);
45
+ margin-bottom: var(--tl-spacing-4);
46
46
  }
47
47
 
48
48
  .empty-title {
49
- margin: 0 0 var(--tl-spacing-2, 0.5rem);
49
+ margin: 0 0 var(--tl-spacing-2);
50
50
  font-size: 16px;
51
51
  font-weight: 600;
52
- color: var(--tl-color-foreground, #111827);
52
+ color: var(--tl-color-foreground);
53
53
  }
54
54
 
55
55
  .empty-message {
56
56
  margin: 0;
57
57
  font-size: 14px;
58
- color: var(--tl-color-muted-foreground, #6b7280);
58
+ color: var(--tl-color-muted-foreground);
59
59
  }
60
60
 
61
61
  /* Cart */
62
62
  .cart {
63
- background: var(--tl-color-background, #ffffff);
63
+ background: var(--tl-color-background);
64
64
  }
65
65
 
66
66
  .cart.compact .cart-items {
67
- margin-bottom: var(--tl-spacing-2, 0.5rem);
67
+ margin-bottom: var(--tl-spacing-2);
68
68
  }
69
69
 
70
70
  /* Cart items */
71
71
  .cart-items {
72
- margin-bottom: var(--tl-spacing-4, 1rem);
72
+ margin-bottom: var(--tl-spacing-4);
73
73
  }
74
74
 
75
75
  .cart-item {
76
76
  display: flex;
77
77
  justify-content: space-between;
78
78
  align-items: flex-start;
79
- padding: var(--tl-spacing-3, 0.75rem) 0;
80
- border-bottom: 1px solid var(--tl-color-border, #e5e7eb);
79
+ padding: var(--tl-spacing-3) 0;
80
+ border-bottom: 1px solid var(--tl-color-border);
81
81
  transition: opacity 0.2s;
82
82
  }
83
83
 
@@ -98,39 +98,39 @@
98
98
  margin: 0;
99
99
  font-weight: 600;
100
100
  font-size: 15px;
101
- color: var(--tl-color-foreground, #111827);
101
+ color: var(--tl-color-foreground);
102
102
  }
103
103
 
104
104
  .item-event {
105
- margin: var(--tl-spacing-1, 0.25rem) 0 0;
105
+ margin: var(--tl-spacing-1) 0 0;
106
106
  font-size: 14px;
107
- color: var(--tl-color-muted-foreground, #6b7280);
107
+ color: var(--tl-color-muted-foreground);
108
108
  }
109
109
 
110
110
  .item-date {
111
- margin: var(--tl-spacing-1, 0.25rem) 0 0;
111
+ margin: var(--tl-spacing-1) 0 0;
112
112
  font-size: 13px;
113
- color: var(--tl-color-muted-foreground, #9ca3af);
113
+ color: var(--tl-color-muted-foreground);
114
114
  }
115
115
 
116
116
  .item-quantity {
117
- margin: var(--tl-spacing-1, 0.25rem) 0 0;
117
+ margin: var(--tl-spacing-1) 0 0;
118
118
  font-size: 13px;
119
- color: var(--tl-color-muted-foreground, #6b7280);
119
+ color: var(--tl-color-muted-foreground);
120
120
  }
121
121
 
122
122
  .item-actions {
123
123
  display: flex;
124
124
  align-items: center;
125
- gap: var(--tl-spacing-3, 0.75rem);
126
- margin-left: var(--tl-spacing-4, 1rem);
125
+ gap: var(--tl-spacing-3);
126
+ margin-left: var(--tl-spacing-4);
127
127
  }
128
128
 
129
129
  .item-price {
130
130
  margin: 0;
131
131
  font-weight: 600;
132
132
  font-size: 15px;
133
- color: var(--tl-color-foreground, #111827);
133
+ color: var(--tl-color-foreground);
134
134
  white-space: nowrap;
135
135
  }
136
136
 
@@ -140,8 +140,8 @@
140
140
  padding: 0;
141
141
  border: none;
142
142
  background: transparent;
143
- border-radius: var(--tl-radius-sm, 0.25rem);
144
- color: var(--tl-color-muted-foreground, #9ca3af);
143
+ border-radius: var(--tl-radius-sm);
144
+ color: var(--tl-color-muted-foreground);
145
145
  cursor: pointer;
146
146
  display: flex;
147
147
  align-items: center;
@@ -150,8 +150,8 @@
150
150
  }
151
151
 
152
152
  .remove-btn:hover:not(:disabled) {
153
- background-color: var(--tl-color-destructive-bg, #fee2e2);
154
- color: var(--tl-color-destructive, #ef4444);
153
+ background-color: var(--tl-color-destructive-bg);
154
+ color: var(--tl-color-destructive);
155
155
  }
156
156
 
157
157
  .remove-btn:disabled {
@@ -167,8 +167,8 @@
167
167
  .spinner {
168
168
  width: 14px;
169
169
  height: 14px;
170
- border: 2px solid var(--tl-color-border, #e5e7eb);
171
- border-top-color: var(--tl-color-primary, #6366f1);
170
+ border: 2px solid var(--tl-color-border);
171
+ border-top-color: var(--tl-color-primary);
172
172
  border-radius: 50%;
173
173
  animation: spin 0.6s linear infinite;
174
174
  }
@@ -179,41 +179,42 @@
179
179
 
180
180
  /* Cart totals */
181
181
  .cart-totals {
182
- padding: var(--tl-spacing-3, 0.75rem) 0;
183
- border-top: 1px solid var(--tl-color-border, #e5e7eb);
182
+ padding: var(--tl-spacing-3) 0;
183
+ border-top: 1px solid var(--tl-color-border);
184
184
  }
185
185
 
186
186
  .total-row {
187
187
  display: flex;
188
188
  justify-content: space-between;
189
189
  align-items: center;
190
- padding: var(--tl-spacing-1, 0.25rem) 0;
190
+ padding: var(--tl-spacing-1) 0;
191
191
  }
192
192
 
193
193
  .total-row.subtotal,
194
- .total-row.fees {
194
+ .total-row.fees,
195
+ .total-row.discount {
195
196
  font-size: 14px;
196
- color: var(--tl-color-muted-foreground, #6b7280);
197
+ color: var(--tl-color-muted-foreground);
197
198
  }
198
199
 
199
200
  .total-row.total {
200
201
  font-size: 16px;
201
202
  font-weight: 700;
202
- color: var(--tl-color-foreground, #111827);
203
- padding-top: var(--tl-spacing-2, 0.5rem);
204
- border-top: 1px solid var(--tl-color-border, #e5e7eb);
205
- margin-top: var(--tl-spacing-2, 0.5rem);
203
+ color: var(--tl-color-foreground);
204
+ padding-top: var(--tl-spacing-2);
205
+ border-top: 1px solid var(--tl-color-border);
206
+ margin-top: var(--tl-spacing-2);
206
207
  }
207
208
 
208
209
  /* Checkout button */
209
210
  .checkout-btn {
210
211
  width: 100%;
211
- margin-top: var(--tl-spacing-4, 1rem);
212
- padding: var(--tl-spacing-3, 0.75rem) var(--tl-spacing-4, 1rem);
213
- border-radius: var(--tl-radius-md, 0.5rem);
212
+ margin-top: var(--tl-spacing-4);
213
+ padding: var(--tl-spacing-3) var(--tl-spacing-4);
214
+ border-radius: var(--tl-radius-md);
214
215
  border: none;
215
- background-color: var(--tl-color-primary, #6366f1);
216
- color: var(--tl-color-primary-foreground, #ffffff);
216
+ background-color: var(--tl-color-primary);
217
+ color: var(--tl-color-primary-foreground);
217
218
  font-weight: 600;
218
219
  font-size: 16px;
219
220
  cursor: pointer;
@@ -229,8 +230,8 @@
229
230
  }
230
231
 
231
232
  .checkout-btn:disabled {
232
- background-color: var(--tl-color-muted, #d1d5db);
233
- color: var(--tl-color-muted-foreground, #6b7280);
233
+ background-color: var(--tl-color-muted);
234
+ color: var(--tl-color-muted-foreground);
234
235
  cursor: not-allowed;
235
236
  }
236
237
 
@@ -241,7 +242,7 @@
241
242
  }
242
243
 
243
244
  .cart.compact .cart-totals {
244
- padding: var(--tl-spacing-2, 0.5rem) 0;
245
+ padding: var(--tl-spacing-2) 0;
245
246
  }
246
247
 
247
248
  .cart.compact .total-row.total {
@@ -1,5 +1,15 @@
1
1
  import { h } from "@stencil/core";
2
- import { getSDK, hasSDK, whenSDK } from "../../utils/sdk-connector";
2
+ import { cartCore, createElement, } from "@ticketlayer/elements-core";
3
+ import { getSDK, whenSDK } from "../../utils/sdk-connector";
4
+ /**
5
+ * The web harness for `cartCore`.
6
+ *
7
+ * It renders and it forwards. The cart, the money rows, the subscription that
8
+ * keeps them current and every string are in `@ticketlayer/elements-core`
9
+ * (AGENTS.md, TKT-11); what is left here is the Stencil surface a host writes
10
+ * HTML against and the one genuinely web thing, finding the client the page
11
+ * published on `window.Ticketlayer`.
12
+ */
3
13
  export class TlCart {
4
14
  constructor() {
5
15
  /**
@@ -18,119 +28,78 @@ export class TlCart {
18
28
  * Compact mode - hides some details
19
29
  */
20
30
  this.compact = false;
21
- this.cart = null;
22
- this.loading = true;
23
- this.error = null;
24
- this.removingItemId = null;
25
- this.handleCheckout = () => {
26
- if (this.cart && this.cart.items.length > 0) {
27
- this.tlCheckout.emit({ cart: this.cart });
28
- }
29
- };
30
- }
31
- componentWillLoad() {
32
- this.loadCart();
33
- }
34
- componentDidLoad() {
35
- this.subscribeToCartUpdates();
36
- }
37
- disconnectedCallback() {
38
- if (this.unsubscribe) {
39
- this.unsubscribe();
40
- }
41
- }
42
- async loadCart() {
43
- try {
44
- console.log('[tl-cart] Loading cart...');
45
- this.loading = true;
46
- this.error = null;
47
- const sdk = await whenSDK();
48
- const cartManager = sdk.getCartManager?.();
49
- if (cartManager) {
50
- const cartData = await cartManager.get();
51
- console.log('[tl-cart] Cart loaded:', cartData);
52
- this.cart = cartData;
53
- }
54
- }
55
- catch (err) {
56
- console.error('[tl-cart] Failed to load cart:', err);
57
- this.error = err instanceof Error ? err.message : 'Failed to load cart';
58
- this.tlError.emit({ message: this.error });
59
- }
60
- finally {
61
- this.loading = false;
62
- }
31
+ this.element = createElement(cartCore, {
32
+ client: () => getSDK(),
33
+ // What "the client is up" means on the web. The core waits on it in its
34
+ // own mount, subscribes there and loads there; the harness decides none
35
+ // of it (TKT-197).
36
+ clientReady: () => whenSDK(),
37
+ emit: (event, detail) => this.forward(event, detail),
38
+ });
39
+ /** The core's whole view. Assigning it is what makes Stencil re-render. */
40
+ this.view = this.element.view;
63
41
  }
64
- async subscribeToCartUpdates() {
65
- const sdk = await whenSDK().catch(() => null);
66
- if (!sdk)
67
- return;
68
- const cartManager = sdk.getCartManager?.();
69
- if (!cartManager)
70
- return;
71
- this.unsubscribe = cartManager.on?.('cart:updated', (cartData) => {
72
- console.log('[tl-cart] Cart updated:', cartData);
73
- this.cart = cartData;
74
- this.tlCartUpdated.emit({ cart: cartData });
42
+ syncProps() {
43
+ this.element.setProps({
44
+ showCheckoutButton: this.showCheckoutButton,
45
+ checkoutLabel: this.checkoutLabel,
46
+ showRemoveButtons: this.showRemoveButtons,
47
+ compact: this.compact,
75
48
  });
76
49
  }
77
- async handleRemoveItem(itemId) {
78
- if (!hasSDK())
79
- return;
80
- this.removingItemId = itemId;
81
- try {
82
- const sdk = getSDK();
83
- const cartManager = sdk.getCartManager?.();
84
- if (cartManager) {
85
- await cartManager.removeItem(itemId);
86
- console.log('[tl-cart] Item removed:', itemId);
87
- this.tlItemRemoved.emit({ itemId });
88
- }
89
- }
90
- catch (err) {
91
- console.error('[tl-cart] Failed to remove item:', err);
92
- this.error = err instanceof Error ? err.message : 'Failed to remove item';
93
- this.tlError.emit({ message: this.error });
94
- }
95
- finally {
96
- this.removingItemId = null;
97
- }
50
+ /**
51
+ * On screen: render what the core says and put the core to work. For this
52
+ * element that means waiting for the client, subscribing to `cart:updated`
53
+ * and reading the cart - all of it the core's business.
54
+ */
55
+ connectedCallback() {
56
+ this.syncProps();
57
+ this.unsubscribe ?? (this.unsubscribe = this.element.subscribe((view) => {
58
+ this.view = view;
59
+ }));
60
+ this.view = this.element.view;
61
+ this.teardown = this.element.mount();
98
62
  }
99
- formatPrice(priceInPence, currency = 'GBP') {
100
- return new Intl.NumberFormat('en-GB', {
101
- style: 'currency',
102
- currency,
103
- }).format(priceInPence / 100);
63
+ /**
64
+ * Off screen: run the mount's teardown, which is what drops the cart
65
+ * subscription. Not `destroy()`: Stencil calls this for a DOM move as well
66
+ * as a removal, and a destroyed core never mounts again.
67
+ */
68
+ disconnectedCallback() {
69
+ this.teardown?.();
70
+ this.teardown = undefined;
71
+ this.unsubscribe?.();
72
+ this.unsubscribe = undefined;
104
73
  }
105
- formatDate(dateString) {
106
- const date = new Date(dateString);
107
- return date.toLocaleDateString('en-GB', {
108
- weekday: 'short',
109
- day: 'numeric',
110
- month: 'short',
111
- hour: '2-digit',
112
- minute: '2-digit',
113
- });
74
+ forward(event, detail) {
75
+ if (event === 'tlCheckout')
76
+ this.tlCheckout.emit(detail);
77
+ else if (event === 'tlItemRemoved')
78
+ this.tlItemRemoved.emit(detail);
79
+ else if (event === 'tlCartUpdated')
80
+ this.tlCartUpdated.emit(detail);
81
+ else if (event === 'tlError')
82
+ this.tlError.emit(detail);
114
83
  }
115
84
  renderSkeleton() {
116
85
  return (h("div", { class: "skeleton-container" }, h("div", { class: "skeleton-item" }), h("div", { class: "skeleton-item" }), h("div", { class: "skeleton-totals" })));
117
86
  }
118
87
  renderEmptyCart() {
119
- return (h("div", { class: "empty-cart" }, h("svg", { class: "empty-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor" }, h("path", { "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "1.5", 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" })), h("p", { class: "empty-title" }, "Your cart is empty"), h("p", { class: "empty-message" }, "Add tickets to get started")));
88
+ const strings = this.view.strings;
89
+ return (h("div", { class: "empty-cart" }, h("svg", { class: "empty-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor" }, h("path", { "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "1.5", 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" })), h("p", { class: "empty-title" }, strings.emptyTitle), h("p", { class: "empty-message" }, strings.emptyMessage)));
120
90
  }
121
- renderCartItem(item) {
122
- const isRemoving = this.removingItemId === item.id;
123
- return (h("div", { class: `cart-item ${isRemoving ? 'removing' : ''}`, key: item.id }, h("div", { class: "item-info" }, h("p", { class: "item-name" }, item.ticketTypeName), !this.compact && (h("p", { class: "item-event" }, item.eventName)), !this.compact && item.occurrenceDate && (h("p", { class: "item-date" }, this.formatDate(item.occurrenceDate))), h("p", { class: "item-quantity" }, "Qty: ", item.quantity)), h("div", { class: "item-actions" }, h("p", { class: "item-price" }, this.formatPrice(item.totalPrice, item.currency)), this.showRemoveButtons && (h("button", { class: "remove-btn", onClick: () => this.handleRemoveItem(item.id), disabled: isRemoving, "aria-label": "Remove item" }, isRemoving ? (h("span", { class: "spinner" })) : (h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor" }, h("path", { "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "2", d: "M6 18L18 6M6 6l12 12" }))))))));
91
+ renderCartItem(row) {
92
+ return (h("div", { class: `cart-item ${row.removing ? 'removing' : ''}`, key: row.id }, h("div", { class: "item-info" }, h("p", { class: "item-name" }, row.name), row.showEvent && h("p", { class: "item-event" }, row.eventName), row.showDate && h("p", { class: "item-date" }, row.dateLabel), h("p", { class: "item-quantity" }, row.quantityLabel)), h("div", { class: "item-actions" }, h("p", { class: "item-price" }, row.priceLabel), this.showRemoveButtons && (h("button", { class: "remove-btn", onClick: () => this.element.actions.removeItem(row.id), disabled: row.removing, "aria-label": this.view.strings.removeItem }, row.removing ? (h("span", { class: "spinner" })) : (h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor" }, h("path", { "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "2", d: "M6 18L18 6M6 6l12 12" }))))))));
124
93
  }
125
94
  render() {
126
- if (this.loading) {
95
+ const { status, strings, derived } = this.view;
96
+ if (status === 'loading') {
127
97
  return this.renderSkeleton();
128
98
  }
129
- if (!this.cart || this.cart.items.length === 0) {
99
+ if (status === 'empty') {
130
100
  return this.renderEmptyCart();
131
101
  }
132
- const { items, subtotal, fees, total, currency } = this.cart;
133
- return (h("div", { class: `cart ${this.compact ? 'compact' : ''}` }, h("div", { class: "cart-items" }, items.map(item => this.renderCartItem(item))), h("div", { class: "cart-totals" }, !this.compact && (h("div", { class: "total-row subtotal" }, h("span", null, "Subtotal"), h("span", null, this.formatPrice(subtotal, currency)))), fees > 0 && !this.compact && (h("div", { class: "total-row fees" }, h("span", null, "Fees"), h("span", null, this.formatPrice(fees, currency)))), h("div", { class: "total-row total" }, h("span", null, "Total"), h("span", null, this.formatPrice(total, currency)))), this.showCheckoutButton && (h("button", { class: "checkout-btn", onClick: this.handleCheckout, disabled: items.length === 0 }, this.checkoutLabel))));
102
+ return (h("div", { class: `cart ${this.compact ? 'compact' : ''}` }, h("div", { class: "cart-items" }, derived.rows.map((row) => this.renderCartItem(row))), h("div", { class: "cart-totals" }, derived.showSubtotalRow && (h("div", { class: "total-row subtotal" }, h("span", null, strings.subtotalRow), h("span", null, derived.subtotalLabel))), derived.showFeeRow && (h("div", { class: "total-row fees" }, h("span", null, derived.totals.feeLabel), h("span", null, derived.feeAmountLabel))), derived.showDiscountRow && (h("div", { class: "total-row discount" }, h("span", null, strings.discountRow), h("span", null, "-", derived.discountLabel))), h("div", { class: "total-row total" }, h("span", null, strings.totalRow), h("span", null, derived.totalLabel))), this.showCheckoutButton && (h("button", { class: "checkout-btn", onClick: () => this.element.actions.checkout(), disabled: derived.checkoutDisabled }, this.checkoutLabel))));
134
103
  }
135
104
  static get is() { return "tl-cart"; }
136
105
  static get encapsulation() { return "shadow"; }
@@ -230,10 +199,7 @@ export class TlCart {
230
199
  }
231
200
  static get states() {
232
201
  return {
233
- "cart": {},
234
- "loading": {},
235
- "error": {},
236
- "removingItemId": {}
202
+ "view": {}
237
203
  };
238
204
  }
239
205
  static get events() {
@@ -311,4 +277,19 @@ export class TlCart {
311
277
  }
312
278
  }];
313
279
  }
280
+ static get watchers() {
281
+ return [{
282
+ "propName": "showCheckoutButton",
283
+ "methodName": "syncProps"
284
+ }, {
285
+ "propName": "checkoutLabel",
286
+ "methodName": "syncProps"
287
+ }, {
288
+ "propName": "showRemoveButtons",
289
+ "methodName": "syncProps"
290
+ }, {
291
+ "propName": "compact",
292
+ "methodName": "syncProps"
293
+ }];
294
+ }
314
295
  }
@@ -10,14 +10,14 @@
10
10
  background: transparent;
11
11
  border: none;
12
12
  cursor: pointer;
13
- padding: var(--tl-spacing-2, 0.5rem);
14
- border-radius: var(--tl-radius-md, 0.5rem);
15
- color: var(--tl-color-foreground, #111827);
13
+ padding: var(--tl-spacing-2);
14
+ border-radius: var(--tl-radius-md);
15
+ color: var(--tl-color-foreground);
16
16
  transition: background-color 0.2s, transform 0.15s;
17
17
  }
18
18
 
19
19
  .cart-badge:hover {
20
- background-color: var(--tl-color-muted, #f3f4f6);
20
+ background-color: var(--tl-color-muted);
21
21
  }
22
22
 
23
23
  .cart-badge:active {
@@ -25,13 +25,13 @@
25
25
  }
26
26
 
27
27
  .cart-badge:focus-visible {
28
- outline: 2px solid var(--tl-color-primary, #6366f1);
28
+ outline: 2px solid var(--tl-color-primary);
29
29
  outline-offset: 2px;
30
30
  }
31
31
 
32
32
  /* Size variants */
33
33
  .size-sm {
34
- padding: var(--tl-spacing-1, 0.25rem);
34
+ padding: var(--tl-spacing-1);
35
35
  }
36
36
 
37
37
  .size-sm .icon-svg,
@@ -49,7 +49,7 @@
49
49
  }
50
50
 
51
51
  .size-lg {
52
- padding: var(--tl-spacing-3, 0.75rem);
52
+ padding: var(--tl-spacing-3);
53
53
  }
54
54
 
55
55
  .size-lg .icon-svg,
@@ -80,11 +80,11 @@
80
80
  height: 18px;
81
81
  padding: 0 5px;
82
82
  border-radius: 9px;
83
- background-color: var(--tl-color-primary, #6366f1);
84
- color: var(--tl-color-primary-foreground, #ffffff);
83
+ background-color: var(--tl-color-primary);
84
+ color: var(--tl-color-primary-foreground);
85
85
  font-size: 11px;
86
86
  font-weight: 600;
87
- font-family: var(--tl-font-family, system-ui, sans-serif);
87
+ font-family: var(--tl-font-family);
88
88
  display: flex;
89
89
  align-items: center;
90
90
  justify-content: center;
@@ -119,7 +119,7 @@
119
119
  color: inherit;
120
120
  font-size: 12px;
121
121
  font-weight: 600;
122
- font-family: var(--tl-font-family, system-ui, sans-serif);
122
+ font-family: var(--tl-font-family);
123
123
  line-height: 1;
124
124
  }
125
125