@riverbankcms/sdk 0.135.1 → 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 (152) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +4 -8
  3. package/dist/{PreviewEditorSidebar-D4p_5TdY.mjs → PreviewEditorSidebar-BU5ZlhQR.mjs} +4 -4
  4. package/dist/{PreviewEditorUI-D0cRoTX1.mjs → PreviewEditorUI-9XkHL-bC.mjs} +3 -3
  5. package/dist/{PreviewQueryProvider-DcgaESkm.mjs → PreviewQueryProvider-wbEpXryy.mjs} +1 -1
  6. package/dist/{SdkPreviewModeRuntime-BKLtM3Nz.mjs → SdkPreviewModeRuntime-CnWmj-2B.mjs} +50 -99
  7. package/dist/{SiteChromeCustomizeContext-61X2m7QV.mjs → SiteChromeCustomizeContext-B6d5zkog.mjs} +2299 -1149
  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/data/index.d.ts +2 -0
  26. package/dist/_dts/blocks/src/system/data/publicLoaderCachePolicy.d.ts +78 -0
  27. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +2 -18
  28. package/dist/_dts/blocks/src/system/manifest/validation.d.ts +103 -16
  29. package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +1 -1
  30. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +2 -1
  31. package/dist/_dts/blocks/src/system/runtime/api/endpoints.d.ts +8 -0
  32. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  33. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +19 -0
  34. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +52 -0
  35. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +24 -0
  36. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.d.ts +44 -18
  37. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.state.d.ts +20 -3
  38. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/VerifyingTimeoutStep.d.ts +3 -1
  39. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.d.ts +1 -0
  40. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCalendar.client.d.ts +2 -2
  41. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCalendar.interactive.d.ts +40 -0
  42. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +2 -0
  43. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +43 -0
  44. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarDayCell.d.ts +3 -1
  45. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarNavigationChevron.d.ts +4 -0
  46. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/DayEventsModal.d.ts +2 -1
  47. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventModalContext.d.ts +3 -2
  48. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekAgendaView.d.ts +3 -0
  49. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekBoardView.d.ts +31 -3
  50. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekTimetableView.d.ts +3 -1
  51. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +9 -1
  52. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/timetableModel.d.ts +4 -3
  53. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/utils.d.ts +3 -3
  54. package/dist/_dts/blocks/src/system/transforms/registry/layout.d.ts +0 -1
  55. package/dist/_dts/calendar/src/grid.d.ts +24 -66
  56. package/dist/_dts/calendar/src/index.d.ts +2 -2
  57. package/dist/_dts/calendar/src/timetable.d.ts +5 -9
  58. package/dist/_dts/commerce/src/purchase/allocation.d.ts +11 -0
  59. package/dist/_dts/commerce/src/purchase/index.d.ts +2 -0
  60. package/dist/_dts/commerce/src/purchase/settlement.d.ts +33 -0
  61. package/dist/_dts/commerce/src/purchase/stripeCheckoutReturnUrl.d.ts +8 -0
  62. package/dist/_dts/content-model/src/templates/defaults.d.ts +6 -0
  63. package/dist/_dts/core/src/slug.d.ts +20 -5
  64. package/dist/_dts/preview-next/src/client/blocks/EditablePageRenderer.d.ts +1 -1
  65. package/dist/_dts/preview-next/src/client/preview/headerInteractionPaletteSurfaceState.d.ts +2 -1
  66. package/dist/_dts/sdk/src/client/publicLoaderCacheAccess.d.ts +6 -0
  67. package/dist/_dts/sdk/src/public-api/contracts.d.ts +5 -1
  68. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +10 -6
  69. package/dist/_dts/sdk/src/rendering/components/Block.shared.d.ts +0 -1
  70. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +4 -4
  71. package/dist/_dts/sdk/src/rendering/helpers/footerPageOutline.d.ts +3 -0
  72. package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +3 -0
  73. package/dist/_dts/sdk/src/rendering/helpers/loadPage.d.ts +1 -1
  74. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +17 -0
  75. package/dist/_dts/sdk/src/rendering/helpers/templateContent.d.ts +9 -3
  76. package/dist/_dts/sdk/src/rendering/hooks/usePage.d.ts +1 -1
  77. package/dist/_dts/sdk/src/rendering/index.d.ts +2 -2
  78. package/dist/_dts/sdk/src/rendering/overrideResolution.d.ts +7 -4
  79. package/dist/_dts/sdk/src/version.d.ts +1 -1
  80. package/dist/_dts/theme-core/src/cards/types.d.ts +8 -8
  81. package/dist/_dts/theme-core/src/data.d.ts +12 -0
  82. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  83. package/dist/_dts/theme-core/src/header/legacyHeaderVariant.d.ts +2 -6
  84. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +6 -807
  85. package/dist/_dts/theme-core/src/schema.d.ts +452 -1278
  86. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +213 -1
  87. package/dist/_dts/theme-core/src/site-styles/headerLayoutCatalog.d.ts +0 -29
  88. package/dist/_dts/theme-core/src/site-styles/headerLayoutStyles.d.ts +10 -0
  89. package/dist/_dts/theme-core/src/site-styles/headerLayoutTypes.d.ts +8 -5
  90. package/dist/_dts/theme-core/src/site-styles/headerOpeningForeground.d.ts +4 -4
  91. package/dist/_dts/theme-core/src/site-styles/headerStyleCompiler.d.ts +16 -2
  92. package/dist/_dts/theme-core/src/site-styles/headerStyleDefaults.d.ts +465 -0
  93. package/dist/_dts/theme-core/src/site-styles/headerStyleRecipe.d.ts +161 -0
  94. package/dist/client/{BookingConsentAgreement-Bz9znbpn.mjs → BookingConsentAgreement-DCch21a6.mjs} +2 -2
  95. package/dist/client/{DiscountCodeDisclosure-35Ru8yB9.mjs → DiscountCodeDisclosure-DIj1T59K.mjs} +1 -1
  96. package/dist/client/{EventCombined.client-BKB0ZxRR.mjs → EventCombined.client-BWVNlXTx.mjs} +226 -206
  97. package/dist/client/{EventListing.client-Dx8I21ok.mjs → EventListing.client-DVFCDe3i.mjs} +2 -2
  98. package/dist/client/{LeafletStaticMap-CEWx-Bhe.mjs → LeafletStaticMap-BY5mIHw9.mjs} +1 -1
  99. package/dist/client/{accordion-KIDsKTwS.mjs → accordion-CK29E8rG.mjs} +1 -1
  100. package/dist/client/{bookingForm-D96Rmp-5.mjs → bookingForm-DFvnet-N.mjs} +5 -5
  101. package/dist/client/bookings.mjs +86 -47
  102. package/dist/client/{carousel-YwUgyL66.mjs → carousel-BVU5NQlb.mjs} +1 -1
  103. package/dist/client/{cart-BbwuNrUT.mjs → cart-BNItcZVa.mjs} +3 -3
  104. package/dist/client/{checkout-hp1ucmEY.mjs → checkout-Bu6iCdkP.mjs} +3 -3
  105. package/dist/client/client.mjs +1950 -1031
  106. package/dist/client/{context-DljQn8L5.mjs → context-BImarOAq.mjs} +12 -0
  107. package/dist/client/{eventCalendar-DU4iNLpo.mjs → eventCalendar-DS2h-UXD.mjs} +256 -114
  108. package/dist/client/{eventCombined-CZuupW8m.mjs → eventCombined-Drt4Oq9p.mjs} +3 -3
  109. package/dist/client/{eventDetails-DPQWwCIi.mjs → eventDetails-Bl2vWgTX.mjs} +4 -3
  110. package/dist/client/{eventListing-C7oMidwS.mjs → eventListing-CS7PHY7v.mjs} +3 -3
  111. package/dist/client/{eventRegistration-zEiunlUs.mjs → eventRegistration-D-j8eNy2.mjs} +85 -41
  112. package/dist/client/{form-D2KIyCVJ.mjs → form-RMpoLTyr.mjs} +2 -2
  113. package/dist/client/{headerSection-CK5uChUK.mjs → headerSection-BYE3Lb3k.mjs} +2 -2
  114. package/dist/client/hooks.mjs +2225 -276
  115. package/dist/client/{locationMap-DLQNH1ln.mjs → locationMap-BxSr7Kkh.mjs} +2 -2
  116. package/dist/client/{newsletterForm-ZuhIG7fZ.mjs → newsletterForm-DerbXwFC.mjs} +2 -2
  117. package/dist/client/{productDetail-7hIcGeae.mjs → productDetail-4SZCLhAf.mjs} +3 -3
  118. package/dist/client/{productList-T4Cii1ot.mjs → productList-D7AP4GNq.mjs} +3 -3
  119. package/dist/client/{propsDecoder-mB0aC_Fi.mjs → propsDecoder-pzBeCh14.mjs} +94 -24
  120. package/dist/client/rendering/client.mjs +758 -464
  121. package/dist/client/rendering/islands.mjs +17 -17
  122. package/dist/client/rendering.mjs +2126 -1244
  123. package/dist/client/{scrollToBlock-Du5mHgvL.mjs → scrollToBlock-CduAKf8T.mjs} +1 -1
  124. package/dist/client/{shop-B5zAcKZn.mjs → shop-Cp5p_kGe.mjs} +6 -6
  125. package/dist/client/{shop-commerce-BKBZB6l5.mjs → shop-commerce-DicXYaYX.mjs} +5 -5
  126. package/dist/client/{shop-commerce-store-Cq4qlNtQ.mjs → shop-commerce-store-CGWnpY4K.mjs} +1 -1
  127. package/dist/client/{shopShared-DYGzEs9D.mjs → shopShared-BDf9ljkm.mjs} +3 -3
  128. package/dist/client/{useEventFilters-Bphkda8m.mjs → useEventFilters-DeeyGYuk.mjs} +3 -3
  129. package/dist/preview-next/before-render.mjs +7 -0
  130. package/dist/preview-next/client/runtime.mjs +4 -4
  131. package/dist/preview-next/keepAlive.mjs +7 -0
  132. package/dist/preview-next/middleware.mjs +7 -0
  133. package/dist/{previewAuthStore-C7ksxt5b.mjs → previewAuthStore-DbqBol0V.mjs} +7 -0
  134. package/dist/{sdk-runtime-BbIC8G4J.mjs → sdk-runtime-19MO27F0.mjs} +2 -2
  135. package/dist/{separator-CadhAtI7.mjs → separator-DaPLtJ1f.mjs} +1 -1
  136. package/dist/server/components.mjs +1527 -893
  137. package/dist/server/config-validation.mjs +65 -113
  138. package/dist/server/config.mjs +65 -113
  139. package/dist/server/data.mjs +65 -112
  140. package/dist/server/index.mjs +122 -4
  141. package/dist/server/manifest.mjs +0 -1
  142. package/dist/server/next.mjs +1432 -708
  143. package/dist/server/page-converter.mjs +58 -91
  144. package/dist/server/prebuild.mjs +1 -1
  145. package/dist/server/rendering/server.mjs +1682 -915
  146. package/dist/server/rendering.mjs +1694 -1020
  147. package/dist/server/routing.mjs +3230 -1843
  148. package/dist/server/server.mjs +21710 -19779
  149. package/dist/server/theme-bridge.mjs +656 -264
  150. package/dist/server/theme.mjs +2 -17
  151. package/dist/styles/index.css +609 -181
  152. 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]);
