@riverbankcms/sdk 0.84.0 → 0.84.2

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 (97) hide show
  1. package/dist/{PreviewEditorSidebar-HML67UDA.mjs → PreviewEditorSidebar-4PH35ZIE.mjs} +3 -3
  2. package/dist/{PreviewEditorUI-I4BQUU6K.mjs → PreviewEditorUI-WHMCRJGM.mjs} +11 -6
  3. package/dist/SdkPreviewModeRuntime-4FGSVUYI.mjs +8 -0
  4. package/dist/_dts/api/src/bookingConfig.d.ts +2 -0
  5. package/dist/_dts/api/src/index.d.ts +2 -2
  6. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +2 -1
  7. package/dist/_dts/api/src/sdk-event-payment-terms.d.ts +16 -0
  8. package/dist/_dts/api/src/sdk-event-upsert.d.ts +11 -2
  9. package/dist/_dts/api/src/sdkContracts.d.ts +3 -0
  10. package/dist/_dts/api/src/types.d.ts +1 -0
  11. package/dist/_dts/api/src/url.d.ts +12 -4
  12. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +4 -4
  13. package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +2 -0
  14. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +6 -6
  15. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +3 -3
  16. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationWizard.d.ts +0 -2
  17. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/constants.d.ts +1 -0
  18. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +275 -0
  19. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.override.d.ts +10 -0
  20. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.planning.d.ts +22 -0
  21. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.state.d.ts +3 -303
  22. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +3 -1
  23. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +9 -1
  24. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +8 -6
  25. package/dist/_dts/content-editor/src/hooks/useSimpleAutosave.d.ts +8 -0
  26. package/dist/_dts/editor-blocks/src/BlockForm.d.ts +6 -4
  27. package/dist/_dts/preview-next/src/client/preview/MaintenanceModeBadge.d.ts +3 -2
  28. package/dist/_dts/preview-next/src/client/preview/PreviewEditorUI.d.ts +2 -1
  29. package/dist/_dts/sdk/src/client/management/index.d.ts +1 -1
  30. package/dist/_dts/sdk/src/client/management/types.d.ts +6 -0
  31. package/dist/_dts/sdk/src/version.d.ts +1 -1
  32. package/dist/{chunk-LBBPD2IW.mjs → chunk-4QNLOTES.mjs} +11 -16
  33. package/dist/{chunk-5E33VO6J.mjs → chunk-NFWGLRZZ.mjs} +1 -70
  34. package/dist/{chunk-HFMGVJCE.mjs → chunk-OCGTXHSO.mjs} +8 -7
  35. package/dist/{chunk-3LXFQS7T.mjs → chunk-PYDHOMEO.mjs} +1 -1
  36. package/dist/{chunk-6X2OVO3S.mjs → chunk-WFPYN7KA.mjs} +2 -2
  37. package/dist/{chunk-MSHZO4SL.mjs → chunk-ZR2GQK2A.mjs} +274 -223
  38. package/dist/cli/index.mjs +332 -45
  39. package/dist/cli/init-docs/content/agents-section.md +5 -0
  40. package/dist/cli/init-docs/content/cli-reference.md +13 -0
  41. package/dist/cli/init-docs/content/content-management.md +31 -0
  42. package/dist/cli/init-docs/content/getting-started.md +12 -0
  43. package/dist/cli/init-docs/content/workflow-add-block.md +3 -1
  44. package/dist/cli/init-docs/content/workflow-agent-safe-sync.md +81 -0
  45. package/dist/cli/init-docs/content/workflow-create-page.md +13 -3
  46. package/dist/cli/init-docs/content/workflow-custom-block.md +9 -0
  47. package/dist/cli/init-docs/content/workflow-templates.md +14 -0
  48. package/dist/client/{accordion-ESY65T56.mjs → accordion-2UZPBMYM.mjs} +1 -1
  49. package/dist/client/{bookingForm-JRFNZUHD.mjs → bookingForm-36CWQUMV.mjs} +4 -4
  50. package/dist/client/bookings.mjs +156 -138
  51. package/dist/client/{carousel-CPR5VWIP.mjs → carousel-QH77HR6X.mjs} +2 -2
  52. package/dist/client/{cart-ZUX5BA7O.mjs → cart-X4YK4FTW.mjs} +5 -5
  53. package/dist/client/{checkout-RULGBADZ.mjs → checkout-OM2BEPWD.mjs} +5 -5
  54. package/dist/client/{chunk-RDJFCPY3.mjs → chunk-3C2VTPWI.mjs} +34 -117
  55. package/dist/client/{chunk-BT6AEIKN.mjs → chunk-3DTWLTXM.mjs} +1 -1
  56. package/dist/client/{chunk-JWEYB4V6.mjs → chunk-4OXKTA3D.mjs} +1 -1
  57. package/dist/client/{chunk-URQCZD5W.mjs → chunk-52CGCQ7B.mjs} +4 -4
  58. package/dist/client/{chunk-52I7BGEK.mjs → chunk-7UCLJ5SP.mjs} +1 -1
  59. package/dist/client/{chunk-Z5OBQ5I4.mjs → chunk-F5VRX5Y6.mjs} +1 -1
  60. package/dist/client/{chunk-GFSQNTRW.mjs → chunk-SDIYSQAY.mjs} +0 -4
  61. package/dist/client/{chunk-HXPWP5EN.mjs → chunk-VGDBVNOO.mjs} +175 -14
  62. package/dist/client/{chunk-5ZEAZ33K.mjs → chunk-ZKUO52W3.mjs} +1 -1
  63. package/dist/client/client.mjs +348 -232
  64. package/dist/client/{courseRegistration-QTUDC35T.mjs → courseRegistration-TMKU6ABO.mjs} +4 -4
  65. package/dist/client/{eventCalendar-Q7NS4XLD.mjs → eventCalendar-G6TI32X6.mjs} +6 -6
  66. package/dist/client/{eventCombined-QAO7VUO5.mjs → eventCombined-SCKEMNAR.mjs} +6 -6
  67. package/dist/client/{eventDetails-WTNNU6Q3.mjs → eventDetails-XPIFXXPK.mjs} +6 -6
  68. package/dist/client/{eventListing-5TA2ELDT.mjs → eventListing-7QFMEMGT.mjs} +6 -6
  69. package/dist/client/{eventRegistration-M6USZGRF.mjs → eventRegistration-TOODSZUI.mjs} +6 -6
  70. package/dist/client/{form-DGVGXLMH.mjs → form-MTCMVCZT.mjs} +2 -2
  71. package/dist/client/{headerSection-O2AGMPCU.mjs → headerSection-Y5TMR3TW.mjs} +2 -2
  72. package/dist/client/hooks.mjs +315 -35
  73. package/dist/client/{locationMap-EJRNRIKJ.mjs → locationMap-RH2LG7FZ.mjs} +1 -1
  74. package/dist/client/{newsletterForm-7NTC2DTR.mjs → newsletterForm-PCAIPFMA.mjs} +2 -2
  75. package/dist/client/{productDetail-HH4LP53D.mjs → productDetail-OIGDR4YE.mjs} +5 -5
  76. package/dist/client/{productList-YVHYM2AF.mjs → productList-4MA5S2CX.mjs} +5 -5
  77. package/dist/client/rendering/client.mjs +312 -195
  78. package/dist/client/rendering/islands.mjs +18 -18
  79. package/dist/client/rendering.mjs +312 -195
  80. package/dist/client/{shop-UIFX7XRK.mjs → shop-WXSYV5QO.mjs} +5 -5
  81. package/dist/client/spam-protection.mjs +0 -4
  82. package/dist/preview-next/client/runtime.mjs +5 -5
  83. package/dist/{sdk-runtime-ZENAOYMN.mjs → sdk-runtime-QLOCYKVU.mjs} +6 -6
  84. package/dist/server/components.mjs +188 -61
  85. package/dist/server/config-validation.mjs +313 -33
  86. package/dist/server/config.mjs +313 -33
  87. package/dist/server/data.mjs +315 -35
  88. package/dist/server/index.mjs +10 -11
  89. package/dist/server/next.mjs +198 -72
  90. package/dist/server/page-converter.mjs +315 -35
  91. package/dist/server/prebuild.mjs +1 -1
  92. package/dist/server/rendering/server.mjs +188 -61
  93. package/dist/server/rendering.mjs +188 -61
  94. package/dist/server/routing.mjs +334 -34
  95. package/dist/server/server.mjs +331 -52
  96. package/package.json +1 -1
  97. package/dist/SdkPreviewModeRuntime-MCKMVDTK.mjs +0 -8
