@riverbankcms/sdk 0.78.0 → 0.78.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/README.md +45 -43
  2. package/dist/{PreviewEditorSidebar-RIKFQ72L.mjs → PreviewEditorSidebar-4DXLYX2V.mjs} +29 -21
  3. package/dist/{PreviewEditorUI-XO7TUWKK.mjs → PreviewEditorUI-CS5P4N3P.mjs} +4 -4
  4. package/dist/SdkPreviewModeRuntime-IJDHTW4W.mjs +8 -0
  5. package/dist/_dts/ai/src/contracts/proposals.d.ts +36 -0
  6. package/dist/_dts/api/src/contentRuntime.d.ts +1 -0
  7. package/dist/_dts/api/src/endpoints.d.ts +9 -0
  8. package/dist/_dts/api/src/index.d.ts +3 -3
  9. package/dist/_dts/api/src/public/types.d.ts +1 -1
  10. package/dist/_dts/api/src/request.d.ts +3 -11
  11. package/dist/_dts/api/src/sdkConfig/contracts.d.ts +1 -0
  12. package/dist/_dts/api/src/sdkContracts.d.ts +7 -1
  13. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +10 -0
  14. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +1 -0
  15. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +15 -19
  16. package/dist/_dts/api/src/types.d.ts +11 -26
  17. package/dist/_dts/block-form/src/fields/types.d.ts +6 -0
  18. package/dist/_dts/block-form/src/widgets/RepeaterField/components/RepeaterList.d.ts +3 -2
  19. package/dist/_dts/block-form/src/widgets/RepeaterField/components/RepeaterRow.d.ts +6 -3
  20. package/dist/_dts/block-form/src/widgets/RepeaterField/components/RepeaterRowActions.d.ts +8 -3
  21. package/dist/_dts/block-form/src/widgets/RepeaterField/hooks/index.d.ts +1 -1
  22. package/dist/_dts/block-form/src/widgets/RepeaterField/hooks/useLinearRepeaterDnd.d.ts +1 -0
  23. package/dist/_dts/block-form/src/widgets/RepeaterField/hooks/useRepeaterPointerDragCapability.d.ts +1 -0
  24. package/dist/_dts/block-form/src/widgets/RepeaterField/hooks/useResolvedItemLabel.d.ts +7 -0
  25. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/buildSummary.d.ts +1 -0
  26. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/index.d.ts +3 -1
  27. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/repeaterDndDomain.d.ts +1 -1
  28. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/repeaterLabelSource.d.ts +15 -0
  29. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/repeaterRowActionsDomain.d.ts +50 -0
  30. package/dist/_dts/blocks/src/system/blocks/appointment-booking.d.ts +591 -0
  31. package/dist/_dts/blocks/src/system/blocks/blog-listing.d.ts +591 -0
  32. package/dist/_dts/blocks/src/system/blocks/cart.d.ts +591 -0
  33. package/dist/_dts/blocks/src/system/blocks/checkout.d.ts +591 -0
  34. package/dist/_dts/blocks/src/system/blocks/collection.d.ts +591 -0
  35. package/dist/_dts/blocks/src/system/blocks/faq.d.ts +591 -0
  36. package/dist/_dts/blocks/src/system/blocks/gifting.d.ts +591 -0
  37. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +2 -0
  38. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +47 -0
  39. package/dist/_dts/blocks/src/system/blocks/product-detail.d.ts +591 -0
  40. package/dist/_dts/blocks/src/system/blocks/product-list.d.ts +591 -0
  41. package/dist/_dts/blocks/src/system/blocks/shop.d.ts +591 -0
  42. package/dist/_dts/blocks/src/system/blocks/team-members.d.ts +3 -0
  43. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +164 -0
  44. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.state.d.ts +1 -1
  45. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +1 -1
  46. package/dist/_dts/content-editor/src/index.d.ts +1 -1
  47. package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +2 -2
  48. package/dist/_dts/content-model/src/content-types/schema.d.ts +14 -0
  49. package/dist/_dts/content-model/src/templates/bindingTypeCompatibility.d.ts +3 -1
  50. package/dist/_dts/content-model/src/templates/bindingValidation.d.ts +10 -4
  51. package/dist/_dts/content-model/src/templates/fieldPaths.d.ts +20 -0
  52. package/dist/_dts/content-model/src/templates/manifestAdapter.d.ts +5 -2
  53. package/dist/_dts/core/src/branded.d.ts +108 -85
  54. package/dist/_dts/core/src/csv-types.d.ts +2 -2
  55. package/dist/_dts/core/src/editor-state.d.ts +7 -7
  56. package/dist/_dts/core/src/participants.d.ts +2 -2
  57. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +11 -0
  58. package/dist/_dts/editor-blocks/src/blockPayload.d.ts +1 -1
  59. package/dist/_dts/media-editor/src/MediaEditor.d.ts +3 -1
  60. package/dist/_dts/media-editor/src/MediaPreview.d.ts +3 -1
  61. package/dist/_dts/media-editor/src/fieldUi.d.ts +5 -0
  62. package/dist/_dts/media-editor/src/index.d.ts +1 -1
  63. package/dist/_dts/sdk/src/cli/commands/push/consts.d.ts +1 -1
  64. package/dist/_dts/sdk/src/cli/commands/push/metadata.d.ts +2 -0
  65. package/dist/_dts/sdk/src/cli/commands/push/stale.d.ts +3 -3
  66. package/dist/_dts/sdk/src/cli/commands/push-execute.d.ts +7 -0
  67. package/dist/_dts/sdk/src/cli/commands/push.d.ts +2 -0
  68. package/dist/_dts/sdk/src/cli/content/reader.d.ts +13 -0
  69. package/dist/_dts/sdk/src/cli/content/writer.d.ts +2 -1
  70. package/dist/_dts/sdk/src/cli/helpers.d.ts +2 -0
  71. package/dist/_dts/sdk/src/cli/site-commands/commandKeys.d.ts +6 -6
  72. package/dist/_dts/sdk/src/cli/site-commands/commandRuntime.d.ts +5 -0
  73. package/dist/_dts/sdk/src/cli/site-commands/commandSurfaceDispatch.d.ts +4 -0
  74. package/dist/_dts/sdk/src/cli/site-commands/pageCommands.d.ts +5 -2
  75. package/dist/_dts/sdk/src/cli/site-commands/pushExecution.d.ts +10 -1
  76. package/dist/_dts/sdk/src/cli/site-commands/pushExecutionTypes.d.ts +1 -1
  77. package/dist/_dts/sdk/src/client/management/types.d.ts +6 -0
  78. package/dist/_dts/sdk/src/client/types.d.ts +2 -2
  79. package/dist/_dts/sdk/src/config/content-types.d.ts +7 -0
  80. package/dist/_dts/sdk/src/config/field-definitions.d.ts +2 -0
  81. package/dist/_dts/sdk/src/version.d.ts +1 -1
  82. package/dist/_dts/site-commands/src/commands.d.ts +3 -0
  83. package/dist/{altcha-B5XGSXP5.mjs → altcha-EKUEQ4RP.mjs} +1 -1
  84. package/dist/{chunk-NIDXI46P.mjs → chunk-4QEGTLK6.mjs} +1 -1
  85. package/dist/{chunk-TXDES5P2.mjs → chunk-6HYXHRAI.mjs} +5 -5
  86. package/dist/{chunk-SVMMM2NA.mjs → chunk-CR5HKAGU.mjs} +24 -5
  87. package/dist/{chunk-OECWLDHN.mjs → chunk-MCRQMPET.mjs} +1030 -588
  88. package/dist/{chunk-SXOLGNMX.mjs → chunk-OKMBEAXY.mjs} +1 -1
  89. package/dist/{chunk-XGB3TDIC.mjs → chunk-R7POPVJR.mjs} +2 -8
  90. package/dist/{chunk-F7RTCZYN.mjs → chunk-RGTOD4AJ.mjs} +20 -14
  91. package/dist/cli/index.mjs +681 -225
  92. package/dist/cli/init-docs/content/cli-reference.md +3 -2
  93. package/dist/cli/init-docs/content/content-management.md +2 -2
  94. package/dist/cli/init-docs/content/workflow-preview-mode.md +68 -2
  95. package/dist/client/{accordion-EVDEOUPR.mjs → accordion-PLYNJIIM.mjs} +2 -2
  96. package/dist/client/analytics.mjs +1 -1
  97. package/dist/client/{bookingForm-DIHBLC64.mjs → bookingForm-BXAP6AO7.mjs} +55 -48
  98. package/dist/client/bookings.mjs +62 -55
  99. package/dist/client/{carousel-FEBQHIWI.mjs → carousel-TRBXDHGF.mjs} +3 -3
  100. package/dist/client/{cart-7CKSXAE4.mjs → cart-Z7H3HJRS.mjs} +7 -7
  101. package/dist/client/{checkout-WKYCANLV.mjs → checkout-WAFCUBIX.mjs} +7 -7
  102. package/dist/client/{chunk-OFMSCGNY.mjs → chunk-75OUS5MT.mjs} +2 -2
  103. package/dist/client/{chunk-IVNCUVAV.mjs → chunk-AUJ5DBZJ.mjs} +18 -18
  104. package/dist/client/{chunk-36WJCERQ.mjs → chunk-CE7IBGVW.mjs} +3 -1
  105. package/dist/client/{chunk-RZDWX7QW.mjs → chunk-CWGTG37I.mjs} +1 -1
  106. package/dist/client/{chunk-YDSEG6GZ.mjs → chunk-DNRGY432.mjs} +2 -2
  107. package/dist/client/{chunk-RV6FX7UH.mjs → chunk-FUXW6VW2.mjs} +9 -9
  108. package/dist/client/{chunk-65F47D7Y.mjs → chunk-JGXPTEI2.mjs} +43 -36
  109. package/dist/client/{chunk-GUK2FPXQ.mjs → chunk-JRDUHZCT.mjs} +37 -15
  110. package/dist/client/{chunk-VPPMNXCF.mjs → chunk-UVQEJJTN.mjs} +2 -2
  111. package/dist/client/{chunk-F7LHOKEH.mjs → chunk-XSV6KW4D.mjs} +1 -1
  112. package/dist/client/{chunk-PD6NBCEY.mjs → chunk-ZFHRN6W2.mjs} +1 -1
  113. package/dist/client/{chunk-2SAVKN2M.mjs → chunk-ZI3LLBPZ.mjs} +2 -2
  114. package/dist/client/client.mjs +249 -160
  115. package/dist/client/{courseRegistration-5QF2PHKM.mjs → courseRegistration-AHFQHWIJ.mjs} +10 -10
  116. package/dist/client/{eventCalendar-4ZOSETDU.mjs → eventCalendar-LDXTV5R7.mjs} +9 -9
  117. package/dist/client/{eventCombined-WQGU7JUX.mjs → eventCombined-A4JGTNJO.mjs} +9 -9
  118. package/dist/client/{eventDetails-AYWVUJ5Y.mjs → eventDetails-4YXTZ7EG.mjs} +9 -9
  119. package/dist/client/{eventListing-NT7C6UT5.mjs → eventListing-P72TPFFM.mjs} +9 -9
  120. package/dist/client/{eventRegistration-OH24F4ZJ.mjs → eventRegistration-LSYJHGMT.mjs} +9 -9
  121. package/dist/client/{form-7L42SRBB.mjs → form-AOPYOKOW.mjs} +6 -3
  122. package/dist/client/{headerSection-OZRZNZ52.mjs → headerSection-5TFYDFVQ.mjs} +3 -3
  123. package/dist/client/hooks.mjs +78 -48
  124. package/dist/client/{locationMap-ZBXRPQ7C.mjs → locationMap-QSZ3ZVAZ.mjs} +3 -3
  125. package/dist/client/{newsletterForm-SNAGFF2I.mjs → newsletterForm-KTRHZY52.mjs} +2 -2
  126. package/dist/client/{productDetail-I46BOFGV.mjs → productDetail-N4E775RG.mjs} +7 -7
  127. package/dist/client/{productList-BOYHTYI6.mjs → productList-UGUQ2S45.mjs} +7 -7
  128. package/dist/client/rendering/client.mjs +173 -131
  129. package/dist/client/rendering/islands.mjs +19 -19
  130. package/dist/client/rendering.mjs +230 -150
  131. package/dist/client/{shop-XTXPZTKR.mjs → shop-VHSZEEQ2.mjs} +7 -7
  132. package/dist/preview-next/before-render.mjs +10 -1
  133. package/dist/preview-next/client/runtime.mjs +6 -6
  134. package/dist/preview-next/middleware.mjs +10 -1
  135. package/dist/preview-next/tailwind-sources.css +1 -0
  136. package/dist/sdk-runtime-WHPJEF5G.mjs +8 -0
  137. package/dist/server/components.mjs +101 -54
  138. package/dist/server/config-template-validation.mjs +221 -15
  139. package/dist/server/config-validation.mjs +76 -42
  140. package/dist/server/config.mjs +76 -42
  141. package/dist/server/data.mjs +77 -47
  142. package/dist/server/index.mjs +31 -10
  143. package/dist/server/next.mjs +133 -71
  144. package/dist/server/page-converter.mjs +60 -40
  145. package/dist/server/prebuild.mjs +1 -1
  146. package/dist/server/rendering/server.mjs +107 -60
  147. package/dist/server/rendering.mjs +111 -61
  148. package/dist/server/routing.mjs +93 -63
  149. package/dist/server/server.mjs +102 -57
  150. package/package.json +1 -1
  151. package/dist/SdkPreviewModeRuntime-LAGYMPNF.mjs +0 -8
  152. package/dist/sdk-runtime-ZJLKC6DR.mjs +0 -8