@@ -18473,14 +18500,19 @@ function buildEventCollectionPresentationDisplay(source) {
18473
18500
  emptyMessage: source.emptyMessage ?? "No upcoming events scheduled."
18474
18501
  };
18475
18502
  }
18476
- function buildEventCollectionHydration(source) {
18503
+ function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date()) {
18504
+ const timeZone = toBookingTimeZone(source.bookingTimeZone);
18477
18505
  return {
18478
18506
  siteId: source.siteId,
18479
18507
  stage: source.stage,
18480
18508
  prefetchedEvents: source.events != null,
18481
18509
  eventSurface: normalizeEventSurfaceScope(source.eventSurface),
18482
18510
  filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
18483
- scheduleScope: normalizeEventScheduleScope(source.scheduleScope)
18511
+ scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
18512
+ calendarContext: {
18513
+ timeZone,
18514
+ initialToday: getLocalScheduleDate(now, timeZone)
18515
+ }
18484
18516
  };
18485
18517
  }
18486
18518
  function buildEventCollectionListingDisplay(display, prefetchedEvents, className) {
@@ -18506,6 +18538,7 @@ function buildEventCollectionListingDisplay(display, prefetchedEvents, className
18506
18538
  var eventSurfaceScopeSchema$1, eventScheduleScopeSchema$1, eventCollectionFilterSourceSchemaShape, eventCollectionSourceSchemaShape, eventCollectionDisplaySchemaShape, eventCollectionHydrationSchema;
18507
18539
  var init_eventCollectionContract = __esmMin((() => {
18508
18540
  init_cards();
18541
+ init_src$3();
18509
18542
  init_schemas();
18510
18543
  init_shared$2();
18511
18544
  init_contract_schemas();
@@ -18547,7 +18580,8 @@ var init_eventCollectionContract = __esmMin((() => {
18547
18580
  buttonVariant: eventButtonVariantSchema.optional(),
18548
18581
  buttonText: z.string().optional(),
18549
18582
  emptyMessage: z.string().optional(),
18550
- className: z.string().optional()
18583
+ className: z.string().optional(),
18584
+ bookingTimeZone: z.string().optional()
18551
18585
  };
18552
18586
  eventCollectionDisplaySchemaShape = {
18553
18587
  events: z.array(publicEventSchema),
@@ -18582,7 +18616,15 @@ var init_eventCollectionContract = __esmMin((() => {
18582
18616
  prefetchedEvents: z.boolean(),
18583
18617
  eventSurface: eventSurfaceScopeSchema$1,
18584
18618
  filterEventPresets: z.string().nullable(),
18585
- 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
+ })
18586
18628
  });
18587
18629
  }));
18588
18630
  //#endregion
@@ -23196,30 +23238,6 @@ function asHeaderStyleId(value) {
23196
23238
  return value;
23197
23239
  }
23198
23240
  var init_headerLayoutTypes = __esmMin((() => {}));
23199
- var clearSplitInteractionPalette;
23200
- var init_headerInteractionPalette = __esmMin((() => {
23201
- init_interactionPalette();
23202
- init_lookOptionGroups();
23203
- clearSplitInteractionPalette = defineLookOptionGroup({
23204
- id: "interaction-palette",
23205
- label: "Hover colour",
23206
- defaultOptionId: "accent",
23207
- options: [
23208
- {
23209
- id: "accent",
23210
- label: "Accent"
23211
- },
23212
- {
23213
- id: "primary",
23214
- label: "Primary"
23215
- },
23216
- {
23217
- id: "secondary",
23218
- label: "Secondary"
23219
- }
23220
- ]
23221
- });
23222
- }));
23223
23241
  function supportedLayouts(ids) {
23224
23242
  return ids.map(asHeaderLayoutId);
23225
23243
  }
@@ -23227,7 +23245,6 @@ var titleOnlyLogoAccommodation, inlineWordmarkLogoAccommodation, inlineMarkWithT
23227
23245
  var init_headerLayoutCatalog = __esmMin((() => {
23228
23246
  init_logoBranding();
23229
23247
  init_types$9();
23230
- init_headerInteractionPalette();
23231
23248
  init_headerLayoutTypes();
23232
23249
  titleOnlyLogoAccommodation = {
23233
23250
  pattern: "title-only",
@@ -23384,43 +23401,37 @@ var init_headerLayoutCatalog = __esmMin((() => {
23384
23401
  id: asHeaderStyleId("minimal"),
23385
23402
  label: "Minimal",
23386
23403
  description: "Quiet surface with simple color-change navigation.",
23387
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23388
- navTypography: "plain"
23404
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23389
23405
  },
23390
23406
  {
23391
23407
  id: asHeaderStyleId("fine-line"),
23392
23408
  label: "Seamless",
23393
23409
  description: "Borderless surface with underline hover for a quieter page transition.",
23394
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23395
- navTypography: "plain"
23410
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23396
23411
  },
23397
23412
  {
23398
23413
  id: asHeaderStyleId("soft-bar"),
23399
23414
  label: "Soft Bar",
23400
23415
  description: "Soft tinted surface with gentle pill hover states.",
23401
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23402
- navTypography: "plain"
23416
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23403
23417
  },
23404
23418
  {
23405
23419
  id: asHeaderStyleId("pill-nav"),
23406
23420
  label: "Pill Nav",
23407
23421
  description: "A calm pill navigation rail over a neutral header.",
23408
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23409
- navTypography: "plain"
23422
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23410
23423
  },
23411
23424
  {
23412
23425
  id: asHeaderStyleId("brand-bar"),
23413
23426
  label: "Brand Bar",
23414
23427
  description: "Solid brand surface with high-contrast navigation.",
23415
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23416
- navTypography: "brand-caps"
23428
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23417
23429
  },
23418
23430
  {
23419
23431
  id: asHeaderStyleId("brand-underline"),
23420
23432
  label: "Brand Underline",
23421
23433
  description: "Brand surface with underline-grow navigation.",
23422
- supportedLayoutIds: supportedLayouts(["classic"]),
23423
- navTypography: "brand-caps"
23434
+ supportedLayoutIds: supportedLayouts(["classic"])
23424
23435
  },
23425
23436
  {
23426
23437
  id: asHeaderStyleId("brand-pill"),
@@ -23430,69 +23441,55 @@ var init_headerLayoutCatalog = __esmMin((() => {
23430
23441
  "classic",
23431
23442
  "centered",
23432
23443
  "floating"
23433
- ]),
23434
- navTypography: "brand-caps"
23444
+ ])
23435
23445
  },
23436
23446
  {
23437
23447
  id: asHeaderStyleId("brand-capsule"),
23438
23448
  label: "Brand Capsule",
23439
23449
  description: "Solid brand chrome designed as a floating capsule, with quiet-caps nav, a soft pill active state, and an inverted CTA pill.",
23440
- supportedLayoutIds: supportedLayouts(["classic"]),
23441
- navTypography: "quiet-caps"
23450
+ supportedLayoutIds: supportedLayouts(["classic"])
23442
23451
  },
23443
23452
  {
23444
23453
  id: asHeaderStyleId("serif-line"),
23445
23454
  label: "Serif Line",
23446
23455
  description: "Typographic logo treatment with understated underline navigation.",
23447
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23448
- navTypography: "heading"
23456
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23449
23457
  },
23450
23458
  {
23451
23459
  id: asHeaderStyleId("flat-tabs"),
23452
23460
  label: "Flat Tabs",
23453
23461
  description: "Flat block hover and active states with a Swiss utility feel.",
23454
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
23455
- navTypography: "quiet-caps"
23462
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
23456
23463
  },
23457
23464
  {
23458
23465
  id: asHeaderStyleId("glass"),
23459
23466
  label: "Glass",
23460
23467
  description: "Translucent chrome with frosted navigation backing.",
23461
- supportedLayoutIds: supportedLayouts(["floating"]),
23462
- navTypography: "plain"
23468
+ supportedLayoutIds: supportedLayouts(["floating"])
23463
23469
  },
23464
23470
  {
23465
23471
  id: asHeaderStyleId("minimal-surface"),
23466
23472
  label: "Clear Split",
23467
23473
  description: "Floating logo with transparent navigation and no shared shell.",
23468
- supportedLayoutIds: supportedLayouts(["floating"]),
23469
- navTypography: "plain",
23470
- openingForegroundTarget: "all",
23471
- scrollTreatment: "contrast-glass",
23472
- interactionPalette: clearSplitInteractionPalette
23474
+ supportedLayoutIds: supportedLayouts(["floating"])
23473
23475
  },
23474
23476
  {
23475
23477
  id: asHeaderStyleId("soft-shell"),
23476
23478
  label: "Soft Shell",
23477
23479
  description: "Floating rounded shell with soft pill navigation states.",
23478
- supportedLayoutIds: supportedLayouts(["floating"]),
23479
- navTypography: "plain"
23480
+ supportedLayoutIds: supportedLayouts(["floating"])
23480
23481
  },
23481
23482
  {
23482
23483
  id: asHeaderStyleId("split-glass"),
23483
23484
  label: "Split Glass",
23484
23485
  description: "Logo floats independently while the navigation sits in a glass rail.",
23485
- supportedLayoutIds: supportedLayouts(["floating"]),
23486
- navTypography: "quiet-caps",
23487
- openingForegroundTarget: "brand-only"
23486
+ supportedLayoutIds: supportedLayouts(["floating"])
23488
23487
  },
23489
23488
  {
23490
23489
  id: asHeaderStyleId("split-pill"),
23491
23490
  label: "Split Pill",
23492
23491
  description: "Logo floats independently with a soft pill-backed navigation rail.",
23493
- supportedLayoutIds: supportedLayouts(["floating"]),
23494
- navTypography: "heading",
23495
- openingForegroundTarget: "brand-only"
23492
+ supportedLayoutIds: supportedLayouts(["floating"])
23496
23493
  }
23497
23494
  ]);
23498
23495
  new Map(headerLayoutCatalog.map((layout) => [layout.id, layout]));
@@ -23502,22 +23499,53 @@ var init_headerLayoutResolution = __esmMin((() => {
23502
23499
  init_headerLayoutCatalog();
23503
23500
  init_headerLayoutTypes();
23504
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
+ }));
23505
23528
  var init_headerNavStyles = __esmMin((() => {
23506
23529
  init_types$9();
23507
23530
  }));
23508
- var init_headerStyleCompiler = __esmMin((() => {
23531
+ var init_headerStyleRecipe = __esmMin((() => {
23509
23532
  init_headerCtaVariants();
23510
- init_headerInteractionPalette();
23511
23533
  init_headerLayoutCatalog();
23512
23534
  init_headerLayoutTypes();
23513
23535
  init_headerNavStyles();
23514
23536
  init_types$9();
23515
23537
  }));
23538
+ var init_headerStyleCompiler = __esmMin((() => {
23539
+ init_headerInteractionPalette();
23540
+ init_headerStyleDefaults();
23541
+ init_headerStyleRecipe();
23542
+ }));
23516
23543
  var init_headerLayoutStyles = __esmMin((() => {
23517
23544
  init_headerLayoutTypes();
23518
23545
  init_headerLayoutCatalog();
23519
23546
  init_headerLayoutResolution();
23520
23547
  init_headerStyleCompiler();
23548
+ init_headerStyleDefaults();
23521
23549
  init_headerLayoutTypes();
23522
23550
  }));
23523
23551
  //#endregion
@@ -24359,6 +24387,7 @@ var init_curatedSiteStyles = __esmMin((() => {
24359
24387
  init_gradients();
24360
24388
  init_headerLayoutStyles();
24361
24389
  init_footerLooks();
24390
+ init_headerStyleDefaults();
24362
24391
  init_curatedChoices();
24363
24392
  init_sourceCatalogs();
24364
24393
  init_types$9();
@@ -26771,7 +26800,6 @@ var init_validation_constants = __esmMin((() => {
26771
26800
  "layout.footerRootClass",
26772
26801
  "layout.headerRootStyle",
26773
26802
  "layout.headerSectionBackground",
26774
- "layout.classicNavMode",
26775
26803
  "layout.footerRootStyle",
26776
26804
  "ui.headerNavLinkClass",
26777
26805
  "ui.headingClassFromAlignment",
@@ -35978,12 +36006,13 @@ var init_AgendaEventCard = __esmMin((() => {
35978
36006
  * @returns "Monday, January 13"
35979
36007
  */
35980
36008
  function formatAgendaDayHeader(date) {
35981
- const dayName = FULL_DAY_NAMES$1[date.getDay()];
35982
- const monthName = MONTH_NAMES[date.getMonth()];
35983
- 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}`;
35984
36012
  }
35985
36013
  var FULL_DAY_NAMES$1, WeekAgendaView;
35986
36014
  var init_WeekAgendaView = __esmMin((() => {
36015
+ init_src$1();
35987
36016
  init_AgendaEventCard();
35988
36017
  init_utils$3();
35989
36018
  FULL_DAY_NAMES$1 = [
@@ -35995,14 +36024,14 @@ var init_WeekAgendaView = __esmMin((() => {
35995
36024
  "Friday",
35996
36025
  "Saturday"
35997
36026
  ];
35998
- WeekAgendaView = ({ days, events, showCapacity, emptyMessage = "No events scheduled" }) => {
35999
- const eventsByDate = groupEventsByDate(events);
36027
+ WeekAgendaView = ({ days, events, showCapacity, emptyMessage = "No events scheduled", calendarTimeZone, today: currentDate }) => {
36028
+ const eventsByDate = groupEventsByDate(events, calendarTimeZone);
36000
36029
  return /* @__PURE__ */ jsx("div", {
36001
36030
  className: "event-agenda-week",
36002
36031
  children: days.map((date) => {
36003
36032
  const dateKey = formatDateKey(date);
36004
36033
  const dayEvents = eventsByDate.get(dateKey) || [];
36005
- const today = isToday(date);
36034
+ const today = isToday(date, currentDate);
36006
36035
  return /* @__PURE__ */ jsxs("div", {
36007
36036
  className: `event-agenda-day ${today ? "event-agenda-day--today" : ""}`,
36008
36037
  children: [/* @__PURE__ */ jsx("div", {
@@ -36033,11 +36062,37 @@ var init_WeekAgendaView = __esmMin((() => {
36033
36062
  };
36034
36063
  }));
36035
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
36036
36084
  //#region ../blocks/src/system/runtime/nodes/events/shared/WeekBoardView.tsx
36037
- 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) {
36038
36092
  return {
36039
36093
  days,
36040
- events: [...display.events],
36094
+ events: [...events],
36095
+ navigation,
36041
36096
  showCapacity: display.showCapacity,
36042
36097
  emptyMessage: display.emptyMessage,
36043
36098
  title: display.boardTitle,
@@ -36046,7 +36101,9 @@ function buildWeekBoardViewProps(display, days) {
36046
36101
  ctaHref: display.seeAllUrl,
36047
36102
  buttonVariant: display.buttonVariant,
36048
36103
  elevated: display.elevated,
36049
- banded: display.banded
36104
+ banded: display.banded,
36105
+ calendarTimeZone: display.calendarTimeZone,
36106
+ today: display.today
36050
36107
  };
36051
36108
  }
36052
36109
  /**
@@ -36062,12 +36119,14 @@ function formatCompactTimeRange(event) {
36062
36119
  if ((startMeridiem === "AM" || startMeridiem === "PM") && startMeridiem === endMeridiem) return `${start.slice(0, -3).trim()} – ${end}`;
36063
36120
  return `${start} – ${end}`;
36064
36121
  }
36065
- var SHORT_DAY_NAMES, LEGEND_ITEMS, WeekBoardCard, WeekBoardView;
36122
+ var SHORT_DAY_NAMES, LEGEND_ITEMS, WeekBoardCard, WeekBoardNavigationControls, WeekBoardLegend, WeekBoardLoadError, WeekBoardGrid, WeekBoardFooter, WeekBoardView;
36066
36123
  var init_WeekBoardView = __esmMin((() => {
36067
36124
  init_clsx();
36068
36125
  init_buttons();
36126
+ init_src$1();
36069
36127
  init_eventCapacity();
36070
36128
  init_utils$3();
36129
+ init_CalendarNavigationChevron();
36071
36130
  SHORT_DAY_NAMES = [
36072
36131
  "Sun",
36073
36132
  "Mon",
@@ -36116,18 +36175,129 @@ var init_WeekBoardView = __esmMin((() => {
36116
36175
  ]
36117
36176
  });
36118
36177
  };
36119
- WeekBoardView = ({ days, events, showCapacity, emptyMessage = "No classes scheduled this week", title, footerNote, ctaLabel = "Reserve a place", ctaHref = null, buttonVariant = "outline", elevated = false, banded = false }) => {
36120
- 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);
36121
36288
  const hasAnyEvents = days.some((date) => (eventsByDate.get(formatDateKey(date)) ?? []).length > 0);
36122
36289
  const ctaClassName = themeButtonClassName({
36123
36290
  variant: buttonVariant,
36124
36291
  size: "sm"
36125
36292
  });
36293
+ const todayClassName = themeButtonClassName({
36294
+ variant: buttonVariant,
36295
+ size: "sm"
36296
+ });
36126
36297
  const hasTitle = typeof title === "string" && title.length > 0;
36127
36298
  const hasFooterNote = typeof footerNote === "string" && footerNote.length > 0;
36128
- const hasCta = typeof ctaHref === "string" && ctaHref.length > 0;
36129
36299
  const footerNoteText = hasAnyEvents ? hasFooterNote ? footerNote : null : emptyMessage;
36130
- const showFooter = hasCta || footerNoteText !== null;
36300
+ const resolvedCtaHref = typeof ctaHref === "string" && ctaHref.length > 0 ? ctaHref : null;
36131
36301
  return /* @__PURE__ */ jsx("div", {
36132
36302
  className: "event-calendar event-calendar--week-board",
36133
36303
  "data-block": "event-calendar",
@@ -36139,59 +36309,34 @@ var init_WeekBoardView = __esmMin((() => {
36139
36309
  children: [
36140
36310
  /* @__PURE__ */ jsxs("div", {
36141
36311
  className: "event-week-board-top",
36142
- children: [hasTitle ? /* @__PURE__ */ jsx("span", {
36143
- className: "event-week-board-title",
36144
- children: title
36145
- }) : null, /* @__PURE__ */ jsx("div", {
36146
- className: "event-week-board-legend",
36147
- "aria-hidden": "true",
36148
- children: LEGEND_ITEMS.map((item) => /* @__PURE__ */ jsxs("span", {
36149
- className: "event-week-board-legend-item",
36150
- children: [/* @__PURE__ */ jsx("i", {
36151
- className: "event-week-board-legend-dot",
36152
- "data-status": item.status
36153
- }), item.label]
36154
- }, item.status))
36155
- })]
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
+ ]
36156
36323
  }),
36157
- /* @__PURE__ */ jsx("div", {
36158
- className: "event-week-board-grid",
36159
- children: days.map((date) => {
36160
- const dateKey = formatDateKey(date);
36161
- const dayEvents = eventsByDate.get(dateKey) ?? [];
36162
- const today = isToday(date);
36163
- return /* @__PURE__ */ jsxs("div", {
36164
- className: clsx("event-week-board-day", dayEvents.length === 0 && "event-week-board-day--empty", today && "event-week-board-day--today"),
36165
- children: [/* @__PURE__ */ jsxs("div", {
36166
- className: "event-week-board-day-head",
36167
- children: [/* @__PURE__ */ jsx("span", {
36168
- className: "event-week-board-day-abbr",
36169
- children: SHORT_DAY_NAMES[date.getDay()]
36170
- }), /* @__PURE__ */ jsx("span", {
36171
- className: "event-week-board-day-num",
36172
- children: date.getDate()
36173
- })]
36174
- }), /* @__PURE__ */ jsx("div", {
36175
- className: "event-week-board-day-body",
36176
- children: dayEvents.map((event) => /* @__PURE__ */ jsx(WeekBoardCard, {
36177
- event,
36178
- showCapacity
36179
- }, event.occurrenceId || event.id))
36180
- })]
36181
- }, dateKey);
36182
- })
36324
+ /* @__PURE__ */ jsx(WeekBoardLoadError, {
36325
+ navigation,
36326
+ buttonClassName: todayClassName
36183
36327
  }),
36184
- showFooter ? /* @__PURE__ */ jsxs("div", {
36185
- className: "event-week-board-foot",
36186
- children: [footerNoteText !== null ? /* @__PURE__ */ jsx("p", {
36187
- className: "event-week-board-foot-note",
36188
- children: footerNoteText
36189
- }) : null, hasCta ? /* @__PURE__ */ jsx("a", {
36190
- className: ctaClassName,
36191
- href: ctaHref ?? void 0,
36192
- children: ctaLabel
36193
- }) : null]
36194
- }) : 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
+ })
36195
36340
  ]
36196
36341
  })
36197
36342
  });
@@ -36204,6 +36349,7 @@ function buildTimetableModel(input) {
36204
36349
  items: input.events,
36205
36350
  viewDate: input.viewDate,
36206
36351
  startOfWeek: input.startOfWeek,
36352
+ today: input.today,
36207
36353
  getId: (event) => event.id,
36208
36354
  getStartsAt: (event) => event.startsAt,
36209
36355
  getEndsAt: (event) => event.endsAt,
@@ -36265,10 +36411,10 @@ function formatEventTimeRange(event) {
36265
36411
  return `${formatTime$2(event.startsAt, { timeZone })} - ${formatTime$2(event.endsAt, { timeZone })}`;
36266
36412
  }
36267
36413
  function formatDayLabel(date) {
36268
- 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}`;
36269
36415
  }
36270
36416
  function formatShortDayLabel(date) {
36271
- return `${(FULL_DAY_NAMES[date.getDay()] ?? "").slice(0, 3)} ${date.getDate()}`;
36417
+ return `${(FULL_DAY_NAMES[getDayOfWeek(date)] ?? "").slice(0, 3)} ${date.day}`;
36272
36418
  }
36273
36419
  var DEFAULT_EVENT_CELL_COLOR, FULL_DAY_NAMES;
36274
36420
  var init_timetableModel = __esmMin((() => {
@@ -36339,15 +36485,15 @@ function renderListSsr(display, prefetchedEvents) {
36339
36485
  renderEventCard: (event) => renderEventCard(event, listDisplay)
36340
36486
  });
36341
36487
  }
36342
- function renderCalendarSsr(display) {
36488
+ function renderCalendarSsr(display, hydration) {
36343
36489
  const calendarView = display.defaultCalendarView;
36344
- const viewDate = /* @__PURE__ */ new Date();
36490
+ const viewDate = hydration.calendarContext.initialToday;
36345
36491
  const viewport = buildCalendarViewport({
36346
36492
  view: calendarView,
36347
36493
  anchorDate: viewDate,
36348
36494
  startOfWeek: display.startOfWeek
36349
36495
  });
36350
- const eventsByDate = groupEventsByDate([...display.events]);
36496
+ const eventsByDate = groupEventsByDate([...display.events], hydration.calendarContext.timeZone);
36351
36497
  const dayNames = getOrderedDayNames(display.startOfWeek);
36352
36498
  return /* @__PURE__ */ jsxs("div", {
36353
36499
  className: clsx("event-calendar", display.className ?? void 0),
@@ -36414,7 +36560,9 @@ function renderCalendarSsr(display) {
36414
36560
  days: viewport.days,
36415
36561
  events: [...display.events],
36416
36562
  emptyMessage: display.emptyMessage,
36417
- showCapacity: display.showCapacity
36563
+ showCapacity: display.showCapacity,
36564
+ calendarTimeZone: hydration.calendarContext.timeZone,
36565
+ today: hydration.calendarContext.initialToday
36418
36566
  }) : /* @__PURE__ */ jsxs("div", {
36419
36567
  className: "event-calendar-container",
36420
36568
  children: [/* @__PURE__ */ jsx("div", {
@@ -36428,13 +36576,13 @@ function renderCalendarSsr(display) {
36428
36576
  children: viewport.days.map((date) => {
36429
36577
  const dateKey = formatDateKey(date);
36430
36578
  const dayEvents = eventsByDate.get(dateKey) || [];
36431
- const isCurrentMonth = date.getMonth() === viewDate.getMonth();
36432
- const today = isToday(date);
36579
+ const isCurrentMonth = date.month === viewDate.month;
36580
+ const today = isToday(date, hydration.calendarContext.initialToday);
36433
36581
  return /* @__PURE__ */ jsxs("div", {
36434
36582
  className: clsx("event-calendar-day", !isCurrentMonth && "event-calendar-day--other-month", today && "event-calendar-day--today"),
36435
36583
  children: [/* @__PURE__ */ jsx("div", {
36436
36584
  className: "event-calendar-day-number",
36437
- children: date.getDate()
36585
+ children: date.day
36438
36586
  }), /* @__PURE__ */ jsxs("div", {
36439
36587
  className: "event-calendar-events",
36440
36588
  children: [dayEvents.slice(0, 3).map((event) => /* @__PURE__ */ jsxs("a", {
@@ -36472,8 +36620,8 @@ function renderCalendarSsr(display) {
36472
36620
  ]
36473
36621
  });
36474
36622
  }
36475
- function renderTimetableSsr(display) {
36476
- const viewDate = /* @__PURE__ */ new Date();
36623
+ function renderTimetableSsr(display, hydration) {
36624
+ const viewDate = hydration.calendarContext.initialToday;
36477
36625
  const viewport = buildCalendarViewport({
36478
36626
  view: "week",
36479
36627
  anchorDate: viewDate,
@@ -36482,7 +36630,8 @@ function renderTimetableSsr(display) {
36482
36630
  const model = buildTimetableModel({
36483
36631
  events: [...display.events],
36484
36632
  viewDate,
36485
- startOfWeek: display.startOfWeek
36633
+ startOfWeek: display.startOfWeek,
36634
+ today: hydration.calendarContext.initialToday
36486
36635
  });
36487
36636
  const selectedDayKey = model.days.find((day) => day.isToday)?.dateKey ?? model.days[0]?.dateKey ?? "";
36488
36637
  return /* @__PURE__ */ jsxs("div", {
@@ -36637,21 +36786,21 @@ function renderTimetableSsr(display) {
36637
36786
  })]
36638
36787
  });
36639
36788
  }
36640
- function renderWeekBoardSsr(display) {
36641
- const days = getWeekCalendarDayTuple(/* @__PURE__ */ new Date(), display.startOfWeek);
36642
- return /* @__PURE__ */ jsx(WeekBoardView, {
36643
- days,
36644
- events: [...display.events],
36645
- showCapacity: display.showCapacity,
36646
- emptyMessage: display.emptyMessage,
36647
- title: display.boardTitle,
36648
- footerNote: display.footerNote,
36649
- ctaLabel: display.loadMoreText ?? display.buttonText,
36650
- ctaHref: display.seeAllUrl,
36651
- buttonVariant: display.buttonVariant,
36652
- elevated: display.elevated,
36653
- banded: display.banded
36654
- });
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) });
36655
36804
  }
36656
36805
  function formatHourLabel$1(hour) {
36657
36806
  if (hour === 0) return "12 AM";
@@ -36677,13 +36826,13 @@ const EventCalendarSSR = (props) => {
36677
36826
  content = renderListSsr(display, hydration.prefetchedEvents);
36678
36827
  break;
36679
36828
  case "timetable":
36680
- content = renderTimetableSsr(display);
36829
+ content = renderTimetableSsr(display, hydration);
36681
36830
  break;
36682
36831
  case "week-board":
36683
- content = renderWeekBoardSsr(display);
36832
+ content = renderWeekBoardSsr(display, hydration);
36684
36833
  break;
36685
36834
  case "calendar":
36686
- content = renderCalendarSsr(display);
36835
+ content = renderCalendarSsr(display, hydration);
36687
36836
  break;
36688
36837
  default: content = assertNeverDisplayMode(display.displayMode);
36689
36838
  }
@@ -45747,41 +45896,78 @@ var init_sessionStorage = __esmMin((() => {
45747
45896
  }));
45748
45897
  //#endregion
45749
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
+ }
45750
45961
  function useEventRegistrationStripeReturn(options) {
45751
45962
  return useEventRegistrationStripeReturnWithDeps(options, eventRegistrationStripeReturnDeps);
45752
45963
  }
45753
45964
  function useEventRegistrationStripeReturnWithDeps(options, deps) {
45754
- 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;
45755
45966
  const checkoutAttemptIdRef = useRef(null);
45756
45967
  const verificationConfig = useMemo(() => step === "verifying-payment" && pendingRegistrationReference ? { reference: pendingRegistrationReference } : null, [step, pendingRegistrationReference]);
45757
45968
  const verification = deps.usePaymentVerification(verificationConfig);
45758
45969
  useEffect(() => {
45759
- deps.cleanupStaleRegistrations();
45760
- const returnParams = deps.consumeReturnParams();
45761
- const registrationStatus = returnParams.registration;
45762
- if (registrationStatus !== "cancelled" && registrationStatus !== "success") return;
45763
- deps.scrollToBlock(EVENT_REGISTRATION_ANCHOR_ID);
45764
- const siteId = api.config.siteId;
45765
- if (!siteId) return;
45766
- const checkoutAttemptId = returnParams[EVENT_REGISTRATION_CHECKOUT_ATTEMPT_PARAM];
45767
- if (!checkoutAttemptId) return;
45768
- const pending = deps.getPendingRegistration(siteId, checkoutAttemptId);
45769
- if (!pending) return;
45770
- checkoutAttemptIdRef.current = checkoutAttemptId;
45771
- setFormData(pending.formData);
45772
- setTicketSelections(pending.ticketSelections);
45773
- setTicketsCount(getTicketSelectionTotal(pending.ticketSelections));
45774
- if (pending.selectedEventId) {
45775
- const event = events.find((e) => e.selectionId === pending.selectedEventId) ?? null;
45776
- if (event) setSelectedEvent(event);
45777
- }
45778
- setSelectedAttendanceMode(pending.selectedAttendanceMode ?? null);
45779
- setPaymentSelection(pending.paymentSelection);
45780
- if (registrationStatus === "cancelled") setStep("select-payment");
45781
- else if (registrationStatus === "success") {
45782
- setPendingRegistrationReference(pending.reference);
45783
- setStep("verifying-payment");
45784
- }
45970
+ handleCheckoutReturn(options, deps, checkoutAttemptIdRef);
45785
45971
  }, []);
45786
45972
  useEffect(() => {
45787
45973
  if (verification.status === "completed") {
@@ -45815,7 +46001,11 @@ var init_useEventRegistrationStripeReturn = __esmMin((() => {
45815
46001
  init_ticketSelectionLines();
45816
46002
  eventRegistrationStripeReturnDeps = {
45817
46003
  usePaymentVerification,
45818
- consumeReturnParams: () => consumeSearchParams(["registration", EVENT_REGISTRATION_CHECKOUT_ATTEMPT_PARAM]),
46004
+ consumeReturnParams: () => consumeSearchParams([
46005
+ "registration",
46006
+ EVENT_REGISTRATION_CHECKOUT_ATTEMPT_PARAM,
46007
+ "session_id"
46008
+ ]),
45819
46009
  scrollToBlock,
45820
46010
  cleanupStaleRegistrations,
45821
46011
  clearPendingRegistration,
@@ -45876,7 +46066,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
45876
46066
  options.setStep("submitting");
45877
46067
  try {
45878
46068
  const prepared = prepareSubmitContext(options, target, method, passId, membershipId, selection);
45879
- if (prepared.subject.kind === "wholeSeries" && method === "stripe") return submitWholeSeriesCheckout(options, deps, {
46069
+ if (prepared.subject.kind === "wholeSeries" && method === "stripe") return await submitWholeSeriesCheckout(options, deps, {
45880
46070
  ...prepared,
45881
46071
  subject: prepared.subject
45882
46072
  }, submitOptions);
@@ -45897,7 +46087,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
45897
46087
  claimToken: options.claimToken ?? void 0,
45898
46088
  guests: prepared.guestsPayload
45899
46089
  });
45900
- 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);
45901
46091
  options.setRegistrationResult(toRegistrationResult(result));
45902
46092
  options.setStep("success");
45903
46093
  return {
@@ -45980,6 +46170,7 @@ async function submitWholeSeriesCheckout(options, deps, prepared, submitOptions)
45980
46170
  claimToken: options.claimToken ?? void 0,
45981
46171
  discountCode: options.discountCode.trim() || void 0,
45982
46172
  collectionOptionKind: prepared.selectionSnapshot.collectionOptionKind,
46173
+ checkoutAttemptId,
45983
46174
  ...urls
45984
46175
  });
45985
46176
  if (result.scope !== "wholeSeries") throw new Error("Unexpected registration scope for event checkout.");
@@ -47373,7 +47564,10 @@ var init_EventRegistrationWizardActions = __esmMin((() => {
47373
47564
  }));
47374
47565
  //#endregion
47375
47566
  //#region ../commerce/src/purchase/types.ts
47376
- 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;
47377
47571
  var init_orderTypes = __esmMin((() => {
47378
47572
  ORDER_STATUSES = [
47379
47573
  "pending",
@@ -47789,6 +47983,7 @@ var init_stripeMinimumCharge = __esmMin((() => {
47789
47983
  THB: 1e3
47790
47984
  };
47791
47985
  }));
47986
+ var init_stripeCheckoutReturnUrl = __esmMin((() => {}));
47792
47987
  var init_stateTransitions = __esmMin((() => {
47793
47988
  init_src$3();
47794
47989
  init_assertNever();
@@ -47797,6 +47992,7 @@ var init_stateTransitions = __esmMin((() => {
47797
47992
  //#region ../commerce/src/purchase/index.ts
47798
47993
  var init_purchase = __esmMin((() => {
47799
47994
  init_types$1();
47995
+ init_allocation();
47800
47996
  init_orderTypes();
47801
47997
  init_orderPlanningTypes();
47802
47998
  init_bookingInstalmentSchedule();
@@ -47850,6 +48046,7 @@ var init_purchase = __esmMin((() => {
47850
48046
  init_settlement();
47851
48047
  init_shopRefundPlanning();
47852
48048
  init_stripeMinimumCharge();
48049
+ init_stripeCheckoutReturnUrl();
47853
48050
  init_stateTransitions();
47854
48051
  }));
47855
48052
  //#endregion
@@ -103696,7 +103893,7 @@ var init_PaymentFailedStep = __esmMin((() => {
103696
103893
  var VerifyingTimeoutStep;
103697
103894
  var init_VerifyingTimeoutStep = __esmMin((() => {
103698
103895
  init_shared();
103699
- 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." }) => {
103700
103897
  return /* @__PURE__ */ jsx(TerminalPanel, {
103701
103898
  tone: "warning",
103702
103899
  className: "er-center",
@@ -103705,18 +103902,18 @@ var init_VerifyingTimeoutStep = __esmMin((() => {
103705
103902
  variant: "warning",
103706
103903
  children: /* @__PURE__ */ jsx(ClockIcon, {})
103707
103904
  }),
103708
- title: "Your registration is saved",
103905
+ title,
103709
103906
  body: /* @__PURE__ */ jsx("p", {
103710
103907
  className: "er-text--muted er-message",
103711
- 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
103712
103909
  }),
103713
103910
  actionsClassName: "er-button-group",
103714
- actions: /* @__PURE__ */ jsx("button", {
103911
+ actions: onCheckAgain ? /* @__PURE__ */ jsx("button", {
103715
103912
  type: "button",
103716
103913
  onClick: onCheckAgain,
103717
103914
  className: "er-btn er-btn--primary",
103718
103915
  children: "Check Again"
103719
- }),
103916
+ }) : void 0,
103720
103917
  secondaryBody: supportEmail ? /* @__PURE__ */ jsxs("p", {
103721
103918
  className: "er-text--sm er-text--muted er-message",
103722
103919
  children: [
@@ -104018,7 +104215,9 @@ function EventRegistrationTerminalState(props) {
104018
104215
  onRetry: () => wizard.setStep("select-payment")
104019
104216
  });
104020
104217
  case "verifying-timeout": return /* @__PURE__ */ jsx(VerifyingTimeoutStep, {
104021
- 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,
104022
104221
  supportEmail: props.supportEmail
104023
104222
  });
104024
104223
  case "success": return wizard.registrationResult ? /* @__PURE__ */ jsx(SuccessStep, {
@@ -111149,25 +111348,34 @@ var init_TabBar = __esmMin((() => {
111149
111348
  }));
111150
111349
  //#endregion
111151
111350
  //#region ../blocks/src/system/runtime/hooks/useCalendarEvents.state.ts
111152
- function calendarEventCacheLoadReducer(_state, action) {
111351
+ function calendarEventCacheLoadReducer(state, action) {
111153
111352
  switch (action.type) {
111154
- case "started": return { kind: "loading" };
111155
- case "succeeded": return { kind: "idle" };
111156
- 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) ? {
111157
111359
  kind: "error",
111360
+ scope: action.scope,
111158
111361
  error: action.error
111159
- };
111362
+ } : state;
111160
111363
  default: return assertNever$11(action);
111161
111364
  }
111162
111365
  }
111163
- function toCalendarEventCacheLoadError(error) {
111164
- 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
+ };
111165
111372
  }
111166
- function isCalendarEventCacheLoading(state) {
111167
- 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;
111168
111376
  }
111169
- function getCalendarEventCacheError(state) {
111170
- return state.kind === "error" ? state.error : null;
111377
+ function toCalendarEventCacheLoadError(error) {
111378
+ return toError(error, "Unknown error");
111171
111379
  }
111172
111380
  var init_useCalendarEvents_state = __esmMin((() => {
111173
111381
  init_dist$1();
@@ -111181,18 +111389,35 @@ var init_useCalendarEvents_state = __esmMin((() => {
111181
111389
  * Uses the Block API Client for type-safe API calls.
111182
111390
  * Must be used within a BlockApiProvider.
111183
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
+ }
111184
111413
  /**
111185
111414
  * Generate a cache key for a month
111186
111415
  */
111187
111416
  function getMonthKey(date) {
111188
- return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}`;
111417
+ return `${date.year}-${String(date.month).padStart(2, "0")}`;
111189
111418
  }
111190
- /**
111191
- * Owns calendar viewport state only: selected anchor date, derived visible
111192
- * period, and navigation by the natural unit for the active view.
111193
- */
111194
- function useCalendarViewport({ view = "month", startOfWeek = "monday", initialDate } = {}) {
111195
- const [viewDate, setViewDate] = useState(() => initialDate ?? /* @__PURE__ */ new Date());
111419
+ function useCalendarViewport({ view = "month", startOfWeek = "monday", initialDate }) {
111420
+ const [viewDate, setViewDate] = useState(initialDate);
111196
111421
  const viewport = useMemo(() => buildCalendarViewport({
111197
111422
  view,
111198
111423
  anchorDate: viewDate,
@@ -111217,15 +111442,44 @@ function useCalendarViewport({ view = "month", startOfWeek = "monday", initialDa
111217
111442
  goToPrevious,
111218
111443
  goToNext,
111219
111444
  goToToday: useCallback(() => {
111220
- setViewDate(/* @__PURE__ */ new Date());
111221
- }, [])
111445
+ setViewDate(initialDate);
111446
+ }, [initialDate])
111222
111447
  };
111223
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
+ }
111224
111478
  /**
111225
111479
  * Owns event loading and month-window caching for a supplied viewport anchor.
111226
111480
  * It does not decide navigation semantics or visible calendar days.
111227
111481
  */
111228
- function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1, filters, stage }) {
111482
+ function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1, filters, stage, timeZone }) {
111229
111483
  const { getPublicEvents } = useBlockApi();
111230
111484
  const [loadState, dispatchLoadState] = useReducer(calendarEventCacheLoadReducer, { kind: "idle" });
111231
111485
  const [cacheVersion, setCacheVersion] = useState(0);
@@ -111237,7 +111491,7 @@ function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1
111237
111491
  filters?.staffMemberId,
111238
111492
  filters?.venueId
111239
111493
  ]);
111240
- const cacheRef = useRef(/* @__PURE__ */ new Map());
111494
+ const cacheRef = useInitiallySeededCalendarCache(initialEvents, timeZone);
111241
111495
  const loadedMonthsRef = useRef(/* @__PURE__ */ new Set());
111242
111496
  const fetchingRef = useRef(/* @__PURE__ */ new Set());
111243
111497
  const requestIdRef = useRef(0);
@@ -111249,24 +111503,26 @@ function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1
111249
111503
  loadedMonthsRef.current = /* @__PURE__ */ new Set();
111250
111504
  fetchingRef.current = /* @__PURE__ */ new Set();
111251
111505
  requestIdRef.current += 1;
111252
- if (initialEvents.length > 0) for (const event of initialEvents) {
111253
- const monthKey = getMonthKey(new Date(event.startsAt));
111254
- const existing = cacheRef.current.get(monthKey) || [];
111255
- if (!existing.some((e) => e.id === event.id)) cacheRef.current.set(monthKey, [...existing, event]);
111256
- }
111506
+ addEventsToCalendarCache(cacheRef.current, initialEvents, timeZone);
111257
111507
  setCacheVersion((v) => v + 1);
111258
- }, [filtersKey, initialEvents]);
111259
- const fetchEventsForRange = useCallback(async (from, to, targetMonths) => {
111508
+ }, [
111509
+ filtersKey,
111510
+ initialEvents,
111511
+ timeZone
111512
+ ]);
111513
+ const fetchEventsForRange = useCallback(async (from, to, targetMonths, scope) => {
111260
111514
  const monthsToFetch = targetMonths.filter((m) => !loadedMonthsRef.current.has(m) && !fetchingRef.current.has(m));
111261
111515
  if (monthsToFetch.length === 0) return;
111262
111516
  monthsToFetch.forEach((m) => fetchingRef.current.add(m));
111263
111517
  const currentRequestId = ++requestIdRef.current;
111264
- dispatchLoadState({ type: "started" });
111518
+ dispatchLoadState({
111519
+ type: "started",
111520
+ scope
111521
+ });
111265
111522
  try {
111266
- const result = await getPublicEvents({
111523
+ const result = await loadCalendarEventPages(getPublicEvents, {
111267
111524
  from,
111268
111525
  to,
111269
- limit: CALENDAR_FETCH_LIMIT,
111270
111526
  stage,
111271
111527
  detailLevel: "listing",
111272
111528
  eventSurface: filters?.eventSurface,
@@ -111275,23 +111531,27 @@ function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1
111275
111531
  categoryIds: filters?.categoryIds,
111276
111532
  staffMemberId: filters?.staffMemberId,
111277
111533
  venueId: filters?.venueId
111278
- });
111279
- if (currentRequestId === requestIdRef.current) {
111280
- for (const event of result) {
111281
- const monthKey = getMonthKey(new Date(event.startsAt));
111282
- const existing = cacheRef.current.get(monthKey) || [];
111283
- if (!existing.some((e) => e.id === event.id)) cacheRef.current.set(monthKey, [...existing, event]);
111284
- }
111285
- for (const month of monthsToFetch) {
111286
- loadedMonthsRef.current.add(month);
111287
- if (!cacheRef.current.has(month)) cacheRef.current.set(month, []);
111288
- }
111289
- setCacheVersion((v) => v + 1);
111290
- 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, []);
111291
111544
  }
111545
+ setCacheVersion((v) => v + 1);
111546
+ dispatchLoadState({
111547
+ type: "succeeded",
111548
+ scope
111549
+ });
111292
111550
  } catch (err) {
111551
+ monthsToFetch.forEach((m) => fetchingRef.current.delete(m));
111293
111552
  if (currentRequestId === requestIdRef.current) dispatchLoadState({
111294
111553
  type: "failed",
111554
+ scope,
111295
111555
  error: toCalendarEventCacheLoadError(err)
111296
111556
  });
111297
111557
  } finally {
@@ -111305,7 +111565,8 @@ function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1
111305
111565
  filters?.scheduleScope,
111306
111566
  filters?.staffMemberId,
111307
111567
  filters?.venueId,
111308
- stage
111568
+ stage,
111569
+ timeZone
111309
111570
  ]);
111310
111571
  const ensureEventsLoaded = useCallback((date) => {
111311
111572
  const targetMonths = [];
@@ -111315,74 +111576,71 @@ function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1
111315
111576
  }
111316
111577
  const unloadedMonths = targetMonths.filter((m) => !loadedMonthsRef.current.has(m) && !fetchingRef.current.has(m));
111317
111578
  if (unloadedMonths.length > 0) {
111318
- const range = getThreeMonthRange(date);
111319
- 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);
111320
111591
  }
111321
- }, [preloadMonths, fetchEventsForRange]);
111592
+ }, [
111593
+ preloadMonths,
111594
+ fetchEventsForRange,
111595
+ filtersKey,
111596
+ timeZone
111597
+ ]);
111322
111598
  useEffect(() => {
111323
111599
  ensureEventsLoaded(viewDate);
111324
111600
  }, [viewDate, ensureEventsLoaded]);
111601
+ const retryCurrentView = useCallback(() => {
111602
+ ensureEventsLoaded(viewDate);
111603
+ }, [ensureEventsLoaded, viewDate]);
111325
111604
  return {
111326
- events: useMemo(() => {
111327
- const allEvents = [];
111328
- for (let i = -1; i <= 1; i++) {
111329
- const monthKey = getMonthKey(addMonths(viewDate, i));
111330
- const monthEvents = cacheRef.current.get(monthKey) || [];
111331
- allEvents.push(...monthEvents);
111332
- }
111333
- const seen = /* @__PURE__ */ new Set();
111334
- return allEvents.filter((e) => {
111335
- if (seen.has(e.id)) return false;
111336
- seen.add(e.id);
111337
- return true;
111338
- }).sort((a, b) => new Date(a.startsAt).getTime() - new Date(b.startsAt).getTime());
111339
- }, [viewDate, cacheVersion]),
111340
- loading: isCalendarEventCacheLoading(loadState),
111341
- 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
111342
111611
  };
111343
111612
  }
111344
- /**
111345
- * Hook for calendar event management with month-based caching.
111346
- *
111347
- * Pre-fetches 3 months (previous, current, next) and caches by month.
111348
- * Navigation within cached range is instant; fetches at boundaries.
111349
- *
111350
- * @example
111351
- * ```tsx
111352
- * const { events, viewDate, loading, goToPrevious, goToNext } = useCalendarEvents({
111353
- * siteId: 'site-123',
111354
- * initialEvents: serverEvents,
111355
- * });
111356
- * ```
111357
- */
111358
- 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 }) {
111359
111614
  const { viewDate, viewport, goToDate, goToPrevious, goToNext, goToToday } = useCalendarViewport({
111360
111615
  view,
111361
- startOfWeek
111616
+ startOfWeek,
111617
+ initialDate: calendarContext.initialToday
111362
111618
  });
111363
- const { events, loading, error } = useCalendarEventCache({
111619
+ const { events, loadState, retryCurrentView } = useCalendarEventCache({
111364
111620
  viewDate,
111365
111621
  initialEvents,
111366
111622
  preloadMonths,
111367
111623
  filters,
111368
- stage
111624
+ stage,
111625
+ timeZone: calendarContext.timeZone
111369
111626
  });
111370
111627
  return {
111371
111628
  events,
111372
111629
  viewDate,
111373
111630
  viewport,
111374
- loading,
111375
- error,
111631
+ loadState,
111376
111632
  setViewDate: useCallback((date) => {
111377
111633
  goToDate(date);
111378
111634
  }, [goToDate]),
111379
111635
  goToPrevious,
111380
111636
  goToNext,
111381
- goToToday
111637
+ goToToday,
111638
+ retryCurrentView
111382
111639
  };
111383
111640
  }
111384
111641
  var CALENDAR_FETCH_LIMIT;
111385
111642
  var init_useCalendarEvents = __esmMin((() => {
111643
+ init_src$3();
111386
111644
  init_utils$3();
111387
111645
  init_api();
111388
111646
  init_listOptions();
@@ -111444,9 +111702,9 @@ var CalendarDayCell;
111444
111702
  var init_CalendarDayCell = __esmMin((() => {
111445
111703
  init_utils$3();
111446
111704
  init_EventModalContext();
111447
- CalendarDayCell = ({ date, events, isCurrentMonth }) => {
111705
+ CalendarDayCell = ({ date, events, isCurrentMonth, today: currentDate }) => {
111448
111706
  const { openEventModal, openDayModal } = useEventModal();
111449
- const today = isToday(date);
111707
+ const today = isToday(date, currentDate);
111450
111708
  const dayClasses = [
111451
111709
  "event-calendar-day",
111452
111710
  !isCurrentMonth && "event-calendar-day--other-month",
@@ -111462,7 +111720,7 @@ var init_CalendarDayCell = __esmMin((() => {
111462
111720
  className: dayClasses,
111463
111721
  children: [/* @__PURE__ */ jsx("div", {
111464
111722
  className: "event-calendar-day-number",
111465
- children: date.getDate()
111723
+ children: date.day
111466
111724
  }), /* @__PURE__ */ jsxs("div", {
111467
111725
  className: "event-calendar-events",
111468
111726
  children: [events.slice(0, 3).map((event) => {
@@ -111574,7 +111832,7 @@ var init_EventDetailModal = __esmMin((() => {
111574
111832
  * Clicking an event triggers onSelectEvent (typically opens EventDetailModal).
111575
111833
  */
111576
111834
  function DayEventsModal({ date, events, showCapacity, onClose, onSelectEvent, portalRoot }) {
111577
- const formattedDate = formatDate$2(date.toISOString());
111835
+ const formattedDate = formatDate$2(`${formatLocalScheduleDate(date)}T12:00:00Z`);
111578
111836
  return /* @__PURE__ */ jsxs(ModalShell, {
111579
111837
  title: formattedDate,
111580
111838
  titleId: "ec-day-modal-title",
@@ -111609,6 +111867,7 @@ function DayEventsModal({ date, events, showCapacity, onClose, onSelectEvent, po
111609
111867
  });
111610
111868
  }
111611
111869
  var init_DayEventsModal = __esmMin((() => {
111870
+ init_src$3();
111612
111871
  init_AgendaEventCard();
111613
111872
  init_utils$3();
111614
111873
  init_ModalShell();
@@ -111729,7 +111988,8 @@ function toEventCombinedControllerProps(props) {
111729
111988
  buttonVariant: props.render.display.buttonVariant,
111730
111989
  buttonText: props.render.display.buttonText,
111731
111990
  emptyMessage: props.render.display.emptyMessage,
111732
- className: props.render.display.className ?? void 0
111991
+ className: props.render.display.className ?? void 0,
111992
+ calendarContext: props.render.hydration.calendarContext
111733
111993
  };
111734
111994
  }
111735
111995
  var EventCombinedClient, EventCombinedIslandClient;
@@ -111752,7 +112012,7 @@ var init_EventCombined_client = __esmMin((() => {
111752
112012
  EventCombinedClient = ({ events: initialEvents, siteId, stage, listLayout = "stack", listColumns = "3", eventsPerPage = 12, paginationAction = {
111753
112013
  kind: "loadMore",
111754
112014
  label: "Load more events"
111755
- }, 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 }) => {
111756
112016
  const fetchInitialEventsOnMount = initialEvents == null;
111757
112017
  const resolvedShowFilters = showFilters ?? true;
111758
112018
  const resolvedShowVenueFilter = showVenueFilter ?? false;
@@ -111810,7 +112070,7 @@ var init_EventCombined_client = __esmMin((() => {
111810
112070
  pageSize,
111811
112071
  stage
111812
112072
  });
111813
- const { events: calendarEventsRaw, viewDate, viewport, loading: calendarLoading, goToPrevious, goToNext, goToToday } = useCalendarEvents({
112073
+ const { events: calendarEventsRaw, viewDate, viewport, loadState: calendarLoadState, goToPrevious, goToNext, goToToday } = useCalendarEvents({
111814
112074
  siteId,
111815
112075
  initialEvents: useMemo(() => {
111816
112076
  return getEventRuntimeFiltersKey(initialListFilters) === getEventRuntimeFiltersKey(listFilters) ? initialEvents ?? [] : [];
@@ -111823,9 +112083,10 @@ var init_EventCombined_client = __esmMin((() => {
111823
112083
  startOfWeek,
111824
112084
  preloadMonths: 1,
111825
112085
  filters: listFilters,
111826
- stage
112086
+ stage,
112087
+ calendarContext
111827
112088
  });
111828
- const eventsByDate = useMemo(() => groupEventsByDate(calendarEventsRaw), [calendarEventsRaw]);
112089
+ const eventsByDate = useMemo(() => groupEventsByDate(calendarEventsRaw, calendarContext.timeZone), [calendarContext.timeZone, calendarEventsRaw]);
111829
112090
  const dayNames = useMemo(() => getOrderedDayNames(startOfWeek), [startOfWeek]);
111830
112091
  const tabs = [{
111831
112092
  id: "list",
@@ -111927,7 +112188,7 @@ var init_EventCombined_client = __esmMin((() => {
111927
112188
  }),
111928
112189
  /* @__PURE__ */ jsxs("h3", {
111929
112190
  className: "event-calendar-title",
111930
- children: [viewport.title, calendarLoading && /* @__PURE__ */ jsx("span", {
112191
+ children: [viewport.title, calendarLoadState.kind === "loading" && /* @__PURE__ */ jsx("span", {
111931
112192
  className: "rb-ml-2 rb-caption status-muted",
111932
112193
  children: "(loading...)"
111933
112194
  })]
@@ -111966,7 +112227,9 @@ var init_EventCombined_client = __esmMin((() => {
111966
112227
  days: viewport.days,
111967
112228
  events: calendarEventsRaw,
111968
112229
  emptyMessage: "No events scheduled",
111969
- showCapacity: resolvedShowCapacity
112230
+ showCapacity: resolvedShowCapacity,
112231
+ calendarTimeZone: calendarContext.timeZone,
112232
+ today: calendarContext.initialToday
111970
112233
  }) : /* @__PURE__ */ jsxs("div", {
111971
112234
  className: "event-calendar-container",
111972
112235
  children: [/* @__PURE__ */ jsx("div", {
@@ -111983,12 +112246,13 @@ var init_EventCombined_client = __esmMin((() => {
111983
112246
  return /* @__PURE__ */ jsx(CalendarDayCell, {
111984
112247
  date,
111985
112248
  events: dayEvents,
111986
- isCurrentMonth: date.getMonth() === viewDate.getMonth()
112249
+ isCurrentMonth: date.month === viewDate.month,
112250
+ today: calendarContext.initialToday
111987
112251
  }, dateKey);
111988
112252
  })
111989
112253
  })]
111990
112254
  }),
111991
- calendarEventsRaw.length === 0 && !calendarLoading && /* @__PURE__ */ jsx("p", {
112255
+ calendarEventsRaw.length === 0 && calendarLoadState.kind === "idle" && /* @__PURE__ */ jsx("p", {
111992
112256
  className: "event-calendar-empty",
111993
112257
  children: emptyMessage
111994
112258
  })
@@ -112021,15 +112285,17 @@ var WeekTimetableView, TimeRail, TimetableDayColumn, TimetableEventButton;
112021
112285
  var init_WeekTimetableView = __esmMin((() => {
112022
112286
  init_EventModalContext();
112023
112287
  init_timetableModel();
112024
- WeekTimetableView = ({ viewDate, events, startOfWeek, showCapacity, emptyMessage = "No classes scheduled" }) => {
112288
+ WeekTimetableView = ({ viewDate, events, startOfWeek, today, showCapacity, emptyMessage = "No classes scheduled" }) => {
112025
112289
  const { openEventModal } = useEventModal();
112026
112290
  const model = useMemo(() => buildTimetableModel({
112027
112291
  events,
112028
112292
  viewDate,
112029
- startOfWeek
112293
+ startOfWeek,
112294
+ today
112030
112295
  }), [
112031
112296
  events,
112032
112297
  startOfWeek,
112298
+ today,
112033
112299
  viewDate
112034
112300
  ]);
112035
112301
  const [selectedDayKey, setSelectedDayKey] = useState(() => model.days.find((day) => day.isToday)?.dateKey ?? model.days[0]?.dateKey ?? "");
@@ -112209,21 +112475,6 @@ function buildDisplayFilterParams(display) {
112209
112475
  filterVenueId: display.filterVenueId
112210
112476
  });
112211
112477
  }
112212
- function CalendarChevron({ direction }) {
112213
- return /* @__PURE__ */ jsx("svg", {
112214
- width: "20",
112215
- height: "20",
112216
- fill: "none",
112217
- stroke: "currentColor",
112218
- strokeWidth: 2,
112219
- viewBox: "0 0 24 24",
112220
- children: /* @__PURE__ */ jsx("path", {
112221
- strokeLinecap: "round",
112222
- strokeLinejoin: "round",
112223
- d: direction === "previous" ? "M15 19l-7-7 7-7" : "M9 5l7 7-7 7"
112224
- })
112225
- });
112226
- }
112227
112478
  var EventCalendarClient, EventCalendarWeekBoardClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarChrome;
112228
112479
  var init_EventCalendar_client = __esmMin((() => {
112229
112480
  init_EventCalendar_interactive();
@@ -112232,6 +112483,7 @@ var init_EventCalendar_client = __esmMin((() => {
112232
112483
  init_useCalendarEvents();
112233
112484
  init_useEventFilters();
112234
112485
  init_CalendarDayCell();
112486
+ init_CalendarNavigationChevron();
112235
112487
  init_EventFilters();
112236
112488
  init_utils$3();
112237
112489
  init_EventModalContext();
@@ -112271,38 +112523,75 @@ var init_EventCalendar_client = __esmMin((() => {
112271
112523
  buttonVariant: display.buttonVariant,
112272
112524
  buttonText: display.buttonText,
112273
112525
  emptyMessage: display.emptyMessage,
112274
- className: display.className ?? void 0
112526
+ className: display.className ?? void 0,
112527
+ calendarContext: hydration.calendarContext
112275
112528
  });
112276
112529
  if (display.displayMode === "list") return /* @__PURE__ */ jsx(EventListingController, { render: buildEventCalendarListingRender(render) });
112277
112530
  if (display.displayMode === "timetable") return /* @__PURE__ */ jsx(EventCalendarTimetableClient, { render });
112278
- if (display.displayMode === "week-board") return /* @__PURE__ */ jsx(EventCalendarWeekBoardClient, { display });
112531
+ if (display.displayMode === "week-board") return /* @__PURE__ */ jsx(EventCalendarWeekBoardClient, { render });
112279
112532
  return /* @__PURE__ */ jsx(EventCalendarGridClient, { render });
112280
112533
  };
112281
- EventCalendarWeekBoardClient = ({ display }) => {
112282
- const days = useMemo(() => getWeekCalendarDayTuple(/* @__PURE__ */ new Date(), display.startOfWeek), [display.startOfWeek]);
112283
- 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) });
112284
112572
  };
112285
112573
  EventCalendarTimetableClient = ({ render }) => {
112286
112574
  const { display, hydration } = render;
112287
112575
  const { filtersNode, listFilters } = useEventCalendarFilterState(display);
112288
112576
  const calendarInitialEvents = usePrefetchedCalendarEvents(display, listFilters);
112289
- const { events, viewDate, viewport, loading, error, goToPrevious, goToNext, goToToday } = useCalendarEvents({
112577
+ const { events, viewDate, viewport, loadState, retryCurrentView, goToPrevious, goToNext, goToToday } = useCalendarEvents({
112290
112578
  siteId: hydration.siteId,
112291
112579
  initialEvents: calendarInitialEvents,
112292
112580
  view: "week",
112293
112581
  startOfWeek: display.startOfWeek,
112294
112582
  preloadMonths: 1,
112295
112583
  filters: listFilters,
112296
- stage: hydration.stage
112584
+ stage: hydration.stage,
112585
+ calendarContext: hydration.calendarContext
112297
112586
  });
112298
112587
  return /* @__PURE__ */ jsxs(EventModalProvider, { children: [/* @__PURE__ */ jsx(EventCalendarChrome, {
112299
112588
  display,
112300
112589
  calendarView: "week",
112301
112590
  className: "event-calendar--timetable",
112302
- error,
112591
+ loadState,
112303
112592
  filters: filtersNode,
112304
112593
  headerTitle: viewport.title,
112305
- loading,
112594
+ onRetry: retryCurrentView,
112306
112595
  onNext: goToNext,
112307
112596
  onPrevious: goToPrevious,
112308
112597
  onToday: goToToday,
@@ -112311,7 +112600,8 @@ var init_EventCalendar_client = __esmMin((() => {
112311
112600
  events,
112312
112601
  startOfWeek: display.startOfWeek,
112313
112602
  emptyMessage: display.emptyMessage,
112314
- showCapacity: display.showCapacity
112603
+ showCapacity: display.showCapacity,
112604
+ today: hydration.calendarContext.initialToday
112315
112605
  })
112316
112606
  }), /* @__PURE__ */ jsx(EventModals, {
112317
112607
  cardRole: display.cardRole,
@@ -112325,24 +112615,25 @@ var init_EventCalendar_client = __esmMin((() => {
112325
112615
  const calendarView = display.defaultCalendarView;
112326
112616
  const { filtersNode, listFilters } = useEventCalendarFilterState(display);
112327
112617
  const calendarInitialEvents = usePrefetchedCalendarEvents(display, listFilters);
112328
- const { events, viewDate, viewport, loading, error, goToPrevious, goToNext, goToToday } = useCalendarEvents({
112618
+ const { events, viewDate, viewport, loadState, retryCurrentView, goToPrevious, goToNext, goToToday } = useCalendarEvents({
112329
112619
  siteId: hydration.siteId,
112330
112620
  initialEvents: calendarInitialEvents,
112331
112621
  view: calendarView,
112332
112622
  startOfWeek: display.startOfWeek,
112333
112623
  preloadMonths: 1,
112334
112624
  filters: listFilters,
112335
- stage: hydration.stage
112625
+ stage: hydration.stage,
112626
+ calendarContext: hydration.calendarContext
112336
112627
  });
112337
- const eventsByDate = useMemo(() => groupEventsByDate(events), [events]);
112628
+ const eventsByDate = useMemo(() => groupEventsByDate(events, hydration.calendarContext.timeZone), [events, hydration.calendarContext.timeZone]);
112338
112629
  const dayNames = useMemo(() => getOrderedDayNames(display.startOfWeek), [display.startOfWeek]);
112339
112630
  return /* @__PURE__ */ jsxs(EventModalProvider, { children: [/* @__PURE__ */ jsxs(EventCalendarChrome, {
112340
112631
  display,
112341
112632
  calendarView,
112342
- error,
112633
+ loadState,
112343
112634
  filters: filtersNode,
112344
112635
  headerTitle: viewport.title,
112345
- loading,
112636
+ onRetry: retryCurrentView,
112346
112637
  onNext: goToNext,
112347
112638
  onPrevious: goToPrevious,
112348
112639
  onToday: goToToday,
@@ -112350,7 +112641,9 @@ var init_EventCalendar_client = __esmMin((() => {
112350
112641
  days: viewport.days,
112351
112642
  events,
112352
112643
  emptyMessage: display.emptyMessage,
112353
- showCapacity: display.showCapacity
112644
+ showCapacity: display.showCapacity,
112645
+ calendarTimeZone: hydration.calendarContext.timeZone,
112646
+ today: hydration.calendarContext.initialToday
112354
112647
  }) : /* @__PURE__ */ jsxs("div", {
112355
112648
  className: "event-calendar-container",
112356
112649
  children: [/* @__PURE__ */ jsx("div", {
@@ -112367,11 +112660,12 @@ var init_EventCalendar_client = __esmMin((() => {
112367
112660
  return /* @__PURE__ */ jsx(CalendarDayCell, {
112368
112661
  date,
112369
112662
  events: dayEvents,
112370
- isCurrentMonth: date.getMonth() === viewDate.getMonth()
112663
+ isCurrentMonth: date.month === viewDate.month,
112664
+ today: hydration.calendarContext.initialToday
112371
112665
  }, dateKey);
112372
112666
  })
112373
112667
  })]
112374
- }), viewport.kind === "month" && events.length === 0 && !loading && !error ? /* @__PURE__ */ jsx("p", {
112668
+ }), viewport.kind === "month" && events.length === 0 && loadState.kind === "idle" ? /* @__PURE__ */ jsx("p", {
112375
112669
  className: "event-calendar-empty",
112376
112670
  children: display.emptyMessage
112377
112671
  }) : null]
@@ -112382,7 +112676,7 @@ var init_EventCalendar_client = __esmMin((() => {
112382
112676
  showCapacity: display.showCapacity
112383
112677
  })] });
112384
112678
  };
112385
- 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", {
112386
112680
  className: [
112387
112681
  "event-calendar",
112388
112682
  className,
@@ -112401,11 +112695,11 @@ var init_EventCalendar_client = __esmMin((() => {
112401
112695
  onClick: onPrevious,
112402
112696
  className: "event-calendar-nav-btn",
112403
112697
  "aria-label": calendarView === "week" ? "Previous week" : "Previous month",
112404
- children: /* @__PURE__ */ jsx(CalendarChevron, { direction: "previous" })
112698
+ children: /* @__PURE__ */ jsx(CalendarNavigationChevron, { direction: "previous" })
112405
112699
  }),
112406
112700
  /* @__PURE__ */ jsxs("h3", {
112407
112701
  className: "event-calendar-title",
112408
- children: [headerTitle, loading ? /* @__PURE__ */ jsx("span", {
112702
+ children: [headerTitle, loadState.kind === "loading" ? /* @__PURE__ */ jsx("span", {
112409
112703
  className: "rb-ml-2 rb-caption status-muted",
112410
112704
  children: "(loading...)"
112411
112705
  }) : null]
@@ -112415,7 +112709,7 @@ var init_EventCalendar_client = __esmMin((() => {
112415
112709
  onClick: onNext,
112416
112710
  className: "event-calendar-nav-btn",
112417
112711
  "aria-label": calendarView === "week" ? "Next week" : "Next month",
112418
- children: /* @__PURE__ */ jsx(CalendarChevron, { direction: "next" })
112712
+ children: /* @__PURE__ */ jsx(CalendarNavigationChevron, { direction: "next" })
112419
112713
  })
112420
112714
  ]
112421
112715
  }), /* @__PURE__ */ jsx("button", {
@@ -112429,14 +112723,14 @@ var init_EventCalendar_client = __esmMin((() => {
112429
112723
  })]
112430
112724
  }),
112431
112725
  children,
112432
- error ? /* @__PURE__ */ jsxs("div", {
112726
+ loadState.kind === "error" ? /* @__PURE__ */ jsxs("div", {
112433
112727
  className: "rb-mt-4 rb-text-center",
112434
112728
  children: [/* @__PURE__ */ jsx("p", {
112435
112729
  className: "status-error rb-caption rb-mb-2",
112436
112730
  children: "Failed to load events"
112437
112731
  }), /* @__PURE__ */ jsx("button", {
112438
112732
  type: "button",
112439
- onClick: onToday,
112733
+ onClick: onRetry,
112440
112734
  className: themeButtonClassName({
112441
112735
  variant: display.buttonVariant,
112442
112736
  size: "sm"