@riverbankcms/sdk 0.140.0 → 0.142.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 (145) hide show
  1. package/dist/{PreviewEditorSidebar-CUyTzd5z.mjs → PreviewEditorSidebar-Dk6Dt11f.mjs} +24 -15
  2. package/dist/{PreviewEditorUI-Agkw4v5i.mjs → PreviewEditorUI-D6EQTsCA.mjs} +3 -3
  3. package/dist/{PreviewQueryProvider-CN0ewic5.mjs → PreviewQueryProvider-CC-EPkyQ.mjs} +1 -1
  4. package/dist/{SdkPreviewModeRuntime-DdbeAdS8.mjs → SdkPreviewModeRuntime-DH1n4ytY.mjs} +85 -54
  5. package/dist/{SiteChromeCustomizeContext-CqGOz-Kv.mjs → SiteChromeCustomizeContext-DunIzY0K.mjs} +797 -216
  6. package/dist/_dts/api/src/billing.d.ts +6 -1
  7. package/dist/_dts/api/src/bookingConfig.d.ts +1 -1
  8. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +2 -2
  9. package/dist/_dts/api/src/contentRuntime.d.ts +12 -31
  10. package/dist/_dts/api/src/domainConnection.d.ts +4 -0
  11. package/dist/_dts/api/src/endpoints.d.ts +0 -27
  12. package/dist/_dts/api/src/footerCompositionContracts.d.ts +25 -0
  13. package/dist/_dts/api/src/index.d.ts +2 -2
  14. package/dist/_dts/api/src/launchReadiness.d.ts +1 -0
  15. package/dist/_dts/api/src/navigation/dashboardSiteNav.d.ts +2 -1
  16. package/dist/_dts/api/src/publicBookingService.d.ts +1 -0
  17. package/dist/_dts/api/src/sdkConfig/layout.d.ts +13 -0
  18. package/dist/_dts/api/src/sdkContracts.d.ts +3 -8
  19. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +3 -26
  20. package/dist/_dts/api/src/siteOnboarding.d.ts +7 -0
  21. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +1 -31
  22. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +6 -1
  23. package/dist/_dts/billing/src/site-arrangements.d.ts +18 -5
  24. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +4 -0
  25. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +2 -0
  26. package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +2 -0
  27. package/dist/_dts/blocks/src/system/blocks/events/eventSelectionFields.d.ts +122 -0
  28. package/dist/_dts/blocks/src/system/blocks/events/shared/calendarWindow.d.ts +2 -1
  29. package/dist/_dts/blocks/src/system/blocks/events/shared/eventSelection.d.ts +11 -0
  30. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +56 -0
  31. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +8 -0
  32. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +2 -2
  33. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +47 -47
  34. package/dist/_dts/blocks/src/system/data/prefetchBlockData.d.ts +5 -0
  35. package/dist/_dts/blocks/src/system/data/utils.d.ts +1 -1
  36. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +27 -1
  37. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +12 -180
  38. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +6 -90
  39. package/dist/_dts/blocks/src/system/runtime/hooks/useEventFilters.d.ts +2 -1
  40. package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +5 -1
  41. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +4 -0
  42. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.state.d.ts +5 -0
  43. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useDiscountCodeUi.d.ts +3 -0
  44. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useDiscountCodeUi.state.d.ts +10 -3
  45. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventCheckoutHandoffRestore.d.ts +9 -0
  46. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +4 -5
  47. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useSettledCommerceView.d.ts +37 -0
  48. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +4 -3
  49. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +3 -0
  50. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +11 -101
  51. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +63 -2
  52. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/listOptions.d.ts +2 -0
  53. package/dist/_dts/blocks/src/system/transforms/registry/eventCalendar.d.ts +12 -0
  54. package/dist/_dts/commerce/src/purchase/bookingInstalmentSchedule.d.ts +4 -0
  55. package/dist/_dts/commerce/src/purchase/stripeCommissionMetadata.d.ts +1 -2
  56. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +3102 -3122
  57. package/dist/_dts/editor-blocks/src/block-editor/ColourFieldOptionsProvider.d.ts +7 -0
  58. package/dist/_dts/editor-blocks/src/block-editor/colourFieldVisibility.d.ts +7 -0
  59. package/dist/_dts/editor-blocks/src/block-editor/preparedManifest.d.ts +2 -0
  60. package/dist/_dts/editor-blocks/src/index.d.ts +1 -0
  61. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/loaders.d.ts +27 -1
  62. package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +2 -2
  63. package/dist/_dts/preview-next/src/client/preview/PreviewFooterEditorPanel.d.ts +3 -6
  64. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +2 -2
  65. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +2 -2
  66. package/dist/_dts/preview-next/src/client/preview/footerInspection.d.ts +16 -0
  67. package/dist/_dts/preview-next/src/client/preview/sdkConfig.d.ts +6 -0
  68. package/dist/_dts/sdk/src/config/types.d.ts +2 -18
  69. package/dist/_dts/sdk/src/config/validation.d.ts +6 -0
  70. package/dist/_dts/sdk/src/public-api/contracts.d.ts +4 -1
  71. package/dist/_dts/sdk/src/version.d.ts +1 -1
  72. package/dist/_dts/theme-core/src/ThemeFontLoader.d.ts +17 -1
  73. package/dist/_dts/theme-core/src/buttons/affordanceSuppression.d.ts +17 -0
  74. package/dist/_dts/theme-core/src/buttons/buttonColourContract.d.ts +1 -1
  75. package/dist/_dts/theme-core/src/buttons/classNames.d.ts +16 -0
  76. package/dist/_dts/theme-core/src/buttons/generateButtonCss.d.ts +0 -6
  77. package/dist/_dts/theme-core/src/buttons/resolvedButtonCss.d.ts +4 -4
  78. package/dist/_dts/theme-core/src/footer/mode.d.ts +10 -1
  79. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  80. package/dist/_dts/theme-core/src/hosted-booking-appearance.d.ts +54 -12
  81. package/dist/_dts/theme-core/src/index.d.ts +1 -1
  82. package/dist/_dts/theme-core/src/schema.d.ts +1 -7
  83. package/dist/_dts/theme-core/src/site-styles/effectivePageDesign.d.ts +32 -0
  84. package/dist/_dts/theme-core/src/site-styles/index.d.ts +1 -0
  85. package/dist/client/{BookingConsentAgreement-CuKa82V4.mjs → BookingConsentAgreement-CnJeq3_r.mjs} +2 -2
  86. package/dist/client/{DiscountCodeDisclosure-BbYieKWB.mjs → DiscountCodeDisclosure-BINEO6J9.mjs} +1 -1
  87. package/dist/client/{EventCombined.client-LTfR1Aby.mjs → EventCombined.client-srxNQ6sZ.mjs} +11 -15
  88. package/dist/client/{EventListing.client-DUHpYSuo.mjs → EventListing.client-DbyVyGkX.mjs} +4 -17
  89. package/dist/client/{LeafletStaticMap-CHRupL6m.mjs → LeafletStaticMap-B-wpijzL.mjs} +1 -1
  90. package/dist/client/{accordion-6HiIFxNL.mjs → accordion-B-iUXU7n.mjs} +1 -1
  91. package/dist/client/{bookingForm-Dlmid43H.mjs → bookingForm-BXYPke5q.mjs} +5 -5
  92. package/dist/client/bookings.mjs +194 -102
  93. package/dist/client/{carousel-DmkZRRq_.mjs → carousel-Cr4aj63H.mjs} +1 -1
  94. package/dist/client/{cart-CIC24330.mjs → cart-DibP9WWa.mjs} +3 -3
  95. package/dist/client/{checkout-D1Zw9imo.mjs → checkout-CrSBVnL8.mjs} +3 -3
  96. package/dist/client/client.mjs +643 -192
  97. package/dist/client/{context-Cy1OayHx.mjs → context-Ces-AgdR.mjs} +1 -1
  98. package/dist/client/{dates-aDcfoLHr.mjs → dates-BXyNeNhB.mjs} +2 -2
  99. package/dist/client/{eventCalendar-FQxMPAjf.mjs → eventCalendar-HwpPeqrH.mjs} +11 -7
  100. package/dist/client/{eventCombined-Dr3ac6Hb.mjs → eventCombined-BpFUkuEI.mjs} +3 -3
  101. package/dist/client/{eventDetails-D-AzUHFQ.mjs → eventDetails-DK_agiWy.mjs} +4 -4
  102. package/dist/client/{eventListing-B3XxBf3i.mjs → eventListing-DhzHqP1c.mjs} +3 -3
  103. package/dist/client/{eventRegistration-I6EaokFD.mjs → eventRegistration-BdQ_Dn2d.mjs} +124 -32
  104. package/dist/client/{form-BbWckVWY.mjs → form-B1frcuzy.mjs} +2 -2
  105. package/dist/client/{headerSection-C9qU4Y7x.mjs → headerSection-CT5z460s.mjs} +2 -2
  106. package/dist/client/hooks.mjs +274 -45
  107. package/dist/client/{locationMap-CLCShvlG.mjs → locationMap-CIQXB9i2.mjs} +2 -2
  108. package/dist/client/{newsletterForm-Briukxzi.mjs → newsletterForm-BYNYZSes.mjs} +23 -10
  109. package/dist/client/{pricing-Copadu-2.mjs → pricing-CbTlAsmt.mjs} +1 -1
  110. package/dist/client/{productDetail-oujlRd-r.mjs → productDetail-CR7Z3yjS.mjs} +3 -3
  111. package/dist/client/{productList-BRiIRUcd.mjs → productList-DXj00vzR.mjs} +3 -3
  112. package/dist/client/{propsDecoder-CB2KS_ko.mjs → propsDecoder-DiLiBdek.mjs} +57 -16
  113. package/dist/client/rendering/client.mjs +476 -132
  114. package/dist/client/rendering/islands.mjs +17 -17
  115. package/dist/client/rendering.mjs +686 -195
  116. package/dist/client/{scrollToBlock-B1IS1_ua.mjs → scrollToBlock-CrcbBf0h.mjs} +28 -11
  117. package/dist/client/{shop-Vn6yNFED.mjs → shop-DgqiB_1b.mjs} +6 -6
  118. package/dist/client/{shop-commerce-BVTqipYp.mjs → shop-commerce-D_J781in.mjs} +5 -5
  119. package/dist/client/{shop-commerce-store-BVnJVy7v.mjs → shop-commerce-store-PGUbDwqe.mjs} +1 -1
  120. package/dist/client/{shopShared-COIeK77T.mjs → shopShared-C_Bb2zwG.mjs} +3 -3
  121. package/dist/client/{useEventFilters-DzIUcS9n.mjs → useEventFilters-CM17Xpr1.mjs} +17 -11
  122. package/dist/preview-next/before-render.mjs +0 -37
  123. package/dist/preview-next/client/runtime.mjs +4 -4
  124. package/dist/preview-next/editor-chrome.css +4 -8
  125. package/dist/preview-next/keepAlive.mjs +0 -37
  126. package/dist/preview-next/middleware.mjs +0 -37
  127. package/dist/{previewAuthStore-Gjb6r6vz.mjs → previewAuthStore-oVttoRDO.mjs} +0 -37
  128. package/dist/{sdk-runtime-CnCLvZRv.mjs → sdk-runtime-DhmuRhIX.mjs} +2 -2
  129. package/dist/{separator-DKDRJ1oH.mjs → separator-C3hlg9LH.mjs} +1 -1
  130. package/dist/server/components.mjs +452 -111
  131. package/dist/server/config-validation.mjs +263 -40
  132. package/dist/server/config.mjs +263 -40
  133. package/dist/server/data.mjs +274 -45
  134. package/dist/server/index.mjs +1 -38
  135. package/dist/server/next.mjs +427 -119
  136. package/dist/server/page-converter.mjs +208 -33
  137. package/dist/server/prebuild.mjs +1 -1
  138. package/dist/server/rendering/server.mjs +467 -119
  139. package/dist/server/rendering.mjs +467 -117
  140. package/dist/server/routing.mjs +301 -50
  141. package/dist/server/server.mjs +275 -83
  142. package/dist/server/theme-bridge.mjs +57 -23
  143. package/dist/server/theme.mjs +11 -9
  144. package/dist/styles/index.css +28 -2
  145. package/package.json +1 -1
@@ -1649,30 +1649,30 @@ function parseMailingListPlacementTargeting(value) {
1649
1649
  }
1650
1650
  }
