@riverbankcms/sdk 0.72.0 → 0.75.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 (146) hide show
  1. package/README.md +1 -1
  2. package/dist/{PreviewEditorSidebar-44T64SAR.mjs → PreviewEditorSidebar-U2IHCBYN.mjs} +3 -3
  3. package/dist/{PreviewEditorUI-4WKHZTXW.mjs → PreviewEditorUI-ZGH2RQNP.mjs} +3 -3
  4. package/dist/SdkPreviewModeRuntime-MTUGBTLQ.mjs +8 -0
  5. package/dist/_dts/ai/src/contracts/proposals.d.ts +10 -10
  6. package/dist/_dts/api/src/cache-tags.d.ts +22 -0
  7. package/dist/_dts/api/src/contentRuntime.d.ts +1 -0
  8. package/dist/_dts/api/src/endpoints.d.ts +24 -24
  9. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +2 -1
  10. package/dist/_dts/block-form/src/blockDraftSaveability.d.ts +4 -1
  11. package/dist/_dts/blocks/src/client/booking-form.d.ts +2 -0
  12. package/dist/_dts/blocks/src/client/carousel.d.ts +1 -0
  13. package/dist/_dts/blocks/src/client/course-registration.d.ts +2 -0
  14. package/dist/_dts/blocks/src/client/events.d.ts +4 -0
  15. package/dist/_dts/blocks/src/client/form.d.ts +2 -0
  16. package/dist/_dts/blocks/src/client/header.d.ts +1 -0
  17. package/dist/_dts/blocks/src/client/location-map.d.ts +1 -0
  18. package/dist/_dts/blocks/src/client/newsletter-form.d.ts +2 -0
  19. package/dist/_dts/blocks/src/client/shop.d.ts +6 -0
  20. package/dist/_dts/blocks/src/lib/video.d.ts +2 -0
  21. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +21 -1
  22. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +6 -6
  23. package/dist/_dts/blocks/src/system/node/fragments/backgroundLayer.d.ts +15 -1
  24. package/dist/_dts/blocks/src/system/node/fragments/styledSection.d.ts +11 -0
  25. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +1 -0
  26. package/dist/_dts/blocks/src/system/runtime/header/enhanceHeaderSection.d.ts +13 -0
  27. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +3 -2
  28. package/dist/_dts/blocks/src/system/runtime/nodes/events/index.d.ts +3 -0
  29. package/dist/_dts/blocks/src/system/runtime/nodes/header-section.client.d.ts +1 -0
  30. package/dist/_dts/blocks/src/system/runtime/nodes/header-section.server.d.ts +1 -0
  31. package/dist/_dts/blocks/src/system/runtime/nodes/media.d.ts +6 -0
  32. package/dist/_dts/content-editor/src/hooks/validateBlocksForPublish.d.ts +5 -0
  33. package/dist/_dts/preview-next/src/client/preview/SiteChromeEditableSurface.d.ts +12 -2
  34. package/dist/_dts/sdk/src/public-api/contracts.d.ts +1 -0
  35. package/dist/_dts/sdk/src/rendering/components/Layout.d.ts +2 -2
  36. package/dist/_dts/sdk/src/rendering/islands/deferredVideoEmbeds.d.ts +2 -0
  37. package/dist/_dts/sdk/src/rendering/islands/enhancers/accordion.d.ts +1 -0
  38. package/dist/_dts/sdk/src/rendering/islands/enhancers/bookingForm.d.ts +1 -0
  39. package/dist/_dts/sdk/src/rendering/islands/enhancers/carousel.d.ts +1 -0
  40. package/dist/_dts/sdk/src/rendering/islands/enhancers/cart.d.ts +1 -0
  41. package/dist/_dts/sdk/src/rendering/islands/enhancers/checkout.d.ts +1 -0
  42. package/dist/_dts/sdk/src/rendering/islands/enhancers/courseRegistration.d.ts +1 -0
  43. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventCalendar.d.ts +1 -0
  44. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventCombined.d.ts +1 -0
  45. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventDetails.d.ts +1 -0
  46. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventListing.d.ts +1 -0
  47. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventRegistration.d.ts +1 -0
  48. package/dist/_dts/sdk/src/rendering/islands/enhancers/form.d.ts +1 -0
  49. package/dist/_dts/sdk/src/rendering/islands/enhancers/headerSection.d.ts +1 -0
  50. package/dist/_dts/sdk/src/rendering/islands/enhancers/locationMap.d.ts +1 -0
  51. package/dist/_dts/sdk/src/rendering/islands/enhancers/newsletterForm.d.ts +1 -0
  52. package/dist/_dts/sdk/src/rendering/islands/enhancers/productDetail.d.ts +1 -0
  53. package/dist/_dts/sdk/src/rendering/islands/enhancers/productList.d.ts +1 -0
  54. package/dist/_dts/sdk/src/rendering/islands/enhancers/shop.d.ts +1 -0
  55. package/dist/_dts/sdk/src/rendering/islands/hydrateBlocksIslands.d.ts +2 -2
  56. package/dist/_dts/sdk/src/rendering/islands/propsDecoder.d.ts +7 -0
  57. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +9 -0
  58. package/dist/_dts/sdk/src/rendering/server.d.ts +3 -0
  59. package/dist/_dts/sdk/src/version.d.ts +1 -1
  60. package/dist/_dts/theme-core/src/accordions/types.d.ts +3 -3
  61. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +7 -7
  62. package/dist/_dts/theme-core/src/buttons/types.d.ts +20 -20
  63. package/dist/_dts/theme-core/src/cards/types.d.ts +2 -2
  64. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  65. package/dist/_dts/theme-core/src/header/navDropdownSizing.d.ts +7 -0
  66. package/dist/_dts/theme-core/src/inputs/types.d.ts +3 -3
  67. package/dist/_dts/theme-core/src/interactive/baseSchema.d.ts +1 -1
  68. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +156 -156
  69. package/dist/_dts/theme-core/src/navigation/types.d.ts +1 -1
  70. package/dist/_dts/theme-core/src/palette/variants/types.d.ts +4 -4
  71. package/dist/_dts/theme-core/src/schema.d.ts +178 -178
  72. package/dist/_dts/theme-core/src/shared/componentStyles.d.ts +2 -2
  73. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +8 -8
  74. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +5 -5
  75. package/dist/_dts/theme-core/src/tokens/themeColorTokens.d.ts +2 -2
  76. package/dist/{chunk-G4NLITC2.mjs → chunk-BGMNDF6T.mjs} +7 -7
  77. package/dist/{chunk-3YNCQG5N.mjs → chunk-GFE74WRD.mjs} +457 -98
  78. package/dist/{chunk-HV745JYE.mjs → chunk-RWXQBRQZ.mjs} +1 -1
  79. package/dist/{chunk-7RX72SK2.mjs → chunk-VX7B5VAC.mjs} +36 -25
  80. package/dist/{chunk-YRJKZEQ3.mjs → chunk-Z7JLNTJR.mjs} +1 -1
  81. package/dist/{chunk-KWQPAJYS.mjs → chunk-ZSHFGFUG.mjs} +2 -2
  82. package/dist/cli/index.mjs +3498 -3826
  83. package/dist/client/accordion-T2UD2ZTH.mjs +120 -0
  84. package/dist/client/altcha-LIGLPZS5.mjs +2755 -0
  85. package/dist/client/bookingForm-GUP75FKN.mjs +3022 -0
  86. package/dist/client/bookings.mjs +32 -10
  87. package/dist/client/carousel-2NQA6V57.mjs +47 -0
  88. package/dist/client/cart-5TFIAFDS.mjs +18 -0
  89. package/dist/client/checkout-TP4WAHZE.mjs +18 -0
  90. package/dist/client/chunk-2PHQZ666.mjs +383 -0
  91. package/dist/client/chunk-3DCJ45Z2.mjs +36 -0
  92. package/dist/client/chunk-3PEDD5KJ.mjs +146 -0
  93. package/dist/client/chunk-CY2ZTSE5.mjs +204 -0
  94. package/dist/client/chunk-F7LHOKEH.mjs +146 -0
  95. package/dist/client/chunk-FU2QRZMX.mjs +7617 -0
  96. package/dist/client/chunk-I2MMZO53.mjs +6 -0
  97. package/dist/client/chunk-II7O4XN3.mjs +2206 -0
  98. package/dist/client/chunk-M3L3KYYR.mjs +1181 -0
  99. package/dist/client/chunk-N7PBWBWQ.mjs +26 -0
  100. package/dist/client/chunk-NWOUL6JY.mjs +1378 -0
  101. package/dist/client/chunk-OJPZEZU2.mjs +31 -0
  102. package/dist/client/chunk-PMAIXMAB.mjs +1960 -0
  103. package/dist/client/chunk-RTZ3JKKX.mjs +178 -0
  104. package/dist/client/chunk-TQ5MSPDX.mjs +74 -0
  105. package/dist/client/chunk-VUAOE3AG.mjs +5592 -0
  106. package/dist/client/chunk-WJXXNDSE.mjs +245 -0
  107. package/dist/client/chunk-YLMKMCSJ.mjs +86 -0
  108. package/dist/client/chunk-ZLMS67RR.mjs +106 -0
  109. package/dist/client/client.mjs +51865 -52071
  110. package/dist/client/courseRegistration-5DPU6PDY.mjs +1737 -0
  111. package/dist/client/eventCalendar-F3GZGTEF.mjs +40 -0
  112. package/dist/client/eventCombined-BQOB6QMY.mjs +37 -0
  113. package/dist/client/eventDetails-PEM2EJWE.mjs +25 -0
  114. package/dist/client/eventListing-YMIQPVME.mjs +40 -0
  115. package/dist/client/eventRegistration-4I6ZNDUF.mjs +40 -0
  116. package/dist/client/form-ZJVAYZ6G.mjs +300 -0
  117. package/dist/client/headerSection-TOT5MGTF.mjs +729 -0
  118. package/dist/client/hooks.mjs +91 -42
  119. package/dist/client/locationMap-J66NZREU.mjs +227 -0
  120. package/dist/client/newsletterForm-ET2XUMRO.mjs +208 -0
  121. package/dist/client/productDetail-C2XIH7C5.mjs +18 -0
  122. package/dist/client/productList-T2AZLFTP.mjs +18 -0
  123. package/dist/client/rendering/client.mjs +12796 -18295
  124. package/dist/client/rendering/islands.mjs +108 -44022
  125. package/dist/client/rendering.mjs +45141 -45346
  126. package/dist/client/shop-UZ6IUZXD.mjs +20 -0
  127. package/dist/preview-next/before-render.mjs +37 -25
  128. package/dist/preview-next/client/runtime.mjs +5 -5
  129. package/dist/preview-next/middleware.mjs +37 -25
  130. package/dist/{sdk-runtime-NGDWSWOS.mjs → sdk-runtime-JCUQM63Y.mjs} +6 -6
  131. package/dist/server/components.mjs +472 -276
  132. package/dist/server/config-validation.mjs +91 -42
  133. package/dist/server/config.mjs +91 -42
  134. package/dist/server/data.mjs +91 -42
  135. package/dist/server/index.mjs +45 -33
  136. package/dist/server/next.mjs +468 -272
  137. package/dist/server/page-converter.mjs +41 -17
  138. package/dist/server/prebuild.mjs +1 -1
  139. package/dist/server/rendering/server.mjs +556 -275
  140. package/dist/server/rendering.mjs +474 -278
  141. package/dist/server/routing.mjs +99 -43
  142. package/dist/server/server.mjs +92 -43
  143. package/dist/server/theme-bridge.mjs +29 -0
  144. package/dist/styles/index.css +16 -0
  145. package/package.json +2 -1
  146. package/dist/SdkPreviewModeRuntime-FO6V7YVY.mjs +0 -8
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { ApiRequestError } from './chunk-7RX72SK2.mjs';
2
+ import { ApiRequestError } from './chunk-VX7B5VAC.mjs';
3
3
  import { __commonJS, __export, __toESM, __require } from './chunk-XGB3TDIC.mjs';
