@riverbankcms/sdk 0.70.3 → 0.70.4

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 (79) hide show
  1. package/dist/_dts/api/src/contentTypes.d.ts +2 -1
  2. package/dist/_dts/block-form/src/client/index.d.ts +1 -1
  3. package/dist/_dts/block-form/src/fields/types.d.ts +14 -2
  4. package/dist/_dts/block-form/src/registry/schemas.d.ts +2 -0
  5. package/dist/_dts/block-form/src/widgets/MediaField/mediaFieldDefaults.d.ts +2 -2
  6. package/dist/_dts/block-form/src/widgets/MediaField/mediaFieldSchema.d.ts +2 -2
  7. package/dist/_dts/blocks/src/lib/media.d.ts +1 -1
  8. package/dist/_dts/blocks/src/system/blocks/appointment-booking.d.ts +1829 -149
  9. package/dist/_dts/blocks/src/system/blocks/blog-listing.d.ts +1829 -149
  10. package/dist/_dts/blocks/src/system/blocks/cart.d.ts +1829 -149
  11. package/dist/_dts/blocks/src/system/blocks/checkout.d.ts +1829 -149
  12. package/dist/_dts/blocks/src/system/blocks/collection.d.ts +1829 -149
  13. package/dist/_dts/blocks/src/system/blocks/cta-full.d.ts +1 -30727
  14. package/dist/_dts/blocks/src/system/blocks/events/event-spotlight.d.ts +11 -30827
  15. package/dist/_dts/blocks/src/system/blocks/faq.d.ts +1829 -149
  16. package/dist/_dts/blocks/src/system/blocks/file-download.d.ts +3 -3
  17. package/dist/_dts/blocks/src/system/blocks/gifting.d.ts +1829 -149
  18. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +106 -1
  19. package/dist/_dts/blocks/src/system/blocks/product-detail.d.ts +1829 -149
  20. package/dist/_dts/blocks/src/system/blocks/product-list.d.ts +1829 -149
  21. package/dist/_dts/blocks/src/system/blocks/shop.d.ts +1829 -149
  22. package/dist/_dts/blocks/src/system/defineBlock.d.ts +3 -3
  23. package/dist/_dts/blocks/src/system/fragments/library/card.d.ts +2 -30793
  24. package/dist/_dts/blocks/src/system/fragments/library/ctaRow.d.ts +2 -30727
  25. package/dist/_dts/blocks/src/system/fragments/library/feedbackCallout.d.ts +2 -30779
  26. package/dist/_dts/blocks/src/system/fragments/library/heroCtaRow.d.ts +33 -30743
  27. package/dist/_dts/blocks/src/system/fragments/library/sectionState.d.ts +2 -30770
  28. package/dist/_dts/blocks/src/system/fragments/types.d.ts +8 -7
  29. package/dist/_dts/blocks/src/system/manifest/derivedContent.d.ts +7 -5
  30. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +1 -1
  31. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +192 -3
  32. package/dist/_dts/blocks/src/system/runtime/nodes/file-download.d.ts +1 -1
  33. package/dist/_dts/content-model/src/content-types/schema.d.ts +7 -0
  34. package/dist/_dts/content-model/src/contentManifest.d.ts +4 -1
  35. package/dist/_dts/content-model/src/templates/bindingTypeCompatibility.d.ts +1 -1
  36. package/dist/_dts/core/src/index.d.ts +1 -1
  37. package/dist/_dts/core/src/planner.d.ts +4 -0
  38. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +53 -20
  39. package/dist/_dts/editor-blocks/src/index.d.ts +1 -1
  40. package/dist/_dts/editor-blocks/src/media/MediaField.d.ts +6 -5
  41. package/dist/_dts/media-core/src/videoSlotPolicy.d.ts +0 -1
  42. package/dist/_dts/media-editor/src/context.d.ts +4 -1
  43. package/dist/_dts/media-react/src/hooks/useApiMediaUploader.d.ts +8 -1
  44. package/dist/_dts/media-react/src/index.d.ts +1 -5
  45. package/dist/_dts/preview-next/src/client/widgets/PreviewMediaField.d.ts +2 -1
  46. package/dist/_dts/preview-next/src/client/widgets/widgetOverrides.d.ts +1 -0
  47. package/dist/_dts/sdk/src/config/field-definitions.d.ts +6 -2
  48. package/dist/_dts/sdk/src/config/typed-entries.d.ts +4 -2
  49. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +2 -1
  50. package/dist/_dts/sdk/src/manifest/prompt/examples/cta.d.ts +5 -5
  51. package/dist/_dts/sdk/src/manifest/prompt/examples/features-grid.d.ts +2 -2
  52. package/dist/_dts/sdk/src/manifest/prompt/examples/hero.d.ts +2 -2
  53. package/dist/_dts/sdk/src/manifest/prompt/examples/pricing.d.ts +10 -10
  54. package/dist/_dts/sdk/src/manifest/prompt/examples/testimonials.d.ts +4 -4
  55. package/dist/_dts/sdk/src/manifest/validation/output-schema.d.ts +11 -1
  56. package/dist/_dts/sdk/src/public-api/contracts.d.ts +2 -1
  57. package/dist/_dts/sdk/src/version.d.ts +1 -1
  58. package/dist/cli/index.mjs +395 -190
  59. package/dist/cli/init-docs/content/workflow-preview-mode.md +167 -0
  60. package/dist/client/client.mjs +243 -203
  61. package/dist/client/hooks.mjs +172 -121
  62. package/dist/client/rendering/client.mjs +148 -112
  63. package/dist/client/rendering/islands.mjs +80 -31
  64. package/dist/client/rendering.mjs +242 -202
  65. package/dist/preview-next/client/runtime.mjs +386 -1135
  66. package/dist/server/components.mjs +219 -171
  67. package/dist/server/config-template-validation.mjs +31 -1
  68. package/dist/server/config-validation.mjs +172 -121
  69. package/dist/server/config.mjs +172 -121
  70. package/dist/server/data.mjs +172 -121
  71. package/dist/server/index.mjs +1 -1
  72. package/dist/server/next.mjs +220 -172
  73. package/dist/server/page-converter.mjs +379 -185
  74. package/dist/server/prebuild.mjs +1 -1
  75. package/dist/server/rendering/server.mjs +219 -171
  76. package/dist/server/rendering.mjs +219 -171
  77. package/dist/server/routing.mjs +175 -124
  78. package/dist/server/server.mjs +173 -122
  79. package/package.json +2 -1
@@ -916,6 +916,9 @@ var init_repeaterGrid = __esm({
916
916
  DEFAULT_REPEATER_GRID_COLUMN_FIELD_ID = "gridColumn";
917
917
  }
918
918
  });
919
+ function isDisplayMediaKind(kind) {
920
+ return DISPLAY_MEDIA_KINDS.includes(kind);
921
+ }
919
922
  function assertNeverSelectSource(value) {
920
923
  throw new Error(`Unhandled select source: ${JSON.stringify(value)}`);
921
924
  }
@@ -927,6 +930,7 @@ function getFieldSchemaInternal() {
927
930
  textFieldSchema,
928
931
  richTextFieldSchema,
929
932
  mediaFieldSchema,
933
+ fileFieldSchema,
930
934
  booleanFieldSchema,
931
935
  numberFieldSchema,
932
936
  dateFieldSchema,
@@ -993,13 +997,32 @@ function createSdkSelectField(input) {
993
997
  })
994
998
  );
995
999
  }
