@riverbankcms/sdk 0.84.0 → 0.84.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/{PreviewEditorSidebar-HML67UDA.mjs → PreviewEditorSidebar-X7RLMEI6.mjs} +2 -2
  2. package/dist/{PreviewEditorUI-I4BQUU6K.mjs → PreviewEditorUI-CT67N4O3.mjs} +2 -2
  3. package/dist/SdkPreviewModeRuntime-EIMQ3S2V.mjs +8 -0
  4. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +4 -4
  5. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +6 -6
  6. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +3 -3
  7. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationWizard.d.ts +0 -2
  8. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/constants.d.ts +1 -0
  9. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +275 -0
  10. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.override.d.ts +10 -0
  11. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.planning.d.ts +22 -0
  12. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.state.d.ts +3 -303
  13. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +9 -1
  14. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +8 -6
  15. package/dist/_dts/editor-blocks/src/BlockForm.d.ts +6 -4
  16. package/dist/_dts/sdk/src/version.d.ts +1 -1
  17. package/dist/{chunk-MSHZO4SL.mjs → chunk-O62NDCTI.mjs} +268 -186
  18. package/dist/{chunk-HFMGVJCE.mjs → chunk-QRKJDWT7.mjs} +5 -5
  19. package/dist/{chunk-6X2OVO3S.mjs → chunk-RCTJAZSK.mjs} +1 -1
  20. package/dist/{chunk-5E33VO6J.mjs → chunk-X5ZCSU6F.mjs} +1 -1
  21. package/dist/cli/index.mjs +323 -35
  22. package/dist/cli/init-docs/content/agents-section.md +5 -0
  23. package/dist/cli/init-docs/content/cli-reference.md +13 -0
  24. package/dist/cli/init-docs/content/content-management.md +31 -0
  25. package/dist/cli/init-docs/content/getting-started.md +12 -0
  26. package/dist/cli/init-docs/content/workflow-add-block.md +3 -1
  27. package/dist/cli/init-docs/content/workflow-agent-safe-sync.md +81 -0
  28. package/dist/cli/init-docs/content/workflow-create-page.md +13 -3
  29. package/dist/cli/init-docs/content/workflow-custom-block.md +9 -0
  30. package/dist/cli/init-docs/content/workflow-templates.md +14 -0
  31. package/dist/client/{accordion-ESY65T56.mjs → accordion-2UZPBMYM.mjs} +1 -1
  32. package/dist/client/{bookingForm-JRFNZUHD.mjs → bookingForm-DYXT6YB6.mjs} +3 -3
  33. package/dist/client/bookings.mjs +155 -134
  34. package/dist/client/{carousel-CPR5VWIP.mjs → carousel-QH77HR6X.mjs} +2 -2
  35. package/dist/client/{cart-ZUX5BA7O.mjs → cart-X4YK4FTW.mjs} +5 -5
  36. package/dist/client/{checkout-RULGBADZ.mjs → checkout-OM2BEPWD.mjs} +5 -5
  37. package/dist/client/{chunk-BT6AEIKN.mjs → chunk-3DTWLTXM.mjs} +1 -1
  38. package/dist/client/{chunk-JWEYB4V6.mjs → chunk-4OXKTA3D.mjs} +1 -1
  39. package/dist/client/{chunk-URQCZD5W.mjs → chunk-52CGCQ7B.mjs} +4 -4
  40. package/dist/client/{chunk-52I7BGEK.mjs → chunk-7UCLJ5SP.mjs} +1 -1
  41. package/dist/client/{chunk-Z5OBQ5I4.mjs → chunk-F5VRX5Y6.mjs} +1 -1
  42. package/dist/client/{chunk-RDJFCPY3.mjs → chunk-UHDWIXVR.mjs} +31 -115
  43. package/dist/client/{chunk-HXPWP5EN.mjs → chunk-VGDBVNOO.mjs} +175 -14
  44. package/dist/client/{chunk-5ZEAZ33K.mjs → chunk-ZKUO52W3.mjs} +1 -1
  45. package/dist/client/client.mjs +337 -217
  46. package/dist/client/{courseRegistration-QTUDC35T.mjs → courseRegistration-YBOGURTA.mjs} +3 -3
  47. package/dist/client/{eventCalendar-Q7NS4XLD.mjs → eventCalendar-K4QJVCMD.mjs} +5 -5
  48. package/dist/client/{eventCombined-QAO7VUO5.mjs → eventCombined-MTXGMTCZ.mjs} +5 -5
  49. package/dist/client/{eventDetails-WTNNU6Q3.mjs → eventDetails-3PC4NL3U.mjs} +5 -5
  50. package/dist/client/{eventListing-5TA2ELDT.mjs → eventListing-TFJET6DN.mjs} +5 -5
  51. package/dist/client/{eventRegistration-M6USZGRF.mjs → eventRegistration-QGPBGJTW.mjs} +5 -5
  52. package/dist/client/{form-DGVGXLMH.mjs → form-MDKR4FNB.mjs} +1 -1
  53. package/dist/client/{headerSection-O2AGMPCU.mjs → headerSection-Y5TMR3TW.mjs} +2 -2
  54. package/dist/client/hooks.mjs +315 -35
  55. package/dist/client/{locationMap-EJRNRIKJ.mjs → locationMap-RH2LG7FZ.mjs} +1 -1
  56. package/dist/client/{newsletterForm-7NTC2DTR.mjs → newsletterForm-ZR5UDGBT.mjs} +1 -1
  57. package/dist/client/{productDetail-HH4LP53D.mjs → productDetail-OIGDR4YE.mjs} +5 -5
  58. package/dist/client/{productList-YVHYM2AF.mjs → productList-4MA5S2CX.mjs} +5 -5
  59. package/dist/client/rendering/client.mjs +310 -190
  60. package/dist/client/rendering/islands.mjs +18 -18
  61. package/dist/client/rendering.mjs +310 -190
  62. package/dist/client/{shop-UIFX7XRK.mjs → shop-WXSYV5QO.mjs} +5 -5
  63. package/dist/preview-next/client/runtime.mjs +3 -3
  64. package/dist/{sdk-runtime-ZENAOYMN.mjs → sdk-runtime-7HJYPRWQ.mjs} +4 -4
  65. package/dist/server/components.mjs +188 -61
  66. package/dist/server/config-validation.mjs +313 -33
  67. package/dist/server/config.mjs +313 -33
  68. package/dist/server/data.mjs +315 -35
  69. package/dist/server/index.mjs +1 -1
  70. package/dist/server/next.mjs +189 -62
  71. package/dist/server/page-converter.mjs +315 -35
  72. package/dist/server/prebuild.mjs +1 -1
  73. package/dist/server/rendering/server.mjs +188 -61
  74. package/dist/server/rendering.mjs +188 -61
  75. package/dist/server/routing.mjs +334 -34
  76. package/dist/server/server.mjs +322 -42
  77. package/package.json +1 -1
  78. 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