1651
1651
  function parseMailingListVisitorSelection(value) {
1652
- if (!isRecord$41(value)) return visitorSelectionError("shape");
1652
+ if (!isRecord$41(value)) return visitorSelectionError$1("shape");
1653
1653
  switch (value.provider) {
1654
1654
  case "native": {
1655
1655
  const topicIds = parseVisitorIds(value.topicIds, parseNewsletterListId);
1656
- return topicIds === null ? visitorSelectionError("targets") : ok$3({
1656
+ return topicIds === null ? visitorSelectionError$1("targets") : ok$3({
1657
1657
  provider: "native",
1658
1658
  topicIds
1659
1659
  });
1660
1660
  }
1661
1661
  case "brevo": {
1662
1662
  const listIds = parseVisitorIds(value.listIds, parseBrevoListId);
1663
- return listIds === null ? visitorSelectionError("targets") : ok$3({
1663
+ return listIds === null ? visitorSelectionError$1("targets") : ok$3({
1664
1664
  provider: "brevo",
1665
1665
  listIds
1666
1666
  });
1667
1667
  }
1668
1668
  case "mailchimp": {
1669
1669
  const interestIds = parseVisitorIds(value.interestIds, parseMailchimpInterestId);
1670
- return interestIds === null ? visitorSelectionError("targets") : ok$3({
1670
+ return interestIds === null ? visitorSelectionError$1("targets") : ok$3({
1671
1671
  provider: "mailchimp",
1672
1672
  interestIds
1673
1673
  });
1674
1674
  }
1675
- default: return visitorSelectionError("provider");
1675
+ default: return visitorSelectionError$1("provider");
1676
1676
  }
1677
1677
  }
1678
1678
  function parseNativeTargeting(selection) {
@@ -1791,7 +1791,7 @@ function targetingError(field) {
1791
1791
  field
1792
1792
  });
1793
1793
  }
1794
- function visitorSelectionError(field) {
1794
+ function visitorSelectionError$1(field) {
1795
1795
  return err$3({
1796
1796
  tag: "invalid_mailing_list_visitor_selection",
1797
1797
  field
@@ -3571,7 +3571,10 @@ var init_contentMediaSnapshotAudit = __esmMin((() => {
3571
3571
  init_contentMediaAudit();
3572
3572
  init_contentMediaAuditFieldAdapter();
3573
3573
  init_identifiers();
3574
- })), init_src$1 = __esmMin((() => {
3574
+ }));
3575
+ //#endregion
3576
+ //#region ../media-core/src/index.ts
3577
+ var init_src$1 = __esmMin((() => {
3575
3578
  init_types$15();
3576
3579
  init_fileDomain();
3577
3580
  init_fileStorage();
@@ -3622,6 +3625,56 @@ var init_contentMediaSnapshotAudit = __esmMin((() => {
3622
3625
  init_contentMediaAudit();
3623
3626
  init_contentMediaAuditFieldAdapter();
3624
3627
  init_contentMediaSnapshotAudit();
3628
+ }));
3629
+ //#endregion
3630
+ //#region ../theme-core/src/footer/mode.ts
3631
+ /** Reads only SDK footer intent; unrelated config and theme fields are not authorities. */
3632
+ function resolveSdkFooterMode(config) {
3633
+ const parsed = z$1.object({ layout: z$1.object({ footerMode: footerModeSchema.optional() }).optional() }).safeParse(config);
3634
+ return parsed.success ? parsed.data.layout?.footerMode ?? "default" : "default";
3635
+ }
3636
+ /**
3637
+ * Resolve what to render for the footer given the current mode and whether the
3638
+ * site is SDK-managed.
3639
+ *
3640
+ * Backwards compatible: missing/undefined mode is treated as 'default'.
3641
+ */
3642
+ function resolveFooterRenderPlan(params) {
3643
+ if (!params.isSdkSite) return {
3644
+ mode: "default",
3645
+ renderDefaultFooter: true,
3646
+ renderFooterBlocks: false
3647
+ };
3648
+ switch (params.mode ?? "default") {
3649
+ case "blocks": return {
3650
+ mode: "blocks",
3651
+ renderDefaultFooter: false,
3652
+ renderFooterBlocks: true
3653
+ };
3654
+ case "default+blocks": return {
3655
+ mode: "default+blocks",
3656
+ renderDefaultFooter: true,
3657
+ renderFooterBlocks: true
3658
+ };
3659
+ case "none": return {
3660
+ mode: "none",
3661
+ renderDefaultFooter: false,
3662
+ renderFooterBlocks: false
3663
+ };
3664
+ default: return {
3665
+ mode: "default",
3666
+ renderDefaultFooter: true,
3667
+ renderFooterBlocks: false
3668
+ };
3669
+ }
3670
+ }
3671
+ var footerModeSchema, init_mode = __esmMin((() => {
3672
+ footerModeSchema = z$1.enum([
3673
+ "default",
3674
+ "blocks",
3675
+ "default+blocks",
3676
+ "none"
3677
+ ]);
3625
3678
  })), hotspotSchema, rotationSchema, rectSchema, aspectCropSchema, transformSchema, mediaPosterSchema, mediaBaseSchema, mediaIdentifierSchema, imageMediaSchema, videoMediaSchema, audioMediaSchema, documentMediaSchema, spreadsheetMediaSchema, archiveMediaSchema, mediaSchema, persistableMediaBaseSchema;
3626
3679
  var init_media$2 = __esmMin((() => {
3627
3680
  hotspotSchema = z$1.object({
@@ -5146,7 +5199,7 @@ var init_buttonColourContract = __esmMin((() => {
5146
5199
  nonTextMinimumRatio: 3,
5147
5200
  gradientSamplesPerSegment: 20,
5148
5201
  alphaBackgrounds: "reject-without-known-surface",
5149
- disabled: "retain-full-colour-contract"
5202
+ disabled: "validated-colour-pair-with-muted-control-opacity"
5150
5203
  };
5151
5204
  }));
5152
5205
  //#endregion
@@ -5718,6 +5771,12 @@ var init_parseThemeForPersistence = __esmMin((() => {
5718
5771
  init_types$14();
5719
5772
  }));
5720
5773
  //#endregion
5774
+ //#region ../theme-core/src/buttons/affordanceSuppression.ts
5775
+ var AFFORDANCE_SUPPRESS_CLASS;
5776
+ var init_affordanceSuppression = __esmMin((() => {
5777
+ AFFORDANCE_SUPPRESS_CLASS = "rb-affordance-off";
5778
+ }));
5779
+ //#endregion
5721
5780
  //#region ../theme-core/src/buttons/classNames.ts
5722
5781
  /**
5723
5782
  * Parse content/runtime variant identifiers into the closed theme-button class
@@ -5750,7 +5809,29 @@ function themeButtonClassName(spec) {
5750
5809
  spec.extraClassName
5751
5810
  ].filter(Boolean).join(" ");
5752
5811
  }
5812
+ /**
5813
+ * Button classes for an authored button that renders its own trailing icon.
5814
+ *
5815
+ * A separate function rather than a flag on `themeButtonClassName`, because
5816
+ * there is exactly one caller and it should stay visible in a diff. The name
5817
+ * states what the caller knows to be true of its own markup — that it renders a
5818
+ * trailing icon — rather than what the theme does about it. The consequence is
5819
+ * the theme's to decide and to change; a caller naming the consequence would be
5820
+ * asserting a policy it does not own, and would quietly become a lie the moment
5821
+ * that policy moved.
5822
+ *
5823
+ * Do not reach for this to remove an arrow you simply do not want. A trailing
5824
+ * affordance is declared by the button style, and a block overriding that is the
5825
+ * defect this replaced.
5826
+ */
5827
+ function themeButtonClassNameWithTrailingIcon(spec) {
5828
+ return themeButtonClassName({
5829
+ ...spec,
5830
+ extraClassName: [spec.extraClassName, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ")
5831
+ });
5832
+ }
5753
5833
  var init_classNames = __esmMin((() => {
5834
+ init_affordanceSuppression();
5754
5835
  init_types$14();
5755
5836
  }));
5756
5837
  //#endregion
@@ -8290,8 +8371,7 @@ var init_resolvedButtonCss = __esmMin((() => {
8290
8371
  ["cursor", "not-allowed"],
8291
8372
  ["transform", "none"],
8292
8373
  ["box-shadow", "none"],
8293
- ["outline", "2px dashed currentColor"],
8294
- ["outline-offset", "-4px"]
8374
+ ["opacity", "0.55"]
8295
8375
  ];
8296
8376
  }));
8297
8377
  //#endregion
@@ -8629,7 +8709,7 @@ function resolveBoxShadow(variant, global, theme, tokens) {
8629
8709
  const color = shadowConfig.colorToken ? tokens.getColor(shadowConfig.colorToken) : void 0;
8630
8710
  return generateShadowValue$1(shadowConfig.elevation, shadowConfig.softness, shadowConfig.position ?? "bottom", color);
8631
8711
  }
8632
- var AFFORDANCE_SUPPRESS_CLASS, BUTTON_SIZE_NAMES, LETTER_SPACING_MAP, STRUCTURAL_DECLARATIONS;
8712
+ var BUTTON_SIZE_NAMES, LETTER_SPACING_MAP, STRUCTURAL_DECLARATIONS;
8633
8713
  var init_generateButtonCss = __esmMin((() => {
8634
8714
  init_types$14();
8635
8715
  init_classNames();
@@ -8644,7 +8724,7 @@ var init_generateButtonCss = __esmMin((() => {
8644
8724
  init_resolveButtonColourStates();
8645
8725
  init_resolvedButtonCss();
8646
8726
  init_buttonSurfaceContext();
8647
- AFFORDANCE_SUPPRESS_CLASS = "rb-affordance-off";
8727
+ init_affordanceSuppression();
8648
8728
  BUTTON_SIZE_NAMES = buttonSizeNameSchema.options;
8649
8729
  LETTER_SPACING_MAP = {
8650
8730
  tight: "-0.025em",
@@ -11111,14 +11191,12 @@ function generateVariantCSS(variant, themeId, cardClasses, tokens, theme) {
11111
11191
  const shadowValue = generateShadowValue(shadow);
11112
11192
  rules.push(`box-shadow: ${shadowValue}`);
11113
11193
  }
11114
- rules.push(`display: flex`);
11115
- rules.push(`flex-direction: column`);
11116
- rules.push(`position: relative`);
11117
- rules.push(`overflow: visible`);
11194
+ const structureSelector = cardClasses.map((cardClass) => `:where([data-theme-scope="${themeId}"]) :where(.${cardClass})`).join(",\n");
11118
11195
  const mediaRadius = MEDIA_CORNER_MAP[corners];
11119
11196
  const mediaRules = [`border-top-left-radius: ${mediaRadius}`, `border-top-right-radius: ${mediaRadius}`];
11120
11197
  const contentRules = [`padding: ${resolveContentPadding(variant)}`];
11121
11198
  return [
11199
+ `${structureSelector} {\n display: flex;\n flex-direction: column;\n position: relative;\n overflow: visible;\n}`,
11122
11200
  `${containerSelector} {\n ${rules.join(";\n ")};\n}`,
11123
11201
  ...cardDecorationPseudoRules(containerSelectors, variant.decorations, resolveColor),
11124
11202
  `${fallbackBackgroundSelector} {\n background: transparent;\n}`,
@@ -12462,8 +12540,9 @@ var init_boxBackgroundSchema = __esmMin((() => {
12462
12540
  showVideoOnMobile: z$1.boolean().nullable().optional()
12463
12541
  })
12464
12542
  ]);
12465
- })), 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, headerPositioningValues, 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, testimonialQuoteTreatmentSchema, themeSchema;
12543
+ })), 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, headerPositioningValues, headerPositioning, headerNavStyle, navFontWeight, headerMaxWidth, headerBorderSchema, logoStyleSchema, headerLogoTextSchema, dropdownStyleSchema, headerCtaGapSchema, headerCtaTreatmentSchema, navContainerSchema, headerBackgroundSchema, headerSchema, footerVariant, footerMaxWidth, footerNavLayoutMode, footerNavLayoutAlign, footerSpacing, footerLogoPlacement, footerLogoSize, footerLogoMaxHeight, footerBottomTextLinkStyleSchema, footerBottomBarSchema, footerNavLayoutSchema, footerLogoSchema, footerSchema, containerPaddingPresetSchema, layoutSchema, heroTypographySizeSchema, heroTypographyLineHeightSchema, heroResponsiveTypographySchema, heroTypographySchema, heroSchema, bodyTextIntroTypographySizeSchema, bodyTextSchema, testimonialQuoteTreatmentSchema, themeSchema;
12466
12544
  var init_schema$2 = __esmMin((() => {
12545
+ init_mode();
12467
12546
  init_media$2();
12468
12547
  init_schema$3();
12469
12548
  init_buttons();
@@ -12962,12 +13041,6 @@ var init_schema$2 = __esmMin((() => {
12962
13041
  "split"
12963
13042
  ]);
12964
13043
  footerMaxWidth = z$1.enum(["container", "full"]);
12965
- footerMode = z$1.enum([
12966
- "default",
12967
- "blocks",
12968
- "default+blocks",
12969
- "none"
12970
- ]);
12971
13044
  footerNavLayoutMode = z$1.enum([
12972
13045
  "stack",
12973
13046
  "inline",
@@ -13056,9 +13129,9 @@ var init_schema$2 = __esmMin((() => {
13056
13129
  /**
13057
13130
  * SDK-only footer rendering mode.
13058
13131
  *
13059
- * Backwards compatible: missing/undefined behaves as 'default'.
13132
+ * Historical persisted field; SDK rendering mode now lives in layout.footerMode.
13060
13133
  */
13061
- mode: footerMode.optional(),
13134
+ mode: footerModeSchema.optional(),
13062
13135
  variant: footerVariant,
13063
13136
  maxWidth: footerMaxWidth,
13064
13137
  showLogoText: z$1.boolean().optional(),
@@ -13673,6 +13746,15 @@ var init_schemas = __esmMin((() => {
13673
13746
  timeZone: z$1.string(),
13674
13747
  pricing: publicEventPricingSchema,
13675
13748
  paymentTerms: blockBookingPaymentTermsSchema,
13749
+ cancellationPolicy: z$1.object({ refunds: z$1.object({
13750
+ mode: z$1.enum([
13751
+ "never",
13752
+ "always",
13753
+ "cutoff"
13754
+ ]),
13755
+ cutoffHours: z$1.number(),
13756
+ method: z$1.enum(["original_payment_method", "site_credit"])
13757
+ }) }),
13676
13758
  consent: blockBookingConsentSchema.nullable(),
13677
13759
  accessRestriction: accessRestrictionSchema,
13678
13760
  allowedCategoryIds: z$1.array(z$1.string()),
@@ -13838,6 +13920,7 @@ function calendarQueryKey(siteId, stage, filters) {
13838
13920
  filters.eventSurface ?? "all",
13839
13921
  normalizedCsv(filters.eventPresets),
13840
13922
  filters.scheduleScope ?? "any",
13923
+ ...filters.seriesIds === void 0 ? [] : [normalizedCsv(filters.seriesIds)],
13841
13924
  normalizedCsv(filters.categoryIds),
13842
13925
  normalizeCalendarFilterId(filters.venueId) ?? "",
13843
13926
  normalizeCalendarFilterId(filters.staffMemberId) ?? "",
@@ -13915,6 +13998,7 @@ var init_calendarWindow = __esmMin((() => {
13915
13998
  eventSurface: z$1.enum(eventSurfaceScopeValues).optional(),
13916
13999
  eventPresets: z$1.string().optional(),
13917
14000
  scheduleScope: z$1.enum(eventScheduleScopeValues).optional(),
14001
+ seriesIds: z$1.string().optional(),
13918
14002
  categoryIds: z$1.string().optional(),
13919
14003
  venueId: z$1.string().transform(normalizeCalendarFilterId).optional(),
13920
14004
  staffMemberId: z$1.string().transform(normalizeCalendarFilterId).optional()
@@ -21455,6 +21539,10 @@ var init_headerOpeningForeground = __esmMin((() => {
21455
21539
  init_colorTokenParts();
21456
21540
  init_types$8();
21457
21541
  }));
21542
+ var init_effectivePageDesign = __esmMin((() => {
21543
+ init_pageDesignIntent();
21544
+ init_siteStyleBlockPolicies();
21545
+ }));
21458
21546
  function validateBlockSequence(snapshots, ctx) {
21459
21547
  for (const issue of collectBlockSequenceIssues(snapshots)) ctx.addIssue(issue);
21460
21548
  }
@@ -21731,6 +21819,7 @@ var init_site_styles = __esmMin((() => {
21731
21819
  init_lookResolution();
21732
21820
  init_lookOptionGroups();
21733
21821
  init_logoBranding();
21822
+ init_effectivePageDesign();
21734
21823
  init_pageDesignAuthority();
21735
21824
  init_pageDesignEditorErrors();
21736
21825
  init_pageDesignEditorCapabilities();
@@ -24029,6 +24118,7 @@ var init_schema = __esmMin((() => {
24029
24118
  ];
24030
24119
  siteOptionSources = [
24031
24120
  "eventCategories",
24121
+ "eventSeries",
24032
24122
  "venues",
24033
24123
  "staffMembers"
24034
24124
  ];
@@ -28976,6 +29066,38 @@ var init_booking_form_interactive = __esmMin((() => {
28976
29066
  });
28977
29067
  }));
28978
29068
  //#endregion
29069
+ //#region ../blocks/src/system/blocks/events/shared/eventSelection.ts
29070
+ /** Invalid saved selections fail closed rather than widening discovery. */
29071
+ function resolveEventSelection(mode, value) {
29072
+ if (mode !== "selected") return { kind: "matching" };
29073
+ const candidates = Array.isArray(value) ? value : typeof value === "string" ? value.split(",").filter(Boolean) : [];
29074
+ const ids = [];
29075
+ for (const candidate of candidates) {
29076
+ if (typeof candidate !== "string") return {
29077
+ kind: "selected",
29078
+ seriesIds: []
29079
+ };
29080
+ const parsed = parseEventSeriesId(candidate.trim());
29081
+ if (!parsed.ok) return {
29082
+ kind: "selected",
29083
+ seriesIds: []
29084
+ };
29085
+ ids.push(parsed.value);
29086
+ }
29087
+ return {
29088
+ kind: "selected",
29089
+ seriesIds: [...new Set(ids)].sort()
29090
+ };
29091
+ }
29092
+ /** Undefined means discovery; an empty string is an explicitly empty selection. */
29093
+ function eventSeriesScopeCsv(value) {
29094
+ if (value == null) return void 0;
29095
+ return typeof value === "string" ? value : value.join(",");
29096
+ }
29097
+ var init_eventSelection = __esmMin((() => {
29098
+ init_src$2();
29099
+ }));
29100
+ //#endregion
28979
29101
  //#region ../blocks/src/system/runtime/nodes/events/domain/capacity.ts
28980
29102
  /**
28981
29103
  * Compute remaining spots for an event from `availableSpots` with a fallback
@@ -31660,12 +31782,12 @@ var init_EventCompactRow = __esmMin((() => {
31660
31782
  }), cta.hidden ? /* @__PURE__ */ jsx("span", {
31661
31783
  className: "event-compact-row-status",
31662
31784
  children: cta.label
31663
- }) : /* @__PURE__ */ jsxs("a", {
31785
+ }) : /* @__PURE__ */ jsx("a", {
31664
31786
  href: cta.href,
31665
31787
  target: cta.external ? "_blank" : void 0,
31666
31788
  rel: cta.external ? "noopener noreferrer" : void 0,
31667
31789
  className: `${buttonClass} event-compact-row-cta`,
31668
- children: [/* @__PURE__ */ jsx("span", { children: cta.label }), /* @__PURE__ */ jsx(ArrowRightIcon, { "aria-hidden": "true" })]
31790
+ children: /* @__PURE__ */ jsx("span", { children: cta.label })
31669
31791
  })]
31670
31792
  })]
31671
31793
  })]
@@ -31970,6 +32092,7 @@ function normalizeFilterId(value) {
31970
32092
  return id === "all" ? void 0 : id;
31971
32093
  }
31972
32094
  function buildEventRuntimeFilters(input) {
32095
+ if (input.seriesIds != null) return { seriesIds: input.seriesIds };
31973
32096
  const params = {};
31974
32097
  if (input.eventSurface && input.eventSurface !== "all") params.eventSurface = input.eventSurface;
31975
32098
  const eventPresets = normalizeCsvString(input.filterEventPresets);
@@ -31985,6 +32108,7 @@ function buildEventRuntimeFilters(input) {
31985
32108
  }
31986
32109
  function getEventRuntimeFiltersKey(filters) {
31987
32110
  return JSON.stringify({
32111
+ seriesIds: filters?.seriesIds == null ? null : [...new Set(filters.seriesIds.split(",").filter(Boolean))].sort().join(","),
31988
32112
  categoryIds: normalizeCsvString(filters?.categoryIds),
31989
32113
  staffMemberId: normalizeOptionalId(filters?.staffMemberId),
31990
32114
  venueId: normalizeOptionalId(filters?.venueId),
@@ -32045,11 +32169,15 @@ function buildEventCollectionDisplay(source) {
32045
32169
  };
32046
32170
  }
32047
32171
  function buildEventCollectionFilterDisplay(source) {
32048
- return {
32049
- showFilters: source.showFilters ?? true,
32050
- showCategoryFilter: source.showCategoryFilter ?? "auto",
32051
- showVenueFilter: source.showVenueFilter ?? false,
32052
- showStaffFilter: source.showStaffFilter ?? true,
32172
+ const selected = source.seriesIds != null;
32173
+ const matchingFilters = selected ? {
32174
+ eventSurface: "all",
32175
+ filterEventPresets: null,
32176
+ scheduleScope: "any",
32177
+ filterCategoryIds: null,
32178
+ filterStaffMemberId: null,
32179
+ filterVenueId: null
32180
+ } : {
32053
32181
  eventSurface: normalizeEventSurfaceScope(source.eventSurface),
32054
32182
  filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
32055
32183
  scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
@@ -32057,6 +32185,14 @@ function buildEventCollectionFilterDisplay(source) {
32057
32185
  filterStaffMemberId: normalizeEventStaffMemberId(source.filterStaffMemberId),
32058
32186
  filterVenueId: normalizeEventVenueId(source.filterVenueId)
32059
32187
  };
32188
+ return {
32189
+ seriesIds: eventSeriesScopeCsv(source.seriesIds),
32190
+ showFilters: selected ? false : source.showFilters ?? true,
32191
+ showCategoryFilter: source.showCategoryFilter ?? "auto",
32192
+ showVenueFilter: source.showVenueFilter ?? false,
32193
+ showStaffFilter: source.showStaffFilter ?? true,
32194
+ ...matchingFilters
32195
+ };
32060
32196
  }
32061
32197
  function buildEventCollectionPresentationDisplay(source) {
32062
32198
  return {
@@ -32071,14 +32207,15 @@ function buildEventCollectionPresentationDisplay(source) {
32071
32207
  }
32072
32208
  function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date()) {
32073
32209
  const timeZone = source.calendarWindow?.scope.timeZone ?? toBookingTimeZone(source.bookingTimeZone);
32210
+ const selected = source.seriesIds != null;
32074
32211
  return {
32075
32212
  calendarWindow: source.calendarWindow ?? void 0,
32076
32213
  siteId: source.siteId,
32077
32214
  stage: source.stage,
32078
32215
  prefetchedEvents: source.events != null,
32079
- eventSurface: normalizeEventSurfaceScope(source.eventSurface),
32080
- filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
32081
- scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
32216
+ eventSurface: selected ? "all" : normalizeEventSurfaceScope(source.eventSurface),
32217
+ filterEventPresets: selected ? null : normalizeEventSurfacePresetsCsv(source.filterEventPresets),
32218
+ scheduleScope: selected ? "any" : normalizeEventScheduleScope(source.scheduleScope),
32082
32219
  calendarContext: {
32083
32220
  timeZone,
32084
32221
  initialToday: source.calendarWindow?.initialToday ?? getLocalScheduleDate(now, timeZone)
@@ -32107,6 +32244,7 @@ function buildEventCollectionListingDisplay(display, prefetchedEvents, className
32107
32244
  }
32108
32245
  var eventSurfaceScopeSchema$1, eventScheduleScopeSchema$1, eventCollectionFilterSourceSchemaShape, eventCollectionSourceSchemaShape, eventCollectionDisplaySchemaShape, eventCollectionHydrationSchema;
32109
32246
  var init_eventCollectionContract = __esmMin((() => {
32247
+ init_eventSelection();
32110
32248
  init_calendarWindow();
32111
32249
  init_cards();
32112
32250
  init_src$2();
@@ -32125,6 +32263,7 @@ var init_eventCollectionContract = __esmMin((() => {
32125
32263
  eventSurface: eventSurfaceScopeSchema$1.nullable().optional(),
32126
32264
  filterEventPresets: z$1.union([z$1.string(), z$1.array(z$1.string())]).nullable().optional(),
32127
32265
  scheduleScope: eventScheduleScopeSchema$1.nullable().optional(),
32266
+ seriesIds: z$1.union([z$1.string(), z$1.array(z$1.string())]).nullable().optional(),
32128
32267
  filterCategoryIds: z$1.union([z$1.string(), z$1.array(z$1.string())]).nullable().optional(),
32129
32268
  filterStaffMemberId: z$1.string().nullable().optional(),
32130
32269
  filterVenueId: z$1.string().nullable().optional()
@@ -32171,6 +32310,7 @@ var init_eventCollectionContract = __esmMin((() => {
32171
32310
  eventSurface: eventSurfaceScopeSchema$1,
32172
32311
  filterEventPresets: z$1.string().nullable(),
32173
32312
  scheduleScope: eventScheduleScopeSchema$1,
32313
+ seriesIds: z$1.string().nullable().optional(),
32174
32314
  filterCategoryIds: z$1.string().nullable(),
32175
32315
  filterStaffMemberId: z$1.string().nullable(),
32176
32316
  filterVenueId: z$1.string().nullable(),
@@ -32216,6 +32356,7 @@ function buildEventListingInteractiveIslandProps(props) {
32216
32356
  }
32217
32357
  var cardOrientationSchema, eventSurfaceScopeSchema, eventScheduleScopeSchema, eventListingSourceSchema, eventListingDisplaySchema, eventListingHydrationSchema, eventListingRenderSchema, eventListingIslandMetaCodec, eventListingBlockRuntime, eventListingIslandMetaKeys, eventListingInteractiveIslandPropsCodec;
32218
32358
  var init_EventListing_interactive = __esmMin((() => {
32359
+ init_eventSelection();
32219
32360
  init_cards();
32220
32361
  init_schemas();
32221
32362
  init_shared$3();
@@ -32282,6 +32423,7 @@ var init_EventListing_interactive = __esmMin((() => {
32282
32423
  eventSurface: eventSurfaceScopeSchema,
32283
32424
  filterEventPresets: z$1.string().nullable(),
32284
32425
  scheduleScope: eventScheduleScopeSchema,
32426
+ seriesIds: z$1.string().nullable().optional(),
32285
32427
  filterCategoryIds: z$1.string().nullable().optional(),
32286
32428
  filterStaffMemberId: z$1.string().nullable().optional(),
32287
32429
  filterVenueId: z$1.string().nullable().optional(),
@@ -32342,6 +32484,7 @@ var init_EventListing_interactive = __esmMin((() => {
32342
32484
  eventSurface: normalizeEventSurfaceScope(source.eventSurface),
32343
32485
  filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
32344
32486
  scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
32487
+ seriesIds: eventSeriesScopeCsv(source.seriesIds),
32345
32488
  filterCategoryIds: normalizeEventCategoryIdsCsv(source.filterCategoryIds),
32346
32489
  filterStaffMemberId: normalizeEventStaffMemberId(source.filterStaffMemberId),
32347
32490
  filterVenueId: normalizeEventVenueId(source.filterVenueId),
@@ -32415,6 +32558,7 @@ function buildEventCalendarListingRender(render, className = render.display.clas
32415
32558
  eventSurface: display.eventSurface,
32416
32559
  filterEventPresets: display.filterEventPresets,
32417
32560
  scheduleScope: display.scheduleScope,
32561
+ seriesIds: display.seriesIds,
32418
32562
  filterCategoryIds: display.filterCategoryIds,
32419
32563
  filterStaffMemberId: display.filterStaffMemberId,
32420
32564
  filterVenueId: display.filterVenueId,
@@ -96935,10 +97079,14 @@ function buildDiscountAvailabilityRequestPlan(options) {
96935
97079
  }
96936
97080
  };
96937
97081
  }
96938
- function discountAvailabilityStateFromResponse(response) {
96939
- if (!discountAvailabilityHasDiscounts(response)) return { tag: "unavailable" };
97082
+ function discountAvailabilityStateFromResponse(requestKey, response) {
97083
+ if (!discountAvailabilityHasDiscounts(response)) return {
97084
+ tag: "unavailable",
97085
+ requestKey
97086
+ };
96940
97087
  return {
96941
97088
  tag: "available",
97089
+ requestKey,
96942
97090
  manualCodeEntryAllowed: discountAvailabilityAllowsManualEntry(response),
96943
97091
  autoAppliedDiscount: getAutoAppliedDiscountPreview(response)
96944
97092
  };
@@ -96948,10 +97096,13 @@ function discountCodeUiReducer(state, event) {
96948
97096
  case "availability-disabled": return initialDiscountCodeUiState;
96949
97097
  case "availability-loading": return {
96950
97098
  ...state,
96951
- availability: { tag: "loading" }
97099
+ availability: {
97100
+ tag: "loading",
97101
+ previous: state.availability.tag === "available" || state.availability.tag === "unavailable" ? state.availability : state.availability.tag === "loading" ? state.availability.previous : null
97102
+ }
96952
97103
  };
96953
97104
  case "availability-loaded": {
96954
- const availability = discountAvailabilityStateFromResponse(event.response);
97105
+ const availability = discountAvailabilityStateFromResponse(event.requestKey, event.response);
96955
97106
  if (availability.tag !== "available" || !availability.manualCodeEntryAllowed) return {
96956
97107
  ...state,
96957
97108
  discountUiOpen: false,
@@ -96967,7 +97118,10 @@ function discountCodeUiReducer(state, event) {
96967
97118
  ...state,
96968
97119
  discountUiOpen: false,
96969
97120
  discountCode: "",
96970
- availability: { tag: "error" }
97121
+ availability: {
97122
+ tag: "error",
97123
+ requestKey: event.requestKey
97124
+ }
96971
97125
  };
96972
97126
  case "discount-code-changed": return {
96973
97127
  ...state,
@@ -97012,11 +97166,15 @@ function useDiscountCodeUi(options) {
97012
97166
  if (cancelled) return;
97013
97167
  dispatch({
97014
97168
  type: "availability-loaded",
97169
+ requestKey: requestPlan.key,
97015
97170
  response: res
97016
97171
  });
97017
97172
  } catch {
97018
97173
  if (cancelled) return;
97019
- dispatch({ type: "availability-failed" });
97174
+ dispatch({
97175
+ type: "availability-failed",
97176
+ requestKey: requestPlan.key
97177
+ });
97020
97178
  }
97021
97179
  }
97022
97180
  checkDiscountAvailability();
@@ -97025,8 +97183,9 @@ function useDiscountCodeUi(options) {
97025
97183
  };
97026
97184
  }, [options.api, requestPlan]);
97027
97185
  const availability = state.availability;
97028
- const isAvailable = availability.tag === "available";
97029
- const manualCodeEntryAllowed = isAvailable ? availability.manualCodeEntryAllowed : false;
97186
+ const settledAvailability = availability.tag === "loading" ? availability.previous : availability.tag === "available" || availability.tag === "unavailable" ? availability : null;
97187
+ const isAvailable = settledAvailability?.tag === "available";
97188
+ const manualCodeEntryAllowed = isAvailable ? settledAvailability.manualCodeEntryAllowed : false;
97030
97189
  return {
97031
97190
  discountUiOpen: state.discountUiOpen,
97032
97191
  setDiscountUiOpen: (isOpen) => dispatch({
@@ -97040,8 +97199,10 @@ function useDiscountCodeUi(options) {
97040
97199
  }),
97041
97200
  discountsAvailable: isAvailable,
97042
97201
  manualCodeEntryAllowed,
97043
- autoAppliedDiscount: isAvailable ? availability.autoAppliedDiscount : null,
97044
- discountsAvailableLoading: availability.tag === "loading"
97202
+ autoAppliedDiscount: isAvailable ? settledAvailability.autoAppliedDiscount : null,
97203
+ discountsAvailableLoading: availability.tag === "loading",
97204
+ discountAvailabilityRequestKey: requestPlan.key,
97205
+ settledDiscountAvailabilityRequestKey: availability.tag === "error" ? availability.requestKey : settledAvailability?.requestKey ?? null
97045
97206
  };
97046
97207
  }
97047
97208
  var init_useDiscountCodeUi = __esmMin((() => {
@@ -101784,16 +101945,19 @@ function eligibilityLookupReducer(state, action) {
101784
101945
  case "loading-started": return {
101785
101946
  tag: "loading",
101786
101947
  eligibility: state.eligibility,
101948
+ settledRequestKey: state.settledRequestKey,
101787
101949
  error: null
101788
101950
  };
101789
101951
  case "resolved": return {
101790
101952
  tag: "resolved",
101791
101953
  eligibility: action.eligibility,
101954
+ settledRequestKey: action.requestKey,
101792
101955
  error: null
101793
101956
  };
101794
101957
  case "failed": return {
101795
101958
  tag: "failed",
101796
101959
  eligibility: null,
101960
+ settledRequestKey: null,
101797
101961
  error: action.message
101798
101962
  };
101799
101963
  default: return assertNever$11(action);
@@ -101819,6 +101983,7 @@ var init_hooks_state = __esmMin((() => {
101819
101983
  initialEligibilityLookupState = {
101820
101984
  tag: "idle",
101821
101985
  eligibility: null,
101986
+ settledRequestKey: null,
101822
101987
  error: null
101823
101988
  };
101824
101989
  initialExistingRegistrationLookupState = {
@@ -101898,9 +102063,23 @@ function toRegistrationOptionsSubject(subject, attendanceMode) {
101898
102063
  function useEligibility(params) {
101899
102064
  return useEligibilityWithDeps(params, eventRegistrationHooksDeps);
101900
102065
  }
102066
+ function eligibilityRequestKey(params) {
102067
+ return JSON.stringify({
102068
+ enabled: params.enabled,
102069
+ refreshKey: params.refreshKey ?? 0,
102070
+ subject: params.subject,
102071
+ attendanceMode: params.attendanceMode ?? null,
102072
+ ticketSelections: params.ticketSelectionsKey,
102073
+ selectedSlidingAmount: params.selectedSlidingAmount ?? null
102074
+ });
102075
+ }
101901
102076
  function useEligibilityWithDeps(params, deps) {
101902
102077
  const api = deps.useBlockApi();
101903
102078
  const ticketSelectionsKey = JSON.stringify(normalizeTicketSelectionLines(params.ticketSelections));
102079
+ const requestKey = eligibilityRequestKey({
102080
+ ...params,
102081
+ ticketSelectionsKey
102082
+ });
101904
102083
  const [state, dispatch] = useReducer(eligibilityLookupReducer, initialEligibilityLookupState);
101905
102084
  const requestIdRef = useRef(0);
101906
102085
  useEffect(() => {
@@ -101933,7 +102112,8 @@ function useEligibilityWithDeps(params, deps) {
101933
102112
  if (cancelled || requestIdRef.current !== requestId) return;
101934
102113
  dispatch({
101935
102114
  type: "resolved",
101936
- eligibility: transformRegistrationOptionsResponse(result)
102115
+ eligibility: transformRegistrationOptionsResponse(result),
102116
+ requestKey
101937
102117
  });
101938
102118
  } catch {
101939
102119
  if (cancelled || requestIdRef.current !== requestId) return;
@@ -101962,6 +102142,8 @@ function useEligibilityWithDeps(params, deps) {
101962
102142
  return {
101963
102143
  state,
101964
102144
  eligibility: state.eligibility,
102145
+ settledRequestKey: state.settledRequestKey,
102146
+ requestKey,
101965
102147
  isLoading: state.tag === "loading",
101966
102148
  error: state.error,
101967
102149
  creditState
@@ -102383,7 +102565,6 @@ var init_stripeCommissionMetadata = __esmMin((() => {
102383
102565
  "no_commission_plan",
102384
102566
  "billing_evidence_invalid",
102385
102567
  "fee_rounds_to_zero",
102386
- "non_commissionable_scope",
102387
102568
  "payment_not_stripe"
102388
102569
  ];
102389
102570
  historicalContext = {
@@ -103563,6 +103744,71 @@ var init_useEventRegistrationSubmit = __esmMin((() => {
103563
103744
  };
103564
103745
  }));
103565
103746
  //#endregion
103747
+ //#region ../blocks/src/system/runtime/nodes/event-registration/useSettledCommerceView.ts
103748
+ function buildCandidate(input) {
103749
+ if (!input.eligibilityIsSettled || !input.eligibility || !input.currentEvent) return null;
103750
+ return {
103751
+ eventSelectionId: input.currentEvent.selectionId,
103752
+ discountContext: resolveDiscountContext({
103753
+ paymentSelection: input.paymentSelection,
103754
+ event: input.currentEvent,
103755
+ eventRequiresPayment: input.eventRequiresPayment,
103756
+ ticketsCount: input.ticketsCount
103757
+ }),
103758
+ subtotalCents: input.eligibility.price,
103759
+ summaryLines: input.eligibility.ticketLines.map((line) => ({
103760
+ pricingOptionId: line.pricingOptionId,
103761
+ label: line.label,
103762
+ quantity: line.quantity,
103763
+ unitPriceCents: line.unitPriceCents,
103764
+ subtotalCents: line.subtotalCents
103765
+ }))
103766
+ };
103767
+ }
103768
+ function eligibilityIsSettled(result) {
103769
+ return result.settledRequestKey === result.requestKey;
103770
+ }
103771
+ function viewIsStale(view, currentEvent, eligibilityState) {
103772
+ return view.eventSelectionId !== currentEvent?.selectionId || eligibilityState?.tag === "failed" || eligibilityState?.tag === "idle";
103773
+ }
103774
+ function requestIsSettled(discountUi) {
103775
+ return discountUi.discountAvailabilityRequestKey === "disabled" || discountUi.settledDiscountAvailabilityRequestKey === discountUi.discountAvailabilityRequestKey;
103776
+ }
103777
+ function discountRequest(view) {
103778
+ const discountContext = view?.discountContext ?? null;
103779
+ return {
103780
+ discountContext,
103781
+ subtotalCents: discountContext?.type === "event" && view?.subtotalCents !== null ? view?.subtotalCents : void 0
103782
+ };
103783
+ }
103784
+ function useSettledCommerceView(input) {
103785
+ const candidate = buildCandidate({
103786
+ eligibilityIsSettled: eligibilityIsSettled(input.eligibilityResult),
103787
+ eligibility: input.eligibility,
103788
+ currentEvent: input.currentEvent,
103789
+ paymentSelection: input.paymentSelection,
103790
+ eventRequiresPayment: input.eventRequiresPayment,
103791
+ ticketsCount: input.ticketsCount
103792
+ });
103793
+ const settledRef = useRef(candidate);
103794
+ if (settledRef.current && viewIsStale(settledRef.current, input.currentEvent, input.eligibilityResult.state)) settledRef.current = null;
103795
+ const requestView = candidate ?? settledRef.current;
103796
+ const discountUi = input.useDiscountCodeUi({
103797
+ api: input.api,
103798
+ ...discountRequest(requestView)
103799
+ });
103800
+ if (candidate && requestIsSettled(discountUi)) settledRef.current = candidate;
103801
+ return {
103802
+ discountUi,
103803
+ discountContext: settledRef.current?.discountContext ?? null,
103804
+ ticketSelectionSubtotalCents: settledRef.current?.subtotalCents ?? null,
103805
+ ticketSelectionSummaryLines: settledRef.current?.summaryLines ?? []
103806
+ };
103807
+ }
103808
+ var init_useSettledCommerceView = __esmMin((() => {
103809
+ init_registrationDerivations();
103810
+ }));
103811
+ //#endregion
103566
103812
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationWizardContext.ts
103567
103813
  function getEventSelectionDefaults(event) {
103568
103814
  const suggestedAmount = getSlidingScaleForEvent(event)?.suggestedAmount;
@@ -103725,10 +103971,6 @@ function isSoldOutWithoutWaitlist(input) {
103725
103971
  var init_registrationCompletion = __esmMin((() => {}));
103726
103972
  //#endregion
103727
103973
  //#region ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
103728
- function resolveDiscountSubtotalCents(context, subtotalCents) {
103729
- if (context?.type !== "event" || subtotalCents === null) return void 0;
103730
- return subtotalCents;
103731
- }
103732
103974
  function usesTieredPricing(event) {
103733
103975
  return event !== null && event !== void 0 ? publicEventPricingStrategy(event.pricing) === "tiered" : false;
103734
103976
  }
@@ -104171,30 +104413,15 @@ function useEventRegistrationWizardWithDeps(options, deps) {
104171
104413
  }
104172
104414
  setStep("select-tickets");
104173
104415
  };
104174
- const discountContext = useMemo(() => resolveDiscountContext({
104175
- paymentSelection,
104176
- event: currentEvent,
104177
- eventRequiresPayment,
104178
- ticketsCount
104179
- }), [
104416
+ const { discountUi, discountContext, ticketSelectionSubtotalCents, ticketSelectionSummaryLines } = useSettledCommerceView({
104417
+ api,
104418
+ useDiscountCodeUi: deps.useDiscountCodeUi,
104419
+ eligibilityResult,
104420
+ eligibility,
104180
104421
  currentEvent,
104181
104422
  eventRequiresPayment,
104182
104423
  paymentSelection,
104183
104424
  ticketsCount
104184
- ]);
104185
- const ticketSelectionSubtotalCents = eligibility?.price ?? null;
104186
- const ticketSelectionSummaryLines = useMemo(() => eligibility?.ticketLines.map((line) => ({
104187
- pricingOptionId: line.pricingOptionId,
104188
- label: line.label,
104189
- quantity: line.quantity,
104190
- unitPriceCents: line.unitPriceCents,
104191
- subtotalCents: line.subtotalCents
104192
- })) ?? [], [eligibility]);
104193
- const discountSubtotalCents = resolveDiscountSubtotalCents(discountContext, ticketSelectionSubtotalCents);
104194
- const discountUi = deps.useDiscountCodeUi({
104195
- api,
104196
- discountContext,
104197
- subtotalCents: discountSubtotalCents
104198
104425
  });
104199
104426
  const selectionMethod = paymentSelection.method;
104200
104427
  const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
@@ -104373,6 +104600,7 @@ var init_useEventRegistrationWizard = __esmMin((() => {
104373
104600
  init_useEventRegistrationStripeReturn();
104374
104601
  init_useEventRegistrationSubmit();
104375
104602
  init_useDiscountCodeUi();
104603
+ init_useSettledCommerceView();
104376
104604
  init_utils();
104377
104605
  init_ticketSelectionLines();
104378
104606
  init_registrationStateMachine();
@@ -104395,6 +104623,38 @@ var init_useEventRegistrationWizard = __esmMin((() => {
104395
104623
  };
104396
104624
  }));
104397
104625
  //#endregion
104626
+ //#region ../blocks/src/system/runtime/nodes/event-registration/useEventCheckoutHandoffRestore.ts
104627
+ function eventRegistrationReloadTarget(location) {
104628
+ return `${location.pathname}${location.search}#${EVENT_REGISTRATION_ANCHOR_ID}`;
104629
+ }
104630
+ function reloadAtEventRegistration() {
104631
+ const target = eventRegistrationReloadTarget(window.location);
104632
+ window.history.replaceState(window.history.state, "", target);
104633
+ window.location.reload();
104634
+ }
104635
+ function useEventCheckoutHandoffRestore(active) {
104636
+ useEventCheckoutHandoffRestoreWithDeps(active, browserCheckoutHandoffRestoreDeps);
104637
+ }
104638
+ function useEventCheckoutHandoffRestoreWithDeps(active, deps) {
104639
+ useEffect(() => {
104640
+ if (!active) return;
104641
+ const handlePageShow = (event) => {
104642
+ if (event.persisted) deps.reloadAtRegistration();
104643
+ };
104644
+ deps.addPageShowListener(handlePageShow);
104645
+ return () => deps.removePageShowListener(handlePageShow);
104646
+ }, [active, deps]);
104647
+ }
104648
+ var browserCheckoutHandoffRestoreDeps;
104649
+ var init_useEventCheckoutHandoffRestore = __esmMin((() => {
104650
+ init_constants();
104651
+ browserCheckoutHandoffRestoreDeps = {
104652
+ addPageShowListener: (listener) => window.addEventListener("pageshow", listener),
104653
+ removePageShowListener: (listener) => window.removeEventListener("pageshow", listener),
104654
+ reloadAtRegistration: reloadAtEventRegistration
104655
+ };
104656
+ }));
104657
+ //#endregion
104398
104658
  //#region ../blocks/src/system/runtime/nodes/shared/MagicLinkForm.state.ts
104399
104659
  function magicLinkSubmissionReducer(state, action) {
104400
104660
  switch (action.type) {
@@ -107055,6 +107315,7 @@ function EventRegistrationWizard(props) {
107055
107315
  events: events ?? [],
107056
107316
  maxTicketsNum
107057
107317
  });
107318
+ useEventCheckoutHandoffRestore(wizard.step === "redirecting");
107058
107319
  const [bookingOverlayOpen, setBookingOverlayOpen] = useState(false);
107059
107320
  const [floatingPortalRoot, setFloatingPortalRoot] = useState(null);
107060
107321
  useEffect(() => {
@@ -107187,6 +107448,7 @@ var init_EventRegistrationWizard = __esmMin((() => {
107187
107448
  init_themePortalRoot();
107188
107449
  init_buttons();
107189
107450
  init_constants();
107451
+ init_useEventCheckoutHandoffRestore();
107190
107452
  init_EventRegistrationSurface();
107191
107453
  init_EventRegistrationBookingLayer();
107192
107454
  EVENT_PORTAL_AUTH_COPY = {
@@ -108645,6 +108907,7 @@ function useEventPagination({ siteId: _siteId, initialEvents = [], fetchInitialO
108645
108907
  const eventSurface = filters?.eventSurface;
108646
108908
  const eventPresets = normalizeCsvString(filters?.eventPresets);
108647
108909
  const scheduleScope = filters?.scheduleScope;
108910
+ const seriesIds = filters?.seriesIds;
108648
108911
  const eventsRef = useRef(events);
108649
108912
  const loadingRef = useRef(loading);
108650
108913
  const hasMoreRef = useRef(hasMore);
@@ -108672,6 +108935,7 @@ function useEventPagination({ siteId: _siteId, initialEvents = [], fetchInitialO
108672
108935
  const currentEvents = eventsRef.current;
108673
108936
  const lastEvent = options.reset ? void 0 : currentEvents[currentEvents.length - 1];
108674
108937
  const newEvents = await getPublicEvents({
108938
+ seriesIds,
108675
108939
  afterStartsAt: lastEvent ? lastEvent.startsAt : void 0,
108676
108940
  afterId: lastEvent ? lastEvent.occurrenceId : void 0,
108677
108941
  limit: pageSize,
@@ -108710,6 +108974,7 @@ function useEventPagination({ siteId: _siteId, initialEvents = [], fetchInitialO
108710
108974
  eventSurface,
108711
108975
  eventPresets,
108712
108976
  scheduleScope,
108977
+ seriesIds,
108713
108978
  normalizedCategoryIds,
108714
108979
  normalizedStaffMemberId,
108715
108980
  normalizedVenueId
@@ -108719,7 +108984,7 @@ function useEventPagination({ siteId: _siteId, initialEvents = [], fetchInitialO
108719
108984
  }, [fetchPage]);
108720
108985
  const initialFetchAttemptKeyRef = useRef(null);
108721
108986
  useEffect(() => {
108722
- if (!fetchInitialOnMount) return;
108987
+ if (!fetchInitialOnMount || seriesIds === "") return;
108723
108988
  if (!filtersMatchInitial) return;
108724
108989
  if (initialEventsRef.current.length > 0) return;
108725
108990
  if (eventsRef.current.length > 0) return;
@@ -108733,7 +108998,8 @@ function useEventPagination({ siteId: _siteId, initialEvents = [], fetchInitialO
108733
108998
  fetchPage,
108734
108999
  filtersKey,
108735
109000
  filtersMatchInitial,
108736
- stage
109001
+ stage,
109002
+ seriesIds
108737
109003
  ]);
108738
109004
  const prevFiltersMatchInitialRef = useRef(filtersMatchInitial);
108739
109005
  const prevInitialEventsKeyRef = useRef(initialEventsKey);
@@ -108868,7 +109134,7 @@ var init_useEventFilters_state = __esmMin((() => {
108868
109134
  * const events = await api.getPublicEvents(params);
108869
109135
  * ```
108870
109136
  */
108871
- function useEventFilters({ showCategoryFilter = "auto", showVenueFilter = false, showStaffFilter = false, preFilterCategoryIds, preFilterStaffMemberId, preFilterVenueId, preFilterEventSurface, preFilterEventPresets, preFilterScheduleScope } = {}) {
109137
+ function useEventFilters({ showCategoryFilter = "auto", showVenueFilter = false, showStaffFilter = false, preFilterSeriesIds, preFilterCategoryIds, preFilterStaffMemberId, preFilterVenueId, preFilterEventSurface, preFilterEventPresets, preFilterScheduleScope } = {}) {
108872
109138
  const api = useBlockApi();
108873
109139
  const [loadState, dispatchLoadState] = useReducer(eventFiltersLoadReducer, void 0, createInitialEventFiltersLoadState);
108874
109140
  const filters = getEventFiltersData(loadState);
@@ -109017,6 +109283,7 @@ function useEventFilters({ showCategoryFilter = "auto", showVenueFilter = false,
109017
109283
  setSelectedVenueId("all");
109018
109284
  }, []),
109019
109285
  getFilterParams: useCallback(() => {
109286
+ if (preFilterSeriesIds != null) return { seriesIds: preFilterSeriesIds };
109020
109287
  const params = {};
109021
109288
  if (fixedEventSurface) params.eventSurface = fixedEventSurface;
109022
109289
  if (fixedEventPresets) params.eventPresets = fixedEventPresets;
@@ -109030,6 +109297,7 @@ function useEventFilters({ showCategoryFilter = "auto", showVenueFilter = false,
109030
109297
  params.staffMemberId = fixedStaffMemberId ?? (selectedStaffMemberId !== "all" ? selectedStaffMemberId : void 0);
109031
109298
  return params;
109032
109299
  }, [
109300
+ preFilterSeriesIds,
109033
109301
  allowedCategoryIds,
109034
109302
  allowedCategorySet,
109035
109303
  fixedEventPresets,
@@ -109065,25 +109333,12 @@ var init_EventListing_client = __esmMin((() => {
109065
109333
  const hydration = render.hydration;
109066
109334
  const filtersIdBase = useId();
109067
109335
  const initialListEvents = useMemo(() => [...display.events], [display.events]);
109068
- const initialListFilters = useMemo(() => buildEventRuntimeFilters({
109069
- eventSurface: hydration.eventSurface,
109070
- filterEventPresets: hydration.filterEventPresets,
109071
- scheduleScope: hydration.scheduleScope,
109072
- filterCategoryIds: hydration.filterCategoryIds,
109073
- filterStaffMemberId: hydration.filterStaffMemberId,
109074
- filterVenueId: hydration.filterVenueId
109075
- }), [
109076
- hydration.eventSurface,
109077
- hydration.filterEventPresets,
109078
- hydration.scheduleScope,
109079
- hydration.filterCategoryIds,
109080
- hydration.filterStaffMemberId,
109081
- hydration.filterVenueId
109082
- ]);
109336
+ const initialListFilters = buildEventRuntimeFilters(hydration);
109083
109337
  const { categories, venues, staffMembers, selectedCategoryId, selectedStaffMemberId, selectedVenueId, loading: filtersLoading, shouldShowCategoryFilter, shouldShowVenueFilter, shouldShowStaffFilter, hasActiveFilters, setSelectedCategoryId, setSelectedStaffMemberId, setSelectedVenueId, resetFilters, getFilterParams } = useEventFilters({
109084
109338
  showCategoryFilter: hydration.showFilters ? hydration.showCategoryFilter : "never",
109085
109339
  showVenueFilter: hydration.showFilters ? hydration.showVenueFilter : false,
109086
109340
  showStaffFilter: hydration.showFilters ? hydration.showStaffFilter : false,
109341
+ preFilterSeriesIds: hydration.seriesIds,
109087
109342
  preFilterCategoryIds: hydration.filterCategoryIds ?? void 0,
109088
109343
  preFilterStaffMemberId: hydration.filterStaffMemberId ?? void 0,
109089
109344
  preFilterVenueId: hydration.filterVenueId ?? void 0,
@@ -110155,6 +110410,7 @@ function toEventCombinedControllerProps(props) {
110155
110410
  eventSurface: props.render.display.eventSurface,
110156
110411
  filterEventPresets: props.render.display.filterEventPresets,
110157
110412
  scheduleScope: props.render.display.scheduleScope,
110413
+ seriesIds: props.render.display.seriesIds,
110158
110414
  filterCategoryIds: props.render.display.filterCategoryIds,
110159
110415
  filterStaffMemberId: props.render.display.filterStaffMemberId,
110160
110416
  filterVenueId: props.render.display.filterVenueId,
@@ -110290,7 +110546,7 @@ var init_EventCombined_client = __esmMin((() => {
110290
110546
  EventCombinedClient = ({ events: initialEvents, siteId, stage, listLayout = "stack", listColumns = "3", eventsPerPage = 12, paginationAction = {
110291
110547
  kind: "loadMore",
110292
110548
  label: "Load more events"
110293
- }, 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, calendarWindow }) => {
110549
+ }, startOfWeek = "monday", calendarTabViews = "both", defaultCalendarView, showFilters, showCategoryFilter = "auto", showVenueFilter, showStaffFilter, eventSurface, filterEventPresets, scheduleScope, seriesIds, filterCategoryIds, filterStaffMemberId, filterVenueId, showVenue, showMap, showCapacity, cardRole, buttonVariant = "primary", buttonText = "Book", emptyMessage = "No upcoming events scheduled.", className, calendarContext, calendarWindow }) => {
110294
110550
  const hydrationReady = useHydrationReady();
110295
110551
  const fetchInitialEventsOnMount = initialEvents == null;
110296
110552
  const resolvedShowFilters = showFilters ?? true;
@@ -110316,6 +110572,7 @@ var init_EventCombined_client = __esmMin((() => {
110316
110572
  showCategoryFilter: resolvedShowFilters ? showCategoryFilter : "never",
110317
110573
  showVenueFilter: resolvedShowFilters ? resolvedShowVenueFilter : false,
110318
110574
  showStaffFilter: resolvedShowFilters ? resolvedShowStaffFilter : false,
110575
+ preFilterSeriesIds: seriesIds,
110319
110576
  preFilterCategoryIds: filterCategoryIds,
110320
110577
  preFilterStaffMemberId: filterStaffMemberId,
110321
110578
  preFilterVenueId: filterVenueId,
@@ -110323,21 +110580,15 @@ var init_EventCombined_client = __esmMin((() => {
110323
110580
  preFilterEventPresets: filterEventPresets,
110324
110581
  preFilterScheduleScope: resolvedScheduleScope
110325
110582
  });
110326
- const initialListFilters = useMemo(() => buildEventRuntimeFilters({
110583
+ const initialListFilters = buildEventRuntimeFilters({
110327
110584
  eventSurface: resolvedEventSurface,
110328
110585
  filterEventPresets,
110329
110586
  scheduleScope: resolvedScheduleScope,
110587
+ seriesIds,
110330
110588
  filterCategoryIds,
110331
110589
  filterStaffMemberId,
110332
110590
  filterVenueId
110333
- }), [
110334
- resolvedEventSurface,
110335
- filterCategoryIds,
110336
- filterEventPresets,
110337
- filterStaffMemberId,
110338
- filterVenueId,
110339
- resolvedScheduleScope
110340
- ]);
110591
+ });
110341
110592
  const listFilters = useMemo(() => getFilterParams(), [getFilterParams]);
110342
110593
  const pageSize = eventsPerPage;
110343
110594
  const { events: paginatedEvents, loading: eventsLoading, error: eventsError, hasMore, loadMore } = useEventPagination({
@@ -110950,6 +111201,7 @@ function useEventCalendarFilterState(display) {
110950
111201
  showCategoryFilter: display.showFilters ? display.showCategoryFilter : "never",
110951
111202
  showVenueFilter: display.showFilters ? display.showVenueFilter : false,
110952
111203
  showStaffFilter: display.showFilters ? display.showStaffFilter : false,
111204
+ preFilterSeriesIds: display.seriesIds,
110953
111205
  preFilterCategoryIds: display.filterCategoryIds,
110954
111206
  preFilterStaffMemberId: display.filterStaffMemberId,
110955
111207
  preFilterVenueId: display.filterVenueId,
@@ -110983,6 +111235,7 @@ function buildDisplayFilterParams(display) {
110983
111235
  eventSurface: display.eventSurface,
110984
111236
  filterEventPresets: display.filterEventPresets,
110985
111237
  scheduleScope: display.scheduleScope,
111238
+ seriesIds: display.seriesIds,
110986
111239
  filterCategoryIds: display.filterCategoryIds,
110987
111240
  filterStaffMemberId: display.filterStaffMemberId,
110988
111241
  filterVenueId: display.filterVenueId
@@ -111029,6 +111282,7 @@ var init_EventCalendar_client = __esmMin((() => {
111029
111282
  eventSurface: display.eventSurface,
111030
111283
  filterEventPresets: display.filterEventPresets,
111031
111284
  scheduleScope: display.scheduleScope,
111285
+ seriesIds: display.seriesIds,
111032
111286
  filterCategoryIds: display.filterCategoryIds,
111033
111287
  filterStaffMemberId: display.filterStaffMemberId,
111034
111288
  filterVenueId: display.filterVenueId,
@@ -111052,6 +111306,7 @@ var init_EventCalendar_client = __esmMin((() => {
111052
111306
  const { display, hydration } = render;
111053
111307
  const filters = useMemo(() => buildDisplayFilterParams(display), [
111054
111308
  display.eventSurface,
111309
+ display.seriesIds,
111055
111310
  display.filterCategoryIds,
111056
111311
  display.filterEventPresets,
111057
111312
  display.filterStaffMemberId,
@@ -113677,7 +113932,7 @@ function NewsletterFormClient({ render }) {
113677
113932
  if (submitTarget.tag === "unavailable") {
113678
113933
  dispatchSubmission({
113679
113934
  type: "failed",
113680
- error: newsletterFormError("Newsletter list is not configured")
113935
+ error: newsletterFormError(SIGNUPS_PAUSED_MESSAGE)
113681
113936
  });
113682
113937
  return;
113683
113938
  }
@@ -113688,14 +113943,16 @@ function NewsletterFormClient({ render }) {
113688
113943
  });
113689
113944
  return;
113690
113945
  }
113691
- const visitorSelection = readVisitorSelection(formData, render.hydration);
113692
- if (visitorSelection === null) {
113946
+ const selection = readVisitorSelection(formData, render.hydration);
113947
+ const selectionError = visitorSelectionError(selection);
113948
+ if (selectionError) {
113693
113949
  dispatchSubmission({
113694
113950
  type: "failed",
113695
- error: newsletterFieldError(TOPIC_CHOICE_FIELD_ID, "Choose at least one email topic.")
113951
+ error: selectionError
113696
113952
  });
113697
113953
  return;
113698
113954
  }
113955
+ const visitorSelection = selection.tag === "chosen" ? selection.value : void 0;
113699
113956
  dispatchSubmission({ type: "submitted" });
113700
113957
  try {
113701
113958
  const result = await api.subscribeNewsletter({
@@ -113889,10 +114146,18 @@ function transportFailureMessage(err) {
113889
114146
  }
113890
114147
  return RETRY_SHORTLY_MESSAGE;
113891
114148
  }
114149
+ function visitorSelectionError(selection) {
114150
+ switch (selection.tag) {
114151
+ case "nothing_chosen": return newsletterFieldError(TOPIC_CHOICE_FIELD_ID, "Choose at least one email topic.");
114152
+ case "unusable": return newsletterFormError(SIGNUPS_PAUSED_MESSAGE);
114153
+ case "not_offered":
114154
+ case "chosen": return null;
114155
+ }
114156
+ }
113892
114157
  function readVisitorSelection(formData, hydration) {
113893
- if (hydration.choicePresentation !== "visitor_choice") return void 0;
114158
+ if (hydration.choicePresentation !== "visitor_choice") return { tag: "not_offered" };
113894
114159
  const ids = formData.getAll(TOPIC_CHOICE_FIELD_ID).flatMap((value) => typeof value === "string" ? [value] : []);
113895
- if (ids.length === 0) return null;
114160
+ if (ids.length === 0) return { tag: "nothing_chosen" };
113896
114161
  const raw = hydration.choiceProvider === "native" ? {
113897
114162
  provider: "native",
113898
114163
  topicIds: ids
@@ -113903,9 +114168,12 @@ function readVisitorSelection(formData, hydration) {
113903
114168
  provider: "mailchimp",
113904
114169
  interestIds: ids
113905
114170
  } : null;
113906
- if (raw === null) return null;
114171
+ if (raw === null) return { tag: "unusable" };
113907
114172
  const parsed = parseMailingListVisitorSelection(raw);
113908
- return parsed.ok ? parsed.value : null;
114173
+ return parsed.ok ? {
114174
+ tag: "chosen",
114175
+ value: parsed.value
114176
+ } : { tag: "unusable" };
113909
114177
  }
113910
114178
  function publicSignupError(outcome) {
113911
114179
  switch (outcome.tag) {
@@ -116199,6 +116467,27 @@ const headerRuntimeTransforms = [{
116199
116467
  init_events$2();
116200
116468
  init_core$1();
116201
116469
  init_calendarWindow();
116470
+ init_eventSelection();
116471
+ const eventCalendarSelectionParam = {
116472
+ id: "events.calendarSelectionParam",
116473
+ kind: "formatter",
116474
+ summary: "Resolve selected events instead of discovery filters",
116475
+ schema: z$1.object({ key: z$1.enum([
116476
+ "seriesIds",
116477
+ "eventSurface",
116478
+ "filterEventPresets",
116479
+ "scheduleScope",
116480
+ "filterCategoryIds",
116481
+ "filterStaffMemberId",
116482
+ "filterVenueId"
116483
+ ]) }),
116484
+ run(value, { key }) {
116485
+ const content = asPartialObject(value) ?? {};
116486
+ const selection = resolveEventSelection(content.eventSelection, content.selectedEventSeriesIds);
116487
+ if (selection.kind === "selected") return key === "seriesIds" ? selection.seriesIds : void 0;
116488
+ return key === "seriesIds" ? void 0 : content[key];
116489
+ }
116490
+ };
116202
116491
  const readJobSchema = z$1.object({ job: z$1.enum(["list", "calendar"]) });
116203
116492
  const eventCalendarReadProfile = {
116204
116493
  id: "events.calendarReadProfile",
@@ -116224,6 +116513,7 @@ init_core$1();
116224
116513
  init_boxStyles$1();
116225
116514
  init_boxStyleClassNames();
116226
116515
  const defaultTransforms = createTransformRegistry([
116516
+ eventCalendarSelectionParam,
116227
116517
  eventCalendarReadEnabled,
116228
116518
  eventCalendarReadProfile,
116229
116519
  ...formattingTransforms,
@@ -117290,17 +117580,16 @@ const ButtonNode = ({ value, children, href, variantId = "primary", size = "md",
117290
117580
  console.warn("[ButtonNode] Missing href for link-required button");
117291
117581
  return null;
117292
117582
  }
117293
- const extraClassName = affordanceIcon ? [className, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ") : className;
117294
117583
  const resolvedVariantId = parseThemeButtonVariantId(variantId);
117295
117584
  if (variantId && !resolvedVariantId) {
117296
117585
  console.error("[ButtonNode] Invalid button variant", { variantId });
117297
117586
  return null;
117298
117587
  }
117299
- const combinedClassName = resolvedVariantId ? themeButtonClassName({
117588
+ const combinedClassName = resolvedVariantId ? (affordanceIcon ? themeButtonClassNameWithTrailingIcon : themeButtonClassName)({
117300
117589
  variant: resolvedVariantId,
117301
117590
  size,
117302
- extraClassName
117303
- }) : extraClassName;
117591
+ extraClassName: className
117592
+ }) : className;
117304
117593
  if (resolvedHref) return /* @__PURE__ */ jsxs("a", {
117305
117594
  href: resolvedHref,
117306
117595
  target,
@@ -118425,6 +118714,7 @@ const publicPricingSchema = z$1.object({
118425
118714
  });
118426
118715
  const publicAppointmentServiceSchema = z$1.object({
118427
118716
  id: z$1.string().min(1),
118717
+ slug: z$1.string().min(1).optional(),
118428
118718
  title: z$1.string(),
118429
118719
  description: z$1.string().nullable().optional(),
118430
118720
  durationMinutes: z$1.number().int().positive(),
@@ -118501,7 +118791,7 @@ function formatAmountOrFree(amount, currency) {
118501
118791
  currency
118502
118792
  }, { decimals: "auto" });
118503
118793
  }
118504
- function buildRows(services, pathname) {
118794
+ function buildRows(services, pathname, servicePathPrefix) {
118505
118795
  return services.map((service) => ({
118506
118796
  id: service.id,
118507
118797
  title: service.title,
@@ -118512,7 +118802,8 @@ function buildRows(services, pathname) {
118512
118802
  href: resolveDedicatedBookingHref(pathname, {
118513
118803
  kind: "appointment_service",
118514
118804
  serviceId: service.id
118515
- })
118805
+ }),
118806
+ detailsHref: servicePathPrefix && service.slug ? `${servicePathPrefix.replace(/\/$/, "")}/${encodeURIComponent(service.slug)}` : null
118516
118807
  }));
118517
118808
  }
118518
118809
  function buildAppointmentServicesView(input) {
@@ -118531,13 +118822,14 @@ function buildAppointmentServicesView(input) {
118531
118822
  };
118532
118823
  return {
118533
118824
  kind: "items",
118534
- rows: buildRows(parsed.services, input.pathname)
118825
+ rows: buildRows(parsed.services, input.pathname, input.servicePathPrefix ?? null)
118535
118826
  };
118536
118827
  }
118537
- function AppointmentServicesNode({ sectionHeading, services, pathname, className }) {
118828
+ function AppointmentServicesNode({ sectionHeading, services, pathname, servicePathPrefix, className }) {
118538
118829
  const view = buildAppointmentServicesView({
118539
118830
  services,
118540
- pathname: typeof pathname === "string" ? pathname : void 0
118831
+ pathname: typeof pathname === "string" ? pathname : void 0,
118832
+ servicePathPrefix: typeof servicePathPrefix === "string" ? servicePathPrefix : null
118541
118833
  });
118542
118834
  const rootClassName = `appointment-services ${className ?? ""}`.trim();
118543
118835
  const RowTitle = sectionHeading ? "h3" : "h2";
@@ -118568,7 +118860,10 @@ function AppointmentServicesNode({ sectionHeading, services, pathname, className
118568
118860
  children: [
118569
118861
  /* @__PURE__ */ jsx(RowTitle, {
118570
118862
  className: "appointment-services-row-title rb-text-lg rb-font-medium rb-leading-tight",
118571
- children: row.title
118863
+ children: row.detailsHref ? /* @__PURE__ */ jsx("a", {
118864
+ href: row.detailsHref,
118865
+ children: row.title
118866
+ }) : row.title
118572
118867
  }),
118573
118868
  row.description ? /* @__PURE__ */ jsx("p", {
118574
118869
  className: "appointment-services-row-description rb-text-sm rb-leading-6 status-muted",
@@ -119301,7 +119596,6 @@ function OfferingsCatalogue(props) {
119301
119596
  //#endregion
119302
119597
  //#region ../blocks/src/system/runtime/nodes/offerings-preview-content.tsx
119303
119598
  init_buttons();
119304
- init_svg();
119305
119599
  init_shared$2();
119306
119600
  function OfferingsPreviewContent(props) {
119307
119601
  const groupLinkClass = themeButtonClassName({
@@ -119348,13 +119642,10 @@ function OfferingsPreviewContent(props) {
119348
119642
  }),
119349
119643
  groupCta ? /* @__PURE__ */ jsx("footer", {
119350
119644
  className: "offerings-preview-card-footer rb-mt-auto rb-flex",
119351
- children: /* @__PURE__ */ jsxs("a", {
119645
+ children: /* @__PURE__ */ jsx("a", {
119352
119646
  className: groupLinkClass,
119353
119647
  href: groupCta.href,
119354
- children: [/* @__PURE__ */ jsx("span", { children: groupCta.label }), /* @__PURE__ */ jsx(ArrowRightIcon, {
119355
- "aria-hidden": "true",
119356
- className: "offerings-preview-link-icon rb-h-4 rb-w-4"
119357
- })]
119648
+ children: /* @__PURE__ */ jsx("span", { children: groupCta.label })
119358
119649
  })
119359
119650
  }) : null
119360
119651
  ]
@@ -120771,23 +121062,123 @@ const formBlockDefinition = {
120771
121062
  runtime: formBlockRuntime
120772
121063
  };
120773
121064
  //#endregion
121065
+ //#region ../blocks/src/system/blocks/events/eventSelectionFields.ts
121066
+ init_schema();
121067
+ const eventSelectionFields = [{
121068
+ id: "eventSelection",
121069
+ type: "select",
121070
+ label: "Events to show",
121071
+ required: false,
121072
+ multiple: false,
121073
+ defaultValue: "matching",
121074
+ options: [{
121075
+ value: "matching",
121076
+ label: "All matching events"
121077
+ }, {
121078
+ value: "selected",
121079
+ label: "Selected events"
121080
+ }],
121081
+ ui: { intent: "behavior" }
121082
+ }, createSiteOptionSelectField({
121083
+ id: "selectedEventSeriesIds",
121084
+ label: "Selected events",
121085
+ description: "Show upcoming dates for these events. Other event filters do not apply.",
121086
+ required: false,
121087
+ multiple: true,
121088
+ defaultValue: [],
121089
+ optionSource: "eventSeries",
121090
+ ui: {
121091
+ intent: "behavior",
121092
+ searchThreshold: 1,
121093
+ visibleWhen: {
121094
+ field: "eventSelection",
121095
+ equals: "selected"
121096
+ }
121097
+ }
121098
+ })];
121099
+ function withEventSelectionVisibility(field) {
121100
+ if (![
121101
+ "eventSurface",
121102
+ "filterEventPresets",
121103
+ "scheduleScope",
121104
+ "filterCategoryIds",
121105
+ "filterStaffMemberId",
121106
+ "filterVenueId",
121107
+ "showFilters",
121108
+ "showCategoryFilter",
121109
+ "showVenueFilter",
121110
+ "showStaffFilter"
121111
+ ].includes(field.id)) return field;
121112
+ const visibleWhen = field.ui?.visibleWhen;
121113
+ return {
121114
+ ...field,
121115
+ ui: {
121116
+ ...field.ui,
121117
+ visibleWhen: { allOf: [{
121118
+ field: "eventSelection",
121119
+ notEquals: "selected"
121120
+ }, ...visibleWhen ? [visibleWhen] : []] }
121121
+ }
121122
+ };
121123
+ }
121124
+ //#endregion
120774
121125
  //#region ../blocks/src/system/blocks/events/eventCalendarDataLoaders.ts
120775
121126
  init_calendarWindow();
120776
121127
  const scopeParams = {
120777
121128
  siteId: { $bind: { from: "$root.siteId" } },
121129
+ seriesIds: { $bind: {
121130
+ from: "content",
121131
+ transforms: [{
121132
+ id: "events.calendarSelectionParam",
121133
+ options: { key: "seriesIds" }
121134
+ }]
121135
+ } },
120778
121136
  stage: { $bind: {
120779
121137
  from: "$root.previewStage",
120780
121138
  fallback: "published"
120781
121139
  } },
120782
- eventSurface: { $bind: { from: "content.eventSurface" } },
121140
+ eventSurface: { $bind: {
121141
+ from: "content",
121142
+ transforms: [{
121143
+ id: "events.calendarSelectionParam",
121144
+ options: { key: "eventSurface" }
121145
+ }, { id: "value.csv" }]
121146
+ } },
120783
121147
  eventPresets: { $bind: {
120784
- from: "content.filterEventPresets",
120785
- transforms: [{ id: "value.csv" }]
121148
+ from: "content",
121149
+ transforms: [{
121150
+ id: "events.calendarSelectionParam",
121151
+ options: { key: "filterEventPresets" }
121152
+ }, { id: "value.csv" }]
121153
+ } },
121154
+ scheduleScope: { $bind: {
121155
+ from: "content",
121156
+ transforms: [{
121157
+ id: "events.calendarSelectionParam",
121158
+ options: { key: "scheduleScope" }
121159
+ }, { id: "value.csv" }]
121160
+ } },
121161
+ categoryIds: { $bind: {
121162
+ from: "content",
121163
+ transforms: [{
121164
+ id: "events.calendarSelectionParam",
121165
+ options: { key: "filterCategoryIds" }
121166
+ }, { id: "value.csv" }]
120786
121167
  } },
120787
- scheduleScope: { $bind: { from: "content.scheduleScope" } },
120788
- categoryIds: { $bind: { from: "content.filterCategoryIds" } },
120789
- staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
120790
- venueId: { $bind: { from: "content.filterVenueId" } }
121168
+ staffMemberId: { $bind: {
121169
+ from: "content",
121170
+ transforms: [{
121171
+ id: "events.calendarSelectionParam",
121172
+ options: { key: "filterStaffMemberId" }
121173
+ }, { id: "value.csv" }]
121174
+ } },
121175
+ venueId: { $bind: {
121176
+ from: "content",
121177
+ transforms: [{
121178
+ id: "events.calendarSelectionParam",
121179
+ options: { key: "filterVenueId" }
121180
+ }, { id: "value.csv" }]
121181
+ } }
120791
121182
  };
120792
121183
  /** Combined renders two jobs; calendar-only variants never pay for the list seed. */
120793
121184
  const eventCalendarDataLoaders = {
@@ -120928,6 +121319,13 @@ const eventCalendarLayout = [styledSection({
120928
121319
  from: "content.defaultCalendarView",
120929
121320
  fallback: "month"
120930
121321
  } },
121322
+ seriesIds: { $bind: {
121323
+ from: "content",
121324
+ transforms: [{
121325
+ id: "events.calendarSelectionParam",
121326
+ options: { key: "seriesIds" }
121327
+ }]
121328
+ } },
120931
121329
  showFilters: { $bind: {
120932
121330
  from: "content.showFilters",
120933
121331
  fallback: true
@@ -120949,17 +121347,47 @@ const eventCalendarLayout = [styledSection({
120949
121347
  fallback: true
120950
121348
  } },
120951
121349
  eventSurface: { $bind: {
120952
- from: "content.eventSurface",
120953
- fallback: "all"
121350
+ from: "content",
121351
+ transforms: [{
121352
+ id: "events.calendarSelectionParam",
121353
+ options: { key: "eventSurface" }
121354
+ }]
121355
+ } },
121356
+ filterEventPresets: { $bind: {
121357
+ from: "content",
121358
+ transforms: [{
121359
+ id: "events.calendarSelectionParam",
121360
+ options: { key: "filterEventPresets" }
121361
+ }]
120954
121362
  } },
120955
- filterEventPresets: { $bind: { from: "content.filterEventPresets" } },
120956
121363
  scheduleScope: { $bind: {
120957
- from: "content.scheduleScope",
120958
- fallback: "any"
121364
+ from: "content",
121365
+ transforms: [{
121366
+ id: "events.calendarSelectionParam",
121367
+ options: { key: "scheduleScope" }
121368
+ }]
121369
+ } },
121370
+ filterCategoryIds: { $bind: {
121371
+ from: "content",
121372
+ transforms: [{
121373
+ id: "events.calendarSelectionParam",
121374
+ options: { key: "filterCategoryIds" }
121375
+ }]
121376
+ } },
121377
+ filterStaffMemberId: { $bind: {
121378
+ from: "content",
121379
+ transforms: [{
121380
+ id: "events.calendarSelectionParam",
121381
+ options: { key: "filterStaffMemberId" }
121382
+ }]
121383
+ } },
121384
+ filterVenueId: { $bind: {
121385
+ from: "content",
121386
+ transforms: [{
121387
+ id: "events.calendarSelectionParam",
121388
+ options: { key: "filterVenueId" }
121389
+ }]
120959
121390
  } },
120960
- filterCategoryIds: { $bind: { from: "content.filterCategoryIds" } },
120961
- filterStaffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
120962
- filterVenueId: { $bind: { from: "content.filterVenueId" } },
120963
121391
  cardRole: { $bind: {
120964
121392
  from: "content._cardStyles.role",
120965
121393
  fallback: "default"
@@ -121463,6 +121891,7 @@ const eventCalendarAdditionalFields = [
121463
121891
  }
121464
121892
  }
121465
121893
  },
121894
+ ...eventSelectionFields,
121466
121895
  {
121467
121896
  id: "eventSurface",
121468
121897
  type: "select",
@@ -121672,7 +122101,7 @@ const eventCalendarBlockDefinition = {
121672
122101
  titleSource: "heading",
121673
122102
  description: "Display events with calendar, list, or combined views with filtering",
121674
122103
  skipSectionStyles: true,
121675
- additionalFields: eventCalendarAdditionalFields,
122104
+ additionalFields: eventCalendarAdditionalFields.map(withEventSelectionVisibility),
121676
122105
  styleTokens: {
121677
122106
  background: "surface",
121678
122107
  typography: "body",
@@ -125801,9 +126230,56 @@ function generateNavLinkCSS(options) {
125801
126230
  if (baseRules.length > 0) cssChunks.unshift(`\n${selector} {\n ${baseRules.join("\n ")}\n}\n`);
125802
126231
  if (hoverRules.length > 0) cssChunks.push(`\n${hoverSelector} {\n ${hoverRules.join("\n ")}\n}\n`);
125803
126232
  if (activeRules.length > 0) cssChunks.push(`\n${activeSelector} {\n ${activeRules.join("\n ")}\n}\n`);
126233
+ cssChunks.push(navLinkFocusVisibleCss(selector, style, theme, tokens));
125804
126234
  cssChunks.push(generateInteractiveChildInheritanceCSS(selector));
125805
126235
  return cssChunks.join("");
125806
126236
  }
126237
+ /**
126238
+ * Keyboard focus indicator for nav links, in the header, the footer and header
126239
+ * dropdown menus — the three surfaces `generateNavLinkCSS` serves.
126240
+ *
126241
+ * Emitted unconditionally rather than as an effect, because focus visibility is
126242
+ * a floor rather than a style choice. Only the interaction-palette pill ever
126243
+ * wrote an `effects.focus` group, so every other nav — every `quiet` palette,
126244
+ * every footer, every dropdown — previously fell back to whatever outline the
126245
+ * browser drew.
126246
+ *
126247
+ * The outline takes the link's own resolved colour, so on a header that adapts
126248
+ * to the section it floats over it moves with the adaptation instead of
126249
+ * asserting a brand colour against an unknown backdrop.
126250
+ *
126251
+ * Where the style asks for `soft-glow`, the same halo goes on the outline. That
126252
+ * treatment exists because the theme has already conceded the resolved colour
126253
+ * alone is not reliable over an unpredictable backdrop — a hero photograph with
126254
+ * mixed luminance. Without it the text would stay legible by its halo while the
126255
+ * focus ring, which is the part with a contrast requirement of its own, would
126256
+ * not.
126257
+ *
126258
+ * A style that also paints a focus pill keeps it: this adds an outline around
126259
+ * that pill rather than replacing it.
126260
+ */
126261
+ function navLinkFocusVisibleCss(selector, style, theme, tokens) {
126262
+ const color = tokens.getColor(style.colorToken);
126263
+ const halo = buildTextContrastShadow({
126264
+ theme,
126265
+ colorToken: style.colorToken,
126266
+ treatment: style.contrastTreatment
126267
+ });
126268
+ return `
126269
+ ${selector}:focus-visible {
126270
+ outline: 2px solid ${color};
126271
+ outline-offset: ${focusOutlineOffset(selector)};${halo ? `\n box-shadow: ${halo};` : ""}
126272
+ }
126273
+ `;
126274
+ }
126275
+ /**
126276
+ * Dropdown items are full-width inside a panel with no horizontal padding, so
126277
+ * an outset outline would paint over and past the panel's own border. Keeping
126278
+ * it flush is the only way it reads as belonging to the item.
126279
+ */
126280
+ function focusOutlineOffset(selector) {
126281
+ return selector.includes("nav-dropdown-link") ? "-2px" : "3px";
126282
+ }
125807
126283
  function buildTextContrastShadow(input) {
125808
126284
  if (input.treatment !== "soft-glow") return null;
125809
126285
  return isLikelyLightColorToken(input.theme, input.colorToken) ? "0 1px 3px rgb(0 0 0 / 0.55), 0 0 18px rgb(0 0 0 / 0.38)" : "0 1px 3px rgb(255 255 255 / 0.72), 0 0 18px rgb(255 255 255 / 0.5)";
@@ -128956,7 +129432,7 @@ function pageBlockPosition(index, blockCount) {
128956
129432
  //#endregion
128957
129433
  //#region ../blocks/src/pageRendererContracts.ts
128958
129434
  function buildPageRendererRootRuntime(dataContext) {
128959
- const { siteId = null, pageId = null, pathname = null, bookingTimeZone, previewStage = "published", apiBaseUrl = null, portalToken = null, bookingOfferingPresets = [], mailingList = { tag: "not_configured" }, eventRegistrationOverlayEnabled = false, loaderFailures = {} } = dataContext ?? {};
129435
+ const { siteId = null, pageId = null, pathname = null, bookingTimeZone, previewStage = "published", apiBaseUrl = null, portalToken = null, bookingOfferingPresets = [], appointmentServicePathPrefix = null, mailingList = { tag: "not_configured" }, eventRegistrationOverlayEnabled = false, loaderFailures = {} } = dataContext ?? {};
128960
129436
  return {
128961
129437
  siteId,
128962
129438
  pageId,
@@ -128966,6 +129442,7 @@ function buildPageRendererRootRuntime(dataContext) {
128966
129442
  apiBaseUrl,
128967
129443
  portalToken,
128968
129444
  bookingOfferingPresets,
129445
+ appointmentServicePathPrefix,
128969
129446
  mailingList,
128970
129447
  eventRegistrationOverlayEnabled,
128971
129448
  loaderFailures
@@ -133841,7 +134318,8 @@ const appointmentServicesBlockDefinition = {
133841
134318
  el("appointment-services", {
133842
134319
  sectionHeading: { $bind: { from: "content.heading" } },
133843
134320
  services: { $bind: { from: "data.services" } },
133844
- pathname: { $bind: { from: "$root.pathname" } }
134321
+ pathname: { $bind: { from: "$root.pathname" } },
134322
+ servicePathPrefix: { $bind: { from: "$root.appointmentServicePathPrefix" } }
133845
134323
  })
133846
134324
  ], { gap: "lg" })
133847
134325
  })]
@@ -140403,10 +140881,19 @@ const containerResponsiveThemeCss = `/*
140403
140881
  padding-top: 2.5rem;
140404
140882
  padding-bottom: 2.5rem;
140405
140883
  }
140884
+ /* Clearance for a surface that is not an authored block page.
140885
+ An authored page gets this through its opening block's container (see the
140886
+ overlay-clearance rule in styles.css). A reserved surface or a system
140887
+ destination page has no such block, so it consumes the same variable here.
140888
+ Marked with one class rather than per-surface selectors, because the last
140889
+ two additions to this family were both missed and shipped overlapping. */
140406
140890
  :where(.theme-scope)
140407
140891
  [data-site-document-layout-mode="header-overlay"]
140408
- [data-rb-reserved-surface].rb-reserved-surface-main {
140409
- padding-top: calc(var(--rb-reserved-surface-header-offset, 5.5rem) + 2.5rem);
140892
+ .rb-overlay-clearance-surface {
140893
+ padding-top: calc(
140894
+ var(--site-overlay-header-clearance, 5.5rem) +
140895
+ var(--site-overlay-opening-content-extra-pad, clamp(1rem, 2vw, 1.75rem))
140896
+ );
140410
140897
  }
140411
140898
  .rb-preview-editor-offset {
140412
140899
  padding-bottom: calc(
@@ -150763,6 +151250,23 @@ const containerResponsiveThemeCss = `/*
150763
151250
  gap: 0.5rem;
150764
151251
  }
150765
151252
 
151253
+ /* Error panel and field notes. The form block scopes these to its own
151254
+ data-block, so the newsletter form (which also renders in the footer)
151255
+ needs its own copy of the treatment. */
151256
+ :where(.theme-scope) .newsletter-form .fb-error:not([data-field-validation-message]) {
151257
+ background-color: var(--fb-error-bg);
151258
+ color: var(--fb-error-text);
151259
+ border: 1px solid var(--fb-error-border);
151260
+ border-radius: var(--rb-block-radius);
151261
+ padding: 1rem;
151262
+ font-size: 0.875rem;
151263
+ }
151264
+
151265
+ :where(.theme-scope) .newsletter-form [data-field-validation-message] {
151266
+ font-size: 0.875rem;
151267
+ color: var(--fb-error-text);
151268
+ }
151269
+
150766
151270
  /* Required indicator */
150767
151271
  :where(.theme-scope) .newsletter-required {
150768
151272
  color: rgb(var(--tb-primary));
@@ -153032,44 +153536,10 @@ function ThemeScope$1({ theme, children, themeId = "theme-default", responsiveMo
153032
153536
  //#endregion
153033
153537
  //#region ../blocks/src/system/blocks/site-footer-runtime.ts
153034
153538
  init_src$2();
153035
- /**
153036
- * Resolve what to render for the footer given the current mode and whether the
153037
- * site is SDK-managed.
153038
- *
153039
- * Backwards compatible: missing/undefined mode is treated as 'default'.
153040
- */
153041
- function resolveFooterRenderPlan(params) {
153042
- if (!params.isSdkSite) return {
153043
- mode: "default",
153044
- renderDefaultFooter: true,
153045
- renderFooterBlocks: false
153046
- };
153047
- switch (params.mode ?? "default") {
153048
- case "blocks": return {
153049
- mode: "blocks",
153050
- renderDefaultFooter: false,
153051
- renderFooterBlocks: true
153052
- };
153053
- case "default+blocks": return {
153054
- mode: "default+blocks",
153055
- renderDefaultFooter: true,
153056
- renderFooterBlocks: true
153057
- };
153058
- case "none": return {
153059
- mode: "none",
153060
- renderDefaultFooter: false,
153061
- renderFooterBlocks: false
153062
- };
153063
- default: return {
153064
- mode: "default",
153065
- renderDefaultFooter: true,
153066
- renderFooterBlocks: false
153067
- };
153068
- }
153069
- }
153070
153539
  //#endregion
153071
153540
  //#region ../blocks/src/rendering/server.ts
153072
153541
  init_schema();
153542
+ init_mode();
153073
153543
  //#endregion
153074
153544
  //#region ../theme-core/src/ResponsiveScope.tsx
153075
153545
  /**
@@ -153163,9 +153633,20 @@ z$1.object({
153163
153633
  }).passthrough();
153164
153634
  //#endregion
153165
153635
  //#region ../theme-core/src/hosted-booking-appearance.ts
153636
+ init_schema$2();
153166
153637
  init_colors();
153167
153638
  init_expandPalette();
153168
153639
  init_tokens();
153640
+ init_modern_minimal();
153641
+ z$1.object({
153642
+ palette: paletteColorsSchema,
153643
+ paletteMode: paletteModeSchema,
153644
+ typography: z$1.object({
153645
+ headingFamily: z$1.string().trim().min(1),
153646
+ bodyFamily: z$1.string().trim().min(1)
153647
+ }).strict(),
153648
+ corners
153649
+ }).strict();
153169
153650
  //#endregion
153170
153651
  //#region ../theme-core/src/palette/utils/colorPlacement.ts
153171
153652
  init_colorConversion();
@@ -155185,12 +155666,12 @@ function normalizeContent(block) {
155185
155666
  }
155186
155667
  /**
155187
155668
  * Normalize params for API calls.
155188
- * Converts all values to strings.
155669
+ * Converts supplied values to strings, preserving absent versus explicitly empty params.
155189
155670
  */
155190
155671
  function normalizeParams(input) {
155191
155672
  if (!input || typeof input !== "object") return {};
155192
155673
  const output = {};
155193
- for (const [key, value] of Object.entries(input)) output[key] = coerceToString(value);
155674
+ for (const [key, value] of Object.entries(input)) if (value !== void 0 && value !== null) output[key] = coerceToString(value);
155194
155675
  return output;
155195
155676
  }
155196
155677
  function isNonArrayObject(value) {
@@ -155254,6 +155735,14 @@ function coercePayload(payload) {
155254
155735
  * - Frontend: provide internal API client
155255
155736
  * - SDK: provide SDK client with endpoint mapping
155256
155737
  */
155738
+ function projectDataLoaders(loaders, shouldLoad, blockId, blockKind) {
155739
+ if (!shouldLoad) return [...loaders];
155740
+ return loaders.filter(({ key }) => shouldLoad({
155741
+ blockId,
155742
+ blockKind,
155743
+ loaderKey: key
155744
+ }));
155745
+ }
155257
155746
  function shouldSkipResolvedLoader(input) {
155258
155747
  if (input.loader.requiredParams?.some((param) => !input.params[param]?.trim())) return true;
155259
155748
  return Boolean(input.isValidEndpoint && !input.isValidEndpoint(input.endpoint));
@@ -155282,7 +155771,7 @@ async function prefetchBlockData$1(page, context, options) {
155282
155771
  return (await prefetchBlockDataWithFailures(page, context, options)).resolvedData;
155283
155772
  }
155284
155773
  async function prefetchBlockDataWithFailures(page, context, options) {
155285
- const { apiClient, isValidEndpoint, onError, getCustomBlockLoaders, getBlockDefinition: getBlockDefinition$1 = getBlockDefinition, resolveParamsBindings: resolveParamsBindings$1 = resolveParamsBindings } = options;
155774
+ const { apiClient, isValidEndpoint, onError, getCustomBlockLoaders, getBlockDefinition: getBlockDefinition$1 = getBlockDefinition, resolveParamsBindings: resolveParamsBindings$1 = resolveParamsBindings, shouldLoad } = options;
155286
155775
  const results = {};
155287
155776
  const loaderFailures = {};
155288
155777
  const tasks = [];
@@ -155299,6 +155788,7 @@ async function prefetchBlockDataWithFailures(page, context, options) {
155299
155788
  loader
155300
155789
  })) : [];
155301
155790
  } else loaders = [];
155791
+ loaders = projectDataLoaders(loaders, shouldLoad, blockId, block.kind);
155302
155792
  if (loaders.length === 0) continue;
155303
155793
  const root = {
155304
155794
  ...context.root ?? {},
@@ -155400,8 +155890,8 @@ function toStringParams(value) {
155400
155890
  for (const [k, v] of Object.entries(value)) if (typeof v === "string") out[k] = v;
155401
155891
  return out;
155402
155892
  }
155403
- function stripEmptyStringValues(params) {
155404
- for (const [key, value] of Object.entries(params)) if (value === "") delete params[key];
155893
+ function stripEmptyStringValues(params, endpoint) {
155894
+ for (const [key, value] of Object.entries(params)) if (value === "" && !(key === "seriesIds" && (endpoint === "listPublicEvents" || endpoint === "listPublicEventCalendarWindow"))) delete params[key];
155405
155895
  }
155406
155896
  function ensureSiteId(params, context) {
155407
155897
  if (!params.siteId && typeof context.siteId === "string" && context.siteId) params.siteId = context.siteId;
@@ -155414,7 +155904,7 @@ function ensureSiteId(params, context) {
155414
155904
  */
155415
155905
  function normalizeLoaderParams(endpoint, params, context) {
155416
155906
  const out = toStringParams(params);
155417
- stripEmptyStringValues(out);
155907
+ stripEmptyStringValues(out, endpoint);
155418
155908
  if (endpoint === "getPublicFormById") {
155419
155909
  ensureSiteId(out, context);
155420
155910
  if (!out.formId && out.formSlug) {
@@ -155543,6 +156033,7 @@ init_buttons();
155543
156033
  init_cards();
155544
156034
  init_tokens();
155545
156035
  init_gradients();
156036
+ init_mode();
155546
156037
  init_richTextSchema();
155547
156038
  init_media();
155548
156039
  init_media$1();
@@ -155718,11 +156209,7 @@ function buildFooterRenderablePageOutline(siteData, blocks) {
155718
156209
  }
155719
156210
  //#endregion
155720
156211
  //#region src/rendering/components/Layout.tsx
155721
- /**
155722
- * Layout component with header and footer
155723
- *
155724
- * Renders site header and footer around content. Fetches site data if not provided.
155725
- */
156212
+ init_mode();
155726
156213
  function isOverrideOnlyLayout(props) {
155727
156214
  return props.rendering?.kind === "overrides-only";
155728
156215
  }
@@ -155897,7 +156384,7 @@ async function Layout(props) {
155897
156384
  if (footer === true) {
155898
156385
  const footerPlan = resolveFooterRenderPlan({
155899
156386
  isSdkSite: Boolean(site.is_sdk_site),
155900
- mode: theme.footer?.mode
156387
+ mode: resolveSdkFooterMode(siteData.sdkConfig)
155901
156388
  });
155902
156389
  const footerBlocksElement = footerPlan.renderFooterBlocks && footerBlocks.length > 0 ? /* @__PURE__ */ jsx(PageRenderer, {
155903
156390
  theme,
@@ -158285,6 +158772,7 @@ function internalNavigationLinkToLocalLink(item) {
158285
158772
  }
158286
158773
  //#endregion
158287
158774
  //#region ../api/src/sdkConfig/contracts.ts
158775
+ init_mode();
158288
158776
  init_src$2();
158289
158777
  /**
158290
158778
  * Canonical SDK config Zod contracts.
@@ -158457,11 +158945,14 @@ const sdkSiteStyleConfigSchema = z$1.object({
158457
158945
  sectionOptions: sdkSectionOptionsConfigSchema.optional(),
158458
158946
  containerOptions: sdkContainerOptionsConfigSchema.optional()
158459
158947
  });
158460
- const sdkSiteLayoutConfigSchema = z$1.object({ footerBlocks: z$1.array(z$1.object({
158461
- id: z$1.string().min(1).optional(),
158462
- kind: z$1.string().min(1),
158463
- content: z$1.record(z$1.string(), z$1.unknown()).optional()
158464
- })).optional() });
158948
+ const sdkSiteLayoutConfigSchema = z$1.object({
158949
+ footerMode: footerModeSchema.optional(),
158950
+ footerBlocks: z$1.array(z$1.object({
158951
+ id: z$1.string().min(1).optional(),
158952
+ kind: z$1.string().min(1),
158953
+ content: z$1.record(z$1.string(), z$1.unknown()).optional()
158954
+ })).optional()
158955
+ });
158465
158956
  const sdkFieldSelectOptionSchema = z$1.object({
158466
158957
  value: z$1.string(),
158467
158958
  label: z$1.string()