@riverbankcms/sdk 0.140.0 → 0.141.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 (112) hide show
  1. package/dist/{PreviewEditorSidebar-CUyTzd5z.mjs → PreviewEditorSidebar-Q-fy9GYw.mjs} +3 -3
  2. package/dist/{PreviewEditorUI-Agkw4v5i.mjs → PreviewEditorUI-LYGzgk85.mjs} +2 -2
  3. package/dist/{SdkPreviewModeRuntime-DdbeAdS8.mjs → SdkPreviewModeRuntime-CoPYI5Jq.mjs} +72 -46
  4. package/dist/{SiteChromeCustomizeContext-CqGOz-Kv.mjs → SiteChromeCustomizeContext-D8LePX8x.mjs} +681 -196
  5. package/dist/_dts/api/src/contentRuntime.d.ts +12 -31
  6. package/dist/_dts/api/src/domainConnection.d.ts +4 -0
  7. package/dist/_dts/api/src/footerCompositionContracts.d.ts +25 -0
  8. package/dist/_dts/api/src/index.d.ts +1 -1
  9. package/dist/_dts/api/src/launchReadiness.d.ts +1 -0
  10. package/dist/_dts/api/src/navigation/dashboardSiteNav.d.ts +2 -1
  11. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +3 -26
  12. package/dist/_dts/api/src/siteOnboarding.d.ts +7 -0
  13. package/dist/_dts/billing/src/site-arrangements.d.ts +12 -3
  14. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +4 -0
  15. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +2 -0
  16. package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +2 -0
  17. package/dist/_dts/blocks/src/system/blocks/events/eventSelectionFields.d.ts +122 -0
  18. package/dist/_dts/blocks/src/system/blocks/events/shared/calendarWindow.d.ts +2 -1
  19. package/dist/_dts/blocks/src/system/blocks/events/shared/eventSelection.d.ts +11 -0
  20. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +2 -2
  21. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +47 -47
  22. package/dist/_dts/blocks/src/system/data/prefetchBlockData.d.ts +5 -0
  23. package/dist/_dts/blocks/src/system/data/utils.d.ts +1 -1
  24. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +27 -1
  25. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +12 -180
  26. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +6 -90
  27. package/dist/_dts/blocks/src/system/runtime/hooks/useEventFilters.d.ts +2 -1
  28. package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +5 -1
  29. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +4 -0
  30. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.state.d.ts +5 -0
  31. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useDiscountCodeUi.d.ts +3 -0
  32. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useDiscountCodeUi.state.d.ts +10 -3
  33. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventCheckoutHandoffRestore.d.ts +9 -0
  34. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +4 -5
  35. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useSettledCommerceView.d.ts +37 -0
  36. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +4 -3
  37. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +3 -0
  38. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +11 -101
  39. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +7 -2
  40. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/listOptions.d.ts +2 -0
  41. package/dist/_dts/blocks/src/system/transforms/registry/eventCalendar.d.ts +12 -0
  42. package/dist/_dts/commerce/src/purchase/bookingInstalmentSchedule.d.ts +4 -0
  43. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +3 -0
  44. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/loaders.d.ts +27 -1
  45. package/dist/_dts/sdk/src/public-api/contracts.d.ts +1 -1
  46. package/dist/_dts/sdk/src/version.d.ts +1 -1
  47. package/dist/_dts/theme-core/src/ThemeFontLoader.d.ts +17 -1
  48. package/dist/_dts/theme-core/src/buttons/affordanceSuppression.d.ts +17 -0
  49. package/dist/_dts/theme-core/src/buttons/buttonColourContract.d.ts +1 -1
  50. package/dist/_dts/theme-core/src/buttons/classNames.d.ts +16 -0
  51. package/dist/_dts/theme-core/src/buttons/generateButtonCss.d.ts +0 -6
  52. package/dist/_dts/theme-core/src/buttons/resolvedButtonCss.d.ts +4 -4
  53. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  54. package/dist/_dts/theme-core/src/hosted-booking-appearance.d.ts +54 -12
  55. package/dist/_dts/theme-core/src/index.d.ts +1 -1
  56. package/dist/client/{BookingConsentAgreement-CuKa82V4.mjs → BookingConsentAgreement-xJeYNdnb.mjs} +2 -2
  57. package/dist/client/{DiscountCodeDisclosure-BbYieKWB.mjs → DiscountCodeDisclosure-DdT6uzl9.mjs} +1 -1
  58. package/dist/client/{EventCombined.client-LTfR1Aby.mjs → EventCombined.client-Cp28uYuM.mjs} +11 -15
  59. package/dist/client/{EventListing.client-DUHpYSuo.mjs → EventListing.client-CD6AJsMr.mjs} +4 -17
  60. package/dist/client/{LeafletStaticMap-CHRupL6m.mjs → LeafletStaticMap-DBsAi9-e.mjs} +1 -1
  61. package/dist/client/{accordion-6HiIFxNL.mjs → accordion-6dwbOKYR.mjs} +1 -1
  62. package/dist/client/{bookingForm-Dlmid43H.mjs → bookingForm-CZE9_qPQ.mjs} +5 -5
  63. package/dist/client/bookings.mjs +175 -93
  64. package/dist/client/{carousel-DmkZRRq_.mjs → carousel-7VHGQARz.mjs} +1 -1
  65. package/dist/client/{cart-CIC24330.mjs → cart-Qg_mvQhh.mjs} +3 -3
  66. package/dist/client/{checkout-D1Zw9imo.mjs → checkout-D84rpgdr.mjs} +3 -3
  67. package/dist/client/client.mjs +602 -139
  68. package/dist/client/{context-Cy1OayHx.mjs → context-Ctp3T0Wr.mjs} +1 -1
  69. package/dist/client/{dates-aDcfoLHr.mjs → dates-DJKFcI_N.mjs} +2 -2
  70. package/dist/client/{eventCalendar-FQxMPAjf.mjs → eventCalendar-CK31z3vs.mjs} +11 -7
  71. package/dist/client/{eventCombined-Dr3ac6Hb.mjs → eventCombined-DiXd-ewn.mjs} +3 -3
  72. package/dist/client/{eventDetails-D-AzUHFQ.mjs → eventDetails-CTRgt2DK.mjs} +4 -4
  73. package/dist/client/{eventListing-B3XxBf3i.mjs → eventListing-Dy9vi_j_.mjs} +3 -3
  74. package/dist/client/{eventRegistration-I6EaokFD.mjs → eventRegistration-CnalYMr2.mjs} +124 -31
  75. package/dist/client/{form-BbWckVWY.mjs → form-eUiMveTT.mjs} +2 -2
  76. package/dist/client/{headerSection-C9qU4Y7x.mjs → headerSection-Dy9kQpB1.mjs} +2 -2
  77. package/dist/client/hooks.mjs +247 -32
  78. package/dist/client/{locationMap-CLCShvlG.mjs → locationMap-DalCmWU0.mjs} +2 -2
  79. package/dist/client/{newsletterForm-Briukxzi.mjs → newsletterForm-SDDPvhS0.mjs} +23 -10
  80. package/dist/client/{pricing-Copadu-2.mjs → pricing-OcMz4SnX.mjs} +1 -1
  81. package/dist/client/{productDetail-oujlRd-r.mjs → productDetail-BQrgHElM.mjs} +3 -3
  82. package/dist/client/{productList-BRiIRUcd.mjs → productList-OnPn_UJj.mjs} +3 -3
  83. package/dist/client/{propsDecoder-CB2KS_ko.mjs → propsDecoder-zBdsnS-N.mjs} +38 -8
  84. package/dist/client/rendering/client.mjs +446 -121
  85. package/dist/client/rendering/islands.mjs +17 -17
  86. package/dist/client/rendering.mjs +601 -138
  87. package/dist/client/{scrollToBlock-B1IS1_ua.mjs → scrollToBlock-BNM4Ob2Y.mjs} +28 -11
  88. package/dist/client/{shop-Vn6yNFED.mjs → shop-Bv1fPTwQ.mjs} +6 -6
  89. package/dist/client/{shop-commerce-BVTqipYp.mjs → shop-commerce-D4KNGaW8.mjs} +5 -5
  90. package/dist/client/{shop-commerce-store-BVnJVy7v.mjs → shop-commerce-store-2N5EV0Rc.mjs} +1 -1
  91. package/dist/client/{shopShared-COIeK77T.mjs → shopShared-DvJGdHTV.mjs} +3 -3
  92. package/dist/client/{useEventFilters-DzIUcS9n.mjs → useEventFilters-BBBvGDHQ.mjs} +17 -11
  93. package/dist/preview-next/client/runtime.mjs +3 -3
  94. package/dist/preview-next/editor-chrome.css +4 -8
  95. package/dist/{sdk-runtime-CnCLvZRv.mjs → sdk-runtime-Defnbfzw.mjs} +1 -1
  96. package/dist/{separator-DKDRJ1oH.mjs → separator-CZXO3Sb0.mjs} +1 -1
  97. package/dist/server/components.mjs +384 -62
  98. package/dist/server/config-validation.mjs +232 -26
  99. package/dist/server/config.mjs +232 -26
  100. package/dist/server/data.mjs +247 -32
  101. package/dist/server/index.mjs +1 -1
  102. package/dist/server/next.mjs +400 -69
  103. package/dist/server/page-converter.mjs +189 -25
  104. package/dist/server/prebuild.mjs +1 -1
  105. package/dist/server/rendering/server.mjs +399 -68
  106. package/dist/server/rendering.mjs +399 -68
  107. package/dist/server/routing.mjs +261 -33
  108. package/dist/server/server.mjs +248 -33
  109. package/dist/server/theme-bridge.mjs +47 -15
  110. package/dist/server/theme.mjs +1 -1
  111. package/dist/styles/index.css +28 -2
  112. package/package.json +1 -1
@@ -1578,30 +1578,30 @@ function parseMailingListPlacementTargeting(value) {
1578
1578
  }
1579
1579
  }
