@bettercms-ai/types 1.39.0 → 1.41.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
@@ -25,6 +25,20 @@ declare const DOCK_ICON_NAMES: readonly ["access-denied", "activity", "add", "ad
25
25
  type DockIconName = (typeof DOCK_ICON_NAMES)[number];
26
26
  declare const DOCK_ICON_NAME_SET: ReadonlySet<string>;
27
27
 
28
+ /** Longest `description` a choice option may carry: one line under its label (V2's longest is 71). */
29
+ declare const OPTION_DESCRIPTION_MAX = 140;
30
+ /**
31
+ * One choice of a select / multiselect / tags field or prop. Values are judged by `value` alone;
32
+ * `icon` (a dock icon name, bettercms://icons/dock) and `description` (one line under the label)
33
+ * are editor chrome. A bare string is a choice whose label is its value.
34
+ */
35
+ interface ChoiceOption {
36
+ label: string;
37
+ value: string;
38
+ /** A `DockIconName`, typed as a string so a stored row (db `ComponentPropDef`) stays assignable. */
39
+ icon?: string;
40
+ description?: string;
41
+ }
28
42
  /**
29
43
  * ContentModel — the structured content model (schema) for a workspace.
30
44
  * Defines which content fields are available for authors to fill in.
@@ -48,7 +62,7 @@ interface ContentModel {
48
62
  * by the API but normalized to `array` + zones on write, so stored/delivered
49
63
  * content never contains them.
50
64
  */
51
- 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";
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";
52
66
  type ContentModelKind = "model" | "block";
53
67
  /**
54
68
  * How a fieldset renders in the dock. ABSENT ≡ today's flat list (V2): a legacy `{id, name}`
@@ -69,6 +83,11 @@ interface UiBefore {
69
83
  position: number;
70
84
  label?: string;
71
85
  helpText?: string;
86
+ /** The V2 editor keys, snapshotted with the rest so a Revert restores them. */
87
+ helpMore?: string;
88
+ advanced?: boolean;
89
+ recommendedMax?: number;
90
+ openMode?: OpenMode;
72
91
  }
73
92
  /**
74
93
  * A fieldset's chrome before the first agent change over a human/derived (or unstamped) state,
@@ -82,6 +101,9 @@ interface FieldsetUiBefore {
82
101
  tab?: string;
83
102
  icon?: DockIconName;
84
103
  collapsed?: boolean;
104
+ collapsible?: boolean;
105
+ columns?: 1 | 2;
106
+ layout?: "stack" | "breakpoints";
85
107
  };
86
108
  /** Its index among the model's fieldsets before the agent's change; absent on older snapshots. */
87
109
  position?: number;
@@ -98,6 +120,12 @@ interface Fieldset {
98
120
  collapsed?: boolean;
99
121
  /** A group/row that sits inside this `kind:"tab"` fieldset. */
100
122
  tab?: string;
123
+ /** `false`: a static heading with no toggle. */
124
+ collapsible?: boolean;
125
+ /** `2`: short fields side by side. */
126
+ columns?: 1 | 2;
127
+ /** `breakpoints`: its per-screen-size `object` fields (desktop, tablet, phone; joined by `fieldsetId`) shown as ONE group with a switcher. */
128
+ layout?: "stack" | "breakpoints";
101
129
  uiOrigin?: UiOrigin;
102
130
  uiBefore?: FieldsetUiBefore;
103
131
  }