9
  import { isSpamProtectionEnabled, getChallengeUrl, AltchaWidget } from './chunk-GFSQNTRW.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) {
@@ -15628,8 +15711,10 @@ function requiresPaymentStep(params) {
15628
15711
  return !isEntitlementSelection(params.paymentSelection);
15629
15712
  }
15630
15713
 
15631
- // ../blocks/src/system/runtime/nodes/event-registration/event-registration.headless.state.ts
15714
+ // ../blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.ts
15632
15715
  var DEFAULT_EVENT_REGISTRATION_MAX_TICKETS = 5;
15716
+
15717
+ // ../blocks/src/system/runtime/nodes/event-registration/event-registration.headless.override.ts
15633
15718
  function createEventRegistrationBlockApiConfig(input) {
15634
15719
  return {
15635
15720
  baseUrl: input.apiBaseUrl,
@@ -15639,19 +15724,6 @@ function createEventRegistrationBlockApiConfig(input) {
15639
15724
  ...input.portalToken ? { authOverrides: { portal: { type: "bearer", token: input.portalToken } } } : {}
15640
15725
  };
15641
15726
  }
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
15727
  function getEventRegistrationOverrideInput(props) {
15656
15728
  if (!props.siteId) {
15657
15729
  return {
@@ -15694,6 +15766,36 @@ function getEventRegistrationOverrideInput(props) {
15694
15766
  }
15695
15767
  };
15696
15768
  }
15769
+ function isRecord5(value) {
15770
+ return typeof value === "object" && value !== null;
15771
+ }
15772
+ function isPublicEventLike(value) {
15773
+ return isRecord5(value) && typeof value.id === "string" && typeof value.occurrenceId === "string" && typeof value.seriesId === "string" && typeof value.title === "string" && typeof value.slug === "string" && typeof value.path === "string" && typeof value.requiresRegistration === "boolean" && isDeliveryMode(value.deliveryMode) && Array.isArray(value.attendanceModes) && typeof value.startsAt === "string" && typeof value.endsAt === "string" && typeof value.timeZone === "string" && isRecord5(value.pricing) && isRecord5(value.paymentTerms) && isAccessRestriction(value.accessRestriction) && Array.isArray(value.allowedCategoryIds);
15774
+ }
15775
+ function isDeliveryMode(value) {
15776
+ return value === "in_person" || value === "online" || value === "hybrid";
15777
+ }
15778
+ function isAccessRestriction(value) {
15779
+ return value === "none" || value === "category";
15780
+ }
15781
+ function isEventRegistrationContentEntryLike(value) {
15782
+ return isRecord5(value) && typeof value.id === "string" && typeof value.slug === "string" && typeof value.contentTypeSlug === "string";
15783
+ }
15784
+
15785
+ // ../blocks/src/system/runtime/nodes/event-registration/event-registration.headless.planning.ts
15786
+ function getRegistrableStatuses(isPreview) {
15787
+ return isPreview ? ["active", "draft"] : ["active"];
15788
+ }
15789
+ function normalizeEventRegistrationMaxTickets(value) {
15790
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
15791
+ return Math.floor(value);
15792
+ }
15793
+ if (typeof value === "string") {
15794
+ const parsed = Number.parseInt(value, 10);
15795
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_EVENT_REGISTRATION_MAX_TICKETS;
15796
+ }
15797
+ return DEFAULT_EVENT_REGISTRATION_MAX_TICKETS;
15798
+ }
15697
15799
  function toHeadlessPaymentSelection(selection) {
15698
15800
  switch (selection.method) {
15699
15801
  case null:
@@ -15843,7 +15945,9 @@ function resolveHeadlessEventRegistrationView(wizard) {
15843
15945
  return { kind: "empty", message: "No events available for registration." };
15844
15946
  }
15845
15947
  const allowedStatuses = getRegistrableStatuses(wizard.api.config.isPreview);
15846
- const hasRegistrableEvents = wizard.scopedEvents.some((event) => !event.status || allowedStatuses.includes(event.status));
15948
+ const hasRegistrableEvents = wizard.scopedEvents.some(
15949
+ (event) => !event.status || allowedStatuses.includes(event.status)
15950
+ );
15847
15951
  if (!hasRegistrableEvents && !wizard.occurrenceContext) {
15848
15952
  return {
15849
15953
  kind: "unavailable",
@@ -15869,16 +15973,6 @@ function resolveHeadlessEventRegistrationView(wizard) {
15869
15973
  return { kind: "form" };
15870
15974
  }
15871
15975
  }
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
15976
  function deriveEventRegistrationSteps(input) {
15883
15977
  const ids = [];
15884
15978
  if (!input.hasPreSelectedContext) ids.push("select-event");
@@ -15895,6 +15989,16 @@ function deriveEventRegistrationSteps(input) {
15895
15989
  canLeave: activeIndex !== index
15896
15990
  }));
15897
15991
  }
15992
+ function withOptionalSelection(args, selection) {
15993
+ return selection ? { ...args, selection } : args;
15994
+ }
15995
+ function missingPaymentSelection() {
15996
+ return {
15997
+ ok: false,
15998
+ reason: "payment-selection-required",
15999
+ message: "Select a payment option to continue."
16000
+ };
16001
+ }
15898
16002
  function getStepLabel(step) {
15899
16003
  switch (step) {
15900
16004
  case "select-event":
@@ -15907,21 +16011,6 @@ function getStepLabel(step) {
15907
16011
  return "Payment";
15908
16012
  }
15909
16013
  }
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
16014
 
15926
16015
  // ../blocks/src/system/runtime/nodes/event-registration/utils.ts
15927
16016
  var DEFAULT_EVENT_CURRENCY2 = "usd";
@@ -16749,89 +16838,6 @@ function useEventRegistrationSubmit(options) {
16749
16838
  };
16750
16839
  }
16751
16840
 
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
16841
  // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
16836
16842
  function useEventRegistrationWizard(options) {
16837
16843
  const api = useBlockApi();
@@ -17125,23 +17131,29 @@ function useEventRegistrationWizard(options) {
17125
17131
  );
17126
17132
  const handleDetailsComplete = async () => {
17127
17133
  if (ticketTypeSelectionRequired && !hasValidSelectedTicketType) {
17128
- setErrorMessage("Select a ticket type to continue.");
17134
+ const message = "Select a ticket type to continue.";
17135
+ setErrorMessage(message);
17129
17136
  setStep("error");
17130
- return;
17137
+ return { ok: false, reason: "blocked", message };
17131
17138
  }
17132
17139
  if (!validateForm()) {
17133
17140
  setGuestSectionShake(true);
17134
- return;
17141
+ return {
17142
+ ok: false,
17143
+ reason: "validation-failed",
17144
+ message: "Check the highlighted fields and try again."
17145
+ };
17135
17146
  }
17136
17147
  if (waitlistClaim.claim === null && eligibility?.isFull && !eligibility.canJoinWaitlist) {
17137
- setErrorMessage("This event is sold out.");
17148
+ const message = "This event is sold out.";
17149
+ setErrorMessage(message);
17138
17150
  setStep("error");
17139
- return;
17151
+ return { ok: false, reason: "blocked", message };
17140
17152
  }
17141
17153
  const shouldCollectPayment = !eligibility?.canJoinWaitlist && requiresPaymentStep({ eventRequiresPayment, paymentSelection });
17142
17154
  if (shouldCollectPayment) {
17143
17155
  setStep("select-payment");
17144
- return;
17156
+ return { ok: true, outcome: "payment-step" };
17145
17157
  }
17146
17158
  const submitPlan = resolveEventRegistrationSubmitPlan({
17147
17159
  paymentSelection,
@@ -17151,14 +17163,22 @@ function useEventRegistrationWizard(options) {
17151
17163
  if (!submitPlan.ok) {
17152
17164
  setErrorMessage(submitPlan.message);
17153
17165
  setStep("error");
17154
- return;
17166
+ return { ok: false, reason: "blocked", message: submitPlan.message };
17155
17167
  }
17156
- await handleSubmit(
17168
+ const submitResult = await handleSubmit(
17157
17169
  submitPlan.args.method,
17158
17170
  submitPlan.args.passId,
17159
17171
  submitPlan.args.membershipId,
17160
17172
  submitPlan.args.selection
17161
17173
  );
17174
+ if (!submitResult.ok) {
17175
+ return {
17176
+ ok: false,
17177
+ reason: submitResult.reason === "submission-failed" ? "submission-failed" : "blocked",
17178
+ message: submitResult.message
17179
+ };
17180
+ }
17181
+ return { ok: true, outcome: "submitted" };
17162
17182
  };
17163
17183
  const handlePaymentSelect = async () => {
17164
17184
  const submitPlan = resolveEventRegistrationSubmitPlan({
@@ -18146,9 +18166,10 @@ function useEventRegistrationController(options) {
18146
18166
  }
18147
18167
  wizard.setStep("enter-details");
18148
18168
  return { ok: true };
18149
- case "enter-details":
18150
- await wizard.handleDetailsComplete();
18151
- return { ok: true };
18169
+ case "enter-details": {
18170
+ const result = await wizard.handleDetailsComplete();
18171
+ return result.ok ? { ok: true } : result;
18172
+ }
18152
18173
  case "select-payment": {
18153
18174
  const result = await submit({ redirect: "manual" });
18154
18175
  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
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { useBlockApi, BlockApiError } from './chunk-UDNSI5PY.mjs';
3
- import { themeButtonClassName } from './chunk-HXPWP5EN.mjs';
3
+ import { themeButtonClassName } from './chunk-VGDBVNOO.mjs';
4
4
  import { useState, useSyncExternalStore, useEffect } from 'react';
5
5
  import { jsxs, jsx } from 'react/jsx-runtime';
6
6
 
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { ChevronLeft, ChevronRight } from './chunk-HXPWP5EN.mjs';
2
+ import { ChevronLeft, ChevronRight } from './chunk-VGDBVNOO.mjs';
3
3
  import { clsx_default } from './chunk-ZE5G642V.mjs';
4
4
  import React, { useRef, useState, useCallback, useEffect } from 'react';
5
5
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';