@bettercms-ai/types 1.41.0 → 1.42.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.
package/dist/index.d.ts CHANGED
@@ -15,16 +15,70 @@ interface Workspace {
15
15
 
16
16
  /**
17
17
  * Generated by scripts/gen-dock-icon-names.mjs from the vendored icon tarball
18
- * (sha256 0691620e50bdf453c2fed06224d9dc52d521574ab254a149eba47664b92fb889).
18
+ * (sha256 0691620e50bdf453c2fed06224d9dc52d521574ab254a149eba47664b92fb889)
19
+ * and the vendored line-icon subset (sha256 06cd85d602d1104d962ed8ace64f6c4d64846ee50bd62bd328252c9d8f697b75).
19
20
  * Do not edit by hand: rerun the script (`--check` fails CI on drift).
20
21
  *
21
22
  * The closed vocabulary for `ui.icon` (field ui, fieldsets, prop ui.group). `as const` because a
22
23
  * z.enum needs the literal tuple; a `readonly string[]` would type every string as valid.
23
24
  */
24
- declare const DOCK_ICON_NAMES: readonly ["access-denied", "activity", "add", "add-circle", "add-comment", "add-document", "add-user", "api", "archive", "arrow-down", "arrow-left", "arrow-right", "arrow-top-right", "arrow-up", "asterisk", "bar-chart", "basket", "bell", "bill", "binary-document", "block-content", "block-element", "blockquote", "bold", "bolt", "book", "bookmark", "bookmark-filled", "bottle", "bug", "bulb-filled", "bulb-outline", "calendar", "case", "chart-upward", "checkmark", "checkmark-circle", "chevron-down", "chevron-left", "chevron-right", "chevron-up", "circle", "clipboard", "clipboard-image", "clock", "close", "close-circle", "code", "code-block", "cog", "collapse", "color-wheel", "comment", "component", "compose", "compose-sparkles", "confetti", "controls", "copy", "credit-card", "crop", "cube", "dashboard", "database", "desktop", "diamond", "document", "document-pdf", "document-remove", "document-sheet", "document-text", "document-video", "document-word", "document-zip", "documents", "dot", "double-chevron-down", "double-chevron-left", "double-chevron-right", "double-chevron-up", "double-quote", "download", "drag-handle", "drop", "earth-americas", "earth-globe", "edit", "ellipsis-horizontal", "ellipsis-vertical", "empty", "enter", "enter-right", "envelope", "equal", "error-filled", "error-outline", "error-screen", "expand", "eye-closed", "eye-open", "face-happy", "face-indifferent", "face-sad", "feedback", "filter", "folder", "generate", "github", "groq", "hash", "heart", "heart-filled", "help-circle", "highlight", "home", "ice-cream", "image", "image-remove", "images", "inbox", "info-filled", "info-outline", "inline", "inline-element", "insert-above", "insert-below", "italic", "joystick", "json", "launch", "leave", "lemon", "link", "link-removed", "linkedin", "list", "lock", "logo-js", "logo-ts", "marker", "marker-removed", "master-detail", "menu", "microphone", "microphone-slash", "mobile-device", "moon", "number", "ok-hand", "olist", "overage", "package", "panel-left", "panel-right", "pause", "pin", "pin-filled", "pin-removed", "play", "plug", "presentation", "progress-50", "progress-75", "projects", "publish", "read-only", "redo", "refresh", "remove", "remove-circle", "reset", "restore", "retrieve", "retry", "revert", "robot", "rocket", "schema", "search", "select", "share", "sort", "sparkle", "sparkles", "spinner", "split-horizontal", "split-vertical", "square", "stack", "stack-compact", "star", "star-filled", "stop", "strikethrough", "string", "sun", "sync", "tablet-device", "tag", "tags", "target", "task", "terminal", "text", "th-large", "th-list", "thumbs-down", "thumbs-up", "tiers", "timeline", "toggle-arrow-right", "token", "transfer", "translate", "trash", "trend-upward", "triangle-outline", "trolley", "truncate", "twitter", "ulist", "unarchive", "underline", "undo", "unknown", "unlink", "unlock", "unpublish", "upload", "user", "users", "versions", "video", "warning-filled", "warning-outline", "wrench"];
25
+ declare const DOCK_ICON_NAMES: readonly ["abc", "access-denied", "activity", "add", "add-circle", "add-comment", "add-document", "add-user", "address-book", "adjustments", "adjustments-horizontal", "alarm", "alert-triangle", "align-left", "api", "app-window", "apple", "apps", "archive", "arrow-back-up", "arrow-down", "arrow-guide", "arrow-left", "arrow-right", "arrow-top-right", "arrow-up", "arrows-diagonal", "arrows-down", "arrows-exchange", "arrows-horizontal", "arrows-left-right", "arrows-shuffle", "arrows-sort", "article", "aspect-ratio", "asterisk", "award", "axis-x", "backpack", "badge", "badge-cc", "badges", "bar-chart", "basket", "bell", "bill", "binary-document", "block-content", "block-element", "blockquote", "bold", "bolt", "book", "book-2", "bookmark", "bookmark-filled", "books", "bottle", "box", "brand-dribbble", "brand-facebook", "brand-instagram", "brand-linkedin", "brand-pinterest", "brand-tiktok", "brand-x", "brand-youtube", "briefcase", "broadcast", "browser", "bug", "building", "building-skyscraper", "building-store", "bulb-filled", "bulb-outline", "calculator", "calendar", "calendar-dollar", "calendar-event", "calendar-exclamation", "calendar-off", "calendar-plus", "calendar-star", "calendar-time", "camera", "campfire", "carousel-horizontal", "case", "cash", "category", "category-2", "chart-area", "chart-arrows", "chart-bar", "chart-bar-popular", "chart-donut", "chart-dots", "chart-line", "chart-upward", "check", "checkbox", "checklist", "checkmark", "checkmark-circle", "chef-hat", "chevron-down", "chevron-left", "chevron-right", "chevron-up", "chevrons-right", "circle", "circle-check", "circle-dot", "circle-number-1", "circle-plus", "click", "clipboard", "clipboard-image", "clipboard-text", "clock", "clock-check", "clock-hour-4", "close", "close-circle", "code", "code-block", "cog", "collapse", "color-wheel", "columns", "columns-2", "columns-3", "comment", "component", "compose", "compose-sparkles", "confetti", "controls", "cookie", "copy", "credit-card", "crop", "cube", "currency-dollar", "dashboard", "database", "database-search", "desktop", "device-desktop", "device-mobile", "device-tablet", "devices", "diamond", "discount", "document", "document-pdf", "document-remove", "document-sheet", "document-text", "document-video", "document-word", "document-zip", "documents", "door-exit", "dot", "double-chevron-down", "double-chevron-left", "double-chevron-right", "double-chevron-up", "double-quote", "download", "drag-handle", "drop", "droplet", "droplet-half", "earth-americas", "earth-globe", "edit", "egg", "ellipsis-horizontal", "ellipsis-vertical", "empty", "enter", "enter-right", "envelope", "equal", "error-filled", "error-outline", "error-screen", "expand", "eye-closed", "eye-off", "eye-open", "face-happy", "face-indifferent", "face-sad", "feather", "feedback", "file", "file-certificate", "file-code", "file-download", "file-text", "filter", "flag", "flame", "flask", "focus-2", "folder", "folders", "forms", "frame", "generate", "gift", "git-branch", "github", "grid-dots", "groq", "hammer", "hand-finger", "hanger", "hash", "headphones", "headset", "heart", "heart-filled", "heart-handshake", "help-circle", "highlight", "history", "home", "hourglass", "ice-cream", "id-badge", "id-badge-2", "image", "image-remove", "images", "inbox", "infinity", "info-circle", "info-filled", "info-outline", "info-square-rounded", "inline", "inline-element", "input-search", "insert-above", "insert-below", "italic", "joystick", "json", "language", "launch", "layout", "layout-align-center", "layout-board", "layout-board-split", "layout-bottombar", "layout-bottombar-expand", "layout-cards", "layout-columns", "layout-dashboard", "layout-grid", "layout-list", "layout-navbar", "layout-rows", "layout-sidebar", "layout-sidebar-right", "leaf", "leave", "lemon", "library-photo", "lifebuoy", "link", "link-removed", "linkedin", "list", "list-check", "list-details", "list-numbers", "list-tree", "lock", "logo-js", "logo-ts", "mail", "map-2", "map-pin", "map-pins", "marker", "marker-removed", "master-detail", "math-function", "meat", "menu", "message", "message-2", "message-check", "message-circle", "message-circle-2", "message-plus", "message-star", "microphone", "microphone-slash", "mobile-device", "mood-empty", "moon", "movie", "news", "notes", "number", "ok-hand", "olist", "overage", "package", "packages", "palette", "panel-left", "panel-right", "paperclip", "pause", "pencil", "phone", "photo", "photo-scan", "photo-search", "pig-money", "pin", "pin-filled", "pin-removed", "play", "player-play", "player-track-next", "playlist-add", "plug", "plug-connected", "plus-minus", "point", "presentation", "printer", "progress-50", "progress-75", "projects", "publish", "qrcode", "quote", "read-only", "receipt", "recycle", "redo", "refresh", "remove", "remove-circle", "repeat", "reset", "restore", "retrieve", "retry", "revert", "robot", "rocket", "rosette", "route", "ruler", "ruler-measure", "salad", "scale", "schema", "school", "search", "section", "select", "send", "server", "settings", "share", "shield-check", "shield-lock", "shopping-bag", "shopping-cart", "shopping-cart-plus", "signature", "sitemap", "slideshow", "sort", "sort-descending", "spacing-vertical", "sparkle", "sparkles", "speakerphone", "spinner", "split-horizontal", "split-vertical", "square", "stack", "stack-2", "stack-compact", "stairs", "stairs-up", "star", "star-filled", "stars", "stop", "strikethrough", "string", "subtask", "sun", "superscript", "sync", "table", "table-options", "tablet-device", "tag", "tags", "target", "task", "template", "tent", "terminal", "terminal-2", "text", "th-large", "th-list", "thumb-up", "thumbs-down", "thumbs-up", "ticket", "tiers", "timeline", "toggle-arrow-right", "toggle-right", "token", "tool", "tools-kitchen-2", "transfer", "translate", "trash", "trend-upward", "triangle-outline", "trolley", "truck", "truck-delivery", "truncate", "twitter", "typography", "ulist", "unarchive", "underline", "undo", "unknown", "unlink", "unlock", "unpublish", "upload", "user", "user-circle", "user-plus", "user-search", "user-star", "users", "users-group", "versions", "video", "vocabulary", "vs", "warning-filled", "warning-outline", "weight", "world", "wrench", "zoom-question"];
25
26
  type DockIconName = (typeof DOCK_ICON_NAMES)[number];
26
27
  declare const DOCK_ICON_NAME_SET: ReadonlySet<string>;
27
28
 
29
+ /**
30
+ * How a `number` field's value is SHOWN: `config.format` on the field.
31
+ *
32
+ * An imported site shows `$1,299.00`, `38%`, `12,000+`, `4 900 €`. The value an author edits and
33
+ * Delivery returns is the number (`1299`, `38`, `12000`, `4900`); everything around the digits is
34
+ * presentation, read once off the built page and kept here. The contract both halves hold:
35
+ *
36
+ * formatNumber(parseNumberText(text).value, parseNumberText(text).format) === text
37
+ *
38
+ * so a page nobody edited is published byte for byte, and an edited value is shown the way the
39
+ * site showed the old one. `parseNumberText` answers null for anything it cannot give back
40
+ * exactly, and that text stays a text field.
41
+ *
42
+ * Pure, and in this package because three programs read it: the import (parse), the publish
43
+ * writers (format) and the dashboard's number input (format, for the preview beside the box).
44
+ */
45
+ /** `config.format` of a `number` field. Every key optional; absent = none. */
46
+ interface NumberFieldFormat {
47
+ /** Shown before the digits: `$`, `€ `, `+`, `(`, `~`. */
48
+ prefix?: string;
49
+ /** Shown after the digits: `%`, `+`, `k`, ` / month`, ` €`, `)`. */
50
+ suffix?: string;
51
+ /** Thousands separator: `,` `.` ` ` (also no-break and narrow no-break space) `'`. `""` or absent = none. */
52
+ group?: string;
53
+ /** Decimal mark, `.` unless the site writes `,`. */
54
+ decimal?: "." | ",";
55
+ /** Fraction digits always shown (`2` for `£3.20`). A value with more keeps its own, up to six. */
56
+ decimals?: number;
57
+ }
58
+ /** The format a stored `config.format` holds, with anything malformed dropped: a bad row never throws at publish. */
59
+ declare function readNumberFormat(raw: unknown): NumberFieldFormat;
60
+ /** The number as the site shows it. A value that is no finite number prints as nothing. */
61
+ declare function formatNumber(value: number, format?: NumberFieldFormat): string;
62
+ /**
63
+ * A text that is ONE number and its presentation, or null.
64
+ *
65
+ * Null, on purpose, for: words around the number (`From £2,400`, `3 products`), a leading zero
66
+ * (`01`, `007`: a step marker, a code), digits grouped any other way than in threes (a phone
67
+ * number), two decimal marks (`1.2.3`), a minus (a dash is as often an ornament), an ordinal, and
68
+ * anything `formatNumber` would not print back exactly.
69
+ *
70
+ * `lang` (a BCP 47 tag) settles the one ambiguity, `1.234` and `1,234`, and names the thousands
71
+ * mark of a number too short to show one. `machine`: an attribute a script reads (`data-target`),
72
+ * which is plain digits and stays so.
73
+ */
74
+ declare function parseNumberText(text: string, opts?: {
75
+ lang?: string | null;
76
+ machine?: boolean;
77
+ }): {
78
+ value: number;
79
+ format: NumberFieldFormat;
80
+ } | null;
81
+
28
82
  /** Longest `description` a choice option may carry: one line under its label (V2's longest is 71). */
29
83
  declare const OPTION_DESCRIPTION_MAX = 140;
30
84
  /**
@@ -62,7 +116,7 @@ interface ContentModel {
62
116
  * by the API but normalized to `array` + zones on write, so stored/delivered
63
117
  * content never contains them.
64
118
  */
65
- type ContentModelFieldType = "text" | "richtext" | "document" | "image" | "boolean" | "number" | "select" | "reference" | "multi-reference" | "multiReference" | "array" | "date" | "datetime" | "longtext" | "slug" | "email" | "phone" | "link" | "color" | "json" | "file" | "component-ref" | "modular" | "sections" | "location" | "button" | "multiselect" | "icon" | "object" | "tags" | "rating" | "code";
119
+ type ContentModelFieldType = "text" | "richtext" | "document" | "image" | "boolean" | "number" | "select" | "reference" | "multi-reference" | "multiReference" | "array" | "date" | "datetime" | "longtext" | "slug" | "email" | "phone" | "link" | "color" | "json" | "file" | "component-ref" | "modular" | "sections" | "location" | "button" | "multiselect" | "icon" | "object" | "tags" | "rating" | "code" | "video" | "table" | "slot";
66
120
  type ContentModelKind = "model" | "block";
67
121
  /**
68
122
  * How a fieldset renders in the dock. ABSENT ≡ today's flat list (V2): a legacy `{id, name}`
@@ -147,23 +201,33 @@ interface ArrayZoneConfig {
147
201
  }
148
202
  /** Per-type config for a field (the typed shape behind the loose `config` bag). */
149
203
  interface FieldConfig {
150
- /** primitive array: list of scalars */
151
- itemType?: "text" | "number" | "date";
204
+ /**
205
+ * primitive array: list of scalars, or of images, links or rich text (V2 `array` of one
206
+ * primitive), each item judged by its own type's validator.
207
+ */
208
+ itemType?: "text" | "number" | "date" | "image" | "link" | "richtext";
152
209
  /** nested array: zoned fields (recursive) */
153
210
  zones?: ArrayZoneConfig;
154
211
  /** reference / multi-reference */
155
212
  contentModelId?: string;
156
213
  min?: number;
157
214
  max?: number;
215
+ /** number: how the value is shown on the site (`$1,299.00`, `38%`). @see NumberFieldFormat */
216
+ format?: NumberFieldFormat;
217
+ /** A derived field whose value lives in an ATTRIBUTE and is written there: `aria-label`, or the `data-target` a count-up script reads. */
218
+ attr?: string;
158
219
  /** date / datetime */
159
220
  includeTime?: boolean;
160
221
  /**
161
- * date / datetime with a time: "site" (the project's own zone) or an IANA zone name. When set,
162
- * a stored value must carry `Z` or a numeric offset, so it names one instant in every region.
222
+ * date / datetime with a time: "site" (the project's own zone), an IANA zone name, or V2 `true`
223
+ * (the editor picks a zone) / `false` (no zone, ≡ absent). When set (not false), a stored value
224
+ * must carry `Z` or a numeric offset, so it names one instant in every region.
163
225
  */
164
- timezone?: string;
165
- /** modular: SLUGS of the kind='block' models this field accepts. Non-empty. */
226
+ timezone?: string | boolean;
227
+ /** modular / slot: SLUGS of the kind='block' models this field accepts. Non-empty. */
166
228
  blockSlugs?: string[];
229
+ /** slot: per-child layout settings, what each child's `_settings` holds (leaf fields). */
230
+ slotSettings?: ContentModelField[];
167
231
  /** modular: bounds on how many block instances the field may hold; a primitive array (itemType): how many items. */
168
232
  minItems?: number;
169
233
  maxItems?: number;
@@ -200,8 +264,10 @@ interface FieldConfig {
200
264
  zoneId?: string;
201
265
  /** Explicit migration acknowledgement while the legacy allowlist remains readable. */
202
266
  legacyResolved?: boolean;
203
- /** number: a V2 numeric scale (stepped range or numeric steps, optional units and presets). */
267
+ /** number: a V2 scale (stepped range, numeric or token steps, units, presets, custom escape hatch). */
204
268
  scale?: NumberScale;
269
+ /** number: V2 `numeric.unit`, what it counts ("%", "USD", "days"), shown beside the input. 1–24 chars. */
270
+ unit?: string;
205
271
  /** number: V2 `validation.min / max`, the error bounds; they win over `min` / `max` (the input's range). */
206
272
  validation?: {
207
273
  min?: number;
@@ -225,7 +291,16 @@ interface FieldConfig {
225
291
  [key: string]: unknown;
226
292
  }
227
293
  type ScaleUnit = "px" | "%" | "rem" | "em" | "vw" | "vh";
228
- /** A number field's `config.scale` (V2 scale.ts), numeric values only. Editor-only. */
294
+ /** A V2 scale's custom value: a number in one of the scale's units. */
295
+ interface ScaleCustomValue {
296
+ value: number;
297
+ unit: ScaleUnit;
298
+ }
299
+ /**
300
+ * A number field's `config.scale` (V2 scale.ts, CPO D41). The value a field with a scale stores is
301
+ * a bare number (range or numeric steps), a token step's string value, or a {@link ScaleCustomValue}
302
+ * when `allowCustom` is set (within its bounds).
303
+ */
229
304
  interface NumberScale {
230
305
  steps: {
231
306
  min: number;
@@ -234,13 +309,25 @@ interface NumberScale {
234
309
  } | Array<{
235
310
  value: number;
236
311
  label?: string;
312
+ }> | Array<{
313
+ value: string;
314
+ label: string;
315
+ title?: string;
316
+ px?: number;
317
+ css?: string;
237
318
  }>;
238
319
  units?: ScaleUnit[];
239
320
  defaultUnit?: ScaleUnit;
240
- allowCustom?: boolean;
321
+ /** Fixed values only (false, absent) or fixed + custom: `true`, or the custom value's bounds. */
322
+ allowCustom?: boolean | {
323
+ min?: number | Partial<Record<ScaleUnit, number>>;
324
+ max?: number | Partial<Record<ScaleUnit, number>>;
325
+ units?: ScaleUnit[];
326
+ step?: number;
327
+ };
241
328
  presets?: Array<{
242
329
  label?: string;
243
- value: number;
330
+ value: number | string | ScaleCustomValue;
244
331
  }>;
245
332
  }
246
333
  /** V2: how a compound field (an `object`, or an array's rows) opens when edited. Editor-only. */
@@ -334,6 +421,12 @@ interface ContentModelField {
334
421
  readOnly?: true | "developer";
335
422
  /** Which system owns the value; shown on the refusal. At most 200 characters. */
336
423
  lockReason?: string;
424
+ /**
425
+ * V2 per-field localization (the locale chip). Once any field of a schema is marked, a
426
+ * translation row owns only its localized values; the rest are inherited from its source, and a
427
+ * translation write that changes one is 409 `FIELD_NOT_LOCALIZED`. None marked: rows copy as before.
428
+ */
429
+ localized?: boolean;
337
430
  /**
338
431
  * Authoring chrome — how the field PRESENTS in the editor. Never delivered, never read by a
339
432
  * renderer, and never able to move a value; the same contract as {@link placement}.
@@ -371,6 +464,8 @@ interface ContentModelFieldUi {
371
464
  media?: string;
372
465
  /** A literal row label while the title child is empty ("Untitled question"). Not a key. */
373
466
  fallback?: string;
467
+ /** The row's icon while it has no media (V2 `preview.icon`). */
468
+ icon?: DockIconName;
374
469
  };
375
470
  /**
376
471
  * How the ITEMS of a nesting field are arranged. ABSENT ≡ `"list"` — every field stored
@@ -396,11 +491,39 @@ interface ContentModelFieldUi {
396
491
  * `slider` on a `number` whose config.min < config.max; `rating` on a `number` with numeric
397
492
  * config.min, max and step (stars).
398
493
  */
399
- control?: "segmented" | "slider" | "rating";
494
+ control?: "segmented" | "slider" | "rating" | "dropdown" | "radio" | "cards" | "grid" | "switch" | "checkbox";
400
495
  /** The branch row's icon. Nesting fields only. */
401
496
  icon?: DockIconName;
402
- /** What one item is called ("Slide", "Member"), 1–24 chars. Nesting fields only. */
497
+ /** What one item is called ("Slide", "Member"), 1–24 chars (V2 itemNoun). Nesting fields and lists. */
403
498
  itemLabel?: string;
499
+ /** V2 `rows`: the lines a text box opens with (1–40). text / longtext only. */
500
+ rows?: number;
501
+ /** V2 `placeholder` on a field of any type. A prop keeps its own `placeholder`. */
502
+ placeholder?: string;
503
+ /** V2 item identity on a list: the item type's own name (an identifier) and title. */
504
+ itemName?: string;
505
+ itemTitle?: string;
506
+ /** V2 `synced`: the value comes from a global, so an edit applies everywhere. A marker. */
507
+ synced?: {
508
+ from: string;
509
+ };
510
+ /** V2 `valueShape`: a link / image / button writes a plain string or the object. */
511
+ valueShape?: "string" | "object";
512
+ /** V2 field access (D58): who sees and who changes it. The editor gates; the backend stores. */
513
+ access?: {
514
+ view?: "schema.view";
515
+ edit?: "schema.manage";
516
+ };
517
+ /** V2 `hidden`: true = never shown in the form; false ≡ absent. A conditional hide is `showIf`. */
518
+ hidden?: boolean;
519
+ /**
520
+ * V2 per-item chrome of a `modular` field (`of[i].icon` / `preview`), by block slug: how a row
521
+ * of that block type reads in this field. Each slug is one of `config.blockSlugs`.
522
+ */
523
+ blocks?: Record<string, {
524
+ icon?: DockIconName;
525
+ preview?: ContentModelFieldUi["preview"];
526
+ }>;
404
527
  /**
405
528
  * A custom dock input, by NAME: the project's own input (built with its site, served on its
406
529
  * own inputs origin, never the dashboard's) draws this field instead of the stock control.
@@ -550,7 +673,7 @@ type ButtonVariant = (typeof BUTTON_VARIANTS)[number];
550
673
  /** Each icon's inner SVG markup (viewBox `0 0 25 25`), by name. */
551
674
  declare const BUTTON_ICONS: Readonly<Record<DockIconName, string>>;
552
675
  type ButtonIcon = DockIconName;
553
- declare const BUTTON_ICON_NAMES: readonly ["access-denied", "activity", "add", "add-circle", "add-comment", "add-document", "add-user", "api", "archive", "arrow-down", "arrow-left", "arrow-right", "arrow-top-right", "arrow-up", "asterisk", "bar-chart", "basket", "bell", "bill", "binary-document", "block-content", "block-element", "blockquote", "bold", "bolt", "book", "bookmark", "bookmark-filled", "bottle", "bug", "bulb-filled", "bulb-outline", "calendar", "case", "chart-upward", "checkmark", "checkmark-circle", "chevron-down", "chevron-left", "chevron-right", "chevron-up", "circle", "clipboard", "clipboard-image", "clock", "close", "close-circle", "code", "code-block", "cog", "collapse", "color-wheel", "comment", "component", "compose", "compose-sparkles", "confetti", "controls", "copy", "credit-card", "crop", "cube", "dashboard", "database", "desktop", "diamond", "document", "document-pdf", "document-remove", "document-sheet", "document-text", "document-video", "document-word", "document-zip", "documents", "dot", "double-chevron-down", "double-chevron-left", "double-chevron-right", "double-chevron-up", "double-quote", "download", "drag-handle", "drop", "earth-americas", "earth-globe", "edit", "ellipsis-horizontal", "ellipsis-vertical", "empty", "enter", "enter-right", "envelope", "equal", "error-filled", "error-outline", "error-screen", "expand", "eye-closed", "eye-open", "face-happy", "face-indifferent", "face-sad", "feedback", "filter", "folder", "generate", "github", "groq", "hash", "heart", "heart-filled", "help-circle", "highlight", "home", "ice-cream", "image", "image-remove", "images", "inbox", "info-filled", "info-outline", "inline", "inline-element", "insert-above", "insert-below", "italic", "joystick", "json", "launch", "leave", "lemon", "link", "link-removed", "linkedin", "list", "lock", "logo-js", "logo-ts", "marker", "marker-removed", "master-detail", "menu", "microphone", "microphone-slash", "mobile-device", "moon", "number", "ok-hand", "olist", "overage", "package", "panel-left", "panel-right", "pause", "pin", "pin-filled", "pin-removed", "play", "plug", "presentation", "progress-50", "progress-75", "projects", "publish", "read-only", "redo", "refresh", "remove", "remove-circle", "reset", "restore", "retrieve", "retry", "revert", "robot", "rocket", "schema", "search", "select", "share", "sort", "sparkle", "sparkles", "spinner", "split-horizontal", "split-vertical", "square", "stack", "stack-compact", "star", "star-filled", "stop", "strikethrough", "string", "sun", "sync", "tablet-device", "tag", "tags", "target", "task", "terminal", "text", "th-large", "th-list", "thumbs-down", "thumbs-up", "tiers", "timeline", "toggle-arrow-right", "token", "transfer", "translate", "trash", "trend-upward", "triangle-outline", "trolley", "truncate", "twitter", "ulist", "unarchive", "underline", "undo", "unknown", "unlink", "unlock", "unpublish", "upload", "user", "users", "versions", "video", "warning-filled", "warning-outline", "wrench"];
676
+ declare const BUTTON_ICON_NAMES: readonly ["abc", "access-denied", "activity", "add", "add-circle", "add-comment", "add-document", "add-user", "address-book", "adjustments", "adjustments-horizontal", "alarm", "alert-triangle", "align-left", "api", "app-window", "apple", "apps", "archive", "arrow-back-up", "arrow-down", "arrow-guide", "arrow-left", "arrow-right", "arrow-top-right", "arrow-up", "arrows-diagonal", "arrows-down", "arrows-exchange", "arrows-horizontal", "arrows-left-right", "arrows-shuffle", "arrows-sort", "article", "aspect-ratio", "asterisk", "award", "axis-x", "backpack", "badge", "badge-cc", "badges", "bar-chart", "basket", "bell", "bill", "binary-document", "block-content", "block-element", "blockquote", "bold", "bolt", "book", "book-2", "bookmark", "bookmark-filled", "books", "bottle", "box", "brand-dribbble", "brand-facebook", "brand-instagram", "brand-linkedin", "brand-pinterest", "brand-tiktok", "brand-x", "brand-youtube", "briefcase", "broadcast", "browser", "bug", "building", "building-skyscraper", "building-store", "bulb-filled", "bulb-outline", "calculator", "calendar", "calendar-dollar", "calendar-event", "calendar-exclamation", "calendar-off", "calendar-plus", "calendar-star", "calendar-time", "camera", "campfire", "carousel-horizontal", "case", "cash", "category", "category-2", "chart-area", "chart-arrows", "chart-bar", "chart-bar-popular", "chart-donut", "chart-dots", "chart-line", "chart-upward", "check", "checkbox", "checklist", "checkmark", "checkmark-circle", "chef-hat", "chevron-down", "chevron-left", "chevron-right", "chevron-up", "chevrons-right", "circle", "circle-check", "circle-dot", "circle-number-1", "circle-plus", "click", "clipboard", "clipboard-image", "clipboard-text", "clock", "clock-check", "clock-hour-4", "close", "close-circle", "code", "code-block", "cog", "collapse", "color-wheel", "columns", "columns-2", "columns-3", "comment", "component", "compose", "compose-sparkles", "confetti", "controls", "cookie", "copy", "credit-card", "crop", "cube", "currency-dollar", "dashboard", "database", "database-search", "desktop", "device-desktop", "device-mobile", "device-tablet", "devices", "diamond", "discount", "document", "document-pdf", "document-remove", "document-sheet", "document-text", "document-video", "document-word", "document-zip", "documents", "door-exit", "dot", "double-chevron-down", "double-chevron-left", "double-chevron-right", "double-chevron-up", "double-quote", "download", "drag-handle", "drop", "droplet", "droplet-half", "earth-americas", "earth-globe", "edit", "egg", "ellipsis-horizontal", "ellipsis-vertical", "empty", "enter", "enter-right", "envelope", "equal", "error-filled", "error-outline", "error-screen", "expand", "eye-closed", "eye-off", "eye-open", "face-happy", "face-indifferent", "face-sad", "feather", "feedback", "file", "file-certificate", "file-code", "file-download", "file-text", "filter", "flag", "flame", "flask", "focus-2", "folder", "folders", "forms", "frame", "generate", "gift", "git-branch", "github", "grid-dots", "groq", "hammer", "hand-finger", "hanger", "hash", "headphones", "headset", "heart", "heart-filled", "heart-handshake", "help-circle", "highlight", "history", "home", "hourglass", "ice-cream", "id-badge", "id-badge-2", "image", "image-remove", "images", "inbox", "infinity", "info-circle", "info-filled", "info-outline", "info-square-rounded", "inline", "inline-element", "input-search", "insert-above", "insert-below", "italic", "joystick", "json", "language", "launch", "layout", "layout-align-center", "layout-board", "layout-board-split", "layout-bottombar", "layout-bottombar-expand", "layout-cards", "layout-columns", "layout-dashboard", "layout-grid", "layout-list", "layout-navbar", "layout-rows", "layout-sidebar", "layout-sidebar-right", "leaf", "leave", "lemon", "library-photo", "lifebuoy", "link", "link-removed", "linkedin", "list", "list-check", "list-details", "list-numbers", "list-tree", "lock", "logo-js", "logo-ts", "mail", "map-2", "map-pin", "map-pins", "marker", "marker-removed", "master-detail", "math-function", "meat", "menu", "message", "message-2", "message-check", "message-circle", "message-circle-2", "message-plus", "message-star", "microphone", "microphone-slash", "mobile-device", "mood-empty", "moon", "movie", "news", "notes", "number", "ok-hand", "olist", "overage", "package", "packages", "palette", "panel-left", "panel-right", "paperclip", "pause", "pencil", "phone", "photo", "photo-scan", "photo-search", "pig-money", "pin", "pin-filled", "pin-removed", "play", "player-play", "player-track-next", "playlist-add", "plug", "plug-connected", "plus-minus", "point", "presentation", "printer", "progress-50", "progress-75", "projects", "publish", "qrcode", "quote", "read-only", "receipt", "recycle", "redo", "refresh", "remove", "remove-circle", "repeat", "reset", "restore", "retrieve", "retry", "revert", "robot", "rocket", "rosette", "route", "ruler", "ruler-measure", "salad", "scale", "schema", "school", "search", "section", "select", "send", "server", "settings", "share", "shield-check", "shield-lock", "shopping-bag", "shopping-cart", "shopping-cart-plus", "signature", "sitemap", "slideshow", "sort", "sort-descending", "spacing-vertical", "sparkle", "sparkles", "speakerphone", "spinner", "split-horizontal", "split-vertical", "square", "stack", "stack-2", "stack-compact", "stairs", "stairs-up", "star", "star-filled", "stars", "stop", "strikethrough", "string", "subtask", "sun", "superscript", "sync", "table", "table-options", "tablet-device", "tag", "tags", "target", "task", "template", "tent", "terminal", "terminal-2", "text", "th-large", "th-list", "thumb-up", "thumbs-down", "thumbs-up", "ticket", "tiers", "timeline", "toggle-arrow-right", "toggle-right", "token", "tool", "tools-kitchen-2", "transfer", "translate", "trash", "trend-upward", "triangle-outline", "trolley", "truck", "truck-delivery", "truncate", "twitter", "typography", "ulist", "unarchive", "underline", "undo", "unknown", "unlink", "unlock", "unpublish", "upload", "user", "user-circle", "user-plus", "user-search", "user-star", "users", "users-group", "versions", "video", "vocabulary", "vs", "warning-filled", "warning-outline", "weight", "world", "wrench", "zoom-question"];
554
677
  /** A stored variant as it renders: anything off the list is Primary. */
555
678
  declare function buttonVariantOf(value: unknown): ButtonVariant;
556
679
  /**
@@ -1524,7 +1647,9 @@ declare const FOOTER_SECTION_ID: "footer";
1524
1647
 
1525
1648
  type LayoutZone = "above-page-content" | "below-page-content";
1526
1649
  type ReservedLayoutSection = "navigation" | "footer";
1527
- type LayoutScalarFieldType = "text" | "longtext" | "richtext" | "number" | "toggle" | "date" | "image" | "file" | "link" | "email" | "phone" | "select" | "color" | "json" | "reference" | "multi-reference";
1650
+ type LayoutScalarFieldType = "text" | "longtext" | "richtext" | "number" | "toggle" | "date" | "image" | "file" | "link"
1651
+ /** A call to action as one value, `{ label, href, variant? }`: what a page's `button` field holds. */
1652
+ | "button" | "email" | "phone" | "select" | "color" | "json" | "reference" | "multi-reference";
1528
1653
  type LayoutFieldType = LayoutScalarFieldType | "group" | "repeater";
1529
1654
  /** A recursive, stable-ID field contract shared by Sections and variant inputs. */
1530
1655
  interface LayoutFieldDefinition {
@@ -1858,7 +1983,15 @@ interface DeliveredLayout {
1858
1983
  id: string;
1859
1984
  kind: "field";
1860
1985
  fieldId: string;
1986
+ /** The stored value, unchanged. */
1861
1987
  value: unknown;
1988
+ /**
1989
+ * Present only when the field holds references: `value` with them hydrated (depth 1),
1990
+ * as Delivery serves an entry's (an entry → `{ id, slug, title, data, … }`, a page /
1991
+ * form / collection target → `{ kind, id, title, slug, url }`). A published read
1992
+ * resolves published targets only; one that did not resolve stays as stored.
1993
+ */
1994
+ resolved?: unknown;
1862
1995
  } | {
1863
1996
  id: string;
1864
1997
  kind: "component";
@@ -1934,7 +2067,7 @@ declare function visibleDeliveredLayout<T extends DeliveredLayout | null | undef
1934
2067
  *
1935
2068
  * A constant rather than three paraphrases, because updating some of them is exactly how this happened.
1936
2069
  */
1937
- declare const SECTION_DOCTRINE = "STRUCTURE (separate from schema): a page is composed of SECTIONS. NEVER build a page out of loose top-level heading/text/image/button/spacer blocks \u2014 they cannot be moved, duplicated or swapped as a unit, the visual editor cannot outline or name them, and every one of them becomes its own section in the editor. A hero of a headline, a lede and two CTAs is ONE section, not four. TWO SHAPES, and the choice is about REUSE. (1) A band that appears on more than one page, or that needs layout variants, is a COMPONENT with a `sectionType` \u2014 see create_component. Components sharing a `sectionType` are that section's VARIANTS (one Hero: 'Centered' for the home page and 'Two-column' for about, same prop keys so a swap keeps the content). This is also the only shape the editor's 'Add a section' picker can insert, and the only one that gets a family name and a variant switcher. (2) A genuinely one-off band on a single page is a `section` BLOCK whose `props.children` hold its blocks. THE TRADEOFF, stated in the present tense because it is real today: inside a component, ONLY the leaves a declared prop TARGETS are click-to-edit on the canvas \u2014 each declared prop's `target` is re-keyed to that PLACEMENT's own override address, so editing it changes this page and not the shared definition. A prop with no `target` still SHOWS as a dock control, but its override reaches no rendered slot, so editing it changes nothing on the page. Copy that no prop points at is worse still: no binding and no control, unreachable from click-to-edit AND from the dock, changeable only by editing the component definition, which rewrites every page that places it. A `section` block's children stay click-to-edit unconditionally. So when you choose a component, DECLARE A PROP \u2014 WITH A `target` \u2014 for every string, link and image a marketer will ever touch; a component with un-propped editable copy is the defect, not the component. In the dock an unset prop shows EMPTY and inherits the definition's default, so set props explicitly when you want the current copy visible there. An IMPORTED site's components are its own (read the repo); its nav, footer and modals are the Layout. On a blank site, do not hand-write a band's JSON: start from a built-in section blueprint (list_components returns locked `builtin:*` blueprints with no projectId \u2014 hero-centered, hero-split, feature-grid-three, cta-banner and nine more), each already rooted in a `section` block with its editable leaves declared as props. INLINE its blockJson as a `section` block for a one-off band; for a recurring band, materialize the blueprint with create_component so it becomes project-scoped before implementation validation, Output or publication. Direct `builtin:*` component references exist only for legacy delivery compatibility. Two consecutive call-to-action buttons are two sibling `button` blocks inside the same section \u2014 never a `columns` block, which is a `repeat(N,1fr)` grid and would stretch each CTA to half the container. Buttons are inline-level and flow side by side on their own.";
2070
+ declare const SECTION_DOCTRINE = "STRUCTURE (separate from schema): a page is composed of SECTIONS. NEVER build a page out of loose top-level heading/text/image/button/spacer blocks \u2014 they cannot be moved, duplicated or swapped as a unit, the visual editor cannot outline or name them, and every one of them becomes its own section in the editor. A hero of a headline, a lede and two CTAs is ONE section, not four. TWO SHAPES, and the choice is about REUSE. (1) A band that appears on more than one page, or that needs layout variants, is a COMPONENT with a `sectionType` \u2014 see create_component. Components sharing a `sectionType` are that section's VARIANTS (one Hero: 'Centered' for the home page and 'Two-column' for about, same prop keys so a swap keeps the content). This is also the only shape the editor's 'Add a section' picker can insert, and the only one that gets a family name and a variant switcher. (2) A genuinely one-off band on a single page is a `section` BLOCK whose `props.children` hold its blocks. THE TRADEOFF, stated in the present tense because it is real today: inside a component, ONLY the leaves a declared prop TARGETS are click-to-edit on the canvas \u2014 each declared prop's `target` is re-keyed to that PLACEMENT's own override address, so editing it changes this page and not the shared definition. A prop with no `target` still SHOWS as a dock control, but its override reaches no rendered slot, so editing it changes nothing on the page. Copy that no prop points at is worse still: no binding and no control, unreachable from click-to-edit AND from the dock, changeable only by editing the component definition, which rewrites every page that places it. A `section` block's children stay click-to-edit unconditionally. So when you choose a component, DECLARE A PROP \u2014 WITH A `target` \u2014 for every string, link and image a marketer will ever touch; a component with un-propped editable copy is the defect, not the component. In the dock an unset prop shows EMPTY and inherits the definition's default, so set props explicitly when you want the current copy visible there. An IMPORTED site's components are its own (read the repo); its nav, footer and modals are the Layout. On a blank site, do not hand-write a band's JSON: start from a built-in section blueprint (list_components returns locked `builtin:*` blueprints with no projectId \u2014 hero-centered, hero-split, feature-grid-three, cta-banner and more), each already rooted in a `section` block with its editable leaves declared as props. INLINE its blockJson as a `section` block for a one-off band; for a recurring band, materialize it with create_component `from` so it becomes project-scoped before implementation validation, Output or publication. Direct `builtin:*` component references exist only for legacy delivery compatibility. Two consecutive call-to-action buttons are two sibling `button` blocks inside the same section \u2014 never a `columns` block, which is a `repeat(N,1fr)` grid and would stretch each CTA to half the container. Buttons are inline-level and flow side by side on their own.";
1938
2071
  type ComponentCategory = "navbar" | "footer" | "button" | "section" | "slider" | "tabs" | "form" | "custom" | "hero" | "content" | "social-proof" | "conversion";
1939
2072
  /**
1940
2073
  * A single overridable field on a component. `target` points at the block + JSON
@@ -1953,7 +2086,7 @@ type ComponentCategory = "navbar" | "footer" | "button" | "section" | "slider" |
1953
2086
  *
1954
2087
  * Order is not semantic; append rather than re-sort, so a diff stays readable.
1955
2088
  */
1956
- declare const COMPONENT_PROP_TYPES: readonly ["text", "richtext", "image", "url", "boolean", "number", "select", "group", "table", "slot", "form", "link", "button", "date", "color", "file", "icon", "multiselect", "object", "datetime", "slug", "email", "phone", "json", "location", "tags", "rating", "code", "reference", "multi-reference"];
2089
+ declare const COMPONENT_PROP_TYPES: readonly ["text", "richtext", "image", "url", "boolean", "number", "select", "group", "table", "slot", "form", "link", "button", "date", "color", "file", "icon", "multiselect", "object", "datetime", "slug", "email", "phone", "json", "location", "tags", "rating", "code", "reference", "multi-reference", "video", "array", "longtext"];
1957
2090
  type ComponentPropType = (typeof COMPONENT_PROP_TYPES)[number];
1958
2091
  /**
1959
2092
  * The value a `form` prop STORES: just the id. The form itself is a Form document and stays the
@@ -1999,7 +2132,11 @@ interface ComponentPropDef {
1999
2132
  * number → a number (heading.level, columns.count)
2000
2133
  * select → one string from `config.options`
2001
2134
  * group → an object keyed by `config.fields`
2002
- * table → an array of such objects (slider.slides)
2135
+ * table → an array of such objects (slider.slides); with `config.mode: "data"` instead ONE
2136
+ * V2 `TableValue` (typed, keyed columns × keyed rows, table-value.ts), the value a
2137
+ * `table` FIELD stores. Aimed at a text or richtext block's `props.html` it renders
2138
+ * as the semantic HTML table. With `config.mode: "types"` a V2 polymorphic list: rows of
2139
+ * several item types (`config.itemTypes`), each row naming its type in `_type`.
2003
2140
  * link → an href string (URL, internal path or #fragment)
2004
2141
  * button → ONE `ButtonValue` (button-look.ts): label, href and look as a unit, never a text prop plus
2005
2142
  * a url prop that drift apart. Targets the `props` of a `button` block.
@@ -2016,6 +2153,11 @@ interface ComponentPropDef {
2016
2153
  * list of them (`config.contentModelId`, or `polymorphic` + `allowedModelSlugs`;
2017
2154
  * `min`/`max` on the list). Delivery and preview hydrate the ids in a page's overrides
2018
2155
  * to entries at the read's `depth`; a plain-text slot renders the entry's title.
2156
+ * video → a URL string or `{ url, poster?, autoplay?, loop?, transcript? }` (the video
2157
+ * block's props; aimed at a video block it lands as them) @see VideoValue
2158
+ * array → a list of `config.itemType` values: text, number, date, image, link or richtext
2159
+ * (the model field's primitive `array`; a list of objects is a `table`)
2160
+ * longtext → a multi-line string (the model field `longtext`; `text` is one line)
2019
2161
  */
2020
2162
  type: ComponentPropType;
2021
2163
  defaultValue?: unknown;
@@ -2057,6 +2199,8 @@ interface ComponentPropDef {
2057
2199
  */
2058
2200
  readOnly?: true | "developer";
2059
2201
  lockReason?: string;
2202
+ /** V2 per-field localization (the locale chip): a stored marker, as on a model field. */
2203
+ localized?: boolean;
2060
2204
  /** Per-type settings; the save schema enforces that each is present on the type needing it. */
2061
2205
  config?: {
2062
2206
  /** `slot` — a pick allowlist. */
@@ -2066,6 +2210,20 @@ interface ComponentPropDef {
2066
2210
  /** `slot` with `multiple` — bounds on the list. `maxItems` defaults to {@link SLOT_MAX_ITEMS}. */
2067
2211
  minItems?: number;
2068
2212
  maxItems?: number;
2213
+ /**
2214
+ * `slot` — per-child layout settings (V2 `slotSettings`, e.g. a bento span): what a V2 child's
2215
+ * `_settings` holds (`{ _key, _type, _settings, ...props }`, slot-child.ts). Leaf sub-fields.
2216
+ */
2217
+ slotSettings?: ComponentSubField[];
2218
+ /**
2219
+ * `table` with `mode: "types"` — a V2 polymorphic list: each row is ONE of these item types,
2220
+ * named by the row's `_type` (`{ _key?, _type, ...values }`), its values keyed by that type's `fields`.
2221
+ */
2222
+ itemTypes?: Array<{
2223
+ name: string;
2224
+ label?: string;
2225
+ fields: ComponentSubField[];
2226
+ }>;
2069
2227
  /**
2070
2228
  * `select` / `multiselect` — the choices. Required, and a default must be one of them. `{ label, value }`
2071
2229
  * when the stored value is not what an author should read (a component id, for instance).
@@ -2073,6 +2231,12 @@ interface ComponentPropDef {
2073
2231
  options?: Array<string | ChoiceOption>;
2074
2232
  /** `group` / `table` / `object` — the sub-shape; 10 levels at most, counting the prop (MAX_FIELD_DEPTH). */
2075
2233
  fields?: ComponentSubField[];
2234
+ /**
2235
+ * `table` — which value it holds: `"rows"` (the default, an array of `fields` rows) or
2236
+ * `"data"` (one V2 TableValue, with the table field's options beside it: columnTypes,
2237
+ * lockColumns, minRows, maxRows, maxColumns, requireCaption, …). A data table has no `fields`.
2238
+ */
2239
+ mode?: "rows" | "data" | "types";
2076
2240
  /** `number` — bounds for the control; `multiselect` / `tags` / `multi-reference` — how many items. */
2077
2241
  min?: number;
2078
2242
  max?: number;
@@ -2124,6 +2288,12 @@ interface PropGroup {
2124
2288
  kind?: Exclude<FieldsetKind, "tab">;
2125
2289
  icon?: DockIconName;
2126
2290
  collapsed?: boolean;
2291
+ /** V2 fieldset keys (CPO D45), on the defining prop: a line under the header (≤200), members side by side, a static header, a breakpoint switcher, and its place among the groups (0–99; absent = where its first prop sits). */
2292
+ description?: string;
2293
+ columns?: 1 | 2;
2294
+ collapsible?: boolean;
2295
+ layout?: "stack" | "breakpoints";
2296
+ order?: number;
2127
2297
  }
2128
2298
  /** A prop's `ui`: the field-lane chrome plus its inline {@link PropGroup}. */
2129
2299
  type ComponentPropUi = ContentModelFieldUi & {
@@ -2150,7 +2320,13 @@ interface ComponentSubField {
2150
2320
  unique?: boolean;
2151
2321
  openMode?: OpenMode;
2152
2322
  showIf?: ShowIf;
2153
- ui?: ContentModelFieldUi;
2323
+ /** The prop's `ui`, inline group included: V2 fieldsets nest, so sub-fields group too. */
2324
+ ui?: ComponentPropUi;
2325
+ /** V2 sub-field read-only / developer lock: stored markers, as on the prop. `"developer"` needs a lockReason. */
2326
+ readOnly?: true | "developer";
2327
+ lockReason?: string;
2328
+ /** V2 per-field localization: a stored marker, as on the prop. */
2329
+ localized?: boolean;
2154
2330
  /** CANONICAL. A nested `group`/`table`/`object`'s own sub-shape. */
2155
2331
  fields?: ComponentSubField[];
2156
2332
  /**
@@ -2282,6 +2458,66 @@ interface DeliveryComponent {
2282
2458
  props: ComponentPropDef[];
2283
2459
  }
2284
2460
 
2461
+ /**
2462
+ * V2 slot children (DESIGN.md, V2 `engine/slot.tsx`): blocks inside a block, stored INLINE as
2463
+ * `{ _key, _type, _variant?, _settings?, ...values }`. The block's own values sit at the child's
2464
+ * root, beside four reserved keys:
2465
+ *
2466
+ * _key the child's stable identity (reorders, diffs, React keys). Unique in its slot.
2467
+ * _type the block type: a `kind: 'block'` model's SLUG on a model's `slot` field, a
2468
+ * component's ID on a `slot` prop.
2469
+ * _variant a block variant (layout) name. Model slots only: a component variant is its own
2470
+ * component in BetterCMS, so a prop slot names it in `_type`.
2471
+ * _settings per-child layout settings, keyed by the slot's `slotSettings`.
2472
+ *
2473
+ * The same `_key` / `_type` pair discriminates the items of a polymorphic list prop (a `table` prop
2474
+ * with `config.mode: "types"`): `_type` names one of its `config.itemTypes`.
2475
+ *
2476
+ * Pure: shape only. Whether a block type exists, is allowed, and whether a child's values fit it,
2477
+ * is the caller's (it knows the block models or the components).
2478
+ */
2479
+ /** The reserved keys of a slot child; every other key is one of the block's own values. */
2480
+ declare const SLOT_CHILD_KEYS: readonly ["_key", "_type", "_variant", "_settings"];
2481
+ /** One block inside a V2 slot. @see SLOT_CHILD_KEYS */
2482
+ interface SlotChild {
2483
+ _key: string;
2484
+ _type: string;
2485
+ _variant?: string;
2486
+ _settings?: Record<string, unknown>;
2487
+ [value: string]: unknown;
2488
+ }
2489
+ /** Is this a V2 slot child (an object naming its block type in `_type`)? */
2490
+ declare const isSlotChild: (v: unknown) => v is SlotChild;
2491
+ /** A slot child's own values: everything but the reserved keys (a new object; the values are shared). */
2492
+ declare function slotChildValues(child: Record<string, unknown>): Record<string, unknown>;
2493
+ type SlotShapeProblem = {
2494
+ path: Array<string | number>;
2495
+ code: string;
2496
+ message: string;
2497
+ };
2498
+ type SlotShapeOptions = {
2499
+ /** Bounds on the list. `max` is clamped by the caller's hard cap. */
2500
+ min?: number;
2501
+ max?: number;
2502
+ /** Does the slot declare `slotSettings`? A `_settings` is refused without them. */
2503
+ settings?: boolean;
2504
+ /** May a child name a `_variant`? (model slots yes, prop slots no) */
2505
+ variants?: boolean;
2506
+ /** What the list is called in messages ("Body", "slot 'cards'"). */
2507
+ label?: string;
2508
+ /** What `_type` names, for messages ("a block model slug", "a component id"). */
2509
+ typeNoun?: string;
2510
+ };
2511
+ /**
2512
+ * Why a value cannot be a slot's list of children, each at its path inside the value (`[2, "_key"]`),
2513
+ * codes first in each message. Shape only: a list of objects, each with a non-empty `_key` (unique)
2514
+ * and `_type`, `_variant` a string where allowed, `_settings` an object where declared, no other
2515
+ * `_`-prefixed key (a typo'd reserved key would otherwise be stored as a value nothing reads).
2516
+ */
2517
+ declare function slotShapeProblems(value: unknown, opts?: SlotShapeOptions): SlotShapeProblem[];
2518
+ /** `rows[2]._key`-style path text for a problem path. */
2519
+ declare const slotPathString: (path: Array<string | number>) => string;
2520
+
2285
2521
  /**
2286
2522
  * The dock's click budget, as ONE pure function both ends read (V9): the backend's next-steps
2287
2523
  * rules call it on live data, and the dashboard's reach test measures its RENDERED dock against the
@@ -2451,6 +2687,210 @@ declare function derivedPairs(candidates: readonly ButtonLinkCandidate[]): Map<n
2451
2687
  /** Every unambiguous pair in one sibling list, as `[textIndex, linkIndex]`, in list order. */
2452
2688
  declare function buttonLinkPairs(candidates: readonly ButtonLinkCandidate[]): Array<[number, number]>;
2453
2689
 
2690
+ /**
2691
+ * The V2 video value (DESIGN.md §6.2, §8.15): a pasted provider link or a file URL, as a bare
2692
+ * string or as `{ url, poster?, autoplay?, loop?, transcript? }`.
2693
+ *
2694
+ * The object's keys are the `video` block's own props (`VideoProps`, block.ts), so a video prop
2695
+ * aimed at a video block lands as that block's props unchanged, and a video field renders the way
2696
+ * the block does. Any other key is refused by name (`video_value_invalid`), never dropped.
2697
+ */
2698
+ /** The keys a video object may carry: exactly the `video` block's props. */
2699
+ declare const VIDEO_VALUE_KEYS: readonly ["url", "poster", "autoplay", "loop", "transcript"];
2700
+ /** A video value's object form. A bare string is the same value with only `url`. */
2701
+ interface VideoValue {
2702
+ url: string;
2703
+ poster?: string;
2704
+ autoplay?: boolean;
2705
+ loop?: boolean;
2706
+ transcript?: string;
2707
+ }
2708
+ /** Same cap as the video block's transcript (CPO-093). */
2709
+ declare const VIDEO_TRANSCRIPT_MAX = 100000;
2710
+ /** The url a video value plays, or null when it holds none (a bare string is its url). */
2711
+ declare function videoUrlOf(value: unknown): string | null;
2712
+ /** Why `value` is not a video value, or null when it is. Every message starts `video_value_invalid:`. */
2713
+ declare function videoValueProblem(value: unknown): string | null;
2714
+
2715
+ declare const TABLE_COLUMN_TYPES: readonly ["text", "number", "money", "boolean", "rating", "link", "richtext-inline", "reference"];
2716
+ type TableColumnType = (typeof TABLE_COLUMN_TYPES)[number];
2717
+ declare const TABLE_RESPONSIVE: readonly ["scroll", "stack", "cards"];
2718
+ type TableResponsive = (typeof TABLE_RESPONSIVE)[number];
2719
+ declare const TABLE_JSONLD_TYPES: readonly ["none", "ItemList", "Dataset", "Offers"];
2720
+ type TableJsonLdType = (typeof TABLE_JSONLD_TYPES)[number];
2721
+ /** Hard limits, whatever a field allows: past these a table is a dataset, not page content. */
2722
+ declare const TABLE_LIMITS: {
2723
+ readonly columns: 50;
2724
+ readonly rows: 1000;
2725
+ readonly cellChars: 5000;
2726
+ readonly captionChars: 300;
2727
+ readonly notesChars: 2000;
2728
+ readonly keyChars: 64;
2729
+ readonly labelChars: 300;
2730
+ };
2731
+ interface TableColumn {
2732
+ _key: string;
2733
+ label: string;
2734
+ type: TableColumnType;
2735
+ description?: string;
2736
+ unit?: string;
2737
+ currency?: string;
2738
+ decimals?: number;
2739
+ align?: "start" | "center" | "end";
2740
+ sortable?: boolean;
2741
+ group?: string;
2742
+ trueLabel?: string;
2743
+ falseLabel?: string;
2744
+ max?: number;
2745
+ refTo?: string[];
2746
+ highlight?: boolean;
2747
+ }
2748
+ interface TableGroup {
2749
+ _key: string;
2750
+ label: string;
2751
+ }
2752
+ interface TableLink {
2753
+ label: string;
2754
+ href: string;
2755
+ newTab?: boolean;
2756
+ rel?: "follow" | "nofollow" | "ugc" | "sponsored";
2757
+ }
2758
+ /** What a read that resolves references writes onto a reference cell (never stored). */
2759
+ interface TableRefResolved {
2760
+ kind: "page" | "entry";
2761
+ id: string;
2762
+ title: string;
2763
+ slug: string | null;
2764
+ url: string | null;
2765
+ }
2766
+ interface TableRef {
2767
+ ref: string;
2768
+ label?: string;
2769
+ href?: string;
2770
+ resolved?: TableRefResolved;
2771
+ }
2772
+ type TableCellValue = string | number | boolean | null | TableLink | TableRef;
2773
+ interface TableCellObject {
2774
+ value: TableCellValue;
2775
+ type?: TableColumnType;
2776
+ note?: string;
2777
+ }
2778
+ type TableCell = TableCellValue | TableCellObject;
2779
+ interface TableRow {
2780
+ _key: string;
2781
+ cells: Record<string, TableCell | undefined>;
2782
+ group?: string;
2783
+ footer?: boolean;
2784
+ type?: TableColumnType;
2785
+ highlight?: boolean;
2786
+ }
2787
+ interface TableFootnote {
2788
+ _key: string;
2789
+ text: string;
2790
+ }
2791
+ interface TableValue {
2792
+ id?: string;
2793
+ caption: string;
2794
+ notes?: string;
2795
+ headerRow: boolean;
2796
+ headerColumn: boolean;
2797
+ columns: TableColumn[];
2798
+ columnGroups?: TableGroup[];
2799
+ rowGroups?: TableGroup[];
2800
+ rows: TableRow[];
2801
+ footnotes?: TableFootnote[];
2802
+ filterable?: boolean;
2803
+ design?: {
2804
+ responsive?: TableResponsive;
2805
+ sticky?: boolean;
2806
+ striped?: boolean;
2807
+ density?: "compact" | "comfortable";
2808
+ hideCaption?: boolean;
2809
+ };
2810
+ jsonLd?: {
2811
+ type: TableJsonLdType;
2812
+ axis?: "rows" | "columns";
2813
+ priceRow?: string;
2814
+ };
2815
+ }
2816
+ /** The field-level options (`config` of a `table` field, or of a `table` prop in `mode: "data"`). */
2817
+ interface TableFieldOptions {
2818
+ columnTypes?: TableColumnType[];
2819
+ lockColumns?: boolean;
2820
+ minRows?: number;
2821
+ maxRows?: number;
2822
+ maxColumns?: number;
2823
+ requireCaption?: boolean;
2824
+ allowGroups?: boolean;
2825
+ allowFootnotes?: boolean;
2826
+ allowNote?: boolean;
2827
+ settings?: {
2828
+ headers?: boolean;
2829
+ totals?: boolean;
2830
+ phones?: TableResponsive[];
2831
+ highlight?: boolean;
2832
+ sticky?: boolean;
2833
+ sort?: boolean;
2834
+ search?: boolean;
2835
+ };
2836
+ jsonLd?: Exclude<TableJsonLdType, "none">[];
2837
+ }
2838
+ /** A value shaped like a table (`columns` and `rows` arrays): what a walker hands to the table lane. */
2839
+ declare const isTableValue: (v: unknown) => v is TableValue;
2840
+ type TableProblem = {
2841
+ path: Array<string | number>;
2842
+ code: string;
2843
+ message: string;
2844
+ };
2845
+ type TableCheckOptions = TableFieldOptions & {
2846
+ /** The columns a `lockColumns` table must keep (the field's default table): same keys, types and order. */
2847
+ lockedColumns?: ReadonlyArray<{
2848
+ _key: string;
2849
+ type: string;
2850
+ }>;
2851
+ /** The caller's href grammar (which relative forms a site may hold); script hrefs are always refused. */
2852
+ hrefProblem?: (href: string) => string | null;
2853
+ };
2854
+ /**
2855
+ * Every reason `value` is not a table this field takes, each at its own path inside the value
2856
+ * (`rows[2].cells.price`). Empty when it is one. Cells whose words do not match their column's type
2857
+ * (text in a number column) are accepted, as V2 accepts them: the type decides formatting, and the
2858
+ * editor warns. A cell OBJECT must match its type (a link in a link cell, a reference in a reference
2859
+ * cell), so nothing is stored that the renderer would drop.
2860
+ */
2861
+ declare function tableValueProblems(value: unknown, opts?: TableCheckOptions): TableProblem[];
2862
+ /** A {@link TableProblem}'s path as the dotted / indexed string error maps use: `rows[2].cells.price`. */
2863
+ declare function tablePathString(path: ReadonlyArray<string | number>): string;
2864
+ /**
2865
+ * The stored form of a table value: explicit `headerRow` / `headerColumn`, and no `resolved` on a
2866
+ * reference cell (a read writes it; a client echoing a read back must not store it). Everything
2867
+ * else is kept as sent. A value that is not table-shaped is returned as is, for the validator.
2868
+ */
2869
+ declare function normalizeTableValue<T>(value: T): T;
2870
+ /** Every reference cell a table holds: the object (resolved in place by a read), its id, path and column's `refTo`. */
2871
+ declare function tableRefCells(value: unknown): Array<{
2872
+ cell: TableRef;
2873
+ id: string;
2874
+ path: Array<string | number>;
2875
+ refTo: string[] | null;
2876
+ }>;
2877
+ /** The words a cell says (Markdown, search, screen readers). Booleans say their words, never a tick. */
2878
+ declare function tableCellText(col: TableColumn, row: TableRow | undefined, c: unknown): string;
2879
+ /**
2880
+ * The table as semantic HTML (published form: no editing marks): `<figure class="bt-table">` ›
2881
+ * `<table>` with caption, column-group headers, `<thead>`, one `<tbody>` per row group, `<tfoot>`,
2882
+ * then notes and footnotes. Stack / cards layouts restate the table roles (CSS display drops them).
2883
+ */
2884
+ declare function renderTableHtml(input: TableValue): string;
2885
+ /**
2886
+ * The table as GFM: the caption in bold above, one header row (a column group prefixes its
2887
+ * columns: "Sizes · Chest"), a row group as a bold label row, then notes, column descriptions and
2888
+ * footnotes. Booleans say their words. Links and resolved references are Markdown links.
2889
+ */
2890
+ declare function tableToMarkdown(input: TableValue): string;
2891
+ /** The words a table holds, for site search: caption, notes, headers, group labels, every cell's text, footnotes. */
2892
+ declare function tableSearchText(input: unknown): string;
2893
+
2454
2894
  /**
2455
2895
  * ContentEntry — a single unit of content, representing the
2456
2896
  * published layout of a page: a collection of ordered blocks
@@ -2591,18 +3031,41 @@ interface DeliveryEntry<T = Record<string, unknown>> {
2591
3031
  */
2592
3032
  interface PageMetaJson {
2593
3033
  canonical?: string;
3034
+ /** The card. `image*` describe `image`; `locale` is `og:locale`, `localeAlternate` every `og:locale:alternate`. */
2594
3035
  og?: {
2595
3036
  title?: string;
2596
3037
  description?: string;
2597
3038
  image?: string;
2598
3039
  type?: string;
3040
+ imageWidth?: number;
3041
+ imageHeight?: number;
3042
+ imageAlt?: string;
3043
+ locale?: string;
3044
+ localeAlternate?: string[];
3045
+ siteName?: string;
2599
3046
  };
2600
3047
  twitter?: {
2601
3048
  card?: string;
2602
3049
  title?: string;
2603
3050
  description?: string;
2604
3051
  image?: string;
3052
+ imageAlt?: string;
3053
+ site?: string;
3054
+ creator?: string;
3055
+ };
3056
+ /** `article:*`: published and modified times (ISO 8601), author, section, tags. */
3057
+ article?: {
3058
+ publishedTime?: string;
3059
+ modifiedTime?: string;
3060
+ author?: string;
3061
+ section?: string;
3062
+ tags?: string[];
2605
3063
  };
3064
+ /** `<link rel="alternate" hreflang>`: the same page in other languages. */
3065
+ alternates?: Array<{
3066
+ hreflang: string;
3067
+ href: string;
3068
+ }>;
2606
3069
  schema?: Record<string, unknown> | Array<Record<string, unknown>>;
2607
3070
  }
2608
3071
  /** `DeliveryEntry.seo`: the page meta shape plus the entry's flat title, description and noindex. */
@@ -2624,10 +3087,18 @@ interface SiteSeoDefaults {
2624
3087
  og?: {
2625
3088
  image?: string;
2626
3089
  type?: string;
3090
+ siteName?: string;
3091
+ locale?: string;
2627
3092
  };
2628
3093
  twitter?: {
2629
3094
  card?: string;
2630
3095
  };
3096
+ /** The feeds the site links from every page (`<link rel="alternate" type="application/rss+xml">`). */
3097
+ feeds?: Array<{
3098
+ type: string;
3099
+ href: string;
3100
+ title?: string;
3101
+ }>;
2631
3102
  /** Site-wide JSON-LD emitted alongside the page's own `schema`. */
2632
3103
  siteSchema?: Record<string, unknown> | Array<Record<string, unknown>>;
2633
3104
  }
@@ -3079,4 +3550,77 @@ declare function regionOf<E extends {
3079
3550
  el: E;
3080
3551
  }[], el: unknown): string | null;
3081
3552
 
3082
- export { type AlignToken, type ApiError, type ApiKey, type ApiKeyPermission, type ApiKeyTokenType, type ArrayZoneConfig, type AssertEqual, type AuthResponse, type AuthSession, type AuthUser, BLOCK_BINDINGS, BREAKPOINTS, BUTTON_ICONS, BUTTON_ICON_NAMES, BUTTON_LOOK_KEYS, BUTTON_PLACEMENT_KEYS, BUTTON_SIZES, BUTTON_VARIANTS, type BetterCMSErrorCode, type BgToken, type BindingKind, type BlockBinding, type BlockHoverStyle, type BlockStyle, type BlockType, type ButtonBlock, type ButtonIcon, type ButtonLinkCandidate, type ButtonLookKey, type ButtonProps, type ButtonSiteLook, type ButtonSizeName, type ButtonValue, type ButtonVariant, COMPONENT_PROP_TYPES, type CanonicalInputDefinition, type ChoiceOption, type CollectionBlock, type CollectionFilter, type CollectionProps, type ColorToken, type ColumnsBlock, type ColumnsProps, type Component, type ComponentBlock, type ComponentCategory, type ComponentFormPropRef, type ComponentPropDef, type ComponentPropType, type ComponentPropUi, type ComponentProps, type ComponentSubField, type ComponentVariantGroup, type Content, type ContentBlock, type ContentEntry, type ContentModel, type ContentModelField, type ContentModelFieldType, type ContentModelFieldUi, type ContentPageResult, type ContentResponse, type ContentWidthToken, type CornerToken, DIALOG_SELECTOR, DOCK_BUDGET, DOCK_ICON_NAMES, DOCK_ICON_NAME_SET, type DeepReadonly, type DeliveredLayout, type DeliveryComponent, type DeliveryEntry, type DeliveryEntrySeo, type DeliveryList, type DeliveryPage, type DerivedLocator, type DockBudget, type DockFieldLike, type DockFieldsetLike, type DockIconName, type DockInputRef, type DockLane, type DockNode, type DockPropGroupLike, type DockScreen, type ElementLike, type ExpandedBinding, FIELD_SIZE_ZOOM, FIELD_STYLE_KEYS, FOOTER_SECTION_ID, type FieldConfig, type FieldSize, type FieldStyle, type FieldStyleKey, type FieldStyles, type Fieldset, type FieldsetKind, type FieldsetUiBefore, type FontSizeToken, type FooterBlock, type FooterColumn, type FooterProps, type Form, type FormBlock, type FormField, type FormProps, type FormSubmission, type HeadingBlock, type HeadingProps, type ImageBlock, type ImageProps, LANDMARK_SELECTOR, LAYOUT_SECTION_ICONS, LAYOUT_SECTION_ICON_SET, LINK_RELS, LINK_VALUE_TYPES, type LandmarkChainElement, type LandmarkElement, type LayoutComponentItem, type LayoutDataDocument, type LayoutFieldDefinition, type LayoutFieldItem, type LayoutFieldType, type LayoutScalarFieldType, type LayoutSection, type LayoutSectionIcon, type LayoutSectionItem, type LayoutStructureDocument, type LayoutZone, type LinkRel, type LinkValue, type LinkValueType, type LocatorGrammar, MAIN_SELECTOR, type ManagementLayoutCommand, type MediaAsset, type MediaCaptionTrack, type MediaFieldValue, NAVIGATION_SECTION_ID, type NavLink, type NavbarBlock, type NavbarProps, type NumberScale, OPTION_DESCRIPTION_MAX, type OpenMode, PAGE_CONTENT_ANCHOR_ID, type Page, type PageLayoutOverrideDataDocument, type PageLayoutOverrideDocument, type PageLayoutOverrideState, type PageLayoutOverrideStructureDocument, type PageLayoutSectionOverride, type PageLayoutSectionStructureOverride, type PageMetaJson, type PageOnlyLayoutSection, type PageSectionPlacement, type PaginatedResult, type Perspective, type PortableTextDocument, type PortableTextNode, type PropGroup, RESPONSIVE_CSS, type RadiusToken, type ReadButtonValue, type Redirect, type ReservedLayoutSection, type ResolvedLayoutNode, type RichTextBlock, type RichTextProps, SECTION_DOCTRINE, SECTION_SPACE_TOKENS, SLOT_ITEMS_CAP, SLOT_MAX_ITEMS, SPACE_BOTTOM_TOKENS, SPACE_STEP_TOKENS, type ScaleUnit, type SectionBlock, type SectionProps, type SectionSpaceToken, type ShadowToken, type ShowIf, type ShowIfRule, type SignInInput, type SignUpInput, type SiteSeoDefaults, type SlideItem, type SliderBlock, type SliderProps, type SlotItem, type SlotValue, type SpaceStepToken, type SpaceToken, type SpacerBlock, type SpacerProps, type TabItem, type TabsBlock, type TabsProps, type TextBlock, type TextProps, type ThemeToken, type UiBefore, type UiOrigin, type VariantInputMapping, type VideoBlock, type VideoProps, type VisibilityWindow, type WeightToken, type WindowState, type Workspace, type ZoneField, anchorTargetRel, blockStyleToColumnCss, blockStyleToCss, blockStyleToInnerCss, buttonBlockProps, buttonIconOf, buttonIconSvg, buttonLinkPairs, buttonLookValue, buttonSiteLookOf, buttonValueOfInstance, buttonValueProblem, buttonVariantOf, candidateRole, componentInstanceAddresses, componentPropTargetKey, derivedPairs, dockBudget, dockScreens, expandBlockBindings, fieldStyleCssText, fieldStyleToCss, formatPropsAttribute, getBlockType, headingPaintCss, hideOnAttr, inWindow, isBlock, isButtonLookValue, isChromeLandmark, isLinkObject, isScriptHref, keyWords, landmarkRegions, linkAnchorOf, linkHref, linkRefOf, linkValueProblem, locatorFor, normalizeLinkValue, normalizeWindow, parsePropsAttribute, pickFieldStyle, readButtonValue, readPath, regionOf, safeCssUrl, slotItems, spaceTokenCss, splitButtonStyle, usesHideOn, visibleBlocks, visibleDeliveredLayout, visibleLayoutStructure, windowState, withButtonLookProps };
3553
+ /**
3554
+ * `<BcmsSections>`: which of a page's sections render, in what order, and which block each one is.
3555
+ *
3556
+ * A code-built page passes every section it can draw as a named SLOT; the CMS page's block list
3557
+ * says the order. This is the one place that joins the two, shared by @bettercms-ai/astro and
3558
+ * @bettercms-ai/next so a site renders the same list on either. The backend reads a placement's
3559
+ * group through the same `placementBindOf`, so a slot's name is the id the platform measured.
3560
+ *
3561
+ * Pure: no DOM, no framework, no I/O.
3562
+ */
3563
+ /**
3564
+ * The tag-shaped heads the derive lane mints keys from (`h1-welcome`, `p-we-build-things`,
3565
+ * `img-logo`, `list-benefits`, `a-contact`). A key whose head is one of these names an ELEMENT,
3566
+ * not a section family, so it has no group root.
3567
+ *
3568
+ * 🔴 NOT ONLY TEXT TAGS. Derive also keys a text leaf found by SHAPE by its own tag (`span-dismiss`,
3569
+ * `div-samantha-ruiz`, `time-…`) and a media leaf by its kind (`icon-icon`, `bg-…`). Missing here,
3570
+ * each of those heads read as a FAMILY: an unmarked announcement bar became components called
3571
+ * "Span" and "Icon".
3572
+ */
3573
+ declare const TAG_HEADS: ReadonlySet<string>;
3574
+ /** The top-level field key a path belongs to: `hero.title` → `hero`, `faq[0].q` → `faq`. */
3575
+ declare const topFieldKeyOf: (path: string) => string;
3576
+ /**
3577
+ * The GROUP a top-level field key belongs to, and whether that group has a real root.
3578
+ *
3579
+ * Two shapes are groups: a repeater the derive lane already folded (`group-*`), and a family prefix
3580
+ * on an authored or renamed key (`hero-title`, `hero.title` → `hero`). Everything else is a bare
3581
+ * element key with no family, and grouping those by their tag would mint one section per heading.
3582
+ */
3583
+ declare function fieldGroupOf(topKey: string, flat?: boolean): {
3584
+ groupKey: string;
3585
+ rooted: boolean;
3586
+ };
3587
+ /**
3588
+ * The GROUP a placement renders, or null if this block is not a placement of the site's own code.
3589
+ *
3590
+ * Two spellings: `props.bind` says the group outright; `props.source` (`{ propKey: "<page path>" }`)
3591
+ * is what is left once the copy moved onto the instance, and the group is derived from it. A
3592
+ * section added from the library carries neither, which is how it is told apart: the site's code
3593
+ * has nothing to draw it with.
3594
+ */
3595
+ declare function placementBindOf(block: unknown): string | null;
3596
+ /**
3597
+ * A slot the CMS was not known to hold when the page was wrapped is spelled `code:<bind>`.
3598
+ * It matches a block bound to `<bind>` like the bare spelling does; it differs only when no block
3599
+ * names it: a `code:` slot then renders where the source has it, a bare one is a removed section.
3600
+ */
3601
+ declare const CODE_SLOT_PREFIX = "code:";
3602
+ /** The bind a slot answers to: `code:hero` and `hero` → `hero`. */
3603
+ declare const slotBindOf: (slot: string) => string;
3604
+ /** One thing `<BcmsSections>` renders: the page's own slot (with its block, when one names it), or a CMS block. */
3605
+ type SectionPlanItem<B> = {
3606
+ slot: string;
3607
+ block: B | null;
3608
+ } | {
3609
+ slot: null;
3610
+ block: B;
3611
+ };
3612
+ /**
3613
+ * The render order of a page: its slots (in source order) joined with its block list (in CMS order).
3614
+ *
3615
+ * - No block list (a build with no snapshot, the API down): every slot, in source order, no block.
3616
+ * - A block bound to a slot renders that slot at the block's position. Each slot renders once: a
3617
+ * second block of the same bind is skipped, as is a bound block the page passed no slot for
3618
+ * (the site draws that one somewhere this list cannot reach, so drawing it again would double it).
3619
+ * - A block with no bind (a section added from the library) is the CMS's own to draw.
3620
+ * - A slot no block names: a `code:` slot always renders, after the source slot before it. A bare
3621
+ * slot renders the same way while the list names none of this page's slots (another project's
3622
+ * snapshot, a page never placed); once it names one, an unnamed bare slot is a removed section.
3623
+ */
3624
+ declare function planSections<B>(slots: readonly string[], blocks: readonly B[] | null | undefined): SectionPlanItem<B>[];
3625
+
3626
+ export { type AlignToken, type ApiError, type ApiKey, type ApiKeyPermission, type ApiKeyTokenType, type ArrayZoneConfig, type AssertEqual, type AuthResponse, type AuthSession, type AuthUser, BLOCK_BINDINGS, BREAKPOINTS, BUTTON_ICONS, BUTTON_ICON_NAMES, BUTTON_LOOK_KEYS, BUTTON_PLACEMENT_KEYS, BUTTON_SIZES, BUTTON_VARIANTS, type BetterCMSErrorCode, type BgToken, type BindingKind, type BlockBinding, type BlockHoverStyle, type BlockStyle, type BlockType, type ButtonBlock, type ButtonIcon, type ButtonLinkCandidate, type ButtonLookKey, type ButtonProps, type ButtonSiteLook, type ButtonSizeName, type ButtonValue, type ButtonVariant, CODE_SLOT_PREFIX, COMPONENT_PROP_TYPES, type CanonicalInputDefinition, type ChoiceOption, type CollectionBlock, type CollectionFilter, type CollectionProps, type ColorToken, type ColumnsBlock, type ColumnsProps, type Component, type ComponentBlock, type ComponentCategory, type ComponentFormPropRef, type ComponentPropDef, type ComponentPropType, type ComponentPropUi, type ComponentProps, type ComponentSubField, type ComponentVariantGroup, type Content, type ContentBlock, type ContentEntry, type ContentModel, type ContentModelField, type ContentModelFieldType, type ContentModelFieldUi, type ContentPageResult, type ContentResponse, type ContentWidthToken, type CornerToken, DIALOG_SELECTOR, DOCK_BUDGET, DOCK_ICON_NAMES, DOCK_ICON_NAME_SET, type DeepReadonly, type DeliveredLayout, type DeliveryComponent, type DeliveryEntry, type DeliveryEntrySeo, type DeliveryList, type DeliveryPage, type DerivedLocator, type DockBudget, type DockFieldLike, type DockFieldsetLike, type DockIconName, type DockInputRef, type DockLane, type DockNode, type DockPropGroupLike, type DockScreen, type ElementLike, type ExpandedBinding, FIELD_SIZE_ZOOM, FIELD_STYLE_KEYS, FOOTER_SECTION_ID, type FieldConfig, type FieldSize, type FieldStyle, type FieldStyleKey, type FieldStyles, type Fieldset, type FieldsetKind, type FieldsetUiBefore, type FontSizeToken, type FooterBlock, type FooterColumn, type FooterProps, type Form, type FormBlock, type FormField, type FormProps, type FormSubmission, type HeadingBlock, type HeadingProps, type ImageBlock, type ImageProps, LANDMARK_SELECTOR, LAYOUT_SECTION_ICONS, LAYOUT_SECTION_ICON_SET, LINK_RELS, LINK_VALUE_TYPES, type LandmarkChainElement, type LandmarkElement, type LayoutComponentItem, type LayoutDataDocument, type LayoutFieldDefinition, type LayoutFieldItem, type LayoutFieldType, type LayoutScalarFieldType, type LayoutSection, type LayoutSectionIcon, type LayoutSectionItem, type LayoutStructureDocument, type LayoutZone, type LinkRel, type LinkValue, type LinkValueType, type LocatorGrammar, MAIN_SELECTOR, type ManagementLayoutCommand, type MediaAsset, type MediaCaptionTrack, type MediaFieldValue, NAVIGATION_SECTION_ID, type NavLink, type NavbarBlock, type NavbarProps, type NumberFieldFormat, type NumberScale, OPTION_DESCRIPTION_MAX, type OpenMode, PAGE_CONTENT_ANCHOR_ID, type Page, type PageLayoutOverrideDataDocument, type PageLayoutOverrideDocument, type PageLayoutOverrideState, type PageLayoutOverrideStructureDocument, type PageLayoutSectionOverride, type PageLayoutSectionStructureOverride, type PageMetaJson, type PageOnlyLayoutSection, type PageSectionPlacement, type PaginatedResult, type Perspective, type PortableTextDocument, type PortableTextNode, type PropGroup, RESPONSIVE_CSS, type RadiusToken, type ReadButtonValue, type Redirect, type ReservedLayoutSection, type ResolvedLayoutNode, type RichTextBlock, type RichTextProps, SECTION_DOCTRINE, SECTION_SPACE_TOKENS, SLOT_CHILD_KEYS, SLOT_ITEMS_CAP, SLOT_MAX_ITEMS, SPACE_BOTTOM_TOKENS, SPACE_STEP_TOKENS, type ScaleUnit, type SectionBlock, type SectionPlanItem, type SectionProps, type SectionSpaceToken, type ShadowToken, type ShowIf, type ShowIfRule, type SignInInput, type SignUpInput, type SiteSeoDefaults, type SlideItem, type SliderBlock, type SliderProps, type SlotChild, type SlotItem, type SlotShapeOptions, type SlotShapeProblem, type SlotValue, type SpaceStepToken, type SpaceToken, type SpacerBlock, type SpacerProps, TABLE_COLUMN_TYPES, TABLE_JSONLD_TYPES, TABLE_LIMITS, TABLE_RESPONSIVE, TAG_HEADS, type TabItem, type TableCell, type TableCellObject, type TableCellValue, type TableCheckOptions, type TableColumn, type TableColumnType, type TableFieldOptions, type TableFootnote, type TableGroup, type TableLink, type TableProblem, type TableRef, type TableRefResolved, type TableRow, type TableValue, type TabsBlock, type TabsProps, type TextBlock, type TextProps, type ThemeToken, type UiBefore, type UiOrigin, VIDEO_TRANSCRIPT_MAX, VIDEO_VALUE_KEYS, type VariantInputMapping, type VideoBlock, type VideoProps, type VideoValue, type VisibilityWindow, type WeightToken, type WindowState, type Workspace, type ZoneField, anchorTargetRel, blockStyleToColumnCss, blockStyleToCss, blockStyleToInnerCss, buttonBlockProps, buttonIconOf, buttonIconSvg, buttonLinkPairs, buttonLookValue, buttonSiteLookOf, buttonValueOfInstance, buttonValueProblem, buttonVariantOf, candidateRole, componentInstanceAddresses, componentPropTargetKey, derivedPairs, dockBudget, dockScreens, expandBlockBindings, fieldGroupOf, fieldStyleCssText, fieldStyleToCss, formatNumber, formatPropsAttribute, getBlockType, headingPaintCss, hideOnAttr, inWindow, isBlock, isButtonLookValue, isChromeLandmark, isLinkObject, isScriptHref, isSlotChild, isTableValue, keyWords, landmarkRegions, linkAnchorOf, linkHref, linkRefOf, linkValueProblem, locatorFor, normalizeLinkValue, normalizeTableValue, normalizeWindow, parseNumberText, parsePropsAttribute, pickFieldStyle, placementBindOf, planSections, readButtonValue, readNumberFormat, readPath, regionOf, renderTableHtml, safeCssUrl, slotBindOf, slotChildValues, slotItems, slotPathString, slotShapeProblems, spaceTokenCss, splitButtonStyle, tableCellText, tablePathString, tableRefCells, tableSearchText, tableToMarkdown, tableValueProblems, topFieldKeyOf, usesHideOn, videoUrlOf, videoValueProblem, visibleBlocks, visibleDeliveredLayout, visibleLayoutStructure, windowState, withButtonLookProps };