@riverbankcms/sdk 0.132.0 → 0.134.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 (159) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/{PreviewEditorSidebar-DKQ5eFK9.mjs → PreviewEditorSidebar-DfRhJPFQ.mjs} +3 -3
  3. package/dist/{PreviewEditorUI-CNTcOjCC.mjs → PreviewEditorUI-Dppxcr_g.mjs} +2 -2
  4. package/dist/{SdkPreviewModeRuntime-DJu3qu33.mjs → SdkPreviewModeRuntime-8CyGCXir.mjs} +46 -15
  5. package/dist/{SiteChromeCustomizeContext-2TzT3vbj.mjs → SiteChromeCustomizeContext-DVMTMvqA.mjs} +497 -169
  6. package/dist/_dts/ai/src/contracts/proposals.d.ts +384 -384
  7. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +219 -219
  8. package/dist/_dts/api/src/accountApi.d.ts +5 -5
  9. package/dist/_dts/api/src/appointmentEndpointDefinitions.d.ts +1 -1
  10. package/dist/_dts/api/src/bookingOperations.d.ts +2 -14
  11. package/dist/_dts/api/src/bookings.d.ts +2 -2
  12. package/dist/_dts/api/src/contentRuntime.d.ts +1 -1
  13. package/dist/_dts/api/src/courseEndpointDefinitions.d.ts +2 -2
  14. package/dist/_dts/api/src/endpoints.d.ts +3 -3
  15. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -1
  16. package/dist/_dts/api/src/navigation/contracts.d.ts +9 -6
  17. package/dist/_dts/api/src/navigation/linkResolver.d.ts +6 -2
  18. package/dist/_dts/api/src/navigation/types.d.ts +23 -6
  19. package/dist/_dts/api/src/navigation.d.ts +1 -1
  20. package/dist/_dts/api/src/publicBookingService.d.ts +15 -0
  21. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +3 -1
  22. package/dist/_dts/api/src/publicExperience/wholeSeriesEndpoints.d.ts +2 -0
  23. package/dist/_dts/api/src/sdk-event-upsert.d.ts +1 -1
  24. package/dist/_dts/api/src/sdkThemeWire.d.ts +50 -50
  25. package/dist/_dts/api/src/siteBanner.d.ts +4 -2
  26. package/dist/_dts/api/src/types.d.ts +1 -1
  27. package/dist/_dts/api/src/webhooks.d.ts +12 -12
  28. package/dist/_dts/blocks/src/client.d.ts +1 -1
  29. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +28 -72
  30. package/dist/_dts/blocks/src/index.d.ts +3 -2
  31. package/dist/_dts/blocks/src/primitives/content/components/RichText.d.ts +2 -2
  32. package/dist/_dts/blocks/src/primitives/content/primitives.d.ts +1 -0
  33. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +36 -14
  34. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +3 -0
  35. package/dist/_dts/blocks/src/system/blocks/events/whole-series/schemas.d.ts +3 -3
  36. package/dist/_dts/blocks/src/system/blocks/events/whole-series/types.d.ts +3 -0
  37. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +4 -4
  38. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +148 -148
  39. package/dist/_dts/blocks/src/system/blocks/offerings-preview/model.d.ts +2 -1
  40. package/dist/_dts/blocks/src/system/blocks/shared/bookingConsent.d.ts +36 -0
  41. package/dist/_dts/blocks/src/system/manifest/hydrateLinks.d.ts +9 -2
  42. package/dist/_dts/blocks/src/system/manifest/resolveBlockData.d.ts +8 -0
  43. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +79 -79
  44. package/dist/_dts/blocks/src/system/runtime/api/types/appointments.d.ts +2 -11
  45. package/dist/_dts/blocks/src/system/runtime/api/types/courses.d.ts +2 -0
  46. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +1 -0
  47. package/dist/_dts/blocks/src/system/runtime/components/multi-step/DynamicFormFields.d.ts +3 -19
  48. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +1 -1
  49. package/dist/_dts/blocks/src/system/runtime/hooks/useSelectedAppointmentConsentForm.d.ts +2 -0
  50. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.consent.d.ts +10 -0
  51. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.field-values.d.ts +4 -0
  52. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.fields.d.ts +21 -0
  53. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +2 -1
  54. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.interactive.d.ts +38 -144
  55. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +5 -19
  56. package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +3 -2
  57. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/AttendeeDetailsStep.d.ts +2 -0
  58. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationSurface.d.ts +18 -1
  59. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +4 -4
  60. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/validation.d.ts +2 -1
  61. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/components.d.ts +2 -1
  62. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/whole-series-registration.headless.contract.d.ts +2 -0
  63. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +34 -12
  64. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingConsentAgreement.d.ts +7 -0
  65. package/dist/_dts/blocks/src/system/runtime/shared/types.d.ts +1 -0
  66. package/dist/_dts/blocks/src/system/types/link.d.ts +7 -1
  67. package/dist/_dts/content-model/src/content-types/schema.d.ts +4 -4
  68. package/dist/_dts/core/src/booking-consent.d.ts +8 -0
  69. package/dist/_dts/core/src/index.d.ts +1 -0
  70. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +9 -3
  71. package/dist/_dts/db/src/schemas/forms.d.ts +21 -21
  72. package/dist/_dts/db/src/types/jsonb.d.ts +1 -1
  73. package/dist/_dts/editor/src/primitives/rich-text/RichTextEditorSurface.d.ts +2 -1
  74. package/dist/_dts/editor/src/primitives/rich-text/config.d.ts +2 -1
  75. package/dist/_dts/editor/src/primitives/rich-text/toolbar/linkPopoverUtils.d.ts +3 -2
  76. package/dist/_dts/editor/src/primitives/rich-text/useRichTextEditor.d.ts +3 -4
  77. package/dist/_dts/media-core/src/usageScanner.d.ts +1 -1
  78. package/dist/_dts/sdk/src/bookings/types.d.ts +7 -89
  79. package/dist/_dts/sdk/src/config/validation.d.ts +30 -30
  80. package/dist/_dts/sdk/src/contracts/content.d.ts +10 -36
  81. package/dist/_dts/sdk/src/contracts/rendering.d.ts +1 -1
  82. package/dist/_dts/sdk/src/manifest/passes/pass1-fields.d.ts +9 -9
  83. package/dist/_dts/sdk/src/public-api/contracts.d.ts +6 -19
  84. package/dist/_dts/sdk/src/version.d.ts +1 -1
  85. package/dist/_dts/theme-core/src/accordions/types.d.ts +2 -2
  86. package/dist/_dts/theme-core/src/buttons/types.d.ts +12 -12
  87. package/dist/_dts/theme-core/src/cards/types.d.ts +5 -5
  88. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +72 -72
  89. package/dist/_dts/theme-core/src/navigation/types.d.ts +4 -4
  90. package/dist/_dts/theme-core/src/palette/colors.d.ts +1 -1
  91. package/dist/_dts/theme-core/src/palette/curated/types.d.ts +2 -2
  92. package/dist/_dts/theme-core/src/schema.d.ts +82 -82
  93. package/dist/_dts/theme-core/src/site-styles/cardRoleVocabulary.d.ts +1 -1
  94. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -2
  95. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +4 -4
  96. package/dist/_dts/theme-core/src/site-styles/logoBranding.d.ts +4 -4
  97. package/dist/_dts/theme-core/src/tokens/themeColorTokens.d.ts +1 -1
  98. package/dist/_dts/ui/src/badge.d.ts +1 -1
  99. package/dist/_dts/ui/src/button.d.ts +1 -1
  100. package/dist/_dts/ui/src/callout.d.ts +1 -1
  101. package/dist/_dts/ui/src/card.d.ts +1 -1
  102. package/dist/client/{StepIndicator-CGixP_LW.mjs → BookingConsentAgreement-BxgpGEFD.mjs} +26 -4
  103. package/dist/client/{DiscountCodeDisclosure-DO7llLxm.mjs → DiscountCodeDisclosure-CfuPOHD0.mjs} +1 -1
  104. package/dist/client/{EventCombined.client-xID7zN__.mjs → EventCombined.client-DB8Qfzi-.mjs} +3 -3
  105. package/dist/client/{EventListing.client-CriBslp0.mjs → EventListing.client-DD4X8hp4.mjs} +2 -2
  106. package/dist/client/{LeafletStaticMap-DYmHnM8g.mjs → LeafletStaticMap-QhgIBQbv.mjs} +1 -1
  107. package/dist/client/{WholeSeriesRegistrationWizard-BEjzSiOA.mjs → WholeSeriesRegistrationWizard-DwtC7bCs.mjs} +72 -22
  108. package/dist/client/{accordion-CgFbnnnQ.mjs → accordion-DFXpLvwg.mjs} +1 -1
  109. package/dist/client/{bookingForm-dUyGpbxc.mjs → bookingForm-sI05d3lk.mjs} +73 -47
  110. package/dist/client/bookings.mjs +989 -140
  111. package/dist/client/{carousel-BvBwkUzx.mjs → carousel-wjyWTZCh.mjs} +1 -1
  112. package/dist/client/{cart-DiZENT2E.mjs → cart-DCwdpA4i.mjs} +3 -3
  113. package/dist/client/{checkout-Dq13KIgR.mjs → checkout-DTDW3l0R.mjs} +3 -3
  114. package/dist/client/checkoutUrls-DQYC_Br-.mjs +187 -0
  115. package/dist/client/client.mjs +556 -237
  116. package/dist/client/{context-B83PiNzm.mjs → context-TSK1CGx8.mjs} +1 -14
  117. package/dist/client/{courseRegistration-CKC5NmyH.mjs → courseRegistration-A-Tg7qw_.mjs} +3 -3
  118. package/dist/client/{eventCalendar-BF0Jatfw.mjs → eventCalendar-B0Zg-i_w.mjs} +5 -5
  119. package/dist/client/{eventCombined-BuoCF8je.mjs → eventCombined-B8Y2wizd.mjs} +3 -3
  120. package/dist/client/{eventDetails-CKwh0S9s.mjs → eventDetails-DPDOwURJ.mjs} +3 -3
  121. package/dist/client/{eventListing-eUxaWFaB.mjs → eventListing-CjBcmSLn.mjs} +3 -3
  122. package/dist/client/{eventRegistration-CfkNOkPb.mjs → eventRegistration-CK30HsAq.mjs} +111 -64
  123. package/dist/client/{form-C17H1c_H.mjs → form-CUXfsABE.mjs} +2 -2
  124. package/dist/client/{headerSection-DEwUmrtt.mjs → headerSection-N-mN3rjr.mjs} +2 -2
  125. package/dist/client/hooks.mjs +106 -3
  126. package/dist/client/{locationMap-Pf2QwuvW.mjs → locationMap-oiIDQMBt.mjs} +2 -2
  127. package/dist/client/{newsletterForm-BWQAH5Sv.mjs → newsletterForm-CkQ2tTrM.mjs} +2 -2
  128. package/dist/client/{pricing-CVdvbopJ.mjs → pricing-Caa0QWzh.mjs} +1 -1
  129. package/dist/client/{productDetail-BZi1Fa_G.mjs → productDetail-CnidyrsN.mjs} +3 -3
  130. package/dist/client/{productList-qq-55DNk.mjs → productList-CttYcS_S.mjs} +3 -3
  131. package/dist/client/{propsDecoder-BxmqPKdP.mjs → propsDecoder-CeUMxI9a.mjs} +211 -100
  132. package/dist/client/rendering/client.mjs +428 -151
  133. package/dist/client/rendering/islands.mjs +18 -18
  134. package/dist/client/rendering.mjs +643 -324
  135. package/dist/client/{scrollToBlock-B3CcKdtG.mjs → scrollToBlock-lPr1oqxB.mjs} +1 -1
  136. package/dist/client/{shop-DNWJPut5.mjs → shop-DXQtMo2O.mjs} +6 -6
  137. package/dist/client/{shop-commerce-BhvQCosS.mjs → shop-commerce-quDL411J.mjs} +7 -164
  138. package/dist/client/{shop-commerce-store-B04sCNnW.mjs → shop-commerce-store-Dnu-8Iub.mjs} +1 -1
  139. package/dist/client/{shopShared-DNNgZlmW.mjs → shopShared-BWPUURvG.mjs} +3 -3
  140. package/dist/client/{useEventFilters-CUmhE24_.mjs → useEventFilters-DRhWp2_5.mjs} +3 -3
  141. package/dist/client/{usePolling-M5jG675x.mjs → usePolling-UN4WKnaM.mjs} +2 -2
  142. package/dist/preview-next/client/runtime.mjs +3 -3
  143. package/dist/{sdk-runtime-BEXb1wqo.mjs → sdk-runtime-Ca5RD78X.mjs} +1 -1
  144. package/dist/{separator-DGMuip1D.mjs → separator-CMhj6BTi.mjs} +1 -1
  145. package/dist/server/components.mjs +117 -37
  146. package/dist/server/config-validation.mjs +106 -3
  147. package/dist/server/config.mjs +106 -3
  148. package/dist/server/data.mjs +106 -3
  149. package/dist/server/index.mjs +1 -1
  150. package/dist/server/next.mjs +186 -106
  151. package/dist/server/page-converter.mjs +105 -2
  152. package/dist/server/prebuild.mjs +1 -1
  153. package/dist/server/rendering/server.mjs +119 -37
  154. package/dist/server/rendering.mjs +117 -37
  155. package/dist/server/routing.mjs +132 -73
  156. package/dist/server/server.mjs +107 -4
  157. package/dist/server/theme-bridge.mjs +4 -4
  158. package/package.json +2 -2
  159. package/dist/client/checkoutUrls-Ct8Mxna3.mjs +0 -26
