@riverbankcms/sdk 0.78.0 → 0.78.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 (152) hide show
  1. package/README.md +45 -43
  2. package/dist/{PreviewEditorSidebar-RIKFQ72L.mjs → PreviewEditorSidebar-4DXLYX2V.mjs} +29 -21
  3. package/dist/{PreviewEditorUI-XO7TUWKK.mjs → PreviewEditorUI-CS5P4N3P.mjs} +4 -4
  4. package/dist/SdkPreviewModeRuntime-IJDHTW4W.mjs +8 -0
  5. package/dist/_dts/ai/src/contracts/proposals.d.ts +36 -0
  6. package/dist/_dts/api/src/contentRuntime.d.ts +1 -0
  7. package/dist/_dts/api/src/endpoints.d.ts +9 -0
  8. package/dist/_dts/api/src/index.d.ts +3 -3
  9. package/dist/_dts/api/src/public/types.d.ts +1 -1
  10. package/dist/_dts/api/src/request.d.ts +3 -11
  11. package/dist/_dts/api/src/sdkConfig/contracts.d.ts +1 -0
  12. package/dist/_dts/api/src/sdkContracts.d.ts +7 -1
  13. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +10 -0
  14. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +1 -0
  15. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +15 -19
  16. package/dist/_dts/api/src/types.d.ts +11 -26
  17. package/dist/_dts/block-form/src/fields/types.d.ts +6 -0
  18. package/dist/_dts/block-form/src/widgets/RepeaterField/components/RepeaterList.d.ts +3 -2
  19. package/dist/_dts/block-form/src/widgets/RepeaterField/components/RepeaterRow.d.ts +6 -3
  20. package/dist/_dts/block-form/src/widgets/RepeaterField/components/RepeaterRowActions.d.ts +8 -3
  21. package/dist/_dts/block-form/src/widgets/RepeaterField/hooks/index.d.ts +1 -1
  22. package/dist/_dts/block-form/src/widgets/RepeaterField/hooks/useLinearRepeaterDnd.d.ts +1 -0
  23. package/dist/_dts/block-form/src/widgets/RepeaterField/hooks/useRepeaterPointerDragCapability.d.ts +1 -0
  24. package/dist/_dts/block-form/src/widgets/RepeaterField/hooks/useResolvedItemLabel.d.ts +7 -0
  25. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/buildSummary.d.ts +1 -0
  26. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/index.d.ts +3 -1
  27. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/repeaterDndDomain.d.ts +1 -1
  28. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/repeaterLabelSource.d.ts +15 -0
  29. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/repeaterRowActionsDomain.d.ts +50 -0
  30. package/dist/_dts/blocks/src/system/blocks/appointment-booking.d.ts +591 -0
  31. package/dist/_dts/blocks/src/system/blocks/blog-listing.d.ts +591 -0
  32. package/dist/_dts/blocks/src/system/blocks/cart.d.ts +591 -0
  33. package/dist/_dts/blocks/src/system/blocks/checkout.d.ts +591 -0
  34. package/dist/_dts/blocks/src/system/blocks/collection.d.ts +591 -0
  35. package/dist/_dts/blocks/src/system/blocks/faq.d.ts +591 -0
  36. package/dist/_dts/blocks/src/system/blocks/gifting.d.ts +591 -0
  37. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +2 -0
  38. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +47 -0
  39. package/dist/_dts/blocks/src/system/blocks/product-detail.d.ts +591 -0
  40. package/dist/_dts/blocks/src/system/blocks/product-list.d.ts +591 -0
  41. package/dist/_dts/blocks/src/system/blocks/shop.d.ts +591 -0
  42. package/dist/_dts/blocks/src/system/blocks/team-members.d.ts +3 -0
  43. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +164 -0
  44. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.state.d.ts +1 -1
  45. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +1 -1
  46. package/dist/_dts/content-editor/src/index.d.ts +1 -1
  47. package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +2 -2
  48. package/dist/_dts/content-model/src/content-types/schema.d.ts +14 -0
  49. package/dist/_dts/content-model/src/templates/bindingTypeCompatibility.d.ts +3 -1
  50. package/dist/_dts/content-model/src/templates/bindingValidation.d.ts +10 -4
  51. package/dist/_dts/content-model/src/templates/fieldPaths.d.ts +20 -0
  52. package/dist/_dts/content-model/src/templates/manifestAdapter.d.ts +5 -2
  53. package/dist/_dts/core/src/branded.d.ts +108 -85
  54. package/dist/_dts/core/src/csv-types.d.ts +2 -2
  55. package/dist/_dts/core/src/editor-state.d.ts +7 -7
  56. package/dist/_dts/core/src/participants.d.ts +2 -2
  57. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +11 -0
  58. package/dist/_dts/editor-blocks/src/blockPayload.d.ts +1 -1
  59. package/dist/_dts/media-editor/src/MediaEditor.d.ts +3 -1
  60. package/dist/_dts/media-editor/src/MediaPreview.d.ts +3 -1
  61. package/dist/_dts/media-editor/src/fieldUi.d.ts +5 -0
  62. package/dist/_dts/media-editor/src/index.d.ts +1 -1
  63. package/dist/_dts/sdk/src/cli/commands/push/consts.d.ts +1 -1
  64. package/dist/_dts/sdk/src/cli/commands/push/metadata.d.ts +2 -0
  65. package/dist/_dts/sdk/src/cli/commands/push/stale.d.ts +3 -3
  66. package/dist/_dts/sdk/src/cli/commands/push-execute.d.ts +7 -0
  67. package/dist/_dts/sdk/src/cli/commands/push.d.ts +2 -0
  68. package/dist/_dts/sdk/src/cli/content/reader.d.ts +13 -0
  69. package/dist/_dts/sdk/src/cli/content/writer.d.ts +2 -1
  70. package/dist/_dts/sdk/src/cli/helpers.d.ts +2 -0
  71. package/dist/_dts/sdk/src/cli/site-commands/commandKeys.d.ts +6 -6
  72. package/dist/_dts/sdk/src/cli/site-commands/commandRuntime.d.ts +5 -0
  73. package/dist/_dts/sdk/src/cli/site-commands/commandSurfaceDispatch.d.ts +4 -0
  74. package/dist/_dts/sdk/src/cli/site-commands/pageCommands.d.ts +5 -2
  75. package/dist/_dts/sdk/src/cli/site-commands/pushExecution.d.ts +10 -1
  76. package/dist/_dts/sdk/src/cli/site-commands/pushExecutionTypes.d.ts +1 -1
  77. package/dist/_dts/sdk/src/client/management/types.d.ts +6 -0
  78. package/dist/_dts/sdk/src/client/types.d.ts +2 -2
  79. package/dist/_dts/sdk/src/config/content-types.d.ts +7 -0
  80. package/dist/_dts/sdk/src/config/field-definitions.d.ts +2 -0
  81. package/dist/_dts/sdk/src/version.d.ts +1 -1
  82. package/dist/_dts/site-commands/src/commands.d.ts +3 -0
  83. package/dist/{altcha-B5XGSXP5.mjs → altcha-EKUEQ4RP.mjs} +1 -1
  84. package/dist/{chunk-NIDXI46P.mjs → chunk-4QEGTLK6.mjs} +1 -1
  85. package/dist/{chunk-TXDES5P2.mjs → chunk-6HYXHRAI.mjs} +5 -5
  86. package/dist/{chunk-SVMMM2NA.mjs → chunk-CR5HKAGU.mjs} +24 -5
  87. package/dist/{chunk-OECWLDHN.mjs → chunk-MCRQMPET.mjs} +1030 -588
  88. package/dist/{chunk-SXOLGNMX.mjs → chunk-OKMBEAXY.mjs} +1 -1
  89. package/dist/{chunk-XGB3TDIC.mjs → chunk-R7POPVJR.mjs} +2 -8
  90. package/dist/{chunk-F7RTCZYN.mjs → chunk-RGTOD4AJ.mjs} +20 -14
  91. package/dist/cli/index.mjs +681 -225
  92. package/dist/cli/init-docs/content/cli-reference.md +3 -2
  93. package/dist/cli/init-docs/content/content-management.md +2 -2
  94. package/dist/cli/init-docs/content/workflow-preview-mode.md +68 -2
  95. package/dist/client/{accordion-EVDEOUPR.mjs → accordion-PLYNJIIM.mjs} +2 -2
  96. package/dist/client/analytics.mjs +1 -1
  97. package/dist/client/{bookingForm-DIHBLC64.mjs → bookingForm-BXAP6AO7.mjs} +55 -48
  98. package/dist/client/bookings.mjs +62 -55
  99. package/dist/client/{carousel-FEBQHIWI.mjs → carousel-TRBXDHGF.mjs} +3 -3
  100. package/dist/client/{cart-7CKSXAE4.mjs → cart-Z7H3HJRS.mjs} +7 -7
  101. package/dist/client/{checkout-WKYCANLV.mjs → checkout-WAFCUBIX.mjs} +7 -7
  102. package/dist/client/{chunk-OFMSCGNY.mjs → chunk-75OUS5MT.mjs} +2 -2
  103. package/dist/client/{chunk-IVNCUVAV.mjs → chunk-AUJ5DBZJ.mjs} +18 -18
  104. package/dist/client/{chunk-36WJCERQ.mjs → chunk-CE7IBGVW.mjs} +3 -1
  105. package/dist/client/{chunk-RZDWX7QW.mjs → chunk-CWGTG37I.mjs} +1 -1
  106. package/dist/client/{chunk-YDSEG6GZ.mjs → chunk-DNRGY432.mjs} +2 -2
  107. package/dist/client/{chunk-RV6FX7UH.mjs → chunk-FUXW6VW2.mjs} +9 -9
  108. package/dist/client/{chunk-65F47D7Y.mjs → chunk-JGXPTEI2.mjs} +43 -36
  109. package/dist/client/{chunk-GUK2FPXQ.mjs → chunk-JRDUHZCT.mjs} +37 -15
  110. package/dist/client/{chunk-VPPMNXCF.mjs → chunk-UVQEJJTN.mjs} +2 -2
  111. package/dist/client/{chunk-F7LHOKEH.mjs → chunk-XSV6KW4D.mjs} +1 -1
  112. package/dist/client/{chunk-PD6NBCEY.mjs → chunk-ZFHRN6W2.mjs} +1 -1
  113. package/dist/client/{chunk-2SAVKN2M.mjs → chunk-ZI3LLBPZ.mjs} +2 -2
  114. package/dist/client/client.mjs +249 -160
  115. package/dist/client/{courseRegistration-5QF2PHKM.mjs → courseRegistration-AHFQHWIJ.mjs} +10 -10
  116. package/dist/client/{eventCalendar-4ZOSETDU.mjs → eventCalendar-LDXTV5R7.mjs} +9 -9
  117. package/dist/client/{eventCombined-WQGU7JUX.mjs → eventCombined-A4JGTNJO.mjs} +9 -9
  118. package/dist/client/{eventDetails-AYWVUJ5Y.mjs → eventDetails-4YXTZ7EG.mjs} +9 -9
  119. package/dist/client/{eventListing-NT7C6UT5.mjs → eventListing-P72TPFFM.mjs} +9 -9
  120. package/dist/client/{eventRegistration-OH24F4ZJ.mjs → eventRegistration-LSYJHGMT.mjs} +9 -9
  121. package/dist/client/{form-7L42SRBB.mjs → form-AOPYOKOW.mjs} +6 -3
  122. package/dist/client/{headerSection-OZRZNZ52.mjs → headerSection-5TFYDFVQ.mjs} +3 -3
  123. package/dist/client/hooks.mjs +78 -48
  124. package/dist/client/{locationMap-ZBXRPQ7C.mjs → locationMap-QSZ3ZVAZ.mjs} +3 -3
  125. package/dist/client/{newsletterForm-SNAGFF2I.mjs → newsletterForm-KTRHZY52.mjs} +2 -2
  126. package/dist/client/{productDetail-I46BOFGV.mjs → productDetail-N4E775RG.mjs} +7 -7
  127. package/dist/client/{productList-BOYHTYI6.mjs → productList-UGUQ2S45.mjs} +7 -7
  128. package/dist/client/rendering/client.mjs +173 -131
  129. package/dist/client/rendering/islands.mjs +19 -19
  130. package/dist/client/rendering.mjs +230 -150
  131. package/dist/client/{shop-XTXPZTKR.mjs → shop-VHSZEEQ2.mjs} +7 -7
  132. package/dist/preview-next/before-render.mjs +10 -1
  133. package/dist/preview-next/client/runtime.mjs +6 -6
  134. package/dist/preview-next/middleware.mjs +10 -1
  135. package/dist/preview-next/tailwind-sources.css +1 -0
  136. package/dist/sdk-runtime-WHPJEF5G.mjs +8 -0
  137. package/dist/server/components.mjs +101 -54
  138. package/dist/server/config-template-validation.mjs +221 -15
  139. package/dist/server/config-validation.mjs +76 -42
  140. package/dist/server/config.mjs +76 -42
  141. package/dist/server/data.mjs +77 -47
  142. package/dist/server/index.mjs +31 -10
  143. package/dist/server/next.mjs +133 -71
  144. package/dist/server/page-converter.mjs +60 -40
  145. package/dist/server/prebuild.mjs +1 -1
  146. package/dist/server/rendering/server.mjs +107 -60
  147. package/dist/server/rendering.mjs +111 -61
  148. package/dist/server/routing.mjs +93 -63
  149. package/dist/server/server.mjs +102 -57
  150. package/package.json +1 -1
  151. package/dist/SdkPreviewModeRuntime-LAGYMPNF.mjs +0 -8
  152. package/dist/sdk-runtime-ZJLKC6DR.mjs +0 -8
