@coras-io/embed 0.2.0 → 0.4.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 (237) hide show
  1. package/CHANGELOG.md +142 -0
  2. package/README.md +8 -7
  3. package/dist/components/accordion/accordion-item/accordion-item.styles.js +1 -1
  4. package/dist/components/alert/alert.styles.js +14 -14
  5. package/dist/components/attraction-card/base/attraction-card.styles.js +7 -3
  6. package/dist/components/attraction-discovery/attraction-discovery.styles.js +1 -1
  7. package/dist/components/attraction-header/attraction-header.styles.js +1 -1
  8. package/dist/components/attraction-option/attraction-option.styles.js +4 -4
  9. package/dist/components/basket/basket.styles.js +27 -26
  10. package/dist/components/basket-empty/basket-empty.styles.js +1 -0
  11. package/dist/components/basket-item/basket-item.component.js +10 -4
  12. package/dist/components/basket-item/basket-item.styles.js +9 -3
  13. package/dist/components/basket-item-ticket/basket-item-ticket.styles.js +1 -3
  14. package/dist/components/basket-mobile/basket-mobile.styles.js +5 -5
  15. package/dist/components/better-carousel/better-carousel.styles.js +2 -0
  16. package/dist/components/bottom-drawer/bottom-drawer.styles.js +6 -4
  17. package/dist/components/button/button.component.d.ts +0 -1
  18. package/dist/components/button/button.component.js +1 -8
  19. package/dist/components/button/button.constants.d.ts +1 -1
  20. package/dist/components/button/button.constants.js +1 -1
  21. package/dist/components/button/button.styles.js +66 -39
  22. package/dist/components/calendar/base/calendar.styles.js +3 -5
  23. package/dist/components/calendar/multi/multi.styles.js +7 -0
  24. package/dist/components/category-tag/category-tag.styles.js +10 -7
  25. package/dist/components/checkbox/checkbox.styles.js +2 -2
  26. package/dist/components/chip/chip.styles.js +2 -2
  27. package/dist/components/collect-fida/collect-fida.component.js +5 -3
  28. package/dist/components/collect-fida/collect-fida.styles.js +9 -16
  29. package/dist/components/crypto-auth-modal/crypto-auth-modal.component.js +6 -4
  30. package/dist/components/crypto-auth-modal/crypto-auth-modal.styles.js +2 -2
  31. package/dist/components/dialog/dialog.styles.js +10 -17
  32. package/dist/components/drawer/drawer.component.js +6 -0
  33. package/dist/components/drawer/drawer.styles.js +17 -3
  34. package/dist/components/dropdown/dropdown.component.js +7 -0
  35. package/dist/components/dropdown/dropdown.styles.js +3 -6
  36. package/dist/components/expiration-timer/expiration-timer.styles.js +3 -3
  37. package/dist/components/explore-card/explore-card.styles.js +1 -1
  38. package/dist/components/filter-chip/filter-chip.styles.js +11 -9
  39. package/dist/components/filters-drawer/filters-drawer.component.js +1 -1
  40. package/dist/components/filters-drawer/filters-drawer.styles.js +6 -5
  41. package/dist/components/image/image.styles.js +3 -3
  42. package/dist/components/image-chip/image-chip.styles.js +1 -1
  43. package/dist/components/input-field/input-field.styles.js +22 -17
  44. package/dist/components/itinerary/itinerary-item/itinerary-item.styles.js +1 -1
  45. package/dist/components/joined-fields/joined-fields.styles.js +10 -6
  46. package/dist/components/loading-spinner/loading-spinner.styles.js +1 -1
  47. package/dist/components/location-image/location-image.component.d.ts +6 -0
  48. package/dist/components/location-image/location-image.component.js +15 -2
  49. package/dist/components/location-image/location-image.styles.js +1 -1
  50. package/dist/components/locations-results/locations-results.styles.js +4 -6
  51. package/dist/components/marketing-tag/marketing-tag.styles.js +1 -1
  52. package/dist/components/message-card/message-card.styles.js +6 -6
  53. package/dist/components/option-group/option-chip/option-chip.styles.js +4 -3
  54. package/dist/components/order-confirmation/order-confirmation-item/order-confirmation-item.styles.js +9 -0
  55. package/dist/components/order-confirmation/order-confirmation.component.js +4 -3
  56. package/dist/components/order-confirmation/order-confirmation.styles.js +1 -1
  57. package/dist/components/otp/otp.styles.js +6 -6
  58. package/dist/components/overlay/overlay.styles.js +5 -1
  59. package/dist/components/pay-in/pay-in.styles.js +2 -2
  60. package/dist/components/payment-fiat-method/payment-fiat-method.styles.js +20 -4
  61. package/dist/components/payment-option/payment-option.styles.js +10 -12
  62. package/dist/components/performance-time/performance-time.styles.js +2 -2
  63. package/dist/components/phone-country-code/phone-country-code.styles.js +1 -1
  64. package/dist/components/points/points.styles.js +1 -1
  65. package/dist/components/search-button/search-button.styles.js +15 -7
  66. package/dist/components/seated-selector/seated-selector.component.d.ts +2 -0
  67. package/dist/components/seated-selector/seated-selector.component.js +53 -10
  68. package/dist/components/seated-selector/seated-selector.styles.js +77 -14
  69. package/dist/components/seats-io/seats-io.component.d.ts +2 -0
  70. package/dist/components/seats-io/seats-io.component.js +25 -2
  71. package/dist/components/seats-io/seats-io.constants.d.ts +2 -1
  72. package/dist/components/seats-io/seats-io.constants.js +6 -1
  73. package/dist/components/seats-io/seats-io.transform.d.ts +8 -2
  74. package/dist/components/seats-io/seats-io.transform.js +12 -4
  75. package/dist/components/select-list/select-list.styles.js +1 -0
  76. package/dist/components/select-list/select-option/select-option.styles.js +3 -3
  77. package/dist/components/sort-dropdown/sort-dropdown.styles.js +1 -1
  78. package/dist/components/sort-list/sort-list.styles.js +1 -1
  79. package/dist/components/sport-options/sport-option/sport-option.styles.js +2 -2
  80. package/dist/components/star-rating/star-rating.component.d.ts +1 -0
  81. package/dist/components/star-rating/star-rating.component.js +19 -23
  82. package/dist/components/star-rating/star-rating.styles.js +32 -6
  83. package/dist/components/tab/tab.styles.js +1 -1
  84. package/dist/components/tabs/tabs.styles.js +1 -1
  85. package/dist/components/tag/tag.styles.js +7 -7
  86. package/dist/components/text-section/text-section.styles.js +2 -1
  87. package/dist/components/time-tag/time-tag.styles.js +1 -2
  88. package/dist/components/tooltip/tooltip.styles.js +3 -3
  89. package/dist/components/tour-ticket-type-selector/tour-ticket-type/tour-ticket-type.styles.js +2 -2
  90. package/dist/components/tour-ticket-type-selector/tour-ticket-type-selector.component.js +1 -1
  91. package/dist/components/tour-ticket-type-selector/tour-ticket-type-selector.styles.js +1 -10
  92. package/dist/components/transfer-modal/transfer-modal.component.js +3 -3
  93. package/dist/components/transfer-modal/transfer-modal.styles.js +6 -8
  94. package/dist/containers/basket/basket.component.d.ts +1 -1
  95. package/dist/containers/basket/basket.component.js +56 -25
  96. package/dist/containers/footer/footer.component.d.ts +2 -0
  97. package/dist/containers/footer/footer.component.js +8 -0
  98. package/dist/containers/footer/footer.styles.js +12 -0
  99. package/dist/containers/navbar/navbar.component.d.ts +6 -1
  100. package/dist/containers/navbar/navbar.component.js +41 -9
  101. package/dist/containers/navbar/navbar.styles.js +47 -13
  102. package/dist/contexts/basket/basket.provider.d.ts +1 -0
  103. package/dist/contexts/basket/basket.provider.js +31 -4
  104. package/dist/contexts/properties.context.d.ts +4 -4
  105. package/dist/core/api/middlewares/booking-session/booking-session.constants.d.ts +1 -0
  106. package/dist/core/api/middlewares/booking-session/booking-session.constants.js +1 -0
  107. package/dist/core/api/middlewares/booking-session/booking-session.js +18 -27
  108. package/dist/core/api/middlewares/booking-session/booking-session.utils.d.ts +4 -4
  109. package/dist/core/api/middlewares/booking-session/booking-session.utils.js +13 -10
  110. package/dist/core/api/queries.js +3 -2
  111. package/dist/core/color-scheme.d.ts +14 -0
  112. package/dist/core/color-scheme.js +48 -0
  113. package/dist/core/currency/constants.d.ts +1 -1
  114. package/dist/core/currency/constants.js +4 -3
  115. package/dist/core/i18n/date.js +20 -9
  116. package/dist/core/i18n/locale-codes.d.ts +2 -2
  117. package/dist/core/i18n/locale-codes.js +4 -0
  118. package/dist/core/images/constants.d.ts +0 -5
  119. package/dist/core/images/constants.js +0 -5
  120. package/dist/core/images/helpers.d.ts +8 -0
  121. package/dist/core/images/helpers.js +14 -6
  122. package/dist/core/images/srcset.js +2 -2
  123. package/dist/core/storybook/demo.d.ts +4 -0
  124. package/dist/core/storybook/demo.js +17 -0
  125. package/dist/core/types/locales.d.ts +7 -0
  126. package/dist/core/utils/datetime.js +10 -4
  127. package/dist/core/utils/locale.d.ts +8 -1
  128. package/dist/core/utils/locale.js +10 -0
  129. package/dist/helpers/helpers.d.ts +1 -1
  130. package/dist/index.d.ts +2 -3
  131. package/dist/index.js +1 -2
  132. package/dist/locales/ar-SA.d.ts +279 -0
  133. package/dist/locales/ar-SA.js +288 -0
  134. package/dist/locales/da-DK.d.ts +100 -82
  135. package/dist/locales/da-DK.js +104 -89
  136. package/dist/locales/de-DE.d.ts +100 -82
  137. package/dist/locales/de-DE.js +104 -89
  138. package/dist/locales/en-IE.d.ts +250 -232
  139. package/dist/locales/en-IE.js +254 -239
  140. package/dist/locales/en-US.d.ts +100 -82
  141. package/dist/locales/en-US.js +107 -92
  142. package/dist/locales/es-ES.d.ts +100 -82
  143. package/dist/locales/es-ES.js +104 -89
  144. package/dist/locales/fr-FR.d.ts +100 -82
  145. package/dist/locales/fr-FR.js +104 -89
  146. package/dist/locales/fr-MA.d.ts +100 -82
  147. package/dist/locales/fr-MA.js +104 -89
  148. package/dist/locales/is-IS.d.ts +100 -82
  149. package/dist/locales/is-IS.js +104 -89
  150. package/dist/locales/it-IT.d.ts +100 -82
  151. package/dist/locales/it-IT.js +104 -89
  152. package/dist/locales/ms-MY.d.ts +100 -82
  153. package/dist/locales/ms-MY.js +106 -91
  154. package/dist/locales/nb-NO.d.ts +100 -82
  155. package/dist/locales/nb-NO.js +104 -89
  156. package/dist/locales/pl-PL.d.ts +100 -82
  157. package/dist/locales/pl-PL.js +104 -89
  158. package/dist/locales/pt-PT.d.ts +100 -82
  159. package/dist/locales/pt-PT.js +104 -89
  160. package/dist/locales/sv-SE.d.ts +100 -82
  161. package/dist/locales/sv-SE.js +104 -89
  162. package/dist/locales/th-TH.d.ts +100 -82
  163. package/dist/locales/th-TH.js +104 -89
  164. package/dist/locales/tr-TR.d.ts +100 -82
  165. package/dist/locales/tr-TR.js +104 -89
  166. package/dist/locales/zh-CN.d.ts +100 -82
  167. package/dist/locales/zh-CN.js +105 -90
  168. package/dist/locales/zh-HK.d.ts +279 -0
  169. package/dist/locales/zh-HK.js +288 -0
  170. package/dist/mixins/coinbase.mixin.js +1 -1
  171. package/dist/mixins/error-modal.styles.js +2 -2
  172. package/dist/mixins/location-search/location-search.js +3 -3
  173. package/dist/mixins/location-search/location-search.styles.js +6 -5
  174. package/dist/sdk/chrome.d.ts +9 -3
  175. package/dist/sdk/chrome.js +21 -9
  176. package/dist/sdk/element-adapter.js +11 -8
  177. package/dist/sdk/mount.d.ts +3 -3
  178. package/dist/sdk/mount.js +153 -48
  179. package/dist/sdk/navigation-intent.js +3 -0
  180. package/dist/sdk/page-registry.d.ts +14 -2
  181. package/dist/sdk/page-registry.js +33 -13
  182. package/dist/sdk/theme.d.ts +2 -16
  183. package/dist/sdk/theme.js +12 -44
  184. package/dist/sdk/types.d.ts +59 -30
  185. package/dist/sdk/url.d.ts +24 -3
  186. package/dist/sdk/url.js +66 -27
  187. package/dist/sdk/validation.d.ts +0 -7
  188. package/dist/sdk/validation.js +104 -48
  189. package/dist/styles/contrast-fixtures.d.ts +0 -5
  190. package/dist/styles/contrast-fixtures.js +79 -9
  191. package/dist/styles/contrast.js +4 -3
  192. package/dist/styles/defaults/component.js +17 -1
  193. package/dist/styles/primitives.d.ts +0 -10
  194. package/dist/styles/primitives.js +2 -12
  195. package/dist/styles/tokens.d.ts +1 -1
  196. package/dist/styles/tokens.generated.d.ts +1 -1
  197. package/dist/styles/tokens.generated.js +1 -1
  198. package/dist/styles/tokens.metadata.d.ts +1 -1
  199. package/dist/styles/tokens.metadata.js +378 -90
  200. package/dist/views/details-page/details-page.component.d.ts +5 -5
  201. package/dist/views/details-page/details-page.component.js +77 -80
  202. package/dist/views/details-page/details-page.styles.js +64 -9
  203. package/dist/views/help-page/help-page.component.d.ts +1 -0
  204. package/dist/views/help-page/help-page.component.js +11 -4
  205. package/dist/views/help-page/help-page.styles.js +21 -8
  206. package/dist/views/landing-page/landing-page.component.d.ts +4 -4
  207. package/dist/views/landing-page/landing-page.component.js +65 -65
  208. package/dist/views/landing-page/landing-page.styles.js +70 -3
  209. package/dist/views/payment-page/partials/activity-details/activity-details.styles.js +10 -33
  210. package/dist/views/payment-page/partials/billing-address/billing-address.styles.js +4 -9
  211. package/dist/views/payment-page/partials/confirmation/confirmation.styles.js +6 -6
  212. package/dist/views/payment-page/partials/hotel-pickup-list/hotel-pickup-list.styles.js +4 -4
  213. package/dist/views/payment-page/partials/payment-type-selector/payment-type-selector.styles.js +1 -0
  214. package/dist/views/payment-page/partials/stripe/stripe.component.d.ts +1 -1
  215. package/dist/views/payment-page/partials/stripe/stripe.component.js +11 -12
  216. package/dist/views/payment-page/partials/stripe/stripe.constants.d.ts +2 -15
  217. package/dist/views/payment-page/partials/stripe/stripe.constants.js +4 -17
  218. package/dist/views/payment-page/partials/stripe/stripe.styles.js +16 -23
  219. package/dist/views/payment-page/partials/stripe/stripe.utils.d.ts +25 -14
  220. package/dist/views/payment-page/partials/stripe/stripe.utils.js +111 -62
  221. package/dist/views/payment-page/partials/terms-checkbox/terms-checkbox.styles.js +1 -1
  222. package/dist/views/payment-page/payment-page.component.d.ts +1 -0
  223. package/dist/views/payment-page/payment-page.component.js +19 -9
  224. package/dist/views/payment-page/payment-page.styles.js +37 -32
  225. package/dist/views/payment-page/payment-page.utils.d.ts +7 -0
  226. package/dist/views/payment-page/payment-page.utils.js +29 -14
  227. package/dist/views/payment-page/payment-page.validators.js +9 -3
  228. package/dist/views/payment-page/services/payment-api.service.d.ts +1 -1
  229. package/dist/views/search-page/search-page.component.d.ts +1 -0
  230. package/dist/views/search-page/search-page.component.js +12 -6
  231. package/dist/views/search-page/search-page.styles.js +24 -2
  232. package/dist/views/suggestion-widget/suggestion-widget.styles.js +1 -1
  233. package/package.json +63 -76
  234. package/dist/custom-elements.json +0 -37397
  235. package/dist/sdk/meta.d.ts +0 -7
  236. package/dist/sdk/meta.js +0 -9
  237. package/dist/styles/tokens.css +0 -359
