@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,7 +1,7 @@
1
1
  :host {
2
2
  display: block;
3
- font-family: var(--tl-font-family, system-ui, sans-serif);
4
- color: var(--tl-foreground, #111827);
3
+ font-family: var(--tl-font-family);
4
+ color: var(--tl-foreground);
5
5
  }
6
6
 
7
7
  .confirmation {
@@ -11,13 +11,13 @@
11
11
  .check {
12
12
  width: 4rem;
13
13
  height: 4rem;
14
- margin: 0 auto var(--tl-spacing-4, 1rem);
14
+ margin: 0 auto var(--tl-spacing-4);
15
15
  display: flex;
16
16
  align-items: center;
17
17
  justify-content: center;
18
18
  border-radius: 9999px;
19
- background: var(--tl-success, #10b981);
20
- color: var(--tl-success-foreground, #ffffff);
19
+ background: var(--tl-success);
20
+ color: var(--tl-success-foreground);
21
21
  }
22
22
 
23
23
  .check svg {
@@ -26,49 +26,49 @@
26
26
  }
27
27
 
28
28
  .title {
29
- margin: 0 0 var(--tl-spacing-2, 0.5rem);
29
+ margin: 0 0 var(--tl-spacing-2);
30
30
  font-size: 1.875rem;
31
31
  font-weight: 700;
32
32
  line-height: 1.2;
33
33
  }
34
34
 
35
35
  .lead {
36
- margin: 0 0 var(--tl-spacing-6, 1.5rem);
37
- color: var(--tl-muted-foreground, #6b7280);
36
+ margin: 0 0 var(--tl-spacing-6);
37
+ color: var(--tl-muted-foreground);
38
38
  }
39
39
 
40
40
  .error {
41
- margin: 0 0 var(--tl-spacing-6, 1.5rem);
41
+ margin: 0 0 var(--tl-spacing-6);
42
42
  font-size: 0.875rem;
43
- color: var(--tl-error, #ef4444);
43
+ color: var(--tl-error);
44
44
  }
45
45
 
46
46
  .summary {
47
47
  text-align: left;
48
- padding: var(--tl-spacing-6, 1.5rem);
49
- margin-bottom: var(--tl-spacing-6, 1.5rem);
50
- background: var(--tl-muted, #f9fafb);
51
- border: 1px solid var(--tl-border, #e5e7eb);
52
- border-radius: var(--tl-radius-lg, 0.75rem);
48
+ padding: var(--tl-spacing-6);
49
+ margin-bottom: var(--tl-spacing-6);
50
+ background: var(--tl-muted);
51
+ border: 1px solid var(--tl-border);
52
+ border-radius: var(--tl-radius-lg);
53
53
  }
54
54
 
55
55
  .rows {
56
56
  display: grid;
57
- gap: var(--tl-spacing-2, 0.5rem);
58
- margin: 0 0 var(--tl-spacing-4, 1rem);
59
- padding: 0 0 var(--tl-spacing-4, 1rem);
60
- border-bottom: 1px solid var(--tl-border, #e5e7eb);
57
+ gap: var(--tl-spacing-2);
58
+ margin: 0 0 var(--tl-spacing-4);
59
+ padding: 0 0 var(--tl-spacing-4);
60
+ border-bottom: 1px solid var(--tl-border);
61
61
  }
62
62
 
63
63
  .row {
64
64
  display: flex;
65
65
  justify-content: space-between;
66
- gap: var(--tl-spacing-4, 1rem);
66
+ gap: var(--tl-spacing-4);
67
67
  font-size: 0.875rem;
68
68
  }
69
69
 
70
70
  .row dt {
71
- color: var(--tl-muted-foreground, #6b7280);
71
+ color: var(--tl-muted-foreground);
72
72
  }
73
73
 
74
74
  .row dd {
@@ -78,7 +78,7 @@
78
78
  }
79
79
 
80
80
  .reference {
81
- font-family: var(--tl-font-family-mono, ui-monospace, monospace);
81
+ font-family: var(--tl-font-family-mono);
82
82
  font-weight: 600;
83
83
  }
84
84
 
@@ -87,40 +87,40 @@
87
87
  margin: 0;
88
88
  padding: 0;
89
89
  display: grid;
90
- gap: var(--tl-spacing-2, 0.5rem);
90
+ gap: var(--tl-spacing-2);
91
91
  }
92
92
 
93
93
  .line {
94
94
  display: flex;
95
95
  justify-content: space-between;
96
- gap: var(--tl-spacing-4, 1rem);
96
+ gap: var(--tl-spacing-4);
97
97
  font-size: 0.875rem;
98
98
  }
99
99
 
100
100
  .totals {
101
- margin-top: var(--tl-spacing-3, 0.75rem);
102
- padding-top: var(--tl-spacing-3, 0.75rem);
103
- border-top: 1px solid var(--tl-border, #e5e7eb);
101
+ margin-top: var(--tl-spacing-3);
102
+ padding-top: var(--tl-spacing-3);
103
+ border-top: 1px solid var(--tl-border);
104
104
  display: grid;
105
- gap: var(--tl-spacing-1, 0.25rem);
105
+ gap: var(--tl-spacing-1);
106
106
  font-size: 0.875rem;
107
107
  }
108
108
 
109
109
  .total-row {
110
110
  display: flex;
111
111
  justify-content: space-between;
112
- color: var(--tl-muted-foreground, #6b7280);
112
+ color: var(--tl-muted-foreground);
113
113
  }
114
114
 
115
115
  .total-row.discount {
116
- color: var(--tl-success, #10b981);
116
+ color: var(--tl-success);
117
117
  }
118
118
 
119
119
  .total-row.total {
120
- margin-top: var(--tl-spacing-1, 0.25rem);
120
+ margin-top: var(--tl-spacing-1);
121
121
  font-size: 1rem;
122
122
  font-weight: 600;
123
- color: var(--tl-foreground, #111827);
123
+ color: var(--tl-foreground);
124
124
  }
125
125
 
126
126
  .tickets {
@@ -128,24 +128,24 @@
128
128
  }
129
129
 
130
130
  .subtitle {
131
- margin: 0 0 var(--tl-spacing-4, 1rem);
131
+ margin: 0 0 var(--tl-spacing-4);
132
132
  font-size: 1.125rem;
133
133
  font-weight: 600;
134
134
  }
135
135
 
136
136
  .hint {
137
- margin: var(--tl-spacing-3, 0.75rem) 0 0;
137
+ margin: var(--tl-spacing-3) 0 0;
138
138
  font-size: 0.75rem;
139
- color: var(--tl-muted-foreground, #6b7280);
139
+ color: var(--tl-muted-foreground);
140
140
  }
141
141
 
142
142
  /* Skeleton */
143
143
  .skeleton-line,
144
144
  .skeleton-block {
145
- background: var(--tl-secondary, #f3f4f6);
146
- border-radius: var(--tl-radius-md, 0.5rem);
145
+ background: var(--tl-secondary);
146
+ border-radius: var(--tl-radius-md);
147
147
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
148
- margin: 0 auto var(--tl-spacing-3, 0.75rem);
148
+ margin: 0 auto var(--tl-spacing-3);
149
149
  }
150
150
 
151
151
  .skeleton-line {
@@ -1,6 +1,7 @@
1
1
  import { h } from "@stencil/core";
2
- import { onSDKEvent, whenSDK } from "../../utils/sdk-connector";
3
- import { errorMessage, formatDateTime, formatPrice, orderCustomerEmail, orderEventName, resolveOccurrence, ticketItems, } from "../../utils/order-summary";
2
+ import { createElement, orderConfirmationCore, } from "@ticketlayer/elements-core";
3
+ import { getSDK, whenSDK } from "../../utils/sdk-connector";
4
+ import { webQuery } from "../../utils/web-query";
4
5
  /**
5
6
  * tl-order-confirmation - the "thank you" page block: order reference,
6
7
  * customer email, event and date, ticket lines, totals, then the tickets
@@ -13,6 +14,13 @@ import { errorMessage, formatDateTime, formatPrice, orderCustomerEmail, orderEve
13
14
  * 3. the SDK's `checkout:completed` event, for a page that mounts this before
14
15
  * the customer pays
15
16
  *
17
+ * The web harness for `orderConfirmationCore`: it renders and it forwards. All
18
+ * three of those routes, the money rows, the event lookup and every string are
19
+ * in `@ticketlayer/elements-core` (AGENTS.md, TKT-11). What is left here is the
20
+ * Stencil surface and the two genuinely web things: the client the page
21
+ * published on `window.Ticketlayer`, and `window.location.search`, which is
22
+ * where this runtime keeps the parameters the core asks for.
23
+ *
16
24
  * Usage: <tl-order-confirmation order-id="ord_xxx"></tl-order-confirmation>
17
25
  *
18
26
  * @event tlOrderLoaded - the order was loaded
@@ -24,125 +32,82 @@ export class TlOrderConfirmation {
24
32
  this.showTickets = true;
25
33
  /** Columns for the ticket grid. */
26
34
  this.columns = 2;
27
- this.order = null;
28
- this.resolvedOrderId = null;
29
- this.loading = false;
30
- this.error = null;
31
- this.paymentFailed = false;
32
- this.occurrence = null;
33
- this.signedInCustomer = null;
35
+ this.element = createElement(orderConfirmationCore, {
36
+ client: () => getSDK(),
37
+ clientReady: () => whenSDK(),
38
+ query: webQuery,
39
+ emit: (event, detail) => this.forward(event, detail),
40
+ });
41
+ /** The core's whole view. Assigning it is what makes Stencil re-render. */
42
+ this.view = this.element.view;
34
43
  }
35
- watchOrderId(next) {
36
- this.resolvedOrderId = next || this.orderIdFromUrl();
37
- this.load();
44
+ /**
45
+ * A new order id is a new subject, and the core resolves it again the way
46
+ * the mount did - the prop first, the link second. Not a remount: the
47
+ * `checkout:completed` subscription belongs to the element rather than to
48
+ * the order it is showing.
49
+ */
50
+ watchOrderId() {
51
+ this.syncProps();
52
+ this.element.actions.orderIdChanged();
38
53
  }
39
- async componentWillLoad() {
40
- const params = this.urlParams();
41
- // Stripe returns with ?redirect_status=; anything but succeeded is not paid.
42
- const redirect = params?.get('redirect_status');
43
- this.paymentFailed = !!redirect && redirect !== 'succeeded';
44
- this.resolvedOrderId = this.orderId || this.orderIdFromUrl();
45
- if (this.resolvedOrderId && !this.paymentFailed) {
46
- await this.load();
47
- }
48
- }
49
- componentDidLoad() {
50
- // A page that mounts before checkout: pick the order up when the SDK completes it.
51
- this.unsubscribe = onSDKEvent('checkout:completed', (payload) => {
52
- const order = payload;
53
- if (!order?.id)
54
- return;
55
- this.paymentFailed = false;
56
- this.order = order;
57
- this.resolvedOrderId = order.id;
58
- this.tlOrderLoaded.emit({ order });
59
- // Re-read for tickets, which are issued after the order is created.
60
- this.load();
54
+ syncProps() {
55
+ this.element.setProps({
56
+ orderId: this.orderId,
57
+ customerEmail: this.customerEmail,
58
+ showTickets: this.showTickets,
59
+ columns: this.columns,
61
60
  });
62
61
  }
62
+ connectedCallback() {
63
+ this.syncProps();
64
+ this.unsubscribe ?? (this.unsubscribe = this.element.subscribe((view) => {
65
+ this.view = view;
66
+ }));
67
+ this.view = this.element.view;
68
+ this.teardown = this.element.mount();
69
+ }
70
+ /**
71
+ * Off screen: run the mount's teardown, which drops the
72
+ * `checkout:completed` subscription. Not `destroy()`: Stencil calls this for
73
+ * a DOM move as well as a removal, and a destroyed core never mounts again.
74
+ */
63
75
  disconnectedCallback() {
76
+ this.teardown?.();
77
+ this.teardown = undefined;
64
78
  this.unsubscribe?.();
79
+ this.unsubscribe = undefined;
65
80
  }
66
- urlParams() {
67
- if (typeof window === 'undefined' || !window.location?.search)
68
- return null;
69
- return new URLSearchParams(window.location.search);
81
+ forward(event, detail) {
82
+ if (event === 'tlOrderLoaded')
83
+ this.tlOrderLoaded.emit(detail);
84
+ else if (event === 'tlError')
85
+ this.tlError.emit(detail);
70
86
  }
71
- orderIdFromUrl() {
72
- return this.urlParams()?.get('orderId') || null;
87
+ renderRows() {
88
+ return (h("dl", { class: "rows" }, this.view.derived.rows.map((row) => (h("div", { class: "row", key: row.label }, h("dt", null, row.label), h("dd", { class: row.reference ? 'reference' : undefined }, row.value))))));
73
89
  }
74
- async load() {
75
- const id = this.resolvedOrderId;
76
- if (!id)
77
- return;
78
- try {
79
- this.loading = !this.order;
80
- this.error = null;
81
- const sdk = await whenSDK();
82
- const orders = sdk.getOrdersManager?.();
83
- if (!orders)
84
- throw new Error('Orders are not available');
85
- const order = (await orders.get(id));
86
- if (!order)
87
- throw new Error('Order not found');
88
- this.order = order;
89
- this.signedInCustomer = sdk.getAuthManager?.()?.customer ?? null;
90
- this.tlOrderLoaded.emit({ order });
91
- this.resolveEvent(sdk, order);
92
- }
93
- catch (err) {
94
- console.error('[tl-order-confirmation] Failed to load order:', err);
95
- this.error = errorMessage(err, 'Failed to load your order');
96
- this.tlError.emit({ message: this.error });
97
- }
98
- finally {
99
- this.loading = false;
100
- }
101
- }
102
- // The order view has no event name or date; look them up from the first
103
- // ticket's occurrence. Non-blocking and best effort.
104
- async resolveEvent(sdk, order) {
105
- const occurrenceId = order.tickets?.find((t) => t.eventOccurrenceId)?.eventOccurrenceId;
106
- if (!occurrenceId)
107
- return;
108
- try {
109
- const resolved = await resolveOccurrence(sdk, occurrenceId);
110
- if (resolved && this.order?.id === order.id)
111
- this.occurrence = resolved;
112
- }
113
- catch {
114
- // Leave the event line at what the order gives us.
115
- }
116
- }
117
- renderRows(order) {
118
- const email = this.customerEmail || orderCustomerEmail(order, this.signedInCustomer);
119
- const eventName = this.occurrence?.eventName || orderEventName(order);
120
- const startsAt = this.occurrence?.startsAt;
121
- return (h("dl", { class: "rows" }, h("div", { class: "row" }, h("dt", null, "Order reference"), h("dd", { class: "reference" }, order.orderNumber)), email && (h("div", { class: "row" }, h("dt", null, "Email"), h("dd", null, email))), eventName && (h("div", { class: "row" }, h("dt", null, "Event"), h("dd", null, eventName))), startsAt && (h("div", { class: "row" }, h("dt", null, "Date"), h("dd", null, formatDateTime(startsAt))))));
122
- }
123
- renderTotals(order) {
124
- const c = order.currency || 'GBP';
125
- const fees = Number(order.totalFees) || 0;
126
- const tax = Number(order.totalTax) || 0;
127
- const discounts = Number(order.totalDiscounts) || 0;
128
- return (h("div", { class: "totals" }, h("div", { class: "total-row" }, h("span", null, "Subtotal"), h("span", null, formatPrice(order.subtotal, c))), fees > 0 && (h("div", { class: "total-row" }, h("span", null, "Fees"), h("span", null, formatPrice(order.totalFees, c)))), tax > 0 && (h("div", { class: "total-row" }, h("span", null, "Tax"), h("span", null, formatPrice(order.totalTax, c)))), discounts > 0 && (h("div", { class: "total-row discount" }, h("span", null, "Discount"), h("span", null, "-", formatPrice(order.totalDiscounts, c)))), h("div", { class: "total-row total" }, h("span", null, "Total"), h("span", null, formatPrice(order.total, c)))));
90
+ // Money comes from the core's orderTotals: the booking fee is its own row
91
+ // named after the channel's fee profile, the subtotal is the ticket lines
92
+ // alone (the order's own `subtotal` folds the fee line into it) and the
93
+ // total is the order's figure, so what is shown is what was charged.
94
+ renderTotals() {
95
+ const { strings, derived } = this.view;
96
+ return (h("div", { class: "totals" }, h("div", { class: "total-row" }, h("span", null, strings.subtotalRow), h("span", null, derived.subtotalLabel)), derived.totals.showFee && (h("div", { class: "total-row fee" }, h("span", null, derived.totals.feeLabel), h("span", null, derived.feeAmountLabel))), derived.showTaxRow && (h("div", { class: "total-row" }, h("span", null, strings.taxRow), h("span", null, derived.taxLabel))), 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))));
129
97
  }
130
98
  render() {
131
- if (this.paymentFailed) {
132
- return (h("div", { class: "confirmation" }, h("h1", { class: "title" }, "Payment not completed"), h("p", { class: "lead" }, "Your payment wasn't completed. Your cart is still saved, so you can try again.")));
99
+ const { status, state, strings, derived } = this.view;
100
+ if (status === 'payment-failed') {
101
+ return (h("div", { class: "confirmation" }, h("h1", { class: "title" }, strings.paymentFailedTitle), h("p", { class: "lead" }, strings.paymentFailedLead)));
133
102
  }
134
103
  // Nothing to show yet: no order in props, URL or from checkout.
135
- if (!this.resolvedOrderId && !this.order) {
104
+ if (status === 'idle') {
136
105
  return null;
137
106
  }
138
- if (this.loading) {
107
+ if (status === 'loading') {
139
108
  return (h("div", { class: "confirmation" }, h("div", { class: "skeleton-line short" }), h("div", { class: "skeleton-line long" }), h("div", { class: "skeleton-block" })));
140
109
  }
141
- const order = this.order;
142
- const orderId = order?.id || this.resolvedOrderId;
143
- return (h("div", { class: "confirmation" }, h("div", { class: "check", "aria-hidden": "true" }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor" }, h("path", { "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "2", d: "M5 13l4 4L19 7" }))), h("h1", { class: "title" }, "You're going!"), h("p", { class: "lead" }, order?.orderNumber
144
- ? `Order ${order.orderNumber} is confirmed. Your tickets are on their way to your email.`
145
- : 'Your order is confirmed. Your tickets are on their way to your email.'), this.error && !order && (h("p", { class: "error" }, "We couldn't load your order details yet. ", this.error)), order && Array.isArray(order.items) && (h("div", { class: "summary" }, this.renderRows(order), h("ul", { class: "lines" }, ticketItems(order).map((item, i) => (h("li", { class: "line", key: i }, h("span", { class: "line-name" }, item.quantity, " x ", item.name), h("span", { class: "line-price" }, formatPrice(item.subtotal, order.currency)))))), this.renderTotals(order))), this.showTickets && order && (h("div", { class: "tickets" }, h("h2", { class: "subtitle" }, "Your tickets"), h("tl-order-tickets", { orderId: orderId, columns: this.columns }), h("p", { class: "hint" }, "Show these QR codes at the door for entry. Use Download PDF on a ticket to save it.")))));
110
+ return (h("div", { class: "confirmation" }, h("div", { class: "check", "aria-hidden": "true" }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor" }, h("path", { "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "2", d: "M5 13l4 4L19 7" }))), h("h1", { class: "title" }, strings.title), h("p", { class: "lead" }, derived.leadText), derived.showError && (h("p", { class: "error" }, strings.errorPrefix, state.error)), derived.showSummary && (h("div", { class: "summary" }, this.renderRows(), h("ul", { class: "lines" }, derived.lines.map((line, i) => (h("li", { class: "line", key: i }, h("span", { class: "line-name" }, line.label), h("span", { class: "line-price" }, line.priceLabel))))), this.renderTotals())), derived.showTickets && (h("div", { class: "tickets" }, h("h2", { class: "subtitle" }, strings.ticketsTitle), h("tl-order-tickets", { orderId: derived.ticketsOrderId, columns: this.columns }), h("p", { class: "hint" }, strings.ticketsHint)))));
146
111
  }
147
112
  static get is() { return "tl-order-confirmation"; }
148
113
  static get encapsulation() { return "shadow"; }
@@ -240,13 +205,7 @@ export class TlOrderConfirmation {
240
205
  }
241
206
  static get states() {
242
207
  return {
243
- "order": {},
244
- "resolvedOrderId": {},
245
- "loading": {},
246
- "error": {},
247
- "paymentFailed": {},
248
- "occurrence": {},
249
- "signedInCustomer": {}
208
+ "view": {}
250
209
  };
251
210
  }
252
211
  static get events() {
@@ -266,8 +225,8 @@ export class TlOrderConfirmation {
266
225
  "references": {
267
226
  "TlOrderData": {
268
227
  "location": "import",
269
- "path": "../../utils/order-summary",
270
- "id": "src/utils/order-summary.ts::TlOrderData",
228
+ "path": "@ticketlayer/elements-core",
229
+ "id": "../elements-core/dist/esm/index.d.ts::TlOrderData",
271
230
  "referenceLocation": "TlOrderData"
272
231
  }
273
232
  }
@@ -293,6 +252,15 @@ export class TlOrderConfirmation {
293
252
  return [{
294
253
  "propName": "orderId",
295
254
  "methodName": "watchOrderId"
255
+ }, {
256
+ "propName": "customerEmail",
257
+ "methodName": "syncProps"
258
+ }, {
259
+ "propName": "showTickets",
260
+ "methodName": "syncProps"
261
+ }, {
262
+ "propName": "columns",
263
+ "methodName": "syncProps"
296
264
  }];
297
265
  }
298
266
  }
@@ -1,11 +1,11 @@
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
  .grid {
7
7
  display: grid;
8
- gap: var(--tl-spacing-4, 1rem);
8
+ gap: var(--tl-spacing-4);
9
9
  grid-template-columns: 1fr;
10
10
  }
11
11
 
@@ -19,28 +19,28 @@
19
19
  }
20
20
 
21
21
  .state {
22
- padding: var(--tl-spacing-6, 1.5rem);
22
+ padding: var(--tl-spacing-6);
23
23
  text-align: center;
24
- color: var(--tl-muted-foreground, #6b7280);
24
+ color: var(--tl-muted-foreground);
25
25
  font-size: 0.875rem;
26
26
  }
27
27
 
28
28
  .state.error {
29
- color: var(--tl-error, #dc2626);
29
+ color: var(--tl-error);
30
30
  }
31
31
 
32
32
  .state.issuing {
33
33
  display: flex;
34
34
  align-items: center;
35
35
  justify-content: center;
36
- gap: var(--tl-spacing-2, 0.5rem);
36
+ gap: var(--tl-spacing-2);
37
37
  }
38
38
 
39
39
  .spinner {
40
40
  width: 0.875rem;
41
41
  height: 0.875rem;
42
- border: 2px solid var(--tl-border, #e5e7eb);
43
- border-top-color: var(--tl-primary, #6366f1);
42
+ border: 2px solid var(--tl-border);
43
+ border-top-color: var(--tl-primary);
44
44
  border-radius: 50%;
45
45
  animation: tl-spin 0.7s linear infinite;
46
46
  flex: none;
@@ -57,6 +57,6 @@
57
57
  @media (prefers-reduced-motion: reduce) {
58
58
  .spinner {
59
59
  animation: none;
60
- border-top-color: var(--tl-border, #e5e7eb);
60
+ border-top-color: var(--tl-border);
61
61
  }
62
62
  }