@riverbankcms/sdk 0.72.0 → 0.75.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 (146) hide show
  1. package/README.md +1 -1
  2. package/dist/{PreviewEditorSidebar-44T64SAR.mjs → PreviewEditorSidebar-U2IHCBYN.mjs} +3 -3
  3. package/dist/{PreviewEditorUI-4WKHZTXW.mjs → PreviewEditorUI-ZGH2RQNP.mjs} +3 -3
  4. package/dist/SdkPreviewModeRuntime-MTUGBTLQ.mjs +8 -0
  5. package/dist/_dts/ai/src/contracts/proposals.d.ts +10 -10
  6. package/dist/_dts/api/src/cache-tags.d.ts +22 -0
  7. package/dist/_dts/api/src/contentRuntime.d.ts +1 -0
  8. package/dist/_dts/api/src/endpoints.d.ts +24 -24
  9. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +2 -1
  10. package/dist/_dts/block-form/src/blockDraftSaveability.d.ts +4 -1
  11. package/dist/_dts/blocks/src/client/booking-form.d.ts +2 -0
  12. package/dist/_dts/blocks/src/client/carousel.d.ts +1 -0
  13. package/dist/_dts/blocks/src/client/course-registration.d.ts +2 -0
  14. package/dist/_dts/blocks/src/client/events.d.ts +4 -0
  15. package/dist/_dts/blocks/src/client/form.d.ts +2 -0
  16. package/dist/_dts/blocks/src/client/header.d.ts +1 -0
  17. package/dist/_dts/blocks/src/client/location-map.d.ts +1 -0
  18. package/dist/_dts/blocks/src/client/newsletter-form.d.ts +2 -0
  19. package/dist/_dts/blocks/src/client/shop.d.ts +6 -0
  20. package/dist/_dts/blocks/src/lib/video.d.ts +2 -0
  21. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +21 -1
  22. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +6 -6
  23. package/dist/_dts/blocks/src/system/node/fragments/backgroundLayer.d.ts +15 -1
  24. package/dist/_dts/blocks/src/system/node/fragments/styledSection.d.ts +11 -0
  25. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +1 -0
  26. package/dist/_dts/blocks/src/system/runtime/header/enhanceHeaderSection.d.ts +13 -0
  27. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +3 -2
  28. package/dist/_dts/blocks/src/system/runtime/nodes/events/index.d.ts +3 -0
  29. package/dist/_dts/blocks/src/system/runtime/nodes/header-section.client.d.ts +1 -0
  30. package/dist/_dts/blocks/src/system/runtime/nodes/header-section.server.d.ts +1 -0
  31. package/dist/_dts/blocks/src/system/runtime/nodes/media.d.ts +6 -0
  32. package/dist/_dts/content-editor/src/hooks/validateBlocksForPublish.d.ts +5 -0
  33. package/dist/_dts/preview-next/src/client/preview/SiteChromeEditableSurface.d.ts +12 -2
  34. package/dist/_dts/sdk/src/public-api/contracts.d.ts +1 -0
  35. package/dist/_dts/sdk/src/rendering/components/Layout.d.ts +2 -2
  36. package/dist/_dts/sdk/src/rendering/islands/deferredVideoEmbeds.d.ts +2 -0
  37. package/dist/_dts/sdk/src/rendering/islands/enhancers/accordion.d.ts +1 -0
  38. package/dist/_dts/sdk/src/rendering/islands/enhancers/bookingForm.d.ts +1 -0
  39. package/dist/_dts/sdk/src/rendering/islands/enhancers/carousel.d.ts +1 -0
  40. package/dist/_dts/sdk/src/rendering/islands/enhancers/cart.d.ts +1 -0
  41. package/dist/_dts/sdk/src/rendering/islands/enhancers/checkout.d.ts +1 -0
  42. package/dist/_dts/sdk/src/rendering/islands/enhancers/courseRegistration.d.ts +1 -0
  43. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventCalendar.d.ts +1 -0
  44. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventCombined.d.ts +1 -0
  45. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventDetails.d.ts +1 -0
  46. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventListing.d.ts +1 -0
  47. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventRegistration.d.ts +1 -0
  48. package/dist/_dts/sdk/src/rendering/islands/enhancers/form.d.ts +1 -0
  49. package/dist/_dts/sdk/src/rendering/islands/enhancers/headerSection.d.ts +1 -0
  50. package/dist/_dts/sdk/src/rendering/islands/enhancers/locationMap.d.ts +1 -0
  51. package/dist/_dts/sdk/src/rendering/islands/enhancers/newsletterForm.d.ts +1 -0
  52. package/dist/_dts/sdk/src/rendering/islands/enhancers/productDetail.d.ts +1 -0
  53. package/dist/_dts/sdk/src/rendering/islands/enhancers/productList.d.ts +1 -0
  54. package/dist/_dts/sdk/src/rendering/islands/enhancers/shop.d.ts +1 -0
  55. package/dist/_dts/sdk/src/rendering/islands/hydrateBlocksIslands.d.ts +2 -2
  56. package/dist/_dts/sdk/src/rendering/islands/propsDecoder.d.ts +7 -0
  57. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +9 -0
  58. package/dist/_dts/sdk/src/rendering/server.d.ts +3 -0
  59. package/dist/_dts/sdk/src/version.d.ts +1 -1
  60. package/dist/_dts/theme-core/src/accordions/types.d.ts +3 -3
  61. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +7 -7
  62. package/dist/_dts/theme-core/src/buttons/types.d.ts +20 -20
  63. package/dist/_dts/theme-core/src/cards/types.d.ts +2 -2
  64. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  65. package/dist/_dts/theme-core/src/header/navDropdownSizing.d.ts +7 -0
  66. package/dist/_dts/theme-core/src/inputs/types.d.ts +3 -3
  67. package/dist/_dts/theme-core/src/interactive/baseSchema.d.ts +1 -1
  68. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +156 -156
  69. package/dist/_dts/theme-core/src/navigation/types.d.ts +1 -1
  70. package/dist/_dts/theme-core/src/palette/variants/types.d.ts +4 -4
  71. package/dist/_dts/theme-core/src/schema.d.ts +178 -178
  72. package/dist/_dts/theme-core/src/shared/componentStyles.d.ts +2 -2
  73. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +8 -8
  74. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +5 -5
  75. package/dist/_dts/theme-core/src/tokens/themeColorTokens.d.ts +2 -2
  76. package/dist/{chunk-G4NLITC2.mjs → chunk-BGMNDF6T.mjs} +7 -7
  77. package/dist/{chunk-3YNCQG5N.mjs → chunk-GFE74WRD.mjs} +457 -98
  78. package/dist/{chunk-HV745JYE.mjs → chunk-RWXQBRQZ.mjs} +1 -1
  79. package/dist/{chunk-7RX72SK2.mjs → chunk-VX7B5VAC.mjs} +36 -25
  80. package/dist/{chunk-YRJKZEQ3.mjs → chunk-Z7JLNTJR.mjs} +1 -1
  81. package/dist/{chunk-KWQPAJYS.mjs → chunk-ZSHFGFUG.mjs} +2 -2
  82. package/dist/cli/index.mjs +3498 -3826
  83. package/dist/client/accordion-T2UD2ZTH.mjs +120 -0
  84. package/dist/client/altcha-LIGLPZS5.mjs +2755 -0
  85. package/dist/client/bookingForm-GUP75FKN.mjs +3022 -0
  86. package/dist/client/bookings.mjs +32 -10
  87. package/dist/client/carousel-2NQA6V57.mjs +47 -0
  88. package/dist/client/cart-5TFIAFDS.mjs +18 -0
  89. package/dist/client/checkout-TP4WAHZE.mjs +18 -0
  90. package/dist/client/chunk-2PHQZ666.mjs +383 -0
  91. package/dist/client/chunk-3DCJ45Z2.mjs +36 -0
  92. package/dist/client/chunk-3PEDD5KJ.mjs +146 -0
  93. package/dist/client/chunk-CY2ZTSE5.mjs +204 -0
  94. package/dist/client/chunk-F7LHOKEH.mjs +146 -0
  95. package/dist/client/chunk-FU2QRZMX.mjs +7617 -0
  96. package/dist/client/chunk-I2MMZO53.mjs +6 -0
  97. package/dist/client/chunk-II7O4XN3.mjs +2206 -0
  98. package/dist/client/chunk-M3L3KYYR.mjs +1181 -0
  99. package/dist/client/chunk-N7PBWBWQ.mjs +26 -0
  100. package/dist/client/chunk-NWOUL6JY.mjs +1378 -0
  101. package/dist/client/chunk-OJPZEZU2.mjs +31 -0
  102. package/dist/client/chunk-PMAIXMAB.mjs +1960 -0
  103. package/dist/client/chunk-RTZ3JKKX.mjs +178 -0
  104. package/dist/client/chunk-TQ5MSPDX.mjs +74 -0
  105. package/dist/client/chunk-VUAOE3AG.mjs +5592 -0
  106. package/dist/client/chunk-WJXXNDSE.mjs +245 -0
  107. package/dist/client/chunk-YLMKMCSJ.mjs +86 -0
  108. package/dist/client/chunk-ZLMS67RR.mjs +106 -0
  109. package/dist/client/client.mjs +51865 -52071
  110. package/dist/client/courseRegistration-5DPU6PDY.mjs +1737 -0
  111. package/dist/client/eventCalendar-F3GZGTEF.mjs +40 -0
  112. package/dist/client/eventCombined-BQOB6QMY.mjs +37 -0
  113. package/dist/client/eventDetails-PEM2EJWE.mjs +25 -0
  114. package/dist/client/eventListing-YMIQPVME.mjs +40 -0
  115. package/dist/client/eventRegistration-4I6ZNDUF.mjs +40 -0
  116. package/dist/client/form-ZJVAYZ6G.mjs +300 -0
  117. package/dist/client/headerSection-TOT5MGTF.mjs +729 -0
  118. package/dist/client/hooks.mjs +91 -42
  119. package/dist/client/locationMap-J66NZREU.mjs +227 -0
  120. package/dist/client/newsletterForm-ET2XUMRO.mjs +208 -0
  121. package/dist/client/productDetail-C2XIH7C5.mjs +18 -0
  122. package/dist/client/productList-T2AZLFTP.mjs +18 -0
  123. package/dist/client/rendering/client.mjs +12796 -18295
  124. package/dist/client/rendering/islands.mjs +108 -44022
  125. package/dist/client/rendering.mjs +45141 -45346
  126. package/dist/client/shop-UZ6IUZXD.mjs +20 -0
  127. package/dist/preview-next/before-render.mjs +37 -25
  128. package/dist/preview-next/client/runtime.mjs +5 -5
  129. package/dist/preview-next/middleware.mjs +37 -25
  130. package/dist/{sdk-runtime-NGDWSWOS.mjs → sdk-runtime-JCUQM63Y.mjs} +6 -6
  131. package/dist/server/components.mjs +472 -276
  132. package/dist/server/config-validation.mjs +91 -42
  133. package/dist/server/config.mjs +91 -42
  134. package/dist/server/data.mjs +91 -42
  135. package/dist/server/index.mjs +45 -33
  136. package/dist/server/next.mjs +468 -272
  137. package/dist/server/page-converter.mjs +41 -17
  138. package/dist/server/prebuild.mjs +1 -1
  139. package/dist/server/rendering/server.mjs +556 -275
  140. package/dist/server/rendering.mjs +474 -278
  141. package/dist/server/routing.mjs +99 -43
  142. package/dist/server/server.mjs +92 -43
  143. package/dist/server/theme-bridge.mjs +29 -0
  144. package/dist/styles/index.css +16 -0
  145. package/package.json +2 -1
  146. package/dist/SdkPreviewModeRuntime-FO6V7YVY.mjs +0 -8