@@ -1,17 +1,44 @@
1
1
  import { css } from "lit";
2
2
  import component from "../../styles/defaults/component.js";
3
+ import { skeleton, visuallyHidden } from "../../styles/primitives.js";
3
4
  export default css `
4
5
  ${component}
6
+ ${skeleton}
7
+ ${visuallyHidden}
8
+
9
+ .payment-skeleton {
10
+ display: flex;
11
+ flex-direction: column;
12
+ gap: 1.25rem;
13
+ width: 100%;
14
+ max-width: var(--payment-page-max-width);
15
+ margin-inline: auto;
16
+ padding-block: 1rem;
17
+
18
+ .sk-field {
19
+ width: 100%;
20
+ height: 3rem;
21
+ }
22
+
23
+ .sk-block {
24
+ width: 100%;
25
+ height: 12rem;
26
+ }
27
+ }
5
28
 
6
29
  :host {
7
- --field-input-border-color: var(--coras-color-neutral-400);
30
+ --field-input-border-color: var(--coras-color-field-border);
8
31
  --field-input-border-radius: var(--coras-radius-field);
32
+ --field-input-focused-border-color: var(--coras-color-primary);
33
+ --field-input-error-color: var(--coras-color-error);
34
+ --field-input-color: var(--coras-color-text);
35
+ --field-input-placeholder-color: var(--coras-color-text-muted);
9
36
  --field-input-box-shadow: 0px 4px 4px 0px
10
37
  color-mix(in srgb, black, transparent 90%);
11
38
  --field-label-font-size: var(--coras-font-size-base);
12
39
  --field-label-line-height: var(--coras-font-size-2xl);
13
40
  --field-label-color: var(--coras-color-text);
14
- --payment-page-header-font-size: var(--coras-font-size-2xl);
41
+ --payment-page-header-font-size: var(--coras-font-size-heading);
15
42
  --payment-page-header-line-height: var(--coras-font-size-3xl);
16
43
  --payment-page-header-color: var(--coras-color-text);
17
44
  --confirmation-checkbox-label-font-size: var(--coras-font-size-xxs);
@@ -22,7 +49,7 @@ export default css `
22
49
  --activities-details-label-span-font-weight: var(
23
50
  --coras-font-weight-medium
24
51
  );
