@riverbankcms/sdk 0.82.0 → 0.84.1

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 (206) hide show
  1. package/README.md +16 -0
  2. package/dist/{PreviewEditorSidebar-LHGK6RIO.mjs → PreviewEditorSidebar-X7RLMEI6.mjs} +330 -11
  3. package/dist/{PreviewEditorUI-AXZG2SDC.mjs → PreviewEditorUI-CT67N4O3.mjs} +3 -3
  4. package/dist/SdkPreviewModeRuntime-EIMQ3S2V.mjs +8 -0
  5. package/dist/_dts/ai/src/contracts/proposals.d.ts +200 -0
  6. package/dist/_dts/api/src/blocks.d.ts +36 -0
  7. package/dist/_dts/api/src/contentRuntime.d.ts +46 -0
  8. package/dist/_dts/api/src/endpoints.d.ts +40 -0
  9. package/dist/_dts/api/src/index.d.ts +2 -2
  10. package/dist/_dts/api/src/sdk-event-pricing.d.ts +61 -0
  11. package/dist/_dts/api/src/sdk-event-schedule.d.ts +52 -0
  12. package/dist/_dts/api/src/sdk-event-upsert.d.ts +50 -0
  13. package/dist/_dts/api/src/sdkContracts.d.ts +67 -33
  14. package/dist/_dts/api/src/shared-contracts.d.ts +13 -0
  15. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +22 -36
  16. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +46 -1
  17. package/dist/_dts/block-form/src/backend/useBackendWatch.d.ts +6 -1
  18. package/dist/_dts/block-form/src/utils/evaluateVisibility.d.ts +3 -2
  19. package/dist/_dts/block-form/src/utils/visibleWhen.d.ts +7 -0
  20. package/dist/_dts/blocks/src/PageRenderer.d.ts +11 -0
  21. package/dist/_dts/blocks/src/bindings/index.d.ts +1 -1
  22. package/dist/_dts/blocks/src/client/site-chrome.d.ts +1 -1
  23. package/dist/_dts/blocks/src/client.d.ts +4 -0
  24. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +16 -4
  25. package/dist/_dts/blocks/src/system/blocks/appointment-booking.d.ts +288 -2016
  26. package/dist/_dts/blocks/src/system/blocks/blog-listing.d.ts +288 -2016
  27. package/dist/_dts/blocks/src/system/blocks/cart.d.ts +288 -2016
  28. package/dist/_dts/blocks/src/system/blocks/checkout.d.ts +288 -2016
  29. package/dist/_dts/blocks/src/system/blocks/collection.d.ts +288 -2016
  30. package/dist/_dts/blocks/src/system/blocks/contact-newsletter.d.ts +171 -0
  31. package/dist/_dts/blocks/src/system/blocks/faq.d.ts +288 -2016
  32. package/dist/_dts/blocks/src/system/blocks/gifting.d.ts +288 -2016
  33. package/dist/_dts/blocks/src/system/blocks/hero.d.ts +3 -2
  34. package/dist/_dts/blocks/src/system/blocks/index.d.ts +1 -0
  35. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +1 -7
  36. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +2534 -151
  37. package/dist/_dts/blocks/src/system/blocks/product-detail.d.ts +288 -2016
  38. package/dist/_dts/blocks/src/system/blocks/product-list.d.ts +288 -2016
  39. package/dist/_dts/blocks/src/system/blocks/shop.d.ts +288 -2016
  40. package/dist/_dts/blocks/src/system/blocks/site-header.d.ts +36 -3
  41. package/dist/_dts/blocks/src/system/blocks/team-members.d.ts +2 -2
  42. package/dist/_dts/blocks/src/system/constants/blockKinds.d.ts +1 -1
  43. package/dist/_dts/blocks/src/system/fields/aspectRatio.d.ts +4 -1
  44. package/dist/_dts/blocks/src/system/fields/imageShape.d.ts +30 -0
  45. package/dist/_dts/blocks/src/system/fragments/library/heroLayoutControls.d.ts +25 -0
  46. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +35 -161
  47. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +24 -6
  48. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +12 -3
  49. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessEventRegistrationFlow.d.ts +33 -0
  50. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationWizard.d.ts +0 -2
  51. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/constants.d.ts +1 -0
  52. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +275 -0
  53. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.override.d.ts +10 -0
  54. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.planning.d.ts +22 -0
  55. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.state.d.ts +3 -0
  56. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +20 -1
  57. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +13 -4
  58. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/utils.d.ts +1 -1
  59. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +28 -6
  60. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/pricing.d.ts +14 -0
  61. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +1 -1
  62. package/dist/_dts/content-editor/src/controller/buildBlockPublishedBaselines.d.ts +1 -1
  63. package/dist/_dts/content-editor/src/controller/seedDraftBaselinesFromBlocks.d.ts +1 -1
  64. package/dist/_dts/content-editor/src/controller/useBlocksList.d.ts +1 -1
  65. package/dist/_dts/content-editor/src/controller/useInvalidBlockRecovery.d.ts +1 -1
  66. package/dist/_dts/content-editor/src/primitives/PreviewRichTextEditor.d.ts +2 -1
  67. package/dist/_dts/content-editor/src/primitives/PreviewTextEditor.d.ts +1 -0
  68. package/dist/_dts/content-model/src/entry-slots/index.d.ts +1 -0
  69. package/dist/_dts/content-model/src/entry-slots/types.d.ts +356 -0
  70. package/dist/_dts/content-model/src/index.d.ts +1 -0
  71. package/dist/_dts/content-model/src/templates/defaults.d.ts +7 -0
  72. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +100 -5
  73. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +6 -1
  74. package/dist/_dts/editor-blocks/src/BlockForm.d.ts +7 -5
  75. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockCreation.d.ts +3 -2
  76. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockDuplication.d.ts +3 -2
  77. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockReorder.d.ts +3 -2
  78. package/dist/_dts/editor-blocks/src/block-editor/owner.d.ts +27 -0
  79. package/dist/_dts/editor-blocks/src/index.d.ts +1 -0
  80. package/dist/_dts/media-core/src/assetsInUseSummary.d.ts +8 -0
  81. package/dist/_dts/media-core/src/mediaUsageProjection.d.ts +37 -3
  82. package/dist/_dts/preview-next/src/client/blocks/pageDesignRuntimePreview.d.ts +4 -2
  83. package/dist/_dts/preview-next/src/client/blocks/previewProjection/runtimeContentDecoration.d.ts +2 -2
  84. package/dist/_dts/preview-next/src/client/preview/EntryEditorPanel.d.ts +3 -1
  85. package/dist/_dts/preview-next/src/client/preview/EntrySlotBlockEditorPanel.d.ts +19 -0
  86. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeButton.d.ts +8 -0
  87. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +4 -1
  88. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +1 -1
  89. package/dist/_dts/preview-next/src/client/preview/linkedEntryEditEvents.d.ts +9 -0
  90. package/dist/_dts/preview-next/src/client/preview/previewCustomizeControls.d.ts +9 -8
  91. package/dist/_dts/preview-next/src/client/preview/siteChromeLookRows.d.ts +10 -1
  92. package/dist/_dts/preview-next/src/client/preview/siteChromeQuickControlHistoryState.d.ts +5 -1
  93. package/dist/_dts/sdk/src/bookings/index.d.ts +5 -4
  94. package/dist/_dts/sdk/src/bookings/types.d.ts +2 -2
  95. package/dist/_dts/sdk/src/cli/content/reader.d.ts +9 -8
  96. package/dist/_dts/sdk/src/cli/content/writer.d.ts +6 -1
  97. package/dist/_dts/sdk/src/cli/helpers.d.ts +10 -5
  98. package/dist/_dts/sdk/src/cli/merge-remote/entryLocal.d.ts +2 -2
  99. package/dist/_dts/sdk/src/cli/merge-remote/entryMerge.d.ts +2 -1
  100. package/dist/_dts/sdk/src/cli/merge-remote/entrySnapshots.d.ts +2 -2
  101. package/dist/_dts/sdk/src/client/management/index.d.ts +1 -1
  102. package/dist/_dts/sdk/src/client/management/types.d.ts +40 -10
  103. package/dist/_dts/sdk/src/config/field-definitions.d.ts +13 -7
  104. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +26 -3
  105. package/dist/_dts/sdk/src/public-api/contracts.d.ts +13 -0
  106. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +1 -0
  107. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +6 -1
  108. package/dist/_dts/sdk/src/rendering/overrides.d.ts +6 -1
  109. package/dist/_dts/sdk/src/types/block-kinds.d.ts +1 -1
  110. package/dist/_dts/sdk/src/version.d.ts +1 -1
  111. package/dist/_dts/site-commands/src/commands.d.ts +15 -0
  112. package/dist/_dts/theme-core/src/accordions/types.d.ts +1 -1
  113. package/dist/_dts/theme-core/src/buttons/personalities/index.d.ts +11 -0
  114. package/dist/_dts/theme-core/src/buttons/personalities/ornate-ritual.d.ts +16 -0
  115. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +1 -1
  116. package/dist/_dts/theme-core/src/buttons/types.d.ts +3 -3
  117. package/dist/_dts/theme-core/src/cards/types.d.ts +15 -15
  118. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  119. package/dist/_dts/theme-core/src/inputs/types.d.ts +1 -1
  120. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +33 -33
  121. package/dist/_dts/theme-core/src/palette/variants/index.d.ts +15 -0
  122. package/dist/_dts/theme-core/src/palette/variants/warm-dark.d.ts +16 -0
  123. package/dist/_dts/theme-core/src/schema.d.ts +30 -25
  124. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  125. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +141 -1
  126. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -0
  127. package/dist/_dts/theme-core/src/site-styles/footerLooks.d.ts +110 -5
  128. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +4 -2
  129. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +1 -1
  130. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +5 -1
  131. package/dist/_dts/theme-core/src/site-styles/tokenRecipes.d.ts +1 -1
  132. package/dist/_dts/theme-core/src/site-styles/types.d.ts +1 -1
  133. package/dist/_dts/theme-core/src/site-styles/typographyPresets.d.ts +16 -1
  134. package/dist/_dts/theme-core/src/siteChromePlanning.d.ts +1 -0
  135. package/dist/_dts/theme-core/src/utils/colorStyles.d.ts +6 -6
  136. package/dist/{chunk-2BUMISSH.mjs → chunk-3LXFQS7T.mjs} +1 -1
  137. package/dist/{chunk-FIREV57T.mjs → chunk-LBBPD2IW.mjs} +40 -0
  138. package/dist/{chunk-XQR6THQJ.mjs → chunk-O62NDCTI.mjs} +3390 -1331
  139. package/dist/{chunk-6FWNF3DJ.mjs → chunk-QRKJDWT7.mjs} +158 -20
  140. package/dist/{chunk-HKB6XVIP.mjs → chunk-RCTJAZSK.mjs} +2 -2
  141. package/dist/{chunk-G35HOQEN.mjs → chunk-X5ZCSU6F.mjs} +132 -46
  142. package/dist/cli/index.mjs +2925 -577
  143. package/dist/cli/init-docs/content/agents-section.md +5 -0
  144. package/dist/cli/init-docs/content/cli-reference.md +13 -0
  145. package/dist/cli/init-docs/content/content-management.md +31 -0
  146. package/dist/cli/init-docs/content/getting-started.md +14 -0
  147. package/dist/cli/init-docs/content/workflow-add-block.md +3 -1
  148. package/dist/cli/init-docs/content/workflow-agent-safe-sync.md +81 -0
  149. package/dist/cli/init-docs/content/workflow-create-page.md +13 -3
  150. package/dist/cli/init-docs/content/workflow-custom-block.md +9 -0
  151. package/dist/cli/init-docs/content/workflow-templates.md +107 -2
  152. package/dist/client/{accordion-G34C45TW.mjs → accordion-2UZPBMYM.mjs} +2 -2
  153. package/dist/client/{bookingForm-BLBVKSAQ.mjs → bookingForm-DYXT6YB6.mjs} +5 -5
  154. package/dist/client/bookings.mjs +3477 -186
  155. package/dist/client/{carousel-7ZVTBRMD.mjs → carousel-QH77HR6X.mjs} +3 -3
  156. package/dist/client/{cart-Q6S6LZUO.mjs → cart-X4YK4FTW.mjs} +6 -6
  157. package/dist/client/{checkout-5QJLDE4I.mjs → checkout-OM2BEPWD.mjs} +6 -6
  158. package/dist/client/{chunk-ZF4XEWDM.mjs → chunk-3DTWLTXM.mjs} +1 -1
  159. package/dist/client/{chunk-5PQH4Y75.mjs → chunk-4OXKTA3D.mjs} +2 -2
  160. package/dist/client/{chunk-WJFHDTYF.mjs → chunk-52CGCQ7B.mjs} +5 -5
  161. package/dist/client/{chunk-CHAB5ACD.mjs → chunk-7UCLJ5SP.mjs} +2 -2
  162. package/dist/client/{chunk-U2EW7RSR.mjs → chunk-F5VRX5Y6.mjs} +1 -1
  163. package/dist/client/{chunk-SBBSMFFG.mjs → chunk-SYIJ5JO2.mjs} +1 -1
  164. package/dist/client/{chunk-EQKYMX4N.mjs → chunk-UHDWIXVR.mjs} +180 -157
  165. package/dist/client/{chunk-RJHTCTCZ.mjs → chunk-VGDBVNOO.mjs} +429 -15
  166. package/dist/client/{chunk-S3MKFGOG.mjs → chunk-ZE5G642V.mjs} +1 -1
  167. package/dist/client/{chunk-CSZGLBYR.mjs → chunk-ZKUO52W3.mjs} +1 -1
  168. package/dist/client/client.mjs +2685 -847
  169. package/dist/client/{courseRegistration-VUG2JJDB.mjs → courseRegistration-YBOGURTA.mjs} +5 -5
  170. package/dist/client/{eventCalendar-E7D2LD4N.mjs → eventCalendar-K4QJVCMD.mjs} +7 -7
  171. package/dist/client/{eventCombined-FUZ2Z3CS.mjs → eventCombined-MTXGMTCZ.mjs} +7 -7
  172. package/dist/client/{eventDetails-QRITJAOW.mjs → eventDetails-3PC4NL3U.mjs} +7 -7
  173. package/dist/client/{eventListing-INMQMJZ5.mjs → eventListing-TFJET6DN.mjs} +7 -7
  174. package/dist/client/{eventRegistration-TOOJD4WU.mjs → eventRegistration-QGPBGJTW.mjs} +7 -7
  175. package/dist/client/{form-BOWN7ZNQ.mjs → form-MDKR4FNB.mjs} +2 -2
  176. package/dist/client/{headerSection-HFQNZOUU.mjs → headerSection-Y5TMR3TW.mjs} +3 -3
  177. package/dist/client/hooks.mjs +2077 -546
  178. package/dist/client/{locationMap-VUZGC7Y5.mjs → locationMap-RH2LG7FZ.mjs} +2 -2
  179. package/dist/client/{newsletterForm-X2XQTPCB.mjs → newsletterForm-ZR5UDGBT.mjs} +2 -2
  180. package/dist/client/{productDetail-TA7D2G2B.mjs → productDetail-OIGDR4YE.mjs} +6 -6
  181. package/dist/client/{productList-AZOLOZKM.mjs → productList-4MA5S2CX.mjs} +6 -6
  182. package/dist/client/rendering/client.mjs +2560 -1205
  183. package/dist/client/rendering/islands.mjs +19 -19
  184. package/dist/client/rendering.mjs +2932 -1021
  185. package/dist/client/{shop-ZDLO7IIG.mjs → shop-WXSYV5QO.mjs} +6 -6
  186. package/dist/preview-next/before-render.mjs +40 -0
  187. package/dist/preview-next/client/runtime.mjs +5 -5
  188. package/dist/preview-next/middleware.mjs +40 -0
  189. package/dist/{sdk-runtime-CTWKNBDQ.mjs → sdk-runtime-7HJYPRWQ.mjs} +6 -6
  190. package/dist/server/components.mjs +2232 -534
  191. package/dist/server/config-validation.mjs +2068 -536
  192. package/dist/server/config.mjs +2068 -536
  193. package/dist/server/data.mjs +2077 -546
  194. package/dist/server/index.mjs +42 -1
  195. package/dist/server/next.mjs +2345 -574
  196. package/dist/server/page-converter.mjs +2684 -1220
  197. package/dist/server/prebuild.mjs +1 -1
  198. package/dist/server/rendering/server.mjs +2244 -546
  199. package/dist/server/rendering.mjs +2323 -552
  200. package/dist/server/routing.mjs +2012 -420
  201. package/dist/server/server.mjs +2153 -549
  202. package/dist/server/theme-bridge.mjs +1180 -101
  203. package/dist/server/theme.mjs +92 -1
  204. package/dist/styles/index.css +292 -36
  205. package/package.json +1 -1
  206. package/dist/SdkPreviewModeRuntime-RNVRHFFR.mjs +0 -8
@@ -86,7 +86,7 @@ function ze() {
86
86
  /* @__PURE__ */ Te(P)
87
87
  );
88
88
  }
