@riverbankcms/sdk 0.82.0 → 0.84.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/README.md +16 -0
  2. package/dist/{PreviewEditorSidebar-LHGK6RIO.mjs → PreviewEditorSidebar-HML67UDA.mjs} +330 -11
  3. package/dist/{PreviewEditorUI-AXZG2SDC.mjs → PreviewEditorUI-I4BQUU6K.mjs} +3 -3
  4. package/dist/SdkPreviewModeRuntime-MCKMVDTK.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/event-registration.headless.state.d.ts +303 -0
  51. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +20 -1
  52. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +4 -3
  53. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/utils.d.ts +1 -1
  54. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +26 -6
  55. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/pricing.d.ts +14 -0
  56. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +1 -1
  57. package/dist/_dts/content-editor/src/controller/buildBlockPublishedBaselines.d.ts +1 -1
  58. package/dist/_dts/content-editor/src/controller/seedDraftBaselinesFromBlocks.d.ts +1 -1
  59. package/dist/_dts/content-editor/src/controller/useBlocksList.d.ts +1 -1
  60. package/dist/_dts/content-editor/src/controller/useInvalidBlockRecovery.d.ts +1 -1
  61. package/dist/_dts/content-editor/src/primitives/PreviewRichTextEditor.d.ts +2 -1
  62. package/dist/_dts/content-editor/src/primitives/PreviewTextEditor.d.ts +1 -0
  63. package/dist/_dts/content-model/src/entry-slots/index.d.ts +1 -0
  64. package/dist/_dts/content-model/src/entry-slots/types.d.ts +356 -0
  65. package/dist/_dts/content-model/src/index.d.ts +1 -0
  66. package/dist/_dts/content-model/src/templates/defaults.d.ts +7 -0
  67. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +100 -5
  68. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +6 -1
  69. package/dist/_dts/editor-blocks/src/BlockForm.d.ts +1 -1
  70. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockCreation.d.ts +3 -2
  71. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockDuplication.d.ts +3 -2
  72. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockReorder.d.ts +3 -2
  73. package/dist/_dts/editor-blocks/src/block-editor/owner.d.ts +27 -0
  74. package/dist/_dts/editor-blocks/src/index.d.ts +1 -0
  75. package/dist/_dts/media-core/src/assetsInUseSummary.d.ts +8 -0
  76. package/dist/_dts/media-core/src/mediaUsageProjection.d.ts +37 -3
  77. package/dist/_dts/preview-next/src/client/blocks/pageDesignRuntimePreview.d.ts +4 -2
  78. package/dist/_dts/preview-next/src/client/blocks/previewProjection/runtimeContentDecoration.d.ts +2 -2
  79. package/dist/_dts/preview-next/src/client/preview/EntryEditorPanel.d.ts +3 -1
  80. package/dist/_dts/preview-next/src/client/preview/EntrySlotBlockEditorPanel.d.ts +19 -0
  81. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeButton.d.ts +8 -0
  82. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +4 -1
  83. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +1 -1
  84. package/dist/_dts/preview-next/src/client/preview/linkedEntryEditEvents.d.ts +9 -0
  85. package/dist/_dts/preview-next/src/client/preview/previewCustomizeControls.d.ts +9 -8
  86. package/dist/_dts/preview-next/src/client/preview/siteChromeLookRows.d.ts +10 -1
  87. package/dist/_dts/preview-next/src/client/preview/siteChromeQuickControlHistoryState.d.ts +5 -1
  88. package/dist/_dts/sdk/src/bookings/index.d.ts +5 -4
  89. package/dist/_dts/sdk/src/bookings/types.d.ts +2 -2
  90. package/dist/_dts/sdk/src/cli/content/reader.d.ts +9 -8
  91. package/dist/_dts/sdk/src/cli/content/writer.d.ts +6 -1
  92. package/dist/_dts/sdk/src/cli/helpers.d.ts +10 -5
  93. package/dist/_dts/sdk/src/cli/merge-remote/entryLocal.d.ts +2 -2
  94. package/dist/_dts/sdk/src/cli/merge-remote/entryMerge.d.ts +2 -1
  95. package/dist/_dts/sdk/src/cli/merge-remote/entrySnapshots.d.ts +2 -2
  96. package/dist/_dts/sdk/src/client/management/index.d.ts +1 -1
  97. package/dist/_dts/sdk/src/client/management/types.d.ts +40 -10
  98. package/dist/_dts/sdk/src/config/field-definitions.d.ts +13 -7
  99. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +26 -3
  100. package/dist/_dts/sdk/src/public-api/contracts.d.ts +13 -0
  101. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +1 -0
  102. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +6 -1
  103. package/dist/_dts/sdk/src/rendering/overrides.d.ts +6 -1
  104. package/dist/_dts/sdk/src/types/block-kinds.d.ts +1 -1
  105. package/dist/_dts/sdk/src/version.d.ts +1 -1
  106. package/dist/_dts/site-commands/src/commands.d.ts +15 -0
  107. package/dist/_dts/theme-core/src/accordions/types.d.ts +1 -1
  108. package/dist/_dts/theme-core/src/buttons/personalities/index.d.ts +11 -0
  109. package/dist/_dts/theme-core/src/buttons/personalities/ornate-ritual.d.ts +16 -0
  110. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +1 -1
  111. package/dist/_dts/theme-core/src/buttons/types.d.ts +3 -3
  112. package/dist/_dts/theme-core/src/cards/types.d.ts +15 -15
  113. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  114. package/dist/_dts/theme-core/src/inputs/types.d.ts +1 -1
  115. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +33 -33
  116. package/dist/_dts/theme-core/src/palette/variants/index.d.ts +15 -0
  117. package/dist/_dts/theme-core/src/palette/variants/warm-dark.d.ts +16 -0
  118. package/dist/_dts/theme-core/src/schema.d.ts +30 -25
  119. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  120. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +141 -1
  121. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -0
  122. package/dist/_dts/theme-core/src/site-styles/footerLooks.d.ts +110 -5
  123. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +4 -2
  124. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +1 -1
  125. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +5 -1
  126. package/dist/_dts/theme-core/src/site-styles/tokenRecipes.d.ts +1 -1
  127. package/dist/_dts/theme-core/src/site-styles/types.d.ts +1 -1
  128. package/dist/_dts/theme-core/src/site-styles/typographyPresets.d.ts +16 -1
  129. package/dist/_dts/theme-core/src/siteChromePlanning.d.ts +1 -0
  130. package/dist/_dts/theme-core/src/utils/colorStyles.d.ts +6 -6
  131. package/dist/{chunk-2BUMISSH.mjs → chunk-3LXFQS7T.mjs} +1 -1
  132. package/dist/{chunk-G35HOQEN.mjs → chunk-5E33VO6J.mjs} +132 -46
  133. package/dist/{chunk-HKB6XVIP.mjs → chunk-6X2OVO3S.mjs} +2 -2
  134. package/dist/{chunk-6FWNF3DJ.mjs → chunk-HFMGVJCE.mjs} +158 -20
  135. package/dist/{chunk-FIREV57T.mjs → chunk-LBBPD2IW.mjs} +40 -0
  136. package/dist/{chunk-XQR6THQJ.mjs → chunk-MSHZO4SL.mjs} +3193 -1216
  137. package/dist/cli/index.mjs +2635 -575
  138. package/dist/cli/init-docs/content/getting-started.md +2 -0
  139. package/dist/cli/init-docs/content/workflow-templates.md +93 -2
  140. package/dist/client/{accordion-G34C45TW.mjs → accordion-ESY65T56.mjs} +2 -2
  141. package/dist/client/{bookingForm-BLBVKSAQ.mjs → bookingForm-JRFNZUHD.mjs} +5 -5
  142. package/dist/client/bookings.mjs +3539 -269
  143. package/dist/client/{carousel-7ZVTBRMD.mjs → carousel-CPR5VWIP.mjs} +3 -3
  144. package/dist/client/{cart-Q6S6LZUO.mjs → cart-ZUX5BA7O.mjs} +6 -6
  145. package/dist/client/{checkout-5QJLDE4I.mjs → checkout-RULGBADZ.mjs} +6 -6
  146. package/dist/client/{chunk-CHAB5ACD.mjs → chunk-52I7BGEK.mjs} +2 -2
  147. package/dist/client/{chunk-CSZGLBYR.mjs → chunk-5ZEAZ33K.mjs} +1 -1
  148. package/dist/client/{chunk-ZF4XEWDM.mjs → chunk-BT6AEIKN.mjs} +1 -1
  149. package/dist/client/{chunk-RJHTCTCZ.mjs → chunk-HXPWP5EN.mjs} +268 -15
  150. package/dist/client/{chunk-5PQH4Y75.mjs → chunk-JWEYB4V6.mjs} +2 -2
  151. package/dist/client/{chunk-EQKYMX4N.mjs → chunk-RDJFCPY3.mjs} +158 -51
  152. package/dist/client/{chunk-SBBSMFFG.mjs → chunk-SYIJ5JO2.mjs} +1 -1
  153. package/dist/client/{chunk-WJFHDTYF.mjs → chunk-URQCZD5W.mjs} +5 -5
  154. package/dist/client/{chunk-U2EW7RSR.mjs → chunk-Z5OBQ5I4.mjs} +1 -1
  155. package/dist/client/{chunk-S3MKFGOG.mjs → chunk-ZE5G642V.mjs} +1 -1
  156. package/dist/client/client.mjs +2391 -673
  157. package/dist/client/{courseRegistration-VUG2JJDB.mjs → courseRegistration-QTUDC35T.mjs} +5 -5
  158. package/dist/client/{eventCalendar-E7D2LD4N.mjs → eventCalendar-Q7NS4XLD.mjs} +7 -7
  159. package/dist/client/{eventCombined-FUZ2Z3CS.mjs → eventCombined-QAO7VUO5.mjs} +7 -7
  160. package/dist/client/{eventDetails-QRITJAOW.mjs → eventDetails-WTNNU6Q3.mjs} +7 -7
  161. package/dist/client/{eventListing-INMQMJZ5.mjs → eventListing-5TA2ELDT.mjs} +7 -7
  162. package/dist/client/{eventRegistration-TOOJD4WU.mjs → eventRegistration-M6USZGRF.mjs} +7 -7
  163. package/dist/client/{form-BOWN7ZNQ.mjs → form-DGVGXLMH.mjs} +2 -2
  164. package/dist/client/{headerSection-HFQNZOUU.mjs → headerSection-O2AGMPCU.mjs} +3 -3
  165. package/dist/client/hooks.mjs +1636 -385
  166. package/dist/client/{locationMap-VUZGC7Y5.mjs → locationMap-EJRNRIKJ.mjs} +2 -2
  167. package/dist/client/{newsletterForm-X2XQTPCB.mjs → newsletterForm-7NTC2DTR.mjs} +2 -2
  168. package/dist/client/{productDetail-TA7D2G2B.mjs → productDetail-HH4LP53D.mjs} +6 -6
  169. package/dist/client/{productList-AZOLOZKM.mjs → productList-YVHYM2AF.mjs} +6 -6
  170. package/dist/client/rendering/client.mjs +2303 -1068
  171. package/dist/client/rendering/islands.mjs +19 -19
  172. package/dist/client/rendering.mjs +2587 -796
  173. package/dist/client/{shop-ZDLO7IIG.mjs → shop-UIFX7XRK.mjs} +6 -6
  174. package/dist/preview-next/before-render.mjs +40 -0
  175. package/dist/preview-next/client/runtime.mjs +5 -5
  176. package/dist/preview-next/middleware.mjs +40 -0
  177. package/dist/{sdk-runtime-CTWKNBDQ.mjs → sdk-runtime-ZENAOYMN.mjs} +6 -6
  178. package/dist/server/components.mjs +2028 -457
  179. package/dist/server/config-validation.mjs +1629 -377
  180. package/dist/server/config.mjs +1629 -377
  181. package/dist/server/data.mjs +1636 -385
  182. package/dist/server/index.mjs +42 -1
  183. package/dist/server/next.mjs +2215 -571
  184. package/dist/server/page-converter.mjs +2068 -884
  185. package/dist/server/prebuild.mjs +1 -1
  186. package/dist/server/rendering/server.mjs +2040 -469
  187. package/dist/server/rendering.mjs +2119 -475
  188. package/dist/server/routing.mjs +1711 -419
  189. package/dist/server/server.mjs +1718 -394
  190. package/dist/server/theme-bridge.mjs +1180 -101
  191. package/dist/server/theme.mjs +92 -1
  192. package/dist/styles/index.css +292 -36
  193. package/package.json +1 -1
  194. 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
  })
@@ -10749,8 +11858,8 @@ function AltchaWidget({
10749
11858
  }
10750
11859
  }));
10751
11860
  containerRef.current.appendChild(widget);
10752
- }).catch((err) => {
10753
- console.error("Failed to load ALTCHA widget:", err);
11861
+ }).catch((err3) => {
11862
+ console.error("Failed to load ALTCHA widget:", err3);
10754
11863
  });
10755
11864
  return () => {
10756
11865
  if (widget && containerRef.current) {
@@ -10990,10 +12099,10 @@ function useAvailableDates({
10990
12099
  start: append && prev ? prev.start : data.startDate,
10991
12100
  end: data.endDate
10992
12101
  }));
10993
- } catch (err) {
12102
+ } catch (err3) {
10994
12103
  if (requestId !== requestIdRef.current) return;
10995
12104
  setError(
10996
- err instanceof Error ? err.message : "Failed to load available dates"
12105
+ err3 instanceof Error ? err3.message : "Failed to load available dates"
10997
12106
  );
10998
12107
  } finally {
10999
12108
  if (mode === "refresh" && requestId === requestIdRef.current) {
@@ -11109,10 +12218,10 @@ function useAvailableSlots({
11109
12218
  }))
11110
12219
  );
11111
12220
  setHasLoaded(true);