@@ -7042,6 +7042,7 @@ function clearBookingFieldError(errors, fieldId) {
7042
7042
  function createInitialBookingFlowReducerState(input) {
7043
7043
  const initialData = input.initialData ?? {};
7044
7044
  return {
7045
+ phase: "editing",
7045
7046
  currentStepId: "service-selection",
7046
7047
  selectedServiceId: toOptionalAppointmentServiceId(
7047
7048
  toOptionalString(initialData.serviceId) ?? input.defaultServiceId
@@ -7062,8 +7063,7 @@ function createInitialBookingFlowReducerState(input) {
7062
7063
  ),
7063
7064
  altchaSolution: null,
7064
7065
  validationErrors: createEmptyBookingValidationErrors(),
7065
- feedback: { kind: "none" },
7066
- isSubmitting: false
7066
+ feedback: { kind: "none" }
7067
7067
  };
7068
7068
  }
7069
7069
  function collectInitialFieldValues(initialData) {
@@ -7193,8 +7193,15 @@ function bookingFlowReducer(state, event) {
7193
7193
  case "validation-errors-set":
7194
7194
  return { ...state, validationErrors: event.errors };
7195
7195
  case "feedback-set":
7196
- return { ...state, feedback: event.feedback };
7196
+ return {
7197
+ ...state,
7198
+ phase: event.feedback.kind === "success" ? "completed" : "editing",
7199
+ feedback: event.feedback
7200
+ };
7197
7201
  case "availability-selection-invalidated":
7202
+ if (state.phase !== "editing") {
7203
+ return state;
7204
+ }
7198
7205
  return {
7199
7206
  ...state,
7200
7207
  currentStepId: "datetime-selection",
@@ -7208,11 +7215,11 @@ function bookingFlowReducer(state, event) {
7208
7215
  validationErrors: clearBookingFormError(state.validationErrors)
7209
7216
  };
7210
7217
  case "feedback-cleared":
7211
- return { ...state, feedback: { kind: "none" } };
7218
+ return { ...state, phase: "editing", feedback: { kind: "none" } };
7212
7219
  case "submission-started":
7213
- return { ...state, isSubmitting: true };
7220
+ return { ...state, phase: "submitting" };
7214
7221
  case "submission-finished":
7215
- return { ...state, isSubmitting: false };
7222
+ return state.phase === "submitting" ? { ...state, phase: "editing" } : state;
7216
7223
  case "reset":
7217
7224
  return event.initial;
7218
7225
  default:
@@ -7718,8 +7725,8 @@ function toHeadlessEligibleAppointmentPackage(appointmentPackage) {
7718
7725
  };
7719
7726
  }
7720
7727
  function resolveHeadlessBookingStatus(input) {
7721
- if (input.isSubmitting) return { tag: "submitting" };
7722
- if (input.feedback.kind === "success") {
7728
+ if (input.phase === "submitting") return { tag: "submitting" };
7729
+ if (input.phase === "completed" && input.feedback.kind === "success") {
7723
7730
  return {
7724
7731
  tag: "success",
7725
7732
  resourceName: input.feedback.resourceName
@@ -7901,6 +7908,7 @@ function useHeadlessBookingFlow(options) {
7901
7908
  [availableDates]
7902
7909
  );
7903
7910
  useEffect6(() => {
7911
+ if (state.phase !== "editing") return;
7904
7912
  const canEvaluateDate = availabilityDatesQuery.ok && Boolean(availableDatesLoadedRange) && !isLoadingDates && !datesError;
7905
7913
  const canEvaluateSlot = !state.selectedSlot || availabilitySlotsQuery.ok && hasLoadedSlots && !isLoadingSlots && !slotsError;
7906
7914
  if (!canEvaluateDate || !canEvaluateSlot) return;
@@ -7926,6 +7934,7 @@ function useHeadlessBookingFlow(options) {
7926
7934
  isLoadingSlots,
7927
7935
  slotViews,
7928
7936
  slotsError,
7937
+ state.phase,
7929
7938
  state.selectedDate,
7930
7939
  state.selectedSlot
7931
7940
  ]);
@@ -8086,7 +8095,7 @@ function useHeadlessBookingFlow(options) {
8086
8095
  const submitBooking = useCallback3(
8087
8096
  async (submitOptions) => {
8088
8097
  const latest = latestRef.current;
8089
- if (submittingRef.current || latest.state.isSubmitting) {
8098
+ if (submittingRef.current || latest.state.phase === "submitting") {
8090
8099
  return {
8091
8100
  ok: false,
8092
8101
  reason: "blocked",
@@ -8282,7 +8291,7 @@ function useHeadlessBookingFlow(options) {
8282
8291
  const spamProtectionEnabled = options.spamProtectionEnabled ?? isSpamProtectionEnabled();
8283
8292
  const status = resolveHeadlessBookingStatus({
8284
8293
  feedback: state.feedback,
8285
- isSubmitting: state.isSubmitting
8294
+ phase: state.phase
8286
8295
  });
8287
8296
  const view = resolveHeadlessBookingView({
8288
8297
  form: options.form,
@@ -9690,6 +9699,19 @@ var BookingFormClient = ({
9690
9699
  ] });
9691
9700
  };
9692
9701
 
9702
+ // ../theme-core/src/header/navDropdownSizing.ts
9703
+ var NAV_DROPDOWN_MIN_WIDTH_REM = 12;
9704
+ var NAV_DROPDOWN_MAX_WIDTH_REM = 22;
9705
+ var NAV_DROPDOWN_VIEWPORT_GUTTER_REM = 1;
9706
+ var NAV_DROPDOWN_SHIFT_PROPERTY = "--nav-dropdown-shift-x";
9707
+ var NAV_DROPDOWN_MAX_WIDTH_CSS = `min(${NAV_DROPDOWN_MAX_WIDTH_REM}rem, calc(100vw - ${NAV_DROPDOWN_VIEWPORT_GUTTER_REM * 2}rem))`;
9708
+ var NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
9709
+ `min-width: ${NAV_DROPDOWN_MIN_WIDTH_REM}rem;`,
9710
+ `width: max-content;`,
9711
+ `max-width: ${NAV_DROPDOWN_MAX_WIDTH_CSS};`,
9712
+ `transform: translateX(var(${NAV_DROPDOWN_SHIFT_PROPERTY}, 0px));`
9713
+ ];
9714
+
9693
9715
  // ../theme-core/src/ClientThemeScope.tsx
9694
9716
  import { useMemo as useMemo4 } from "react";
9695
9717
 
@@ -0,0 +1,47 @@
1
+ import { normalizeCarouselProps, CarouselNodeClient } from './chunk-II7O4XN3.mjs';
2
+ import './chunk-RTZ3JKKX.mjs';
3
+ import { mountReactIsland } from './chunk-N7PBWBWQ.mjs';
4
+ import { defineIslandPropsDecoder } from './chunk-FU2QRZMX.mjs';
5
+ import './chunk-PMAIXMAB.mjs';
6
+ import { jsx } from 'react/jsx-runtime';
7
+
8
+ var decode = defineIslandPropsDecoder("carousel");
9
+ function extractSlides(root) {
10
+ const scrollContainer = root.querySelector(
11
+ ".rb-overflow-x-auto, .overflow-x-auto"
12
+ );
13
+ const track = scrollContainer?.querySelector(".rb-flex, .flex");
14
+ if (!track) return [];
15
+ const slideElements = Array.from(track.children).filter(
16
+ (el) => el instanceof HTMLElement
17
+ );
18
+ return slideElements.map((el) => ({
19
+ html: el.innerHTML
20
+ }));
21
+ }
22
+ var enhance = (root, props) => {
23
+ if (root.dataset.rbReactMounted === "true") return;
24
+ const extractedSlides = extractSlides(root);
25
+ const parsedProps = normalizeCarouselProps(props);
26
+ return mountReactIsland(root, ({ root: reactRoot }) => {
27
+ reactRoot.render(
28
+ /* @__PURE__ */ jsx(
29
+ CarouselNodeClient,
30
+ {
31
+ renderRoot: false,
32
+ slidesToShow: parsedProps.slidesToShow,
33
+ transition: parsedProps.transition,
34
+ showControls: parsedProps.showControls,
35
+ showDots: parsedProps.showDots,
36
+ arrowVisibility: parsedProps.arrowVisibility,
37
+ autoplay: parsedProps.autoplay,
38
+ autoplayDelay: parsedProps.autoplayDelay,
39
+ loop: parsedProps.loop,
40
+ children: extractedSlides.map((slide, index) => /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: slide.html } }, index))
41
+ }
42
+ )
43
+ );
44
+ });
45
+ };
46
+
47
+ export { decode, enhance };
@@ -0,0 +1,18 @@
1
+ import { mountShopBlockIsland, CartClient } from './chunk-NWOUL6JY.mjs';
2
+ import './chunk-ZLMS67RR.mjs';
3
+ import './chunk-II7O4XN3.mjs';
4
+ import './chunk-I2MMZO53.mjs';
5
+ import './chunk-RTZ3JKKX.mjs';
6
+ import './chunk-2PHQZ666.mjs';
7
+ import './chunk-3DCJ45Z2.mjs';
8
+ import './chunk-3PEDD5KJ.mjs';
9
+ import './chunk-M3L3KYYR.mjs';
10
+ import './chunk-N7PBWBWQ.mjs';
11
+ import { defineIslandPropsDecoder } from './chunk-FU2QRZMX.mjs';
12
+ import './chunk-PMAIXMAB.mjs';
13
+
14
+ // src/rendering/islands/enhancers/cart.tsx
15
+ var decode = defineIslandPropsDecoder("cart");
16
+ var enhance = (root, props) => mountShopBlockIsland(root, props, CartClient, "cart");
17
+
18
+ export { decode, enhance };
@@ -0,0 +1,18 @@
1
+ import { mountShopBlockIsland, CheckoutClient } from './chunk-NWOUL6JY.mjs';
2
+ import './chunk-ZLMS67RR.mjs';
3
+ import './chunk-II7O4XN3.mjs';
4
+ import './chunk-I2MMZO53.mjs';
5
+ import './chunk-RTZ3JKKX.mjs';
6
+ import './chunk-2PHQZ666.mjs';
7
+ import './chunk-3DCJ45Z2.mjs';
8
+ import './chunk-3PEDD5KJ.mjs';
9
+ import './chunk-M3L3KYYR.mjs';
10
+ import './chunk-N7PBWBWQ.mjs';
11
+ import { defineIslandPropsDecoder } from './chunk-FU2QRZMX.mjs';
12
+ import './chunk-PMAIXMAB.mjs';
13
+
14
+ // src/rendering/islands/enhancers/checkout.tsx
15
+ var decode = defineIslandPropsDecoder("checkout");
16
+ var enhance = (root, props) => mountShopBlockIsland(root, props, CheckoutClient, "checkout");
17
+
18
+ export { decode, enhance };
@@ -0,0 +1,383 @@
1
+ import { FeedbackMessage } from './chunk-M3L3KYYR.mjs';
2
+ import { clsx_default } from './chunk-PMAIXMAB.mjs';
3
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
+
5
+ // ../blocks/src/system/runtime/shared/utils/checkoutUrls.ts
6
+ function buildCheckoutReturnUrls(paramName, anchorId) {
7
+ const currentUrl = new URL(window.location.href);
8
+ const hash = `#${anchorId}`;
9
+ const successParams = new URLSearchParams(currentUrl.search);
10
+ successParams.set(paramName, "success");
11
+ const successUrl = `${currentUrl.origin}${currentUrl.pathname}?${successParams.toString()}${hash}`;
12
+ const cancelParams = new URLSearchParams(currentUrl.search);
13
+ cancelParams.set(paramName, "cancelled");
14
+ const cancelUrl = `${currentUrl.origin}${currentUrl.pathname}?${cancelParams.toString()}${hash}`;
15
+ return { successUrl, cancelUrl };
16
+ }
17
+
18
+ // ../blocks/src/system/runtime/shared/utils/scrollToBlock.ts
19
+ function scrollToBlock(anchorId) {
20
+ requestAnimationFrame(() => {
21
+ document.getElementById(anchorId)?.scrollIntoView({ behavior: "smooth", block: "start" });
22
+ });
23
+ }
24
+
25
+ // ../blocks/src/system/runtime/shared/utils/themePortalRoot.ts
26
+ function copyDataAttributes(from, to) {
27
+ for (const name of from.getAttributeNames()) {
28
+ if (!name.startsWith("data-")) continue;
29
+ const value = from.getAttribute(name);
30
+ if (value === null) continue;
31
+ to.setAttribute(name, value);
32
+ }
33
+ }
34
+ function createBodyThemePortalRoot(sourceEl) {
35
+ if (typeof document === "undefined") return null;
36
+ const scope = sourceEl.closest(".theme-scope");
37
+ if (!scope) return null;
38
+ const root = document.createElement("div");
39
+ root.className = "theme-scope rb-theme-portal-root";
40
+ root.style.cssText = scope.style.cssText;
41
+ copyDataAttributes(scope, root);
42
+ const responsiveMode = scope.getAttribute("data-rb-responsive-mode");
43
+ if (responsiveMode) {
44
+ root.setAttribute("data-rb-responsive-mode", responsiveMode);
45
+ }
46
+ document.body.appendChild(root);
47
+ return {
48
+ root,
49
+ cleanup: () => {
50
+ root.remove();
51
+ }
52
+ };
53
+ }
54
+
55
+ // ../blocks/src/system/runtime/shared/utils/urlParams.ts
56
+ function consumeSearchParam(paramName) {
57
+ const url = new URL(window.location.href);
58
+ const value = url.searchParams.get(paramName);
59
+ if (value === null) return null;
60
+ url.searchParams.delete(paramName);
61
+ const newUrl = url.pathname + (url.search ? url.search : "") + url.hash;
62
+ window.history.replaceState({}, "", newUrl);
63
+ return value;
64
+ }
65
+ function consumeSearchParams(paramNames) {
66
+ const url = new URL(window.location.href);
67
+ const values = Object.fromEntries(
68
+ paramNames.map((name) => [name, url.searchParams.get(name)])
69
+ );
70
+ let changed = false;
71
+ for (const name of paramNames) {
72
+ if (url.searchParams.has(name)) {
73
+ url.searchParams.delete(name);
74
+ changed = true;
75
+ }
76
+ }
77
+ if (changed) {
78
+ const newUrl = url.pathname + (url.search ? url.search : "") + url.hash;
79
+ window.history.replaceState({}, "", newUrl);
80
+ }
81
+ return values;
82
+ }
83
+
84
+ // ../blocks/src/system/runtime/shared/types.ts
85
+ var DEFAULT_CURRENCY = "GBP";
86
+
87
+ // ../blocks/src/system/runtime/shared/utils/formatting.ts
88
+ function formatPrice(cents, currency = DEFAULT_CURRENCY, locale) {
89
+ return new Intl.NumberFormat(locale, {
90
+ style: "currency",
91
+ currency: currency.toUpperCase()
92
+ }).format(cents / 100);
93
+ }
94
+
95
+ // ../blocks/src/system/runtime/shared/utils/portalLogout.ts
96
+ function logoutPortal(anchorId) {
97
+ const form = document.createElement("form");
98
+ form.method = "POST";
99
+ form.action = "/api/portal/logout";
100
+ const redirectInput = document.createElement("input");
101
+ redirectInput.type = "hidden";
102
+ redirectInput.name = "redirect_to";
103
+ redirectInput.value = `${window.location.pathname}#${anchorId}`;
104
+ form.appendChild(redirectInput);
105
+ document.body.appendChild(form);
106
+ form.submit();
107
+ }
108
+
109
+ // ../blocks/src/system/runtime/shared/utils/validation.ts
110
+ var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
111
+ function validateFormData(data) {
112
+ const errors = {};
113
+ if (!data.name.trim()) {
114
+ errors.name = "Name is required";
115
+ }
116
+ if (!data.email.trim()) {
117
+ errors.email = "Email is required";
118
+ } else if (!EMAIL_REGEX.test(data.email.trim())) {
119
+ errors.email = "Please enter a valid email";
120
+ }
121
+ return errors;
122
+ }
123
+
124
+ // ../blocks/src/system/runtime/shared/utils/wizardSteps.ts
125
+ function getStepNumber(step, wizardSteps) {
126
+ const index = wizardSteps.indexOf(step);
127
+ return index >= 0 ? index + 1 : 1;
128
+ }
129
+ function CheckIcon({ className, strokeWidth = 2 }) {
130
+ return /* @__PURE__ */ jsx(
131
+ "svg",
132
+ {
133
+ fill: "none",
134
+ strokeLinecap: "round",
135
+ strokeLinejoin: "round",
136
+ strokeWidth,
137
+ viewBox: "0 0 24 24",
138
+ stroke: "currentColor",
139
+ className,
140
+ width: "1em",
141
+ height: "1em",
142
+ "aria-hidden": "true",
143
+ children: /* @__PURE__ */ jsx("path", { d: "M5 13l4 4L19 7" })
144
+ }
145
+ );
146
+ }
147
+ function CrossIcon({ className, strokeWidth = 2 }) {
148
+ return /* @__PURE__ */ jsx(
149
+ "svg",
150
+ {
151
+ fill: "none",
152
+ strokeLinecap: "round",
153
+ strokeLinejoin: "round",
154
+ strokeWidth,
155
+ viewBox: "0 0 24 24",
156
+ stroke: "currentColor",
157
+ className,
158
+ width: "1em",
159
+ height: "1em",
160
+ "aria-hidden": "true",
161
+ children: /* @__PURE__ */ jsx("path", { d: "M6 18L18 6M6 6l12 12" })
162
+ }
163
+ );
164
+ }
165
+ var alignmentClasses = {
166
+ start: "rb-justify-start",
167
+ end: "rb-justify-end",
168
+ between: "rb-justify-between"
169
+ };
170
+ function joinClasses(...parts) {
171
+ return parts.filter((part) => typeof part === "string" && part.length > 0).join(" ");
172
+ }
173
+ function ActionRow({
174
+ children,
175
+ className,
176
+ align = "start"
177
+ }) {
178
+ return /* @__PURE__ */ jsx(
179
+ "div",
180
+ {
181
+ className: joinClasses("rb-flex rb-flex-wrap rb-items-center rb-gap-2", alignmentClasses[align], className),
182
+ "data-action-row": true,
183
+ children
184
+ }
185
+ );
186
+ }
187
+ function StateIcon({ variant, children }) {
188
+ return /* @__PURE__ */ jsx("div", { className: `rb-state-icon rb-state-icon--${variant}`, "aria-hidden": "true", children });
189
+ }
190
+ function joinClasses2(...parts) {
191
+ return parts.filter((part) => typeof part === "string" && part.length > 0).join(" ");
192
+ }
193
+ function TerminalPanel({
194
+ tone,
195
+ title,
196
+ titleAs: Title = "h3",
197
+ body,
198
+ secondaryBody,
199
+ icon,
200
+ actions,
201
+ className,
202
+ titleClassName,
203
+ bodyClassName,
204
+ secondaryBodyClassName,
205
+ iconClassName,
206
+ actionsClassName,
207
+ role,
208
+ live
209
+ }) {
210
+ const resolvedRole = role ?? (tone === "error" ? "alert" : "status");
211
+ const resolvedLive = live ?? (resolvedRole === "alert" ? "assertive" : "polite");
212
+ return /* @__PURE__ */ jsxs(
213
+ "div",
214
+ {
215
+ className,
216
+ "data-terminal-panel": true,
217
+ "data-terminal-tone": tone,
218
+ role: resolvedRole,
219
+ "aria-live": resolvedLive === "off" ? void 0 : resolvedLive,
220
+ children: [
221
+ icon ? /* @__PURE__ */ jsx("div", { className: joinClasses2(iconClassName), "data-terminal-icon": true, children: icon }) : null,
222
+ /* @__PURE__ */ jsx(Title, { className: joinClasses2(titleClassName), "data-terminal-title": true, children: title }),
223
+ body ? /* @__PURE__ */ jsx("div", { className: joinClasses2(bodyClassName), "data-terminal-body": true, children: body }) : null,
224
+ actions ? /* @__PURE__ */ jsx("div", { className: joinClasses2(actionsClassName), "data-terminal-actions": true, children: actions }) : null,
225
+ secondaryBody ? /* @__PURE__ */ jsx("div", { className: joinClasses2(secondaryBodyClassName), "data-terminal-secondary-body": true, children: secondaryBody }) : null
226
+ ]
227
+ }
228
+ );
229
+ }
230
+ function ClockIcon({ className, strokeWidth = 2 }) {
231
+ return /* @__PURE__ */ jsx(
232
+ "svg",
233
+ {
234
+ fill: "none",
235
+ strokeLinecap: "round",
236
+ strokeLinejoin: "round",
237
+ strokeWidth,
238
+ viewBox: "0 0 24 24",
239
+ stroke: "currentColor",
240
+ className,
241
+ width: "1em",
242
+ height: "1em",
243
+ "aria-hidden": "true",
244
+ children: /* @__PURE__ */ jsx("path", { d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" })
245
+ }
246
+ );
247
+ }
248
+ function LoggedInAsUser({ email, onLogout, classPrefix }) {
249
+ return /* @__PURE__ */ jsxs("p", { className: `${classPrefix}-logged-in-hint`, children: [
250
+ "Logged in as ",
251
+ email,
252
+ onLogout && /* @__PURE__ */ jsxs(Fragment, { children: [
253
+ " \u2014 ",
254
+ /* @__PURE__ */ jsx("button", { type: "button", className: `${classPrefix}-link`, onClick: onLogout, children: "Not you? Log out" })
255
+ ] })
256
+ ] });
257
+ }
258
+ function MembershipHero({
259
+ membershipName,
260
+ classPrefix,
261
+ onBookForSomeoneElse
262
+ }) {
263
+ return /* @__PURE__ */ jsxs(FeedbackMessage, { tone: "success", className: `${classPrefix}-membership-hero`, role: "status", children: [
264
+ /* @__PURE__ */ jsx("div", { className: `${classPrefix}-membership-hero__icon`, "aria-hidden": "true", children: "\u2728" }),
265
+ /* @__PURE__ */ jsxs("h3", { className: `${classPrefix}-membership-hero__title`, children: [
266
+ "Included with your ",
267
+ membershipName
268
+ ] }),
269
+ /* @__PURE__ */ jsx("p", { className: `${classPrefix}-membership-hero__subtitle`, children: "No payment required" }),
270
+ onBookForSomeoneElse && /* @__PURE__ */ jsx(
271
+ "button",
272
+ {
273
+ type: "button",
274
+ className: `${classPrefix}-membership-hero__link`,
275
+ onClick: onBookForSomeoneElse,
276
+ children: "Booking for someone else?"
277
+ }
278
+ )
279
+ ] });
280
+ }
281
+ function clampIndex(idx, len) {
282
+ if (len <= 0) return 0;
283
+ const mod = idx % len;
284
+ return mod < 0 ? mod + len : mod;
285
+ }
286
+ function TabBarFragment({
287
+ tabs,
288
+ activeTab,
289
+ onTabChange,
290
+ ariaLabel,
291
+ className,
292
+ tabClassName,
293
+ activeTabClassName
294
+ }) {
295
+ return /* @__PURE__ */ jsx(
296
+ "div",
297
+ {
298
+ className,
299
+ role: "tablist",
300
+ "aria-label": ariaLabel,
301
+ children: tabs.map((tab, idx) => {
302
+ const isActive = tab.id === activeTab;
303
+ return /* @__PURE__ */ jsx(
304
+ "button",
305
+ {
306
+ type: "button",
307
+ role: "tab",
308
+ "aria-selected": isActive,
309
+ tabIndex: isActive ? 0 : -1,
310
+ className: clsx_default(tabClassName, isActive && activeTabClassName),
311
+ onClick: () => onTabChange(tab.id),
312
+ onKeyDown: (e) => {
313
+ if (tabs.length === 0) return;
314
+ if (!(e.currentTarget instanceof HTMLButtonElement)) return;
315
+ let nextIdx = null;
316
+ if (e.key === "ArrowRight") nextIdx = clampIndex(idx + 1, tabs.length);
317
+ else if (e.key === "ArrowLeft") nextIdx = clampIndex(idx - 1, tabs.length);
318
+ else if (e.key === "Home") nextIdx = 0;
319
+ else if (e.key === "End") nextIdx = tabs.length - 1;
320
+ if (nextIdx === null) return;
321
+ e.preventDefault();
322
+ const nextId = tabs[nextIdx]?.id;
323
+ if (!nextId) return;
324
+ onTabChange(nextId);
325
+ requestAnimationFrame(() => {
326
+ const root = e.currentTarget.closest('[role="tablist"]') ?? null;
327
+ const btns = root?.querySelectorAll('[role="tab"]') ?? null;
328
+ btns?.[nextIdx]?.focus();
329
+ });
330
+ },
331
+ children: tab.label
332
+ },
333
+ tab.id
334
+ );
335
+ })
336
+ }
337
+ );
338
+ }
339
+ function StepIndicator({
340
+ currentStep,
341
+ totalSteps,
342
+ stepLabels,
343
+ classPrefix
344
+ }) {
345
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Registration progress", className: `${classPrefix}-steps-nav`, children: /* @__PURE__ */ jsx("ol", { className: `${classPrefix}-steps`, children: Array.from({ length: totalSteps }, (_, i) => {
346
+ const stepNum = i + 1;
347
+ const isActive = stepNum === currentStep;
348
+ const isComplete = stepNum < currentStep;
349
+ return /* @__PURE__ */ jsxs(
350
+ "li",
351
+ {
352
+ className: `${classPrefix}-step`,
353
+ "aria-current": isActive ? "step" : void 0,
354
+ children: [
355
+ /* @__PURE__ */ jsx(
356
+ "div",
357
+ {
358
+ className: `${classPrefix}-step-circle${isActive ? ` ${classPrefix}-step-circle--active` : ""}${isComplete ? ` ${classPrefix}-step-circle--completed` : ""}`,
359
+ children: isComplete ? /* @__PURE__ */ jsx(CheckIcon, { className: `${classPrefix}-step-check`, strokeWidth: 3 }) : stepNum
360
+ }
361
+ ),
362
+ stepLabels?.[i] && /* @__PURE__ */ jsx(
363
+ "span",
364
+ {
365
+ className: `${classPrefix}-step-label${isActive ? ` ${classPrefix}-step-label--active` : ""}`,
366
+ children: stepLabels[i]
367
+ }
368
+ ),
369
+ stepNum < totalSteps && /* @__PURE__ */ jsx(
370
+ "div",
371
+ {
372
+ className: `${classPrefix}-step-connector${isComplete ? ` ${classPrefix}-step-connector--completed` : ""}`,
373
+ "aria-hidden": "true"
374
+ }
375
+ )
376
+ ]
377
+ },
378
+ i
379
+ );
380
+ }) }) });
381
+ }
382
+
383
+ export { ActionRow, CheckIcon, ClockIcon, CrossIcon, LoggedInAsUser, MembershipHero, StateIcon, StepIndicator, TabBarFragment, TerminalPanel, buildCheckoutReturnUrls, consumeSearchParam, consumeSearchParams, createBodyThemePortalRoot, formatPrice, getStepNumber, logoutPortal, scrollToBlock, validateFormData };
@@ -0,0 +1,36 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+
3
+ // ../blocks/src/system/runtime/shared/components/FieldValidationMessage.tsx
4
+ function getFieldValidationControlProps({
5
+ message,
6
+ messageId,
7
+ describedBy
8
+ }) {
9
+ const hasMessage = Boolean(message);
10
+ const ariaDescribedBy = [describedBy, hasMessage ? messageId : void 0].filter((part) => typeof part === "string" && part.length > 0).join(" ");
11
+ return {
12
+ "aria-invalid": hasMessage ? "true" : void 0,
13
+ "aria-describedby": ariaDescribedBy || void 0
14
+ };
15
+ }
16
+ function FieldValidationMessage({
17
+ id,
18
+ children,
19
+ className,
20
+ live = "assertive"
21
+ }) {
22
+ return /* @__PURE__ */ jsx(
23
+ "p",
24
+ {
25
+ id,
26
+ className,
27
+ "data-field-validation-message": true,
28
+ "data-field-validation-tone": "error",
29
+ role: "alert",
30
+ "aria-live": live === "off" ? void 0 : live,
31
+ children
32
+ }
33
+ );
34
+ }
35
+
36
+ export { FieldValidationMessage, getFieldValidationControlProps };