25
- --section-border-bottom-color: var(--coras-color-neutral-200);
52
+ --section-border-bottom-color: var(--coras-color-divider);
26
53
  --payment-page-max-width: var(--coras-page-max-width);
27
54
 
28
55
  --field-label-bottom-margin: 0.25rem;
@@ -151,17 +178,12 @@ export default css `
151
178
  gap: 0.5rem;
152
179
  }
153
180
 
154
- /* Stripe element styling to match coras-input */
155
-
156
181
  .stripe-element {
157
- padding: 0; /* Padding is applied to the Light DOM container */
182
+ padding: 0;
158
183
  border: 1px solid var(--field-input-border-color);
159
184
  border-radius: var(--field-input-border-radius);
160
- background-color: var(--coras-color-surface);
161
- min-height: var(
162
- --field-input-height,
163
- 3.25rem
164
- ); /* Match coras-input height */
185
+ background-color: var(--coras-input-field-background-color);
186
+ min-height: var(--field-input-height, 3.25rem);
165
187
  box-shadow: var(--field-input-box-shadow);
166
188
  box-sizing: border-box;
167
189
  overflow: hidden;
@@ -169,7 +191,6 @@ export default css `
169
191
  align-items: center;
170
192
  }
171
193
 
172
- /* Focus and validation states for Stripe element */
173
194
  .stripe-element.StripeElement--focus {
174
195
  border-color: var(--field-input-focused-border-color);
175
196
  }