@@ -136,7 +164,7 @@ interface FieldConfig {
136
164
  timezone?: string;
137
165
  /** modular: SLUGS of the kind='block' models this field accepts. Non-empty. */
138
166
  blockSlugs?: string[];
139
- /** modular: bounds on how many block instances the field may hold. */
167
+ /** modular: bounds on how many block instances the field may hold; a primitive array (itemType): how many items. */
140
168
  minItems?: number;
141
169
  maxItems?: number;
142
170
  /**
@@ -172,6 +200,19 @@ interface FieldConfig {
172
200
  zoneId?: string;
173
201
  /** Explicit migration acknowledgement while the legacy allowlist remains readable. */
174
202
  legacyResolved?: boolean;
203
+ /** number: a V2 numeric scale (stepped range or numeric steps, optional units and presets). */
204
+ scale?: NumberScale;
205
+ /** number: V2 `validation.min / max`, the error bounds; they win over `min` / `max` (the input's range). */
206
+ validation?: {
207
+ min?: number;
208
+ max?: number;
209
+ };
210
+ /** text / longtext / richtext: length in characters (richtext: its plain text). */
211
+ minLength?: number;
212
+ maxLength?: number;
213
+ /** text / longtext: a regex (≤ 200 characters) and the message shown when a value does not match it. */
214
+ pattern?: string;
215
+ patternMessage?: string;
175
216
  legacyMappings?: Record<string, string>;
176
217
  /**
177
218
  * image: `"icon"` marks an inline SVG icon the import derived (its value a `data:image/svg+xml`
@@ -179,8 +220,31 @@ interface FieldConfig {
179
220
  * and the field-pruning guards leave it alone: an icon is editable content, never markup to tidy.
180
221
  */
181
222
  media?: "icon";
223
+ /** multiselect / tags: the choices (tags: suggestions unless allowCustom is false). */
224
+ options?: Array<string | ChoiceOption>;
182
225
  [key: string]: unknown;
183
226
  }
227
+ type ScaleUnit = "px" | "%" | "rem" | "em" | "vw" | "vh";
228
+ /** A number field's `config.scale` (V2 scale.ts), numeric values only. Editor-only. */
229
+ interface NumberScale {
230
+ steps: {
231
+ min: number;
232
+ max: number;
233
+ step?: number;
234
+ } | Array<{
235
+ value: number;
236
+ label?: string;
237
+ }>;
238
+ units?: ScaleUnit[];
239
+ defaultUnit?: ScaleUnit;
240
+ allowCustom?: boolean;
241
+ presets?: Array<{
242
+ label?: string;
243
+ value: number;
244
+ }>;
245
+ }
246
+ /** V2: how a compound field (an `object`, or an array's rows) opens when edited. Editor-only. */
247
+ type OpenMode = "inline" | "drill" | "popover" | "dialog";
184
248
  /**
185
249
  * Where a field renders in the entry editor.
186
250
  *
@@ -213,7 +277,8 @@ type ContentModelFieldPlacement = "cover" | "title" | "excerpt" | "body" | "inli
213
277
  */
214
278
  interface ShowIfRule {
215
279
  field: string;
216
- op: "eq" | "neq" | "in" | "isSet";
280
+ /** `notEmpty` ≡ `isSet`; `empty` passes while the source holds nothing. Neither reads `value`. */
281
+ op: "eq" | "neq" | "in" | "isSet" | "notEmpty" | "empty";
217
282
  value?: string | string[];
218
283
  }
