@riverbankcms/sdk 0.140.0 → 0.141.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/dist/{PreviewEditorSidebar-CUyTzd5z.mjs → PreviewEditorSidebar-Q-fy9GYw.mjs} +3 -3
  2. package/dist/{PreviewEditorUI-Agkw4v5i.mjs → PreviewEditorUI-LYGzgk85.mjs} +2 -2
  3. package/dist/{SdkPreviewModeRuntime-DdbeAdS8.mjs → SdkPreviewModeRuntime-CoPYI5Jq.mjs} +72 -46
  4. package/dist/{SiteChromeCustomizeContext-CqGOz-Kv.mjs → SiteChromeCustomizeContext-D8LePX8x.mjs} +681 -196
  5. package/dist/_dts/api/src/contentRuntime.d.ts +12 -31
  6. package/dist/_dts/api/src/domainConnection.d.ts +4 -0
  7. package/dist/_dts/api/src/footerCompositionContracts.d.ts +25 -0
  8. package/dist/_dts/api/src/index.d.ts +1 -1
  9. package/dist/_dts/api/src/launchReadiness.d.ts +1 -0
  10. package/dist/_dts/api/src/navigation/dashboardSiteNav.d.ts +2 -1
  11. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +3 -26
  12. package/dist/_dts/api/src/siteOnboarding.d.ts +7 -0
  13. package/dist/_dts/billing/src/site-arrangements.d.ts +12 -3
  14. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +4 -0
  15. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +2 -0
  16. package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +2 -0
  17. package/dist/_dts/blocks/src/system/blocks/events/eventSelectionFields.d.ts +122 -0
  18. package/dist/_dts/blocks/src/system/blocks/events/shared/calendarWindow.d.ts +2 -1
  19. package/dist/_dts/blocks/src/system/blocks/events/shared/eventSelection.d.ts +11 -0
  20. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +2 -2
  21. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +47 -47
  22. package/dist/_dts/blocks/src/system/data/prefetchBlockData.d.ts +5 -0
  23. package/dist/_dts/blocks/src/system/data/utils.d.ts +1 -1
  24. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +27 -1
  25. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +12 -180
  26. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +6 -90
  27. package/dist/_dts/blocks/src/system/runtime/hooks/useEventFilters.d.ts +2 -1
  28. package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +5 -1
  29. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +4 -0
  30. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.state.d.ts +5 -0
  31. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useDiscountCodeUi.d.ts +3 -0
  32. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useDiscountCodeUi.state.d.ts +10 -3
  33. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventCheckoutHandoffRestore.d.ts +9 -0
  34. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +4 -5
  35. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useSettledCommerceView.d.ts +37 -0
  36. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +4 -3
  37. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +3 -0
  38. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +11 -101
  39. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +7 -2
  40. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/listOptions.d.ts +2 -0
  41. package/dist/_dts/blocks/src/system/transforms/registry/eventCalendar.d.ts +12 -0
  42. package/dist/_dts/commerce/src/purchase/bookingInstalmentSchedule.d.ts +4 -0
  43. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +3 -0
  44. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/loaders.d.ts +27 -1
  45. package/dist/_dts/sdk/src/public-api/contracts.d.ts +1 -1
  46. package/dist/_dts/sdk/src/version.d.ts +1 -1
  47. package/dist/_dts/theme-core/src/ThemeFontLoader.d.ts +17 -1
  48. package/dist/_dts/theme-core/src/buttons/affordanceSuppression.d.ts +17 -0
  49. package/dist/_dts/theme-core/src/buttons/buttonColourContract.d.ts +1 -1
  50. package/dist/_dts/theme-core/src/buttons/classNames.d.ts +16 -0
  51. package/dist/_dts/theme-core/src/buttons/generateButtonCss.d.ts +0 -6
  52. package/dist/_dts/theme-core/src/buttons/resolvedButtonCss.d.ts +4 -4
  53. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  54. package/dist/_dts/theme-core/src/hosted-booking-appearance.d.ts +54 -12
  55. package/dist/_dts/theme-core/src/index.d.ts +1 -1
  56. package/dist/client/{BookingConsentAgreement-CuKa82V4.mjs → BookingConsentAgreement-xJeYNdnb.mjs} +2 -2
  57. package/dist/client/{DiscountCodeDisclosure-BbYieKWB.mjs → DiscountCodeDisclosure-DdT6uzl9.mjs} +1 -1
  58. package/dist/client/{EventCombined.client-LTfR1Aby.mjs → EventCombined.client-Cp28uYuM.mjs} +11 -15
  59. package/dist/client/{EventListing.client-DUHpYSuo.mjs → EventListing.client-CD6AJsMr.mjs} +4 -17
  60. package/dist/client/{LeafletStaticMap-CHRupL6m.mjs → LeafletStaticMap-DBsAi9-e.mjs} +1 -1
  61. package/dist/client/{accordion-6HiIFxNL.mjs → accordion-6dwbOKYR.mjs} +1 -1
  62. package/dist/client/{bookingForm-Dlmid43H.mjs → bookingForm-CZE9_qPQ.mjs} +5 -5
  63. package/dist/client/bookings.mjs +175 -93
  64. package/dist/client/{carousel-DmkZRRq_.mjs → carousel-7VHGQARz.mjs} +1 -1
  65. package/dist/client/{cart-CIC24330.mjs → cart-Qg_mvQhh.mjs} +3 -3
  66. package/dist/client/{checkout-D1Zw9imo.mjs → checkout-D84rpgdr.mjs} +3 -3
  67. package/dist/client/client.mjs +602 -139
  68. package/dist/client/{context-Cy1OayHx.mjs → context-Ctp3T0Wr.mjs} +1 -1
  69. package/dist/client/{dates-aDcfoLHr.mjs → dates-DJKFcI_N.mjs} +2 -2
  70. package/dist/client/{eventCalendar-FQxMPAjf.mjs → eventCalendar-CK31z3vs.mjs} +11 -7
  71. package/dist/client/{eventCombined-Dr3ac6Hb.mjs → eventCombined-DiXd-ewn.mjs} +3 -3
  72. package/dist/client/{eventDetails-D-AzUHFQ.mjs → eventDetails-CTRgt2DK.mjs} +4 -4
  73. package/dist/client/{eventListing-B3XxBf3i.mjs → eventListing-Dy9vi_j_.mjs} +3 -3
  74. package/dist/client/{eventRegistration-I6EaokFD.mjs → eventRegistration-CnalYMr2.mjs} +124 -31
  75. package/dist/client/{form-BbWckVWY.mjs → form-eUiMveTT.mjs} +2 -2
  76. package/dist/client/{headerSection-C9qU4Y7x.mjs → headerSection-Dy9kQpB1.mjs} +2 -2
  77. package/dist/client/hooks.mjs +247 -32
  78. package/dist/client/{locationMap-CLCShvlG.mjs → locationMap-DalCmWU0.mjs} +2 -2
  79. package/dist/client/{newsletterForm-Briukxzi.mjs → newsletterForm-SDDPvhS0.mjs} +23 -10
  80. package/dist/client/{pricing-Copadu-2.mjs → pricing-OcMz4SnX.mjs} +1 -1
  81. package/dist/client/{productDetail-oujlRd-r.mjs → productDetail-BQrgHElM.mjs} +3 -3
  82. package/dist/client/{productList-BRiIRUcd.mjs → productList-OnPn_UJj.mjs} +3 -3
  83. package/dist/client/{propsDecoder-CB2KS_ko.mjs → propsDecoder-zBdsnS-N.mjs} +38 -8
  84. package/dist/client/rendering/client.mjs +446 -121
  85. package/dist/client/rendering/islands.mjs +17 -17
  86. package/dist/client/rendering.mjs +601 -138
  87. package/dist/client/{scrollToBlock-B1IS1_ua.mjs → scrollToBlock-BNM4Ob2Y.mjs} +28 -11
  88. package/dist/client/{shop-Vn6yNFED.mjs → shop-Bv1fPTwQ.mjs} +6 -6
  89. package/dist/client/{shop-commerce-BVTqipYp.mjs → shop-commerce-D4KNGaW8.mjs} +5 -5
  90. package/dist/client/{shop-commerce-store-BVnJVy7v.mjs → shop-commerce-store-2N5EV0Rc.mjs} +1 -1
  91. package/dist/client/{shopShared-COIeK77T.mjs → shopShared-DvJGdHTV.mjs} +3 -3
  92. package/dist/client/{useEventFilters-DzIUcS9n.mjs → useEventFilters-BBBvGDHQ.mjs} +17 -11
  93. package/dist/preview-next/client/runtime.mjs +3 -3
  94. package/dist/preview-next/editor-chrome.css +4 -8
  95. package/dist/{sdk-runtime-CnCLvZRv.mjs → sdk-runtime-Defnbfzw.mjs} +1 -1
  96. package/dist/{separator-DKDRJ1oH.mjs → separator-CZXO3Sb0.mjs} +1 -1
  97. package/dist/server/components.mjs +384 -62
  98. package/dist/server/config-validation.mjs +232 -26
  99. package/dist/server/config.mjs +232 -26
  100. package/dist/server/data.mjs +247 -32
  101. package/dist/server/index.mjs +1 -1
  102. package/dist/server/next.mjs +400 -69
  103. package/dist/server/page-converter.mjs +189 -25
  104. package/dist/server/prebuild.mjs +1 -1
  105. package/dist/server/rendering/server.mjs +399 -68
  106. package/dist/server/rendering.mjs +399 -68
  107. package/dist/server/routing.mjs +261 -33
  108. package/dist/server/server.mjs +248 -33
  109. package/dist/server/theme-bridge.mjs +47 -15
  110. package/dist/server/theme.mjs +1 -1
  111. package/dist/styles/index.css +28 -2
  112. package/package.json +1 -1