4
4
  import * as React63 from 'react';
5
5
  import React63__default, { forwardRef, createElement, createContext, useRef, useMemo, useEffect, useState, useCallback, useImperativeHandle, useLayoutEffect, useContext, memo, createRef, Component as Component$1, useDebugValue, useId as useId$1, useSyncExternalStore, isValidElement, cloneElement, useReducer, startTransition } from 'react';
@@ -30415,6 +30415,9 @@ function validationContext(options = {}) {
30415
30415
  function formatFieldPath(path) {
30416
30416
  return path.map((segment) => String(segment)).join(".");
30417
30417
  }
30418
+ function toZodIssuePath(path) {
30419
+ return [...path];
30420
+ }
30418
30421
  function fieldIssueToMessage(issue2) {
30419
30422
  switch (issue2.kind) {
30420
30423
  case "required":
@@ -30543,6 +30546,9 @@ function deriveFieldValidationPlan(field, path = [field.id]) {
30543
30546
  return assertNever4(field);
30544
30547
  }
30545
30548
  }
30549
+ function deriveFieldValidationPlans(fields3, parentPath = []) {
30550
+ return fields3.map((field) => deriveFieldValidationPlan(field, [...parentPath, field.id]));
30551
+ }
30546
30552
  function commonConstraints(required, ...specific) {
30547
30553
  return required ? [{ kind: "required" }, ...specific] : [...specific];
30548
30554
  }
@@ -30558,9 +30564,19 @@ function makePlan(kind, valueKind, field, path, required, constraints) {
30558
30564
  fieldType: field.type,
30559
30565
  path,
30560
30566
  required,
30567
+ visibility: fieldVisibility(field),
30561
30568
  constraints
30562
30569
  };
30563
30570
  }
30571
+ function fieldVisibility(field) {
30572
+ if (field.ui?.hidden) {
30573
+ return { kind: "hidden" };
30574
+ }
30575
+ if (field.visibleRoles && field.visibleRoles.length > 0) {
30576
+ return { kind: "roleRestricted", roles: field.visibleRoles };
30577
+ }
30578
+ return { kind: "visible" };
30579
+ }
30564
30580
  function withRepeaterItemConstraints(field, constraints) {
30565
30581
  const next = [...constraints];
30566
30582
  if (typeof field.minItems === "number") next.push({ kind: "minItems", minimum: field.minItems });
@@ -30574,7 +30590,7 @@ function deriveRepeatedItemVariants(field, parentPath) {
30574
30590
  }));
30575
30591
  }
30576
30592
  function deriveNestedFieldPlans(fields3, parentPath) {
30577
- return fields3.map((field) => deriveFieldValidationPlan(field, [...parentPath, field.id]));
30593
+ return deriveFieldValidationPlans(fields3, parentPath);
30578
30594
  }
30579
30595
  function getRepeaterFields(field) {
30580
30596
  const fields3 = field.polymorphic && field.itemTypes ? Object.values(field.itemTypes).flatMap((itemType) => itemType.fields) : field.schema?.fields ?? [];
@@ -30600,6 +30616,71 @@ function resolveSelectConstraintSource(field) {
30600
30616
  return assertNever4(source);
30601
30617
  }
30602
30618
  }