996
- var visibilityLevels, siteOptionSources, mediaDeliverySchema, selectOptionSchema, selectSourceSchema, uiSchema, baseFieldSchema, textFieldSchema, richTextFieldSchema, mediaFieldSchema, booleanFieldSchema, dateFieldSchema, timeFieldSchema, dateTimeFieldSchema, slugFieldSchema, urlFieldSchema, linkFieldSchema, selectFieldSchema, referenceFieldSchema, itemTypeSchema, repeaterFieldSchema, groupFieldSchema, modalFieldSchema, numberFieldSchema, tabDefinitionSchema, tabGroupFieldSchema, presetOptionSchema, presetOrCustomFieldSchema, contentTypeSelectFieldSchema, entryPickerFieldSchema, _fieldSchemaInternal, fieldSchema, slotSchema, typographyTokens, colorTokens, spacingTokens, radiusTokens, styleTokenSchema, behaviourSchema, blockCategoryEnum;
1000
+ var visibilityLevels, MEDIA_KINDS, DISPLAY_MEDIA_KINDS, PUBLIC_FILE_FIELD_KINDS, siteOptionSources, mediaDeliverySchema, selectOptionSchema, selectSourceSchema, uiSchema, baseFieldSchema, textFieldSchema, richTextFieldSchema, mediaFieldSchema, fileFieldSchema, booleanFieldSchema, dateFieldSchema, timeFieldSchema, dateTimeFieldSchema, slugFieldSchema, urlFieldSchema, linkFieldSchema, selectFieldSchema, referenceFieldSchema, itemTypeSchema, repeaterFieldSchema, groupFieldSchema, modalFieldSchema, numberFieldSchema, tabDefinitionSchema, tabGroupFieldSchema, presetOptionSchema, presetOrCustomFieldSchema, contentTypeSelectFieldSchema, entryPickerFieldSchema, _fieldSchemaInternal, fieldSchema, slotSchema, typographyTokens, colorTokens, spacingTokens, radiusTokens, styleTokenSchema, behaviourSchema, blockCategoryEnum;
997
1001
  var init_schema2 = __esm({
998
1002
  "../blocks/src/system/manifest/schema.ts"() {
999
1003
  init_src2();
1000
1004
  init_node();
1001
1005
  init_repeaterGrid();
1002
1006
  visibilityLevels = ["admin", "designer", "author"];
1007
+ MEDIA_KINDS = [
1008
+ "image",
1009
+ "video",
1010
+ "audio",
1011
+ "document",
1012
+ "spreadsheet",
1013
+ "archive"
1014
+ ];
1015
+ DISPLAY_MEDIA_KINDS = [
1016
+ "image",
1017
+ "video",
1018
+ "audio"
1019
+ ];
1020
+ PUBLIC_FILE_FIELD_KINDS = [
1021
+ "document",
1022
+ "spreadsheet",
1023
+ "archive",
1024
+ "audio"
1025
+ ];
1003
1026
  siteOptionSources = [
1004
1027
  "eventCategories",
1005
1028
  "venues",
@@ -1160,11 +1183,19 @@ var init_schema2 = __esm({
1160
1183
  });
1161
1184
  mediaFieldSchema = baseFieldSchema.extend({
1162
1185
  type: z.literal("media"),
1163
- mediaKinds: z.array(
1164
- z.enum(["image", "video", "audio", "document", "spreadsheet", "archive"])
1165
- ).default(["image"]),
1186
+ // Keep full MEDIA_KINDS parse compatibility for pre-file-field manifests.
1187
+ // New authoring surfaces should use `file.fileKinds` for document/archive
1188
+ // style assets, but old saved schemas must not fail to open.
1189
+ mediaKinds: z.array(z.enum(MEDIA_KINDS)).default(["image"]).transform((kinds) => {
1190
+ const displayKinds = kinds.filter(isDisplayMediaKind);
1191
+ return displayKinds.length > 0 ? displayKinds : ["image"];
1192
+ }),
1166
1193
  aspectRatio: z.string().optional()
1167
1194
  });
1195
+ fileFieldSchema = baseFieldSchema.extend({
1196
+ type: z.literal("file"),
1197
+ fileKinds: z.array(z.enum(PUBLIC_FILE_FIELD_KINDS)).default([...PUBLIC_FILE_FIELD_KINDS])
1198
+ });
1168
1199
  booleanFieldSchema = baseFieldSchema.extend({
1169
1200
  type: z.literal("boolean")
1170
1201
  });
@@ -9269,13 +9300,19 @@ function defineFragment(config2) {
9269
9300
  function scopeFragmentFields(fragment, scope) {
9270
9301
  const normalizedScope = scope.trim();
9271
9302
  if (!normalizedScope) {
9272
- return fragment.fields.map((field) => cloneFieldDefinition2(field));
9303
+ return fragment.fields.map(
9304
+ (field) => cloneFieldDefinition2(field)
9305
+ );
9273
9306
  }
9274
- return fragment.fields.map((field) => prefixFieldId(field, normalizedScope));
9307
+ return fragment.fields.map(
9308
+ (field) => prefixFieldId(field, normalizedScope)
9309
+ );
9275
9310
  }
9276
9311
  function scopeFragmentLayout(fragment, scope) {
9277
9312
  const normalizedScope = scope.trim();
9278
- return fragment.layout.map((node) => cloneAndScopeNode(node, normalizedScope));
9313
+ return fragment.layout.map(
9314
+ (node) => cloneAndScopeNode(node, normalizedScope)
9315
+ );
9279
9316
  }
9280
9317
  function validateFieldDefinitions(fields3, fragmentId) {
9281
9318
  const seen = /* @__PURE__ */ new Set();
@@ -9357,7 +9394,9 @@ function cloneAndScopeNode(node, scope) {
9357
9394
  ...node
9358
9395
  };
9359
9396
  if (node.children) {
9360
- cloned.children = node.children.map((child) => cloneAndScopeNode(child, scope));
9397
+ cloned.children = node.children.map(
9398
+ (child) => cloneAndScopeNode(child, scope)
9399
+ );
9361
9400
  }
9362
9401
  if (node.props) {
9363
9402
  cloned.props = scopePropBindings(node.props, scope);
@@ -9383,7 +9422,9 @@ function scopeBinding(binding, scope) {
9383
9422
  const cloned = {
9384
9423
  ...binding,
9385
9424
  transforms: binding.transforms?.map(
9386
- (step) => ({ ...step })
9425
+ (step) => ({
9426
+ ...step
9427
+ })
9387
9428
  ) ?? []
9388
9429
  };
9389
9430
  cloned.from = scopeContentPath(binding.from, scope);
@@ -9427,7 +9468,9 @@ function scopePropValue(value, scope) {
9427
9468
  };
9428
9469
  }
9429
9470
  const result = {};
9430
- for (const [key, entry] of Object.entries(value)) {
9471
+ for (const [key, entry] of Object.entries(
9472
+ value
9473
+ )) {
9431
9474
  result[key] = scopePropValue(entry, scope);
9432
9475
  }
9433
9476
  return result;
@@ -9473,13 +9516,18 @@ var init_types13 = __esm({
9473
9516
  loader: dataLoaderSchema.optional()
9474
9517
  });
9475
9518
  fragmentConfigSchema = z.object({
9476
- id: z.string().min(1, "Fragment id is required").regex(FRAGMENT_ID_PATTERN, "Fragment id must be alphanumeric with optional . _ - separators"),
9519
+ id: z.string().min(1, "Fragment id is required").regex(
9520
+ FRAGMENT_ID_PATTERN,
9521
+ "Fragment id must be alphanumeric with optional . _ - separators"
9522
+ ),
9477
9523
  title: z.string().optional(),
9478
9524
  description: z.string().optional(),
9479
9525
  category: z.enum(["content", "media", "interactive", "layout"]).optional(),
9480
9526
  icon: z.string().optional(),
9481
9527
  fields: fieldSchema.array().default([]),
9482
- layout: z.union([NodeSchema, NodeSchema.array()]).transform((value) => Array.isArray(value) ? value : [value]),
9528
+ layout: z.union([NodeSchema, NodeSchema.array()]).transform(
9529
+ (value) => Array.isArray(value) ? value : [value]
9530
+ ),
9483
9531
  data: fragmentDataSchema.optional()
9484
9532
  });
9485
9533
  FragmentConfigError = class extends Error {
@@ -9949,34 +9997,35 @@ var init_ctaRow2 = __esm({
9949
9997
  });
9950
9998
 
9951
9999
  // ../blocks/src/system/fragments/library/heroCtaRow.ts
9952
- var heroCtaRowFragment;
10000
+ var heroCtaFields, heroCtaRowFragment;
9953
10001
  var init_heroCtaRow = __esm({
9954
10002
  "../blocks/src/system/fragments/library/heroCtaRow.ts"() {
9955
10003
  init_types13();
9956
10004
  init_fragments();
9957
10005
  init_ctas();
10006
+ heroCtaFields = [
10007
+ createCtasRepeater({
10008
+ label: "Calls to action",
10009
+ itemLabel: "CTA",
10010
+ maxItems: 3,
10011
+ button: {
10012
+ variants: [
10013
+ { value: "default", label: "Default" },
10014
+ { value: "primary", label: "Primary" },
10015
+ { value: "secondary", label: "Secondary" },
10016
+ { value: "outline", label: "Outline" }
10017
+ ],
10018
+ defaultVariant: "default",
10019
+ includeSize: true,
10020
+ defaultSize: "lg"
10021
+ }
10022
+ })
10023
+ ];
9958
10024
  heroCtaRowFragment = defineFragment({
9959
10025
  id: "heroCtaRow",
9960
10026
  title: "Hero CTAs",
9961
10027
  description: "Repeatable hero calls to action rendered inline.",
9962
- fields: [
9963
- createCtasRepeater({
9964
- label: "Calls to action",
9965
- itemLabel: "CTA",
9966
- maxItems: 3,
9967
- button: {
9968
- variants: [
9969
- { value: "default", label: "Default" },
9970
- { value: "primary", label: "Primary" },
9971
- { value: "secondary", label: "Secondary" },
9972
- { value: "outline", label: "Outline" }
9973
- ],
9974
- defaultVariant: "default",
9975
- includeSize: true,
9976
- defaultSize: "lg"
9977
- }
9978
- })
9979
- ],
10028
+ fields: heroCtaFields,
9980
10029
  layout: [
9981
10030
  ctaRow({
9982
10031
  collectionPath: "content.ctas",
@@ -12569,8 +12618,7 @@ var init_media2 = __esm({
12569
12618
  "document",
12570
12619
  "spreadsheet",
12571
12620
  "archive",
12572
- "audio",
12573
- "video"
12621
+ "audio"
12574
12622
  ];
12575
12623
  hotspotSchema2 = z41.object({
12576
12624
  x: z41.number().min(0).max(1),
@@ -24623,6 +24671,7 @@ function deriveFieldValidationPlan(field, path24 = [field.id]) {
24623
24671
  case "richText":
24624
24672
  return makePlan("richText", "object", field, path24, required, commonConstraints(required, { kind: "richTextDoc" }));
24625
24673
  case "media":
24674
+ case "file":
24626
24675
  return makePlan("media", "object", field, path24, required, commonConstraints(required, { kind: "mediaObject" }));
24627
24676
  case "link":
24628
24677
  return makePlan("link", "object", field, path24, required, commonConstraints(required, { kind: "linkObject" }));
@@ -29319,104 +29368,107 @@ init_fragments();
29319
29368
  init_boxStyles();
29320
29369
  init_defineBlock();
29321
29370
  init_shared3();
29322
- var eventSpotlightManifest = createBlockManifest({
29371
+ var eventSpotlightFields = [
29372
+ ...sectionHeaderFields("Upcoming Events"),
29373
+ {
29374
+ id: "maxEvents",
29375
+ type: "select",
29376
+ label: "Events to display",
29377
+ description: "Number of events to show",
29378
+ required: false,
29379
+ multiple: false,
29380
+ defaultValue: "3",
29381
+ options: [
29382
+ { value: "1", label: "1 event" },
29383
+ { value: "2", label: "2 events" },
29384
+ { value: "3", label: "3 events" },
29385
+ { value: "4", label: "4 events" },
29386
+ { value: "5", label: "5 events" },
29387
+ { value: "6", label: "6 events" }
29388
+ ],
29389
+ ui: { intent: "display" }
29390
+ },
29391
+ {
29392
+ id: "ctaLabel",
29393
+ type: "text",
29394
+ label: "Section button text",
29395
+ description: "Optional button shown below the spotlight cards",
29396
+ required: false,
29397
+ multiline: false,
29398
+ maxLength: 40,
29399
+ ui: { intent: "content" }
29400
+ },
29401
+ {
29402
+ id: "ctaUrl",
29403
+ type: "link",
29404
+ label: "Section button destination",
29405
+ required: false,
29406
+ ui: { intent: "display" }
29407
+ },
29408
+ layoutField,
29409
+ columnsField(["2", "3"]),
29410
+ ...cardStylingFields,
29411
+ ...eventDisplayFields,
29412
+ emptyStateField,
29413
+ sectionStylesField({
29414
+ id: "_sectionStyles",
29415
+ label: "Section styles"
29416
+ })
29417
+ ];
29418
+ var eventSpotlightLayout = [
29419
+ styledSection({
29420
+ children: sectionContainer([
29421
+ // Optional heading
29422
+ text(
29423
+ { as: "h2" },
29424
+ bind("content.heading"),
29425
+ when("content.heading")
29426
+ ),
29427
+ // Optional description
29428
+ richText(
29429
+ { className: "rb-prose rb-max-w-none" },
29430
+ bind("content.description"),
29431
+ when("content.description")
29432
+ ),
29433
+ // Event spotlight component
29434
+ el("event-spotlight", {
29435
+ events: { $bind: { from: "data.events" } },
29436
+ layout: { $bind: { from: "content.layout", fallback: "grid" } },
29437
+ columns: { $bind: { from: "content.columns", fallback: "3" } },
29438
+ cardVariant: { $bind: { from: "content.cardVariant", fallback: "default" } },
29439
+ buttonVariant: { $bind: { from: "content.buttonVariant", fallback: "primary" } },
29440
+ buttonText: { $bind: { from: "content.buttonText", fallback: "View event" } },
29441
+ ctaLabel: { $bind: { from: "content.ctaLabel" } },
29442
+ ctaUrl: { $bind: { from: "content.ctaUrl", transforms: [{ id: "links.resolve" }] } },
29443
+ showVenue: { $bind: { from: "content.showVenue" } },
29444
+ showMap: { $bind: { from: "content.showMap" } },
29445
+ showCapacity: { $bind: { from: "content.showCapacity" } },
29446
+ emptyMessage: { $bind: { from: "content.emptyMessage" } }
29447
+ })
29448
+ ], {
29449
+ gap: "lg"
29450
+ }),
29451
+ // sectionContainer (rb-container) already provides horizontal padding
29452
+ baseClass: "",
29453
+ spacing: "comfortable"
29454
+ })
29455
+ ];
29456
+ var eventSpotlightConfig = {
29323
29457
  id: "block.event-spotlight",
29324
29458
  version: "1.1.0",
29325
29459
  title: "Event Spotlight",
29326
29460
  titleSource: "heading",
29327
29461
  description: "Feature a few upcoming events on your homepage",
29328
29462
  skipSectionStyles: true,
29329
- additionalFields: [
29330
- ...sectionHeaderFields("Upcoming Events"),
29331
- {
29332
- id: "maxEvents",
29333
- type: "select",
29334
- label: "Events to display",
29335
- description: "Number of events to show",
29336
- required: false,
29337
- multiple: false,
29338
- defaultValue: "3",
29339
- options: [
29340
- { value: "1", label: "1 event" },
29341
- { value: "2", label: "2 events" },
29342
- { value: "3", label: "3 events" },
29343
- { value: "4", label: "4 events" },
29344
- { value: "5", label: "5 events" },
29345
- { value: "6", label: "6 events" }
29346
- ],
29347
- ui: { intent: "display" }
29348
- },
29349
- {
29350
- id: "ctaLabel",
29351
- type: "text",
29352
- label: "Section button text",
29353
- description: "Optional button shown below the spotlight cards",
29354
- required: false,
29355
- multiline: false,
29356
- maxLength: 40,
29357
- ui: { intent: "content" }
29358
- },
29359
- {
29360
- id: "ctaUrl",
29361
- type: "link",
29362
- label: "Section button destination",
29363
- required: false,
29364
- ui: { intent: "display" }
29365
- },
29366
- layoutField,
29367
- columnsField(["2", "3"]),
29368
- ...cardStylingFields,
29369
- ...eventDisplayFields,
29370
- emptyStateField,
29371
- sectionStylesField({
29372
- id: "_sectionStyles",
29373
- label: "Section styles"
29374
- })
29375
- ],
29463
+ additionalFields: eventSpotlightFields,
29376
29464
  styleTokens: { background: "surface", typography: "body", spacing: "md" },
29377
29465
  behaviours: { supportsThemeSwitching: true, inlineEditing: false, animation: false, paletteHidden: false },
29378
29466
  category: "content",
29379
29467
  tags: ["events", "featured", "homepage", "spotlight", "upcoming"],
29380
29468
  icon: "Star",
29381
- layout: [
29382
- styledSection({
29383
- children: sectionContainer([
29384
- // Optional heading
29385
- text(
29386
- { as: "h2" },
29387
- bind("content.heading"),
29388
- when("content.heading")
29389
- ),
29390
- // Optional description
29391
- richText(
29392
- { className: "rb-prose rb-max-w-none" },
29393
- bind("content.description"),
29394
- when("content.description")
29395
- ),
29396
- // Event spotlight component
29397
- el("event-spotlight", {
29398
- events: { $bind: { from: "data.events" } },
29399
- layout: { $bind: { from: "content.layout", fallback: "grid" } },
29400
- columns: { $bind: { from: "content.columns", fallback: "3" } },
29401
- cardVariant: { $bind: { from: "content.cardVariant", fallback: "default" } },
29402
- buttonVariant: { $bind: { from: "content.buttonVariant", fallback: "primary" } },
29403
- buttonText: { $bind: { from: "content.buttonText", fallback: "View event" } },
29404
- ctaLabel: { $bind: { from: "content.ctaLabel" } },
29405
- ctaUrl: { $bind: { from: "content.ctaUrl", transforms: [{ id: "links.resolve" }] } },
29406
- showVenue: { $bind: { from: "content.showVenue" } },
29407
- showMap: { $bind: { from: "content.showMap" } },
29408
- showCapacity: { $bind: { from: "content.showCapacity" } },
29409
- emptyMessage: { $bind: { from: "content.emptyMessage" } }
29410
- })
29411
- ], {
29412
- gap: "lg"
29413
- }),
29414
- // sectionContainer (rb-container) already provides horizontal padding
29415
- baseClass: "",
29416
- spacing: "comfortable"
29417
- })
29418
- ]
29419
- });
29469
+ layout: eventSpotlightLayout
29470
+ };
29471
+ var eventSpotlightManifest = createBlockManifest(eventSpotlightConfig);
29420
29472
  var eventSpotlightBlockDefinition = {
29421
29473
  manifest: eventSpotlightManifest,
29422
29474
  dataSchemas: {
@@ -30830,18 +30882,18 @@ var fileDownloadManifest = createBlockManifest({
30830
30882
  title: "File Download",
30831
30883
  titleSource: ["title", "file.filename"],
30832
30884
  category: "media",
30833
- description: "Add a simple public download link for a document, ZIP, audio, or video file.",
30885
+ description: "Add a simple public download link for a document, ZIP, or audio file.",
30834
30886
  tags: ["file", "download", "document", "zip", "media"],
30835
30887
  icon: "Download",
30836
30888
  includeContainerStyles: true,
30837
30889
  additionalFields: [
30838
30890
  {
30839
30891
  id: "file",
30840
- type: "media",
30892
+ type: "file",
30841
30893
  label: "Download file",
30842
30894
  description: "Choose the file visitors can download.",
30843
30895
  required: false,
30844
- mediaKinds: [...PUBLIC_DOWNLOAD_MEDIA_TYPES],
30896
+ fileKinds: [...PUBLIC_DOWNLOAD_MEDIA_TYPES],
30845
30897
  ui: { intent: "content" }
30846
30898
  },
30847
30899
  {
@@ -37701,6 +37753,7 @@ function createListCommand(config2) {
37701
37753
  }
37702
37754
 
37703
37755
  // src/cli/push-config.ts
37756
+ var DEFAULT_CONFIG_PATH = "./riverbank.config.ts";
37704
37757
  function isRecord5(value) {
37705
37758
  return typeof value === "object" && value !== null;
37706
37759
  }
@@ -37836,6 +37889,13 @@ async function pushConfigAction(output, options) {
37836
37889
  let siteIdForErrorContext;
37837
37890
  try {
37838
37891
  process.env.RIVERBANK_ENV = options.isRemote ? "remote" : "local";
37892
+ if (!isJsonOutput) {
37893
+ output.info("push-config target", {
37894
+ env: process.env.RIVERBANK_ENV,
37895
+ dashboardUrl: options.dashboard,
37896
+ configPath: options.config ?? DEFAULT_CONFIG_PATH
37897
+ });
37898
+ }
37839
37899
  const rawConfig = await loadConfigFile(options.config);
37840
37900
  if (!isJsonOutput) output.info("Validating config...");
37841
37901
  const parseResult = riverbankSiteConfigSchema.safeParse(rawConfig);
@@ -37948,7 +38008,7 @@ function resolveManagementApiKey(output, cliOption, isRemote) {
37948
38008
  }
37949
38009
  return apiKey;
37950
38010
  }
37951
- var pushConfigCommand = new Command("push-config").description("Push SDK config to dashboard").option("--api-key <key>", "Management API key (or set RIVERBANK_*_MGMT_API_KEY)").option("--dashboard <url>", "Dashboard URL (or set RIVERBANK_*_DASHBOARD_URL env var)").option("--config <path>", "Path to config file (default: ./riverbank.config.ts)").option(
38011
+ var pushConfigCommand = new Command("push-config").description("Push SDK config to dashboard").option("--api-key <key>", "Management API key (or set RIVERBANK_*_MGMT_API_KEY)").option("--dashboard <url>", "Dashboard URL (or set RIVERBANK_*_DASHBOARD_URL env var)").option("--config <path>", `Path to config file (default: ${DEFAULT_CONFIG_PATH})`).option(
37952
38012
  "--force-content-types",
37953
38013
  "Force overwrite content type schema even if modified in dashboard after last SDK sync"
37954
38014
  ).addHelpText("after", `
@@ -37966,6 +38026,7 @@ Description:
37966
38026
 
37967
38027
  Examples:
37968
38028
  $ npx riverbankcms push-config
38029
+ $ npx riverbankcms push-config --env=remote
37969
38030
  $ npx riverbankcms push-config --api-key bld_mgmt_sk_... --dashboard https://www.riverbankcms.com
37970
38031
  $ npx riverbankcms push-config --config ./src/riverbank.config.ts
37971
38032
  `).action(async (options, command) => {
@@ -54444,7 +54505,8 @@ async function initDocs(options) {
54444
54505
  { filename: "content-types.md", template: "workflow-content-types" },
54445
54506
  { filename: "templates.md", template: "workflow-templates" },
54446
54507
  { filename: "cmsify-page.md", template: "workflow-cmsify-page" },
54447
- { filename: "editor-workflows.md", template: "workflow-editor-workflows" }
54508
+ { filename: "editor-workflows.md", template: "workflow-editor-workflows" },
54509
+ { filename: "preview-mode.md", template: "workflow-preview-mode" }
54448
54510
  ];
54449
54511
  await Promise.all(
54450
54512
  coreWorkflows.map(
@@ -54774,7 +54836,7 @@ var SimpleCache = class {
54774
54836
  };
54775
54837
 
54776
54838
  // src/version.ts
54777
- var SDK_VERSION = "0.70.3";
54839
+ var SDK_VERSION = "0.70.4";
54778
54840
 
54779
54841
  // src/client/error.ts
54780
54842
  var RiverbankApiError = class _RiverbankApiError extends Error {
@@ -57827,7 +57889,14 @@ function collectLayoutClassNames(node, out = /* @__PURE__ */ new Set()) {
57827
57889
  }
57828
57890
 
57829
57891
  // src/manifest/validation/output-schema.ts
57830
- var blockCategoryEnum2 = z.enum(["marketing", "content", "blog", "media", "layout", "interactive"]);
57892
+ var blockCategoryEnum2 = z.enum([
57893
+ "marketing",
57894
+ "content",
57895
+ "blog",
57896
+ "media",
57897
+ "layout",
57898
+ "interactive"
57899
+ ]);
57831
57900
  var llmColorValue = z.object({
57832
57901
  name: z.string(),
57833
57902
  hex: z.string()
@@ -57845,8 +57914,16 @@ var llmThemePatchValue = z.union([
57845
57914
  z.array(llmThemePrimitive)
57846
57915
  ]);
57847
57916
  var llmThemePatchOpSchema = z.discriminatedUnion("op", [
57848
- z.object({ op: z.literal("add"), path: z.string().min(1), value: llmThemePatchValue }),
57849
- z.object({ op: z.literal("replace"), path: z.string().min(1), value: llmThemePatchValue }),
57917
+ z.object({
57918
+ op: z.literal("add"),
57919
+ path: z.string().min(1),
57920
+ value: llmThemePatchValue
57921
+ }),
57922
+ z.object({
57923
+ op: z.literal("replace"),
57924
+ path: z.string().min(1),
57925
+ value: llmThemePatchValue
57926
+ }),
57850
57927
  z.object({ op: z.literal("remove"), path: z.string().min(1) })
57851
57928
  ]);
57852
57929
  var llmCssDeclaration = z.object({
@@ -57923,7 +58000,11 @@ var llmRichTextFieldSchema = llmBaseFieldSchema.extend({
57923
58000
  });
57924
58001
  var llmMediaFieldSchema = llmBaseFieldSchema.extend({
57925
58002
  type: z.literal("media"),
57926
- mediaKinds: z.array(z.enum(["image", "video", "audio", "document", "spreadsheet", "archive"])).nullable()
58003
+ mediaKinds: z.array(z.enum(["image", "video", "audio"])).nullable()
58004
+ });
58005
+ var llmFileFieldSchema = llmBaseFieldSchema.extend({
58006
+ type: z.literal("file"),
58007
+ fileKinds: z.array(z.enum(["document", "spreadsheet", "archive", "audio"])).nullable()
57927
58008
  });
57928
58009
  var llmBooleanFieldSchema = llmBaseFieldSchema.extend({
57929
58010
  type: z.literal("boolean")
@@ -57933,10 +58014,12 @@ var llmLinkFieldSchema = llmBaseFieldSchema.extend({
57933
58014
  });
57934
58015
  var llmSelectFieldSchema = llmBaseFieldSchema.extend({
57935
58016
  type: z.literal("select"),
57936
- options: z.array(z.object({
57937
- value: z.string(),
57938
- label: z.string()
57939
- })),
58017
+ options: z.array(
58018
+ z.object({
58019
+ value: z.string(),
58020
+ label: z.string()
58021
+ })
58022
+ ),
57940
58023
  multiple: z.boolean().nullable()
57941
58024
  });
57942
58025
  var llmNumberFieldSchema = llmBaseFieldSchema.extend({
@@ -57972,6 +58055,7 @@ var llmFieldSchema = z.union([
57972
58055
  llmTextFieldSchema,
57973
58056
  llmRichTextFieldSchema,
57974
58057
  llmMediaFieldSchema,
58058
+ llmFileFieldSchema,
57975
58059
  llmBooleanFieldSchema,
57976
58060
  llmLinkFieldSchema,
57977
58061
  llmSelectFieldSchema,
@@ -57982,9 +58066,11 @@ var llmFieldSchema = z.union([
57982
58066
  var llmBindingSchema = z.object({
57983
58067
  from: z.string(),
57984
58068
  fallback: z.string().nullable(),
57985
- transforms: z.array(z.object({
57986
- id: z.string()
57987
- })).nullable()
58069
+ transforms: z.array(
58070
+ z.object({
58071
+ id: z.string()
58072
+ })
58073
+ ).nullable()
57988
58074
  });
57989
58075
  var llmRepeatSchema = z.object({
57990
58076
  collection: z.object({ from: z.string() }),
@@ -58043,11 +58129,17 @@ function collectValidationErrors(output) {
58043
58129
  const blockIds = output.blocks.map((b) => b.id);
58044
58130
  const singleBlockId = blockIds.length === 1 ? blockIds[0] ?? null : null;
58045
58131
  for (const block of output.blocks) {
58046
- const layoutErrors = validateLayoutDeep(block.layout, block.id, block.fields);
58132
+ const layoutErrors = validateLayoutDeep(
58133
+ block.layout,
58134
+ block.id,
58135
+ block.fields
58136
+ );
58047
58137
  errors.push(...layoutErrors);
58048
58138
  const fieldInfo = collectFieldInfo(block.fields);
58049
58139
  const used = collectUsedFieldRefs(block.layout);
58050
- const unusedTopLevelFields = Array.from(fieldInfo.topLevelFieldIds).filter((id) => !used.topLevel.has(id));
58140
+ const unusedTopLevelFields = Array.from(fieldInfo.topLevelFieldIds).filter(
58141
+ (id) => !used.topLevel.has(id)
58142
+ );
58051
58143
  if (unusedTopLevelFields.length > 0) {
58052
58144
  errors.push({
58053
58145
  path: `blocks["${block.id}"].fields`,
@@ -58055,10 +58147,15 @@ function collectValidationErrors(output) {
58055
58147
  suggestion: `Every field should be bound to a layout node. Add $bind: { from: "content.${unusedTopLevelFields[0]}" } to an appropriate node, or remove unused fields.`
58056
58148
  });
58057
58149
  }
58058
- for (const [repeaterFieldId, nestedFieldIds] of fieldInfo.repeaterNestedFieldIds.entries()) {
58150
+ for (const [
58151
+ repeaterFieldId,
58152
+ nestedFieldIds
58153
+ ] of fieldInfo.repeaterNestedFieldIds.entries()) {
58059
58154
  if (!used.topLevel.has(repeaterFieldId)) continue;
58060
58155
  const usedNested = used.nestedByRepeater.get(repeaterFieldId) ?? /* @__PURE__ */ new Set();
58061
- const missingNested = Array.from(nestedFieldIds).filter((id) => !usedNested.has(id));
58156
+ const missingNested = Array.from(nestedFieldIds).filter(
58157
+ (id) => !usedNested.has(id)
58158
+ );
58062
58159
  if (missingNested.length === 0) continue;
58063
58160
  const itemName = used.itemNameByRepeater.get(repeaterFieldId) ?? "item";
58064
58161
  errors.push({
@@ -58071,10 +58168,18 @@ function collectValidationErrors(output) {
58071
58168
  errors.push(...missingBindings);
58072
58169
  errors.push(...validateLinkFieldDefaultValues(block));
58073
58170
  errors.push(...findMissingLinkHrefs(block.layout, block.id, block.fields));
58074
- errors.push(...detectRedundantLinkLabels(block.layout, block.id, block.fields));
58171
+ errors.push(
58172
+ ...detectRedundantLinkLabels(block.layout, block.id, block.fields)
58173
+ );
58075
58174
  }
58076
58175
  if (output.customCssRules && output.customCssRules.length > 0) {
58077
- errors.push(...validateCustomCssRules(output.customCssRules, singleBlockId, output.blocks));
58176
+ errors.push(
58177
+ ...validateCustomCssRules(
58178
+ output.customCssRules,
58179
+ singleBlockId,
58180
+ output.blocks
58181
+ )
58182
+ );
58078
58183
  }
58079
58184
  return errors;
58080
58185
  }
@@ -58150,7 +58255,9 @@ function resolveFieldTypeForFrom(allFields, from, repeatStack) {
58150
58255
  const segments = from.slice(prefix.length).split(".").filter(Boolean);
58151
58256
  const [nestedId, ...rest] = segments;
58152
58257
  if (!nestedId) return null;
58153
- let current = ctx.fields.find((f) => f.id === nestedId);
58258
+ let current = ctx.fields.find(
58259
+ (f) => f.id === nestedId
58260
+ );
58154
58261
  if (!current) return null;
58155
58262
  for (const seg of rest) {
58156
58263
  const nested = getNestedFields(current);
@@ -58166,7 +58273,9 @@ function bindingHasTransform(bind2, id) {
58166
58273
  if (!bind2) return false;
58167
58274
  const transforms = bind2.transforms;
58168
58275
  if (!Array.isArray(transforms)) return false;
58169
- return transforms.some((t) => t && typeof t === "object" && t.id === id);
58276
+ return transforms.some(
58277
+ (t) => t && typeof t === "object" && t.id === id
58278
+ );
58170
58279
  }
58171
58280
  function extractNestedHrefBindFromProps(props2) {
58172
58281
  if (!props2 || typeof props2 !== "object") return null;
@@ -58227,7 +58336,15 @@ function findMissingLinkHrefs(node, blockId, fields3, path24 = "layout", repeatS
58227
58336
  }
58228
58337
  if ("children" in n && Array.isArray(n.children)) {
58229
58338
  for (let i = 0; i < n.children.length; i++) {
58230
- errors.push(...findMissingLinkHrefs(n.children[i], blockId, fields3, `${path24}.children[${i}]`, nextRepeatStack));
58339
+ errors.push(
58340
+ ...findMissingLinkHrefs(
58341
+ n.children[i],
58342
+ blockId,
58343
+ fields3,
58344
+ `${path24}.children[${i}]`,
58345
+ nextRepeatStack
58346
+ )
58347
+ );
58231
58348
  }
58232
58349
  }
58233
58350
  return errors;
@@ -58251,22 +58368,30 @@ function detectRedundantLinkLabels(node, blockId, fields3, path24 = "layout", re
58251
58368
  }
58252
58369
  if (Array.isArray(n.children) && n.children.length > 1) {
58253
58370
  const children = n.children;
58254
- const redundancies = findRedundantLinkTextSiblings(children, nextRepeatStack, path24);
58255
- errors.push(...redundancies.map((r) => ({
58256
- path: r.path,
58257
- message: `Block "${blockId}": ${r.message}`,
58258
- suggestion: r.suggestion
58259
- })));
58371
+ const redundancies = findRedundantLinkTextSiblings(
58372
+ children,
58373
+ nextRepeatStack,
58374
+ path24
58375
+ );
58376
+ errors.push(
58377
+ ...redundancies.map((r) => ({
58378
+ path: r.path,
58379
+ message: `Block "${blockId}": ${r.message}`,
58380
+ suggestion: r.suggestion
58381
+ }))
58382
+ );
58260
58383
  }
58261
58384
  if (Array.isArray(n.children)) {
58262
58385
  for (let i = 0; i < n.children.length; i++) {
58263
- errors.push(...detectRedundantLinkLabels(
58264
- n.children[i],
58265
- blockId,
58266
- fields3,
58267
- `${path24}.children[${i}]`,
58268
- nextRepeatStack
58269
- ));
58386
+ errors.push(
58387
+ ...detectRedundantLinkLabels(
58388
+ n.children[i],
58389
+ blockId,
58390
+ fields3,
58391
+ `${path24}.children[${i}]`,
58392
+ nextRepeatStack
58393
+ )
58394
+ );
58270
58395
  }
58271
58396
  }
58272
58397
  return errors;
@@ -58320,7 +58445,8 @@ function checkRedundantLabelBinding(linkBindFrom, textBindFrom, repeatStack) {
58320
58445
  const ctx = repeatStack[i];
58321
58446
  if (!ctx) continue;
58322
58447
  const prefix = `${ctx.itemName}.`;
58323
- if (!linkBindFrom.startsWith(prefix) || !textBindFrom.startsWith(prefix)) continue;
58448
+ if (!linkBindFrom.startsWith(prefix) || !textBindFrom.startsWith(prefix))
58449
+ continue;
58324
58450
  const linkFieldId = linkBindFrom.slice(prefix.length).split(".")[0] ?? "";
58325
58451
  const textFieldId = textBindFrom.slice(prefix.length).split(".")[0] ?? "";
58326
58452
  const linkField = ctx.fields.find((f) => f.id === linkFieldId);
@@ -58345,7 +58471,10 @@ function validateCustomCssRules(rules, singleBlockId, blocks) {
58345
58471
  const layoutClassNamesByBlockId = /* @__PURE__ */ new Map();
58346
58472
  const layoutNodeInfosByBlockId = /* @__PURE__ */ new Map();
58347
58473
  for (const block of blocks) {
58348
- layoutClassNamesByBlockId.set(block.id, collectLayoutClassNames(block.layout));
58474
+ layoutClassNamesByBlockId.set(
58475
+ block.id,
58476
+ collectLayoutClassNames(block.layout)
58477
+ );
58349
58478
  layoutNodeInfosByBlockId.set(block.id, collectLayoutNodeInfos(block.layout));
58350
58479
  }
58351
58480
  const missingLayoutHooksByBlockId = /* @__PURE__ */ new Map();
@@ -58414,11 +58543,18 @@ function validateCustomCssRules(rules, singleBlockId, blocks) {
58414
58543
  }
58415
58544
  }
58416
58545
  }
58417
- for (const [blockId, missingClassNames] of missingLayoutHooksByBlockId.entries()) {
58546
+ for (const [
58547
+ blockId,
58548
+ missingClassNames
58549
+ ] of missingLayoutHooksByBlockId.entries()) {
58418
58550
  const missing = Array.from(missingClassNames).sort();
58419
58551
  if (missing.length === 0) continue;
58420
58552
  const layoutNodeInfos = layoutNodeInfosByBlockId.get(blockId) ?? [];
58421
- const attachSuggestions = buildClassHookAttachSuggestions(blockId, missing, layoutNodeInfos);
58553
+ const attachSuggestions = buildClassHookAttachSuggestions(
58554
+ blockId,
58555
+ missing,
58556
+ layoutNodeInfos
58557
+ );
58422
58558
  const attachSuggestionsLine = attachSuggestions ? `
58423
58559
 
58424
58560
  Suggested attachments:
@@ -58452,7 +58588,9 @@ function buildClassHookAttachSuggestions(blockId, missingClassNames, nodes) {
58452
58588
  continue;
58453
58589
  }
58454
58590
  if ((lower.includes("headline") || lower.includes("title")) && (headlineNode ?? firstStack)) {
58455
- lines.push(`- ${className} \u2192 add to ${headlineNode ?? firstStack}.props.className`);
58591
+ lines.push(
58592
+ `- ${className} \u2192 add to ${headlineNode ?? firstStack}.props.className`
58593
+ );
58456
58594
  continue;
58457
58595
  }
58458
58596
  if (lower.includes("highlight") && highlightNode) {
@@ -58460,7 +58598,9 @@ function buildClassHookAttachSuggestions(blockId, missingClassNames, nodes) {
58460
58598
  continue;
58461
58599
  }
58462
58600
  if ((lower.includes("body") || lower.includes("copy") || lower.includes("paragraph")) && (paragraphNode ?? firstStack)) {
58463
- lines.push(`- ${className} \u2192 add to ${paragraphNode ?? firstStack}.props.className`);
58601
+ lines.push(
58602
+ `- ${className} \u2192 add to ${paragraphNode ?? firstStack}.props.className`
58603
+ );
58464
58604
  continue;
58465
58605
  }
58466
58606
  lines.push(`- ${className} \u2192 add to ${rootPath}.props.className (fallback)`);
@@ -58468,7 +58608,10 @@ function buildClassHookAttachSuggestions(blockId, missingClassNames, nodes) {
58468
58608
  return lines.slice(0, 8).join("\n");
58469
58609
  }
58470
58610
  function extractSelectorClasses(selector) {
58471
- const withoutDataBlockAttrs = selector.replace(/\[data-block=(["']).*?\1\]/g, "");
58611
+ const withoutDataBlockAttrs = selector.replace(
58612
+ /\[data-block=(["']).*?\1\]/g,
58613
+ ""
58614
+ );
58472
58615
  const classes = /* @__PURE__ */ new Set();
58473
58616
  const re = /\.([_a-zA-Z][-_a-zA-Z0-9]*)/g;
58474
58617
  let match;
@@ -58485,7 +58628,9 @@ function extractBlockIdFromSelector(selector) {
58485
58628
  return match?.[2] ?? null;
58486
58629
  }
58487
58630
  function validateNodeType(nodeType, path24, ctx) {
58488
- if (!ALLOWED_NODE_TYPES.includes(nodeType)) {
58631
+ if (!ALLOWED_NODE_TYPES.includes(
58632
+ nodeType
58633
+ )) {
58489
58634
  return {
58490
58635
  path: `${path24}.type`,
58491
58636
  message: `Block "${ctx.blockId}": Unknown node type "${nodeType}" at ${path24}`,
@@ -58499,7 +58644,9 @@ function validateTransforms(transforms, path24, ctx) {
58499
58644
  for (let i = 0; i < transforms.length; i++) {
58500
58645
  const transform = transforms[i];
58501
58646
  if (transform.id && typeof transform.id === "string") {
58502
- if (!ALLOWED_TRANSFORM_IDS.includes(transform.id)) {
58647
+ if (!ALLOWED_TRANSFORM_IDS.includes(
58648
+ transform.id
58649
+ )) {
58503
58650
  errors.push({
58504
58651
  path: `${path24}.transforms[${i}].id`,
58505
58652
  message: `Block "${ctx.blockId}": Unknown transform "${transform.id}"`,
@@ -58548,16 +58695,28 @@ function validateLayoutNode(node, path24, ctx) {
58548
58695
  if (typeError) errors.push(typeError);
58549
58696
  }
58550
58697
  if ("$bind" in n && n.$bind && typeof n.$bind === "object") {
58551
- const bindErrors = validateBinding(n.$bind, `${path24}.$bind`, ctx);
58698
+ const bindErrors = validateBinding(
58699
+ n.$bind,
58700
+ `${path24}.$bind`,
58701
+ ctx
58702
+ );
58552
58703
  errors.push(...bindErrors);
58553
58704
  }
58554
58705
  if ("props" in n && n.props && typeof n.props === "object") {
58555
- const propsErrors = validatePropsBindings(n.props, `${path24}.props`, ctx);
58706
+ const propsErrors = validatePropsBindings(
58707
+ n.props,
58708
+ `${path24}.props`,
58709
+ ctx
58710
+ );
58556
58711
  errors.push(...propsErrors);
58557
58712
  }
58558
58713
  if ("children" in n && Array.isArray(n.children)) {
58559
58714
  for (let i = 0; i < n.children.length; i++) {
58560
- const childErrors = validateLayoutNode(n.children[i], `${path24}.children[${i}]`, ctx);
58715
+ const childErrors = validateLayoutNode(
58716
+ n.children[i],
58717
+ `${path24}.children[${i}]`,
58718
+ ctx
58719
+ );
58561
58720
  errors.push(...childErrors);
58562
58721
  }
58563
58722
  }
@@ -58571,7 +58730,11 @@ function validatePropsBindings(props2, path24, ctx) {
58571
58730
  const bindErrors = validateBinding(bind2, `${path24}.${key}.$bind`, ctx);
58572
58731
  errors.push(...bindErrors);
58573
58732
  } else if (value && typeof value === "object" && !Array.isArray(value)) {
58574
- const nestedErrors = validatePropsBindings(value, `${path24}.${key}`, ctx);
58733
+ const nestedErrors = validatePropsBindings(
58734
+ value,
58735
+ `${path24}.${key}`,
58736
+ ctx
58737
+ );
58575
58738
  errors.push(...nestedErrors);
58576
58739
  }
58577
58740
  }
@@ -58612,7 +58775,10 @@ function collectFieldInfo(fields3) {
58612
58775
  topLevelFieldIds.add(field.id);
58613
58776
  if (field.type === "repeater" && field.schema && typeof field.schema === "object" && "fields" in field.schema) {
58614
58777
  const nestedFields = field.schema.fields ?? [];
58615
- repeaterNestedFieldIds.set(field.id, new Set(nestedFields.map((f) => f.id)));
58778
+ repeaterNestedFieldIds.set(
58779
+ field.id,
58780
+ new Set(nestedFields.map((f) => f.id))
58781
+ );
58616
58782
  }
58617
58783
  }
58618
58784
  return { topLevelFieldIds, repeaterNestedFieldIds };
@@ -58732,7 +58898,11 @@ function findMissingBindings(node, blockId, path24 = "layout") {
58732
58898
  }
58733
58899
  if ("children" in n && Array.isArray(n.children)) {
58734
58900
  for (let i = 0; i < n.children.length; i++) {
58735
- const childErrors = findMissingBindings(n.children[i], blockId, `${path24}.children[${i}]`);
58901
+ const childErrors = findMissingBindings(
58902
+ n.children[i],
58903
+ blockId,
58904
+ `${path24}.children[${i}]`
58905
+ );
58736
58906
  errors.push(...childErrors);
58737
58907
  }
58738
58908
  }
@@ -58743,7 +58913,9 @@ function getMaxDepth(node, currentDepth = 0) {
58743
58913
  const n = node;
58744
58914
  if (!n.children || !Array.isArray(n.children)) return currentDepth;
58745
58915
  if (n.children.length === 0) return currentDepth;
58746
- return Math.max(...n.children.map((child) => getMaxDepth(child, currentDepth + 1)));
58916
+ return Math.max(
58917
+ ...n.children.map((child) => getMaxDepth(child, currentDepth + 1))
58918
+ );
58747
58919
  }
58748
58920
  var CONTAINER_NODE_TYPES = ["section", "stack", "grid", "div", "inline"];
58749
58921
  function detectPotentialTruncation(node, maxAllowedDepth, currentDepth = 0, path24 = "layout") {
@@ -58758,7 +58930,12 @@ function detectPotentialTruncation(node, maxAllowedDepth, currentDepth = 0, path
58758
58930
  if (n.children && Array.isArray(n.children)) {
58759
58931
  n.children.forEach((child, i) => {
58760
58932
  truncatedPaths.push(
58761
- ...detectPotentialTruncation(child, maxAllowedDepth, currentDepth + 1, `${path24}.children[${i}]`)
58933
+ ...detectPotentialTruncation(
58934
+ child,
58935
+ maxAllowedDepth,
58936
+ currentDepth + 1,
58937
+ `${path24}.children[${i}]`
58938
+ )
58762
58939
  );
58763
58940
  });
58764
58941
  }
@@ -58773,14 +58950,20 @@ function formatValidationFeedback(errors, output) {
58773
58950
  if (truncatedPaths.length > 0) {
58774
58951
  lines.push("### DEPTH LIMIT WARNING");
58775
58952
  lines.push("");
58776
- lines.push(`The layout reached the maximum depth of ${MAX_LAYOUT_DEPTH} levels.`);
58953
+ lines.push(
58954
+ `The layout reached the maximum depth of ${MAX_LAYOUT_DEPTH} levels.`
58955
+ );
58777
58956
  lines.push("These container nodes at the depth limit have no children:");
58778
58957
  for (const path24 of truncatedPaths) {
58779
58958
  lines.push(` \u26A0\uFE0F ${path24}`);
58780
58959
  }
58781
58960
  lines.push("");
58782
- lines.push("**FIX**: Flatten your layout structure or use $repeat for lists.");
58783
- lines.push("- Combine wrapper nodes where possible (e.g., section > stack > div \u2192 section > stack)");
58961
+ lines.push(
58962
+ "**FIX**: Flatten your layout structure or use $repeat for lists."
58963
+ );
58964
+ lines.push(
58965
+ "- Combine wrapper nodes where possible (e.g., section > stack > div \u2192 section > stack)"
58966
+ );
58784
58967
  lines.push("- Use $repeat instead of manual nesting for repeated items");
58785
58968
  lines.push(`- Current max depth: ${maxDepth}, limit: ${MAX_LAYOUT_DEPTH}`);
58786
58969
  lines.push("");
@@ -58789,13 +58972,19 @@ function formatValidationFeedback(errors, output) {
58789
58972
  if (errors.length === 0) {
58790
58973
  return lines.length > 0 ? lines.join("\n") : "";
58791
58974
  }
58792
- lines.push("## CRITICAL: Your output failed validation. You MUST fix these errors.");
58975
+ lines.push(
58976
+ "## CRITICAL: Your output failed validation. You MUST fix these errors."
58977
+ );
58793
58978
  lines.push("");
58794
58979
  lines.push("Your previous output had the following problems:");
58795
58980
  lines.push("");
58796
58981
  const missingBindErrors = errors.filter((e) => e.message.includes("no $bind"));
58797
- const unusedFieldErrors = errors.filter((e) => e.message.includes("never used"));
58798
- const otherErrors = errors.filter((e) => !e.message.includes("no $bind") && !e.message.includes("never used"));
58982
+ const unusedFieldErrors = errors.filter(
58983
+ (e) => e.message.includes("never used")
58984
+ );
58985
+ const otherErrors = errors.filter(
58986
+ (e) => !e.message.includes("no $bind") && !e.message.includes("never used")
58987
+ );
58799
58988
  if (missingBindErrors.length > 0) {
58800
58989
  lines.push("### MISSING $bind ERRORS (nodes that display nothing)");
58801
58990
  lines.push("");
@@ -58803,16 +58992,22 @@ function formatValidationFeedback(errors, output) {
58803
58992
  lines.push(`\u274C ${error.message}`);
58804
58993
  }
58805
58994
  lines.push("");
58806
- lines.push("**FIX**: Every text, richText, media, button, and link node MUST have $bind.");
58995
+ lines.push(
58996
+ "**FIX**: Every text, richText, media, button, and link node MUST have $bind."
58997
+ );
58807
58998
  lines.push("");
58808
58999
  lines.push("WRONG (displays nothing):");
58809
59000
  lines.push("```json");
58810
- lines.push('{ "type": "text", "props": { "as": "h1" }, "children": null, "$bind": null }');
59001
+ lines.push(
59002
+ '{ "type": "text", "props": { "as": "h1" }, "children": null, "$bind": null }'
59003
+ );
58811
59004
  lines.push("```");
58812
59005
  lines.push("");
58813
59006
  lines.push("CORRECT (bound to field):");
58814
59007
  lines.push("```json");
58815
- lines.push('{ "type": "text", "props": { "as": "h1" }, "children": null, "$bind": { "from": "content.headline", "fallback": null, "transforms": null } }');
59008
+ lines.push(
59009
+ '{ "type": "text", "props": { "as": "h1" }, "children": null, "$bind": { "from": "content.headline", "fallback": null, "transforms": null } }'
59010
+ );
58816
59011
  lines.push("```");
58817
59012
  lines.push("");
58818
59013
  }
@@ -58831,11 +59026,15 @@ function formatValidationFeedback(errors, output) {
58831
59026
  if (fieldNames.length > 0) {
58832
59027
  lines.push("**CHECKLIST - Add a binding for EACH of these fields:**");
58833
59028
  for (const field of fieldNames) {
58834
- lines.push(`- [ ] ${field} \u2192 text node with $bind: { from: "content.${field}" }`);
59029
+ lines.push(
59030
+ `- [ ] ${field} \u2192 text node with $bind: { from: "content.${field}" }`
59031
+ );
58835
59032
  }
58836
59033
  lines.push("");
58837
59034
  }
58838
- lines.push("**COMMON MISTAKE**: Creating container nodes with `children: null` instead of actual bindings.");
59035
+ lines.push(
59036
+ "**COMMON MISTAKE**: Creating container nodes with `children: null` instead of actual bindings."
59037
+ );
58839
59038
  lines.push("");
58840
59039
  lines.push("This is WRONG (container with no content inside):");
58841
59040
  lines.push("```json");
@@ -58845,12 +59044,18 @@ function formatValidationFeedback(errors, output) {
58845
59044
  lines.push("This is CORRECT (container with bound text node):");
58846
59045
  lines.push("```json");
58847
59046
  lines.push('{ "type": "inline", "children": [');
58848
- lines.push(' { "type": "text", "$bind": { "from": "content.fieldName", "fallback": null, "transforms": null }, "props": null, "$repeat": null, "$when": null, "children": null }');
59047
+ lines.push(
59048
+ ' { "type": "text", "$bind": { "from": "content.fieldName", "fallback": null, "transforms": null }, "props": null, "$repeat": null, "$when": null, "children": null }'
59049
+ );
58849
59050
  lines.push("] }");
58850
59051
  lines.push("```");
58851
59052
  lines.push("");
58852
- lines.push("**FIX**: Every field you define MUST be used in a $bind somewhere in the layout.");
58853
- lines.push('If you have a field "highlight", you MUST have a node with $bind: { from: "content.highlight" }');
59053
+ lines.push(
59054
+ "**FIX**: Every field you define MUST be used in a $bind somewhere in the layout."
59055
+ );
59056
+ lines.push(
59057
+ 'If you have a field "highlight", you MUST have a node with $bind: { from: "content.highlight" }'
59058
+ );
58854
59059
  lines.push("");
58855
59060
  }
58856
59061
  if (otherErrors.length > 0) {