@riverbankcms/sdk 0.139.0 → 0.140.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 (196) hide show
  1. package/README.md +1 -1
  2. package/dist/{PreviewEditorSidebar-BDeenhi3.mjs → PreviewEditorSidebar-CUyTzd5z.mjs} +4 -4
  3. package/dist/{PreviewEditorUI-DSRhgjF5.mjs → PreviewEditorUI-Agkw4v5i.mjs} +3 -3
  4. package/dist/{PreviewQueryProvider-D2K8GLUG.mjs → PreviewQueryProvider-CN0ewic5.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-CL7wSnYu.mjs → SdkPreviewModeRuntime-DdbeAdS8.mjs} +22 -8
  6. package/dist/{SiteChromeCustomizeContext-BhDn-5ir.mjs → SiteChromeCustomizeContext-CqGOz-Kv.mjs} +2053 -1110
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +165 -165
  8. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +212 -212
  9. package/dist/_dts/api/src/accessAdmin.d.ts +74 -104
  10. package/dist/_dts/api/src/aiEndpoints.d.ts +5 -1
  11. package/dist/_dts/api/src/authSubmission.d.ts +46 -0
  12. package/dist/_dts/api/src/billing.d.ts +8 -4
  13. package/dist/_dts/api/src/billingEndpointDefinitions.d.ts +23 -0
  14. package/dist/_dts/api/src/billingEndpointTypes.d.ts +26 -0
  15. package/dist/_dts/api/src/blocks.d.ts +2 -0
  16. package/dist/_dts/api/src/bookingRecords.d.ts +1 -2
  17. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +8 -1
  18. package/dist/_dts/api/src/communications.d.ts +0 -1
  19. package/dist/_dts/api/src/contentRuntime.d.ts +8 -3
  20. package/dist/_dts/api/src/endpoints.d.ts +93 -64
  21. package/dist/_dts/api/src/event-destination-policy.d.ts +2 -1
  22. package/dist/_dts/api/src/footerSettings.d.ts +9 -6
  23. package/dist/_dts/api/src/index.d.ts +5 -6
  24. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -1
  25. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
  26. package/dist/_dts/api/src/mailingListIntegration.d.ts +8 -2
  27. package/dist/_dts/api/src/navigation/dashboardSettingsNav.d.ts +1 -1
  28. package/dist/_dts/api/src/navigation/types.d.ts +1 -1
  29. package/dist/_dts/api/src/onboarding/confirmationResend.d.ts +25 -0
  30. package/dist/_dts/api/src/onboarding/surfaceData.d.ts +32 -32
  31. package/dist/_dts/api/src/publicBookingAvailabilityEndpointDefinitions.d.ts +8 -0
  32. package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +1 -0
  33. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +11 -3
  34. package/dist/_dts/api/src/publicExperience/sharedTypes.d.ts +3 -29
  35. package/dist/_dts/api/src/publicOnboardingAttemptEndpointDefinitions.d.ts +65 -0
  36. package/dist/_dts/api/src/saveOutcome.d.ts +20 -0
  37. package/dist/_dts/api/src/sdkContracts.d.ts +3 -22
  38. package/dist/_dts/api/src/sdkPushContracts.d.ts +18 -0
  39. package/dist/_dts/api/src/sdkThemeWire.d.ts +44 -44
  40. package/dist/_dts/api/src/settings/permissions.d.ts +12 -0
  41. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +9 -5
  42. package/dist/_dts/api/src/siteOnboarding.d.ts +2 -9
  43. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +2 -4
  44. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +3 -1
  45. package/dist/_dts/api/src/siteSettings.d.ts +20 -7
  46. package/dist/_dts/api/src/types.d.ts +77 -77
  47. package/dist/_dts/api/src/wholeSeriesRuns.d.ts +2 -37
  48. package/dist/_dts/billing/src/membership/index.d.ts +3 -0
  49. package/dist/_dts/billing/src/plans/types.d.ts +3 -0
  50. package/dist/_dts/billing/src/site-arrangements.d.ts +14 -3
  51. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +16 -4
  52. package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +2 -0
  53. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +5 -0
  54. package/dist/_dts/blocks/src/portal/types.d.ts +2 -4
  55. package/dist/_dts/blocks/src/portal/waitlist-types.d.ts +35 -0
  56. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +2 -0
  57. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +42 -0
  58. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +4 -0
  59. package/dist/_dts/blocks/src/system/data/index.d.ts +2 -2
  60. package/dist/_dts/blocks/src/system/data/prefetchBlockData.d.ts +2 -1
  61. package/dist/_dts/blocks/src/system/data/types.d.ts +9 -0
  62. package/dist/_dts/blocks/src/system/registry.d.ts +1 -0
  63. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +0 -28
  64. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  65. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +7 -3
  66. package/dist/_dts/blocks/src/system/runtime/api/types/portal.d.ts +1 -1
  67. package/dist/_dts/blocks/src/system/runtime/api/types/waitlist-claims.d.ts +7 -2
  68. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +30 -6
  69. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +15 -3
  70. package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +43 -0
  71. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.d.ts +1 -2
  72. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +2 -0
  73. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/checkoutRecovery.d.ts +14 -0
  74. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.d.ts +56 -0
  75. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +6 -8
  76. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useCheckoutRecovery.d.ts +8 -0
  77. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +8 -7
  78. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +10 -2
  79. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventSourceRecovery.d.ts +18 -0
  80. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.client.d.ts +1 -1
  81. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +24 -6
  82. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.server.d.ts +4 -2
  83. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.interactive.d.ts +6 -0
  84. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +1 -0
  85. package/dist/_dts/blocks/src/system/runtime/resolver.d.ts +1 -0
  86. package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +2 -6
  87. package/dist/_dts/blocks/src/system/runtime/shared/index.d.ts +2 -2
  88. package/dist/_dts/blocks/src/system/runtime/shared/useWaitlistClaim.d.ts +2 -0
  89. package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +4 -0
  90. package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +27 -4
  91. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +2 -1
  92. package/dist/_dts/content-editor/src/hooks/useBlockAutosave.d.ts +3 -1
  93. package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +3 -0
  94. package/dist/_dts/core/src/branded.d.ts +0 -8
  95. package/dist/_dts/core/src/index.d.ts +1 -0
  96. package/dist/_dts/core/src/mailing-list-setup-parser.d.ts +1 -1
  97. package/dist/_dts/core/src/mailing-list-setup.d.ts +14 -1
  98. package/dist/_dts/core/src/mailing-list-submission.d.ts +7 -27
  99. package/dist/_dts/core/src/participants.d.ts +2 -29
  100. package/dist/_dts/core/src/public-experience.d.ts +4 -0
  101. package/dist/_dts/core/src/public-profile.d.ts +27 -1
  102. package/dist/_dts/core/src/site-route-target.d.ts +9 -2
  103. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +293 -606
  104. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListGlobalSettingsSummary.d.ts +10 -0
  105. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListTargetingField.d.ts +3 -2
  106. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/context.d.ts +3 -2
  107. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/loaders.d.ts +3 -2
  108. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/targetingState.d.ts +19 -0
  109. package/dist/_dts/sdk/src/public-api/contracts.d.ts +14 -20
  110. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +2 -0
  111. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +2 -0
  112. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +7 -1
  113. package/dist/_dts/sdk/src/rendering/helpers/templateContent.d.ts +1 -0
  114. package/dist/_dts/sdk/src/version.d.ts +1 -1
  115. package/dist/_dts/theme-core/src/accordions/types.d.ts +3 -3
  116. package/dist/_dts/theme-core/src/cards/types.d.ts +21 -21
  117. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  118. package/dist/_dts/theme-core/src/header/interactionPalette.d.ts +8 -2
  119. package/dist/_dts/theme-core/src/header/legacyHeaderVariant.d.ts +2 -2
  120. package/dist/_dts/theme-core/src/inputs/types.d.ts +2 -2
  121. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +54 -54
  122. package/dist/_dts/theme-core/src/runtime/buildThemeRuntimeFromBridge.d.ts +1 -4
  123. package/dist/_dts/theme-core/src/schema.d.ts +84 -84
  124. package/dist/_dts/theme-core/src/shared/componentStyles.d.ts +1 -1
  125. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  126. package/dist/_dts/theme-core/src/surfaces/foregroundInteraction.d.ts +77 -0
  127. package/dist/_dts/theme-core/src/surfaces/index.d.ts +1 -0
  128. package/dist/_dts/theme-core/src/typography/generateTypographyCss.d.ts +2 -2
  129. package/dist/_dts/ui/src/lib/use-delayed-flag.d.ts +9 -0
  130. package/dist/_dts/ui/src/pending-button.d.ts +10 -0
  131. package/dist/client/{BookingConsentAgreement-CZvTDtsK.mjs → BookingConsentAgreement-CuKa82V4.mjs} +4 -4
  132. package/dist/client/{DiscountCodeDisclosure-D-DsLCMU.mjs → DiscountCodeDisclosure-BbYieKWB.mjs} +1 -1
  133. package/dist/client/{EventCombined.client-dWqgd5ZO.mjs → EventCombined.client-LTfR1Aby.mjs} +6 -6
  134. package/dist/client/{EventListing.client-BMRa9IYp.mjs → EventListing.client-DUHpYSuo.mjs} +2 -2
  135. package/dist/client/{LeafletStaticMap-D21W9kBZ.mjs → LeafletStaticMap-CHRupL6m.mjs} +1 -1
  136. package/dist/client/{accordion-FxF_ta47.mjs → accordion-6HiIFxNL.mjs} +1 -1
  137. package/dist/client/{bookingForm-YnwW4TGw.mjs → bookingForm-Dlmid43H.mjs} +7 -7
  138. package/dist/client/bookings.mjs +325 -140
  139. package/dist/client/{carousel-vng7fFT5.mjs → carousel-DmkZRRq_.mjs} +2 -2
  140. package/dist/client/{carousel.client-59G_WMr4.mjs → carousel.client-DQTjCVQT.mjs} +1 -1
  141. package/dist/client/{cart-DEPDsjNk.mjs → cart-CIC24330.mjs} +3 -3
  142. package/dist/client/{checkout-CZRWu9rW.mjs → checkout-D1Zw9imo.mjs} +3 -3
  143. package/dist/client/{checkoutUrls-BuseL0dw.mjs → checkoutUrls-FL6lRkrt.mjs} +1 -1
  144. package/dist/client/client.mjs +1717 -882
  145. package/dist/client/{colorStyles-CrxJrPjJ.mjs → colorStyles-3013aRAY.mjs} +3 -1
  146. package/dist/client/{context-DvU_WUmd.mjs → context-Cy1OayHx.mjs} +6 -19
  147. package/dist/client/{dates-wnPMiRl5.mjs → dates-aDcfoLHr.mjs} +2 -2
  148. package/dist/client/{eventCalendar-BA3Q5L15.mjs → eventCalendar-FQxMPAjf.mjs} +8 -8
  149. package/dist/client/{eventCombined-51wgR-1R.mjs → eventCombined-Dr3ac6Hb.mjs} +3 -3
  150. package/dist/client/{eventDetails-modaetpm.mjs → eventDetails-D-AzUHFQ.mjs} +4 -4
  151. package/dist/client/{eventListing-D8t2J3Kv.mjs → eventListing-B3XxBf3i.mjs} +3 -3
  152. package/dist/client/{eventRegistration-CYqtkCE_.mjs → eventRegistration-I6EaokFD.mjs} +500 -152
  153. package/dist/client/{form-CBKXN5In.mjs → form-BbWckVWY.mjs} +3 -3
  154. package/dist/client/{headerSection-DylDqNrs.mjs → headerSection-C9qU4Y7x.mjs} +2 -2
  155. package/dist/client/hooks.mjs +445 -180
  156. package/dist/client/{locationMap-CvWrG0vZ.mjs → locationMap-CLCShvlG.mjs} +3 -3
  157. package/dist/client/{media-BOHuueS5.mjs → media-DHpfFwd3.mjs} +1 -1
  158. package/dist/client/{newsletterForm-Btwk70zw.mjs → newsletterForm-Briukxzi.mjs} +130 -87
  159. package/dist/client/{pricing-Uzw-GQ6Y.mjs → pricing-Copadu-2.mjs} +1 -1
  160. package/dist/client/{productDetail-JLcUYKnd.mjs → productDetail-oujlRd-r.mjs} +3 -3
  161. package/dist/client/{productList-FM0cbUzj.mjs → productList-BRiIRUcd.mjs} +3 -3
  162. package/dist/client/{propsDecoder-DYzafZb2.mjs → propsDecoder-CB2KS_ko.mjs} +130 -24
  163. package/dist/client/rendering/client.mjs +911 -400
  164. package/dist/client/rendering/islands.mjs +19 -19
  165. package/dist/client/rendering.mjs +1696 -818
  166. package/dist/client/{scrollToBlock-CvXszexS.mjs → scrollToBlock-B1IS1_ua.mjs} +1 -1
  167. package/dist/client/{shop-BIcjvy5a.mjs → shop-Vn6yNFED.mjs} +6 -6
  168. package/dist/client/{shop-commerce-BZQsy7xw.mjs → shop-commerce-BVTqipYp.mjs} +7 -7
  169. package/dist/client/{shop-commerce-store-D5V7XAb5.mjs → shop-commerce-store-BVnJVy7v.mjs} +1 -1
  170. package/dist/client/{shopShared-DowkXevB.mjs → shopShared-COIeK77T.mjs} +4 -4
  171. package/dist/client/{useEventFilters-oMoTw_JE.mjs → useEventFilters-DzIUcS9n.mjs} +7 -7
  172. package/dist/preview-next/before-render.mjs +119 -64
  173. package/dist/preview-next/client/runtime.mjs +4 -4
  174. package/dist/preview-next/keepAlive.mjs +119 -64
  175. package/dist/preview-next/middleware.mjs +119 -64
  176. package/dist/{previewAuthStore-COUyAKaX.mjs → previewAuthStore-Gjb6r6vz.mjs} +119 -64
  177. package/dist/{sdk-runtime-D4k2LSGF.mjs → sdk-runtime-CnCLvZRv.mjs} +2 -2
  178. package/dist/{separator-UGtpag4Z.mjs → separator-DKDRJ1oH.mjs} +1 -1
  179. package/dist/server/components.mjs +787 -323
  180. package/dist/server/config-validation.mjs +328 -79
  181. package/dist/server/config.mjs +332 -83
  182. package/dist/server/data.mjs +441 -180
  183. package/dist/server/index.mjs +126 -66
  184. package/dist/server/next.mjs +1031 -595
  185. package/dist/server/page-converter.mjs +183 -74
  186. package/dist/server/prebuild.mjs +1 -1
  187. package/dist/server/rendering/server.mjs +1068 -592
  188. package/dist/server/rendering.mjs +802 -324
  189. package/dist/server/routing.mjs +506 -214
  190. package/dist/server/server.mjs +468 -244
  191. package/dist/server/theme-bridge.mjs +433 -100
  192. package/dist/server/theme.mjs +8 -2
  193. package/dist/styles/index.css +237 -43
  194. package/package.json +1 -1
  195. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionCompactRow.d.ts +0 -29
  196. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionList.d.ts +0 -13
@@ -647,7 +647,7 @@ function parseUuidBrand(value, unsafeConstructor) {
647
647
  if (!UUID_PATTERN$1.test(normalized)) return err$2({ kind: "invalid_uuid" });
648
648
  return ok$2(unsafeConstructor(normalized));
649
649
  }
