@bettercms-ai/types 1.40.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/README.md +18 -18
- package/dist/index.d.ts +805 -42
- package/dist/index.js +1186 -18
- package/dist/index.js.map +1 -1
- package/package.json +34 -34
package/dist/index.d.ts
CHANGED
|
@@ -15,16 +15,84 @@ 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
|
+
|
|
82
|
+
/** Longest `description` a choice option may carry: one line under its label (V2's longest is 71). */
|
|
83
|
+
declare const OPTION_DESCRIPTION_MAX = 140;
|
|
84
|
+
/**
|
|
85
|
+
* One choice of a select / multiselect / tags field or prop. Values are judged by `value` alone;
|
|
86
|
+
* `icon` (a dock icon name, bettercms://icons/dock) and `description` (one line under the label)
|
|
87
|
+
* are editor chrome. A bare string is a choice whose label is its value.
|
|
88
|
+
*/
|
|
89
|
+
interface ChoiceOption {
|
|
90
|
+
label: string;
|
|
91
|
+
value: string;
|
|
92
|
+
/** A `DockIconName`, typed as a string so a stored row (db `ComponentPropDef`) stays assignable. */
|
|
93
|
+
icon?: string;
|
|
94
|
+
description?: string;
|
|
95
|
+
}
|
|
28
96
|
/**
|
|
29
97
|
* ContentModel — the structured content model (schema) for a workspace.
|
|
30
98
|
* Defines which content fields are available for authors to fill in.
|
|
@@ -48,7 +116,7 @@ interface ContentModel {
|
|
|
48
116
|
* by the API but normalized to `array` + zones on write, so stored/delivered
|
|
49
117
|
* content never contains them.
|
|
50
118
|
*/
|
|
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";
|
|
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";
|
|
52
120
|
type ContentModelKind = "model" | "block";
|
|
53
121
|
/**
|
|
54
122
|
* How a fieldset renders in the dock. ABSENT ≡ today's flat list (V2): a legacy `{id, name}`
|
|
@@ -69,6 +137,11 @@ interface UiBefore {
|
|
|
69
137
|
position: number;
|
|
70
138
|
label?: string;
|
|
71
139
|
helpText?: string;
|
|
140
|
+
/** The V2 editor keys, snapshotted with the rest so a Revert restores them. */
|
|
141
|
+
helpMore?: string;
|
|
142
|
+
advanced?: boolean;
|
|
143
|
+
recommendedMax?: number;
|
|
144
|
+
openMode?: OpenMode;
|
|
72
145
|
}
|
|
73
146
|
/**
|
|
74
147
|
* A fieldset's chrome before the first agent change over a human/derived (or unstamped) state,
|
|
@@ -82,6 +155,9 @@ interface FieldsetUiBefore {
|
|
|
82
155
|
tab?: string;
|
|
83
156
|
icon?: DockIconName;
|
|
84
157
|
collapsed?: boolean;
|
|
158
|
+
collapsible?: boolean;
|
|
159
|
+
columns?: 1 | 2;
|
|
160
|
+
layout?: "stack" | "breakpoints";
|
|
85
161
|
};
|
|
86
162
|
/** Its index among the model's fieldsets before the agent's change; absent on older snapshots. */
|
|
87
163
|
position?: number;
|
|
@@ -98,6 +174,12 @@ interface Fieldset {
|
|
|
98
174
|
collapsed?: boolean;
|
|
99
175
|
/** A group/row that sits inside this `kind:"tab"` fieldset. */
|
|
100
176
|
tab?: string;
|
|
177
|
+
/** `false`: a static heading with no toggle. */
|
|
178
|
+
collapsible?: boolean;
|
|
179
|
+
/** `2`: short fields side by side. */
|
|
180
|
+
columns?: 1 | 2;
|
|
181
|
+
/** `breakpoints`: its per-screen-size `object` fields (desktop, tablet, phone; joined by `fieldsetId`) shown as ONE group with a switcher. */
|
|
182
|
+
layout?: "stack" | "breakpoints";
|
|
101
183
|
uiOrigin?: UiOrigin;
|
|
102
184
|
uiBefore?: FieldsetUiBefore;
|
|
103
185
|
}
|
|
@@ -119,24 +201,34 @@ interface ArrayZoneConfig {
|
|
|
119
201
|
}
|
|
120
202
|
/** Per-type config for a field (the typed shape behind the loose `config` bag). */
|
|
121
203
|
interface FieldConfig {
|
|
122
|
-
/**
|
|
123
|
-
|
|
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";
|
|
124
209
|
/** nested array: zoned fields (recursive) */
|
|
125
210
|
zones?: ArrayZoneConfig;
|
|
126
211
|
/** reference / multi-reference */
|
|
127
212
|
contentModelId?: string;
|
|
128
213
|
min?: number;
|
|
129
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;
|
|
130
219
|
/** date / datetime */
|
|
131
220
|
includeTime?: boolean;
|
|
132
221
|
/**
|
|
133
|
-
* date / datetime with a time: "site" (the project's own zone)
|
|
134
|
-
*
|
|
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.
|
|
135
225
|
*/
|
|
136
|
-
timezone?: string;
|
|
137
|
-
/** 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. */
|
|
138
228
|
blockSlugs?: string[];
|
|
139
|
-
/**
|
|
229
|
+
/** slot: per-child layout settings, what each child's `_settings` holds (leaf fields). */
|
|
230
|
+
slotSettings?: ContentModelField[];
|
|
231
|
+
/** modular: bounds on how many block instances the field may hold; a primitive array (itemType): how many items. */
|
|
140
232
|
minItems?: number;
|
|
141
233
|
maxItems?: number;
|
|
142
234
|
/**
|
|
@@ -172,6 +264,21 @@ interface FieldConfig {
|
|
|
172
264
|
zoneId?: string;
|
|
173
265
|
/** Explicit migration acknowledgement while the legacy allowlist remains readable. */
|
|
174
266
|
legacyResolved?: boolean;
|
|
267
|
+
/** number: a V2 scale (stepped range, numeric or token steps, units, presets, custom escape hatch). */
|
|
268
|
+
scale?: NumberScale;
|
|
269
|
+
/** number: V2 `numeric.unit`, what it counts ("%", "USD", "days"), shown beside the input. 1–24 chars. */
|
|
270
|
+
unit?: string;
|
|
271
|
+
/** number: V2 `validation.min / max`, the error bounds; they win over `min` / `max` (the input's range). */
|
|
272
|
+
validation?: {
|
|
273
|
+
min?: number;
|
|
274
|
+
max?: number;
|
|
275
|
+
};
|
|
276
|
+
/** text / longtext / richtext: length in characters (richtext: its plain text). */
|
|
277
|
+
minLength?: number;
|
|
278
|
+
maxLength?: number;
|
|
279
|
+
/** text / longtext: a regex (≤ 200 characters) and the message shown when a value does not match it. */
|
|
280
|
+
pattern?: string;
|
|
281
|
+
patternMessage?: string;
|
|
175
282
|
legacyMappings?: Record<string, string>;
|
|
176
283
|
/**
|
|
177
284
|
* image: `"icon"` marks an inline SVG icon the import derived (its value a `data:image/svg+xml`
|
|
@@ -179,8 +286,52 @@ interface FieldConfig {
|
|
|
179
286
|
* and the field-pruning guards leave it alone: an icon is editable content, never markup to tidy.
|
|
180
287
|
*/
|
|
181
288
|
media?: "icon";
|
|
289
|
+
/** multiselect / tags: the choices (tags: suggestions unless allowCustom is false). */
|
|
290
|
+
options?: Array<string | ChoiceOption>;
|
|
182
291
|
[key: string]: unknown;
|
|
183
292
|
}
|
|
293
|
+
type ScaleUnit = "px" | "%" | "rem" | "em" | "vw" | "vh";
|
|
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
|
+
*/
|
|
304
|
+
interface NumberScale {
|
|
305
|
+
steps: {
|
|
306
|
+
min: number;
|
|
307
|
+
max: number;
|
|
308
|
+
step?: number;
|
|
309
|
+
} | Array<{
|
|
310
|
+
value: number;
|
|
311
|
+
label?: string;
|
|
312
|
+
}> | Array<{
|
|
313
|
+
value: string;
|
|
314
|
+
label: string;
|
|
315
|
+
title?: string;
|
|
316
|
+
px?: number;
|
|
317
|
+
css?: string;
|
|
318
|
+
}>;
|
|
319
|
+
units?: ScaleUnit[];
|
|
320
|
+
defaultUnit?: ScaleUnit;
|
|
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
|
+
};
|
|
328
|
+
presets?: Array<{
|
|
329
|
+
label?: string;
|
|
330
|
+
value: number | string | ScaleCustomValue;
|
|
331
|
+
}>;
|
|
332
|
+
}
|
|
333
|
+
/** V2: how a compound field (an `object`, or an array's rows) opens when edited. Editor-only. */
|
|
334
|
+
type OpenMode = "inline" | "drill" | "popover" | "dialog";
|
|
184
335
|
/**
|
|
185
336
|
* Where a field renders in the entry editor.
|
|
186
337
|
*
|
|
@@ -213,7 +364,8 @@ type ContentModelFieldPlacement = "cover" | "title" | "excerpt" | "body" | "inli
|
|
|
213
364
|
*/
|
|
214
365
|
interface ShowIfRule {
|
|
215
366
|
field: string;
|
|
216
|
-
|
|
367
|
+
/** `notEmpty` ≡ `isSet`; `empty` passes while the source holds nothing. Neither reads `value`. */
|
|
368
|
+
op: "eq" | "neq" | "in" | "isSet" | "notEmpty" | "empty";
|
|
217
369
|
value?: string | string[];
|
|
218
370
|
}
|
|
219
371
|
interface ShowIf {
|
|
@@ -233,9 +385,20 @@ interface ContentModelField {
|
|
|
233
385
|
*/
|
|
234
386
|
unique?: boolean;
|
|
235
387
|
defaultValue?: unknown;
|
|
236
|
-
options
|
|
388
|
+
/** select: the choices (multiselect / tags keep theirs on `config.options`). */
|
|
389
|
+
options?: Array<string | ChoiceOption>;
|
|
237
390
|
/** Per-type config. For `array`: either `itemType` (primitive) or `zones` (nested). */
|
|
238
391
|
config?: FieldConfig | null;
|
|
392
|
+
/** `object`: its child fields. */
|
|
393
|
+
fields?: ContentModelField[];
|
|
394
|
+
/** `object` / `array`: how the value (or each row) opens when edited. */
|
|
395
|
+
openMode?: OpenMode;
|
|
396
|
+
/** Longer help behind the ⓘ next to the label. Editor-only. */
|
|
397
|
+
helpMore?: string;
|
|
398
|
+
/** Tuck into the closed "Advanced" section. Editor-only. */
|
|
399
|
+
advanced?: boolean;
|
|
400
|
+
/** A soft limit the editor warns at, never a refusal. */
|
|
401
|
+
recommendedMax?: number;
|
|
239
402
|
/**
|
|
240
403
|
* Which fieldset this field renders under in the schema builder. Authoring-only: it is
|
|
241
404
|
* never delivered and cannot move a value — see {@link Fieldset}.
|
|
@@ -258,6 +421,12 @@ interface ContentModelField {
|
|
|
258
421
|
readOnly?: true | "developer";
|
|
259
422
|
/** Which system owns the value; shown on the refusal. At most 200 characters. */
|
|
260
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;
|
|
261
430
|
/**
|
|
262
431
|
* Authoring chrome — how the field PRESENTS in the editor. Never delivered, never read by a
|
|
263
432
|
* renderer, and never able to move a value; the same contract as {@link placement}.
|
|
@@ -293,6 +462,10 @@ interface ContentModelFieldUi {
|
|
|
293
462
|
subtitle?: string;
|
|
294
463
|
/** Child field key whose value is the row's thumbnail. Type is not constrained. */
|
|
295
464
|
media?: string;
|
|
465
|
+
/** A literal row label while the title child is empty ("Untitled question"). Not a key. */
|
|
466
|
+
fallback?: string;
|
|
467
|
+
/** The row's icon while it has no media (V2 `preview.icon`). */
|
|
468
|
+
icon?: DockIconName;
|
|
296
469
|
};
|
|
297
470
|
/**
|
|
298
471
|
* How the ITEMS of a nesting field are arranged. ABSENT ≡ `"list"` — every field stored
|
|
@@ -301,7 +474,7 @@ interface ContentModelFieldUi {
|
|
|
301
474
|
*
|
|
302
475
|
* Same placement rule as {@link ContentModelFieldUi.preview}: nesting fields only.
|
|
303
476
|
*/
|
|
304
|
-
layout?: "list" | "grid" | "table";
|
|
477
|
+
layout?: "list" | "grid" | "table" | "rows" | "chips" | "gallery";
|
|
305
478
|
/**
|
|
306
479
|
* Whether the items of a list may be dragged. ABSENT ≡ `true`, for the same reason — nothing
|
|
307
480
|
* stored today carries it, and everything stored today is reorderable.
|
|
@@ -318,11 +491,39 @@ interface ContentModelFieldUi {
|
|
|
318
491
|
* `slider` on a `number` whose config.min < config.max; `rating` on a `number` with numeric
|
|
319
492
|
* config.min, max and step (stars).
|
|
320
493
|
*/
|
|
321
|
-
control?: "segmented" | "slider" | "rating";
|
|
494
|
+
control?: "segmented" | "slider" | "rating" | "dropdown" | "radio" | "cards" | "grid" | "switch" | "checkbox";
|
|
322
495
|
/** The branch row's icon. Nesting fields only. */
|
|
323
496
|
icon?: DockIconName;
|
|
324
|
-
/** What one item is called ("Slide", "Member"), 1–24 chars. Nesting fields
|
|
497
|
+
/** What one item is called ("Slide", "Member"), 1–24 chars (V2 itemNoun). Nesting fields and lists. */
|
|
325
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
|
+
}>;
|
|
326
527
|
/**
|
|
327
528
|
* A custom dock input, by NAME: the project's own input (built with its site, served on its
|
|
328
529
|
* own inputs origin, never the dashboard's) draws this field instead of the stock control.
|
|
@@ -399,14 +600,110 @@ declare const SPACE_BOTTOM_TOKENS: ("section-space-none" | "section-space-small"
|
|
|
399
600
|
/** `var(--bcms-<token>,<px>)`, or "" for anything that is not a known token (closed set). */
|
|
400
601
|
declare function spaceTokenCss(token: unknown): string;
|
|
401
602
|
|
|
603
|
+
/**
|
|
604
|
+
* A LINK VALUE: what a `link` field, a `link` prop and a button's `href` store.
|
|
605
|
+
*
|
|
606
|
+
* Two shapes, both valid forever:
|
|
607
|
+
* - a plain href string ("/about", "https://example.com"), which is what every value stored
|
|
608
|
+
* before the V2 link element holds;
|
|
609
|
+
* - the V2 link object (dashboard kit `controls/link.tsx`, `LinkValue` after `finalizeLink`):
|
|
610
|
+
* `{ type, href, title?, newTab?, target?, rel?, section?, ref? }`.
|
|
611
|
+
*
|
|
612
|
+
* `href` is always the final href the site renders (`mailto:`, `tel:`, `#anchor` included), so a
|
|
613
|
+
* reader that only wants a destination reads `href` and nothing else. `ref` is the id of the page
|
|
614
|
+
* or CMS item a `page` / `entry` link points at: the write path checks it exists and delivery
|
|
615
|
+
* resolves it like a reference. Keys the kit writes beside these (`pageId`, `entryId`, `assetId`,
|
|
616
|
+
* `anchor`, `email`, `subject`, `phone`, `label`) are kept as sent.
|
|
617
|
+
*/
|
|
618
|
+
/** A link's relation beyond a new tab's own `noopener noreferrer`. */
|
|
619
|
+
declare const LINK_RELS: readonly ["nofollow", "sponsored", "ugc"];
|
|
620
|
+
type LinkRel = (typeof LINK_RELS)[number];
|
|
621
|
+
/**
|
|
622
|
+
* What a link points at. `section` is the kit's spelling of `anchor` (a `#fragment` on the page);
|
|
623
|
+
* both are accepted and stored as sent.
|
|
624
|
+
*/
|
|
625
|
+
declare const LINK_VALUE_TYPES: readonly ["url", "page", "entry", "email", "phone", "anchor", "section", "file"];
|
|
626
|
+
type LinkValueType = (typeof LINK_VALUE_TYPES)[number];
|
|
627
|
+
interface LinkValue {
|
|
628
|
+
type?: LinkValueType;
|
|
629
|
+
href: string;
|
|
630
|
+
title?: string;
|
|
631
|
+
newTab?: boolean;
|
|
632
|
+
/** Legacy mirror of `newTab`; must agree with it. */
|
|
633
|
+
target?: "_self" | "_blank";
|
|
634
|
+
/** Absent = a normal link (the kit's "follow" is dropped on write). */
|
|
635
|
+
rel?: LinkRel;
|
|
636
|
+
/** The `#anchor` on the target page. */
|
|
637
|
+
section?: string;
|
|
638
|
+
/** The page id (`type: "page"`) or entry id (`type: "entry"`) this link points at. */
|
|
639
|
+
ref?: string;
|
|
640
|
+
}
|
|
641
|
+
/** A link object (`{ href: string, … }`), as opposed to a plain href string. */
|
|
642
|
+
declare function isLinkObject(value: unknown): value is LinkValue & Record<string, unknown>;
|
|
643
|
+
/** A link value's destination: the string itself, or the object's `href`. Null for anything else. */
|
|
644
|
+
declare function linkHref(value: unknown): string | null;
|
|
645
|
+
/** The page or entry a `page` / `entry` link points at, or null. Reads `ref`, then the kit's `pageId` / `entryId`. */
|
|
646
|
+
declare function linkRefOf(value: unknown): {
|
|
647
|
+
kind: "page" | "entry";
|
|
648
|
+
id: string;
|
|
649
|
+
} | null;
|
|
650
|
+
/** `javascript:`, `data:` and `vbscript:`, also behind the control characters a URL parser strips. */
|
|
651
|
+
declare const isScriptHref: (href: string) => boolean;
|
|
652
|
+
/**
|
|
653
|
+
* Why a link OBJECT is not a link value, or null when it is. The href's own grammar (which schemes,
|
|
654
|
+
* which relative forms) is the caller's rule; this refuses only what no link may be.
|
|
655
|
+
* Messages start with `link_value_invalid:` so every surface can name the refusal.
|
|
656
|
+
*/
|
|
657
|
+
declare function linkValueProblem(value: unknown): string | null;
|
|
658
|
+
/**
|
|
659
|
+
* A link value as it is stored: a string as sent; an object with the kit's `rel: "follow"` dropped
|
|
660
|
+
* (no rel IS a normal link), `newTab` filled from a lone `target`, a page/entry link's
|
|
661
|
+
* `pageId` / `entryId` copied to `ref`, and the read-only `resolved` dropped. Never invents a destination.
|
|
662
|
+
*/
|
|
663
|
+
declare function normalizeLinkValue<T>(value: T): T;
|
|
664
|
+
/** What an anchor for this link value carries: its href, whether it opens a new tab, and its rel. */
|
|
665
|
+
declare function linkAnchorOf(value: unknown): {
|
|
666
|
+
href: string;
|
|
667
|
+
newTab: boolean;
|
|
668
|
+
rel?: LinkRel;
|
|
669
|
+
} | null;
|
|
670
|
+
|
|
402
671
|
declare const BUTTON_VARIANTS: readonly ["primary", "secondary", "tertiary", "brand", "dark", "light", "outline", "link"];
|
|
403
672
|
type ButtonVariant = (typeof BUTTON_VARIANTS)[number];
|
|
404
673
|
/** Each icon's inner SVG markup (viewBox `0 0 25 25`), by name. */
|
|
405
674
|
declare const BUTTON_ICONS: Readonly<Record<DockIconName, string>>;
|
|
406
675
|
type ButtonIcon = DockIconName;
|
|
407
|
-
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"];
|
|
408
677
|
/** A stored variant as it renders: anything off the list is Primary. */
|
|
409
678
|
declare function buttonVariantOf(value: unknown): ButtonVariant;
|
|
679
|
+
/**
|
|
680
|
+
* How an IMPORTED site draws one look of its Button family: the classes its own stylesheet PAINTS
|
|
681
|
+
* the look by, the `data-variant` it keys the look on when it uses one, and the paint classes of
|
|
682
|
+
* every other spelling of the same look (`also`), which a publish takes off the anchor with the rest.
|
|
683
|
+
* A look comes in sizes: `size` are the classes that size its most-used spelling and `sizeAlso`
|
|
684
|
+
* those of the others. A publish leaves a button's size classes on it and adds `size` only to a
|
|
685
|
+
* button that has none. Measured from the built site and stored on the look's button block as
|
|
686
|
+
* `props.siteLook`.
|
|
687
|
+
*/
|
|
688
|
+
interface ButtonSiteLook {
|
|
689
|
+
classes: string[];
|
|
690
|
+
attrs?: {
|
|
691
|
+
"data-variant"?: string;
|
|
692
|
+
};
|
|
693
|
+
also?: string[];
|
|
694
|
+
size?: string[];
|
|
695
|
+
sizeAlso?: string[];
|
|
696
|
+
}
|
|
697
|
+
/** A button block's `props.siteLook`, read defensively: null when it names nothing to paint with. */
|
|
698
|
+
declare function buttonSiteLookOf(value: unknown): ButtonSiteLook | null;
|
|
699
|
+
/**
|
|
700
|
+
* The value a `button` stores to pick one look of the project's Button family: what the site's own
|
|
701
|
+
* `data-variant` calls the look when it keys on one, the look's component slug otherwise. A
|
|
702
|
+
* publish writes it back as the anchor's `data-variant`.
|
|
703
|
+
*/
|
|
704
|
+
declare function buttonLookValue(slug: string, siteLook: ButtonSiteLook | null): string;
|
|
705
|
+
/** Is this a value that could name a family look (or one of the fixed names)? */
|
|
706
|
+
declare function isButtonLookValue(value: unknown): value is string;
|
|
410
707
|
/** A stored icon as it renders: anything off the list is no icon. */
|
|
411
708
|
declare function buttonIconOf(value: unknown): ButtonIcon | null;
|
|
412
709
|
/** One icon as inline SVG sized to the button's text, hidden from assistive tech (the label names the button). */
|
|
@@ -418,8 +715,6 @@ type ButtonSizeName = (typeof BUTTON_SIZES)[number];
|
|
|
418
715
|
* object. Only `label` and `href` are required; every look key is optional and absent reads as
|
|
419
716
|
* today's default (Primary, medium, no arrow, no icon, same tab).
|
|
420
717
|
*/
|
|
421
|
-
declare const LINK_RELS: readonly ["nofollow", "sponsored", "ugc"];
|
|
422
|
-
type LinkRel = (typeof LINK_RELS)[number];
|
|
423
718
|
/**
|
|
424
719
|
* The target and rel attributes of an anchor, as one string. A new tab keeps the `noopener
|
|
425
720
|
* noreferrer` pair; a link relation joins it in the SAME rel attribute, so an anchor never
|
|
@@ -428,7 +723,8 @@ type LinkRel = (typeof LINK_RELS)[number];
|
|
|
428
723
|
declare function anchorTargetRel(newTab: boolean, rel?: unknown): string;
|
|
429
724
|
interface ButtonValue {
|
|
430
725
|
label: string;
|
|
431
|
-
href
|
|
726
|
+
/** A plain href, or a link object (@see LinkValue) whose newTab / rel apply when the button sets none. */
|
|
727
|
+
href: string | LinkValue;
|
|
432
728
|
variant?: ButtonVariant;
|
|
433
729
|
size?: ButtonSizeName;
|
|
434
730
|
arrow?: boolean;
|
|
@@ -438,11 +734,17 @@ interface ButtonValue {
|
|
|
438
734
|
rel?: LinkRel;
|
|
439
735
|
}
|
|
440
736
|
/** 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"
|
|
737
|
+
type ReadButtonValue = Required<Omit<ButtonValue, "rel" | "href">> & Pick<ButtonValue, "rel"> & {
|
|
738
|
+
href: string;
|
|
739
|
+
};
|
|
442
740
|
/** A stored button value as it renders: every key read through the same allow-lists as a block. */
|
|
443
741
|
declare function readButtonValue(value: unknown): ReadButtonValue;
|
|
444
|
-
/**
|
|
445
|
-
|
|
742
|
+
/**
|
|
743
|
+
* Why a value is not a button, or null when it is. Look keys are checked only when present.
|
|
744
|
+
* `looks` are the values that pick a look of the project's own Button family (@see
|
|
745
|
+
* buttonLookValue): a variant is one of those or one of the fixed names.
|
|
746
|
+
*/
|
|
747
|
+
declare function buttonValueProblem(value: unknown, looks?: ReadonlySet<string>): string | null;
|
|
446
748
|
/** The look keys an instance of a Button component may override, beside its label and link. */
|
|
447
749
|
declare const BUTTON_LOOK_KEYS: readonly ["variant", "size", "arrow", "icon", "newTab"];
|
|
448
750
|
type ButtonLookKey = (typeof BUTTON_LOOK_KEYS)[number];
|
|
@@ -721,8 +1023,11 @@ interface ImageBlock {
|
|
|
721
1023
|
interface ButtonProps {
|
|
722
1024
|
text: string;
|
|
723
1025
|
href: string;
|
|
724
|
-
/**
|
|
725
|
-
|
|
1026
|
+
/**
|
|
1027
|
+
* One of the fixed names, which render `bcms-btn-{variant}`, or the value of a look of the
|
|
1028
|
+
* project's own Button family (@see buttonLookValue). Absent ⇒ "primary".
|
|
1029
|
+
*/
|
|
1030
|
+
variant?: ButtonVariant | (string & {});
|
|
726
1031
|
/** Padding + font-size step. Absent ⇒ "md", today's button. sm/lg render `bcms-btn-sm|lg`. */
|
|
727
1032
|
size?: "sm" | "md" | "lg";
|
|
728
1033
|
/** Stretch to the column's width. Absent ⇒ false. true renders `bcms-btn-full`. */
|
|
@@ -1342,7 +1647,9 @@ declare const FOOTER_SECTION_ID: "footer";
|
|
|
1342
1647
|
|
|
1343
1648
|
type LayoutZone = "above-page-content" | "below-page-content";
|
|
1344
1649
|
type ReservedLayoutSection = "navigation" | "footer";
|
|
1345
|
-
type LayoutScalarFieldType = "text" | "longtext" | "richtext" | "number" | "toggle" | "date" | "image" | "file" | "link"
|
|
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";
|
|
1346
1653
|
type LayoutFieldType = LayoutScalarFieldType | "group" | "repeater";
|
|
1347
1654
|
/** A recursive, stable-ID field contract shared by Sections and variant inputs. */
|
|
1348
1655
|
interface LayoutFieldDefinition {
|
|
@@ -1676,7 +1983,15 @@ interface DeliveredLayout {
|
|
|
1676
1983
|
id: string;
|
|
1677
1984
|
kind: "field";
|
|
1678
1985
|
fieldId: string;
|
|
1986
|
+
/** The stored value, unchanged. */
|
|
1679
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;
|
|
1680
1995
|
} | {
|
|
1681
1996
|
id: string;
|
|
1682
1997
|
kind: "component";
|
|
@@ -1752,7 +2067,7 @@ declare function visibleDeliveredLayout<T extends DeliveredLayout | null | undef
|
|
|
1752
2067
|
*
|
|
1753
2068
|
* A constant rather than three paraphrases, because updating some of them is exactly how this happened.
|
|
1754
2069
|
*/
|
|
1755
|
-
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
|
|
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.";
|
|
1756
2071
|
type ComponentCategory = "navbar" | "footer" | "button" | "section" | "slider" | "tabs" | "form" | "custom" | "hero" | "content" | "social-proof" | "conversion";
|
|
1757
2072
|
/**
|
|
1758
2073
|
* A single overridable field on a component. `target` points at the block + JSON
|
|
@@ -1771,7 +2086,7 @@ type ComponentCategory = "navbar" | "footer" | "button" | "section" | "slider" |
|
|
|
1771
2086
|
*
|
|
1772
2087
|
* Order is not semantic; append rather than re-sort, so a diff stays readable.
|
|
1773
2088
|
*/
|
|
1774
|
-
declare const COMPONENT_PROP_TYPES: readonly ["text", "richtext", "image", "url", "boolean", "number", "select", "group", "table", "slot", "form", "link", "button", "date", "color", "file", "icon", "multiselect"];
|
|
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"];
|
|
1775
2090
|
type ComponentPropType = (typeof COMPONENT_PROP_TYPES)[number];
|
|
1776
2091
|
/**
|
|
1777
2092
|
* The value a `form` prop STORES: just the id. The form itself is a Form document and stays the
|
|
@@ -1817,7 +2132,11 @@ interface ComponentPropDef {
|
|
|
1817
2132
|
* number → a number (heading.level, columns.count)
|
|
1818
2133
|
* select → one string from `config.options`
|
|
1819
2134
|
* group → an object keyed by `config.fields`
|
|
1820
|
-
* 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`.
|
|
1821
2140
|
* link → an href string (URL, internal path or #fragment)
|
|
1822
2141
|
* button → ONE `ButtonValue` (button-look.ts): label, href and look as a unit, never a text prop plus
|
|
1823
2142
|
* a url prop that drift apart. Targets the `props` of a `button` block.
|
|
@@ -1826,9 +2145,19 @@ interface ComponentPropDef {
|
|
|
1826
2145
|
* file → `{ url, name?, size? }`, or a bare URL string
|
|
1827
2146
|
* icon → a BetterCMS icon name (`DOCK_ICON_NAMES`), or an uploaded icon as an image value
|
|
1828
2147
|
* multiselect → a `string[]`, each one of `config.options`
|
|
1829
|
-
*
|
|
1830
|
-
*
|
|
1831
|
-
*
|
|
2148
|
+
* object → ONE `{ [childKey]: value }` keyed by `config.fields` (the V2 model-field `object`)
|
|
2149
|
+
* datetime · slug · email · phone · json · location → what the same-named model FIELD stores
|
|
2150
|
+
* tags · rating · code → what the same-named model FIELD stores (a string[], a number,
|
|
2151
|
+
* `{ language?, code }` or a string)
|
|
2152
|
+
* reference · multi-reference → what the same-named model FIELD stores: an entry id, or a
|
|
2153
|
+
* list of them (`config.contentModelId`, or `polymorphic` + `allowedModelSlugs`;
|
|
2154
|
+
* `min`/`max` on the list). Delivery and preview hydrate the ids in a page's overrides
|
|
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)
|
|
1832
2161
|
*/
|
|
1833
2162
|
type: ComponentPropType;
|
|
1834
2163
|
defaultValue?: unknown;
|
|
@@ -1853,12 +2182,25 @@ interface ComponentPropDef {
|
|
|
1853
2182
|
* key) hold these values. The save schema refuses a key no prop of the component declares.
|
|
1854
2183
|
*/
|
|
1855
2184
|
showIf?: ShowIf;
|
|
2185
|
+
/** V2 editor-only keys, as on a model field. @see ContentModelField.helpMore */
|
|
2186
|
+
helpMore?: string;
|
|
2187
|
+
advanced?: boolean;
|
|
2188
|
+
recommendedMax?: number;
|
|
2189
|
+
/**
|
|
2190
|
+
* F1.x: a list prop's items (a table's rows) distinct; on a table sub-field, no two rows share
|
|
2191
|
+
* the value. Refused (`unique_prop_scope`) on a top-level scalar: nothing to be unique across.
|
|
2192
|
+
*/
|
|
2193
|
+
unique?: boolean;
|
|
2194
|
+
/** `object` / `group` / `table`: how the value (or each row) opens when edited. */
|
|
2195
|
+
openMode?: OpenMode;
|
|
1856
2196
|
/**
|
|
1857
2197
|
* The content-model field's `readOnly` / `lockReason` pair, as STORED MARKERS only: the
|
|
1858
2198
|
* editor may render the prop read-only, and no write of a prop value is refused for them.
|
|
1859
2199
|
*/
|
|
1860
2200
|
readOnly?: true | "developer";
|
|
1861
2201
|
lockReason?: string;
|
|
2202
|
+
/** V2 per-field localization (the locale chip): a stored marker, as on a model field. */
|
|
2203
|
+
localized?: boolean;
|
|
1862
2204
|
/** Per-type settings; the save schema enforces that each is present on the type needing it. */
|
|
1863
2205
|
config?: {
|
|
1864
2206
|
/** `slot` — a pick allowlist. */
|
|
@@ -1868,20 +2210,52 @@ interface ComponentPropDef {
|
|
|
1868
2210
|
/** `slot` with `multiple` — bounds on the list. `maxItems` defaults to {@link SLOT_MAX_ITEMS}. */
|
|
1869
2211
|
minItems?: number;
|
|
1870
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
|
+
}>;
|
|
1871
2227
|
/**
|
|
1872
2228
|
* `select` / `multiselect` — the choices. Required, and a default must be one of them. `{ label, value }`
|
|
1873
2229
|
* when the stored value is not what an author should read (a component id, for instance).
|
|
1874
2230
|
*/
|
|
1875
|
-
options?: Array<string |
|
|
1876
|
-
|
|
1877
|
-
value: string;
|
|
1878
|
-
}>;
|
|
1879
|
-
/** `group` / `table` — the sub-shape, nestable to 3 levels. */
|
|
2231
|
+
options?: Array<string | ChoiceOption>;
|
|
2232
|
+
/** `group` / `table` / `object` — the sub-shape; 10 levels at most, counting the prop (MAX_FIELD_DEPTH). */
|
|
1880
2233
|
fields?: ComponentSubField[];
|
|
1881
|
-
/**
|
|
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";
|
|
2240
|
+
/** `number` — bounds for the control; `multiselect` / `tags` / `multi-reference` — how many items. */
|
|
1882
2241
|
min?: number;
|
|
1883
2242
|
max?: number;
|
|
1884
2243
|
step?: number;
|
|
2244
|
+
/** `number` — V2 `validation.min / max`: the error bounds, which win over `min` / `max`. */
|
|
2245
|
+
validation?: {
|
|
2246
|
+
min?: number;
|
|
2247
|
+
max?: number;
|
|
2248
|
+
};
|
|
2249
|
+
/** `text` / `url` / `richtext` — length in characters (richtext: its plain text). */
|
|
2250
|
+
minLength?: number;
|
|
2251
|
+
maxLength?: number;
|
|
2252
|
+
/** `text` / `url` — a regex (≤ 200 characters) and the message shown when it does not match. */
|
|
2253
|
+
pattern?: string;
|
|
2254
|
+
patternMessage?: string;
|
|
2255
|
+
/** `reference` / `multi-reference` — the target model, or `polymorphic` with an allowlist of model slugs. */
|
|
2256
|
+
contentModelId?: string;
|
|
2257
|
+
polymorphic?: boolean;
|
|
2258
|
+
allowedModelSlugs?: string[];
|
|
1885
2259
|
} & Record<string, unknown>;
|
|
1886
2260
|
/**
|
|
1887
2261
|
* AUTHORING CHROME — the same object a content-model FIELD carries ({@link ContentModelFieldUi}),
|
|
@@ -1914,12 +2288,18 @@ interface PropGroup {
|
|
|
1914
2288
|
kind?: Exclude<FieldsetKind, "tab">;
|
|
1915
2289
|
icon?: DockIconName;
|
|
1916
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;
|
|
1917
2297
|
}
|
|
1918
2298
|
/** A prop's `ui`: the field-lane chrome plus its inline {@link PropGroup}. */
|
|
1919
2299
|
type ComponentPropUi = ContentModelFieldUi & {
|
|
1920
2300
|
group?: PropGroup;
|
|
1921
2301
|
};
|
|
1922
|
-
/** One field inside a `group` prop or a `table` row. Recursive,
|
|
2302
|
+
/** One field inside a `group` / `object` prop or a `table` row. Recursive, 10 levels at most counting the prop (MAX_FIELD_DEPTH). */
|
|
1923
2303
|
interface ComponentSubField {
|
|
1924
2304
|
key: string;
|
|
1925
2305
|
label: string;
|
|
@@ -1931,8 +2311,23 @@ interface ComponentSubField {
|
|
|
1931
2311
|
helpText?: string;
|
|
1932
2312
|
helpSource?: "auto" | "human" | "agent";
|
|
1933
2313
|
placeholder?: string;
|
|
1934
|
-
options?: string
|
|
1935
|
-
/**
|
|
2314
|
+
options?: Array<string | ChoiceOption>;
|
|
2315
|
+
/** The V2 editor keys, one level down. `showIf` names SIBLING sub-fields. @see ComponentPropDef */
|
|
2316
|
+
helpMore?: string;
|
|
2317
|
+
advanced?: boolean;
|
|
2318
|
+
recommendedMax?: number;
|
|
2319
|
+
/** On a table's sub-field: no two rows share the value; on a list: no item repeats. */
|
|
2320
|
+
unique?: boolean;
|
|
2321
|
+
openMode?: OpenMode;
|
|
2322
|
+
showIf?: ShowIf;
|
|
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;
|
|
2330
|
+
/** CANONICAL. A nested `group`/`table`/`object`'s own sub-shape. */
|
|
1936
2331
|
fields?: ComponentSubField[];
|
|
1937
2332
|
/**
|
|
1938
2333
|
* A READ-ONLY MIRROR of `options`/`fields`, in the shape `ComponentPropDef` puts them in.
|
|
@@ -1950,7 +2345,7 @@ interface ComponentSubField {
|
|
|
1950
2345
|
*/
|
|
1951
2346
|
config?: {
|
|
1952
2347
|
fields?: ComponentSubField[];
|
|
1953
|
-
options?: string
|
|
2348
|
+
options?: Array<string | ChoiceOption>;
|
|
1954
2349
|
} & Record<string, unknown>;
|
|
1955
2350
|
}
|
|
1956
2351
|
/** The value a `slot` prop holds — the draft half of a `component-ref`, deliberately. */
|
|
@@ -2063,6 +2458,66 @@ interface DeliveryComponent {
|
|
|
2063
2458
|
props: ComponentPropDef[];
|
|
2064
2459
|
}
|
|
2065
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
|
+
|
|
2066
2521
|
/**
|
|
2067
2522
|
* The dock's click budget, as ONE pure function both ends read (V9): the backend's next-steps
|
|
2068
2523
|
* rules call it on live data, and the dashboard's reach test measures its RENDERED dock against the
|
|
@@ -2232,6 +2687,210 @@ declare function derivedPairs(candidates: readonly ButtonLinkCandidate[]): Map<n
|
|
|
2232
2687
|
/** Every unambiguous pair in one sibling list, as `[textIndex, linkIndex]`, in list order. */
|
|
2233
2688
|
declare function buttonLinkPairs(candidates: readonly ButtonLinkCandidate[]): Array<[number, number]>;
|
|
2234
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
|
+
|
|
2235
2894
|
/**
|
|
2236
2895
|
* ContentEntry — a single unit of content, representing the
|
|
2237
2896
|
* published layout of a page: a collection of ordered blocks
|
|
@@ -2372,18 +3031,41 @@ interface DeliveryEntry<T = Record<string, unknown>> {
|
|
|
2372
3031
|
*/
|
|
2373
3032
|
interface PageMetaJson {
|
|
2374
3033
|
canonical?: string;
|
|
3034
|
+
/** The card. `image*` describe `image`; `locale` is `og:locale`, `localeAlternate` every `og:locale:alternate`. */
|
|
2375
3035
|
og?: {
|
|
2376
3036
|
title?: string;
|
|
2377
3037
|
description?: string;
|
|
2378
3038
|
image?: string;
|
|
2379
3039
|
type?: string;
|
|
3040
|
+
imageWidth?: number;
|
|
3041
|
+
imageHeight?: number;
|
|
3042
|
+
imageAlt?: string;
|
|
3043
|
+
locale?: string;
|
|
3044
|
+
localeAlternate?: string[];
|
|
3045
|
+
siteName?: string;
|
|
2380
3046
|
};
|
|
2381
3047
|
twitter?: {
|
|
2382
3048
|
card?: string;
|
|
2383
3049
|
title?: string;
|
|
2384
3050
|
description?: string;
|
|
2385
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[];
|
|
2386
3063
|
};
|
|
3064
|
+
/** `<link rel="alternate" hreflang>`: the same page in other languages. */
|
|
3065
|
+
alternates?: Array<{
|
|
3066
|
+
hreflang: string;
|
|
3067
|
+
href: string;
|
|
3068
|
+
}>;
|
|
2387
3069
|
schema?: Record<string, unknown> | Array<Record<string, unknown>>;
|
|
2388
3070
|
}
|
|
2389
3071
|
/** `DeliveryEntry.seo`: the page meta shape plus the entry's flat title, description and noindex. */
|
|
@@ -2405,10 +3087,18 @@ interface SiteSeoDefaults {
|
|
|
2405
3087
|
og?: {
|
|
2406
3088
|
image?: string;
|
|
2407
3089
|
type?: string;
|
|
3090
|
+
siteName?: string;
|
|
3091
|
+
locale?: string;
|
|
2408
3092
|
};
|
|
2409
3093
|
twitter?: {
|
|
2410
3094
|
card?: string;
|
|
2411
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
|
+
}>;
|
|
2412
3102
|
/** Site-wide JSON-LD emitted alongside the page's own `schema`. */
|
|
2413
3103
|
siteSchema?: Record<string, unknown> | Array<Record<string, unknown>>;
|
|
2414
3104
|
}
|
|
@@ -2860,4 +3550,77 @@ declare function regionOf<E extends {
|
|
|
2860
3550
|
el: E;
|
|
2861
3551
|
}[], el: unknown): string | null;
|
|
2862
3552
|
|
|
2863
|
-
|
|
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 };
|