@@ -0,0 +1,81 @@
1
+ # Workflow: Agent-Safe Sync
2
+
3
+ Use this workflow when an agent needs to push a narrow CMS change without overwriting unrelated dashboard edits.
4
+
5
+ ## Golden Rules
6
+
7
+ 1. Prefer the CLI `--env` flag over shell environment overrides.
8
+ 2. Dry-run the exact scope you plan to apply.
9
+ 3. Push the narrowest possible content scope.
10
+ 4. Treat stale-content warnings as evidence of unrelated remote edits.
11
+ 5. Use `push-config` for schema/config only; use `push` for pages, entries, navigation, settings, and other content files.
12
+
13
+ ## Environment Targeting
14
+
15
+ Use the CLI environment flag:
16
+
17
+ ```bash
18
+ riverbankcms pull --env=remote
19
+ riverbankcms push pages privacy-policy --env=remote --dry-run
20
+ riverbankcms push-config --env=remote
21
+ ```
22
+
23
+ Do not rely on `RIVERBANK_ENV=remote riverbankcms ...` for CLI sync commands. Site projects often load `.env.local`, and an existing `RIVERBANK_ENV=local` value can override the shell value in config-loading paths. The CLI `--env` flag is explicit and survives project env defaults.
24
+
25
+ ## Narrow Page Push
26
+
27
+ For a single page, push the page identifier rather than all pages:
28
+
29
+ ```bash
30
+ riverbankcms push pages privacy-policy --env=remote --dry-run --force
31
+ riverbankcms push pages privacy-policy --env=remote --yes --force
32
+ ```
33
+
34
+ If you need to isolate a local file snapshot from the rest of `content/pages`, use a temporary content directory:
35
+
36
+ ```bash
37
+ tmpdir=$(mktemp -d)
38
+ mkdir -p "$tmpdir/pages"
39
+ cp content/pages/privacy-policy.json "$tmpdir/pages/privacy-policy.json"
40
+
41
+ riverbankcms push pages --content-dir "$tmpdir" --env=remote --dry-run --force
42
+ riverbankcms push pages --content-dir "$tmpdir" --env=remote --yes --force
43
+
44
+ rm -rf "$tmpdir"
45
+ ```
46
+
47
+ This is useful when local content files include older or unrelated page differences that should not be pushed.
48
+
49
+ ## Stale Content
50
+
51
+ If a push aborts because unrelated remote content is newer:
52
+
53
+ - Do not blindly run a broad `push --force`.
54
+ - Prefer pushing the exact changed page, entry, or navigation scope.
55
+ - Use `--force` only after a dry-run confirms the planned changes are limited to the intended objects.
56
+ - If you truly need the latest remote state, run a scoped pull first, for example `riverbankcms pull pages privacy-policy --env=remote`.
57
+
58
+ ## Content vs Config
59
+
60
+ Use these commands for different surfaces:
61
+
62
+ ```bash
63
+ # Pages, entries, navigation, settings, forms, footer content, themes
64
+ riverbankcms push <scope> ...
65
+
66
+ # Custom blocks, block extensions/options, content type schemas/templates,
67
+ # SDK-managed settings, footer blocks/layout config
68
+ riverbankcms push-config ...
69
+ ```
70
+
71
+ `push-config` does not replace `push pages` or `push entries`; it syncs schema/config surfaces. If config validation fails, read the field errors as schema feedback before working around them in the site.
72
+
73
+ ## Before Applying
74
+
75
+ Checklist:
76
+
77
+ - [ ] I used `--env=local`, `--env=remote`, or `--env=both` explicitly.
78
+ - [ ] I ran a dry-run for the same scope and target environment.
79
+ - [ ] The dry-run contains only intended creates/updates/deletes.
80
+ - [ ] I understand any stale-content warnings.
81
+ - [ ] For remote writes, I included `--yes` only after reviewing the dry-run.
@@ -10,6 +10,16 @@ This workflow guides you through creating a new page in the CMS.
10
10
 