650
- var UUID_PATTERN$1, unsafeAsEventOfferingId, unsafeAsEventSeriesId, unsafeAsMediaAssetId, unsafeAsStorageBucketName, unsafeAsStoragePath, unsafeAsPositiveByteCount, unsafeAsPositiveSeconds, unsafeAsFormId, unsafeAsPassId, unsafeAsCustomerPassId, unsafeAsAppointmentServiceId, unsafeAsAppointmentResourceId, parseEventOfferingId, parseEventSeriesId;
650
+ var UUID_PATTERN$1, unsafeAsEventOfferingId, unsafeAsEventSeriesId, unsafeAsMediaAssetId, unsafeAsStorageBucketName, unsafeAsStoragePath, unsafeAsPositiveByteCount, unsafeAsPositiveSeconds, unsafeAsFormId, unsafeAsPassId, unsafeAsCustomerPassId, unsafeAsAppointmentServiceId, unsafeAsAppointmentResourceId, unsafeAsContentVersionId, parseEventOfferingId, parseContentVersionId, parseEventSeriesId;
651
651
  var init_branded = __esmMin((() => {
652
652
  init_result$1();
653
653
  UUID_PATTERN$1 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -663,7 +663,9 @@ var init_branded = __esmMin((() => {
663
663
  unsafeAsCustomerPassId = (id) => id;
664
664
  unsafeAsAppointmentServiceId = (id) => id;
665
665
  unsafeAsAppointmentResourceId = (id) => id;
666
+ unsafeAsContentVersionId = (id) => id;
666
667
  parseEventOfferingId = (value) => parseUuidBrand(value, unsafeAsEventOfferingId);
668
+ parseContentVersionId = (value) => parseUuidBrand(value, unsafeAsContentVersionId);
667
669
  parseEventSeriesId = (value) => parseUuidBrand(value, unsafeAsEventSeriesId);
668
670
  }));
669
671
  //#endregion
@@ -1016,7 +1018,7 @@ function parseEventPageSurfaceDestinationMode(value) {
1016
1018
  return value === "cms-managed" || value === "system-managed" ? value : void 0;
1017
1019
  }
1018
1020
  function parseEventPageSurfaceSubject(value) {
1019
- if (!isRecord$28(value)) return err$2({ kind: "notObject" });
1021
+ if (!isRecord$29(value)) return err$2({ kind: "notObject" });
1020
1022
  switch (value.kind) {
1021
1023
  case "eventSeries": {
1022
1024
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -1071,7 +1073,7 @@ function parseEventSeriesIdList(values) {
1071
1073
  }
1072
1074
  return ok$2(parsed);
1073
1075
  }
1074
- function isRecord$28(value) {
1076
+ function isRecord$29(value) {
1075
1077
  return typeof value === "object" && value !== null && !Array.isArray(value);
1076
1078
  }
1077
1079
  var init_event_page_surface_subject = __esmMin((() => {
@@ -1563,7 +1565,6 @@ var init_assertNever$1 = __esmMin((() => {
1563
1565
  init_assert_never();
1564
1566
  }));
1565
1567
  var init_participants = __esmMin((() => {
1566
- init_branded();
1567
1568
  init_result$1();
1568
1569
  init_string();
1569
1570
  }));
@@ -1575,9 +1576,10 @@ var init_public_profile = __esmMin((() => {
1575
1576
  init_public_url_validation();
1576
1577
  init_result$1();
1577
1578
  }));
1579
+ var init_public_experience = __esmMin((() => {}));
1578
1580
  //#endregion
1579
1581
  //#region ../core/src/rich-text.ts
1580
- function isRecord$26(value) {
1582
+ function isRecord$27(value) {
1581
1583
  return typeof value === "object" && value !== null && !Array.isArray(value);
1582
1584
  }
1583
1585
  function hasOnlyKeys(value, allowed) {
@@ -1588,10 +1590,10 @@ function isDenseArrayOf(value, predicate) {
1588
1590
  return true;
1589
1591
  }
1590
1592
  function isTipTapMark(value) {
1591
- return isRecord$26(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$26(value.attrs));
1593
+ return isRecord$27(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$27(value.attrs));
1592
1594
  }
1593
1595
  function isTipTapNode(value) {
1594
- if (!isRecord$26(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$26(value.attrs) || value.marks !== void 0 && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== void 0 && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) return false;
1596
+ if (!isRecord$27(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$27(value.attrs) || value.marks !== void 0 && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== void 0 && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) return false;
1595
1597
  if (value.type === "text") return typeof value.text === "string" && value.text.length > 0 && value.content === void 0;
1596
1598
  return value.text === void 0;
1597
1599
  }
@@ -1636,10 +1638,10 @@ var init_mailing_list_identifiers = __esmMin((() => {
1636
1638
  //#endregion
1637
1639
  //#region ../core/src/mailing-list-targeting-parser.ts
1638
1640
  function parseMailingListPlacementTargeting(value) {
1639
- if (!isRecord$25(value)) return targetingError("shape");
1641
+ if (!isRecord$26(value)) return targetingError("shape");
1640
1642
  if (value.mode === "default") return ok$2({ mode: "default" });
1641
1643
  if (value.mode !== "custom") return targetingError("mode");
1642
- if (!isRecord$25(value.selection)) return targetingError("selection");
1644
+ if (!isRecord$26(value.selection)) return targetingError("selection");
1643
1645
  switch (value.provider) {
1644
1646
  case "native": return parseNativeTargeting(value.selection);
1645
1647
  case "brevo": return parseBrevoTargeting(value.selection);
@@ -1648,7 +1650,7 @@ function parseMailingListPlacementTargeting(value) {
1648
1650
  }
1649
1651
  }
1650
1652
  function parseMailingListVisitorSelection(value) {
1651
- if (!isRecord$25(value)) return visitorSelectionError("shape");
1653
+ if (!isRecord$26(value)) return visitorSelectionError("shape");
1652
1654
  switch (value.provider) {
1653
1655
  case "native": {
1654
1656
  const topicIds = parseVisitorIds(value.topicIds, parseNewsletterListId);
@@ -1781,7 +1783,7 @@ function parseVisitorIds(value, parseId) {
1781
1783
  }
1782
1784
  return parsed;
1783
1785
  }
1784
- function isRecord$25(value) {
1786
+ function isRecord$26(value) {
1785
1787
  return typeof value === "object" && value !== null && !Array.isArray(value);
1786
1788
  }
1787
1789
  function targetingError(field) {
@@ -1829,8 +1831,12 @@ var init_footer_composition = __esmMin((() => {
1829
1831
  var init_footer_navigation_layout = __esmMin((() => {}));
1830
1832
  //#endregion
1831
1833
  //#region ../core/src/footer-composition-types.ts
1832
- var init_footer_composition_types = __esmMin((() => {}));
1833
- var init_mailing_list_setup = __esmMin((() => {}));
1834
+ var init_footer_composition_types = __esmMin((() => {})), DEFAULT_MAILING_LIST_SUCCESS_MESSAGE;
1835
+ var init_mailing_list_setup = __esmMin((() => {
1836
+ init_mailing_list_identifiers();
1837
+ init_result$1();
1838
+ DEFAULT_MAILING_LIST_SUCCESS_MESSAGE = "Thanks — you're on the list.";
1839
+ }));
1834
1840
  //#endregion
1835
1841
  //#region ../core/src/mailing-list-setup-parser.ts
1836
1842
  function parseMailingListGlobalForm(value) {
@@ -1840,12 +1846,15 @@ function parseMailingListGlobalForm(value) {
1840
1846
  if (typeof value.includeOptionalPhone !== "boolean") return formError("includeOptionalPhone");
1841
1847
  const buttonLabel = parseRequiredString(value.buttonLabel);
1842
1848
  if (buttonLabel === null) return formError("buttonLabel");
1849
+ const successMessage = parseRequiredString(value.successMessage);
1850
+ if (successMessage === null) return formError("successMessage");
1843
1851
  const privacyNote = parseOptionalString(value.privacyNote);
1844
1852
  if (privacyNote === void 0) return formError("privacyNote");
1845
1853
  return ok$2({
1846
1854
  fields,
1847
1855
  includeOptionalPhone: value.includeOptionalPhone,
1848
1856
  buttonLabel,
1857
+ successMessage,
1849
1858
  privacyNote
1850
1859
  });
1851
1860
  }
@@ -2067,11 +2076,17 @@ function parseMailingListSignedSourceToken(value) {
2067
2076
  const parsed = typeof value === "string" ? value.trim() : "";
2068
2077
  return /^[A-Za-z0-9._~-]{16,1000}$/u.test(parsed) ? parsed : null;
2069
2078
  }
2070
- function buildMailingListSignupBlockSourceRef(blockId) {
2071
- const parsed = parseMailingListBlockId(blockId);
2072
- return parsed !== null ? {
2079
+ function parseMailingListContentVersionId(value) {
2080
+ const parsed = parseContentVersionId(value);
2081
+ return parsed.ok ? parsed.value : null;
2082
+ }
2083
+ function buildMailingListSignupBlockSourceRef(blockId, contentVersionId) {
2084
+ const parsedBlockId = parseMailingListBlockId(blockId);
2085
+ const parsedContentVersionId = parseMailingListContentVersionId(contentVersionId);
2086
+ return parsedBlockId !== null && parsedContentVersionId !== null ? {
2073
2087
  tag: "block_ref",
2074
- blockId: parsed
2088
+ blockId: parsedBlockId,
2089
+ contentVersionId: parsedContentVersionId
2075
2090
  } : null;
2076
2091
  }
2077
2092
  var init_mailing_list_submission = __esmMin((() => {
@@ -2492,6 +2507,7 @@ var init_src$2 = __esmMin((() => {
2492
2507
  init_participant_identity();
2493
2508
  init_public_url_validation();
2494
2509
  init_public_profile();
2510
+ init_public_experience();
2495
2511
  init_rich_text();
2496
2512
  init_footer_composition();
2497
2513
  init_footer_navigation_layout();
@@ -4480,111 +4496,22 @@ function themeButtonClassName(spec) {
4480
4496
  var init_classNames = __esmMin((() => {
4481
4497
  init_types$14();
4482
4498
  }));
4483
- var init_resolver$1 = __esmMin((() => {}));
4484
- var init_generateBaseCSS = __esmMin((() => {}));
4485
- var STATE_SELECTORS;
4486
- var init_cssUtils = __esmMin((() => {
4487
- STATE_SELECTORS = {
4488
- hover: ":hover, [data-force-hover=\"true\"]",
4489
- active: ":active",
4490
- focus: ":focus-visible",
4491
- base: ""
4492
- };
4493
- }));
4494
- //#endregion
4495
- //#region ../theme-core/src/buttons/effects/presets/background.ts
4496
- function shadeBackgroundEffect(config) {
4497
- return {
4498
- id: config.id,
4499
- name: config.name,
4500
- description: config.description,
4501
- category: "background",
4502
- pseudoElement: "none",
4503
- applicableTo: ["button"],
4504
- customizableOption: {
4505
- name: "amount",
4506
- type: "select",
4507
- label: config.label,
4508
- default: 100,
4509
- options: [
4510
- 0,
4511
- 100,
4512
- 200,
4513
- 300,
4514
- 400,
4515
- 500,
4516
- 600,
4517
- 700,
4518
- 800,
4519
- 900
4520
- ]
4521
- },
4522
- isApplicable: (buttonConfig) => buttonConfig.background.type === "solid",
4523
- generateCSS: ({ themeId, variantId, options, tokens, buttonConfig }) => {
4524
- if (buttonConfig.background.type !== "solid") return "";
4525
- const amount = (options.amount || 100) * config.shadeDirection;
4526
- const baseToken = buttonConfig.background.colorToken ?? "primary-500";
4527
- return `
4528
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
4529
- background-color: ${tokens.getColor(tokens.adjustShade(baseToken, amount))};
4530
- }
4531
- `;
4532
- }
4533
- };
4534
- }
4535
- var init_background$2 = __esmMin((() => {
4536
- init_cssUtils();
4537
- shadeBackgroundEffect({
4538
- id: "darken-background",
4539
- name: "Darken on Hover",
4540
- description: "Darkens the background color on hover",
4541
- label: "Darken Amount (shade step)",
4542
- shadeDirection: 1
4543
- });
4544
- shadeBackgroundEffect({
4545
- id: "lighten-background",
4546
- name: "Lighten on Hover",
4547
- description: "Lightens the background color on hover",
4548
- label: "Lighten Amount (shade step)",
4549
- shadeDirection: -1
4550
- });
4551
- }));
4552
- var init_shadow = __esmMin((() => {
4553
- init_cssUtils();
4554
- }));
4555
- var init_transform = __esmMin((() => {
4556
- init_cssUtils();
4557
- init_constants$2();
4558
- }));
4559
- var init_overlay = __esmMin((() => {}));
4560
- var init_text = __esmMin((() => {}));
4561
- var init_border = __esmMin((() => {}));
4562
- var init_animation = __esmMin((() => {}));
4563
- var init_nav_underline = __esmMin((() => {}));
4564
- var init_nav_frosted = __esmMin((() => {}));
4499
+ var init_tokens$1 = __esmMin((() => {}));
4565
4500
  //#endregion
4566
- //#region ../theme-core/src/interactive/effects/index.ts
4567
- var init_effects = __esmMin((() => {
4568
- init_nav_underline();
4569
- init_nav_frosted();
4570
- }));
4571
- var init_registry$2 = __esmMin((() => {
4572
- init_background$2();
4573
- init_shadow();
4574
- init_transform();
4575
- init_overlay();
4576
- init_text();
4577
- init_border();
4578
- init_animation();
4579
- init_effects();
4580
- init_effectClassification();
4581
- })), init_generateEffectsCSS = __esmMin((() => {
4582
- init_registry$2();
4501
+ //#region ../theme-core/src/tokens/index.ts
4502
+ var init_tokens = __esmMin((() => {
4503
+ init_tokens$1();
4504
+ init_blockColorTokens();
4505
+ init_themeColorTokens();
4506
+ init_colorTokenParts();
4507
+ init_resolver$1();
4583
4508
  }));
4584
- var init_generateDefaultButtonSystem = __esmMin((() => {
4585
- init_types$14();
4509
+ var init_foregroundInteraction = __esmMin((() => {
4510
+ init_contrast$1();
4511
+ init_colorConversion();
4512
+ init_colorTokenParts();
4513
+ init_tokens();
4586
4514
  }));
4587
- var init_affordanceIcons = __esmMin((() => {}));
4588
4515
  //#endregion
4589
4516
  //#region ../theme-core/src/palette/utils/opaqueSurfaceColor.ts
4590
4517
  /** Resolve an opaque colour, compositing alpha against an explicit underlay. */
@@ -4737,6 +4664,7 @@ var init_resolveSurfaceForeground = __esmMin((() => {
4737
4664
  //#region ../theme-core/src/surfaces/index.ts
4738
4665
  var init_surfaces = __esmMin((() => {
4739
4666
  init_foregroundContract();
4667
+ init_foregroundInteraction();
4740
4668
  init_foregroundRoles();
4741
4669
  init_resolveSurfaceForeground();
4742
4670
  }));
@@ -4841,6 +4769,113 @@ var init_colorStyles = __esmMin((() => {
4841
4769
  mutedText: "supporting"
4842
4770
  };
4843
4771
  }));
4772
+ var init_resolver$1 = __esmMin((() => {
4773
+ init_colorStyles();
4774
+ }));
4775
+ var init_generateBaseCSS = __esmMin((() => {}));
4776
+ var STATE_SELECTORS;
4777
+ var init_cssUtils = __esmMin((() => {
4778
+ STATE_SELECTORS = {
4779
+ hover: ":hover, [data-force-hover=\"true\"]",
4780
+ active: ":active",
4781
+ focus: ":focus-visible",
4782
+ base: ""
4783
+ };
4784
+ }));
4785
+ //#endregion
4786
+ //#region ../theme-core/src/buttons/effects/presets/background.ts
4787
+ function shadeBackgroundEffect(config) {
4788
+ return {
4789
+ id: config.id,
4790
+ name: config.name,
4791
+ description: config.description,
4792
+ category: "background",
4793
+ pseudoElement: "none",
4794
+ applicableTo: ["button"],
4795
+ customizableOption: {
4796
+ name: "amount",
4797
+ type: "select",
4798
+ label: config.label,
4799
+ default: 100,
4800
+ options: [
4801
+ 0,
4802
+ 100,
4803
+ 200,
4804
+ 300,
4805
+ 400,
4806
+ 500,
4807
+ 600,
4808
+ 700,
4809
+ 800,
4810
+ 900
4811
+ ]
4812
+ },
4813
+ isApplicable: (buttonConfig) => buttonConfig.background.type === "solid",
4814
+ generateCSS: ({ themeId, variantId, options, tokens, buttonConfig }) => {
4815
+ if (buttonConfig.background.type !== "solid") return "";
4816
+ const amount = (options.amount || 100) * config.shadeDirection;
4817
+ const baseToken = buttonConfig.background.colorToken ?? "primary-500";
4818
+ return `
4819
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
4820
+ background-color: ${tokens.getColor(tokens.adjustShade(baseToken, amount))};
4821
+ }
4822
+ `;
4823
+ }
4824
+ };
4825
+ }
4826
+ var init_background$2 = __esmMin((() => {
4827
+ init_cssUtils();
4828
+ shadeBackgroundEffect({
4829
+ id: "darken-background",
4830
+ name: "Darken on Hover",
4831
+ description: "Darkens the background color on hover",
4832
+ label: "Darken Amount (shade step)",
4833
+ shadeDirection: 1
4834
+ });
4835
+ shadeBackgroundEffect({
4836
+ id: "lighten-background",
4837
+ name: "Lighten on Hover",
4838
+ description: "Lightens the background color on hover",
4839
+ label: "Lighten Amount (shade step)",
4840
+ shadeDirection: -1
4841
+ });
4842
+ }));
4843
+ var init_shadow = __esmMin((() => {
4844
+ init_cssUtils();
4845
+ }));
4846
+ var init_transform = __esmMin((() => {
4847
+ init_cssUtils();
4848
+ init_constants$2();
4849
+ }));
4850
+ var init_overlay = __esmMin((() => {}));
4851
+ var init_text = __esmMin((() => {}));
4852
+ var init_border = __esmMin((() => {}));
4853
+ var init_animation = __esmMin((() => {}));
4854
+ var init_nav_underline = __esmMin((() => {}));
4855
+ var init_nav_frosted = __esmMin((() => {}));
4856
+ //#endregion
4857
+ //#region ../theme-core/src/interactive/effects/index.ts
4858
+ var init_effects = __esmMin((() => {
4859
+ init_nav_underline();
4860
+ init_nav_frosted();
4861
+ }));
4862
+ var init_registry$2 = __esmMin((() => {
4863
+ init_background$2();
4864
+ init_shadow();
4865
+ init_transform();
4866
+ init_overlay();
4867
+ init_text();
4868
+ init_border();
4869
+ init_animation();
4870
+ init_effects();
4871
+ init_effectClassification();
4872
+ })), init_generateEffectsCSS = __esmMin((() => {
4873
+ init_registry$2();
4874
+ }));
4875
+ var init_generateDefaultButtonSystem = __esmMin((() => {
4876
+ init_types$14();
4877
+ }));
4878
+ var init_affordanceIcons = __esmMin((() => {}));
4844
4879
  //#endregion
4845
4880
  //#region ../theme-core/src/utils/tokenOrColor.ts
4846
4881
  function isCssColorLiteral(value) {
@@ -8884,15 +8919,34 @@ var init_bookingConsent = __esmMin((() => {
8884
8919
  checkboxLabel: z.string().min(1)
8885
8920
  });
8886
8921
  z.union([blockBookingConsentSchema, bookingRequirementConsentFieldSchema]);
8887
- }));
8888
- //#endregion
8889
- //#region ../blocks/src/system/blocks/events/shared/schemas.ts
8890
- var eventPresetSchema, eventScheduleScopeSchema$2, publicEventRecurrenceSchema, eventDestinationModeSchema, publicEventDestinationSchema, eventVenueSchema, eventCategorySchema, accessRestrictionSchema, publicCurrencySchema, publicCentsSchema, publicPositiveCentsSchema, publicIsoDateTimeSchema, publicEventAttendanceModeSchema, publicEventAttendanceModeAvailabilitySchema, publicEventPricingOptionAvailabilitySchema, publicEventPricingOptionSchema, publicEventPricingSchema, publicTeamMemberSummarySchema, publicEventBookingAvailabilitySchema, publicRunSessionSchema, publicWholeSeriesRunSchema, publicEventBaseSchema, publicEventSchema, publicEventsArraySchema;
8922
+ })), publicEventLoaderQuerySchemaShape, eventPresetSchema, eventScheduleScopeSchema$2, publicEventRecurrenceSchema, eventDestinationModeSchema, publicEventDestinationSchema, eventVenueSchema, eventCategorySchema, accessRestrictionSchema, publicCurrencySchema, publicCentsSchema, publicPositiveCentsSchema, publicIsoDateTimeSchema, publicEventAttendanceModeSchema, publicEventAttendanceModeAvailabilitySchema, publicEventPricingOptionAvailabilitySchema, publicEventPricingOptionSchema, publicEventPricingSchema, publicTeamMemberSummarySchema, publicEventBookingAvailabilitySchema, publicRunSessionSchema, publicWholeSeriesRunSchema, publicEventBaseSchema, publicEventSchema, publicEventsArraySchema;
8891
8923
  var init_schemas = __esmMin((() => {
8892
8924
  init_media$1();
8893
8925
  init_richTextSchema();
8894
8926
  init_bookingPaymentTerms();
8895
8927
  init_bookingConsent();
8928
+ publicEventLoaderQuerySchemaShape = {
8929
+ limit: z.string().optional(),
8930
+ from: z.string().optional(),
8931
+ to: z.string().optional(),
8932
+ afterStartsAt: z.string().optional(),
8933
+ afterId: z.string().optional(),
8934
+ categoryIds: z.string().optional(),
8935
+ venueId: z.string().optional(),
8936
+ staffMemberId: z.string().optional(),
8937
+ eventSurface: z.string().optional(),
8938
+ eventPresets: z.string().optional(),
8939
+ scheduleScope: z.string().optional(),
8940
+ seriesId: z.string().optional(),
8941
+ seriesIds: z.string().optional(),
8942
+ runSeriesId: z.string().optional(),
8943
+ seriesSlug: z.string().optional(),
8944
+ includeOccurrenceId: z.string().optional(),
8945
+ readIntent: z.string().optional(),
8946
+ detailLevel: z.string().optional(),
8947
+ readProfile: z.string().optional()
8948
+ };
8949
+ z.object(publicEventLoaderQuerySchemaShape);
8896
8950
  eventPresetSchema = z.enum([
8897
8951
  "event",
8898
8952
  "class",
@@ -9318,7 +9372,7 @@ function planCalendarMonthRanges(months) {
9318
9372
  const sorted = [...new Set(months)].sort();
9319
9373
  const ranges = [];
9320
9374
  for (const month of sorted) {
9321
- const previous = ranges.at(-1);
9375
+ const previous = ranges[ranges.length - 1];
9322
9376
  const end = calendarMonthKey$1(addMonths(calendarMonthDate(month), 1));
9323
9377
  if (previous?.endMonthExclusive === month && monthNumber(end) - monthNumber(previous.startMonth) <= 3) previous.endMonthExclusive = end;
9324
9378
  else ranges.push({
@@ -9898,6 +9952,9 @@ function isApiSuccessResponse(json) {
9898
9952
  * });
9899
9953
  * ```
9900
9954
  */
9955
+ function publicEventsQuery(params) {
9956
+ return { ...params ?? {} };
9957
+ }
9901
9958
  function createBlockApi(config) {
9902
9959
  const { baseUrl, auth, authOverrides, siteId, isPreview } = config;
9903
9960
  const dedup = createDeduplicationCache({ ttl: 100 });
@@ -10050,23 +10107,7 @@ function createBlockApi(config) {
10050
10107
  const path = buildPath(EVENTS.list.path, { siteId: sid });
10051
10108
  return request(EVENTS.list, {
10052
10109
  path,
10053
- query: {
10054
- from: params?.from,
10055
- to: params?.to,
10056
- afterStartsAt: params?.afterStartsAt,
10057
- afterId: params?.afterId,
10058
- limit: params?.limit,
10059
- stage: params?.stage,
10060
- eventSurface: params?.eventSurface,
10061
- eventPresets: params?.eventPresets,
10062
- scheduleScope: params?.scheduleScope,
10063
- categoryIds: params?.categoryIds,
10064
- venueId: params?.venueId,
10065
- staffMemberId: params?.staffMemberId,
10066
- seriesId: params?.seriesId,
10067
- includeOccurrenceId: params?.includeOccurrenceId,
10068
- detailLevel: params?.detailLevel
10069
- }
10110
+ query: publicEventsQuery(params)
10070
10111
  });
10071
10112
  },
10072
10113
  async getEventFilters(params) {
@@ -10130,7 +10171,7 @@ function createBlockApi(config) {
10130
10171
  const path = buildPath(WHOLE_SERIES.waitlistClaimResolve.path, { siteId: sid });
10131
10172
  return request(WHOLE_SERIES.waitlistClaimResolve, {
10132
10173
  path,
10133
- body: { claimToken: data.claimToken }
10174
+ body: data
10134
10175
  });
10135
10176
  },
10136
10177
  async getDiscountsAvailable(data) {
@@ -15147,7 +15188,7 @@ const publicPricingSchema = z.object({
15147
15188
  singlePriceAmount: z.number().nullable(),
15148
15189
  slidingMinAmount: z.number().nullable(),
15149
15190
  slidingMaxAmount: z.number().nullable(),
15150
- options: z.array(publicPricingOptionSchema)
15191
+ options: z.array(publicPricingOptionSchema).readonly()
15151
15192
  });
15152
15193
  const publicAppointmentServiceSchema = z.object({
15153
15194
  id: z.string().min(1),
@@ -22697,16 +22738,6 @@ var init_appearancePresets = __esmMin((() => {
22697
22738
  var init_blockFlow = __esmMin((() => {
22698
22739
  init_types$8();
22699
22740
  }));
22700
- var init_tokens$1 = __esmMin((() => {}));
22701
- //#endregion
22702
- //#region ../theme-core/src/tokens/index.ts
22703
- var init_tokens = __esmMin((() => {
22704
- init_tokens$1();
22705
- init_blockColorTokens();
22706
- init_themeColorTokens();
22707
- init_colorTokenParts();
22708
- init_resolver$1();
22709
- }));
22710
22741
  //#endregion
22711
22742
  //#region ../theme-core/src/site-styles/backgroundAppearance.ts
22712
22743
  function parseBackgroundAppearanceColorToken(value) {
@@ -28091,6 +28122,7 @@ function diffJsonPaths(left, right, path = "") {
28091
28122
  }
28092
28123
  var init_headerBytesComparison = __esmMin((() => {}));
28093
28124
  var init_headerOpeningForeground = __esmMin((() => {
28125
+ init_foregroundInteraction();
28094
28126
  init_expandPalette();
28095
28127
  init_colorConversion();
28096
28128
  init_tokens();
@@ -33624,6 +33656,49 @@ var init_registrationEventAdapter = __esmMin((() => {
33624
33656
  init_runGrouping();
33625
33657
  }));
33626
33658
  //#endregion
33659
+ //#region ../blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.ts
33660
+ function resolveEventRegistrationEventSource(input) {
33661
+ if (input.wholeSeriesRunEvents != null) return {
33662
+ kind: "loaded",
33663
+ events: input.wholeSeriesRunEvents
33664
+ };
33665
+ if (input.events != null) return {
33666
+ kind: "loaded",
33667
+ events: input.events
33668
+ };
33669
+ return {
33670
+ kind: "unresolved",
33671
+ request: parseEventLoaderRecoveryRequest(input.failures?.wholeSeriesRunEvents ?? input.failures?.events)
33672
+ };
33673
+ }
33674
+ function parseEventLoaderRecoveryRequest(value) {
33675
+ const parsed = eventLoaderFailureSchema.safeParse(value);
33676
+ if (!parsed.success) return null;
33677
+ const { siteId: _siteId, stage, ...params } = parsed.data.params;
33678
+ return {
33679
+ ...params,
33680
+ stage: stage ?? "published"
33681
+ };
33682
+ }
33683
+ var _rawLimit, _rawEventSurface, _rawScheduleScope, _rawDetailLevel, stringEventQueryShape, eventRecoveryRequestSchema, eventLoaderFailureSchema;
33684
+ var init_eventSourceRecovery = __esmMin((() => {
33685
+ init_schemas();
33686
+ init_filtering();
33687
+ ({limit: _rawLimit, eventSurface: _rawEventSurface, scheduleScope: _rawScheduleScope, detailLevel: _rawDetailLevel, ...stringEventQueryShape} = publicEventLoaderQuerySchemaShape);
33688
+ eventRecoveryRequestSchema = z.object({
33689
+ ...stringEventQueryShape,
33690
+ limit: z.coerce.number().int().positive().optional(),
33691
+ eventSurface: z.enum(eventSurfaceScopeValues).optional(),
33692
+ scheduleScope: z.enum(eventScheduleScopeValues).optional(),
33693
+ detailLevel: z.enum(["full", "listing"]).optional(),
33694
+ stage: z.enum(["preview", "published"]).optional()
33695
+ });
33696
+ eventLoaderFailureSchema = z.object({
33697
+ endpoint: z.literal("listPublicEvents"),
33698
+ params: eventRecoveryRequestSchema.extend({ siteId: z.string().optional() })
33699
+ });
33700
+ }));
33701
+ //#endregion
33627
33702
  //#region ../blocks/src/system/runtime/nodes/event-registration.interactive.ts
33628
33703
  function buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents) {
33629
33704
  const selectedRun = resolveSelectedWholeSeriesRun(scopedSourceEvents);
@@ -33672,16 +33747,12 @@ function buildEventRegistrationShellStepLabels(source, scopedSourceEvents) {
33672
33747
  function toScopedEventRegistrationEvents(scopedSourceEvents) {
33673
33748
  return [...toRegistrationEvents(scopedSourceEvents), ...toWholeSeriesRegistrationEvents(scopedSourceEvents)];
33674
33749
  }
33675
- function scopeEventRegistrationSourceEvents(source) {
33676
- return resolveEventRegistrationScopedEvents(source.wholeSeriesRunEvents ?? source.events ?? [], {
33750
+ function scopeEventRegistrationSourceEvents(source, eventSource) {
33751
+ return resolveEventRegistrationScopedEvents(eventSource.kind === "loaded" ? eventSource.events : [], {
33677
33752
  occurrenceContext: source.occurrenceContext,
33678
33753
  subject: source.subject
33679
33754
  });
33680
33755
  }
33681
- function resolveLoadedEventRegistrationSourceEvents(source, scopedSourceEvents) {
33682
- if (source.events == null && source.wholeSeriesRunEvents == null) return null;
33683
- return [...scopedSourceEvents];
33684
- }
33685
33756
  /**
33686
33757
  * The one run this surface is registering for, when the scoped events describe
33687
33758
  * exactly one. More than one run means the visitor still has to choose.
@@ -33738,7 +33809,7 @@ function buildEventRegistrationInteractiveIslandProps(props) {
33738
33809
  source: props
33739
33810
  });
33740
33811
  }
33741
- var EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS, EVENT_REGISTRATION_SHELL_STEP_LABELS, eventRegistrationPublicEventSchema, eventRegistrationHydrationSchemaShape, eventRegistrationSourceSchema, eventRegistrationDisplaySchema, eventRegistrationHydrationSchema, eventRegistrationRenderSchema, eventRegistrationIslandMetaCodec, eventRegistrationIslandMetaKeys, eventRegistrationBlockRuntime, eventRegistrationInteractiveIslandPropsCodec;
33812
+ var EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS, EVENT_REGISTRATION_SHELL_STEP_LABELS, eventRegistrationPublicEventSchema, eventRegistrationHydrationSchemaShape, eventRegistrationEventSourceSchema, eventRegistrationSourceSchema, eventRegistrationDisplaySchema, eventRegistrationHydrationSchema, eventRegistrationRenderSchema, eventRegistrationIslandMetaCodec, eventRegistrationIslandMetaKeys, eventRegistrationBlockRuntime, eventRegistrationInteractiveIslandPropsCodec;
33742
33813
  var init_event_registration_interactive = __esmMin((() => {
33743
33814
  init_schemas();
33744
33815
  init_runGrouping();
@@ -33752,6 +33823,7 @@ var init_event_registration_interactive = __esmMin((() => {
33752
33823
  init_wizardSteps$1();
33753
33824
  init_registrationDerivations();
33754
33825
  init_registrationEventAdapter();
33826
+ init_eventSourceRecovery();
33755
33827
  EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS = [
33756
33828
  "Date",
33757
33829
  "Tickets",
@@ -33768,8 +33840,6 @@ var init_event_registration_interactive = __esmMin((() => {
33768
33840
  eventRegistrationHydrationSchemaShape = {
33769
33841
  occurrenceContext: occurrenceContextSchema.optional(),
33770
33842
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
33771
- events: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
33772
- wholeSeriesRunEvents: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
33773
33843
  maxTickets: z.string().optional(),
33774
33844
  showVenue: z.boolean().optional(),
33775
33845
  showCapacity: z.boolean().optional(),
@@ -33781,12 +33851,22 @@ var init_event_registration_interactive = __esmMin((() => {
33781
33851
  sitePasses: publicPassProductCollectionSchema.nullable().optional(),
33782
33852
  siteMemberships: publicMembershipProductCollectionSchema.nullable().optional()
33783
33853
  };
33854
+ eventRegistrationEventSourceSchema = z.discriminatedUnion("kind", [z.object({
33855
+ kind: z.literal("loaded"),
33856
+ events: z.array(eventRegistrationPublicEventSchema)
33857
+ }), z.object({
33858
+ kind: z.literal("unresolved"),
33859
+ request: eventRecoveryRequestSchema.nullable()
33860
+ })]);
33784
33861
  eventRegistrationSourceSchema = z.object({
33785
33862
  siteId: z.string().optional(),
33786
33863
  apiBaseUrl: z.string().optional(),
33787
33864
  portalToken: z.string().nullable().optional(),
33788
33865
  previewToken: z.string().nullable().optional(),
33789
33866
  ...eventRegistrationHydrationSchemaShape,
33867
+ events: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
33868
+ wholeSeriesRunEvents: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
33869
+ eventLoaderFailures: z.record(z.string(), z.unknown()).nullable().optional(),
33790
33870
  className: z.string().nullable().optional(),
33791
33871
  buttonText: z.string().nullable().optional(),
33792
33872
  maxTickets: z.string().nullable().optional(),
@@ -33807,7 +33887,10 @@ var init_event_registration_interactive = __esmMin((() => {
33807
33887
  titleText: z.string(),
33808
33888
  bodyText: z.string()
33809
33889
  })]);
33810
- eventRegistrationHydrationSchema = z.object(eventRegistrationHydrationSchemaShape);
33890
+ eventRegistrationHydrationSchema = z.object({
33891
+ ...eventRegistrationHydrationSchemaShape,
33892
+ eventSource: eventRegistrationEventSourceSchema
33893
+ });
33811
33894
  eventRegistrationRenderSchema = z.object({
33812
33895
  display: eventRegistrationDisplaySchema,
33813
33896
  hydration: eventRegistrationHydrationSchema
@@ -33827,14 +33910,21 @@ var init_event_registration_interactive = __esmMin((() => {
33827
33910
  render: createZodCodec(eventRegistrationRenderSchema)
33828
33911
  },
33829
33912
  buildRender: (source) => {
33830
- const scopedSourceEvents = scopeEventRegistrationSourceEvents(source);
33831
- const events = resolveLoadedEventRegistrationSourceEvents(source, scopedSourceEvents);
33913
+ const eventSource = resolveEventRegistrationEventSource({
33914
+ events: source.events,
33915
+ wholeSeriesRunEvents: source.wholeSeriesRunEvents,
33916
+ failures: source.eventLoaderFailures
33917
+ });
33918
+ const scopedSourceEvents = scopeEventRegistrationSourceEvents(source, eventSource);
33832
33919
  return {
33833
33920
  display: buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents),
33834
33921
  hydration: {
33835
33922
  occurrenceContext: source.occurrenceContext ?? null,
33836
33923
  subject: source.subject ?? null,
33837
- events,
33924
+ eventSource: eventSource.kind === "loaded" ? {
33925
+ ...eventSource,
33926
+ events: [...scopedSourceEvents]
33927
+ } : eventSource,
33838
33928
  maxTickets: source.maxTickets ?? void 0,
33839
33929
  showVenue: source.showVenue,
33840
33930
  showCapacity: source.showCapacity,
@@ -34026,6 +34116,7 @@ const eventRegistrationBlockDefinition = {
34026
34116
  } },
34027
34117
  events: { $bind: { from: "data.events" } },
34028
34118
  wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
34119
+ loaderFailures: { $bind: { from: "$root.loaderFailures" } },
34029
34120
  sitePasses: { $bind: { from: "data.sitePasses" } },
34030
34121
  siteMemberships: { $bind: { from: "data.siteMemberships" } },
34031
34122
  stage: { $bind: {
@@ -36096,6 +36187,7 @@ function buildNewsletterDisplay(source) {
36096
36187
  fields: { preset: "emailOnly" },
36097
36188
  includeOptionalPhone: false,
36098
36189
  buttonLabel: "Subscribe",
36190
+ successMessage: DEFAULT_MAILING_LIST_SUCCESS_MESSAGE,
36099
36191
  privacyNote: null
36100
36192
  };
36101
36193
  const targeting = source.targeting ?? { mode: "default" };
@@ -36105,6 +36197,7 @@ function buildNewsletterDisplay(source) {
36105
36197
  availability: runtimeTargetingIsAvailable(context, targeting, choices) ? "ready" : "unavailable",
36106
36198
  className: source.className ?? null,
36107
36199
  buttonLabel: form.buttonLabel,
36200
+ successMessage: form.successMessage,
36108
36201
  buttonVariant: source.buttonVariant ?? "primary",
36109
36202
  privacyNote: form.privacyNote,
36110
36203
  fields: getGlobalFormFields(form),
@@ -36114,7 +36207,7 @@ function buildNewsletterDisplay(source) {
36114
36207
  function projectNewsletterFormHydrationTarget(source) {
36115
36208
  switch (source.source) {
36116
36209
  case "block": {
36117
- const sourceRef = buildMailingListSignupBlockSourceRef(source.blockId);
36210
+ const sourceRef = buildMailingListSignupBlockSourceRef(source.blockId, source.contentVersionId);
36118
36211
  if (sourceRef?.tag === "block_ref") return {
36119
36212
  tag: "block-source",
36120
36213
  sourceRef
@@ -36214,7 +36307,7 @@ function parseRequiredMailingListSignedSourceToken(value) {
36214
36307
  if (!parsed) throw new Error("Mailing-list signup signed source ref requires token");
36215
36308
  return parsed;
36216
36309
  }
36217
- var newsletterButtonVariantSchema, mailingListContextSchema, mailingListTargetingSchema, newsletterFieldSchema, mailingListSignupBlockIdSchema, signedMailingListSourceTokenSchema, newsletterSourceCommonSchema, newsletterSourceSchema, newsletterDisplaySchema, newsletterHydrationSchema, newsletterRenderSchema, newsletterIslandMetaCodec, newsletterIslandMetaKeys, newsletterFormBlockRuntime, newsletterFormInteractiveIslandPropsCodec;
36310
+ var newsletterButtonVariantSchema, mailingListContextSchema, mailingListTargetingSchema, newsletterFieldSchema, mailingListSignupBlockIdSchema, mailingListContentVersionIdSchema, signedMailingListSourceTokenSchema, newsletterSourceCommonSchema, newsletterSourceSchema, newsletterDisplaySchema, newsletterHydrationSchema, newsletterRenderSchema, newsletterIslandMetaCodec, newsletterIslandMetaKeys, newsletterFormBlockRuntime, newsletterFormInteractiveIslandPropsCodec;
36218
36311
  var init_newsletter_form_interactive = __esmMin((() => {
36219
36312
  init_src$2();
36220
36313
  init_islands();
@@ -36252,6 +36345,15 @@ var init_newsletter_form_interactive = __esmMin((() => {
36252
36345
  placeholder: z.string().optional()
36253
36346
  });
36254
36347
  mailingListSignupBlockIdSchema = z.string().trim().min(1).transform(parseRequiredMailingListSignupBlockId);
36348
+ mailingListContentVersionIdSchema = z.string().transform((value, ctx) => {
36349
+ const parsed = parseMailingListContentVersionId(value);
36350
+ if (parsed) return parsed;
36351
+ ctx.addIssue({
36352
+ code: z.ZodIssueCode.custom,
36353
+ message: "Invalid mailing-list content version ID"
36354
+ });
36355
+ return z.NEVER;
36356
+ });
36255
36357
  signedMailingListSourceTokenSchema = z.string().trim().min(1).transform(parseRequiredMailingListSignedSourceToken);
36256
36358
  newsletterSourceCommonSchema = z.object({
36257
36359
  siteId: z.string().optional(),
@@ -36265,7 +36367,8 @@ var init_newsletter_form_interactive = __esmMin((() => {
36265
36367
  newsletterSourceSchema = z.discriminatedUnion("source", [
36266
36368
  newsletterSourceCommonSchema.extend({
36267
36369
  source: z.literal("block"),
36268
- blockId: z.string().nullable().optional()
36370
+ blockId: z.string().nullable().optional(),
36371
+ contentVersionId: z.string().nullable().optional()
36269
36372
  }),
36270
36373
  newsletterSourceCommonSchema.extend({
36271
36374
  source: z.literal("signed-footer"),
@@ -36281,6 +36384,7 @@ var init_newsletter_form_interactive = __esmMin((() => {
36281
36384
  availability: z.enum(["ready", "unavailable"]),
36282
36385
  className: z.string().nullable(),
36283
36386
  buttonLabel: z.string(),
36387
+ successMessage: z.string(),
36284
36388
  buttonVariant: newsletterButtonVariantSchema,
36285
36389
  privacyNote: z.string().nullable(),
36286
36390
  fields: z.array(newsletterFieldSchema),
@@ -36295,7 +36399,8 @@ var init_newsletter_form_interactive = __esmMin((() => {
36295
36399
  tag: z.literal("block-source"),
36296
36400
  sourceRef: z.object({
36297
36401
  tag: z.literal("block_ref"),
36298
- blockId: mailingListSignupBlockIdSchema
36402
+ blockId: mailingListSignupBlockIdSchema,
36403
+ contentVersionId: mailingListContentVersionIdSchema
36299
36404
  }).nullable()
36300
36405
  }),
36301
36406
  z.object({
@@ -38728,9 +38833,10 @@ function cx(...classes) {
38728
38833
  * Server-safe placeholder for event registration.
38729
38834
  * Provides a static container for island hydration without importing client hooks.
38730
38835
  */
38731
- function EventRegistrationSSR({ blockId, subject, children, ...sourceProps }) {
38836
+ function EventRegistrationSSR({ blockId, subject, loaderFailures, children, ...sourceProps }) {
38732
38837
  const islandProps = buildEventRegistrationInteractiveIslandProps({
38733
38838
  ...sourceProps,
38839
+ eventLoaderFailures: blockId ? loaderFailures?.[blockId] : void 0,
38734
38840
  subject: normalizeEventRegistrationPageSurfaceSubject(subject)
38735
38841
  });
38736
38842
  const display = islandProps.render.display;
@@ -39071,7 +39177,7 @@ function NewsletterFormSSR(props) {
39071
39177
  className: clsx("newsletter-form-ssr", className),
39072
39178
  children: /* @__PURE__ */ jsx("p", {
39073
39179
  role: "status",
39074
- children: "Mailing-list signup is not available right now."
39180
+ children: "We can’t accept signups right now. Please try again later."
39075
39181
  })
39076
39182
  });
39077
39183
  const renderField = (field) => {
@@ -39117,14 +39223,18 @@ function NewsletterFormSSR(props) {
39117
39223
  children: [
39118
39224
  fields.map(renderField),
39119
39225
  islandProps.render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsxs("fieldset", {
39120
- className: "newsletter-topics",
39121
- children: [/* @__PURE__ */ jsx("legend", { children: "What would you like to hear about?" }), display.choices.map((choice) => /* @__PURE__ */ jsxs("label", {
39122
- className: "newsletter-topic-choice",
39226
+ className: "fb-fieldset newsletter-topics",
39227
+ children: [/* @__PURE__ */ jsx("legend", {
39228
+ className: "form-label",
39229
+ children: "What would you like to hear about?"
39230
+ }), display.choices.map((choice) => /* @__PURE__ */ jsxs("label", {
39231
+ className: "fb-inline form-label newsletter-topic-choice",
39123
39232
  children: [/* @__PURE__ */ jsx("input", {
39124
39233
  type: "checkbox",
39125
39234
  name: "mailingListChoice",
39126
- value: choice.id
39127
- }), choice.label]
39235
+ value: choice.id,
39236
+ className: "form-checkbox"
39237
+ }), /* @__PURE__ */ jsx("span", { children: choice.label })]
39128
39238
  }, choice.id))]
39129
39239
  }) : null,
39130
39240
  /* @__PURE__ */ jsx("div", {
@@ -45929,12 +46039,6 @@ var init_ActionRow = __esmMin((() => {
45929
46039
  between: "rb-justify-between"
45930
46040
  };
45931
46041
  }));
45932
- var init_BookingOptionCompactRow = __esmMin((() => {
45933
- init_buttons();
45934
- }));
45935
- var init_BookingOptionList = __esmMin((() => {
45936
- init_BookingOptionCompactRow();
45937
- }));
45938
46042
  //#endregion
45939
46043
  //#region ../blocks/src/system/runtime/shared/components/LoggedInAsUser.tsx
45940
46044
  /**
@@ -46163,8 +46267,6 @@ var init_components = __esmMin((() => {
46163
46267
  init_CrossIcon();
46164
46268
  init_DiscountCodeDisclosure();
46165
46269
  init_ActionRow();
46166
- init_BookingOptionCompactRow();
46167
- init_BookingOptionList();
46168
46270
  init_FieldValidationMessage();
46169
46271
  init_FeedbackMessage();
46170
46272
  init_LoggedInAsUser();
@@ -46730,6 +46832,93 @@ var init_event_registration_headless_state = __esmMin((() => {
46730
46832
  init_event_registration_headless_planning();
46731
46833
  }));
46732
46834
  //#endregion
46835
+ //#region ../blocks/src/system/runtime/nodes/event-registration/checkoutRecovery.ts
46836
+ /** Recovery may select held places; checkout still owns admission and payment validation. */
46837
+ function checkoutRecoveryOptionAvailability(availability) {
46838
+ if (availability.kind === "available" || availability.reason === "sold_out" || availability.reason === "overallCapacityUnavailable") return {
46839
+ kind: "available",
46840
+ remainingPlaces: null
46841
+ };
46842
+ return availability;
46843
+ }
46844
+ /**
46845
+ * A form-only projection for the explicit existing-checkout path. It permits
46846
+ * collecting the original selection without claiming a new place is available.
46847
+ * The public checkout service identifies the customer and remains the admission
46848
+ * authority; no reservation/customer data is exposed through this projection.
46849
+ */
46850
+ function getCheckoutRecoveryFormEligibility(eligibility) {
46851
+ if (!eligibility || eligibility.registration.kind !== "none" && eligibility.registration.kind !== "pending_payment" || eligibility.availability.kind === "unavailable" && eligibility.availability.reason !== "full" && eligibility.availability.reason !== "selectionRequired") return eligibility;
46852
+ const amountCents = eligibility.price ?? 0;
46853
+ if (amountCents <= 0 || !eligibility.currency || eligibility.availability.kind === "unavailable" && eligibility.availability.reason === "selectionRequired") return eligibility.registration.kind === "pending_payment" ? {
46854
+ ...eligibility,
46855
+ registration: { kind: "none" },
46856
+ ticketTypes: eligibility.ticketTypes.map((option) => ({
46857
+ ...option,
46858
+ availability: checkoutRecoveryOptionAvailability(option.availability)
46859
+ }))
46860
+ } : eligibility;
46861
+ const currency = eligibility.currency;
46862
+ const paymentOptions = eligibility.paymentTerms.allowedOptions.map((option) => {
46863
+ switch (option.kind) {
46864
+ case "upfront": return {
46865
+ kind: "payInFull",
46866
+ amountCents,
46867
+ currency
46868
+ };
46869
+ case "deferred_manual": return {
46870
+ kind: "deferredManual",
46871
+ amountCents,
46872
+ currency
46873
+ };
46874
+ case "instalment_plan": return {
46875
+ kind: "instalmentPlan",
46876
+ amountCents,
46877
+ currency
46878
+ };
46879
+ case "flexible_balance": return {
46880
+ kind: "flexibleBalance",
46881
+ amountCents,
46882
+ currency
46883
+ };
46884
+ }
46885
+ });
46886
+ return {
46887
+ ...eligibility,
46888
+ registration: { kind: "none" },
46889
+ availability: {
46890
+ kind: "available",
46891
+ remainingPlaces: null,
46892
+ waitlistEnabled: eligibility.waitlistEnabled
46893
+ },
46894
+ eligible: paymentOptions.length > 0,
46895
+ isFull: false,
46896
+ canJoinWaitlist: false,
46897
+ isFree: false,
46898
+ requiresPayment: true,
46899
+ canPayDirectly: paymentOptions.length > 0,
46900
+ paymentOptions,
46901
+ eligiblePasses: [],
46902
+ eligibleMemberships: [],
46903
+ ticketTypes: eligibility.ticketTypes.map((option) => ({
46904
+ ...option,
46905
+ availability: checkoutRecoveryOptionAvailability(option.availability)
46906
+ }))
46907
+ };
46908
+ }
46909
+ function isSoldOutEventSelectable(event, waitlistAvailable) {
46910
+ return waitlistAvailable || canRecoverEventCheckout(event);
46911
+ }
46912
+ function canJoinWaitlistOutsideRecovery(event, attendanceMode, checkoutRecovery) {
46913
+ return !checkoutRecovery && event !== null && canJoinEventWaitlist(event, { attendanceMode });
46914
+ }
46915
+ function canRecoverEventCheckout(event) {
46916
+ return event !== null && (event.registrationSubject.kind === "wholeSeries" || event.pricing.kind !== "free" && event.pricing.kind !== "external");
46917
+ }
46918
+ var init_checkoutRecovery = __esmMin((() => {
46919
+ init_domain();
46920
+ }));
46921
+ //#endregion
46733
46922
  //#region ../blocks/src/system/runtime/nodes/event-registration/utils.ts
46734
46923
  function getPortalSubjectEmail(profile) {
46735
46924
  return profile?.email ?? null;
@@ -46901,6 +47090,7 @@ function getEventSelectionMode(events) {
46901
47090
  }
46902
47091
  var EventSelectionStep;
46903
47092
  var init_EventSelectionStep = __esmMin((() => {
47093
+ init_checkoutRecovery();
46904
47094
  init_utils();
46905
47095
  init_domain();
46906
47096
  EventSelectionStep = ({ events, selectedEvent, onSelect, showVenue, showCapacity }) => {
@@ -46917,7 +47107,7 @@ var init_EventSelectionStep = __esmMin((() => {
46917
47107
  const remaining = getRemainingPlaces(selectMostOpenCapacitySource(event));
46918
47108
  const isSoldOut = isEventFull(event);
46919
47109
  const canJoinWaitlist = canJoinEventWaitlistOnAnyMode(event);
46920
- const isUnavailable = isSoldOut && !canJoinWaitlist;
47110
+ const isUnavailable = isSoldOut && !isSoldOutEventSelectable(event, canJoinWaitlist);
46921
47111
  const isLowCapacity = remaining.kind === "low";
46922
47112
  const capacityLabel = formatEventRemainingPlaces(event, { full: "Sold out" });
46923
47113
  const timeZone = event.timeZone ?? null;
@@ -46963,6 +47153,36 @@ var init_EventSelectionStep = __esmMin((() => {
46963
47153
  };
46964
47154
  }));
46965
47155
  //#endregion
47156
+ //#region ../blocks/src/system/runtime/nodes/event-registration/useCheckoutRecovery.ts
47157
+ /** Recovery belongs to the selected booking subject; changing events resets its scope. */
47158
+ function useCheckoutRecovery(event, setStep) {
47159
+ const [recoveryEventId, setRecoveryEventId] = useState(null);
47160
+ return {
47161
+ checkoutRecovery: event !== null && recoveryEventId === event.selectionId,
47162
+ startCheckoutRecovery: useCallback(() => {
47163
+ if (!event) return;
47164
+ setRecoveryEventId(event.selectionId);
47165
+ setStep("select-tickets");
47166
+ }, [event, setStep])
47167
+ };
47168
+ }
47169
+ /** Authenticated pending bookings enter the same form-only recovery path as guests. */
47170
+ function useCheckoutRecoveryEligibility(eligibility, step, checkoutRecovery, startCheckoutRecovery) {
47171
+ const registrationKind = eligibility?.registration.kind;
47172
+ useEffect(() => {
47173
+ if ((step === "select-event" || step === "select-tickets" || step === "enter-details" || step === "select-payment") && registrationKind === "pending_payment" && !checkoutRecovery) startCheckoutRecovery();
47174
+ }, [
47175
+ registrationKind,
47176
+ step,
47177
+ checkoutRecovery,
47178
+ startCheckoutRecovery
47179
+ ]);
47180
+ return useMemo(() => checkoutRecovery ? getCheckoutRecoveryFormEligibility(eligibility) : eligibility, [checkoutRecovery, eligibility]);
47181
+ }
47182
+ var init_useCheckoutRecovery = __esmMin((() => {
47183
+ init_checkoutRecovery();
47184
+ }));
47185
+ //#endregion
46966
47186
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationErrorRecovery.ts
46967
47187
  function resolveRegistrationRecoveryAction(step, action) {
46968
47188
  if (step === "payment-failed") return "payment-options";
@@ -47835,6 +48055,10 @@ var init_event_registration_errors = __esmMin((() => {
47835
48055
  message: "We’re checking your booking and payment. Please don’t try to book again yet. If you’ve already paid, you don’t need to pay again.",
47836
48056
  action: "payment-status"
47837
48057
  },
48058
+ paymentProviderUnavailable: {
48059
+ message: "We couldn’t reach the payment provider. Please try again in a minute.",
48060
+ action: "retry"
48061
+ },
47838
48062
  paymentPageUnavailable: {
47839
48063
  message: "We couldn’t open the payment page. Please refresh this page and try again. If this keeps happening, contact the organiser for help.",
47840
48064
  action: "retry"
@@ -48020,11 +48244,6 @@ function ensureWaitlistClaimLocationTracking() {
48020
48244
  } catch {}
48021
48245
  window.addEventListener("popstate", emitWaitlistClaimLocationChange);
48022
48246
  }
48023
- function getWaitlistClaimTokenFromUrl() {
48024
- if (typeof window === "undefined") return null;
48025
- const token = new URLSearchParams(window.location.search).get("waitlist_claim")?.trim() ?? "";
48026
- return token.length > 0 ? token : null;
48027
- }
48028
48247
  function subscribeToWaitlistClaimToken(callback) {
48029
48248
  if (typeof window === "undefined") return () => {};
48030
48249
  ensureWaitlistClaimLocationTracking();
@@ -48033,28 +48252,42 @@ function subscribeToWaitlistClaimToken(callback) {
48033
48252
  window.removeEventListener(WAITLIST_CLAIM_LOCATION_EVENT, callback);
48034
48253
  };
48035
48254
  }
48036
- function getWaitlistClaimTokenSnapshot() {
48037
- return getWaitlistClaimTokenFromUrl();
48255
+ function getWaitlistClaimLocationSnapshot() {
48256
+ return typeof window === "undefined" ? "" : window.location.search;
48257
+ }
48258
+ function parseWaitlistClaimCredential(search) {
48259
+ const params = new URLSearchParams(search);
48260
+ const token = params.get("waitlist_claim")?.trim();
48261
+ if (token) return {
48262
+ kind: "emailedToken",
48263
+ token
48264
+ };
48265
+ const entryId = params.get("waitlistEntry")?.trim();
48266
+ return entryId ? {
48267
+ kind: "portalOwnedEntry",
48268
+ entryId
48269
+ } : null;
48038
48270
  }
48039
48271
  function useWaitlistClaim() {
48040
48272
  return useWaitlistClaimWithDeps(useWaitlistClaimDeps);
48041
48273
  }
48042
48274
  function useWaitlistClaimWithDeps(deps) {
48043
- return useResolvedWaitlistClaim(deps, useSyncExternalStore(subscribeToWaitlistClaimToken, getWaitlistClaimTokenSnapshot, () => null));
48275
+ const locationSearch = useSyncExternalStore(subscribeToWaitlistClaimToken, getWaitlistClaimLocationSnapshot, () => "");
48276
+ return useResolvedWaitlistClaim(deps, useMemo(() => parseWaitlistClaimCredential(locationSearch), [locationSearch]));
48044
48277
  }
48045
- function useResolvedWaitlistClaim(deps, token) {
48278
+ function useResolvedWaitlistClaim(deps, credential) {
48046
48279
  const api = deps.useBlockApi();
48047
- const [state, dispatch] = useReducer(waitlistClaimReducer, Boolean(token), createInitialWaitlistClaimState);
48280
+ const [state, dispatch] = useReducer(waitlistClaimReducer, Boolean(credential), createInitialWaitlistClaimState);
48048
48281
  useEffect(() => {
48049
48282
  let cancelled = false;
48050
48283
  async function resolveClaim() {
48051
- if (!token) {
48284
+ if (!credential) {
48052
48285
  dispatch({ type: "cleared" });
48053
48286
  return;
48054
48287
  }
48055
48288
  dispatch({ type: "started" });
48056
48289
  try {
48057
- const result = await api.resolveWaitlistClaim({ claimToken: token });
48290
+ const result = credential.kind === "portalOwnedEntry" ? await api.resolveWaitlistClaim({ waitlistEntryId: credential.entryId }) : await api.resolveWaitlistClaim({ claimToken: credential.token });
48058
48291
  if (cancelled) return;
48059
48292
  dispatch({
48060
48293
  type: "resolved",
@@ -48072,9 +48305,10 @@ function useResolvedWaitlistClaim(deps, token) {
48072
48305
  return () => {
48073
48306
  cancelled = true;
48074
48307
  };
48075
- }, [api, token]);
48308
+ }, [api, credential]);
48076
48309
  return {
48077
- token,
48310
+ token: credential?.kind === "emailedToken" ? credential.token : null,
48311
+ entryId: credential?.kind === "portalOwnedEntry" ? credential.entryId : null,
48078
48312
  claim: getWaitlistClaim(state),
48079
48313
  error: getWaitlistClaimError(state),
48080
48314
  loginMessage: getWaitlistClaimLoginMessage(state),
@@ -48577,15 +48811,12 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
48577
48811
  * landed — a success, or a hand-off to checkout — because until then nobody
48578
48812
  * knows whether the first one committed.
48579
48813
  *
48580
- * Reusing it after a failure is safe even if the customer edits their
48581
- * details. The server consults the command record before it re-checks
48582
- * anything, so a submission that already booked is answered with the booking
48583
- * that exists — not refused for spending a credit or a claim that this very
48584
- * command already spent, and not treated as a second booking because a name
48585
- * or a note changed in between.
48814
+ * Identical retries retain the command after a lost response. Changed form
48815
+ * details get a new command so the server applies the new booking intent.
48586
48816
  */
48587
- const commandIdRef = useRef(null);
48588
- return async (method, passId, membershipId, selection, submitOptions) => {
48817
+ const commandRef = useRef(null);
48818
+ const inFlightRef = useRef(null);
48819
+ const submit = async (method, passId, membershipId, selection, submitOptions) => {
48589
48820
  const target = options.registrationTarget;
48590
48821
  if (!target) return {
48591
48822
  ok: false,
@@ -48593,44 +48824,34 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
48593
48824
  message: "Select an event to continue."
48594
48825
  };
48595
48826
  options.setStep("submitting");
48596
- const registrationCommandId = commandIdRef.current ?? deps.createClientCommandId();
48597
- commandIdRef.current = registrationCommandId;
48827
+ const registrationCommandId = commandRef.current?.id ?? deps.createClientCommandId();
48598
48828
  try {
48599
- const prepared = prepareSubmitContext(options, registrationCommandId, target, method, passId, membershipId, selection);
48829
+ let prepared = prepareSubmitContext(options, registrationCommandId, target, method, passId, membershipId, selection);
48600
48830
  if (prepared.subject.kind === "wholeSeries" && method === "stripe") {
48601
- commandIdRef.current = null;
48831
+ commandRef.current = null;
48602
48832
  return await submitWholeSeriesCheckout(options, deps, {
48603
48833
  ...prepared,
48604
48834
  subject: prepared.subject
48605
48835
  }, submitOptions);
48606
48836
  }
48837
+ const request = buildOccurrenceRegistrationRequest(options, prepared, method, passId, membershipId);
48838
+ const intentKey = registrationRequestIntentKey(request);
48839
+ if (commandRef.current !== null && commandRef.current.intentKey !== intentKey) prepared = {
48840
+ ...prepared,
48841
+ registrationCommandId: deps.createClientCommandId()
48842
+ };
48843
+ commandRef.current = {
48844
+ id: prepared.registrationCommandId,
48845
+ intentKey
48846
+ };
48607
48847
  const result = await options.api.registerForEvent({
48608
- registrationCommandId: prepared.registrationCommandId,
48609
- subject: prepared.subject,
48610
- ticketSelections: toTicketSelectionRequests(prepared.ticketSelections),
48611
- selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
48612
- email: options.formData.email.trim().toLowerCase(),
48613
- name: options.formData.name.trim(),
48614
- phone: options.formData.phone.trim() || void 0,
48615
- notes: options.formData.notes.trim() || void 0,
48616
- consentAccepted: options.formData.consentAccepted,
48617
- altchaSolution: options.altchaSolution,
48618
- paymentMethod: method,
48619
- customerPassId: method === "pass" ? passId : void 0,
48620
- customerMembershipId: method === "membership" ? membershipId : void 0,
48621
- bundleProductId: prepared.bundleProductId,
48622
- claimToken: options.claimToken ?? void 0,
48623
- guests: prepared.guestsPayload
48848
+ ...request,
48849
+ registrationCommandId: prepared.registrationCommandId
48624
48850
  });
48625
- commandIdRef.current = null;
48626
- if (needsOccurrenceCheckout(result, method)) return await submitOccurrenceCheckout(options, deps, prepared, result, method, submitOptions);
48627
- options.setRegistrationResult(toRegistrationResult(result));
48628
- options.setStep("success");
48629
- return {
48630
- ok: true,
48631
- outcome: { kind: "completed" }
48632
- };
48851
+ commandRef.current = null;
48852
+ return await completeRegistrationSubmission(options, deps, prepared, result, method, submitOptions);
48633
48853
  } catch (error) {
48854
+ if (error instanceof BlockApiError && error.tag === "registrationPreparationChanged") commandRef.current = null;
48634
48855
  const { message, action } = registrationErrorPresentation(error);
48635
48856
  options.setErrorAction?.(action);
48636
48857
  options.setErrorMessage(message);
@@ -48642,6 +48863,24 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
48642
48863
  };
48643
48864
  }
48644
48865
  };
48866
+ return (...args) => {
48867
+ if (inFlightRef.current) return inFlightRef.current;
48868
+ const pending = Promise.resolve().then(() => submit(...args));
48869
+ inFlightRef.current = pending;
48870
+ pending.finally(() => {
48871
+ if (inFlightRef.current === pending) inFlightRef.current = null;
48872
+ });
48873
+ return pending;
48874
+ };
48875
+ }
48876
+ async function completeRegistrationSubmission(options, deps, prepared, result, method, submitOptions) {
48877
+ if (needsOccurrenceCheckout(result, method)) return await submitOccurrenceCheckout(options, deps, prepared, result, method, submitOptions);
48878
+ options.setRegistrationResult(toRegistrationResult(result));
48879
+ options.setStep("success");
48880
+ return {
48881
+ ok: true,
48882
+ outcome: { kind: "completed" }
48883
+ };
48645
48884
  }
48646
48885
  function toTicketSelectionRequests(lines) {
48647
48886
  return lines.map((line) => ({
@@ -48716,6 +48955,7 @@ async function submitWholeSeriesCheckout(options, deps, prepared, submitOptions)
48716
48955
  altchaSolution: options.altchaSolution,
48717
48956
  guests: prepared.guestsPayload,
48718
48957
  claimToken: options.claimToken ?? void 0,
48958
+ waitlistEntryId: options.waitlistEntryId ?? void 0,
48719
48959
  discountCode: options.discountCode.trim() || void 0,
48720
48960
  collectionOptionKind: prepared.selectionSnapshot.collectionOptionKind,
48721
48961
  checkoutAttemptId,
@@ -48737,14 +48977,14 @@ async function submitWholeSeriesCheckout(options, deps, prepared, submitOptions)
48737
48977
  }
48738
48978
  if (result.bypassed) return completeBypassedCheckout(options);
48739
48979
  if (!result.checkoutUrl) throw new Error("Checkout URL missing");
48740
- savePendingCheckout(options, deps, prepared, checkoutAttemptId, {
48980
+ savePendingCheckout(options, deps, prepared, result.checkoutAttemptId, {
48741
48981
  scope: "wholeSeries",
48742
48982
  registrationId: result.registrationId
48743
48983
  });
48744
48984
  return redirectToCheckout(result.checkoutUrl, submitOptions);
48745
48985
  }
48746
48986
  function needsOccurrenceCheckout(result, method) {
48747
- return result.scope === "occurrence" && !result.alreadyRegistered && result.status === "confirmed" && result.pendingPayment && [
48987
+ return result.scope === "occurrence" && result.status === "confirmed" && result.pendingPayment && [
48748
48988
  "stripe",
48749
48989
  "pass_bundle",
48750
48990
  "membership_bundle"
@@ -48764,6 +49004,7 @@ async function submitOccurrenceCheckout(options, deps, prepared, registration, m
48764
49004
  kind: "occurrence",
48765
49005
  attendeeId: registration.attendeeId
48766
49006
  },
49007
+ registrationCommandId: prepared.registrationCommandId,
48767
49008
  checkoutType: method === "pass_bundle" ? "pass_bundle" : method === "membership_bundle" ? "membership_bundle" : "event",
48768
49009
  productId: prepared.bundleProductId,
48769
49010
  discountCode: options.discountCode.trim() || void 0,
@@ -48806,10 +49047,36 @@ function redirectToCheckout(checkoutUrl, submitOptions) {
48806
49047
  }
48807
49048
  };
48808
49049
  }
49050
+ function registrationRequestIntentKey(request) {
49051
+ const { registrationCommandId: _command, altchaSolution: _proof, ...intent } = request;
49052
+ return JSON.stringify(intent);
49053
+ }
49054
+ function buildOccurrenceRegistrationRequest(options, prepared, method, passId, membershipId) {
49055
+ return {
49056
+ registrationCommandId: prepared.registrationCommandId,
49057
+ subject: prepared.subject,
49058
+ ticketSelections: toTicketSelectionRequests(prepared.ticketSelections),
49059
+ selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
49060
+ email: options.formData.email.trim().toLowerCase(),
49061
+ name: options.formData.name.trim(),
49062
+ phone: options.formData.phone.trim() || void 0,
49063
+ notes: options.formData.notes.trim() || void 0,
49064
+ consentAccepted: options.formData.consentAccepted,
49065
+ altchaSolution: options.altchaSolution,
49066
+ paymentMethod: method,
49067
+ customerPassId: method === "pass" ? passId : void 0,
49068
+ customerMembershipId: method === "membership" ? membershipId : void 0,
49069
+ bundleProductId: prepared.bundleProductId,
49070
+ claimToken: options.claimToken ?? void 0,
49071
+ waitlistEntryId: options.waitlistEntryId ?? void 0,
49072
+ guests: prepared.guestsPayload
49073
+ };
49074
+ }
48809
49075
  var eventRegistrationSubmitDeps;
48810
49076
  var init_useEventRegistrationSubmit = __esmMin((() => {
48811
- init_registrationErrorPresentation();
49077
+ init_client$1();
48812
49078
  init_shared();
49079
+ init_registrationErrorPresentation();
48813
49080
  init_constants();
48814
49081
  init_sessionStorage();
48815
49082
  init_ticketSelectionLines();
@@ -49056,14 +49323,28 @@ function useEventRegistrationWizardWithDeps(options, deps) {
49056
49323
  }), [options.occurrenceContext, selectedEvent]);
49057
49324
  const registrationOccurrenceId = getRegistrationOccurrenceId(registrationTarget);
49058
49325
  const currentEvent = selectedEvent ?? preSelectedEvent;
49326
+ const setStep = useCallback((nextStep) => {
49327
+ dispatchFlow({
49328
+ type: "set-step",
49329
+ step: nextStep
49330
+ });
49331
+ }, []);
49332
+ const { checkoutRecovery, startCheckoutRecovery } = useCheckoutRecovery(currentEvent, setStep);
49059
49333
  const currentEventUsesTicketTypes = usesTieredPricing(currentEvent);
49060
- const currentCanJoinWaitlist = currentEvent ? canJoinEventWaitlist(currentEvent, { attendanceMode: selectedAttendanceMode }) : false;
49334
+ const currentCanJoinWaitlist = canJoinWaitlistOutsideRecovery(currentEvent, selectedAttendanceMode, checkoutRecovery);
49061
49335
  const usesTicketTypeSelections = currentEventUsesTicketTypes && !currentCanJoinWaitlist;
49062
49336
  const eventTicketTypesForSelection = useMemo(() => getVisibleTicketTypes({
49063
49337
  event: currentEvent,
49064
49338
  eligibility: null,
49065
49339
  selectedAttendanceMode
49066
- }), [currentEvent, selectedAttendanceMode]);
49340
+ }).map((option) => checkoutRecovery ? {
49341
+ ...option,
49342
+ availability: checkoutRecoveryOptionAvailability(option.availability)
49343
+ } : option), [
49344
+ currentEvent,
49345
+ selectedAttendanceMode,
49346
+ checkoutRecovery
49347
+ ]);
49067
49348
  const normalizedSelectedTicketLines = useMemo(() => normalizeTicketSelectionLines(selectedTicketLines), [selectedTicketLines]);
49068
49349
  const ticketTypeSelectionTotal = useMemo(() => getTicketSelectionTotal(normalizedSelectedTicketLines), [normalizedSelectedTicketLines]);
49069
49350
  const ticketsCount = usesTicketTypeSelections ? ticketTypeSelectionTotal : flowState.ticketsCount;
@@ -49101,17 +49382,11 @@ function useEventRegistrationWizardWithDeps(options, deps) {
49101
49382
  isAuthenticated: portalAuthState === "authenticated",
49102
49383
  occurrenceId: registrationOccurrenceId
49103
49384
  });
49104
- const eligibility = eligibilityResult.eligibility;
49385
+ const eligibility = useCheckoutRecoveryEligibility(eligibilityResult.eligibility, step, checkoutRecovery, startCheckoutRecovery);
49105
49386
  const eligibilityLoading = eligibilityResult.isLoading;
49106
49387
  const eligibilityError = eligibilityResult.error;
49107
49388
  const portalCreditState = eligibilityResult.creditState;
49108
49389
  const registrationState = eligibility?.registration ?? { kind: "none" };
49109
- const setStep = useCallback((nextStep) => {
49110
- dispatchFlow({
49111
- type: "set-step",
49112
- step: nextStep
49113
- });
49114
- }, []);
49115
49390
  const setTicketsCount = useCallback((nextTicketsCount) => {
49116
49391
  dispatchFlow({
49117
49392
  type: "set-tickets-count",
@@ -49219,10 +49494,14 @@ function useEventRegistrationWizardWithDeps(options, deps) {
49219
49494
  event: currentEvent,
49220
49495
  eligibility,
49221
49496
  selectedAttendanceMode
49222
- }), [
49497
+ }).map((option) => checkoutRecovery ? {
49498
+ ...option,
49499
+ availability: checkoutRecoveryOptionAvailability(option.availability)
49500
+ } : option), [
49223
49501
  currentEvent,
49224
49502
  selectedAttendanceMode,
49225
- eligibility
49503
+ eligibility,
49504
+ checkoutRecovery
49226
49505
  ]);
49227
49506
  const singleSelectedPricingOptionId = getSingleSelectedPricingOptionId(normalizedSelectedTicketLines);
49228
49507
  const selectedTicketType = useMemo(() => findSelectedTicketType({
@@ -49246,8 +49525,12 @@ function useEventRegistrationWizardWithDeps(options, deps) {
49246
49525
  const event = currentEvent;
49247
49526
  if (!usesTieredPricing(event)) return false;
49248
49527
  if ((event.deliveryMode ?? "in_person") === "hybrid" && !selectedAttendanceMode) return false;
49249
- return !canJoinEventWaitlist(event, { attendanceMode: selectedAttendanceMode });
49250
- }, [currentEvent, selectedAttendanceMode]);
49528
+ return checkoutRecovery || !canJoinEventWaitlist(event, { attendanceMode: selectedAttendanceMode });
49529
+ }, [
49530
+ currentEvent,
49531
+ selectedAttendanceMode,
49532
+ checkoutRecovery
49533
+ ]);
49251
49534
  const hasValidTicketSelection = hasValidPricingOptionSelection({
49252
49535
  selectionRequired: ticketTypeSelectionRequired,
49253
49536
  lines: normalizedSelectedTicketLines,
@@ -49451,6 +49734,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
49451
49734
  guests,
49452
49735
  discountCode: discountUi.discountCode,
49453
49736
  claimToken: waitlistClaim.token,
49737
+ waitlistEntryId: waitlistClaim.entryId,
49454
49738
  setPendingRegistrationReference,
49455
49739
  setStep,
49456
49740
  setRegistrationResult: (result) => setRegistrationResult(result),
@@ -49513,6 +49797,8 @@ function useEventRegistrationWizardWithDeps(options, deps) {
49513
49797
  scopedEvents,
49514
49798
  preSelectedEvent,
49515
49799
  hasPreSelectedContext,
49800
+ checkoutRecovery,
49801
+ startCheckoutRecovery,
49516
49802
  step,
49517
49803
  setStep,
49518
49804
  selectedEvent,
@@ -49597,6 +49883,8 @@ function useEventRegistrationWizardWithDeps(options, deps) {
49597
49883
  }
49598
49884
  var eventRegistrationWizardDeps;
49599
49885
  var init_useEventRegistrationWizard = __esmMin((() => {
49886
+ init_checkoutRecovery();
49887
+ init_useCheckoutRecovery();
49600
49888
  init_src$2();
49601
49889
  init_registrationErrorRecovery();
49602
49890
  init_api();
@@ -49759,6 +50047,50 @@ var init_MagicLinkForm = __esmMin((() => {
49759
50047
  init_MagicLinkForm_state();
49760
50048
  }));
49761
50049
  //#endregion
50050
+ //#region ../blocks/src/system/runtime/nodes/event-registration/ErrorStep.tsx
50051
+ var labels, ErrorStep;
50052
+ var init_ErrorStep = __esmMin((() => {
50053
+ init_shared();
50054
+ labels = {
50055
+ none: "",
50056
+ retry: "Try again",
50057
+ places: "Choose places",
50058
+ start: "Start again",
50059
+ details: "Check my details",
50060
+ "payment-options": "View payment options",
50061
+ "payment-status": "Check payment status",
50062
+ portal: "View my bookings",
50063
+ event: "View event"
50064
+ };
50065
+ ErrorStep = ({ message, onRetry, action = "retry", canJoinWaitlist = false }) => {
50066
+ const offerWaitlist = action === "places" && canJoinWaitlist;
50067
+ return /* @__PURE__ */ jsx(TerminalPanel, {
50068
+ tone: "error",
50069
+ className: "er-center",
50070
+ titleClassName: "er-title--lg er-message",
50071
+ icon: /* @__PURE__ */ jsx(StateIcon, {
50072
+ variant: "error",
50073
+ children: /* @__PURE__ */ jsx(CrossIcon, {})
50074
+ }),
50075
+ title: "We couldn’t complete your booking",
50076
+ body: /* @__PURE__ */ jsx("p", {
50077
+ className: "er-text--muted er-message",
50078
+ children: offerWaitlist ? "Sorry, this event is now full. You can join the waiting list, and we’ll email you if a place becomes available." : message
50079
+ }),
50080
+ actions: action === "none" ? void 0 : action === "portal" || action === "payment-status" ? /* @__PURE__ */ jsx("a", {
50081
+ href: "/portal",
50082
+ className: "er-retry-btn",
50083
+ children: labels[action]
50084
+ }) : /* @__PURE__ */ jsx("button", {
50085
+ type: "button",
50086
+ onClick: onRetry,
50087
+ className: "er-retry-btn",
50088
+ children: offerWaitlist ? "Join the waiting list" : labels[action]
50089
+ })
50090
+ });
50091
+ };
50092
+ }));
50093
+ //#endregion
49762
50094
  //#region ../blocks/src/system/runtime/nodes/event-registration/EventRegistrationSummaryBar.tsx
49763
50095
  function getScheduleSummary(wizard, summaryEvent) {
49764
50096
  if (summaryEvent.registrationSubject.kind !== "wholeSeries") {
@@ -50048,7 +50380,7 @@ function SelectTicketsActions(props) {
50048
50380
  const currentEvent = wizard.selectedEvent ?? wizard.preSelectedEvent;
50049
50381
  const registrationOptionsPending = wizard.registrationOptionsState.tag === "idle" || wizard.registrationOptionsState.tag === "loading";
50050
50382
  const registrationOptionsFailed = wizard.registrationOptionsState.tag === "failed";
50051
- const isSoldOutWithoutWaitlist = !hasWaitlistClaim && isFullWithNoWaitlist(currentEvent, wizard.selectedAttendanceMode);
50383
+ const isSoldOutWithoutWaitlist = !wizard.checkoutRecovery && !hasWaitlistClaim && isFullWithNoWaitlist(currentEvent, wizard.selectedAttendanceMode);
50052
50384
  const isCheckingExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistrationLoading;
50053
50385
  const hasExistingRegistration = isExistingRegistrationBlocking$1(wizard);
50054
50386
  const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidTicketSelection;
@@ -50653,21 +50985,42 @@ function resolveTicketSelectionPricing(event) {
50653
50985
  currency: event ? publicEventPricingCurrency(event.pricing) : null
50654
50986
  };
50655
50987
  }
50988
+ function CheckoutRecoveryEntry(props) {
50989
+ return props.onContinue ? /* @__PURE__ */ jsx("button", {
50990
+ type: "button",
50991
+ className: "er-back-btn",
50992
+ onClick: props.onContinue,
50993
+ children: "Continue an existing booking"
50994
+ }) : null;
50995
+ }
50996
+ function getTicketSelectionCapacity(event, attendanceMode, checkoutRecovery) {
50997
+ if (checkoutRecovery) return {
50998
+ availableSpots: null,
50999
+ isSoldOut: false,
51000
+ canJoinWaitlist: false,
51001
+ eventAvailabilityLabel: null
51002
+ };
51003
+ const source = event ? selectEventCapacitySource(event, attendanceMode) : null;
51004
+ const availability = source ? getEventAvailability(source) : null;
51005
+ const canJoinWaitlist = source ? canJoinEventWaitlist(source) : false;
51006
+ return {
51007
+ availableSpots: availability?.available,
51008
+ isSoldOut: availability?.isFull ?? false,
51009
+ canJoinWaitlist,
51010
+ eventAvailabilityLabel: !canJoinWaitlist && source ? formatRemainingPlaces(source) : null
51011
+ };
51012
+ }
50656
51013
  var TicketSelectionStep;
50657
51014
  var init_TicketSelectionStep = __esmMin((() => {
50658
51015
  init_src$2();
50659
51016
  init_domain();
50660
51017
  init_utils();
50661
51018
  init_ticketSelectionLines();
50662
- TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, selectedAttendanceMode = null, onAttendanceModeChange, ticketsCount, maxTickets, visibleTicketTypes: visibleTicketTypesOverride, ticketSelections = [], onTicketSelectionsChange, slidingScale = null, selectedSlidingAmountInput = "", slidingScaleSelectionMessage = null, onSlidingAmountChange, onTicketsChange, bookingUnit = { kind: "ticket" } }) => {
51019
+ TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, selectedAttendanceMode = null, onAttendanceModeChange, ticketsCount, maxTickets, visibleTicketTypes: visibleTicketTypesOverride, ticketSelections = [], onTicketSelectionsChange, slidingScale = null, selectedSlidingAmountInput = "", slidingScaleSelectionMessage = null, onSlidingAmountChange, onTicketsChange, bookingUnit = { kind: "ticket" }, checkoutRecovery = false, onCheckoutRecovery }) => {
50663
51020
  const unit = bookingUnit.kind;
50664
51021
  const deliveryMode = event?.deliveryMode ?? "in_person";
50665
51022
  const attendanceModes = event?.attendanceModes ?? [];
50666
- const capacitySource = event ? selectEventCapacitySource(event, selectedAttendanceMode) : null;
50667
- const availability = capacitySource ? getEventAvailability(capacitySource) : null;
50668
- const availableSpots = availability?.available;
50669
- const isSoldOut = availability?.isFull ?? false;
50670
- const canJoinWaitlist = capacitySource ? canJoinEventWaitlist(capacitySource) : false;
51023
+ const { availableSpots, isSoldOut, canJoinWaitlist, eventAvailabilityLabel } = getTicketSelectionCapacity(event, selectedAttendanceMode, checkoutRecovery);
50671
51024
  const { mode: eventPricingMode, currency: eventPricingCurrency } = resolveTicketSelectionPricing(event);
50672
51025
  const usesTicketTypes = eventPricingMode === "tiered" && !canJoinWaitlist;
50673
51026
  const visibleTicketTypes = usesTicketTypes ? visibleTicketTypesOverride ?? getVisibleTicketTypes({
@@ -50686,7 +51039,6 @@ var init_TicketSelectionStep = __esmMin((() => {
50686
51039
  selectedTicketTypeRemainingCapacity: implicitTicketType?.availability.remainingPlaces ?? null,
50687
51040
  hasSelectedTicketType: implicitTicketType !== null
50688
51041
  });
50689
- const eventAvailabilityLabel = !canJoinWaitlist && capacitySource ? formatRemainingPlaces(capacitySource) : null;
50690
51042
  if (deliveryMode === "hybrid" && !selectedAttendanceMode) return /* @__PURE__ */ jsxs("div", {
50691
51043
  className: "rb-reg-stack er-stack",
50692
51044
  children: [
@@ -50707,13 +51059,17 @@ var init_TicketSelectionStep = __esmMin((() => {
50707
51059
  });
50708
51060
  if (isSoldOut && !canJoinWaitlist) return /* @__PURE__ */ jsxs("div", {
50709
51061
  className: "rb-reg-stack er-stack",
50710
- children: [/* @__PURE__ */ jsx("h3", {
50711
- className: "er-title",
50712
- children: "Sold out"
50713
- }), /* @__PURE__ */ jsx("p", {
50714
- className: "er-text er-text--muted",
50715
- children: "Sorry you missed out! This event is fully booked."
50716
- })]
51062
+ children: [
51063
+ /* @__PURE__ */ jsx("h3", {
51064
+ className: "er-title",
51065
+ children: "Sold out"
51066
+ }),
51067
+ /* @__PURE__ */ jsx("p", {
51068
+ className: "er-text er-text--muted",
51069
+ children: "Sorry you missed out! This event is fully booked."
51070
+ }),
51071
+ /* @__PURE__ */ jsx(CheckoutRecoveryEntry, { onContinue: onCheckoutRecovery })
51072
+ ]
50717
51073
  });
50718
51074
  if (!eventPricingCurrency) return /* @__PURE__ */ jsx("div", {
50719
51075
  className: "rb-reg-stack er-stack",
@@ -50781,9 +51137,13 @@ var init_TicketSelectionStep = __esmMin((() => {
50781
51137
  })]
50782
51138
  })
50783
51139
  ] }),
50784
- canJoinWaitlist && /* @__PURE__ */ jsx("p", {
51140
+ canJoinWaitlist && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
50785
51141
  className: "er-text er-text--muted",
50786
51142
  children: "This event is currently full. Continue to join the waitlist if a place opens up."
51143
+ }), /* @__PURE__ */ jsx(CheckoutRecoveryEntry, { onContinue: onCheckoutRecovery })] }),
51144
+ checkoutRecovery && /* @__PURE__ */ jsx("p", {
51145
+ className: "er-text er-text--muted",
51146
+ children: "Enter the details from your earlier booking. We’ll check your checkout before continuing to payment."
50787
51147
  })
50788
51148
  ]
50789
51149
  });
@@ -105942,50 +106302,6 @@ var init_SuccessStep = __esmMin((() => {
105942
106302
  };
105943
106303
  }));
105944
106304
  //#endregion
105945
- //#region ../blocks/src/system/runtime/nodes/event-registration/ErrorStep.tsx
105946
- var labels, ErrorStep;
105947
- var init_ErrorStep = __esmMin((() => {
105948
- init_shared();
105949
- labels = {
105950
- none: "",
105951
- retry: "Try again",
105952
- places: "Choose places",
105953
- start: "Start again",
105954
- details: "Check my details",
105955
- "payment-options": "View payment options",
105956
- "payment-status": "Check payment status",
105957
- portal: "View my bookings",
105958
- event: "View event"
105959
- };
105960
- ErrorStep = ({ message, onRetry, action = "retry", canJoinWaitlist = false }) => {
105961
- const offerWaitlist = action === "places" && canJoinWaitlist;
105962
- return /* @__PURE__ */ jsx(TerminalPanel, {
105963
- tone: "error",
105964
- className: "er-center",
105965
- titleClassName: "er-title--lg er-message",
105966
- icon: /* @__PURE__ */ jsx(StateIcon, {
105967
- variant: "error",
105968
- children: /* @__PURE__ */ jsx(CrossIcon, {})
105969
- }),
105970
- title: "We couldn’t complete your booking",
105971
- body: /* @__PURE__ */ jsx("p", {
105972
- className: "er-text--muted er-message",
105973
- children: offerWaitlist ? "Sorry, this event is now full. You can join the waiting list, and we’ll email you if a place becomes available." : message
105974
- }),
105975
- actions: action === "none" ? void 0 : action === "portal" || action === "payment-status" ? /* @__PURE__ */ jsx("a", {
105976
- href: "/portal",
105977
- className: "er-retry-btn",
105978
- children: labels[action]
105979
- }) : /* @__PURE__ */ jsx("button", {
105980
- type: "button",
105981
- onClick: onRetry,
105982
- className: "er-retry-btn",
105983
- children: offerWaitlist ? "Join the waiting list" : labels[action]
105984
- })
105985
- });
105986
- };
105987
- }));
105988
- //#endregion
105989
106305
  //#region ../blocks/src/system/runtime/nodes/event-registration/VerifyingPaymentStep.tsx
105990
106306
  var VerifyingPaymentStep;
105991
106307
  var init_VerifyingPaymentStep = __esmMin((() => {
@@ -106272,12 +106588,14 @@ function EventRegistrationWizardContent(props) {
106272
106588
  onBookForSomeoneElse: wizard.handleBookForSomeoneElse
106273
106589
  }), /* @__PURE__ */ jsx(TicketSelectionStep, {
106274
106590
  event: wizard.selectedEvent,
106591
+ checkoutRecovery: wizard.checkoutRecovery,
106592
+ onCheckoutRecovery: canRecoverEventCheckout(wizard.selectedEvent) ? wizard.startCheckoutRecovery : void 0,
106275
106593
  occurrenceContext: wizard.occurrenceContext,
106276
106594
  selectedAttendanceMode: wizard.selectedAttendanceMode,
106277
106595
  onAttendanceModeChange: wizard.setSelectedAttendanceMode,
106278
106596
  ticketsCount: wizard.ticketsCount,
106279
106597
  maxTickets: wizard.maxTicketsNum,
106280
- visibleTicketTypes: wizard.eligibility ? wizard.visibleTicketTypes : void 0,
106598
+ visibleTicketTypes: wizard.visibleTicketTypes,
106281
106599
  ticketSelections: wizard.selectedTicketLines,
106282
106600
  onTicketSelectionsChange: wizard.setSelectedTicketLines,
106283
106601
  slidingScale: wizard.selectedEventSlidingScale,
@@ -106299,6 +106617,7 @@ var init_EventRegistrationWizardContent = __esmMin((() => {
106299
106617
  init_client();
106300
106618
  init_src();
106301
106619
  init_shared();
106620
+ init_checkoutRecovery();
106302
106621
  init_registrationStateMachine();
106303
106622
  init_siteCreditPreview();
106304
106623
  init_PaymentBlockingPanel();
@@ -106446,19 +106765,20 @@ function EventRegistrationSurface(props) {
106446
106765
  }), /* @__PURE__ */ jsx(EventRegistrationTerminalState, {
106447
106766
  wizard,
106448
106767
  supportEmail: props.supportEmail,
106449
- successMessage: props.successMessage
106768
+ successMessage: props.successMessage,
106769
+ buttonClass: props.buttonClass
106450
106770
  })]
106451
106771
  });
106452
106772
  }
106453
106773
  var init_EventRegistrationSurface = __esmMin((() => {
106454
- init_spinner$1();
106455
106774
  init_MagicLinkForm();
106775
+ init_spinner$1();
106776
+ init_ErrorStep();
106456
106777
  init_EventRegistrationSummaryBar();
106457
106778
  init_EventRegistrationWizardActions();
106458
106779
  init_EventRegistrationWizardContent();
106459
- init_StepIndicator();
106460
- init_ErrorStep();
106461
106780
  init_PaymentFailedStep();
106781
+ init_StepIndicator();
106462
106782
  init_SuccessStep();
106463
106783
  init_VerifyingPaymentStep();
106464
106784
  init_VerifyingTimeoutStep();
@@ -106857,6 +107177,88 @@ var init_PastOccurrenceNotice = __esmMin((() => {
106857
107177
  init_utils();
106858
107178
  }));
106859
107179
  //#endregion
107180
+ //#region ../blocks/src/system/runtime/nodes/event-registration/useEventSourceRecovery.ts
107181
+ function useEventSourceRecovery(source, deps = defaultRecoveryDeps) {
107182
+ const api = deps.useApi();
107183
+ const wait = deps.wait;
107184
+ const [cycle, setCycle] = useState(0);
107185
+ const [state, setState] = useState(() => source.kind === "loaded" ? {
107186
+ kind: "ready",
107187
+ events: source.events
107188
+ } : { kind: "loading" });
107189
+ const retry = useCallback(() => {
107190
+ setState({ kind: "loading" });
107191
+ setCycle((value) => value + 1);
107192
+ }, []);
107193
+ useEffect(() => {
107194
+ if (source.kind === "loaded") {
107195
+ setState({
107196
+ kind: "ready",
107197
+ events: source.events
107198
+ });
107199
+ return;
107200
+ }
107201
+ if (!source.request) {
107202
+ setState({
107203
+ kind: "exhausted",
107204
+ retry
107205
+ });
107206
+ return;
107207
+ }
107208
+ const controller = new AbortController();
107209
+ const isCurrent = () => !controller.signal.aborted;
107210
+ (async () => {
107211
+ for (const delayMs of RECOVERY_DELAYS_MS) try {
107212
+ await wait(delayMs, controller.signal);
107213
+ const events = await api.getPublicEvents(source.request ?? void 0);
107214
+ if (isCurrent()) setState({
107215
+ kind: "ready",
107216
+ events
107217
+ });
107218
+ return;
107219
+ } catch {
107220
+ if (!isCurrent()) return;
107221
+ }
107222
+ if (isCurrent()) setState({
107223
+ kind: "exhausted",
107224
+ retry
107225
+ });
107226
+ })();
107227
+ return () => controller.abort();
107228
+ }, [
107229
+ api,
107230
+ cycle,
107231
+ retry,
107232
+ source,
107233
+ wait
107234
+ ]);
107235
+ return state;
107236
+ }
107237
+ function waitForRetry(milliseconds, signal) {
107238
+ if (signal.aborted) return Promise.reject(/* @__PURE__ */ new Error("Recovery aborted"));
107239
+ if (milliseconds === 0) return Promise.resolve();
107240
+ return new Promise((resolve, reject) => {
107241
+ const timeout = setTimeout(resolve, milliseconds);
107242
+ signal.addEventListener("abort", () => {
107243
+ clearTimeout(timeout);
107244
+ reject(/* @__PURE__ */ new Error("Recovery aborted"));
107245
+ }, { once: true });
107246
+ });
107247
+ }
107248
+ var RECOVERY_DELAYS_MS, defaultRecoveryDeps;
107249
+ var init_useEventSourceRecovery = __esmMin((() => {
107250
+ init_api();
107251
+ RECOVERY_DELAYS_MS = [
107252
+ 0,
107253
+ 250,
107254
+ 750
107255
+ ];
107256
+ defaultRecoveryDeps = {
107257
+ useApi: useBlockApi,
107258
+ wait: waitForRetry
107259
+ };
107260
+ }));
107261
+ //#endregion
106860
107262
  //#region ../blocks/src/system/runtime/nodes/event-registration.client.tsx
106861
107263
  function toEventRegistrationClientProps(props, display) {
106862
107264
  return {
@@ -106865,13 +107267,77 @@ function toEventRegistrationClientProps(props, display) {
106865
107267
  className: display.className ?? void 0
106866
107268
  };
106867
107269
  }
107270
+ function RecoverableEventRegistrationClient({ props, display }) {
107271
+ const recovery = useEventSourceRecovery(props.render.hydration.eventSource);
107272
+ if (recovery.kind === "loading") return /* @__PURE__ */ jsxs("div", {
107273
+ id: EVENT_REGISTRATION_ANCHOR_ID,
107274
+ className: "rb-reg-surface er-container er-registration-shell",
107275
+ "aria-busy": "true",
107276
+ role: "status",
107277
+ children: [
107278
+ /* @__PURE__ */ jsx("p", {
107279
+ className: "er-registration-shell__eyebrow",
107280
+ children: "Registration"
107281
+ }),
107282
+ /* @__PURE__ */ jsx("h3", {
107283
+ className: "er-title er-registration-shell__title",
107284
+ children: display.titleText
107285
+ }),
107286
+ /* @__PURE__ */ jsx("p", {
107287
+ className: "er-text er-text--muted",
107288
+ children: "Loading event dates…"
107289
+ }),
107290
+ /* @__PURE__ */ jsxs("div", {
107291
+ className: "er-event-grid er-registration-shell__cards",
107292
+ "aria-hidden": "true",
107293
+ children: [/* @__PURE__ */ jsx("div", { className: "er-event-card er-registration-shell__card" }), /* @__PURE__ */ jsx("div", { className: "er-event-card er-registration-shell__card" })]
107294
+ })
107295
+ ]
107296
+ });
107297
+ if (recovery.kind === "exhausted") return /* @__PURE__ */ jsxs("div", {
107298
+ id: EVENT_REGISTRATION_ANCHOR_ID,
107299
+ className: "rb-reg-surface er-container er-registration-shell",
107300
+ role: "alert",
107301
+ children: [/* @__PURE__ */ jsx("p", { children: "We couldn’t load the event dates. Please try again." }), /* @__PURE__ */ jsx("button", {
107302
+ type: "button",
107303
+ className: themeButtonClassName({
107304
+ variant: props.render.hydration.buttonVariant ?? "primary",
107305
+ size: "md"
107306
+ }),
107307
+ onClick: recovery.retry,
107308
+ children: "Try again"
107309
+ })]
107310
+ });
107311
+ const events = resolveEventRegistrationScopedEvents(recovery.events, {
107312
+ occurrenceContext: props.render.hydration.occurrenceContext,
107313
+ subject: props.render.hydration.subject
107314
+ });
107315
+ const recoveredDisplay = buildEventRegistrationDisplayFromScopedEvents({
107316
+ ...props.render.hydration,
107317
+ events,
107318
+ className: display.className,
107319
+ buttonText: display.summaryButtonText
107320
+ }, events);
107321
+ if (recoveredDisplay.state === "registration-closed") return /* @__PURE__ */ jsx(RegistrationClosedState, {
107322
+ title: recoveredDisplay.titleText,
107323
+ body: recoveredDisplay.bodyText
107324
+ });
107325
+ return /* @__PURE__ */ jsx(EventRegistrationClient, {
107326
+ ...toEventRegistrationClientProps(props, display),
107327
+ events
107328
+ });
107329
+ }
106868
107330
  var EventRegistrationClient, EventRegistrationIslandClient;
106869
107331
  var init_event_registration_client = __esmMin((() => {
106870
107332
  init_EventRegistrationWizard();
106871
107333
  init_registrationSurface();
106872
107334
  init_constants();
106873
107335
  init_PastOccurrenceNotice();
107336
+ init_event_registration_interactive();
106874
107337
  init_RegistrationClosedState();
107338
+ init_useEventSourceRecovery();
107339
+ init_eventScope();
107340
+ init_buttons();
106875
107341
  EventRegistrationClient = (clientProps) => {
106876
107342
  const surface = planEventRegistrationSurface({
106877
107343
  events: clientProps.events ?? [],
@@ -106897,7 +107363,10 @@ var init_event_registration_client = __esmMin((() => {
106897
107363
  title: props.render.display.titleText,
106898
107364
  body: props.render.display.bodyText
106899
107365
  });
106900
- return /* @__PURE__ */ jsx(EventRegistrationClient, { ...toEventRegistrationClientProps(props, props.render.display) });
107366
+ return /* @__PURE__ */ jsx(RecoverableEventRegistrationClient, {
107367
+ props,
107368
+ display: props.render.display
107369
+ });
106901
107370
  };
106902
107371
  }));
106903
107372
  //#endregion
@@ -115623,6 +116092,11 @@ function NewsletterFormClient({ render }) {
115623
116092
  const api = useBlockApi();
115624
116093
  const [submissionState, dispatchSubmission] = useReducer(newsletterFormSubmissionReducer, initialNewsletterFormSubmissionState);
115625
116094
  const [altchaSolution, setAltchaSolution] = useState(null);
116095
+ const successRef = useRef(null);
116096
+ const succeeded = isNewsletterFormSuccess(submissionState);
116097
+ useEffect(() => {
116098
+ if (succeeded) successRef.current?.focus();
116099
+ }, [succeeded]);
115626
116100
  const showSpamProtection = render.hydration.spamProtectionEnabled ?? isSpamProtectionEnabled();
115627
116101
  const fields = render.display.fields;
115628
116102
  const handleSubmit = async (e) => {
@@ -115662,7 +116136,7 @@ function NewsletterFormClient({ render }) {
115662
116136
  if (render.hydration.setupRevision === null || render.display.availability === "unavailable") {
115663
116137
  dispatchSubmission({
115664
116138
  type: "failed",
115665
- error: newsletterFormError("Mailing-list signup is not available right now.")
116139
+ error: newsletterFormError(SIGNUPS_PAUSED_MESSAGE)
115666
116140
  });
115667
116141
  return;
115668
116142
  }
@@ -115670,7 +116144,7 @@ function NewsletterFormClient({ render }) {
115670
116144
  if (visitorSelection === null) {
115671
116145
  dispatchSubmission({
115672
116146
  type: "failed",
115673
- error: newsletterFormError("Choose at least one email topic.")
116147
+ error: newsletterFieldError(TOPIC_CHOICE_FIELD_ID, "Choose at least one email topic.")
115674
116148
  });
115675
116149
  return;
115676
116150
  }
@@ -115702,71 +116176,27 @@ function NewsletterFormClient({ render }) {
115702
116176
  } catch (err) {
115703
116177
  dispatchSubmission({
115704
116178
  type: "failed",
115705
- error: newsletterFormError(err instanceof Error ? err.message : "Subscription failed. Please try again.")
116179
+ error: newsletterFormError(transportFailureMessage(err))
115706
116180
  });
115707
116181
  }
115708
116182
  };
115709
- const renderField = (field) => {
115710
- const inputId = `newsletter_${field.id}`;
115711
- const fieldError = getNewsletterSubmissionFieldError(submissionState, field.id);
115712
- const fieldErrorId = `${inputId}-error`;
115713
- const validationProps = getFieldValidationControlProps({
115714
- message: fieldError,
115715
- messageId: fieldErrorId
115716
- });
115717
- return /* @__PURE__ */ jsxs("div", {
115718
- className: "fb-field newsletter-field",
115719
- children: [
115720
- /* @__PURE__ */ jsxs("label", {
115721
- htmlFor: inputId,
115722
- className: "form-label",
115723
- children: [field.label, field.required && /* @__PURE__ */ jsx("span", {
115724
- className: "newsletter-required",
115725
- "aria-hidden": "true",
115726
- children: "*"
115727
- })]
115728
- }),
115729
- /* @__PURE__ */ jsx("input", {
115730
- id: inputId,
115731
- name: field.id,
115732
- type: field.type,
115733
- required: field.required,
115734
- placeholder: field.placeholder,
115735
- className: "form-input",
115736
- autoComplete: field.type === "email" ? "email" : void 0,
115737
- disabled: isNewsletterFormSubmitting(submissionState),
115738
- ...validationProps
115739
- }),
115740
- fieldError && /* @__PURE__ */ jsx(FieldValidationMessage, {
115741
- id: fieldErrorId,
115742
- className: "fb-error",
115743
- children: fieldError
115744
- })
115745
- ]
115746
- }, field.id);
115747
- };
116183
+ const submitting = isNewsletterFormSubmitting(submissionState);
115748
116184
  const formError = getNewsletterSubmissionFormError(submissionState);
115749
- if (isNewsletterFormSuccess(submissionState)) {
115750
- const outcome = getNewsletterSuccessOutcome(submissionState);
115751
- return /* @__PURE__ */ jsx("div", {
115752
- className: clsx("newsletter-form", "newsletter-success", render.display.className ?? void 0),
115753
- children: /* @__PURE__ */ jsx(FeedbackMessage, {
115754
- tone: "success",
115755
- className: "fb-success",
115756
- role: "status",
115757
- children: outcome === "confirmation_required" ? "Please check your inbox to confirm your signup." : "Thanks — you’re on the list."
115758
- })
115759
- });
115760
- }
116185
+ if (succeeded) return /* @__PURE__ */ jsx("div", {
116186
+ ref: successRef,
116187
+ tabIndex: -1,
116188
+ className: clsx("newsletter-form", "newsletter-success", render.display.className ?? void 0),
116189
+ children: /* @__PURE__ */ jsx(FeedbackMessage, {
116190
+ tone: "success",
116191
+ className: "fb-success",
116192
+ role: "status",
116193
+ children: getNewsletterSuccessOutcome(submissionState) === "confirmation_required" ? "Please check your inbox to confirm your signup." : render.display.successMessage
116194
+ })
116195
+ });
115761
116196
  if (render.display.availability === "unavailable") return /* @__PURE__ */ jsx(UnavailableNewsletterForm, { className: render.display.className });
115762
- return /* @__PURE__ */ jsxs("div", {
116197
+ return /* @__PURE__ */ jsx("div", {
115763
116198
  className: clsx("newsletter-form", render.display.className ?? void 0),
115764
- children: [formError && /* @__PURE__ */ jsx(FeedbackMessage, {
115765
- tone: "error",
115766
- className: "fb-error",
115767
- role: "alert",
115768
- children: formError
115769
- }), /* @__PURE__ */ jsxs("form", {
116199
+ children: /* @__PURE__ */ jsxs("form", {
115770
116200
  onSubmit: handleSubmit,
115771
116201
  className: "fb-form",
115772
116202
  children: [
@@ -115781,18 +116211,15 @@ function NewsletterFormClient({ render }) {
115781
116211
  /* @__PURE__ */ jsxs("div", {
115782
116212
  className: "newsletter-form-fields",
115783
116213
  children: [
115784
- fields.map(renderField),
115785
- render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsxs("fieldset", {
115786
- className: "newsletter-topics",
115787
- children: [/* @__PURE__ */ jsx("legend", { children: "What would you like to hear about?" }), render.display.choices.map((choice) => /* @__PURE__ */ jsxs("label", {
115788
- className: "newsletter-topic-choice",
115789
- children: [/* @__PURE__ */ jsx("input", {
115790
- type: "checkbox",
115791
- name: "mailingListChoice",
115792
- value: choice.id,
115793
- disabled: isNewsletterFormSubmitting(submissionState)
115794
- }), choice.label]
115795
- }, choice.id))]
116214
+ fields.map((field) => /* @__PURE__ */ jsx(NewsletterField, {
116215
+ field,
116216
+ submitting,
116217
+ error: getNewsletterSubmissionFieldError(submissionState, field.id)
116218
+ }, field.id)),
116219
+ render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsx(NewsletterTopicChoices, {
116220
+ choices: render.display.choices,
116221
+ submitting,
116222
+ error: getNewsletterSubmissionFieldError(submissionState, TOPIC_CHOICE_FIELD_ID)
115796
116223
  }) : null,
115797
116224
  showSpamProtection && /* @__PURE__ */ jsx("div", {
115798
116225
  className: "newsletter-altcha",
@@ -115801,6 +116228,12 @@ function NewsletterFormClient({ render }) {
115801
116228
  onSolutionChange: setAltchaSolution
115802
116229
  })
115803
116230
  }),
116231
+ formError && /* @__PURE__ */ jsx(FeedbackMessage, {
116232
+ tone: "error",
116233
+ className: "fb-error",
116234
+ role: "alert",
116235
+ children: formError
116236
+ }),
115804
116237
  /* @__PURE__ */ jsx("div", {
115805
116238
  className: "newsletter-submit",
115806
116239
  children: /* @__PURE__ */ jsx("button", {
@@ -115809,8 +116242,8 @@ function NewsletterFormClient({ render }) {
115809
116242
  variant: render.display.buttonVariant,
115810
116243
  size: "md"
115811
116244
  }),
115812
- disabled: isNewsletterFormSubmitting(submissionState),
115813
- children: isNewsletterFormSubmitting(submissionState) ? "Subscribing..." : render.display.buttonLabel
116245
+ disabled: submitting,
116246
+ children: submitting ? "Subscribing..." : render.display.buttonLabel
115814
116247
  })
115815
116248
  })
115816
116249
  ]
@@ -115820,9 +116253,70 @@ function NewsletterFormClient({ render }) {
115820
116253
  children: render.display.privacyNote
115821
116254
  })
115822
116255
  ]
115823
- })]
116256
+ })
116257
+ });
116258
+ }
116259
+ function NewsletterField({ field, submitting, error }) {
116260
+ const inputId = `newsletter_${field.id}`;
116261
+ const errorId = `${inputId}-error`;
116262
+ return /* @__PURE__ */ jsxs("div", {
116263
+ className: "fb-field newsletter-field",
116264
+ children: [
116265
+ /* @__PURE__ */ jsxs("label", {
116266
+ htmlFor: inputId,
116267
+ className: "form-label",
116268
+ children: [field.label, field.required && /* @__PURE__ */ jsx("span", {
116269
+ className: "newsletter-required",
116270
+ "aria-hidden": "true",
116271
+ children: "*"
116272
+ })]
116273
+ }),
116274
+ /* @__PURE__ */ jsx("input", {
116275
+ id: inputId,
116276
+ name: field.id,
116277
+ type: field.type,
116278
+ required: field.required,
116279
+ placeholder: field.placeholder,
116280
+ className: "form-input",
116281
+ autoComplete: field.type === "email" ? "email" : void 0,
116282
+ disabled: submitting,
116283
+ ...getFieldValidationControlProps({
116284
+ message: error,
116285
+ messageId: errorId
116286
+ })
116287
+ }),
116288
+ error && /* @__PURE__ */ jsx(FieldValidationMessage, {
116289
+ id: errorId,
116290
+ className: "fb-error",
116291
+ children: error
116292
+ })
116293
+ ]
115824
116294
  });
115825
116295
  }
116296
+ function NewsletterTopicChoices({ choices, submitting, error }) {
116297
+ const errorId = `newsletter_${TOPIC_CHOICE_FIELD_ID}-error`;
116298
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("fieldset", {
116299
+ className: "fb-fieldset newsletter-topics",
116300
+ "aria-describedby": error ? errorId : void 0,
116301
+ children: [/* @__PURE__ */ jsx("legend", {
116302
+ className: "form-label",
116303
+ children: "What would you like to hear about?"
116304
+ }), choices.map((choice) => /* @__PURE__ */ jsxs("label", {
116305
+ className: "fb-inline form-label newsletter-topic-choice",
116306
+ children: [/* @__PURE__ */ jsx("input", {
116307
+ type: "checkbox",
116308
+ name: TOPIC_CHOICE_FIELD_ID,
116309
+ value: choice.id,
116310
+ className: "form-checkbox",
116311
+ disabled: submitting
116312
+ }), /* @__PURE__ */ jsx("span", { children: choice.label })]
116313
+ }, choice.id))]
116314
+ }), error && /* @__PURE__ */ jsx(FieldValidationMessage, {
116315
+ id: errorId,
116316
+ className: "fb-error",
116317
+ children: error
116318
+ })] });
116319
+ }
115826
116320
  function UnavailableNewsletterForm({ className }) {
115827
116321
  return /* @__PURE__ */ jsx("div", {
115828
116322
  className: clsx("newsletter-form", className ?? void 0),
@@ -115830,13 +116324,26 @@ function UnavailableNewsletterForm({ className }) {
115830
116324
  tone: "error",
115831
116325
  className: "fb-error",
115832
116326
  role: "status",
115833
- children: "Mailing-list signup is not available right now."
116327
+ children: SIGNUPS_PAUSED_MESSAGE
115834
116328
  })
115835
116329
  });
115836
116330
  }
116331
+ /**
116332
+ * Vetted copy for a request that never produced a signup response. The raw
116333
+ * error text ("Failed to fetch", "received invalid JSON") is for logs, not
116334
+ * visitors.
116335
+ */
116336
+ function transportFailureMessage(err) {
116337
+ if (err instanceof BlockApiError) {
116338
+ if (err.status === 429) return TOO_MANY_ATTEMPTS_MESSAGE;
116339
+ if (err.status === 403) return "We couldn’t verify this submission. Please try again.";
116340
+ if (err.status === 400 || err.status === 422) return "Please check your details and try again.";
116341
+ }
116342
+ return RETRY_SHORTLY_MESSAGE;
116343
+ }
115837
116344
  function readVisitorSelection(formData, hydration) {
115838
116345
  if (hydration.choicePresentation !== "visitor_choice") return void 0;
115839
- const ids = formData.getAll("mailingListChoice").flatMap((value) => typeof value === "string" ? [value] : []);
116346
+ const ids = formData.getAll(TOPIC_CHOICE_FIELD_ID).flatMap((value) => typeof value === "string" ? [value] : []);
115840
116347
  if (ids.length === 0) return null;
115841
116348
  const raw = hydration.choiceProvider === "native" ? {
115842
116349
  provider: "native",
@@ -115858,15 +116365,15 @@ function publicSignupError(outcome) {
115858
116365
  case "unavailable": switch (outcome.reason) {
115859
116366
  case "configuration_unavailable":
115860
116367
  case "authentication_failed":
115861
- case "target_unavailable": return "Mailing-list signup is not available right now.";
116368
+ case "target_unavailable": return SIGNUPS_PAUSED_MESSAGE;
115862
116369
  case "stale_configuration": return "This signup form has changed. Refresh the page, then try again.";
115863
- case "subscriber_suppressed": return "This address cannot be added. Please contact the site if you would like help.";
115864
- case "rate_limited": return "There have been too many signup attempts. Please wait a moment and try again.";
115865
- case "temporarily_unavailable": return "We could not sign you up just now. Please try again shortly.";
116370
+ case "rate_limited": return TOO_MANY_ATTEMPTS_MESSAGE;
116371
+ case "temporarily_unavailable": return RETRY_SHORTLY_MESSAGE;
115866
116372
  }
115867
116373
  case "uncertain": return "We could not confirm whether your signup completed. Please wait a moment, then try again.";
115868
116374
  }
115869
116375
  }
116376
+ var TOPIC_CHOICE_FIELD_ID, SIGNUPS_PAUSED_MESSAGE, RETRY_SHORTLY_MESSAGE, TOO_MANY_ATTEMPTS_MESSAGE;
115870
116377
  var init_newsletter_form_client = __esmMin((() => {
115871
116378
  init_clsx();
115872
116379
  init_client();
@@ -115878,6 +116385,10 @@ var init_newsletter_form_client = __esmMin((() => {
115878
116385
  init_FieldValidationMessage();
115879
116386
  init_newsletter_form_client_state();
115880
116387
  init_newsletter_form_submission();
116388
+ TOPIC_CHOICE_FIELD_ID = "mailingListChoice";
116389
+ SIGNUPS_PAUSED_MESSAGE = "We can’t accept signups right now. Please try again later.";
116390
+ RETRY_SHORTLY_MESSAGE = "We couldn’t confirm your signup. Please try again in a little while.";
116391
+ TOO_MANY_ATTEMPTS_MESSAGE = "There have been too many signup attempts. Please wait a moment and try again.";
115881
116392
  }));
115882
116393
  //#endregion
115883
116394
  //#region ../blocks/src/system/runtime/nodes/weekly-slot-availability.client.state.ts