@@ -9565,7 +9565,7 @@ var SimpleCache = class {
9565
9565
  * 1. This constant
9566
9566
  * 2. The "version" field in package.json
9567
9567
  */
9568
- const SDK_VERSION = "0.140.0";
9568
+ const SDK_VERSION = "0.141.0";
9569
9569
  //#endregion
9570
9570
  //#region src/client/error.ts
9571
9571
  let _Symbol$for;
@@ -10899,7 +10899,7 @@ const BUTTON_CONTRAST_POLICY = {
10899
10899
  nonTextMinimumRatio: 3,
10900
10900
  gradientSamplesPerSegment: 20,
10901
10901
  alphaBackgrounds: "reject-without-known-surface",
10902
- disabled: "retain-full-colour-contract"
10902
+ disabled: "validated-colour-pair-with-muted-control-opacity"
10903
10903
  };
10904
10904
  function validateButtonSurfaceContrast(input) {
10905
10905
  const ratio = contrastRatio(input.buttonPaint, input.surfaceHex);
@@ -16457,6 +16457,7 @@ function isDisplayMediaKind(kind) {
16457
16457
  }
16458
16458
  const siteOptionSources = [
16459
16459
  "eventCategories",
16460
+ "eventSeries",
16460
16461
  "venues",
16461
16462
  "staffMembers"
16462
16463
  ];
@@ -35383,7 +35384,8 @@ const appointmentServicesBlockDefinition = {
35383
35384
  el("appointment-services", {
35384
35385
  sectionHeading: { $bind: { from: "content.heading" } },
35385
35386
  services: { $bind: { from: "data.services" } },
35386
- pathname: { $bind: { from: "$root.pathname" } }
35387
+ pathname: { $bind: { from: "$root.pathname" } },
35388
+ servicePathPrefix: { $bind: { from: "$root.appointmentServicePathPrefix" } }
35387
35389
  })
35388
35390
  ], { gap: "lg" })
35389
35391
  })]