11
11
  ## Steps
12
12
 
13
+ ### Before You Add Custom Blocks
14
+
15
+ For simple content pages such as privacy policies, terms pages, FAQs, about copy, and editorial articles, start with built-in blocks:
16
+
17
+ - `block.body-text` for long-form rich text
18
+ - `block.hero` only when the page genuinely needs a visual/intro hero
19
+ - `block.cta-full` or existing CTA blocks for action strips
20
+
21
+ Check `block-types.md` before creating a custom block. A plain content page should usually be one `block.body-text` block with an `h1` and intro paragraph in the rich text body, not a site-specific custom block.
22
+
13
23
  ### 1. Create the Page
14
24
 
15
25
  ```bash
@@ -45,7 +55,7 @@ Add a body text block:
45
55
  ```bash
46
56
  riverbankcms block upsert contact intro-text \
47
57
  --kind block.body-text \
48
- --data '{"content": "<p>Reach out using the form below or email us directly.</p>"}'
58
+ --data '{"body": {"type": "doc", "content": [{"type": "heading", "attrs": {"level": 1}, "content": [{"type": "text", "text": "Contact Us"}]}, {"type": "paragraph", "content": [{"type": "text", "text": "Reach out using the form below or email us directly."}]}]}}'
49
59
  ```
50
60
 
51
61
  Add more blocks as needed. See `block-types.md` for available block types.
@@ -159,12 +169,12 @@ riverbankcms block upsert about hero \
159
169
  # 3. Add introduction text
160
170
  riverbankcms block upsert about intro \
161
171
  --kind block.body-text \
162
- --data '{"content": "<p>Founded in 2020, we have been...</p>"}'
172
+ --data '{"body": {"type": "doc", "content": [{"type": "paragraph", "content": [{"type": "text", "text": "Founded in 2020, we have been..."}]}]}}'
163
173
 
164
174
  # 4. Add team section (if using a team block)
165
175
  riverbankcms block upsert about team \
166
176
  --kind block.body-text \
167
- --data '{"content": "<h2>Our Team</h2><p>Meet the people behind the company.</p>"}'
177
+ --data '{"body": {"type": "doc", "content": [{"type": "heading", "attrs": {"level": 2}, "content": [{"type": "text", "text": "Our Team"}]}, {"type": "paragraph", "content": [{"type": "text", "text": "Meet the people behind the company."}]}]}}'
168
178
 
169
179
  # 5. Verify
170
180
  riverbankcms page get about
@@ -4,6 +4,15 @@ Create a site-specific block with custom fields and rendering when system blocks
4
4
 
5
5
  ## When to Use Custom Blocks
6
6
 
7
+ Before creating a custom block, check `block-types.md` and the site `schema.md`. Many content needs are already covered by system blocks:
8
+
9
+ - `block.body-text` for policy pages, terms pages, simple articles, and editorial copy
10
+ - `block.hero` for page intros and visual mastheads
11
+ - `block.cta-full` / CTA blocks for call-to-action sections
12
+ - `block.image-gallery`, `block.media-text`, and similar media/content patterns
13
+
14
+ Do not create a custom block just to get “a rich text area with different spacing.” Use a built-in block and add scoped site CSS or block field extensions when that is enough.
15
+
7
16
  **Use custom blocks when:**
8
17
  - You need a completely unique block structure
9
18
  - The functionality doesn't map to any system block
@@ -210,6 +210,19 @@ Bindings map block fields to data sources. Available binding sources:
210
210
 
211
211
  **Valid meta paths:** `title`, `slug`, `publishedAt`, `createdAt`, `updatedAt`
212
212
 
213
+ ### Binding Type Compatibility
214
+
215
+ Template bindings must connect compatible source and target field types. `push-config` validates this and will reject mismatches before they reach the dashboard.
216
+
217
+ Common examples:
218
+
219
+ - `richText` entry field -> `richText` block field
220
+ - `media` entry field -> `media` block field
221
+ - `reference` entry field -> `reference` block field with the same `referenceKind`
222
+ - `text` entry field -> `text` block field
223
+
224
+ Do not bind a `reference` source into a `text` target just because the renderer eventually wants an identifier string. Make the custom block field a `reference` too, then convert/normalize the rendered value in code if needed. This keeps the block schema honest and allows dashboard validation/editor UI to work correctly.
225
+
213
226
  ### Step 4: Push Configuration
214
227
 
215
228
  Push the template to sync it with the CMS:
@@ -365,3 +378,4 @@ When you first push a template to a content type that has existing entries:
365
378
  - Check binding keys match block field IDs
366
379
  - Verify field paths exist in content type fields
367
380
  - Ensure block kinds are valid system or custom blocks
381
+ - Ensure source and target field types are compatible, especially `reference` fields
@@ -1,4 +1,4 @@
1
- import { defineIslandPropsDecoder } from './chunk-HXPWP5EN.mjs';
1
+ import { defineIslandPropsDecoder } from './chunk-VGDBVNOO.mjs';
2
2
  import './chunk-ZE5G642V.mjs';
3
3
 
4
4
  // src/rendering/islands/enhancers/accordion.ts
@@ -1,15 +1,15 @@
1
1
  "use client";
2
- import { usePolling } from './chunk-5ZEAZ33K.mjs';
2
+ import { usePolling } from './chunk-ZKUO52W3.mjs';
3
3
  import { SpinnerNode } from './chunk-SYIJ5JO2.mjs';
4
4
  import { useDiscountCodeUi } from './chunk-ZFHRN6W2.mjs';
5
5
  import { buildRouteIslandApiConfig } from './chunk-L4J5Y62O.mjs';
6
- import { scrollToBlock, buildCheckoutReturnUrls, DiscountCodeDisclosure, formatPrice } from './chunk-52I7BGEK.mjs';
6
+ import { scrollToBlock, buildCheckoutReturnUrls, DiscountCodeDisclosure, formatPrice } from './chunk-7UCLJ5SP.mjs';
7
7
  import { FieldValidationMessage, getFieldValidationControlProps } from './chunk-3DCJ45Z2.mjs';
8
8
  import './chunk-DVNUDUVT.mjs';
9
- import { isSpamProtectionEnabled, getChallengeUrl, AltchaWidget } from './chunk-GFSQNTRW.mjs';
9
+ import { isSpamProtectionEnabled, getChallengeUrl, AltchaWidget } from './chunk-SDIYSQAY.mjs';
10
10
  import { BlockApiProvider, useBlockApi, FeedbackMessage } from './chunk-UDNSI5PY.mjs';
11
11
  import { mountReactIsland } from './chunk-N7PBWBWQ.mjs';
12
- import { defineIslandPropsDecoder, resolveBookingSiteId, resolveDefaultBookingServiceId, getBookingRedirectStateFromLocation, deriveBookingFormViewState, logger, getBookingSuccessMessage, resolveAppointmentCheckoutVerificationState, themeButtonClassName, toSelectedCollectionOptionKind, assertNever11, prepareBookingSubmission, formatBookingSubmissionPreparationError, resolveBookingPaymentStep, BOOKING_FORM_DATA_RESERVED_KEYS, clearWorkflowFeedback, reportWorkflowError, reportWorkflowSuccess, okWith2, err2 } from './chunk-HXPWP5EN.mjs';
12
+ import { defineIslandPropsDecoder, resolveBookingSiteId, resolveDefaultBookingServiceId, getBookingRedirectStateFromLocation, deriveBookingFormViewState, logger, getBookingSuccessMessage, resolveAppointmentCheckoutVerificationState, themeButtonClassName, toSelectedCollectionOptionKind, assertNever11, prepareBookingSubmission, formatBookingSubmissionPreparationError, resolveBookingPaymentStep, BOOKING_FORM_DATA_RESERVED_KEYS, clearWorkflowFeedback, reportWorkflowError, reportWorkflowSuccess, okWith2, err2 } from './chunk-VGDBVNOO.mjs';
13
13
  import { resolveBookingTimeZoneId, DEFAULT_BOOKING_TIME_ZONE, unsafeAsFormId, unsafeAsAppointmentResourceId, unsafeAsCustomerPassId, unsafeAsAppointmentServiceId, formatLocalScheduleDate, addLocalScheduleDays, parseBookingLocalDate, resolveFlexibleBalanceInitialPaymentCents, resolveFlexibleBalanceDueAt, getBookingInstalmentDepositRefundability, unsafeAsPassId, splitAmountWithRemainderInFirst, addIntervalPreservingMonthAnchor, clampConfiguredAmount, getBookingInstalmentPlanIntervalCount, omitZeroAmountFutureRows, formatBookingInstant } from './chunk-ZE5G642V.mjs';
14
14
  import React2, { useRef, useState, useMemo, useReducer, useEffect, useCallback, useLayoutEffect } from 'react';
15
15
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -11786,6 +11786,89 @@ var MQ_TABLET_ONLY = mqBetween(BREAKPOINT_SM, BREAKPOINT_LG_DOWN);
11786
11786
  var MQ_MAX_640 = mqDown(BREAKPOINT_SM);
11787
11787
  var MQ_MAX_768 = mqDown(BREAKPOINT_MD);
11788
11788
 
11789
+ // ../blocks/src/system/runtime/nodes/event-registration/registrationDerivations.ts
11790
+ function eventMatchesOccurrenceId(event, occurrenceId) {
11791
+ return event.registrationOccurrenceId === occurrenceId || event.publicEventId === occurrenceId;
11792
+ }
11793
+ function findEventByOccurrenceId(events, occurrenceId) {
11794
+ return events.find((event) => eventMatchesOccurrenceId(event, occurrenceId)) ?? null;
11795
+ }
11796
+ function findPreSelectedEvent(input) {
11797
+ const occurrenceContext = input.occurrenceContext;
11798
+ if (!occurrenceContext) {
11799
+ return null;
11800
+ }
11801
+ const contextDate = getBookingLocalDateKey(toScheduledBookingDateTime({
11802
+ startsAt: occurrenceContext.startsAt,
11803
+ timeZone: occurrenceContext.timeZone
11804
+ }));
11805
+ return input.scopedEvents.find(
11806
+ (event) => eventMatchesOccurrenceId(event, occurrenceContext.id) || getBookingLocalDateKey(toScheduledBookingDateTime({
11807
+ startsAt: event.startsAt,
11808
+ timeZone: event.timeZone
11809
+ })) === contextDate
11810
+ ) ?? null;
11811
+ }
11812
+ function resolveRegistrationTarget(input) {
11813
+ const occurrenceId = input.occurrenceContext?.id ?? input.selectedEvent?.registrationOccurrenceId ?? null;
11814
+ if (!occurrenceId) {
11815
+ return null;
11816
+ }
11817
+ return {
11818
+ occurrenceId,
11819
+ selectedEventId: input.selectedEvent?.publicEventId ?? null
11820
+ };
11821
+ }
11822
+ function resolveEventRequiresPayment(input) {
11823
+ if (input.eligibility) {
11824
+ return input.eligibility.requiresPayment;
11825
+ }
11826
+ if (input.selectedTicketType) {
11827
+ return input.selectedTicketType.priceAmount > 0;
11828
+ }
11829
+ if (!input.event) {
11830
+ return false;
11831
+ }
11832
+ return publicEventPricingType(resolveRuntimeEventPricing(input.event)) !== "free";
11833
+ }
11834
+ function resolveDiscountContext(input) {
11835
+ const selection = input.paymentSelection.method ? input.paymentSelection : null;
11836
+ if (!input.event) {
11837
+ return null;
11838
+ }
11839
+ if (selection?.method === "pass_bundle" && selection.bundlePassId) {
11840
+ return { type: "pass", passId: selection.bundlePassId };
11841
+ }
11842
+ if (selection?.method === "membership_bundle" && selection.bundleMembershipId) {
11843
+ return { type: "membership", membershipId: selection.bundleMembershipId };
11844
+ }
11845
+ if (!input.eventRequiresPayment) {
11846
+ return null;
11847
+ }
11848
+ if (selection?.method && selection.method !== "stripe") {
11849
+ return null;
11850
+ }
11851
+ return {
11852
+ type: "event",
11853
+ eventSeriesId: input.event.seriesId,
11854
+ eventCategoryId: input.event.eventCategory?.id ?? null,
11855
+ ticketsCount: input.ticketsCount
11856
+ };
11857
+ }
11858
+
11859
+ // ../blocks/src/system/runtime/nodes/event-registration/registrationEventAdapter.ts
11860
+ function toRegistrationEvent(event) {
11861
+ return {
11862
+ ...event,
11863
+ pricing: resolveRuntimeEventPricing(event),
11864
+ publicEventId: event.id,
11865
+ registrationOccurrenceId: event.occurrenceId
11866
+ };
11867
+ }
11868
+ function toRegistrationEvents(events) {
11869
+ return events.map(toRegistrationEvent);
11870
+ }
11871
+
11789
11872
  // ../blocks/src/system/runtime/shared/components/FeedbackMessage.tsx
11790
11873
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
11791
11874
  function joinClasses(...parts) {
@@ -11928,10 +12011,6 @@ function getCmsApiUrl() {
11928
12011
  if (dashboardUrl) {
11929
12012
  return `${dashboardUrl.replace(/\/$/, "")}/api`;
11930
12013
  }
11931
- const legacyApiUrl = process.env.NEXT_PUBLIC_CMS_API_URL;
11932
- if (legacyApiUrl) {
11933
- return legacyApiUrl.replace(/\/$/, "");
11934
- }
11935
12014
  throw new Error("Dashboard URL not configured. Set NEXT_PUBLIC_DASHBOARD_URL");
11936
12015
  }
11937
12016
  function getChallengeUrl() {
@@ -15628,8 +15707,10 @@ function requiresPaymentStep(params) {
15628
15707
  return !isEntitlementSelection(params.paymentSelection);
15629
15708
  }
15630
15709
 
15631
- // ../blocks/src/system/runtime/nodes/event-registration/event-registration.headless.state.ts
15710
+ // ../blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.ts
15632
15711
  var DEFAULT_EVENT_REGISTRATION_MAX_TICKETS = 5;
15712
+
15713
+ // ../blocks/src/system/runtime/nodes/event-registration/event-registration.headless.override.ts
15633
15714
  function createEventRegistrationBlockApiConfig(input) {
15634
15715
  return {
15635
15716
  baseUrl: input.apiBaseUrl,
@@ -15639,19 +15720,6 @@ function createEventRegistrationBlockApiConfig(input) {
15639
15720
  ...input.portalToken ? { authOverrides: { portal: { type: "bearer", token: input.portalToken } } } : {}
15640
15721
  };
15641
15722
  }
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
15723
  function getEventRegistrationOverrideInput(props) {
15656
15724
  if (!props.siteId) {
15657
15725
  return {
@@ -15694,6 +15762,36 @@ function getEventRegistrationOverrideInput(props) {
15694
15762
  }
15695
15763
  };
15696
15764
  }
15765
+ function isRecord5(value) {
15766
+ return typeof value === "object" && value !== null;
15767
+ }
15768
+ function isPublicEventLike(value) {
15769
+ 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);
15770
+ }
15771
+ function isDeliveryMode(value) {
15772
+ return value === "in_person" || value === "online" || value === "hybrid";
15773
+ }
15774
+ function isAccessRestriction(value) {
15775
+ return value === "none" || value === "category";
15776
+ }
15777
+ function isEventRegistrationContentEntryLike(value) {
15778
+ return isRecord5(value) && typeof value.id === "string" && typeof value.slug === "string" && typeof value.contentTypeSlug === "string";
15779
+ }
15780
+
15781
+ // ../blocks/src/system/runtime/nodes/event-registration/event-registration.headless.planning.ts
15782
+ function getRegistrableStatuses(isPreview) {
15783
+ return isPreview ? ["active", "draft"] : ["active"];
15784
+ }
15785
+ function normalizeEventRegistrationMaxTickets(value) {
15786
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
15787
+ return Math.floor(value);
15788
+ }
15789
+ if (typeof value === "string") {
15790
+ const parsed = Number.parseInt(value, 10);
15791
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_EVENT_REGISTRATION_MAX_TICKETS;
15792
+ }
15793
+ return DEFAULT_EVENT_REGISTRATION_MAX_TICKETS;
15794
+ }
15697
15795
  function toHeadlessPaymentSelection(selection) {
15698
15796
  switch (selection.method) {
15699
15797
  case null:
@@ -15843,7 +15941,9 @@ function resolveHeadlessEventRegistrationView(wizard) {
15843
15941
  return { kind: "empty", message: "No events available for registration." };
15844
15942
  }
15845
15943
  const allowedStatuses = getRegistrableStatuses(wizard.api.config.isPreview);
15846
- const hasRegistrableEvents = wizard.scopedEvents.some((event) => !event.status || allowedStatuses.includes(event.status));
15944
+ const hasRegistrableEvents = wizard.scopedEvents.some(
15945
+ (event) => !event.status || allowedStatuses.includes(event.status)
15946
+ );
15847
15947
  if (!hasRegistrableEvents && !wizard.occurrenceContext) {
15848
15948
  return {
15849
15949
  kind: "unavailable",
@@ -15869,16 +15969,6 @@ function resolveHeadlessEventRegistrationView(wizard) {
15869
15969
  return { kind: "form" };
15870
15970
  }
15871
15971
  }
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
15972
  function deriveEventRegistrationSteps(input) {
15883
15973
  const ids = [];
15884
15974
  if (!input.hasPreSelectedContext) ids.push("select-event");
@@ -15895,6 +15985,16 @@ function deriveEventRegistrationSteps(input) {
15895
15985
  canLeave: activeIndex !== index
15896
15986
  }));
15897
15987
  }
15988
+ function withOptionalSelection(args, selection) {
15989
+ return selection ? { ...args, selection } : args;
15990
+ }
15991
+ function missingPaymentSelection() {
15992
+ return {
15993
+ ok: false,
15994
+ reason: "payment-selection-required",
15995
+ message: "Select a payment option to continue."
15996
+ };
15997
+ }
15898
15998
  function getStepLabel(step) {
15899
15999
  switch (step) {
15900
16000
  case "select-event":
@@ -15907,21 +16007,6 @@ function getStepLabel(step) {
15907
16007
  return "Payment";
15908
16008
  }
15909
16009
  }
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
16010
 
15926
16011
  // ../blocks/src/system/runtime/nodes/event-registration/utils.ts
15927
16012
  var DEFAULT_EVENT_CURRENCY2 = "usd";
@@ -16680,6 +16765,7 @@ function useEventRegistrationSubmit(options) {
16680
16765
  checkoutType,
16681
16766
  productId: bundleProductId,
16682
16767
  discountCode: options.discountCode.trim() ? options.discountCode.trim() : void 0,
16768
+ collectionOptionKind: selectionSnapshot.collectionOptionKind,
16683
16769
  successUrl,
16684
16770
  cancelUrl
16685
16771
  });
@@ -16749,89 +16835,6 @@ function useEventRegistrationSubmit(options) {
16749
16835
  };
16750
16836
  }
16751
16837
 
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
16838
  // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
16836
16839
  function useEventRegistrationWizard(options) {
16837
16840
  const api = useBlockApi();
@@ -17125,23 +17128,29 @@ function useEventRegistrationWizard(options) {
17125
17128
  );
17126
17129
  const handleDetailsComplete = async () => {
17127
17130
  if (ticketTypeSelectionRequired && !hasValidSelectedTicketType) {
17128
- setErrorMessage("Select a ticket type to continue.");
17131
+ const message = "Select a ticket type to continue.";
17132
+ setErrorMessage(message);
17129
17133
  setStep("error");
17130
- return;
17134
+ return { ok: false, reason: "blocked", message };
17131
17135
  }
17132
17136
  if (!validateForm()) {
17133
17137
  setGuestSectionShake(true);
17134
- return;
17138
+ return {
17139
+ ok: false,
17140
+ reason: "validation-failed",
17141
+ message: "Check the highlighted fields and try again."
17142
+ };
17135
17143
  }
17136
17144
  if (waitlistClaim.claim === null && eligibility?.isFull && !eligibility.canJoinWaitlist) {
17137
- setErrorMessage("This event is sold out.");
17145
+ const message = "This event is sold out.";
17146
+ setErrorMessage(message);
17138
17147
  setStep("error");
17139
- return;
17148
+ return { ok: false, reason: "blocked", message };
17140
17149
  }
17141
17150
  const shouldCollectPayment = !eligibility?.canJoinWaitlist && requiresPaymentStep({ eventRequiresPayment, paymentSelection });
17142
17151
  if (shouldCollectPayment) {
17143
17152
  setStep("select-payment");
17144
- return;
17153
+ return { ok: true, outcome: "payment-step" };
17145
17154
  }
17146
17155
  const submitPlan = resolveEventRegistrationSubmitPlan({
17147
17156
  paymentSelection,
@@ -17151,14 +17160,22 @@ function useEventRegistrationWizard(options) {
17151
17160
  if (!submitPlan.ok) {
17152
17161
  setErrorMessage(submitPlan.message);
17153
17162
  setStep("error");
17154
- return;
17163
+ return { ok: false, reason: "blocked", message: submitPlan.message };
17155
17164
  }
17156
- await handleSubmit(
17165
+ const submitResult = await handleSubmit(
17157
17166
  submitPlan.args.method,
17158
17167
  submitPlan.args.passId,
17159
17168
  submitPlan.args.membershipId,
17160
17169
  submitPlan.args.selection
17161
17170
  );
17171
+ if (!submitResult.ok) {
17172
+ return {
17173
+ ok: false,
17174
+ reason: submitResult.reason === "submission-failed" ? "submission-failed" : "blocked",
17175
+ message: submitResult.message
17176
+ };
17177
+ }
17178
+ return { ok: true, outcome: "submitted" };
17162
17179
  };
17163
17180
  const handlePaymentSelect = async () => {
17164
17181
  const submitPlan = resolveEventRegistrationSubmitPlan({
@@ -18146,9 +18163,10 @@ function useEventRegistrationController(options) {
18146
18163
  }
18147
18164
  wizard.setStep("enter-details");
18148
18165
  return { ok: true };
18149
- case "enter-details":
18150
- await wizard.handleDetailsComplete();
18151
- return { ok: true };
18166
+ case "enter-details": {
18167
+ const result = await wizard.handleDetailsComplete();
18168
+ return result.ok ? { ok: true } : result;
18169
+ }
18152
18170
  case "select-payment": {
18153
18171
  const result = await submit({ redirect: "manual" });
18154
18172
  return result.ok ? { ok: true } : {
@@ -1,6 +1,6 @@
1
- import { normalizeCarouselProps, CarouselNodeClient } from './chunk-JWEYB4V6.mjs';
1
+ import { normalizeCarouselProps, CarouselNodeClient } from './chunk-4OXKTA3D.mjs';
2
2
  import { mountReactIsland } from './chunk-N7PBWBWQ.mjs';
3
- import { defineIslandPropsDecoder } from './chunk-HXPWP5EN.mjs';
3
+ import { defineIslandPropsDecoder } from './chunk-VGDBVNOO.mjs';
4
4
  import './chunk-ZE5G642V.mjs';
5
5
  import { jsx } from 'react/jsx-runtime';
6
6
 
@@ -1,15 +1,15 @@
1
- import { mountShopBlockIsland, CartClient } from './chunk-URQCZD5W.mjs';
2
- import './chunk-Z5OBQ5I4.mjs';
3
- import './chunk-JWEYB4V6.mjs';
1
+ import { mountShopBlockIsland, CartClient } from './chunk-52CGCQ7B.mjs';
2
+ import './chunk-F5VRX5Y6.mjs';
3
+ import './chunk-4OXKTA3D.mjs';
4
4
  import './chunk-I2MMZO53.mjs';
5
5
  import './chunk-ZFHRN6W2.mjs';
6
6
  import './chunk-L4J5Y62O.mjs';
7
- import './chunk-52I7BGEK.mjs';
7
+ import './chunk-7UCLJ5SP.mjs';
8
8
  import './chunk-3DCJ45Z2.mjs';
9
9
  import './chunk-DVNUDUVT.mjs';
10
10
  import './chunk-UDNSI5PY.mjs';
11
11
  import './chunk-N7PBWBWQ.mjs';
12
- import { defineIslandPropsDecoder } from './chunk-HXPWP5EN.mjs';
12
+ import { defineIslandPropsDecoder } from './chunk-VGDBVNOO.mjs';
13
13
  import './chunk-ZE5G642V.mjs';
14
14
 
15
15
  // src/rendering/islands/enhancers/cart.tsx
@@ -1,15 +1,15 @@
1
- import { mountShopBlockIsland, CheckoutClient } from './chunk-URQCZD5W.mjs';
2
- import './chunk-Z5OBQ5I4.mjs';
3
- import './chunk-JWEYB4V6.mjs';
1
+ import { mountShopBlockIsland, CheckoutClient } from './chunk-52CGCQ7B.mjs';
2
+ import './chunk-F5VRX5Y6.mjs';
3
+ import './chunk-4OXKTA3D.mjs';
4
4
  import './chunk-I2MMZO53.mjs';
5
5
  import './chunk-ZFHRN6W2.mjs';
6
6
  import './chunk-L4J5Y62O.mjs';
7
- import './chunk-52I7BGEK.mjs';
7
+ import './chunk-7UCLJ5SP.mjs';
8
8
  import './chunk-3DCJ45Z2.mjs';
9
9
  import './chunk-DVNUDUVT.mjs';
10
10
  import './chunk-UDNSI5PY.mjs';
11
11
  import './chunk-N7PBWBWQ.mjs';
12
- import { defineIslandPropsDecoder } from './chunk-HXPWP5EN.mjs';
12
+ import { defineIslandPropsDecoder } from './chunk-VGDBVNOO.mjs';
13
13
  import './chunk-ZE5G642V.mjs';
14
14
 
15
15
  // src/rendering/islands/enhancers/checkout.tsx