11112
- } catch (err) {
12221
+ } catch (err3) {
11113
12222
  if (requestId !== requestIdRef.current) return;
11114
12223
  setError(
11115
- err instanceof Error ? err.message : "Failed to load available times"
12224
+ err3 instanceof Error ? err3.message : "Failed to load available times"
11116
12225
  );
11117
12226
  } finally {
11118
12227
  if (mode === "refresh" && requestId === requestIdRef.current) {
@@ -12315,7 +13424,7 @@ function omitRecordKey(record, key) {
12315
13424
  return rest;
12316
13425
  }
12317
13426
  function readAppointmentBookingOverrideData(value) {
12318
- if (!isRecord3(value)) return null;
13427
+ if (!isRecord4(value)) return null;
12319
13428
  const services = normalizeBookingServices(value.services);
12320
13429
  return {
12321
13430
  form: normalizeBookingFormConfig(value.form),
@@ -12328,7 +13437,7 @@ function createOverrideInputError(reason, message, warnInDev = false) {
12328
13437
  }
12329
13438
  return { ok: false, reason, message };
12330
13439
  }
12331
- function isRecord3(value) {
13440
+ function isRecord4(value) {
12332
13441
  return typeof value === "object" && value !== null;
12333
13442
  }
12334
13443
 
@@ -13064,13 +14173,13 @@ function usePolling(config) {
13064
14173
  dispatch({ type: "polling-progressed", result: data });
13065
14174
  isPollingRef.current = false;
13066
14175
  return false;
13067
- } catch (err) {
14176
+ } catch (err3) {
13068
14177
  if (generation !== generationRef.current || !isActiveRef.current) {
13069
14178
  isPollingRef.current = false;
13070
14179
  return true;
13071
14180
  }
13072
- if (err instanceof Error) {
13073
- dispatch({ type: "polling-request-failed", error: err });
14181
+ if (err3 instanceof Error) {
14182
+ dispatch({ type: "polling-request-failed", error: err3 });
13074
14183
  }
13075
14184
  isPollingRef.current = false;
13076
14185
  return false;
@@ -14163,6 +15272,20 @@ function buildCheckoutReturnUrls(paramName, anchorId) {
14163
15272
  return { successUrl, cancelUrl };
14164
15273
  }
14165
15274
 
15275
+ // ../blocks/src/system/runtime/shared/utils/portalLogout.ts
15276
+ function logoutPortal(anchorId) {
15277
+ const form = document.createElement("form");
15278
+ form.method = "POST";
15279
+ form.action = "/api/portal/logout";
15280
+ const redirectInput = document.createElement("input");
15281
+ redirectInput.type = "hidden";
15282
+ redirectInput.name = "redirect_to";
15283
+ redirectInput.value = `${window.location.pathname}#${anchorId}`;
15284
+ form.appendChild(redirectInput);
15285
+ document.body.appendChild(form);
15286
+ form.submit();
15287
+ }
15288
+
14166
15289
  // ../blocks/src/system/runtime/shared/utils/scrollToBlock.ts
14167
15290
  function scrollToBlock(anchorId) {
14168
15291
  requestAnimationFrame(() => {
@@ -14170,6 +15293,17 @@ function scrollToBlock(anchorId) {
14170
15293
  });
14171
15294
  }
14172
15295
 
15296
+ // ../blocks/src/system/runtime/shared/utils/urlParams.ts
15297
+ function consumeSearchParam(paramName) {
15298
+ const url = new URL(window.location.href);
15299
+ const value = url.searchParams.get(paramName);
15300
+ if (value === null) return null;
15301
+ url.searchParams.delete(paramName);
15302
+ const newUrl = url.pathname + (url.search ? url.search : "") + url.hash;
15303
+ window.history.replaceState({}, "", newUrl);
15304
+ return value;
15305
+ }
15306
+
14173
15307
  // ../blocks/src/system/runtime/nodes/booking-form.client.tsx
14174
15308
  import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
14175
15309
  var PORTAL_REBOOK_QUERY_PARAM = "rebook";
@@ -14341,180 +15475,2033 @@ var BookingFormClient = ({
14341
15475
  ] });
14342
15476
  };
14343
15477
 
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
- ]
14379
- }
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" } }]
14395
- }
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" } }]
14411
- }
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",
14435
- options: { colorToken: "primary", opacity: 15 }
14436
- }
14437
- ]
14438
- }
14439
- },
14440
- /**
14441
- * Solid - solid background color on hover
14442
- */
14443
- solid: {
14444
- name: "Solid",
14445
- typography: "body",
14446
- fontWeight: "medium",
14447
- textTransform: "none",
14448
- italic: false,
14449
- colorToken: "text",
14450
- padding: "compact",
14451
- borderRadius: "none",
14452
- effects: {
14453
- hover: [
14454
- {
14455
- effectId: "background-on-hover",
14456
- options: { colorToken: "primary", textColorToken: "primaryForeground" }
14457
- }
14458
- ],
14459
- active: [
14460
- {
14461
- effectId: "background-on-hover",
14462
- options: { colorToken: "primary", textColorToken: "primaryForeground" }
14463
- }
14464
- ]
14465
- }
14466
- },
14467
- /**
14468
- * Scale - gentle scale-up on hover
14469
- */
14470
- scale: {
14471
- name: "Scale",
14472
- typography: "body",
14473
- fontWeight: "medium",
14474
- textTransform: "none",
14475
- italic: false,
14476
- colorToken: "text",
14477
- padding: "none",
14478
- borderRadius: "none",
14479
- effects: {
14480
- hover: [{ effectId: "scale-up", options: { scale: 1.05 } }]
15478
+ // ../blocks/src/system/runtime/nodes/event-registration/registrationStateMachine.ts
15479
+ function createInitialRegistrationFlowState(hasPreSelectedContext) {
15480
+ return {
15481
+ step: hasPreSelectedContext ? "select-tickets" : "select-event",
15482
+ ticketsCount: 1,
15483
+ isAuthenticated: false,
15484
+ eligibility: null,
15485
+ passOptOut: false,
15486
+ paymentSelection: { method: null },
15487
+ selectionSource: "auto"
15488
+ };
15489
+ }
15490
+ function selectionEquals(a, b2) {
15491
+ 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;
15492
+ }
15493
+ function withDefaultSelection(selection) {
15494
+ if (!selection || !selection.method) {
15495
+ return { method: null };
15496
+ }
15497
+ return selection;
15498
+ }
15499
+ function computeAutoSelection(input) {
15500
+ const { isAuthenticated, eligibility, ticketsCount, passOptOut } = input;
15501
+ if (!eligibility) return { method: null };
15502
+ if (eligibility.isFree) return { method: "free" };
15503
+ if (isAuthenticated && ticketsCount === 1) {
15504
+ const membership = eligibility.eligibleMemberships[0];
15505
+ if (membership) {
15506
+ return {
15507
+ method: "membership",
15508
+ membershipId: membership.id,
15509
+ productName: membership.membershipName
15510
+ };
14481
15511
  }
14482
- },
14483
- /**
14484
- * Frosted - semi-transparent glass-like background
14485
- */
14486
- frosted: {
14487
- name: "Frosted",
14488
- typography: "body",
14489
- fontWeight: "medium",
14490
- textTransform: "none",
14491
- italic: false,
14492
- colorToken: "text",
14493
- padding: "compact",
14494
- borderRadius: "md",
14495
- effects: {
14496
- base: [{ effectId: "nav-frosted-base" }],
14497
- hover: [{ effectId: "nav-frosted-hover" }],
14498
- active: [{ effectId: "nav-frosted-active" }]
15512
+ const pass = eligibility.eligiblePasses[0];
15513
+ if (pass && !passOptOut) {
15514
+ return {
15515
+ method: "pass",
15516
+ passId: pass.id,
15517
+ productName: pass.passName
15518
+ };
14499
15519
  }
14500
15520
  }
14501
- };
14502
- var NAV_LINK_PRESET_IDS = Object.keys(NAV_LINK_PRESETS);
14503
-
14504
- // ../theme-core/src/layout/generateLayoutCss.ts
14505
- var classicWaveTransitionMask = svgDataUrl(
14506
- "<svg viewBox='0 0 1440 72' xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='none'><path d='M0 72V46C130 55 260 24 420 30C590 36 690 62 860 42C1035 21 1160 47 1305 36C1365 31 1415 33 1440 38V72H0Z' fill='white'/></svg>"
14507
- );
14508
- var balancedWaveTransitionMask = svgDataUrl(
14509
- "<svg viewBox='0 0 1440 72' xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='none'><path d='M0 72V42C120 24 240 24 360 42C480 60 600 60 720 42C840 24 960 24 1080 42C1200 60 1320 60 1440 42V72H0Z' fill='white'/></svg>"
14510
- );
14511
- var gentleWaveTransitionMask = svgDataUrl(
14512
- "<svg viewBox='0 0 1440 72' xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='none'><path d='M0 72V43C180 32 300 32 480 43C660 54 780 54 960 43C1140 32 1260 32 1440 43V72H0Z' fill='white'/></svg>"
14513
- );
14514
- var boldWaveTransitionMask = svgDataUrl(
14515
- "<svg viewBox='0 0 1440 72' xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='none'><path d='M0 72V44C90 14 270 14 360 44C450 74 630 74 720 44C810 14 990 14 1080 44C1170 74 1350 74 1440 44V72H0Z' fill='white'/></svg>"
14516
- );
14517
- var driftWaveTransitionMask = svgDataUrl(
15521
+ if (eligibility.canPayDirectly && eligibility.price) {
15522
+ return { method: "stripe" };
15523
+ }
15524
+ return { method: null };
15525
+ }
15526
+ function isSelectionValid(input) {
15527
+ const { selection, isAuthenticated, eligibility, ticketsCount } = input;
15528
+ if (!selection.method) return false;
15529
+ if (!eligibility) {
15530
+ return selection.method === "stripe" || selection.method === "pass_bundle" || selection.method === "membership_bundle";
15531
+ }
15532
+ switch (selection.method) {
15533
+ case "free":
15534
+ return eligibility.isFree;
15535
+ case "stripe":
15536
+ return Boolean(eligibility.canPayDirectly && eligibility.price);
15537
+ case "pass":
15538
+ return isAuthenticated && ticketsCount === 1 && !!selection.passId && eligibility.eligiblePasses.some((pass) => pass.id === selection.passId);
15539
+ case "membership":
15540
+ return isAuthenticated && ticketsCount === 1 && !!selection.membershipId && eligibility.eligibleMemberships.some((membership) => membership.id === selection.membershipId);
15541
+ case "pass_bundle":
15542
+ return ticketsCount === 1 && !!selection.bundlePassId && eligibility.availablePasses.some((pass) => pass.id === selection.bundlePassId);
15543
+ case "membership_bundle":
15544
+ return ticketsCount === 1 && !!selection.bundleMembershipId && eligibility.availableMemberships.some((membership) => membership.id === selection.bundleMembershipId);
15545
+ default:
15546
+ return false;
15547
+ }
15548
+ }
15549
+ function normalizeRegistrationFlowState(state) {
15550
+ const hasPass = Boolean(state.eligibility?.eligiblePasses.length);
15551
+ const hasMembership = Boolean(state.eligibility?.eligibleMemberships.length);
15552
+ let nextPassOptOut = state.passOptOut;
15553
+ if (nextPassOptOut && (state.step === "select-tickets" || state.ticketsCount !== 1 || !hasPass || hasMembership)) {
15554
+ nextPassOptOut = false;
15555
+ }
15556
+ const autoSelection = computeAutoSelection({
15557
+ isAuthenticated: state.isAuthenticated,
15558
+ eligibility: state.eligibility,
15559
+ ticketsCount: state.ticketsCount,
15560
+ passOptOut: nextPassOptOut
15561
+ });
15562
+ const canKeepManualSelection = state.step === "select-payment" && state.selectionSource === "manual" && isSelectionValid({
15563
+ selection: state.paymentSelection,
15564
+ isAuthenticated: state.isAuthenticated,
15565
+ eligibility: state.eligibility,
15566
+ ticketsCount: state.ticketsCount
15567
+ });
15568
+ const nextSelection = canKeepManualSelection ? state.paymentSelection : autoSelection;
15569
+ const nextSource = canKeepManualSelection ? "manual" : "auto";
15570
+ const normalizedSelection = withDefaultSelection(nextSelection);
15571
+ if (nextPassOptOut === state.passOptOut && nextSource === state.selectionSource && selectionEquals(normalizedSelection, state.paymentSelection)) {
15572
+ return state;
15573
+ }
15574
+ return {
15575
+ ...state,
15576
+ passOptOut: nextPassOptOut,
15577
+ selectionSource: nextSource,
15578
+ paymentSelection: normalizedSelection
15579
+ };
15580
+ }
15581
+ function registrationFlowReducer(state, action) {
15582
+ switch (action.type) {
15583
+ case "set-step":
15584
+ return normalizeRegistrationFlowState({ ...state, step: action.step });
15585
+ case "set-tickets-count":
15586
+ return normalizeRegistrationFlowState({
15587
+ ...state,
15588
+ ticketsCount: Math.max(1, action.ticketsCount)
15589
+ });
15590
+ case "set-authenticated":
15591
+ return normalizeRegistrationFlowState({ ...state, isAuthenticated: action.isAuthenticated });
15592
+ case "eligibility-updated":
15593
+ return normalizeRegistrationFlowState({ ...state, eligibility: action.eligibility });
15594
+ case "set-manual-payment-selection":
15595
+ return normalizeRegistrationFlowState({
15596
+ ...state,
15597
+ paymentSelection: withDefaultSelection(action.selection),
15598
+ selectionSource: "manual",
15599
+ passOptOut: action.selection.method === "stripe" ? true : state.passOptOut
15600
+ });
15601
+ case "use-card-instead-of-pass":
15602
+ return normalizeRegistrationFlowState({
15603
+ ...state,
15604
+ passOptOut: true,
15605
+ paymentSelection: { method: "stripe" },
15606
+ selectionSource: "manual"
15607
+ });
15608
+ case "event-changed":
15609
+ return normalizeRegistrationFlowState({
15610
+ ...state,
15611
+ step: action.hasPreSelectedContext ? "select-tickets" : "select-event",
15612
+ passOptOut: false,
15613
+ paymentSelection: { method: null },
15614
+ selectionSource: "auto",
15615
+ eligibility: null
15616
+ });
15617
+ case "reset":
15618
+ return createInitialRegistrationFlowState(action.hasPreSelectedContext);
15619
+ default:
15620
+ return state;
15621
+ }
15622
+ }
15623
+ function isEntitlementSelection(selection) {
15624
+ return selection.method === "pass" || selection.method === "membership";
15625
+ }
15626
+ function requiresPaymentStep(params) {
15627
+ if (!params.eventRequiresPayment) return false;
15628
+ return !isEntitlementSelection(params.paymentSelection);
15629
+ }
15630
+
15631
+ // ../blocks/src/system/runtime/nodes/event-registration/event-registration.headless.state.ts
15632
+ var DEFAULT_EVENT_REGISTRATION_MAX_TICKETS = 5;
15633
+ function createEventRegistrationBlockApiConfig(input) {
15634
+ return {
15635
+ baseUrl: input.apiBaseUrl,
15636
+ auth: input.previewToken ? { type: "bearer", token: input.previewToken } : { type: "none" },
15637
+ siteId: input.siteId,
15638
+ isPreview: input.stage === "preview",
15639
+ ...input.portalToken ? { authOverrides: { portal: { type: "bearer", token: input.portalToken } } } : {}
15640
+ };
15641
+ }
15642
+ function getRegistrableStatuses(isPreview) {
15643
+ return isPreview ? ["active", "draft"] : ["active"];
15644
+ }
15645
+ function normalizeEventRegistrationMaxTickets(value) {
15646
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
15647
+ return Math.floor(value);
15648
+ }
15649
+ if (typeof value === "string") {
15650
+ const parsed = Number.parseInt(value, 10);
15651
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_EVENT_REGISTRATION_MAX_TICKETS;
15652
+ }
15653
+ return DEFAULT_EVENT_REGISTRATION_MAX_TICKETS;
15654
+ }
15655
+ function getEventRegistrationOverrideInput(props) {
15656
+ if (!props.siteId) {
15657
+ return {
15658
+ ok: false,
15659
+ reason: "missing-site-id",
15660
+ message: "Event registration is missing site context."
15661
+ };
15662
+ }
15663
+ if (!props.apiBaseUrl) {
15664
+ return {
15665
+ ok: false,
15666
+ reason: "missing-api-base-url",
15667
+ message: "Event registration is missing API configuration."
15668
+ };
15669
+ }
15670
+ const content = props.content ?? {};
15671
+ const data = isRecord5(props.data) ? props.data : {};
15672
+ const events = Array.isArray(data.events) ? data.events.filter(isPublicEventLike) : [];
15673
+ return {
15674
+ ok: true,
15675
+ value: {
15676
+ siteId: props.siteId,
15677
+ apiBaseUrl: props.apiBaseUrl,
15678
+ portalToken: props.portalToken ?? null,
15679
+ previewToken: props.previewToken ?? null,
15680
+ events,
15681
+ ...props.stage ? { stage: props.stage } : {},
15682
+ ...props.occurrenceContext ? { occurrenceContext: props.occurrenceContext } : {},
15683
+ ...isEventRegistrationContentEntryLike(props.contentEntry) ? { contentEntry: props.contentEntry } : {},
15684
+ ...content.maxTickets != null ? { maxTickets: content.maxTickets } : {},
15685
+ ...content.showVenue != null ? { showVenue: content.showVenue } : {},
15686
+ ...content.showCapacity != null ? { showCapacity: content.showCapacity } : {},
15687
+ ...content.successMessage ? { successMessage: content.successMessage } : {},
15688
+ ...content.waitlistMessage ? { waitlistMessage: content.waitlistMessage } : {},
15689
+ ...content.buttonText != null ? { buttonText: content.buttonText } : {},
15690
+ ...content.buttonVariant ? { buttonVariant: content.buttonVariant } : {},
15691
+ ...content.spamProtectionEnabled != null ? { spamProtectionEnabled: content.spamProtectionEnabled } : {},
15692
+ ...content.supportEmail ? { supportEmail: content.supportEmail } : {},
15693
+ ...props.blockId !== void 0 ? { blockId: props.blockId } : {}
15694
+ }
15695
+ };
15696
+ }
15697
+ function toHeadlessPaymentSelection(selection) {
15698
+ switch (selection.method) {
15699
+ case null:
15700
+ return { method: "none" };
15701
+ case "free":
15702
+ return { method: "free" };
15703
+ case "stripe":
15704
+ return { method: "stripe" };
15705
+ case "pass":
15706
+ if (!selection.passId) return { method: "none" };
15707
+ return {
15708
+ method: "pass",
15709
+ passId: selection.passId,
15710
+ ...selection.productName ? { productName: selection.productName } : {}
15711
+ };
15712
+ case "membership":
15713
+ if (!selection.membershipId) return { method: "none" };
15714
+ return {
15715
+ method: "membership",
15716
+ membershipId: selection.membershipId,
15717
+ ...selection.productName ? { productName: selection.productName } : {}
15718
+ };
15719
+ case "pass_bundle":
15720
+ if (!selection.bundlePassId) return { method: "none" };
15721
+ return {
15722
+ method: "pass_bundle",
15723
+ passId: selection.bundlePassId,
15724
+ ...selection.productName ? { productName: selection.productName } : {}
15725
+ };
15726
+ case "membership_bundle":
15727
+ if (!selection.bundleMembershipId) return { method: "none" };
15728
+ return {
15729
+ method: "membership_bundle",
15730
+ membershipId: selection.bundleMembershipId,
15731
+ ...selection.productName ? { productName: selection.productName } : {}
15732
+ };
15733
+ }
15734
+ }
15735
+ function toInternalPaymentSelection(selection) {
15736
+ switch (selection.method) {
15737
+ case "none":
15738
+ return { method: null };
15739
+ case "free":
15740
+ return { method: "free" };
15741
+ case "stripe":
15742
+ return { method: "stripe" };
15743
+ case "pass":
15744
+ return {
15745
+ method: "pass",
15746
+ passId: selection.passId,
15747
+ ...selection.productName ? { productName: selection.productName } : {}
15748
+ };
15749
+ case "membership":
15750
+ return {
15751
+ method: "membership",
15752
+ membershipId: selection.membershipId,
15753
+ ...selection.productName ? { productName: selection.productName } : {}
15754
+ };
15755
+ case "pass_bundle":
15756
+ return {
15757
+ method: "pass_bundle",
15758
+ bundlePassId: selection.passId,
15759
+ ...selection.productName ? { productName: selection.productName } : {}
15760
+ };
15761
+ case "membership_bundle":
15762
+ return {
15763
+ method: "membership_bundle",
15764
+ bundleMembershipId: selection.membershipId,
15765
+ ...selection.productName ? { productName: selection.productName } : {}
15766
+ };
15767
+ }
15768
+ }
15769
+ function resolveEventRegistrationSubmitPlan(input) {
15770
+ const selection = input.paymentSelection.method ? input.paymentSelection : void 0;
15771
+ if (input.canJoinWaitlist) {
15772
+ return { ok: true, args: withOptionalSelection({ method: "free" }, selection) };
15773
+ }
15774
+ switch (input.paymentSelection.method) {
15775
+ case "pass":
15776
+ return input.paymentSelection.passId ? {
15777
+ ok: true,
15778
+ args: withOptionalSelection(
15779
+ { method: "pass", passId: input.paymentSelection.passId },
15780
+ selection
15781
+ )
15782
+ } : missingPaymentSelection();
15783
+ case "membership":
15784
+ return input.paymentSelection.membershipId ? {
15785
+ ok: true,
15786
+ args: withOptionalSelection(
15787
+ { method: "membership", membershipId: input.paymentSelection.membershipId },
15788
+ selection
15789
+ )
15790
+ } : missingPaymentSelection();
15791
+ case "free":
15792
+ return { ok: true, args: withOptionalSelection({ method: "free" }, selection) };
15793
+ case null:
15794
+ return input.eventRequiresPayment ? missingPaymentSelection() : { ok: true, args: { method: "free" } };
15795
+ case "pass_bundle":
15796
+ return input.paymentSelection.bundlePassId ? {
15797
+ ok: true,
15798
+ args: withOptionalSelection(
15799
+ { method: "pass_bundle", passId: input.paymentSelection.bundlePassId },
15800
+ selection
15801
+ )
15802
+ } : missingPaymentSelection();
15803
+ case "membership_bundle":
15804
+ return input.paymentSelection.bundleMembershipId ? {
15805
+ ok: true,
15806
+ args: withOptionalSelection(
15807
+ {
15808
+ method: "membership_bundle",
15809
+ membershipId: input.paymentSelection.bundleMembershipId
15810
+ },
15811
+ selection
15812
+ )
15813
+ } : missingPaymentSelection();
15814
+ case "stripe":
15815
+ return { ok: true, args: withOptionalSelection({ method: "stripe" }, selection) };
15816
+ }
15817
+ }
15818
+ function resolveHeadlessEventRegistrationStatus(wizard) {
15819
+ switch (wizard.step) {
15820
+ case "submitting":
15821
+ return { tag: "submitting" };
15822
+ case "redirecting":
15823
+ return { tag: "redirecting" };
15824
+ case "verifying-payment":
15825
+ return { tag: "verifying-payment" };
15826
+ case "verifying-timeout":
15827
+ return { tag: "verifying-timeout" };
15828
+ case "payment-failed":
15829
+ return { tag: "payment-failed", message: wizard.errorMessage };
15830
+ case "success":
15831
+ return wizard.registrationResult ? { tag: "success", result: wizard.registrationResult } : { tag: "ready" };
15832
+ case "error":
15833
+ return { tag: "error", message: wizard.errorMessage };
15834
+ case "select-event":
15835
+ case "select-tickets":
15836
+ case "enter-details":
15837
+ case "select-payment":
15838
+ return { tag: "ready" };
15839
+ }
15840
+ }
15841
+ function resolveHeadlessEventRegistrationView(wizard) {
15842
+ if (wizard.scopedEvents.length === 0 && !wizard.occurrenceContext) {
15843
+ return { kind: "empty", message: "No events available for registration." };
15844
+ }
15845
+ const allowedStatuses = getRegistrableStatuses(wizard.api.config.isPreview);
15846
+ const hasRegistrableEvents = wizard.scopedEvents.some((event) => !event.status || allowedStatuses.includes(event.status));
15847
+ if (!hasRegistrableEvents && !wizard.occurrenceContext) {
15848
+ return {
15849
+ kind: "unavailable",
15850
+ message: "Registration is not currently available for this event."
15851
+ };
15852
+ }
15853
+ switch (wizard.step) {
15854
+ case "verifying-payment":
15855
+ return { kind: "verifying", message: "Verifying your payment..." };
15856
+ case "success":
15857
+ return wizard.registrationResult ? { kind: "success", result: wizard.registrationResult } : { kind: "form" };
15858
+ case "error":
15859
+ case "payment-failed":
15860
+ return { kind: "error", message: wizard.errorMessage };
15861
+ case "verifying-timeout":
15862
+ return { kind: "verifying", message: "Your registration is saved." };
15863
+ case "select-event":
15864
+ case "select-tickets":
15865
+ case "enter-details":
15866
+ case "select-payment":
15867
+ case "submitting":
15868
+ case "redirecting":
15869
+ return { kind: "form" };
15870
+ }
15871
+ }
15872
+ function withOptionalSelection(args, selection) {
15873
+ return selection ? { ...args, selection } : args;
15874
+ }
15875
+ function missingPaymentSelection() {
15876
+ return {
15877
+ ok: false,
15878
+ reason: "payment-selection-required",
15879
+ message: "Select a payment option to continue."
15880
+ };
15881
+ }
15882
+ function deriveEventRegistrationSteps(input) {
15883
+ const ids = [];
15884
+ if (!input.hasPreSelectedContext) ids.push("select-event");
15885
+ ids.push("select-tickets", "enter-details");
15886
+ const needsPaymentStep = input.eventRequiresPayment && input.paymentSelection.method !== "pass" && input.paymentSelection.method !== "membership";
15887
+ if (needsPaymentStep) ids.push("select-payment");
15888
+ const activeIndex = ids.indexOf(input.step);
15889
+ return ids.map((id, index) => ({
15890
+ id,
15891
+ label: getStepLabel(id),
15892
+ index,
15893
+ state: index === activeIndex ? "active" : activeIndex === -1 || index > activeIndex ? "available" : "complete",
15894
+ canEnter: index <= Math.max(activeIndex + 1, 0),
15895
+ canLeave: activeIndex !== index
15896
+ }));
15897
+ }
15898
+ function getStepLabel(step) {
15899
+ switch (step) {
15900
+ case "select-event":
15901
+ return "Event";
15902
+ case "select-tickets":
15903
+ return "Tickets";
15904
+ case "enter-details":
15905
+ return "Details";
15906
+ case "select-payment":
15907
+ return "Payment";
15908
+ }
15909
+ }
15910
+ function isRecord5(value) {
15911
+ return typeof value === "object" && value !== null;
15912
+ }
15913
+ function isPublicEventLike(value) {
15914
+ 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);
15915
+ }
15916
+ function isDeliveryMode(value) {
15917
+ return value === "in_person" || value === "online" || value === "hybrid";
15918
+ }
15919
+ function isAccessRestriction(value) {
15920
+ return value === "none" || value === "category";
15921
+ }
15922
+ function isEventRegistrationContentEntryLike(value) {
15923
+ return isRecord5(value) && typeof value.id === "string" && typeof value.slug === "string" && typeof value.contentTypeSlug === "string";
15924
+ }
15925
+
15926
+ // ../blocks/src/system/runtime/nodes/event-registration/utils.ts
15927
+ var DEFAULT_EVENT_CURRENCY2 = "usd";
15928
+ function transformEligibilityResponse(response) {
15929
+ const { eligibility } = response;
15930
+ const eligiblePasses = eligibility.passes.map((p) => ({
15931
+ id: p.customerPassId,
15932
+ passName: p.passName,
15933
+ creditsRemaining: p.creditsRemaining
15934
+ }));
15935
+ const eligibleMemberships = eligibility.membership ? [{
15936
+ id: eligibility.membership.customerMembershipId,
15937
+ membershipName: eligibility.membership.membershipName
15938
+ }] : [];
15939
+ const isFree = !eligibility.requiresPayment && !eligibility.eventPrice;
15940
+ const canPayDirectly = eligibility.eventPrice !== null && eligibility.eventPrice > 0;
15941
+ const hasPaymentOptions = eligiblePasses.length > 0 || eligibleMemberships.length > 0 || canPayDirectly;
15942
+ const hasUpsellOptions = eligibility.availableForPurchase.passes.length > 0 || eligibility.availableForPurchase.memberships.length > 0;
15943
+ const eligible = eligibility.canJoinWaitlist || !eligibility.isFull && (isFree || hasPaymentOptions || hasUpsellOptions);
15944
+ return {
15945
+ isFree,
15946
+ eligible,
15947
+ requiresPayment: eligibility.requiresPayment,
15948
+ pricingMode: eligibility.pricingMode,
15949
+ selectedTicketTypeId: eligibility.selectedTicketTypeId ?? null,
15950
+ ticketTypes: eligibility.ticketTypes ?? [],
15951
+ isFull: eligibility.isFull,
15952
+ waitlistEnabled: eligibility.waitlistEnabled,
15953
+ canJoinWaitlist: eligibility.canJoinWaitlist,
15954
+ price: eligibility.eventPrice,
15955
+ currency: eligibility.eventPriceCurrency ?? DEFAULT_EVENT_CURRENCY2,
15956
+ requiresAuthForPasses: eligibility.requiresAuthForPasses,
15957
+ requiresAuthForMemberships: eligibility.requiresAuthForMemberships,
15958
+ eligiblePasses,
15959
+ eligibleMemberships,
15960
+ canPayDirectly,
15961
+ eventAcceptsPasses: eligibility.eventAcceptsPasses,
15962
+ eventAcceptsMemberships: eligibility.eventAcceptsMemberships,
15963
+ availablePasses: eligibility.availableForPurchase.passes,
15964
+ availableMemberships: eligibility.availableForPurchase.memberships
15965
+ };
15966
+ }
15967
+ function getVisibleTicketTypes(input) {
15968
+ const eligibilityTicketTypes = input.eligibility?.ticketTypes;
15969
+ const eventTicketTypes = input.event ? publicEventTicketTypes(resolveRuntimeEventPricing(input.event)) : [];
15970
+ const source = eligibilityTicketTypes && eligibilityTicketTypes.length > 0 ? eligibilityTicketTypes : eventTicketTypes;
15971
+ return source.filter(
15972
+ (ticketType) => ticketType.isActive && (!input.selectedAttendanceMode || (ticketType.attendanceScope ?? "both") === "both" || (ticketType.attendanceScope ?? "both") === input.selectedAttendanceMode)
15973
+ );
15974
+ }
15975
+ function getImplicitSingleAvailableTicketType(ticketTypes) {
15976
+ return ticketTypes.length === 1 && ticketTypes[0]?.availability.kind === "available" ? ticketTypes[0] : null;
15977
+ }
15978
+ function findSelectedTicketType(input) {
15979
+ if (!input.selectedTicketTypeId) {
15980
+ return null;
15981
+ }
15982
+ return getVisibleTicketTypes({
15983
+ event: input.event,
15984
+ eligibility: input.eligibility,
15985
+ selectedAttendanceMode: input.selectedAttendanceMode
15986
+ }).find((ticketType) => ticketType.id === input.selectedTicketTypeId) ?? null;
15987
+ }
15988
+
15989
+ // ../blocks/src/system/runtime/nodes/event-registration/hooks.ts
15990
+ import { useState as useState6, useEffect as useEffect8, useCallback as useCallback5, useRef as useRef8, useReducer as useReducer4 } from "react";
15991
+
15992
+ // ../blocks/src/system/runtime/nodes/event-registration/hooks.state.ts
15993
+ var initialEligibilityLookupState = {
15994
+ tag: "idle",
15995
+ eligibility: null,
15996
+ error: null
15997
+ };
15998
+ function eligibilityLookupReducer(state, action) {
15999
+ switch (action.type) {
16000
+ case "reset":
16001
+ return initialEligibilityLookupState;
16002
+ case "loading-started":
16003
+ return {
16004
+ tag: "loading",
16005
+ eligibility: state.eligibility,
16006
+ error: null
16007
+ };
16008
+ case "resolved":
16009
+ return {
16010
+ tag: "resolved",
16011
+ eligibility: action.eligibility,
16012
+ error: null
16013
+ };
16014
+ case "failed":
16015
+ return {
16016
+ tag: "failed",
16017
+ eligibility: null,
16018
+ error: action.message
16019
+ };
16020
+ default:
16021
+ return assertNever11(action);
16022
+ }
16023
+ }
16024
+ var initialExistingRegistrationLookupState = {
16025
+ tag: "idle",
16026
+ registration: null
16027
+ };
16028
+ function existingRegistrationLookupReducer(state, action) {
16029
+ switch (action.type) {
16030
+ case "reset":
16031
+ return initialExistingRegistrationLookupState;
16032
+ case "loading-started":
16033
+ return {
16034
+ tag: "loading",
16035
+ registration: state.registration
16036
+ };
16037
+ case "resolved":
16038
+ return {
16039
+ tag: "resolved",
16040
+ registration: action.registration
16041
+ };
16042
+ default:
16043
+ return assertNever11(action);
16044
+ }
16045
+ }
16046
+
16047
+ // ../blocks/src/system/runtime/nodes/event-registration/hooks.ts
16048
+ function usePortalAuth() {
16049
+ const api = useBlockApi();
16050
+ const [authState, setAuthState] = useState6("checking");
16051
+ const [profile, setProfile] = useState6(null);
16052
+ useEffect8(() => {
16053
+ let cancelled = false;
16054
+ async function checkPortalAuth() {
16055
+ const effectivePortalAuth = api.config.authOverrides?.portal ?? api.config.auth;
16056
+ if (effectivePortalAuth.type !== "bearer") {
16057
+ setAuthState("unauthenticated");
16058
+ return;
16059
+ }
16060
+ setAuthState("checking");
16061
+ try {
16062
+ const me = await api.getPortalProfile();
16063
+ if (cancelled) return;
16064
+ setAuthState("authenticated");
16065
+ setProfile({
16066
+ email: me.profile.email,
16067
+ name: me.profile.name,
16068
+ phone: me.profile.phone || ""
16069
+ });
16070
+ } catch {
16071
+ if (cancelled) return;
16072
+ setAuthState("unauthenticated");
16073
+ setProfile(null);
16074
+ }
16075
+ }
16076
+ void checkPortalAuth();
16077
+ return () => {
16078
+ cancelled = true;
16079
+ };
16080
+ }, [api]);
16081
+ const logout = useCallback5(() => {
16082
+ const form = document.createElement("form");
16083
+ form.method = "POST";
16084
+ form.action = "/api/portal/logout";
16085
+ document.body.appendChild(form);
16086
+ form.submit();
16087
+ }, []);
16088
+ return {
16089
+ authState,
16090
+ isAuthenticated: authState === "authenticated",
16091
+ isChecking: authState === "checking",
16092
+ profile,
16093
+ logout
16094
+ };
16095
+ }
16096
+ function useEligibility(params) {
16097
+ const api = useBlockApi();
16098
+ const [state, dispatch] = useReducer4(
16099
+ eligibilityLookupReducer,
16100
+ initialEligibilityLookupState
16101
+ );
16102
+ const requestIdRef = useRef8(0);
16103
+ useEffect8(() => {
16104
+ let cancelled = false;
16105
+ async function fetchEligibility() {
16106
+ if (!params.enabled) {
16107
+ requestIdRef.current += 1;
16108
+ dispatch({ type: "reset" });
16109
+ return;
16110
+ }
16111
+ if (!params.occurrenceId || !params.email.trim()) {
16112
+ requestIdRef.current += 1;
16113
+ dispatch({ type: "reset" });
16114
+ return;
16115
+ }
16116
+ const requestId = requestIdRef.current + 1;
16117
+ requestIdRef.current = requestId;
16118
+ dispatch({ type: "loading-started" });
16119
+ try {
16120
+ const result = await api.checkEligibility({
16121
+ occurrenceId: params.occurrenceId,
16122
+ attendanceMode: params.attendanceMode ?? void 0,
16123
+ ticketTypeId: params.ticketTypeId ?? void 0,
16124
+ email: params.email.trim().toLowerCase(),
16125
+ ticketsCount: params.ticketsCount
16126
+ });
16127
+ if (cancelled || requestIdRef.current !== requestId) return;
16128
+ dispatch({
16129
+ type: "resolved",
16130
+ eligibility: transformEligibilityResponse(result)
16131
+ });
16132
+ } catch (err3) {
16133
+ if (cancelled || requestIdRef.current !== requestId) return;
16134
+ dispatch({
16135
+ type: "failed",
16136
+ message: err3 instanceof Error ? err3.message : "Failed to check eligibility"
16137
+ });
16138
+ }
16139
+ }
16140
+ void fetchEligibility();
16141
+ return () => {
16142
+ cancelled = true;
16143
+ };
16144
+ }, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.email, params.ticketsCount]);
16145
+ return {
16146
+ state,
16147
+ eligibility: state.eligibility,
16148
+ isLoading: state.tag === "loading",
16149
+ error: state.error
16150
+ };
16151
+ }
16152
+ function useExistingEventRegistration({
16153
+ isAuthenticated,
16154
+ occurrenceId
16155
+ }) {
16156
+ const api = useBlockApi();
16157
+ const [state, dispatch] = useReducer4(
16158
+ existingRegistrationLookupReducer,
16159
+ initialExistingRegistrationLookupState
16160
+ );
16161
+ const requestIdRef = useRef8(0);
16162
+ useEffect8(() => {
16163
+ let cancelled = false;
16164
+ async function fetchExistingRegistration() {
16165
+ if (!isAuthenticated || !occurrenceId) {
16166
+ requestIdRef.current += 1;
16167
+ dispatch({ type: "reset" });
16168
+ return;
16169
+ }
16170
+ const requestId = requestIdRef.current + 1;
16171
+ requestIdRef.current = requestId;
16172
+ dispatch({ type: "loading-started" });
16173
+ try {
16174
+ const events = await api.getPortalEvents({ occurrenceId });
16175
+ if (cancelled || requestIdRef.current !== requestId) return;
16176
+ const existing = events.find(
16177
+ (event) => event.occurrenceId === occurrenceId && event.status !== "cancelled" && event.transferState !== "transferred_out"
16178
+ ) ?? null;
16179
+ dispatch({ type: "resolved", registration: existing });
16180
+ } catch {
16181
+ if (cancelled || requestIdRef.current !== requestId) return;
16182
+ dispatch({ type: "resolved", registration: null });
16183
+ }
16184
+ }
16185
+ void fetchExistingRegistration();
16186
+ return () => {
16187
+ cancelled = true;
16188
+ };
16189
+ }, [api, isAuthenticated, occurrenceId]);
16190
+ return {
16191
+ state,
16192
+ registration: state.registration,
16193
+ isLoading: state.tag === "loading"
16194
+ };
16195
+ }
16196
+
16197
+ // ../blocks/src/system/runtime/nodes/event-registration/sessionStorage.ts
16198
+ var STORAGE_PREFIX = "riverbank:event-registration:";
16199
+ var STALE_THRESHOLD_MS = 24 * 60 * 60 * 1e3;
16200
+ function getStorageKey(siteId, occurrenceId) {
16201
+ return `${STORAGE_PREFIX}${siteId}:${occurrenceId}`;
16202
+ }
16203
+ function isStorageAvailable() {
16204
+ try {
16205
+ const testKey = "__riverbank_test__";
16206
+ sessionStorage.setItem(testKey, "test");
16207
+ sessionStorage.removeItem(testKey);
16208
+ return true;
16209
+ } catch {
16210
+ return false;
16211
+ }
16212
+ }
16213
+ function savePendingRegistration(siteId, occurrenceId, data) {
16214
+ if (!isStorageAvailable()) {
16215
+ console.warn("[sessionStorage] Storage not available, skipping save");
16216
+ return;
16217
+ }
16218
+ try {
16219
+ const key = getStorageKey(siteId, occurrenceId);
16220
+ const entry = {
16221
+ ...data,
16222
+ version: 3,
16223
+ timestamp: Date.now()
16224
+ };
16225
+ sessionStorage.setItem(key, JSON.stringify(entry));
16226
+ } catch (error) {
16227
+ console.warn("[sessionStorage] Failed to save registration:", error);
16228
+ }
16229
+ }
16230
+ function getPendingRegistration(siteId, occurrenceId) {
16231
+ if (!isStorageAvailable()) {
16232
+ return null;
16233
+ }
16234
+ try {
16235
+ if (occurrenceId) {
16236
+ const key = getStorageKey(siteId, occurrenceId);
16237
+ const stored = sessionStorage.getItem(key);
16238
+ if (stored) {
16239
+ return parseAndValidateEntry(stored, key);
16240
+ }
16241
+ return null;
16242
+ }
16243
+ const sitePrefix = `${STORAGE_PREFIX}${siteId}:`;
16244
+ for (let i = 0; i < sessionStorage.length; i++) {
16245
+ const key = sessionStorage.key(i);
16246
+ if (key?.startsWith(sitePrefix)) {
16247
+ const stored = sessionStorage.getItem(key);
16248
+ if (stored) {
16249
+ const entry = parseAndValidateEntry(stored, key);
16250
+ if (entry) return entry;
16251
+ }
16252
+ }
16253
+ }
16254
+ return null;
16255
+ } catch (error) {
16256
+ console.warn("[sessionStorage] Failed to read registration:", error);
16257
+ return null;
16258
+ }
16259
+ }
16260
+ function parseAndValidateEntry(stored, key) {
16261
+ try {
16262
+ const raw = JSON.parse(stored);
16263
+ if (!raw || typeof raw !== "object") {
16264
+ sessionStorage.removeItem(key);
16265
+ return null;
16266
+ }
16267
+ const version = raw.version;
16268
+ if (version !== 1 && version !== 2 && version !== 3) {
16269
+ console.warn("[sessionStorage] Unknown version, ignoring entry");
16270
+ sessionStorage.removeItem(key);
16271
+ return null;
16272
+ }
16273
+ const entry = raw;
16274
+ const timestamp = typeof entry.timestamp === "number" ? entry.timestamp : NaN;
16275
+ if (!Number.isFinite(timestamp)) {
16276
+ sessionStorage.removeItem(key);
16277
+ return null;
16278
+ }
16279
+ const age = Date.now() - timestamp;
16280
+ if (age > STALE_THRESHOLD_MS) {
16281
+ console.info("[sessionStorage] Entry is stale, removing");
16282
+ sessionStorage.removeItem(key);
16283
+ return null;
16284
+ }
16285
+ if (entry.version === 1) {
16286
+ const legacy = entry;
16287
+ return {
16288
+ version: 3,
16289
+ attendeeId: legacy.attendeeId,
16290
+ formData: legacy.formData,
16291
+ ticketsCount: legacy.ticketsCount,
16292
+ selectedEventId: legacy.selectedEventId,
16293
+ selectedAttendanceMode: null,
16294
+ selectedTicketTypeId: null,
16295
+ paymentSelection: { method: legacy.paymentMethod },
16296
+ timestamp: legacy.timestamp
16297
+ };
16298
+ }
16299
+ if (entry.version === 2) {
16300
+ return {
16301
+ version: 3,
16302
+ attendeeId: entry.attendeeId,
16303
+ formData: entry.formData,
16304
+ ticketsCount: entry.ticketsCount,
16305
+ selectedEventId: entry.selectedEventId,
16306
+ selectedAttendanceMode: null,
16307
+ selectedTicketTypeId: null,
16308
+ paymentSelection: entry.paymentSelection,
16309
+ timestamp: entry.timestamp
16310
+ };
16311
+ }
16312
+ return entry;
16313
+ } catch {
16314
+ console.warn("[sessionStorage] Failed to parse entry, removing");
16315
+ sessionStorage.removeItem(key);
16316
+ return null;
16317
+ }
16318
+ }
16319
+ function clearPendingRegistration(siteId, occurrenceId) {
16320
+ if (!isStorageAvailable()) {
16321
+ return;
16322
+ }
16323
+ try {
16324
+ const key = getStorageKey(siteId, occurrenceId);
16325
+ sessionStorage.removeItem(key);
16326
+ } catch {
16327
+ }
16328
+ }
16329
+ function cleanupStaleRegistrations() {
16330
+ if (!isStorageAvailable()) {
16331
+ return;
16332
+ }
16333
+ try {
16334
+ const keysToRemove = [];
16335
+ for (let i = 0; i < sessionStorage.length; i++) {
16336
+ const key = sessionStorage.key(i);
16337
+ if (!key?.startsWith(STORAGE_PREFIX)) {
16338
+ continue;
16339
+ }
16340
+ try {
16341
+ const stored = sessionStorage.getItem(key);
16342
+ if (!stored) continue;
16343
+ const entry = JSON.parse(stored);
16344
+ const age = Date.now() - entry.timestamp;
16345
+ if (age > STALE_THRESHOLD_MS) {
16346
+ keysToRemove.push(key);
16347
+ }
16348
+ } catch {
16349
+ keysToRemove.push(key);
16350
+ }
16351
+ }
16352
+ for (const key of keysToRemove) {
16353
+ sessionStorage.removeItem(key);
16354
+ }
16355
+ if (keysToRemove.length > 0) {
16356
+ console.info(`[sessionStorage] Cleaned up ${keysToRemove.length} stale entries`);
16357
+ }
16358
+ } catch (error) {
16359
+ console.warn("[sessionStorage] Cleanup failed:", error);
16360
+ }
16361
+ }
16362
+
16363
+ // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
16364
+ import { useCallback as useCallback6, useEffect as useEffect11, useMemo as useMemo6, useReducer as useReducer5, useState as useState8 } from "react";
16365
+
16366
+ // ../blocks/src/system/runtime/nodes/event-registration/validation.ts
16367
+ function validateFormData2(formData) {
16368
+ const errors = {};
16369
+ if (!formData.name.trim()) {
16370
+ errors.name = "Name is required";
16371
+ }
16372
+ if (!formData.email.trim()) {
16373
+ errors.email = "Email is required";
16374
+ } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
16375
+ errors.email = "Invalid email address";
16376
+ }
16377
+ return errors;
16378
+ }
16379
+
16380
+ // ../blocks/src/system/runtime/shared/useWaitlistClaim.ts
16381
+ import { useEffect as useEffect9, useState as useState7, useSyncExternalStore } from "react";
16382
+ var WAITLIST_CLAIM_LOCATION_EVENT = "riverbank:waitlist-claim-location-change";
16383
+ var historyPatched = false;
16384
+ function emitWaitlistClaimLocationChange() {
16385
+ if (typeof window === "undefined") return;
16386
+ window.dispatchEvent(new Event(WAITLIST_CLAIM_LOCATION_EVENT));
16387
+ }
16388
+ function ensureWaitlistClaimLocationTracking() {
16389
+ if (typeof window === "undefined" || historyPatched) {
16390
+ return;
16391
+ }
16392
+ historyPatched = true;
16393
+ const history = window.history;
16394
+ if (history.__riverbankWaitlistClaimPatched__) {
16395
+ return;
16396
+ }
16397
+ const wrapHistoryMethod = (method) => {
16398
+ return function patched(...args) {
16399
+ method.apply(this, args);
16400
+ emitWaitlistClaimLocationChange();
16401
+ };
16402
+ };
16403
+ try {
16404
+ history.pushState = wrapHistoryMethod(history.pushState);
16405
+ history.replaceState = wrapHistoryMethod(history.replaceState);
16406
+ history.__riverbankWaitlistClaimPatched__ = true;
16407
+ } catch {
16408
+ }
16409
+ window.addEventListener("popstate", emitWaitlistClaimLocationChange);
16410
+ }
16411
+ function getWaitlistClaimTokenFromUrl() {
16412
+ if (typeof window === "undefined") {
16413
+ return null;
16414
+ }
16415
+ const token = new URLSearchParams(window.location.search).get("waitlist_claim")?.trim() ?? "";
16416
+ return token.length > 0 ? token : null;
16417
+ }
16418
+ function subscribeToWaitlistClaimToken(callback) {
16419
+ if (typeof window === "undefined") {
16420
+ return () => {
16421
+ };
16422
+ }
16423
+ ensureWaitlistClaimLocationTracking();
16424
+ window.addEventListener(WAITLIST_CLAIM_LOCATION_EVENT, callback);
16425
+ return () => {
16426
+ window.removeEventListener(WAITLIST_CLAIM_LOCATION_EVENT, callback);
16427
+ };
16428
+ }
16429
+ function getWaitlistClaimTokenSnapshot() {
16430
+ return getWaitlistClaimTokenFromUrl();
16431
+ }
16432
+ function useWaitlistClaim() {
16433
+ const api = useBlockApi();
16434
+ const token = useSyncExternalStore(
16435
+ subscribeToWaitlistClaimToken,
16436
+ getWaitlistClaimTokenSnapshot,
16437
+ () => null
16438
+ );
16439
+ const [claim, setClaim] = useState7(null);
16440
+ const [error, setError] = useState7(null);
16441
+ const [loginMessage, setLoginMessage] = useState7(null);
16442
+ const [requiresPortalLogin, setRequiresPortalLogin] = useState7(false);
16443
+ const [isLoading, setIsLoading] = useState7(() => Boolean(token));
16444
+ useEffect9(() => {
16445
+ let cancelled = false;
16446
+ async function resolveClaim() {
16447
+ if (!token) {
16448
+ setClaim(null);
16449
+ setError(null);
16450
+ setLoginMessage(null);
16451
+ setRequiresPortalLogin(false);
16452
+ setIsLoading(false);
16453
+ return;
16454
+ }
16455
+ setIsLoading(true);
16456
+ setClaim(null);
16457
+ setError(null);
16458
+ setLoginMessage(null);
16459
+ setRequiresPortalLogin(false);
16460
+ try {
16461
+ const result = await api.resolveWaitlistClaim({ claimToken: token });
16462
+ if (cancelled) return;
16463
+ setClaim(result);
16464
+ } catch (claimError) {
16465
+ if (cancelled) return;
16466
+ const message = claimError instanceof Error ? claimError.message : "Failed to resolve waitlist claim";
16467
+ setClaim(null);
16468
+ if (claimError instanceof BlockApiError && claimError.status === 401) {
16469
+ setRequiresPortalLogin(true);
16470
+ setLoginMessage(message);
16471
+ setError(null);
16472
+ } else {
16473
+ setError(message);
16474
+ }
16475
+ } finally {
16476
+ if (!cancelled) {
16477
+ setIsLoading(false);
16478
+ }
16479
+ }
16480
+ }
16481
+ void resolveClaim();
16482
+ return () => {
16483
+ cancelled = true;
16484
+ };
16485
+ }, [api, token]);
16486
+ return {
16487
+ token,
16488
+ claim,
16489
+ error,
16490
+ loginMessage,
16491
+ requiresPortalLogin,
16492
+ isLoading
16493
+ };
16494
+ }
16495
+
16496
+ // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.ts
16497
+ import { useEffect as useEffect10, useMemo as useMemo5 } from "react";
16498
+
16499
+ // ../blocks/src/system/runtime/hooks/usePaymentVerification.ts
16500
+ import { useMemo as useMemo4 } from "react";
16501
+ function usePaymentVerification(config) {
16502
+ const api = useBlockApi();
16503
+ const pollingConfig = useMemo4(() => {
16504
+ if (!config) return null;
16505
+ return {
16506
+ pollFn: () => api.getEventRegistrationStatus({ attendeeId: config.transactionId }),
16507
+ isComplete: (result) => result.paymentStatus === "completed" || result.paymentStatus === "not_required",
16508
+ isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "refunded",
16509
+ maxAttempts: config.maxAttempts,
16510
+ interval: config.pollInterval
16511
+ };
16512
+ }, [api, config]);
16513
+ const polling = usePolling(pollingConfig);
16514
+ const paymentStatus = polling.result?.paymentStatus ?? null;
16515
+ let errorMessage = null;
16516
+ if (polling.status === "timeout") {
16517
+ errorMessage = "Could not verify payment. If you were charged, please contact support.";
16518
+ } else if (polling.status === "failed" && paymentStatus) {
16519
+ errorMessage = paymentStatus === "refunded" ? "Payment was refunded. Please contact support." : "Payment was declined. Please try again.";
16520
+ } else if (polling.error) {
16521
+ errorMessage = polling.error.message;
16522
+ }
16523
+ return {
16524
+ status: polling.status,
16525
+ paymentStatus,
16526
+ attendeeStatus: polling.result?.attendeeStatus ?? null,
16527
+ waitlistPosition: polling.result?.waitlistPosition ?? null,
16528
+ error: errorMessage,
16529
+ retry: polling.retry
16530
+ };
16531
+ }
16532
+
16533
+ // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.ts
16534
+ function useEventRegistrationStripeReturn(options) {
16535
+ const {
16536
+ api,
16537
+ events,
16538
+ occurrenceId,
16539
+ pendingAttendeeId,
16540
+ setErrorMessage,
16541
+ setFormData,
16542
+ setPaymentSelection,
16543
+ setPendingAttendeeId,
16544
+ setRegistrationResult,
16545
+ setSelectedEvent,
16546
+ setSelectedAttendanceMode,
16547
+ setSelectedTicketTypeId,
16548
+ setStep,
16549
+ setTicketsCount,
16550
+ step
16551
+ } = options;
16552
+ const verificationConfig = useMemo5(
16553
+ () => step === "verifying-payment" && pendingAttendeeId ? { transactionId: pendingAttendeeId } : null,
16554
+ [step, pendingAttendeeId]
16555
+ );
16556
+ const verification = usePaymentVerification(verificationConfig);
16557
+ useEffect10(() => {
16558
+ cleanupStaleRegistrations();
16559
+ const registrationStatus = consumeSearchParam("registration");
16560
+ if (!registrationStatus) return;
16561
+ const siteId = api.config.siteId;
16562
+ if (!siteId) return;
16563
+ const pending = getPendingRegistration(siteId, occurrenceId || void 0);
16564
+ if (!pending) return;
16565
+ setFormData(pending.formData);
16566
+ setTicketsCount(pending.ticketsCount);
16567
+ if (pending.selectedEventId) {
16568
+ const event = events.find((e) => e.publicEventId === pending.selectedEventId) ?? null;
16569
+ if (event) setSelectedEvent(event);
16570
+ }
16571
+ setSelectedAttendanceMode(pending.selectedAttendanceMode ?? null);
16572
+ setSelectedTicketTypeId(pending.selectedTicketTypeId ?? null);
16573
+ setPaymentSelection(pending.paymentSelection);
16574
+ if (registrationStatus === "cancelled") {
16575
+ setStep("select-payment");
16576
+ } else if (registrationStatus === "success") {
16577
+ setPendingAttendeeId(pending.attendeeId);
16578
+ setStep("verifying-payment");
16579
+ }
16580
+ }, []);
16581
+ useEffect10(() => {
16582
+ if (verification.status === "completed") {
16583
+ const siteId = api.config.siteId;
16584
+ if (siteId && occurrenceId) {
16585
+ clearPendingRegistration(siteId, occurrenceId);
16586
+ }
16587
+ setRegistrationResult({
16588
+ status: "confirmed"
16589
+ });
16590
+ setStep("success");
16591
+ } else if (verification.status === "failed") {
16592
+ setErrorMessage(verification.error ?? "Payment failed. Please try again.");
16593
+ setStep("payment-failed");
16594
+ } else if (verification.status === "timeout") {
16595
+ setStep("verifying-timeout");
16596
+ }
16597
+ }, [
16598
+ verification.status,
16599
+ verification.attendeeStatus,
16600
+ verification.waitlistPosition,
16601
+ verification.error,
16602
+ api.config.siteId,
16603
+ occurrenceId,
16604
+ setErrorMessage,
16605
+ setRegistrationResult,
16606
+ setStep
16607
+ ]);
16608
+ return verification;
16609
+ }
16610
+
16611
+ // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.ts
16612
+ function useEventRegistrationSubmit(options) {
16613
+ return async (method, passId, membershipId, selection, submitOptions) => {
16614
+ const submitOccurrenceId = options.registrationTarget?.occurrenceId;
16615
+ if (!submitOccurrenceId) {
16616
+ return {
16617
+ ok: false,
16618
+ reason: "missing-target",
16619
+ message: "Select an event to continue."
16620
+ };
16621
+ }
16622
+ options.setStep("submitting");
16623
+ try {
16624
+ const isBundle = method === "pass_bundle" || method === "membership_bundle";
16625
+ const bundleProductId = isBundle ? passId || membershipId : void 0;
16626
+ const selectionSnapshot = (() => {
16627
+ if (selection?.method) {
16628
+ return selection;
16629
+ }
16630
+ if (method === "pass") {
16631
+ return { method: "pass", passId: passId ?? void 0 };
16632
+ }
16633
+ if (method === "membership") {
16634
+ return { method: "membership", membershipId: membershipId ?? void 0 };
16635
+ }
16636
+ if (method === "pass_bundle") {
16637
+ return { method: "pass_bundle", bundlePassId: bundleProductId ?? void 0 };
16638
+ }
16639
+ if (method === "membership_bundle") {
16640
+ return { method: "membership_bundle", bundleMembershipId: bundleProductId ?? void 0 };
16641
+ }
16642
+ return { method };
16643
+ })();
16644
+ const guestsPayload = options.requireGuestDetails && options.guests.length > 0 ? options.guests.map((guest) => ({
16645
+ name: guest.name.trim(),
16646
+ email: guest.email?.trim().toLowerCase() || void 0,
16647
+ phone: guest.phone?.trim() || void 0
16648
+ })) : void 0;
16649
+ const result = await options.api.registerForEvent({
16650
+ occurrenceId: submitOccurrenceId,
16651
+ attendanceMode: options.selectedAttendanceMode ?? void 0,
16652
+ ticketTypeId: options.selectedTicketTypeId ?? void 0,
16653
+ email: options.formData.email.trim().toLowerCase(),
16654
+ name: options.formData.name.trim(),
16655
+ ticketsCount: options.ticketsCount,
16656
+ phone: options.formData.phone.trim() || void 0,
16657
+ notes: options.formData.notes.trim() || void 0,
16658
+ altchaSolution: options.altchaSolution,
16659
+ paymentMethod: method,
16660
+ customerPassId: method === "pass" ? passId : void 0,
16661
+ customerMembershipId: method === "membership" ? membershipId : void 0,
16662
+ bundleProductId,
16663
+ claimToken: options.claimToken ?? void 0,
16664
+ guests: guestsPayload
16665
+ });
16666
+ const needsStripeCheckout = !result.alreadyRegistered && result.status === "confirmed" && result.pendingPayment && (method === "stripe" || method === "pass_bundle" || method === "membership_bundle");
16667
+ if (needsStripeCheckout) {
16668
+ options.setPendingAttendeeId(result.attendeeId);
16669
+ options.setStep("redirecting");
16670
+ const currentUrl = new URL(window.location.href);
16671
+ const successParams = new URLSearchParams(currentUrl.search);
16672
+ successParams.set("registration", "success");
16673
+ const successUrl = `${currentUrl.origin}${currentUrl.pathname}?${successParams.toString()}${currentUrl.hash}`;
16674
+ const cancelParams = new URLSearchParams(currentUrl.search);
16675
+ cancelParams.set("registration", "cancelled");
16676
+ const cancelUrl = `${currentUrl.origin}${currentUrl.pathname}?${cancelParams.toString()}${currentUrl.hash}`;
16677
+ const checkoutType = method === "pass_bundle" ? "pass_bundle" : method === "membership_bundle" ? "membership_bundle" : "event";
16678
+ const checkoutResult = await options.api.createEventCheckout({
16679
+ attendeeId: result.attendeeId,
16680
+ checkoutType,
16681
+ productId: bundleProductId,
16682
+ discountCode: options.discountCode.trim() ? options.discountCode.trim() : void 0,
16683
+ successUrl,
16684
+ cancelUrl
16685
+ });
16686
+ if (checkoutResult.bypassed) {
16687
+ options.setRegistrationResult({ status: "confirmed" });
16688
+ options.setStep("success");
16689
+ return { ok: true, outcome: { kind: "completed" } };
16690
+ }
16691
+ if (!checkoutResult.checkoutUrl) {
16692
+ throw new Error("Checkout URL missing");
16693
+ }
16694
+ const siteId = options.api.config.siteId;
16695
+ if (siteId && submitOccurrenceId) {
16696
+ savePendingRegistration(siteId, submitOccurrenceId, {
16697
+ attendeeId: result.attendeeId,
16698
+ formData: options.formData,
16699
+ ticketsCount: options.ticketsCount,
16700
+ selectedEventId: options.registrationTarget?.selectedEventId ?? null,
16701
+ selectedAttendanceMode: options.selectedAttendanceMode,
16702
+ selectedTicketTypeId: options.selectedTicketTypeId ?? null,
16703
+ paymentSelection: selectionSnapshot
16704
+ });
16705
+ }
16706
+ if (submitOptions?.redirect === "manual") {
16707
+ return {
16708
+ ok: true,
16709
+ outcome: {
16710
+ kind: "checkout_redirect",
16711
+ checkoutUrl: checkoutResult.checkoutUrl
16712
+ }
16713
+ };
16714
+ }
16715
+ window.location.href = checkoutResult.checkoutUrl;
16716
+ return { ok: true, outcome: { kind: "checkout_redirect", checkoutUrl: checkoutResult.checkoutUrl } };
16717
+ }
16718
+ if (result.alreadyRegistered) {
16719
+ const title = result.status === "waitlist" ? "Already waitlisted" : "Already registered";
16720
+ const fallbackMessage = result.status === "waitlist" ? "You are already on the waitlist for this event." : "You are already registered for this event.";
16721
+ options.setRegistrationResult({
16722
+ status: result.status,
16723
+ variant: "info",
16724
+ title,
16725
+ message: result.message ?? fallbackMessage
16726
+ });
16727
+ } else if (result.status === "waitlist") {
16728
+ const waitlistMessage = typeof result.waitlistPosition === "number" ? `You've been added to the waitlist (position ${result.waitlistPosition}).` : "You've been added to the waitlist.";
16729
+ options.setRegistrationResult({
16730
+ status: "waitlist",
16731
+ title: "Added to waitlist",
16732
+ message: result.message ?? waitlistMessage
16733
+ });
16734
+ } else {
16735
+ options.setRegistrationResult({ status: result.status });
16736
+ }
16737
+ options.setStep("success");
16738
+ return { ok: true, outcome: { kind: "completed" } };
16739
+ } catch (error) {
16740
+ const message = error instanceof Error ? error.message : "Registration failed";
16741
+ options.setErrorMessage(message);
16742
+ options.setStep("error");
16743
+ return {
16744
+ ok: false,
16745
+ reason: "submission-failed",
16746
+ message
16747
+ };
16748
+ }
16749
+ };
16750
+ }
16751
+
16752
+ // ../blocks/src/system/runtime/nodes/event-registration/registrationDerivations.ts
16753
+ function eventMatchesOccurrenceId(event, occurrenceId) {
16754
+ return event.registrationOccurrenceId === occurrenceId || event.publicEventId === occurrenceId;
16755
+ }
16756
+ function findEventByOccurrenceId(events, occurrenceId) {
16757
+ return events.find((event) => eventMatchesOccurrenceId(event, occurrenceId)) ?? null;
16758
+ }
16759
+ function findPreSelectedEvent(input) {
16760
+ const occurrenceContext = input.occurrenceContext;
16761
+ if (!occurrenceContext) {
16762
+ return null;
16763
+ }
16764
+ const contextDate = getBookingLocalDateKey(toScheduledBookingDateTime({
16765
+ startsAt: occurrenceContext.startsAt,
16766
+ timeZone: occurrenceContext.timeZone
16767
+ }));
16768
+ return input.scopedEvents.find(
16769
+ (event) => eventMatchesOccurrenceId(event, occurrenceContext.id) || getBookingLocalDateKey(toScheduledBookingDateTime({
16770
+ startsAt: event.startsAt,
16771
+ timeZone: event.timeZone
16772
+ })) === contextDate
16773
+ ) ?? null;
16774
+ }
16775
+ function resolveRegistrationTarget(input) {
16776
+ const occurrenceId = input.occurrenceContext?.id ?? input.selectedEvent?.registrationOccurrenceId ?? null;
16777
+ if (!occurrenceId) {
16778
+ return null;
16779
+ }
16780
+ return {
16781
+ occurrenceId,
16782
+ selectedEventId: input.selectedEvent?.publicEventId ?? null
16783
+ };
16784
+ }
16785
+ function resolveEventRequiresPayment(input) {
16786
+ if (input.eligibility) {
16787
+ return input.eligibility.requiresPayment;
16788
+ }
16789
+ if (input.selectedTicketType) {
16790
+ return input.selectedTicketType.priceAmount > 0;
16791
+ }
16792
+ if (!input.event) {
16793
+ return false;
16794
+ }
16795
+ return publicEventPricingType(resolveRuntimeEventPricing(input.event)) !== "free";
16796
+ }
16797
+ function resolveDiscountContext(input) {
16798
+ const selection = input.paymentSelection.method ? input.paymentSelection : null;
16799
+ if (!input.event) {
16800
+ return null;
16801
+ }
16802
+ if (selection?.method === "pass_bundle" && selection.bundlePassId) {
16803
+ return { type: "pass", passId: selection.bundlePassId };
16804
+ }
16805
+ if (selection?.method === "membership_bundle" && selection.bundleMembershipId) {
16806
+ return { type: "membership", membershipId: selection.bundleMembershipId };
16807
+ }
16808
+ if (!input.eventRequiresPayment) {
16809
+ return null;
16810
+ }
16811
+ if (selection?.method && selection.method !== "stripe") {
16812
+ return null;
16813
+ }
16814
+ return {
16815
+ type: "event",
16816
+ eventSeriesId: input.event.seriesId,
16817
+ eventCategoryId: input.event.eventCategory?.id ?? null,
16818
+ ticketsCount: input.ticketsCount
16819
+ };
16820
+ }
16821
+
16822
+ // ../blocks/src/system/runtime/nodes/event-registration/registrationEventAdapter.ts
16823
+ function toRegistrationEvent(event) {
16824
+ return {
16825
+ ...event,
16826
+ pricing: resolveRuntimeEventPricing(event),
16827
+ publicEventId: event.id,
16828
+ registrationOccurrenceId: event.occurrenceId
16829
+ };
16830
+ }
16831
+ function toRegistrationEvents(events) {
16832
+ return events.map(toRegistrationEvent);
16833
+ }
16834
+
16835
+ // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
16836
+ function useEventRegistrationWizard(options) {
16837
+ const api = useBlockApi();
16838
+ const registrationEvents = useMemo6(
16839
+ () => toRegistrationEvents(options.events ?? []),
16840
+ [options.events]
16841
+ );
16842
+ const scopedEvents = useMemo6(() => {
16843
+ const allEvents = registrationEvents;
16844
+ if (options.occurrenceContext?.seriesId) {
16845
+ return allEvents.filter((event) => event.seriesId === options.occurrenceContext?.seriesId);
16846
+ }
16847
+ const entrySlug = options.contentEntry?.slug;
16848
+ const entryContentType = options.contentEntry?.contentTypeSlug;
16849
+ if (entrySlug && entryContentType && isEventContentType(entryContentType)) {
16850
+ return allEvents.filter((event) => event.slug === entrySlug);
16851
+ }
16852
+ return allEvents;
16853
+ }, [registrationEvents, options.occurrenceContext?.seriesId, options.contentEntry?.slug, options.contentEntry?.contentTypeSlug]);
16854
+ const preSelectedEvent = useMemo6(
16855
+ () => findPreSelectedEvent({
16856
+ scopedEvents,
16857
+ occurrenceContext: options.occurrenceContext
16858
+ }),
16859
+ [scopedEvents, options.occurrenceContext]
16860
+ );
16861
+ const hasPreSelectedContext = !!(options.occurrenceContext || preSelectedEvent);
16862
+ const [flowState, dispatchFlow] = useReducer5(
16863
+ registrationFlowReducer,
16864
+ hasPreSelectedContext,
16865
+ createInitialRegistrationFlowState
16866
+ );
16867
+ const step = flowState.step;
16868
+ const ticketsCount = flowState.ticketsCount;
16869
+ const paymentSelection = flowState.paymentSelection;
16870
+ const [selectedEvent, setSelectedEvent] = useState8(preSelectedEvent ?? null);
16871
+ const [formData, setFormData] = useState8({ name: "", email: "", phone: "", notes: "" });
16872
+ const [errors, setErrors] = useState8({});
16873
+ const [guests, setGuests] = useState8([]);
16874
+ const [guestErrors, setGuestErrors] = useState8({});
16875
+ const [guestSectionShake, setGuestSectionShake] = useState8(false);
16876
+ const [selectedAttendanceMode, setSelectedAttendanceMode] = useState8(
16877
+ preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
16878
+ );
16879
+ const [selectedTicketTypeId, setSelectedTicketTypeId] = useState8(null);
16880
+ const [registrationResult, setRegistrationResult] = useState8(null);
16881
+ const [errorMessage, setErrorMessage] = useState8("");
16882
+ const [altchaSolution, setAltchaSolution] = useState8(null);
16883
+ const { authState: portalAuthState, profile: portalProfile } = usePortalAuth();
16884
+ const waitlistClaim = useWaitlistClaim();
16885
+ const [showMagicLinkModal, setShowMagicLinkModal] = useState8(false);
16886
+ const [pendingAttendeeId, setPendingAttendeeId] = useState8(null);
16887
+ const [paymentStepState, setPaymentStepState] = useState8({
16888
+ status: "loading",
16889
+ canContinue: false,
16890
+ buttonText: "Continue",
16891
+ showLoginPrompt: false
16892
+ });
16893
+ useEffect11(() => {
16894
+ if (portalAuthState !== "authenticated" || !portalProfile) return;
16895
+ setFormData((prev) => ({
16896
+ ...prev,
16897
+ email: portalProfile.email,
16898
+ name: prev.name || portalProfile.name,
16899
+ phone: prev.phone || portalProfile.phone || ""
16900
+ }));
16901
+ }, [portalAuthState, portalProfile]);
16902
+ const handleLogout = () => logoutPortal(options.anchorId);
16903
+ const registrationTarget = useMemo6(
16904
+ () => resolveRegistrationTarget({
16905
+ occurrenceContext: options.occurrenceContext,
16906
+ selectedEvent
16907
+ }),
16908
+ [options.occurrenceContext, selectedEvent]
16909
+ );
16910
+ const occurrenceId = registrationTarget?.occurrenceId ?? "";
16911
+ const eligibilityResult = useEligibility({
16912
+ enabled: portalAuthState === "authenticated" || step === "enter-details" || step === "select-payment",
16913
+ occurrenceId,
16914
+ attendanceMode: selectedAttendanceMode,
16915
+ ticketTypeId: selectedTicketTypeId,
16916
+ email: formData.email,
16917
+ ticketsCount
16918
+ });
16919
+ const existingRegistrationResult = useExistingEventRegistration({
16920
+ isAuthenticated: portalAuthState === "authenticated",
16921
+ occurrenceId
16922
+ });
16923
+ const eligibility = eligibilityResult.eligibility;
16924
+ const eligibilityLoading = eligibilityResult.isLoading;
16925
+ const eligibilityError = eligibilityResult.error;
16926
+ const setStep = useCallback6((nextStep) => {
16927
+ dispatchFlow({ type: "set-step", step: nextStep });
16928
+ }, []);
16929
+ const setTicketsCount = useCallback6((nextTicketsCount) => {
16930
+ dispatchFlow({
16931
+ type: "set-tickets-count",
16932
+ ticketsCount: waitlistClaim.claim ? 1 : nextTicketsCount
16933
+ });
16934
+ }, [waitlistClaim.claim]);
16935
+ useEffect11(() => {
16936
+ const claim = waitlistClaim.claim;
16937
+ if (!claim || claim.subject.kind !== "event_occurrence") return;
16938
+ const occurrenceId2 = claim.subject.occurrenceId;
16939
+ const matchedEvent = findEventByOccurrenceId(scopedEvents, occurrenceId2);
16940
+ if (!matchedEvent && options.occurrenceContext?.id !== occurrenceId2) {
16941
+ setErrorMessage("This waitlist claim is for a different event.");
16942
+ setStep("error");
16943
+ return;
16944
+ }
16945
+ if (matchedEvent) {
16946
+ setSelectedEvent(matchedEvent);
16947
+ }
16948
+ setSelectedAttendanceMode(claim.subject.attendanceMode);
16949
+ dispatchFlow({ type: "set-tickets-count", ticketsCount: 1 });
16950
+ setFormData((prev) => ({
16951
+ ...prev,
16952
+ email: claim.prefill.email,
16953
+ name: claim.prefill.name,
16954
+ phone: claim.prefill.phone ?? "",
16955
+ notes: claim.prefill.notes ?? ""
16956
+ }));
16957
+ setGuests(
16958
+ claim.prefill.guests.map((guest) => ({
16959
+ name: guest.name,
16960
+ email: guest.email ?? "",
16961
+ phone: guest.phone ?? ""
16962
+ }))
16963
+ );
16964
+ }, [waitlistClaim.claim, scopedEvents, options.occurrenceContext?.id, setStep]);
16965
+ useEffect11(() => {
16966
+ if (waitlistClaim.requiresPortalLogin) return;
16967
+ if (!waitlistClaim.error) return;
16968
+ setErrorMessage(waitlistClaim.error);
16969
+ setStep("error");
16970
+ }, [waitlistClaim.error, waitlistClaim.requiresPortalLogin, setStep]);
16971
+ useEffect11(() => {
16972
+ if (!waitlistClaim.requiresPortalLogin) return;
16973
+ if (portalAuthState !== "unauthenticated") return;
16974
+ setShowMagicLinkModal(true);
16975
+ }, [portalAuthState, waitlistClaim.requiresPortalLogin]);
16976
+ useEffect11(() => {
16977
+ if (portalAuthState === "authenticated" || !waitlistClaim.requiresPortalLogin) {
16978
+ setShowMagicLinkModal(false);
16979
+ }
16980
+ }, [portalAuthState, waitlistClaim.requiresPortalLogin]);
16981
+ useEffect11(() => {
16982
+ dispatchFlow({ type: "set-authenticated", isAuthenticated: portalAuthState === "authenticated" });
16983
+ }, [portalAuthState]);
16984
+ useEffect11(() => {
16985
+ const event = selectedEvent ?? preSelectedEvent;
16986
+ if (!event) {
16987
+ if (selectedAttendanceMode !== null) {
16988
+ setSelectedAttendanceMode(null);
16989
+ }
16990
+ return;
16991
+ }
16992
+ const deliveryMode = event.deliveryMode ?? "in_person";
16993
+ if (deliveryMode === "online") {
16994
+ if (selectedAttendanceMode !== "online") {
16995
+ setSelectedAttendanceMode("online");
16996
+ }
16997
+ return;
16998
+ }
16999
+ if (deliveryMode === "in_person") {
17000
+ if (selectedAttendanceMode !== "in_person") {
17001
+ setSelectedAttendanceMode("in_person");
17002
+ }
17003
+ return;
17004
+ }
17005
+ if (selectedAttendanceMode && (event.attendanceModes ?? []).some((mode) => mode.mode === selectedAttendanceMode)) {
17006
+ return;
17007
+ }
17008
+ setSelectedAttendanceMode(null);
17009
+ }, [preSelectedEvent, selectedAttendanceMode, selectedEvent]);
17010
+ useEffect11(() => {
17011
+ dispatchFlow({ type: "eligibility-updated", eligibility });
17012
+ }, [eligibility]);
17013
+ const verification = useEventRegistrationStripeReturn({
17014
+ api,
17015
+ events: registrationEvents,
17016
+ occurrenceId,
17017
+ step,
17018
+ pendingAttendeeId,
17019
+ setFormData,
17020
+ setTicketsCount,
17021
+ setSelectedEvent,
17022
+ setSelectedAttendanceMode,
17023
+ setSelectedTicketTypeId,
17024
+ setPaymentSelection: (selection) => dispatchFlow({ type: "set-manual-payment-selection", selection }),
17025
+ setPendingAttendeeId,
17026
+ setStep,
17027
+ setRegistrationResult: (result) => setRegistrationResult(result),
17028
+ setErrorMessage
17029
+ });
17030
+ const requireGuestDetails = useMemo6(() => {
17031
+ const event = selectedEvent ?? preSelectedEvent;
17032
+ return event?.requireGuestDetails === true;
17033
+ }, [selectedEvent, preSelectedEvent]);
17034
+ const visibleTicketTypes = useMemo6(
17035
+ () => getVisibleTicketTypes({
17036
+ event: selectedEvent ?? preSelectedEvent,
17037
+ eligibility,
17038
+ selectedAttendanceMode
17039
+ }),
17040
+ [selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility]
17041
+ );
17042
+ const selectedTicketType = useMemo6(
17043
+ () => findSelectedTicketType({
17044
+ event: selectedEvent ?? preSelectedEvent,
17045
+ eligibility,
17046
+ selectedTicketTypeId,
17047
+ selectedAttendanceMode
17048
+ }),
17049
+ [selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility, selectedTicketTypeId]
17050
+ );
17051
+ const ticketTypeSelectionRequired = useMemo6(() => {
17052
+ const event = selectedEvent ?? preSelectedEvent;
17053
+ if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
17054
+ return false;
17055
+ }
17056
+ if ((event.deliveryMode ?? "in_person") === "hybrid" && !selectedAttendanceMode) {
17057
+ return false;
17058
+ }
17059
+ const selectedModeAvailability = selectedAttendanceMode ? (event.attendanceModes ?? []).find((mode) => mode.mode === selectedAttendanceMode) ?? null : null;
17060
+ const canJoinWaitlist = (selectedModeAvailability?.availableSpots ?? event.availableSpots) === 0 && (selectedModeAvailability?.waitlistEnabled ?? event.waitlistEnabled) === true;
17061
+ return !canJoinWaitlist;
17062
+ }, [selectedAttendanceMode, selectedEvent, preSelectedEvent]);
17063
+ const hasValidSelectedTicketType = !ticketTypeSelectionRequired || Boolean(
17064
+ selectedTicketType && selectedTicketType.availability.kind === "available"
17065
+ );
17066
+ useEffect11(() => {
17067
+ const event = selectedEvent ?? preSelectedEvent;
17068
+ if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
17069
+ if (selectedTicketTypeId !== null) {
17070
+ setSelectedTicketTypeId(null);
17071
+ }
17072
+ return;
17073
+ }
17074
+ const implicitTicketType = getImplicitSingleAvailableTicketType(visibleTicketTypes);
17075
+ if (implicitTicketType && selectedTicketTypeId !== implicitTicketType.id) {
17076
+ setSelectedTicketTypeId(implicitTicketType.id);
17077
+ return;
17078
+ }
17079
+ if (selectedTicketTypeId && !visibleTicketTypes.some((ticketType) => ticketType.id === selectedTicketTypeId)) {
17080
+ setSelectedTicketTypeId(null);
17081
+ }
17082
+ }, [selectedEvent, preSelectedEvent, selectedTicketTypeId, visibleTicketTypes]);
17083
+ useEffect11(() => {
17084
+ if (!requireGuestDetails) {
17085
+ if (guests.length > 0) setGuests([]);
17086
+ return;
17087
+ }
17088
+ const guestCount = ticketsCount - 1;
17089
+ if (guestCount <= 0) {
17090
+ if (guests.length > 0) setGuests([]);
17091
+ return;
17092
+ }
17093
+ if (guests.length !== guestCount) {
17094
+ const newGuests = [];
17095
+ for (let i = 0; i < guestCount; i++) {
17096
+ newGuests.push(guests[i] ?? { name: "", email: "", phone: "" });
17097
+ }
17098
+ setGuests(newGuests);
17099
+ }
17100
+ }, [ticketsCount, requireGuestDetails, guests]);
17101
+ const validateForm = () => {
17102
+ const newErrors = validateFormData2(formData);
17103
+ setErrors(newErrors);
17104
+ const newGuestErrors = {};
17105
+ if (requireGuestDetails && guests.length > 0) {
17106
+ for (const [index, guest] of guests.entries()) {
17107
+ if (!guest.name.trim()) {
17108
+ newGuestErrors[index] = { name: "Name is required" };
17109
+ }
17110
+ }
17111
+ }
17112
+ setGuestErrors(newGuestErrors);
17113
+ return Object.keys(newErrors).length === 0 && Object.keys(newGuestErrors).length === 0;
17114
+ };
17115
+ const handleGuestShakeEnd = () => {
17116
+ setGuestSectionShake(false);
17117
+ };
17118
+ const eventRequiresPayment = useMemo6(
17119
+ () => resolveEventRequiresPayment({
17120
+ eligibility,
17121
+ selectedTicketType,
17122
+ event: selectedEvent ?? preSelectedEvent
17123
+ }),
17124
+ [eligibility, selectedTicketType, selectedEvent, preSelectedEvent]
17125
+ );
17126
+ const handleDetailsComplete = async () => {
17127
+ if (ticketTypeSelectionRequired && !hasValidSelectedTicketType) {
17128
+ setErrorMessage("Select a ticket type to continue.");
17129
+ setStep("error");
17130
+ return;
17131
+ }
17132
+ if (!validateForm()) {
17133
+ setGuestSectionShake(true);
17134
+ return;
17135
+ }
17136
+ if (waitlistClaim.claim === null && eligibility?.isFull && !eligibility.canJoinWaitlist) {
17137
+ setErrorMessage("This event is sold out.");
17138
+ setStep("error");
17139
+ return;
17140
+ }
17141
+ const shouldCollectPayment = !eligibility?.canJoinWaitlist && requiresPaymentStep({ eventRequiresPayment, paymentSelection });
17142
+ if (shouldCollectPayment) {
17143
+ setStep("select-payment");
17144
+ return;
17145
+ }
17146
+ const submitPlan = resolveEventRegistrationSubmitPlan({
17147
+ paymentSelection,
17148
+ eventRequiresPayment,
17149
+ canJoinWaitlist: eligibility?.canJoinWaitlist
17150
+ });
17151
+ if (!submitPlan.ok) {
17152
+ setErrorMessage(submitPlan.message);
17153
+ setStep("error");
17154
+ return;
17155
+ }
17156
+ await handleSubmit(
17157
+ submitPlan.args.method,
17158
+ submitPlan.args.passId,
17159
+ submitPlan.args.membershipId,
17160
+ submitPlan.args.selection
17161
+ );
17162
+ };
17163
+ const handlePaymentSelect = async () => {
17164
+ const submitPlan = resolveEventRegistrationSubmitPlan({
17165
+ paymentSelection,
17166
+ eventRequiresPayment,
17167
+ canJoinWaitlist: eligibility?.canJoinWaitlist
17168
+ });
17169
+ if (!submitPlan.ok) {
17170
+ setErrorMessage(submitPlan.message);
17171
+ setStep("error");
17172
+ return;
17173
+ }
17174
+ await handleSubmit(
17175
+ submitPlan.args.method,
17176
+ submitPlan.args.passId,
17177
+ submitPlan.args.membershipId,
17178
+ submitPlan.args.selection
17179
+ );
17180
+ };
17181
+ const handleUseCardInsteadOfPass = () => {
17182
+ dispatchFlow({ type: "use-card-instead-of-pass" });
17183
+ };
17184
+ const handleBookForSomeoneElse = () => {
17185
+ if (portalAuthState === "authenticated") {
17186
+ handleLogout();
17187
+ return;
17188
+ }
17189
+ setStep("select-tickets");
17190
+ };
17191
+ const discountContext = useMemo6(
17192
+ () => resolveDiscountContext({
17193
+ paymentSelection,
17194
+ event: selectedEvent ?? preSelectedEvent,
17195
+ eventRequiresPayment,
17196
+ ticketsCount
17197
+ }),
17198
+ [eventRequiresPayment, paymentSelection, selectedEvent, preSelectedEvent, ticketsCount]
17199
+ );
17200
+ const discountSubtotalCents = useMemo6(() => {
17201
+ if (discountContext?.type !== "event") return void 0;
17202
+ const event = selectedEvent ?? preSelectedEvent;
17203
+ const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
17204
+ return Math.max(0, eventPriceCents * ticketsCount);
17205
+ }, [discountContext, selectedTicketType, eligibility, selectedEvent, preSelectedEvent, ticketsCount]);
17206
+ const discountUi = useDiscountCodeUi({ api, discountContext, subtotalCents: discountSubtotalCents });
17207
+ const selectionMethod = paymentSelection.method;
17208
+ const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
17209
+ const handleSubmit = useEventRegistrationSubmit({
17210
+ api,
17211
+ registrationTarget,
17212
+ selectedAttendanceMode,
17213
+ selectedTicketTypeId,
17214
+ ticketsCount,
17215
+ formData,
17216
+ altchaSolution,
17217
+ requireGuestDetails,
17218
+ guests,
17219
+ discountCode: discountUi.discountCode,
17220
+ claimToken: waitlistClaim.token,
17221
+ setPendingAttendeeId: (id) => setPendingAttendeeId(id),
17222
+ setStep,
17223
+ setRegistrationResult: (result) => setRegistrationResult(result),
17224
+ setErrorMessage
17225
+ });
17226
+ const handleEventSelect = (event) => {
17227
+ setSelectedEvent(event);
17228
+ setSelectedAttendanceMode(
17229
+ (event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person"
17230
+ );
17231
+ setSelectedTicketTypeId(null);
17232
+ dispatchFlow({ type: "event-changed", hasPreSelectedContext: true });
17233
+ };
17234
+ const handleRetry = () => {
17235
+ dispatchFlow({ type: "reset", hasPreSelectedContext });
17236
+ setSelectedTicketTypeId(null);
17237
+ setSelectedAttendanceMode(
17238
+ preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
17239
+ );
17240
+ setErrorMessage("");
17241
+ setPendingAttendeeId(null);
17242
+ };
17243
+ const handlePaymentStepStateChange = useCallback6((state) => {
17244
+ setPaymentStepState(state);
17245
+ }, []);
17246
+ const handlePaymentSelectionChange = useCallback6((selection) => {
17247
+ dispatchFlow({ type: "set-manual-payment-selection", selection });
17248
+ }, []);
17249
+ const hasEligibility = eligibility !== null && (eligibility.eligiblePasses.length > 0 || eligibility.eligibleMemberships.length > 0);
17250
+ const hasMembershipEligibility = eligibility !== null && eligibility.eligibleMemberships.length > 0;
17251
+ const isMembershipFastTrack = portalAuthState === "authenticated" && hasMembershipEligibility && ticketsCount === 1 && paymentSelection.method === "membership";
17252
+ return {
17253
+ api,
17254
+ anchorId: options.anchorId,
17255
+ occurrenceContext: options.occurrenceContext,
17256
+ registrationTarget,
17257
+ contentEntry: options.contentEntry,
17258
+ events: options.events,
17259
+ maxTicketsNum: waitlistClaim.claim ? 1 : options.maxTicketsNum,
17260
+ scopedEvents,
17261
+ preSelectedEvent,
17262
+ hasPreSelectedContext,
17263
+ step,
17264
+ setStep,
17265
+ selectedEvent,
17266
+ setSelectedEvent,
17267
+ ticketsCount,
17268
+ setTicketsCount,
17269
+ selectedAttendanceMode,
17270
+ setSelectedAttendanceMode,
17271
+ selectedTicketTypeId,
17272
+ setSelectedTicketTypeId,
17273
+ selectedTicketType,
17274
+ visibleTicketTypes,
17275
+ ticketTypeSelectionRequired,
17276
+ hasValidSelectedTicketType,
17277
+ eventRequiresPayment,
17278
+ formData,
17279
+ setFormData,
17280
+ errors,
17281
+ guests,
17282
+ setGuests,
17283
+ guestErrors,
17284
+ guestSectionShake,
17285
+ handleGuestShakeEnd,
17286
+ registrationResult,
17287
+ errorMessage,
17288
+ altchaSolution,
17289
+ setAltchaSolution,
17290
+ portalAuthState,
17291
+ portalProfile,
17292
+ showMagicLinkModal,
17293
+ setShowMagicLinkModal,
17294
+ handleLogout,
17295
+ paymentStepState,
17296
+ handlePaymentStepStateChange,
17297
+ handlePaymentSelectionChange,
17298
+ paymentSelection,
17299
+ isMembershipFastTrack,
17300
+ waitlistClaim,
17301
+ eligibility,
17302
+ eligibilityLoading,
17303
+ eligibilityError,
17304
+ existingRegistration: existingRegistrationResult.registration,
17305
+ existingRegistrationLoading: existingRegistrationResult.isLoading,
17306
+ existingRegistrationState: existingRegistrationResult.state,
17307
+ hasEligibility,
17308
+ hasMembershipEligibility,
17309
+ requireGuestDetails,
17310
+ discountCode: discountUi.discountCode,
17311
+ setDiscountCode: discountUi.setDiscountCode,
17312
+ discountUiOpen: discountUi.discountUiOpen,
17313
+ setDiscountUiOpen: discountUi.setDiscountUiOpen,
17314
+ discountsAvailable: discountUi.discountsAvailable,
17315
+ manualCodeEntryAllowed: discountUi.manualCodeEntryAllowed,
17316
+ autoAppliedDiscount: discountUi.autoAppliedDiscount,
17317
+ discountsAvailableLoading: discountUi.discountsAvailableLoading,
17318
+ discountContext,
17319
+ shouldShowDiscountToggle,
17320
+ verification,
17321
+ handleDetailsComplete,
17322
+ handlePaymentSelect,
17323
+ handleUseCardInsteadOfPass,
17324
+ handleBookForSomeoneElse,
17325
+ handleSubmit,
17326
+ handleEventSelect,
17327
+ handleRetry
17328
+ };
17329
+ }
17330
+
17331
+ // ../theme-core/src/header/navDropdownSizing.ts
17332
+ var NAV_DROPDOWN_MIN_WIDTH_REM = 12;
17333
+ var NAV_DROPDOWN_MAX_WIDTH_REM = 22;
17334
+ var NAV_DROPDOWN_VIEWPORT_GUTTER_REM = 1;
17335
+ var NAV_DROPDOWN_SHIFT_PROPERTY = "--nav-dropdown-shift-x";
17336
+ var NAV_DROPDOWN_MAX_WIDTH_CSS = `min(${NAV_DROPDOWN_MAX_WIDTH_REM}rem, calc(100vw - ${NAV_DROPDOWN_VIEWPORT_GUTTER_REM * 2}rem))`;
17337
+ var NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
17338
+ `min-width: ${NAV_DROPDOWN_MIN_WIDTH_REM}rem;`,
17339
+ `width: max-content;`,
17340
+ `max-width: ${NAV_DROPDOWN_MAX_WIDTH_CSS};`,
17341
+ `transform: translateX(var(${NAV_DROPDOWN_SHIFT_PROPERTY}, 0px));`
17342
+ ];
17343
+
17344
+ // ../theme-core/src/ClientThemeScope.tsx
17345
+ import { useMemo as useMemo7 } from "react";
17346
+
17347
+ // ../theme-core/src/navigation/presets.ts
17348
+ var NAV_LINK_PRESETS = {
17349
+ /**
17350
+ * Minimal - subtle color change on hover
17351
+ */
17352
+ minimal: {
17353
+ name: "Minimal",
17354
+ typography: "body",
17355
+ fontWeight: "medium",
17356
+ textTransform: "none",
17357
+ italic: false,
17358
+ colorToken: "text",
17359
+ hoverColorToken: "primary",
17360
+ padding: "none",
17361
+ borderRadius: "none",
17362
+ effects: {
17363
+ hover: [
17364
+ { effectId: "text-color-change", options: { hoverColorToken: "primary" } }
17365
+ ]
17366
+ }
17367
+ },
17368
+ /**
17369
+ * Underline - static underline appears on hover
17370
+ */
17371
+ underline: {
17372
+ name: "Underline",
17373
+ typography: "body",
17374
+ fontWeight: "medium",
17375
+ textTransform: "none",
17376
+ italic: false,
17377
+ colorToken: "text",
17378
+ padding: "none",
17379
+ borderRadius: "none",
17380
+ effects: {
17381
+ hover: [{ effectId: "nav-underline", options: { style: "static" } }]
17382
+ }
17383
+ },
17384
+ /**
17385
+ * Underline Grow - animated underline grows from center on hover
17386
+ */
17387
+ "underline-grow": {
17388
+ name: "Underline Grow",
17389
+ typography: "body",
17390
+ fontWeight: "medium",
17391
+ textTransform: "none",
17392
+ italic: false,
17393
+ colorToken: "text",
17394
+ padding: "none",
17395
+ borderRadius: "none",
17396
+ effects: {
17397
+ hover: [{ effectId: "nav-underline", options: { style: "grow" } }]
17398
+ }
17399
+ },
17400
+ /**
17401
+ * Capsule - pill-shaped background on hover
17402
+ */
17403
+ capsule: {
17404
+ name: "Capsule",
17405
+ typography: "body",
17406
+ fontWeight: "medium",
17407
+ textTransform: "none",
17408
+ italic: false,
17409
+ colorToken: "text",
17410
+ padding: "compact",
17411
+ borderRadius: "full",
17412
+ effects: {
17413
+ hover: [
17414
+ {
17415
+ effectId: "background-on-hover-alpha",
17416
+ options: { colorToken: "primary", opacity: 10 }
17417
+ }
17418
+ ],
17419
+ active: [
17420
+ {
17421
+ effectId: "background-on-hover-alpha",
17422
+ options: { colorToken: "primary", opacity: 15 }
17423
+ }
17424
+ ]
17425
+ }
17426
+ },
17427
+ /**
17428
+ * Solid - solid background color on hover
17429
+ */
17430
+ solid: {
17431
+ name: "Solid",
17432
+ typography: "body",
17433
+ fontWeight: "medium",
17434
+ textTransform: "none",
17435
+ italic: false,
17436
+ colorToken: "text",
17437
+ padding: "compact",
17438
+ borderRadius: "none",
17439
+ effects: {
17440
+ hover: [
17441
+ {
17442
+ effectId: "background-on-hover",
17443
+ options: { colorToken: "primary", textColorToken: "primaryForeground" }
17444
+ }
17445
+ ],
17446
+ active: [
17447
+ {
17448
+ effectId: "background-on-hover",
17449
+ options: { colorToken: "primary", textColorToken: "primaryForeground" }
17450
+ }
17451
+ ]
17452
+ }
17453
+ },
17454
+ /**
17455
+ * Scale - gentle scale-up on hover
17456
+ */
17457
+ scale: {
17458
+ name: "Scale",
17459
+ typography: "body",
17460
+ fontWeight: "medium",
17461
+ textTransform: "none",
17462
+ italic: false,
17463
+ colorToken: "text",
17464
+ padding: "none",
17465
+ borderRadius: "none",
17466
+ effects: {
17467
+ hover: [{ effectId: "scale-up", options: { scale: 1.05 } }]
17468
+ }
17469
+ },
17470
+ /**
17471
+ * Frosted - semi-transparent glass-like background
17472
+ */
17473
+ frosted: {
17474
+ name: "Frosted",
17475
+ typography: "body",
17476
+ fontWeight: "medium",
17477
+ textTransform: "none",
17478
+ italic: false,
17479
+ colorToken: "text",
17480
+ padding: "compact",
17481
+ borderRadius: "md",
17482
+ effects: {
17483
+ base: [{ effectId: "nav-frosted-base" }],
17484
+ hover: [{ effectId: "nav-frosted-hover" }],
17485
+ active: [{ effectId: "nav-frosted-active" }]
17486
+ }
17487
+ }
17488
+ };
17489
+ var NAV_LINK_PRESET_IDS = Object.keys(NAV_LINK_PRESETS);
17490
+
17491
+ // ../theme-core/src/layout/generateLayoutCss.ts
17492
+ var classicWaveTransitionMask = svgDataUrl(
17493
+ "<svg viewBox='0 0 1440 72' xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='none'><path d='M0 72V46C130 55 260 24 420 30C590 36 690 62 860 42C1035 21 1160 47 1305 36C1365 31 1415 33 1440 38V72H0Z' fill='white'/></svg>"
17494
+ );
17495
+ var balancedWaveTransitionMask = svgDataUrl(
17496
+ "<svg viewBox='0 0 1440 72' xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='none'><path d='M0 72V42C120 24 240 24 360 42C480 60 600 60 720 42C840 24 960 24 1080 42C1200 60 1320 60 1440 42V72H0Z' fill='white'/></svg>"
17497
+ );
17498
+ var gentleWaveTransitionMask = svgDataUrl(
17499
+ "<svg viewBox='0 0 1440 72' xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='none'><path d='M0 72V43C180 32 300 32 480 43C660 54 780 54 960 43C1140 32 1260 32 1440 43V72H0Z' fill='white'/></svg>"
17500
+ );
17501
+ var boldWaveTransitionMask = svgDataUrl(
17502
+ "<svg viewBox='0 0 1440 72' xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='none'><path d='M0 72V44C90 14 270 14 360 44C450 74 630 74 720 44C810 14 990 14 1080 44C1170 74 1350 74 1440 44V72H0Z' fill='white'/></svg>"
17503
+ );
17504
+ var driftWaveTransitionMask = svgDataUrl(
14518
17505
  "<svg viewBox='0 0 1440 72' xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='none'><path d='M0 72V39C115 31 205 54 340 48C505 41 610 16 760 33C920 51 1015 64 1160 44C1280 27 1375 35 1440 50V72H0Z' fill='white'/></svg>"
14519
17506
  );