@@ -178,8 +199,6 @@ export default css `
178
199
  border-color: var(--field-input-error-color);
179
200
  }
180
201
 
181
- /* Card field container styling to match coras-input container */
182
-
183
202
  .card-field-container {
184
203
  display: flex;
185
204
  flex-direction: column;
@@ -198,7 +217,6 @@ export default css `
198
217
  text-overflow: ellipsis;
199
218
  }
200
219
 
201
- /* Generic field label to match coras-field label styling */
202
220
  .field-label {
203
221
  font-size: var(--field-label-font-size);
204
222
  line-height: var(--field-label-line-height);
@@ -210,20 +228,18 @@ export default css `
210
228
  text-overflow: ellipsis;
211
229
  }
212
230
 
213
- /* Stripe elements inside joined fields */
214
-
215
231
  coras-joined-fields .stripe-element {
216
232
  border: none;
217
- padding: 0; /* Padding is applied to the Light DOM container */
233
+ padding: 0;
218
234
  height: 100%;
219
235
  }
220
236
 
221
237
  .stripe-element-error {
222
- border-color: var(--coras-color-error-500);
238
+ border-color: var(--coras-color-error);
223
239
  }
224
240
 
225
241
  .error-message {
226
- color: var(--coras-color-error-500);
242
+ color: var(--coras-color-error);
227
243
  font-size: var(--coras-font-size-sm);
228
244
  margin-top: 0.5rem;
229
245
  }
@@ -256,7 +272,7 @@ export default css `
256
272
  }
257
273
 