@@ -6,6 +6,24 @@ var TEMPLATE_BINDING_TRANSFORMS = {
6
6
  };
7
7
 
8
8
  // ../content-model/src/templates/bindingTypeCompatibility.ts
9
+ var SCALAR_BLOCK_FIELD_TYPES = [
10
+ "text",
11
+ "number",
12
+ "slug",
13
+ "url",
14
+ "richText",
15
+ "media",
16
+ "file",
17
+ "boolean",
18
+ "select",
19
+ "reference",
20
+ "link",
21
+ "date",
22
+ "datetime"
23
+ ];
24
+ function isScalarBlockFieldType(type) {
25
+ return SCALAR_BLOCK_FIELD_TYPES.includes(type);
26
+ }
9
27
  var CONTENT_TO_BLOCK_COMPATIBILITY = {
10
28
  // Simple text fields
11
29
  text: ["text", "slug", "url"],
@@ -36,7 +54,7 @@ var CONTENT_TO_BLOCK_COMPATIBILITY = {
36
54
  // Group fields (nested structure - not directly bindable)
37
55
  group: [],
38
56
  // Repeater fields (list structure - not directly bindable)
39
- repeater: [],
57
+ repeater: ["repeater"],
40
58
  // Datetime fields can map to datetime/date inputs or text display fields.
41
59
  datetime: ["datetime", "date", "text"]
42
60
  };
@@ -80,6 +98,9 @@ var NESTED_PATH_COMPATIBILITY = {
80
98
  "file.filename": ["text"]
81
99
  };
82
100
  function isCompatibleBinding(sourceType, targetType) {
101
+ if (targetType === "repeater") {
102
+ return sourceType === "repeater";
103
+ }
83
104
  const compatibleTypes = CONTENT_TO_BLOCK_COMPATIBILITY[sourceType];
84
105
  if (compatibleTypes) {
85
106
  return compatibleTypes.includes(targetType);
@@ -87,11 +108,13 @@ function isCompatibleBinding(sourceType, targetType) {
87
108
  return false;
88
109
  }
89
110
  function isCompatibleMetaBinding(metaFieldName, targetType) {
111
+ if (targetType === "repeater") return false;
90
112
  if (!isMetaFieldPath(metaFieldName)) return false;
91
113
  const compatibleTypes = META_FIELD_COMPATIBILITY[metaFieldName];
92
114
  return compatibleTypes.includes(targetType);
93
115
  }
94
116
  function isCompatibleNestedPath(parentType, nestedSuffix, targetType) {
117
+ if (targetType === "repeater") return false;
95
118
  const pathKey = `${parentType}.${nestedSuffix}`;
96
119
  const compatibleTypes = NESTED_PATH_COMPATIBILITY[pathKey];
97
120
  if (compatibleTypes) {
@@ -223,10 +246,76 @@ function nestedFields(field) {
223
246
  const record = field;
224
247
  return record.fields ?? record.schema?.fields ?? [];
225
248
  }
226
- function getFieldTypeFromPath(schema, path) {
249
+ function getFieldDescriptorFromPath(schema, path) {
227
250
  const paths = getAvailableFieldPaths(schema);
228
251
  const match = paths.find((p) => p.path === path);
229
- return match?.type ?? null;
252
+ if (match) return { kind: "scalar", type: match.type };
253
+ const field = findContentFieldByPath(schema.fields ?? [], path.split("."));
254
+ if (!field || field.type !== "repeater") return null;
255
+ return {
256
+ kind: "repeater",
257
+ shape: buildRepeaterFieldShape(field)
258
+ };
259
+ }
260
+ function findContentFieldByPath(fields, segments) {
261
+ if (segments.length === 0) return null;
262
+ const [head, ...tail] = segments;
263
+ const field = fields.find((candidate) => candidate.id === head);
264
+ if (!field) return null;
265
+ if (tail.length === 0) return field;
266
+ if (field.type !== "group") return null;
267
+ return findContentFieldByPath(nestedFields(field), tail);
268
+ }
269
+ function buildRepeaterFieldShape(field) {
270
+ const record = field;
271
+ if (record.polymorphic || record.itemTypes) {
272
+ return { kind: "unsupported", reason: "polymorphic_unsupported" };
273
+ }
274
+ const fields = nestedFields(field);
275
+ if (fields.length === 0) {
276
+ return { kind: "unsupported", reason: "missing_item_schema" };
277
+ }
278
+ const itemFields = [];
279
+ for (const child of fields) {
280
+ if (child.type === "repeater") {
281
+ return { kind: "unsupported", reason: "nested_repeater_unsupported" };
282
+ }
283
+ if (!isRepeaterItemScalarType(child.type)) {
284
+ return { kind: "unsupported", reason: "unsupported_item_field" };
285
+ }
286
+ itemFields.push({
287
+ id: child.id,
288
+ type: child.type,
289
+ required: Boolean(child.required)
290
+ });
291
+ }
292
+ return { kind: "supported", itemFields };
293
+ }
294
+ function isRepeaterItemScalarType(type) {
295
+ switch (type) {
296
+ case "text":
297
+ case "textarea":
298
+ case "richText":
299
+ case "number":
300
+ case "date":
301
+ case "url":
302
+ case "media":
303
+ case "file":
304
+ case "boolean":
305
+ case "select":
306
+ case "reference":
307
+ case "link":
308
+ case "button":
309
+ case "datetime":
310
+ return true;
311
+ case "group":
312
+ case "repeater":
313
+ return false;
314
+ default: {
315
+ const _exhaustive = type;
316
+ return _exhaustive;
317
+ }
318
+ }
230
319
  }
231
320
 
232
321
  // ../content-model/src/templates/bindingValidation.ts
@@ -247,9 +336,6 @@ var TRANSFORM_IO = {
247
336
  function getTransformIO(name) {
248
337
  return name in TRANSFORM_IO ? TRANSFORM_IO[name] : void 0;
249
338
  }
250
- function resolveContentPathType(schema, path) {
251
- return getFieldTypeFromPath(schema, path);
252
- }
253
339
  function resolveMetaPathType(path) {
254
340
  return resolveMetaFieldType(path);
255
341
  }
@@ -276,8 +362,8 @@ function isSourceCompatibleWithTarget(sourceType, targetType) {
276
362
  return isCompatibleBinding(sourceType, targetType);
277
363
  }
278
364
  function resolveFieldSource(path, context) {
279
- const type = resolveContentPathType(context.schema, path);
280
- if (type === null) {
365
+ const descriptor = getFieldDescriptorFromPath(context.schema, path);
366
+ if (descriptor === null) {
281
367
  return {
282
368
  kind: "invalidPath",
283
369
  error: {
@@ -288,7 +374,10 @@ function resolveFieldSource(path, context) {
288
374
  }
289
375
  };
290
376
  }
291
- return { kind: "ok", type, path };
377
+ if (descriptor.kind === "repeater") {
378
+ return { kind: "ok", type: "repeater", path, shape: descriptor.shape };
379
+ }
380
+ return { kind: "ok", type: descriptor.type, path };
292
381
  }
293
382
  function resolveMetaSource(path, context) {
294
383
  const type = resolveMetaPathType(path);
@@ -318,6 +407,21 @@ function checkDirectCompatibility(resolved, context, isMetaSource) {
318
407
  via: "direct"
319
408
  };
320
409
  }
410
+ if (context.target.type === "repeater") {
411
+ const mismatch = checkRepeaterCompatibility(resolved, context);
412
+ return mismatch;
413
+ }
414
+ if (resolved.type === "repeater") {
415
+ return {
416
+ kind: "typeIncompatible",
417
+ blockIdentifier: context.blockIdentifier,
418
+ fieldKey: context.fieldKey,
419
+ sourceType: describeResolvedSourceType(resolved),
420
+ sourcePath: resolved.path,
421
+ targetType: context.target.type,
422
+ via: "direct"
423
+ };
424
+ }
321
425
  if (isSourceCompatibleWithTarget(resolved.type, context.target.type)) return null;
322
426
  return {
323
427
  kind: "typeIncompatible",
@@ -329,6 +433,51 @@ function checkDirectCompatibility(resolved, context, isMetaSource) {
329
433
  via: "direct"
330
434
  };
331
435
  }
436
+ function describeResolvedSourceType(resolved) {
437
+ if (resolved.type !== "repeater") return resolved.type;
438
+ return resolved.shape?.kind === "unsupported" ? `repeater(${resolved.shape.reason})` : "repeater";
439
+ }
440
+ function describeTargetType(target) {
441
+ return target.type;
442
+ }
443
+ function checkRepeaterCompatibility(resolved, context) {
444
+ if (context.target.type !== "repeater") return null;
445
+ const incompatible = (sourceType) => ({
446
+ kind: "typeIncompatible",
447
+ blockIdentifier: context.blockIdentifier,
448
+ fieldKey: context.fieldKey,
449
+ sourceType,
450
+ sourcePath: resolved.path,
451
+ targetType: describeTargetType(context.target),
452
+ via: "direct"
453
+ });
454
+ if (resolved.type !== "repeater" || !resolved.shape) {
455
+ return incompatible(describeResolvedSourceType(resolved));
456
+ }
457
+ const sourceShape = resolved.shape;
458
+ const targetShape = context.target.shape;
459
+ if (sourceShape.kind === "unsupported") {
460
+ return incompatible(`repeater(${sourceShape.reason})`);
461
+ }
462
+ if (targetShape.kind === "unsupported") {
463
+ return incompatible(`target-repeater(${targetShape.reason})`);
464
+ }
465
+ const sourceById = new Map(sourceShape.itemFields.map((field) => [field.id, field]));
466
+ for (const targetField of targetShape.itemFields) {
467
+ const sourceField = sourceById.get(targetField.id);
468
+ if (!sourceField) {
469
+ if (targetField.required) return incompatible("repeater(missing_required_target_field)");
470
+ continue;
471
+ }
472
+ if (targetField.required && !sourceField.required) {
473
+ return incompatible("repeater(requiredness_mismatch)");
474
+ }
475
+ if (!isScalarBlockFieldType(targetField.type) || !isSourceCompatibleWithTarget(sourceField.type, targetField.type)) {
476
+ return incompatible(`repeater(type_mismatch:${sourceField.id})`);
477
+ }
478
+ }
479
+ return null;
480
+ }
332
481
  function validateBinding(binding, context) {
333
482
  if (typeof binding === "string") {
334
483
  const resolved = resolveFieldSource(binding, context);
@@ -464,10 +613,13 @@ function validateTransform(binding, context) {
464
613
  }
465
614
  return errors;
466
615
  }
616
+ function isTemplateBindingValueArray(value) {
617
+ return Array.isArray(value);
618
+ }
467
619
  function readFallbackOptions(binding) {
468
- if (Array.isArray(binding.options)) return binding.options;
620
+ if (isTemplateBindingValueArray(binding.options)) return binding.options;
469
621
  const legacy = binding.sources;
470
- return Array.isArray(legacy) ? legacy : [];
622
+ return isTemplateBindingValueArray(legacy) ? legacy : [];
471
623
  }
472
624
  function resolveTransformInput(binding) {
473
625
  if (binding.input !== void 0) {
@@ -592,9 +744,8 @@ var FIELD_TYPE_CLASSIFICATION = {
592
744
  group: "composite",
593
745
  modal: "composite",
594
746
  tabGroup: "composite",
595
- // Repeaters: monomorphic has a single inner shape we could walk, but the
596
- // leaves would be bindings to repeated items, not to a fixed path. Skip.
597
- repeater: "opaque",
747
+ // Whole-field containers.
748
+ repeater: "whole",
598
749
  // Opaque types — dashboard-only widgets without an underlying bindable leaf.
599
750
  presetOrCustom: "opaque",
600
751
  contentTypeSelect: "opaque",
@@ -620,6 +771,15 @@ function collectLeaves(fields, prefix, out) {
620
771
  });
621
772
  continue;
622
773
  }
774
+ if (cls === "whole") {
775
+ out.push({
776
+ id,
777
+ type: "repeater",
778
+ required: Boolean(field.required),
779
+ shape: buildManifestRepeaterShape(field)
780
+ });
781
+ continue;
782
+ }
623
783
  if (cls === "composite") {
624
784
  const groupChildren = field.schema?.fields;
625
785
  if (groupChildren) collectLeaves(groupChildren, id, out);
@@ -630,6 +790,31 @@ function collectLeaves(fields, prefix, out) {
630
790
  void leafToBlockFieldType;
631
791
  }
632
792
  }
793
+ function buildManifestRepeaterShape(field) {
794
+ if (field.polymorphic || field.itemTypes) {
795
+ return { kind: "unsupported", reason: "polymorphic_unsupported" };
796
+ }
797
+ const fields = field.repeatedItem?.fields ?? field.schema?.fields;
798
+ if (!fields || fields.length === 0) {
799
+ return { kind: "unsupported", reason: "missing_item_schema" };
800
+ }
801
+ const itemFields = [];
802
+ for (const child of fields) {
803
+ if (child.type === "repeater") {
804
+ return { kind: "unsupported", reason: "nested_repeater_unsupported" };
805
+ }
806
+ const type = leafToBlockFieldType(child.type);
807
+ if (!type) {
808
+ return { kind: "unsupported", reason: "unsupported_item_field" };
809
+ }
810
+ itemFields.push({
811
+ id: child.id,
812
+ type,
813
+ required: Boolean(child.required)
814
+ });
815
+ }
816
+ return { kind: "supported", itemFields };
817
+ }
633
818
  function manifestToValidationShape(manifest) {
634
819
  const fields = [];
635
820
  collectLeaves(manifest.fields, "", fields);
@@ -637,6 +822,9 @@ function manifestToValidationShape(manifest) {
637
822
  }
638
823
 
639
824
  // src/config/template-validation.ts
825
+ function assertNeverField(field) {
826
+ throw new Error(`Unhandled field type while reading nested SDK fields: ${JSON.stringify(field)}`);
827
+ }
640
828
  function toContentTypeSchema(fields) {
641
829
  return {
642
830
  version: 1,
@@ -662,8 +850,26 @@ function nestedSdkFields(field) {
662
850
  return field.schema?.fields;
663
851
  case "tabGroup":
664
852
  return field.tabs.flatMap((tab) => tab.fields);
665
- default:
853
+ case "text":
854
+ case "richText":
855
+ case "media":
856
+ case "file":
857
+ case "boolean":
858
+ case "number":
859
+ case "date":
860
+ case "time":
861
+ case "datetime":
862
+ case "slug":
863
+ case "url":
864
+ case "link":
865
+ case "select":
866
+ case "reference":
867
+ case "presetOrCustom":
868
+ case "contentTypeSelect":
869
+ case "entryPicker":
666
870
  return void 0;
871
+ default:
872
+ return assertNeverField(field);
667
873
  }
668
874
  }
669
875
  function toContentFieldType(type) {
@@ -1751,7 +1751,16 @@ var ENDPOINT_DEFINITIONS = {
1751
1751
  revalidate: 60,
1752
1752
  tags: ["site-{siteId}", "content-{siteId}-{type}"],
1753
1753
  auth: "user",
1754
- responseKind: "json"
1754
+ responseKind: "json",
1755
+ errors: ["validation:invalid_input", "resource:not_found", "resource:conflict", "server:internal_error"]
1756
+ },
1757
+ reorderContentEntries: {
1758
+ path: "/sites/{siteId}/content/{type}/order",
1759
+ method: "POST",
1760
+ tags: ["site-{siteId}", "content-{siteId}-{type}"],
1761
+ auth: "user",
1762
+ responseKind: "json",
1763
+ errors: ["validation:invalid_input", "resource:not_found", "resource:conflict", "server:internal_error"]
1755
1764
  },
1756
1765
  getContentTemplate: {
1757
1766
  path: "/sites/{siteId}/content/types/{type}/template",
@@ -6495,14 +6504,14 @@ function rotateNormalizedPoint(point, rotation) {
6495
6504
  const x = point.x;
6496
6505
  const y = point.y;
6497
6506
  switch (rotation) {
6507
+ case 0:
6508
+ return { x, y };
6498
6509
  case 90:
6499
6510
  return { x: 1 - y, y: x };
6500
6511
  case 180:
6501
6512
  return { x: 1 - x, y: 1 - y };
6502
6513
  case 270:
6503
6514
  return { x: y, y: 1 - x };
6504
- default:
6505
- return { x, y };
6506
6515
  }
6507
6516
  }
6508
6517
 
@@ -6795,6 +6804,8 @@ var uiSchema = z4.object({
6795
6804
  mediaPickerAutoOpen: z4.boolean().optional(),
6796
6805
  showMediaPreview: z4.boolean().optional(),
6797
6806
  showMediaOverlayActions: z4.boolean().optional(),
6807
+ mediaPreviewMaxWidth: z4.enum(["xs", "sm", "md", "none"]).optional(),
6808
+ preventMediaPreviewUpscale: z4.boolean().optional(),
6798
6809
  mediaDelivery: mediaDeliverySchema.optional(),
6799
6810
  mediaDeliveryByVariant: z4.record(z4.string(), mediaDeliverySchema).optional(),
6800
6811
  // Optional input hints for validators/widgets
@@ -7044,6 +7055,9 @@ var repeaterFieldSchema = baseFieldSchema.extend({
7044
7055
  type: z4.literal("repeater"),
7045
7056
  itemLabel: z4.string().default("Item"),
7046
7057
  itemLabelSource: z4.string().optional(),
7058
+ showSummary: z4.boolean().optional(),
7059
+ summaryFields: z4.string().array().optional(),
7060
+ summaryMaxChars: z4.number().int().positive().optional(),
7047
7061
  minItems: z4.number().int().min(0).default(0),
7048
7062
  maxItems: z4.number().int().positive().optional(),
7049
7063
  // Monomorphic mode
@@ -16088,47 +16102,48 @@ function validateFieldDefinitions(fields3, fragmentId) {
16088
16102
  function prefixFieldId(field, scope) {
16089
16103
  const cloned = cloneFieldDefinition2(field);
16090
16104
  cloned.id = `${scope}.${field.id}`;
16091
- cloned.defaultValue = cloneUnknown(cloned.defaultValue);
16105
+ const defaultValue = cloned.defaultValue;
16106
+ cloned.defaultValue = cloneUnknown(defaultValue);
16092
16107
  cloned.visibleRoles = cloned.visibleRoles ? [...cloned.visibleRoles] : void 0;
16093
16108
  cloned.ui = cloneUnknown(cloned.ui);
16094
16109
  return cloned;
16095
16110
  }
16096
16111
  function cloneFieldDefinition2(field) {
16097
- switch (field.type) {
16098
- case "repeater":
16099
- if (field.polymorphic && field.itemTypes) {
16100
- return {
16101
- ...field,
16102
- polymorphic: true,
16103
- itemTypes: Object.fromEntries(
16104
- Object.entries(field.itemTypes).map(([key, itemType]) => [
16105
- key,
16106
- {
16107
- ...itemType,
16108
- fields: itemType.fields.map(cloneFieldDefinition2)
16109
- }
16110
- ])
16111
- )
16112
- };
16113
- } else if (field.schema) {
16114
- return {
16115
- ...field,
16116
- schema: {
16117
- fields: field.schema.fields.map(cloneFieldDefinition2)
16118
- }
16119
- };
16120
- }
16121
- return { ...field };
16122
- case "group":
16112
+ if (field.type === "repeater") {
16113
+ if (field.polymorphic && field.itemTypes) {
16114
+ return {
16115
+ ...field,
16116
+ polymorphic: true,
16117
+ itemTypes: Object.fromEntries(
16118
+ Object.entries(field.itemTypes).map(([key, itemType]) => [
16119
+ key,
16120
+ {
16121
+ ...itemType,
16122
+ fields: itemType.fields.map(cloneFieldDefinition2)
16123
+ }
16124
+ ])
16125
+ )
16126
+ };
16127
+ }
16128
+ if (field.schema) {
16123
16129
  return {
16124
16130
  ...field,
16125
16131
  schema: {
16126
16132
  fields: field.schema.fields.map(cloneFieldDefinition2)
16127
16133
  }
16128
16134
  };
16129
- default:
16130
- return { ...field };
16135
+ }
16136
+ return { ...field };
16137
+ }
16138
+ if (field.type === "group") {
16139
+ return {
16140
+ ...field,
16141
+ schema: {
16142
+ fields: field.schema.fields.map(cloneFieldDefinition2)
16143
+ }
16144
+ };
16131
16145
  }
16146
+ return { ...field };
16132
16147
  }
16133
16148
  function cloneUnknown(value) {
16134
16149
  if (value == null || typeof value !== "object") {
@@ -18471,7 +18486,8 @@ function createBlockManifestWithContentShape(config, _contentShape) {
18471
18486
  return createBlockManifest(config);
18472
18487
  }
18473
18488
  function normalizeBlockLayout(layout) {
18474
- return Array.isArray(layout) ? [...layout] : layout;
18489
+ const rawLayout = layout;
18490
+ return Array.isArray(rawLayout) ? rawLayout : rawLayout;
18475
18491
  }
18476
18492
  function deriveComponentName(id) {
18477
18493
  const base = id.replace(/^block\./, "");
@@ -20017,16 +20033,20 @@ var marqueeLoopTransform = {
20017
20033
  summary: "Repeat an array to a minimum length, then duplicate it for seamless marquee looping",
20018
20034
  schema: marqueeLoopOptionsSchema,
20019
20035
  run: (value, options) => {
20020
- if (!Array.isArray(value) || value.length === 0) return [];
20036
+ const items = toUnknownArray(value);
20037
+ if (items.length === 0) return [];
20021
20038
  const minItems = options?.minItems ?? 10;
20022
20039
  const base = [];
20023
20040
  while (base.length < minItems) {
20024
- base.push(...value);
20041
+ base.push(...items);
20025
20042
  if (base.length > 1e3) break;
20026
20043
  }
20027
20044
  return [...base, ...base];
20028
20045
  }
20029
20046
  };
20047
+ function toUnknownArray(value) {
20048
+ return Array.isArray(value) ? value : [];
20049
+ }
20030
20050
  var formattingTransforms = [
20031
20051
  uppercaseTransform,
20032
20052
  fallbackTransform,
@@ -23693,8 +23713,8 @@ var eventSurfaceScopeValues = [
23693
23713
  "custom"
23694
23714
  ];
23695
23715
  var eventScheduleScopeValues = ["any", "recurring", "oneOff"];
23696
- var asEventCategoryId = (value) => value;
23697
- var asVenueId = (value) => value;
23716
+ var unsafeAsEventCategoryId = (value) => value;
23717
+ var unsafeAsVenueId = (value) => value;
23698
23718
  function normalizeEventBlockKind(value) {
23699
23719
  return value === "courses" || value === "events" ? value : "all";
23700
23720
  }
@@ -23720,10 +23740,10 @@ function normalizeEventCategoryIds(value) {
23720
23740
  if (Array.isArray(value)) {
23721
23741
  return normalizeIdList(
23722
23742
  value.filter((entry) => typeof entry === "string")
23723
- ).map(asEventCategoryId);
23743
+ ).map(unsafeAsEventCategoryId);
23724
23744
  }
23725
23745
  if (typeof value === "string") {
23726
- return normalizeIdList(value.split(",")).map(asEventCategoryId);
23746
+ return normalizeIdList(value.split(",")).map(unsafeAsEventCategoryId);
23727
23747
  }
23728
23748
  return [];
23729
23749
  }
@@ -23736,7 +23756,7 @@ function normalizeEventVenueId(value) {
23736
23756
  return null;
23737
23757
  }
23738
23758
  const trimmed = value.trim();
23739
- return trimmed ? asVenueId(trimmed) : null;
23759
+ return trimmed ? unsafeAsVenueId(trimmed) : null;
23740
23760
  }
23741
23761
  function normalizeEventStaffMemberId(value) {
23742
23762
  if (typeof value !== "string") {
@@ -33221,10 +33241,16 @@ var dashboardConfigSchema = z61.object({
33221
33241
  var fieldDefinitionInputSchema = unsafeRetypeZodSchema(fieldSchema);
33222
33242
  var nodeDefinitionSchema = unsafeRetypeZodSchema(NodeSchema);
33223
33243
  var sdkLoaderEndpointSchema = z61.enum(SUPPORTED_LOADER_ENDPOINTS);
33244
+ var loaderFallbackScalarSchema = z61.union([
33245
+ z61.string(),
33246
+ z61.number(),
33247
+ z61.boolean(),
33248
+ z61.null()
33249
+ ]);
33224
33250
  var loaderParamBindingSchema = z61.object({
33225
33251
  $bind: z61.object({
33226
33252
  from: z61.string().min(1, "Binding path is required"),
33227
- fallback: z61.string().optional()
33253
+ fallback: loaderFallbackScalarSchema.optional()
33228
33254
  })
33229
33255
  });
33230
33256
  var loaderParamValueSchema = z61.union([
@@ -33370,9 +33396,13 @@ var sdkBlockFieldOptionsMapSchema = z61.record(
33370
33396
  var sdkContentTypeTemplateConfigSchema = z61.object({
33371
33397
  blocks: z61.array(z61.unknown())
33372
33398
  }).passthrough();
33399
+ var sdkContentTypeOrderingConfigSchema = z61.object({
33400
+ mode: z61.enum(["default", "manual"]).optional()
33401
+ }).optional();
33373
33402
  var sdkContentTypeConfigSchema = z61.object({
33374
33403
  key: z61.string().min(1),
33375
33404
  fields: z61.array(z61.unknown()),
33405
+ ordering: sdkContentTypeOrderingConfigSchema,
33376
33406
  template: sdkContentTypeTemplateConfigSchema.nullable().optional()
33377
33407
  }).passthrough();
33378
33408
  var sdkContentConfigSchema = z61.object({
@@ -34518,6 +34548,9 @@ var templateConfigSchemaForward = z67.object({
34518
34548
  })
34519
34549
  )
34520
34550
  }).optional();
34551
+ var contentTypeOrderingSchema = z67.object({
34552
+ mode: z67.enum(["default", "manual"]).optional()
34553
+ }).optional();
34521
34554
  var contentTypeConfigSchema = z67.object({
34522
34555
  key: contentTypeKeySchema,
34523
34556
  name: z67.string().min(1),
@@ -34527,6 +34560,7 @@ var contentTypeConfigSchema = z67.object({
34527
34560
  // Fields are validated as unknown[] here - deep field validation happens in @riverbankcms/blocks
34528
34561
  fields: z67.array(z67.any()).min(1, "At least one field is required"),
34529
34562
  titleField: z67.string().optional(),
34563
+ ordering: contentTypeOrderingSchema,
34530
34564
  isSingleton: z67.boolean().optional().default(false),
34531
34565
  template: templateConfigSchemaForward
34532
34566
  }).refine(
@@ -35058,7 +35092,7 @@ var loaderParamBindingSchema2 = z70.object({
35058
35092
  // Loader params are ultimately string-normalized for query strings, so fallbacks should
35059
35093
  // stay scalar. Use transforms (e.g. `value.jsonArray`) when you need to serialize
35060
35094
  // more complex values into a string.
35061
- fallback: z70.union([z70.string(), z70.number(), z70.boolean(), z70.null()]).optional(),
35095
+ fallback: loaderFallbackScalarSchema.optional(),
35062
35096
  transforms: z70.array(loaderTransformStepSchema).default([]),
35063
35097
  pick: z70.enum(["value", "collection", "context"]).default("value"),
35064
35098
  coerce: z70.enum(["number", "boolean", "string"]).optional()