219
284
  interface ShowIf {
@@ -233,9 +298,20 @@ interface ContentModelField {
233
298
  */
234
299
  unique?: boolean;
235
300
  defaultValue?: unknown;
236
- options?: string[];
301
+ /** select: the choices (multiselect / tags keep theirs on `config.options`). */
302
+ options?: Array<string | ChoiceOption>;
237
303
  /** Per-type config. For `array`: either `itemType` (primitive) or `zones` (nested). */
238
304
  config?: FieldConfig | null;
305
+ /** `object`: its child fields. */
306
+ fields?: ContentModelField[];
307
+ /** `object` / `array`: how the value (or each row) opens when edited. */
308
+ openMode?: OpenMode;
309
+ /** Longer help behind the ⓘ next to the label. Editor-only. */
310
+ helpMore?: string;
311
+ /** Tuck into the closed "Advanced" section. Editor-only. */
312
+ advanced?: boolean;
313
+ /** A soft limit the editor warns at, never a refusal. */
314
+ recommendedMax?: number;
239
315
  /**
240
316
  * Which fieldset this field renders under in the schema builder. Authoring-only: it is
241
317
  * never delivered and cannot move a value — see {@link Fieldset}.
@@ -293,6 +369,8 @@ interface ContentModelFieldUi {
293
369
  subtitle?: string;
294
370
  /** Child field key whose value is the row's thumbnail. Type is not constrained. */
295
371
  media?: string;
372
+ /** A literal row label while the title child is empty ("Untitled question"). Not a key. */
373
+ fallback?: string;
296
374
  };
297
375
  /**
298
376
  * How the ITEMS of a nesting field are arranged. ABSENT ≡ `"list"` — every field stored
@@ -301,7 +379,7 @@ interface ContentModelFieldUi {
301
379
  *
302
380
  * Same placement rule as {@link ContentModelFieldUi.preview}: nesting fields only.
303
381
  */
304
- layout?: "list" | "grid" | "table";
382
+ layout?: "list" | "grid" | "table" | "rows" | "chips" | "gallery";
305
383
  /**
306
384
  * Whether the items of a list may be dragged. ABSENT ≡ `true`, for the same reason — nothing
307
385
  * stored today carries it, and everything stored today is reorderable.
@@ -399,6 +477,74 @@ declare const SPACE_BOTTOM_TOKENS: ("section-space-none" | "section-space-small"
399
477
  /** `var(--bcms-<token>,<px>)`, or "" for anything that is not a known token (closed set). */
400
478
  declare function spaceTokenCss(token: unknown): string;
401
479
 
480
+ /**
481
+ * A LINK VALUE: what a `link` field, a `link` prop and a button's `href` store.
482
+ *
483
+ * Two shapes, both valid forever:
484
+ * - a plain href string ("/about", "https://example.com"), which is what every value stored
485
+ * before the V2 link element holds;
486
+ * - the V2 link object (dashboard kit `controls/link.tsx`, `LinkValue` after `finalizeLink`):
487
+ * `{ type, href, title?, newTab?, target?, rel?, section?, ref? }`.
488
+ *
489
+ * `href` is always the final href the site renders (`mailto:`, `tel:`, `#anchor` included), so a
490
+ * reader that only wants a destination reads `href` and nothing else. `ref` is the id of the page
491
+ * or CMS item a `page` / `entry` link points at: the write path checks it exists and delivery
492
+ * resolves it like a reference. Keys the kit writes beside these (`pageId`, `entryId`, `assetId`,
493
+ * `anchor`, `email`, `subject`, `phone`, `label`) are kept as sent.
494
+ */
495
+ /** A link's relation beyond a new tab's own `noopener noreferrer`. */
496
+ declare const LINK_RELS: readonly ["nofollow", "sponsored", "ugc"];
497
+ type LinkRel = (typeof LINK_RELS)[number];
498
+ /**
499
+ * What a link points at. `section` is the kit's spelling of `anchor` (a `#fragment` on the page);
500
+ * both are accepted and stored as sent.
501
+ */
502
+ declare const LINK_VALUE_TYPES: readonly ["url", "page", "entry", "email", "phone", "anchor", "section", "file"];
503
+ type LinkValueType = (typeof LINK_VALUE_TYPES)[number];
504
+ interface LinkValue {
505
+ type?: LinkValueType;
506
+ href: string;
507
+ title?: string;
508
+ newTab?: boolean;
509
+ /** Legacy mirror of `newTab`; must agree with it. */
510
+ target?: "_self" | "_blank";
511
+ /** Absent = a normal link (the kit's "follow" is dropped on write). */
512
+ rel?: LinkRel;
513
+ /** The `#anchor` on the target page. */
514
+ section?: string;
515
+ /** The page id (`type: "page"`) or entry id (`type: "entry"`) this link points at. */
516
+ ref?: string;
517
+ }
518
+ /** A link object (`{ href: string, … }`), as opposed to a plain href string. */
519
+ declare function isLinkObject(value: unknown): value is LinkValue & Record<string, unknown>;
520
+ /** A link value's destination: the string itself, or the object's `href`. Null for anything else. */
521
+ declare function linkHref(value: unknown): string | null;
522
+ /** The page or entry a `page` / `entry` link points at, or null. Reads `ref`, then the kit's `pageId` / `entryId`. */
523
+ declare function linkRefOf(value: unknown): {
524
+ kind: "page" | "entry";
525
+ id: string;
526
+ } | null;
527
+ /** `javascript:`, `data:` and `vbscript:`, also behind the control characters a URL parser strips. */
528
+ declare const isScriptHref: (href: string) => boolean;
529
+ /**
530
+ * Why a link OBJECT is not a link value, or null when it is. The href's own grammar (which schemes,
531
+ * which relative forms) is the caller's rule; this refuses only what no link may be.
532
+ * Messages start with `link_value_invalid:` so every surface can name the refusal.
533
+ */
534
+ declare function linkValueProblem(value: unknown): string | null;
535
+ /**
536
+ * A link value as it is stored: a string as sent; an object with the kit's `rel: "follow"` dropped
537
+ * (no rel IS a normal link), `newTab` filled from a lone `target`, a page/entry link's
538
+ * `pageId` / `entryId` copied to `ref`, and the read-only `resolved` dropped. Never invents a destination.
539
+ */
540
+ declare function normalizeLinkValue<T>(value: T): T;
541
+ /** What an anchor for this link value carries: its href, whether it opens a new tab, and its rel. */
542
+ declare function linkAnchorOf(value: unknown): {
543
+ href: string;
544
+ newTab: boolean;
545
+ rel?: LinkRel;
546
+ } | null;
547
+
402
548
  declare const BUTTON_VARIANTS: readonly ["primary", "secondary", "tertiary", "brand", "dark", "light", "outline", "link"];
403
549
  type ButtonVariant = (typeof BUTTON_VARIANTS)[number];
404
550
  /** Each icon's inner SVG markup (viewBox `0 0 25 25`), by name. */
@@ -407,6 +553,34 @@ type ButtonIcon = DockIconName;
407
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"];
408
554
  /** A stored variant as it renders: anything off the list is Primary. */
409
555
  declare function buttonVariantOf(value: unknown): ButtonVariant;
556
+ /**
557
+ * How an IMPORTED site draws one look of its Button family: the classes its own stylesheet PAINTS
558
+ * the look by, the `data-variant` it keys the look on when it uses one, and the paint classes of
559
+ * every other spelling of the same look (`also`), which a publish takes off the anchor with the rest.
560
+ * A look comes in sizes: `size` are the classes that size its most-used spelling and `sizeAlso`
561
+ * those of the others. A publish leaves a button's size classes on it and adds `size` only to a
562
+ * button that has none. Measured from the built site and stored on the look's button block as
563
+ * `props.siteLook`.
564
+ */
565
+ interface ButtonSiteLook {
566
+ classes: string[];
567
+ attrs?: {
568
+ "data-variant"?: string;
569
+ };
570
+ also?: string[];
571
+ size?: string[];
572
+ sizeAlso?: string[];
573
+ }
574
+ /** A button block's `props.siteLook`, read defensively: null when it names nothing to paint with. */
575
+ declare function buttonSiteLookOf(value: unknown): ButtonSiteLook | null;
576
+ /**
577
+ * The value a `button` stores to pick one look of the project's Button family: what the site's own
578
+ * `data-variant` calls the look when it keys on one, the look's component slug otherwise. A
579
+ * publish writes it back as the anchor's `data-variant`.
580
+ */
581
+ declare function buttonLookValue(slug: string, siteLook: ButtonSiteLook | null): string;
582
+ /** Is this a value that could name a family look (or one of the fixed names)? */
583
+ declare function isButtonLookValue(value: unknown): value is string;
410
584
  /** A stored icon as it renders: anything off the list is no icon. */
411
585
  declare function buttonIconOf(value: unknown): ButtonIcon | null;
412
586
  /** One icon as inline SVG sized to the button's text, hidden from assistive tech (the label names the button). */
@@ -418,8 +592,6 @@ type ButtonSizeName = (typeof BUTTON_SIZES)[number];
418
592
  * object. Only `label` and `href` are required; every look key is optional and absent reads as
419
593
  * today's default (Primary, medium, no arrow, no icon, same tab).
420
594
  */
421
- declare const LINK_RELS: readonly ["nofollow", "sponsored", "ugc"];
422
- type LinkRel = (typeof LINK_RELS)[number];
423
595
  /**
424
596
  * The target and rel attributes of an anchor, as one string. A new tab keeps the `noopener
425
597
  * noreferrer` pair; a link relation joins it in the SAME rel attribute, so an anchor never
@@ -428,7 +600,8 @@ type LinkRel = (typeof LINK_RELS)[number];
428
600
  declare function anchorTargetRel(newTab: boolean, rel?: unknown): string;
429
601
  interface ButtonValue {
430
602
  label: string;
431
- href: string;
603
+ /** A plain href, or a link object (@see LinkValue) whose newTab / rel apply when the button sets none. */
604
+ href: string | LinkValue;
432
605
  variant?: ButtonVariant;
433
606
  size?: ButtonSizeName;
434
607
  arrow?: boolean;
@@ -438,11 +611,17 @@ interface ButtonValue {
438
611
  rel?: LinkRel;
439
612
  }
440
613
  /** A stored button value as it renders: `rel` stays optional, every other key is filled. */
441
- type ReadButtonValue = Required<Omit<ButtonValue, "rel">> & Pick<ButtonValue, "rel">;
614
+ type ReadButtonValue = Required<Omit<ButtonValue, "rel" | "href">> & Pick<ButtonValue, "rel"> & {
615
+ href: string;
616
+ };
442
617
  /** A stored button value as it renders: every key read through the same allow-lists as a block. */
443
618
  declare function readButtonValue(value: unknown): ReadButtonValue;
444
- /** Why a value is not a button, or null when it is. Look keys are checked only when present. */
445
- declare function buttonValueProblem(value: unknown): string | null;
619
+ /**
620
+ * Why a value is not a button, or null when it is. Look keys are checked only when present.
621
+ * `looks` are the values that pick a look of the project's own Button family (@see
622
+ * buttonLookValue): a variant is one of those or one of the fixed names.
623
+ */
624
+ declare function buttonValueProblem(value: unknown, looks?: ReadonlySet<string>): string | null;
446
625
  /** The look keys an instance of a Button component may override, beside its label and link. */
447
626
  declare const BUTTON_LOOK_KEYS: readonly ["variant", "size", "arrow", "icon", "newTab"];
448
627
  type ButtonLookKey = (typeof BUTTON_LOOK_KEYS)[number];
@@ -721,8 +900,11 @@ interface ImageBlock {
721
900
  interface ButtonProps {
722
901
  text: string;
723
902
  href: string;
724
- /** Absent or off the list ⇒ "primary". Renders `bcms-btn-{variant}`. */
725
- variant?: ButtonVariant;
903
+ /**
904
+ * One of the fixed names, which render `bcms-btn-{variant}`, or the value of a look of the
905
+ * project's own Button family (@see buttonLookValue). Absent ⇒ "primary".
906
+ */
907
+ variant?: ButtonVariant | (string & {});
726
908
  /** Padding + font-size step. Absent ⇒ "md", today's button. sm/lg render `bcms-btn-sm|lg`. */
727
909
  size?: "sm" | "md" | "lg";
728
910
  /** Stretch to the column's width. Absent ⇒ false. true renders `bcms-btn-full`. */
@@ -1280,14 +1462,25 @@ declare function splitButtonStyle(style: BlockStyle | undefined): {
1280
1462
  };
1281
1463
  /**
1282
1464
  * The style keys a PAGE FIELD takes (`pages.field_styles`, keyed by field path): its width and
1283
- * placement, the space above and below it, and its text alignment, size and weight. A subset of
1284
- * `BlockStyle`, so every key keeps the token set and the CSS table it already has — a field never
1285
- * gets a second scale. 🔴 Twin: `FIELD_STYLE_KEYS` in the dashboard's fieldStyle.ts.
1465
+ * placement, the space above and below it, its text alignment, font size and weight, and `size` — a
1466
+ * whole element's Small / Large (a button's). Every key but `size` is a `BlockStyle` key, so it
1467
+ * keeps the token set and the CSS table it already has — a field never gets a second scale.
1468
+ * 🔴 Twin: `FIELD_STYLE_KEYS` in the dashboard's fieldStyle.ts.
1286
1469
  */
1287
- declare const FIELD_STYLE_KEYS: readonly ["contentWidth", "contentAlign", "marginTop", "marginBottom", "align", "fontSize", "weight"];
1470
+ declare const FIELD_STYLE_KEYS: readonly ["contentWidth", "contentAlign", "marginTop", "marginBottom", "align", "fontSize", "weight", "size"];
1288
1471
  type FieldStyleKey = (typeof FIELD_STYLE_KEYS)[number];
1472
+ /** A field element's Small / Large. Medium is UNSET — no "md" token is ever stored. */
1473
+ type FieldSize = "sm" | "lg";
1474
+ /**
1475
+ * `size` → the element's `zoom`, which scales the WHOLE element (padding, font, icon, border) — what
1476
+ * Small / Large mean for a button whose CSS the site wrote. Any other value (`md` included) paints
1477
+ * nothing. 🔴 Inlined in the convert helper (`STYLE_SIZE_ZOOM`), parity-tested against this table.
1478
+ */
1479
+ declare const FIELD_SIZE_ZOOM: Readonly<Record<FieldSize, string>>;
1289
1480
  /** One field's style. */
1290
- type FieldStyle = Pick<BlockStyle, FieldStyleKey>;
1481
+ type FieldStyle = Pick<BlockStyle, Exclude<FieldStyleKey, "size">> & {
1482
+ size?: FieldSize;
1483
+ };
1291
1484
  /** A page's field styles, keyed by field path (the `data-bcms-field` address). */
1292
1485
  type FieldStyles = Record<string, FieldStyle>;
1293
1486
  /** Only the field keys of `style` (an empty object for none). */
@@ -1296,7 +1489,9 @@ declare function pickFieldStyle(style: BlockStyle | Record<string, unknown> | nu
1296
1489
  * A field's declarations, for its OWN element (`fieldAttrs`). Spacing, alignment, size and weight are
1297
1490
  * `blockStyleToCss`'s. The width is `blockStyleToInnerCss`'s column, drawn on the element itself —
1298
1491
  * a field has no wrapper to nest a column in — so its placement becomes left/right margins, and
1299
- * the vertical margins the spacing set stay. `undefined` when nothing applies (no `style` at all).
1492
+ * the vertical margins the spacing set stay. `size` (`FIELD_SIZE_ZOOM`) is LAST, so a style without
1493
+ * it keeps the exact declarations, in the exact order, it always had. `undefined` when nothing
1494
+ * applies (no `style` at all).
1300
1495
  */
1301
1496
  declare function fieldStyleToCss(style: BlockStyle | Record<string, unknown> | null | undefined): Record<string, string | number> | undefined;
1302
1497
  /**
@@ -1758,7 +1953,7 @@ type ComponentCategory = "navbar" | "footer" | "button" | "section" | "slider" |
1758
1953
  *
1759
1954
  * Order is not semantic; append rather than re-sort, so a diff stays readable.
1760
1955
  */
1761
- declare const COMPONENT_PROP_TYPES: readonly ["text", "richtext", "image", "url", "boolean", "number", "select", "group", "table", "slot", "form", "link", "button", "date", "color", "file", "icon", "multiselect"];
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"];
1762
1957
  type ComponentPropType = (typeof COMPONENT_PROP_TYPES)[number];
1763
1958
  /**
1764
1959
  * The value a `form` prop STORES: just the id. The form itself is a Form document and stays the
@@ -1813,9 +2008,14 @@ interface ComponentPropDef {
1813
2008
  * file → `{ url, name?, size? }`, or a bare URL string
1814
2009
  * icon → a BetterCMS icon name (`DOCK_ICON_NAMES`), or an uploaded icon as an image value
1815
2010
  * multiselect → a `string[]`, each one of `config.options`
1816
- *
1817
- * `reference` is absent on purpose: nothing resolves a content-entry id at component render
1818
- * time, so such a prop would save cleanly and render as nothing.
2011
+ * object → ONE `{ [childKey]: value }` keyed by `config.fields` (the V2 model-field `object`)
2012
+ * datetime · slug · email · phone · json · location → what the same-named model FIELD stores
2013
+ * tags · rating · code → what the same-named model FIELD stores (a string[], a number,
2014
+ * `{ language?, code }` or a string)
2015
+ * reference · multi-reference → what the same-named model FIELD stores: an entry id, or a
2016
+ * list of them (`config.contentModelId`, or `polymorphic` + `allowedModelSlugs`;
2017
+ * `min`/`max` on the list). Delivery and preview hydrate the ids in a page's overrides
2018
+ * to entries at the read's `depth`; a plain-text slot renders the entry's title.
1819
2019
  */
1820
2020
  type: ComponentPropType;
1821
2021
  defaultValue?: unknown;
@@ -1840,6 +2040,17 @@ interface ComponentPropDef {
1840
2040
  * key) hold these values. The save schema refuses a key no prop of the component declares.
1841
2041
  */
1842
2042
  showIf?: ShowIf;
2043
+ /** V2 editor-only keys, as on a model field. @see ContentModelField.helpMore */
2044
+ helpMore?: string;
2045
+ advanced?: boolean;
2046
+ recommendedMax?: number;
2047
+ /**
2048
+ * F1.x: a list prop's items (a table's rows) distinct; on a table sub-field, no two rows share
2049
+ * the value. Refused (`unique_prop_scope`) on a top-level scalar: nothing to be unique across.
2050
+ */
2051
+ unique?: boolean;
2052
+ /** `object` / `group` / `table`: how the value (or each row) opens when edited. */
2053
+ openMode?: OpenMode;
1843
2054
  /**
1844
2055
  * The content-model field's `readOnly` / `lockReason` pair, as STORED MARKERS only: the
1845
2056
  * editor may render the prop read-only, and no write of a prop value is refused for them.
@@ -1859,16 +2070,28 @@ interface ComponentPropDef {
1859
2070
  * `select` / `multiselect` — the choices. Required, and a default must be one of them. `{ label, value }`
1860
2071
  * when the stored value is not what an author should read (a component id, for instance).
1861
2072
  */
1862
- options?: Array<string | {
1863
- label: string;
1864
- value: string;
1865
- }>;
1866
- /** `group` / `table` — the sub-shape, nestable to 3 levels. */
2073
+ options?: Array<string | ChoiceOption>;
2074
+ /** `group` / `table` / `object` — the sub-shape; 10 levels at most, counting the prop (MAX_FIELD_DEPTH). */
1867
2075
  fields?: ComponentSubField[];
1868
- /** `number` — bounds for the control. */
2076
+ /** `number` — bounds for the control; `multiselect` / `tags` / `multi-reference` — how many items. */
1869
2077
  min?: number;
1870
2078
  max?: number;
1871
2079
  step?: number;
2080
+ /** `number` — V2 `validation.min / max`: the error bounds, which win over `min` / `max`. */
2081
+ validation?: {
2082
+ min?: number;
2083
+ max?: number;
2084
+ };
2085
+ /** `text` / `url` / `richtext` — length in characters (richtext: its plain text). */
2086
+ minLength?: number;
2087
+ maxLength?: number;
2088
+ /** `text` / `url` — a regex (≤ 200 characters) and the message shown when it does not match. */
2089
+ pattern?: string;
2090
+ patternMessage?: string;
2091
+ /** `reference` / `multi-reference` — the target model, or `polymorphic` with an allowlist of model slugs. */
2092
+ contentModelId?: string;
2093
+ polymorphic?: boolean;
2094
+ allowedModelSlugs?: string[];
1872
2095
  } & Record<string, unknown>;
1873
2096
  /**
1874
2097
  * AUTHORING CHROME — the same object a content-model FIELD carries ({@link ContentModelFieldUi}),
@@ -1906,7 +2129,7 @@ interface PropGroup {
1906
2129
  type ComponentPropUi = ContentModelFieldUi & {
1907
2130
  group?: PropGroup;
1908
2131
  };
1909
- /** One field inside a `group` prop or a `table` row. Recursive, capped at 3 levels deep. */
2132
+ /** One field inside a `group` / `object` prop or a `table` row. Recursive, 10 levels at most counting the prop (MAX_FIELD_DEPTH). */
1910
2133
  interface ComponentSubField {
1911
2134
  key: string;
1912
2135
  label: string;
@@ -1918,8 +2141,17 @@ interface ComponentSubField {
1918
2141
  helpText?: string;
1919
2142
  helpSource?: "auto" | "human" | "agent";
1920
2143
  placeholder?: string;
1921
- options?: string[];
1922
- /** CANONICAL. A nested `group`/`table`'s own sub-shape. */
2144
+ options?: Array<string | ChoiceOption>;
2145
+ /** The V2 editor keys, one level down. `showIf` names SIBLING sub-fields. @see ComponentPropDef */
2146
+ helpMore?: string;
2147
+ advanced?: boolean;
2148
+ recommendedMax?: number;
2149
+ /** On a table's sub-field: no two rows share the value; on a list: no item repeats. */
2150
+ unique?: boolean;
2151
+ openMode?: OpenMode;
2152
+ showIf?: ShowIf;
2153
+ ui?: ContentModelFieldUi;
2154
+ /** CANONICAL. A nested `group`/`table`/`object`'s own sub-shape. */
1923
2155
  fields?: ComponentSubField[];
1924
2156
  /**
1925
2157
  * A READ-ONLY MIRROR of `options`/`fields`, in the shape `ComponentPropDef` puts them in.
@@ -1937,7 +2169,7 @@ interface ComponentSubField {
1937
2169
  */
1938
2170
  config?: {
1939
2171
  fields?: ComponentSubField[];
1940
- options?: string[];
2172
+ options?: Array<string | ChoiceOption>;
1941
2173
  } & Record<string, unknown>;
1942
2174
  }
1943
2175
  /** The value a `slot` prop holds — the draft half of a `component-ref`, deliberately. */
@@ -2847,4 +3079,4 @@ declare function regionOf<E extends {
2847
3079
  el: E;
2848
3080
  }[], el: unknown): string | null;
2849
3081
 
2850
- 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 ButtonSizeName, type ButtonValue, type ButtonVariant, COMPONENT_PROP_TYPES, type CanonicalInputDefinition, 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_STYLE_KEYS, FOOTER_SECTION_ID, type FieldConfig, 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, 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 LocatorGrammar, MAIN_SELECTOR, type ManagementLayoutCommand, type MediaAsset, type MediaCaptionTrack, type MediaFieldValue, NAVIGATION_SECTION_ID, type NavLink, type NavbarBlock, type NavbarProps, 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 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, buttonValueOfInstance, buttonValueProblem, buttonVariantOf, candidateRole, componentInstanceAddresses, componentPropTargetKey, derivedPairs, dockBudget, dockScreens, expandBlockBindings, fieldStyleCssText, fieldStyleToCss, formatPropsAttribute, getBlockType, headingPaintCss, hideOnAttr, inWindow, isBlock, isChromeLandmark, keyWords, landmarkRegions, locatorFor, normalizeWindow, parsePropsAttribute, pickFieldStyle, readButtonValue, readPath, regionOf, safeCssUrl, slotItems, spaceTokenCss, splitButtonStyle, usesHideOn, visibleBlocks, visibleDeliveredLayout, visibleLayoutStructure, windowState, withButtonLookProps };
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 };