258
274
  .terms-container coras-checkbox {
259
- --checkbox-label-font-family: Inter, sans-serif;
275
+ --checkbox-label-font-family: var(--coras-font-family-sans);
260
276
  --checkbox-label-font-weight: 400;
261
277
  --checkbox-label-font-size: 10px;
262
278
  --checkbox-label-line-height: 14px;
@@ -272,7 +288,6 @@ export default css `
272
288
  min-width: 160px;
273
289
  }
274
290
 
275
- /* Crypto footer: terms above, full-width button below */
276
291
  .terms-and-button.crypto-footer {
277
292
  flex-direction: column;
278
293
  align-items: stretch;
@@ -303,24 +318,20 @@ export default css `
303
318
  flex-basis: auto;
304
319
  }
305
320
 
306
- /* Hide the desktop basket in mobile layout */
307
321
  coras-basket {
308
322
  display: none;
309
323
  }
310
324
 
311
- /* Inside the bottom drawer, switch content based on drawer state */
312
325
  coras-bottom-drawer .drawer-expanded-content {
313
326
  display: none;
314
327
  }
315
328
 
316
- /* Show expanded content when drawer is open (expanded) */
317
329
  coras-bottom-drawer[open] .drawer-expanded-content {
318
330
  coras-basket {
319
331
  display: block;
320
332
  }
321
333
  }
322
334
 