89
- function z19(e) {
89
+ function z20(e) {
90
90
  if (L) {
91
91
  if (/* @__PURE__ */ Te(P) !== null)
92
92
  throw Tt(), Je;
@@ -2115,12 +2115,12 @@ function ha(e, t) {
2115
2115
  var mt = we(Dr, 2);
2116
2116
  let Pr;
2117
2117
  var We = X(mt);
2118
- en(We), We.__change = ui, z19(mt);
2118
+ en(We), We.__change = ui, z20(mt);
2119
2119
  var Ut = we(mt, 2), wi = X(Ut);
2120
2120
  {
2121
2121
  var pi = (n) => {
2122
2122
  var u = na(), _ = Gr(u), y = X(_);
2123
- Ge(y, () => c(re).verified), z19(_);
2123
+ Ge(y, () => c(re).verified), z20(_);
2124
2124
  var T = we(_, 2);
2125
2125
  en(T), Pe(() => {
2126
2126
  se(T, "name", V()), jo(T, c(Le));
@@ -2129,10 +2129,10 @@ function ha(e, t) {
2129
2129
  {
2130
2130
  var _ = (T) => {
2131
2131
  var E = ia(), p = X(E);
2132
- Ge(p, () => c(re).verifying), z19(E), ne(T, E);
2132
+ Ge(p, () => c(re).verifying), z20(E), ne(T, E);
2133
2133
  }, y = (T) => {
2134
2134
  var E = oa(), p = X(E);
2135
- Ge(p, () => c(re).label), z19(E), Pe(() => se(E, "for", c(cr))), ne(T, E);
2135
+ Ge(p, () => c(re).label), z20(E), Pe(() => se(E, "for", c(cr))), ne(T, E);
2136
2136
  };
2137
2137
  $e(
2138
2138
  n,
@@ -2147,18 +2147,18 @@ function ha(e, t) {
2147
2147
  c(C) === b.VERIFIED ? n(pi) : n(bi, false);
2148
2148
  });
2149
2149
  }
2150
- z19(Ut);
2150
+ z20(Ut);
2151
2151
  var yi = we(Ut, 2);
2152
2152
  {
2153
2153
  var Ei = (n) => {
2154
2154
  var u = aa(), _ = X(u);
2155
- se(_, "href", sr), z19(u), Pe(() => se(_, "aria-label", c(re).ariaLinkLabel)), ne(n, u);
2155
+ se(_, "href", sr), z20(u), Pe(() => se(_, "aria-label", c(re).ariaLinkLabel)), ne(n, u);
2156
2156
  };
2157
2157
  $e(yi, (n) => {
2158
2158
  (N() !== true || c(Dt)) && n(Ei);
2159
2159
  });
2160
2160
  }
2161
- z19(Mt);
2161
+ z20(Mt);
2162
2162
  var Or = we(Mt, 2);
2163
2163
  {
2164
2164
  var xi = (n) => {
@@ -2166,16 +2166,16 @@ function ha(e, t) {
2166
2166
  {
2167
2167
  var y = (E) => {
2168
2168
  var p = la(), x = X(p);
2169
- Ge(x, () => c(re).expired), z19(p), Pe(() => se(p, "title", c(He))), ne(E, p);
2169
+ Ge(x, () => c(re).expired), z20(p), Pe(() => se(p, "title", c(He))), ne(E, p);
2170
2170
  }, T = (E) => {
2171
2171
  var p = sa(), x = X(p);
2172
- Ge(x, () => c(re).error), z19(p), Pe(() => se(p, "title", c(He))), ne(E, p);
2172
+ Ge(x, () => c(re).error), z20(p), Pe(() => se(p, "title", c(He))), ne(E, p);
2173
2173
  };
2174
2174
  $e(_, (E) => {
2175
2175
  c(C) === b.EXPIRED ? E(y) : E(T, false);
2176
2176
  });
2177
2177
  }
2178
- z19(u), ne(n, u);
2178
+ z20(u), ne(n, u);
2179
2179
  };
2180
2180
  $e(Or, (n) => {
2181
2181
  (c(He) || c(C) === b.EXPIRED) && n(xi);
@@ -2185,7 +2185,7 @@ function ha(e, t) {
2185
2185
  {
2186
2186
  var $i = (n) => {
2187
2187
  var u = ua(), _ = X(u), y = X(_);
2188
- Ge(y, () => c(re).footer), z19(_), z19(u), ne(n, u);
2188
+ Ge(y, () => c(re).footer), z20(_), z20(u), ne(n, u);
2189
2189
  };
2190
2190
  $e(Fr, (n) => {
2191
2191
  c(re).footer && (k() !== true || c(Dt)) && n($i);
@@ -2201,7 +2201,7 @@ function ha(e, t) {
2201
2201
  v() && n(Ci);
2202
2202
  });
2203
2203
  }
2204
- return z19(ot), nn(ot, (n) => D(B, n), () => c(B)), Pe(
2204
+ return z20(ot), nn(ot, (n) => D(B, n), () => c(B)), Pe(
2205
2205
  (n) => {
2206
2206
  se(ot, "data-state", c(C)), se(ot, "data-floating", v()), Pr = Fo(mt, 1, "altcha-checkbox", null, Pr, n), se(We, "id", c(cr)), We.required = r2() !== "onsubmit" && (!v() || r2() !== "off");
2207
2207
  },
@@ -2765,7 +2765,7 @@ var init_altcha = __esm({
2765
2765
  });
2766
2766
 
2767
2767
  // src/bookings/index.ts
2768
- import * as React4 from "react";
2768
+ import * as React5 from "react";
2769
2769
 
2770
2770
  // ../blocks/src/system/runtime/api/deduplication.ts
2771
2771
  function createDeduplicationCache(options = {}) {
@@ -4001,7 +4001,7 @@ function rgbColorValue(token) {
4001
4001
  if (alpha === void 0) {
4002
4002
  return `rgb(var(${cssVar}))`;
4003
4003
  }
4004
- return `rgba(var(${cssVar}), ${alpha})`;
4004
+ return `rgb(var(${cssVar}) / ${alpha})`;
4005
4005
  }
4006
4006
 
4007
4007
  // ../theme-core/src/buttons/types.ts
@@ -4823,6 +4823,95 @@ var joyStamp = defineButtonPersonality({
4823
4823
  }
4824
4824
  });
4825
4825
 
4826
+ // ../theme-core/src/buttons/personalities/ornate-ritual.ts
4827
+ var ornateRitual = defineButtonPersonality({
4828
+ id: "ornate-ritual",
4829
+ name: "Ornate Ritual",
4830
+ description: "Ceremonial framed buttons with jewel-toned fills and quiet color-change hover states.",
4831
+ tags: { tone: "classic", energy: "vibrant", motion: "subtle", era: "organic" },
4832
+ buttonSystem: {
4833
+ global: {
4834
+ cornerStyle: "rounded",
4835
+ shadow: "none",
4836
+ textTransform: "uppercase",
4837
+ fontWeight: 600,
4838
+ borderWidth: 1,
4839
+ hoverTransform: "none",
4840
+ hoverColor: "none",
4841
+ letterSpacing: "loose"
4842
+ },
4843
+ sizes: {
4844
+ sm: { padding: "0.5625rem 1.25rem", fontSize: "text-xs" },
4845
+ md: { padding: "0.75rem 1.75rem", fontSize: "text-xs" },
4846
+ lg: { padding: "0.875rem 2.25rem", fontSize: "text-sm" },
4847
+ xl: { padding: "1rem 2.75rem", fontSize: "text-base" }
4848
+ },
4849
+ variants: [
4850
+ {
4851
+ id: "primary",
4852
+ name: "Primary",
4853
+ enabled: true,
4854
+ priority: 1,
4855
+ background: { type: "solid", colorToken: "primary" },
4856
+ textColorToken: "primaryForeground",
4857
+ borderRadius: "rounded-md",
4858
+ border: { widthClass: "border", colorToken: "primary" },
4859
+ shadow: { elevation: "none", softness: null, position: "bottom" },
4860
+ effects: {
4861
+ hover: [{ effectId: "background-on-hover", options: { colorToken: "primary-100" } }],
4862
+ active: [{ effectId: "scale-down", options: { scale: "0.98" } }]
4863
+ }
4864
+ },
4865
+ {
4866
+ id: "secondary",
4867
+ name: "Secondary",
4868
+ enabled: true,
4869
+ priority: 2,
4870
+ background: { type: "solid", colorToken: "secondary" },
4871
+ textColorToken: "primaryForeground",
4872
+ borderRadius: "rounded-md",
4873
+ border: { widthClass: "border", colorToken: "primary" },
4874
+ shadow: { elevation: "none", softness: null, position: "bottom" },
4875
+ effects: {
4876
+ hover: [{ effectId: "background-on-hover", options: { colorToken: "surface" } }]
4877
+ }
4878
+ },
4879
+ {
4880
+ id: "outline",
4881
+ name: "Outline",
4882
+ enabled: true,
4883
+ priority: 3,
4884
+ background: { type: "transparent" },
4885
+ textColorToken: "primary",
4886
+ borderRadius: "rounded-md",
4887
+ border: { widthClass: "border", colorToken: "primary" },
4888
+ shadow: { elevation: "none", softness: null, position: "bottom" },
4889
+ effects: {
4890
+ hover: [{ effectId: "background-on-hover", options: { colorToken: "muted" } }]
4891
+ }
4892
+ },
4893
+ {
4894
+ id: "ghost",
4895
+ name: "Ghost",
4896
+ enabled: true,
4897
+ priority: 3,
4898
+ background: { type: "transparent" },
4899
+ textColorToken: "accent",
4900
+ borderRadius: "rounded-none",
4901
+ sizes: {
4902
+ sm: { padding: "0.375rem 0", fontSize: "text-xs" },
4903
+ md: { padding: "0.5rem 0", fontSize: "text-sm" },
4904
+ lg: { padding: "0.625rem 0", fontSize: "text-base" },
4905
+ xl: { padding: "0.75rem 0", fontSize: "text-lg" }
4906
+ },
4907
+ effects: {
4908
+ base: [{ effectId: "border-bottom-grow", options: { height: 1, colorToken: "accent", origin: "left" } }]
4909
+ }
4910
+ }
4911
+ ]
4912
+ }
4913
+ });
4914
+
4826
4915
  // ../theme-core/src/buttons/personalities/pebble.ts
4827
4916
  var pebble = defineButtonPersonality({
4828
4917
  id: "pebble",
@@ -5096,12 +5185,21 @@ var buttonPersonalities = [
5096
5185
  inkStamp,
5097
5186
  brushedWash,
5098
5187
  showtimePill,
5099
- joyStamp
5188
+ joyStamp,
5189
+ ornateRitual
5100
5190
  ];
5101
5191
  var personalitiesById = new Map(
5102
5192
  buttonPersonalities.map((p) => [p.id, p])
5103
5193
  );
5104
5194
 
5195
+ // ../core/src/result.ts
5196
+ function ok(value) {
5197
+ return { ok: true, value };
5198
+ }
5199
+ function err(error) {
5200
+ return { ok: false, error };
5201
+ }
5202
+
5105
5203
  // ../core/src/branded.ts
5106
5204
  var unsafeAsSiteId = (id) => id;
5107
5205
  var unsafeAsFormId = (id) => id;
@@ -5127,6 +5225,50 @@ function subtractDaysFromIso(isoString, dayCount) {
5127
5225
  return addDaysToIso(isoString, -dayCount);
5128
5226
  }
5129
5227
 
5228
+ // ../core/src/event-pricing.ts
5229
+ function publicEventPricingType(pricing) {
5230
+ switch (pricing.kind) {
5231
+ case "drop_in":
5232
+ case "free_registration":
5233
+ return "free";
5234
+ case "single_paid":
5235
+ case "ticket_types":
5236
+ case "course":
5237
+ return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
5238
+ }
5239
+ }
5240
+ function publicEventScalarPrice(pricing) {
5241
+ return pricing.kind === "single_paid" ? pricing.amount : null;
5242
+ }
5243
+ function publicEventPricingMode(pricing) {
5244
+ switch (pricing.kind) {
5245
+ case "single_paid":
5246
+ case "free_registration":
5247
+ return "single";
5248
+ case "ticket_types":
5249
+ return "ticket_types";
5250
+ case "drop_in":
5251
+ case "course":
5252
+ return void 0;
5253
+ }
5254
+ }
5255
+ function publicEventTicketTypes(pricing) {
5256
+ return pricing.kind === "ticket_types" ? pricing.ticketTypes : [];
5257
+ }
5258
+ function isFreePublicEventPriceDisplay(display) {
5259
+ switch (display.kind) {
5260
+ case "free":
5261
+ return true;
5262
+ case "course":
5263
+ return display.display.kind === "free";
5264
+ case "exact":
5265
+ case "from":
5266
+ case "mixed":
5267
+ case "unavailable":
5268
+ return false;
5269
+ }
5270
+ }
5271
+
5130
5272
  // ../core/src/booking-flexible-balance.ts
5131
5273
  function clampFlexibleBalanceConfiguredAmount(amountCents, totalAmountCents) {
5132
5274
  return Math.max(0, Math.min(amountCents, totalAmountCents));
@@ -5261,6 +5403,51 @@ function getSafeTimeZone(timeZone) {
5261
5403
  const normalized = typeof timeZone === "string" ? timeZone.trim() : "";
5262
5404
  return normalized && isValidTimeZone(normalized) ? normalized : FALLBACK_TIMEZONE;
5263
5405
  }
5406
+ function parseStrictBookingTimeZone(timeZone) {
5407
+ const normalized = timeZone.trim();
5408
+ if (!normalized || !isValidTimeZone(normalized)) {
5409
+ return null;
5410
+ }
5411
+ return normalized;
5412
+ }
5413
+ function formatParseError(error) {
5414
+ switch (error.reason) {
5415
+ case "invalid_starts_at":
5416
+ return `Expected a valid UTC/offset-aware ISO datetime in startsAt, received "${error.value}"`;
5417
+ case "invalid_ends_at":
5418
+ return `Expected a valid UTC/offset-aware ISO datetime in endsAt, received "${error.value ?? ""}"`;
5419
+ case "invalid_time_zone":
5420
+ return `Expected a valid IANA timezone in timeZone, received "${error.value}"`;
5421
+ }
5422
+ }
5423
+ function formatToPartsLookup(date, locale, timeZone, format) {
5424
+ return new Map(
5425
+ new Intl.DateTimeFormat(locale, {
5426
+ ...format,
5427
+ timeZone
5428
+ }).formatToParts(date).map((part) => [part.type, part.value])
5429
+ );
5430
+ }
5431
+ function getZonedDateTimeParts(date, timeZone) {
5432
+ const parts = formatToPartsLookup(date, "en-GB", timeZone, {
5433
+ year: "numeric",
5434
+ month: "2-digit",
5435
+ day: "2-digit",
5436
+ hour: "2-digit",
5437
+ minute: "2-digit",
5438
+ second: "2-digit",
5439
+ hour12: false
5440
+ });
5441
+ const read = (type) => Number(parts.get(type) ?? "");
5442
+ return {
5443
+ year: read("year"),
5444
+ month: read("month"),
5445
+ day: read("day"),
5446
+ hour: read("hour"),
5447
+ minute: read("minute"),
5448
+ second: read("second")
5449
+ };
5450
+ }
5264
5451
  function formatDateKey(date) {
5265
5452
  const year = String(date.year).padStart(4, "0");
5266
5453
  const month = String(date.month).padStart(2, "0");
@@ -5280,6 +5467,63 @@ function resolveBookingTimeZoneId(...candidates) {
5280
5467
  }
5281
5468
  return FALLBACK_TIMEZONE;
5282
5469
  }
5470
+ function parseUtcIsoDateTimeString(value) {
5471
+ const normalized = value.trim();
5472
+ const hasUtcSuffix = normalized.endsWith("Z");
5473
+ const hasExplicitOffset = /[+-]\d{2}:\d{2}$/u.test(normalized);
5474
+ if (!hasUtcSuffix && !hasExplicitOffset) {
5475
+ return err("missing-timezone-offset");
5476
+ }
5477
+ const date = new Date(normalized);
5478
+ if (Number.isNaN(date.getTime())) {
5479
+ return err("invalid-date-time");
5480
+ }
5481
+ return ok(date.toISOString());
5482
+ }
5483
+ function toUtcIsoDateTimeString(value) {
5484
+ const parsed = parseUtcIsoDateTimeString(value);
5485
+ if (!parsed.ok) {
5486
+ const message = parsed.error === "missing-timezone-offset" ? `Expected an offset-aware ISO datetime, received "${value}"` : `Expected a valid ISO datetime, received "${value}"`;
5487
+ throw new Error(message);
5488
+ }
5489
+ return parsed.value;
5490
+ }
5491
+ function parseScheduledBookingDateTime(input) {
5492
+ try {
5493
+ const startsAt = toUtcIsoDateTimeString(input.startsAt);
5494
+ const timeZone = parseStrictBookingTimeZone(input.timeZone);
5495
+ if (!timeZone) {
5496
+ return {
5497
+ ok: false,
5498
+ field: "timeZone",
5499
+ reason: "invalid_time_zone",
5500
+ value: input.timeZone
5501
+ };
5502
+ }
5503
+ return {
5504
+ ok: true,
5505
+ value: {
5506
+ startsAt,
5507
+ timeZone,
5508
+ locale: input.locale
5509
+ }
5510
+ };
5511
+ } catch {
5512
+ return {
5513
+ ok: false,
5514
+ field: "startsAt",
5515
+ reason: "invalid_starts_at",
5516
+ value: input.startsAt
5517
+ };
5518
+ }
5519
+ }
5520
+ function toScheduledBookingDateTime(input) {
5521
+ const result = parseScheduledBookingDateTime(input);
5522
+ if (result.ok) {
5523
+ return result.value;
5524
+ }
5525
+ throw new Error(formatParseError(result));
5526
+ }
5283
5527
  function formatBookingInstant(isoString, options) {
5284
5528
  const date = new Date(isoString);
5285
5529
  if (Number.isNaN(date.getTime())) {
@@ -5290,6 +5534,9 @@ function formatBookingInstant(isoString, options) {
5290
5534
  timeZone: getSafeTimeZone(options.timeZone)
5291
5535
  }).format(date);
5292
5536
  }
5537
+ function getBookingLocalDateKey(input) {
5538
+ return formatDateKey(getLocalScheduleDate(new Date(input.startsAt), input.timeZone));
5539
+ }
5293
5540
  function parseBookingLocalDate(value) {
5294
5541
  const match = LOCAL_DATE_PATTERN.exec(value.trim());
5295
5542
  if (!match?.groups) {
@@ -5304,6 +5551,10 @@ function parseBookingLocalDate(value) {
5304
5551
  }
5305
5552
  return { year, month, day };
5306
5553
  }
5554
+ function getLocalScheduleDate(date, timeZone) {
5555
+ const parts = getZonedDateTimeParts(date, getSafeTimeZone(timeZone));
5556
+ return { year: parts.year, month: parts.month, day: parts.day };
5557
+ }
5307
5558
  function formatLocalScheduleDate(date) {
5308
5559
  return formatDateKey(date);
5309
5560
  }
@@ -5402,6 +5653,9 @@ var accordionSystemSchema = z5.object({
5402
5653
  function defineExactCatalog() {
5403
5654
  return (entries) => entries;
5404
5655
  }
5656
+ function asDesignBlockId(value) {
5657
+ return brandNonEmptyString(value, "DesignBlockId");
5658
+ }
5405
5659
  function asAppearancePresetId(value) {
5406
5660
  return brandNonEmptyString(value, "AppearancePresetId");
5407
5661
  }
@@ -5450,6 +5704,7 @@ var eventListTreatmentValues = [
5450
5704
  ];
5451
5705
  var eyebrowTreatmentValues = [
5452
5706
  "plain",
5707
+ "accent",
5453
5708
  "pill",
5454
5709
  "accent-pill",
5455
5710
  "pill-bounce",
@@ -6151,6 +6406,126 @@ var logger = {
6151
6406
  withFields: (_) => logger
6152
6407
  };
6153
6408
 
6409
+ // ../blocks/src/system/runtime/nodes/events/shared/pricing.ts
6410
+ var DEFAULT_EVENT_CURRENCY = "USD";
6411
+ function resolveRuntimeEventPricing(event) {
6412
+ if (isPublicEventPricing(event.pricing)) {
6413
+ return event.pricing;
6414
+ }
6415
+ const legacy = event;
6416
+ const currency = readCurrency(legacy.currency);
6417
+ if (event.requiresRegistration === false) {
6418
+ return {
6419
+ kind: "drop_in",
6420
+ currency,
6421
+ display: { kind: "free", currency }
6422
+ };
6423
+ }
6424
+ if (legacy.pricingMode === "ticket_types") {
6425
+ const ticketTypes = Array.isArray(legacy.ticketTypes) ? legacy.ticketTypes.filter(isPublicEventTicketType) : [];
6426
+ return {
6427
+ kind: "ticket_types",
6428
+ currency,
6429
+ ticketTypes,
6430
+ display: readTicketTypePriceDisplay(legacy.priceDisplay, currency)
6431
+ };
6432
+ }
6433
+ const amount = typeof legacy.price === "number" ? legacy.price : 0;
6434
+ if (legacy.pricingType === "paid" && amount > 0) {
6435
+ return {
6436
+ kind: "single_paid",
6437
+ amount,
6438
+ currency,
6439
+ display: { kind: "exact", amount, currency }
6440
+ };
6441
+ }
6442
+ return {
6443
+ kind: "free_registration",
6444
+ currency,
6445
+ display: { kind: "free", currency }
6446
+ };
6447
+ }
6448
+ function readCurrency(value) {
6449
+ return typeof value === "string" && value.trim().length > 0 ? value : DEFAULT_EVENT_CURRENCY;
6450
+ }
6451
+ function isRecord3(value) {
6452
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6453
+ }
6454
+ function isPublicEventPricing(value) {
6455
+ if (!isRecord3(value) || typeof value.kind !== "string") return false;
6456
+ return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "ticket_types" || value.kind === "course";
6457
+ }
6458
+ function isPublicEventTicketType(value) {
6459
+ return isRecord3(value) && typeof value.id === "string";
6460
+ }
6461
+ function readTicketTypePriceDisplay(value, currency) {
6462
+ const display = readLegacyPriceDisplay(value, currency);
6463
+ return display.kind === "course" ? { kind: "unavailable", currency } : display;
6464
+ }
6465
+ function readLegacyPriceDisplay(value, currency) {
6466
+ if (!isRecord3(value) || typeof value.kind !== "string") {
6467
+ return { kind: "unavailable", currency };
6468
+ }
6469
+ const displayCurrency = readCurrency(value.currency);
6470
+ switch (value.kind) {
6471
+ case "free":
6472
+ return { kind: "free", currency: displayCurrency };
6473
+ case "exact":
6474
+ return readAmount(value.amount) !== null ? {
6475
+ kind: "exact",
6476
+ amount: readAmount(value.amount) ?? 0,
6477
+ currency: displayCurrency
6478
+ } : { kind: "unavailable", currency };
6479
+ case "from":
6480
+ return readAmount(value.amount) !== null ? {
6481
+ kind: "from",
6482
+ amount: readAmount(value.amount) ?? 0,
6483
+ currency: displayCurrency
6484
+ } : { kind: "unavailable", currency };
6485
+ case "mixed":
6486
+ return readAmount(value.paidFromAmount) !== null ? {
6487
+ kind: "mixed",
6488
+ paidFromAmount: readAmount(value.paidFromAmount) ?? 0,
6489
+ currency: displayCurrency
6490
+ } : { kind: "unavailable", currency };
6491
+ case "unavailable":
6492
+ return { kind: "unavailable", currency: displayCurrency };
6493
+ case "course":
6494
+ return isRecord3(value.display) ? {
6495
+ kind: "course",
6496
+ display: readCoursePriceDisplay(value.display, displayCurrency)
6497
+ } : {
6498
+ kind: "course",
6499
+ display: { kind: "unavailable", currency: displayCurrency }
6500
+ };
6501
+ default:
6502
+ return { kind: "unavailable", currency };
6503
+ }
6504
+ }
6505
+ function readCoursePriceDisplay(value, currency) {
6506
+ switch (value.kind) {
6507
+ case "free":
6508
+ return { kind: "free", currency: readCurrency(value.currency) };
6509
+ case "exact":
6510
+ return readAmount(value.amount) !== null ? {
6511
+ kind: "exact",
6512
+ amount: readAmount(value.amount) ?? 0,
6513
+ currency: readCurrency(value.currency)
6514
+ } : { kind: "unavailable", currency };
6515
+ case "from":
6516
+ return readAmount(value.amount) !== null ? {
6517
+ kind: "from",
6518
+ amount: readAmount(value.amount) ?? 0,
6519
+ currency: readCurrency(value.currency)
6520
+ } : { kind: "unavailable", currency };
6521
+ default:
6522
+ return { kind: "unavailable", currency };
6523
+ }
6524
+ }
6525
+ function readAmount(value) {
6526
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
6527
+ }
6528
+
6154
6529
  // ../theme-core/src/utils/tokenOrColor.ts
6155
6530
  import { z as z6 } from "zod";
6156
6531
  var tokenOrCssColorValueSchema = z6.string();
@@ -6226,6 +6601,13 @@ var cardSystemSchema = z7.object({
6226
6601
  variants: z7.array(cardVariantSchema).min(1).max(3)
6227
6602
  });
6228
6603
 
6604
+ // ../blocks/src/system/constants/events.ts
6605
+ var EVENT_CONTENT_TYPE_SLUGS = ["event", "events"];
6606
+ function isEventContentType(slug) {
6607
+ if (!slug) return false;
6608
+ return EVENT_CONTENT_TYPE_SLUGS.includes(slug);
6609
+ }
6610
+
6229
6611
  // ../theme-core/src/site-styles/headerCtaVariants.ts
6230
6612
  function hasButtonVariant(theme, variantId) {
6231
6613
  return theme.buttons?.variants.some((variant) => variant.enabled && variant.id === variantId) ?? false;
@@ -7739,6 +8121,28 @@ var warmDarkEmber = definePaletteVariant({
7739
8121
  { name: "border", hex: "#894e31" }
7740
8122
  ]
7741
8123
  });
8124
+ var warmDarkKirtanGold = definePaletteVariant({
8125
+ id: "warm-dark-kirtan-gold",
8126
+ name: "Warm Dark \u2014 Kirtan Gold",
8127
+ description: "Deep plum ground with pale gold primary, rose accent, and soft devotional text.",
8128
+ tags: { tone: "bold", energy: "calm", era: "editorial" },
8129
+ mode: "dark",
8130
+ colors: [
8131
+ { name: "primary", hex: "#ffcdb2" },
8132
+ { name: "secondary", hex: "#b5838d" },
8133
+ { name: "accent", hex: "#e5989b" },
8134
+ { name: "success", hex: "#8fbf8f" },
8135
+ { name: "warning", hex: "#f2b86b" },
8136
+ { name: "destructive", hex: "#d96b6b" },
8137
+ { name: "background", hex: "#403944" },
8138
+ { name: "surface", hex: "#403944" },
8139
+ { name: "surfaceAlt", hex: "#372f3b" },
8140
+ { name: "muted", hex: "#4d4550" },
8141
+ { name: "text", hex: "#e6d2d5" },
8142
+ { name: "primaryForeground", hex: "#403944" },
8143
+ { name: "border", hex: "#8d747a" }
8144
+ ]
8145
+ });
7742
8146
 
7743
8147
  // ../theme-core/src/palette/variants/index.ts
7744
8148
  var paletteVariants = [
@@ -7762,7 +8166,8 @@ var paletteVariants = [
7762
8166
  softNaturalWatercolor,
7763
8167
  softNaturalLilac,
7764
8168
  // Warm-dark family (dark mode)
7765
- warmDarkEmber
8169
+ warmDarkEmber,
8170
+ warmDarkKirtanGold
7766
8171
  ];
7767
8172
  var paletteVariantsById = new Map(
7768
8173
  paletteVariants.map((v) => [v.id, v])
@@ -8970,9 +9375,125 @@ function headerConfigurationKey(configuration) {
8970
9375
  function asFooterLookId(value) {
8971
9376
  return value;
8972
9377
  }
8973
- var guaranteedFallbackFooterLookId = asFooterLookId("footer-muted-grounding");
9378
+ function asFooterLayoutId(value) {
9379
+ return value;
9380
+ }
9381
+ function asFooterStyleId(value) {
9382
+ return value;
9383
+ }
9384
+ var guaranteedFallbackFooterLookId = asFooterLookId("footer-identity-quiet");
9385
+ var footerLayoutCatalog = defineExactCatalog()([
9386
+ {
9387
+ id: asFooterLayoutId("identity"),
9388
+ label: "Identity",
9389
+ description: "Logo, site text, address, and legal copy without relying on footer navigation."
9390
+ },
9391
+ {
9392
+ id: asFooterLayoutId("centered"),
9393
+ label: "Centered",
9394
+ description: "A calm centered stack for identity, short copy, and optional compact navigation.",
9395
+ maxRecommendedNavDensity: "sparse"
9396
+ },
9397
+ {
9398
+ id: asFooterLayoutId("split"),
9399
+ label: "Split",
9400
+ description: "Navigation and brand signoff separated into a wider split footer.",
9401
+ requiresFooterNav: true,
9402
+ maxRecommendedNavDensity: "balanced"
9403
+ },
9404
+ {
9405
+ id: asFooterLayoutId("columns"),
9406
+ label: "Columns",
9407
+ description: "Grouped footer navigation columns with a supporting bottom line.",
9408
+ requiresFooterNav: true,
9409
+ requiresFooterNavGroups: true
9410
+ }
9411
+ ]);
9412
+ var footerStyleCatalog = defineExactCatalog()([
9413
+ {
9414
+ id: asFooterStyleId("quiet"),
9415
+ label: "Quiet",
9416
+ description: "Lightweight, practical footer treatment."
9417
+ },
9418
+ {
9419
+ id: asFooterStyleId("calm"),
9420
+ label: "Calm",
9421
+ description: "Soft centered treatment with restrained dividers."
9422
+ },
9423
+ {
9424
+ id: asFooterStyleId("editorial"),
9425
+ label: "Editorial",
9426
+ description: "Text-forward treatment with fine-line structure."
9427
+ },
9428
+ {
9429
+ id: asFooterStyleId("brand-band"),
9430
+ label: "Brand band",
9431
+ description: "High-contrast brand treatment with a stronger bottom bar."
9432
+ }
9433
+ ]);
9434
+ var footerLayoutsById = new Map(
9435
+ footerLayoutCatalog.map((layout) => [layout.id, layout])
9436
+ );
9437
+ var footerStylesById = new Map(
9438
+ footerStyleCatalog.map((style) => [style.id, style])
9439
+ );
9440
+ function identityQuietFooter(theme) {
9441
+ return {
9442
+ ...theme.footer,
9443
+ variant: "simple",
9444
+ maxWidth: "container",
9445
+ background: {
9446
+ type: "color",
9447
+ color: "surface"
9448
+ },
9449
+ navStyle: "minimal",
9450
+ navWeight: "regular",
9451
+ navColor: "text",
9452
+ navLinkStyle: {
9453
+ typography: "body",
9454
+ fontWeight: "regular",
9455
+ textTransform: "none",
9456
+ italic: false,
9457
+ colorToken: "text",
9458
+ hoverColorToken: "primary",
9459
+ padding: "none",
9460
+ borderRadius: "none"
9461
+ },
9462
+ navLayout: {
9463
+ layout: "inline-wrap",
9464
+ align: "start",
9465
+ gapX: "default",
9466
+ gapY: "tight"
9467
+ },
9468
+ logo: {
9469
+ showLogo: true,
9470
+ showLogoText: true,
9471
+ placement: "left",
9472
+ size: "sm",
9473
+ align: "start"
9474
+ },
9475
+ bottomBar: {
9476
+ enabled: false,
9477
+ fullBleed: false,
9478
+ textAlign: "left",
9479
+ paddingX: "default",
9480
+ paddingY: "compact",
9481
+ borderTop: {
9482
+ width: "none"
9483
+ }
9484
+ }
9485
+ };
9486
+ }
8974
9487
  function mutedGroundingFooter(theme) {
8975
- return theme.footer;
9488
+ return {
9489
+ ...identityQuietFooter(theme),
9490
+ background: theme.footer.background,
9491
+ navStyle: theme.footer.navStyle,
9492
+ navColor: theme.footer.navColor,
9493
+ navWeight: theme.footer.navWeight,
9494
+ navLinkStyle: theme.footer.navLinkStyle,
9495
+ bottomTextLinkStyle: theme.footer.bottomTextLinkStyle
9496
+ };
8976
9497
  }
8977
9498
  function brandTwoBandFooter(theme) {
8978
9499
  return {
@@ -9077,10 +9598,10 @@ function centeredCalmFooter(theme) {
9077
9598
  }
9078
9599
  };
9079
9600
  }
9080
- function editorialColumnsFooter(theme) {
9601
+ function splitEditorialFooter(theme) {
9081
9602
  return {
9082
9603
  ...theme.footer,
9083
- variant: "columns",
9604
+ variant: "split",
9084
9605
  maxWidth: "container",
9085
9606
  background: {
9086
9607
  type: "color",
@@ -9099,17 +9620,23 @@ function editorialColumnsFooter(theme) {
9099
9620
  padding: "none",
9100
9621
  borderRadius: "none"
9101
9622
  },
9623
+ navLayout: {
9624
+ layout: "inline-wrap",
9625
+ align: "start",
9626
+ gapX: "relaxed",
9627
+ gapY: "tight"
9628
+ },
9102
9629
  logo: {
9103
9630
  showLogo: true,
9104
9631
  showLogoText: true,
9105
- placement: "left",
9632
+ placement: "right",
9106
9633
  size: "sm",
9107
- align: "start"
9634
+ align: "end"
9108
9635
  },
9109
9636
  bottomBar: {
9110
9637
  enabled: true,
9111
9638
  fullBleed: false,
9112
- textAlign: "center",
9639
+ textAlign: "left",
9113
9640
  paddingX: "default",
9114
9641
  paddingY: "compact",
9115
9642
  borderTop: {
@@ -9118,26 +9645,89 @@ function editorialColumnsFooter(theme) {
9118
9645
  }
9119
9646
  };
9120
9647
  }
9121
- var footerLookCatalog = defineExactCatalog()([
9122
- {
9123
- id: asFooterLookId("footer-muted-grounding"),
9124
- label: "Muted grounding footer",
9125
- compile: mutedGroundingFooter
9126
- },
9127
- {
9128
- id: asFooterLookId("footer-centered-calm"),
9129
- label: "Centered calm footer",
9130
- compile: centeredCalmFooter
9131
- },
9648
+ function editorialColumnsFooter(theme) {
9649
+ return {
9650
+ ...theme.footer,
9651
+ variant: "columns",
9652
+ maxWidth: "container",
9653
+ background: {
9654
+ type: "color",
9655
+ color: "surface"
9656
+ },
9657
+ navStyle: "minimal",
9658
+ navWeight: "regular",
9659
+ navColor: "text",
9660
+ navLinkStyle: {
9661
+ typography: "body",
9662
+ fontWeight: "regular",
9663
+ textTransform: "none",
9664
+ italic: false,
9665
+ colorToken: "text",
9666
+ hoverColorToken: "primary",
9667
+ padding: "none",
9668
+ borderRadius: "none"
9669
+ },
9670
+ logo: {
9671
+ showLogo: true,
9672
+ showLogoText: true,
9673
+ placement: "left",
9674
+ size: "sm",
9675
+ align: "start"
9676
+ },
9677
+ bottomBar: {
9678
+ enabled: true,
9679
+ fullBleed: false,
9680
+ textAlign: "center",
9681
+ paddingX: "default",
9682
+ paddingY: "compact",
9683
+ borderTop: {
9684
+ width: "thin"
9685
+ }
9686
+ }
9687
+ };
9688
+ }
9689
+ var footerLookCatalog = defineExactCatalog()([
9690
+ {
9691
+ id: asFooterLookId("footer-identity-quiet"),
9692
+ label: "Identity footer",
9693
+ layoutId: asFooterLayoutId("identity"),
9694
+ styleId: asFooterStyleId("quiet"),
9695
+ compile: identityQuietFooter
9696
+ },
9697
+ {
9698
+ id: asFooterLookId("footer-muted-grounding"),
9699
+ label: "Muted grounding footer",
9700
+ layoutId: asFooterLayoutId("identity"),
9701
+ styleId: asFooterStyleId("quiet"),
9702
+ hiddenFromLayoutStyleControls: true,
9703
+ compile: mutedGroundingFooter
9704
+ },
9705
+ {
9706
+ id: asFooterLookId("footer-centered-calm"),
9707
+ label: "Centered calm footer",
9708
+ layoutId: asFooterLayoutId("centered"),
9709
+ styleId: asFooterStyleId("calm"),
9710
+ compile: centeredCalmFooter
9711
+ },
9712
+ {
9713
+ id: asFooterLookId("footer-split-editorial"),
9714
+ label: "Split editorial footer",
9715
+ layoutId: asFooterLayoutId("split"),
9716
+ styleId: asFooterStyleId("editorial"),
9717
+ compile: splitEditorialFooter
9718
+ },
9132
9719
  {
9133
9720
  id: asFooterLookId("footer-editorial-columns"),
9134
9721
  label: "Editorial columns footer",
9722
+ layoutId: asFooterLayoutId("columns"),
9723
+ styleId: asFooterStyleId("editorial"),
9135
9724
  compile: editorialColumnsFooter
9136
9725
  },
9137
9726
  {
9138
9727
  id: asFooterLookId("site-footer-brand-two-band"),
9139
9728
  label: "Two-band brand footer",
9140
- maxRecommendedNavDensity: "balanced",
9729
+ layoutId: asFooterLayoutId("split"),
9730
+ styleId: asFooterStyleId("brand-band"),
9141
9731
  allowedContentPresence: ["default-footer", "default-and-blocks"],
9142
9732
  compile: brandTwoBandFooter
9143
9733
  }
@@ -9340,6 +9930,30 @@ var luxeContrastTypography = {
9340
9930
  },
9341
9931
  scale: "spacious"
9342
9932
  };
9933
+ var kirtanOrnateTypography = {
9934
+ body: {
9935
+ family: "Jost, system-ui, sans-serif",
9936
+ size: "md",
9937
+ weight: "regular",
9938
+ lineHeight: "relaxed",
9939
+ letterSpacing: "normal"
9940
+ },
9941
+ headings: {
9942
+ default: {
9943
+ family: "Marcellus, Georgia, serif",
9944
+ weight: "regular",
9945
+ lineHeight: "normal",
9946
+ letterSpacing: "normal",
9947
+ colorToken: "primary",
9948
+ italic: null,
9949
+ case: null
9950
+ },
9951
+ h1: { size: "2xl", weight: "regular", lineHeight: "normal", letterSpacing: "normal", italic: null },
9952
+ h2: { size: "xl", weight: "regular", lineHeight: "normal", letterSpacing: "normal", italic: null },
9953
+ h3: { size: "md", weight: "regular", lineHeight: "relaxed", letterSpacing: "normal", italic: null }
9954
+ },
9955
+ scale: "spacious"
9956
+ };
9343
9957
  var boldDisplayTypography = {
9344
9958
  body: {
9345
9959
  family: "Manrope, system-ui, sans-serif",
@@ -9374,16 +9988,16 @@ var originalJoyTypography = {
9374
9988
  },
9375
9989
  headings: {
9376
9990
  default: {
9377
- family: "Bricolage Grotesque, system-ui, sans-serif",
9378
- weight: "bold",
9991
+ family: "Lobster, cursive",
9992
+ weight: "regular",
9379
9993
  lineHeight: "normal",
9380
- letterSpacing: "tight",
9994
+ letterSpacing: "normal",
9381
9995
  italic: null,
9382
9996
  case: null
9383
9997
  },
9384
- h1: { size: "2xl", weight: "bold", lineHeight: "normal", letterSpacing: "tight", italic: null },
9385
- h2: { size: "xl", weight: "bold", lineHeight: "normal", letterSpacing: "tight", italic: null },
9386
- h3: { size: "lg", weight: "bold", lineHeight: "normal", letterSpacing: "tight", italic: null }
9998
+ h1: { size: "2xl", weight: "regular", lineHeight: "normal", letterSpacing: "normal", italic: null },
9999
+ h2: { size: "xl", weight: "regular", lineHeight: "normal", letterSpacing: "normal", italic: null },
10000
+ h3: { size: "lg", weight: "regular", lineHeight: "normal", letterSpacing: "normal", italic: null }
9387
10001
  },
9388
10002
  scale: "balanced"
9389
10003
  };
@@ -9448,6 +10062,32 @@ var typographyPresets = [
9448
10062
  slotPolicies: { body: bodyReadablePolicy, heading: displayHeadingPolicy },
9449
10063
  typography: luxeContrastTypography
9450
10064
  }),
10065
+ defineTypographyPreset({
10066
+ id: "typography-preset:kirtan-ornate",
10067
+ name: "Kirtan Ornate",
10068
+ description: "Marcellus devotional headings over a refined Jost body, matching dark ceremonial layouts.",
10069
+ defaultFonts: { body: "Jost, system-ui, sans-serif", heading: "Marcellus, Georgia, serif" },
10070
+ recommendedFonts: {
10071
+ body: ["Jost", "Manrope", "Inter"],
10072
+ heading: ["Marcellus", "Cormorant Garamond", "Playfair Display"]
10073
+ },
10074
+ slotPolicies: { body: bodyReadablePolicy, heading: displayHeadingPolicy },
10075
+ typography: kirtanOrnateTypography,
10076
+ heroTypography: {
10077
+ headlineSize: "6xl",
10078
+ headlineLineHeight: "normal",
10079
+ subheadlineSize: "xl",
10080
+ subheadlineLineHeight: "relaxed",
10081
+ microHeadlineSize: "5xl",
10082
+ microHeadlineLineHeight: "normal",
10083
+ microSubheadlineSize: "lg",
10084
+ microSubheadlineLineHeight: "relaxed",
10085
+ responsive: {
10086
+ tablet: { headlineSize: "5xl" },
10087
+ mobile: { headlineSize: "4xl", subheadlineSize: "lg" }
10088
+ }
10089
+ }
10090
+ }),
9451
10091
  defineTypographyPreset({
9452
10092
  id: "typography-preset:bold-display",
9453
10093
  name: "Bold Display",
@@ -9477,11 +10117,11 @@ var typographyPresets = [
9477
10117
  defineTypographyPreset({
9478
10118
  id: "typography-preset:original-joy",
9479
10119
  name: "Original Joy",
9480
- description: "Bold Bricolage Grotesque display headings over a clean DM Sans body, editorial and warm.",
9481
- defaultFonts: { body: "DM Sans, system-ui, sans-serif", heading: "Bricolage Grotesque, system-ui, sans-serif" },
10120
+ description: "Lobster display headings over a clean DM Sans body, expressive and warm.",
10121
+ defaultFonts: { body: "DM Sans, system-ui, sans-serif", heading: "Lobster, cursive" },
9482
10122
  recommendedFonts: {
9483
10123
  body: ["DM Sans", "Inter", "Manrope"],
9484
- heading: ["Bricolage Grotesque", "Space Grotesk", "Archivo"]
10124
+ heading: ["Lobster", "Bricolage Grotesque", "Space Grotesk"]
9485
10125
  },
9486
10126
  slotPolicies: { body: bodyReadablePolicy, heading: displayHeadingPolicy },
9487
10127
  typography: originalJoyTypography,
@@ -9505,6 +10145,319 @@ var typographyPresetsById = new Map(
9505
10145
  typographyPresets.map((preset) => [preset.id, preset])
9506
10146
  );
9507
10147
 
10148
+ // ../theme-core/src/site-styles/designState.ts
10149
+ import { z as z19 } from "zod";
10150
+ var themeV2DesignStateSchemaVersion = 1;
10151
+ var designResolutionPolicySchema = z19.enum(["generated", "user", "admin", "sdk"]);
10152
+ var runtimeStyleFieldNameSchema = z19.enum(themeV2RuntimeStyleFieldNames);
10153
+ var nonEmptyRuntimeStyleFieldNamesSchema = z19.array(runtimeStyleFieldNameSchema).min(1).transform((fields) => [
10154
+ fields[0],
10155
+ ...fields.slice(1)
10156
+ ]);
10157
+ var heroLegibilityStrategySchema = z19.enum([
10158
+ "none",
10159
+ "scrim-gradient",
10160
+ "solid-panel"
10161
+ ]);
10162
+ var heroCompositionIntentSchema = z19.enum([
10163
+ "center",
10164
+ "bottom-left"
10165
+ ]);
10166
+ var heroTypographyScaleIntentSchema = z19.enum([
10167
+ "quiet",
10168
+ "editorial",
10169
+ "display",
10170
+ "poster"
10171
+ ]);
10172
+ var sectionHeightIntentSchema = z19.enum([
10173
+ "default",
10174
+ "banner",
10175
+ "hero",
10176
+ "immersive"
10177
+ ]);
10178
+ var imageSurfaceTreatmentIntensitySchema = z19.enum(["soft", "balanced", "strong"]);
10179
+ var imageSurfaceMotionSchema = z19.enum(["static", "fixed-frame"]);
10180
+ var imageSurfaceTreatmentSchema = z19.discriminatedUnion("kind", [
10181
+ z19.object({ kind: z19.literal("none") }).strict(),
10182
+ z19.object({
10183
+ kind: z19.literal("brand-scrim"),
10184
+ token: z19.enum(["primary", "secondary", "accent"]),
10185
+ intensity: imageSurfaceTreatmentIntensitySchema.optional()
10186
+ }).strict(),
10187
+ z19.object({
10188
+ kind: z19.literal("brand-wash"),
10189
+ token: z19.enum(["primary", "secondary", "accent"]),
10190
+ intensity: imageSurfaceTreatmentIntensitySchema.optional()
10191
+ }).strict(),
10192
+ z19.object({
10193
+ kind: z19.literal("neutral-scrim"),
10194
+ intensity: imageSurfaceTreatmentIntensitySchema.optional()
10195
+ }).strict(),
10196
+ z19.object({
10197
+ kind: z19.literal("neutral-wash"),
10198
+ intensity: imageSurfaceTreatmentIntensitySchema.optional()
10199
+ }).strict(),
10200
+ z19.object({
10201
+ kind: z19.literal("solid-panel"),
10202
+ intensity: imageSurfaceTreatmentIntensitySchema.optional()
10203
+ }).strict()
10204
+ ]);
10205
+ var testimonialCardTreatmentSchema = z19.enum(["default", "accent-quote"]);
10206
+ var tileTreatmentSchema = z19.enum(tileTreatmentValues);
10207
+ var eventListTreatmentSchema = z19.enum(eventListTreatmentValues);
10208
+ var eyebrowTreatmentSchema = z19.enum(eyebrowTreatmentValues);
10209
+ function uniqueNonEmpty(values) {
10210
+ const uniqueValues = [...new Set(values)];
10211
+ const firstValue = uniqueValues[0];
10212
+ if (!firstValue) {
10213
+ throw new Error("Expected at least one Theme V2 design state option.");
10214
+ }
10215
+ return [firstValue, ...uniqueValues.slice(1)];
10216
+ }
10217
+ var userPanelTreatments = uniqueNonEmpty(
10218
+ userDesignOptionCatalog.contentFrames.filter((frame) => frame.kind === "panel").map((frame) => frame.treatment)
10219
+ );
10220
+ var userFlushTreatments = uniqueNonEmpty(
10221
+ userDesignOptionCatalog.contentFrames.filter((frame) => frame.kind === "flush-panel").map((frame) => frame.treatment)
10222
+ );
10223
+ var userFlushBleeds = uniqueNonEmpty(
10224
+ userDesignOptionCatalog.contentFrames.filter((frame) => frame.kind === "flush-panel").map((frame) => frame.bleed)
10225
+ );
10226
+ var contentFrameIntentSchema = z19.discriminatedUnion("kind", [
10227
+ z19.object({ kind: z19.literal("plain") }).strict(),
10228
+ z19.object({
10229
+ kind: z19.literal("panel"),
10230
+ treatment: z19.enum(userPanelTreatments)
10231
+ }).strict(),
10232
+ z19.object({
10233
+ kind: z19.literal("flush-panel"),
10234
+ treatment: z19.enum(userFlushTreatments),
10235
+ bleed: z19.enum(userFlushBleeds)
10236
+ }).strict()
10237
+ ]);
10238
+ var blockDesignPlanSchema = z19.object({
10239
+ blockId: z19.string().min(1).transform(asDesignBlockId),
10240
+ blockKind: z19.string().min(1),
10241
+ purpose: z19.string().min(1),
10242
+ sectionSurface: z19.enum(userDesignOptionCatalog.sectionSurfaces),
10243
+ contentFrame: contentFrameIntentSchema,
10244
+ itemSurface: z19.enum(userDesignOptionCatalog.itemSurfaces),
10245
+ transitionAfter: z19.enum(userDesignOptionCatalog.transitions),
10246
+ emphasis: z19.enum(userDesignOptionCatalog.emphases),
10247
+ sectionHeight: sectionHeightIntentSchema.optional(),
10248
+ heroLegibility: heroLegibilityStrategySchema.optional(),
10249
+ heroComposition: heroCompositionIntentSchema.optional(),
10250
+ heroTypographyScale: heroTypographyScaleIntentSchema.optional(),
10251
+ imageSurfaceTreatment: imageSurfaceTreatmentSchema.optional(),
10252
+ imageSurfaceMotion: imageSurfaceMotionSchema.optional(),
10253
+ testimonialCardTreatment: testimonialCardTreatmentSchema.optional(),
10254
+ tileTreatment: tileTreatmentSchema.optional(),
10255
+ eventListTreatment: eventListTreatmentSchema.optional(),
10256
+ eyebrowTreatment: eyebrowTreatmentSchema.optional()
10257
+ }).strict();
10258
+ var styleAuthoritySchema = z19.discriminatedUnion("kind", [
10259
+ z19.object({
10260
+ kind: z19.literal("theme-v2"),
10261
+ source: designResolutionPolicySchema,
10262
+ siteStyleId: z19.string().min(1).transform(asSiteStyleId),
10263
+ templateId: z19.string().min(1).transform(asDesignSystemTemplateId),
10264
+ templateVersion: z19.number().int().nonnegative(),
10265
+ resolverVersion: z19.number().int().nonnegative()
10266
+ }).strict(),
10267
+ z19.object({
10268
+ kind: z19.literal("legacy-raw"),
10269
+ reason: z19.enum(["pre-theme-v2", "manual-runtime-fields"])
10270
+ }).strict(),
10271
+ z19.object({
10272
+ kind: z19.literal("advanced-detached"),
10273
+ reason: z19.literal("detached-custom-runtime-fields")
10274
+ }).strict()
10275
+ ]);
10276
+ var blockRuntimeStyleAuthoritySchema = z19.object({
10277
+ unit: z19.literal("block-runtime-fields"),
10278
+ blockId: z19.string().min(1).transform(asDesignBlockId),
10279
+ fields: nonEmptyRuntimeStyleFieldNamesSchema,
10280
+ authority: styleAuthoritySchema
10281
+ }).strict();
10282
+ var persistedPageDesignStateV1Schema = z19.object({
10283
+ schemaVersion: z19.literal(themeV2DesignStateSchemaVersion),
10284
+ siteStyleId: z19.string().min(1).transform(asSiteStyleId),
10285
+ templateId: z19.string().min(1).transform(asDesignSystemTemplateId),
10286
+ templateVersion: z19.number().int().nonnegative(),
10287
+ resolverVersion: z19.number().int().nonnegative(),
10288
+ rhythmPresetId: z19.string().min(1),
10289
+ blocks: z19.array(blockDesignPlanSchema),
10290
+ styleAuthorities: z19.array(blockRuntimeStyleAuthoritySchema)
10291
+ }).strict();
10292
+
10293
+ // ../theme-core/src/site-styles/runtimeCompiler.ts
10294
+ function defineDesignRuntimeRules(rules) {
10295
+ return rules;
10296
+ }
10297
+ function defineComponentRuntimeRules(rules) {
10298
+ return rules;
10299
+ }
10300
+ var defaultDesignRuntimeRules = defineDesignRuntimeRules({
10301
+ sectionSurfaces: {
10302
+ base: {},
10303
+ "muted-band": {
10304
+ background: {
10305
+ type: "color",
10306
+ color: "muted"
10307
+ }
10308
+ },
10309
+ "accent-band": {
10310
+ background: {
10311
+ type: "color",
10312
+ color: "primary"
10313
+ }
10314
+ },
10315
+ "brand-depth-band": {
10316
+ background: {
10317
+ type: "color",
10318
+ color: "primary-800"
10319
+ }
10320
+ },
10321
+ "hero-image": {
10322
+ background: {
10323
+ type: "image",
10324
+ opacity: 1,
10325
+ position: "center center",
10326
+ ...uniformSectionForeground("text")
10327
+ }
10328
+ }
10329
+ },
10330
+ heroLegibility: {
10331
+ "scrim-gradient": {
10332
+ type: "gradient",
10333
+ gradient: "linear-gradient(180deg, rgba(255,255,255,0.38) 0%, rgba(244,241,234,0.62) 90%)",
10334
+ opacity: 1
10335
+ },
10336
+ "solid-panel": {
10337
+ type: "color",
10338
+ color: "surface",
10339
+ opacity: 0.88
10340
+ }
10341
+ },
10342
+ transitionClassName: (transition, fromSurface, toSurface) => transition === "none" ? null : `site-style-transition-${transition}-from-${fromSurface}-to-${toSurface}`
10343
+ });
10344
+ var defaultComponentRuntimeRules = defineComponentRuntimeRules({
10345
+ panelFrames: {
10346
+ inset: {
10347
+ spacing: "comfortable",
10348
+ rounded: "xl",
10349
+ raised: false,
10350
+ background: {
10351
+ type: "color",
10352
+ color: "surfaceAlt",
10353
+ textColor: "text"
10354
+ }
10355
+ },
10356
+ raised: {
10357
+ spacing: "comfortable",
10358
+ rounded: "xl",
10359
+ raised: true,
10360
+ background: {
10361
+ type: "color",
10362
+ color: "surfaceAlt",
10363
+ textColor: "text"
10364
+ }
10365
+ },
10366
+ editorial: {
10367
+ spacing: "medium",
10368
+ rounded: "xl",
10369
+ raised: false,
10370
+ background: {
10371
+ type: "color",
10372
+ color: "surface",
10373
+ textColor: "text"
10374
+ }
10375
+ }
10376
+ },
10377
+ flushFrames: {
10378
+ "media-panel": {
10379
+ fullWidth: true,
10380
+ spacing: "none",
10381
+ rounded: "none",
10382
+ raised: false
10383
+ }
10384
+ },
10385
+ itemSurfaces: {
10386
+ none: null,
10387
+ default: {
10388
+ spacing: "medium",
10389
+ rounded: "lg",
10390
+ raised: false
10391
+ },
10392
+ flat: {
10393
+ spacing: "medium",
10394
+ rounded: "lg",
10395
+ raised: false
10396
+ },
10397
+ outlined: {
10398
+ spacing: "medium",
10399
+ rounded: "lg",
10400
+ raised: false,
10401
+ border: {
10402
+ enabled: true,
10403
+ width: "1",
10404
+ colorToken: "border"
10405
+ }
10406
+ },
10407
+ raised: {
10408
+ spacing: "medium",
10409
+ rounded: "xl",
10410
+ raised: true
10411
+ },
10412
+ inset: {
10413
+ treatment: "soft-panel",
10414
+ spacing: "comfortable",
10415
+ rounded: "xl",
10416
+ raised: false,
10417
+ border: {
10418
+ enabled: false
10419
+ },
10420
+ background: {
10421
+ type: "color",
10422
+ color: "surfaceAlt",
10423
+ textColor: "text"
10424
+ }
10425
+ },
10426
+ editorial: {
10427
+ // Boxless open column with a short rule on top; the visual treatment
10428
+ // lives in blocks-static/card-treatments.css.
10429
+ treatment: "editorial-rule",
10430
+ spacing: "none",
10431
+ rounded: "none",
10432
+ raised: false,
10433
+ border: {
10434
+ enabled: false
10435
+ }
10436
+ },
10437
+ "color-blocked": {
10438
+ // Bold, flat colour-blocked cards. The per-card background colour cycle
10439
+ // (by position) and staggered offset live in
10440
+ // blocks-static/card-treatments.css; here we set the shared shape:
10441
+ // generous padding, large radius, no border, flat (no shadow).
10442
+ treatment: "color-blocked",
10443
+ spacing: "spacious",
10444
+ rounded: "2xl",
10445
+ raised: false,
10446
+ border: {
10447
+ enabled: false
10448
+ }
10449
+ }
10450
+ }
10451
+ });
10452
+ function uniformSectionForeground(token) {
10453
+ return {
10454
+ textColor: token,
10455
+ headingColor: token,
10456
+ linkColor: token,
10457
+ supportingColor: token
10458
+ };
10459
+ }
10460
+
9508
10461
  // ../theme-core/src/site-styles/curatedSiteStyles.ts
9509
10462
  var SOFT_EARTH_SITE_STYLE_ID_VALUE = "site-style:soft-earth";
9510
10463
  var SOFT_EARTH_SITE_STYLE_ID = asSiteStyleId(SOFT_EARTH_SITE_STYLE_ID_VALUE);
@@ -9532,6 +10485,50 @@ var expressiveBudget = {
9532
10485
  mediaDensity: "high",
9533
10486
  decorativeRepetition: "medium"
9534
10487
  };
10488
+ var kirtanOrnateDesignRuntimeRules = defineDesignRuntimeRules({
10489
+ ...defaultDesignRuntimeRules,
10490
+ defaultEyebrowTreatment: "accent",
10491
+ sectionSurfaces: {
10492
+ ...defaultDesignRuntimeRules.sectionSurfaces,
10493
+ "muted-band": {
10494
+ background: {
10495
+ type: "color",
10496
+ color: "muted"
10497
+ },
10498
+ foreground: {
10499
+ textColor: "text",
10500
+ headingColor: "primary",
10501
+ linkColor: "primary",
10502
+ supportingColor: "text"
10503
+ }
10504
+ },
10505
+ "brand-depth-band": {
10506
+ background: {
10507
+ type: "color",
10508
+ color: "primary-800"
10509
+ },
10510
+ foreground: {
10511
+ textColor: "text",
10512
+ headingColor: "primary",
10513
+ linkColor: "primary",
10514
+ supportingColor: "text"
10515
+ }
10516
+ },
10517
+ "hero-image": {
10518
+ background: {
10519
+ type: "image",
10520
+ opacity: 1,
10521
+ position: "center center"
10522
+ },
10523
+ foreground: {
10524
+ textColor: "text",
10525
+ headingColor: "primary",
10526
+ linkColor: "primary",
10527
+ supportingColor: "text"
10528
+ }
10529
+ }
10530
+ }
10531
+ });
9535
10532
  var expressiveUnderlineInputs = {
9536
10533
  base: {
9537
10534
  background: { type: "transparent" },
@@ -9569,6 +10566,43 @@ var expressiveUnderlineInputs = {
9569
10566
  opacity: 0.6
9570
10567
  }
9571
10568
  };
10569
+ var ornateDarkInputs = {
10570
+ base: {
10571
+ background: { type: "solid", colorToken: "surfaceAlt" },
10572
+ textColorToken: "text",
10573
+ border: {
10574
+ widthClass: "border",
10575
+ colorToken: "primary/45",
10576
+ style: "all"
10577
+ },
10578
+ corners: "square",
10579
+ shadow: null,
10580
+ spacing: "medium",
10581
+ fontSize: "base"
10582
+ },
10583
+ label: {
10584
+ textColorToken: "primary",
10585
+ fontWeight: "semibold",
10586
+ fontSize: "xs",
10587
+ textTransform: "uppercase",
10588
+ letterSpacing: "wider",
10589
+ opacity: 1
10590
+ },
10591
+ focus: {
10592
+ ringColorToken: "primary/18",
10593
+ ringWidth: "2",
10594
+ borderColorToken: "primary/70"
10595
+ },
10596
+ error: {
10597
+ borderColorToken: "destructive",
10598
+ textColorToken: "destructive"
10599
+ },
10600
+ disabled: {
10601
+ backgroundColorToken: "muted",
10602
+ textColorToken: "mutedText",
10603
+ opacity: 0.6
10604
+ }
10605
+ };
9572
10606
  function uniqueContentFrameKinds() {
9573
10607
  const kinds = [
9574
10608
  ...new Set(
@@ -9626,6 +10660,7 @@ function defineCuratedSiteStyle(input) {
9626
10660
  // clean/minimal styles default to none.
9627
10661
  headingDecoration: input.headingDecoration ?? noHeadingDecoration,
9628
10662
  ...input.themeOverrides ? { themeOverrides: input.themeOverrides } : {},
10663
+ ...input.designRuntimeRules ? { designRuntimeRules: input.designRuntimeRules } : {},
9629
10664
  ...input.defaultBlockVariants ? { defaultBlockVariants: input.defaultBlockVariants } : {},
9630
10665
  recommendedAppearancePresetIds: (input.recommendedAppearancePresetIds ?? []).map(asAppearancePresetId),
9631
10666
  defaultHeaderSelection: input.defaultHeaderSelection ? {
@@ -10577,48 +11612,54 @@ var curatedSiteStyles = [
10577
11612
  ]
10578
11613
  }),
10579
11614
  defineCuratedSiteStyle({
10580
- id: "site-style:original-joy",
10581
- name: "Original Joy",
10582
- headingDecoration: { family: "organic-squiggle", colorToken: "primary" },
10583
- description: "Warm, dark, and editorial: deep clay grounds, cream type, and bold burnt-orange accents for soulful community brands.",
10584
- generationBrief: "Use a deep brown ground with cream text and burnt-orange accents, large display headings, generous spacing, organic rounded shapes, and bold colour-blocked feature sections. Lead with warmth and belonging; calls to action should feel strong but unhurried.",
11615
+ id: "site-style:kirtan-ornate",
11616
+ name: "Kirtan Ornate",
11617
+ headingDecoration: { family: "short-center-rule", colorToken: "accent" },
11618
+ description: "Ceremonial, jewel-toned, and devotional: ornate frames, warm contrast, and composed rhythm for intimate music gatherings.",
11619
+ generationBrief: "Use a deep plum ground with pale gold as the main brand color, rose accent details, cream text, spacious split hero sections, devotional editorial headings, compact event lists, and framed conversion sections. The mood should feel soulful and ceremonial, not gothic or theatrical.",
11620
+ selectionKeywordRules: [
11621
+ { kind: "word", value: "kirtan" },
11622
+ { kind: "word", value: "chanting" },
11623
+ { kind: "word", value: "ceremony" },
11624
+ { kind: "word", value: "devotional" }
11625
+ ],
10585
11626
  tokenRecipes: {
10586
11627
  palette: "brand-led",
10587
- contrast: "maximum",
10588
- radius: "rounded",
11628
+ contrast: "strong",
11629
+ radius: "soft",
10589
11630
  shadow: "subtle",
10590
- typography: "clean-sans",
11631
+ typography: "serif-editorial",
10591
11632
  spacing: "airy",
10592
- motion: "expressive"
11633
+ motion: "subtle"
10593
11634
  },
10594
11635
  compositionBudget: expressiveBudget,
10595
11636
  typographyPresetChoices: [
10596
- typographyChoice("typography-preset:original-joy"),
10597
- typographyChoice("typography-preset:bold-display"),
10598
- typographyChoice("typography-preset:modern-sans")
11637
+ typographyChoice("typography-preset:kirtan-ornate"),
11638
+ typographyChoice("typography-preset:luxe-contrast"),
11639
+ typographyChoice("typography-preset:editorial-serif")
10599
11640
  ],
10600
- defaultTypographyPresetId: "typography-preset:original-joy",
11641
+ defaultTypographyPresetId: "typography-preset:kirtan-ornate",
10601
11642
  themeOverrides: {
10602
- accordions: boldBorderedAccordionSystem,
10603
- // Shared card system: warm rounded brown cards (event + testimonial cards
10604
- // pick this up automatically) with a burnt-orange statement variant.
11643
+ accordions: warmInsetAccordionSystem,
10605
11644
  cards: originalJoyCardSystem,
10606
- testimonialQuote: accentGlyphQuote,
11645
+ testimonialQuote: serifDisplayQuote,
10607
11646
  bodyText: {
10608
11647
  intro: {
10609
11648
  paragraphSize: "editorial",
10610
11649
  headingSize: "editorial"
10611
11650
  }
10612
- }
11651
+ },
11652
+ inputs: ornateDarkInputs
10613
11653
  },
10614
- // Recommended block looks: the bold colour-blocked feature cards, a calm
10615
- // band for the events spotlight, and statement testimonial cards.
11654
+ designRuntimeRules: kirtanOrnateDesignRuntimeRules,
10616
11655
  recommendedAppearancePresetIds: [
10617
- "feature-cards-bold-colors",
10618
- "offerings-calm-list",
10619
- "testimonials-statement-cards"
11656
+ "hero-brand-scrim-fixed-frame",
11657
+ "media-text-quiet-story",
11658
+ "events-lined-panel",
11659
+ "schedule-details-brand-depth",
11660
+ "testimonials-statement-cards",
11661
+ "contact-form-panel"
10620
11662
  ],
10621
- // Floating, transparent "Clear Split" header (no fill behind the nav links).
10622
11663
  defaultHeaderSelection: { layoutId: "floating", styleId: "minimal-surface" },
10623
11664
  recommendedHeaderLayoutChoices: [headerLayoutChoice("floating")],
10624
11665
  recommendedHeaderStyleChoicesByLayout: {
@@ -10628,19 +11669,87 @@ var curatedSiteStyles = [
10628
11669
  headerStyleChoice("glass")
10629
11670
  ]
10630
11671
  },
10631
- // Legacy bridge only (the real curation is the explicit selection above).
10632
- // Kept to a reserved-space, non-overlay look on purpose: the split hero
10633
- // flows below the Clear Split header, so we must NOT trigger the immersive
10634
- // overlay-hero promotion that looks like `floating-glass` would force.
10635
11672
  recommendedHeaderLookIds: ["minimal-transparent"],
10636
11673
  recommendedFooterLookIds: [
10637
11674
  "site-footer-brand-two-band",
10638
11675
  "footer-muted-grounding"
10639
11676
  ],
10640
11677
  buttonPersonalityChoices: [
11678
+ buttonChoice("ornate-ritual"),
10641
11679
  buttonChoice("joy-stamp"),
10642
- buttonChoice("ink-stamp"),
10643
- buttonChoice("showtime-pill")
11680
+ buttonChoice("ink-stamp")
11681
+ ],
11682
+ paletteVariantChoices: [
11683
+ paletteChoice("warm-dark-kirtan-gold"),
11684
+ paletteChoice("warm-dark-ember"),
11685
+ paletteChoice("brand-led-burgundy-gold")
11686
+ ]
11687
+ }),
11688
+ defineCuratedSiteStyle({
11689
+ id: "site-style:original-joy",
11690
+ name: "Original Joy",
11691
+ headingDecoration: { family: "organic-squiggle", colorToken: "primary" },
11692
+ description: "Warm, dark, and editorial: deep clay grounds, cream type, and bold burnt-orange accents for soulful community brands.",
11693
+ generationBrief: "Use a deep brown ground with cream text and burnt-orange accents, large display headings, generous spacing, organic rounded shapes, and bold colour-blocked feature sections. Lead with warmth and belonging; calls to action should feel strong but unhurried.",
11694
+ tokenRecipes: {
11695
+ palette: "brand-led",
11696
+ contrast: "maximum",
11697
+ radius: "rounded",
11698
+ shadow: "subtle",
11699
+ typography: "clean-sans",
11700
+ spacing: "airy",
11701
+ motion: "expressive"
11702
+ },
11703
+ compositionBudget: expressiveBudget,
11704
+ typographyPresetChoices: [
11705
+ typographyChoice("typography-preset:original-joy"),
11706
+ typographyChoice("typography-preset:bold-display"),
11707
+ typographyChoice("typography-preset:modern-sans")
11708
+ ],
11709
+ defaultTypographyPresetId: "typography-preset:original-joy",
11710
+ themeOverrides: {
11711
+ accordions: boldBorderedAccordionSystem,
11712
+ // Shared card system: warm rounded brown cards (event + testimonial cards
11713
+ // pick this up automatically) with a burnt-orange statement variant.
11714
+ cards: originalJoyCardSystem,
11715
+ testimonialQuote: accentGlyphQuote,
11716
+ bodyText: {
11717
+ intro: {
11718
+ paragraphSize: "editorial",
11719
+ headingSize: "editorial"
11720
+ }
11721
+ }
11722
+ },
11723
+ // Recommended block looks: the bold colour-blocked feature cards, a calm
11724
+ // band for the events spotlight, and statement testimonial cards.
11725
+ recommendedAppearancePresetIds: [
11726
+ "feature-cards-bold-colors",
11727
+ "offerings-calm-list",
11728
+ "testimonials-statement-cards"
11729
+ ],
11730
+ // Floating, transparent "Clear Split" header (no fill behind the nav links).
11731
+ defaultHeaderSelection: { layoutId: "floating", styleId: "minimal-surface" },
11732
+ recommendedHeaderLayoutChoices: [headerLayoutChoice("floating")],
11733
+ recommendedHeaderStyleChoicesByLayout: {
11734
+ floating: [
11735
+ headerStyleChoice("minimal-surface"),
11736
+ headerStyleChoice("split-glass"),
11737
+ headerStyleChoice("glass")
11738
+ ]
11739
+ },
11740
+ // Legacy bridge only (the real curation is the explicit selection above).
11741
+ // Kept to a reserved-space, non-overlay look on purpose: the split hero
11742
+ // flows below the Clear Split header, so we must NOT trigger the immersive
11743
+ // overlay-hero promotion that looks like `floating-glass` would force.
11744
+ recommendedHeaderLookIds: ["minimal-transparent"],
11745
+ recommendedFooterLookIds: [
11746
+ "site-footer-brand-two-band",
11747
+ "footer-muted-grounding"
11748
+ ],
11749
+ buttonPersonalityChoices: [
11750
+ buttonChoice("joy-stamp"),
11751
+ buttonChoice("ink-stamp"),
11752
+ buttonChoice("showtime-pill")
10644
11753
  ],
10645
11754
  paletteVariantChoices: [paletteChoice("warm-dark-ember")]
10646
11755
  })
@@ -10677,6 +11786,89 @@ var MQ_TABLET_ONLY = mqBetween(BREAKPOINT_SM, BREAKPOINT_LG_DOWN);
10677
11786
  var MQ_MAX_640 = mqDown(BREAKPOINT_SM);
10678
11787
  var MQ_MAX_768 = mqDown(BREAKPOINT_MD);
10679
11788
 
11789
+ // ../blocks/src/system/runtime/nodes/event-registration/registrationDerivations.ts
11790
+ function eventMatchesOccurrenceId(event, occurrenceId) {
11791
+ return event.registrationOccurrenceId === occurrenceId || event.publicEventId === occurrenceId;
11792
+ }
11793
+ function findEventByOccurrenceId(events, occurrenceId) {
11794
+ return events.find((event) => eventMatchesOccurrenceId(event, occurrenceId)) ?? null;
11795
+ }
11796
+ function findPreSelectedEvent(input) {
11797
+ const occurrenceContext = input.occurrenceContext;
11798
+ if (!occurrenceContext) {
11799
+ return null;
11800
+ }
11801
+ const contextDate = getBookingLocalDateKey(toScheduledBookingDateTime({
11802
+ startsAt: occurrenceContext.startsAt,
11803
+ timeZone: occurrenceContext.timeZone
11804
+ }));
11805
+ return input.scopedEvents.find(
11806
+ (event) => eventMatchesOccurrenceId(event, occurrenceContext.id) || getBookingLocalDateKey(toScheduledBookingDateTime({
11807
+ startsAt: event.startsAt,
11808
+ timeZone: event.timeZone
11809
+ })) === contextDate
11810
+ ) ?? null;
11811
+ }
11812
+ function resolveRegistrationTarget(input) {
11813
+ const occurrenceId = input.occurrenceContext?.id ?? input.selectedEvent?.registrationOccurrenceId ?? null;
11814
+ if (!occurrenceId) {
11815
+ return null;
11816
+ }
11817
+ return {
11818
+ occurrenceId,
11819
+ selectedEventId: input.selectedEvent?.publicEventId ?? null
11820
+ };
11821
+ }
11822
+ function resolveEventRequiresPayment(input) {
11823
+ if (input.eligibility) {
11824
+ return input.eligibility.requiresPayment;
11825
+ }
11826
+ if (input.selectedTicketType) {
11827
+ return input.selectedTicketType.priceAmount > 0;
11828
+ }
11829
+ if (!input.event) {
11830
+ return false;
11831
+ }
11832
+ return publicEventPricingType(resolveRuntimeEventPricing(input.event)) !== "free";
11833
+ }
11834
+ function resolveDiscountContext(input) {
11835
+ const selection = input.paymentSelection.method ? input.paymentSelection : null;
11836
+ if (!input.event) {
11837
+ return null;
11838
+ }
11839
+ if (selection?.method === "pass_bundle" && selection.bundlePassId) {
11840
+ return { type: "pass", passId: selection.bundlePassId };
11841
+ }
11842
+ if (selection?.method === "membership_bundle" && selection.bundleMembershipId) {
11843
+ return { type: "membership", membershipId: selection.bundleMembershipId };
11844
+ }
11845
+ if (!input.eventRequiresPayment) {
11846
+ return null;
11847
+ }
11848
+ if (selection?.method && selection.method !== "stripe") {
11849
+ return null;
11850
+ }
11851
+ return {
11852
+ type: "event",
11853
+ eventSeriesId: input.event.seriesId,
11854
+ eventCategoryId: input.event.eventCategory?.id ?? null,
11855
+ ticketsCount: input.ticketsCount
11856
+ };
11857
+ }
11858
+
11859
+ // ../blocks/src/system/runtime/nodes/event-registration/registrationEventAdapter.ts
11860
+ function toRegistrationEvent(event) {
11861
+ return {
11862
+ ...event,
11863
+ pricing: resolveRuntimeEventPricing(event),
11864
+ publicEventId: event.id,
11865
+ registrationOccurrenceId: event.occurrenceId
11866
+ };
11867
+ }
11868
+ function toRegistrationEvents(events) {
11869
+ return events.map(toRegistrationEvent);
11870
+ }
11871
+
10680
11872
  // ../blocks/src/system/runtime/shared/components/FeedbackMessage.tsx
10681
11873
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
10682
11874
  function joinClasses(...parts) {
@@ -10749,8 +11941,8 @@ function AltchaWidget({
10749
11941
  }
10750
11942
  }));
10751
11943
  containerRef.current.appendChild(widget);
10752
- }).catch((err) => {
10753
- console.error("Failed to load ALTCHA widget:", err);
11944
+ }).catch((err3) => {
11945
+ console.error("Failed to load ALTCHA widget:", err3);
10754
11946
  });
10755
11947
  return () => {
10756
11948
  if (widget && containerRef.current) {
@@ -10990,10 +12182,10 @@ function useAvailableDates({
10990
12182
  start: append && prev ? prev.start : data.startDate,
10991
12183
  end: data.endDate
10992
12184
  }));
10993
- } catch (err) {
12185
+ } catch (err3) {
10994
12186
  if (requestId !== requestIdRef.current) return;
10995
12187
  setError(
10996
- err instanceof Error ? err.message : "Failed to load available dates"
12188
+ err3 instanceof Error ? err3.message : "Failed to load available dates"
10997
12189
  );
10998
12190
  } finally {
10999
12191
  if (mode === "refresh" && requestId === requestIdRef.current) {
@@ -11109,10 +12301,10 @@ function useAvailableSlots({
11109
12301
  }))
11110
12302
  );
11111
12303
  setHasLoaded(true);
11112
- } catch (err) {
12304
+ } catch (err3) {
11113
12305
  if (requestId !== requestIdRef.current) return;
11114
12306
  setError(
11115
- err instanceof Error ? err.message : "Failed to load available times"
12307
+ err3 instanceof Error ? err3.message : "Failed to load available times"
11116
12308
  );
11117
12309
  } finally {
11118
12310
  if (mode === "refresh" && requestId === requestIdRef.current) {
@@ -12315,7 +13507,7 @@ function omitRecordKey(record, key) {
12315
13507
  return rest;
12316
13508
  }
12317
13509
  function readAppointmentBookingOverrideData(value) {
12318
- if (!isRecord3(value)) return null;
13510
+ if (!isRecord4(value)) return null;
12319
13511
  const services = normalizeBookingServices(value.services);
12320
13512
  return {
12321
13513
  form: normalizeBookingFormConfig(value.form),
@@ -12328,7 +13520,7 @@ function createOverrideInputError(reason, message, warnInDev = false) {
12328
13520
  }
12329
13521
  return { ok: false, reason, message };
12330
13522
  }
12331
- function isRecord3(value) {
13523
+ function isRecord4(value) {
12332
13524
  return typeof value === "object" && value !== null;
12333
13525
  }
12334
13526
 
@@ -13064,13 +14256,13 @@ function usePolling(config) {
13064
14256
  dispatch({ type: "polling-progressed", result: data });
13065
14257
  isPollingRef.current = false;
13066
14258
  return false;
13067
- } catch (err) {
14259
+ } catch (err3) {
13068
14260
  if (generation !== generationRef.current || !isActiveRef.current) {
13069
14261
  isPollingRef.current = false;
13070
14262
  return true;
13071
14263
  }
13072
- if (err instanceof Error) {
13073
- dispatch({ type: "polling-request-failed", error: err });
14264
+ if (err3 instanceof Error) {
14265
+ dispatch({ type: "polling-request-failed", error: err3 });
13074
14266
  }
13075
14267
  isPollingRef.current = false;
13076
14268
  return false;
@@ -14163,6 +15355,20 @@ function buildCheckoutReturnUrls(paramName, anchorId) {
14163
15355
  return { successUrl, cancelUrl };
14164
15356
  }
14165
15357
 
15358
+ // ../blocks/src/system/runtime/shared/utils/portalLogout.ts
15359
+ function logoutPortal(anchorId) {
15360
+ const form = document.createElement("form");
15361
+ form.method = "POST";
15362
+ form.action = "/api/portal/logout";
15363
+ const redirectInput = document.createElement("input");
15364
+ redirectInput.type = "hidden";
15365
+ redirectInput.name = "redirect_to";
15366
+ redirectInput.value = `${window.location.pathname}#${anchorId}`;
15367
+ form.appendChild(redirectInput);
15368
+ document.body.appendChild(form);
15369
+ form.submit();
15370
+ }
15371
+
14166
15372
  // ../blocks/src/system/runtime/shared/utils/scrollToBlock.ts
14167
15373
  function scrollToBlock(anchorId) {
14168
15374
  requestAnimationFrame(() => {
@@ -14170,6 +15376,17 @@ function scrollToBlock(anchorId) {
14170
15376
  });
14171
15377
  }
14172
15378
 
15379
+ // ../blocks/src/system/runtime/shared/utils/urlParams.ts
15380
+ function consumeSearchParam(paramName) {
15381
+ const url = new URL(window.location.href);
15382
+ const value = url.searchParams.get(paramName);
15383
+ if (value === null) return null;
15384
+ url.searchParams.delete(paramName);
15385
+ const newUrl = url.pathname + (url.search ? url.search : "") + url.hash;
15386
+ window.history.replaceState({}, "", newUrl);
15387
+ return value;
15388
+ }
15389
+
14173
15390
  // ../blocks/src/system/runtime/nodes/booking-form.client.tsx
14174
15391
  import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
14175
15392
  var PORTAL_REBOOK_QUERY_PARAM = "rebook";
@@ -14341,97 +15558,1887 @@ var BookingFormClient = ({
14341
15558
  ] });
14342
15559
  };
14343
15560
 
14344
- // ../theme-core/src/header/navDropdownSizing.ts
14345
- var NAV_DROPDOWN_MIN_WIDTH_REM = 12;
14346
- var NAV_DROPDOWN_MAX_WIDTH_REM = 22;
14347
- var NAV_DROPDOWN_VIEWPORT_GUTTER_REM = 1;
14348
- var NAV_DROPDOWN_SHIFT_PROPERTY = "--nav-dropdown-shift-x";
14349
- var NAV_DROPDOWN_MAX_WIDTH_CSS = `min(${NAV_DROPDOWN_MAX_WIDTH_REM}rem, calc(100vw - ${NAV_DROPDOWN_VIEWPORT_GUTTER_REM * 2}rem))`;
14350
- var NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
14351
- `min-width: ${NAV_DROPDOWN_MIN_WIDTH_REM}rem;`,
14352
- `width: max-content;`,
14353
- `max-width: ${NAV_DROPDOWN_MAX_WIDTH_CSS};`,
14354
- `transform: translateX(var(${NAV_DROPDOWN_SHIFT_PROPERTY}, 0px));`
14355
- ];
14356
-
14357
- // ../theme-core/src/ClientThemeScope.tsx
14358
- import { useMemo as useMemo4 } from "react";
14359
-
14360
- // ../theme-core/src/navigation/presets.ts
14361
- var NAV_LINK_PRESETS = {
14362
- /**
14363
- * Minimal - subtle color change on hover
14364
- */
14365
- minimal: {
14366
- name: "Minimal",
14367
- typography: "body",
14368
- fontWeight: "medium",
14369
- textTransform: "none",
14370
- italic: false,
14371
- colorToken: "text",
14372
- hoverColorToken: "primary",
14373
- padding: "none",
14374
- borderRadius: "none",
14375
- effects: {
14376
- hover: [
14377
- { effectId: "text-color-change", options: { hoverColorToken: "primary" } }
14378
- ]
15561
+ // ../blocks/src/system/runtime/nodes/event-registration/registrationStateMachine.ts
15562
+ function createInitialRegistrationFlowState(hasPreSelectedContext) {
15563
+ return {
15564
+ step: hasPreSelectedContext ? "select-tickets" : "select-event",
15565
+ ticketsCount: 1,
15566
+ isAuthenticated: false,
15567
+ eligibility: null,
15568
+ passOptOut: false,
15569
+ paymentSelection: { method: null },
15570
+ selectionSource: "auto"
15571
+ };
15572
+ }
15573
+ function selectionEquals(a, b2) {
15574
+ return a.method === b2.method && a.passId === b2.passId && a.membershipId === b2.membershipId && a.bundlePassId === b2.bundlePassId && a.bundleMembershipId === b2.bundleMembershipId && a.productName === b2.productName && a.productDescription === b2.productDescription && a.productPrice === b2.productPrice && a.productCurrency === b2.productCurrency && a.productInterval === b2.productInterval;
15575
+ }
15576
+ function withDefaultSelection(selection) {
15577
+ if (!selection || !selection.method) {
15578
+ return { method: null };
15579
+ }
15580
+ return selection;
15581
+ }
15582
+ function computeAutoSelection(input) {
15583
+ const { isAuthenticated, eligibility, ticketsCount, passOptOut } = input;
15584
+ if (!eligibility) return { method: null };
15585
+ if (eligibility.isFree) return { method: "free" };
15586
+ if (isAuthenticated && ticketsCount === 1) {
15587
+ const membership = eligibility.eligibleMemberships[0];
15588
+ if (membership) {
15589
+ return {
15590
+ method: "membership",
15591
+ membershipId: membership.id,
15592
+ productName: membership.membershipName
15593
+ };
14379
15594
  }
14380
- },
14381
- /**
14382
- * Underline - static underline appears on hover
14383
- */
14384
- underline: {
14385
- name: "Underline",
14386
- typography: "body",
14387
- fontWeight: "medium",
14388
- textTransform: "none",
14389
- italic: false,
14390
- colorToken: "text",
14391
- padding: "none",
14392
- borderRadius: "none",
14393
- effects: {
14394
- hover: [{ effectId: "nav-underline", options: { style: "static" } }]
15595
+ const pass = eligibility.eligiblePasses[0];
15596
+ if (pass && !passOptOut) {
15597
+ return {
15598
+ method: "pass",
15599
+ passId: pass.id,
15600
+ productName: pass.passName
15601
+ };
14395
15602
  }
14396
- },
14397
- /**
14398
- * Underline Grow - animated underline grows from center on hover
14399
- */
14400
- "underline-grow": {
14401
- name: "Underline Grow",
14402
- typography: "body",
14403
- fontWeight: "medium",
14404
- textTransform: "none",
14405
- italic: false,
14406
- colorToken: "text",
14407
- padding: "none",
14408
- borderRadius: "none",
14409
- effects: {
14410
- hover: [{ effectId: "nav-underline", options: { style: "grow" } }]
15603
+ }
15604
+ if (eligibility.canPayDirectly && eligibility.price) {
15605
+ return { method: "stripe" };
15606
+ }
15607
+ return { method: null };
15608
+ }
15609
+ function isSelectionValid(input) {
15610
+ const { selection, isAuthenticated, eligibility, ticketsCount } = input;
15611
+ if (!selection.method) return false;
15612
+ if (!eligibility) {
15613
+ return selection.method === "stripe" || selection.method === "pass_bundle" || selection.method === "membership_bundle";
15614
+ }
15615
+ switch (selection.method) {
15616
+ case "free":
15617
+ return eligibility.isFree;
15618
+ case "stripe":
15619
+ return Boolean(eligibility.canPayDirectly && eligibility.price);
15620
+ case "pass":
15621
+ return isAuthenticated && ticketsCount === 1 && !!selection.passId && eligibility.eligiblePasses.some((pass) => pass.id === selection.passId);
15622
+ case "membership":
15623
+ return isAuthenticated && ticketsCount === 1 && !!selection.membershipId && eligibility.eligibleMemberships.some((membership) => membership.id === selection.membershipId);
15624
+ case "pass_bundle":
15625
+ return ticketsCount === 1 && !!selection.bundlePassId && eligibility.availablePasses.some((pass) => pass.id === selection.bundlePassId);
15626
+ case "membership_bundle":
15627
+ return ticketsCount === 1 && !!selection.bundleMembershipId && eligibility.availableMemberships.some((membership) => membership.id === selection.bundleMembershipId);
15628
+ default:
15629
+ return false;
15630
+ }
15631
+ }
15632
+ function normalizeRegistrationFlowState(state) {
15633
+ const hasPass = Boolean(state.eligibility?.eligiblePasses.length);
15634
+ const hasMembership = Boolean(state.eligibility?.eligibleMemberships.length);
15635
+ let nextPassOptOut = state.passOptOut;
15636
+ if (nextPassOptOut && (state.step === "select-tickets" || state.ticketsCount !== 1 || !hasPass || hasMembership)) {
15637
+ nextPassOptOut = false;
15638
+ }
15639
+ const autoSelection = computeAutoSelection({
15640
+ isAuthenticated: state.isAuthenticated,
15641
+ eligibility: state.eligibility,
15642
+ ticketsCount: state.ticketsCount,
15643
+ passOptOut: nextPassOptOut
15644
+ });
15645
+ const canKeepManualSelection = state.step === "select-payment" && state.selectionSource === "manual" && isSelectionValid({
15646
+ selection: state.paymentSelection,
15647
+ isAuthenticated: state.isAuthenticated,
15648
+ eligibility: state.eligibility,
15649
+ ticketsCount: state.ticketsCount
15650
+ });
15651
+ const nextSelection = canKeepManualSelection ? state.paymentSelection : autoSelection;
15652
+ const nextSource = canKeepManualSelection ? "manual" : "auto";
15653
+ const normalizedSelection = withDefaultSelection(nextSelection);
15654
+ if (nextPassOptOut === state.passOptOut && nextSource === state.selectionSource && selectionEquals(normalizedSelection, state.paymentSelection)) {
15655
+ return state;
15656
+ }
15657
+ return {
15658
+ ...state,
15659
+ passOptOut: nextPassOptOut,
15660
+ selectionSource: nextSource,
15661
+ paymentSelection: normalizedSelection
15662
+ };
15663
+ }
15664
+ function registrationFlowReducer(state, action) {
15665
+ switch (action.type) {
15666
+ case "set-step":
15667
+ return normalizeRegistrationFlowState({ ...state, step: action.step });
15668
+ case "set-tickets-count":
15669
+ return normalizeRegistrationFlowState({
15670
+ ...state,
15671
+ ticketsCount: Math.max(1, action.ticketsCount)
15672
+ });
15673
+ case "set-authenticated":
15674
+ return normalizeRegistrationFlowState({ ...state, isAuthenticated: action.isAuthenticated });
15675
+ case "eligibility-updated":
15676
+ return normalizeRegistrationFlowState({ ...state, eligibility: action.eligibility });
15677
+ case "set-manual-payment-selection":
15678
+ return normalizeRegistrationFlowState({
15679
+ ...state,
15680
+ paymentSelection: withDefaultSelection(action.selection),
15681
+ selectionSource: "manual",
15682
+ passOptOut: action.selection.method === "stripe" ? true : state.passOptOut
15683
+ });
15684
+ case "use-card-instead-of-pass":
15685
+ return normalizeRegistrationFlowState({
15686
+ ...state,
15687
+ passOptOut: true,
15688
+ paymentSelection: { method: "stripe" },
15689
+ selectionSource: "manual"
15690
+ });
15691
+ case "event-changed":
15692
+ return normalizeRegistrationFlowState({
15693
+ ...state,
15694
+ step: action.hasPreSelectedContext ? "select-tickets" : "select-event",
15695
+ passOptOut: false,
15696
+ paymentSelection: { method: null },
15697
+ selectionSource: "auto",
15698
+ eligibility: null
15699
+ });
15700
+ case "reset":
15701
+ return createInitialRegistrationFlowState(action.hasPreSelectedContext);
15702
+ default:
15703
+ return state;
15704
+ }
15705
+ }
15706
+ function isEntitlementSelection(selection) {
15707
+ return selection.method === "pass" || selection.method === "membership";
15708
+ }
15709
+ function requiresPaymentStep(params) {
15710
+ if (!params.eventRequiresPayment) return false;
15711
+ return !isEntitlementSelection(params.paymentSelection);
15712
+ }
15713
+
15714
+ // ../blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.ts
15715
+ var DEFAULT_EVENT_REGISTRATION_MAX_TICKETS = 5;
15716
+
15717
+ // ../blocks/src/system/runtime/nodes/event-registration/event-registration.headless.override.ts
15718
+ function createEventRegistrationBlockApiConfig(input) {
15719
+ return {
15720
+ baseUrl: input.apiBaseUrl,
15721
+ auth: input.previewToken ? { type: "bearer", token: input.previewToken } : { type: "none" },
15722
+ siteId: input.siteId,
15723
+ isPreview: input.stage === "preview",
15724
+ ...input.portalToken ? { authOverrides: { portal: { type: "bearer", token: input.portalToken } } } : {}
15725
+ };
15726
+ }
15727
+ function getEventRegistrationOverrideInput(props) {
15728
+ if (!props.siteId) {
15729
+ return {
15730
+ ok: false,
15731
+ reason: "missing-site-id",
15732
+ message: "Event registration is missing site context."
15733
+ };
15734
+ }
15735
+ if (!props.apiBaseUrl) {
15736
+ return {
15737
+ ok: false,
15738
+ reason: "missing-api-base-url",
15739
+ message: "Event registration is missing API configuration."
15740
+ };
15741
+ }
15742
+ const content = props.content ?? {};
15743
+ const data = isRecord5(props.data) ? props.data : {};
15744
+ const events = Array.isArray(data.events) ? data.events.filter(isPublicEventLike) : [];
15745
+ return {
15746
+ ok: true,
15747
+ value: {
15748
+ siteId: props.siteId,
15749
+ apiBaseUrl: props.apiBaseUrl,
15750
+ portalToken: props.portalToken ?? null,
15751
+ previewToken: props.previewToken ?? null,
15752
+ events,
15753
+ ...props.stage ? { stage: props.stage } : {},
15754
+ ...props.occurrenceContext ? { occurrenceContext: props.occurrenceContext } : {},
15755
+ ...isEventRegistrationContentEntryLike(props.contentEntry) ? { contentEntry: props.contentEntry } : {},
15756
+ ...content.maxTickets != null ? { maxTickets: content.maxTickets } : {},
15757
+ ...content.showVenue != null ? { showVenue: content.showVenue } : {},
15758
+ ...content.showCapacity != null ? { showCapacity: content.showCapacity } : {},
15759
+ ...content.successMessage ? { successMessage: content.successMessage } : {},
15760
+ ...content.waitlistMessage ? { waitlistMessage: content.waitlistMessage } : {},
15761
+ ...content.buttonText != null ? { buttonText: content.buttonText } : {},
15762
+ ...content.buttonVariant ? { buttonVariant: content.buttonVariant } : {},
15763
+ ...content.spamProtectionEnabled != null ? { spamProtectionEnabled: content.spamProtectionEnabled } : {},
15764
+ ...content.supportEmail ? { supportEmail: content.supportEmail } : {},
15765
+ ...props.blockId !== void 0 ? { blockId: props.blockId } : {}
14411
15766
  }
14412
- },
14413
- /**
14414
- * Capsule - pill-shaped background on hover
14415
- */
14416
- capsule: {
14417
- name: "Capsule",
14418
- typography: "body",
14419
- fontWeight: "medium",
14420
- textTransform: "none",
14421
- italic: false,
14422
- colorToken: "text",
14423
- padding: "compact",
14424
- borderRadius: "full",
14425
- effects: {
14426
- hover: [
14427
- {
14428
- effectId: "background-on-hover-alpha",
14429
- options: { colorToken: "primary", opacity: 10 }
14430
- }
14431
- ],
14432
- active: [
14433
- {
14434
- effectId: "background-on-hover-alpha",
15767
+ };
15768
+ }
15769
+ function isRecord5(value) {
15770
+ return typeof value === "object" && value !== null;
15771
+ }
15772
+ function isPublicEventLike(value) {
15773
+ return isRecord5(value) && typeof value.id === "string" && typeof value.occurrenceId === "string" && typeof value.seriesId === "string" && typeof value.title === "string" && typeof value.slug === "string" && typeof value.path === "string" && typeof value.requiresRegistration === "boolean" && isDeliveryMode(value.deliveryMode) && Array.isArray(value.attendanceModes) && typeof value.startsAt === "string" && typeof value.endsAt === "string" && typeof value.timeZone === "string" && isRecord5(value.pricing) && isRecord5(value.paymentTerms) && isAccessRestriction(value.accessRestriction) && Array.isArray(value.allowedCategoryIds);
15774
+ }
15775
+ function isDeliveryMode(value) {
15776
+ return value === "in_person" || value === "online" || value === "hybrid";
15777
+ }
15778
+ function isAccessRestriction(value) {
15779
+ return value === "none" || value === "category";
15780
+ }
15781
+ function isEventRegistrationContentEntryLike(value) {
15782
+ return isRecord5(value) && typeof value.id === "string" && typeof value.slug === "string" && typeof value.contentTypeSlug === "string";
15783
+ }
15784
+
15785
+ // ../blocks/src/system/runtime/nodes/event-registration/event-registration.headless.planning.ts
15786
+ function getRegistrableStatuses(isPreview) {
15787
+ return isPreview ? ["active", "draft"] : ["active"];
15788
+ }
15789
+ function normalizeEventRegistrationMaxTickets(value) {
15790
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
15791
+ return Math.floor(value);
15792
+ }
15793
+ if (typeof value === "string") {
15794
+ const parsed = Number.parseInt(value, 10);
15795
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_EVENT_REGISTRATION_MAX_TICKETS;
15796
+ }
15797
+ return DEFAULT_EVENT_REGISTRATION_MAX_TICKETS;
15798
+ }
15799
+ function toHeadlessPaymentSelection(selection) {
15800
+ switch (selection.method) {
15801
+ case null:
15802
+ return { method: "none" };
15803
+ case "free":
15804
+ return { method: "free" };
15805
+ case "stripe":
15806
+ return { method: "stripe" };
15807
+ case "pass":
15808
+ if (!selection.passId) return { method: "none" };
15809
+ return {
15810
+ method: "pass",
15811
+ passId: selection.passId,
15812
+ ...selection.productName ? { productName: selection.productName } : {}
15813
+ };
15814
+ case "membership":
15815
+ if (!selection.membershipId) return { method: "none" };
15816
+ return {
15817
+ method: "membership",
15818
+ membershipId: selection.membershipId,
15819
+ ...selection.productName ? { productName: selection.productName } : {}
15820
+ };
15821
+ case "pass_bundle":
15822
+ if (!selection.bundlePassId) return { method: "none" };
15823
+ return {
15824
+ method: "pass_bundle",
15825
+ passId: selection.bundlePassId,
15826
+ ...selection.productName ? { productName: selection.productName } : {}
15827
+ };
15828
+ case "membership_bundle":
15829
+ if (!selection.bundleMembershipId) return { method: "none" };
15830
+ return {
15831
+ method: "membership_bundle",
15832
+ membershipId: selection.bundleMembershipId,
15833
+ ...selection.productName ? { productName: selection.productName } : {}
15834
+ };
15835
+ }
15836
+ }
15837
+ function toInternalPaymentSelection(selection) {
15838
+ switch (selection.method) {
15839
+ case "none":
15840
+ return { method: null };
15841
+ case "free":
15842
+ return { method: "free" };
15843
+ case "stripe":
15844
+ return { method: "stripe" };
15845
+ case "pass":
15846
+ return {
15847
+ method: "pass",
15848
+ passId: selection.passId,
15849
+ ...selection.productName ? { productName: selection.productName } : {}
15850
+ };
15851
+ case "membership":
15852
+ return {
15853
+ method: "membership",
15854
+ membershipId: selection.membershipId,
15855
+ ...selection.productName ? { productName: selection.productName } : {}
15856
+ };
15857
+ case "pass_bundle":
15858
+ return {
15859
+ method: "pass_bundle",
15860
+ bundlePassId: selection.passId,
15861
+ ...selection.productName ? { productName: selection.productName } : {}
15862
+ };
15863
+ case "membership_bundle":
15864
+ return {
15865
+ method: "membership_bundle",
15866
+ bundleMembershipId: selection.membershipId,
15867
+ ...selection.productName ? { productName: selection.productName } : {}
15868
+ };
15869
+ }
15870
+ }
15871
+ function resolveEventRegistrationSubmitPlan(input) {
15872
+ const selection = input.paymentSelection.method ? input.paymentSelection : void 0;
15873
+ if (input.canJoinWaitlist) {
15874
+ return { ok: true, args: withOptionalSelection({ method: "free" }, selection) };
15875
+ }
15876
+ switch (input.paymentSelection.method) {
15877
+ case "pass":
15878
+ return input.paymentSelection.passId ? {
15879
+ ok: true,
15880
+ args: withOptionalSelection(
15881
+ { method: "pass", passId: input.paymentSelection.passId },
15882
+ selection
15883
+ )
15884
+ } : missingPaymentSelection();
15885
+ case "membership":
15886
+ return input.paymentSelection.membershipId ? {
15887
+ ok: true,
15888
+ args: withOptionalSelection(
15889
+ { method: "membership", membershipId: input.paymentSelection.membershipId },
15890
+ selection
15891
+ )
15892
+ } : missingPaymentSelection();
15893
+ case "free":
15894
+ return { ok: true, args: withOptionalSelection({ method: "free" }, selection) };
15895
+ case null:
15896
+ return input.eventRequiresPayment ? missingPaymentSelection() : { ok: true, args: { method: "free" } };
15897
+ case "pass_bundle":
15898
+ return input.paymentSelection.bundlePassId ? {
15899
+ ok: true,
15900
+ args: withOptionalSelection(
15901
+ { method: "pass_bundle", passId: input.paymentSelection.bundlePassId },
15902
+ selection
15903
+ )
15904
+ } : missingPaymentSelection();
15905
+ case "membership_bundle":
15906
+ return input.paymentSelection.bundleMembershipId ? {
15907
+ ok: true,
15908
+ args: withOptionalSelection(
15909
+ {
15910
+ method: "membership_bundle",
15911
+ membershipId: input.paymentSelection.bundleMembershipId
15912
+ },
15913
+ selection
15914
+ )
15915
+ } : missingPaymentSelection();
15916
+ case "stripe":
15917
+ return { ok: true, args: withOptionalSelection({ method: "stripe" }, selection) };
15918
+ }
15919
+ }
15920
+ function resolveHeadlessEventRegistrationStatus(wizard) {
15921
+ switch (wizard.step) {
15922
+ case "submitting":
15923
+ return { tag: "submitting" };
15924
+ case "redirecting":
15925
+ return { tag: "redirecting" };
15926
+ case "verifying-payment":
15927
+ return { tag: "verifying-payment" };
15928
+ case "verifying-timeout":
15929
+ return { tag: "verifying-timeout" };
15930
+ case "payment-failed":
15931
+ return { tag: "payment-failed", message: wizard.errorMessage };
15932
+ case "success":
15933
+ return wizard.registrationResult ? { tag: "success", result: wizard.registrationResult } : { tag: "ready" };
15934
+ case "error":
15935
+ return { tag: "error", message: wizard.errorMessage };
15936
+ case "select-event":
15937
+ case "select-tickets":
15938
+ case "enter-details":
15939
+ case "select-payment":
15940
+ return { tag: "ready" };
15941
+ }
15942
+ }
15943
+ function resolveHeadlessEventRegistrationView(wizard) {
15944
+ if (wizard.scopedEvents.length === 0 && !wizard.occurrenceContext) {
15945
+ return { kind: "empty", message: "No events available for registration." };
15946
+ }
15947
+ const allowedStatuses = getRegistrableStatuses(wizard.api.config.isPreview);
15948
+ const hasRegistrableEvents = wizard.scopedEvents.some(
15949
+ (event) => !event.status || allowedStatuses.includes(event.status)
15950
+ );
15951
+ if (!hasRegistrableEvents && !wizard.occurrenceContext) {
15952
+ return {
15953
+ kind: "unavailable",
15954
+ message: "Registration is not currently available for this event."
15955
+ };
15956
+ }
15957
+ switch (wizard.step) {
15958
+ case "verifying-payment":
15959
+ return { kind: "verifying", message: "Verifying your payment..." };
15960
+ case "success":
15961
+ return wizard.registrationResult ? { kind: "success", result: wizard.registrationResult } : { kind: "form" };
15962
+ case "error":
15963
+ case "payment-failed":
15964
+ return { kind: "error", message: wizard.errorMessage };
15965
+ case "verifying-timeout":
15966
+ return { kind: "verifying", message: "Your registration is saved." };
15967
+ case "select-event":
15968
+ case "select-tickets":
15969
+ case "enter-details":
15970
+ case "select-payment":
15971
+ case "submitting":
15972
+ case "redirecting":
15973
+ return { kind: "form" };
15974
+ }
15975
+ }
15976
+ function deriveEventRegistrationSteps(input) {
15977
+ const ids = [];
15978
+ if (!input.hasPreSelectedContext) ids.push("select-event");
15979
+ ids.push("select-tickets", "enter-details");
15980
+ const needsPaymentStep = input.eventRequiresPayment && input.paymentSelection.method !== "pass" && input.paymentSelection.method !== "membership";
15981
+ if (needsPaymentStep) ids.push("select-payment");
15982
+ const activeIndex = ids.indexOf(input.step);
15983
+ return ids.map((id, index) => ({
15984
+ id,
15985
+ label: getStepLabel(id),
15986
+ index,
15987
+ state: index === activeIndex ? "active" : activeIndex === -1 || index > activeIndex ? "available" : "complete",
15988
+ canEnter: index <= Math.max(activeIndex + 1, 0),
15989
+ canLeave: activeIndex !== index
15990
+ }));
15991
+ }
15992
+ function withOptionalSelection(args, selection) {
15993
+ return selection ? { ...args, selection } : args;
15994
+ }
15995
+ function missingPaymentSelection() {
15996
+ return {
15997
+ ok: false,
15998
+ reason: "payment-selection-required",
15999
+ message: "Select a payment option to continue."
16000
+ };
16001
+ }
16002
+ function getStepLabel(step) {
16003
+ switch (step) {
16004
+ case "select-event":
16005
+ return "Event";
16006
+ case "select-tickets":
16007
+ return "Tickets";
16008
+ case "enter-details":
16009
+ return "Details";
16010
+ case "select-payment":
16011
+ return "Payment";
16012
+ }
16013
+ }
16014
+
16015
+ // ../blocks/src/system/runtime/nodes/event-registration/utils.ts
16016
+ var DEFAULT_EVENT_CURRENCY2 = "usd";
16017
+ function transformEligibilityResponse(response) {
16018
+ const { eligibility } = response;
16019
+ const eligiblePasses = eligibility.passes.map((p) => ({
16020
+ id: p.customerPassId,
16021
+ passName: p.passName,
16022
+ creditsRemaining: p.creditsRemaining
16023
+ }));
16024
+ const eligibleMemberships = eligibility.membership ? [{
16025
+ id: eligibility.membership.customerMembershipId,
16026
+ membershipName: eligibility.membership.membershipName
16027
+ }] : [];
16028
+ const isFree = !eligibility.requiresPayment && !eligibility.eventPrice;
16029
+ const canPayDirectly = eligibility.eventPrice !== null && eligibility.eventPrice > 0;
16030
+ const hasPaymentOptions = eligiblePasses.length > 0 || eligibleMemberships.length > 0 || canPayDirectly;
16031
+ const hasUpsellOptions = eligibility.availableForPurchase.passes.length > 0 || eligibility.availableForPurchase.memberships.length > 0;
16032
+ const eligible = eligibility.canJoinWaitlist || !eligibility.isFull && (isFree || hasPaymentOptions || hasUpsellOptions);
16033
+ return {
16034
+ isFree,
16035
+ eligible,
16036
+ requiresPayment: eligibility.requiresPayment,
16037
+ pricingMode: eligibility.pricingMode,
16038
+ selectedTicketTypeId: eligibility.selectedTicketTypeId ?? null,
16039
+ ticketTypes: eligibility.ticketTypes ?? [],
16040
+ isFull: eligibility.isFull,
16041
+ waitlistEnabled: eligibility.waitlistEnabled,
16042
+ canJoinWaitlist: eligibility.canJoinWaitlist,
16043
+ price: eligibility.eventPrice,
16044
+ currency: eligibility.eventPriceCurrency ?? DEFAULT_EVENT_CURRENCY2,
16045
+ requiresAuthForPasses: eligibility.requiresAuthForPasses,
16046
+ requiresAuthForMemberships: eligibility.requiresAuthForMemberships,
16047
+ eligiblePasses,
16048
+ eligibleMemberships,
16049
+ canPayDirectly,
16050
+ eventAcceptsPasses: eligibility.eventAcceptsPasses,
16051
+ eventAcceptsMemberships: eligibility.eventAcceptsMemberships,
16052
+ availablePasses: eligibility.availableForPurchase.passes,
16053
+ availableMemberships: eligibility.availableForPurchase.memberships
16054
+ };
16055
+ }
16056
+ function getVisibleTicketTypes(input) {
16057
+ const eligibilityTicketTypes = input.eligibility?.ticketTypes;
16058
+ const eventTicketTypes = input.event ? publicEventTicketTypes(resolveRuntimeEventPricing(input.event)) : [];
16059
+ const source = eligibilityTicketTypes && eligibilityTicketTypes.length > 0 ? eligibilityTicketTypes : eventTicketTypes;
16060
+ return source.filter(
16061
+ (ticketType) => ticketType.isActive && (!input.selectedAttendanceMode || (ticketType.attendanceScope ?? "both") === "both" || (ticketType.attendanceScope ?? "both") === input.selectedAttendanceMode)
16062
+ );
16063
+ }
16064
+ function getImplicitSingleAvailableTicketType(ticketTypes) {
16065
+ return ticketTypes.length === 1 && ticketTypes[0]?.availability.kind === "available" ? ticketTypes[0] : null;
16066
+ }
16067
+ function findSelectedTicketType(input) {
16068
+ if (!input.selectedTicketTypeId) {
16069
+ return null;
16070
+ }
16071
+ return getVisibleTicketTypes({
16072
+ event: input.event,
16073
+ eligibility: input.eligibility,
16074
+ selectedAttendanceMode: input.selectedAttendanceMode
16075
+ }).find((ticketType) => ticketType.id === input.selectedTicketTypeId) ?? null;
16076
+ }
16077
+
16078
+ // ../blocks/src/system/runtime/nodes/event-registration/hooks.ts
16079
+ import { useState as useState6, useEffect as useEffect8, useCallback as useCallback5, useRef as useRef8, useReducer as useReducer4 } from "react";
16080
+
16081
+ // ../blocks/src/system/runtime/nodes/event-registration/hooks.state.ts
16082
+ var initialEligibilityLookupState = {
16083
+ tag: "idle",
16084
+ eligibility: null,
16085
+ error: null
16086
+ };
16087
+ function eligibilityLookupReducer(state, action) {
16088
+ switch (action.type) {
16089
+ case "reset":
16090
+ return initialEligibilityLookupState;
16091
+ case "loading-started":
16092
+ return {
16093
+ tag: "loading",
16094
+ eligibility: state.eligibility,
16095
+ error: null
16096
+ };
16097
+ case "resolved":
16098
+ return {
16099
+ tag: "resolved",
16100
+ eligibility: action.eligibility,
16101
+ error: null
16102
+ };
16103
+ case "failed":
16104
+ return {
16105
+ tag: "failed",
16106
+ eligibility: null,
16107
+ error: action.message
16108
+ };
16109
+ default:
16110
+ return assertNever11(action);
16111
+ }
16112
+ }
16113
+ var initialExistingRegistrationLookupState = {
16114
+ tag: "idle",
16115
+ registration: null
16116
+ };
16117
+ function existingRegistrationLookupReducer(state, action) {
16118
+ switch (action.type) {
16119
+ case "reset":
16120
+ return initialExistingRegistrationLookupState;
16121
+ case "loading-started":
16122
+ return {
16123
+ tag: "loading",
16124
+ registration: state.registration
16125
+ };
16126
+ case "resolved":
16127
+ return {
16128
+ tag: "resolved",
16129
+ registration: action.registration
16130
+ };
16131
+ default:
16132
+ return assertNever11(action);
16133
+ }
16134
+ }
16135
+
16136
+ // ../blocks/src/system/runtime/nodes/event-registration/hooks.ts
16137
+ function usePortalAuth() {
16138
+ const api = useBlockApi();
16139
+ const [authState, setAuthState] = useState6("checking");
16140
+ const [profile, setProfile] = useState6(null);
16141
+ useEffect8(() => {
16142
+ let cancelled = false;
16143
+ async function checkPortalAuth() {
16144
+ const effectivePortalAuth = api.config.authOverrides?.portal ?? api.config.auth;
16145
+ if (effectivePortalAuth.type !== "bearer") {
16146
+ setAuthState("unauthenticated");
16147
+ return;
16148
+ }
16149
+ setAuthState("checking");
16150
+ try {
16151
+ const me = await api.getPortalProfile();
16152
+ if (cancelled) return;
16153
+ setAuthState("authenticated");
16154
+ setProfile({
16155
+ email: me.profile.email,
16156
+ name: me.profile.name,
16157
+ phone: me.profile.phone || ""
16158
+ });
16159
+ } catch {
16160
+ if (cancelled) return;
16161
+ setAuthState("unauthenticated");
16162
+ setProfile(null);
16163
+ }
16164
+ }
16165
+ void checkPortalAuth();
16166
+ return () => {
16167
+ cancelled = true;
16168
+ };
16169
+ }, [api]);
16170
+ const logout = useCallback5(() => {
16171
+ const form = document.createElement("form");
16172
+ form.method = "POST";
16173
+ form.action = "/api/portal/logout";
16174
+ document.body.appendChild(form);
16175
+ form.submit();
16176
+ }, []);
16177
+ return {
16178
+ authState,
16179
+ isAuthenticated: authState === "authenticated",
16180
+ isChecking: authState === "checking",
16181
+ profile,
16182
+ logout
16183
+ };
16184
+ }
16185
+ function useEligibility(params) {
16186
+ const api = useBlockApi();
16187
+ const [state, dispatch] = useReducer4(
16188
+ eligibilityLookupReducer,
16189
+ initialEligibilityLookupState
16190
+ );
16191
+ const requestIdRef = useRef8(0);
16192
+ useEffect8(() => {
16193
+ let cancelled = false;
16194
+ async function fetchEligibility() {
16195
+ if (!params.enabled) {
16196
+ requestIdRef.current += 1;
16197
+ dispatch({ type: "reset" });
16198
+ return;
16199
+ }
16200
+ if (!params.occurrenceId || !params.email.trim()) {
16201
+ requestIdRef.current += 1;
16202
+ dispatch({ type: "reset" });
16203
+ return;
16204
+ }
16205
+ const requestId = requestIdRef.current + 1;
16206
+ requestIdRef.current = requestId;
16207
+ dispatch({ type: "loading-started" });
16208
+ try {
16209
+ const result = await api.checkEligibility({
16210
+ occurrenceId: params.occurrenceId,
16211
+ attendanceMode: params.attendanceMode ?? void 0,
16212
+ ticketTypeId: params.ticketTypeId ?? void 0,
16213
+ email: params.email.trim().toLowerCase(),
16214
+ ticketsCount: params.ticketsCount
16215
+ });
16216
+ if (cancelled || requestIdRef.current !== requestId) return;
16217
+ dispatch({
16218
+ type: "resolved",
16219
+ eligibility: transformEligibilityResponse(result)
16220
+ });
16221
+ } catch (err3) {
16222
+ if (cancelled || requestIdRef.current !== requestId) return;
16223
+ dispatch({
16224
+ type: "failed",
16225
+ message: err3 instanceof Error ? err3.message : "Failed to check eligibility"
16226
+ });
16227
+ }
16228
+ }
16229
+ void fetchEligibility();
16230
+ return () => {
16231
+ cancelled = true;
16232
+ };
16233
+ }, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.email, params.ticketsCount]);
16234
+ return {
16235
+ state,
16236
+ eligibility: state.eligibility,
16237
+ isLoading: state.tag === "loading",
16238
+ error: state.error
16239
+ };
16240
+ }
16241
+ function useExistingEventRegistration({
16242
+ isAuthenticated,
16243
+ occurrenceId
16244
+ }) {
16245
+ const api = useBlockApi();
16246
+ const [state, dispatch] = useReducer4(
16247
+ existingRegistrationLookupReducer,
16248
+ initialExistingRegistrationLookupState
16249
+ );
16250
+ const requestIdRef = useRef8(0);
16251
+ useEffect8(() => {
16252
+ let cancelled = false;
16253
+ async function fetchExistingRegistration() {
16254
+ if (!isAuthenticated || !occurrenceId) {
16255
+ requestIdRef.current += 1;
16256
+ dispatch({ type: "reset" });
16257
+ return;
16258
+ }
16259
+ const requestId = requestIdRef.current + 1;
16260
+ requestIdRef.current = requestId;
16261
+ dispatch({ type: "loading-started" });
16262
+ try {
16263
+ const events = await api.getPortalEvents({ occurrenceId });
16264
+ if (cancelled || requestIdRef.current !== requestId) return;
16265
+ const existing = events.find(
16266
+ (event) => event.occurrenceId === occurrenceId && event.status !== "cancelled" && event.transferState !== "transferred_out"
16267
+ ) ?? null;
16268
+ dispatch({ type: "resolved", registration: existing });
16269
+ } catch {
16270
+ if (cancelled || requestIdRef.current !== requestId) return;
16271
+ dispatch({ type: "resolved", registration: null });
16272
+ }
16273
+ }
16274
+ void fetchExistingRegistration();
16275
+ return () => {
16276
+ cancelled = true;
16277
+ };
16278
+ }, [api, isAuthenticated, occurrenceId]);
16279
+ return {
16280
+ state,
16281
+ registration: state.registration,
16282
+ isLoading: state.tag === "loading"
16283
+ };
16284
+ }
16285
+
16286
+ // ../blocks/src/system/runtime/nodes/event-registration/sessionStorage.ts
16287
+ var STORAGE_PREFIX = "riverbank:event-registration:";
16288
+ var STALE_THRESHOLD_MS = 24 * 60 * 60 * 1e3;
16289
+ function getStorageKey(siteId, occurrenceId) {
16290
+ return `${STORAGE_PREFIX}${siteId}:${occurrenceId}`;
16291
+ }
16292
+ function isStorageAvailable() {
16293
+ try {
16294
+ const testKey = "__riverbank_test__";
16295
+ sessionStorage.setItem(testKey, "test");
16296
+ sessionStorage.removeItem(testKey);
16297
+ return true;
16298
+ } catch {
16299
+ return false;
16300
+ }
16301
+ }
16302
+ function savePendingRegistration(siteId, occurrenceId, data) {
16303
+ if (!isStorageAvailable()) {
16304
+ console.warn("[sessionStorage] Storage not available, skipping save");
16305
+ return;
16306
+ }
16307
+ try {
16308
+ const key = getStorageKey(siteId, occurrenceId);
16309
+ const entry = {
16310
+ ...data,
16311
+ version: 3,
16312
+ timestamp: Date.now()
16313
+ };
16314
+ sessionStorage.setItem(key, JSON.stringify(entry));
16315
+ } catch (error) {
16316
+ console.warn("[sessionStorage] Failed to save registration:", error);
16317
+ }
16318
+ }
16319
+ function getPendingRegistration(siteId, occurrenceId) {
16320
+ if (!isStorageAvailable()) {
16321
+ return null;
16322
+ }
16323
+ try {
16324
+ if (occurrenceId) {
16325
+ const key = getStorageKey(siteId, occurrenceId);
16326
+ const stored = sessionStorage.getItem(key);
16327
+ if (stored) {
16328
+ return parseAndValidateEntry(stored, key);
16329
+ }
16330
+ return null;
16331
+ }
16332
+ const sitePrefix = `${STORAGE_PREFIX}${siteId}:`;
16333
+ for (let i = 0; i < sessionStorage.length; i++) {
16334
+ const key = sessionStorage.key(i);
16335
+ if (key?.startsWith(sitePrefix)) {
16336
+ const stored = sessionStorage.getItem(key);
16337
+ if (stored) {
16338
+ const entry = parseAndValidateEntry(stored, key);
16339
+ if (entry) return entry;
16340
+ }
16341
+ }
16342
+ }
16343
+ return null;
16344
+ } catch (error) {
16345
+ console.warn("[sessionStorage] Failed to read registration:", error);
16346
+ return null;
16347
+ }
16348
+ }
16349
+ function parseAndValidateEntry(stored, key) {
16350
+ try {
16351
+ const raw = JSON.parse(stored);
16352
+ if (!raw || typeof raw !== "object") {
16353
+ sessionStorage.removeItem(key);
16354
+ return null;
16355
+ }
16356
+ const version = raw.version;
16357
+ if (version !== 1 && version !== 2 && version !== 3) {
16358
+ console.warn("[sessionStorage] Unknown version, ignoring entry");
16359
+ sessionStorage.removeItem(key);
16360
+ return null;
16361
+ }
16362
+ const entry = raw;
16363
+ const timestamp = typeof entry.timestamp === "number" ? entry.timestamp : NaN;
16364
+ if (!Number.isFinite(timestamp)) {
16365
+ sessionStorage.removeItem(key);
16366
+ return null;
16367
+ }
16368
+ const age = Date.now() - timestamp;
16369
+ if (age > STALE_THRESHOLD_MS) {
16370
+ console.info("[sessionStorage] Entry is stale, removing");
16371
+ sessionStorage.removeItem(key);
16372
+ return null;
16373
+ }
16374
+ if (entry.version === 1) {
16375
+ const legacy = entry;
16376
+ return {
16377
+ version: 3,
16378
+ attendeeId: legacy.attendeeId,
16379
+ formData: legacy.formData,
16380
+ ticketsCount: legacy.ticketsCount,
16381
+ selectedEventId: legacy.selectedEventId,
16382
+ selectedAttendanceMode: null,
16383
+ selectedTicketTypeId: null,
16384
+ paymentSelection: { method: legacy.paymentMethod },
16385
+ timestamp: legacy.timestamp
16386
+ };
16387
+ }
16388
+ if (entry.version === 2) {
16389
+ return {
16390
+ version: 3,
16391
+ attendeeId: entry.attendeeId,
16392
+ formData: entry.formData,
16393
+ ticketsCount: entry.ticketsCount,
16394
+ selectedEventId: entry.selectedEventId,
16395
+ selectedAttendanceMode: null,
16396
+ selectedTicketTypeId: null,
16397
+ paymentSelection: entry.paymentSelection,
16398
+ timestamp: entry.timestamp
16399
+ };
16400
+ }
16401
+ return entry;
16402
+ } catch {
16403
+ console.warn("[sessionStorage] Failed to parse entry, removing");
16404
+ sessionStorage.removeItem(key);
16405
+ return null;
16406
+ }
16407
+ }
16408
+ function clearPendingRegistration(siteId, occurrenceId) {
16409
+ if (!isStorageAvailable()) {
16410
+ return;
16411
+ }
16412
+ try {
16413
+ const key = getStorageKey(siteId, occurrenceId);
16414
+ sessionStorage.removeItem(key);
16415
+ } catch {
16416
+ }
16417
+ }
16418
+ function cleanupStaleRegistrations() {
16419
+ if (!isStorageAvailable()) {
16420
+ return;
16421
+ }
16422
+ try {
16423
+ const keysToRemove = [];
16424
+ for (let i = 0; i < sessionStorage.length; i++) {
16425
+ const key = sessionStorage.key(i);
16426
+ if (!key?.startsWith(STORAGE_PREFIX)) {
16427
+ continue;
16428
+ }
16429
+ try {
16430
+ const stored = sessionStorage.getItem(key);
16431
+ if (!stored) continue;
16432
+ const entry = JSON.parse(stored);
16433
+ const age = Date.now() - entry.timestamp;
16434
+ if (age > STALE_THRESHOLD_MS) {
16435
+ keysToRemove.push(key);
16436
+ }
16437
+ } catch {
16438
+ keysToRemove.push(key);
16439
+ }
16440
+ }
16441
+ for (const key of keysToRemove) {
16442
+ sessionStorage.removeItem(key);
16443
+ }
16444
+ if (keysToRemove.length > 0) {
16445
+ console.info(`[sessionStorage] Cleaned up ${keysToRemove.length} stale entries`);
16446
+ }
16447
+ } catch (error) {
16448
+ console.warn("[sessionStorage] Cleanup failed:", error);
16449
+ }
16450
+ }
16451
+
16452
+ // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
16453
+ import { useCallback as useCallback6, useEffect as useEffect11, useMemo as useMemo6, useReducer as useReducer5, useState as useState8 } from "react";
16454
+
16455
+ // ../blocks/src/system/runtime/nodes/event-registration/validation.ts
16456
+ function validateFormData2(formData) {
16457
+ const errors = {};
16458
+ if (!formData.name.trim()) {
16459
+ errors.name = "Name is required";
16460
+ }
16461
+ if (!formData.email.trim()) {
16462
+ errors.email = "Email is required";
16463
+ } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
16464
+ errors.email = "Invalid email address";
16465
+ }
16466
+ return errors;
16467
+ }
16468
+
16469
+ // ../blocks/src/system/runtime/shared/useWaitlistClaim.ts
16470
+ import { useEffect as useEffect9, useState as useState7, useSyncExternalStore } from "react";
16471
+ var WAITLIST_CLAIM_LOCATION_EVENT = "riverbank:waitlist-claim-location-change";
16472
+ var historyPatched = false;
16473
+ function emitWaitlistClaimLocationChange() {
16474
+ if (typeof window === "undefined") return;
16475
+ window.dispatchEvent(new Event(WAITLIST_CLAIM_LOCATION_EVENT));
16476
+ }
16477
+ function ensureWaitlistClaimLocationTracking() {
16478
+ if (typeof window === "undefined" || historyPatched) {
16479
+ return;
16480
+ }
16481
+ historyPatched = true;
16482
+ const history = window.history;
16483
+ if (history.__riverbankWaitlistClaimPatched__) {
16484
+ return;
16485
+ }
16486
+ const wrapHistoryMethod = (method) => {
16487
+ return function patched(...args) {
16488
+ method.apply(this, args);
16489
+ emitWaitlistClaimLocationChange();
16490
+ };
16491
+ };
16492
+ try {
16493
+ history.pushState = wrapHistoryMethod(history.pushState);
16494
+ history.replaceState = wrapHistoryMethod(history.replaceState);
16495
+ history.__riverbankWaitlistClaimPatched__ = true;
16496
+ } catch {
16497
+ }
16498
+ window.addEventListener("popstate", emitWaitlistClaimLocationChange);
16499
+ }
16500
+ function getWaitlistClaimTokenFromUrl() {
16501
+ if (typeof window === "undefined") {
16502
+ return null;
16503
+ }
16504
+ const token = new URLSearchParams(window.location.search).get("waitlist_claim")?.trim() ?? "";
16505
+ return token.length > 0 ? token : null;
16506
+ }
16507
+ function subscribeToWaitlistClaimToken(callback) {
16508
+ if (typeof window === "undefined") {
16509
+ return () => {
16510
+ };
16511
+ }
16512
+ ensureWaitlistClaimLocationTracking();
16513
+ window.addEventListener(WAITLIST_CLAIM_LOCATION_EVENT, callback);
16514
+ return () => {
16515
+ window.removeEventListener(WAITLIST_CLAIM_LOCATION_EVENT, callback);
16516
+ };
16517
+ }
16518
+ function getWaitlistClaimTokenSnapshot() {
16519
+ return getWaitlistClaimTokenFromUrl();
16520
+ }
16521
+ function useWaitlistClaim() {
16522
+ const api = useBlockApi();
16523
+ const token = useSyncExternalStore(
16524
+ subscribeToWaitlistClaimToken,
16525
+ getWaitlistClaimTokenSnapshot,
16526
+ () => null
16527
+ );
16528
+ const [claim, setClaim] = useState7(null);
16529
+ const [error, setError] = useState7(null);
16530
+ const [loginMessage, setLoginMessage] = useState7(null);
16531
+ const [requiresPortalLogin, setRequiresPortalLogin] = useState7(false);
16532
+ const [isLoading, setIsLoading] = useState7(() => Boolean(token));
16533
+ useEffect9(() => {
16534
+ let cancelled = false;
16535
+ async function resolveClaim() {
16536
+ if (!token) {
16537
+ setClaim(null);
16538
+ setError(null);
16539
+ setLoginMessage(null);
16540
+ setRequiresPortalLogin(false);
16541
+ setIsLoading(false);
16542
+ return;
16543
+ }
16544
+ setIsLoading(true);
16545
+ setClaim(null);
16546
+ setError(null);
16547
+ setLoginMessage(null);
16548
+ setRequiresPortalLogin(false);
16549
+ try {
16550
+ const result = await api.resolveWaitlistClaim({ claimToken: token });
16551
+ if (cancelled) return;
16552
+ setClaim(result);
16553
+ } catch (claimError) {
16554
+ if (cancelled) return;
16555
+ const message = claimError instanceof Error ? claimError.message : "Failed to resolve waitlist claim";
16556
+ setClaim(null);
16557
+ if (claimError instanceof BlockApiError && claimError.status === 401) {
16558
+ setRequiresPortalLogin(true);
16559
+ setLoginMessage(message);
16560
+ setError(null);
16561
+ } else {
16562
+ setError(message);
16563
+ }
16564
+ } finally {
16565
+ if (!cancelled) {
16566
+ setIsLoading(false);
16567
+ }
16568
+ }
16569
+ }
16570
+ void resolveClaim();
16571
+ return () => {
16572
+ cancelled = true;
16573
+ };
16574
+ }, [api, token]);
16575
+ return {
16576
+ token,
16577
+ claim,
16578
+ error,
16579
+ loginMessage,
16580
+ requiresPortalLogin,
16581
+ isLoading
16582
+ };
16583
+ }
16584
+
16585
+ // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.ts
16586
+ import { useEffect as useEffect10, useMemo as useMemo5 } from "react";
16587
+
16588
+ // ../blocks/src/system/runtime/hooks/usePaymentVerification.ts
16589
+ import { useMemo as useMemo4 } from "react";
16590
+ function usePaymentVerification(config) {
16591
+ const api = useBlockApi();
16592
+ const pollingConfig = useMemo4(() => {
16593
+ if (!config) return null;
16594
+ return {
16595
+ pollFn: () => api.getEventRegistrationStatus({ attendeeId: config.transactionId }),
16596
+ isComplete: (result) => result.paymentStatus === "completed" || result.paymentStatus === "not_required",
16597
+ isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "refunded",
16598
+ maxAttempts: config.maxAttempts,
16599
+ interval: config.pollInterval
16600
+ };
16601
+ }, [api, config]);
16602
+ const polling = usePolling(pollingConfig);
16603
+ const paymentStatus = polling.result?.paymentStatus ?? null;
16604
+ let errorMessage = null;
16605
+ if (polling.status === "timeout") {
16606
+ errorMessage = "Could not verify payment. If you were charged, please contact support.";
16607
+ } else if (polling.status === "failed" && paymentStatus) {
16608
+ errorMessage = paymentStatus === "refunded" ? "Payment was refunded. Please contact support." : "Payment was declined. Please try again.";
16609
+ } else if (polling.error) {
16610
+ errorMessage = polling.error.message;
16611
+ }
16612
+ return {
16613
+ status: polling.status,
16614
+ paymentStatus,
16615
+ attendeeStatus: polling.result?.attendeeStatus ?? null,
16616
+ waitlistPosition: polling.result?.waitlistPosition ?? null,
16617
+ error: errorMessage,
16618
+ retry: polling.retry
16619
+ };
16620
+ }
16621
+
16622
+ // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.ts
16623
+ function useEventRegistrationStripeReturn(options) {
16624
+ const {
16625
+ api,
16626
+ events,
16627
+ occurrenceId,
16628
+ pendingAttendeeId,
16629
+ setErrorMessage,
16630
+ setFormData,
16631
+ setPaymentSelection,
16632
+ setPendingAttendeeId,
16633
+ setRegistrationResult,
16634
+ setSelectedEvent,
16635
+ setSelectedAttendanceMode,
16636
+ setSelectedTicketTypeId,
16637
+ setStep,
16638
+ setTicketsCount,
16639
+ step
16640
+ } = options;
16641
+ const verificationConfig = useMemo5(
16642
+ () => step === "verifying-payment" && pendingAttendeeId ? { transactionId: pendingAttendeeId } : null,
16643
+ [step, pendingAttendeeId]
16644
+ );
16645
+ const verification = usePaymentVerification(verificationConfig);
16646
+ useEffect10(() => {
16647
+ cleanupStaleRegistrations();
16648
+ const registrationStatus = consumeSearchParam("registration");
16649
+ if (!registrationStatus) return;
16650
+ const siteId = api.config.siteId;
16651
+ if (!siteId) return;
16652
+ const pending = getPendingRegistration(siteId, occurrenceId || void 0);
16653
+ if (!pending) return;
16654
+ setFormData(pending.formData);
16655
+ setTicketsCount(pending.ticketsCount);
16656
+ if (pending.selectedEventId) {
16657
+ const event = events.find((e) => e.publicEventId === pending.selectedEventId) ?? null;
16658
+ if (event) setSelectedEvent(event);
16659
+ }
16660
+ setSelectedAttendanceMode(pending.selectedAttendanceMode ?? null);
16661
+ setSelectedTicketTypeId(pending.selectedTicketTypeId ?? null);
16662
+ setPaymentSelection(pending.paymentSelection);
16663
+ if (registrationStatus === "cancelled") {
16664
+ setStep("select-payment");
16665
+ } else if (registrationStatus === "success") {
16666
+ setPendingAttendeeId(pending.attendeeId);
16667
+ setStep("verifying-payment");
16668
+ }
16669
+ }, []);
16670
+ useEffect10(() => {
16671
+ if (verification.status === "completed") {
16672
+ const siteId = api.config.siteId;
16673
+ if (siteId && occurrenceId) {
16674
+ clearPendingRegistration(siteId, occurrenceId);
16675
+ }
16676
+ setRegistrationResult({
16677
+ status: "confirmed"
16678
+ });
16679
+ setStep("success");
16680
+ } else if (verification.status === "failed") {
16681
+ setErrorMessage(verification.error ?? "Payment failed. Please try again.");
16682
+ setStep("payment-failed");
16683
+ } else if (verification.status === "timeout") {
16684
+ setStep("verifying-timeout");
16685
+ }
16686
+ }, [
16687
+ verification.status,
16688
+ verification.attendeeStatus,
16689
+ verification.waitlistPosition,
16690
+ verification.error,
16691
+ api.config.siteId,
16692
+ occurrenceId,
16693
+ setErrorMessage,
16694
+ setRegistrationResult,
16695
+ setStep
16696
+ ]);
16697
+ return verification;
16698
+ }
16699
+
16700
+ // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.ts
16701
+ function useEventRegistrationSubmit(options) {
16702
+ return async (method, passId, membershipId, selection, submitOptions) => {
16703
+ const submitOccurrenceId = options.registrationTarget?.occurrenceId;
16704
+ if (!submitOccurrenceId) {
16705
+ return {
16706
+ ok: false,
16707
+ reason: "missing-target",
16708
+ message: "Select an event to continue."
16709
+ };
16710
+ }
16711
+ options.setStep("submitting");
16712
+ try {
16713
+ const isBundle = method === "pass_bundle" || method === "membership_bundle";
16714
+ const bundleProductId = isBundle ? passId || membershipId : void 0;
16715
+ const selectionSnapshot = (() => {
16716
+ if (selection?.method) {
16717
+ return selection;
16718
+ }
16719
+ if (method === "pass") {
16720
+ return { method: "pass", passId: passId ?? void 0 };
16721
+ }
16722
+ if (method === "membership") {
16723
+ return { method: "membership", membershipId: membershipId ?? void 0 };
16724
+ }
16725
+ if (method === "pass_bundle") {
16726
+ return { method: "pass_bundle", bundlePassId: bundleProductId ?? void 0 };
16727
+ }
16728
+ if (method === "membership_bundle") {
16729
+ return { method: "membership_bundle", bundleMembershipId: bundleProductId ?? void 0 };
16730
+ }
16731
+ return { method };
16732
+ })();
16733
+ const guestsPayload = options.requireGuestDetails && options.guests.length > 0 ? options.guests.map((guest) => ({
16734
+ name: guest.name.trim(),
16735
+ email: guest.email?.trim().toLowerCase() || void 0,
16736
+ phone: guest.phone?.trim() || void 0
16737
+ })) : void 0;
16738
+ const result = await options.api.registerForEvent({
16739
+ occurrenceId: submitOccurrenceId,
16740
+ attendanceMode: options.selectedAttendanceMode ?? void 0,
16741
+ ticketTypeId: options.selectedTicketTypeId ?? void 0,
16742
+ email: options.formData.email.trim().toLowerCase(),
16743
+ name: options.formData.name.trim(),
16744
+ ticketsCount: options.ticketsCount,
16745
+ phone: options.formData.phone.trim() || void 0,
16746
+ notes: options.formData.notes.trim() || void 0,
16747
+ altchaSolution: options.altchaSolution,
16748
+ paymentMethod: method,
16749
+ customerPassId: method === "pass" ? passId : void 0,
16750
+ customerMembershipId: method === "membership" ? membershipId : void 0,
16751
+ bundleProductId,
16752
+ claimToken: options.claimToken ?? void 0,
16753
+ guests: guestsPayload
16754
+ });
16755
+ const needsStripeCheckout = !result.alreadyRegistered && result.status === "confirmed" && result.pendingPayment && (method === "stripe" || method === "pass_bundle" || method === "membership_bundle");
16756
+ if (needsStripeCheckout) {
16757
+ options.setPendingAttendeeId(result.attendeeId);
16758
+ options.setStep("redirecting");
16759
+ const currentUrl = new URL(window.location.href);
16760
+ const successParams = new URLSearchParams(currentUrl.search);
16761
+ successParams.set("registration", "success");
16762
+ const successUrl = `${currentUrl.origin}${currentUrl.pathname}?${successParams.toString()}${currentUrl.hash}`;
16763
+ const cancelParams = new URLSearchParams(currentUrl.search);
16764
+ cancelParams.set("registration", "cancelled");
16765
+ const cancelUrl = `${currentUrl.origin}${currentUrl.pathname}?${cancelParams.toString()}${currentUrl.hash}`;
16766
+ const checkoutType = method === "pass_bundle" ? "pass_bundle" : method === "membership_bundle" ? "membership_bundle" : "event";
16767
+ const checkoutResult = await options.api.createEventCheckout({
16768
+ attendeeId: result.attendeeId,
16769
+ checkoutType,
16770
+ productId: bundleProductId,
16771
+ discountCode: options.discountCode.trim() ? options.discountCode.trim() : void 0,
16772
+ successUrl,
16773
+ cancelUrl
16774
+ });
16775
+ if (checkoutResult.bypassed) {
16776
+ options.setRegistrationResult({ status: "confirmed" });
16777
+ options.setStep("success");
16778
+ return { ok: true, outcome: { kind: "completed" } };
16779
+ }
16780
+ if (!checkoutResult.checkoutUrl) {
16781
+ throw new Error("Checkout URL missing");
16782
+ }
16783
+ const siteId = options.api.config.siteId;
16784
+ if (siteId && submitOccurrenceId) {
16785
+ savePendingRegistration(siteId, submitOccurrenceId, {
16786
+ attendeeId: result.attendeeId,
16787
+ formData: options.formData,
16788
+ ticketsCount: options.ticketsCount,
16789
+ selectedEventId: options.registrationTarget?.selectedEventId ?? null,
16790
+ selectedAttendanceMode: options.selectedAttendanceMode,
16791
+ selectedTicketTypeId: options.selectedTicketTypeId ?? null,
16792
+ paymentSelection: selectionSnapshot
16793
+ });
16794
+ }
16795
+ if (submitOptions?.redirect === "manual") {
16796
+ return {
16797
+ ok: true,
16798
+ outcome: {
16799
+ kind: "checkout_redirect",
16800
+ checkoutUrl: checkoutResult.checkoutUrl
16801
+ }
16802
+ };
16803
+ }
16804
+ window.location.href = checkoutResult.checkoutUrl;
16805
+ return { ok: true, outcome: { kind: "checkout_redirect", checkoutUrl: checkoutResult.checkoutUrl } };
16806
+ }
16807
+ if (result.alreadyRegistered) {
16808
+ const title = result.status === "waitlist" ? "Already waitlisted" : "Already registered";
16809
+ const fallbackMessage = result.status === "waitlist" ? "You are already on the waitlist for this event." : "You are already registered for this event.";
16810
+ options.setRegistrationResult({
16811
+ status: result.status,
16812
+ variant: "info",
16813
+ title,
16814
+ message: result.message ?? fallbackMessage
16815
+ });
16816
+ } else if (result.status === "waitlist") {
16817
+ const waitlistMessage = typeof result.waitlistPosition === "number" ? `You've been added to the waitlist (position ${result.waitlistPosition}).` : "You've been added to the waitlist.";
16818
+ options.setRegistrationResult({
16819
+ status: "waitlist",
16820
+ title: "Added to waitlist",
16821
+ message: result.message ?? waitlistMessage
16822
+ });
16823
+ } else {
16824
+ options.setRegistrationResult({ status: result.status });
16825
+ }
16826
+ options.setStep("success");
16827
+ return { ok: true, outcome: { kind: "completed" } };
16828
+ } catch (error) {
16829
+ const message = error instanceof Error ? error.message : "Registration failed";
16830
+ options.setErrorMessage(message);
16831
+ options.setStep("error");
16832
+ return {
16833
+ ok: false,
16834
+ reason: "submission-failed",
16835
+ message
16836
+ };
16837
+ }
16838
+ };
16839
+ }
16840
+
16841
+ // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
16842
+ function useEventRegistrationWizard(options) {
16843
+ const api = useBlockApi();
16844
+ const registrationEvents = useMemo6(
16845
+ () => toRegistrationEvents(options.events ?? []),
16846
+ [options.events]
16847
+ );
16848
+ const scopedEvents = useMemo6(() => {
16849
+ const allEvents = registrationEvents;
16850
+ if (options.occurrenceContext?.seriesId) {
16851
+ return allEvents.filter((event) => event.seriesId === options.occurrenceContext?.seriesId);
16852
+ }
16853
+ const entrySlug = options.contentEntry?.slug;
16854
+ const entryContentType = options.contentEntry?.contentTypeSlug;
16855
+ if (entrySlug && entryContentType && isEventContentType(entryContentType)) {
16856
+ return allEvents.filter((event) => event.slug === entrySlug);
16857
+ }
16858
+ return allEvents;
16859
+ }, [registrationEvents, options.occurrenceContext?.seriesId, options.contentEntry?.slug, options.contentEntry?.contentTypeSlug]);
16860
+ const preSelectedEvent = useMemo6(
16861
+ () => findPreSelectedEvent({
16862
+ scopedEvents,
16863
+ occurrenceContext: options.occurrenceContext
16864
+ }),
16865
+ [scopedEvents, options.occurrenceContext]
16866
+ );
16867
+ const hasPreSelectedContext = !!(options.occurrenceContext || preSelectedEvent);
16868
+ const [flowState, dispatchFlow] = useReducer5(
16869
+ registrationFlowReducer,
16870
+ hasPreSelectedContext,
16871
+ createInitialRegistrationFlowState
16872
+ );
16873
+ const step = flowState.step;
16874
+ const ticketsCount = flowState.ticketsCount;
16875
+ const paymentSelection = flowState.paymentSelection;
16876
+ const [selectedEvent, setSelectedEvent] = useState8(preSelectedEvent ?? null);
16877
+ const [formData, setFormData] = useState8({ name: "", email: "", phone: "", notes: "" });
16878
+ const [errors, setErrors] = useState8({});
16879
+ const [guests, setGuests] = useState8([]);
16880
+ const [guestErrors, setGuestErrors] = useState8({});
16881
+ const [guestSectionShake, setGuestSectionShake] = useState8(false);
16882
+ const [selectedAttendanceMode, setSelectedAttendanceMode] = useState8(
16883
+ preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
16884
+ );
16885
+ const [selectedTicketTypeId, setSelectedTicketTypeId] = useState8(null);
16886
+ const [registrationResult, setRegistrationResult] = useState8(null);
16887
+ const [errorMessage, setErrorMessage] = useState8("");
16888
+ const [altchaSolution, setAltchaSolution] = useState8(null);
16889
+ const { authState: portalAuthState, profile: portalProfile } = usePortalAuth();
16890
+ const waitlistClaim = useWaitlistClaim();
16891
+ const [showMagicLinkModal, setShowMagicLinkModal] = useState8(false);
16892
+ const [pendingAttendeeId, setPendingAttendeeId] = useState8(null);
16893
+ const [paymentStepState, setPaymentStepState] = useState8({
16894
+ status: "loading",
16895
+ canContinue: false,
16896
+ buttonText: "Continue",
16897
+ showLoginPrompt: false
16898
+ });
16899
+ useEffect11(() => {
16900
+ if (portalAuthState !== "authenticated" || !portalProfile) return;
16901
+ setFormData((prev) => ({
16902
+ ...prev,
16903
+ email: portalProfile.email,
16904
+ name: prev.name || portalProfile.name,
16905
+ phone: prev.phone || portalProfile.phone || ""
16906
+ }));
16907
+ }, [portalAuthState, portalProfile]);
16908
+ const handleLogout = () => logoutPortal(options.anchorId);
16909
+ const registrationTarget = useMemo6(
16910
+ () => resolveRegistrationTarget({
16911
+ occurrenceContext: options.occurrenceContext,
16912
+ selectedEvent
16913
+ }),
16914
+ [options.occurrenceContext, selectedEvent]
16915
+ );
16916
+ const occurrenceId = registrationTarget?.occurrenceId ?? "";
16917
+ const eligibilityResult = useEligibility({
16918
+ enabled: portalAuthState === "authenticated" || step === "enter-details" || step === "select-payment",
16919
+ occurrenceId,
16920
+ attendanceMode: selectedAttendanceMode,
16921
+ ticketTypeId: selectedTicketTypeId,
16922
+ email: formData.email,
16923
+ ticketsCount
16924
+ });
16925
+ const existingRegistrationResult = useExistingEventRegistration({
16926
+ isAuthenticated: portalAuthState === "authenticated",
16927
+ occurrenceId
16928
+ });
16929
+ const eligibility = eligibilityResult.eligibility;
16930
+ const eligibilityLoading = eligibilityResult.isLoading;
16931
+ const eligibilityError = eligibilityResult.error;
16932
+ const setStep = useCallback6((nextStep) => {
16933
+ dispatchFlow({ type: "set-step", step: nextStep });
16934
+ }, []);
16935
+ const setTicketsCount = useCallback6((nextTicketsCount) => {
16936
+ dispatchFlow({
16937
+ type: "set-tickets-count",
16938
+ ticketsCount: waitlistClaim.claim ? 1 : nextTicketsCount
16939
+ });
16940
+ }, [waitlistClaim.claim]);
16941
+ useEffect11(() => {
16942
+ const claim = waitlistClaim.claim;
16943
+ if (!claim || claim.subject.kind !== "event_occurrence") return;
16944
+ const occurrenceId2 = claim.subject.occurrenceId;
16945
+ const matchedEvent = findEventByOccurrenceId(scopedEvents, occurrenceId2);
16946
+ if (!matchedEvent && options.occurrenceContext?.id !== occurrenceId2) {
16947
+ setErrorMessage("This waitlist claim is for a different event.");
16948
+ setStep("error");
16949
+ return;
16950
+ }
16951
+ if (matchedEvent) {
16952
+ setSelectedEvent(matchedEvent);
16953
+ }
16954
+ setSelectedAttendanceMode(claim.subject.attendanceMode);
16955
+ dispatchFlow({ type: "set-tickets-count", ticketsCount: 1 });
16956
+ setFormData((prev) => ({
16957
+ ...prev,
16958
+ email: claim.prefill.email,
16959
+ name: claim.prefill.name,
16960
+ phone: claim.prefill.phone ?? "",
16961
+ notes: claim.prefill.notes ?? ""
16962
+ }));
16963
+ setGuests(
16964
+ claim.prefill.guests.map((guest) => ({
16965
+ name: guest.name,
16966
+ email: guest.email ?? "",
16967
+ phone: guest.phone ?? ""
16968
+ }))
16969
+ );
16970
+ }, [waitlistClaim.claim, scopedEvents, options.occurrenceContext?.id, setStep]);
16971
+ useEffect11(() => {
16972
+ if (waitlistClaim.requiresPortalLogin) return;
16973
+ if (!waitlistClaim.error) return;
16974
+ setErrorMessage(waitlistClaim.error);
16975
+ setStep("error");
16976
+ }, [waitlistClaim.error, waitlistClaim.requiresPortalLogin, setStep]);
16977
+ useEffect11(() => {
16978
+ if (!waitlistClaim.requiresPortalLogin) return;
16979
+ if (portalAuthState !== "unauthenticated") return;
16980
+ setShowMagicLinkModal(true);
16981
+ }, [portalAuthState, waitlistClaim.requiresPortalLogin]);
16982
+ useEffect11(() => {
16983
+ if (portalAuthState === "authenticated" || !waitlistClaim.requiresPortalLogin) {
16984
+ setShowMagicLinkModal(false);
16985
+ }
16986
+ }, [portalAuthState, waitlistClaim.requiresPortalLogin]);
16987
+ useEffect11(() => {
16988
+ dispatchFlow({ type: "set-authenticated", isAuthenticated: portalAuthState === "authenticated" });
16989
+ }, [portalAuthState]);
16990
+ useEffect11(() => {
16991
+ const event = selectedEvent ?? preSelectedEvent;
16992
+ if (!event) {
16993
+ if (selectedAttendanceMode !== null) {
16994
+ setSelectedAttendanceMode(null);
16995
+ }
16996
+ return;
16997
+ }
16998
+ const deliveryMode = event.deliveryMode ?? "in_person";
16999
+ if (deliveryMode === "online") {
17000
+ if (selectedAttendanceMode !== "online") {
17001
+ setSelectedAttendanceMode("online");
17002
+ }
17003
+ return;
17004
+ }
17005
+ if (deliveryMode === "in_person") {
17006
+ if (selectedAttendanceMode !== "in_person") {
17007
+ setSelectedAttendanceMode("in_person");
17008
+ }
17009
+ return;
17010
+ }
17011
+ if (selectedAttendanceMode && (event.attendanceModes ?? []).some((mode) => mode.mode === selectedAttendanceMode)) {
17012
+ return;
17013
+ }
17014
+ setSelectedAttendanceMode(null);
17015
+ }, [preSelectedEvent, selectedAttendanceMode, selectedEvent]);
17016
+ useEffect11(() => {
17017
+ dispatchFlow({ type: "eligibility-updated", eligibility });
17018
+ }, [eligibility]);
17019
+ const verification = useEventRegistrationStripeReturn({
17020
+ api,
17021
+ events: registrationEvents,
17022
+ occurrenceId,
17023
+ step,
17024
+ pendingAttendeeId,
17025
+ setFormData,
17026
+ setTicketsCount,
17027
+ setSelectedEvent,
17028
+ setSelectedAttendanceMode,
17029
+ setSelectedTicketTypeId,
17030
+ setPaymentSelection: (selection) => dispatchFlow({ type: "set-manual-payment-selection", selection }),
17031
+ setPendingAttendeeId,
17032
+ setStep,
17033
+ setRegistrationResult: (result) => setRegistrationResult(result),
17034
+ setErrorMessage
17035
+ });
17036
+ const requireGuestDetails = useMemo6(() => {
17037
+ const event = selectedEvent ?? preSelectedEvent;
17038
+ return event?.requireGuestDetails === true;
17039
+ }, [selectedEvent, preSelectedEvent]);
17040
+ const visibleTicketTypes = useMemo6(
17041
+ () => getVisibleTicketTypes({
17042
+ event: selectedEvent ?? preSelectedEvent,
17043
+ eligibility,
17044
+ selectedAttendanceMode
17045
+ }),
17046
+ [selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility]
17047
+ );
17048
+ const selectedTicketType = useMemo6(
17049
+ () => findSelectedTicketType({
17050
+ event: selectedEvent ?? preSelectedEvent,
17051
+ eligibility,
17052
+ selectedTicketTypeId,
17053
+ selectedAttendanceMode
17054
+ }),
17055
+ [selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility, selectedTicketTypeId]
17056
+ );
17057
+ const ticketTypeSelectionRequired = useMemo6(() => {
17058
+ const event = selectedEvent ?? preSelectedEvent;
17059
+ if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
17060
+ return false;
17061
+ }
17062
+ if ((event.deliveryMode ?? "in_person") === "hybrid" && !selectedAttendanceMode) {
17063
+ return false;
17064
+ }
17065
+ const selectedModeAvailability = selectedAttendanceMode ? (event.attendanceModes ?? []).find((mode) => mode.mode === selectedAttendanceMode) ?? null : null;
17066
+ const canJoinWaitlist = (selectedModeAvailability?.availableSpots ?? event.availableSpots) === 0 && (selectedModeAvailability?.waitlistEnabled ?? event.waitlistEnabled) === true;
17067
+ return !canJoinWaitlist;
17068
+ }, [selectedAttendanceMode, selectedEvent, preSelectedEvent]);
17069
+ const hasValidSelectedTicketType = !ticketTypeSelectionRequired || Boolean(
17070
+ selectedTicketType && selectedTicketType.availability.kind === "available"
17071
+ );
17072
+ useEffect11(() => {
17073
+ const event = selectedEvent ?? preSelectedEvent;
17074
+ if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
17075
+ if (selectedTicketTypeId !== null) {
17076
+ setSelectedTicketTypeId(null);
17077
+ }
17078
+ return;
17079
+ }
17080
+ const implicitTicketType = getImplicitSingleAvailableTicketType(visibleTicketTypes);
17081
+ if (implicitTicketType && selectedTicketTypeId !== implicitTicketType.id) {
17082
+ setSelectedTicketTypeId(implicitTicketType.id);
17083
+ return;
17084
+ }
17085
+ if (selectedTicketTypeId && !visibleTicketTypes.some((ticketType) => ticketType.id === selectedTicketTypeId)) {
17086
+ setSelectedTicketTypeId(null);
17087
+ }
17088
+ }, [selectedEvent, preSelectedEvent, selectedTicketTypeId, visibleTicketTypes]);
17089
+ useEffect11(() => {
17090
+ if (!requireGuestDetails) {
17091
+ if (guests.length > 0) setGuests([]);
17092
+ return;
17093
+ }
17094
+ const guestCount = ticketsCount - 1;
17095
+ if (guestCount <= 0) {
17096
+ if (guests.length > 0) setGuests([]);
17097
+ return;
17098
+ }
17099
+ if (guests.length !== guestCount) {
17100
+ const newGuests = [];
17101
+ for (let i = 0; i < guestCount; i++) {
17102
+ newGuests.push(guests[i] ?? { name: "", email: "", phone: "" });
17103
+ }
17104
+ setGuests(newGuests);
17105
+ }
17106
+ }, [ticketsCount, requireGuestDetails, guests]);
17107
+ const validateForm = () => {
17108
+ const newErrors = validateFormData2(formData);
17109
+ setErrors(newErrors);
17110
+ const newGuestErrors = {};
17111
+ if (requireGuestDetails && guests.length > 0) {
17112
+ for (const [index, guest] of guests.entries()) {
17113
+ if (!guest.name.trim()) {
17114
+ newGuestErrors[index] = { name: "Name is required" };
17115
+ }
17116
+ }
17117
+ }
17118
+ setGuestErrors(newGuestErrors);
17119
+ return Object.keys(newErrors).length === 0 && Object.keys(newGuestErrors).length === 0;
17120
+ };
17121
+ const handleGuestShakeEnd = () => {
17122
+ setGuestSectionShake(false);
17123
+ };
17124
+ const eventRequiresPayment = useMemo6(
17125
+ () => resolveEventRequiresPayment({
17126
+ eligibility,
17127
+ selectedTicketType,
17128
+ event: selectedEvent ?? preSelectedEvent
17129
+ }),
17130
+ [eligibility, selectedTicketType, selectedEvent, preSelectedEvent]
17131
+ );
17132
+ const handleDetailsComplete = async () => {
17133
+ if (ticketTypeSelectionRequired && !hasValidSelectedTicketType) {
17134
+ const message = "Select a ticket type to continue.";
17135
+ setErrorMessage(message);
17136
+ setStep("error");
17137
+ return { ok: false, reason: "blocked", message };
17138
+ }
17139
+ if (!validateForm()) {
17140
+ setGuestSectionShake(true);
17141
+ return {
17142
+ ok: false,
17143
+ reason: "validation-failed",
17144
+ message: "Check the highlighted fields and try again."
17145
+ };
17146
+ }
17147
+ if (waitlistClaim.claim === null && eligibility?.isFull && !eligibility.canJoinWaitlist) {
17148
+ const message = "This event is sold out.";
17149
+ setErrorMessage(message);
17150
+ setStep("error");
17151
+ return { ok: false, reason: "blocked", message };
17152
+ }
17153
+ const shouldCollectPayment = !eligibility?.canJoinWaitlist && requiresPaymentStep({ eventRequiresPayment, paymentSelection });
17154
+ if (shouldCollectPayment) {
17155
+ setStep("select-payment");
17156
+ return { ok: true, outcome: "payment-step" };
17157
+ }
17158
+ const submitPlan = resolveEventRegistrationSubmitPlan({
17159
+ paymentSelection,
17160
+ eventRequiresPayment,
17161
+ canJoinWaitlist: eligibility?.canJoinWaitlist
17162
+ });
17163
+ if (!submitPlan.ok) {
17164
+ setErrorMessage(submitPlan.message);
17165
+ setStep("error");
17166
+ return { ok: false, reason: "blocked", message: submitPlan.message };
17167
+ }
17168
+ const submitResult = await handleSubmit(
17169
+ submitPlan.args.method,
17170
+ submitPlan.args.passId,
17171
+ submitPlan.args.membershipId,
17172
+ submitPlan.args.selection
17173
+ );
17174
+ if (!submitResult.ok) {
17175
+ return {
17176
+ ok: false,
17177
+ reason: submitResult.reason === "submission-failed" ? "submission-failed" : "blocked",
17178
+ message: submitResult.message
17179
+ };
17180
+ }
17181
+ return { ok: true, outcome: "submitted" };
17182
+ };
17183
+ const handlePaymentSelect = async () => {
17184
+ const submitPlan = resolveEventRegistrationSubmitPlan({
17185
+ paymentSelection,
17186
+ eventRequiresPayment,
17187
+ canJoinWaitlist: eligibility?.canJoinWaitlist
17188
+ });
17189
+ if (!submitPlan.ok) {
17190
+ setErrorMessage(submitPlan.message);
17191
+ setStep("error");
17192
+ return;
17193
+ }
17194
+ await handleSubmit(
17195
+ submitPlan.args.method,
17196
+ submitPlan.args.passId,
17197
+ submitPlan.args.membershipId,
17198
+ submitPlan.args.selection
17199
+ );
17200
+ };
17201
+ const handleUseCardInsteadOfPass = () => {
17202
+ dispatchFlow({ type: "use-card-instead-of-pass" });
17203
+ };
17204
+ const handleBookForSomeoneElse = () => {
17205
+ if (portalAuthState === "authenticated") {
17206
+ handleLogout();
17207
+ return;
17208
+ }
17209
+ setStep("select-tickets");
17210
+ };
17211
+ const discountContext = useMemo6(
17212
+ () => resolveDiscountContext({
17213
+ paymentSelection,
17214
+ event: selectedEvent ?? preSelectedEvent,
17215
+ eventRequiresPayment,
17216
+ ticketsCount
17217
+ }),
17218
+ [eventRequiresPayment, paymentSelection, selectedEvent, preSelectedEvent, ticketsCount]
17219
+ );
17220
+ const discountSubtotalCents = useMemo6(() => {
17221
+ if (discountContext?.type !== "event") return void 0;
17222
+ const event = selectedEvent ?? preSelectedEvent;
17223
+ const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
17224
+ return Math.max(0, eventPriceCents * ticketsCount);
17225
+ }, [discountContext, selectedTicketType, eligibility, selectedEvent, preSelectedEvent, ticketsCount]);
17226
+ const discountUi = useDiscountCodeUi({ api, discountContext, subtotalCents: discountSubtotalCents });
17227
+ const selectionMethod = paymentSelection.method;
17228
+ const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
17229
+ const handleSubmit = useEventRegistrationSubmit({
17230
+ api,
17231
+ registrationTarget,
17232
+ selectedAttendanceMode,
17233
+ selectedTicketTypeId,
17234
+ ticketsCount,
17235
+ formData,
17236
+ altchaSolution,
17237
+ requireGuestDetails,
17238
+ guests,
17239
+ discountCode: discountUi.discountCode,
17240
+ claimToken: waitlistClaim.token,
17241
+ setPendingAttendeeId: (id) => setPendingAttendeeId(id),
17242
+ setStep,
17243
+ setRegistrationResult: (result) => setRegistrationResult(result),
17244
+ setErrorMessage
17245
+ });
17246
+ const handleEventSelect = (event) => {
17247
+ setSelectedEvent(event);
17248
+ setSelectedAttendanceMode(
17249
+ (event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person"
17250
+ );
17251
+ setSelectedTicketTypeId(null);
17252
+ dispatchFlow({ type: "event-changed", hasPreSelectedContext: true });
17253
+ };
17254
+ const handleRetry = () => {
17255
+ dispatchFlow({ type: "reset", hasPreSelectedContext });
17256
+ setSelectedTicketTypeId(null);
17257
+ setSelectedAttendanceMode(
17258
+ preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
17259
+ );
17260
+ setErrorMessage("");
17261
+ setPendingAttendeeId(null);
17262
+ };
17263
+ const handlePaymentStepStateChange = useCallback6((state) => {
17264
+ setPaymentStepState(state);
17265
+ }, []);
17266
+ const handlePaymentSelectionChange = useCallback6((selection) => {
17267
+ dispatchFlow({ type: "set-manual-payment-selection", selection });
17268
+ }, []);
17269
+ const hasEligibility = eligibility !== null && (eligibility.eligiblePasses.length > 0 || eligibility.eligibleMemberships.length > 0);
17270
+ const hasMembershipEligibility = eligibility !== null && eligibility.eligibleMemberships.length > 0;
17271
+ const isMembershipFastTrack = portalAuthState === "authenticated" && hasMembershipEligibility && ticketsCount === 1 && paymentSelection.method === "membership";
17272
+ return {
17273
+ api,
17274
+ anchorId: options.anchorId,
17275
+ occurrenceContext: options.occurrenceContext,
17276
+ registrationTarget,
17277
+ contentEntry: options.contentEntry,
17278
+ events: options.events,
17279
+ maxTicketsNum: waitlistClaim.claim ? 1 : options.maxTicketsNum,
17280
+ scopedEvents,
17281
+ preSelectedEvent,
17282
+ hasPreSelectedContext,
17283
+ step,
17284
+ setStep,
17285
+ selectedEvent,
17286
+ setSelectedEvent,
17287
+ ticketsCount,
17288
+ setTicketsCount,
17289
+ selectedAttendanceMode,
17290
+ setSelectedAttendanceMode,
17291
+ selectedTicketTypeId,
17292
+ setSelectedTicketTypeId,
17293
+ selectedTicketType,
17294
+ visibleTicketTypes,
17295
+ ticketTypeSelectionRequired,
17296
+ hasValidSelectedTicketType,
17297
+ eventRequiresPayment,
17298
+ formData,
17299
+ setFormData,
17300
+ errors,
17301
+ guests,
17302
+ setGuests,
17303
+ guestErrors,
17304
+ guestSectionShake,
17305
+ handleGuestShakeEnd,
17306
+ registrationResult,
17307
+ errorMessage,
17308
+ altchaSolution,
17309
+ setAltchaSolution,
17310
+ portalAuthState,
17311
+ portalProfile,
17312
+ showMagicLinkModal,
17313
+ setShowMagicLinkModal,
17314
+ handleLogout,
17315
+ paymentStepState,
17316
+ handlePaymentStepStateChange,
17317
+ handlePaymentSelectionChange,
17318
+ paymentSelection,
17319
+ isMembershipFastTrack,
17320
+ waitlistClaim,
17321
+ eligibility,
17322
+ eligibilityLoading,
17323
+ eligibilityError,
17324
+ existingRegistration: existingRegistrationResult.registration,
17325
+ existingRegistrationLoading: existingRegistrationResult.isLoading,
17326
+ existingRegistrationState: existingRegistrationResult.state,
17327
+ hasEligibility,
17328
+ hasMembershipEligibility,
17329
+ requireGuestDetails,
17330
+ discountCode: discountUi.discountCode,
17331
+ setDiscountCode: discountUi.setDiscountCode,
17332
+ discountUiOpen: discountUi.discountUiOpen,
17333
+ setDiscountUiOpen: discountUi.setDiscountUiOpen,
17334
+ discountsAvailable: discountUi.discountsAvailable,
17335
+ manualCodeEntryAllowed: discountUi.manualCodeEntryAllowed,
17336
+ autoAppliedDiscount: discountUi.autoAppliedDiscount,
17337
+ discountsAvailableLoading: discountUi.discountsAvailableLoading,
17338
+ discountContext,
17339
+ shouldShowDiscountToggle,
17340
+ verification,
17341
+ handleDetailsComplete,
17342
+ handlePaymentSelect,
17343
+ handleUseCardInsteadOfPass,
17344
+ handleBookForSomeoneElse,
17345
+ handleSubmit,
17346
+ handleEventSelect,
17347
+ handleRetry
17348
+ };
17349
+ }
17350
+
17351
+ // ../theme-core/src/header/navDropdownSizing.ts
17352
+ var NAV_DROPDOWN_MIN_WIDTH_REM = 12;
17353
+ var NAV_DROPDOWN_MAX_WIDTH_REM = 22;
17354
+ var NAV_DROPDOWN_VIEWPORT_GUTTER_REM = 1;
17355
+ var NAV_DROPDOWN_SHIFT_PROPERTY = "--nav-dropdown-shift-x";
17356
+ var NAV_DROPDOWN_MAX_WIDTH_CSS = `min(${NAV_DROPDOWN_MAX_WIDTH_REM}rem, calc(100vw - ${NAV_DROPDOWN_VIEWPORT_GUTTER_REM * 2}rem))`;
17357
+ var NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
17358
+ `min-width: ${NAV_DROPDOWN_MIN_WIDTH_REM}rem;`,
17359
+ `width: max-content;`,
17360
+ `max-width: ${NAV_DROPDOWN_MAX_WIDTH_CSS};`,
17361
+ `transform: translateX(var(${NAV_DROPDOWN_SHIFT_PROPERTY}, 0px));`
17362
+ ];
17363
+
17364
+ // ../theme-core/src/ClientThemeScope.tsx
17365
+ import { useMemo as useMemo7 } from "react";
17366
+
17367
+ // ../theme-core/src/navigation/presets.ts
17368
+ var NAV_LINK_PRESETS = {
17369
+ /**
17370
+ * Minimal - subtle color change on hover
17371
+ */
17372
+ minimal: {
17373
+ name: "Minimal",
17374
+ typography: "body",
17375
+ fontWeight: "medium",
17376
+ textTransform: "none",
17377
+ italic: false,
17378
+ colorToken: "text",
17379
+ hoverColorToken: "primary",
17380
+ padding: "none",
17381
+ borderRadius: "none",
17382
+ effects: {
17383
+ hover: [
17384
+ { effectId: "text-color-change", options: { hoverColorToken: "primary" } }
17385
+ ]
17386
+ }
17387
+ },
17388
+ /**
17389
+ * Underline - static underline appears on hover
17390
+ */
17391
+ underline: {
17392
+ name: "Underline",
17393
+ typography: "body",
17394
+ fontWeight: "medium",
17395
+ textTransform: "none",
17396
+ italic: false,
17397
+ colorToken: "text",
17398
+ padding: "none",
17399
+ borderRadius: "none",
17400
+ effects: {
17401
+ hover: [{ effectId: "nav-underline", options: { style: "static" } }]
17402
+ }
17403
+ },
17404
+ /**
17405
+ * Underline Grow - animated underline grows from center on hover
17406
+ */
17407
+ "underline-grow": {
17408
+ name: "Underline Grow",
17409
+ typography: "body",
17410
+ fontWeight: "medium",
17411
+ textTransform: "none",
17412
+ italic: false,
17413
+ colorToken: "text",
17414
+ padding: "none",
17415
+ borderRadius: "none",
17416
+ effects: {
17417
+ hover: [{ effectId: "nav-underline", options: { style: "grow" } }]
17418
+ }
17419
+ },
17420
+ /**
17421
+ * Capsule - pill-shaped background on hover
17422
+ */
17423
+ capsule: {
17424
+ name: "Capsule",
17425
+ typography: "body",
17426
+ fontWeight: "medium",
17427
+ textTransform: "none",
17428
+ italic: false,
17429
+ colorToken: "text",
17430
+ padding: "compact",
17431
+ borderRadius: "full",
17432
+ effects: {
17433
+ hover: [
17434
+ {
17435
+ effectId: "background-on-hover-alpha",
17436
+ options: { colorToken: "primary", opacity: 10 }
17437
+ }
17438
+ ],
17439
+ active: [
17440
+ {
17441
+ effectId: "background-on-hover-alpha",
14435
17442
  options: { colorToken: "primary", opacity: 15 }
14436
17443
  }
14437
17444
  ]
@@ -14533,6 +17540,11 @@ ${root} {
14533
17540
  --er-event-card-bg: rgb(var(--tb-surface));
14534
17541
  --er-event-card-border-width: var(--rb-border-width, 1px);
14535
17542
  --er-event-card-hover-opacity: 1;
17543
+ --er-control-bg: rgb(var(--tb-background, var(--tb-surface)));
17544
+ --er-control-text: rgb(var(--tb-foreground, var(--tb-text)));
17545
+ --er-radius: var(--rb-block-radius);
17546
+ --er-surface-muted: rgba(var(--tb-muted, 241 245 249), 0.42);
17547
+ --er-shell-line: rgba(var(--tb-mutedText, 100 116 139), 0.22);
14536
17548
 
14537
17549
  /* Step indicator */
14538
17550
  --er-step-active: rgb(var(--tb-primary));
@@ -15080,15 +18092,286 @@ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
15080
18092
  // ../theme-core/src/ClientThemeScope.tsx
15081
18093
  import { jsx as jsx13 } from "react/jsx-runtime";
15082
18094
 
18095
+ // ../blocks/src/system/runtime/hooks/useHeadlessEventRegistrationFlow.ts
18096
+ import React4, { useCallback as useCallback7, useMemo as useMemo8 } from "react";
18097
+ function HeadlessEventRegistrationProvider({
18098
+ config,
18099
+ children
18100
+ }) {
18101
+ return React4.createElement(BlockApiProvider, { config, children });
18102
+ }
18103
+ function useHeadlessEventRegistrationFlow(options) {
18104
+ return useEventRegistrationController(options).flow;
18105
+ }
18106
+ function useEventRegistrationController(options) {
18107
+ const { wizard } = useEventRegistrationWizardController(options);
18108
+ const steps = useMemo8(
18109
+ () => deriveEventRegistrationSteps({
18110
+ step: wizard.step,
18111
+ hasPreSelectedContext: wizard.hasPreSelectedContext,
18112
+ eventRequiresPayment: wizard.eventRequiresPayment,
18113
+ paymentSelection: wizard.paymentSelection
18114
+ }),
18115
+ [
18116
+ wizard.eventRequiresPayment,
18117
+ wizard.hasPreSelectedContext,
18118
+ wizard.paymentSelection,
18119
+ wizard.step
18120
+ ]
18121
+ );
18122
+ const currentStep = steps.find((step) => step.state === "active") ?? null;
18123
+ const submit = useCallback7(
18124
+ async (submitOptions) => {
18125
+ const plan = resolveEventRegistrationSubmitPlan({
18126
+ paymentSelection: wizard.paymentSelection,
18127
+ eventRequiresPayment: wizard.eventRequiresPayment,
18128
+ canJoinWaitlist: wizard.eligibility?.canJoinWaitlist
18129
+ });
18130
+ if (!plan.ok) {
18131
+ return {
18132
+ ok: false,
18133
+ reason: "blocked",
18134
+ message: plan.message
18135
+ };
18136
+ }
18137
+ return wizard.handleSubmit(
18138
+ plan.args.method,
18139
+ plan.args.passId,
18140
+ plan.args.membershipId,
18141
+ plan.args.selection,
18142
+ submitOptions
18143
+ );
18144
+ },
18145
+ [wizard]
18146
+ );
18147
+ const next = useCallback7(async () => {
18148
+ switch (wizard.step) {
18149
+ case "select-event":
18150
+ if (!wizard.selectedEvent) {
18151
+ return {
18152
+ ok: false,
18153
+ reason: "blocked",
18154
+ message: "Select an event to continue."
18155
+ };
18156
+ }
18157
+ wizard.setStep("select-tickets");
18158
+ return { ok: true };
18159
+ case "select-tickets":
18160
+ if (wizard.ticketTypeSelectionRequired && !wizard.hasValidSelectedTicketType) {
18161
+ return {
18162
+ ok: false,
18163
+ reason: "blocked",
18164
+ message: "Select a ticket type to continue."
18165
+ };
18166
+ }
18167
+ wizard.setStep("enter-details");
18168
+ return { ok: true };
18169
+ case "enter-details": {
18170
+ const result = await wizard.handleDetailsComplete();
18171
+ return result.ok ? { ok: true } : result;
18172
+ }
18173
+ case "select-payment": {
18174
+ const result = await submit({ redirect: "manual" });
18175
+ return result.ok ? { ok: true } : {
18176
+ ok: false,
18177
+ reason: result.reason === "submission-failed" ? "submission-failed" : "blocked",
18178
+ message: result.message
18179
+ };
18180
+ }
18181
+ case "error":
18182
+ case "success":
18183
+ case "submitting":
18184
+ case "redirecting":
18185
+ case "verifying-payment":
18186
+ case "verifying-timeout":
18187
+ case "payment-failed":
18188
+ return {
18189
+ ok: false,
18190
+ reason: "blocked",
18191
+ message: "This registration step cannot continue."
18192
+ };
18193
+ }
18194
+ }, [submit, wizard]);
18195
+ const back = useCallback7(() => {
18196
+ switch (wizard.step) {
18197
+ case "enter-details":
18198
+ wizard.setStep("select-tickets");
18199
+ return;
18200
+ case "select-payment":
18201
+ wizard.setStep("enter-details");
18202
+ return;
18203
+ case "select-tickets":
18204
+ if (!wizard.hasPreSelectedContext) wizard.setStep("select-event");
18205
+ return;
18206
+ case "select-event":
18207
+ case "error":
18208
+ case "success":
18209
+ case "submitting":
18210
+ case "redirecting":
18211
+ case "verifying-payment":
18212
+ case "verifying-timeout":
18213
+ case "payment-failed":
18214
+ return;
18215
+ }
18216
+ }, [wizard]);
18217
+ const updateAttendee = useCallback7(
18218
+ (values) => {
18219
+ wizard.setFormData(values);
18220
+ },
18221
+ [wizard]
18222
+ );
18223
+ const updateGuests = useCallback7(
18224
+ (guests) => {
18225
+ wizard.setGuests(guests);
18226
+ },
18227
+ [wizard]
18228
+ );
18229
+ const selectPayment = useCallback7(
18230
+ (selection) => {
18231
+ wizard.handlePaymentSelectionChange(toInternalPaymentSelection(selection));
18232
+ },
18233
+ [wizard]
18234
+ );
18235
+ const showSpamProtection = options.spamProtectionEnabled ?? isSpamProtectionEnabled();
18236
+ const spamProtection = showSpamProtection ? {
18237
+ enabled: true,
18238
+ provider: "altcha",
18239
+ challenge: { url: getChallengeUrl(), auto: "onfocus" },
18240
+ solution: wizard.altchaSolution
18241
+ } : { enabled: false };
18242
+ const payment = resolvePaymentModel(wizard);
18243
+ const flow = {
18244
+ status: resolveHeadlessEventRegistrationStatus(wizard),
18245
+ view: resolveHeadlessEventRegistrationView(wizard),
18246
+ steps,
18247
+ currentStep,
18248
+ events: {
18249
+ items: wizard.events,
18250
+ scoped: wizard.scopedEvents,
18251
+ selected: wizard.selectedEvent,
18252
+ preSelected: wizard.preSelectedEvent,
18253
+ hasPreSelectedContext: wizard.hasPreSelectedContext,
18254
+ target: wizard.registrationTarget,
18255
+ occurrenceContext: wizard.occurrenceContext,
18256
+ contentEntry: wizard.contentEntry
18257
+ },
18258
+ tickets: {
18259
+ count: wizard.ticketsCount,
18260
+ max: wizard.maxTicketsNum,
18261
+ selectedTicketTypeId: wizard.selectedTicketTypeId,
18262
+ selectedTicketType: wizard.selectedTicketType,
18263
+ visibleTicketTypes: wizard.visibleTicketTypes,
18264
+ selectionRequired: wizard.ticketTypeSelectionRequired,
18265
+ hasValidSelection: wizard.hasValidSelectedTicketType,
18266
+ eventRequiresPayment: wizard.eventRequiresPayment,
18267
+ selectedAttendanceMode: wizard.selectedAttendanceMode
18268
+ },
18269
+ attendee: {
18270
+ values: wizard.formData,
18271
+ errors: wizard.errors
18272
+ },
18273
+ guests: {
18274
+ required: wizard.requireGuestDetails,
18275
+ items: wizard.guests,
18276
+ errors: wizard.guestErrors,
18277
+ shake: wizard.guestSectionShake
18278
+ },
18279
+ payment,
18280
+ discount: {
18281
+ code: wizard.discountCode,
18282
+ isOpen: wizard.discountUiOpen,
18283
+ available: wizard.discountsAvailable,
18284
+ manualCodeEntryAllowed: wizard.manualCodeEntryAllowed,
18285
+ loading: wizard.discountsAvailableLoading,
18286
+ autoAppliedDiscount: wizard.autoAppliedDiscount
18287
+ },
18288
+ portalAuth: {
18289
+ state: wizard.portalAuthState,
18290
+ profile: wizard.portalProfile,
18291
+ isAuthenticated: wizard.portalAuthState === "authenticated",
18292
+ showMagicLinkModal: wizard.showMagicLinkModal
18293
+ },
18294
+ existingRegistration: {
18295
+ state: resolveExistingRegistrationState(wizard),
18296
+ registration: wizard.existingRegistration
18297
+ },
18298
+ waitlistClaim: wizard.waitlistClaim,
18299
+ spamProtection,
18300
+ terminal: {
18301
+ result: wizard.registrationResult,
18302
+ errorMessage: wizard.errorMessage,
18303
+ verification: wizard.verification
18304
+ },
18305
+ actions: {
18306
+ selectEvent: wizard.handleEventSelect,
18307
+ selectAttendanceMode: wizard.setSelectedAttendanceMode,
18308
+ selectTicketType: wizard.setSelectedTicketTypeId,
18309
+ setTicketsCount: wizard.setTicketsCount,
18310
+ updateAttendee,
18311
+ updateGuests,
18312
+ selectPayment,
18313
+ setDiscountCode: wizard.setDiscountCode,
18314
+ setDiscountOpen: wizard.setDiscountUiOpen,
18315
+ setAltchaSolution: wizard.setAltchaSolution,
18316
+ requestLogin: () => wizard.setShowMagicLinkModal(true),
18317
+ logout: wizard.handleLogout,
18318
+ next,
18319
+ back,
18320
+ submit,
18321
+ retry: wizard.handleRetry
18322
+ }
18323
+ };
18324
+ return { flow, wizard };
18325
+ }
18326
+ function useEventRegistrationWizardController(options) {
18327
+ const maxTicketsNum = normalizeEventRegistrationMaxTickets(options.maxTickets);
18328
+ const wizard = useEventRegistrationWizard({
18329
+ anchorId: options.anchorId ?? "event-registration",
18330
+ occurrenceContext: options.occurrenceContext ?? null,
18331
+ contentEntry: options.contentEntry ?? null,
18332
+ events: [...options.events ?? []],
18333
+ maxTicketsNum
18334
+ });
18335
+ return { wizard };
18336
+ }
18337
+ function resolveExistingRegistrationState(wizard) {
18338
+ switch (wizard.existingRegistrationState.tag) {
18339
+ case "idle":
18340
+ return { tag: "idle", value: wizard.existingRegistration };
18341
+ case "loading":
18342
+ return { tag: "loading", value: wizard.existingRegistration };
18343
+ case "resolved":
18344
+ return { tag: "loaded", value: wizard.existingRegistration };
18345
+ }
18346
+ }
18347
+ function resolvePaymentModel(wizard) {
18348
+ const selection = toHeadlessPaymentSelection(wizard.paymentSelection);
18349
+ if (wizard.step !== "select-payment") {
18350
+ return {
18351
+ kind: "hidden",
18352
+ selection,
18353
+ stepState: wizard.paymentStepState
18354
+ };
18355
+ }
18356
+ const status = wizard.paymentStepState.status;
18357
+ return {
18358
+ kind: status,
18359
+ selection,
18360
+ stepState: wizard.paymentStepState,
18361
+ eligibility: wizard.eligibility,
18362
+ eligibilityError: wizard.eligibilityError
18363
+ };
18364
+ }
18365
+
15083
18366
  // ../blocks/src/system/runtime/hooks/useBookingFormConfig.ts
15084
- import { useState as useState6, useEffect as useEffect8 } from "react";
18367
+ import { useState as useState9, useEffect as useEffect12 } from "react";
15085
18368
  function useBookingFormConfig(siteId, formId) {
15086
18369
  const api = useBlockApi();
15087
- const [formConfig, setFormConfig] = useState6(null);
15088
- const [services, setServices] = useState6([]);
15089
- const [isLoading, setIsLoading] = useState6(true);
15090
- const [error, setError] = useState6(null);
15091
- useEffect8(() => {
18370
+ const [formConfig, setFormConfig] = useState9(null);
18371
+ const [services, setServices] = useState9([]);
18372
+ const [isLoading, setIsLoading] = useState9(true);
18373
+ const [error, setError] = useState9(null);
18374
+ useEffect12(() => {
15092
18375
  let mounted = true;
15093
18376
  async function loadFormAndServices() {
15094
18377
  try {
@@ -15130,8 +18413,8 @@ function useBookingFormConfig(siteId, formId) {
15130
18413
  } catch {
15131
18414
  }
15132
18415
  }
15133
- } catch (err) {
15134
- console.error("Failed to load form:", err);
18416
+ } catch (err3) {
18417
+ console.error("Failed to load form:", err3);
15135
18418
  if (mounted) {
15136
18419
  setError("Failed to load booking form. Please try again later.");
15137
18420
  }
@@ -15151,16 +18434,19 @@ function useBookingFormConfig(siteId, formId) {
15151
18434
 
15152
18435
  // src/bookings/index.ts
15153
18436
  var BookingFormClient2 = (props) => {
15154
- return React4.createElement(BookingFormClient, props);
18437
+ return React5.createElement(BookingFormClient, props);
15155
18438
  };
15156
18439
  function useBookingFormConfig2(siteId, formId) {
15157
18440
  return useBookingFormConfig(siteId, formId);
15158
18441
  }
15159
18442
  var HeadlessBookingProvider2 = (props) => {
15160
- return React4.createElement(HeadlessBookingProvider, props);
18443
+ return React5.createElement(HeadlessBookingProvider, props);
18444
+ };
18445
+ var HeadlessEventRegistrationProvider2 = (props) => {
18446
+ return React5.createElement(HeadlessEventRegistrationProvider, props);
15161
18447
  };
15162
18448
  var HeadlessBookingPaymentSelectionStep2 = (props) => {
15163
- return React4.createElement(HeadlessBookingPaymentSelectionStep, props);
18449
+ return React5.createElement(HeadlessBookingPaymentSelectionStep, props);
15164
18450
  };
15165
18451
  export {
15166
18452
  BOOKING_FORM_DATA_RESERVED_KEY_VALUES,
@@ -15168,8 +18454,13 @@ export {
15168
18454
  AltchaWidget as HeadlessBookingAltchaWidget,
15169
18455
  HeadlessBookingPaymentSelectionStep2 as HeadlessBookingPaymentSelectionStep,
15170
18456
  HeadlessBookingProvider2 as HeadlessBookingProvider,
18457
+ AltchaWidget as HeadlessEventRegistrationAltchaWidget,
18458
+ HeadlessEventRegistrationProvider2 as HeadlessEventRegistrationProvider,
15171
18459
  createBookingBlockApiConfig,
18460
+ createEventRegistrationBlockApiConfig,
15172
18461
  getAppointmentBookingOverrideInput,
18462
+ getEventRegistrationOverrideInput,
15173
18463
  useBookingFormConfig2 as useBookingFormConfig,
15174
- useHeadlessBookingFlow
18464
+ useHeadlessBookingFlow,
18465
+ useHeadlessEventRegistrationFlow
15175
18466
  };