14520
17507
  function svgDataUrl(svg) {
@@ -14533,6 +17520,11 @@ ${root} {
14533
17520
  --er-event-card-bg: rgb(var(--tb-surface));
14534
17521
  --er-event-card-border-width: var(--rb-border-width, 1px);
14535
17522
  --er-event-card-hover-opacity: 1;
17523
+ --er-control-bg: rgb(var(--tb-background, var(--tb-surface)));
17524
+ --er-control-text: rgb(var(--tb-foreground, var(--tb-text)));
17525
+ --er-radius: var(--rb-block-radius);
17526
+ --er-surface-muted: rgba(var(--tb-muted, 241 245 249), 0.42);
17527
+ --er-shell-line: rgba(var(--tb-mutedText, 100 116 139), 0.22);
14536
17528
 
14537
17529
  /* Step indicator */
14538
17530
  --er-step-active: rgb(var(--tb-primary));
@@ -15080,15 +18072,285 @@ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
15080
18072
  // ../theme-core/src/ClientThemeScope.tsx
15081
18073
  import { jsx as jsx13 } from "react/jsx-runtime";
15082
18074
 
18075
+ // ../blocks/src/system/runtime/hooks/useHeadlessEventRegistrationFlow.ts
18076
+ import React4, { useCallback as useCallback7, useMemo as useMemo8 } from "react";
18077
+ function HeadlessEventRegistrationProvider({
18078
+ config,
18079
+ children
18080
+ }) {
18081
+ return React4.createElement(BlockApiProvider, { config, children });
18082
+ }
18083
+ function useHeadlessEventRegistrationFlow(options) {
18084
+ return useEventRegistrationController(options).flow;
18085
+ }
18086
+ function useEventRegistrationController(options) {
18087
+ const { wizard } = useEventRegistrationWizardController(options);
18088
+ const steps = useMemo8(
18089
+ () => deriveEventRegistrationSteps({
18090
+ step: wizard.step,
18091
+ hasPreSelectedContext: wizard.hasPreSelectedContext,
18092
+ eventRequiresPayment: wizard.eventRequiresPayment,
18093
+ paymentSelection: wizard.paymentSelection
18094
+ }),
18095
+ [
18096
+ wizard.eventRequiresPayment,
18097
+ wizard.hasPreSelectedContext,
18098
+ wizard.paymentSelection,
18099
+ wizard.step
18100
+ ]
18101
+ );
18102
+ const currentStep = steps.find((step) => step.state === "active") ?? null;
18103
+ const submit = useCallback7(
18104
+ async (submitOptions) => {
18105
+ const plan = resolveEventRegistrationSubmitPlan({
18106
+ paymentSelection: wizard.paymentSelection,
18107
+ eventRequiresPayment: wizard.eventRequiresPayment,
18108
+ canJoinWaitlist: wizard.eligibility?.canJoinWaitlist
18109
+ });
18110
+ if (!plan.ok) {
18111
+ return {
18112
+ ok: false,
18113
+ reason: "blocked",
18114
+ message: plan.message
18115
+ };
18116
+ }
18117
+ return wizard.handleSubmit(
18118
+ plan.args.method,
18119
+ plan.args.passId,
18120
+ plan.args.membershipId,
18121
+ plan.args.selection,
18122
+ submitOptions
18123
+ );
18124
+ },
18125
+ [wizard]
18126
+ );
18127
+ const next = useCallback7(async () => {
18128
+ switch (wizard.step) {
18129
+ case "select-event":
18130
+ if (!wizard.selectedEvent) {
18131
+ return {
18132
+ ok: false,
18133
+ reason: "blocked",
18134
+ message: "Select an event to continue."
18135
+ };
18136
+ }
18137
+ wizard.setStep("select-tickets");
18138
+ return { ok: true };
18139
+ case "select-tickets":
18140
+ if (wizard.ticketTypeSelectionRequired && !wizard.hasValidSelectedTicketType) {
18141
+ return {
18142
+ ok: false,
18143
+ reason: "blocked",
18144
+ message: "Select a ticket type to continue."
18145
+ };
18146
+ }
18147
+ wizard.setStep("enter-details");
18148
+ return { ok: true };
18149
+ case "enter-details":
18150
+ await wizard.handleDetailsComplete();
18151
+ return { ok: true };
18152
+ case "select-payment": {
18153
+ const result = await submit({ redirect: "manual" });
18154
+ return result.ok ? { ok: true } : {
18155
+ ok: false,
18156
+ reason: result.reason === "submission-failed" ? "submission-failed" : "blocked",
18157
+ message: result.message
18158
+ };
18159
+ }
18160
+ case "error":
18161
+ case "success":
18162
+ case "submitting":
18163
+ case "redirecting":
18164
+ case "verifying-payment":
18165
+ case "verifying-timeout":
18166
+ case "payment-failed":
18167
+ return {
18168
+ ok: false,
18169
+ reason: "blocked",
18170
+ message: "This registration step cannot continue."
18171
+ };
18172
+ }
18173
+ }, [submit, wizard]);
18174
+ const back = useCallback7(() => {
18175
+ switch (wizard.step) {
18176
+ case "enter-details":
18177
+ wizard.setStep("select-tickets");
18178
+ return;
18179
+ case "select-payment":
18180
+ wizard.setStep("enter-details");
18181
+ return;
18182
+ case "select-tickets":
18183
+ if (!wizard.hasPreSelectedContext) wizard.setStep("select-event");
18184
+ return;
18185
+ case "select-event":
18186
+ case "error":
18187
+ case "success":
18188
+ case "submitting":
18189
+ case "redirecting":
18190
+ case "verifying-payment":
18191
+ case "verifying-timeout":
18192
+ case "payment-failed":
18193
+ return;
18194
+ }
18195
+ }, [wizard]);
18196
+ const updateAttendee = useCallback7(
18197
+ (values) => {
18198
+ wizard.setFormData(values);
18199
+ },
18200
+ [wizard]
18201
+ );
18202
+ const updateGuests = useCallback7(
18203
+ (guests) => {
18204
+ wizard.setGuests(guests);
18205
+ },
18206
+ [wizard]
18207
+ );
18208
+ const selectPayment = useCallback7(
18209
+ (selection) => {
18210
+ wizard.handlePaymentSelectionChange(toInternalPaymentSelection(selection));
18211
+ },
18212
+ [wizard]
18213
+ );
18214
+ const showSpamProtection = options.spamProtectionEnabled ?? isSpamProtectionEnabled();
18215
+ const spamProtection = showSpamProtection ? {
18216
+ enabled: true,
18217
+ provider: "altcha",
18218
+ challenge: { url: getChallengeUrl(), auto: "onfocus" },
18219
+ solution: wizard.altchaSolution
18220
+ } : { enabled: false };
18221
+ const payment = resolvePaymentModel(wizard);
18222
+ const flow = {
18223
+ status: resolveHeadlessEventRegistrationStatus(wizard),
18224
+ view: resolveHeadlessEventRegistrationView(wizard),
18225
+ steps,
18226
+ currentStep,
18227
+ events: {
18228
+ items: wizard.events,
18229
+ scoped: wizard.scopedEvents,
18230
+ selected: wizard.selectedEvent,
18231
+ preSelected: wizard.preSelectedEvent,
18232
+ hasPreSelectedContext: wizard.hasPreSelectedContext,
18233
+ target: wizard.registrationTarget,
18234
+ occurrenceContext: wizard.occurrenceContext,
18235
+ contentEntry: wizard.contentEntry
18236
+ },
18237
+ tickets: {
18238
+ count: wizard.ticketsCount,
18239
+ max: wizard.maxTicketsNum,
18240
+ selectedTicketTypeId: wizard.selectedTicketTypeId,
18241
+ selectedTicketType: wizard.selectedTicketType,
18242
+ visibleTicketTypes: wizard.visibleTicketTypes,
18243
+ selectionRequired: wizard.ticketTypeSelectionRequired,
18244
+ hasValidSelection: wizard.hasValidSelectedTicketType,
18245
+ eventRequiresPayment: wizard.eventRequiresPayment,
18246
+ selectedAttendanceMode: wizard.selectedAttendanceMode
18247
+ },
18248
+ attendee: {
18249
+ values: wizard.formData,
18250
+ errors: wizard.errors
18251
+ },
18252
+ guests: {
18253
+ required: wizard.requireGuestDetails,
18254
+ items: wizard.guests,
18255
+ errors: wizard.guestErrors,
18256
+ shake: wizard.guestSectionShake
18257
+ },
18258
+ payment,
18259
+ discount: {
18260
+ code: wizard.discountCode,
18261
+ isOpen: wizard.discountUiOpen,
18262
+ available: wizard.discountsAvailable,
18263
+ manualCodeEntryAllowed: wizard.manualCodeEntryAllowed,
18264
+ loading: wizard.discountsAvailableLoading,
18265
+ autoAppliedDiscount: wizard.autoAppliedDiscount
18266
+ },
18267
+ portalAuth: {
18268
+ state: wizard.portalAuthState,
18269
+ profile: wizard.portalProfile,
18270
+ isAuthenticated: wizard.portalAuthState === "authenticated",
18271
+ showMagicLinkModal: wizard.showMagicLinkModal
18272
+ },
18273
+ existingRegistration: {
18274
+ state: resolveExistingRegistrationState(wizard),
18275
+ registration: wizard.existingRegistration
18276
+ },
18277
+ waitlistClaim: wizard.waitlistClaim,
18278
+ spamProtection,
18279
+ terminal: {
18280
+ result: wizard.registrationResult,
18281
+ errorMessage: wizard.errorMessage,
18282
+ verification: wizard.verification
18283
+ },
18284
+ actions: {
18285
+ selectEvent: wizard.handleEventSelect,
18286
+ selectAttendanceMode: wizard.setSelectedAttendanceMode,
18287
+ selectTicketType: wizard.setSelectedTicketTypeId,
18288
+ setTicketsCount: wizard.setTicketsCount,
18289
+ updateAttendee,
18290
+ updateGuests,
18291
+ selectPayment,
18292
+ setDiscountCode: wizard.setDiscountCode,
18293
+ setDiscountOpen: wizard.setDiscountUiOpen,
18294
+ setAltchaSolution: wizard.setAltchaSolution,
18295
+ requestLogin: () => wizard.setShowMagicLinkModal(true),
18296
+ logout: wizard.handleLogout,
18297
+ next,
18298
+ back,
18299
+ submit,
18300
+ retry: wizard.handleRetry
18301
+ }
18302
+ };
18303
+ return { flow, wizard };
18304
+ }
18305
+ function useEventRegistrationWizardController(options) {
18306
+ const maxTicketsNum = normalizeEventRegistrationMaxTickets(options.maxTickets);
18307
+ const wizard = useEventRegistrationWizard({
18308
+ anchorId: options.anchorId ?? "event-registration",
18309
+ occurrenceContext: options.occurrenceContext ?? null,
18310
+ contentEntry: options.contentEntry ?? null,
18311
+ events: [...options.events ?? []],
18312
+ maxTicketsNum
18313
+ });
18314
+ return { wizard };
18315
+ }
18316
+ function resolveExistingRegistrationState(wizard) {
18317
+ switch (wizard.existingRegistrationState.tag) {
18318
+ case "idle":
18319
+ return { tag: "idle", value: wizard.existingRegistration };
18320
+ case "loading":
18321
+ return { tag: "loading", value: wizard.existingRegistration };
18322
+ case "resolved":
18323
+ return { tag: "loaded", value: wizard.existingRegistration };
18324
+ }
18325
+ }
18326
+ function resolvePaymentModel(wizard) {
18327
+ const selection = toHeadlessPaymentSelection(wizard.paymentSelection);
18328
+ if (wizard.step !== "select-payment") {
18329
+ return {
18330
+ kind: "hidden",
18331
+ selection,
18332
+ stepState: wizard.paymentStepState
18333
+ };
18334
+ }
18335
+ const status = wizard.paymentStepState.status;
18336
+ return {
18337
+ kind: status,
18338
+ selection,
18339
+ stepState: wizard.paymentStepState,
18340
+ eligibility: wizard.eligibility,
18341
+ eligibilityError: wizard.eligibilityError
18342
+ };
18343
+ }
18344
+
15083
18345
  // ../blocks/src/system/runtime/hooks/useBookingFormConfig.ts
15084
- import { useState as useState6, useEffect as useEffect8 } from "react";
18346
+ import { useState as useState9, useEffect as useEffect12 } from "react";
15085
18347
  function useBookingFormConfig(siteId, formId) {
15086
18348
  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(() => {
18349
+ const [formConfig, setFormConfig] = useState9(null);
18350
+ const [services, setServices] = useState9([]);
18351
+ const [isLoading, setIsLoading] = useState9(true);
18352
+ const [error, setError] = useState9(null);
18353
+ useEffect12(() => {
15092
18354
  let mounted = true;
15093
18355
  async function loadFormAndServices() {
15094
18356
  try {
@@ -15130,8 +18392,8 @@ function useBookingFormConfig(siteId, formId) {
15130
18392
  } catch {
15131
18393
  }
15132
18394
  }
15133
- } catch (err) {
15134
- console.error("Failed to load form:", err);
18395
+ } catch (err3) {
18396
+ console.error("Failed to load form:", err3);
15135
18397
  if (mounted) {
15136
18398
  setError("Failed to load booking form. Please try again later.");
15137
18399
  }
@@ -15151,16 +18413,19 @@ function useBookingFormConfig(siteId, formId) {
15151
18413
 
15152
18414
  // src/bookings/index.ts
15153
18415
  var BookingFormClient2 = (props) => {
15154
- return React4.createElement(BookingFormClient, props);
18416
+ return React5.createElement(BookingFormClient, props);
15155
18417
  };
15156
18418
  function useBookingFormConfig2(siteId, formId) {
15157
18419
  return useBookingFormConfig(siteId, formId);
15158
18420
  }
15159
18421
  var HeadlessBookingProvider2 = (props) => {
15160
- return React4.createElement(HeadlessBookingProvider, props);
18422
+ return React5.createElement(HeadlessBookingProvider, props);
18423
+ };
18424
+ var HeadlessEventRegistrationProvider2 = (props) => {
18425
+ return React5.createElement(HeadlessEventRegistrationProvider, props);
15161
18426
  };
15162
18427
  var HeadlessBookingPaymentSelectionStep2 = (props) => {
15163
- return React4.createElement(HeadlessBookingPaymentSelectionStep, props);
18428
+ return React5.createElement(HeadlessBookingPaymentSelectionStep, props);
15164
18429
  };
15165
18430
  export {
15166
18431
  BOOKING_FORM_DATA_RESERVED_KEY_VALUES,
@@ -15168,8 +18433,13 @@ export {
15168
18433
  AltchaWidget as HeadlessBookingAltchaWidget,
15169
18434
  HeadlessBookingPaymentSelectionStep2 as HeadlessBookingPaymentSelectionStep,
15170
18435
  HeadlessBookingProvider2 as HeadlessBookingProvider,
18436
+ AltchaWidget as HeadlessEventRegistrationAltchaWidget,
18437
+ HeadlessEventRegistrationProvider2 as HeadlessEventRegistrationProvider,
15171
18438
  createBookingBlockApiConfig,
18439
+ createEventRegistrationBlockApiConfig,
15172
18440
  getAppointmentBookingOverrideInput,
18441
+ getEventRegistrationOverrideInput,
15173
18442
  useBookingFormConfig2 as useBookingFormConfig,
15174
- useHeadlessBookingFlow
18443
+ useHeadlessBookingFlow,
18444
+ useHeadlessEventRegistrationFlow
15175
18445
  };