@@ -37395,6 +37397,35 @@ const eventSpotlightBlockDefinition = {
37395
37397
  } }
37396
37398
  };
37397
37399
  //#endregion
37400
+ //#region ../blocks/src/system/blocks/events/shared/eventSelection.ts
37401
+ /** Invalid saved selections fail closed rather than widening discovery. */
37402
+ function resolveEventSelection(mode, value) {
37403
+ if (mode !== "selected") return { kind: "matching" };
37404
+ const candidates = Array.isArray(value) ? value : typeof value === "string" ? value.split(",").filter(Boolean) : [];
37405
+ const ids = [];
37406
+ for (const candidate of candidates) {
37407
+ if (typeof candidate !== "string") return {
37408
+ kind: "selected",
37409
+ seriesIds: []
37410
+ };
37411
+ const parsed = parseEventSeriesId(candidate.trim());
37412
+ if (!parsed.ok) return {
37413
+ kind: "selected",
37414
+ seriesIds: []
37415
+ };
37416
+ ids.push(parsed.value);
37417
+ }
37418
+ return {
37419
+ kind: "selected",
37420
+ seriesIds: [...new Set(ids)].sort()
37421
+ };
37422
+ }
37423
+ /** Undefined means discovery; an empty string is an explicitly empty selection. */
37424
+ function eventSeriesScopeCsv(value) {
37425
+ if (value == null) return void 0;
37426
+ return typeof value === "string" ? value : value.join(",");
37427
+ }
37428
+ //#endregion
37398
37429
  //#region ../blocks/src/system/runtime/nodes/events/shared/listingLayout.ts
