@riverbankcms/sdk 0.135.0 → 0.136.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 (153) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +4 -8
  3. package/dist/{PreviewEditorSidebar-roNY0GVy.mjs → PreviewEditorSidebar-BU5ZlhQR.mjs} +4 -4
  4. package/dist/{PreviewEditorUI-KboDbEh_.mjs → PreviewEditorUI-9XkHL-bC.mjs} +3 -3
  5. package/dist/{PreviewQueryProvider-DcgaESkm.mjs → PreviewQueryProvider-wbEpXryy.mjs} +1 -1
  6. package/dist/{SdkPreviewModeRuntime-DBrF7Caa.mjs → SdkPreviewModeRuntime-CnWmj-2B.mjs} +50 -99
  7. package/dist/{SiteChromeCustomizeContext-DrIEpJKn.mjs → SiteChromeCustomizeContext-B6d5zkog.mjs} +2334 -1173
  8. package/dist/_dts/ai/src/contracts/proposals.d.ts +8 -554
  9. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +401 -2312
  10. package/dist/_dts/api/src/contentRuntime.d.ts +6 -0
  11. package/dist/_dts/api/src/endpoints.d.ts +7 -0
  12. package/dist/_dts/api/src/index.d.ts +1 -0
  13. package/dist/_dts/api/src/publicEventEndpointDefinitions.d.ts +7 -0
  14. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +26 -0
  15. package/dist/_dts/api/src/sdkBlockContentAdmission.d.ts +5 -0
  16. package/dist/_dts/api/src/sdkThemeWire.d.ts +6 -432
  17. package/dist/_dts/block-form/src/blockDraftSaveability.d.ts +2 -3
  18. package/dist/_dts/block-form/src/utils/slug.d.ts +6 -0
  19. package/dist/_dts/blocks/src/PageRenderer.d.ts +12 -6
  20. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +48 -0
  21. package/dist/_dts/blocks/src/definitions.d.ts +14 -0
  22. package/dist/_dts/blocks/src/index.d.ts +4 -3
  23. package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +40 -0
  24. package/dist/_dts/blocks/src/server.d.ts +2 -2
  25. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +25 -0
  26. package/dist/_dts/blocks/src/system/data/index.d.ts +2 -0
  27. package/dist/_dts/blocks/src/system/data/publicLoaderCachePolicy.d.ts +78 -0
  28. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +2 -18
  29. package/dist/_dts/blocks/src/system/manifest/validation.d.ts +103 -16
  30. package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +1 -1
  31. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +2 -1
  32. package/dist/_dts/blocks/src/system/runtime/api/endpoints.d.ts +8 -0
  33. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  34. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +19 -0
  35. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +52 -0
  36. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +24 -0
  37. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.d.ts +44 -18
  38. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.state.d.ts +20 -3
  39. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/VerifyingTimeoutStep.d.ts +3 -1
  40. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.d.ts +1 -0
  41. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCalendar.client.d.ts +2 -2
  42. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCalendar.interactive.d.ts +40 -0
  43. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +2 -0
  44. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +43 -0
  45. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarDayCell.d.ts +3 -1
  46. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarNavigationChevron.d.ts +4 -0
  47. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/DayEventsModal.d.ts +2 -1
  48. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventModalContext.d.ts +3 -2
  49. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekAgendaView.d.ts +3 -0
  50. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekBoardView.d.ts +31 -3
  51. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekTimetableView.d.ts +3 -1
  52. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +19 -1
  53. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/timetableModel.d.ts +4 -3
  54. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/utils.d.ts +3 -3
  55. package/dist/_dts/blocks/src/system/transforms/registry/layout.d.ts +0 -1
  56. package/dist/_dts/calendar/src/grid.d.ts +24 -66
  57. package/dist/_dts/calendar/src/index.d.ts +2 -2
  58. package/dist/_dts/calendar/src/timetable.d.ts +5 -9
  59. package/dist/_dts/commerce/src/purchase/allocation.d.ts +11 -0
  60. package/dist/_dts/commerce/src/purchase/index.d.ts +2 -0
  61. package/dist/_dts/commerce/src/purchase/settlement.d.ts +33 -0
  62. package/dist/_dts/commerce/src/purchase/stripeCheckoutReturnUrl.d.ts +8 -0
  63. package/dist/_dts/content-model/src/templates/defaults.d.ts +6 -0
  64. package/dist/_dts/core/src/slug.d.ts +20 -5
  65. package/dist/_dts/preview-next/src/client/blocks/EditablePageRenderer.d.ts +1 -1
  66. package/dist/_dts/preview-next/src/client/preview/headerInteractionPaletteSurfaceState.d.ts +2 -1
  67. package/dist/_dts/sdk/src/client/publicLoaderCacheAccess.d.ts +6 -0
  68. package/dist/_dts/sdk/src/public-api/contracts.d.ts +5 -1
  69. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +10 -6
  70. package/dist/_dts/sdk/src/rendering/components/Block.shared.d.ts +0 -1
  71. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +4 -4
  72. package/dist/_dts/sdk/src/rendering/helpers/footerPageOutline.d.ts +3 -0
  73. package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +3 -0
  74. package/dist/_dts/sdk/src/rendering/helpers/loadPage.d.ts +1 -1
  75. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +17 -0
  76. package/dist/_dts/sdk/src/rendering/helpers/templateContent.d.ts +9 -3
  77. package/dist/_dts/sdk/src/rendering/hooks/usePage.d.ts +1 -1
  78. package/dist/_dts/sdk/src/rendering/index.d.ts +2 -2
  79. package/dist/_dts/sdk/src/rendering/overrideResolution.d.ts +7 -4
  80. package/dist/_dts/sdk/src/version.d.ts +1 -1
  81. package/dist/_dts/theme-core/src/cards/types.d.ts +8 -8
  82. package/dist/_dts/theme-core/src/data.d.ts +12 -0
  83. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  84. package/dist/_dts/theme-core/src/header/legacyHeaderVariant.d.ts +2 -6
  85. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +6 -807
  86. package/dist/_dts/theme-core/src/schema.d.ts +452 -1278
  87. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +213 -1
  88. package/dist/_dts/theme-core/src/site-styles/headerLayoutCatalog.d.ts +0 -29
  89. package/dist/_dts/theme-core/src/site-styles/headerLayoutStyles.d.ts +10 -0
  90. package/dist/_dts/theme-core/src/site-styles/headerLayoutTypes.d.ts +8 -5
  91. package/dist/_dts/theme-core/src/site-styles/headerOpeningForeground.d.ts +4 -4
  92. package/dist/_dts/theme-core/src/site-styles/headerStyleCompiler.d.ts +16 -2
  93. package/dist/_dts/theme-core/src/site-styles/headerStyleDefaults.d.ts +465 -0
  94. package/dist/_dts/theme-core/src/site-styles/headerStyleRecipe.d.ts +161 -0
  95. package/dist/client/{BookingConsentAgreement-BQqwi8Oa.mjs → BookingConsentAgreement-DCch21a6.mjs} +2 -2
  96. package/dist/client/{DiscountCodeDisclosure-B97aMo0V.mjs → DiscountCodeDisclosure-DIj1T59K.mjs} +1 -1
  97. package/dist/client/{EventCombined.client-Bs2Iw9Q6.mjs → EventCombined.client-BWVNlXTx.mjs} +226 -206
  98. package/dist/client/{EventListing.client-C4QUQdmg.mjs → EventListing.client-DVFCDe3i.mjs} +2 -2
  99. package/dist/client/{LeafletStaticMap-CwWRk69M.mjs → LeafletStaticMap-BY5mIHw9.mjs} +1 -1
  100. package/dist/client/{accordion-BA0j8Mpw.mjs → accordion-CK29E8rG.mjs} +1 -1
  101. package/dist/client/{bookingForm-Br2e41H0.mjs → bookingForm-DFvnet-N.mjs} +5 -5
  102. package/dist/client/bookings.mjs +87 -47
  103. package/dist/client/{carousel-B4dmwnpD.mjs → carousel-BVU5NQlb.mjs} +1 -1
  104. package/dist/client/{cart-B_ckGW4b.mjs → cart-BNItcZVa.mjs} +3 -3
  105. package/dist/client/{checkout-DAyspHdf.mjs → checkout-Bu6iCdkP.mjs} +3 -3
  106. package/dist/client/client.mjs +1985 -1055
  107. package/dist/client/{context-DljQn8L5.mjs → context-BImarOAq.mjs} +12 -0
  108. package/dist/client/{eventCalendar-pJu3FUod.mjs → eventCalendar-DS2h-UXD.mjs} +256 -114
  109. package/dist/client/{eventCombined-B6Kacm9F.mjs → eventCombined-Drt4Oq9p.mjs} +3 -3
  110. package/dist/client/{eventDetails-CaX9z1pv.mjs → eventDetails-Bl2vWgTX.mjs} +4 -3
  111. package/dist/client/{eventListing-B9aXPO-I.mjs → eventListing-CS7PHY7v.mjs} +3 -3
  112. package/dist/client/{eventRegistration-CBSovBkg.mjs → eventRegistration-D-j8eNy2.mjs} +85 -41
  113. package/dist/client/{form-Cm0tu_7o.mjs → form-RMpoLTyr.mjs} +2 -2
  114. package/dist/client/{headerSection-OgRtHeKS.mjs → headerSection-BYE3Lb3k.mjs} +2 -2
  115. package/dist/client/hooks.mjs +2254 -298
  116. package/dist/client/{locationMap-DmjcYqNM.mjs → locationMap-BxSr7Kkh.mjs} +2 -2
  117. package/dist/client/{newsletterForm-D08OZQAC.mjs → newsletterForm-DerbXwFC.mjs} +2 -2
  118. package/dist/client/{productDetail-BqZeu2P4.mjs → productDetail-4SZCLhAf.mjs} +3 -3
  119. package/dist/client/{productList-mNyIF9FG.mjs → productList-D7AP4GNq.mjs} +3 -3
  120. package/dist/client/{propsDecoder-DwHXRm9X.mjs → propsDecoder-pzBeCh14.mjs} +123 -46
  121. package/dist/client/rendering/client.mjs +793 -488
  122. package/dist/client/rendering/islands.mjs +17 -17
  123. package/dist/client/rendering.mjs +2161 -1268
  124. package/dist/client/{scrollToBlock-DtmdM3v-.mjs → scrollToBlock-CduAKf8T.mjs} +1 -1
  125. package/dist/client/{shop-CNjZK16F.mjs → shop-Cp5p_kGe.mjs} +6 -6
  126. package/dist/client/{shop-commerce-DkNNao1J.mjs → shop-commerce-DicXYaYX.mjs} +5 -5
  127. package/dist/client/{shop-commerce-store-9WA--zuW.mjs → shop-commerce-store-CGWnpY4K.mjs} +1 -1
  128. package/dist/client/{shopShared-CHCVfccY.mjs → shopShared-BDf9ljkm.mjs} +3 -3
  129. package/dist/client/{useEventFilters-DvuaB4ZN.mjs → useEventFilters-DeeyGYuk.mjs} +3 -3
  130. package/dist/preview-next/before-render.mjs +7 -0
  131. package/dist/preview-next/client/runtime.mjs +4 -4
  132. package/dist/preview-next/keepAlive.mjs +7 -0
  133. package/dist/preview-next/middleware.mjs +7 -0
  134. package/dist/{previewAuthStore-C7ksxt5b.mjs → previewAuthStore-DbqBol0V.mjs} +7 -0
  135. package/dist/{sdk-runtime-3GhW4knb.mjs → sdk-runtime-19MO27F0.mjs} +2 -2
  136. package/dist/{separator-D3bCWYYb.mjs → separator-DaPLtJ1f.mjs} +1 -1
  137. package/dist/server/components.mjs +1562 -917
  138. package/dist/server/config-validation.mjs +94 -135
  139. package/dist/server/config.mjs +94 -135
  140. package/dist/server/data.mjs +94 -134
  141. package/dist/server/index.mjs +122 -4
  142. package/dist/server/manifest.mjs +0 -1
  143. package/dist/server/next.mjs +1467 -732
  144. package/dist/server/page-converter.mjs +87 -113
  145. package/dist/server/prebuild.mjs +1 -1
  146. package/dist/server/rendering/server.mjs +1717 -939
  147. package/dist/server/rendering.mjs +1729 -1044
  148. package/dist/server/routing.mjs +3229 -1835
  149. package/dist/server/server.mjs +21739 -19801
  150. package/dist/server/theme-bridge.mjs +656 -264
  151. package/dist/server/theme.mjs +2 -17
  152. package/dist/styles/index.css +609 -181
  153. package/package.json +1 -1