@@ -846,7 +846,10 @@ var init_booking_date_time = __esmMin((() => {
846
846
  LOCAL_DATE_PATTERN = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/u;
847
847
  DATE_TIME_FORMATTER_CACHE_LIMIT = 100;
848
848
  dateTimeFormatterCache = /* @__PURE__ */ new Map();
849
- })), init_dated_offering_settlement = __esmMin((() => {
849
+ }));
850
+ //#endregion
851
+ //#region ../core/src/booking-consent.ts
852
+ var init_booking_consent = __esmMin((() => {})), init_dated_offering_settlement = __esmMin((() => {
850
853
  init_result$1();
851
854
  }));
852
855
  var init_person_records = __esmMin((() => {
@@ -1404,6 +1407,7 @@ var init_src$3 = __esmMin((() => {
1404
1407
  init_booking_refunds();
1405
1408
  init_booking_instalments();
1406
1409
  init_booking_date_time();
1410
+ init_booking_consent();
1407
1411
  init_dated_offering_settlement();
1408
1412
  init_person_records();
1409
1413
  init_rectification();
@@ -11963,6 +11967,44 @@ var init_bookingPaymentTerms = __esmMin((() => {
11963
11967
  blockBookingPaymentTermsSchema = z$1.object({ allowedOptions: z$1.array(blockBookingPaymentCollectionOptionSchema).min(1) });
11964
11968
  }));
11965
11969
  //#endregion
11970
+ //#region ../blocks/src/system/blocks/shared/bookingConsent.ts
11971
+ function toBookingRequirementConsentFieldId(requirementId) {
11972
+ return `${BOOKING_REQUIREMENT_CONSENT_FIELD_PREFIX}${requirementId}`;
11973
+ }
11974
+ function isBookingRequirementConsentFieldId(value) {
11975
+ return value.startsWith(BOOKING_REQUIREMENT_CONSENT_FIELD_PREFIX);
11976
+ }
11977
+ function toBookingRequirementConsentField(consent) {
11978
+ return {
11979
+ id: toBookingRequirementConsentFieldId(consent.requirementId),
11980
+ label: consent.title,
11981
+ type: "booking_requirement_consent",
11982
+ required: true,
11983
+ agreement: consent.agreement,
11984
+ checkboxLabel: consent.checkboxLabel
11985
+ };
11986
+ }
11987
+ var BOOKING_REQUIREMENT_CONSENT_FIELD_PREFIX, blockBookingConsentSchema, bookingRequirementConsentFieldSchema, bookingConsentCarrierSchema;
11988
+ var init_bookingConsent = __esmMin((() => {
11989
+ init_richTextSchema();
11990
+ BOOKING_REQUIREMENT_CONSENT_FIELD_PREFIX = "booking_requirement_consent_";
11991
+ blockBookingConsentSchema = z$1.object({
11992
+ requirementId: z$1.string(),
11993
+ title: z$1.string(),
11994
+ agreement: RichTextDocSchema,
11995
+ checkboxLabel: z$1.string()
11996
+ });
11997
+ bookingRequirementConsentFieldSchema = z$1.object({
11998
+ id: z$1.string(),
11999
+ label: z$1.string(),
12000
+ type: z$1.literal("booking_requirement_consent"),
12001
+ required: z$1.literal(true),
12002
+ agreement: RichTextDocSchema,
12003
+ checkboxLabel: z$1.string().min(1)
12004
+ });
12005
+ bookingConsentCarrierSchema = z$1.union([blockBookingConsentSchema, bookingRequirementConsentFieldSchema]);
12006
+ }));
12007
+ //#endregion
11966
12008
  //#region ../blocks/src/system/blocks/events/whole-series/pricing.ts
11967
12009
  function isSaleWindowOpen(option, now) {
11968
12010
  if (!option.isActive) return false;
@@ -12144,6 +12186,7 @@ var init_pricing$3 = __esmMin((() => {
12144
12186
  var wholeSeriesVenueSchema, wholeSeriesSessionSchema, wholeSeriesTeamMemberSummarySchema, wholeSeriesPricingOptionSchema, wholeSeriesPricingSchema, publicWholeSeriesOfferingSchema, publicWholeSeriesOfferingsArraySchema;
12145
12187
  var init_schemas$2 = __esmMin((() => {
12146
12188
  init_bookingPaymentTerms();
12189
+ init_bookingConsent();
12147
12190
  wholeSeriesVenueSchema = z$1.object({
12148
12191
  id: z$1.string(),
12149
12192
  name: z$1.string(),
@@ -12207,6 +12250,7 @@ var init_schemas$2 = __esmMin((() => {
12207
12250
  pricing: wholeSeriesPricingSchema,
12208
12251
  currency: z$1.string(),
12209
12252
  paymentTerms: blockBookingPaymentTermsSchema,
12253
+ consent: blockBookingConsentSchema.nullable(),
12210
12254
  enrollmentCapacity: z$1.number().nullable(),
12211
12255
  acceptsMemberships: z$1.boolean(),
12212
12256
  status: z$1.enum([
@@ -12236,6 +12280,7 @@ var init_schemas$1 = __esmMin((() => {
12236
12280
  init_media$1();
12237
12281
  init_richTextSchema();
12238
12282
  init_bookingPaymentTerms();
12283
+ init_bookingConsent();
12239
12284
  init_whole_series();
12240
12285
  eventPresetSchema = z$1.enum([
12241
12286
  "event",
@@ -12526,6 +12571,7 @@ var init_schemas$1 = __esmMin((() => {
12526
12571
  timeZone: z$1.string(),
12527
12572
  pricing: publicEventPricingSchema,
12528
12573
  paymentTerms: blockBookingPaymentTermsSchema,
12574
+ consent: blockBookingConsentSchema.nullable(),
12529
12575
  accessRestriction: accessRestrictionSchema,
12530
12576
  allowedCategoryIds: z$1.array(z$1.string()),
12531
12577
  requireGuestDetails: z$1.boolean().optional(),
@@ -26687,6 +26733,31 @@ var init_booking_form_reserved_fields = __esmMin((() => {
26687
26733
  BOOKING_FORM_DATA_RESERVED_KEYS = new Set(BOOKING_FORM_DATA_RESERVED_KEY_VALUES);
26688
26734
  }));
26689
26735
  //#endregion
26736
+ //#region ../blocks/src/system/runtime/nodes/booking-form.consent.ts
26737
+ function resolveSelectedAppointmentConsent(service) {
26738
+ return service?.consent ? {
26739
+ kind: "required-for-selected-service",
26740
+ field: toBookingRequirementConsentField(service.consent)
26741
+ } : { kind: "not-applicable" };
26742
+ }
26743
+ function projectSelectedAppointmentConsentIntoForm(form, selectedConsent) {
26744
+ if (!form) return null;
26745
+ const sourceFields = form.schema?.fields ?? [];
26746
+ const baseFields = sourceFields.filter((field) => field.type !== "booking_requirement_consent");
26747
+ const fields = selectedConsent.kind === "required-for-selected-service" ? [...baseFields, selectedConsent.field] : baseFields;
26748
+ if (selectedConsent.kind === "not-applicable" && baseFields.length === sourceFields.length) return form;
26749
+ return {
26750
+ ...form,
26751
+ schema: {
26752
+ ...form.schema,
26753
+ fields
26754
+ }
26755
+ };
26756
+ }
26757
+ var init_booking_form_consent = __esmMin((() => {
26758
+ init_bookingConsent();
26759
+ }));
26760
+ //#endregion
26690
26761
  //#region ../blocks/src/system/runtime/nodes/booking-form.state.ts
26691
26762
  function toTrimmedString(value) {
26692
26763
  const trimmed = value?.trim();
@@ -26869,7 +26940,6 @@ function readBookingFieldType(value) {
26869
26940
  case "select":
26870
26941
  case "radio":
26871
26942
  case "checkbox":
26872
- case "booking_requirement_consent":
26873
26943
  case "tel":
26874
26944
  case "url":
26875
26945
  case "number":
@@ -26904,7 +26974,7 @@ function normalizeBookingSettings(value) {
26904
26974
  };
26905
26975
  }
26906
26976
  function isBookingFormService(value) {
26907
- return isRecord$29(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string";
26977
+ return isRecord$29(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string" && (value.consent === void 0 || blockBookingConsentSchema.safeParse(value.consent).success);
26908
26978
  }
26909
26979
  function collectBookingCustomFields(data) {
26910
26980
  const customFields = {};
@@ -27150,7 +27220,9 @@ function getBookingSuccessMessage(successMessage) {
27150
27220
  var init_booking_form_state = __esmMin((() => {
27151
27221
  init_dist$1();
27152
27222
  init_src$3();
27223
+ init_bookingConsent();
27153
27224
  init_booking_form_reserved_fields();
27225
+ init_booking_form_consent();
27154
27226
  }));
27155
27227
  //#endregion
27156
27228
  //#region ../logger/src/noop.ts
@@ -27165,14 +27237,23 @@ var init_noop = __esmMin((() => {
27165
27237
  withFields: (_) => logger
27166
27238
  };
27167
27239
  }));
27168
- var bookingFieldOptionSchema, bookingFieldSchema, bookingSettingsSchema, bookingSourceFormSchema;
27240
+ var bookingFieldOptionSchema, standardBookingFieldRules, standardBookingFieldSchema, bookingFieldSchema, bookingSettingsSchema, bookingSourceFormSchema;
27169
27241
  var init_booking_runtime_sources = __esmMin((() => {
27170
27242
  init_noop();
27171
27243
  bookingFieldOptionSchema = z$1.object({
27172
27244
  value: z$1.string(),
27173
27245
  label: z$1.string()
27174
27246
  });
27175
- bookingFieldSchema = z$1.object({
27247
+ standardBookingFieldRules = {
27248
+ options: z$1.array(bookingFieldOptionSchema).optional(),
27249
+ multiple: z$1.boolean().optional(),
27250
+ minLength: z$1.number().optional(),
27251
+ maxLength: z$1.number().optional(),
27252
+ pattern: z$1.string().optional(),
27253
+ min: z$1.number().optional(),
27254
+ max: z$1.number().optional()
27255
+ };
27256
+ standardBookingFieldSchema = z$1.object({
27176
27257
  id: z$1.string(),
27177
27258
  label: z$1.string(),
27178
27259
  type: z$1.enum([
@@ -27182,7 +27263,6 @@ var init_booking_runtime_sources = __esmMin((() => {
27182
27263
  "select",
27183
27264
  "radio",
27184
27265
  "checkbox",
27185
- "booking_requirement_consent",
27186
27266
  "tel",
27187
27267
  "url",
27188
27268
  "number",
@@ -27192,14 +27272,9 @@ var init_booking_runtime_sources = __esmMin((() => {
27192
27272
  required: z$1.boolean().optional(),
27193
27273
  placeholder: z$1.string().optional(),
27194
27274
  helpText: z$1.string().optional(),
27195
- options: z$1.array(bookingFieldOptionSchema).optional(),
27196
- multiple: z$1.boolean().optional(),
27197
- minLength: z$1.number().optional(),
27198
- maxLength: z$1.number().optional(),
27199
- pattern: z$1.string().optional(),
27200
- min: z$1.number().optional(),
27201
- max: z$1.number().optional()
27275
+ ...standardBookingFieldRules
27202
27276
  });
27277
+ bookingFieldSchema = standardBookingFieldSchema;
27203
27278
  bookingSettingsSchema = z$1.object({
27204
27279
  type: z$1.literal("booking"),
27205
27280
  serviceId: z$1.string().optional(),
@@ -27253,6 +27328,7 @@ var init_booking_form_interactive = __esmMin((() => {
27253
27328
  init_booking_form_state();
27254
27329
  init_booking_runtime_sources();
27255
27330
  init_bookingPaymentTerms();
27331
+ init_bookingConsent();
27256
27332
  blockBookingPaymentTermsAvailabilitySchema = z$1.union([z$1.object({
27257
27333
  kind: z$1.literal("available"),
27258
27334
  paymentTerms: blockBookingPaymentTermsSchema
@@ -27271,7 +27347,8 @@ var init_booking_form_interactive = __esmMin((() => {
27271
27347
  priceAmount: z$1.number().nullable().optional(),
27272
27348
  priceCurrency: z$1.string().nullable().optional(),
27273
27349
  paymentTerms: blockBookingPaymentTermsSchema.optional(),
27274
- paymentTermsAvailability: blockBookingPaymentTermsAvailabilitySchema.optional()
27350
+ paymentTermsAvailability: blockBookingPaymentTermsAvailabilitySchema.optional(),
27351
+ consent: blockBookingConsentSchema.optional()
27275
27352
  });
27276
27353
  bookingServicesSourceSchema = z$1.union([
27277
27354
  z$1.array(bookingServiceSchema),
@@ -31269,6 +31346,57 @@ var init_EventCombined_interactive = __esmMin((() => {
31269
31346
  });
31270
31347
  }));
31271
31348
  //#endregion
31349
+ //#region ../blocks/src/system/runtime/nodes/event-registration/registrationSurface.ts
31350
+ function planEventRegistrationScope(input) {
31351
+ const subject = input.subject;
31352
+ const selectedRunOffering = input.wholeSeriesOffering;
31353
+ if (subject?.kind !== "eventOffering" || !selectedRunOffering) return {
31354
+ kind: "context",
31355
+ events: resolveEventRegistrationScopedEvents(input.events, {
31356
+ occurrenceContext: input.occurrenceContext,
31357
+ subject
31358
+ })
31359
+ };
31360
+ if (!(selectedRunOffering.eventOfferingId === subject.eventOfferingId && subject.availableEventSeriesIds.some((seriesId) => seriesId === selectedRunOffering.eventSeriesId))) return { kind: "invalidSelectedRun" };
31361
+ return {
31362
+ kind: "selectedRun",
31363
+ events: input.events.filter((event) => event.seriesId === selectedRunOffering.eventSeriesId),
31364
+ offering: selectedRunOffering
31365
+ };
31366
+ }
31367
+ function planEventRegistrationSurface(input) {
31368
+ const scope = planEventRegistrationScope(input);
31369
+ if (scope.kind === "invalidSelectedRun") return { kind: "unavailableWholeSeries" };
31370
+ const scopedEvents = scope.events;
31371
+ const bookingScopes = new Set(scopedEvents.map((event) => event.bookingScope));
31372
+ if (scope.kind === "selectedRun") {
31373
+ if (bookingScopes.size !== 1 || !bookingScopes.has("whole_series")) return { kind: "unavailableWholeSeries" };
31374
+ return {
31375
+ kind: "wholeSeries",
31376
+ offerings: [scope.offering]
31377
+ };
31378
+ }
31379
+ if (!input.occurrenceContext && !input.subject && bookingScopes.has("single_occurrence")) return {
31380
+ kind: "occurrence",
31381
+ events: scopedEvents.filter((event) => event.bookingScope === "single_occurrence")
31382
+ };
31383
+ if (bookingScopes.size === 0 || bookingScopes.has("single_occurrence")) return bookingScopes.has("whole_series") ? { kind: "mixedBookingScopes" } : {
31384
+ kind: "occurrence",
31385
+ events: scopedEvents
31386
+ };
31387
+ const requiredSeriesIds = new Set(scopedEvents.map((event) => event.seriesId));
31388
+ const wholeSeriesOffering = input.wholeSeriesOffering;
31389
+ const offerings = (wholeSeriesOffering ? [wholeSeriesOffering, ...input.wholeSeriesOfferings.filter((offering) => offering.eventSeriesId !== wholeSeriesOffering.eventSeriesId)] : input.wholeSeriesOfferings).filter((offering) => requiredSeriesIds.has(offering.eventSeriesId));
31390
+ const loadedSeriesIds = new Set(offerings.map((offering) => offering.eventSeriesId));
31391
+ return [...requiredSeriesIds].every((seriesId) => loadedSeriesIds.has(seriesId)) && offerings.length > 0 ? {
31392
+ kind: "wholeSeries",
31393
+ offerings
31394
+ } : { kind: "unavailableWholeSeries" };
31395
+ }
31396
+ var init_registrationSurface = __esmMin((() => {
31397
+ init_eventScope();
31398
+ }));
31399
+ //#endregion
31272
31400
  //#region ../blocks/src/system/runtime/nodes/event-registration/wizardSteps.ts
31273
31401
  /**
31274
31402
  * Determine which wizard steps to show based on context and payment requirements.
@@ -31416,10 +31544,13 @@ function buildEventRegistrationShellStepLabels(source) {
31416
31544
  }) : false).map((step) => shellLabelForRegistrationStep(step, scopedEvents));
31417
31545
  }
31418
31546
  function scopeEventRegistrationEvents(source) {
31419
- return resolveEventRegistrationScopedEvents(toRegistrationEvents(source.events ?? []), {
31547
+ const scope = planEventRegistrationScope({
31548
+ events: toRegistrationEvents(source.events ?? []),
31549
+ wholeSeriesOffering: source.wholeSeriesOffering,
31420
31550
  occurrenceContext: source.occurrenceContext,
31421
31551
  subject: source.subject
31422
31552
  });
31553
+ return scope.kind === "invalidSelectedRun" ? [] : scope.events;
31423
31554
  }
31424
31555
  function shellLabelForRegistrationStep(step, events) {
31425
31556
  switch (step) {
@@ -31477,6 +31608,7 @@ var init_event_registration_interactive = __esmMin((() => {
31477
31608
  init_shop_shared();
31478
31609
  init_event_registration_shared();
31479
31610
  init_eventScope();
31611
+ init_registrationSurface();
31480
31612
  init_pricing$2();
31481
31613
  init_destination();
31482
31614
  init_islands();
@@ -91523,20 +91655,7 @@ function createBlockApi(config) {
91523
91655
  const path = buildPath(WHOLE_SERIES.checkout.path, { siteId: sid });
91524
91656
  return request(WHOLE_SERIES.checkout, {
91525
91657
  path,
91526
- body: {
91527
- eventSeriesId: data.eventSeriesId,
91528
- ...data.pricingOptionId ? { pricingOptionId: data.pricingOptionId } : {},
91529
- ...data.selectedSlidingAmount !== void 0 ? { selectedSlidingAmount: data.selectedSlidingAmount } : {},
91530
- email: data.email,
91531
- name: data.name,
91532
- phone: data.phone,
91533
- formData: data.formData,
91534
- altchaSolution: data.altchaSolution,
91535
- discountCode: data.discountCode,
91536
- successUrl: data.successUrl,
91537
- cancelUrl: data.cancelUrl,
91538
- claimToken: data.claimToken
91539
- }
91658
+ body: data
91540
91659
  });
91541
91660
  },
91542
91661
  async getWholeSeriesRegistrationStatus(params) {
@@ -94879,6 +94998,14 @@ var init_SuccessMessage = __esmMin((() => {
94879
94998
  };
94880
94999
  }));
94881
95000
  //#endregion
95001
+ //#region ../blocks/src/system/runtime/hooks/useSelectedAppointmentConsentForm.ts
95002
+ function useSelectedAppointmentConsentForm(form, selectedService) {
95003
+ return useMemo(() => projectSelectedAppointmentConsentIntoForm(form, resolveSelectedAppointmentConsent(selectedService)), [form, selectedService]);
95004
+ }
95005
+ var init_useSelectedAppointmentConsentForm = __esmMin((() => {
95006
+ init_booking_form_consent();
95007
+ }));
95008
+ //#endregion
94882
95009
  //#region ../blocks/src/utils/date-formatting.ts
94883
95010
  function warnRuntimeTimeZoneFallback() {
94884
95011
  if (hasWarnedAboutRuntimeTimeZoneFallback) return;
@@ -95961,6 +96088,23 @@ function clearBookingFieldError(errors, fieldId) {
95961
96088
  }
95962
96089
  var init_booking_form_validationErrors = __esmMin((() => {}));
95963
96090
  //#endregion
96091
+ //#region ../blocks/src/system/runtime/nodes/booking-form.field-values.ts
96092
+ function collectInitialBookingFieldValues(initialData) {
96093
+ const values = {};
96094
+ for (const [key, value] of Object.entries(initialData)) if (!BOOKING_FORM_DATA_RESERVED_KEYS.has(key) && !isBookingRequirementConsentFieldId(key) && isBookingFieldValue(value)) values[key] = value;
96095
+ return values;
96096
+ }
96097
+ function omitBookingConsentEntries(record) {
96098
+ return Object.fromEntries(Object.entries(record).filter(([key]) => !isBookingRequirementConsentFieldId(key)));
96099
+ }
96100
+ function isBookingFieldValue(value) {
96101
+ return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || Array.isArray(value) && value.every((item) => typeof item === "string");
96102
+ }
96103
+ var init_booking_form_field_values = __esmMin((() => {
96104
+ init_bookingConsent();
96105
+ init_booking_form_reserved_fields();
96106
+ }));
96107
+ //#endregion
95964
96108
  //#region ../blocks/src/system/runtime/nodes/booking-form.headless.state.ts
95965
96109
  function createInitialBookingFlowReducerState(input) {
95966
96110
  const initialData = input.initialData ?? {};
@@ -95971,7 +96115,7 @@ function createInitialBookingFlowReducerState(input) {
95971
96115
  selectedResourceId: toOptionalAppointmentResourceId(toOptionalString(initialData.resourceId) ?? input.defaultResourceId),
95972
96116
  selectedDate: toOptionalString(initialData.selectedDate),
95973
96117
  selectedSlot: null,
95974
- fieldValues: collectInitialFieldValues(initialData),
96118
+ fieldValues: collectInitialBookingFieldValues(initialData),
95975
96119
  touchedFields: {},
95976
96120
  attemptedStepIds: {},
95977
96121
  discountCode: toOptionalString(initialData.discountCode) ?? "",
@@ -95983,14 +96127,6 @@ function createInitialBookingFlowReducerState(input) {
95983
96127
  feedback: { kind: "none" }
95984
96128
  };
95985
96129
  }
95986
- function collectInitialFieldValues(initialData) {
95987
- const values = {};
95988
- for (const [key, value] of Object.entries(initialData)) {
95989
- if (BOOKING_FORM_DATA_RESERVED_KEYS.has(key) || !isBookingFieldValue(value)) continue;
95990
- values[key] = value;
95991
- }
95992
- return values;
95993
- }
95994
96130
  function toOptionalString(value) {
95995
96131
  if (typeof value !== "string") return void 0;
95996
96132
  const trimmed = value.trim();
@@ -96009,9 +96145,6 @@ function toOptionalAppointmentResourceId(value) {
96009
96145
  function toOptionalCustomerPassId(value) {
96010
96146
  return toOptionalBrandedId(value, unsafeAsCustomerPassId);
96011
96147
  }
96012
- function isBookingFieldValue(value) {
96013
- return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || Array.isArray(value) && value.every((item) => typeof item === "string");
96014
- }
96015
96148
  /**
96016
96149
  * Send the flow back to the date step when the slot it was holding went away,
96017
96150
  * leaving a scoped feedback message. A completed booking is left alone.
@@ -96033,17 +96166,7 @@ function applyAvailabilitySelectionInvalidation(state, invalidation) {
96033
96166
  }
96034
96167
  function bookingFlowReducer(state, event) {
96035
96168
  switch (event.type) {
96036
- case "service-selected": return {
96037
- ...state,
96038
- selectedServiceId: event.serviceId,
96039
- selectedResourceId: void 0,
96040
- selectedDate: void 0,
96041
- selectedSlot: null,
96042
- selectedAppointmentPackageId: void 0,
96043
- selectedSlidingAmountInput: "",
96044
- selectedCollectionOptionKind: void 0,
96045
- validationErrors: clearBookingFormError(state.validationErrors)
96046
- };
96169
+ case "service-selected": return applyBookingServiceSelection(state, event.serviceId);
96047
96170
  case "resource-selected": return {
96048
96171
  ...state,
96049
96172
  selectedResourceId: event.resourceId ?? void 0,
@@ -96150,6 +96273,24 @@ function bookingFlowReducer(state, event) {
96150
96273
  default: return assertNever$11(event);
96151
96274
  }
96152
96275
  }
96276
+ function applyBookingServiceSelection(state, serviceId) {
96277
+ return {
96278
+ ...state,
96279
+ selectedServiceId: serviceId,
96280
+ selectedResourceId: void 0,
96281
+ selectedDate: void 0,
96282
+ selectedSlot: null,
96283
+ selectedAppointmentPackageId: void 0,
96284
+ selectedSlidingAmountInput: "",
96285
+ selectedCollectionOptionKind: void 0,
96286
+ fieldValues: omitBookingConsentEntries(state.fieldValues),
96287
+ touchedFields: omitBookingConsentEntries(state.touchedFields),
96288
+ validationErrors: {
96289
+ ...clearBookingFormError(state.validationErrors),
96290
+ fieldErrors: omitBookingConsentEntries(state.validationErrors.fieldErrors)
96291
+ }
96292
+ };
96293
+ }
96153
96294
  function clearAvailabilityFeedback(feedback) {
96154
96295
  return feedback.kind === "error" && feedback.scope === "availability" ? { kind: "none" } : feedback;
96155
96296
  }
@@ -96310,7 +96451,8 @@ function validateBookingFields(input) {
96310
96451
  return errors;
96311
96452
  }
96312
96453
  function validateBookingField(field, value) {
96313
- if (field.required && isBlankFieldValue(value)) return `${field.label} is required`;
96454
+ const requiredError = validateRequiredBookingField(field, value);
96455
+ if (requiredError) return requiredError;
96314
96456
  if (isBlankFieldValue(value)) return null;
96315
96457
  const strValue = typeof value === "string" ? value : String(value);
96316
96458
  if (field.type === "email") return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(strValue) ? null : "Please enter a valid email address";
@@ -96339,6 +96481,10 @@ function validateBookingField(field, value) {
96339
96481
  }
96340
96482
  return null;
96341
96483
  }
96484
+ function validateRequiredBookingField(field, value) {
96485
+ if (field.type === "booking_requirement_consent") return value === true ? null : `${field.label} is required`;
96486
+ return field.required && isBlankFieldValue(value) ? `${field.label} is required` : null;
96487
+ }
96342
96488
  function deriveBookingFlowSteps(input) {
96343
96489
  const stepResolution = buildBookingStepResolution({
96344
96490
  form: input.form,
@@ -96410,7 +96556,8 @@ function deriveBookingFieldViews(input) {
96410
96556
  return (input.form?.schema?.fields ?? []).map((field) => {
96411
96557
  const fieldId = unsafeAsBookingFieldId(field.id);
96412
96558
  const inputId = `${input.idPrefix}-${fieldId}`;
96413
- const helpTextId = field.helpText ? `${inputId}-help` : null;
96559
+ const helpText = field.type === "booking_requirement_consent" ? null : field.helpText ?? null;
96560
+ const helpTextId = helpText ? `${inputId}-help` : null;
96414
96561
  const fieldValue = input.values[field.id] ?? null;
96415
96562
  const localError = input.touched?.[field.id] ? validateBookingField(field, fieldValue) : null;
96416
96563
  const error = input.errors[field.id] ?? localError;
@@ -96420,17 +96567,17 @@ function deriveBookingFieldViews(input) {
96420
96567
  field,
96421
96568
  id: fieldId,
96422
96569
  label: field.label,
96423
- type: field.type,
96424
96570
  value: fieldValue,
96425
96571
  required: Boolean(field.required),
96426
96572
  error,
96427
- helpText: field.helpText ?? null,
96573
+ helpText,
96428
96574
  inputId,
96429
96575
  labelId: `${inputId}-label`,
96430
96576
  helpTextId,
96431
96577
  errorId,
96432
96578
  describedBy,
96433
- ariaInvalid: Boolean(error)
96579
+ ariaInvalid: Boolean(error),
96580
+ type: field.type
96434
96581
  };
96435
96582
  });
96436
96583
  }
@@ -96605,6 +96752,7 @@ var init_booking_form_headless_state = __esmMin((() => {
96605
96752
  init_dist$1();
96606
96753
  init_booking_form_state();
96607
96754
  init_booking_form_validationErrors();
96755
+ init_booking_form_field_values();
96608
96756
  unsafeAsBookingFieldId = (id) => id;
96609
96757
  }));
96610
96758
  //#endregion
@@ -96637,6 +96785,7 @@ function useHeadlessBookingFlow(options) {
96637
96785
  const selectedServiceId = state.selectedServiceId ?? defaultServiceId;
96638
96786
  const selectedResourceId = state.selectedResourceId ?? defaultResourceId;
96639
96787
  const selectedService = options.services.find((service) => service.id === selectedServiceId) ?? null;
96788
+ const runtimeForm = useSelectedAppointmentConsentForm(options.form, selectedService);
96640
96789
  const lastSlidingServiceIdRef = useRef(null);
96641
96790
  useEffect(() => {
96642
96791
  const selectedId = selectedService?.id ?? null;
@@ -96677,7 +96826,7 @@ function useHeadlessBookingFlow(options) {
96677
96826
  viewerTimeZone
96678
96827
  ]);
96679
96828
  const stepState = useMemo(() => deriveBookingFlowSteps({
96680
- form: options.form,
96829
+ form: runtimeForm,
96681
96830
  services: options.services,
96682
96831
  data,
96683
96832
  defaultServiceId,
@@ -96693,7 +96842,7 @@ function useHeadlessBookingFlow(options) {
96693
96842
  defaultServiceId,
96694
96843
  defaultResourceId,
96695
96844
  options.enableAppointmentPackages,
96696
- options.form,
96845
+ runtimeForm,
96697
96846
  options.requiresResourceSelection,
96698
96847
  options.requiresServiceSelection,
96699
96848
  options.services,
@@ -96747,13 +96896,13 @@ function useHeadlessBookingFlow(options) {
96747
96896
  state.selectedSlot
96748
96897
  ]);
96749
96898
  const fields = useMemo(() => deriveBookingFieldViews({
96750
- form: options.form,
96899
+ form: runtimeForm,
96751
96900
  values: state.fieldValues,
96752
96901
  errors: state.validationErrors.fieldErrors,
96753
96902
  touched: state.touchedFields,
96754
96903
  idPrefix: `booking-${options.formId}`
96755
96904
  }), [
96756
- options.form,
96905
+ runtimeForm,
96757
96906
  options.formId,
96758
96907
  state.fieldValues,
96759
96908
  state.touchedFields,
@@ -96873,7 +97022,7 @@ function useHeadlessBookingFlow(options) {
96873
97022
  const latestRef = useLatestRef({
96874
97023
  state,
96875
97024
  data,
96876
- form: options.form,
97025
+ form: runtimeForm,
96877
97026
  formId: formKey,
96878
97027
  services: options.services,
96879
97028
  defaultServiceId,
@@ -97125,7 +97274,7 @@ function useHeadlessBookingFlow(options) {
97125
97274
  phase: state.phase
97126
97275
  });
97127
97276
  const view = resolveHeadlessBookingView({
97128
- form: options.form,
97277
+ form: runtimeForm,
97129
97278
  feedback: state.feedback
97130
97279
  });
97131
97280
  const appointmentPackagesModel = resolveAppointmentPackagesModel({
@@ -97249,6 +97398,7 @@ var init_useHeadlessBookingFlow = __esmMin((() => {
97249
97398
  init_src$3();
97250
97399
  init_api();
97251
97400
  init_booking_form_state();
97401
+ init_useSelectedAppointmentConsentForm();
97252
97402
  init_useAvailableDates();
97253
97403
  init_useAvailableSlots();
97254
97404
  init_useBookingSubmission();
@@ -97974,6 +98124,195 @@ function FieldValidationMessage({ id, children, className, live = "assertive" })
97974
98124
  }
97975
98125
  var init_FieldValidationMessage = __esmMin((() => {}));
97976
98126
  //#endregion
98127
+ //#region ../blocks/src/primitives/content/utils/sanitizeHref.ts
98128
+ function normalizeInput(value) {
98129
+ return value.replace(CONTROL_CHARS_PATTERN, "").trim();
98130
+ }
98131
+ function decodeForSchemeCheck(value) {
98132
+ try {
98133
+ return decodeURIComponent(value);
98134
+ } catch {
98135
+ return value;
98136
+ }
98137
+ }
98138
+ /**
98139
+ * Returns a safe href for rich-text anchors, or null when the value should not be rendered.
98140
+ *
98141
+ * Policy:
98142
+ * - Allow absolute URLs with protocols: http, https, mailto, tel.
98143
+ * - Allow root-relative ("/path") and hash-only ("#section") links.
98144
+ * - Reject protocol-relative URLs ("//example.com"), bare domains ("example.com"),
98145
+ * executable schemes (javascript/data/vbscript), malformed URLs, and empty values.
98146
+ * - Preserve percent-encoding from the original normalized input.
98147
+ */
98148
+ function sanitizeHref(raw) {
98149
+ if (typeof raw !== "string") return null;
98150
+ const normalized = normalizeInput(raw);
98151
+ if (!normalized) return null;
98152
+ if (normalized.startsWith("//")) return null;
98153
+ if (normalized.startsWith("/")) return normalized;
98154
+ if (normalized.startsWith("#")) return normalized;
98155
+ const schemeMatch = normalizeInput(decodeForSchemeCheck(normalized)).match(/^([a-zA-Z][a-zA-Z0-9+.-]*):/);
98156
+ if (!schemeMatch) return null;
98157
+ const rawScheme = schemeMatch[1];
98158
+ if (!rawScheme) return null;
98159
+ const protocol = `${rawScheme.toLowerCase()}:`;
98160
+ if (!SAFE_PROTOCOLS.has(protocol)) return null;
98161
+ try {
98162
+ const parsed = new URL(normalized);
98163
+ if (!SAFE_PROTOCOLS.has(parsed.protocol.toLowerCase())) return null;
98164
+ } catch {
98165
+ return null;
98166
+ }
98167
+ return normalized;
98168
+ }
98169
+ var SAFE_PROTOCOLS, CONTROL_CHARS_PATTERN;
98170
+ var init_sanitizeHref = __esmMin((() => {
98171
+ SAFE_PROTOCOLS = /* @__PURE__ */ new Set([
98172
+ "http:",
98173
+ "https:",
98174
+ "mailto:",
98175
+ "tel:"
98176
+ ]);
98177
+ CONTROL_CHARS_PATTERN = /[\u0000-\u001F\u007F]+/g;
98178
+ }));
98179
+ //#endregion
98180
+ //#region ../blocks/src/primitives/content/components/RichText.tsx
98181
+ function parseDimension(value) {
98182
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) return Math.round(value);
98183
+ if (typeof value === "string" && value.trim().length > 0) {
98184
+ const parsed = Number(value);
98185
+ if (Number.isFinite(parsed) && parsed > 0) return Math.round(parsed);
98186
+ }
98187
+ }
98188
+ function normalizeRel(target, rel) {
98189
+ const normalizedRel = rel?.trim();
98190
+ if (target !== "_blank") return normalizedRel && normalizedRel.length > 0 ? normalizedRel : void 0;
98191
+ const tokens = new Set((normalizedRel ?? "").split(/\s+/).map((token) => token.trim().toLowerCase()).filter(Boolean));
98192
+ tokens.add("noopener");
98193
+ tokens.add("noreferrer");
98194
+ return Array.from(tokens).join(" ");
98195
+ }
98196
+ function renderMarks(text, marks, key, linkTarget) {
98197
+ if (!marks || marks.length === 0) return text;
98198
+ return marks.reduce((acc, mark) => {
98199
+ switch (mark.type) {
98200
+ case "bold":
98201
+ case "strong": return /* @__PURE__ */ jsx("strong", { children: acc }, `${key}-b`);
98202
+ case "italic":
98203
+ case "em": return /* @__PURE__ */ jsx("em", { children: acc }, `${key}-i`);
98204
+ case "link": {
98205
+ if (typeof acc === "string" && acc.length === 0) return acc;
98206
+ const attrs = mark.attrs ?? {};
98207
+ const href = sanitizeHref(attrs.href);
98208
+ if (!href) return acc;
98209
+ const storedTarget = typeof attrs.target === "string" && attrs.target.trim().length > 0 ? attrs.target.trim() : void 0;
98210
+ const target = linkTarget === "new-tab" ? "_blank" : storedTarget;
98211
+ return /* @__PURE__ */ jsx("a", {
98212
+ href,
98213
+ target,
98214
+ rel: normalizeRel(target, typeof attrs.rel === "string" ? attrs.rel : void 0),
98215
+ children: acc
98216
+ }, `${key}-l`);
98217
+ }
98218
+ default: return acc;
98219
+ }
98220
+ }, text);
98221
+ }
98222
+ function renderDoc(node, key, imageResolveContext, linkTarget) {
98223
+ if (!node || !node.type) return null;
98224
+ const children = node.content?.map((child, index) => renderDoc(child, `${key}-${index}`, imageResolveContext, linkTarget));
98225
+ switch (node.type) {
98226
+ case "doc": return /* @__PURE__ */ jsx(Fragment, { children });
98227
+ case "paragraph":
98228
+ if (!children && !node.text) return /* @__PURE__ */ jsx("p", {}, key);
98229
+ return /* @__PURE__ */ jsx("p", { children: children ?? renderMarks(node.text ?? "", node.marks, key, linkTarget) }, key);
98230
+ case "heading": {
98231
+ const headingTag = `h${Math.min(Math.max(node.attrs?.level ?? 2, 1), 6)}`;
98232
+ return React.createElement(headingTag, { key }, children);
98233
+ }
98234
+ case "bulletList": return /* @__PURE__ */ jsx("ul", { children }, key);
98235
+ case "orderedList": return /* @__PURE__ */ jsx("ol", { children }, key);
98236
+ case "listItem": return /* @__PURE__ */ jsx("li", { children }, key);
98237
+ case "blockquote": return /* @__PURE__ */ jsx("blockquote", { children }, key);
98238
+ case "horizontalRule": return /* @__PURE__ */ jsx("hr", {}, key);
98239
+ case "hardBreak": return /* @__PURE__ */ jsx("br", {}, key);
98240
+ case "image": {
98241
+ const attrs = node.attrs ?? {};
98242
+ const src = typeof attrs.src === "string" ? attrs.src.trim() : "";
98243
+ const identifier = typeof attrs.identifier === "string" ? attrs.identifier.trim() : "";
98244
+ const alt = typeof attrs.alt === "string" ? attrs.alt : "";
98245
+ const title = typeof attrs.title === "string" && attrs.title.trim().length > 0 ? attrs.title : void 0;
98246
+ const width = parseDimension(attrs.width);
98247
+ const height = parseDimension(attrs.height);
98248
+ const resolvedSrc = src || (identifier ? resolveImageUrlWithContext$1({
98249
+ type: "image",
98250
+ identifier
98251
+ }, width ? {
98252
+ width,
98253
+ resize: "contain",
98254
+ quality: 85
98255
+ } : height ? {
98256
+ height,
98257
+ resize: "contain",
98258
+ quality: 85
98259
+ } : ImagePresets$1.full, imageResolveContext ?? void 0) ?? "" : "");
98260
+ if (!resolvedSrc) return null;
98261
+ return /* @__PURE__ */ jsx("img", {
98262
+ src: resolvedSrc,
98263
+ alt,
98264
+ title,
98265
+ width,
98266
+ height,
98267
+ loading: "lazy",
98268
+ decoding: "async"
98269
+ }, key);
98270
+ }
98271
+ case "text": return renderMarks(node.text ?? "", node.marks, key, linkTarget);
98272
+ default: return null;
98273
+ }
98274
+ }
98275
+ function RichText$2({ as: Comp = "div", className, doc, path, linkTarget = "stored" }) {
98276
+ const imageResolveContext = getCurrentResolveImageUrlContext() ?? null;
98277
+ const content = doc ? renderDoc(doc, "doc", imageResolveContext, linkTarget) : null;
98278
+ const dataAttributes = path ? { "data-builder-richtext": path } : void 0;
98279
+ return /* @__PURE__ */ jsx(Comp, {
98280
+ className: className?.trim() || DEFAULT_RICH_TEXT_CLASS,
98281
+ ...dataAttributes,
98282
+ children: content
98283
+ });
98284
+ }
98285
+ var DEFAULT_RICH_TEXT_CLASS;
98286
+ var init_RichText = __esmMin((() => {
98287
+ init_sanitizeHref();
98288
+ init_media();
98289
+ DEFAULT_RICH_TEXT_CLASS = "rb-prose rb-max-w-none";
98290
+ }));
98291
+ //#endregion
98292
+ //#region ../blocks/src/system/runtime/shared/components/BookingConsentAgreement.tsx
98293
+ function BookingConsentAgreement({ agreement, showTitle = true, title, titleId }) {
98294
+ return /* @__PURE__ */ jsxs(Fragment, { children: [showTitle ? /* @__PURE__ */ jsxs("div", {
98295
+ id: titleId,
98296
+ className: "form-label",
98297
+ children: [title, /* @__PURE__ */ jsx("span", {
98298
+ className: "required-marker",
98299
+ children: "*"
98300
+ })]
98301
+ }) : null, /* @__PURE__ */ jsx("div", {
98302
+ role: "group",
98303
+ "aria-label": showTitle ? void 0 : title,
98304
+ "aria-labelledby": showTitle ? titleId : void 0,
98305
+ children: /* @__PURE__ */ jsx(RichText$2, {
98306
+ doc: agreement,
98307
+ linkTarget: "new-tab",
98308
+ className: "rb-prose rb-max-w-none"
98309
+ })
98310
+ })] });
98311
+ }
98312
+ var init_BookingConsentAgreement = __esmMin((() => {
98313
+ init_RichText();
98314
+ }));
98315
+ //#endregion
97977
98316
  //#region ../blocks/src/system/runtime/nodes/booking-form.default-ui.tsx
97978
98317
  function optionCardClassName(isSelected) {
97979
98318
  return `rb-option-card${isSelected ? " rb-option-card--selected" : ""}`;
@@ -98422,7 +98761,11 @@ function DefaultDynamicField({ booking, field }) {
98422
98761
  return /* @__PURE__ */ jsxs("div", {
98423
98762
  className: "rb-space-y-2",
98424
98763
  children: [
98425
- /* @__PURE__ */ jsxs("label", {
98764
+ field.field.type === "booking_requirement_consent" ? /* @__PURE__ */ jsx(BookingConsentAgreement, {
98765
+ agreement: field.field.agreement,
98766
+ title: field.label,
98767
+ titleId: field.labelId
98768
+ }) : /* @__PURE__ */ jsxs("label", {
98426
98769
  id: field.labelId,
98427
98770
  htmlFor: field.inputId,
98428
98771
  className: "form-label",
@@ -98467,7 +98810,7 @@ function DefaultFieldInput({ describedBy, error, errorId, field, onBlur, onChang
98467
98810
  required: field.required,
98468
98811
  ...validationProps
98469
98812
  };
98470
- switch (field.type) {
98813
+ switch (field.field.type) {
98471
98814
  case "textarea": return /* @__PURE__ */ jsx("textarea", {
98472
98815
  ...commonProps,
98473
98816
  value: strValue,
@@ -98581,7 +98924,7 @@ function DefaultFieldInput({ describedBy, error, errorId, field, onBlur, onChang
98581
98924
  className: "form-checkbox rb-mt-0.5"
98582
98925
  }), /* @__PURE__ */ jsx("span", {
98583
98926
  className: "rb-caption",
98584
- children: field.field.placeholder || field.label
98927
+ children: field.field.checkboxLabel
98585
98928
  })]
98586
98929
  });
98587
98930
  case "number": return /* @__PURE__ */ jsx("input", {
@@ -98650,10 +98993,10 @@ function DefaultBookingDiscount({ booking }) {
98650
98993
  children: /* @__PURE__ */ jsxs("p", {
98651
98994
  className: "ab-text",
98652
98995
  children: [
98653
- "Discount available: ",
98654
- booking.discount.autoAppliedDiscount.publicLabel,
98996
+ "Discount available:",
98655
98997
  " ",
98656
- "will apply automatically at checkout."
98998
+ booking.discount.autoAppliedDiscount.publicLabel,
98999
+ " will apply automatically at checkout."
98657
99000
  ]
98658
99001
  })
98659
99002
  }) : null]
@@ -98719,6 +99062,7 @@ var init_booking_form_default_ui = __esmMin((() => {
98719
99062
  init_FeedbackMessage();
98720
99063
  init_DiscountCodeDisclosure();
98721
99064
  init_FieldValidationMessage();
99065
+ init_BookingConsentAgreement();
98722
99066
  }));
98723
99067
  //#endregion
98724
99068
  //#region ../blocks/src/system/runtime/shared/utils/checkoutUrls.ts
@@ -101387,12 +101731,72 @@ var init_GuestDetailsSection = __esmMin((() => {
101387
101731
  }));
101388
101732
  //#endregion
101389
101733
  //#region ../blocks/src/system/runtime/nodes/event-registration/AttendeeDetailsStep.tsx
101734
+ function EventConsentField({ consent, error, formData, idBase, onChange }) {
101735
+ const errorId = `${idBase}-consent-error`;
101736
+ return /* @__PURE__ */ jsxs("div", {
101737
+ className: "er-field",
101738
+ children: [
101739
+ /* @__PURE__ */ jsx(BookingConsentAgreement, {
101740
+ agreement: consent.agreement,
101741
+ title: consent.title,
101742
+ titleId: `${idBase}-consent-title`
101743
+ }),
101744
+ /* @__PURE__ */ jsxs("label", {
101745
+ className: "er-label rb-flex rb-items-start rb-gap-2 rb-cursor-pointer",
101746
+ children: [
101747
+ /* @__PURE__ */ jsx("input", {
101748
+ "aria-describedby": error ? errorId : void 0,
101749
+ className: "form-checkbox rb-mt-0.5",
101750
+ checked: formData.consentAccepted === true,
101751
+ onChange: (event) => onChange({
101752
+ ...formData,
101753
+ consentAccepted: event.target.checked
101754
+ }),
101755
+ type: "checkbox"
101756
+ }),
101757
+ consent.checkboxLabel,
101758
+ " ",
101759
+ /* @__PURE__ */ jsx("span", {
101760
+ className: "er-required",
101761
+ children: "*"
101762
+ })
101763
+ ]
101764
+ }),
101765
+ error ? /* @__PURE__ */ jsx(FieldValidationMessage, {
101766
+ id: errorId,
101767
+ className: "er-error",
101768
+ children: error
101769
+ }) : null
101770
+ ]
101771
+ });
101772
+ }
101773
+ function resolveGuestDetailsChangeHandler(requireGuestDetails, ticketsCount, onGuestsChange) {
101774
+ return requireGuestDetails && ticketsCount > 1 && onGuestsChange ? onGuestsChange : null;
101775
+ }
101776
+ function NotesField({ id, onChange, value }) {
101777
+ return /* @__PURE__ */ jsxs("div", {
101778
+ className: "er-field",
101779
+ children: [/* @__PURE__ */ jsx("label", {
101780
+ className: "er-label",
101781
+ htmlFor: id,
101782
+ children: "Notes"
101783
+ }), /* @__PURE__ */ jsx("textarea", {
101784
+ id,
101785
+ value,
101786
+ onChange: (event) => onChange(event.target.value),
101787
+ className: "er-input",
101788
+ placeholder: "Any special requirements or notes (optional)",
101789
+ rows: 3
101790
+ })]
101791
+ });
101792
+ }
101390
101793
  var AttendeeDetailsStep;
101391
101794
  var init_AttendeeDetailsStep = __esmMin((() => {
101392
101795
  init_GuestDetailsSection();
101393
101796
  init_LoggedInAsUser();
101394
101797
  init_FieldValidationMessage();
101395
- AttendeeDetailsStep = ({ formData, onChange, errors, emailLocked = false, onLogout, ticketsCount = 1, requireGuestDetails = false, guests = [], onGuestsChange, guestErrors = {}, guestSectionShake = false, onGuestShakeEnd }) => {
101798
+ init_BookingConsentAgreement();
101799
+ AttendeeDetailsStep = ({ formData, onChange, errors, emailLocked = false, onLogout, ticketsCount = 1, requireGuestDetails = false, guests = [], onGuestsChange, guestErrors = {}, guestSectionShake = false, onGuestShakeEnd, consent }) => {
101396
101800
  const idBase = useId();
101397
101801
  const nameId = `${idBase}-name`;
101398
101802
  const emailId = `${idBase}-email`;
@@ -101408,7 +101812,7 @@ var init_AttendeeDetailsStep = __esmMin((() => {
101408
101812
  message: errors.email,
101409
101813
  messageId: emailErrorId
101410
101814
  });
101411
- const showGuestSection = requireGuestDetails && ticketsCount > 1 && onGuestsChange;
101815
+ const guestDetailsChangeHandler = resolveGuestDetailsChangeHandler(requireGuestDetails, ticketsCount, onGuestsChange);
101412
101816
  return /* @__PURE__ */ jsxs("div", {
101413
101817
  className: "rb-reg-stack er-stack",
101414
101818
  children: [
@@ -101501,29 +101905,26 @@ var init_AttendeeDetailsStep = __esmMin((() => {
101501
101905
  placeholder: "(optional)"
101502
101906
  })]
101503
101907
  }),
101504
- /* @__PURE__ */ jsxs("div", {
101505
- className: "er-field",
101506
- children: [/* @__PURE__ */ jsx("label", {
101507
- className: "er-label",
101508
- htmlFor: notesId,
101509
- children: "Notes"
101510
- }), /* @__PURE__ */ jsx("textarea", {
101511
- id: notesId,
101512
- value: formData.notes,
101513
- onChange: (e) => onChange({
101514
- ...formData,
101515
- notes: e.target.value
101516
- }),
101517
- className: "er-input",
101518
- placeholder: "Any special requirements or notes (optional)",
101519
- rows: 3
101520
- })]
101521
- })
101908
+ /* @__PURE__ */ jsx(NotesField, {
101909
+ id: notesId,
101910
+ value: formData.notes,
101911
+ onChange: (notes) => onChange({
101912
+ ...formData,
101913
+ notes
101914
+ })
101915
+ }),
101916
+ consent ? /* @__PURE__ */ jsx(EventConsentField, {
101917
+ consent,
101918
+ error: errors.consentAccepted,
101919
+ formData,
101920
+ idBase,
101921
+ onChange
101922
+ }) : null
101522
101923
  ] }),
101523
- showGuestSection && /* @__PURE__ */ jsx(GuestDetailsSection, {
101924
+ guestDetailsChangeHandler && /* @__PURE__ */ jsx(GuestDetailsSection, {
101524
101925
  guests,
101525
101926
  errors: guestErrors,
101526
- onChange: onGuestsChange,
101927
+ onChange: guestDetailsChangeHandler,
101527
101928
  shake: guestSectionShake,
101528
101929
  onShakeEnd: onGuestShakeEnd
101529
101930
  })
@@ -102330,6 +102731,9 @@ var init_event_registration = __esmMin((() => {
102330
102731
  }));
102331
102732
  //#endregion
102332
102733
  //#region ../blocks/src/system/runtime/nodes/event-registration/EventRegistrationWizardContent.tsx
102734
+ function getWizardConsent(wizard) {
102735
+ return (wizard.selectedEvent ?? wizard.preSelectedEvent)?.consent ?? null;
102736
+ }
102333
102737
  function EventRegistrationWizardContent(props) {
102334
102738
  const { wizard } = props;
102335
102739
  const showSpamProtection = props.showSpamProtection ?? isSpamProtectionEnabled();
@@ -102409,7 +102813,8 @@ function EventRegistrationWizardContent(props) {
102409
102813
  onGuestsChange: wizard.setGuests,
102410
102814
  guestErrors: wizard.guestErrors,
102411
102815
  guestSectionShake: wizard.guestSectionShake,
102412
- onGuestShakeEnd: wizard.handleGuestShakeEnd
102816
+ onGuestShakeEnd: wizard.handleGuestShakeEnd,
102817
+ consent: getWizardConsent(wizard)
102413
102818
  }),
102414
102819
  showSpamProtection && /* @__PURE__ */ jsx("div", {
102415
102820
  className: "er-altcha",
@@ -102792,11 +103197,21 @@ var init_EventRegistrationSummaryBar = __esmMin((() => {
102792
103197
  }));
102793
103198
  //#endregion
102794
103199
  //#region ../blocks/src/system/runtime/nodes/event-registration/validation.ts
102795
- function validateFormData(formData) {
103200
+ function createInitialRegistrationFormData() {
103201
+ return {
103202
+ name: "",
103203
+ email: "",
103204
+ phone: "",
103205
+ notes: "",
103206
+ consentAccepted: false
103207
+ };
103208
+ }
103209
+ function validateFormData(formData, requiresConsent = false) {
102796
103210
  const errors = {};
102797
103211
  if (!formData.name.trim()) errors.name = "Name is required";
102798
103212
  if (!formData.email.trim()) errors.email = "Email is required";
102799
103213
  else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) errors.email = "Invalid email address";
103214
+ if (requiresConsent && formData.consentAccepted !== true) errors.consentAccepted = "Please read and accept the agreement before continuing.";
102800
103215
  return errors;
102801
103216
  }
102802
103217
  var init_validation = __esmMin((() => {}));
@@ -103177,6 +103592,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
103177
103592
  name: options.formData.name.trim(),
103178
103593
  phone: options.formData.phone.trim() || void 0,
103179
103594
  notes: options.formData.notes.trim() || void 0,
103595
+ consentAccepted: options.formData.consentAccepted,
103180
103596
  altchaSolution: options.altchaSolution,
103181
103597
  paymentMethod: method,
103182
103598
  customerPassId: method === "pass" ? passId : void 0,
@@ -103312,12 +103728,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
103312
103728
  const step = flowState.step;
103313
103729
  const paymentSelection = flowState.paymentSelection;
103314
103730
  const [selectedEvent, setSelectedEvent] = useState(preSelectedEvent ?? null);
103315
- const [formData, setFormData] = useState({
103316
- name: "",
103317
- email: "",
103318
- phone: "",
103319
- notes: ""
103320
- });
103731
+ const [formData, setFormData] = useState(createInitialRegistrationFormData);
103321
103732
  const [errors, setErrors] = useState({});
103322
103733
  const [guests, setGuests] = useState([]);
103323
103734
  const [guestErrors, setGuestErrors] = useState({});
@@ -103615,7 +104026,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
103615
104026
  guests
103616
104027
  ]);
103617
104028
  const validateForm = () => {
103618
- const newErrors = validateFormData(formData);
104029
+ const newErrors = validateFormData(formData, Boolean(currentEvent?.consent));
103619
104030
  setErrors(newErrors);
103620
104031
  const newGuestErrors = {};
103621
104032
  if (requireGuestDetails && guests.length > 0) {
@@ -103804,6 +104215,10 @@ function useEventRegistrationWizardWithDeps(options, deps) {
103804
104215
  });
103805
104216
  const handleEventSelect = (event) => {
103806
104217
  setSelectedEvent(event);
104218
+ setFormData((current) => ({
104219
+ ...current,
104220
+ consentAccepted: false
104221
+ }));
103807
104222
  const slidingScale = getSlidingScaleForEvent(event);
103808
104223
  setSelectedSlidingAmountInput(slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput$1(slidingScale.suggestedAmount) : "");
103809
104224
  setSelectedAttendanceMode((event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person");
@@ -105071,6 +105486,7 @@ function validateSubmission(state, setters) {
105071
105486
  message: "Choose an available set of dates to continue."
105072
105487
  };
105073
105488
  const errors = validateFormData$1(state.formData);
105489
+ if (state.selectedRun.consent && state.formData.consentAccepted !== true) errors.consentAccepted = "Please read and accept the agreement before continuing.";
105074
105490
  setters.setErrors(errors);
105075
105491
  if (Object.keys(errors).length > 0) return { kind: "validation-failed" };
105076
105492
  const pricingMessage = getMissingWholeSeriesPricingSelectionMessage(state.pricing);
@@ -105094,6 +105510,7 @@ function registrantPayload(state) {
105094
105510
  name: state.formData.name.trim(),
105095
105511
  phone: state.formData.phone.trim() || void 0,
105096
105512
  formData: { notes: state.formData.notes.trim() || void 0 },
105513
+ consentAccepted: state.formData.consentAccepted,
105097
105514
  altchaSolution: state.altchaSolution,
105098
105515
  claimToken: state.claimToken ?? void 0
105099
105516
  };
@@ -105259,7 +105676,8 @@ var init_useWholeSeriesRegistrationPortal = __esmMin((() => {
105259
105676
  name: "",
105260
105677
  email: "",
105261
105678
  phone: "",
105262
- notes: ""
105679
+ notes: "",
105680
+ consentAccepted: false
105263
105681
  };
105264
105682
  }));
105265
105683
  //#endregion
@@ -105790,19 +106208,65 @@ function WholeSeriesSlidingScaleInput({ pricing, value, onChange }) {
105790
106208
  ]
105791
106209
  });
105792
106210
  }
105793
- function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
105794
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(EnrollmentIdentityFields, {
105795
- formData,
105796
- errors,
105797
- onChange,
105798
- isEmailLocked,
105799
- isLoading,
105800
- onLogout
105801
- }), /* @__PURE__ */ jsx(EnrollmentOptionalFields, {
105802
- formData,
105803
- onChange,
105804
- isLoading
105805
- })] });
106211
+ function WholeSeriesConsentField({ consent, error, formData, isLoading, onChange }) {
106212
+ const errorId = "er-whole-series-consent-error";
106213
+ return /* @__PURE__ */ jsxs("div", {
106214
+ className: "er-whole-series-form__field",
106215
+ children: [
106216
+ /* @__PURE__ */ jsx(BookingConsentAgreement, {
106217
+ agreement: consent.agreement,
106218
+ title: consent.title,
106219
+ titleId: "er-whole-series-consent-title"
106220
+ }),
106221
+ /* @__PURE__ */ jsxs("label", {
106222
+ className: "er-whole-series-form__label rb-flex rb-items-start rb-gap-2 rb-cursor-pointer",
106223
+ children: [
106224
+ /* @__PURE__ */ jsx("input", {
106225
+ type: "checkbox",
106226
+ className: "form-checkbox rb-mt-0.5",
106227
+ checked: formData.consentAccepted === true,
106228
+ disabled: isLoading,
106229
+ "aria-describedby": error ? errorId : void 0,
106230
+ onChange: (event) => onChange({
106231
+ ...formData,
106232
+ consentAccepted: event.target.checked
106233
+ })
106234
+ }),
106235
+ consent.checkboxLabel,
106236
+ " *"
106237
+ ]
106238
+ }),
106239
+ error ? /* @__PURE__ */ jsx(FieldValidationMessage, {
106240
+ id: errorId,
106241
+ className: "er-whole-series-form__error",
106242
+ children: error
106243
+ }) : null
106244
+ ]
106245
+ });
106246
+ }
106247
+ function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading, onLogout, consent }) {
106248
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
106249
+ /* @__PURE__ */ jsx(EnrollmentIdentityFields, {
106250
+ formData,
106251
+ errors,
106252
+ onChange,
106253
+ isEmailLocked,
106254
+ isLoading,
106255
+ onLogout
106256
+ }),
106257
+ /* @__PURE__ */ jsx(EnrollmentOptionalFields, {
106258
+ formData,
106259
+ onChange,
106260
+ isLoading
106261
+ }),
106262
+ consent ? /* @__PURE__ */ jsx(WholeSeriesConsentField, {
106263
+ consent,
106264
+ error: errors.consentAccepted,
106265
+ formData,
106266
+ isLoading,
106267
+ onChange
106268
+ }) : null
106269
+ ] });
105806
106270
  }
105807
106271
  function EnrollmentIdentityFields({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
105808
106272
  const nameErrorId = "er-whole-series-name-error";
@@ -105916,6 +106380,7 @@ var init_components = __esmMin((() => {
105916
106380
  init_utils();
105917
106381
  init_LoggedInAsUser();
105918
106382
  init_FieldValidationMessage();
106383
+ init_BookingConsentAgreement();
105919
106384
  }));
105920
106385
  //#endregion
105921
106386
  //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationActiveSteps.tsx
@@ -106003,7 +106468,8 @@ function RegistrationDetailsForm({ wizard, display }) {
106003
106468
  onChange: wizard.updateFormData,
106004
106469
  isEmailLocked: wizard.portalAuthState === "authenticated" || wizard.waitlistClaim.claim !== null,
106005
106470
  isLoading: wizard.portalAuthState === "checking" || wizard.waitlistClaim.isLoading,
106006
- onLogout: wizard.handleLogout
106471
+ onLogout: wizard.handleLogout,
106472
+ consent: wizard.selectedRun?.consent ?? null
106007
106473
  }),
106008
106474
  /* @__PURE__ */ jsx(PricingFields, { wizard }),
106009
106475
  wizard.showSpamProtection ? /* @__PURE__ */ jsx("div", {
@@ -106603,33 +107069,6 @@ var init_WholeSeriesRegistrationWizard = __esmMin((() => {
106603
107069
  };
106604
107070
  }));
106605
107071
  //#endregion
106606
- //#region ../blocks/src/system/runtime/nodes/event-registration/registrationSurface.ts
106607
- function planEventRegistrationSurface(input) {
106608
- const scopedEvents = resolveEventRegistrationScopedEvents(input.events, {
106609
- occurrenceContext: input.occurrenceContext,
106610
- subject: input.subject
106611
- });
106612
- const bookingScopes = new Set(scopedEvents.map((event) => event.bookingScope));
106613
- if (!input.occurrenceContext && !input.subject && bookingScopes.has("single_occurrence")) return {
106614
- kind: "occurrence",
106615
- events: scopedEvents.filter((event) => event.bookingScope === "single_occurrence")
106616
- };
106617
- if (bookingScopes.size === 0 || bookingScopes.has("single_occurrence")) return bookingScopes.has("whole_series") ? { kind: "mixedBookingScopes" } : {
106618
- kind: "occurrence",
106619
- events: scopedEvents
106620
- };
106621
- const requiredSeriesIds = new Set(scopedEvents.map((event) => event.seriesId));
106622
- const offerings = input.wholeSeriesOfferings.filter((offering) => requiredSeriesIds.has(offering.eventSeriesId));
106623
- const loadedSeriesIds = new Set(offerings.map((offering) => offering.eventSeriesId));
106624
- return [...requiredSeriesIds].every((seriesId) => loadedSeriesIds.has(seriesId)) && offerings.length > 0 ? {
106625
- kind: "wholeSeries",
106626
- offerings
106627
- } : { kind: "unavailableWholeSeries" };
106628
- }
106629
- var init_registrationSurface = __esmMin((() => {
106630
- init_eventScope();
106631
- }));
106632
- //#endregion
106633
107072
  //#region ../blocks/src/system/runtime/nodes/event-registration/PastOccurrenceNotice.tsx
106634
107073
  function isPastOccurrence(startsAt) {
106635
107074
  if (!startsAt) return false;
@@ -106724,7 +107163,8 @@ var init_event_registration_client = __esmMin((() => {
106724
107163
  EventRegistrationClient = (clientProps) => {
106725
107164
  const surface = planEventRegistrationSurface({
106726
107165
  events: clientProps.events ?? [],
106727
- wholeSeriesOfferings: clientProps.wholeSeriesOffering ? [clientProps.wholeSeriesOffering] : clientProps.wholeSeriesOfferings ?? [],
107166
+ wholeSeriesOfferings: clientProps.wholeSeriesOfferings ?? [],
107167
+ wholeSeriesOffering: clientProps.wholeSeriesOffering,
106728
107168
  occurrenceContext: clientProps.occurrenceContext,
106729
107169
  subject: clientProps.subject
106730
107170
  });
@@ -110502,170 +110942,6 @@ var init_eventCombined = __esmMin((() => {
110502
110942
  };
110503
110943
  }));
110504
110944
  //#endregion
110505
- //#region ../blocks/src/primitives/content/utils/sanitizeHref.ts
110506
- function normalizeInput(value) {
110507
- return value.replace(CONTROL_CHARS_PATTERN, "").trim();
110508
- }
110509
- function decodeForSchemeCheck(value) {
110510
- try {
110511
- return decodeURIComponent(value);
110512
- } catch {
110513
- return value;
110514
- }
110515
- }
110516
- /**
110517
- * Returns a safe href for rich-text anchors, or null when the value should not be rendered.
110518
- *
110519
- * Policy:
110520
- * - Allow absolute URLs with protocols: http, https, mailto, tel.
110521
- * - Allow root-relative ("/path") and hash-only ("#section") links.
110522
- * - Reject protocol-relative URLs ("//example.com"), bare domains ("example.com"),
110523
- * executable schemes (javascript/data/vbscript), malformed URLs, and empty values.
110524
- * - Preserve percent-encoding from the original normalized input.
110525
- */
110526
- function sanitizeHref(raw) {
110527
- if (typeof raw !== "string") return null;
110528
- const normalized = normalizeInput(raw);
110529
- if (!normalized) return null;
110530
- if (normalized.startsWith("//")) return null;
110531
- if (normalized.startsWith("/")) return normalized;
110532
- if (normalized.startsWith("#")) return normalized;
110533
- const schemeMatch = normalizeInput(decodeForSchemeCheck(normalized)).match(/^([a-zA-Z][a-zA-Z0-9+.-]*):/);
110534
- if (!schemeMatch) return null;
110535
- const rawScheme = schemeMatch[1];
110536
- if (!rawScheme) return null;
110537
- const protocol = `${rawScheme.toLowerCase()}:`;
110538
- if (!SAFE_PROTOCOLS.has(protocol)) return null;
110539
- try {
110540
- const parsed = new URL(normalized);
110541
- if (!SAFE_PROTOCOLS.has(parsed.protocol.toLowerCase())) return null;
110542
- } catch {
110543
- return null;
110544
- }
110545
- return normalized;
110546
- }
110547
- var SAFE_PROTOCOLS, CONTROL_CHARS_PATTERN;
110548
- var init_sanitizeHref = __esmMin((() => {
110549
- SAFE_PROTOCOLS = /* @__PURE__ */ new Set([
110550
- "http:",
110551
- "https:",
110552
- "mailto:",
110553
- "tel:"
110554
- ]);
110555
- CONTROL_CHARS_PATTERN = /[\u0000-\u001F\u007F]+/g;
110556
- }));
110557
- //#endregion
110558
- //#region ../blocks/src/primitives/content/components/RichText.tsx
110559
- function parseDimension(value) {
110560
- if (typeof value === "number" && Number.isFinite(value) && value > 0) return Math.round(value);
110561
- if (typeof value === "string" && value.trim().length > 0) {
110562
- const parsed = Number(value);
110563
- if (Number.isFinite(parsed) && parsed > 0) return Math.round(parsed);
110564
- }
110565
- }
110566
- function normalizeRel(target, rel) {
110567
- const normalizedRel = rel?.trim();
110568
- if (target !== "_blank") return normalizedRel && normalizedRel.length > 0 ? normalizedRel : void 0;
110569
- const tokens = new Set((normalizedRel ?? "").split(/\s+/).map((token) => token.trim().toLowerCase()).filter(Boolean));
110570
- tokens.add("noopener");
110571
- tokens.add("noreferrer");
110572
- return Array.from(tokens).join(" ");
110573
- }
110574
- function renderMarks(text, marks, key) {
110575
- if (!marks || marks.length === 0) return text;
110576
- return marks.reduce((acc, mark) => {
110577
- switch (mark.type) {
110578
- case "bold":
110579
- case "strong": return /* @__PURE__ */ jsx("strong", { children: acc }, `${key}-b`);
110580
- case "italic":
110581
- case "em": return /* @__PURE__ */ jsx("em", { children: acc }, `${key}-i`);
110582
- case "link": {
110583
- if (typeof acc === "string" && acc.length === 0) return acc;
110584
- const attrs = mark.attrs ?? {};
110585
- const href = sanitizeHref(attrs.href);
110586
- if (!href) return acc;
110587
- const target = typeof attrs.target === "string" && attrs.target.trim().length > 0 ? attrs.target.trim() : void 0;
110588
- return /* @__PURE__ */ jsx("a", {
110589
- href,
110590
- target,
110591
- rel: normalizeRel(target, typeof attrs.rel === "string" ? attrs.rel : void 0),
110592
- children: acc
110593
- }, `${key}-l`);
110594
- }
110595
- default: return acc;
110596
- }
110597
- }, text);
110598
- }
110599
- function renderDoc(node, key, imageResolveContext) {
110600
- if (!node || !node.type) return null;
110601
- const children = node.content?.map((child, index) => renderDoc(child, `${key}-${index}`, imageResolveContext));
110602
- switch (node.type) {
110603
- case "doc": return /* @__PURE__ */ jsx(Fragment, { children });
110604
- case "paragraph":
110605
- if (!children && !node.text) return /* @__PURE__ */ jsx("p", {}, key);
110606
- return /* @__PURE__ */ jsx("p", { children: children ?? renderMarks(node.text ?? "", node.marks, key) }, key);
110607
- case "heading": {
110608
- const headingTag = `h${Math.min(Math.max(node.attrs?.level ?? 2, 1), 6)}`;
110609
- return React.createElement(headingTag, { key }, children);
110610
- }
110611
- case "bulletList": return /* @__PURE__ */ jsx("ul", { children }, key);
110612
- case "orderedList": return /* @__PURE__ */ jsx("ol", { children }, key);
110613
- case "listItem": return /* @__PURE__ */ jsx("li", { children }, key);
110614
- case "blockquote": return /* @__PURE__ */ jsx("blockquote", { children }, key);
110615
- case "horizontalRule": return /* @__PURE__ */ jsx("hr", {}, key);
110616
- case "hardBreak": return /* @__PURE__ */ jsx("br", {}, key);
110617
- case "image": {
110618
- const attrs = node.attrs ?? {};
110619
- const src = typeof attrs.src === "string" ? attrs.src.trim() : "";
110620
- const identifier = typeof attrs.identifier === "string" ? attrs.identifier.trim() : "";
110621
- const alt = typeof attrs.alt === "string" ? attrs.alt : "";
110622
- const title = typeof attrs.title === "string" && attrs.title.trim().length > 0 ? attrs.title : void 0;
110623
- const width = parseDimension(attrs.width);
110624
- const height = parseDimension(attrs.height);
110625
- const resolvedSrc = src || (identifier ? resolveImageUrlWithContext$1({
110626
- type: "image",
110627
- identifier
110628
- }, width ? {
110629
- width,
110630
- resize: "contain",
110631
- quality: 85
110632
- } : height ? {
110633
- height,
110634
- resize: "contain",
110635
- quality: 85
110636
- } : ImagePresets$1.full, imageResolveContext ?? void 0) ?? "" : "");
110637
- if (!resolvedSrc) return null;
110638
- return /* @__PURE__ */ jsx("img", {
110639
- src: resolvedSrc,
110640
- alt,
110641
- title,
110642
- width,
110643
- height,
110644
- loading: "lazy",
110645
- decoding: "async"
110646
- }, key);
110647
- }
110648
- case "text": return renderMarks(node.text ?? "", node.marks, key);
110649
- default: return null;
110650
- }
110651
- }
110652
- function RichText$2({ as: Comp = "div", className, doc, path }) {
110653
- const imageResolveContext = getCurrentResolveImageUrlContext() ?? null;
110654
- const content = doc ? renderDoc(doc, "doc", imageResolveContext) : null;
110655
- const dataAttributes = path ? { "data-builder-richtext": path } : void 0;
110656
- return /* @__PURE__ */ jsx(Comp, {
110657
- className: className?.trim() || DEFAULT_RICH_TEXT_CLASS,
110658
- ...dataAttributes,
110659
- children: content
110660
- });
110661
- }
110662
- var DEFAULT_RICH_TEXT_CLASS;
110663
- var init_RichText = __esmMin((() => {
110664
- init_sanitizeHref();
110665
- init_media();
110666
- DEFAULT_RICH_TEXT_CLASS = "rb-prose rb-max-w-none";
110667
- }));
110668
- //#endregion
110669
110945
  //#region ../blocks/src/system/runtime/nodes/richText-coerce.ts
110670
110946
  function parseRichTextDoc(value) {
110671
110947
  const parsed = RichTextDocSchema.safeParse(value);
@@ -113101,6 +113377,11 @@ function BlocksIslandsHydrator(props = {}) {
113101
113377
  //#endregion
113102
113378
  //#region ../blocks/src/system/types/link.ts
113103
113379
  const nullableString = z$1.union([z$1.string().min(1), z$1.null()]);
113380
+ const RESOLVED_INTERNAL_LINK_ENTITY_TYPES = [
113381
+ "page",
113382
+ "content",
113383
+ "pageSurface"
113384
+ ];
113104
113385
  const resolvedInternalLinkKeys = [
113105
113386
  "entityId",
113106
113387
  "entityType",
@@ -113122,7 +113403,7 @@ const internalResolvedLinkSchema = z$1.object({
113122
113403
  kind: z$1.literal("internal"),
113123
113404
  routeId: z$1.string().min(1),
113124
113405
  entityId: z$1.string().min(1),
113125
- entityType: z$1.enum(["page", "content"]),
113406
+ entityType: z$1.enum(RESOLVED_INTERNAL_LINK_ENTITY_TYPES),
113126
113407
  href: z$1.string().min(1),
113127
113408
  title: z$1.string().min(1),
113128
113409
  typeLabel: z$1.string().min(1),
@@ -123163,6 +123444,7 @@ function normalizeGroupPresentation(value) {
123163
123444
  function resolveAutoCtaPath(source, routes) {
123164
123445
  const routeByNormalizedPath = /* @__PURE__ */ new Map();
123165
123446
  for (const route of routes ?? []) {
123447
+ if (route.kind === "pageSurface") continue;
123166
123448
  const normalized = normalizeRoutePath(route.path);
123167
123449
  if (normalized && !routeByNormalizedPath.has(normalized)) routeByNormalizedPath.set(normalized, route.path);
123168
123450
  }
@@ -123223,7 +123505,7 @@ const publicRouteCandidatesSchema = z$1.object({ routes: z$1.array(z$1.object({
123223
123505
  entityId: z$1.string(),
123224
123506
  path: z$1.string(),
123225
123507
  title: z$1.string(),
123226
- kind: z$1.enum(["page", "content"]),
123508
+ kind: z$1.enum(RESOLVED_INTERNAL_LINK_ENTITY_TYPES),
123227
123509
  contentTypeKey: z$1.string().nullable().optional()
123228
123510
  })) });
123229
123511
  const groupOverrideFields = [
@@ -133632,18 +133914,53 @@ init_defineBlock();
133632
133914
  //#endregion
133633
133915
  //#region ../blocks/src/system/manifest/hydrateLinks.ts
133634
133916
  init_typeGuards();
133917
+ init_bookingConsent();
133635
133918
  /**
133636
133919
  * Hydrates link objects within block content using the provided route map. Returns
133637
133920
  * the original content reference when no mutations are required to avoid unnecessary renders.
133638
133921
  */
133639
133922
  function hydrateManifestLinks(manifest, content, routes, pagesByIdentifier, entriesByIdentifier) {
133640
133923
  if (!routes || !manifest?.fields?.length) return content;
133641
- return hydrateValue(content, {
133924
+ return hydrateLinks(content, routes, pagesByIdentifier, entriesByIdentifier);
133925
+ }
133926
+ /** Hydrate identifier-aware links in data loaded after manifest content. */
133927
+ function hydrateLinks(value, routes, pagesByIdentifier, entriesByIdentifier) {
133928
+ return hydrateValue(value, {
133929
+ routes,
133930
+ pagesByIdentifier,
133931
+ entriesByIdentifier
133932
+ });
133933
+ }
133934
+ /**
133935
+ * Hydrate links only inside resolved booking-consent documents. Loader payloads are
133936
+ * otherwise opaque and may legitimately contain objects that resemble link values.
133937
+ */
133938
+ function hydrateResolvedBookingConsentLinks(value, routes, pagesByIdentifier, entriesByIdentifier) {
133939
+ return hydrateResolvedBookingConsentValue(value, {
133642
133940
  routes,
133643
133941
  pagesByIdentifier,
133644
133942
  entriesByIdentifier
133645
133943
  });
133646
133944
  }
133945
+ function hydrateResolvedBookingConsentValue(value, context) {
133946
+ if (Array.isArray(value)) {
133947
+ const hydratedItems = value.map((item) => hydrateResolvedBookingConsentValue(item, context));
133948
+ return hydratedItems.every((item, index) => item === value[index]) ? value : hydratedItems;
133949
+ }
133950
+ if (!isRecord$32(value)) return value;
133951
+ if (isBookingConsentCarrier(value)) {
133952
+ const agreement = hydrateValue(value.agreement, context);
133953
+ return agreement === value.agreement ? value : {
133954
+ ...value,
133955
+ agreement
133956
+ };
133957
+ }
133958
+ const hydratedEntries = Object.entries(value).map(([key, entry]) => [key, hydrateResolvedBookingConsentValue(entry, context)]);
133959
+ return hydratedEntries.every(([key, entry]) => entry === value[key]) ? value : Object.fromEntries(hydratedEntries);
133960
+ }
133961
+ function isBookingConsentCarrier(value) {
133962
+ return bookingConsentCarrierSchema.safeParse(value).success;
133963
+ }
133647
133964
  function hydrateValue(value, context) {
133648
133965
  try {
133649
133966
  if (Array.isArray(value)) {
@@ -133712,6 +134029,14 @@ function hydrateEntryLink(link, context) {
133712
134029
  };
133713
134030
  }
133714
134031
  //#endregion
134032
+ //#region ../blocks/src/system/manifest/resolveBlockData.ts
134033
+ init_typeGuards();
134034
+ function resolveBlockData$1(blockId, dataLoaders, dataContext, routes) {
134035
+ const raw = blockId ? dataContext?.resolvedData?.[blockId] : void 0;
134036
+ if (isRecord$32(raw)) return routes ? hydrateResolvedBookingConsentLinks(raw, routes, dataContext?.pagesByIdentifier, dataContext?.entriesByIdentifier) : raw;
134037
+ return dataLoaders && typeof dataLoaders === "object" && Object.keys(dataLoaders).length > 0 ? {} : void 0;
134038
+ }
134039
+ //#endregion
133715
134040
  //#region ../blocks/src/sdkBlockTransform.ts
133716
134041
  init_augmentManifest();
133717
134042
  /**
@@ -134317,8 +134642,8 @@ function generateInputCss({ themeId, theme, inputSystem }) {
134317
134642
  const radioSelector = `${rootSelector} .form-radio`;
134318
134643
  const checkableRules = [];
134319
134644
  checkableRules.push("appearance: none");
134320
- checkableRules.push("width: 1rem");
134321
- checkableRules.push("height: 1rem");
134645
+ checkableRules.push("width: 1.125rem");
134646
+ checkableRules.push("height: 1.125rem");
134322
134647
  checkableRules.push("flex-shrink: 0");
134323
134648
  checkableRules.push(`border: ${borderPx} solid ${rgbColorValue(inputSystem.base.border.colorToken)}`);
134324
134649
  if (inputSystem.base.background.type === "transparent") checkableRules.push("background-color: transparent");
@@ -138130,11 +138455,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeResources
138130
138455
  try {
138131
138456
  const routes = routeMap ?? dataContext?.routes;
138132
138457
  const hydratedContent = routes ? hydrateManifestLinks(definition.manifest, data, routes, dataContext?.pagesByIdentifier, dataContext?.entriesByIdentifier) : data;
138133
- const resolved = resolveBlockData$1({
138134
- block,
138135
- definition,
138136
- dataContext
138137
- });
138458
+ const resolved = resolveBlockData$1(block.id, definition.dataLoaders, dataContext, routes);
138138
138459
  const hasResolvedData = !!resolved && typeof resolved === "object" && Object.keys(resolved).length > 0;
138139
138460
  const baseProps = {
138140
138461
  content: hydratedContent,
@@ -138224,12 +138545,6 @@ function shouldDebugCustomBlocks() {
138224
138545
  return false;
138225
138546
  }
138226
138547
  }
138227
- function resolveBlockData$1({ block, definition, dataContext }) {
138228
- const blockId = block.id ?? null;
138229
- const raw = blockId ? dataContext?.resolvedData?.[blockId] : void 0;
138230
- if (isObjectRecord$2(raw)) return { ...raw };
138231
- return definition.dataLoaders && Object.keys(definition.dataLoaders).length > 0 ? {} : void 0;
138232
- }
138233
138548
  /**
138234
138549
  * Resolves block content based on stage priority.
138235
138550
  * For draft/preview: draftContent takes priority over content.
@@ -154789,6 +155104,7 @@ init_media$1();
154789
155104
  init_slotContracts();
154790
155105
  init_typeGuards();
154791
155106
  init_booking_form_reserved_fields();
155107
+ init_bookingConsent();
154792
155108
  init_backgroundContent();
154793
155109
  init_events$2();
154794
155110
  init_colorStyles();
@@ -156625,7 +156941,7 @@ const internalLinkPayloadSchema = z$1.object({
156625
156941
  kind: z$1.literal("internal"),
156626
156942
  routeId: z$1.string().uuid(),
156627
156943
  entityId: z$1.string().uuid(),
156628
- entityType: z$1.enum(["page", "content"]),
156944
+ entityType: z$1.enum(RESOLVED_INTERNAL_LINK_ENTITY_TYPES),
156629
156945
  href: z$1.string().min(1),
156630
156946
  title: z$1.string().min(1),
156631
156947
  typeLabel: z$1.string().min(1),
@@ -157768,6 +158084,9 @@ function isNavigationMenuValidationItem(value) {
157768
158084
  return typeof value.label === "string";
157769
158085
  }
157770
158086
  //#endregion
158087
+ //#region ../api/src/navigation/routableLink.ts
158088
+ init_src$3();
158089
+ //#endregion
157771
158090
  //#region ../api/src/navigation/visibility.ts
157772
158091
  /**
157773
158092
  * Navigation Visibility Rules