37399
37430
  /**
37400
37431
  * Layout classes for event listing containers and cards. Presentation
@@ -37523,6 +37554,7 @@ const calendarWindowQuerySchema = z.object({
37523
37554
  eventSurface: z.enum(eventSurfaceScopeValues).optional(),
37524
37555
  eventPresets: z.string().optional(),
37525
37556
  scheduleScope: z.enum(eventScheduleScopeValues).optional(),
37557
+ seriesIds: z.string().optional(),
37526
37558
  categoryIds: z.string().optional(),
37527
37559
  venueId: z.string().transform(normalizeCalendarFilterId).optional(),
37528
37560
  staffMemberId: z.string().transform(normalizeCalendarFilterId).optional()
@@ -37585,6 +37617,7 @@ const eventCollectionFilterSourceSchemaShape = {
37585
37617
  eventSurface: eventSurfaceScopeSchema$1.nullable().optional(),
37586
37618
  filterEventPresets: z.union([z.string(), z.array(z.string())]).nullable().optional(),
37587
37619
  scheduleScope: eventScheduleScopeSchema$1.nullable().optional(),
37620
+ seriesIds: z.union([z.string(), z.array(z.string())]).nullable().optional(),
37588
37621
  filterCategoryIds: z.union([z.string(), z.array(z.string())]).nullable().optional(),
37589
37622
  filterStaffMemberId: z.string().nullable().optional(),
37590
37623
  filterVenueId: z.string().nullable().optional()
@@ -37631,6 +37664,7 @@ const eventCollectionDisplaySchemaShape = {
37631
37664
  eventSurface: eventSurfaceScopeSchema$1,
37632
37665
  filterEventPresets: z.string().nullable(),
37633
37666
  scheduleScope: eventScheduleScopeSchema$1,
37667
+ seriesIds: z.string().nullable().optional(),
37634
37668
  filterCategoryIds: z.string().nullable(),
37635
37669
  filterStaffMemberId: z.string().nullable(),
37636
37670
  filterVenueId: z.string().nullable(),
@@ -37678,11 +37712,15 @@ function buildEventCollectionDisplay(source) {
37678
37712
  };
37679
37713
  }
37680
37714
  function buildEventCollectionFilterDisplay(source) {
37681
- return {
37682
- showFilters: source.showFilters ?? true,
37683
- showCategoryFilter: source.showCategoryFilter ?? "auto",
37684
- showVenueFilter: source.showVenueFilter ?? false,
37685
- showStaffFilter: source.showStaffFilter ?? true,
37715
+ const selected = source.seriesIds != null;
37716
+ const matchingFilters = selected ? {
37717
+ eventSurface: "all",
37718
+ filterEventPresets: null,
37719
+ scheduleScope: "any",
37720
+ filterCategoryIds: null,
37721
+ filterStaffMemberId: null,
37722
+ filterVenueId: null
37723
+ } : {
37686
37724
  eventSurface: normalizeEventSurfaceScope(source.eventSurface),
37687
37725
  filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
37688
37726
  scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
@@ -37690,6 +37728,14 @@ function buildEventCollectionFilterDisplay(source) {
37690
37728
  filterStaffMemberId: normalizeEventStaffMemberId(source.filterStaffMemberId),
37691
37729
  filterVenueId: normalizeEventVenueId(source.filterVenueId)
37692
37730
  };
37731
+ return {
37732
+ seriesIds: eventSeriesScopeCsv(source.seriesIds),
37733
+ showFilters: selected ? false : source.showFilters ?? true,
37734
+ showCategoryFilter: source.showCategoryFilter ?? "auto",
37735
+ showVenueFilter: source.showVenueFilter ?? false,
37736
+ showStaffFilter: source.showStaffFilter ?? true,
37737
+ ...matchingFilters
37738
+ };
37693
37739
  }
37694
37740
  function buildEventCollectionPresentationDisplay(source) {
37695
37741
  return {
@@ -37704,14 +37750,15 @@ function buildEventCollectionPresentationDisplay(source) {
37704
37750
  }
37705
37751
  function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date()) {
37706
37752
  const timeZone = source.calendarWindow?.scope.timeZone ?? toBookingTimeZone(source.bookingTimeZone);
37753
+ const selected = source.seriesIds != null;
37707
37754
  return {
37708
37755
  calendarWindow: source.calendarWindow ?? void 0,
37709
37756
  siteId: source.siteId,
37710
37757
  stage: source.stage,
37711
37758
  prefetchedEvents: source.events != null,
37712
- eventSurface: normalizeEventSurfaceScope(source.eventSurface),
37713
- filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
37714
- scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
37759
+ eventSurface: selected ? "all" : normalizeEventSurfaceScope(source.eventSurface),
37760
+ filterEventPresets: selected ? null : normalizeEventSurfacePresetsCsv(source.filterEventPresets),
37761
+ scheduleScope: selected ? "any" : normalizeEventScheduleScope(source.scheduleScope),
37715
37762
  calendarContext: {
37716
37763
  timeZone,
37717
37764
  initialToday: source.calendarWindow?.initialToday ?? getLocalScheduleDate(now, timeZone)
@@ -37777,6 +37824,7 @@ const eventListingHydrationSchema = z.object({
37777
37824
  eventSurface: eventSurfaceScopeSchema,
37778
37825
  filterEventPresets: z.string().nullable(),
37779
37826
  scheduleScope: eventScheduleScopeSchema,
37827
+ seriesIds: z.string().nullable().optional(),
37780
37828
  filterCategoryIds: z.string().nullable().optional(),
37781
37829
  filterStaffMemberId: z.string().nullable().optional(),
37782
37830
  filterVenueId: z.string().nullable().optional(),
@@ -37837,6 +37885,7 @@ const eventListingBlockRuntime = defineProgressiveBlockRuntime({
37837
37885
  eventSurface: normalizeEventSurfaceScope(source.eventSurface),
37838
37886
  filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
37839
37887
  scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
37888
+ seriesIds: eventSeriesScopeCsv(source.seriesIds),
37840
37889
  filterCategoryIds: normalizeEventCategoryIdsCsv(source.filterCategoryIds),
37841
37890
  filterStaffMemberId: normalizeEventStaffMemberId(source.filterStaffMemberId),
37842
37891
  filterVenueId: normalizeEventVenueId(source.filterVenueId),
@@ -38210,6 +38259,65 @@ const eventListingBlockDefinition = {
38210
38259
  } }
38211
38260
  };
38212
38261
  //#endregion
38262
+ //#region ../blocks/src/system/blocks/events/eventSelectionFields.ts
38263
+ const eventSelectionFields = [{
38264
+ id: "eventSelection",
38265
+ type: "select",
38266
+ label: "Events to show",
38267
+ required: false,
38268
+ multiple: false,
38269
+ defaultValue: "matching",
38270
+ options: [{
38271
+ value: "matching",
38272
+ label: "All matching events"
38273
+ }, {
38274
+ value: "selected",
38275
+ label: "Selected events"
38276
+ }],
38277
+ ui: { intent: "behavior" }
38278
+ }, createSiteOptionSelectField({
38279
+ id: "selectedEventSeriesIds",
38280
+ label: "Selected events",
38281
+ description: "Show upcoming dates for these events. Other event filters do not apply.",
38282
+ required: false,
38283
+ multiple: true,
38284
+ defaultValue: [],
38285
+ optionSource: "eventSeries",
38286
+ ui: {
38287
+ intent: "behavior",
38288
+ searchThreshold: 1,
38289
+ visibleWhen: {
38290
+ field: "eventSelection",
38291
+ equals: "selected"
38292
+ }
38293
+ }
38294
+ })];
38295
+ function withEventSelectionVisibility(field) {
38296
+ if (![
38297
+ "eventSurface",
38298
+ "filterEventPresets",
38299
+ "scheduleScope",
38300
+ "filterCategoryIds",
38301
+ "filterStaffMemberId",
38302
+ "filterVenueId",
38303
+ "showFilters",
38304
+ "showCategoryFilter",
38305
+ "showVenueFilter",
38306
+ "showStaffFilter"
38307
+ ].includes(field.id)) return field;
38308
+ const visibleWhen = field.ui?.visibleWhen;
38309
+ return {
38310
+ ...field,
38311
+ ui: {
38312
+ ...field.ui,
38313
+ visibleWhen: { allOf: [{
38314
+ field: "eventSelection",
38315
+ notEquals: "selected"
38316
+ }, ...visibleWhen ? [visibleWhen] : []] }
38317
+ }
38318
+ };
38319
+ }
38320
+ //#endregion
38213
38321
  //#region ../blocks/src/system/runtime/nodes/events/EventCalendar.interactive.ts
38214
38322
  const eventCalendarSourceSchema = z.object({
38215
38323
  ...eventCollectionSourceSchemaShape,
@@ -38292,19 +38400,59 @@ const eventCalendarBlockRuntime = defineProgressiveBlockRuntime({
38292
38400
  //#region ../blocks/src/system/blocks/events/eventCalendarDataLoaders.ts
38293
38401
  const scopeParams = {
38294
38402
  siteId: { $bind: { from: "$root.siteId" } },
38403
+ seriesIds: { $bind: {
38404
+ from: "content",
38405
+ transforms: [{
38406
+ id: "events.calendarSelectionParam",
38407
+ options: { key: "seriesIds" }
38408
+ }]
38409
+ } },
38295
38410
  stage: { $bind: {
38296
38411
  from: "$root.previewStage",
38297
38412
  fallback: "published"
38298
38413
  } },
38299
- eventSurface: { $bind: { from: "content.eventSurface" } },
38414
+ eventSurface: { $bind: {
38415
+ from: "content",
38416
+ transforms: [{
38417
+ id: "events.calendarSelectionParam",
38418
+ options: { key: "eventSurface" }
38419
+ }, { id: "value.csv" }]
38420
+ } },
38300
38421
  eventPresets: { $bind: {
38301
- from: "content.filterEventPresets",
38302
- transforms: [{ id: "value.csv" }]
38422
+ from: "content",
38423
+ transforms: [{
38424
+ id: "events.calendarSelectionParam",
38425
+ options: { key: "filterEventPresets" }
38426
+ }, { id: "value.csv" }]
38427
+ } },
38428
+ scheduleScope: { $bind: {
38429
+ from: "content",
38430
+ transforms: [{
38431
+ id: "events.calendarSelectionParam",
38432
+ options: { key: "scheduleScope" }
38433
+ }, { id: "value.csv" }]
38434
+ } },
38435
+ categoryIds: { $bind: {
38436
+ from: "content",
38437
+ transforms: [{
38438
+ id: "events.calendarSelectionParam",
38439
+ options: { key: "filterCategoryIds" }
38440
+ }, { id: "value.csv" }]
38303
38441
  } },
38304
- scheduleScope: { $bind: { from: "content.scheduleScope" } },
38305
- categoryIds: { $bind: { from: "content.filterCategoryIds" } },
38306
- staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
38307
- venueId: { $bind: { from: "content.filterVenueId" } }
38442
+ staffMemberId: { $bind: {
38443
+ from: "content",
38444
+ transforms: [{
38445
+ id: "events.calendarSelectionParam",
38446
+ options: { key: "filterStaffMemberId" }
38447
+ }, { id: "value.csv" }]
38448
+ } },
38449
+ venueId: { $bind: {
38450
+ from: "content",
38451
+ transforms: [{
38452
+ id: "events.calendarSelectionParam",
38453
+ options: { key: "filterVenueId" }
38454
+ }, { id: "value.csv" }]
38455
+ } }
38308
38456
  };
38309
38457
  /** Combined renders two jobs; calendar-only variants never pay for the list seed. */