323
- /* When in fullscreen mode, subtract handle height to avoid vertical scroll */
324
335
  coras-bottom-drawer[open][fullscreen] .drawer-expanded-content {
325
336
  height: calc(100% - var(--bottom-drawer-handle-block-size, 1rem));
326
337
 
@@ -329,12 +340,6 @@ export default css `
329
340
  }
330
341
  }
331
342
 
332
- /* Hide collapsed summary when drawer is open (expanded) */
333
- /*coras-bottom-drawer[open] .drawer-collapsed-content {*/
334
- /* display: none;*/
335
- /*}*/
336
-
337
- /* Continue to support fullscreen state explicitly */
338
343
  coras-bottom-drawer[fullscreen] .drawer-collapsed-content {
339
344
  display: none;
340
345
  }
@@ -108,6 +108,13 @@ export declare function prepareReservationData(reservations: ReservationSummary[
108
108
  reservations: string[];
109
109
  reservationData: Record<string, Record<string, unknown>>;
110
110
  };
111
+ /**
112
+ * Builds an object from the given entries, omitting any key whose value is
113
+ * empty (null, undefined, or an empty string). Used to keep unrequired
114
+ * attendee fields out of the reservation payload, since the API rejects them
115
+ * with "Field may not be null." when present.
116
+ */
117
+ export declare function removeEmptyFields<T>(fields: Record<string, string | null | undefined>): T;
111
118
  /**
112
119
  * Prepares attendee data for the attendees field in the PUT request to /reservations
113
120
  */
@@ -427,6 +427,15 @@ export function prepareReservationData(reservations, getFieldValue) {
427
427
  });
428
428
  return { reservations: reservationIds, reservationData };
429
429
  }
430
+ /**
431
+ * Builds an object from the given entries, omitting any key whose value is
432
+ * empty (null, undefined, or an empty string). Used to keep unrequired
433
+ * attendee fields out of the reservation payload, since the API rejects them
434
+ * with "Field may not be null." when present.
435
+ */
436
+ export function removeEmptyFields(fields) {
437
+ return Object.fromEntries(Object.entries(fields).filter(([, value]) => value != null && value !== ""));
438
+ }
430
439
  /**
431
440
  * Prepares attendee data for the attendees field in the PUT request to /reservations
432
441
  */
@@ -456,8 +465,6 @@ export function prepareAttendeesData(reservations, reservationsCheck, getFieldVa
456
465
  const dateOfBirth = getFieldValue(`${fieldNamePrefix}date_of_birth`);
457
466
  // Handle phone number with country code
458
467
  const phoneNumberRaw = getFieldValue(`${fieldNamePrefix}phone_number`);
459
- const countryCode = getFieldValue(`${fieldNamePrefix}country_code`) ||
460
- selectedPhoneCode?.code;
461
468
  // Get dial code (e.g. "353") and prepend to local number
462
469
  const phoneCode = getFieldValue(`${fieldNamePrefix}phone_code`) ||
463
470
  selectedPhoneCode?.phoneCode ||
@@ -466,19 +473,27 @@ export function prepareAttendeesData(reservations, reservationsCheck, getFieldVa
466
473
  ? `${phoneCode}${phoneNumberRaw}`
467
474
  : phoneNumberRaw;
468
475
  const phoneNumber = formatPhoneWithPlus(fullPhone);
469
- const attendee = {
476
+ // Only send country_code alongside an actual phone number.
477
+ const countryCode = phoneNumber
478
+ ? getFieldValue(`${fieldNamePrefix}country_code`) ||
479
+ selectedPhoneCode?.code
480
+ : undefined;
481
+ // The API rejects null for any attendee field it did not require
482
+ // ("Field may not be null."). Only the fields the customer filled in
483
+ // are required and rendered, so send those and omit the rest.
484
+ const attendee = removeEmptyFields({
470
485
  ticket_id: ticketId,
471
- first_name: firstName || null,
472
- second_name: secondName || null,
473
- email: email || null,
474
- phone_number: phoneNumber || null,
475
- id_number: idNumber || null,
476
- gender: gender || null,
477
- city: city || null,
478
- province: province || null,
479
- country_code: countryCode || null,
480
- date_of_birth: dateOfBirth || null,
481
- };
486
+ first_name: firstName,
487
+ second_name: secondName,
488
+ email,
489
+ phone_number: phoneNumber,
490
+ id_number: idNumber,
491
+ gender,
492
+ city,
493
+ province,
494
+ country_code: countryCode,
495
+ date_of_birth: dateOfBirth,
496
+ });
482
497
  attendees.push(attendee);
483
498
  }
484
499
  });
@@ -1,5 +1,6 @@
1
1
  import { msg, str } from "@lit/localize";
2
2
  import { isValidPhoneNumber } from "libphonenumber-js/min";
3
+ import { isAfter, parseISO, startOfDay } from "date-fns";
3
4
  /**
4
5
  * Required field validator
5
6
  */
@@ -128,9 +129,14 @@ export const validPassportExpiry = ({ value }) => {
128
129
  const dateError = validDate({ value });
129
130
  if (dateError)
130
131
  return dateError;
131
- const today = new Date();
132
- const expiryDate = new Date(value);
133
- if (expiryDate <= today) {
132
+ if (!value)
133
+ return undefined; // Let required validator handle empty values
134
+ // Passport expiry is a calendar day. Compare against today's local day so the
135
+ // check does not flip near midnight: native `new Date("YYYY-MM-DD")` reads it
136
+ // as UTC midnight, which can read as expired a day early west of UTC. Expiry
137
+ // on today's date counts as expired, matching the original rule.
138
+ const expiryDate = parseISO(value);
139
+ if (!isAfter(expiryDate, startOfDay(new Date()))) {
134
140
  return msg("Passport must not be expired");
135
141
  }
136
142
  return undefined;
@@ -74,7 +74,7 @@ export declare class PaymentApiService {
74
74
  fetchTransactions(userId: string): Promise<{
75
75
  data: {
76
76
  transaction_id: string;
77
- status: string;
77
+ status: "ADDED" | "PAID" | "PENDING" | "FAILED" | "SUSPENDED" | "REFUNDED" | "PARTIAL_REFUNDED" | "CANCELLED" | "PARTIALLY_CANCELLED" | "PARTIALLY_CONFIRMED";
78
78
  created_at: string;
79
79
  reference_id: string;
80
80
  loyalty: components["schemas"]["LoyaltySchema"];
@@ -53,6 +53,7 @@ export declare class CorasSearchPage extends CorasSearchPage_base {
53
53
  connectedCallback(): void;
54
54
  disconnectedCallback(): void;
55
55
  updated(changedProperties: PropertyValues): void;
56
+ private renderSkeleton;
56
57
  private renderAttractions;
57
58
  private handleAttractionClick;
58
59
  private renderBottomSection;
@@ -29,6 +29,7 @@ import { apiGet, withErrorHandling } from "../../core/api/queries.js";
29
29
  import { adaptPresetImages } from "../../core/images/preset-adapter.js";
30
30
  import { ErrorModalMixin } from "../../mixins/error-modal.mixin.js";
31
31
  import { getLocale, setLocale } from "../../core/i18n/localization.js";
32
+ import { getApiLanguageCode } from "../../core/utils/locale.js";
32
33
  /**
33
34
  * Search page component for displaying search results.
34
35
  *
@@ -57,7 +58,7 @@ let CorasSearchPage = class CorasSearchPage extends ErrorModalMixin(LocationSear
57
58
  query: {
58
59
  date_start: dateStart,
59
60
  search_term: search,
60
- language_code: locale.split("-")[0],
61
+ language_code: getApiLanguageCode(locale),
61
62
  currency,
62
63
  page,
63
64
  size,
@@ -225,6 +226,15 @@ let CorasSearchPage = class CorasSearchPage extends ErrorModalMixin(LocationSear
225
226
  }
226
227
  this._isFirstUpdate = false;
227
228
  }
229
+ renderSkeleton() {
230
+ return html `
231
+ <div class="search-skeleton" aria-hidden="true">
232
+ <div class="coras-skeleton sk-title"></div>
233
+ ${Array.from({ length: 4 }, () => html `<div class="coras-skeleton sk-card"></div>`)}
234
+ </div>
235
+ <span class="coras-sr-only" role="status">${msg("Loading")}</span>
236
+ `;
237
+ }
228
238
  renderAttractions() {
229
239
  if (this.attractionsSearchTask.status === TaskStatus.ERROR &&
230
240
  this.attractions.length === 0) {
@@ -233,11 +243,7 @@ let CorasSearchPage = class CorasSearchPage extends ErrorModalMixin(LocationSear
233
243
  }
234
244
  if (this.page === 0 &&
235
245
  this.attractionsSearchTask.status === TaskStatus.PENDING) {
236
- return html `
237
- <div class="loading-container">
238
- <coras-loading-spinner size="large"></coras-loading-spinner>
239
- </div>
240
- `;
246
+ return this.renderSkeleton();
241
247
  }
242
248
  if (this.attractions.length === 0 &&
243
249
  this.attractionsSearchTask.status === TaskStatus.COMPLETE) {
@@ -1,10 +1,33 @@
1
1
  import { css } from "lit";
2
2
  import component from "../../styles/defaults/component.js";
3
+ import { skeleton, visuallyHidden } from "../../styles/primitives.js";
3
4
  export default css `
4
5
  ${component}
6
+ ${skeleton}
7
+ ${visuallyHidden}
8
+
9
+ .search-skeleton {
10
+ display: flex;
11
+ flex-direction: column;
12
+ gap: 1.5rem;
13
+ width: 100%;
14
+ max-width: var(--search-page-max-width);
15
+ margin-inline: auto;
16
+
17
+ .sk-title {
18
+ width: 20rem;
19
+ max-width: 70%;
20
+ height: 2rem;
21
+ }
22
+
23
+ .sk-card {
24
+ width: 100%;
25
+ height: 9rem;
26
+ }
27
+ }
5
28
 
6
29
  :host {
7
- --attractions-title-font-size: var(--coras-font-size-2xl);
30
+ --attractions-title-font-size: var(--coras-font-size-heading);
8
31
  --attractions-title-line-height: var(--coras-font-size-3xl);
9
32
  --attractions-title-font-weight: var(--coras-font-weight-semibold);
10
33
  --attractions-title-color: var(--coras-color-text);
@@ -52,7 +75,6 @@ export default css `
52
75
  width: fit-content;
53
76
  }
54
77
 
55
- .loading-container,
56
78
  .error-container,
57
79
  .empty-container,
58
80
  .loading-more-container {
@@ -4,7 +4,7 @@ export default css `
4
4
  ${component}
5
5
 
6
6
  :host {
7
- --suggestion-widget-header-font-size: var(--coras-font-size-2xl);
7
+ --suggestion-widget-header-font-size: var(--coras-font-size-heading);
8
8
  --suggestion-widget-header-font-weight: var(--coras-font-weight-semibold);
9
9
  --suggestion-widget-header-line-height: var(--coras-font-size-3xl);
10
10
  --suggestion-widget-header-color: var(--coras-color-text);
package/package.json CHANGED
@@ -11,13 +11,16 @@
11
11
  "./dist/components/**",
12
12
  "./dist/containers/**",
13
13
  "./dist/contexts/**",
14
- "./dist/views/**"
14
+ "./dist/views/**",
15
+ "./src/components/**",
16
+ "./src/containers/**",
17
+ "./src/contexts/**",
18
+ "./src/views/**"
15
19
  ],
16
20
  "engines": {
17
- "node": ">=20"
21
+ "node": ">=22"
18
22
  },
19
- "customElements": "dist/custom-elements.json",
20
- "version": "0.2.0",
23
+ "version": "0.4.0",
21
24
  "private": false,
22
25
  "homepage": "https://embed.coras.io",
23
26
  "bugs": {
@@ -35,6 +38,7 @@
35
38
  ],
36
39
  "files": [
37
40
  "dist",
41
+ "!dist/custom-elements.json",
38
42
  "NOTICE",
39
43
  "CHANGELOG.md"
40
44
  ],
@@ -47,19 +51,10 @@
47
51
  "types": "./dist/sdk/url.d.ts",
48
52
  "import": "./dist/sdk/url.js"
49
53
  },
50
- "./custom-elements.json": "./dist/custom-elements.json",
51
- "./types": {
52
- "types": "./dist/core/types/index.d.ts"
53
- },
54
54
  "./helpers": {
55
55
  "types": "./dist/helpers/helpers.d.ts",
56
56
  "import": "./dist/helpers/helpers.js"
57
57
  },
58
- "./tokens.css": "./dist/styles/tokens.css",
59
- "./contrast": {
60
- "types": "./dist/styles/contrast.d.ts",
61
- "import": "./dist/styles/contrast.js"
62
- },
63
58
  "./errors": {
64
59
  "types": "./dist/errors.d.ts",
65
60
  "import": "./dist/errors.js"
@@ -70,72 +65,64 @@
70
65
  "access": "public"
71
66
  },
72
67
  "devDependencies": {
73
- "@custom-elements-manifest/analyzer": "0.10.4",
74
- "@eslint/js": "9.21.0",
75
- "@lit/localize-tools": "0.8.0",
76
- "@ljcl/storybook-addon-cssprops": "4.0.0",
77
- "@playwright/test": "1.55.1",
78
- "@seatsio/seatsio-types": "5.5.0",
79
- "@storybook/addon-a11y": "8.6.18",
80
- "@storybook/addon-actions": "8.6.18",
81
- "@storybook/addon-coverage": "1.0.5",
82
- "@storybook/addon-essentials": "8.6.18",
83
- "@storybook/addon-interactions": "8.6.18",
84
- "@storybook/addon-links": "8.6.18",
85
- "@storybook/blocks": "8.6.18",
86
- "@storybook/preview-api": "8.6.18",
87
- "@storybook/test": "8.6.18",
88
- "@storybook/test-runner": "0.20.1",
89
- "@storybook/web-components": "8.6.18",
90
- "@storybook/web-components-vite": "8.6.18",
91
- "@tsconfig/node24": "24.0.4",
92
- "@types/eslint__js": "8.42.3",
93
- "@types/node": "24.12.0",
94
- "@typescript-eslint/eslint-plugin": "8.43.0",
95
- "@vitest/browser": "3.2.6",
96
- "copyfiles": "2.4.1",
97
- "eslint": "9.21.0",
98
- "eslint-config-prettier": "9.1.0",
99
- "eslint-plugin-lit": "1.15.0",
100
- "eslint-plugin-prettier": "5.2.3",
101
- "eslint-plugin-storybook": "0.11.6",
102
- "eslint-plugin-wc": "2.2.1",
103
- "globals": "15.15.0",
104
- "globby": "14.1.0",
105
- "happy-dom": "20.9.0",
106
- "lorem-ipsum": "2.0.8",
107
- "openapi-typescript": "7.6.1",
108
- "openapi-typescript-helpers": "0.0.15",
109
- "playwright": "1.60.0",
68
+ "@custom-elements-manifest/analyzer": "0.11.0",
69
+ "@eslint/js": "10.0.1",
70
+ "@lit/localize-tools": "0.8.2",
71
+ "@ljcl/storybook-addon-cssprops": "6.1.0",
72
+ "@seatsio/seatsio-types": "6.19.0",
73
+ "@storybook/addon-a11y": "10.5.10",
74
+ "@storybook/addon-designs": "11.1.4",
75
+ "@storybook/addon-docs": "10.5.10",
76
+ "@storybook/addon-links": "10.5.10",
77
+ "@storybook/addon-vitest": "10.5.10",
78
+ "@storybook/web-components": "10.5.10",
79
+ "@storybook/web-components-vite": "10.5.10",
80
+ "@tsconfig/node24": "24.0.5",
81
+ "@types/node": "24.13.3",
82
+ "@typescript-eslint/eslint-plugin": "8.67.0",
83
+ "@vitest/browser": "4.1.11",
84
+ "@vitest/browser-playwright": "4.1.11",
85
+ "@vitest/coverage-v8": "4.1.11",
86
+ "eslint": "10.9.0",
87
+ "eslint-config-prettier": "10.1.8",
88
+ "eslint-plugin-lit": "2.3.1",
89
+ "eslint-plugin-prettier": "5.5.6",
90
+ "eslint-plugin-storybook": "10.5.10",
91
+ "eslint-plugin-wc": "3.1.0",
92
+ "globals": "17.11.0",
93
+ "happy-dom": "20.11.6",
94
+ "lorem-ipsum": "3.0.0",
95
+ "openapi-typescript": "7.13.0",
96
+ "openapi-typescript-helpers": "0.1.0",
97
+ "playwright": "1.62.1",
110
98
  "prettier": "3.5.3",
111
- "rimraf": "6.0.1",
112
- "sirv": "3.0.1",
113
- "storybook": "8.6.18",
99
+ "rimraf": "6.1.3",
100
+ "sirv": "3.0.2",
101
+ "storybook": "10.5.10",
114
102
  "ts-lit-plugin": "2.0.2",
115
103
  "typescript": "6.0.3",
116
- "typescript-eslint": "8.43.0",
117
- "vite": "7.3.6",
118
- "vite-plugin-istanbul": "6.0.2",
119
- "vitest": "3.2.6",
120
- "@coras-io/static": "0.0.2"
104
+ "typescript-eslint": "8.67.0",
105
+ "vite": "8.2.2",
106
+ "vitest": "4.1.11",
107
+ "@coras-io/static": "0.0.4"
121
108
  },
122
109
  "dependencies": {
123
- "@coinbase/cdp-core": "0.0.110",
124
- "@floating-ui/dom": "1.6.13",
125
- "@lit-labs/signals": "^0.1.2",
126
- "@lit-labs/virtualizer": "^2.1.0",
127
- "@lit/context": "^1.1.4",
110
+ "@coinbase/cdp-core": "0.0.122",
111
+ "@floating-ui/dom": "1.8.0",
112
+ "@lit-labs/signals": "^0.3.0",
113
+ "@lit-labs/virtualizer": "^2.1.1",
114
+ "@lit/context": "^1.1.6",
128
115
  "@lit/localize": "^0.12.2",
129
- "@lit/task": "^1.0.2",
130
- "@stripe/stripe-js": "5.6.0",
131
- "date-fns": "4.1.0",
116
+ "@lit/task": "^1.0.3",
117
+ "@stripe/stripe-js": "9.14.0",
118
+ "date-fns": "4.4.0",
132
119
  "date-fns-tz": "3.2.0",
133
- "dompurify": "3.4.11",
134
- "libphonenumber-js": "1.12.36",
135
- "lit": "^3.2.1",
136
- "openapi-fetch": "0.13.5",
137
- "viem": "2.52.2",
138
- "@coras-io/brand-tokens": "^0.2.0"
120
+ "dompurify": "3.4.14",
121
+ "libphonenumber-js": "1.13.11",
122
+ "lit": "^3.3.3",
123
+ "openapi-fetch": "0.17.0",
124
+ "viem": "2.55.19",
125
+ "@coras-io/brand-tokens": "^0.4.0"
139
126
  },
140
127
  "scripts": {
141
128
  "lint": "eslint \"src/**/*.ts*\"",
@@ -147,7 +134,7 @@
147
134
  "prebuild": "rimraf dist node_modules/.cache/embed.tsbuildinfo && pnpm run generate:tokens",
148
135
  "build": "tsc -p tsconfig.build.json",
149
136
  "build:watch": "tsc --build --watch",
150
- "postbuild": "copyfiles -u 1 \"src/styles/tokens.css\" dist && pnpm run generate-manifest",
137
+ "postbuild": "pnpm run generate-manifest",
151
138
  "generate-api-schema": "openapi-typescript openapi.schema.json -o ./src/core/types/api-schema.d.ts && eslint --fix src/core/types/api-schema.d.ts && prettier --write src/core/types/api-schema.d.ts",
152
139
  "test": "vitest",
153
140
  "test:sdk": "vitest run --config vitest.sdk.config.ts",
@@ -156,11 +143,11 @@
156
143
  "check:styles": "node scripts/check-styles.mjs",
157
144
  "measure:bundle": "node scripts/measure-bundle.mjs",
158
145
  "localize:extract": "lit-localize extract",
159
- "localize:build": "lit-localize build",
146
+ "localize:build": "lit-localize build && node scripts/decode-locale-entities.mjs",
160
147
  "storybook": "storybook dev --no-open -p 8082",
161
148
  "storybook:build": "storybook build --output-dir dist-storybook",
162
- "storybook:test": "test-storybook -u --browsers chromium,firefox,webkit --url http://localhost:3003",
163
- "storybook:test:coverage": "test-storybook --coverage --url http://localhost:3003",
149
+ "storybook:test": "vitest run --config vitest.storybook.config.ts",
150
+ "storybook:test:coverage": "vitest run --config vitest.storybook.config.ts --coverage",
164
151
  "storybook:serve-build": "storybook build --output-dir dist-storybook && npx http-server dist-storybook"
165
152
  }
166
153
  }