30619
+ function normalizeStoredContentValues(plans, content, options = {}) {
30620
+ if (!content || typeof content !== "object" || Array.isArray(content)) {
30621
+ return {};
30622
+ }
30623
+ const planMap = new Map(plans.map((plan) => [plan.fieldId, plan]));
30624
+ const normalized = {};
30625
+ const ctx = validationContext(options);
30626
+ for (const [key, value] of Object.entries(content)) {
30627
+ const plan = planMap.get(key);
30628
+ normalized[key] = plan ? normalizeStoredFieldValueWithContext(plan, value, ctx) : value;
30629
+ }
30630
+ return normalized;
30631
+ }
30632
+ function normalizeStoredFieldValueWithContext(plan, value, ctx) {
30633
+ if (value === null && !plan.required) {
30634
+ return void 0;
30635
+ }
30636
+ switch (plan.kind) {
30637
+ case "group":
30638
+ return normalizeStoredObjectChildren(plan.children, value, childValidationContext(plan, ctx));
30639
+ case "repeater":
30640
+ return normalizeStoredRepeaterItems(plan, value, ctx);
30641
+ case "string":
30642
+ case "number":
30643
+ case "boolean":
30644
+ case "richText":
30645
+ case "media":
30646
+ case "link":
30647
+ case "select":
30648
+ case "passthrough":
30649
+ return normalizeFieldValue(plan, value, ctx);
30650
+ default:
30651
+ return assertNever4(plan);
30652
+ }
30653
+ }
30654
+ function normalizeStoredObjectChildren(children, value, ctx) {
30655
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
30656
+ return value;
30657
+ }
30658
+ const normalized = { ...value };
30659
+ for (const child of children) {
30660
+ normalized[child.fieldId] = normalizeStoredFieldValueWithContext(
30661
+ child,
30662
+ normalized[child.fieldId],
30663
+ ctx
30664
+ );
30665
+ }
30666
+ return normalized;
30667
+ }
30668
+ function normalizeStoredRepeaterItems(plan, value, ctx) {
30669
+ if (!Array.isArray(value)) {
30670
+ return value;
30671
+ }
30672
+ return value.map((item) => {
30673
+ if (!item || typeof item !== "object" || Array.isArray(item)) {
30674
+ return item;
30675
+ }
30676
+ const itemRecord = item;
30677
+ const fields3 = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((variant) => variant.typeId === itemRecord._type)?.fields : plan.repeatedItemPlan;
30678
+ if (!fields3) {
30679
+ return item;
30680
+ }
30681
+ return normalizeStoredObjectChildren(fields3, itemRecord, ctx);
30682
+ });
30683
+ }
30603
30684
  function normalizeFieldValue(plan, value, ctx) {
30604
30685
  switch (plan.kind) {
30605
30686
  case "number":
@@ -30854,16 +30935,19 @@ function fieldPlanToZod(plan, options = {}) {
30854
30935
  const ctx = validationContext(options);
30855
30936
  return z.any().transform((value) => normalizeFieldValue(plan, value, ctx)).superRefine((value, zodCtx) => {
30856
30937
  for (const validationIssue of validateNormalizedFieldValue(plan, value, ctx)) {
30857
- addFieldIssueToZodContext(zodCtx, validationIssue);
30938
+ addFieldIssueToZodContext(zodCtx, validationIssue, plan.path);
30858
30939
  }
30859
30940
  });
30860
30941
  }
30861
- function addFieldIssueToZodContext(zodCtx, validationIssue) {
30942
+ function addFieldIssueToZodContext(zodCtx, validationIssue, rootPath) {
30862
30943
  const message2 = fieldIssueToMessage(validationIssue);
30944
+ const path = relativeZodIssuePath(validationIssue.path, rootPath);
30945
+ const issuePath = path.length > 0 ? { path: toZodIssuePath(path) } : {};
30863
30946
  switch (validationIssue.kind) {
30864
30947
  case "required":
30865
30948
  if (validationIssue.emptyOrigin) {
30866
30949
  zodCtx.addIssue({
30950
+ ...issuePath,
30867
30951
  code: "too_small",
30868
30952
  origin: validationIssue.emptyOrigin,
30869
30953
  minimum: 1,
@@ -30872,10 +30956,11 @@ function addFieldIssueToZodContext(zodCtx, validationIssue) {
30872
30956
  });
30873
30957
  return;
30874
30958
  }
30875
- zodCtx.addIssue({ code: "invalid_type", expected: "nonoptional", message: message2 });
30959
+ zodCtx.addIssue({ ...issuePath, code: "invalid_type", expected: "nonoptional", message: message2 });
30876
30960
  return;
30877
30961
  case "tooLong":
30878
30962
  zodCtx.addIssue({
30963
+ ...issuePath,
30879
30964
  code: "too_big",
30880
30965
  origin: "string",
30881
30966
  maximum: validationIssue.maximum,
@@ -30884,7 +30969,7 @@ function addFieldIssueToZodContext(zodCtx, validationIssue) {
30884
30969
  });
30885
30970
  return;
30886
30971
  case "invalidOption":
30887
- zodCtx.addIssue({ code: "invalid_value", values: [], message: message2 });
30972
+ zodCtx.addIssue({ ...issuePath, code: "invalid_value", values: [], message: message2 });
30888
30973
  return;
30889
30974
  case "wrongType":
30890
30975
  case "invalidEmail":
@@ -30901,12 +30986,72 @@ function addFieldIssueToZodContext(zodCtx, validationIssue) {
30901
30986
  case "invalidMedia":
30902
30987
  case "invalidLink":
30903
30988
  case "invalidReference":
30904
- zodCtx.addIssue({ code: "custom", message: message2 });
30989
+ zodCtx.addIssue({ ...issuePath, code: "custom", message: message2 });
30905
30990
  return;
30906
30991
  default:
30907
30992
  assertNever4(validationIssue);
30908
30993
  }
30909
30994
  }
30995
+ function relativeZodIssuePath(path, rootPath) {
30996
+ return startsWithFieldPath(path, rootPath) ? path.slice(rootPath.length) : path;
30997
+ }
30998
+ function resolveFieldValidationDescriptor(plans, path) {
30999
+ const plan = findFieldValidationPlan(plans, path);
31000
+ return plan ? fieldValidationDescriptor(plan) : null;
31001
+ }
31002
+ function findFieldValidationPlan(plans, path) {
31003
+ for (const plan of plans) {
31004
+ if (sameFieldPath(plan.path, path)) {
31005
+ return plan;
31006
+ }
31007
+ const nested = findNestedFieldValidationPlan(plan, path);
31008
+ if (nested) {
31009
+ return nested;
31010
+ }
31011
+ }
31012
+ return null;
31013
+ }
31014
+ function findNestedFieldValidationPlan(plan, path) {
31015
+ switch (plan.kind) {
31016
+ case "group":
31017
+ return findFieldValidationPlan(plan.children, path);
31018
+ case "repeater": {
31019
+ const index2 = path[plan.path.length];
31020
+ if (typeof index2 !== "number") {
31021
+ return null;
31022
+ }
31023
+ const childPlans = plan.repeatedItemVariants ? plan.repeatedItemVariants.flatMap((variant) => variant.fields) : plan.repeatedItemPlan ?? [];
31024
+ const materialized = childPlans.map(
31025
+ (childPlan) => materializeRepeaterItemPlan(childPlan, plan.path, index2)
31026
+ );
31027
+ return findFieldValidationPlan(materialized, path);
31028
+ }
31029
+ case "string":
31030
+ case "number":
31031
+ case "boolean":
31032
+ case "richText":
31033
+ case "media":
31034
+ case "link":
31035
+ case "select":
31036
+ case "passthrough":
31037
+ return null;
31038
+ default:
31039
+ return assertNever4(plan);
31040
+ }
31041
+ }
31042
+ function fieldValidationDescriptor(plan) {
31043
+ return {
31044
+ path: plan.path,
31045
+ fieldPath: formatFieldPath(plan.path),
31046
+ fieldId: plan.fieldId,
31047
+ label: plan.label,
31048
+ fieldType: plan.fieldType,
31049
+ visibility: plan.visibility
31050
+ };
31051
+ }
31052
+ function sameFieldPath(left, right) {
31053
+ return left.length === right.length && left.every((segment, index2) => segment === right[index2]);
31054
+ }
30910
31055
  function compilePattern(pattern) {
30911
31056
  try {
30912
31057
  return new RegExp(pattern);
@@ -30981,24 +31126,33 @@ function preprocessEmptyValues(content) {
30981
31126
  }
30982
31127
  return result;
30983
31128
  }
30984
- function deriveContentZodFromManifest(manifestOrFields, options = {}) {
30985
- const shape = {};
30986
- const fields3 = Array.isArray(manifestOrFields) ? manifestOrFields : manifestOrFields.fields ?? [];
30987
- for (const field of fields3) {
30988
- shape[field.id] = buildFieldSchema(field, options);
30989
- }
30990
- return z.object(shape).catchall(z.unknown()).passthrough();
30991
- }
30992
31129
  function createManifestValidator(manifestOrFields, options = {}) {
30993
31130
  const isDraft = options.mode === "draft";
30994
- const baseSchema = deriveContentZodFromManifest(manifestOrFields, options);
31131
+ const plans = derivePlansFromManifestOrFields(manifestOrFields);
31132
+ const baseSchema = deriveContentZodFromPlans(plans, options);
30995
31133
  if (isDraft) {
30996
- return z.preprocess(preprocessEmptyValues, baseSchema);
31134
+ return z.preprocess(
31135
+ (content) => preprocessEmptyValues(
31136
+ normalizeStoredContentValues(plans, content, options)
31137
+ ),
31138
+ baseSchema
31139
+ );
30997
31140
  }
30998
- return baseSchema;
31141
+ return z.preprocess(
31142
+ (content) => normalizeStoredContentValues(plans, content, options),
31143
+ baseSchema
31144
+ );
30999
31145
  }
31000
- function buildFieldSchema(field, options) {
31001
- return fieldPlanToZod(deriveFieldValidationPlan(field), options);
31146
+ function deriveContentZodFromPlans(plans, options) {
31147
+ const shape = {};
31148
+ for (const plan of plans) {
31149
+ shape[plan.fieldId] = fieldPlanToZod(plan, options);
31150
+ }
31151
+ return z.object(shape).catchall(z.unknown()).passthrough();
31152
+ }
31153
+ function derivePlansFromManifestOrFields(manifestOrFields) {
31154
+ const fields3 = Array.isArray(manifestOrFields) ? manifestOrFields : manifestOrFields.fields ?? [];
31155
+ return deriveFieldValidationPlans(fields3);
31002
31156
  }
31003
31157
 
31004
31158
  // ../blocks/src/system/manifest/variantKey.ts
@@ -40675,7 +40829,9 @@ function backgroundLayer(path, options = {}) {
40675
40829
  imageClassName,
40676
40830
  overlayClassName = "background-overlay rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full rb-w-full rb-pointer-events-none",
40677
40831
  fallbackToken,
40678
- omitImageLayer = false
40832
+ omitImageLayer = false,
40833
+ imageLoading,
40834
+ imageFetchPriority
40679
40835
  } = options;
40680
40836
  const styleLayer = el("div", {
40681
40837
  className: styleClassName,
@@ -40691,11 +40847,14 @@ function backgroundLayer(path, options = {}) {
40691
40847
  }
40692
40848
  }
40693
40849
  });
40694
- const imageLayer = createBackgroundImageNode(path, imageClassName);
40850
+ const imageLayer = createBackgroundImageNode(path, imageClassName, {
40851
+ loading: imageLoading,
40852
+ fetchPriority: imageFetchPriority
40853
+ });
40695
40854
  const overlayLayer = createBackgroundOverlayNode(path, overlayClassName);
40696
40855
  return omitImageLayer ? [styleLayer, overlayLayer] : [styleLayer, imageLayer, overlayLayer];
40697
40856
  }
40698
- function createBackgroundImageNode(path, baseClassName = "rb-absolute rb-z-neg-10") {
40857
+ function createBackgroundImageNode(path, baseClassName = "rb-absolute rb-z-neg-10", options = {}) {
40699
40858
  const imagePath = `${path}.image`;
40700
40859
  return media(
40701
40860
  {
@@ -40716,7 +40875,9 @@ function createBackgroundImageNode(path, baseClassName = "rb-absolute rb-z-neg-1
40716
40875
  transforms: [{ id: "background.resolveImageStyle" }]
40717
40876
  }
40718
40877
  },
40719
- videoPlayback: "background"
40878
+ videoPlayback: "background",
40879
+ ...options.loading ? { loading: options.loading } : {},
40880
+ ...options.fetchPriority ? { fetchPriority: options.fetchPriority } : {}
40720
40881
  },
40721
40882
  when(imagePath),
40722
40883
  bind(imagePath)
@@ -40913,12 +41074,16 @@ function styledSection(config) {
40913
41074
  bindFrom = "_sectionStyles",
40914
41075
  imageClassName = "rb-absolute rb-z-neg-10",
40915
41076
  renderBackgroundImage = true,
41077
+ backgroundImageLoading,
41078
+ backgroundImageFetchPriority,
40916
41079
  fullWidthPath
40917
41080
  } = config;
40918
41081
  const renderedBackgroundNodes = backgroundLayer(`${bindFrom}.background`, {
40919
41082
  imageClassName,
40920
41083
  fallbackToken: background,
40921
- omitImageLayer: !renderBackgroundImage
41084
+ omitImageLayer: !renderBackgroundImage,
41085
+ imageLoading: backgroundImageLoading,
41086
+ imageFetchPriority: backgroundImageFetchPriority
40922
41087
  });
40923
41088
  const childrenArray = Array.isArray(children) ? children : [children];
40924
41089
  return section(
@@ -41129,7 +41294,7 @@ function navRow(opts) {
41129
41294
  el(
41130
41295
  "div",
41131
41296
  {
41132
- className: "nav-dropdown-menu rb-absolute rb-left-0 rb-top-full rb-z-50 rb-hidden rb-min-w-12rem rb-overflow-hidden",
41297
+ className: "nav-dropdown-menu rb-absolute rb-left-0 rb-top-full rb-z-50 rb-hidden rb-overflow-hidden",
41133
41298
  id: dropdownMenuId
41134
41299
  },
41135
41300
  [dropdownLinks]
@@ -44699,6 +44864,10 @@ var heroCopyAndCta = composeFragments([
44699
44864
  { fragment: heroCopyFragment },
44700
44865
  { fragment: heroCtaRowFragment }
44701
44866
  ]);
44867
+ var heroPriorityMediaProps = {
44868
+ loading: "eager",
44869
+ fetchPriority: "high"
44870
+ };
44702
44871
  var heroContentNodes = heroCopyAndCta.layout;
44703
44872
  function heroContentCard(children, gap) {
44704
44873
  return styledContainer({
@@ -44761,7 +44930,8 @@ function heroSplitImagePane() {
44761
44930
  [
44762
44931
  media(
44763
44932
  {
44764
- className: "rb-absolute rb-inset-0 rb-h-full rb-w-full rb-object-cover"
44933
+ className: "rb-absolute rb-inset-0 rb-h-full rb-w-full rb-object-cover",
44934
+ ...heroPriorityMediaProps
44765
44935
  },
44766
44936
  when("_sectionStyles.background.image"),
44767
44937
  bind("_sectionStyles.background.image")
@@ -44772,13 +44942,17 @@ function heroSplitImagePane() {
44772
44942
  var classicLayout = styledSection({
44773
44943
  children: heroContainerStack(heroContentNodes, "md"),
44774
44944
  // styledContainer (rb-container) already provides horizontal padding
44775
- baseClass: ""
44945
+ baseClass: "",
44946
+ backgroundImageLoading: heroPriorityMediaProps.loading,
44947
+ backgroundImageFetchPriority: heroPriorityMediaProps.fetchPriority
44776
44948
  });
44777
44949
  var microLayout = styledSection({
44778
44950
  children: heroContainerStack(heroContentNodes, "sm"),
44779
44951
  // styledContainer (rb-container) already provides horizontal padding
44780
44952
  baseClass: "",
44781
- spacing: "compact"
44953
+ spacing: "compact",
44954
+ backgroundImageLoading: heroPriorityMediaProps.loading,
44955
+ backgroundImageFetchPriority: heroPriorityMediaProps.fetchPriority
44782
44956
  });
44783
44957
  function splitLayoutWith(children) {
44784
44958
  return styledSection({
@@ -49017,7 +49191,7 @@ var cardStylingFields = [
49017
49191
  description: "Text for the event action button",
49018
49192
  required: false,
49019
49193
  multiline: false,
49020
- defaultValue: "View event",
49194
+ defaultValue: "Book now",
49021
49195
  maxLength: 40
49022
49196
  }
49023
49197
  ];
@@ -49508,6 +49682,7 @@ var eventRegistrationBlockDefinition = {
49508
49682
  limit: "50",
49509
49683
  // Get more events for selection
49510
49684
  stage: { $bind: { from: "$root.previewStage", fallback: "published" } },
49685
+ readProfile: "registration",
49511
49686
  // When rendering on an event content entry page, scope the list to that entry so
49512
49687
  // the wizard always includes the current event (and avoids stale cached "all events" responses).
49513
49688
  entryId: { $bind: { from: "$root.contentEntry._entryId", fallback: "" } }
@@ -50429,7 +50604,7 @@ var eventSpotlightLayout = [
50429
50604
  columns: { $bind: { from: "content.columns", fallback: "3" } },
50430
50605
  cardVariant: { $bind: { from: "content.cardVariant", fallback: "default" } },
50431
50606
  buttonVariant: { $bind: { from: "content.buttonVariant", fallback: "primary" } },
50432
- buttonText: { $bind: { from: "content.buttonText", fallback: "View event" } },
50607
+ buttonText: { $bind: { from: "content.buttonText", fallback: "Book now" } },
50433
50608
  ctaLabel: { $bind: { from: "content.ctaLabel" } },
50434
50609
  ctaUrl: { $bind: { from: "content.ctaUrl", transforms: [{ id: "links.resolve" }] } },
50435
50610
  showVenue: { $bind: { from: "content.showVenue" } },
@@ -50473,7 +50648,8 @@ var eventSpotlightBlockDefinition = {
50473
50648
  siteId: { $bind: { from: "$root.siteId" } },
50474
50649
  limit: { $bind: { from: "content.maxEvents", fallback: "3" } },
50475
50650
  stage: { $bind: { from: "$root.previewStage", fallback: "published" } },
50476
- detailLevel: "listing"
50651
+ detailLevel: "listing",
50652
+ readProfile: "spotlight"
50477
50653
  },
50478
50654
  mode: "server"
50479
50655
  }
@@ -50965,7 +51141,7 @@ var COLUMN_CLASSES = {
50965
51141
  };
50966
51142
  function getContainerClass(layout, columns) {
50967
51143
  if (layout === "compact") {
50968
- return "rb-flex rb-flex-col rb-gap-2";
51144
+ return "event-listing-compact-container rb-flex rb-flex-col rb-gap-2";
50969
51145
  }
50970
51146
  if (layout === "stack") {
50971
51147
  return "rb-flex rb-flex-col rb-gap-6";
@@ -51096,7 +51272,7 @@ function formatEventPrice(event) {
51096
51272
  }
51097
51273
  function resolveEventCta(event, buttonText) {
51098
51274
  const { isFull: isSoldOut } = getEventAvailability(event);
51099
- const defaultButtonText = event.kind === "course_session" ? "View course" : "View event";
51275
+ const defaultButtonText = event.kind === "course_session" ? "Book course" : "Book now";
51100
51276
  const effectiveButtonText = buttonText ?? defaultButtonText;
51101
51277
  if (isSoldOut) {
51102
51278
  return { label: "Sold out", href: event.path, hidden: true };
@@ -52285,6 +52461,8 @@ var MediaNodeServer = ({
52285
52461
  className,
52286
52462
  style: style2,
52287
52463
  videoPlayback = "inline",
52464
+ loading = "lazy",
52465
+ fetchPriority,
52288
52466
  size: size4 = ImagePresets.full,
52289
52467
  fieldPath,
52290
52468
  blockKind,
@@ -52321,7 +52499,8 @@ var MediaNodeServer = ({
52321
52499
  alt: value.alt ?? "",
52322
52500
  className,
52323
52501
  style: computedStyle,
52324
- loading: "lazy",
52502
+ loading,
52503
+ fetchPriority,
52325
52504
  decoding: "async"
52326
52505
  }
52327
52506
  );
@@ -52680,7 +52859,7 @@ var eventListingBlockRuntime = defineProgressiveBlockRuntime({
52680
52859
  containerClass: getContainerClass(layout, source.columns ?? "3"),
52681
52860
  cardVariant: source.cardVariant ?? "default",
52682
52861
  buttonVariant: source.buttonVariant ?? "primary",
52683
- buttonText: source.buttonText ?? "View event",
52862
+ buttonText: source.buttonText ?? "Book now",
52684
52863
  showVenue: source.showVenue ?? true,
52685
52864
  showMap: source.showMap ?? true,
52686
52865
  showCapacity: source.showCapacity ?? true,
@@ -52911,7 +53090,7 @@ var eventListingLayout = [
52911
53090
  loadMoreText: { $bind: { from: "content.loadMoreText", fallback: "Load more events" } },
52912
53091
  cardVariant: { $bind: { from: "content.cardVariant", fallback: "default" } },
52913
53092
  buttonVariant: { $bind: { from: "content.buttonVariant", fallback: "primary" } },
52914
- buttonText: { $bind: { from: "content.buttonText", fallback: "View event" } },
53093
+ buttonText: { $bind: { from: "content.buttonText", fallback: "Book now" } },
52915
53094
  showVenue: { $bind: { from: "content.showVenue" } },
52916
53095
  showMap: { $bind: { from: "content.showMap" } },
52917
53096
  showCapacity: { $bind: { from: "content.showCapacity" } },
@@ -52961,6 +53140,7 @@ var eventListingBlockDefinition = {
52961
53140
  limit: { $bind: { from: "content.eventsPerPage", fallback: "12" } },
52962
53141
  stage: { $bind: { from: "$root.previewStage", fallback: "published" } },
52963
53142
  detailLevel: "listing",
53143
+ readProfile: { $bind: { from: "content.layout", fallback: "listing-card" } },
52964
53144
  kind: { $bind: { from: "content.kind" } },
52965
53145
  eventSurface: { $bind: { from: "content.eventSurface" } },
52966
53146
  eventPresets: {
@@ -53092,7 +53272,7 @@ function buildEventCalendarDisplay(source) {
53092
53272
  ),
53093
53273
  filterVenueId: normalizeEventVenueId(source.filterVenueId),
53094
53274
  buttonVariant: source.buttonVariant ?? "primary",
53095
- buttonText: source.buttonText ?? "View event",
53275
+ buttonText: source.buttonText ?? "Book now",
53096
53276
  showVenue: source.showVenue ?? true,
53097
53277
  showMap: source.showMap ?? true,
53098
53278
  showCapacity: source.showCapacity ?? true,
@@ -53300,7 +53480,7 @@ var eventCalendarLayout = [
53300
53480
  $bind: { from: "content.buttonVariant", fallback: "primary" }
53301
53481
  },
53302
53482
  buttonText: {
53303
- $bind: { from: "content.buttonText", fallback: "View event" }
53483
+ $bind: { from: "content.buttonText", fallback: "Book now" }
53304
53484
  },
53305
53485
  emptyMessage: { $bind: { from: "content.emptyMessage" } }
53306
53486
  })
@@ -53754,6 +53934,7 @@ var eventCalendarBlockDefinition = {
53754
53934
  limit: 100,
53755
53935
  stage: { $bind: { from: "$root.previewStage", fallback: "published" } },
53756
53936
  detailLevel: "listing",
53937
+ readProfile: { $bind: { from: "content.variant", fallback: "listing-card" } },
53757
53938
  // Pass filter params if configured
53758
53939
  kind: { $bind: { from: "content.kind" } },
53759
53940
  eventSurface: { $bind: { from: "content.eventSurface" } },
@@ -59779,9 +59960,9 @@ function getEmbedUrl(info) {
59779
59960
  const kind = info.kind ?? "p";
59780
59961
  return `https://www.instagram.com/${kind}/${info.id}/embed`;
59781
59962
  }
59782
- default:
59783
- return "";
59784
59963
  }
59964
+ const exhaustive = info.provider;
59965
+ return exhaustive;
59785
59966
  }
59786
59967
  function getThumbnailUrl(info) {
59787
59968
  switch (info.provider) {
@@ -59791,9 +59972,20 @@ function getThumbnailUrl(info) {
59791
59972
  return `https://vumbnail.com/${info.id}.jpg`;
59792
59973
  case "instagram":
59793
59974
  return "";
59794
- default:
59795
- return "";
59796
59975
  }
59976
+ const exhaustive = info.provider;
59977
+ return exhaustive;
59978
+ }
59979
+ function getVideoEmbedLoadingStrategy(provider) {
59980
+ switch (provider) {
59981
+ case "youtube":
59982
+ case "vimeo":
59983
+ return "native-lazy";
59984
+ case "instagram":
59985
+ return "defer-until-near-viewport";
59986
+ }
59987
+ const exhaustive = provider;
59988
+ return exhaustive;
59797
59989
  }
59798
59990
  function getVideoEmbed(url) {
59799
59991
  const info = parseVideoUrl(url);
@@ -59848,34 +60040,43 @@ var VideoEmbedNode = ({
59848
60040
  );
59849
60041
  }
59850
60042
  const title = getVideoTitle(embedInfo);
59851
- return /* @__PURE__ */ jsx("div", { ...rest, children: /* @__PURE__ */ jsx(
60043
+ const loadingStrategy = getVideoEmbedLoadingStrategy(embedInfo.provider);
60044
+ const shouldDeferSrc = loadingStrategy === "defer-until-near-viewport";
60045
+ return /* @__PURE__ */ jsx("div", { ...rest, children: /* @__PURE__ */ jsxs(
59852
60046
  "div",
59853
60047
  {
59854
60048
  className,
60049
+ "data-rb-video-embed-wrapper": shouldDeferSrc ? "true" : void 0,
59855
60050
  style: {
59856
60051
  ...style2,
59857
60052
  aspectRatio: resolvedAspectRatio,
59858
60053
  position: "relative",
59859
60054
  width: "100%"
59860
60055
  },
59861
- children: /* @__PURE__ */ jsx(
59862
- "iframe",
59863
- {
59864
- src: embedInfo.embedUrl,
59865
- title,
59866
- style: {
59867
- position: "absolute",
59868
- top: 0,
59869
- left: 0,
59870
- width: "100%",
59871
- height: "100%",
59872
- border: "none"
59873
- },
59874
- allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",
59875
- referrerPolicy: "no-referrer-when-downgrade",
59876
- allowFullScreen: true
59877
- }
59878
- )
60056
+ children: [
60057
+ /* @__PURE__ */ jsx(
60058
+ "iframe",
60059
+ {
60060
+ src: shouldDeferSrc ? void 0 : embedInfo.embedUrl,
60061
+ title,
60062
+ loading: "lazy",
60063
+ "data-rb-video-embed-deferred": shouldDeferSrc ? "true" : void 0,
60064
+ "data-rb-video-embed-src": shouldDeferSrc ? embedInfo.embedUrl : void 0,
60065
+ style: {
60066
+ position: "absolute",
60067
+ top: 0,
60068
+ left: 0,
60069
+ width: "100%",
60070
+ height: "100%",
60071
+ border: "none"
60072
+ },
60073
+ allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",
60074
+ referrerPolicy: "no-referrer-when-downgrade",
60075
+ allowFullScreen: true
60076
+ }
60077
+ ),
60078
+ shouldDeferSrc ? /* @__PURE__ */ jsx("noscript", { children: /* @__PURE__ */ jsx("a", { href: embedInfo.url, children: "View on Instagram" }) }) : null
60079
+ ]
59879
60080
  }
59880
60081
  ) });
59881
60082
  };
@@ -59890,9 +60091,9 @@ function getVideoTitle(info) {
59890
60091
  const label = kind === "reel" ? "reel" : kind === "tv" ? "video" : "post";
59891
60092
  return `Instagram ${label} ${info.id}`;
59892
60093
  }
59893
- default:
59894
- return "Embedded video";
59895
60094
  }
60095
+ const exhaustive = info.provider;
60096
+ return exhaustive;
59896
60097
  }
59897
60098
  function getAspectRatio(propAspectRatio, style2) {
59898
60099
  const styleAspectRatio = style2?.aspectRatio;
@@ -60135,10 +60336,15 @@ var HeaderSectionNode = ({
60135
60336
  blockId,
60136
60337
  children,
60137
60338
  className,
60339
+ "data-preview-site-chrome-surface": previewSiteChromeSurface,
60138
60340
  ...rest
60139
60341
  }) => {
60140
60342
  const { wrapperClasses, sectionClasses } = splitPositioningClasses(className);
60141
- const wrapperClassName = `block-site-header${wrapperClasses ? ` ${wrapperClasses}` : ""}`;
60343
+ const wrapperClassName = [
60344
+ "block-site-header",
60345
+ wrapperClasses,
60346
+ previewSiteChromeSurface ? "group/site-chrome rb-relative" : ""
60347
+ ].filter(Boolean).join(" ");
60142
60348
  const asProp = rest.as;
60143
60349
  const styleProp = rest.style;
60144
60350
  const backgroundProp = typeof rest.background === "string" ? rest.background : void 0;
@@ -60154,6 +60360,7 @@ var HeaderSectionNode = ({
60154
60360
  "data-block": "site-header",
60155
60361
  "data-block-kind": "block.site-header",
60156
60362
  "data-block-id": blockId ?? void 0,
60363
+ "data-preview-site-chrome-surface": previewSiteChromeSurface,
60157
60364
  children: [
60158
60365
  /* @__PURE__ */ jsx(IslandPropsScript, { value: { enabled: hasShrinkClasses(className) } }),
60159
60366
  /* @__PURE__ */ jsx(
@@ -61786,7 +61993,7 @@ var EventSpotlight = ({
61786
61993
  columns = "3",
61787
61994
  cardVariant = "default",
61788
61995
  buttonVariant = "primary",
61789
- buttonText = "View event",
61996
+ buttonText = "Book now",
61790
61997
  ctaLabel,
61791
61998
  ctaUrl,
61792
61999
  showVenue = true,
@@ -61932,7 +62139,7 @@ function buildEventCombinedDisplay(source) {
61932
62139
  showMap: source.showMap ?? true,
61933
62140
  showCapacity: source.showCapacity ?? true,
61934
62141
  buttonVariant: source.buttonVariant ?? "primary",
61935
- buttonText: source.buttonText ?? "View event",
62142
+ buttonText: source.buttonText ?? "Book now",
61936
62143
  emptyMessage: source.emptyMessage ?? "No upcoming events scheduled."
61937
62144
  };
61938
62145
  }
@@ -63575,6 +63782,10 @@ function getAbsoluteSegments(fromPath, context) {
63575
63782
  if (scoped?.basePathSegments && scoped.basePathSegments.length > 0) {
63576
63783
  return [...scoped.basePathSegments, ...rest];
63577
63784
  }
63785
+ const hasContentScope = context.scopes.some((entry) => entry.name === "content");
63786
+ if (hasContentScope && !(first2 in context.viewModel)) {
63787
+ return ["content", ...segments];
63788
+ }
63578
63789
  return void 0;
63579
63790
  }
63580
63791
  function readFromSource(source, segments) {
@@ -64219,7 +64430,7 @@ function makeDefaultBlockComponent(args) {
64219
64430
  pathBase,
64220
64431
  blockId,
64221
64432
  blockKind,
64222
- blockContent: content,
64433
+ blockContent: mergedContent,
64223
64434
  blockBindings,
64224
64435
  editableRouteMetadataFieldIds,
64225
64436
  fragmentRegistry: fragmentRegistry2
@@ -65213,6 +65424,20 @@ function getNavLinkPreset(presetId) {
65213
65424
  return NAV_LINK_PRESETS[presetId];
65214
65425
  }
65215
65426
 
65427
+ // ../theme-core/src/header/navDropdownSizing.ts
65428
+ var NAV_DROPDOWN_MIN_WIDTH_REM = 12;
65429
+ var NAV_DROPDOWN_MAX_WIDTH_REM = 22;
65430
+ var NAV_DROPDOWN_VIEWPORT_GUTTER_REM = 1;
65431
+ var NAV_DROPDOWN_VIEWPORT_GUTTER_PX = 16;
65432
+ var NAV_DROPDOWN_SHIFT_PROPERTY = "--nav-dropdown-shift-x";
65433
+ var NAV_DROPDOWN_MAX_WIDTH_CSS = `min(${NAV_DROPDOWN_MAX_WIDTH_REM}rem, calc(100vw - ${NAV_DROPDOWN_VIEWPORT_GUTTER_REM * 2}rem))`;
65434
+ var NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
65435
+ `min-width: ${NAV_DROPDOWN_MIN_WIDTH_REM}rem;`,
65436
+ `width: max-content;`,
65437
+ `max-width: ${NAV_DROPDOWN_MAX_WIDTH_CSS};`,
65438
+ `transform: translateX(var(${NAV_DROPDOWN_SHIFT_PROPERTY}, 0px));`
65439
+ ];
65440
+
65216
65441
  // ../theme-core/src/header/generateHeaderCss.ts
65217
65442
  var HEADER_BLUR = "blur(12px)";
65218
65443
  var FLOATING_BLUR = "blur(16px)";
@@ -65487,6 +65712,7 @@ function generateDropdownContainerStyles(header, themeId, tokens) {
65487
65712
  const selector = `:where([data-theme-scope="${themeId}"]) .nav-dropdown-menu`;
65488
65713
  const rules = [];
65489
65714
  const dropdownStyle = header.dropdownStyle;
65715
+ rules.push(...NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES);
65490
65716
  const bgToken = dropdownStyle?.background ?? "surface";
65491
65717
  rules.push(`background-color: ${tokens.getColor(bgToken)};`);
65492
65718
  const textToken = dropdownStyle?.textColor ?? "text";
@@ -76932,6 +77158,17 @@ var containerResponsiveThemeCss = `/*
76932
77158
  * =============================================================================
76933
77159
  */
76934
77160
 
77161
+ :where(.theme-scope) .nav-dropdown-menu {
77162
+ /*
77163
+ * Keep these rails in sync with header/navDropdownSizing.ts.
77164
+ * The JS placement gutter is 16px, matching the 1rem per-side gutter in calc(100vw - 2rem).
77165
+ */
77166
+ min-width: 12rem;
77167
+ width: max-content;
77168
+ max-width: min(22rem, calc(100vw - 2rem));
77169
+ transform: translateX(var(--nav-dropdown-shift-x, 0px));
77170
+ }
77171
+
76935
77172
  :where(.theme-scope) .nav-dropdown:hover > .nav-dropdown-menu,
76936
77173
  :where(.theme-scope) .nav-dropdown:focus-within > .nav-dropdown-menu,
76937
77174
  :where(.theme-scope) .nav-dropdown .nav-dropdown-trigger[aria-expanded="true"] + .nav-dropdown-menu {
@@ -78402,6 +78639,11 @@ var containerResponsiveThemeCss = `/*
78402
78639
  * Dense row layout for event-calendar compact list mode
78403
78640
  * ============================================================================= */
78404
78641
 
78642
+ :where(.theme-scope) .event-listing-compact-container {
78643
+ width: min(100%, 56rem);
78644
+ margin-inline: auto;
78645
+ }
78646
+
78405
78647
  :where(.theme-scope) .event-compact-row {
78406
78648
  display: flex;
78407
78649
  align-items: center;
@@ -80349,16 +80591,24 @@ function validateBlockManifestIssues(manifest, values, mode) {
80349
80591
  return result.error.issues.map(withNormalizedManifestMessage);
80350
80592
  }
80351
80593
  function validateBlockManifest(manifest, values, mode) {
80594
+ const plans = getManifestValidationCacheEntry(manifest).plans;
80352
80595
  return validateBlockManifestIssues(manifest, values, mode).map((issue2) => {
80353
80596
  const path = normalizeIssuePath(issue2.path);
80597
+ const fieldDescriptor = resolveFieldValidationDescriptor(plans, path);
80354
80598
  return {
80355
80599
  code: issue2.code,
80356
80600
  path,
80357
80601
  fieldPath: normalizePathString(path),
80602
+ fieldDescriptor,
80603
+ isFieldVisibleInSidebar: isValidationFieldVisibleInSidebar(fieldDescriptor),
80358
80604
  message: issue2.message
80359
80605
  };
80360
80606
  });
80361
80607
  }
80608
+ function isValidationFieldVisibleInSidebar(descriptor) {
80609
+ if (!descriptor) return true;
80610
+ return descriptor.visibility.kind === "visible";
80611
+ }
80362
80612
  function normalizeManifestIssueMessage(issue2) {
80363
80613
  switch (issue2.code) {
80364
80614
  case "invalid_type":
@@ -80377,8 +80627,8 @@ function normalizeManifestIssueMessage(issue2) {
80377
80627
  }
80378
80628
  }
80379
80629
  function getManifestValidation(manifest, mode) {
80380
- const cached = manifestValidationCache.get(manifest);
80381
- const existing = cached?.[mode];
80630
+ const cached = getManifestValidationCacheEntry(manifest);
80631
+ const existing = cached.validators[mode];
80382
80632
  if (existing) {
80383
80633
  return existing;
80384
80634
  }
@@ -80386,10 +80636,19 @@ function getManifestValidation(manifest, mode) {
80386
80636
  allowNull: false,
80387
80637
  mode
80388
80638
  });
80389
- manifestValidationCache.set(manifest, {
80390
- ...cached,
80391
- [mode]: created
80392
- });
80639
+ cached.validators[mode] = created;
80640
+ return created;
80641
+ }
80642
+ function getManifestValidationCacheEntry(manifest) {
80643
+ const cached = manifestValidationCache.get(manifest);
80644
+ if (cached) {
80645
+ return cached;
80646
+ }
80647
+ const created = {
80648
+ plans: deriveFieldValidationPlans(manifest.fields ?? []),
80649
+ validators: {}
80650
+ };
80651
+ manifestValidationCache.set(manifest, created);
80393
80652
  return created;
80394
80653
  }
80395
80654
  function normalizeIssuePath(path) {
@@ -81977,6 +82236,8 @@ function deriveBlockedPublishPlan({
81977
82236
  if (!firstError) {
81978
82237
  return { type: "allowed" };
81979
82238
  }
82239
+ const focusError = validationErrors.find((error) => error.isFieldVisibleInSidebar) ?? firstError;
82240
+ const focusFieldPath = focusError.isFieldVisibleInSidebar ? focusError.fieldPath || null : null;
81980
82241
  return {
81981
82242
  type: "blocked",
81982
82243
  invalidBlockIds,
@@ -81985,8 +82246,8 @@ function deriveBlockedPublishPlan({
81985
82246
  reveal: "show-validation"
81986
82247
  })),
81987
82248
  focusTarget: {
81988
- blockId: firstError.blockId,
81989
- fieldPath: firstError.fieldPath || null
82249
+ blockId: focusError.blockId,
82250
+ fieldPath: focusFieldPath
81990
82251
  },
81991
82252
  message: invalidBlockIds.length === 1 ? {
81992
82253
  type: "single-invalid-block",
@@ -82045,9 +82306,12 @@ function validateAllBlocks(uiStore) {
82045
82306
  blockId: snapshot.id,
82046
82307
  blockKind: snapshot.meta.kind,
82047
82308
  fieldPath: issue2.fieldPath,
82309
+ fieldDescriptor: issue2.fieldDescriptor,
82310
+ isFieldVisibleInSidebar: issue2.isFieldVisibleInSidebar,
82048
82311
  fieldLabel: getFieldLabelFromManifest(
82049
82312
  definition.manifest,
82050
- issue2.path
82313
+ issue2.path,
82314
+ issue2.fieldDescriptor
82051
82315
  ),
82052
82316
  message: issue2.message
82053
82317
  });
@@ -82056,7 +82320,8 @@ function validateAllBlocks(uiStore) {
82056
82320
  }
82057
82321
  return errors;
82058
82322
  }
82059
- function getFieldLabelFromManifest(manifest, path) {
82323
+ function getFieldLabelFromManifest(manifest, path, descriptor) {
82324
+ if (descriptor) return descriptor.label;
82060
82325
  if (path.length === 0) return "Unknown field";
82061
82326
  const fieldId = path[0];
82062
82327
  if (typeof fieldId !== "string") return String(fieldId);
@@ -105998,7 +106263,7 @@ var DEFAULT_VALUE_BUILDERS = {
105998
106263
  contentTypeSelect: getContentTypeSelectFieldDefault,
105999
106264
  entryPicker: getEntryPickerFieldDefault
106000
106265
  };
106001
- function buildFieldSchema2(field, ctx) {
106266
+ function buildFieldSchema(field, ctx) {
106002
106267
  const builder = SCHEMA_BUILDERS[field.type];
106003
106268
  if (!builder) {
106004
106269
  console.warn(`No schema builder registered for field type: ${field.type}`);
@@ -106104,10 +106369,10 @@ function isFieldVisible(field, role) {
106104
106369
  function buildValidationSchema(fields3) {
106105
106370
  const shape = {};
106106
106371
  const ctx = {
106107
- getFieldSchema: (field) => buildFieldSchema2(field, ctx)
106372
+ getFieldSchema: (field) => buildFieldSchema(field, ctx)
106108
106373
  };
106109
106374
  for (const field of fields3) {
106110
- shape[field.id] = buildFieldSchema2(field, ctx);
106375
+ shape[field.id] = buildFieldSchema(field, ctx);
106111
106376
  }
106112
106377
  return z.object(shape).catchall(z.unknown()).passthrough();
106113
106378
  }
@@ -109326,6 +109591,7 @@ function clearBookingFieldError(errors, fieldId) {
109326
109591
  function createInitialBookingFlowReducerState(input) {
109327
109592
  const initialData = input.initialData ?? {};
109328
109593
  return {
109594
+ phase: "editing",
109329
109595
  currentStepId: "service-selection",
109330
109596
  selectedServiceId: toOptionalAppointmentServiceId(
109331
109597
  toOptionalString(initialData.serviceId) ?? input.defaultServiceId
@@ -109346,8 +109612,7 @@ function createInitialBookingFlowReducerState(input) {
109346
109612
  ),
109347
109613
  altchaSolution: null,
109348
109614
  validationErrors: createEmptyBookingValidationErrors(),
109349
- feedback: { kind: "none" },
109350
- isSubmitting: false
109615
+ feedback: { kind: "none" }
109351
109616
  };
109352
109617
  }
109353
109618
  function collectInitialFieldValues(initialData) {
@@ -109474,8 +109739,15 @@ function bookingFlowReducer(state, event) {
109474
109739
  case "validation-errors-set":
109475
109740
  return { ...state, validationErrors: event.errors };
109476
109741
  case "feedback-set":
109477
- return { ...state, feedback: event.feedback };
109742
+ return {
109743
+ ...state,
109744
+ phase: event.feedback.kind === "success" ? "completed" : "editing",
109745
+ feedback: event.feedback
109746
+ };
109478
109747
  case "availability-selection-invalidated":
109748
+ if (state.phase !== "editing") {
109749
+ return state;
109750
+ }
109479
109751
  return {
109480
109752
  ...state,
109481
109753
  currentStepId: "datetime-selection",
@@ -109489,11 +109761,11 @@ function bookingFlowReducer(state, event) {
109489
109761
  validationErrors: clearBookingFormError(state.validationErrors)
109490
109762
  };
109491
109763
  case "feedback-cleared":
109492
- return { ...state, feedback: { kind: "none" } };
109764
+ return { ...state, phase: "editing", feedback: { kind: "none" } };
109493
109765
  case "submission-started":
109494
- return { ...state, isSubmitting: true };
109766
+ return { ...state, phase: "submitting" };
109495
109767
  case "submission-finished":
109496
- return { ...state, isSubmitting: false };
109768
+ return state.phase === "submitting" ? { ...state, phase: "editing" } : state;
109497
109769
  case "reset":
109498
109770
  return event.initial;
109499
109771
  default:
@@ -109928,8 +110200,8 @@ function toHeadlessEligibleAppointmentPackage(appointmentPackage) {
109928
110200
  };
109929
110201
  }
109930
110202
  function resolveHeadlessBookingStatus(input) {
109931
- if (input.isSubmitting) return { tag: "submitting" };
109932
- if (input.feedback.kind === "success") {
110203
+ if (input.phase === "submitting") return { tag: "submitting" };
110204
+ if (input.phase === "completed" && input.feedback.kind === "success") {
109933
110205
  return {
109934
110206
  tag: "success",
109935
110207
  resourceName: input.feedback.resourceName
@@ -110088,6 +110360,7 @@ function useHeadlessBookingFlow(options) {
110088
110360
  [availableDates]
110089
110361
  );
110090
110362
  useEffect(() => {
110363
+ if (state.phase !== "editing") return;
110091
110364
  const canEvaluateDate = availabilityDatesQuery.ok && Boolean(availableDatesLoadedRange) && !isLoadingDates && !datesError;
110092
110365
  const canEvaluateSlot = !state.selectedSlot || availabilitySlotsQuery.ok && hasLoadedSlots && !isLoadingSlots && !slotsError;
110093
110366
  if (!canEvaluateDate || !canEvaluateSlot) return;
@@ -110113,6 +110386,7 @@ function useHeadlessBookingFlow(options) {
110113
110386
  isLoadingSlots,
110114
110387
  slotViews,
110115
110388
  slotsError,
110389
+ state.phase,
110116
110390
  state.selectedDate,
110117
110391
  state.selectedSlot
110118
110392
  ]);
@@ -110273,7 +110547,7 @@ function useHeadlessBookingFlow(options) {
110273
110547
  const submitBooking = useCallback(
110274
110548
  async (submitOptions) => {
110275
110549
  const latest = latestRef.current;
110276
- if (submittingRef.current || latest.state.isSubmitting) {
110550
+ if (submittingRef.current || latest.state.phase === "submitting") {
110277
110551
  return {
110278
110552
  ok: false,
110279
110553
  reason: "blocked",
@@ -110469,7 +110743,7 @@ function useHeadlessBookingFlow(options) {
110469
110743
  const spamProtectionEnabled = options.spamProtectionEnabled ?? isSpamProtectionEnabled();
110470
110744
  const status = resolveHeadlessBookingStatus({
110471
110745
  feedback: state.feedback,
110472
- isSubmitting: state.isSubmitting
110746
+ phase: state.phase
110473
110747
  });
110474
110748
  const view = resolveHeadlessBookingView({
110475
110749
  form: options.form,
@@ -119606,6 +119880,7 @@ function mountHeaderCartRuntime(root, siteId, mounts) {
119606
119880
  // ../blocks/src/system/runtime/header/enhanceHeaderSection.ts
119607
119881
  var SELECTORS = {
119608
119882
  dropdown: ".nav-dropdown",
119883
+ dropdownMenu: ".nav-dropdown-menu",
119609
119884
  dropdownTrigger: ".nav-dropdown-trigger",
119610
119885
  mobileOverlay: "[data-nav-mobile-overlay]",
119611
119886
  mobileToggle: "[data-nav-mobile-toggle]",
@@ -119623,6 +119898,39 @@ var CLASSES = {
119623
119898
  mobileOpen: "nav-mobile-open"
119624
119899
  };
119625
119900
  var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])';
119901
+ function planDropdownViewportShift(input) {
119902
+ const { left, right, viewportWidth, gutter } = input;
119903
+ if (!Number.isFinite(left) || !Number.isFinite(right) || !Number.isFinite(viewportWidth) || !Number.isFinite(gutter)) {
119904
+ return { kind: "unchanged" };
119905
+ }
119906
+ const normalizedGutter = Math.max(0, gutter);
119907
+ const viewportLeft = normalizedGutter;
119908
+ const viewportRight = Math.max(viewportLeft, viewportWidth - normalizedGutter);
119909
+ const menuWidth = right - left;
119910
+ const availableWidth = viewportRight - viewportLeft;
119911
+ if (menuWidth >= availableWidth) {
119912
+ const x3 = viewportLeft - left;
119913
+ return x3 === 0 ? { kind: "unchanged" } : { kind: "shift", x: x3 };
119914
+ }
119915
+ let x2 = 0;
119916
+ if (right > viewportRight) x2 = viewportRight - right;
119917
+ if (left + x2 < viewportLeft) x2 += viewportLeft - (left + x2);
119918
+ return x2 === 0 ? { kind: "unchanged" } : { kind: "shift", x: x2 };
119919
+ }
119920
+ function applyDropdownPlacementPlan(menu, plan) {
119921
+ switch (plan.kind) {
119922
+ case "unchanged":
119923
+ menu.style.removeProperty(NAV_DROPDOWN_SHIFT_PROPERTY);
119924
+ return;
119925
+ case "shift":
119926
+ menu.style.setProperty(NAV_DROPDOWN_SHIFT_PROPERTY, `${plan.x}px`);
119927
+ return;
119928
+ default: {
119929
+ const _exhaustive = plan;
119930
+ return _exhaustive;
119931
+ }
119932
+ }
119933
+ }
119626
119934
  function getFirstNonScriptChild(root) {
119627
119935
  const children = Array.from(root.children);
119628
119936
  for (const child of children) {
@@ -119640,16 +119948,58 @@ function enhanceDesktopDropdownAria(root) {
119640
119948
  dropdowns.forEach((dropdown) => {
119641
119949
  const trigger = dropdown.querySelector(SELECTORS.dropdownTrigger);
119642
119950
  if (!trigger) return;
119951
+ const menu = dropdown.querySelector(SELECTORS.dropdownMenu);
119952
+ let placementRafId = null;
119953
+ let placementRafScheduled = false;
119954
+ const cancelPlacementFrame = () => {
119955
+ if (placementRafId !== null) {
119956
+ window.cancelAnimationFrame(placementRafId);
119957
+ placementRafId = null;
119958
+ }
119959
+ placementRafScheduled = false;
119960
+ };
119961
+ const resetPlacement = () => {
119962
+ cancelPlacementFrame();
119963
+ menu?.style.removeProperty(NAV_DROPDOWN_SHIFT_PROPERTY);
119964
+ };
119965
+ const schedulePlacement = () => {
119966
+ if (!menu) return;
119967
+ resetPlacement();
119968
+ placementRafScheduled = true;
119969
+ const id = window.requestAnimationFrame(() => {
119970
+ placementRafScheduled = false;
119971
+ placementRafId = null;
119972
+ const rect = menu.getBoundingClientRect();
119973
+ const plan = planDropdownViewportShift({
119974
+ left: rect.left,
119975
+ right: rect.right,
119976
+ viewportWidth: document.documentElement.clientWidth,
119977
+ gutter: NAV_DROPDOWN_VIEWPORT_GUTTER_PX
119978
+ });
119979
+ applyDropdownPlacementPlan(menu, plan);
119980
+ });
119981
+ placementRafId = placementRafScheduled ? id : null;
119982
+ };
119643
119983
  setExpanded(trigger, false);
119644
- const handleEnter = () => setExpanded(trigger, true);
119984
+ const handleEnter = () => {
119985
+ setExpanded(trigger, true);
119986
+ schedulePlacement();
119987
+ };
119645
119988
  const handleLeave = () => {
119646
119989
  if (dropdown.contains(document.activeElement)) return;
119647
119990
  setExpanded(trigger, false);
119991
+ resetPlacement();
119992
+ };
119993
+ const handleFocusIn = () => {
119994
+ setExpanded(trigger, true);
119995
+ schedulePlacement();
119648
119996
  };
119649
- const handleFocusIn = () => setExpanded(trigger, true);
119650
119997
  const handleFocusOut = (event) => {
119651
119998
  const next = event.relatedTarget;
119652
- if (!next || !dropdown.contains(next)) setExpanded(trigger, false);
119999
+ if (!next || !dropdown.contains(next)) {
120000
+ setExpanded(trigger, false);
120001
+ resetPlacement();
120002
+ }
119653
120003
  };
119654
120004
  dropdown.addEventListener("mouseenter", handleEnter);
119655
120005
  dropdown.addEventListener("mouseleave", handleLeave);
@@ -119660,6 +120010,7 @@ function enhanceDesktopDropdownAria(root) {
119660
120010
  dropdown.removeEventListener("mouseleave", handleLeave);
119661
120011
  dropdown.removeEventListener("focusin", handleFocusIn);
119662
120012
  dropdown.removeEventListener("focusout", handleFocusOut);
120013
+ resetPlacement();
119663
120014
  });
119664
120015
  });
119665
120016
  return cleanups;
@@ -119926,6 +120277,7 @@ var HeaderSectionNode2 = ({
119926
120277
  pathBase,
119927
120278
  children,
119928
120279
  className: originalClassName,
120280
+ "data-preview-site-chrome-surface": previewSiteChromeSurface,
119929
120281
  ...restProps
119930
120282
  }) => {
119931
120283
  const rootRef = useRef(null);
@@ -119933,7 +120285,11 @@ var HeaderSectionNode2 = ({
119933
120285
  () => splitPositioningClasses(originalClassName),
119934
120286
  [originalClassName]
119935
120287
  );
119936
- const wrapperClassName = `block-site-header${wrapperClasses ? ` ${wrapperClasses}` : ""}`;
120288
+ const wrapperClassName = [
120289
+ "block-site-header",
120290
+ wrapperClasses,
120291
+ previewSiteChromeSurface ? "group/site-chrome rb-relative" : ""
120292
+ ].filter(Boolean).join(" ");
119937
120293
  const hasShrinkClasses2 = useMemo(
119938
120294
  () => Boolean(sectionClasses?.includes("rb-header-shrink")),
119939
120295
  [sectionClasses]
@@ -119966,6 +120322,7 @@ var HeaderSectionNode2 = ({
119966
120322
  "data-block-content": blockContent ? "true" : void 0,
119967
120323
  "data-fragment-registry": fragmentRegistry2 ? "true" : void 0,
119968
120324
  "data-path-base": typeof pathBase === "string" ? pathBase : void 0,
120325
+ "data-preview-site-chrome-surface": previewSiteChromeSurface,
119969
120326
  children: /* @__PURE__ */ jsx(
119970
120327
  Section_default,
119971
120328
  {
@@ -121406,7 +121763,7 @@ var EventCombinedClient = ({
121406
121763
  showCapacity,
121407
121764
  // Styling
121408
121765
  buttonVariant = "primary",
121409
- buttonText = "View event",
121766
+ buttonText = "Book now",
121410
121767
  emptyMessage = "No upcoming events scheduled.",
121411
121768
  className
121412
121769
  }) => {
@@ -122542,6 +122899,8 @@ var MediaNode = ({
122542
122899
  className,
122543
122900
  style: style2,
122544
122901
  videoPlayback = "inline",
122902
+ loading = "lazy",
122903
+ fetchPriority,
122545
122904
  size: size4 = ImagePresets.full,
122546
122905
  fieldPath,
122547
122906
  blockKind,
@@ -122588,7 +122947,8 @@ var MediaNode = ({
122588
122947
  alt: value.alt ?? "",
122589
122948
  className,
122590
122949
  style: computedStyle,
122591
- loading: "lazy",
122950
+ loading,
122951
+ fetchPriority,
122592
122952
  decoding: "async",
122593
122953
  onError: handleImageError
122594
122954
  }
@@ -162806,7 +163166,6 @@ var PreviewRichTextEditorInner = ({
162806
163166
  toolbarTone: "dark",
162807
163167
  toolbarPortalToChrome: false,
162808
163168
  hideToolbar: true,
162809
- onClick: () => editor?.chain().focus().run(),
162810
163169
  renderContent: (content) => /* @__PURE__ */ jsx(
162811
163170
  "div",
162812
163171
  {