@@ -135,6 +135,7 @@ riverbankcms push entries blog-post welcome # Specific entry
135
135
  riverbankcms push pages # All pages with blocks
136
136
  riverbankcms push pages home # Specific page with blocks
137
137
  riverbankcms push navigation # Navigation menus
138
+ riverbankcms push settings # Site settings / branding
138
139
  riverbankcms push forms # Forms
139
140
  riverbankcms push theme # Push content/themes/{activeTheme|current}.json
140
141
  riverbankcms push venues # Event venues
@@ -158,7 +159,7 @@ riverbankcms push --dry-run --json-diff=full
158
159
  | `--force-update-asset` | Replace CMS media when identifiers conflict (local media sync only) |
159
160
  | `--allow-truncated` | Push even if remote content was truncated (may cause incomplete sync) |
160
161
  | `--json-diff [mode]` | Output JSON diff: `summary` or `full` |
161
- | `--with-config` | Also push SDK config after content |
162
+ | `--with-config` | Also push SDK schema/config after file content |
162
163
  | `--with-theme` | Also push theme when pushing all content |
163
164
  | `--sync-media` | Sync media files from local to remote environment |
164
165
  | `--overwrite-media` | When using `--sync-media`, overwrite target media on checksum mismatch |
@@ -248,7 +249,7 @@ For theme and footer pushes, stale resolution updates only the metadata timestam
248
249
 