38310
38458
  const eventCalendarDataLoaders = {
@@ -38434,6 +38582,13 @@ const eventCalendarLayout = [styledSection({
38434
38582
  from: "content.defaultCalendarView",
38435
38583
  fallback: "month"
38436
38584
  } },
38585
+ seriesIds: { $bind: {
38586
+ from: "content",
38587
+ transforms: [{
38588
+ id: "events.calendarSelectionParam",
38589
+ options: { key: "seriesIds" }
38590
+ }]
38591
+ } },
38437
38592
  showFilters: { $bind: {
38438
38593
  from: "content.showFilters",
38439
38594
  fallback: true
@@ -38455,17 +38610,47 @@ const eventCalendarLayout = [styledSection({
38455
38610
  fallback: true
38456
38611
  } },
38457
38612
  eventSurface: { $bind: {
38458
- from: "content.eventSurface",
38459
- fallback: "all"
38613
+ from: "content",
38614
+ transforms: [{
38615
+ id: "events.calendarSelectionParam",
38616
+ options: { key: "eventSurface" }
38617
+ }]
38618
+ } },
38619
+ filterEventPresets: { $bind: {
38620
+ from: "content",
38621
+ transforms: [{
38622
+ id: "events.calendarSelectionParam",
38623
+ options: { key: "filterEventPresets" }
38624
+ }]
38460
38625
  } },
38461
- filterEventPresets: { $bind: { from: "content.filterEventPresets" } },
38462
38626
  scheduleScope: { $bind: {
38463
- from: "content.scheduleScope",
38464
- fallback: "any"
38627
+ from: "content",
38628
+ transforms: [{
38629
+ id: "events.calendarSelectionParam",
38630
+ options: { key: "scheduleScope" }
38631
+ }]
38632
+ } },
38633
+ filterCategoryIds: { $bind: {
38634
+ from: "content",
38635
+ transforms: [{
38636
+ id: "events.calendarSelectionParam",
38637
+ options: { key: "filterCategoryIds" }
38638
+ }]
38639
+ } },
38640
+ filterStaffMemberId: { $bind: {
38641
+ from: "content",
38642
+ transforms: [{
38643
+ id: "events.calendarSelectionParam",
38644
+ options: { key: "filterStaffMemberId" }
38645
+ }]
38646
+ } },
38647
+ filterVenueId: { $bind: {
38648
+ from: "content",
38649
+ transforms: [{
38650
+ id: "events.calendarSelectionParam",
38651
+ options: { key: "filterVenueId" }
38652
+ }]
38465
38653
  } },
38466
- filterCategoryIds: { $bind: { from: "content.filterCategoryIds" } },
38467
- filterStaffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
38468
- filterVenueId: { $bind: { from: "content.filterVenueId" } },
38469
38654
  cardRole: { $bind: {
38470
38655
  from: "content._cardStyles.role",
38471
38656
  fallback: "default"
@@ -38969,6 +39154,7 @@ const eventCalendarAdditionalFields = [
38969
39154
  }
38970
39155
  }
38971
39156
  },
39157
+ ...eventSelectionFields,
38972
39158
  {
38973
39159
  id: "eventSurface",
38974
39160
  type: "select",
@@ -39178,7 +39364,7 @@ const eventCalendarBlockDefinition = {
39178
39364
  titleSource: "heading",
39179
39365
  description: "Display events with calendar, list, or combined views with filtering",
39180
39366
  skipSectionStyles: true,
39181
- additionalFields: eventCalendarAdditionalFields,
39367
+ additionalFields: eventCalendarAdditionalFields.map(withEventSelectionVisibility),
39182
39368
  styleTokens: {
39183
39369
  background: "surface",
39184
39370
  typography: "body",
@@ -45837,6 +46023,26 @@ const linksTransforms = [{
45837
46023
  }
45838
46024
  }];
45839
46025
  const defaultTransforms = createTransformRegistry([
46026
+ {
46027
+ id: "events.calendarSelectionParam",
46028
+ kind: "formatter",
46029
+ summary: "Resolve selected events instead of discovery filters",
46030
+ schema: z.object({ key: z.enum([
46031
+ "seriesIds",
46032
+ "eventSurface",
46033
+ "filterEventPresets",
46034
+ "scheduleScope",
46035
+ "filterCategoryIds",
46036
+ "filterStaffMemberId",
46037
+ "filterVenueId"
46038
+ ]) }),
46039
+ run(value, { key }) {
46040
+ const content = asPartialObject(value) ?? {};
46041
+ const selection = resolveEventSelection(content.eventSelection, content.selectedEventSeriesIds);
46042
+ if (selection.kind === "selected") return key === "seriesIds" ? selection.seriesIds : void 0;
46043
+ return key === "seriesIds" ? void 0 : content[key];
46044
+ }
46045
+ },
45840
46046
  {
45841
46047
  id: "events.calendarReadEnabled",
45842
46048
  kind: "formatter",
@@ -46151,12 +46357,12 @@ function normalizeContent(block) {
46151
46357
  }
46152
46358
  /**
46153
46359
  * Normalize params for API calls.
46154
- * Converts all values to strings.
46360
+ * Converts supplied values to strings, preserving absent versus explicitly empty params.
46155
46361
  */
46156
46362
  function normalizeParams(input) {
46157
46363
  if (!input || typeof input !== "object") return {};
46158
46364
  const output = {};
46159
- for (const [key, value] of Object.entries(input)) output[key] = coerceToString(value);
46365
+ for (const [key, value] of Object.entries(input)) if (value !== void 0 && value !== null) output[key] = coerceToString(value);
46160
46366
  return output;
46161
46367
  }
46162
46368
  function isNonArrayObject(value) {
@@ -46220,6 +46426,14 @@ function coercePayload(payload) {
46220
46426
  * - Frontend: provide internal API client
46221
46427
  * - SDK: provide SDK client with endpoint mapping
46222
46428
  */
46429
+ function projectDataLoaders(loaders, shouldLoad, blockId, blockKind) {
46430
+ if (!shouldLoad) return [...loaders];
46431
+ return loaders.filter(({ key }) => shouldLoad({
46432
+ blockId,
46433
+ blockKind,
46434
+ loaderKey: key
46435
+ }));
46436
+ }
46223
46437
  function shouldSkipResolvedLoader(input) {
46224
46438
  if (input.loader.requiredParams?.some((param) => !input.params[param]?.trim())) return true;
46225
46439
  return Boolean(input.isValidEndpoint && !input.isValidEndpoint(input.endpoint));
@@ -46248,7 +46462,7 @@ async function prefetchBlockData$1(page, context, options) {
46248
46462
  return (await prefetchBlockDataWithFailures(page, context, options)).resolvedData;
46249
46463
  }
46250
46464
  async function prefetchBlockDataWithFailures(page, context, options) {
46251
- const { apiClient, isValidEndpoint, onError, getCustomBlockLoaders, getBlockDefinition: getBlockDefinition$1 = getBlockDefinition, resolveParamsBindings: resolveParamsBindings$1 = resolveParamsBindings } = options;
46465
+ const { apiClient, isValidEndpoint, onError, getCustomBlockLoaders, getBlockDefinition: getBlockDefinition$1 = getBlockDefinition, resolveParamsBindings: resolveParamsBindings$1 = resolveParamsBindings, shouldLoad } = options;
46252
46466
  const results = {};
46253
46467
  const loaderFailures = {};
46254
46468
  const tasks = [];
@@ -46265,6 +46479,7 @@ async function prefetchBlockDataWithFailures(page, context, options) {
46265
46479
  loader
46266
46480
  })) : [];
46267
46481
  } else loaders = [];
46482
+ loaders = projectDataLoaders(loaders, shouldLoad, blockId, block.kind);
46268
46483
  if (loaders.length === 0) continue;
46269
46484
  const root = {
46270
46485
  ...context.root ?? {},
@@ -46346,8 +46561,8 @@ function toStringParams(value) {
46346
46561
  for (const [k, v] of Object.entries(value)) if (typeof v === "string") out[k] = v;
46347
46562
  return out;
46348
46563
  }
46349
- function stripEmptyStringValues(params) {
46350
- for (const [key, value] of Object.entries(params)) if (value === "") delete params[key];
46564
+ function stripEmptyStringValues(params, endpoint) {
46565
+ for (const [key, value] of Object.entries(params)) if (value === "" && !(key === "seriesIds" && (endpoint === "listPublicEvents" || endpoint === "listPublicEventCalendarWindow"))) delete params[key];
46351
46566
  }
46352
46567
  function ensureSiteId(params, context) {
46353
46568
  if (!params.siteId && typeof context.siteId === "string" && context.siteId) params.siteId = context.siteId;
@@ -46360,7 +46575,7 @@ function ensureSiteId(params, context) {
46360
46575
  */
46361
46576
  function normalizeLoaderParams(endpoint, params, context) {
46362
46577
  const out = toStringParams(params);
46363
- stripEmptyStringValues(out);
46578
+ stripEmptyStringValues(out, endpoint);
46364
46579
  if (endpoint === "getPublicFormById") {
46365
46580
  ensureSiteId(out, context);
46366
46581
  if (!out.formId && out.formSlug) {
@@ -1096,7 +1096,7 @@ const BUTTON_CONTRAST_POLICY = {
1096
1096
  nonTextMinimumRatio: 3,
1097
1097
  gradientSamplesPerSegment: 20,
1098
1098
  alphaBackgrounds: "reject-without-known-surface",
1099
- disabled: "retain-full-colour-contract"
1099
+ disabled: "validated-colour-pair-with-muted-control-opacity"
1100
1100
  };
1101
1101
  function formatButtonColourContractError(error) {
1102
1102
  switch (error.tag) {
@@ -1789,17 +1789,16 @@ function resolvedButtonFocusDeclarations(indicator, role) {
1789
1789
  ] : [["outline", value("outline", `3px solid ${indicator.colorCss}`)], ["outline-offset", value("outline-offset", "3px")]];
1790
1790
  }
1791
1791
  /**
1792
- * Disabled buttons retain their validated colour pair and add a non-layout
1793
- * visual affordance. `currentColor` keeps the cue inside the same contrast
1794
- * relationship, while retaining pointer events lets the not-allowed cursor
1795
- * remain observable.
1792
+ * Disabled buttons are deliberately muted as unavailable controls. Native
1793
+ * disabled controls are exempt from active-control contrast requirements;
1794
+ * opacity distinguishes the state without introducing a focus-like outline.
1795
+ * Retaining pointer events lets the not-allowed cursor remain observable.
1796
1796
  */
1797
1797
  const RESOLVED_BUTTON_DISABLED_DECLARATIONS = [
1798
1798
  ["cursor", "not-allowed"],
1799
1799
  ["transform", "none"],
1800
1800
  ["box-shadow", "none"],
1801
- ["outline", "2px dashed currentColor"],
1802
- ["outline-offset", "-4px"]
1801
+ ["opacity", "0.55"]
1803
1802
  ];
1804
1803
  buttonSizeNameSchema.options;
1805
1804
  //#endregion
@@ -12509,10 +12508,19 @@ const containerResponsiveThemeCss = `/*
12509
12508
  padding-top: 2.5rem;
12510
12509
  padding-bottom: 2.5rem;
12511
12510
  }
12511
+ /* Clearance for a surface that is not an authored block page.
12512
+ An authored page gets this through its opening block's container (see the
12513
+ overlay-clearance rule in styles.css). A reserved surface or a system
12514
+ destination page has no such block, so it consumes the same variable here.
12515
+ Marked with one class rather than per-surface selectors, because the last
12516
+ two additions to this family were both missed and shipped overlapping. */
12512
12517
  :where(.theme-scope)
12513
12518
  [data-site-document-layout-mode="header-overlay"]
12514
- [data-rb-reserved-surface].rb-reserved-surface-main {
12515
- padding-top: calc(var(--rb-reserved-surface-header-offset, 5.5rem) + 2.5rem);
12519
+ .rb-overlay-clearance-surface {
12520
+ padding-top: calc(
12521
+ var(--site-overlay-header-clearance, 5.5rem) +
12522
+ var(--site-overlay-opening-content-extra-pad, clamp(1rem, 2vw, 1.75rem))
12523
+ );
12516
12524
  }
12517
12525
  .rb-preview-editor-offset {
12518
12526
  padding-bottom: calc(
@@ -22869,6 +22877,23 @@ const containerResponsiveThemeCss = `/*
22869
22877
  gap: 0.5rem;
22870
22878
  }
22871
22879
 
22880
+ /* Error panel and field notes. The form block scopes these to its own
22881
+ data-block, so the newsletter form (which also renders in the footer)
22882
+ needs its own copy of the treatment. */
22883
+ :where(.theme-scope) .newsletter-form .fb-error:not([data-field-validation-message]) {
22884
+ background-color: var(--fb-error-bg);
22885
+ color: var(--fb-error-text);
22886
+ border: 1px solid var(--fb-error-border);
22887
+ border-radius: var(--rb-block-radius);
22888
+ padding: 1rem;
22889
+ font-size: 0.875rem;
22890
+ }
22891
+
22892
+ :where(.theme-scope) .newsletter-form [data-field-validation-message] {
22893
+ font-size: 0.875rem;
22894
+ color: var(--fb-error-text);
22895
+ }
22896
+
22872
22897
  /* Required indicator */
22873
22898
  :where(.theme-scope) .newsletter-required {
22874
22899
  color: rgb(var(--tb-primary));
@@ -25528,14 +25553,11 @@ function normalizeTokenValue(value) {
25528
25553
  if (trimmedValue.startsWith("#")) return hexToRgbChannels(trimmedValue);
25529
25554
  return trimmedValue;
25530
25555
  }
25531
- function buildThemeRuntimeFromBridge(config) {
25532
- validateThemeBridgeConfig(config);
25533
- return buildBridgeCssVars(config);
25534
- }
25535
25556
  function buildThemeBridgeRuntime(config) {
25536
- const cssVars = buildThemeRuntimeFromBridge(config);
25557
+ const validatedConfig = validateThemeBridgeConfig(config);
25558
+ const cssVars = buildBridgeCssVars(validatedConfig);
25537
25559
  const themeId = "sdk";
25538
- const corners = config.corners ?? "rounded";
25560
+ const corners = validatedConfig.corners ?? "rounded";
25539
25561
  const generatorTheme = buildBridgeGeneratorTheme(corners);
25540
25562
  return {
25541
25563
  themeId,
@@ -25694,6 +25716,7 @@ function validateThemeBridgeConfig(config) {
25694
25716
  }
25695
25717
  validateBridgeTokens(config.tokens);
25696
25718
  if (config.overrides !== void 0) parseBridgeOverrideRules(config.overrides);
25719
+ return config;
25697
25720
  }
25698
25721
  function resolveBridgeTokens(tokens) {
25699
25722
  const resolved = {};
@@ -25872,6 +25895,15 @@ function buildBridgeGeneratorTheme(corners) {
25872
25895
  }
25873
25896
  };
25874
25897
  }
25898
+ z.object({
25899
+ palette: paletteColorsSchema,
25900
+ paletteMode: paletteModeSchema,
25901
+ typography: z.object({
25902
+ headingFamily: z.string().trim().min(1),
25903
+ bodyFamily: z.string().trim().min(1)
25904
+ }).strict(),
25905
+ corners
25906
+ }).strict();
25875
25907
  //#endregion
25876
25908
  //#region src/theme-bridge/generateCssVars.ts
25877
25909
  /**
@@ -1335,7 +1335,7 @@ const BUTTON_CONTRAST_POLICY = {
1335
1335
  nonTextMinimumRatio: 3,
1336
1336
  gradientSamplesPerSegment: 20,
1337
1337
  alphaBackgrounds: "reject-without-known-surface",
1338
- disabled: "retain-full-colour-contract"
1338
+ disabled: "validated-colour-pair-with-muted-control-opacity"
1339
1339
  };
1340
1340
  function validateButtonSurfaceContrast(input) {
1341
1341
  const ratio = contrastRatio(input.buttonPaint, input.surfaceHex);
@@ -792,10 +792,19 @@
792
792
  padding-top: 2.5rem;
793
793
  padding-bottom: 2.5rem;
794
794
  }
795
+ /* Clearance for a surface that is not an authored block page.
796
+ An authored page gets this through its opening block's container (see the
797
+ overlay-clearance rule in styles.css). A reserved surface or a system
798
+ destination page has no such block, so it consumes the same variable here.
799
+ Marked with one class rather than per-surface selectors, because the last
800
+ two additions to this family were both missed and shipped overlapping. */
795
801
  :where(.theme-scope)
796
802
  [data-site-document-layout-mode="header-overlay"]
797
- [data-rb-reserved-surface].rb-reserved-surface-main {
798
- padding-top: calc(var(--rb-reserved-surface-header-offset, 5.5rem) + 2.5rem);
803
+ .rb-overlay-clearance-surface {
804
+ padding-top: calc(
805
+ var(--site-overlay-header-clearance, 5.5rem) +
806
+ var(--site-overlay-opening-content-extra-pad, clamp(1rem, 2vw, 1.75rem))
807
+ );
799
808
  }
800
809
  .rb-preview-editor-offset {
801
810
  padding-bottom: calc(
@@ -11094,6 +11103,23 @@
11094
11103
  gap: 0.5rem;
11095
11104
  }
11096
11105
 
11106
+ /* Error panel and field notes. The form block scopes these to its own
11107
+ data-block, so the newsletter form (which also renders in the footer)
11108
+ needs its own copy of the treatment. */
11109
+ :where(.theme-scope) .newsletter-form .fb-error:not([data-field-validation-message]) {
11110
+ background-color: var(--fb-error-bg);
11111
+ color: var(--fb-error-text);
11112
+ border: 1px solid var(--fb-error-border);
11113
+ border-radius: var(--rb-block-radius);
11114
+ padding: 1rem;
11115
+ font-size: 0.875rem;
11116
+ }
11117
+
11118
+ :where(.theme-scope) .newsletter-form [data-field-validation-message] {
11119
+ font-size: 0.875rem;
11120
+ color: var(--fb-error-text);
11121
+ }
11122
+
11097
11123
  /* Required indicator */
11098
11124
  :where(.theme-scope) .newsletter-required {
11099
11125
  color: rgb(var(--tb-primary));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riverbankcms/sdk",
3
- "version": "0.140.0",
3
+ "version": "0.141.0",
4
4
  "description": "Riverbank CMS SDK for headless content consumption",
5
5
  "main": "./dist/server/index.mjs",
6
6
  "module": "./dist/server/index.mjs",