@@ -211,6 +211,10 @@ var init_endpoints = __esmMin((() => {
211
211
  registrationStatus: {
212
212
  path: "/public/sites/{siteId}/events/registration-status",
213
213
  method: "GET"
214
+ },
215
+ checkoutReturn: {
216
+ path: "/public/sites/{siteId}/events/checkout-return",
217
+ method: "POST"
214
218
  }
215
219
  };
216
220
  WHOLE_SERIES = {
@@ -792,6 +796,14 @@ function createBlockApi(config) {
792
796
  skipDedup: true
793
797
  });
794
798
  },
799
+ async resolveEventCheckoutReturn(data) {
800
+ const sid = requireSiteId();
801
+ const path = buildPath(EVENTS.checkoutReturn.path, { siteId: sid });
802
+ return request(EVENTS.checkoutReturn, {
803
+ path,
804
+ body: data
805
+ });
806
+ },
795
807
  async resolveWaitlistClaim(data) {
796
808
  const sid = requireSiteId();
797
809
  const path = buildPath(WHOLE_SERIES.waitlistClaimResolve.path, { siteId: sid });
@@ -3732,7 +3744,7 @@ var init_boxBackgroundSchema = __esmMin((() => {
3732
3744
  showVideoOnMobile: z.boolean().nullable().optional()
3733
3745
  })
3734
3746
  ]);
3735
- })), axesSchema, typographyStyleSchema, bodyTypographyStyleSchema, headingSizeSchema, headingTypographyOverridesSchema, headingTypographyStyleSchema, proseLinkUnderlineStyleSchema, proseLinkUnderlineThicknessSchema, proseLinkUnderlineOffsetSchema, proseLinkStyleSchema, semanticSpacingSchema, boxRoundedSchema, noHeadingDecorationSchema, visibleHeadingDecorationSchema, headingDecorationSchema, headingDecorationOverrideSchema, accordionIconTreatmentSchema, sectionStylesOverrideSchema, containerStylesOverrideSchema, cardBorderOverrideSchema, cardStylesOverrideSchema, blockStyleOverridesSchema, blockThemeOverrideSchema, typographyScaleSchema, eyebrowTypographyStyleSchema, typographySchema, spaceSchema, corners, shadow, border, motion, inputStyle$1, headerPositioning, headerNavStyle, navFontWeight, headerMaxWidth, headerBarFrame, headerBorderSchema, logoStyleSchema, headerLogoTextSchema, navEffectsSchema, dropdownStyleSchema, headerCtaGapSchema, headerCtaTreatmentSchema, navContainerSchema, headerBackgroundSchema, headerSchema, footerVariant, footerMaxWidth, footerMode, footerNavLayoutMode, footerNavLayoutAlign, footerSpacing, footerLogoPlacement, footerLogoSize, footerLogoMaxHeight, footerBottomTextLinkStyleSchema, footerBottomBarSchema, footerNavLayoutSchema, footerLogoSchema, footerSchema, containerPaddingPresetSchema, layoutSchema, heroTypographySizeSchema, heroTypographyLineHeightSchema, heroResponsiveTypographySchema, heroTypographySchema, heroSchema, bodyTextIntroTypographySizeSchema, bodyTextSchema, gradientsSchema, testimonialQuoteTreatmentSchema, themeSchema;
3747
+ })), axesSchema, typographyStyleSchema, bodyTypographyStyleSchema, headingSizeSchema, headingTypographyOverridesSchema, headingTypographyStyleSchema, proseLinkUnderlineStyleSchema, proseLinkUnderlineThicknessSchema, proseLinkUnderlineOffsetSchema, proseLinkStyleSchema, semanticSpacingSchema, boxRoundedSchema, noHeadingDecorationSchema, visibleHeadingDecorationSchema, headingDecorationSchema, headingDecorationOverrideSchema, accordionIconTreatmentSchema, sectionStylesOverrideSchema, containerStylesOverrideSchema, cardBorderOverrideSchema, cardStylesOverrideSchema, blockStyleOverridesSchema, blockThemeOverrideSchema, typographyScaleSchema, eyebrowTypographyStyleSchema, typographySchema, spaceSchema, corners, shadow, border, motion, inputStyle$1, headerPositioning, headerNavStyle, navFontWeight, headerMaxWidth, headerBorderSchema, logoStyleSchema, headerLogoTextSchema, dropdownStyleSchema, headerCtaGapSchema, headerCtaTreatmentSchema, navContainerSchema, headerBackgroundSchema, headerSchema, footerVariant, footerMaxWidth, footerMode, footerNavLayoutMode, footerNavLayoutAlign, footerSpacing, footerLogoPlacement, footerLogoSize, footerLogoMaxHeight, footerBottomTextLinkStyleSchema, footerBottomBarSchema, footerNavLayoutSchema, footerLogoSchema, footerSchema, containerPaddingPresetSchema, layoutSchema, heroTypographySizeSchema, heroTypographyLineHeightSchema, heroResponsiveTypographySchema, heroTypographySchema, heroSchema, bodyTextIntroTypographySizeSchema, bodyTextSchema, gradientsSchema, testimonialQuoteTreatmentSchema, themeSchema;
3736
3748
  var init_schema$2 = __esmMin((() => {
3737
3749
  init_media$2();
3738
3750
  init_schema$3();
@@ -4086,7 +4098,6 @@ var init_schema$2 = __esmMin((() => {
4086
4098
  "bold"
4087
4099
  ]);
4088
4100
  headerMaxWidth = z.enum(["container", "full"]);
4089
- headerBarFrame = z.enum(["full-bleed", "inset-shell"]);
4090
4101
  headerBorderSchema = componentBorderSchema.extend({ position: z.enum([
4091
4102
  "bottom",
4092
4103
  "top",
@@ -4115,12 +4126,6 @@ var init_schema$2 = __esmMin((() => {
4115
4126
  ]).optional(),
4116
4127
  hideOnShrink: z.boolean().optional()
4117
4128
  }).optional();
4118
- navEffectsSchema = z.object({
4119
- underlineGradient: z.boolean().default(false),
4120
- glow: z.boolean().default(false),
4121
- glowColor: z.string().optional(),
4122
- neumorphic: z.boolean().default(false)
4123
- }).optional();
4124
4129
  dropdownStyleSchema = z.object({
4125
4130
  background: themeColorTokenSchema.default("surface"),
4126
4131
  textColor: themeColorTokenSchema.default("text"),
@@ -4208,9 +4213,7 @@ var init_schema$2 = __esmMin((() => {
4208
4213
  positioning: headerPositioning,
4209
4214
  shrinkOnScroll: z.boolean(),
4210
4215
  maxWidth: headerMaxWidth,
4211
- barFrame: headerBarFrame.optional(),
4212
4216
  scrollTreatment: headerScrollTreatmentSchema,
4213
- logoOverride: mediaSchema.nullable().optional(),
4214
4217
  background: headerBackgroundSchema.default({
4215
4218
  type: "color",
4216
4219
  color: "surface"
@@ -4222,13 +4225,11 @@ var init_schema$2 = __esmMin((() => {
4222
4225
  navFontRole: z.enum(["body", "heading"]).optional(),
4223
4226
  navTextSize: navLinkStyleSchema.shape.textSize,
4224
4227
  interactionPalette: headerInteractionPaletteSchema.optional(),
4225
- navPlacement: z.enum(["end", "center"]).optional(),
4226
4228
  container: headerContainerSchema,
4227
4229
  border: headerBorderSchema,
4228
4230
  shadow: componentShadowSchema.optional(),
4229
4231
  logo: logoStyleSchema,
4230
4232
  logoText: headerLogoTextSchema,
4231
- navEffects: navEffectsSchema,
4232
4233
  navContainer: navContainerSchema,
4233
4234
  navLinkStyle: navLinkStyleSchema.optional(),
4234
4235
  ctaGap: headerCtaGapSchema.optional(),
@@ -7248,6 +7249,9 @@ function formatBookingDateParts(input, options) {
7248
7249
  function getBookingLocalDateKey(input) {
7249
7250
  return formatDateKey$1(getLocalScheduleDate(new Date(input.startsAt), input.timeZone));
7250
7251
  }
7252
+ function compareLocalScheduleDates(left, right) {
7253
+ return Date.UTC(left.year, left.month - 1, left.day) - Date.UTC(right.year, right.month - 1, right.day);
7254
+ }
7251
7255
  function parseBookingLocalDate(value) {
7252
7256
  const match = LOCAL_DATE_PATTERN.exec(value.trim());
7253
7257
  if (match === null || match.groups === void 0) throw new Error(`Invalid booking date format: "${value}" (expected YYYY-MM-DD)`);
@@ -7262,6 +7266,53 @@ function parseBookingLocalDate(value) {
7262
7266
  day
7263
7267
  };
7264
7268
  }
7269
+ function parseBookingUtcDateWindow(input) {
7270
+ const timeZone = resolveBookingTimeZoneId(input.timeZone);
7271
+ let startLocalDate;
7272
+ try {
7273
+ startLocalDate = parseBookingLocalDate(input.startDate);
7274
+ } catch {
7275
+ return {
7276
+ ok: false,
7277
+ field: "startDate",
7278
+ reason: "invalid_date_format",
7279
+ value: input.startDate
7280
+ };
7281
+ }
7282
+ let endLocalDate;
7283
+ try {
7284
+ endLocalDate = parseBookingLocalDate(input.endDate);
7285
+ } catch {
7286
+ return {
7287
+ ok: false,
7288
+ field: "endDate",
7289
+ reason: "invalid_date_format",
7290
+ value: input.endDate
7291
+ };
7292
+ }
7293
+ if (compareLocalScheduleDates(startLocalDate, endLocalDate) > 0) return {
7294
+ ok: false,
7295
+ field: "endDate",
7296
+ reason: "invalid_date_range",
7297
+ value: input.endDate
7298
+ };
7299
+ return {
7300
+ ok: true,
7301
+ value: {
7302
+ timeZone,
7303
+ startLocalDate,
7304
+ endLocalDate,
7305
+ startAt: localScheduleDateTimeToUtcDate(startLocalDate, START_OF_DAY, timeZone),
7306
+ endExclusive: localScheduleDateTimeToUtcDate(addLocalScheduleDays(endLocalDate, 1), START_OF_DAY, timeZone)
7307
+ }
7308
+ };
7309
+ }
7310
+ function buildBookingUtcDateWindow(input) {
7311
+ const result = parseBookingUtcDateWindow(input);
7312
+ if (result.ok) return result.value;
7313
+ if (result.reason === "invalid_date_range") throw new Error(`Invalid booking date range: startDate "${input.startDate}" must be on or before endDate "${input.endDate}"`);
7314
+ throw new Error(`Invalid booking date format: "${result.value}" (expected YYYY-MM-DD)`);
7315
+ }
7265
7316
  function getLocalScheduleDate(date, timeZone) {
7266
7317
  const parts = getZonedDateTimeParts(date, getSafeTimeZone(timeZone));
7267
7318
  return {
@@ -7281,7 +7332,23 @@ function addLocalScheduleDays(date, days) {
7281
7332
  day: utcDate.getUTCDate()
7282
7333
  };
7283
7334
  }
7284
- var DEFAULT_LOCALE, FALLBACK_TIMEZONE, DEFAULT_BOOKING_DATE_TIME_FORMAT, LOCAL_DATE_PATTERN, DATE_TIME_FORMATTER_CACHE_LIMIT, dateTimeFormatterCache;
7335
+ function localScheduleDateTimeToUtcDate(localDate, localTime, timeZone) {
7336
+ const resolvedTimeZone = getSafeTimeZone(timeZone);
7337
+ const targetLocalMs = Date.UTC(localDate.year, localDate.month - 1, localDate.day, localTime.hour, localTime.minute, localTime.second, 0);
7338
+ let guess = targetLocalMs;
7339
+ const seenGuesses = /* @__PURE__ */ new Set();
7340
+ for (let iteration = 0; iteration < 4; iteration += 1) {
7341
+ seenGuesses.add(guess);
7342
+ const actual = getZonedDateTimeParts(new Date(guess), resolvedTimeZone);
7343
+ const diff = Date.UTC(actual.year, actual.month - 1, actual.day, actual.hour, actual.minute, actual.second, 0) - targetLocalMs;
7344
+ if (diff === 0) return new Date(guess);
7345
+ const nextGuess = guess - diff;
7346
+ if (seenGuesses.has(nextGuess)) return new Date(Math.max(guess, nextGuess));
7347
+ guess = nextGuess;
7348
+ }
7349
+ return new Date(guess);
7350
+ }
7351
+ var DEFAULT_LOCALE, FALLBACK_TIMEZONE, DEFAULT_BOOKING_DATE_TIME_FORMAT, START_OF_DAY, LOCAL_DATE_PATTERN, DATE_TIME_FORMATTER_CACHE_LIMIT, dateTimeFormatterCache;
7285
7352
  var init_booking_date_time = __esmMin((() => {
7286
7353
  init_result$1();
7287
7354
  init_booking_time_zone();
@@ -7294,6 +7361,11 @@ var init_booking_date_time = __esmMin((() => {
7294
7361
  hour: "numeric",
7295
7362
  minute: "2-digit"
7296
7363
  };
7364
+ START_OF_DAY = {
7365
+ hour: 0,
7366
+ minute: 0,
7367
+ second: 0
7368
+ };
7297
7369
  LOCAL_DATE_PATTERN = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/u;
7298
7370
  DATE_TIME_FORMATTER_CACHE_LIMIT = 100;
7299
7371
  dateTimeFormatterCache = /* @__PURE__ */ new Map();
@@ -7441,8 +7513,7 @@ var init_csv_render = __esmMin((() => {
7441
7513
  init_csv_escape();
7442
7514
  init_csv_filename();
7443
7515
  }));
7444
- var init_csv_types = __esmMin((() => {}));
7445
- var init_email_format = __esmMin((() => {}));
7516
+ var init_csv_types = __esmMin((() => {})), init_email_format = __esmMin((() => {}));
7446
7517
  var init_slug = __esmMin((() => {}));
7447
7518
  var init_uuid = __esmMin((() => {}));
7448
7519
  function sortStableJsonValue(value) {
@@ -14179,7 +14250,8 @@ function isOrdinaryEvent(event) {
14179
14250
  function deriveWholeSeriesPhase(sessions, nowIso) {
14180
14251
  const now = Date.parse(nowIso);
14181
14252
  if (now < Date.parse(sessions[0].startsAt)) return "upcoming";
14182
- return now <= Date.parse(sessions.at(-1)?.endsAt ?? sessions[0].endsAt) ? "inProgress" : "completed";
14253
+ const finalSession = sessions[sessions.length - 1] ?? sessions[0];
14254
+ return now <= Date.parse(finalSession.endsAt) ? "inProgress" : "completed";
14183
14255
  }
14184
14256
  function selectRelatedDates(input) {
14185
14257
  if (!input.seriesId) return [];
@@ -14749,111 +14821,73 @@ var init_pricing = __esmMin((() => {
14749
14821
  }));
14750
14822
  //#endregion
14751
14823
  //#region ../calendar/src/grid.ts
14752
- /** Format a date as YYYY-MM-DD using the runtime's local timezone. */
14753
14824
  function formatDateKey(date) {
14754
- return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
14825
+ return `${String(date.year).padStart(4, "0")}-${String(date.month).padStart(2, "0")}-${String(date.day).padStart(2, "0")}`;
14755
14826
  }
14756
- /**
14757
- * True when `date` and `now` are the same local calendar day.
14758
- * `now` defaults to `new Date()` so casual callers don't need to thread it,
14759
- * but tests and snapshot-rendering should pass an explicit value.
14760
- */
14761
- function isToday(date, now = /* @__PURE__ */ new Date()) {
14762
- return isSameLocalDay(date, now);
14827
+ function isToday(date, today) {
14828
+ return isSameCalendarDay(date, today);
14763
14829
  }
14764
- /** True when two dates fall on the same local calendar day. */
14765
- function isSameLocalDay(left, right) {
14766
- return left.getFullYear() === right.getFullYear() && left.getMonth() === right.getMonth() && left.getDate() === right.getDate();
14830
+ function isSameCalendarDay(left, right) {
14831
+ return left.year === right.year && left.month === right.month && left.day === right.day;
14767
14832
  }
14768
- /**
14769
- * Add (or subtract) months to a date, clamping the day-of-month to the
14770
- * target month's last day. Avoids JS Date overflow (Jan 29 + 1 month → Mar 1
14771
- * in non-leap years).
14772
- */
14773
- function addMonths(date, months) {
14774
- const year = date.getFullYear();
14775
- const month = date.getMonth();
14776
- const day = date.getDate();
14777
- const hours = date.getHours();
14778
- const minutes = date.getMinutes();
14779
- const seconds = date.getSeconds();
14780
- const ms = date.getMilliseconds();
14781
- const base = new Date(year, month + months, 1, hours, minutes, seconds, ms);
14782
- const lastDayOfTargetMonth = new Date(base.getFullYear(), base.getMonth() + 1, 0).getDate();
14783
- base.setDate(Math.min(day, lastDayOfTargetMonth));
14784
- return base;
14785
- }
14786
- /** Add (or subtract) days while preserving local time-of-day fields. */
14787
- function addDays(date, days) {
14788
- const result = new Date(date);
14789
- result.setDate(result.getDate() + days);
14790
- return result;
14833
+ function getStartOfMonth(date) {
14834
+ return {
14835
+ year: date.year,
14836
+ month: date.month,
14837
+ day: 1
14838
+ };
14791
14839
  }
14792
- /** Shift a calendar anchor by the natural unit for a viewport kind. */
14793
- function shiftCalendarAnchorDate(date, view, steps) {
14794
- if (view === "week") return addDays(date, steps * 7);
14795
- return addMonths(date, steps);
14840
+ function getEndOfMonth(date) {
14841
+ return addDays(addMonths(getStartOfMonth(date), 1), -1);
14796
14842
  }
14797
- /**
14798
- * Get an inclusive 3-month window around `date`, returned as ISO strings
14799
- * with UTC midnight bounds. Suitable for prefetching event windows when
14800
- * the consumer handles timezone conversion downstream.
14801
- */
14802
- function getThreeMonthRange(date) {
14803
- const year = date.getFullYear();
14804
- const month = date.getMonth();
14805
- const prevStart = new Date(year, month - 1, 1);
14806
- const nextEnd = new Date(year, month + 2, 0);
14843
+ function addMonths(date, months) {
14844
+ const target = new Date(Date.UTC(date.year, date.month - 1 + months, 1, 12));
14845
+ const year = target.getUTCFullYear();
14846
+ const month = target.getUTCMonth() + 1;
14847
+ const lastDay = new Date(Date.UTC(year, month, 0, 12)).getUTCDate();
14807
14848
  return {
14808
- from: `${formatDateKey(prevStart)}T00:00:00Z`,
14809
- to: `${formatDateKey(nextEnd)}T23:59:59Z`
14849
+ year,
14850
+ month,
14851
+ day: Math.min(date.day, lastDay)
14810
14852
  };
14811
14853
  }
14812
- /**
14813
- * Build the calendar days for a month view. Returns 42 dates (6 rows × 7
14814
- * days) including padding from prior/next months for a stable grid.
14815
- */
14854
+ function addDays(date, days) {
14855
+ const result = new Date(Date.UTC(date.year, date.month - 1, date.day + days, 12));
14856
+ return {
14857
+ year: result.getUTCFullYear(),
14858
+ month: result.getUTCMonth() + 1,
14859
+ day: result.getUTCDate()
14860
+ };
14861
+ }
14862
+ function shiftCalendarAnchorDate(date, view, steps) {
14863
+ return view === "week" ? addDays(date, steps * 7) : addMonths(date, steps);
14864
+ }
14816
14865
  function getMonthCalendarDays(year, month, startOfWeek) {
14817
- const firstDayOfMonth = new Date(year, month, 1);
14818
- const lastDayOfMonth = new Date(year, month + 1, 0);
14819
- let startOffset = firstDayOfMonth.getDay();
14820
- if (startOfWeek === "monday") startOffset = startOffset === 0 ? 6 : startOffset - 1;
14821
- const days = [];
14822
- for (let i = startOffset - 1; i >= 0; i--) days.push(new Date(year, month, -i));
14823
- for (let day = 1; day <= lastDayOfMonth.getDate(); day++) days.push(new Date(year, month, day));
14824
- while (days.length < 42) {
14825
- const nextDay = days.length - startOffset - lastDayOfMonth.getDate() + 1;
14826
- days.push(new Date(year, month + 1, nextDay));
14827
- }
14828
- return days;
14866
+ const firstDay = {
14867
+ year,
14868
+ month,
14869
+ day: 1
14870
+ };
14871
+ const dayOfWeek = getDayOfWeek(firstDay);
14872
+ const gridStart = addDays(firstDay, -(startOfWeek === "monday" ? dayOfWeek === 0 ? 6 : dayOfWeek - 1 : dayOfWeek));
14873
+ return Array.from({ length: 42 }, (_, index) => addDays(gridStart, index));
14829
14874
  }
14830
- /** Build the 7 dates of the week containing `baseDate`. */
14831
14875
  function getWeekCalendarDays(baseDate, startOfWeek) {
14832
- const days = [];
14833
- const dayOfWeek = baseDate.getDay();
14834
- const daysToStart = startOfWeek === "monday" ? dayOfWeek === 0 ? 6 : dayOfWeek - 1 : dayOfWeek;
14835
- const weekStart = new Date(baseDate);
14836
- weekStart.setDate(baseDate.getDate() - daysToStart);
14837
- for (let i = 0; i < 7; i++) {
14838
- const date = new Date(weekStart);
14839
- date.setDate(weekStart.getDate() + i);
14840
- days.push(date);
14841
- }
14842
- return days;
14876
+ const dayOfWeek = getDayOfWeek(baseDate);
14877
+ const weekStart = addDays(baseDate, -(startOfWeek === "monday" ? dayOfWeek === 0 ? 6 : dayOfWeek - 1 : dayOfWeek));
14878
+ return Array.from({ length: 7 }, (_, index) => addDays(weekStart, index));
14879
+ }
14880
+ function getDayOfWeek(date) {
14881
+ return new Date(Date.UTC(date.year, date.month - 1, date.day, 12)).getUTCDay();
14843
14882
  }
14844
- /** Build the 7 dates of the week containing `baseDate` as a fixed-width tuple. */
14845
14883
  function getWeekCalendarDayTuple(baseDate, startOfWeek) {
14846
14884
  const days = getWeekCalendarDays(baseDate, startOfWeek);
14847
14885
  assertWeekCalendarDays(days);
14848
14886
  return days;
14849
14887
  }
14850
14888
  function assertWeekCalendarDays(days) {
14851
- if (days.length !== 7) throw new Error("Expected week calendar helper to return exactly 7 days");
14889
+ if (days.length !== 7) throw new Error("Expected exactly 7 calendar days");
14852
14890
  }
14853
- /**
14854
- * Day-name labels reordered for the chosen week start. Pass a custom
14855
- * `dayNames` array (length 7, Sunday-first) to localize.
14856
- */
14857
14891
  function getOrderedDayNames(startOfWeek, dayNames = DAY_NAMES) {
14858
14892
  if (startOfWeek === "monday") {
14859
14893
  const sunday = dayNames[0] ?? "Sun";
@@ -14861,22 +14895,17 @@ function getOrderedDayNames(startOfWeek, dayNames = DAY_NAMES) {
14861
14895
  }
14862
14896
  return [...dayNames];
14863
14897
  }
14864
- /**
14865
- * Header title for a calendar view.
14866
- * - month: "January 2025"
14867
- * - week: "January 5 - 11, 2025" or "December 30 - January 5, 2025"
14868
- */
14869
14898
  function formatCalendarTitle(viewDate, view, days, monthNames = MONTH_NAMES) {
14870
14899
  if (view === "week") {
14871
14900
  const weekStart = days[0];
14872
14901
  const weekEnd = days[6];
14873
- if (weekStart === void 0 || weekEnd === void 0) return `${monthNames[viewDate.getMonth()] ?? ""} ${viewDate.getFullYear()}`;
14874
- const startMonth = monthNames[weekStart.getMonth()] ?? "";
14875
- const endMonth = monthNames[weekEnd.getMonth()] ?? "";
14876
- if (weekStart.getMonth() === weekEnd.getMonth()) return `${startMonth} ${weekStart.getDate()} - ${weekEnd.getDate()}, ${weekEnd.getFullYear()}`;
14877
- return `${startMonth} ${weekStart.getDate()} - ${endMonth} ${weekEnd.getDate()}, ${weekEnd.getFullYear()}`;
14902
+ if (weekStart === void 0 || weekEnd === void 0) return `${monthNames[viewDate.month - 1] ?? ""} ${viewDate.year}`;
14903
+ const startMonth = monthNames[weekStart.month - 1] ?? "";
14904
+ const endMonth = monthNames[weekEnd.month - 1] ?? "";
14905
+ if (weekStart.month === weekEnd.month) return `${startMonth} ${weekStart.day} - ${weekEnd.day}, ${weekEnd.year}`;
14906
+ return `${startMonth} ${weekStart.day} - ${endMonth} ${weekEnd.day}, ${weekEnd.year}`;
14878
14907
  }
14879
- return `${monthNames[viewDate.getMonth()] ?? ""} ${viewDate.getFullYear()}`;
14908
+ return `${monthNames[viewDate.month - 1] ?? ""} ${viewDate.year}`;
14880
14909
  }
14881
14910
  function buildCalendarViewport(input) {
14882
14911
  const monthNames = input.monthNames ?? MONTH_NAMES;
@@ -14886,10 +14915,10 @@ function buildCalendarViewport(input) {
14886
14915
  kind: "week",
14887
14916
  anchorDate: input.anchorDate,
14888
14917
  days,
14889
- title: formatCalendarTitle(input.anchorDate, "week", [...days], monthNames)
14918
+ title: formatCalendarTitle(input.anchorDate, "week", days, monthNames)
14890
14919
  };
14891
14920
  }
14892
- const days = getMonthCalendarDays(input.anchorDate.getFullYear(), input.anchorDate.getMonth(), input.startOfWeek);
14921
+ const days = getMonthCalendarDays(input.anchorDate.year, input.anchorDate.month, input.startOfWeek);
14893
14922
  return {
14894
14923
  kind: "month",
14895
14924
  anchorDate: input.anchorDate,
@@ -15040,13 +15069,12 @@ function buildTimetableModel$1(input) {
15040
15069
  const bounds = resolveBounds(input.bounds);
15041
15070
  const viewportDays = getTimetableDays(input.viewDate, input.view ?? "week", input.startOfWeek);
15042
15071
  const viewportKeys = new Set(viewportDays.map(formatDateKey));
15043
- const now = input.now ?? /* @__PURE__ */ new Date();
15044
15072
  const parsed = parseAllItems(input.items, input);
15045
15073
  const inViewport = deriveVisibleSegments(parsed.drafts, viewportKeys);
15046
15074
  const hourRange = resolveHourRange(inViewport, bounds);
15047
15075
  const laid = layoutCellsByDate(inViewport, hourRange, bounds);
15048
15076
  return {
15049
- days: assembleDays(viewportDays, laid.cellsByDate, now),
15077
+ days: assembleDays(viewportDays, laid.cellsByDate, input.today),
15050
15078
  hourTicks: buildHourTicks(hourRange.startHour, hourRange.endHour),
15051
15079
  startHour: hourRange.startHour,
15052
15080
  endHour: hourRange.endHour,
@@ -15103,13 +15131,13 @@ function layoutCellsByDate(segments, hourRange, bounds) {
15103
15131
  diagnostics
15104
15132
  };
15105
15133
  }
15106
- function assembleDays(viewportDays, cellsByDate, now) {
15134
+ function assembleDays(viewportDays, cellsByDate, today) {
15107
15135
  return viewportDays.map((date) => {
15108
15136
  const dateKey = formatDateKey(date);
15109
15137
  return {
15110
15138
  date,
15111
15139
  dateKey,
15112
- isToday: isSameLocalDay(date, now),
15140
+ isToday: isSameCalendarDay(date, today),
15113
15141
  cells: cellsByDate.get(dateKey) ?? []
15114
15142
  };
15115
15143
  });
@@ -15261,13 +15289,12 @@ function getTimetableDays(viewDate, view, startOfWeek) {
15261
15289
  function enumerateDateKeys(startDateKey, endDateKey) {
15262
15290
  if (startDateKey > endDateKey) throw new Error(`Invalid timetable date range: ${startDateKey} is after ${endDateKey}`);
15263
15291
  const start = parseDateKey(startDateKey);
15264
- const end = parseDateKey(endDateKey);
15292
+ parseDateKey(endDateKey);
15265
15293
  const keys = [];
15266
- const cursor = new Date(start.year, start.month - 1, start.day);
15267
- const endDate = new Date(end.year, end.month - 1, end.day);
15268
- while (cursor.getTime() <= endDate.getTime()) {
15294
+ let cursor = start;
15295
+ while (formatDateKey(cursor) <= endDateKey) {
15269
15296
  keys.push(formatDateKey(cursor));
15270
- cursor.setDate(cursor.getDate() + 1);
15297
+ cursor = addDays(cursor, 1);
15271
15298
  }
15272
15299
  return keys;
15273
15300
  }
@@ -15495,10 +15522,10 @@ function formatEventTeacherLine(event) {
15495
15522
  * timezone). Thin domain wrapper over `groupItemsByDate` from the calendar
15496
15523
  * package; preserves the historical `Map<string, PublicEvent[]>` shape.
15497
15524
  */
15498
- function groupEventsByDate(events) {
15525
+ function groupEventsByDate(events, calendarTimeZone) {
15499
15526
  const grouped = groupItemsByDate(events, {
15500
15527
  getStartsAt: (event) => event.startsAt,
15501
- getTimeZone: (event) => event.timeZone ?? "UTC"
15528
+ getTimeZone: () => calendarTimeZone
15502
15529
  });
15503
15530
  const map = /* @__PURE__ */ new Map();
15504
15531
  for (const [dateKey, bucket] of grouped) map.set(dateKey, [...bucket]);
@@ -15946,9 +15973,13 @@ function EventDetailsSSR(props) {
15946
15973
  const { blockId, occurrenceContext = null, subject, events = null, className, children } = props;
15947
15974
  const nowIso = (/* @__PURE__ */ new Date()).toISOString();
15948
15975
  const normalizedSubject = normalizeEventRegistrationPageSurfaceSubject(subject);
15976
+ const scopedEvents = events === null ? null : resolveEventRegistrationScopedEvents(events, {
15977
+ occurrenceContext,
15978
+ subject: normalizedSubject
15979
+ });
15949
15980
  const presentation = resolveEventDetailsPresentation({
15950
15981
  ...props,
15951
- events,
15982
+ events: scopedEvents,
15952
15983
  occurrenceContext,
15953
15984
  subject: normalizedSubject,
15954
15985
  nowIso
@@ -15961,7 +15992,7 @@ function EventDetailsSSR(props) {
15961
15992
  /* @__PURE__ */ jsx(IslandPropsScript, { value: {
15962
15993
  occurrenceContext,
15963
15994
  subject: normalizedSubject,
15964
- events,
15995
+ events: scopedEvents,
15965
15996
  showVenue: presentation.showVenue,
15966
15997
  showMap: presentation.showMap,
15967
15998
  showOtherDates: presentation.showOtherDates,
@@ -16812,6 +16843,7 @@ var init_schemas = __esmMin((() => {
16812
16843
  freePriceDisplaySchema,
16813
16844
  exactPriceDisplaySchema,
16814
16845
  fromPriceDisplaySchema,
16846
+ rangePriceDisplaySchema,
16815
16847
  unavailablePriceDisplaySchema
16816
16848
  ]);
16817
16849
  z.discriminatedUnion("kind", [
@@ -18468,14 +18500,19 @@ function buildEventCollectionPresentationDisplay(source) {
18468
18500
  emptyMessage: source.emptyMessage ?? "No upcoming events scheduled."
18469
18501
  };
18470
18502
  }
18471
- function buildEventCollectionHydration(source) {
18503
+ function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date()) {
18504
+ const timeZone = toBookingTimeZone(source.bookingTimeZone);
18472
18505
  return {
18473
18506
  siteId: source.siteId,
18474
18507
  stage: source.stage,
18475
18508
  prefetchedEvents: source.events != null,
18476
18509
  eventSurface: normalizeEventSurfaceScope(source.eventSurface),
18477
18510
  filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
18478
- scheduleScope: normalizeEventScheduleScope(source.scheduleScope)
18511
+ scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
18512
+ calendarContext: {
18513
+ timeZone,
18514
+ initialToday: getLocalScheduleDate(now, timeZone)
18515
+ }
18479
18516
  };
18480
18517
  }
18481
18518
  function buildEventCollectionListingDisplay(display, prefetchedEvents, className) {
@@ -18501,6 +18538,7 @@ function buildEventCollectionListingDisplay(display, prefetchedEvents, className
18501
18538
  var eventSurfaceScopeSchema$1, eventScheduleScopeSchema$1, eventCollectionFilterSourceSchemaShape, eventCollectionSourceSchemaShape, eventCollectionDisplaySchemaShape, eventCollectionHydrationSchema;
18502
18539
  var init_eventCollectionContract = __esmMin((() => {
18503
18540
  init_cards();
18541
+ init_src$3();
18504
18542
  init_schemas();
18505
18543
  init_shared$2();
18506
18544
  init_contract_schemas();
@@ -18542,7 +18580,8 @@ var init_eventCollectionContract = __esmMin((() => {
18542
18580
  buttonVariant: eventButtonVariantSchema.optional(),
18543
18581
  buttonText: z.string().optional(),
18544
18582
  emptyMessage: z.string().optional(),
18545
- className: z.string().optional()
18583
+ className: z.string().optional(),
18584
+ bookingTimeZone: z.string().optional()
18546
18585
  };
18547
18586
  eventCollectionDisplaySchemaShape = {
18548
18587
  events: z.array(publicEventSchema),
@@ -18577,7 +18616,15 @@ var init_eventCollectionContract = __esmMin((() => {
18577
18616
  prefetchedEvents: z.boolean(),
18578
18617
  eventSurface: eventSurfaceScopeSchema$1,
18579
18618
  filterEventPresets: z.string().nullable(),
18580
- scheduleScope: eventScheduleScopeSchema$1
18619
+ scheduleScope: eventScheduleScopeSchema$1,
18620
+ calendarContext: z.object({
18621
+ timeZone: z.string().transform(toBookingTimeZone),
18622
+ initialToday: z.object({
18623
+ year: z.number().int(),
18624
+ month: z.number().int().min(1).max(12),
18625
+ day: z.number().int().min(1).max(31)
18626
+ })
18627
+ })
18581
18628
  });
18582
18629
  }));
18583
18630
  //#endregion
@@ -23191,30 +23238,6 @@ function asHeaderStyleId(value) {
23191
23238
  return value;
23192
23239
  }
23193
23240
  var init_headerLayoutTypes = __esmMin((() => {}));
23194
- var clearSplitInteractionPalette;
23195
- var init_headerInteractionPalette = __esmMin((() => {
23196
- init_interactionPalette();
23197
- init_lookOptionGroups();
23198
- clearSplitInteractionPalette = defineLookOptionGroup({
23199
- id: "interaction-palette",
23200
- label: "Hover colour",
23201
- defaultOptionId: "accent",
23202
- options: [
23203
- {
23204
- id: "accent",
23205
- label: "Accent"
23206
- },
23207
- {
23208
- id: "primary",
23209
- label: "Primary"
23210
- },
23211
- {
23212
- id: "secondary",
23213
- label: "Secondary"
23214
- }
23215
- ]
23216
- });
23217
- }));
23218
23241
  function supportedLayouts(ids) {
23219
23242
  return ids.map(asHeaderLayoutId);
23220
23243
  }
@@ -23222,7 +23245,6 @@ var titleOnlyLogoAccommodation, inlineWordmarkLogoAccommodation, inlineMarkWithT
23222
23245
  var init_headerLayoutCatalog = __esmMin((() => {
23223
23246
  init_logoBranding();
23224
23247
  init_types$9();
23225
- init_headerInteractionPalette();
23226
23248
  init_headerLayoutTypes();
23227
23249
  titleOnlyLogoAccommodation = {
23228
23250
  pattern: "title-only",
@@ -23379,43 +23401,37 @@ var init_headerLayoutCatalog = __esmMin((() => {
23379
23401
  id: asHeaderStyleId("minimal"),
23380
23402
  label: "Minimal",
23381
23403
  description: "Quiet surface with simple color-change navigation.",
23382
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23383
- navTypography: "plain"
23404
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23384
23405
  },
23385
23406
  {
23386
23407
  id: asHeaderStyleId("fine-line"),
23387
23408
  label: "Seamless",
23388
23409
  description: "Borderless surface with underline hover for a quieter page transition.",
23389
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23390
- navTypography: "plain"
23410
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23391
23411
  },
23392
23412
  {
23393
23413
  id: asHeaderStyleId("soft-bar"),
23394
23414
  label: "Soft Bar",
23395
23415
  description: "Soft tinted surface with gentle pill hover states.",
23396
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23397
- navTypography: "plain"
23416
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23398
23417
  },
23399
23418
  {
23400
23419
  id: asHeaderStyleId("pill-nav"),
23401
23420
  label: "Pill Nav",
23402
23421
  description: "A calm pill navigation rail over a neutral header.",
23403
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23404
- navTypography: "plain"
23422
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23405
23423
  },
23406
23424
  {
23407
23425
  id: asHeaderStyleId("brand-bar"),
23408
23426
  label: "Brand Bar",
23409
23427
  description: "Solid brand surface with high-contrast navigation.",
23410
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23411
- navTypography: "brand-caps"
23428
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23412
23429
  },
23413
23430
  {
23414
23431
  id: asHeaderStyleId("brand-underline"),
23415
23432
  label: "Brand Underline",
23416
23433
  description: "Brand surface with underline-grow navigation.",
23417
- supportedLayoutIds: supportedLayouts(["classic"]),
23418
- navTypography: "brand-caps"
23434
+ supportedLayoutIds: supportedLayouts(["classic"])
23419
23435
  },
23420
23436
  {
23421
23437
  id: asHeaderStyleId("brand-pill"),
@@ -23425,69 +23441,55 @@ var init_headerLayoutCatalog = __esmMin((() => {
23425
23441
  "classic",
23426
23442
  "centered",
23427
23443
  "floating"
23428
- ]),
23429
- navTypography: "brand-caps"
23444
+ ])
23430
23445
  },
23431
23446
  {
23432
23447
  id: asHeaderStyleId("brand-capsule"),
23433
23448
  label: "Brand Capsule",
23434
23449
  description: "Solid brand chrome designed as a floating capsule, with quiet-caps nav, a soft pill active state, and an inverted CTA pill.",
23435
- supportedLayoutIds: supportedLayouts(["classic"]),
23436
- navTypography: "quiet-caps"
23450
+ supportedLayoutIds: supportedLayouts(["classic"])
23437
23451
  },
23438
23452
  {
23439
23453
  id: asHeaderStyleId("serif-line"),
23440
23454
  label: "Serif Line",
23441
23455
  description: "Typographic logo treatment with understated underline navigation.",
23442
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23443
- navTypography: "heading"
23456
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23444
23457
  },
23445
23458
  {
23446
23459
  id: asHeaderStyleId("flat-tabs"),
23447
23460
  label: "Flat Tabs",
23448
23461
  description: "Flat block hover and active states with a Swiss utility feel.",
23449
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23450
- navTypography: "quiet-caps"
23462
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23451
23463
  },
23452
23464
  {
23453
23465
  id: asHeaderStyleId("glass"),
23454
23466
  label: "Glass",
23455
23467
  description: "Translucent chrome with frosted navigation backing.",
23456
- supportedLayoutIds: supportedLayouts(["floating"]),
23457
- navTypography: "plain"
23468
+ supportedLayoutIds: supportedLayouts(["floating"])
23458
23469
  },
23459
23470
  {
23460
23471
  id: asHeaderStyleId("minimal-surface"),
23461
23472
  label: "Clear Split",
23462
23473
  description: "Floating logo with transparent navigation and no shared shell.",
23463
- supportedLayoutIds: supportedLayouts(["floating"]),
23464
- navTypography: "plain",
23465
- openingForegroundTarget: "all",
23466
- scrollTreatment: "contrast-glass",
23467
- interactionPalette: clearSplitInteractionPalette
23474
+ supportedLayoutIds: supportedLayouts(["floating"])
23468
23475
  },
23469
23476
  {
23470
23477
  id: asHeaderStyleId("soft-shell"),
23471
23478
  label: "Soft Shell",
23472
23479
  description: "Floating rounded shell with soft pill navigation states.",
23473
- supportedLayoutIds: supportedLayouts(["floating"]),
23474
- navTypography: "plain"
23480
+ supportedLayoutIds: supportedLayouts(["floating"])
23475
23481
  },
23476
23482
  {
23477
23483
  id: asHeaderStyleId("split-glass"),
23478
23484
  label: "Split Glass",
23479
23485
  description: "Logo floats independently while the navigation sits in a glass rail.",
23480
- supportedLayoutIds: supportedLayouts(["floating"]),
23481
- navTypography: "quiet-caps",
23482
- openingForegroundTarget: "brand-only"
23486
+ supportedLayoutIds: supportedLayouts(["floating"])
23483
23487
  },
23484
23488
  {
23485
23489
  id: asHeaderStyleId("split-pill"),
23486
23490
  label: "Split Pill",
23487
23491
  description: "Logo floats independently with a soft pill-backed navigation rail.",
23488
- supportedLayoutIds: supportedLayouts(["floating"]),
23489
- navTypography: "heading",
23490
- openingForegroundTarget: "brand-only"
23492
+ supportedLayoutIds: supportedLayouts(["floating"])
23491
23493
  }
23492
23494
  ]);
23493
23495
  new Map(headerLayoutCatalog.map((layout) => [layout.id, layout]));
@@ -23497,22 +23499,53 @@ var init_headerLayoutResolution = __esmMin((() => {
23497
23499
  init_headerLayoutCatalog();
23498
23500
  init_headerLayoutTypes();
23499
23501
  }));
23502
+ var init_headerInteractionPalette = __esmMin((() => {
23503
+ init_interactionPalette();
23504
+ init_lookOptionGroups();
23505
+ defineLookOptionGroup({
23506
+ id: "interaction-palette",
23507
+ label: "Hover colour",
23508
+ defaultOptionId: "accent",
23509
+ options: [
23510
+ {
23511
+ id: "accent",
23512
+ label: "Accent"
23513
+ },
23514
+ {
23515
+ id: "primary",
23516
+ label: "Primary"
23517
+ },
23518
+ {
23519
+ id: "secondary",
23520
+ label: "Secondary"
23521
+ }
23522
+ ]
23523
+ });
23524
+ }));
23525
+ var init_headerStyleDefaults = __esmMin((() => {
23526
+ init_headerInteractionPalette();
23527
+ }));
23500
23528
  var init_headerNavStyles = __esmMin((() => {
23501
23529
  init_types$9();
23502
23530
  }));
23503
- var init_headerStyleCompiler = __esmMin((() => {
23531
+ var init_headerStyleRecipe = __esmMin((() => {
23504
23532
  init_headerCtaVariants();
23505
- init_headerInteractionPalette();
23506
23533
  init_headerLayoutCatalog();
23507
23534
  init_headerLayoutTypes();
23508
23535
  init_headerNavStyles();
23509
23536
  init_types$9();
23510
23537
  }));
23538
+ var init_headerStyleCompiler = __esmMin((() => {
23539
+ init_headerInteractionPalette();
23540
+ init_headerStyleDefaults();
23541
+ init_headerStyleRecipe();
23542
+ }));
23511
23543
  var init_headerLayoutStyles = __esmMin((() => {
23512
23544
  init_headerLayoutTypes();
23513
23545
  init_headerLayoutCatalog();
23514
23546
  init_headerLayoutResolution();
23515
23547
  init_headerStyleCompiler();
23548
+ init_headerStyleDefaults();
23516
23549
  init_headerLayoutTypes();
23517
23550
  }));
23518
23551
  //#endregion
@@ -24354,6 +24387,7 @@ var init_curatedSiteStyles = __esmMin((() => {
24354
24387
  init_gradients();
24355
24388
  init_headerLayoutStyles();
24356
24389
  init_footerLooks();
24390
+ init_headerStyleDefaults();
24357
24391
  init_curatedChoices();
24358
24392
  init_sourceCatalogs();
24359
24393
  init_types$9();
@@ -26766,7 +26800,6 @@ var init_validation_constants = __esmMin((() => {
26766
26800
  "layout.footerRootClass",
26767
26801
  "layout.headerRootStyle",
26768
26802
  "layout.headerSectionBackground",
26769
- "layout.classicNavMode",
26770
26803
  "layout.footerRootStyle",
26771
26804
  "ui.headerNavLinkClass",
26772
26805
  "ui.headingClassFromAlignment",
@@ -31949,13 +31982,16 @@ function buildEventRegistrationShellStepLabels(source) {
31949
31982
  }) : false).map((step) => shellLabelForRegistrationStep(step, scopedEvents));
31950
31983
  }
31951
31984
  function scopeEventRegistrationEvents(source) {
31985
+ return toRegistrationEvents(scopeEventRegistrationSourceEvents(source));
31986
+ }
31987
+ function scopeEventRegistrationSourceEvents(source) {
31952
31988
  const scope = planEventRegistrationScope({
31953
- events: toRegistrationEvents(source.events ?? []),
31989
+ events: source.events ?? [],
31954
31990
  wholeSeriesOffering: source.wholeSeriesOffering,
31955
31991
  occurrenceContext: source.occurrenceContext,
31956
31992
  subject: source.subject
31957
31993
  });
31958
- return scope.kind === "invalidSelectedRun" ? [] : scope.events;
31994
+ return scope.kind === "invalidSelectedRun" ? [] : [...scope.events];
31959
31995
  }
31960
31996
  function shellLabelForRegistrationStep(step, events) {
31961
31997
  switch (step) {
@@ -32098,26 +32134,29 @@ var init_event_registration_interactive = __esmMin((() => {
32098
32134
  source: createZodCodec(eventRegistrationSourceSchema),
32099
32135
  render: createZodCodec(eventRegistrationRenderSchema)
32100
32136
  },
32101
- buildRender: (source) => ({
32102
- display: buildEventRegistrationDisplay(source),
32103
- hydration: {
32104
- occurrenceContext: source.occurrenceContext ?? null,
32105
- subject: source.subject ?? null,
32106
- events: source.events ?? null,
32107
- wholeSeriesOfferings: source.wholeSeriesOfferings ?? null,
32108
- wholeSeriesOffering: resolveWholeSeriesOffering(source),
32109
- maxTickets: source.maxTickets ?? void 0,
32110
- showVenue: source.showVenue,
32111
- showCapacity: source.showCapacity,
32112
- successMessage: source.successMessage,
32113
- buttonVariant: source.buttonVariant,
32114
- overlayEnabled: source.overlayEnabled,
32115
- spamProtectionEnabled: source.spamProtectionEnabled,
32116
- supportEmail: source.supportEmail,
32117
- sitePasses: source.sitePasses ?? null,
32118
- siteMemberships: source.siteMemberships ?? null
32119
- }
32120
- })
32137
+ buildRender: (source) => {
32138
+ const events = source.events == null ? null : scopeEventRegistrationSourceEvents(source);
32139
+ return {
32140
+ display: buildEventRegistrationDisplay(source),
32141
+ hydration: {
32142
+ occurrenceContext: source.occurrenceContext ?? null,
32143
+ subject: source.subject ?? null,
32144
+ events,
32145
+ wholeSeriesOfferings: source.wholeSeriesOfferings ?? null,
32146
+ wholeSeriesOffering: resolveWholeSeriesOffering(source),
32147
+ maxTickets: source.maxTickets ?? void 0,
32148
+ showVenue: source.showVenue,
32149
+ showCapacity: source.showCapacity,
32150
+ successMessage: source.successMessage,
32151
+ buttonVariant: source.buttonVariant,
32152
+ overlayEnabled: source.overlayEnabled,
32153
+ spamProtectionEnabled: source.spamProtectionEnabled,
32154
+ supportEmail: source.supportEmail,
32155
+ sitePasses: source.sitePasses ?? null,
32156
+ siteMemberships: source.siteMemberships ?? null
32157
+ }
32158
+ };
32159
+ }
32121
32160
  });
32122
32161
  eventRegistrationInteractiveIslandPropsCodec = createInteractiveIslandCodec({
32123
32162
  runtime: eventRegistrationBlockRuntime,
@@ -35967,12 +36006,13 @@ var init_AgendaEventCard = __esmMin((() => {
35967
36006
  * @returns "Monday, January 13"
35968
36007
  */
35969
36008
  function formatAgendaDayHeader(date) {
35970
- const dayName = FULL_DAY_NAMES$1[date.getDay()];
35971
- const monthName = MONTH_NAMES[date.getMonth()];
35972
- return `${dayName ?? "Day"}, ${monthName ?? "Month"} ${date.getDate()}`;
36009
+ const dayName = FULL_DAY_NAMES$1[getDayOfWeek(date)];
36010
+ const monthName = MONTH_NAMES[date.month - 1];
36011
+ return `${dayName ?? "Day"}, ${monthName ?? "Month"} ${date.day}`;
35973
36012
  }
35974
36013
  var FULL_DAY_NAMES$1, WeekAgendaView;
35975
36014
  var init_WeekAgendaView = __esmMin((() => {
36015
+ init_src$1();
35976
36016
  init_AgendaEventCard();
35977
36017
  init_utils$3();
35978
36018
  FULL_DAY_NAMES$1 = [
@@ -35984,14 +36024,14 @@ var init_WeekAgendaView = __esmMin((() => {
35984
36024
  "Friday",
35985
36025
  "Saturday"
35986
36026
  ];
35987
- WeekAgendaView = ({ days, events, showCapacity, emptyMessage = "No events scheduled" }) => {
35988
- const eventsByDate = groupEventsByDate(events);
36027
+ WeekAgendaView = ({ days, events, showCapacity, emptyMessage = "No events scheduled", calendarTimeZone, today: currentDate }) => {
36028
+ const eventsByDate = groupEventsByDate(events, calendarTimeZone);
35989
36029
  return /* @__PURE__ */ jsx("div", {
35990
36030
  className: "event-agenda-week",
35991
36031
  children: days.map((date) => {
35992
36032
  const dateKey = formatDateKey(date);
35993
36033
  const dayEvents = eventsByDate.get(dateKey) || [];
35994
- const today = isToday(date);
36034
+ const today = isToday(date, currentDate);
35995
36035
  return /* @__PURE__ */ jsxs("div", {
35996
36036
  className: `event-agenda-day ${today ? "event-agenda-day--today" : ""}`,
35997
36037
  children: [/* @__PURE__ */ jsx("div", {
@@ -36022,11 +36062,37 @@ var init_WeekAgendaView = __esmMin((() => {
36022
36062
  };
36023
36063
  }));
36024
36064
  //#endregion
36065
+ //#region ../blocks/src/system/runtime/nodes/events/shared/CalendarNavigationChevron.tsx
36066
+ function CalendarNavigationChevron({ direction }) {
36067
+ return /* @__PURE__ */ jsx("svg", {
36068
+ width: "20",
36069
+ height: "20",
36070
+ fill: "none",
36071
+ stroke: "currentColor",
36072
+ strokeWidth: 2,
36073
+ viewBox: "0 0 24 24",
36074
+ "aria-hidden": "true",
36075
+ children: /* @__PURE__ */ jsx("path", {
36076
+ strokeLinecap: "round",
36077
+ strokeLinejoin: "round",
36078
+ d: direction === "previous" ? "M15 19l-7-7 7-7" : "M9 5l7 7-7 7"
36079
+ })
36080
+ });
36081
+ }
36082
+ var init_CalendarNavigationChevron = __esmMin((() => {}));
36083
+ //#endregion
36025
36084
  //#region ../blocks/src/system/runtime/nodes/events/shared/WeekBoardView.tsx
36026
- function buildWeekBoardViewProps(display, days) {
36085
+ function buildWeekBoardNavigationState(viewport, today) {
36086
+ return {
36087
+ rangeLabel: viewport.title,
36088
+ isCurrentWeek: viewport.days.some((day) => isToday(day, today))
36089
+ };
36090
+ }
36091
+ function buildWeekBoardViewProps(display, days, navigation, events = display.events) {
36027
36092
  return {
36028
36093
  days,
36029
- events: [...display.events],
36094
+ events: [...events],
36095
+ navigation,
36030
36096
  showCapacity: display.showCapacity,
36031
36097
  emptyMessage: display.emptyMessage,
36032
36098
  title: display.boardTitle,
@@ -36035,7 +36101,9 @@ function buildWeekBoardViewProps(display, days) {
36035
36101
  ctaHref: display.seeAllUrl,
36036
36102
  buttonVariant: display.buttonVariant,
36037
36103
  elevated: display.elevated,
36038
- banded: display.banded
36104
+ banded: display.banded,
36105
+ calendarTimeZone: display.calendarTimeZone,
36106
+ today: display.today
36039
36107
  };
36040
36108
  }
36041
36109
  /**
@@ -36051,12 +36119,14 @@ function formatCompactTimeRange(event) {
36051
36119
  if ((startMeridiem === "AM" || startMeridiem === "PM") && startMeridiem === endMeridiem) return `${start.slice(0, -3).trim()} – ${end}`;
36052
36120
  return `${start} – ${end}`;
36053
36121
  }
36054
- var SHORT_DAY_NAMES, LEGEND_ITEMS, WeekBoardCard, WeekBoardView;
36122
+ var SHORT_DAY_NAMES, LEGEND_ITEMS, WeekBoardCard, WeekBoardNavigationControls, WeekBoardLegend, WeekBoardLoadError, WeekBoardGrid, WeekBoardFooter, WeekBoardView;
36055
36123
  var init_WeekBoardView = __esmMin((() => {
36056
36124
  init_clsx();
36057
36125
  init_buttons();
36126
+ init_src$1();
36058
36127
  init_eventCapacity();
36059
36128
  init_utils$3();
36129
+ init_CalendarNavigationChevron();
36060
36130
  SHORT_DAY_NAMES = [
36061
36131
  "Sun",
36062
36132
  "Mon",
@@ -36105,18 +36175,129 @@ var init_WeekBoardView = __esmMin((() => {
36105
36175
  ]
36106
36176
  });
36107
36177
  };
36108
- WeekBoardView = ({ days, events, showCapacity, emptyMessage = "No classes scheduled this week", title, footerNote, ctaLabel = "Reserve a place", ctaHref = null, buttonVariant = "outline", elevated = false, banded = false }) => {
36109
- const eventsByDate = groupEventsByDate(events);
36178
+ WeekBoardNavigationControls = ({ navigation, todayClassName }) => {
36179
+ const handlers = navigation.kind === "interactive" ? navigation : {
36180
+ onPrevious: void 0,
36181
+ onNext: void 0,
36182
+ onToday: void 0
36183
+ };
36184
+ const isLoading = navigation.kind === "interactive" && navigation.loadState.kind === "loading";
36185
+ return /* @__PURE__ */ jsxs("nav", {
36186
+ className: "event-week-board-navigation",
36187
+ "aria-label": "Choose week",
36188
+ children: [
36189
+ /* @__PURE__ */ jsx("button", {
36190
+ type: "button",
36191
+ className: "event-week-board-nav-button",
36192
+ "aria-label": "Previous week",
36193
+ onClick: handlers.onPrevious,
36194
+ children: /* @__PURE__ */ jsx(CalendarNavigationChevron, { direction: "previous" })
36195
+ }),
36196
+ /* @__PURE__ */ jsxs("h3", {
36197
+ className: "event-week-board-range",
36198
+ "aria-live": "polite",
36199
+ children: [navigation.rangeLabel, isLoading ? /* @__PURE__ */ jsx("span", {
36200
+ className: "event-week-board-loading",
36201
+ children: " Loading…"
36202
+ }) : null]
36203
+ }),
36204
+ /* @__PURE__ */ jsx("button", {
36205
+ type: "button",
36206
+ className: "event-week-board-nav-button",
36207
+ "aria-label": "Next week",
36208
+ onClick: handlers.onNext,
36209
+ children: /* @__PURE__ */ jsx(CalendarNavigationChevron, { direction: "next" })
36210
+ }),
36211
+ /* @__PURE__ */ jsx("button", {
36212
+ type: "button",
36213
+ className: todayClassName,
36214
+ disabled: navigation.isCurrentWeek,
36215
+ onClick: handlers.onToday,
36216
+ children: "Today"
36217
+ })
36218
+ ]
36219
+ });
36220
+ };
36221
+ WeekBoardLegend = () => /* @__PURE__ */ jsx("div", {
36222
+ className: "event-week-board-legend",
36223
+ "aria-hidden": "true",
36224
+ children: LEGEND_ITEMS.map((item) => /* @__PURE__ */ jsxs("span", {
36225
+ className: "event-week-board-legend-item",
36226
+ children: [/* @__PURE__ */ jsx("i", {
36227
+ className: "event-week-board-legend-dot",
36228
+ "data-status": item.status
36229
+ }), item.label]
36230
+ }, item.status))
36231
+ });
36232
+ WeekBoardLoadError = ({ navigation, buttonClassName }) => {
36233
+ if (navigation.kind !== "interactive" || navigation.loadState.kind !== "error") return null;
36234
+ return /* @__PURE__ */ jsxs("div", {
36235
+ className: "event-week-board-error",
36236
+ role: "status",
36237
+ children: [/* @__PURE__ */ jsx("p", { children: "Failed to load events" }), /* @__PURE__ */ jsx("button", {
36238
+ type: "button",
36239
+ className: buttonClassName,
36240
+ onClick: navigation.loadState.onRetry,
36241
+ children: "Try again"
36242
+ })]
36243
+ });
36244
+ };
36245
+ WeekBoardGrid = ({ days, eventsByDate, showCapacity, today: currentDate }) => /* @__PURE__ */ jsx("div", {
36246
+ className: "event-week-board-grid",
36247
+ children: days.map((date) => {
36248
+ const dateKey = formatDateKey(date);
36249
+ const dayEvents = eventsByDate.get(dateKey) ?? [];
36250
+ const today = isToday(date, currentDate);
36251
+ return /* @__PURE__ */ jsxs("div", {
36252
+ className: clsx("event-week-board-day", dayEvents.length === 0 && "event-week-board-day--empty", today && "event-week-board-day--today"),
36253
+ children: [/* @__PURE__ */ jsxs("div", {
36254
+ className: "event-week-board-day-head",
36255
+ children: [/* @__PURE__ */ jsx("span", {
36256
+ className: "event-week-board-day-abbr",
36257
+ children: SHORT_DAY_NAMES[getDayOfWeek(date)]
36258
+ }), /* @__PURE__ */ jsx("span", {
36259
+ className: "event-week-board-day-num",
36260
+ children: date.day
36261
+ })]
36262
+ }), /* @__PURE__ */ jsx("div", {
36263
+ className: "event-week-board-day-body",
36264
+ children: dayEvents.map((event) => /* @__PURE__ */ jsx(WeekBoardCard, {
36265
+ event,
36266
+ showCapacity
36267
+ }, event.occurrenceId || event.id))
36268
+ })]
36269
+ }, dateKey);
36270
+ })
36271
+ });
36272
+ WeekBoardFooter = ({ note, ctaHref, ctaLabel, ctaClassName }) => {
36273
+ if (note === null && ctaHref === null) return null;
36274
+ return /* @__PURE__ */ jsxs("div", {
36275
+ className: "event-week-board-foot",
36276
+ children: [note === null ? null : /* @__PURE__ */ jsx("p", {
36277
+ className: "event-week-board-foot-note",
36278
+ children: note
36279
+ }), ctaHref === null ? null : /* @__PURE__ */ jsx("a", {
36280
+ className: ctaClassName,
36281
+ href: ctaHref,
36282
+ children: ctaLabel
36283
+ })]
36284
+ });
36285
+ };
36286
+ WeekBoardView = ({ days, events, navigation, showCapacity, emptyMessage = "No classes scheduled this week", title, footerNote, ctaLabel = "Reserve a place", ctaHref = null, buttonVariant = "outline", elevated = false, banded = false, calendarTimeZone, today }) => {
36287
+ const eventsByDate = groupEventsByDate(events, calendarTimeZone);
36110
36288
  const hasAnyEvents = days.some((date) => (eventsByDate.get(formatDateKey(date)) ?? []).length > 0);
36111
36289
  const ctaClassName = themeButtonClassName({
36112
36290
  variant: buttonVariant,
36113
36291
  size: "sm"
36114
36292
  });
36293
+ const todayClassName = themeButtonClassName({
36294
+ variant: buttonVariant,
36295
+ size: "sm"
36296
+ });
36115
36297
  const hasTitle = typeof title === "string" && title.length > 0;
36116
36298
  const hasFooterNote = typeof footerNote === "string" && footerNote.length > 0;
36117
- const hasCta = typeof ctaHref === "string" && ctaHref.length > 0;
36118
36299
  const footerNoteText = hasAnyEvents ? hasFooterNote ? footerNote : null : emptyMessage;
36119
- const showFooter = hasCta || footerNoteText !== null;
36300
+ const resolvedCtaHref = typeof ctaHref === "string" && ctaHref.length > 0 ? ctaHref : null;
36120
36301
  return /* @__PURE__ */ jsx("div", {
36121
36302
  className: "event-calendar event-calendar--week-board",
36122
36303
  "data-block": "event-calendar",
@@ -36128,59 +36309,34 @@ var init_WeekBoardView = __esmMin((() => {
36128
36309
  children: [
36129
36310
  /* @__PURE__ */ jsxs("div", {
36130
36311
  className: "event-week-board-top",
36131
- children: [hasTitle ? /* @__PURE__ */ jsx("span", {
36132
- className: "event-week-board-title",
36133
- children: title
36134
- }) : null, /* @__PURE__ */ jsx("div", {
36135
- className: "event-week-board-legend",
36136
- "aria-hidden": "true",
36137
- children: LEGEND_ITEMS.map((item) => /* @__PURE__ */ jsxs("span", {
36138
- className: "event-week-board-legend-item",
36139
- children: [/* @__PURE__ */ jsx("i", {
36140
- className: "event-week-board-legend-dot",
36141
- "data-status": item.status
36142
- }), item.label]
36143
- }, item.status))
36144
- })]
36312
+ children: [
36313
+ hasTitle ? /* @__PURE__ */ jsx("span", {
36314
+ className: "event-week-board-title",
36315
+ children: title
36316
+ }) : null,
36317
+ /* @__PURE__ */ jsx(WeekBoardNavigationControls, {
36318
+ navigation,
36319
+ todayClassName
36320
+ }),
36321
+ /* @__PURE__ */ jsx(WeekBoardLegend, {})
36322
+ ]
36145
36323
  }),
36146
- /* @__PURE__ */ jsx("div", {
36147
- className: "event-week-board-grid",
36148
- children: days.map((date) => {
36149
- const dateKey = formatDateKey(date);
36150
- const dayEvents = eventsByDate.get(dateKey) ?? [];
36151
- const today = isToday(date);
36152
- return /* @__PURE__ */ jsxs("div", {
36153
- className: clsx("event-week-board-day", dayEvents.length === 0 && "event-week-board-day--empty", today && "event-week-board-day--today"),
36154
- children: [/* @__PURE__ */ jsxs("div", {
36155
- className: "event-week-board-day-head",
36156
- children: [/* @__PURE__ */ jsx("span", {
36157
- className: "event-week-board-day-abbr",
36158
- children: SHORT_DAY_NAMES[date.getDay()]
36159
- }), /* @__PURE__ */ jsx("span", {
36160
- className: "event-week-board-day-num",
36161
- children: date.getDate()
36162
- })]
36163
- }), /* @__PURE__ */ jsx("div", {
36164
- className: "event-week-board-day-body",
36165
- children: dayEvents.map((event) => /* @__PURE__ */ jsx(WeekBoardCard, {
36166
- event,
36167
- showCapacity
36168
- }, event.occurrenceId || event.id))
36169
- })]
36170
- }, dateKey);
36171
- })
36324
+ /* @__PURE__ */ jsx(WeekBoardLoadError, {
36325
+ navigation,
36326
+ buttonClassName: todayClassName
36172
36327
  }),
36173
- showFooter ? /* @__PURE__ */ jsxs("div", {
36174
- className: "event-week-board-foot",
36175
- children: [footerNoteText !== null ? /* @__PURE__ */ jsx("p", {
36176
- className: "event-week-board-foot-note",
36177
- children: footerNoteText
36178
- }) : null, hasCta ? /* @__PURE__ */ jsx("a", {
36179
- className: ctaClassName,
36180
- href: ctaHref ?? void 0,
36181
- children: ctaLabel
36182
- }) : null]
36183
- }) : null
36328
+ /* @__PURE__ */ jsx(WeekBoardGrid, {
36329
+ days,
36330
+ eventsByDate,
36331
+ showCapacity,
36332
+ today
36333
+ }),
36334
+ /* @__PURE__ */ jsx(WeekBoardFooter, {
36335
+ note: footerNoteText,
36336
+ ctaHref: resolvedCtaHref,
36337
+ ctaLabel,
36338
+ ctaClassName
36339
+ })
36184
36340
  ]
36185
36341
  })
36186
36342
  });
@@ -36193,6 +36349,7 @@ function buildTimetableModel(input) {
36193
36349
  items: input.events,
36194
36350
  viewDate: input.viewDate,
36195
36351
  startOfWeek: input.startOfWeek,
36352
+ today: input.today,
36196
36353
  getId: (event) => event.id,
36197
36354
  getStartsAt: (event) => event.startsAt,
36198
36355
  getEndsAt: (event) => event.endsAt,
@@ -36254,10 +36411,10 @@ function formatEventTimeRange(event) {
36254
36411
  return `${formatTime$2(event.startsAt, { timeZone })} - ${formatTime$2(event.endsAt, { timeZone })}`;
36255
36412
  }
36256
36413
  function formatDayLabel(date) {
36257
- return `${FULL_DAY_NAMES[date.getDay()] ?? ""}, ${MONTH_NAMES[date.getMonth()] ?? ""} ${date.getDate()}`;
36414
+ return `${FULL_DAY_NAMES[getDayOfWeek(date)] ?? ""}, ${MONTH_NAMES[date.month - 1] ?? ""} ${date.day}`;
36258
36415
  }
36259
36416
  function formatShortDayLabel(date) {
36260
- return `${(FULL_DAY_NAMES[date.getDay()] ?? "").slice(0, 3)} ${date.getDate()}`;
36417
+ return `${(FULL_DAY_NAMES[getDayOfWeek(date)] ?? "").slice(0, 3)} ${date.day}`;
36261
36418
  }
36262
36419
  var DEFAULT_EVENT_CELL_COLOR, FULL_DAY_NAMES;
36263
36420
  var init_timetableModel = __esmMin((() => {
@@ -36328,15 +36485,15 @@ function renderListSsr(display, prefetchedEvents) {
36328
36485
  renderEventCard: (event) => renderEventCard(event, listDisplay)
36329
36486
  });
36330
36487
  }
36331
- function renderCalendarSsr(display) {
36488
+ function renderCalendarSsr(display, hydration) {
36332
36489
  const calendarView = display.defaultCalendarView;
36333
- const viewDate = /* @__PURE__ */ new Date();
36490
+ const viewDate = hydration.calendarContext.initialToday;
36334
36491
  const viewport = buildCalendarViewport({
36335
36492
  view: calendarView,
36336
36493
  anchorDate: viewDate,
36337
36494
  startOfWeek: display.startOfWeek
36338
36495
  });
36339
- const eventsByDate = groupEventsByDate([...display.events]);
36496
+ const eventsByDate = groupEventsByDate([...display.events], hydration.calendarContext.timeZone);
36340
36497
  const dayNames = getOrderedDayNames(display.startOfWeek);
36341
36498
  return /* @__PURE__ */ jsxs("div", {
36342
36499
  className: clsx("event-calendar", display.className ?? void 0),
@@ -36403,7 +36560,9 @@ function renderCalendarSsr(display) {
36403
36560
  days: viewport.days,
36404
36561
  events: [...display.events],
36405
36562
  emptyMessage: display.emptyMessage,
36406
- showCapacity: display.showCapacity
36563
+ showCapacity: display.showCapacity,
36564
+ calendarTimeZone: hydration.calendarContext.timeZone,
36565
+ today: hydration.calendarContext.initialToday
36407
36566
  }) : /* @__PURE__ */ jsxs("div", {
36408
36567
  className: "event-calendar-container",
36409
36568
  children: [/* @__PURE__ */ jsx("div", {
@@ -36417,13 +36576,13 @@ function renderCalendarSsr(display) {
36417
36576
  children: viewport.days.map((date) => {
36418
36577
  const dateKey = formatDateKey(date);
36419
36578
  const dayEvents = eventsByDate.get(dateKey) || [];
36420
- const isCurrentMonth = date.getMonth() === viewDate.getMonth();
36421
- const today = isToday(date);
36579
+ const isCurrentMonth = date.month === viewDate.month;
36580
+ const today = isToday(date, hydration.calendarContext.initialToday);
36422
36581
  return /* @__PURE__ */ jsxs("div", {
36423
36582
  className: clsx("event-calendar-day", !isCurrentMonth && "event-calendar-day--other-month", today && "event-calendar-day--today"),
36424
36583
  children: [/* @__PURE__ */ jsx("div", {
36425
36584
  className: "event-calendar-day-number",
36426
- children: date.getDate()
36585
+ children: date.day
36427
36586
  }), /* @__PURE__ */ jsxs("div", {
36428
36587
  className: "event-calendar-events",
36429
36588
  children: [dayEvents.slice(0, 3).map((event) => /* @__PURE__ */ jsxs("a", {
@@ -36461,8 +36620,8 @@ function renderCalendarSsr(display) {
36461
36620
  ]
36462
36621
  });
36463
36622
  }
36464
- function renderTimetableSsr(display) {
36465
- const viewDate = /* @__PURE__ */ new Date();
36623
+ function renderTimetableSsr(display, hydration) {
36624
+ const viewDate = hydration.calendarContext.initialToday;
36466
36625
  const viewport = buildCalendarViewport({
36467
36626
  view: "week",
36468
36627
  anchorDate: viewDate,
@@ -36471,7 +36630,8 @@ function renderTimetableSsr(display) {
36471
36630
  const model = buildTimetableModel({
36472
36631
  events: [...display.events],
36473
36632
  viewDate,
36474
- startOfWeek: display.startOfWeek
36633
+ startOfWeek: display.startOfWeek,
36634
+ today: hydration.calendarContext.initialToday
36475
36635
  });
36476
36636
  const selectedDayKey = model.days.find((day) => day.isToday)?.dateKey ?? model.days[0]?.dateKey ?? "";
36477
36637
  return /* @__PURE__ */ jsxs("div", {
@@ -36626,21 +36786,21 @@ function renderTimetableSsr(display) {
36626
36786
  })]
36627
36787
  });
36628
36788
  }
36629
- function renderWeekBoardSsr(display) {
36630
- const days = getWeekCalendarDayTuple(/* @__PURE__ */ new Date(), display.startOfWeek);
36631
- return /* @__PURE__ */ jsx(WeekBoardView, {
36632
- days,
36633
- events: [...display.events],
36634
- showCapacity: display.showCapacity,
36635
- emptyMessage: display.emptyMessage,
36636
- title: display.boardTitle,
36637
- footerNote: display.footerNote,
36638
- ctaLabel: display.loadMoreText ?? display.buttonText,
36639
- ctaHref: display.seeAllUrl,
36640
- buttonVariant: display.buttonVariant,
36641
- elevated: display.elevated,
36642
- banded: display.banded
36643
- });
36789
+ function renderWeekBoardSsr(display, hydration) {
36790
+ const today = hydration.calendarContext.initialToday;
36791
+ const days = getWeekCalendarDayTuple(today, display.startOfWeek);
36792
+ const navigation = {
36793
+ kind: "static",
36794
+ ...buildWeekBoardNavigationState({
36795
+ days,
36796
+ title: formatCalendarTitle(today, "week", [...days])
36797
+ }, today)
36798
+ };
36799
+ return /* @__PURE__ */ jsx(WeekBoardView, { ...buildWeekBoardViewProps({
36800
+ ...display,
36801
+ calendarTimeZone: hydration.calendarContext.timeZone,
36802
+ today
36803
+ }, days, navigation) });
36644
36804
  }
36645
36805
  function formatHourLabel$1(hour) {
36646
36806
  if (hour === 0) return "12 AM";
@@ -36666,13 +36826,13 @@ const EventCalendarSSR = (props) => {
36666
36826
  content = renderListSsr(display, hydration.prefetchedEvents);
36667
36827
  break;
36668
36828
  case "timetable":
36669
- content = renderTimetableSsr(display);
36829
+ content = renderTimetableSsr(display, hydration);
36670
36830
  break;
36671
36831
  case "week-board":
36672
- content = renderWeekBoardSsr(display);
36832
+ content = renderWeekBoardSsr(display, hydration);
36673
36833
  break;
36674
36834
  case "calendar":
36675
- content = renderCalendarSsr(display);
36835
+ content = renderCalendarSsr(display, hydration);
36676
36836
  break;
36677
36837
  default: content = assertNeverDisplayMode(display.displayMode);
36678
36838
  }
@@ -45736,41 +45896,78 @@ var init_sessionStorage = __esmMin((() => {
45736
45896
  }));
45737
45897
  //#endregion
45738
45898
  //#region ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.ts
45899
+ function restorePendingPresentation(options, pending) {
45900
+ options.setFormData(pending.formData);
45901
+ options.setTicketSelections(pending.ticketSelections);
45902
+ options.setTicketsCount(getTicketSelectionTotal(pending.ticketSelections));
45903
+ if (pending.selectedEventId) {
45904
+ const event = options.events.find((item) => item.selectionId === pending.selectedEventId) ?? null;
45905
+ if (event) options.setSelectedEvent(event);
45906
+ }
45907
+ options.setSelectedAttendanceMode(pending.selectedAttendanceMode ?? null);
45908
+ options.setPaymentSelection(pending.paymentSelection);
45909
+ }
45910
+ function showReturnReconciliation(options, message) {
45911
+ options.setErrorMessage(message);
45912
+ options.setStep("verifying-timeout");
45913
+ }
45914
+ async function handleCheckoutReturn(options, deps, checkoutAttemptIdRef) {
45915
+ deps.cleanupStaleRegistrations();
45916
+ const params = deps.consumeReturnParams();
45917
+ if (params.registration !== "cancelled" && params.registration !== "success") return;
45918
+ deps.scrollToBlock(EVENT_REGISTRATION_ANCHOR_ID);
45919
+ const siteId = options.api.config.siteId;
45920
+ const checkoutAttemptId = params.registration_attempt;
45921
+ if (!siteId) return;
45922
+ if (!checkoutAttemptId) {
45923
+ showReturnReconciliation(options, "We could not identify this payment attempt. Please contact us before trying again.");
45924
+ return;
45925
+ }
45926
+ const pending = deps.getPendingRegistration(siteId, checkoutAttemptId);
45927
+ checkoutAttemptIdRef.current = checkoutAttemptId;
45928
+ if (pending) restorePendingPresentation(options, pending);
45929
+ try {
45930
+ const outcome = params.registration === "success" ? params.session_id ? await options.api.resolveEventCheckoutReturn({
45931
+ kind: "resolveSuccess",
45932
+ checkoutAttemptId,
45933
+ sessionId: params.session_id
45934
+ }) : { kind: "notFound" } : await options.api.resolveEventCheckoutReturn({
45935
+ kind: "abandon",
45936
+ checkoutAttemptId
45937
+ });
45938
+ switch (outcome.kind) {
45939
+ case "resolved":
45940
+ options.setPendingRegistrationReference(outcome.reference);
45941
+ options.setStep("verifying-payment");
45942
+ return;
45943
+ case "abandoned":
45944
+ options.setErrorMessage("Your payment was cancelled. You can choose a payment option and try again.");
45945
+ options.setStep("select-payment");
45946
+ return;
45947
+ case "notFound":
45948
+ if (params.registration === "cancelled" && (options.registrationSubject?.kind === "occurrence" || pending?.reference.scope === "occurrence")) {
45949
+ options.setErrorMessage("Your payment was cancelled. You can choose a payment option and try again.");
45950
+ options.setStep("select-payment");
45951
+ return;
45952
+ }
45953
+ break;
45954
+ case "reconciliationRequired": break;
45955
+ }
45956
+ showReturnReconciliation(options, "We’re checking your payment. Please wait a moment before trying again.");
45957
+ } catch {
45958
+ showReturnReconciliation(options, "We could not check your payment yet. Please try again shortly.");
45959
+ }
45960
+ }
45739
45961
  function useEventRegistrationStripeReturn(options) {
45740
45962
  return useEventRegistrationStripeReturnWithDeps(options, eventRegistrationStripeReturnDeps);
45741
45963
  }
45742
45964
  function useEventRegistrationStripeReturnWithDeps(options, deps) {
45743
- const { api, events, pendingRegistrationReference, setErrorMessage, setFormData, setPaymentSelection, setPendingRegistrationReference, setRegistrationResult, setSelectedEvent, setSelectedAttendanceMode, setTicketSelections, setStep, setTicketsCount, step } = options;
45965
+ const { api, pendingRegistrationReference, setErrorMessage, setRegistrationResult, setStep, step } = options;
45744
45966
  const checkoutAttemptIdRef = useRef(null);
45745
45967
  const verificationConfig = useMemo(() => step === "verifying-payment" && pendingRegistrationReference ? { reference: pendingRegistrationReference } : null, [step, pendingRegistrationReference]);
45746
45968
  const verification = deps.usePaymentVerification(verificationConfig);
45747
45969
  useEffect(() => {
45748
- deps.cleanupStaleRegistrations();
45749
- const returnParams = deps.consumeReturnParams();
45750
- const registrationStatus = returnParams.registration;
45751
- if (registrationStatus !== "cancelled" && registrationStatus !== "success") return;
45752
- deps.scrollToBlock(EVENT_REGISTRATION_ANCHOR_ID);
45753
- const siteId = api.config.siteId;
45754
- if (!siteId) return;
45755
- const checkoutAttemptId = returnParams[EVENT_REGISTRATION_CHECKOUT_ATTEMPT_PARAM];
45756
- if (!checkoutAttemptId) return;
45757
- const pending = deps.getPendingRegistration(siteId, checkoutAttemptId);
45758
- if (!pending) return;
45759
- checkoutAttemptIdRef.current = checkoutAttemptId;
45760
- setFormData(pending.formData);
45761
- setTicketSelections(pending.ticketSelections);
45762
- setTicketsCount(getTicketSelectionTotal(pending.ticketSelections));
45763
- if (pending.selectedEventId) {
45764
- const event = events.find((e) => e.selectionId === pending.selectedEventId) ?? null;
45765
- if (event) setSelectedEvent(event);
45766
- }
45767
- setSelectedAttendanceMode(pending.selectedAttendanceMode ?? null);
45768
- setPaymentSelection(pending.paymentSelection);
45769
- if (registrationStatus === "cancelled") setStep("select-payment");
45770
- else if (registrationStatus === "success") {
45771
- setPendingRegistrationReference(pending.reference);
45772
- setStep("verifying-payment");
45773
- }
45970
+ handleCheckoutReturn(options, deps, checkoutAttemptIdRef);
45774
45971
  }, []);
45775
45972
  useEffect(() => {
45776
45973
  if (verification.status === "completed") {
@@ -45804,7 +46001,11 @@ var init_useEventRegistrationStripeReturn = __esmMin((() => {
45804
46001
  init_ticketSelectionLines();
45805
46002
  eventRegistrationStripeReturnDeps = {
45806
46003
  usePaymentVerification,
45807
- consumeReturnParams: () => consumeSearchParams(["registration", EVENT_REGISTRATION_CHECKOUT_ATTEMPT_PARAM]),
46004
+ consumeReturnParams: () => consumeSearchParams([
46005
+ "registration",
46006
+ EVENT_REGISTRATION_CHECKOUT_ATTEMPT_PARAM,
46007
+ "session_id"
46008
+ ]),
45808
46009
  scrollToBlock,
45809
46010
  cleanupStaleRegistrations,
45810
46011
  clearPendingRegistration,
@@ -45865,7 +46066,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
45865
46066
  options.setStep("submitting");
45866
46067
  try {
45867
46068
  const prepared = prepareSubmitContext(options, target, method, passId, membershipId, selection);
45868
- if (prepared.subject.kind === "wholeSeries" && method === "stripe") return submitWholeSeriesCheckout(options, deps, {
46069
+ if (prepared.subject.kind === "wholeSeries" && method === "stripe") return await submitWholeSeriesCheckout(options, deps, {
45869
46070
  ...prepared,
45870
46071
  subject: prepared.subject
45871
46072
  }, submitOptions);
@@ -45886,7 +46087,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
45886
46087
  claimToken: options.claimToken ?? void 0,
45887
46088
  guests: prepared.guestsPayload
45888
46089
  });
45889
- if (needsOccurrenceCheckout(result, method)) return submitOccurrenceCheckout(options, deps, prepared, result, method, submitOptions);
46090
+ if (needsOccurrenceCheckout(result, method)) return await submitOccurrenceCheckout(options, deps, prepared, result, method, submitOptions);
45890
46091
  options.setRegistrationResult(toRegistrationResult(result));
45891
46092
  options.setStep("success");
45892
46093
  return {
@@ -45969,6 +46170,7 @@ async function submitWholeSeriesCheckout(options, deps, prepared, submitOptions)
45969
46170
  claimToken: options.claimToken ?? void 0,
45970
46171
  discountCode: options.discountCode.trim() || void 0,
45971
46172
  collectionOptionKind: prepared.selectionSnapshot.collectionOptionKind,
46173
+ checkoutAttemptId,
45972
46174
  ...urls
45973
46175
  });
45974
46176
  if (result.scope !== "wholeSeries") throw new Error("Unexpected registration scope for event checkout.");
@@ -47362,7 +47564,10 @@ var init_EventRegistrationWizardActions = __esmMin((() => {
47362
47564
  }));
47363
47565
  //#endregion
47364
47566
  //#region ../commerce/src/purchase/types.ts
47365
- var init_types$1 = __esmMin((() => {})), ORDER_STATUSES, ORDER_PAYMENT_METHODS, CHECKOUT_COMMIT_STATES, ORDER_CHECKOUT_RECONCILIATION_STATES, ORDER_ITEM_RECONCILIATION_STATES, ORDER_ITEM_COMMIT_STATES, RESERVATION_FINALIZATION_STATES, DISCOUNT_REDEMPTION_STATUSES, ORDER_ITEM_KINDS;
47567
+ var init_types$1 = __esmMin((() => {}));
47568
+ var init_allocation = __esmMin((() => {
47569
+ init_src$3();
47570
+ })), ORDER_STATUSES, ORDER_PAYMENT_METHODS, CHECKOUT_COMMIT_STATES, ORDER_CHECKOUT_RECONCILIATION_STATES, ORDER_ITEM_RECONCILIATION_STATES, ORDER_ITEM_COMMIT_STATES, RESERVATION_FINALIZATION_STATES, DISCOUNT_REDEMPTION_STATUSES, ORDER_ITEM_KINDS;
47366
47571
  var init_orderTypes = __esmMin((() => {
47367
47572
  ORDER_STATUSES = [
47368
47573
  "pending",
@@ -47778,6 +47983,7 @@ var init_stripeMinimumCharge = __esmMin((() => {
47778
47983
  THB: 1e3
47779
47984
  };
47780
47985
  }));
47986
+ var init_stripeCheckoutReturnUrl = __esmMin((() => {}));
47781
47987
  var init_stateTransitions = __esmMin((() => {
47782
47988
  init_src$3();
47783
47989
  init_assertNever();
@@ -47786,6 +47992,7 @@ var init_stateTransitions = __esmMin((() => {
47786
47992
  //#region ../commerce/src/purchase/index.ts
47787
47993
  var init_purchase = __esmMin((() => {
47788
47994
  init_types$1();
47995
+ init_allocation();
47789
47996
  init_orderTypes();
47790
47997
  init_orderPlanningTypes();
47791
47998
  init_bookingInstalmentSchedule();
@@ -47839,6 +48046,7 @@ var init_purchase = __esmMin((() => {
47839
48046
  init_settlement();
47840
48047
  init_shopRefundPlanning();
47841
48048
  init_stripeMinimumCharge();
48049
+ init_stripeCheckoutReturnUrl();
47842
48050
  init_stateTransitions();
47843
48051
  }));
47844
48052
  //#endregion
@@ -103685,7 +103893,7 @@ var init_PaymentFailedStep = __esmMin((() => {
103685
103893
  var VerifyingTimeoutStep;
103686
103894
  var init_VerifyingTimeoutStep = __esmMin((() => {
103687
103895
  init_shared();
103688
- VerifyingTimeoutStep = ({ onCheckAgain, supportEmail }) => {
103896
+ VerifyingTimeoutStep = ({ onCheckAgain, supportEmail, title = "Your registration is saved", message = "We're still confirming your payment. This usually resolves within a few minutes. You'll receive a confirmation email once everything is verified." }) => {
103689
103897
  return /* @__PURE__ */ jsx(TerminalPanel, {
103690
103898
  tone: "warning",
103691
103899
  className: "er-center",
@@ -103694,18 +103902,18 @@ var init_VerifyingTimeoutStep = __esmMin((() => {
103694
103902
  variant: "warning",
103695
103903
  children: /* @__PURE__ */ jsx(ClockIcon, {})
103696
103904
  }),
103697
- title: "Your registration is saved",
103905
+ title,
103698
103906
  body: /* @__PURE__ */ jsx("p", {
103699
103907
  className: "er-text--muted er-message",
103700
- children: "We're still confirming your payment. This usually resolves within a few minutes. You'll receive a confirmation email once everything is verified."
103908
+ children: message
103701
103909
  }),
103702
103910
  actionsClassName: "er-button-group",
103703
- actions: /* @__PURE__ */ jsx("button", {
103911
+ actions: onCheckAgain ? /* @__PURE__ */ jsx("button", {
103704
103912
  type: "button",
103705
103913
  onClick: onCheckAgain,
103706
103914
  className: "er-btn er-btn--primary",
103707
103915
  children: "Check Again"
103708
- }),
103916
+ }) : void 0,
103709
103917
  secondaryBody: supportEmail ? /* @__PURE__ */ jsxs("p", {
103710
103918
  className: "er-text--sm er-text--muted er-message",
103711
103919
  children: [
@@ -104007,7 +104215,9 @@ function EventRegistrationTerminalState(props) {
104007
104215
  onRetry: () => wizard.setStep("select-payment")
104008
104216
  });
104009
104217
  case "verifying-timeout": return /* @__PURE__ */ jsx(VerifyingTimeoutStep, {
104010
- onCheckAgain: wizard.verification.retry,
104218
+ onCheckAgain: wizard.verification.status === "timeout" ? wizard.verification.retry : void 0,
104219
+ title: wizard.verification.status === "timeout" ? void 0 : "We’re checking your payment",
104220
+ message: wizard.verification.status === "timeout" ? void 0 : wizard.errorMessage,
104011
104221
  supportEmail: props.supportEmail
104012
104222
  });
104013
104223
  case "success": return wizard.registrationResult ? /* @__PURE__ */ jsx(SuccessStep, {
@@ -111138,25 +111348,34 @@ var init_TabBar = __esmMin((() => {
111138
111348
  }));
111139
111349
  //#endregion
111140
111350
  //#region ../blocks/src/system/runtime/hooks/useCalendarEvents.state.ts
111141
- function calendarEventCacheLoadReducer(_state, action) {
111351
+ function calendarEventCacheLoadReducer(state, action) {
111142
111352
  switch (action.type) {
111143
- case "started": return { kind: "loading" };
111144
- case "succeeded": return { kind: "idle" };
111145
- case "failed": return {
111353
+ case "started": return {
111354
+ kind: "loading",
111355
+ scope: action.scope
111356
+ };
111357
+ case "succeeded": return sameCalendarLoadScope(state, action.scope) ? { kind: "idle" } : state;
111358
+ case "failed": return sameCalendarLoadScope(state, action.scope) ? {
111146
111359
  kind: "error",
111360
+ scope: action.scope,
111147
111361
  error: action.error
111148
- };
111362
+ } : state;
111149
111363
  default: return assertNever$11(action);
111150
111364
  }
111151
111365
  }
111152
- function toCalendarEventCacheLoadError(error) {
111153
- return toError(error, "Unknown error");
111366
+ function projectCalendarLoadState(state, scope) {
111367
+ if (state.kind === "idle" || !sameCalendarLoadScope(state, scope)) return { kind: "idle" };
111368
+ return state.kind === "loading" ? { kind: "loading" } : {
111369
+ kind: "error",
111370
+ error: state.error
111371
+ };
111154
111372
  }
111155
- function isCalendarEventCacheLoading(state) {
111156
- return state.kind === "loading";
111373
+ function sameCalendarLoadScope(state, scope) {
111374
+ if (state.kind === "idle") return false;
111375
+ return state.scope.filtersKey === scope.filtersKey && state.scope.anchorDate.year === scope.anchorDate.year && state.scope.anchorDate.month === scope.anchorDate.month && state.scope.anchorDate.day === scope.anchorDate.day;
111157
111376
  }
111158
- function getCalendarEventCacheError(state) {
111159
- return state.kind === "error" ? state.error : null;
111377
+ function toCalendarEventCacheLoadError(error) {
111378
+ return toError(error, "Unknown error");
111160
111379
  }
111161
111380
  var init_useCalendarEvents_state = __esmMin((() => {
111162
111381
  init_dist$1();
@@ -111170,18 +111389,35 @@ var init_useCalendarEvents_state = __esmMin((() => {
111170
111389
  * Uses the Block API Client for type-safe API calls.
111171
111390
  * Must be used within a BlockApiProvider.
111172
111391
  */
111392
+ async function loadCalendarEventPages(loadPage, request, isCurrent) {
111393
+ const events = [];
111394
+ let afterStartsAt;
111395
+ let afterId;
111396
+ for (;;) {
111397
+ const page = await loadPage({
111398
+ ...request,
111399
+ afterStartsAt,
111400
+ afterId,
111401
+ limit: CALENDAR_FETCH_LIMIT
111402
+ });
111403
+ if (!isCurrent()) return null;
111404
+ events.push(...page);
111405
+ if (page.length < CALENDAR_FETCH_LIMIT) return events;
111406
+ const last = page[page.length - 1];
111407
+ if (!last) return events;
111408
+ if (last.startsAt === afterStartsAt && last.occurrenceId === afterId) throw new Error("Calendar event pagination cursor did not advance");
111409
+ afterStartsAt = last.startsAt;
111410
+ afterId = last.occurrenceId;
111411
+ }
111412
+ }
111173
111413
  /**
111174
111414
  * Generate a cache key for a month
111175
111415
  */
111176
111416
  function getMonthKey(date) {
111177
- return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}`;
111417
+ return `${date.year}-${String(date.month).padStart(2, "0")}`;
111178
111418
  }
111179
- /**
111180
- * Owns calendar viewport state only: selected anchor date, derived visible
111181
- * period, and navigation by the natural unit for the active view.
111182
- */
111183
- function useCalendarViewport({ view = "month", startOfWeek = "monday", initialDate } = {}) {
111184
- const [viewDate, setViewDate] = useState(() => initialDate ?? /* @__PURE__ */ new Date());
111419
+ function useCalendarViewport({ view = "month", startOfWeek = "monday", initialDate }) {
111420
+ const [viewDate, setViewDate] = useState(initialDate);
111185
111421
  const viewport = useMemo(() => buildCalendarViewport({
111186
111422
  view,
111187
111423
  anchorDate: viewDate,
@@ -111206,15 +111442,44 @@ function useCalendarViewport({ view = "month", startOfWeek = "monday", initialDa
111206
111442
  goToPrevious,
111207
111443
  goToNext,
111208
111444
  goToToday: useCallback(() => {
111209
- setViewDate(/* @__PURE__ */ new Date());
111210
- }, [])
111445
+ setViewDate(initialDate);
111446
+ }, [initialDate])
111211
111447
  };
111212
111448
  }
111449
+ function addEventsToCalendarCache(cache, events, timeZone) {
111450
+ for (const event of events) {
111451
+ const monthKey = getMonthKey(getLocalScheduleDate(new Date(event.startsAt), timeZone));
111452
+ const existing = cache.get(monthKey) ?? [];
111453
+ if (!existing.some((cachedEvent) => cachedEvent.id === event.id)) cache.set(monthKey, [...existing, event]);
111454
+ }
111455
+ }
111456
+ function useInitiallySeededCalendarCache(initialEvents, timeZone) {
111457
+ const cacheRef = useRef(/* @__PURE__ */ new Map());
111458
+ const seededRef = useRef(false);
111459
+ if (!seededRef.current) {
111460
+ addEventsToCalendarCache(cacheRef.current, initialEvents, timeZone);
111461
+ seededRef.current = true;
111462
+ }
111463
+ return cacheRef;
111464
+ }
111465
+ function readEventsFromCalendarCache(cache, viewDate) {
111466
+ const allEvents = [];
111467
+ for (let offset = -1; offset <= 1; offset += 1) {
111468
+ const monthEvents = cache.get(getMonthKey(addMonths(viewDate, offset))) ?? [];
111469
+ allEvents.push(...monthEvents);
111470
+ }
111471
+ const seen = /* @__PURE__ */ new Set();
111472
+ return allEvents.filter((event) => {
111473
+ if (seen.has(event.id)) return false;
111474
+ seen.add(event.id);
111475
+ return true;
111476
+ }).sort((left, right) => new Date(left.startsAt).getTime() - new Date(right.startsAt).getTime());
111477
+ }
111213
111478
  /**
111214
111479
  * Owns event loading and month-window caching for a supplied viewport anchor.
111215
111480
  * It does not decide navigation semantics or visible calendar days.
111216
111481
  */
111217
- function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1, filters, stage }) {
111482
+ function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1, filters, stage, timeZone }) {
111218
111483
  const { getPublicEvents } = useBlockApi();
111219
111484
  const [loadState, dispatchLoadState] = useReducer(calendarEventCacheLoadReducer, { kind: "idle" });
111220
111485
  const [cacheVersion, setCacheVersion] = useState(0);
@@ -111226,7 +111491,7 @@ function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1
111226
111491
  filters?.staffMemberId,
111227
111492
  filters?.venueId
111228
111493
  ]);
111229
- const cacheRef = useRef(/* @__PURE__ */ new Map());
111494
+ const cacheRef = useInitiallySeededCalendarCache(initialEvents, timeZone);
111230
111495
  const loadedMonthsRef = useRef(/* @__PURE__ */ new Set());
111231
111496
  const fetchingRef = useRef(/* @__PURE__ */ new Set());
111232
111497
  const requestIdRef = useRef(0);
@@ -111238,24 +111503,26 @@ function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1
111238
111503
  loadedMonthsRef.current = /* @__PURE__ */ new Set();
111239
111504
  fetchingRef.current = /* @__PURE__ */ new Set();
111240
111505
  requestIdRef.current += 1;
111241
- if (initialEvents.length > 0) for (const event of initialEvents) {
111242
- const monthKey = getMonthKey(new Date(event.startsAt));
111243
- const existing = cacheRef.current.get(monthKey) || [];
111244
- if (!existing.some((e) => e.id === event.id)) cacheRef.current.set(monthKey, [...existing, event]);
111245
- }
111506
+ addEventsToCalendarCache(cacheRef.current, initialEvents, timeZone);
111246
111507
  setCacheVersion((v) => v + 1);
111247
- }, [filtersKey, initialEvents]);
111248
- const fetchEventsForRange = useCallback(async (from, to, targetMonths) => {
111508
+ }, [
111509
+ filtersKey,
111510
+ initialEvents,
111511
+ timeZone
111512
+ ]);
111513
+ const fetchEventsForRange = useCallback(async (from, to, targetMonths, scope) => {
111249
111514
  const monthsToFetch = targetMonths.filter((m) => !loadedMonthsRef.current.has(m) && !fetchingRef.current.has(m));
111250
111515
  if (monthsToFetch.length === 0) return;
111251
111516
  monthsToFetch.forEach((m) => fetchingRef.current.add(m));
111252
111517
  const currentRequestId = ++requestIdRef.current;
111253
- dispatchLoadState({ type: "started" });
111518
+ dispatchLoadState({
111519
+ type: "started",
111520
+ scope
111521
+ });
111254
111522
  try {
111255
- const result = await getPublicEvents({
111523
+ const result = await loadCalendarEventPages(getPublicEvents, {
111256
111524
  from,
111257
111525
  to,
111258
- limit: CALENDAR_FETCH_LIMIT,
111259
111526
  stage,
111260
111527
  detailLevel: "listing",
111261
111528
  eventSurface: filters?.eventSurface,
@@ -111264,23 +111531,27 @@ function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1
111264
111531
  categoryIds: filters?.categoryIds,
111265
111532
  staffMemberId: filters?.staffMemberId,
111266
111533
  venueId: filters?.venueId
111267
- });
111268
- if (currentRequestId === requestIdRef.current) {
111269
- for (const event of result) {
111270
- const monthKey = getMonthKey(new Date(event.startsAt));
111271
- const existing = cacheRef.current.get(monthKey) || [];
111272
- if (!existing.some((e) => e.id === event.id)) cacheRef.current.set(monthKey, [...existing, event]);
111273
- }
111274
- for (const month of monthsToFetch) {
111275
- loadedMonthsRef.current.add(month);
111276
- if (!cacheRef.current.has(month)) cacheRef.current.set(month, []);
111277
- }
111278
- setCacheVersion((v) => v + 1);
111279
- dispatchLoadState({ type: "succeeded" });
111534
+ }, () => currentRequestId === requestIdRef.current);
111535
+ if (result === null) return;
111536
+ for (const event of result) {
111537
+ const monthKey = getMonthKey(getLocalScheduleDate(new Date(event.startsAt), timeZone));
111538
+ const existing = cacheRef.current.get(monthKey) || [];
111539
+ if (!existing.some((e) => e.id === event.id)) cacheRef.current.set(monthKey, [...existing, event]);
111540
+ }
111541
+ for (const month of monthsToFetch) {
111542
+ loadedMonthsRef.current.add(month);
111543
+ if (!cacheRef.current.has(month)) cacheRef.current.set(month, []);
111280
111544
  }
111545
+ setCacheVersion((v) => v + 1);
111546
+ dispatchLoadState({
111547
+ type: "succeeded",
111548
+ scope
111549
+ });
111281
111550
  } catch (err) {
111551
+ monthsToFetch.forEach((m) => fetchingRef.current.delete(m));
111282
111552
  if (currentRequestId === requestIdRef.current) dispatchLoadState({
111283
111553
  type: "failed",
111554
+ scope,
111284
111555
  error: toCalendarEventCacheLoadError(err)
111285
111556
  });
111286
111557
  } finally {
@@ -111294,7 +111565,8 @@ function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1
111294
111565
  filters?.scheduleScope,
111295
111566
  filters?.staffMemberId,
111296
111567
  filters?.venueId,
111297
- stage
111568
+ stage,
111569
+ timeZone
111298
111570
  ]);
111299
111571
  const ensureEventsLoaded = useCallback((date) => {
111300
111572
  const targetMonths = [];
@@ -111304,74 +111576,71 @@ function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1
111304
111576
  }
111305
111577
  const unloadedMonths = targetMonths.filter((m) => !loadedMonthsRef.current.has(m) && !fetchingRef.current.has(m));
111306
111578
  if (unloadedMonths.length > 0) {
111307
- const range = getThreeMonthRange(date);
111308
- fetchEventsForRange(range.from, range.to, unloadedMonths);
111579
+ const startDate = getStartOfMonth(addMonths(date, -preloadMonths));
111580
+ const endDate = getEndOfMonth(addMonths(date, preloadMonths));
111581
+ const range = buildBookingUtcDateWindow({
111582
+ startDate: formatLocalScheduleDate(startDate),
111583
+ endDate: formatLocalScheduleDate(endDate),
111584
+ timeZone
111585
+ });
111586
+ const scope = {
111587
+ anchorDate: date,
111588
+ filtersKey
111589
+ };
111590
+ fetchEventsForRange(range.startAt.toISOString(), (/* @__PURE__ */ new Date(range.endExclusive.getTime() - 1)).toISOString(), unloadedMonths, scope);
111309
111591
  }
111310
- }, [preloadMonths, fetchEventsForRange]);
111592
+ }, [
111593
+ preloadMonths,
111594
+ fetchEventsForRange,
111595
+ filtersKey,
111596
+ timeZone
111597
+ ]);
111311
111598
  useEffect(() => {
111312
111599
  ensureEventsLoaded(viewDate);
111313
111600
  }, [viewDate, ensureEventsLoaded]);
111601
+ const retryCurrentView = useCallback(() => {
111602
+ ensureEventsLoaded(viewDate);
111603
+ }, [ensureEventsLoaded, viewDate]);
111314
111604
  return {
111315
- events: useMemo(() => {
111316
- const allEvents = [];
111317
- for (let i = -1; i <= 1; i++) {
111318
- const monthKey = getMonthKey(addMonths(viewDate, i));
111319
- const monthEvents = cacheRef.current.get(monthKey) || [];
111320
- allEvents.push(...monthEvents);
111321
- }
111322
- const seen = /* @__PURE__ */ new Set();
111323
- return allEvents.filter((e) => {
111324
- if (seen.has(e.id)) return false;
111325
- seen.add(e.id);
111326
- return true;
111327
- }).sort((a, b) => new Date(a.startsAt).getTime() - new Date(b.startsAt).getTime());
111328
- }, [viewDate, cacheVersion]),
111329
- loading: isCalendarEventCacheLoading(loadState),
111330
- error: getCalendarEventCacheError(loadState)
111605
+ events: useMemo(() => readEventsFromCalendarCache(cacheRef.current, viewDate), [viewDate, cacheVersion]),
111606
+ loadState: projectCalendarLoadState(loadState, useMemo(() => ({
111607
+ anchorDate: viewDate,
111608
+ filtersKey
111609
+ }), [filtersKey, viewDate])),
111610
+ retryCurrentView
111331
111611
  };
111332
111612
  }
111333
- /**
111334
- * Hook for calendar event management with month-based caching.
111335
- *
111336
- * Pre-fetches 3 months (previous, current, next) and caches by month.
111337
- * Navigation within cached range is instant; fetches at boundaries.
111338
- *
111339
- * @example
111340
- * ```tsx
111341
- * const { events, viewDate, loading, goToPrevious, goToNext } = useCalendarEvents({
111342
- * siteId: 'site-123',
111343
- * initialEvents: serverEvents,
111344
- * });
111345
- * ```
111346
- */
111347
- function useCalendarEvents({ siteId: _siteId, initialEvents = [], view = "month", startOfWeek = "monday", preloadMonths = 1, filters, stage }) {
111613
+ function useCalendarEvents({ siteId: _siteId, initialEvents = [], view = "month", startOfWeek = "monday", preloadMonths = 1, filters, stage, calendarContext }) {
111348
111614
  const { viewDate, viewport, goToDate, goToPrevious, goToNext, goToToday } = useCalendarViewport({
111349
111615
  view,
111350
- startOfWeek
111616
+ startOfWeek,
111617
+ initialDate: calendarContext.initialToday
111351
111618
  });
111352
- const { events, loading, error } = useCalendarEventCache({
111619
+ const { events, loadState, retryCurrentView } = useCalendarEventCache({
111353
111620
  viewDate,
111354
111621
  initialEvents,
111355
111622
  preloadMonths,
111356
111623
  filters,
111357
- stage
111624
+ stage,
111625
+ timeZone: calendarContext.timeZone
111358
111626
  });
111359
111627
  return {
111360
111628
  events,
111361
111629
  viewDate,
111362
111630
  viewport,
111363
- loading,
111364
- error,
111631
+ loadState,
111365
111632
  setViewDate: useCallback((date) => {
111366
111633
  goToDate(date);
111367
111634
  }, [goToDate]),
111368
111635
  goToPrevious,
111369
111636
  goToNext,
111370
- goToToday
111637
+ goToToday,
111638
+ retryCurrentView
111371
111639
  };
111372
111640
  }
111373
111641
  var CALENDAR_FETCH_LIMIT;
111374
111642
  var init_useCalendarEvents = __esmMin((() => {
111643
+ init_src$3();
111375
111644
  init_utils$3();
111376
111645
  init_api();
111377
111646
  init_listOptions();
@@ -111433,9 +111702,9 @@ var CalendarDayCell;
111433
111702
  var init_CalendarDayCell = __esmMin((() => {
111434
111703
  init_utils$3();
111435
111704
  init_EventModalContext();
111436
- CalendarDayCell = ({ date, events, isCurrentMonth }) => {
111705
+ CalendarDayCell = ({ date, events, isCurrentMonth, today: currentDate }) => {
111437
111706
  const { openEventModal, openDayModal } = useEventModal();
111438
- const today = isToday(date);
111707
+ const today = isToday(date, currentDate);
111439
111708
  const dayClasses = [
111440
111709
  "event-calendar-day",
111441
111710
  !isCurrentMonth && "event-calendar-day--other-month",
@@ -111451,7 +111720,7 @@ var init_CalendarDayCell = __esmMin((() => {
111451
111720
  className: dayClasses,
111452
111721
  children: [/* @__PURE__ */ jsx("div", {
111453
111722
  className: "event-calendar-day-number",
111454
- children: date.getDate()
111723
+ children: date.day
111455
111724
  }), /* @__PURE__ */ jsxs("div", {
111456
111725
  className: "event-calendar-events",
111457
111726
  children: [events.slice(0, 3).map((event) => {
@@ -111563,7 +111832,7 @@ var init_EventDetailModal = __esmMin((() => {
111563
111832
  * Clicking an event triggers onSelectEvent (typically opens EventDetailModal).
111564
111833
  */
111565
111834
  function DayEventsModal({ date, events, showCapacity, onClose, onSelectEvent, portalRoot }) {
111566
- const formattedDate = formatDate$2(date.toISOString());
111835
+ const formattedDate = formatDate$2(`${formatLocalScheduleDate(date)}T12:00:00Z`);
111567
111836
  return /* @__PURE__ */ jsxs(ModalShell, {
111568
111837
  title: formattedDate,
111569
111838
  titleId: "ec-day-modal-title",
@@ -111598,6 +111867,7 @@ function DayEventsModal({ date, events, showCapacity, onClose, onSelectEvent, po
111598
111867
  });
111599
111868
  }
111600
111869
  var init_DayEventsModal = __esmMin((() => {
111870
+ init_src$3();
111601
111871
  init_AgendaEventCard();
111602
111872
  init_utils$3();
111603
111873
  init_ModalShell();
@@ -111718,7 +111988,8 @@ function toEventCombinedControllerProps(props) {
111718
111988
  buttonVariant: props.render.display.buttonVariant,
111719
111989
  buttonText: props.render.display.buttonText,
111720
111990
  emptyMessage: props.render.display.emptyMessage,
111721
- className: props.render.display.className ?? void 0
111991
+ className: props.render.display.className ?? void 0,
111992
+ calendarContext: props.render.hydration.calendarContext
111722
111993
  };
111723
111994
  }
111724
111995
  var EventCombinedClient, EventCombinedIslandClient;
@@ -111741,7 +112012,7 @@ var init_EventCombined_client = __esmMin((() => {
111741
112012
  EventCombinedClient = ({ events: initialEvents, siteId, stage, listLayout = "stack", listColumns = "3", eventsPerPage = 12, paginationAction = {
111742
112013
  kind: "loadMore",
111743
112014
  label: "Load more events"
111744
- }, startOfWeek = "monday", calendarTabViews = "both", defaultCalendarView, showFilters, showCategoryFilter = "auto", showVenueFilter, showStaffFilter, eventSurface, filterEventPresets, scheduleScope, filterCategoryIds, filterStaffMemberId, filterVenueId, showVenue, showMap, showCapacity, cardRole, buttonVariant = "primary", buttonText = "Book", emptyMessage = "No upcoming events scheduled.", className }) => {
112015
+ }, startOfWeek = "monday", calendarTabViews = "both", defaultCalendarView, showFilters, showCategoryFilter = "auto", showVenueFilter, showStaffFilter, eventSurface, filterEventPresets, scheduleScope, filterCategoryIds, filterStaffMemberId, filterVenueId, showVenue, showMap, showCapacity, cardRole, buttonVariant = "primary", buttonText = "Book", emptyMessage = "No upcoming events scheduled.", className, calendarContext }) => {
111745
112016
  const fetchInitialEventsOnMount = initialEvents == null;
111746
112017
  const resolvedShowFilters = showFilters ?? true;
111747
112018
  const resolvedShowVenueFilter = showVenueFilter ?? false;
@@ -111799,7 +112070,7 @@ var init_EventCombined_client = __esmMin((() => {
111799
112070
  pageSize,
111800
112071
  stage
111801
112072
  });
111802
- const { events: calendarEventsRaw, viewDate, viewport, loading: calendarLoading, goToPrevious, goToNext, goToToday } = useCalendarEvents({
112073
+ const { events: calendarEventsRaw, viewDate, viewport, loadState: calendarLoadState, goToPrevious, goToNext, goToToday } = useCalendarEvents({
111803
112074
  siteId,
111804
112075
  initialEvents: useMemo(() => {
111805
112076
  return getEventRuntimeFiltersKey(initialListFilters) === getEventRuntimeFiltersKey(listFilters) ? initialEvents ?? [] : [];
@@ -111812,9 +112083,10 @@ var init_EventCombined_client = __esmMin((() => {
111812
112083
  startOfWeek,
111813
112084
  preloadMonths: 1,
111814
112085
  filters: listFilters,
111815
- stage
112086
+ stage,
112087
+ calendarContext
111816
112088
  });
111817
- const eventsByDate = useMemo(() => groupEventsByDate(calendarEventsRaw), [calendarEventsRaw]);
112089
+ const eventsByDate = useMemo(() => groupEventsByDate(calendarEventsRaw, calendarContext.timeZone), [calendarContext.timeZone, calendarEventsRaw]);
111818
112090
  const dayNames = useMemo(() => getOrderedDayNames(startOfWeek), [startOfWeek]);
111819
112091
  const tabs = [{
111820
112092
  id: "list",
@@ -111916,7 +112188,7 @@ var init_EventCombined_client = __esmMin((() => {
111916
112188
  }),
111917
112189
  /* @__PURE__ */ jsxs("h3", {
111918
112190
  className: "event-calendar-title",
111919
- children: [viewport.title, calendarLoading && /* @__PURE__ */ jsx("span", {
112191
+ children: [viewport.title, calendarLoadState.kind === "loading" && /* @__PURE__ */ jsx("span", {
111920
112192
  className: "rb-ml-2 rb-caption status-muted",
111921
112193
  children: "(loading...)"
111922
112194
  })]
@@ -111955,7 +112227,9 @@ var init_EventCombined_client = __esmMin((() => {
111955
112227
  days: viewport.days,
111956
112228
  events: calendarEventsRaw,
111957
112229
  emptyMessage: "No events scheduled",
111958
- showCapacity: resolvedShowCapacity
112230
+ showCapacity: resolvedShowCapacity,
112231
+ calendarTimeZone: calendarContext.timeZone,
112232
+ today: calendarContext.initialToday
111959
112233
  }) : /* @__PURE__ */ jsxs("div", {
111960
112234
  className: "event-calendar-container",
111961
112235
  children: [/* @__PURE__ */ jsx("div", {
@@ -111972,12 +112246,13 @@ var init_EventCombined_client = __esmMin((() => {
111972
112246
  return /* @__PURE__ */ jsx(CalendarDayCell, {
111973
112247
  date,
111974
112248
  events: dayEvents,
111975
- isCurrentMonth: date.getMonth() === viewDate.getMonth()
112249
+ isCurrentMonth: date.month === viewDate.month,
112250
+ today: calendarContext.initialToday
111976
112251
  }, dateKey);
111977
112252
  })
111978
112253
  })]
111979
112254
  }),
111980
- calendarEventsRaw.length === 0 && !calendarLoading && /* @__PURE__ */ jsx("p", {
112255
+ calendarEventsRaw.length === 0 && calendarLoadState.kind === "idle" && /* @__PURE__ */ jsx("p", {
111981
112256
  className: "event-calendar-empty",
111982
112257
  children: emptyMessage
111983
112258
  })
@@ -112010,15 +112285,17 @@ var WeekTimetableView, TimeRail, TimetableDayColumn, TimetableEventButton;
112010
112285
  var init_WeekTimetableView = __esmMin((() => {
112011
112286
  init_EventModalContext();
112012
112287
  init_timetableModel();
112013
- WeekTimetableView = ({ viewDate, events, startOfWeek, showCapacity, emptyMessage = "No classes scheduled" }) => {
112288
+ WeekTimetableView = ({ viewDate, events, startOfWeek, today, showCapacity, emptyMessage = "No classes scheduled" }) => {
112014
112289
  const { openEventModal } = useEventModal();
112015
112290
  const model = useMemo(() => buildTimetableModel({
112016
112291
  events,
112017
112292
  viewDate,
112018
- startOfWeek
112293
+ startOfWeek,
112294
+ today
112019
112295
  }), [
112020
112296
  events,
112021
112297
  startOfWeek,
112298
+ today,
112022
112299
  viewDate
112023
112300
  ]);
112024
112301
  const [selectedDayKey, setSelectedDayKey] = useState(() => model.days.find((day) => day.isToday)?.dateKey ?? model.days[0]?.dateKey ?? "");
@@ -112198,21 +112475,6 @@ function buildDisplayFilterParams(display) {
112198
112475
  filterVenueId: display.filterVenueId
112199
112476
  });
112200
112477
  }
112201
- function CalendarChevron({ direction }) {
112202
- return /* @__PURE__ */ jsx("svg", {
112203
- width: "20",
112204
- height: "20",
112205
- fill: "none",
112206
- stroke: "currentColor",
112207
- strokeWidth: 2,
112208
- viewBox: "0 0 24 24",
112209
- children: /* @__PURE__ */ jsx("path", {
112210
- strokeLinecap: "round",
112211
- strokeLinejoin: "round",
112212
- d: direction === "previous" ? "M15 19l-7-7 7-7" : "M9 5l7 7-7 7"
112213
- })
112214
- });
112215
- }
112216
112478
  var EventCalendarClient, EventCalendarWeekBoardClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarChrome;
112217
112479
  var init_EventCalendar_client = __esmMin((() => {
112218
112480
  init_EventCalendar_interactive();
@@ -112221,6 +112483,7 @@ var init_EventCalendar_client = __esmMin((() => {
112221
112483
  init_useCalendarEvents();
112222
112484
  init_useEventFilters();
112223
112485
  init_CalendarDayCell();
112486
+ init_CalendarNavigationChevron();
112224
112487
  init_EventFilters();
112225
112488
  init_utils$3();
112226
112489
  init_EventModalContext();
@@ -112260,38 +112523,75 @@ var init_EventCalendar_client = __esmMin((() => {
112260
112523
  buttonVariant: display.buttonVariant,
112261
112524
  buttonText: display.buttonText,
112262
112525
  emptyMessage: display.emptyMessage,
112263
- className: display.className ?? void 0
112526
+ className: display.className ?? void 0,
112527
+ calendarContext: hydration.calendarContext
112264
112528
  });
112265
112529
  if (display.displayMode === "list") return /* @__PURE__ */ jsx(EventListingController, { render: buildEventCalendarListingRender(render) });
112266
112530
  if (display.displayMode === "timetable") return /* @__PURE__ */ jsx(EventCalendarTimetableClient, { render });
112267
- if (display.displayMode === "week-board") return /* @__PURE__ */ jsx(EventCalendarWeekBoardClient, { display });
112531
+ if (display.displayMode === "week-board") return /* @__PURE__ */ jsx(EventCalendarWeekBoardClient, { render });
112268
112532
  return /* @__PURE__ */ jsx(EventCalendarGridClient, { render });
112269
112533
  };
112270
- EventCalendarWeekBoardClient = ({ display }) => {
112271
- const days = useMemo(() => getWeekCalendarDayTuple(/* @__PURE__ */ new Date(), display.startOfWeek), [display.startOfWeek]);
112272
- return /* @__PURE__ */ jsx(WeekBoardView, { ...buildWeekBoardViewProps(display, days) });
112534
+ EventCalendarWeekBoardClient = ({ render }) => {
112535
+ const { display, hydration } = render;
112536
+ const filters = useMemo(() => buildDisplayFilterParams(display), [
112537
+ display.eventSurface,
112538
+ display.filterCategoryIds,
112539
+ display.filterEventPresets,
112540
+ display.filterStaffMemberId,
112541
+ display.filterVenueId,
112542
+ display.scheduleScope
112543
+ ]);
112544
+ const initialEvents = usePrefetchedCalendarEvents(display, filters);
112545
+ const { events, viewport, loadState, goToPrevious, goToNext, goToToday, retryCurrentView } = useCalendarEvents({
112546
+ siteId: hydration.siteId,
112547
+ initialEvents,
112548
+ view: "week",
112549
+ startOfWeek: display.startOfWeek,
112550
+ preloadMonths: 1,
112551
+ filters,
112552
+ stage: hydration.stage,
112553
+ calendarContext: hydration.calendarContext
112554
+ });
112555
+ const weekBoardLoadState = loadState.kind === "error" ? {
112556
+ kind: "error",
112557
+ onRetry: retryCurrentView
112558
+ } : loadState;
112559
+ const navigation = {
112560
+ kind: "interactive",
112561
+ ...buildWeekBoardNavigationState(viewport, hydration.calendarContext.initialToday),
112562
+ loadState: weekBoardLoadState,
112563
+ onPrevious: goToPrevious,
112564
+ onNext: goToNext,
112565
+ onToday: goToToday
112566
+ };
112567
+ return /* @__PURE__ */ jsx(WeekBoardView, { ...buildWeekBoardViewProps({
112568
+ ...display,
112569
+ calendarTimeZone: hydration.calendarContext.timeZone,
112570
+ today: hydration.calendarContext.initialToday
112571
+ }, viewport.days, navigation, events) });
112273
112572
  };
112274
112573
  EventCalendarTimetableClient = ({ render }) => {
112275
112574
  const { display, hydration } = render;
112276
112575
  const { filtersNode, listFilters } = useEventCalendarFilterState(display);
112277
112576
  const calendarInitialEvents = usePrefetchedCalendarEvents(display, listFilters);
112278
- const { events, viewDate, viewport, loading, error, goToPrevious, goToNext, goToToday } = useCalendarEvents({
112577
+ const { events, viewDate, viewport, loadState, retryCurrentView, goToPrevious, goToNext, goToToday } = useCalendarEvents({
112279
112578
  siteId: hydration.siteId,
112280
112579
  initialEvents: calendarInitialEvents,
112281
112580
  view: "week",
112282
112581
  startOfWeek: display.startOfWeek,
112283
112582
  preloadMonths: 1,
112284
112583
  filters: listFilters,
112285
- stage: hydration.stage
112584
+ stage: hydration.stage,
112585
+ calendarContext: hydration.calendarContext
112286
112586
  });
112287
112587
  return /* @__PURE__ */ jsxs(EventModalProvider, { children: [/* @__PURE__ */ jsx(EventCalendarChrome, {
112288
112588
  display,
112289
112589
  calendarView: "week",
112290
112590
  className: "event-calendar--timetable",
112291
- error,
112591
+ loadState,
112292
112592
  filters: filtersNode,
112293
112593
  headerTitle: viewport.title,
112294
- loading,
112594
+ onRetry: retryCurrentView,
112295
112595
  onNext: goToNext,
112296
112596
  onPrevious: goToPrevious,
112297
112597
  onToday: goToToday,
@@ -112300,7 +112600,8 @@ var init_EventCalendar_client = __esmMin((() => {
112300
112600
  events,
112301
112601
  startOfWeek: display.startOfWeek,
112302
112602
  emptyMessage: display.emptyMessage,
112303
- showCapacity: display.showCapacity
112603
+ showCapacity: display.showCapacity,
112604
+ today: hydration.calendarContext.initialToday
112304
112605
  })
112305
112606
  }), /* @__PURE__ */ jsx(EventModals, {
112306
112607
  cardRole: display.cardRole,
@@ -112314,24 +112615,25 @@ var init_EventCalendar_client = __esmMin((() => {
112314
112615
  const calendarView = display.defaultCalendarView;
112315
112616
  const { filtersNode, listFilters } = useEventCalendarFilterState(display);
112316
112617
  const calendarInitialEvents = usePrefetchedCalendarEvents(display, listFilters);
112317
- const { events, viewDate, viewport, loading, error, goToPrevious, goToNext, goToToday } = useCalendarEvents({
112618
+ const { events, viewDate, viewport, loadState, retryCurrentView, goToPrevious, goToNext, goToToday } = useCalendarEvents({
112318
112619
  siteId: hydration.siteId,
112319
112620
  initialEvents: calendarInitialEvents,
112320
112621
  view: calendarView,
112321
112622
  startOfWeek: display.startOfWeek,
112322
112623
  preloadMonths: 1,
112323
112624
  filters: listFilters,
112324
- stage: hydration.stage
112625
+ stage: hydration.stage,
112626
+ calendarContext: hydration.calendarContext
112325
112627
  });
112326
- const eventsByDate = useMemo(() => groupEventsByDate(events), [events]);
112628
+ const eventsByDate = useMemo(() => groupEventsByDate(events, hydration.calendarContext.timeZone), [events, hydration.calendarContext.timeZone]);
112327
112629
  const dayNames = useMemo(() => getOrderedDayNames(display.startOfWeek), [display.startOfWeek]);
112328
112630
  return /* @__PURE__ */ jsxs(EventModalProvider, { children: [/* @__PURE__ */ jsxs(EventCalendarChrome, {
112329
112631
  display,
112330
112632
  calendarView,
112331
- error,
112633
+ loadState,
112332
112634
  filters: filtersNode,
112333
112635
  headerTitle: viewport.title,
112334
- loading,
112636
+ onRetry: retryCurrentView,
112335
112637
  onNext: goToNext,
112336
112638
  onPrevious: goToPrevious,
112337
112639
  onToday: goToToday,
@@ -112339,7 +112641,9 @@ var init_EventCalendar_client = __esmMin((() => {
112339
112641
  days: viewport.days,
112340
112642
  events,
112341
112643
  emptyMessage: display.emptyMessage,
112342
- showCapacity: display.showCapacity
112644
+ showCapacity: display.showCapacity,
112645
+ calendarTimeZone: hydration.calendarContext.timeZone,
112646
+ today: hydration.calendarContext.initialToday
112343
112647
  }) : /* @__PURE__ */ jsxs("div", {
112344
112648
  className: "event-calendar-container",
112345
112649
  children: [/* @__PURE__ */ jsx("div", {
@@ -112356,11 +112660,12 @@ var init_EventCalendar_client = __esmMin((() => {
112356
112660
  return /* @__PURE__ */ jsx(CalendarDayCell, {
112357
112661
  date,
112358
112662
  events: dayEvents,
112359
- isCurrentMonth: date.getMonth() === viewDate.getMonth()
112663
+ isCurrentMonth: date.month === viewDate.month,
112664
+ today: hydration.calendarContext.initialToday
112360
112665
  }, dateKey);
112361
112666
  })
112362
112667
  })]
112363
- }), viewport.kind === "month" && events.length === 0 && !loading && !error ? /* @__PURE__ */ jsx("p", {
112668
+ }), viewport.kind === "month" && events.length === 0 && loadState.kind === "idle" ? /* @__PURE__ */ jsx("p", {
112364
112669
  className: "event-calendar-empty",
112365
112670
  children: display.emptyMessage
112366
112671
  }) : null]
@@ -112371,7 +112676,7 @@ var init_EventCalendar_client = __esmMin((() => {
112371
112676
  showCapacity: display.showCapacity
112372
112677
  })] });
112373
112678
  };
112374
- EventCalendarChrome = ({ children, display, calendarView, className, error, filters, headerTitle, loading, onNext, onPrevious, onToday }) => /* @__PURE__ */ jsxs("div", {
112679
+ EventCalendarChrome = ({ children, display, calendarView, className, loadState, filters, headerTitle, onRetry, onNext, onPrevious, onToday }) => /* @__PURE__ */ jsxs("div", {
112375
112680
  className: [
112376
112681
  "event-calendar",
112377
112682
  className,
@@ -112390,11 +112695,11 @@ var init_EventCalendar_client = __esmMin((() => {
112390
112695
  onClick: onPrevious,
112391
112696
  className: "event-calendar-nav-btn",
112392
112697
  "aria-label": calendarView === "week" ? "Previous week" : "Previous month",
112393
- children: /* @__PURE__ */ jsx(CalendarChevron, { direction: "previous" })
112698
+ children: /* @__PURE__ */ jsx(CalendarNavigationChevron, { direction: "previous" })
112394
112699
  }),
112395
112700
  /* @__PURE__ */ jsxs("h3", {
112396
112701
  className: "event-calendar-title",
112397
- children: [headerTitle, loading ? /* @__PURE__ */ jsx("span", {
112702
+ children: [headerTitle, loadState.kind === "loading" ? /* @__PURE__ */ jsx("span", {
112398
112703
  className: "rb-ml-2 rb-caption status-muted",
112399
112704
  children: "(loading...)"
112400
112705
  }) : null]
@@ -112404,7 +112709,7 @@ var init_EventCalendar_client = __esmMin((() => {
112404
112709
  onClick: onNext,
112405
112710
  className: "event-calendar-nav-btn",
112406
112711
  "aria-label": calendarView === "week" ? "Next week" : "Next month",
112407
- children: /* @__PURE__ */ jsx(CalendarChevron, { direction: "next" })
112712
+ children: /* @__PURE__ */ jsx(CalendarNavigationChevron, { direction: "next" })
112408
112713
  })
112409
112714
  ]
112410
112715
  }), /* @__PURE__ */ jsx("button", {
@@ -112418,14 +112723,14 @@ var init_EventCalendar_client = __esmMin((() => {
112418
112723
  })]
112419
112724
  }),
112420
112725
  children,
112421
- error ? /* @__PURE__ */ jsxs("div", {
112726
+ loadState.kind === "error" ? /* @__PURE__ */ jsxs("div", {
112422
112727
  className: "rb-mt-4 rb-text-center",
112423
112728
  children: [/* @__PURE__ */ jsx("p", {
112424
112729
  className: "status-error rb-caption rb-mb-2",
112425
112730
  children: "Failed to load events"
112426
112731
  }), /* @__PURE__ */ jsx("button", {
112427
112732
  type: "button",
112428
- onClick: onToday,
112733
+ onClick: onRetry,
112429
112734
  className: themeButtonClassName({
112430
112735
  variant: display.buttonVariant,
112431
112736
  size: "sm"