249
250
  - Use `logoIdentifier` / `faviconIdentifier` to manage the site logo and favicon from the repo
250
251
  - The identifiers should match files in `content/media/`
251
- - `riverbankcms push` reuses the normal local-media upload flow before updating site settings
252
+ - `riverbankcms push settings` reuses the normal local-media upload flow before updating site settings, without pushing unrelated content
252
253
  - `riverbankcms pull settings` warns and omits a branding field if the current CMS asset cannot be represented by an identifier yet
253
254
  - Dashboard branding edits and CLI pushes are last-write-wins on the same settings row, so pull before pushing after dashboard-side changes
254
255
 
@@ -193,12 +193,12 @@ Recommended workflow:
193
193
 
194
194
  1. Add the branding files to `content/media/`, for example `content/media/positive-play-primary-logo.svg`
195
195
  2. Reference those identifiers in `content/settings.json`
196
- 3. Run `riverbankcms push`
196
+ 3. Run `riverbankcms push settings`
197
197
  4. Run `riverbankcms pull settings` if you want to confirm the CMS state round-trips cleanly
198
198
 
199
199
  Notes:
200
200
 
201
- - `riverbankcms push` uploads missing branding files through the normal local-media sync path before updating site settings
201
+ - `riverbankcms push settings` uploads missing branding files through the normal local-media sync path before updating site settings, without pushing unrelated content
202
202
  - `riverbankcms pull settings` warns and omits `logoIdentifier` / `faviconIdentifier` if the current CMS branding asset has no media identifier yet