1580
1580
  function parseMailingListVisitorSelection(value) {
1581
- if (!isRecord$37(value)) return visitorSelectionError("shape");
1581
+ if (!isRecord$37(value)) return visitorSelectionError$1("shape");
1582
1582
  switch (value.provider) {
1583
1583
  case "native": {
1584
1584
  const topicIds = parseVisitorIds(value.topicIds, parseNewsletterListId);
1585
- return topicIds === null ? visitorSelectionError("targets") : ok$2({
1585
+ return topicIds === null ? visitorSelectionError$1("targets") : ok$2({
1586
1586
  provider: "native",
1587
1587
  topicIds
1588
1588
  });
1589
1589
  }
1590
1590
  case "brevo": {
1591
1591
  const listIds = parseVisitorIds(value.listIds, parseBrevoListId);
1592
- return listIds === null ? visitorSelectionError("targets") : ok$2({
1592
+ return listIds === null ? visitorSelectionError$1("targets") : ok$2({
1593
1593
  provider: "brevo",
1594
1594
  listIds
1595
1595
  });
1596
1596
  }
1597
1597
  case "mailchimp": {
1598
1598
  const interestIds = parseVisitorIds(value.interestIds, parseMailchimpInterestId);
1599
- return interestIds === null ? visitorSelectionError("targets") : ok$2({
1599
+ return interestIds === null ? visitorSelectionError$1("targets") : ok$2({
1600
1600
  provider: "mailchimp",
1601
1601
  interestIds
1602
1602
  });
1603
1603
  }
1604
- default: return visitorSelectionError("provider");
1604
+ default: return visitorSelectionError$1("provider");
1605
1605
  }
1606
1606
  }
1607
1607
  function parseNativeTargeting(selection) {
@@ -1720,7 +1720,7 @@ function targetingError(field) {
1720
1720
  field
1721
1721
  });
1722
1722
  }
1723
- function visitorSelectionError(field) {
1723
+ function visitorSelectionError$1(field) {
1724
1724
  return err$2({
1725
1725
  tag: "invalid_mailing_list_visitor_selection",
1726
1726
  field
@@ -5078,7 +5078,7 @@ var init_buttonColourContract = __esmMin((() => {
5078
5078
  nonTextMinimumRatio: 3,
5079
5079
  gradientSamplesPerSegment: 20,
5080
5080
  alphaBackgrounds: "reject-without-known-surface",
5081
- disabled: "retain-full-colour-contract"
5081
+ disabled: "validated-colour-pair-with-muted-control-opacity"
5082
5082
  };
5083
5083
  }));
5084
5084
  //#endregion
@@ -5650,6 +5650,12 @@ var init_parseThemeForPersistence = __esmMin((() => {
5650
5650
  init_types$14();
5651
5651
  }));
5652
5652
  //#endregion
5653
+ //#region ../theme-core/src/buttons/affordanceSuppression.ts
5654
+ var AFFORDANCE_SUPPRESS_CLASS;
5655
+ var init_affordanceSuppression = __esmMin((() => {
5656
+ AFFORDANCE_SUPPRESS_CLASS = "rb-affordance-off";
5657
+ }));
5658
+ //#endregion
5653
5659
  //#region ../theme-core/src/buttons/classNames.ts
5654
5660
  /**
5655
5661
  * Parse content/runtime variant identifiers into the closed theme-button class
@@ -5682,7 +5688,29 @@ function themeButtonClassName(spec) {
5682
5688
  spec.extraClassName
5683
5689
  ].filter(Boolean).join(" ");
5684
5690
  }
5691
+ /**
5692
+ * Button classes for an authored button that renders its own trailing icon.
5693
+ *
5694
+ * A separate function rather than a flag on `themeButtonClassName`, because
5695
+ * there is exactly one caller and it should stay visible in a diff. The name
5696
+ * states what the caller knows to be true of its own markup — that it renders a
5697
+ * trailing icon — rather than what the theme does about it. The consequence is
5698
+ * the theme's to decide and to change; a caller naming the consequence would be
5699
+ * asserting a policy it does not own, and would quietly become a lie the moment
5700
+ * that policy moved.
5701
+ *
5702
+ * Do not reach for this to remove an arrow you simply do not want. A trailing
5703
+ * affordance is declared by the button style, and a block overriding that is the
5704
+ * defect this replaced.
5705
+ */
5706
+ function themeButtonClassNameWithTrailingIcon(spec) {
5707
+ return themeButtonClassName({
5708
+ ...spec,
5709
+ extraClassName: [spec.extraClassName, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ")
5710
+ });
5711
+ }
5685
5712
  var init_classNames = __esmMin((() => {
5713
+ init_affordanceSuppression();
5686
5714
  init_types$14();
5687
5715
  }));
5688
5716
  //#endregion
@@ -8222,8 +8250,7 @@ var init_resolvedButtonCss = __esmMin((() => {
8222
8250
  ["cursor", "not-allowed"],
8223
8251
  ["transform", "none"],
8224
8252
  ["box-shadow", "none"],
8225
- ["outline", "2px dashed currentColor"],
8226
- ["outline-offset", "-4px"]
8253
+ ["opacity", "0.55"]
8227
8254
  ];
8228
8255
  }));
8229
8256
  //#endregion
@@ -8561,7 +8588,7 @@ function resolveBoxShadow(variant, global, theme, tokens) {
8561
8588
  const color = shadowConfig.colorToken ? tokens.getColor(shadowConfig.colorToken) : void 0;
8562
8589
  return generateShadowValue$1(shadowConfig.elevation, shadowConfig.softness, shadowConfig.position ?? "bottom", color);
8563
8590
  }
8564
- var AFFORDANCE_SUPPRESS_CLASS, BUTTON_SIZE_NAMES, LETTER_SPACING_MAP, STRUCTURAL_DECLARATIONS;
8591
+ var BUTTON_SIZE_NAMES, LETTER_SPACING_MAP, STRUCTURAL_DECLARATIONS;
8565
8592
  var init_generateButtonCss = __esmMin((() => {
8566
8593
  init_types$14();
8567
8594
  init_classNames();
@@ -8576,7 +8603,7 @@ var init_generateButtonCss = __esmMin((() => {
8576
8603
  init_resolveButtonColourStates();
8577
8604
  init_resolvedButtonCss();
8578
8605
  init_buttonSurfaceContext();
8579
- AFFORDANCE_SUPPRESS_CLASS = "rb-affordance-off";
8606
+ init_affordanceSuppression();
8580
8607
  BUTTON_SIZE_NAMES = buttonSizeNameSchema.options;
8581
8608
  LETTER_SPACING_MAP = {
8582
8609
  tight: "-0.025em",
@@ -11043,14 +11070,12 @@ function generateVariantCSS(variant, themeId, cardClasses, tokens, theme) {
11043
11070
  const shadowValue = generateShadowValue(shadow);
11044
11071
  rules.push(`box-shadow: ${shadowValue}`);
11045
11072
  }
11046
- rules.push(`display: flex`);
11047
- rules.push(`flex-direction: column`);
11048
- rules.push(`position: relative`);
11049
- rules.push(`overflow: visible`);
11073
+ const structureSelector = cardClasses.map((cardClass) => `:where([data-theme-scope="${themeId}"]) :where(.${cardClass})`).join(",\n");
11050
11074
  const mediaRadius = MEDIA_CORNER_MAP[corners];
11051
11075
  const mediaRules = [`border-top-left-radius: ${mediaRadius}`, `border-top-right-radius: ${mediaRadius}`];
11052
11076
  const contentRules = [`padding: ${resolveContentPadding(variant)}`];
11053
11077
  return [
11078
+ `${structureSelector} {\n display: flex;\n flex-direction: column;\n position: relative;\n overflow: visible;\n}`,
11054
11079
  `${containerSelector} {\n ${rules.join(";\n ")};\n}`,
11055
11080
  ...cardDecorationPseudoRules(containerSelectors, variant.decorations, resolveColor),
11056
11081
  `${fallbackBackgroundSelector} {\n background: transparent;\n}`,
@@ -13745,6 +13770,7 @@ function calendarQueryKey(siteId, stage, filters) {
13745
13770
  filters.eventSurface ?? "all",
13746
13771
  normalizedCsv(filters.eventPresets),
13747
13772
  filters.scheduleScope ?? "any",
13773
+ ...filters.seriesIds === void 0 ? [] : [normalizedCsv(filters.seriesIds)],
13748
13774
  normalizedCsv(filters.categoryIds),
13749
13775
  normalizeCalendarFilterId(filters.venueId) ?? "",
13750
13776
  normalizeCalendarFilterId(filters.staffMemberId) ?? "",
@@ -13822,6 +13848,7 @@ var init_calendarWindow = __esmMin((() => {
13822
13848
  eventSurface: z$1.enum(eventSurfaceScopeValues).optional(),
13823
13849
  eventPresets: z$1.string().optional(),
13824
13850
  scheduleScope: z$1.enum(eventScheduleScopeValues).optional(),
13851
+ seriesIds: z$1.string().optional(),
13825
13852
  categoryIds: z$1.string().optional(),
13826
13853
  venueId: z$1.string().transform(normalizeCalendarFilterId).optional(),
13827
13854
  staffMemberId: z$1.string().transform(normalizeCalendarFilterId).optional()
@@ -23936,6 +23963,7 @@ var init_schema = __esmMin((() => {
23936
23963
  ];
23937
23964
  siteOptionSources = [
23938
23965
  "eventCategories",
23966
+ "eventSeries",
23939
23967
  "venues",
23940
23968
  "staffMembers"
23941
23969
  ];
@@ -28883,6 +28911,38 @@ var init_booking_form_interactive = __esmMin((() => {
28883
28911
  });
28884
28912
  }));
28885
28913
  //#endregion
28914
+ //#region ../blocks/src/system/blocks/events/shared/eventSelection.ts
28915
+ /** Invalid saved selections fail closed rather than widening discovery. */
28916
+ function resolveEventSelection(mode, value) {
28917
+ if (mode !== "selected") return { kind: "matching" };
28918
+ const candidates = Array.isArray(value) ? value : typeof value === "string" ? value.split(",").filter(Boolean) : [];
28919
+ const ids = [];
28920
+ for (const candidate of candidates) {
28921
+ if (typeof candidate !== "string") return {
28922
+ kind: "selected",
28923
+ seriesIds: []
28924
+ };
28925
+ const parsed = parseEventSeriesId(candidate.trim());
28926
+ if (!parsed.ok) return {
28927
+ kind: "selected",
28928
+ seriesIds: []
28929
+ };
28930
+ ids.push(parsed.value);
28931
+ }
28932
+ return {
28933
+ kind: "selected",
28934
+ seriesIds: [...new Set(ids)].sort()
28935
+ };
28936
+ }
28937
+ /** Undefined means discovery; an empty string is an explicitly empty selection. */
28938
+ function eventSeriesScopeCsv(value) {
28939
+ if (value == null) return void 0;
28940
+ return typeof value === "string" ? value : value.join(",");
28941
+ }
28942
+ var init_eventSelection = __esmMin((() => {
28943
+ init_src$2();
28944
+ }));
28945
+ //#endregion
28886
28946
  //#region ../blocks/src/system/runtime/nodes/events/domain/capacity.ts
28887
28947
  /**
28888
28948
  * Compute remaining spots for an event from `availableSpots` with a fallback
@@ -31542,12 +31602,12 @@ var init_EventCompactRow = __esmMin((() => {
31542
31602
  }), cta.hidden ? /* @__PURE__ */ jsx("span", {
31543
31603
  className: "event-compact-row-status",
31544
31604
  children: cta.label
31545
- }) : /* @__PURE__ */ jsxs("a", {
31605
+ }) : /* @__PURE__ */ jsx("a", {
31546
31606
  href: cta.href,
31547
31607
  target: cta.external ? "_blank" : void 0,
31548
31608
  rel: cta.external ? "noopener noreferrer" : void 0,
31549
31609
  className: `${buttonClass} event-compact-row-cta`,
31550
- children: [/* @__PURE__ */ jsx("span", { children: cta.label }), /* @__PURE__ */ jsx(ArrowRightIcon, { "aria-hidden": "true" })]
31610
+ children: /* @__PURE__ */ jsx("span", { children: cta.label })
31551
31611
  })]
31552
31612
  })]
31553
31613
  })]
@@ -31852,6 +31912,7 @@ function normalizeFilterId(value) {
31852
31912
  return id === "all" ? void 0 : id;
31853
31913
  }
31854
31914
  function buildEventRuntimeFilters(input) {
31915
+ if (input.seriesIds != null) return { seriesIds: input.seriesIds };
31855
31916
  const params = {};
31856
31917
  if (input.eventSurface && input.eventSurface !== "all") params.eventSurface = input.eventSurface;
31857
31918
  const eventPresets = normalizeCsvString(input.filterEventPresets);
@@ -31867,6 +31928,7 @@ function buildEventRuntimeFilters(input) {
31867
31928
  }
31868
31929
  function getEventRuntimeFiltersKey(filters) {
31869
31930
  return JSON.stringify({
31931
+ seriesIds: filters?.seriesIds == null ? null : [...new Set(filters.seriesIds.split(",").filter(Boolean))].sort().join(","),
31870
31932
  categoryIds: normalizeCsvString(filters?.categoryIds),
31871
31933
  staffMemberId: normalizeOptionalId(filters?.staffMemberId),
31872
31934
  venueId: normalizeOptionalId(filters?.venueId),
@@ -31927,11 +31989,15 @@ function buildEventCollectionDisplay(source) {
31927
31989
  };
31928
31990
  }
31929
31991
  function buildEventCollectionFilterDisplay(source) {
31930
- return {
31931
- showFilters: source.showFilters ?? true,
31932
- showCategoryFilter: source.showCategoryFilter ?? "auto",
31933
- showVenueFilter: source.showVenueFilter ?? false,
31934
- showStaffFilter: source.showStaffFilter ?? true,
31992
+ const selected = source.seriesIds != null;
31993
+ const matchingFilters = selected ? {
31994
+ eventSurface: "all",
31995
+ filterEventPresets: null,
31996
+ scheduleScope: "any",
31997
+ filterCategoryIds: null,
31998
+ filterStaffMemberId: null,
31999
+ filterVenueId: null
32000
+ } : {
31935
32001
  eventSurface: normalizeEventSurfaceScope(source.eventSurface),
31936
32002
  filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
31937
32003
  scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
@@ -31939,6 +32005,14 @@ function buildEventCollectionFilterDisplay(source) {
31939
32005
  filterStaffMemberId: normalizeEventStaffMemberId(source.filterStaffMemberId),
31940
32006
  filterVenueId: normalizeEventVenueId(source.filterVenueId)
31941
32007
  };
32008
+ return {
32009
+ seriesIds: eventSeriesScopeCsv(source.seriesIds),
32010
+ showFilters: selected ? false : source.showFilters ?? true,
32011
+ showCategoryFilter: source.showCategoryFilter ?? "auto",
32012
+ showVenueFilter: source.showVenueFilter ?? false,
32013
+ showStaffFilter: source.showStaffFilter ?? true,
32014
+ ...matchingFilters
32015
+ };
31942
32016
  }
31943
32017
  function buildEventCollectionPresentationDisplay(source) {
31944
32018
  return {
@@ -31953,14 +32027,15 @@ function buildEventCollectionPresentationDisplay(source) {
31953
32027
  }
31954
32028
  function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date()) {
31955
32029
  const timeZone = source.calendarWindow?.scope.timeZone ?? toBookingTimeZone(source.bookingTimeZone);
32030
+ const selected = source.seriesIds != null;
31956
32031
  return {
31957
32032
  calendarWindow: source.calendarWindow ?? void 0,
31958
32033
  siteId: source.siteId,
31959
32034
  stage: source.stage,
31960
32035
  prefetchedEvents: source.events != null,
31961
- eventSurface: normalizeEventSurfaceScope(source.eventSurface),
31962
- filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
31963
- scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
32036
+ eventSurface: selected ? "all" : normalizeEventSurfaceScope(source.eventSurface),
32037
+ filterEventPresets: selected ? null : normalizeEventSurfacePresetsCsv(source.filterEventPresets),
32038
+ scheduleScope: selected ? "any" : normalizeEventScheduleScope(source.scheduleScope),
31964
32039
  calendarContext: {
31965
32040
  timeZone,
31966
32041
  initialToday: source.calendarWindow?.initialToday ?? getLocalScheduleDate(now, timeZone)
@@ -31989,6 +32064,7 @@ function buildEventCollectionListingDisplay(display, prefetchedEvents, className
31989
32064
  }
31990
32065
  var eventSurfaceScopeSchema$1, eventScheduleScopeSchema$1, eventCollectionFilterSourceSchemaShape, eventCollectionSourceSchemaShape, eventCollectionDisplaySchemaShape, eventCollectionHydrationSchema;
31991
32066
  var init_eventCollectionContract = __esmMin((() => {
32067
+ init_eventSelection();
31992
32068
  init_calendarWindow();
31993
32069
  init_cards();
31994
32070
  init_src$2();
@@ -32007,6 +32083,7 @@ var init_eventCollectionContract = __esmMin((() => {
32007
32083
  eventSurface: eventSurfaceScopeSchema$1.nullable().optional(),
32008
32084
  filterEventPresets: z$1.union([z$1.string(), z$1.array(z$1.string())]).nullable().optional(),
32009
32085
  scheduleScope: eventScheduleScopeSchema$1.nullable().optional(),
32086
+ seriesIds: z$1.union([z$1.string(), z$1.array(z$1.string())]).nullable().optional(),
32010
32087
  filterCategoryIds: z$1.union([z$1.string(), z$1.array(z$1.string())]).nullable().optional(),
32011
32088
  filterStaffMemberId: z$1.string().nullable().optional(),
32012
32089
  filterVenueId: z$1.string().nullable().optional()
@@ -32053,6 +32130,7 @@ var init_eventCollectionContract = __esmMin((() => {
32053
32130
  eventSurface: eventSurfaceScopeSchema$1,
32054
32131
  filterEventPresets: z$1.string().nullable(),
32055
32132
  scheduleScope: eventScheduleScopeSchema$1,
32133
+ seriesIds: z$1.string().nullable().optional(),
32056
32134
  filterCategoryIds: z$1.string().nullable(),
32057
32135
  filterStaffMemberId: z$1.string().nullable(),
32058
32136
  filterVenueId: z$1.string().nullable(),
@@ -32098,6 +32176,7 @@ function buildEventListingInteractiveIslandProps(props) {
32098
32176
  }
32099
32177
  var cardOrientationSchema, eventSurfaceScopeSchema, eventScheduleScopeSchema, eventListingSourceSchema, eventListingDisplaySchema, eventListingHydrationSchema, eventListingRenderSchema, eventListingIslandMetaCodec, eventListingBlockRuntime, eventListingIslandMetaKeys, eventListingInteractiveIslandPropsCodec;
32100
32178
  var init_EventListing_interactive = __esmMin((() => {
32179
+ init_eventSelection();
32101
32180
  init_cards();
32102
32181
  init_schemas();
32103
32182
  init_shared$3();
@@ -32164,6 +32243,7 @@ var init_EventListing_interactive = __esmMin((() => {
32164
32243
  eventSurface: eventSurfaceScopeSchema,
32165
32244
  filterEventPresets: z$1.string().nullable(),
32166
32245
  scheduleScope: eventScheduleScopeSchema,
32246
+ seriesIds: z$1.string().nullable().optional(),
32167
32247
  filterCategoryIds: z$1.string().nullable().optional(),
32168
32248
  filterStaffMemberId: z$1.string().nullable().optional(),
32169
32249
  filterVenueId: z$1.string().nullable().optional(),
@@ -32224,6 +32304,7 @@ var init_EventListing_interactive = __esmMin((() => {
32224
32304
  eventSurface: normalizeEventSurfaceScope(source.eventSurface),
32225
32305
  filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
32226
32306
  scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
32307
+ seriesIds: eventSeriesScopeCsv(source.seriesIds),
32227
32308
  filterCategoryIds: normalizeEventCategoryIdsCsv(source.filterCategoryIds),
32228
32309
  filterStaffMemberId: normalizeEventStaffMemberId(source.filterStaffMemberId),
32229
32310
  filterVenueId: normalizeEventVenueId(source.filterVenueId),
@@ -32297,6 +32378,7 @@ function buildEventCalendarListingRender(render, className = render.display.clas
32297
32378
  eventSurface: display.eventSurface,
32298
32379
  filterEventPresets: display.filterEventPresets,
32299
32380
  scheduleScope: display.scheduleScope,
32381
+ seriesIds: display.seriesIds,
32300
32382
  filterCategoryIds: display.filterCategoryIds,
32301
32383
  filterStaffMemberId: display.filterStaffMemberId,
32302
32384
  filterVenueId: display.filterVenueId,
@@ -44583,6 +44665,27 @@ const headerRuntimeTransforms = [{
44583
44665
  init_events$2();
44584
44666
  init_core$1();
44585
44667
  init_calendarWindow();
44668
+ init_eventSelection();
44669
+ const eventCalendarSelectionParam = {
44670
+ id: "events.calendarSelectionParam",
44671
+ kind: "formatter",
44672
+ summary: "Resolve selected events instead of discovery filters",
44673
+ schema: z$1.object({ key: z$1.enum([
44674
+ "seriesIds",
44675
+ "eventSurface",
44676
+ "filterEventPresets",
44677
+ "scheduleScope",
44678
+ "filterCategoryIds",
44679
+ "filterStaffMemberId",
44680
+ "filterVenueId"
44681
+ ]) }),
44682
+ run(value, { key }) {
44683
+ const content = asPartialObject(value) ?? {};
44684
+ const selection = resolveEventSelection(content.eventSelection, content.selectedEventSeriesIds);
44685
+ if (selection.kind === "selected") return key === "seriesIds" ? selection.seriesIds : void 0;
44686
+ return key === "seriesIds" ? void 0 : content[key];
44687
+ }
44688
+ };
44586
44689
  const readJobSchema = z$1.object({ job: z$1.enum(["list", "calendar"]) });
44587
44690
  const eventCalendarReadProfile = {
44588
44691
  id: "events.calendarReadProfile",
@@ -44608,6 +44711,7 @@ init_core$1();
44608
44711
  init_boxStyles$1();
44609
44712
  init_boxStyleClassNames();
44610
44713
  const defaultTransforms = createTransformRegistry([
44714
+ eventCalendarSelectionParam,
44611
44715
  eventCalendarReadEnabled,
44612
44716
  eventCalendarReadProfile,
44613
44717
  ...formattingTransforms,
@@ -45868,17 +45972,16 @@ const ButtonNode = ({ value, children, href, variantId = "primary", size = "md",
45868
45972
  console.warn("[ButtonNode] Missing href for link-required button");
45869
45973
  return null;
45870
45974
  }
45871
- const extraClassName = affordanceIcon ? [className, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ") : className;
45872
45975
  const resolvedVariantId = parseThemeButtonVariantId(variantId);
45873
45976
  if (variantId && !resolvedVariantId) {
45874
45977
  console.error("[ButtonNode] Invalid button variant", { variantId });
45875
45978
  return null;
45876
45979
  }
45877
- const combinedClassName = resolvedVariantId ? themeButtonClassName({
45980
+ const combinedClassName = resolvedVariantId ? (affordanceIcon ? themeButtonClassNameWithTrailingIcon : themeButtonClassName)({
45878
45981
  variant: resolvedVariantId,
45879
45982
  size,
45880
- extraClassName
45881
- }) : extraClassName;
45983
+ extraClassName: className
45984
+ }) : className;
45882
45985
  if (resolvedHref) return /* @__PURE__ */ jsxs("a", {
45883
45986
  href: resolvedHref,
45884
45987
  target,
@@ -47100,6 +47203,7 @@ const publicPricingSchema = z$1.object({
47100
47203
  });
47101
47204
  const publicAppointmentServiceSchema = z$1.object({
47102
47205
  id: z$1.string().min(1),
47206
+ slug: z$1.string().min(1).optional(),
47103
47207
  title: z$1.string(),
47104
47208
  description: z$1.string().nullable().optional(),
47105
47209
  durationMinutes: z$1.number().int().positive(),
@@ -47176,7 +47280,7 @@ function formatAmountOrFree(amount, currency) {
47176
47280
  currency
47177
47281
  }, { decimals: "auto" });
47178
47282
  }
47179
- function buildRows(services, pathname) {
47283
+ function buildRows(services, pathname, servicePathPrefix) {
47180
47284
  return services.map((service) => ({
47181
47285
  id: service.id,
47182
47286
  title: service.title,
@@ -47187,7 +47291,8 @@ function buildRows(services, pathname) {
47187
47291
  href: resolveDedicatedBookingHref(pathname, {
47188
47292
  kind: "appointment_service",
47189
47293
  serviceId: service.id
47190
- })
47294
+ }),
47295
+ detailsHref: servicePathPrefix && service.slug ? `${servicePathPrefix.replace(/\/$/, "")}/${encodeURIComponent(service.slug)}` : null
47191
47296
  }));
47192
47297
  }
47193
47298
  function buildAppointmentServicesView(input) {
@@ -47206,13 +47311,14 @@ function buildAppointmentServicesView(input) {
47206
47311
  };
47207
47312
  return {
47208
47313
  kind: "items",
47209
- rows: buildRows(parsed.services, input.pathname)
47314
+ rows: buildRows(parsed.services, input.pathname, input.servicePathPrefix ?? null)
47210
47315
  };
47211
47316
  }
47212
- function AppointmentServicesNode({ sectionHeading, services, pathname, className }) {
47317
+ function AppointmentServicesNode({ sectionHeading, services, pathname, servicePathPrefix, className }) {
47213
47318
  const view = buildAppointmentServicesView({
47214
47319
  services,
47215
- pathname: typeof pathname === "string" ? pathname : void 0
47320
+ pathname: typeof pathname === "string" ? pathname : void 0,
47321
+ servicePathPrefix: typeof servicePathPrefix === "string" ? servicePathPrefix : null
47216
47322
  });
47217
47323
  const rootClassName = `appointment-services ${className ?? ""}`.trim();
47218
47324
  const RowTitle = sectionHeading ? "h3" : "h2";
@@ -47243,7 +47349,10 @@ function AppointmentServicesNode({ sectionHeading, services, pathname, className
47243
47349
  children: [
47244
47350
  /* @__PURE__ */ jsx(RowTitle, {
47245
47351
  className: "appointment-services-row-title rb-text-lg rb-font-medium rb-leading-tight",
47246
- children: row.title
47352
+ children: row.detailsHref ? /* @__PURE__ */ jsx("a", {
47353
+ href: row.detailsHref,
47354
+ children: row.title
47355
+ }) : row.title
47247
47356
  }),
47248
47357
  row.description ? /* @__PURE__ */ jsx("p", {
47249
47358
  className: "appointment-services-row-description rb-text-sm rb-leading-6 status-muted",
@@ -48776,7 +48885,6 @@ function OfferingsCatalogue(props) {
48776
48885
  //#endregion
48777
48886
  //#region ../blocks/src/system/runtime/nodes/offerings-preview-content.tsx
48778
48887
  init_buttons();
48779
- init_svg();
48780
48888
  init_shared$2();
48781
48889
  function OfferingsPreviewContent(props) {
48782
48890
  const groupLinkClass = themeButtonClassName({
@@ -48823,13 +48931,10 @@ function OfferingsPreviewContent(props) {
48823
48931
  }),
48824
48932
  groupCta ? /* @__PURE__ */ jsx("footer", {
48825
48933
  className: "offerings-preview-card-footer rb-mt-auto rb-flex",
48826
- children: /* @__PURE__ */ jsxs("a", {
48934
+ children: /* @__PURE__ */ jsx("a", {
48827
48935
  className: groupLinkClass,
48828
48936
  href: groupCta.href,
48829
- children: [/* @__PURE__ */ jsx("span", { children: groupCta.label }), /* @__PURE__ */ jsx(ArrowRightIcon, {
48830
- "aria-hidden": "true",
48831
- className: "offerings-preview-link-icon rb-h-4 rb-w-4"
48832
- })]
48937
+ children: /* @__PURE__ */ jsx("span", { children: groupCta.label })
48833
48938
  })
48834
48939
  }) : null
48835
48940
  ]
@@ -50246,23 +50351,123 @@ const formBlockDefinition = {
50246
50351
  runtime: formBlockRuntime
50247
50352
  };
50248
50353
  //#endregion
50354
+ //#region ../blocks/src/system/blocks/events/eventSelectionFields.ts
50355
+ init_schema();
50356
+ const eventSelectionFields = [{
50357
+ id: "eventSelection",
50358
+ type: "select",
50359
+ label: "Events to show",
50360
+ required: false,
50361
+ multiple: false,
50362
+ defaultValue: "matching",
50363
+ options: [{
50364
+ value: "matching",
50365
+ label: "All matching events"
50366
+ }, {
50367
+ value: "selected",
50368
+ label: "Selected events"
50369
+ }],
50370
+ ui: { intent: "behavior" }
50371
+ }, createSiteOptionSelectField({
50372
+ id: "selectedEventSeriesIds",
50373
+ label: "Selected events",
50374
+ description: "Show upcoming dates for these events. Other event filters do not apply.",
50375
+ required: false,
50376
+ multiple: true,
50377
+ defaultValue: [],
50378
+ optionSource: "eventSeries",
50379
+ ui: {
50380
+ intent: "behavior",
50381
+ searchThreshold: 1,
50382
+ visibleWhen: {
50383
+ field: "eventSelection",
50384
+ equals: "selected"
50385
+ }
50386
+ }
50387
+ })];
50388
+ function withEventSelectionVisibility(field) {
50389
+ if (![
50390
+ "eventSurface",
50391
+ "filterEventPresets",
50392
+ "scheduleScope",
50393
+ "filterCategoryIds",
50394
+ "filterStaffMemberId",
50395
+ "filterVenueId",
50396
+ "showFilters",
50397
+ "showCategoryFilter",
50398
+ "showVenueFilter",
50399
+ "showStaffFilter"
50400
+ ].includes(field.id)) return field;
50401
+ const visibleWhen = field.ui?.visibleWhen;
50402
+ return {
50403
+ ...field,
50404
+ ui: {
50405
+ ...field.ui,
50406
+ visibleWhen: { allOf: [{
50407
+ field: "eventSelection",
50408
+ notEquals: "selected"
50409
+ }, ...visibleWhen ? [visibleWhen] : []] }
50410
+ }
50411
+ };
50412
+ }
50413
+ //#endregion
50249
50414
  //#region ../blocks/src/system/blocks/events/eventCalendarDataLoaders.ts
50250
50415
  init_calendarWindow();
50251
50416
  const scopeParams = {
50252
50417
  siteId: { $bind: { from: "$root.siteId" } },
50418
+ seriesIds: { $bind: {
50419
+ from: "content",
50420
+ transforms: [{
50421
+ id: "events.calendarSelectionParam",
50422
+ options: { key: "seriesIds" }
50423
+ }]
50424
+ } },
50253
50425
  stage: { $bind: {
50254
50426
  from: "$root.previewStage",
50255
50427
  fallback: "published"
50256
50428
  } },
50257
- eventSurface: { $bind: { from: "content.eventSurface" } },
50429
+ eventSurface: { $bind: {
50430
+ from: "content",
50431
+ transforms: [{
50432
+ id: "events.calendarSelectionParam",
50433
+ options: { key: "eventSurface" }
50434
+ }, { id: "value.csv" }]
50435
+ } },
50258
50436
  eventPresets: { $bind: {
50259
- from: "content.filterEventPresets",
50260
- transforms: [{ id: "value.csv" }]
50437
+ from: "content",
50438
+ transforms: [{
50439
+ id: "events.calendarSelectionParam",
50440
+ options: { key: "filterEventPresets" }
50441
+ }, { id: "value.csv" }]
50442
+ } },
50443
+ scheduleScope: { $bind: {
50444
+ from: "content",
50445
+ transforms: [{
50446
+ id: "events.calendarSelectionParam",
50447
+ options: { key: "scheduleScope" }
50448
+ }, { id: "value.csv" }]
50449
+ } },
50450
+ categoryIds: { $bind: {
50451
+ from: "content",
50452
+ transforms: [{
50453
+ id: "events.calendarSelectionParam",
50454
+ options: { key: "filterCategoryIds" }
50455
+ }, { id: "value.csv" }]
50261
50456
  } },
50262
- scheduleScope: { $bind: { from: "content.scheduleScope" } },
50263
- categoryIds: { $bind: { from: "content.filterCategoryIds" } },
50264
- staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
50265
- venueId: { $bind: { from: "content.filterVenueId" } }
50457
+ staffMemberId: { $bind: {
50458
+ from: "content",
50459
+ transforms: [{
50460
+ id: "events.calendarSelectionParam",
50461
+ options: { key: "filterStaffMemberId" }
50462
+ }, { id: "value.csv" }]
50463
+ } },
50464
+ venueId: { $bind: {
50465
+ from: "content",
50466
+ transforms: [{
50467
+ id: "events.calendarSelectionParam",
50468
+ options: { key: "filterVenueId" }
50469
+ }, { id: "value.csv" }]
50470
+ } }
50266
50471
  };
50267
50472
  /** Combined renders two jobs; calendar-only variants never pay for the list seed. */
50268
50473
  const eventCalendarDataLoaders = {
@@ -50403,6 +50608,13 @@ const eventCalendarLayout = [styledSection({
50403
50608
  from: "content.defaultCalendarView",
50404
50609
  fallback: "month"
50405
50610
  } },
50611
+ seriesIds: { $bind: {
50612
+ from: "content",
50613
+ transforms: [{
50614
+ id: "events.calendarSelectionParam",
50615
+ options: { key: "seriesIds" }
50616
+ }]
50617
+ } },
50406
50618
  showFilters: { $bind: {
50407
50619
  from: "content.showFilters",
50408
50620
  fallback: true
@@ -50424,17 +50636,47 @@ const eventCalendarLayout = [styledSection({
50424
50636
  fallback: true
50425
50637
  } },
50426
50638
  eventSurface: { $bind: {
50427
- from: "content.eventSurface",
50428
- fallback: "all"
50639
+ from: "content",
50640
+ transforms: [{
50641
+ id: "events.calendarSelectionParam",
50642
+ options: { key: "eventSurface" }
50643
+ }]
50644
+ } },
50645
+ filterEventPresets: { $bind: {
50646
+ from: "content",
50647
+ transforms: [{
50648
+ id: "events.calendarSelectionParam",
50649
+ options: { key: "filterEventPresets" }
50650
+ }]
50429
50651
  } },
50430
- filterEventPresets: { $bind: { from: "content.filterEventPresets" } },
50431
50652
  scheduleScope: { $bind: {
50432
- from: "content.scheduleScope",
50433
- fallback: "any"
50653
+ from: "content",
50654
+ transforms: [{
50655
+ id: "events.calendarSelectionParam",
50656
+ options: { key: "scheduleScope" }
50657
+ }]
50658
+ } },
50659
+ filterCategoryIds: { $bind: {
50660
+ from: "content",
50661
+ transforms: [{
50662
+ id: "events.calendarSelectionParam",
50663
+ options: { key: "filterCategoryIds" }
50664
+ }]
50665
+ } },
50666
+ filterStaffMemberId: { $bind: {
50667
+ from: "content",
50668
+ transforms: [{
50669
+ id: "events.calendarSelectionParam",
50670
+ options: { key: "filterStaffMemberId" }
50671
+ }]
50672
+ } },
50673
+ filterVenueId: { $bind: {
50674
+ from: "content",
50675
+ transforms: [{
50676
+ id: "events.calendarSelectionParam",
50677
+ options: { key: "filterVenueId" }
50678
+ }]
50434
50679
  } },
50435
- filterCategoryIds: { $bind: { from: "content.filterCategoryIds" } },
50436
- filterStaffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
50437
- filterVenueId: { $bind: { from: "content.filterVenueId" } },
50438
50680
  cardRole: { $bind: {
50439
50681
  from: "content._cardStyles.role",
50440
50682
  fallback: "default"
@@ -50938,6 +51180,7 @@ const eventCalendarAdditionalFields = [
50938
51180
  }
50939
51181
  }
50940
51182
  },
51183
+ ...eventSelectionFields,
50941
51184
  {
50942
51185
  id: "eventSurface",
50943
51186
  type: "select",
@@ -51147,7 +51390,7 @@ const eventCalendarBlockDefinition = {
51147
51390
  titleSource: "heading",
51148
51391
  description: "Display events with calendar, list, or combined views with filtering",
51149
51392
  skipSectionStyles: true,
51150
- additionalFields: eventCalendarAdditionalFields,
51393
+ additionalFields: eventCalendarAdditionalFields.map(withEventSelectionVisibility),
51151
51394
  styleTokens: {
51152
51395
  background: "surface",
51153
51396
  typography: "body",
@@ -56291,9 +56534,56 @@ function generateNavLinkCSS(options) {
56291
56534
  if (baseRules.length > 0) cssChunks.unshift(`\n${selector} {\n ${baseRules.join("\n ")}\n}\n`);
56292
56535
  if (hoverRules.length > 0) cssChunks.push(`\n${hoverSelector} {\n ${hoverRules.join("\n ")}\n}\n`);
56293
56536
  if (activeRules.length > 0) cssChunks.push(`\n${activeSelector} {\n ${activeRules.join("\n ")}\n}\n`);
56537
+ cssChunks.push(navLinkFocusVisibleCss(selector, style, theme, tokens));
56294
56538
  cssChunks.push(generateInteractiveChildInheritanceCSS(selector));
56295
56539
  return cssChunks.join("");
56296
56540
  }
56541
+ /**
56542
+ * Keyboard focus indicator for nav links, in the header, the footer and header
56543
+ * dropdown menus — the three surfaces `generateNavLinkCSS` serves.
56544
+ *
56545
+ * Emitted unconditionally rather than as an effect, because focus visibility is
56546
+ * a floor rather than a style choice. Only the interaction-palette pill ever
56547
+ * wrote an `effects.focus` group, so every other nav — every `quiet` palette,
56548
+ * every footer, every dropdown — previously fell back to whatever outline the
56549
+ * browser drew.
56550
+ *
56551
+ * The outline takes the link's own resolved colour, so on a header that adapts
56552
+ * to the section it floats over it moves with the adaptation instead of
56553
+ * asserting a brand colour against an unknown backdrop.
56554
+ *
56555
+ * Where the style asks for `soft-glow`, the same halo goes on the outline. That
56556
+ * treatment exists because the theme has already conceded the resolved colour
56557
+ * alone is not reliable over an unpredictable backdrop — a hero photograph with
56558
+ * mixed luminance. Without it the text would stay legible by its halo while the
56559
+ * focus ring, which is the part with a contrast requirement of its own, would
56560
+ * not.
56561
+ *
56562
+ * A style that also paints a focus pill keeps it: this adds an outline around
56563
+ * that pill rather than replacing it.
56564
+ */
56565
+ function navLinkFocusVisibleCss(selector, style, theme, tokens) {
56566
+ const color = tokens.getColor(style.colorToken);
56567
+ const halo = buildTextContrastShadow({
56568
+ theme,
56569
+ colorToken: style.colorToken,
56570
+ treatment: style.contrastTreatment
56571
+ });
56572
+ return `
56573
+ ${selector}:focus-visible {
56574
+ outline: 2px solid ${color};
56575
+ outline-offset: ${focusOutlineOffset(selector)};${halo ? `\n box-shadow: ${halo};` : ""}
56576
+ }
56577
+ `;
56578
+ }
56579
+ /**
56580
+ * Dropdown items are full-width inside a panel with no horizontal padding, so
56581
+ * an outset outline would paint over and past the panel's own border. Keeping
56582
+ * it flush is the only way it reads as belonging to the item.
56583
+ */
56584
+ function focusOutlineOffset(selector) {
56585
+ return selector.includes("nav-dropdown-link") ? "-2px" : "3px";
56586
+ }
56297
56587
  function buildTextContrastShadow(input) {
56298
56588
  if (input.treatment !== "soft-glow") return null;
56299
56589
  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)";
@@ -59459,7 +59749,7 @@ function pageBlockPosition(index, blockCount) {
59459
59749
  //#endregion
59460
59750
  //#region ../blocks/src/pageRendererContracts.ts
59461
59751
  function buildPageRendererRootRuntime(dataContext) {
59462
- const { siteId = null, pageId = null, pathname = null, bookingTimeZone, previewStage = "published", apiBaseUrl = null, portalToken = null, bookingOfferingPresets = [], mailingList = { tag: "not_configured" }, eventRegistrationOverlayEnabled = false, loaderFailures = {} } = dataContext ?? {};
59752
+ 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 ?? {};
59463
59753
  return {
59464
59754
  siteId,
59465
59755
  pageId,
@@ -59469,6 +59759,7 @@ function buildPageRendererRootRuntime(dataContext) {
59469
59759
  apiBaseUrl,
59470
59760
  portalToken,
59471
59761
  bookingOfferingPresets,
59762
+ appointmentServicePathPrefix,
59472
59763
  mailingList,
59473
59764
  eventRegistrationOverlayEnabled,
59474
59765
  loaderFailures
@@ -64280,7 +64571,8 @@ const appointmentServicesBlockDefinition = {
64280
64571
  el("appointment-services", {
64281
64572
  sectionHeading: { $bind: { from: "content.heading" } },
64282
64573
  services: { $bind: { from: "data.services" } },
64283
- pathname: { $bind: { from: "$root.pathname" } }
64574
+ pathname: { $bind: { from: "$root.pathname" } },
64575
+ servicePathPrefix: { $bind: { from: "$root.appointmentServicePathPrefix" } }
64284
64576
  })
64285
64577
  ], { gap: "lg" })
64286
64578
  })]
@@ -71904,10 +72196,19 @@ const containerResponsiveThemeCss = `/*
71904
72196
  padding-top: 2.5rem;
71905
72197
  padding-bottom: 2.5rem;
71906
72198
  }
72199
+ /* Clearance for a surface that is not an authored block page.
72200
+ An authored page gets this through its opening block's container (see the
72201
+ overlay-clearance rule in styles.css). A reserved surface or a system
72202
+ destination page has no such block, so it consumes the same variable here.
72203
+ Marked with one class rather than per-surface selectors, because the last
72204
+ two additions to this family were both missed and shipped overlapping. */
71907
72205
  :where(.theme-scope)
71908
72206
  [data-site-document-layout-mode="header-overlay"]
71909
- [data-rb-reserved-surface].rb-reserved-surface-main {
71910
- padding-top: calc(var(--rb-reserved-surface-header-offset, 5.5rem) + 2.5rem);
72207
+ .rb-overlay-clearance-surface {
72208
+ padding-top: calc(
72209
+ var(--site-overlay-header-clearance, 5.5rem) +
72210
+ var(--site-overlay-opening-content-extra-pad, clamp(1rem, 2vw, 1.75rem))
72211
+ );
71911
72212
  }
71912
72213
  .rb-preview-editor-offset {
71913
72214
  padding-bottom: calc(
@@ -82264,6 +82565,23 @@ const containerResponsiveThemeCss = `/*
82264
82565
  gap: 0.5rem;
82265
82566
  }
82266
82567
 
82568
+ /* Error panel and field notes. The form block scopes these to its own
82569
+ data-block, so the newsletter form (which also renders in the footer)
82570
+ needs its own copy of the treatment. */
82571
+ :where(.theme-scope) .newsletter-form .fb-error:not([data-field-validation-message]) {
82572
+ background-color: var(--fb-error-bg);
82573
+ color: var(--fb-error-text);
82574
+ border: 1px solid var(--fb-error-border);
82575
+ border-radius: var(--rb-block-radius);
82576
+ padding: 1rem;
82577
+ font-size: 0.875rem;
82578
+ }
82579
+
82580
+ :where(.theme-scope) .newsletter-form [data-field-validation-message] {
82581
+ font-size: 0.875rem;
82582
+ color: var(--fb-error-text);
82583
+ }
82584
+
82267
82585
  /* Required indicator */
82268
82586
  :where(.theme-scope) .newsletter-required {
82269
82587
  color: rgb(var(--tb-primary));
@@ -84761,12 +85079,12 @@ function normalizeContent(block) {
84761
85079
  }
84762
85080
  /**
84763
85081
  * Normalize params for API calls.
84764
- * Converts all values to strings.
85082
+ * Converts supplied values to strings, preserving absent versus explicitly empty params.
84765
85083
  */
84766
85084
  function normalizeParams(input) {
84767
85085
  if (!input || typeof input !== "object") return {};
84768
85086
  const output = {};
84769
- for (const [key, value] of Object.entries(input)) output[key] = coerceToString(value);
85087
+ for (const [key, value] of Object.entries(input)) if (value !== void 0 && value !== null) output[key] = coerceToString(value);
84770
85088
  return output;
84771
85089
  }
84772
85090
  function isNonArrayObject(value) {
@@ -84830,6 +85148,14 @@ function coercePayload(payload) {
84830
85148
  * - Frontend: provide internal API client
84831
85149
  * - SDK: provide SDK client with endpoint mapping
84832
85150
  */
85151
+ function projectDataLoaders(loaders, shouldLoad, blockId, blockKind) {
85152
+ if (!shouldLoad) return [...loaders];
85153
+ return loaders.filter(({ key }) => shouldLoad({
85154
+ blockId,
85155
+ blockKind,
85156
+ loaderKey: key
85157
+ }));
85158
+ }
84833
85159
  function shouldSkipResolvedLoader(input) {
84834
85160
  if (input.loader.requiredParams?.some((param) => !input.params[param]?.trim())) return true;
84835
85161
  return Boolean(input.isValidEndpoint && !input.isValidEndpoint(input.endpoint));
@@ -84858,7 +85184,7 @@ async function prefetchBlockData$1(page, context, options) {
84858
85184
  return (await prefetchBlockDataWithFailures(page, context, options)).resolvedData;
84859
85185
  }
84860
85186
  async function prefetchBlockDataWithFailures(page, context, options) {
84861
- const { apiClient, isValidEndpoint, onError, getCustomBlockLoaders, getBlockDefinition: getBlockDefinition$1 = getBlockDefinition, resolveParamsBindings: resolveParamsBindings$1 = resolveParamsBindings } = options;
85187
+ const { apiClient, isValidEndpoint, onError, getCustomBlockLoaders, getBlockDefinition: getBlockDefinition$1 = getBlockDefinition, resolveParamsBindings: resolveParamsBindings$1 = resolveParamsBindings, shouldLoad } = options;
84862
85188
  const results = {};
84863
85189
  const loaderFailures = {};
84864
85190
  const tasks = [];
@@ -84875,6 +85201,7 @@ async function prefetchBlockDataWithFailures(page, context, options) {
84875
85201
  loader
84876
85202
  })) : [];
84877
85203
  } else loaders = [];
85204
+ loaders = projectDataLoaders(loaders, shouldLoad, blockId, block.kind);
84878
85205
  if (loaders.length === 0) continue;
84879
85206
  const root = {
84880
85207
  ...context.root ?? {},
@@ -84979,8 +85306,8 @@ function toStringParams(value) {
84979
85306
  for (const [k, v] of Object.entries(value)) if (typeof v === "string") out[k] = v;
84980
85307
  return out;
84981
85308
  }
84982
- function stripEmptyStringValues(params) {
84983
- for (const [key, value] of Object.entries(params)) if (value === "") delete params[key];
85309
+ function stripEmptyStringValues(params, endpoint) {
85310
+ for (const [key, value] of Object.entries(params)) if (value === "" && !(key === "seriesIds" && (endpoint === "listPublicEvents" || endpoint === "listPublicEventCalendarWindow"))) delete params[key];
84984
85311
  }
84985
85312
  function ensureSiteId(params, context) {
84986
85313
  if (!params.siteId && typeof context.siteId === "string" && context.siteId) params.siteId = context.siteId;
@@ -84993,7 +85320,7 @@ function ensureSiteId(params, context) {
84993
85320
  */
84994
85321
  function normalizeLoaderParams(endpoint, params, context) {
84995
85322
  const out = toStringParams(params);
84996
- stripEmptyStringValues(out);
85323
+ stripEmptyStringValues(out, endpoint);
84997
85324
  if (endpoint === "getPublicFormById") {
84998
85325
  ensureSiteId(out, context);
84999
85326
  if (!out.formId && out.formSlug) {
@@ -149820,10 +150147,14 @@ function buildDiscountAvailabilityRequestPlan(options) {
149820
150147
  }
149821
150148
  };
149822
150149
  }
149823
- function discountAvailabilityStateFromResponse(response) {
149824
- if (!discountAvailabilityHasDiscounts(response)) return { tag: "unavailable" };
150150
+ function discountAvailabilityStateFromResponse(requestKey, response) {
150151
+ if (!discountAvailabilityHasDiscounts(response)) return {
150152
+ tag: "unavailable",
150153
+ requestKey
150154
+ };
149825
150155
  return {
149826
150156
  tag: "available",
150157
+ requestKey,
149827
150158
  manualCodeEntryAllowed: discountAvailabilityAllowsManualEntry(response),
149828
150159
  autoAppliedDiscount: getAutoAppliedDiscountPreview(response)
149829
150160
  };
@@ -149833,10 +150164,13 @@ function discountCodeUiReducer(state, event) {
149833
150164
  case "availability-disabled": return initialDiscountCodeUiState;
149834
150165
  case "availability-loading": return {
149835
150166
  ...state,
149836
- availability: { tag: "loading" }
150167
+ availability: {
150168
+ tag: "loading",
150169
+ previous: state.availability.tag === "available" || state.availability.tag === "unavailable" ? state.availability : state.availability.tag === "loading" ? state.availability.previous : null
150170
+ }
149837
150171
  };
149838
150172
  case "availability-loaded": {
149839
- const availability = discountAvailabilityStateFromResponse(event.response);
150173
+ const availability = discountAvailabilityStateFromResponse(event.requestKey, event.response);
149840
150174
  if (availability.tag !== "available" || !availability.manualCodeEntryAllowed) return {
149841
150175
  ...state,
149842
150176
  discountUiOpen: false,
@@ -149852,7 +150186,10 @@ function discountCodeUiReducer(state, event) {
149852
150186
  ...state,
149853
150187
  discountUiOpen: false,
149854
150188
  discountCode: "",
149855
- availability: { tag: "error" }
150189
+ availability: {
150190
+ tag: "error",
150191
+ requestKey: event.requestKey
150192
+ }
149856
150193
  };
149857
150194
  case "discount-code-changed": return {
149858
150195
  ...state,
@@ -149897,11 +150234,15 @@ function useDiscountCodeUi(options) {
149897
150234
  if (cancelled) return;
149898
150235
  dispatch({
149899
150236
  type: "availability-loaded",
150237
+ requestKey: requestPlan.key,
149900
150238
  response: res
149901
150239
  });
149902
150240
  } catch {
149903
150241
  if (cancelled) return;
149904
- dispatch({ type: "availability-failed" });
150242
+ dispatch({
150243
+ type: "availability-failed",
150244
+ requestKey: requestPlan.key
150245
+ });
149905
150246
  }
149906
150247
  }
149907
150248
  checkDiscountAvailability();
@@ -149910,8 +150251,9 @@ function useDiscountCodeUi(options) {
149910
150251
  };
149911
150252
  }, [options.api, requestPlan]);
149912
150253
  const availability = state.availability;
149913
- const isAvailable = availability.tag === "available";
149914
- const manualCodeEntryAllowed = isAvailable ? availability.manualCodeEntryAllowed : false;
150254
+ const settledAvailability = availability.tag === "loading" ? availability.previous : availability.tag === "available" || availability.tag === "unavailable" ? availability : null;
150255
+ const isAvailable = settledAvailability?.tag === "available";
150256
+ const manualCodeEntryAllowed = isAvailable ? settledAvailability.manualCodeEntryAllowed : false;
149915
150257
  return {
149916
150258
  discountUiOpen: state.discountUiOpen,
149917
150259
  setDiscountUiOpen: (isOpen) => dispatch({
@@ -149925,8 +150267,10 @@ function useDiscountCodeUi(options) {
149925
150267
  }),
149926
150268
  discountsAvailable: isAvailable,
149927
150269
  manualCodeEntryAllowed,
149928
- autoAppliedDiscount: isAvailable ? availability.autoAppliedDiscount : null,
149929
- discountsAvailableLoading: availability.tag === "loading"
150270
+ autoAppliedDiscount: isAvailable ? settledAvailability.autoAppliedDiscount : null,
150271
+ discountsAvailableLoading: availability.tag === "loading",
150272
+ discountAvailabilityRequestKey: requestPlan.key,
150273
+ settledDiscountAvailabilityRequestKey: availability.tag === "error" ? availability.requestKey : settledAvailability?.requestKey ?? null
149930
150274
  };
149931
150275
  }
149932
150276
  var init_useDiscountCodeUi = __esmMin((() => {
@@ -154451,16 +154795,19 @@ function eligibilityLookupReducer(state, action) {
154451
154795
  case "loading-started": return {
154452
154796
  tag: "loading",
154453
154797
  eligibility: state.eligibility,
154798
+ settledRequestKey: state.settledRequestKey,
154454
154799
  error: null
154455
154800
  };
154456
154801
  case "resolved": return {
154457
154802
  tag: "resolved",
154458
154803
  eligibility: action.eligibility,
154804
+ settledRequestKey: action.requestKey,
154459
154805
  error: null
154460
154806
  };
154461
154807
  case "failed": return {
154462
154808
  tag: "failed",
154463
154809
  eligibility: null,
154810
+ settledRequestKey: null,
154464
154811
  error: action.message
154465
154812
  };
154466
154813
  default: return assertNever$11(action);
@@ -154486,6 +154833,7 @@ var init_hooks_state = __esmMin((() => {
154486
154833
  initialEligibilityLookupState = {
154487
154834
  tag: "idle",
154488
154835
  eligibility: null,
154836
+ settledRequestKey: null,
154489
154837
  error: null
154490
154838
  };
154491
154839
  initialExistingRegistrationLookupState = {
@@ -154565,9 +154913,23 @@ function toRegistrationOptionsSubject(subject, attendanceMode) {
154565
154913
  function useEligibility(params) {
154566
154914
  return useEligibilityWithDeps(params, eventRegistrationHooksDeps);
154567
154915
  }
154916
+ function eligibilityRequestKey(params) {
154917
+ return JSON.stringify({
154918
+ enabled: params.enabled,
154919
+ refreshKey: params.refreshKey ?? 0,
154920
+ subject: params.subject,
154921
+ attendanceMode: params.attendanceMode ?? null,
154922
+ ticketSelections: params.ticketSelectionsKey,
154923
+ selectedSlidingAmount: params.selectedSlidingAmount ?? null
154924
+ });
154925
+ }
154568
154926
  function useEligibilityWithDeps(params, deps) {
154569
154927
  const api = deps.useBlockApi();
154570
154928
  const ticketSelectionsKey = JSON.stringify(normalizeTicketSelectionLines(params.ticketSelections));
154929
+ const requestKey = eligibilityRequestKey({
154930
+ ...params,
154931
+ ticketSelectionsKey
154932
+ });
154571
154933
  const [state, dispatch] = useReducer(eligibilityLookupReducer, initialEligibilityLookupState);
154572
154934
  const requestIdRef = useRef(0);
154573
154935
  useEffect(() => {
@@ -154600,7 +154962,8 @@ function useEligibilityWithDeps(params, deps) {
154600
154962
  if (cancelled || requestIdRef.current !== requestId) return;
154601
154963
  dispatch({
154602
154964
  type: "resolved",
154603
- eligibility: transformRegistrationOptionsResponse(result)
154965
+ eligibility: transformRegistrationOptionsResponse(result),
154966
+ requestKey
154604
154967
  });
154605
154968
  } catch {
154606
154969
  if (cancelled || requestIdRef.current !== requestId) return;
@@ -154629,6 +154992,8 @@ function useEligibilityWithDeps(params, deps) {
154629
154992
  return {
154630
154993
  state,
154631
154994
  eligibility: state.eligibility,
154995
+ settledRequestKey: state.settledRequestKey,
154996
+ requestKey,
154632
154997
  isLoading: state.tag === "loading",
154633
154998
  error: state.error,
154634
154999
  creditState
@@ -156223,6 +156588,71 @@ var init_useEventRegistrationSubmit = __esmMin((() => {
156223
156588
  };
156224
156589
  }));
156225
156590
  //#endregion
156591
+ //#region ../blocks/src/system/runtime/nodes/event-registration/useSettledCommerceView.ts
156592
+ function buildCandidate(input) {
156593
+ if (!input.eligibilityIsSettled || !input.eligibility || !input.currentEvent) return null;
156594
+ return {
156595
+ eventSelectionId: input.currentEvent.selectionId,
156596
+ discountContext: resolveDiscountContext({
156597
+ paymentSelection: input.paymentSelection,
156598
+ event: input.currentEvent,
156599
+ eventRequiresPayment: input.eventRequiresPayment,
156600
+ ticketsCount: input.ticketsCount
156601
+ }),
156602
+ subtotalCents: input.eligibility.price,
156603
+ summaryLines: input.eligibility.ticketLines.map((line) => ({
156604
+ pricingOptionId: line.pricingOptionId,
156605
+ label: line.label,
156606
+ quantity: line.quantity,
156607
+ unitPriceCents: line.unitPriceCents,
156608
+ subtotalCents: line.subtotalCents
156609
+ }))
156610
+ };
156611
+ }
156612
+ function eligibilityIsSettled(result) {
156613
+ return result.settledRequestKey === result.requestKey;
156614
+ }
156615
+ function viewIsStale(view, currentEvent, eligibilityState) {
156616
+ return view.eventSelectionId !== currentEvent?.selectionId || eligibilityState?.tag === "failed" || eligibilityState?.tag === "idle";
156617
+ }
156618
+ function requestIsSettled(discountUi) {
156619
+ return discountUi.discountAvailabilityRequestKey === "disabled" || discountUi.settledDiscountAvailabilityRequestKey === discountUi.discountAvailabilityRequestKey;
156620
+ }
156621
+ function discountRequest(view) {
156622
+ const discountContext = view?.discountContext ?? null;
156623
+ return {
156624
+ discountContext,
156625
+ subtotalCents: discountContext?.type === "event" && view?.subtotalCents !== null ? view?.subtotalCents : void 0
156626
+ };
156627
+ }
156628
+ function useSettledCommerceView(input) {
156629
+ const candidate = buildCandidate({
156630
+ eligibilityIsSettled: eligibilityIsSettled(input.eligibilityResult),
156631
+ eligibility: input.eligibility,
156632
+ currentEvent: input.currentEvent,
156633
+ paymentSelection: input.paymentSelection,
156634
+ eventRequiresPayment: input.eventRequiresPayment,
156635
+ ticketsCount: input.ticketsCount
156636
+ });
156637
+ const settledRef = useRef(candidate);
156638
+ if (settledRef.current && viewIsStale(settledRef.current, input.currentEvent, input.eligibilityResult.state)) settledRef.current = null;
156639
+ const requestView = candidate ?? settledRef.current;
156640
+ const discountUi = input.useDiscountCodeUi({
156641
+ api: input.api,
156642
+ ...discountRequest(requestView)
156643
+ });
156644
+ if (candidate && requestIsSettled(discountUi)) settledRef.current = candidate;
156645
+ return {
156646
+ discountUi,
156647
+ discountContext: settledRef.current?.discountContext ?? null,
156648
+ ticketSelectionSubtotalCents: settledRef.current?.subtotalCents ?? null,
156649
+ ticketSelectionSummaryLines: settledRef.current?.summaryLines ?? []
156650
+ };
156651
+ }
156652
+ var init_useSettledCommerceView = __esmMin((() => {
156653
+ init_registrationDerivations();
156654
+ }));
156655
+ //#endregion
156226
156656
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationWizardContext.ts
156227
156657
  function getEventSelectionDefaults(event) {
156228
156658
  const suggestedAmount = getSlidingScaleForEvent(event)?.suggestedAmount;
@@ -156385,10 +156815,6 @@ function isSoldOutWithoutWaitlist(input) {
156385
156815
  var init_registrationCompletion = __esmMin((() => {}));
156386
156816
  //#endregion
156387
156817
  //#region ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
156388
- function resolveDiscountSubtotalCents(context, subtotalCents) {
156389
- if (context?.type !== "event" || subtotalCents === null) return void 0;
156390
- return subtotalCents;
156391
- }
156392
156818
  function usesTieredPricing(event) {
156393
156819
  return event !== null && event !== void 0 ? publicEventPricingStrategy(event.pricing) === "tiered" : false;
156394
156820
  }
@@ -156831,30 +157257,15 @@ function useEventRegistrationWizardWithDeps(options, deps) {
156831
157257
  }
156832
157258
  setStep("select-tickets");
156833
157259
  };
156834
- const discountContext = useMemo(() => resolveDiscountContext({
156835
- paymentSelection,
156836
- event: currentEvent,
156837
- eventRequiresPayment,
156838
- ticketsCount
156839
- }), [
157260
+ const { discountUi, discountContext, ticketSelectionSubtotalCents, ticketSelectionSummaryLines } = useSettledCommerceView({
157261
+ api,
157262
+ useDiscountCodeUi: deps.useDiscountCodeUi,
157263
+ eligibilityResult,
157264
+ eligibility,
156840
157265
  currentEvent,
156841
157266
  eventRequiresPayment,
156842
157267
  paymentSelection,
156843
157268
  ticketsCount
156844
- ]);
156845
- const ticketSelectionSubtotalCents = eligibility?.price ?? null;
156846
- const ticketSelectionSummaryLines = useMemo(() => eligibility?.ticketLines.map((line) => ({
156847
- pricingOptionId: line.pricingOptionId,
156848
- label: line.label,
156849
- quantity: line.quantity,
156850
- unitPriceCents: line.unitPriceCents,
156851
- subtotalCents: line.subtotalCents
156852
- })) ?? [], [eligibility]);
156853
- const discountSubtotalCents = resolveDiscountSubtotalCents(discountContext, ticketSelectionSubtotalCents);
156854
- const discountUi = deps.useDiscountCodeUi({
156855
- api,
156856
- discountContext,
156857
- subtotalCents: discountSubtotalCents
156858
157269
  });
156859
157270
  const selectionMethod = paymentSelection.method;
156860
157271
  const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
@@ -157033,6 +157444,7 @@ var init_useEventRegistrationWizard = __esmMin((() => {
157033
157444
  init_useEventRegistrationStripeReturn();
157034
157445
  init_useEventRegistrationSubmit();
157035
157446
  init_useDiscountCodeUi();
157447
+ init_useSettledCommerceView();
157036
157448
  init_utils();
157037
157449
  init_ticketSelectionLines();
157038
157450
  init_registrationStateMachine();
@@ -157055,6 +157467,38 @@ var init_useEventRegistrationWizard = __esmMin((() => {
157055
157467
  };
157056
157468
  }));
157057
157469
  //#endregion
157470
+ //#region ../blocks/src/system/runtime/nodes/event-registration/useEventCheckoutHandoffRestore.ts
157471
+ function eventRegistrationReloadTarget(location) {
157472
+ return `${location.pathname}${location.search}#${EVENT_REGISTRATION_ANCHOR_ID}`;
157473
+ }
157474
+ function reloadAtEventRegistration() {
157475
+ const target = eventRegistrationReloadTarget(window.location);
157476
+ window.history.replaceState(window.history.state, "", target);
157477
+ window.location.reload();
157478
+ }
157479
+ function useEventCheckoutHandoffRestore(active) {
157480
+ useEventCheckoutHandoffRestoreWithDeps(active, browserCheckoutHandoffRestoreDeps);
157481
+ }
157482
+ function useEventCheckoutHandoffRestoreWithDeps(active, deps) {
157483
+ useEffect(() => {
157484
+ if (!active) return;
157485
+ const handlePageShow = (event) => {
157486
+ if (event.persisted) deps.reloadAtRegistration();
157487
+ };
157488
+ deps.addPageShowListener(handlePageShow);
157489
+ return () => deps.removePageShowListener(handlePageShow);
157490
+ }, [active, deps]);
157491
+ }
157492
+ var browserCheckoutHandoffRestoreDeps;
157493
+ var init_useEventCheckoutHandoffRestore = __esmMin((() => {
157494
+ init_constants();
157495
+ browserCheckoutHandoffRestoreDeps = {
157496
+ addPageShowListener: (listener) => window.addEventListener("pageshow", listener),
157497
+ removePageShowListener: (listener) => window.removeEventListener("pageshow", listener),
157498
+ reloadAtRegistration: reloadAtEventRegistration
157499
+ };
157500
+ }));
157501
+ //#endregion
157058
157502
  //#region ../blocks/src/system/runtime/nodes/shared/MagicLinkForm.state.ts
157059
157503
  function magicLinkSubmissionReducer(state, action) {
157060
157504
  switch (action.type) {
@@ -159715,6 +160159,7 @@ function EventRegistrationWizard(props) {
159715
160159
  events: events ?? [],
159716
160160
  maxTicketsNum
159717
160161
  });
160162
+ useEventCheckoutHandoffRestore(wizard.step === "redirecting");
159718
160163
  const [bookingOverlayOpen, setBookingOverlayOpen] = useState(false);
159719
160164
  const [floatingPortalRoot, setFloatingPortalRoot] = useState(null);
159720
160165
  useEffect(() => {
@@ -159847,6 +160292,7 @@ var init_EventRegistrationWizard = __esmMin((() => {
159847
160292
  init_themePortalRoot();
159848
160293
  init_buttons();
159849
160294
  init_constants();
160295
+ init_useEventCheckoutHandoffRestore();
159850
160296
  init_EventRegistrationSurface();
159851
160297
  init_EventRegistrationBookingLayer();
159852
160298
  EVENT_PORTAL_AUTH_COPY = {
@@ -160653,6 +161099,7 @@ function useEventPagination({ siteId: _siteId, initialEvents = [], fetchInitialO
160653
161099
  const eventSurface = filters?.eventSurface;
160654
161100
  const eventPresets = normalizeCsvString(filters?.eventPresets);
160655
161101
  const scheduleScope = filters?.scheduleScope;
161102
+ const seriesIds = filters?.seriesIds;
160656
161103
  const eventsRef = useRef(events);
160657
161104
  const loadingRef = useRef(loading);
160658
161105
  const hasMoreRef = useRef(hasMore);
@@ -160680,6 +161127,7 @@ function useEventPagination({ siteId: _siteId, initialEvents = [], fetchInitialO
160680
161127
  const currentEvents = eventsRef.current;
160681
161128
  const lastEvent = options.reset ? void 0 : currentEvents[currentEvents.length - 1];
160682
161129
  const newEvents = await getPublicEvents({
161130
+ seriesIds,
160683
161131
  afterStartsAt: lastEvent ? lastEvent.startsAt : void 0,
160684
161132
  afterId: lastEvent ? lastEvent.occurrenceId : void 0,
160685
161133
  limit: pageSize,
@@ -160718,6 +161166,7 @@ function useEventPagination({ siteId: _siteId, initialEvents = [], fetchInitialO
160718
161166
  eventSurface,
160719
161167
  eventPresets,
160720
161168
  scheduleScope,
161169
+ seriesIds,
160721
161170
  normalizedCategoryIds,
160722
161171
  normalizedStaffMemberId,
160723
161172
  normalizedVenueId
@@ -160727,7 +161176,7 @@ function useEventPagination({ siteId: _siteId, initialEvents = [], fetchInitialO
160727
161176
  }, [fetchPage]);
160728
161177
  const initialFetchAttemptKeyRef = useRef(null);
160729
161178
  useEffect(() => {
160730
- if (!fetchInitialOnMount) return;
161179
+ if (!fetchInitialOnMount || seriesIds === "") return;
160731
161180
  if (!filtersMatchInitial) return;
160732
161181
  if (initialEventsRef.current.length > 0) return;
160733
161182
  if (eventsRef.current.length > 0) return;
@@ -160741,7 +161190,8 @@ function useEventPagination({ siteId: _siteId, initialEvents = [], fetchInitialO
160741
161190
  fetchPage,
160742
161191
  filtersKey,
160743
161192
  filtersMatchInitial,
160744
- stage
161193
+ stage,
161194
+ seriesIds
160745
161195
  ]);
160746
161196
  const prevFiltersMatchInitialRef = useRef(filtersMatchInitial);
160747
161197
  const prevInitialEventsKeyRef = useRef(initialEventsKey);
@@ -160876,7 +161326,7 @@ var init_useEventFilters_state = __esmMin((() => {
160876
161326
  * const events = await api.getPublicEvents(params);
160877
161327
  * ```
160878
161328
  */
160879
- function useEventFilters({ showCategoryFilter = "auto", showVenueFilter = false, showStaffFilter = false, preFilterCategoryIds, preFilterStaffMemberId, preFilterVenueId, preFilterEventSurface, preFilterEventPresets, preFilterScheduleScope } = {}) {
161329
+ function useEventFilters({ showCategoryFilter = "auto", showVenueFilter = false, showStaffFilter = false, preFilterSeriesIds, preFilterCategoryIds, preFilterStaffMemberId, preFilterVenueId, preFilterEventSurface, preFilterEventPresets, preFilterScheduleScope } = {}) {
160880
161330
  const api = useBlockApi();
160881
161331
  const [loadState, dispatchLoadState] = useReducer(eventFiltersLoadReducer, void 0, createInitialEventFiltersLoadState);
160882
161332
  const filters = getEventFiltersData(loadState);
@@ -161025,6 +161475,7 @@ function useEventFilters({ showCategoryFilter = "auto", showVenueFilter = false,
161025
161475
  setSelectedVenueId("all");
161026
161476
  }, []),
161027
161477
  getFilterParams: useCallback(() => {
161478
+ if (preFilterSeriesIds != null) return { seriesIds: preFilterSeriesIds };
161028
161479
  const params = {};
161029
161480
  if (fixedEventSurface) params.eventSurface = fixedEventSurface;
161030
161481
  if (fixedEventPresets) params.eventPresets = fixedEventPresets;
@@ -161038,6 +161489,7 @@ function useEventFilters({ showCategoryFilter = "auto", showVenueFilter = false,
161038
161489
  params.staffMemberId = fixedStaffMemberId ?? (selectedStaffMemberId !== "all" ? selectedStaffMemberId : void 0);
161039
161490
  return params;
161040
161491
  }, [
161492
+ preFilterSeriesIds,
161041
161493
  allowedCategoryIds,
161042
161494
  allowedCategorySet,
161043
161495
  fixedEventPresets,
@@ -161073,25 +161525,12 @@ var init_EventListing_client = __esmMin((() => {
161073
161525
  const hydration = render.hydration;
161074
161526
  const filtersIdBase = useId();
161075
161527
  const initialListEvents = useMemo(() => [...display.events], [display.events]);
161076
- const initialListFilters = useMemo(() => buildEventRuntimeFilters({
161077
- eventSurface: hydration.eventSurface,
161078
- filterEventPresets: hydration.filterEventPresets,
161079
- scheduleScope: hydration.scheduleScope,
161080
- filterCategoryIds: hydration.filterCategoryIds,
161081
- filterStaffMemberId: hydration.filterStaffMemberId,
161082
- filterVenueId: hydration.filterVenueId
161083
- }), [
161084
- hydration.eventSurface,
161085
- hydration.filterEventPresets,
161086
- hydration.scheduleScope,
161087
- hydration.filterCategoryIds,
161088
- hydration.filterStaffMemberId,
161089
- hydration.filterVenueId
161090
- ]);
161528
+ const initialListFilters = buildEventRuntimeFilters(hydration);
161091
161529
  const { categories, venues, staffMembers, selectedCategoryId, selectedStaffMemberId, selectedVenueId, loading: filtersLoading, shouldShowCategoryFilter, shouldShowVenueFilter, shouldShowStaffFilter, hasActiveFilters, setSelectedCategoryId, setSelectedStaffMemberId, setSelectedVenueId, resetFilters, getFilterParams } = useEventFilters({
161092
161530
  showCategoryFilter: hydration.showFilters ? hydration.showCategoryFilter : "never",
161093
161531
  showVenueFilter: hydration.showFilters ? hydration.showVenueFilter : false,
161094
161532
  showStaffFilter: hydration.showFilters ? hydration.showStaffFilter : false,
161533
+ preFilterSeriesIds: hydration.seriesIds,
161095
161534
  preFilterCategoryIds: hydration.filterCategoryIds ?? void 0,
161096
161535
  preFilterStaffMemberId: hydration.filterStaffMemberId ?? void 0,
161097
161536
  preFilterVenueId: hydration.filterVenueId ?? void 0,
@@ -161908,6 +162347,7 @@ function toEventCombinedControllerProps(props) {
161908
162347
  eventSurface: props.render.display.eventSurface,
161909
162348
  filterEventPresets: props.render.display.filterEventPresets,
161910
162349
  scheduleScope: props.render.display.scheduleScope,
162350
+ seriesIds: props.render.display.seriesIds,
161911
162351
  filterCategoryIds: props.render.display.filterCategoryIds,
161912
162352
  filterStaffMemberId: props.render.display.filterStaffMemberId,
161913
162353
  filterVenueId: props.render.display.filterVenueId,
@@ -162043,7 +162483,7 @@ var init_EventCombined_client = __esmMin((() => {
162043
162483
  EventCombinedClient = ({ events: initialEvents, siteId, stage, listLayout = "stack", listColumns = "3", eventsPerPage = 12, paginationAction = {
162044
162484
  kind: "loadMore",
162045
162485
  label: "Load more events"
162046
- }, 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 }) => {
162486
+ }, 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 }) => {
162047
162487
  const hydrationReady = useHydrationReady();
162048
162488
  const fetchInitialEventsOnMount = initialEvents == null;
162049
162489
  const resolvedShowFilters = showFilters ?? true;
@@ -162069,6 +162509,7 @@ var init_EventCombined_client = __esmMin((() => {
162069
162509
  showCategoryFilter: resolvedShowFilters ? showCategoryFilter : "never",
162070
162510
  showVenueFilter: resolvedShowFilters ? resolvedShowVenueFilter : false,
162071
162511
  showStaffFilter: resolvedShowFilters ? resolvedShowStaffFilter : false,
162512
+ preFilterSeriesIds: seriesIds,
162072
162513
  preFilterCategoryIds: filterCategoryIds,
162073
162514
  preFilterStaffMemberId: filterStaffMemberId,
162074
162515
  preFilterVenueId: filterVenueId,
@@ -162076,21 +162517,15 @@ var init_EventCombined_client = __esmMin((() => {
162076
162517
  preFilterEventPresets: filterEventPresets,
162077
162518
  preFilterScheduleScope: resolvedScheduleScope
162078
162519
  });
162079
- const initialListFilters = useMemo(() => buildEventRuntimeFilters({
162520
+ const initialListFilters = buildEventRuntimeFilters({
162080
162521
  eventSurface: resolvedEventSurface,
162081
162522
  filterEventPresets,
162082
162523
  scheduleScope: resolvedScheduleScope,
162524
+ seriesIds,
162083
162525
  filterCategoryIds,
162084
162526
  filterStaffMemberId,
162085
162527
  filterVenueId
162086
- }), [
162087
- resolvedEventSurface,
162088
- filterCategoryIds,
162089
- filterEventPresets,
162090
- filterStaffMemberId,
162091
- filterVenueId,
162092
- resolvedScheduleScope
162093
- ]);
162528
+ });
162094
162529
  const listFilters = useMemo(() => getFilterParams(), [getFilterParams]);
162095
162530
  const pageSize = eventsPerPage;
162096
162531
  const { events: paginatedEvents, loading: eventsLoading, error: eventsError, hasMore, loadMore } = useEventPagination({
@@ -162359,6 +162794,7 @@ function useEventCalendarFilterState(display) {
162359
162794
  showCategoryFilter: display.showFilters ? display.showCategoryFilter : "never",
162360
162795
  showVenueFilter: display.showFilters ? display.showVenueFilter : false,
162361
162796
  showStaffFilter: display.showFilters ? display.showStaffFilter : false,
162797
+ preFilterSeriesIds: display.seriesIds,
162362
162798
  preFilterCategoryIds: display.filterCategoryIds,
162363
162799
  preFilterStaffMemberId: display.filterStaffMemberId,
162364
162800
  preFilterVenueId: display.filterVenueId,
@@ -162392,6 +162828,7 @@ function buildDisplayFilterParams(display) {
162392
162828
  eventSurface: display.eventSurface,
162393
162829
  filterEventPresets: display.filterEventPresets,
162394
162830
  scheduleScope: display.scheduleScope,
162831
+ seriesIds: display.seriesIds,
162395
162832
  filterCategoryIds: display.filterCategoryIds,
162396
162833
  filterStaffMemberId: display.filterStaffMemberId,
162397
162834
  filterVenueId: display.filterVenueId
@@ -162438,6 +162875,7 @@ var init_EventCalendar_client = __esmMin((() => {
162438
162875
  eventSurface: display.eventSurface,
162439
162876
  filterEventPresets: display.filterEventPresets,
162440
162877
  scheduleScope: display.scheduleScope,
162878
+ seriesIds: display.seriesIds,
162441
162879
  filterCategoryIds: display.filterCategoryIds,
162442
162880
  filterStaffMemberId: display.filterStaffMemberId,
162443
162881
  filterVenueId: display.filterVenueId,
@@ -162461,6 +162899,7 @@ var init_EventCalendar_client = __esmMin((() => {
162461
162899
  const { display, hydration } = render;
162462
162900
  const filters = useMemo(() => buildDisplayFilterParams(display), [
162463
162901
  display.eventSurface,
162902
+ display.seriesIds,
162464
162903
  display.filterCategoryIds,
162465
162904
  display.filterEventPresets,
162466
162905
  display.filterStaffMemberId,
@@ -164537,7 +164976,7 @@ function NewsletterFormClient({ render }) {
164537
164976
  if (submitTarget.tag === "unavailable") {
164538
164977
  dispatchSubmission({
164539
164978
  type: "failed",
164540
- error: newsletterFormError("Newsletter list is not configured")
164979
+ error: newsletterFormError(SIGNUPS_PAUSED_MESSAGE)
164541
164980
  });
164542
164981
  return;
164543
164982
  }
@@ -164548,14 +164987,16 @@ function NewsletterFormClient({ render }) {
164548
164987
  });
164549
164988
  return;
164550
164989
  }
164551
- const visitorSelection = readVisitorSelection(formData, render.hydration);
164552
- if (visitorSelection === null) {
164990
+ const selection = readVisitorSelection(formData, render.hydration);
164991
+ const selectionError = visitorSelectionError(selection);
164992
+ if (selectionError) {
164553
164993
  dispatchSubmission({
164554
164994
  type: "failed",
164555
- error: newsletterFieldError(TOPIC_CHOICE_FIELD_ID, "Choose at least one email topic.")
164995
+ error: selectionError
164556
164996
  });
164557
164997
  return;
164558
164998
  }
164999
+ const visitorSelection = selection.tag === "chosen" ? selection.value : void 0;
164559
165000
  dispatchSubmission({ type: "submitted" });
164560
165001
  try {
164561
165002
  const result = await api.subscribeNewsletter({
@@ -164749,10 +165190,18 @@ function transportFailureMessage(err) {
164749
165190
  }
164750
165191
  return RETRY_SHORTLY_MESSAGE;
164751
165192
  }
165193
+ function visitorSelectionError(selection) {
165194
+ switch (selection.tag) {
165195
+ case "nothing_chosen": return newsletterFieldError(TOPIC_CHOICE_FIELD_ID, "Choose at least one email topic.");
165196
+ case "unusable": return newsletterFormError(SIGNUPS_PAUSED_MESSAGE);
165197
+ case "not_offered":
165198
+ case "chosen": return null;
165199
+ }
165200
+ }
164752
165201
  function readVisitorSelection(formData, hydration) {
164753
- if (hydration.choicePresentation !== "visitor_choice") return void 0;
165202
+ if (hydration.choicePresentation !== "visitor_choice") return { tag: "not_offered" };
164754
165203
  const ids = formData.getAll(TOPIC_CHOICE_FIELD_ID).flatMap((value) => typeof value === "string" ? [value] : []);
164755
- if (ids.length === 0) return null;
165204
+ if (ids.length === 0) return { tag: "nothing_chosen" };
164756
165205
  const raw = hydration.choiceProvider === "native" ? {
164757
165206
  provider: "native",
164758
165207
  topicIds: ids
@@ -164763,9 +165212,12 @@ function readVisitorSelection(formData, hydration) {
164763
165212
  provider: "mailchimp",
164764
165213
  interestIds: ids
164765
165214
  } : null;
164766
- if (raw === null) return null;
165215
+ if (raw === null) return { tag: "unusable" };
164767
165216
  const parsed = parseMailingListVisitorSelection(raw);
164768
- return parsed.ok ? parsed.value : null;
165217
+ return parsed.ok ? {
165218
+ tag: "chosen",
165219
+ value: parsed.value
165220
+ } : { tag: "unusable" };
164769
165221
  }
164770
165222
  function publicSignupError(outcome) {
164771
165223
  switch (outcome.tag) {
@@ -165091,9 +165543,20 @@ function BlocksIslandsHydrator(props = {}) {
165091
165543
  }
165092
165544
  //#endregion
165093
165545
  //#region ../theme-core/src/hosted-booking-appearance.ts
165546
+ init_schema$2();
165094
165547
  init_colors();
165095
165548
  init_expandPalette();
165096
165549
  init_tokens();
165550
+ init_modern_minimal();
165551
+ z$1.object({
165552
+ palette: paletteColorsSchema,
165553
+ paletteMode: paletteModeSchema,
165554
+ typography: z$1.object({
165555
+ headingFamily: z$1.string().trim().min(1),
165556
+ bodyFamily: z$1.string().trim().min(1)
165557
+ }).strict(),
165558
+ corners
165559
+ }).strict();
165097
165560
  //#endregion
165098
165561
  //#region ../theme-core/src/index.ts
165099
165562
  init_schema$2();
@@ -165459,7 +165922,7 @@ var SimpleCache = class {
165459
165922
  * 1. This constant
165460
165923
  * 2. The "version" field in package.json
165461
165924
  */
165462
- const SDK_VERSION = "0.140.0";
165925
+ const SDK_VERSION = "0.141.0";
165463
165926
  //#endregion
165464
165927
  //#region src/client/error.ts
165465
165928
  let _Symbol$for;