203
203
  - Dashboard branding edits and CLI pushes both update the same site settings row, so treat them as last-write-wins and pull before pushing after dashboard-side edits
204
204
 
@@ -43,9 +43,17 @@ Create `src/proxy.ts`:
43
43
  import { handlePreviewTokens } from '@riverbankcms/sdk/preview-next/middleware'
44
44
  import { NextResponse, type NextRequest } from 'next/server'
45
45
 
46
- export function proxy(request: NextRequest) {
46
+ import { getCmsConfig } from './lib/env'
47
+
48
+ export async function proxy(request: NextRequest) {
47
49
  if (process.env.RIVERBANK_PREVIEW_MODE === 'true') {
48
- const response = handlePreviewTokens(request)
50
+ const { dashboardUrl } = getCmsConfig()
51
+ const response = await handlePreviewTokens(request, {
52
+ dashboardUrl: dashboardUrl ?? null,
53
+ onExchangeFailure: (failure) => {
54
+ console.warn('[riverbank] preview token exchange failed', failure)
55
+ },
56
+ })
49
57
  if (response) return response
50
58
  }
51
59
 
@@ -57,6 +65,10 @@ export const config = {
57
65
  }
58
66
  ```
59
67
 
68
+ The example logs preview exchange failures with `console.warn`; replace it with your app logger if you already centralize server-side logging.
69
+
70
+ If you are upgrading an existing generated site, make sure your proxy imports `getCmsConfig`, is declared `async`, and passes `dashboardUrl` into `handlePreviewTokens`. Without the dashboard URL, visits with `preview_code` cannot exchange the short-lived code for preview cookies.
71
+
60
72
  ## Add Preview Keep-Alive Route
61
73
 
62
74
  Create `src/app/api/preview/keep-alive/route.ts`:
@@ -127,6 +139,60 @@ export default Page
127
139
  export { generateMetadata }
128
140
  ```
129
141
 
142
+ ## Custom Header/Footer Chrome
143
+
144
+ If your site replaces the SDK header or footer, pass that chrome into `PreviewLayoutProvider` only when there is an editable preview session. `RIVERBANK_PREVIEW_MODE=true` makes the route preview-capable, but `getPreviewSession()` tells you whether the current request actually has preview cookies. Regular visitors without preview cookies should keep the normal SDK `Layout`.
145
+
146
+ In `src/app/layout.tsx`:
147
+
148
+ ```tsx
149
+ import type { ReactNode } from 'react'
150
+
151
+ import { Layout } from '@riverbankcms/sdk/rendering/server'
152
+ import { PreviewLayoutProvider } from '@riverbankcms/sdk/preview-next/client'
153
+ import { getPreviewSession } from '@riverbankcms/sdk/preview-next/session'
154
+
155
+ import { getRiverbankClient, getSiteId } from '@/lib/riverbank-client'
156
+
157
+ function SiteHeader() {
158
+ return <header>{/* your site header */}</header>
159
+ }
160
+
161
+ function SiteFooter() {
162
+ return <footer>{/* your site footer */}</footer>
163
+ }
164
+
165
+ export default async function RootLayout({ children }: { children: ReactNode }) {
166
+ const session = await getPreviewSession()
167
+ const hasEditablePreviewSession = Boolean(session?.canEdit && session?.token)
168
+ const headerNode = <SiteHeader />
169
+ const footerNode = <SiteFooter />
170
+
171
+ return (
172
+ <html lang="en">
173
+ <body>
174
+ {hasEditablePreviewSession ? (
175
+ <PreviewLayoutProvider headerNode={headerNode} footerNode={footerNode}>
176
+ {children}
177
+ </PreviewLayoutProvider>
178
+ ) : (
179
+ <Layout
180
+ client={getRiverbankClient()}
181
+ siteId={getSiteId()}
182
+ header={() => headerNode}
183
+ footer={() => footerNode}
184
+ >
185
+ {children}
186
+ </Layout>
187
+ )}
188
+ </body>
189
+ </html>
190
+ )
191
+ }
192
+ ```
193
+
194
+ If your custom chrome needs CMS navigation data, build the `headerNode` and `footerNode` from the same data used by your normal layout before branching. Calling `getPreviewSession()` in the root layout reads cookies, so the layout becomes dynamic.
195
+
130
196
  ## Import Preview CSS
131
197
 
132
198
  For Tailwind sites, add this to `src/app/globals.css`:
@@ -1,5 +1,5 @@
1
- import { defineIslandPropsDecoder } from './chunk-65F47D7Y.mjs';
2
- import './chunk-IVNCUVAV.mjs';
1
+ import { defineIslandPropsDecoder } from './chunk-JGXPTEI2.mjs';
2
+ import './chunk-AUJ5DBZJ.mjs';
3
3
 
4
4
  // src/rendering/islands/enhancers/accordion.ts
5
5
  var decode = defineIslandPropsDecoder("accordion");
@@ -66,7 +66,7 @@ function useAnalytics(config) {
66
66
  console.warn("[analytics] Failed to initialize client", error);
67
67
  }
68
68
  }
69
- start();
69
+ void start();
70
70
  return () => {
71
71
  disposed = true;
72
72
  if (state.client) {
@@ -1,15 +1,15 @@
1
1
  "use client";
2
- import { usePolling } from './chunk-YDSEG6GZ.mjs';
3
- import { SpinnerNode } from './chunk-36WJCERQ.mjs';
4
- import { useDiscountCodeUi } from './chunk-PD6NBCEY.mjs';
5
- import { scrollToBlock, buildCheckoutReturnUrls, DiscountCodeDisclosure, formatPrice } from './chunk-VPPMNXCF.mjs';
2
+ import { usePolling } from './chunk-DNRGY432.mjs';
3
+ import { SpinnerNode } from './chunk-CE7IBGVW.mjs';
4
+ import { useDiscountCodeUi } from './chunk-ZFHRN6W2.mjs';
5
+ import { scrollToBlock, buildCheckoutReturnUrls, DiscountCodeDisclosure, formatPrice } from './chunk-UVQEJJTN.mjs';
6
6
  import { FieldValidationMessage, getFieldValidationControlProps } from './chunk-3DCJ45Z2.mjs';
7
7
  import './chunk-3PEDD5KJ.mjs';
8
8
  import { isSpamProtectionEnabled, getChallengeUrl, AltchaWidget } from './chunk-YLMKMCSJ.mjs';
9
9
  import { BlockApiProvider, useBlockApi, FeedbackMessage } from './chunk-UDNSI5PY.mjs';
10
10
  import { mountReactIsland } from './chunk-N7PBWBWQ.mjs';
11
- 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-65F47D7Y.mjs';
12
- import { resolveBookingTimeZoneId, DEFAULT_BOOKING_TIME_ZONE, asFormId, asAppointmentResourceId, asCustomerPassId, asAppointmentServiceId, formatLocalScheduleDate, addLocalScheduleDays, parseBookingLocalDate, resolveFlexibleBalanceInitialPaymentCents, resolveFlexibleBalanceDueAt, getBookingInstalmentDepositRefundability, asPassId, splitAmountWithRemainderInFirst, addIntervalPreservingMonthAnchor, clampConfiguredAmount, getBookingInstalmentPlanIntervalCount, omitZeroAmountFutureRows, formatBookingInstant } from './chunk-IVNCUVAV.mjs';
11
+ 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-JGXPTEI2.mjs';
12
+ 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-AUJ5DBZJ.mjs';
13
13
  import React2, { useRef, useState, useMemo, useReducer, useEffect, useCallback, useLayoutEffect } from 'react';
14
14
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
15
15
 
@@ -223,7 +223,7 @@ function useAvailableDates({
223
223
  const endDate = formatLocalScheduleDate(
224
224
  addLocalScheduleDays(parseBookingLocalDate(today), initialDays)
225
225
  );
226
- fetchDates(today, endDate, false);
226
+ void fetchDates(today, endDate, false);
227
227
  }, [serviceId, fetchDates, initialDays]);
228
228
  useVisibleTabPolling({
229
229
  enabled: Boolean(serviceId && loadedRange),
@@ -243,7 +243,7 @@ function useAvailableDates({
243
243
  BOOKING_FETCH_CHUNK_DAYS
244
244
  )
245
245
  );
246
- fetchDates(start, end, true);
246
+ void fetchDates(start, end, true);
247
247
  }, [fetchDates, isLoading]);
248
248
  return {
249
249
  availableDates,
@@ -303,7 +303,7 @@ function useAvailableSlots({
303
303
  setSlots(
304
304
  result.slots.map((slot) => ({
305
305
  ...slot,
306
- resourceId: asAppointmentResourceId(slot.resourceId)
306
+ resourceId: unsafeAsAppointmentResourceId(slot.resourceId)
307
307
  }))
308
308
  );
309
309
  setHasLoaded(true);
@@ -675,7 +675,7 @@ function formatScheduleDate(isoString, locale) {
675
675
  }
676
676
 
677
677
  // ../blocks/src/system/runtime/nodes/booking-form.headless.state.ts
678
- var asBookingFieldId = (id) => id;
678
+ var unsafeAsBookingFieldId = (id) => id;
679
679
  function createEmptyBookingValidationErrors() {
680
680
  return { formError: null, fieldErrors: {} };
681
681
  }
@@ -745,13 +745,13 @@ function toOptionalBrandedId(value, brand) {
745
745
  return trimmed ? brand(trimmed) : void 0;
746
746
  }
747
747
  function toOptionalAppointmentServiceId(value) {
748
- return toOptionalBrandedId(value, asAppointmentServiceId);
748
+ return toOptionalBrandedId(value, unsafeAsAppointmentServiceId);
749
749
  }
750
750
  function toOptionalAppointmentResourceId(value) {
751
- return toOptionalBrandedId(value, asAppointmentResourceId);
751
+ return toOptionalBrandedId(value, unsafeAsAppointmentResourceId);
752
752
  }
753
753
  function toOptionalCustomerPassId(value) {
754
- return toOptionalBrandedId(value, asCustomerPassId);
754
+ return toOptionalBrandedId(value, unsafeAsCustomerPassId);
755
755
  }
756
756
  function isBookingFieldValue(value) {
757
757
  return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || Array.isArray(value) && value.every((item) => typeof item === "string");
@@ -905,7 +905,7 @@ function toBookingSlotView(slot) {
905
905
  key: `${slot.startAt}|${slot.endAt}|${slot.resourceId}`,
906
906
  startAt: slot.startAt,
907
907
  endAt: slot.endAt,
908
- resourceId: asAppointmentResourceId(slot.resourceId),
908
+ resourceId: unsafeAsAppointmentResourceId(slot.resourceId),
909
909
  ...slot.resourceName ? { resourceName: slot.resourceName } : {},
910
910
  ...slot.label ? { label: slot.label } : {}
911
911
  };
@@ -1027,29 +1027,30 @@ function validateBookingField(field, value) {
1027
1027
  }
1028
1028
  if (isBlankFieldValue(value)) return null;
1029
1029
  const strValue = typeof value === "string" ? value : String(value);
1030
- switch (field.type) {
1031
- case "email":
1032
- return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(strValue) ? null : "Please enter a valid email address";
1033
- case "url":
1034
- try {
1035
- new URL(strValue);
1036
- return null;
1037
- } catch {
1038
- return "Please enter a valid URL";
1039
- }
1040
- case "tel":
1041
- return /^[+\d\s\-()]+$/.test(strValue) ? null : "Please enter a valid phone number";
1042
- case "number": {
1043
- const num = Number(value);
1044
- if (Number.isNaN(num)) return "Please enter a valid number";
1045
- if (field.min !== void 0 && num < field.min) {
1046
- return `Value must be at least ${field.min}`;
1047
- }
1048
- if (field.max !== void 0 && num > field.max) {
1049
- return `Value must be at most ${field.max}`;
1050
- }
1030
+ if (field.type === "email") {
1031
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(strValue) ? null : "Please enter a valid email address";
1032
+ }
1033
+ if (field.type === "url") {
1034
+ try {
1035
+ new URL(strValue);
1051
1036
  return null;
1037
+ } catch {
1038
+ return "Please enter a valid URL";
1039
+ }
1040
+ }
1041
+ if (field.type === "tel") {
1042
+ return /^[+\d\s\-()]+$/.test(strValue) ? null : "Please enter a valid phone number";
1043
+ }
1044
+ if (field.type === "number") {
1045
+ const num = Number(value);
1046
+ if (Number.isNaN(num)) return "Please enter a valid number";
1047
+ if (field.min !== void 0 && num < field.min) {
1048
+ return `Value must be at least ${field.min}`;
1049
+ }
1050
+ if (field.max !== void 0 && num > field.max) {
1051
+ return `Value must be at most ${field.max}`;
1052
1052
  }
1053
+ return null;
1053
1054
  }
1054
1055
  if (typeof value === "string") {
1055
1056
  if (field.minLength && value.length < field.minLength) {
@@ -1148,7 +1149,7 @@ function buildBookingAvailabilityQuery(input) {
1148
1149
  }
1149
1150
  function deriveBookingFieldViews(input) {
1150
1151
  return (input.form?.schema?.fields ?? []).map((field) => {
1151
- const fieldId = asBookingFieldId(field.id);
1152
+ const fieldId = unsafeAsBookingFieldId(field.id);
1152
1153
  const inputId = `${input.idPrefix}-${fieldId}`;
1153
1154
  const helpTextId = field.helpText ? `${inputId}-help` : null;
1154
1155
  const fieldValue = input.values[field.id] ?? null;
@@ -1305,8 +1306,8 @@ function resolveAppointmentPackagesModel(input) {
1305
1306
  function toHeadlessEligibleAppointmentPackage(appointmentPackage) {
1306
1307
  return {
1307
1308
  ...appointmentPackage,
1308
- customerPassId: asCustomerPassId(appointmentPackage.customerPassId),
1309
- passId: asPassId(appointmentPackage.passId)
1309
+ customerPassId: unsafeAsCustomerPassId(appointmentPackage.customerPassId),
1310
+ passId: unsafeAsPassId(appointmentPackage.passId)
1310
1311
  };
1311
1312
  }
1312
1313
  function resolveHeadlessBookingStatus(input) {
@@ -1366,7 +1367,7 @@ function omitRecordKey(record, key) {
1366
1367
  // ../blocks/src/system/runtime/hooks/useHeadlessBookingFlow.ts
1367
1368
  function useHeadlessBookingFlow(options) {
1368
1369
  const viewerTimeZone = options.viewerTimeZone ?? getRuntimeTimeZone();
1369
- const formKey = asFormId(options.formId);
1370
+ const formKey = unsafeAsFormId(options.formId);
1370
1371
  const defaultServiceId = toOptionalAppointmentServiceId(
1371
1372
  options.initialServiceId ?? resolveDefaultBookingServiceId(options.form, options.services) ?? void 0
1372
1373
  );
@@ -1532,7 +1533,7 @@ function useHeadlessBookingFlow(options) {
1532
1533
  setResourcesState({
1533
1534
  tag: "loaded",
1534
1535
  value: (result.options ?? []).map((option) => ({
1535
- id: asAppointmentResourceId(option.id),
1536
+ id: unsafeAsAppointmentResourceId(option.id),
1536
1537
  label: option.label
1537
1538
  }))
1538
1539
  });
@@ -1748,11 +1749,11 @@ function useHeadlessBookingFlow(options) {
1748
1749
  () => ({
1749
1750
  selectService: (serviceId) => dispatch({
1750
1751
  type: "service-selected",
1751
- serviceId: asAppointmentServiceId(serviceId)
1752
+ serviceId: unsafeAsAppointmentServiceId(serviceId)
1752
1753
  }),
1753
1754
  selectResource: (resourceId) => dispatch({
1754
1755
  type: "resource-selected",
1755
- resourceId: resourceId ? asAppointmentResourceId(resourceId) : null
1756
+ resourceId: resourceId ? unsafeAsAppointmentResourceId(resourceId) : null
1756
1757
  }),
1757
1758
  selectDate: (date) => dispatch({ type: "date-selected", date }),
1758
1759
  selectSlot: (slot) => dispatch({
@@ -1761,14 +1762,14 @@ function useHeadlessBookingFlow(options) {
1761
1762
  }),
1762
1763
  updateField: (fieldId, value) => dispatch({
1763
1764
  type: "field-updated",
1764
- fieldId: asBookingFieldId(fieldId),
1765
+ fieldId: unsafeAsBookingFieldId(fieldId),
1765
1766
  value
1766
1767
  }),
1767
- markFieldTouched: (fieldId) => dispatch({ type: "field-touched", fieldId: asBookingFieldId(fieldId) }),
1768
+ markFieldTouched: (fieldId) => dispatch({ type: "field-touched", fieldId: unsafeAsBookingFieldId(fieldId) }),
1768
1769
  selectPaymentOption: (kind) => dispatch({ type: "payment-option-selected", kind }),
1769
1770
  selectAppointmentPackage: (packageId) => dispatch({
1770
1771
  type: "appointment-package-selected",
1771
- packageId: packageId ? asCustomerPassId(packageId) : null
1772
+ packageId: packageId ? unsafeAsCustomerPassId(packageId) : null
1772
1773
  }),
1773
1774
  setDiscountCode: (code) => {
1774
1775
  dispatch({ type: "discount-code-changed", code });
@@ -2603,7 +2604,7 @@ function DefaultFieldInput({
2603
2604
  ] }, option.value)) });
2604
2605
  case "checkbox":
2605
2606
  if (field.field.options && field.field.options.length > 1) {
2606
- const checkedValues = Array.isArray(value) ? value : [];
2607
+ const checkedValues = toStringArray(value);
2607
2608
  return /* @__PURE__ */ jsx("div", { className: "rb-space-y-2", children: field.field.options.map((option) => /* @__PURE__ */ jsxs("label", { className: "rb-flex rb-items-center rb-gap-2 rb-cursor-pointer", children: [
2608
2609
  /* @__PURE__ */ jsx(
2609
2610
  "input",
@@ -2698,7 +2699,10 @@ function DefaultFieldInput({
2698
2699
  className: "form-input"
2699
2700
  }
2700
2701
  );
2701
- default:
2702
+ case "text":
2703
+ case "email":
2704
+ case "tel":
2705
+ case "url":
2702
2706
  return /* @__PURE__ */ jsx(
2703
2707
  "input",
2704
2708
  {
@@ -2715,6 +2719,9 @@ function DefaultFieldInput({
2715
2719
  );
2716
2720
  }
2717
2721
  }
2722
+ function toStringArray(value) {
2723
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
2724
+ }
2718
2725
  function DefaultBookingDiscount({
2719
2726
  booking
2720
2727
  }) {
@@ -2806,7 +2813,7 @@ function collapseHeadlessSlotsForDisplay(input) {
2806
2813
  visibleSlots.push({
2807
2814
  startAt: slot.startAt,
2808
2815
  endAt: slot.endAt,
2809
- resourceId: asAppointmentResourceId(slot.resourceId)
2816
+ resourceId: unsafeAsAppointmentResourceId(slot.resourceId)
2810
2817
  });
2811
2818
  }
2812
2819
  return visibleSlots;