@bettercms-ai/kit 2.0.0-next.0 → 2.0.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/lossy.d.ts +9 -1
- package/dist/adapters/lossy.js +16 -5
- package/dist/adapters/lossy.js.map +1 -1
- package/dist/adapters/prod-types.d.ts +9 -22
- package/dist/adapters/prod-types.js +36 -35
- package/dist/adapters/prod-types.js.map +1 -1
- package/dist/adapters/schema.js +84 -39
- package/dist/adapters/schema.js.map +1 -1
- package/dist/context.d.ts +39 -0
- package/dist/context.js +40 -1
- package/dist/context.js.map +1 -1
- package/dist/controls/link.js +112 -196
- package/dist/controls/link.js.map +1 -1
- package/dist/controls/location.js +3 -8
- package/dist/controls/location.js.map +1 -1
- package/dist/controls/media.d.ts +0 -14
- package/dist/controls/media.js +52 -95
- package/dist/controls/media.js.map +1 -1
- package/dist/controls/rich-text/article-shell.d.ts +145 -0
- package/dist/controls/rich-text/article-shell.js +510 -0
- package/dist/controls/rich-text/article-shell.js.map +1 -0
- package/dist/controls/rich-text/author.d.ts +25 -0
- package/dist/controls/rich-text/author.js +104 -0
- package/dist/controls/rich-text/author.js.map +1 -0
- package/dist/controls/rich-text/blocks.d.ts +19 -2
- package/dist/controls/rich-text/blocks.js +273 -638
- package/dist/controls/rich-text/blocks.js.map +1 -1
- package/dist/controls/rich-text/button.d.ts +23 -0
- package/dist/controls/rich-text/button.js +85 -0
- package/dist/controls/rich-text/button.js.map +1 -0
- package/dist/controls/rich-text/catalog.d.ts +2 -5
- package/dist/controls/rich-text/catalog.js +120 -6
- package/dist/controls/rich-text/catalog.js.map +1 -1
- package/dist/controls/rich-text/checklist.d.ts +24 -0
- package/dist/controls/rich-text/checklist.js +115 -0
- package/dist/controls/rich-text/checklist.js.map +1 -0
- package/dist/controls/rich-text/codec.d.ts +10 -1
- package/dist/controls/rich-text/codec.js +11 -1
- package/dist/controls/rich-text/codec.js.map +1 -1
- package/dist/controls/rich-text/columns.d.ts +41 -0
- package/dist/controls/rich-text/columns.js +181 -0
- package/dist/controls/rich-text/columns.js.map +1 -0
- package/dist/controls/rich-text/control.js +1 -0
- package/dist/controls/rich-text/control.js.map +1 -1
- package/dist/controls/rich-text/dom.d.ts +84 -4
- package/dist/controls/rich-text/dom.js +171 -10
- package/dist/controls/rich-text/dom.js.map +1 -1
- package/dist/controls/rich-text/editor.d.ts +4 -2
- package/dist/controls/rich-text/editor.js +184 -12
- package/dist/controls/rich-text/editor.js.map +1 -1
- package/dist/controls/rich-text/embed.d.ts +28 -0
- package/dist/controls/rich-text/embed.js +210 -0
- package/dist/controls/rich-text/embed.js.map +1 -0
- package/dist/controls/rich-text/footnote.d.ts +41 -0
- package/dist/controls/rich-text/footnote.js +185 -0
- package/dist/controls/rich-text/footnote.js.map +1 -0
- package/dist/controls/rich-text/gallery.d.ts +28 -0
- package/dist/controls/rich-text/gallery.js +167 -0
- package/dist/controls/rich-text/gallery.js.map +1 -0
- package/dist/controls/rich-text/link-form.d.ts +3 -1
- package/dist/controls/rich-text/link-form.js +2 -2
- package/dist/controls/rich-text/link-form.js.map +1 -1
- package/dist/controls/rich-text/ops.js +6 -0
- package/dist/controls/rich-text/ops.js.map +1 -1
- package/dist/controls/rich-text/related.d.ts +36 -0
- package/dist/controls/rich-text/related.js +213 -0
- package/dist/controls/rich-text/related.js.map +1 -0
- package/dist/controls/rich-text/toc.d.ts +47 -0
- package/dist/controls/rich-text/toc.js +160 -0
- package/dist/controls/rich-text/toc.js.map +1 -0
- package/dist/core/core.d.ts +11 -3
- package/dist/core/core.js +24 -6
- package/dist/core/core.js.map +1 -1
- package/dist/core/facets.d.ts +16 -0
- package/dist/core/facets.js +17 -1
- package/dist/core/facets.js.map +1 -1
- package/dist/core/index.js +2 -2
- package/dist/index.js +4 -4
- package/dist/library/kit-catalog.json +47 -44
- package/dist/schema/types.d.ts +15 -0
- package/dist/schema/types.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/ui/autocomplete.d.ts +29 -1
- package/dist/ui/autocomplete.js +102 -47
- package/dist/ui/autocomplete.js.map +1 -1
- package/dist/ui/button.js +3 -5
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/index.js +2 -2
- package/dist/ui/toast.js +1 -1
- package/package.json +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prod-types.js","names":[],"sources":["../../src/adapters/prod-types.ts"],"sourcesContent":["/**\n * PROD SHAPES — the production schema language and stored values, typed locally so the kit stays a package that could\n * leave the repo (it may not import @bettercms-ai/types, and the dashboard's pin predates F1 / F1.x-props anyway).\n *\n * Mirrors the backend at F1 + F1.x-props + link objects + tags / rating / code (72ea2b68d), then reference props\n * (73a120c50), validation parity (dd021ceba), option meta (ab15fe893), V2 chrome keys and types (98e48b9e3, 324580b2e),\n * the V2 icon vocabulary (e126bf33d) and the localized flag (279a10490) — origin/dev 81f385ff3:\n * packages/types/src/content-model.ts, component.ts, link-value.ts, button-look.ts, dock-icon-names.ts, video-value.ts\n * src/lib/validation/schemas/content.ts (baseField, fieldUiSchema, chromeUiProblems, fieldsets, MAX_FIELD_DEPTH)\n * src/lib/validation/schemas/components.ts (componentPropDefSchema, subFieldSchema, propUiSchema, propValidationHardening)\n * src/lib/content/validation-parity.ts, src/lib/content/dock-vocabulary.ts (TAB_MAX, TAB_NAME_MAX)\n * When the backend widens, widen these and the adapters together; the round-trip test then shrinks the lossy ledger.\n */\n\n/* ── Limits the backend enforces ─────────────────────────────────────── */\n/** Field levels one schema may nest (a top-level field, or a prop, is level 1). */\nexport const MAX_FIELD_DEPTH = 10;\n/** Tabs (`kind: \"tab\"` fieldsets) one screen may hold, and a tab name's length. */\nexport const TAB_MAX = 3;\nexport const TAB_NAME_MAX = 40;\nexport const FIELDSETS_MAX = 30;\nexport const FIELDSET_NAME_MAX = 60;\nexport const FIELDSET_DESCRIPTION_MAX = 500;\nexport const FIELD_HELP_MAX = 500;\nexport const PROP_HELP_MAX = 200;\nexport const PROP_PLACEHOLDER_MAX = 120;\nexport const HELP_MORE_MAX = 2000;\nexport const LOCK_REASON_MAX = 200;\nexport const ITEM_LABEL_MAX = 24;\nexport const PREVIEW_FALLBACK_MAX = 60;\nexport const PROP_GROUP_LABEL_MAX = 32;\nexport const PATTERN_MAX = 200;\n/** A tags value's tag length (TAG_VALUE_MAX_LENGTH), a code value's length (CODE_MAX_LENGTH), a rating's max with none set. */\nexport const TAG_VALUE_MAX_LENGTH = 64;\nexport const CODE_MAX_LENGTH = 100_000;\nexport const RATING_DEFAULT_MAX = 5;\n/** ratingConfigSchema: config.max a whole 1–10; (max − min) / step whole and at most this many stops. */\nexport const RATING_MAX = 10;\nexport const RATING_MAX_STOPS = 100;\n/** tagsConfigSchema: config.min 0–500, config.max 1–500. */\nexport const TAGS_ITEMS_MAX = 500;\n/** A choice option's description (OPTION_DESCRIPTION_MAX): one line. */\nexport const OPTION_DESCRIPTION_MAX = 140;\n/** config.patternMessage (PATTERN_MESSAGE_MAX), config.unit on a number (NUMBER_UNIT_MAX). */\nexport const PATTERN_MESSAGE_MAX = 200;\nexport const NUMBER_UNIT_MAX = 24;\n/** fieldUiSchema: ui.rows 1–40, ui.placeholder 1–120, ui.itemTitle 1–60, ui.synced.from 1–64. */\nexport const UI_ROWS_MAX = 40;\nexport const UI_PLACEHOLDER_MAX = 120;\nexport const ITEM_TITLE_MAX = 60;\nexport const SYNCED_FROM_MAX = 64;\n/** ui.itemName is an identifier: a letter, then letters, digits or _ (≤ 64). */\nexport const ITEM_NAME_RE = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;\n/** propUiSchema group: description 1–200, order 0–99. */\nexport const PROP_GROUP_DESCRIPTION_MAX = 200;\nexport const PROP_GROUP_ORDER_MAX = 99;\n/** propUiSchema tab: at most 8 distinct tabs per component, an id 1–40, a label ≤ TAB_NAME_MAX trimmed, order 0–99. */\nexport const PROP_TAB_MAX = 8;\nexport const PROP_TAB_ID_MAX = 40;\n/** numberScaleSchema: token value 1–32, label 1–24, title 1–60, css 1–60; 1–50 steps; at most 20 presets. */\nexport const SCALE_TOKEN_VALUE_MAX = 32;\nexport const SCALE_LABEL_MAX = 24;\nexport const SCALE_TITLE_MAX = 60;\nexport const SCALE_CSS_MAX = 60;\nexport const SCALE_STEPS_MAX = 50;\nexport const SCALE_PRESETS_MAX = 20;\n/** The video block's transcript cap (VIDEO_TRANSCRIPT_MAX). */\nexport const VIDEO_TRANSCRIPT_MAX = 100_000;\n\n/* ── Icons: the closed dock vocabulary (packages/types/src/dock-icon-names.ts at e126bf33d: 472 names, Sanity's set\n * plus every distinct V2 corpus icon but `map`; copied verbatim from that generated file, regenerate from it) ── */\nexport const DOCK_ICON_NAMES = [\n \"abc\", \"access-denied\", \"activity\", \"add\", \"add-circle\", \"add-comment\", \"add-document\", \"add-user\", \"address-book\",\n \"adjustments\", \"adjustments-horizontal\", \"alarm\", \"alert-triangle\", \"align-left\", \"api\", \"app-window\", \"apple\",\n \"apps\", \"archive\", \"arrow-back-up\", \"arrow-down\", \"arrow-guide\", \"arrow-left\", \"arrow-right\", \"arrow-top-right\",\n \"arrow-up\", \"arrows-diagonal\", \"arrows-down\", \"arrows-exchange\", \"arrows-horizontal\", \"arrows-left-right\",\n \"arrows-shuffle\", \"arrows-sort\", \"article\", \"aspect-ratio\", \"asterisk\", \"award\", \"axis-x\", \"backpack\", \"badge\",\n \"badge-cc\", \"badges\", \"bar-chart\", \"basket\", \"bell\", \"bill\", \"binary-document\", \"block-content\", \"block-element\",\n \"blockquote\", \"bold\", \"bolt\", \"book\", \"book-2\", \"bookmark\", \"bookmark-filled\", \"books\", \"bottle\", \"box\",\n \"brand-dribbble\", \"brand-facebook\", \"brand-instagram\", \"brand-linkedin\", \"brand-pinterest\", \"brand-tiktok\",\n \"brand-x\", \"brand-youtube\", \"briefcase\", \"broadcast\", \"browser\", \"bug\", \"building\", \"building-skyscraper\",\n \"building-store\", \"bulb-filled\", \"bulb-outline\", \"calculator\", \"calendar\", \"calendar-dollar\", \"calendar-event\",\n \"calendar-exclamation\", \"calendar-off\", \"calendar-plus\", \"calendar-star\", \"calendar-time\", \"camera\", \"campfire\",\n \"carousel-horizontal\", \"case\", \"cash\", \"category\", \"category-2\", \"chart-area\", \"chart-arrows\", \"chart-bar\",\n \"chart-bar-popular\", \"chart-donut\", \"chart-dots\", \"chart-line\", \"chart-upward\", \"check\", \"checkbox\", \"checklist\",\n \"checkmark\", \"checkmark-circle\", \"chef-hat\", \"chevron-down\", \"chevron-left\", \"chevron-right\", \"chevron-up\",\n \"chevrons-right\", \"circle\", \"circle-check\", \"circle-dot\", \"circle-number-1\", \"circle-plus\", \"click\", \"clipboard\",\n \"clipboard-image\", \"clipboard-text\", \"clock\", \"clock-check\", \"clock-hour-4\", \"close\", \"close-circle\", \"code\",\n \"code-block\", \"cog\", \"collapse\", \"color-wheel\", \"columns\", \"columns-2\", \"columns-3\", \"comment\", \"component\",\n \"compose\", \"compose-sparkles\", \"confetti\", \"controls\", \"cookie\", \"copy\", \"credit-card\", \"crop\", \"cube\",\n \"currency-dollar\", \"dashboard\", \"database\", \"database-search\", \"desktop\", \"device-desktop\", \"device-mobile\",\n \"device-tablet\", \"devices\", \"diamond\", \"discount\", \"document\", \"document-pdf\", \"document-remove\", \"document-sheet\",\n \"document-text\", \"document-video\", \"document-word\", \"document-zip\", \"documents\", \"door-exit\", \"dot\",\n \"double-chevron-down\", \"double-chevron-left\", \"double-chevron-right\", \"double-chevron-up\", \"double-quote\",\n \"download\", \"drag-handle\", \"drop\", \"droplet\", \"droplet-half\", \"earth-americas\", \"earth-globe\", \"edit\", \"egg\",\n \"ellipsis-horizontal\", \"ellipsis-vertical\", \"empty\", \"enter\", \"enter-right\", \"envelope\", \"equal\", \"error-filled\",\n \"error-outline\", \"error-screen\", \"expand\", \"eye-closed\", \"eye-off\", \"eye-open\", \"face-happy\", \"face-indifferent\",\n \"face-sad\", \"feather\", \"feedback\", \"file\", \"file-certificate\", \"file-code\", \"file-download\", \"file-text\", \"filter\",\n \"flag\", \"flame\", \"flask\", \"focus-2\", \"folder\", \"folders\", \"forms\", \"frame\", \"generate\", \"gift\", \"git-branch\",\n \"github\", \"grid-dots\", \"groq\", \"hammer\", \"hand-finger\", \"hanger\", \"hash\", \"headphones\", \"headset\", \"heart\",\n \"heart-filled\", \"heart-handshake\", \"help-circle\", \"highlight\", \"history\", \"home\", \"hourglass\", \"ice-cream\",\n \"id-badge\", \"id-badge-2\", \"image\", \"image-remove\", \"images\", \"inbox\", \"infinity\", \"info-circle\", \"info-filled\",\n \"info-outline\", \"info-square-rounded\", \"inline\", \"inline-element\", \"input-search\", \"insert-above\", \"insert-below\",\n \"italic\", \"joystick\", \"json\", \"language\", \"launch\", \"layout\", \"layout-align-center\", \"layout-board\",\n \"layout-board-split\", \"layout-bottombar\", \"layout-bottombar-expand\", \"layout-cards\", \"layout-columns\",\n \"layout-dashboard\", \"layout-grid\", \"layout-list\", \"layout-navbar\", \"layout-rows\", \"layout-sidebar\",\n \"layout-sidebar-right\", \"leaf\", \"leave\", \"lemon\", \"library-photo\", \"lifebuoy\", \"link\", \"link-removed\", \"linkedin\",\n \"list\", \"list-check\", \"list-details\", \"list-numbers\", \"list-tree\", \"lock\", \"logo-js\", \"logo-ts\", \"mail\", \"map-2\",\n \"map-pin\", \"map-pins\", \"marker\", \"marker-removed\", \"master-detail\", \"math-function\", \"meat\", \"menu\", \"message\",\n \"message-2\", \"message-check\", \"message-circle\", \"message-circle-2\", \"message-plus\", \"message-star\", \"microphone\",\n \"microphone-slash\", \"mobile-device\", \"mood-empty\", \"moon\", \"movie\", \"news\", \"notes\", \"number\", \"ok-hand\", \"olist\",\n \"overage\", \"package\", \"packages\", \"palette\", \"panel-left\", \"panel-right\", \"paperclip\", \"pause\", \"pencil\", \"phone\",\n \"photo\", \"photo-scan\", \"photo-search\", \"pig-money\", \"pin\", \"pin-filled\", \"pin-removed\", \"play\", \"player-play\",\n \"player-track-next\", \"playlist-add\", \"plug\", \"plug-connected\", \"plus-minus\", \"point\", \"presentation\", \"printer\",\n \"progress-50\", \"progress-75\", \"projects\", \"publish\", \"qrcode\", \"quote\", \"read-only\", \"receipt\", \"recycle\", \"redo\",\n \"refresh\", \"remove\", \"remove-circle\", \"repeat\", \"reset\", \"restore\", \"retrieve\", \"retry\", \"revert\", \"robot\",\n \"rocket\", \"rosette\", \"route\", \"ruler\", \"ruler-measure\", \"salad\", \"scale\", \"schema\", \"school\", \"search\", \"section\",\n \"select\", \"send\", \"server\", \"settings\", \"share\", \"shield-check\", \"shield-lock\", \"shopping-bag\", \"shopping-cart\",\n \"shopping-cart-plus\", \"signature\", \"sitemap\", \"slideshow\", \"sort\", \"sort-descending\", \"spacing-vertical\", \"sparkle\",\n \"sparkles\", \"speakerphone\", \"spinner\", \"split-horizontal\", \"split-vertical\", \"square\", \"stack\", \"stack-2\",\n \"stack-compact\", \"stairs\", \"stairs-up\", \"star\", \"star-filled\", \"stars\", \"stop\", \"strikethrough\", \"string\",\n \"subtask\", \"sun\", \"superscript\", \"sync\", \"table\", \"table-options\", \"tablet-device\", \"tag\", \"tags\", \"target\", \"task\",\n \"template\", \"tent\", \"terminal\", \"terminal-2\", \"text\", \"th-large\", \"th-list\", \"thumb-up\", \"thumbs-down\", \"thumbs-up\",\n \"ticket\", \"tiers\", \"timeline\", \"toggle-arrow-right\", \"toggle-right\", \"token\", \"tool\", \"tools-kitchen-2\", \"transfer\",\n \"translate\", \"trash\", \"trend-upward\", \"triangle-outline\", \"trolley\", \"truck\", \"truck-delivery\", \"truncate\",\n \"twitter\", \"typography\", \"ulist\", \"unarchive\", \"underline\", \"undo\", \"unknown\", \"unlink\", \"unlock\", \"unpublish\",\n \"upload\", \"user\", \"user-circle\", \"user-plus\", \"user-search\", \"user-star\", \"users\", \"users-group\", \"versions\",\n \"video\", \"vocabulary\", \"vs\", \"warning-filled\", \"warning-outline\", \"weight\", \"world\", \"wrench\", \"zoom-question\",\n] as const;\nexport type DockIconName = (typeof DOCK_ICON_NAMES)[number];\nexport const DOCK_ICON_NAME_SET: ReadonlySet<string> = new Set<string>(DOCK_ICON_NAMES);\n\n/* ── Content model fields ────────────────────────────────────────────── */\nexport type ProdFieldType =\n | \"text\" | \"richtext\" | \"document\" | \"image\" | \"boolean\" | \"number\" | \"select\"\n | \"reference\" | \"multi-reference\" | \"multiReference\" | \"array\" | \"date\" | \"datetime\"\n | \"longtext\" | \"slug\" | \"email\" | \"phone\" | \"link\" | \"color\" | \"json\" | \"file\"\n | \"component-ref\" | \"modular\" | \"sections\" | \"location\" | \"button\" | \"multiselect\" | \"icon\" | \"object\"\n | \"tags\" | \"rating\" | \"code\"\n /** V2 video: a URL string or `{ url, poster?, autoplay?, loop?, transcript? }` (VideoValue). */\n | \"video\"\n /** Legacy input only: normalized to `array` + zones on write, still read. */\n | \"group\" | \"repeater\";\n\nexport type OpenMode = \"inline\" | \"drill\" | \"popover\" | \"dialog\";\n/** backend SHOW_IF_OPS (validation/schemas/content.ts). */\nexport type ShowIfOp = \"eq\" | \"neq\" | \"in\" | \"notIn\" | \"gt\" | \"lt\" | \"isSet\" | \"notEmpty\" | \"empty\";\nexport interface ShowIfRule {\n field: string;\n op: ShowIfOp;\n value?: string | string[];\n}\nexport interface ShowIf {\n match: \"all\" | \"any\";\n rules: ShowIfRule[];\n}\n\nexport type UiLayout = \"list\" | \"grid\" | \"table\" | \"rows\" | \"chips\" | \"gallery\";\n/** ui.control (UI_CONTROLS): the leaf controls, the V2 control layouts among them. */\nexport const UI_CONTROLS = [\"segmented\", \"slider\", \"rating\", \"dropdown\", \"radio\", \"cards\", \"grid\", \"switch\", \"checkbox\"] as const;\nexport type UiControl = (typeof UI_CONTROLS)[number];\n/** The V2 control layouts and the types each fits (CONTROL_TYPES); segmented / slider / rating have their own rules. */\nexport const CONTROL_TYPES: Readonly<Partial<Record<UiControl, readonly string[]>>> = {\n dropdown: [\"select\"],\n radio: [\"select\"],\n cards: [\"select\", \"multiselect\"],\n grid: [\"select\"],\n switch: [\"boolean\"],\n checkbox: [\"boolean\", \"multiselect\"],\n};\n/** A row preview: child keys or dotted paths (V2), a literal fallback, and an icon shown while there is no media. */\nexport interface UiPreview {\n title?: string;\n subtitle?: string;\n media?: string;\n fallback?: string;\n icon?: DockIconName;\n}\nexport interface FieldUi {\n collapsed?: boolean;\n preview?: UiPreview;\n layout?: UiLayout;\n reorderable?: boolean;\n control?: UiControl;\n icon?: DockIconName;\n itemLabel?: string;\n /** text / longtext: the lines a text box opens with (1–40). */\n rows?: number;\n /** a field's placeholder when its config is strict (a prop keeps its own `placeholder`). */\n placeholder?: string;\n /** a list's item type: its identifier and its title (V2 `of[0].name` / `title`). */\n itemName?: string;\n itemTitle?: string;\n /** the value comes from a global: an edit applies everywhere. */\n synced?: { from: string };\n /** link / image / button: a plain string or the object. */\n valueShape?: \"string\" | \"object\";\n /** V2 field access (D58): the editor gates, the backend stores. */\n access?: { view?: \"schema.view\"; edit?: \"schema.manage\" };\n /** true = never shown in the form; false ≡ absent. */\n hidden?: boolean;\n /** modular: per block slug, how a row of that block type reads (V2 `of[i].icon` / `preview`). */\n blocks?: Record<string, { icon?: DockIconName; preview?: UiPreview }>;\n input?: { name: string; writes?: string[] };\n}\n\nexport type ScaleUnit = \"px\" | \"%\" | \"rem\" | \"em\" | \"vw\" | \"vh\";\nexport interface ScaleCustomValue {\n value: number;\n unit: ScaleUnit;\n}\nexport interface ScaleTokenStep {\n value: string;\n label: string;\n title?: string;\n px?: number;\n css?: string;\n}\nexport type ScaleBound = number | Partial<Record<ScaleUnit, number>>;\n/**\n * A number's `config.scale` (CPO D41): a stepped range, numeric steps or token steps, units, presets, and the custom\n * escape hatch (a boolean, or its bounds). A token scale stores the token string; a custom value `{ value, unit }`.\n */\nexport interface NumberScale {\n steps: { min: number; max: number; step?: number } | Array<{ value: number; label?: string }> | ScaleTokenStep[];\n units?: ScaleUnit[];\n defaultUnit?: ScaleUnit;\n allowCustom?: boolean | { min?: ScaleBound; max?: ScaleBound; units?: ScaleUnit[]; step?: number };\n presets?: Array<{ label?: string; value: number | string | ScaleCustomValue }>;\n}\n\nexport interface ArrayZoneConfig {\n nonRepeatable?: ContentModelField[];\n repeatable?: { fields: ContentModelField[]; minItems?: number; maxItems?: number };\n}\n\n/** One choice: a bare value, or `{ label, value }` with optional chrome (a dock icon, one line ≤ 140 under the label). */\nexport interface ChoiceOption {\n label: string;\n value: string;\n icon?: DockIconName;\n description?: string;\n}\nexport type SelectOption = string | ChoiceOption;\n\n/**\n * A list of scalars' item settings (backend arrayItemSettingsSchema, an `array` prop's `config.item`): the V2 item field's\n * description, locale chip, required, and a text / rich text item's length (a text item's pattern).\n */\nexport interface ArrayItemSettings {\n helpText?: string;\n localized?: boolean;\n required?: boolean;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n patternMessage?: string;\n}\n\n/** The typed keys of a field's `config` bag; the bag itself stays loose on scalar types. */\nexport interface FieldConfig {\n /** primitive array: scalars, or images, links or rich text (each item judged by its own type). */\n itemType?: \"text\" | \"number\" | \"date\" | \"image\" | \"link\" | \"richtext\";\n zones?: ArrayZoneConfig;\n contentModelId?: string;\n polymorphic?: boolean;\n allowedModelSlugs?: string[];\n /** reference / multi-reference (props): the non-entry targets, and a filter over the target's fields. */\n targets?: (\"page\" | \"form\" | \"collection\")[];\n filter?: string;\n min?: number;\n max?: number;\n step?: number;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n /** text / longtext: the message shown when the pattern does not match (≤ 200, needs `pattern`). */\n patternMessage?: string;\n /** number: the error bounds (V2 validation.min / max); they win over min / max. */\n validation?: { min?: number; max?: number };\n /** number: what it counts (\"%\", \"USD\"), 1–24 characters. */\n unit?: string;\n placeholder?: string;\n includeTime?: boolean;\n /** \"site\", an IANA zone name, true (the editor picks a zone) or false (none). */\n timezone?: string | boolean;\n blockSlugs?: string[];\n minItems?: number;\n maxItems?: number;\n allowedSections?: string[];\n componentIds?: string[];\n /** slot (props): the V2 `of.allow` block names it takes, kept as written (backend slotAllowIssues). */\n allow?: string[];\n /** array (props): the item's own settings (backend arrayItemSettingsSchema). */\n item?: ArrayItemSettings;\n scale?: NumberScale;\n /** multiselect: its choices; with `allowCustom` it is free tags. tags: its suggestions. */\n options?: SelectOption[];\n allowCustom?: boolean;\n /** code: the language, and the languages an editor may pick (strict config, with tags' and rating's). */\n language?: string;\n languages?: string[];\n /**\n * text: \"url\" marks a text field the kit edits as a URL (V2 `url`). The backend keeps a text field's config as sent and\n * enforces its minLength / maxLength / pattern, which a link field would not; it reads no other meaning into the key.\n */\n inputType?: \"url\";\n [key: string]: unknown;\n}\n\nexport interface ContentModelField {\n key: string;\n label: string;\n type: ProdFieldType;\n helpText?: string;\n required?: boolean;\n unique?: boolean;\n defaultValue?: unknown;\n /** select: strings or { label, value }. */\n options?: SelectOption[];\n config?: FieldConfig | null;\n /** object (and legacy group / repeater): child fields. */\n fields?: ContentModelField[];\n openMode?: OpenMode;\n helpMore?: string;\n advanced?: boolean;\n recommendedMax?: number;\n fieldsetId?: string;\n placement?: \"cover\" | \"title\" | \"excerpt\" | \"body\" | \"inline\" | \"panel\";\n showIf?: ShowIf;\n readOnly?: true | \"developer\";\n lockReason?: string;\n /** V2 per-field localization: once any field is marked, a translation owns only its localized values. */\n localized?: boolean;\n ui?: FieldUi;\n searchable?: boolean;\n [key: string]: unknown;\n}\n\nexport type FieldsetKind = \"group\" | \"row\" | \"tab\";\nexport interface Fieldset {\n id: string;\n name: string;\n description?: string;\n kind?: FieldsetKind;\n icon?: DockIconName;\n collapsed?: boolean;\n tab?: string;\n collapsible?: boolean;\n columns?: 1 | 2;\n layout?: \"stack\" | \"breakpoints\";\n}\n\n/** A content model as the adapters read and write it (server-owned ids and timestamps left out). */\nexport interface ProdContentModel {\n name: string;\n slug: string;\n description?: string;\n kind?: \"model\" | \"block\";\n fields: ContentModelField[];\n fieldsets?: Fieldset[];\n}\n\n/* ── Component props ─────────────────────────────────────────────────── */\nexport const COMPONENT_PROP_TYPES = [\n \"text\", \"richtext\", \"image\", \"url\", \"boolean\", \"number\", \"select\", \"group\", \"table\", \"slot\", \"form\",\n \"link\", \"button\", \"date\", \"color\", \"file\", \"icon\", \"multiselect\",\n \"object\", \"datetime\", \"slug\", \"email\", \"phone\", \"json\", \"location\", \"tags\", \"rating\", \"code\",\n /** an entry id (or `{ entryId, modelSlug }`) and a list of them, hydrated on delivery; no definition default. */\n \"reference\", \"multi-reference\",\n /** a video value, a list of `config.itemType` values, multi-line text. */\n \"video\", \"array\", \"longtext\",\n] as const;\nexport type ComponentPropType = (typeof COMPONENT_PROP_TYPES)[number];\nexport type ComponentSubFieldType = Exclude<ComponentPropType, \"slot\" | \"form\">;\n\nexport const COMPONENT_CATEGORIES = [\n \"navbar\", \"footer\", \"button\", \"section\", \"slider\", \"tabs\", \"form\", \"custom\", \"hero\", \"content\", \"social-proof\", \"conversion\",\n] as const;\nexport type ComponentCategory = (typeof COMPONENT_CATEGORIES)[number];\n\nexport interface PropGroup {\n id: string;\n label?: string;\n kind?: \"group\" | \"row\";\n icon?: DockIconName;\n collapsed?: boolean;\n /** V2 fieldset keys, on the defining prop: a line under the header (≤ 200), side by side, a static header, a\n * breakpoint switcher, and its place among the groups (0–99; absent = where its first prop sits). */\n description?: string;\n columns?: 1 | 2;\n collapsible?: boolean;\n layout?: \"stack\" | \"breakpoints\";\n order?: number;\n}\n/**\n * A top-level prop's tab. Defined once: the first top-level prop with an id carries its label / icon / order, later\n * props carry `{ id }` only. A nested prop names one as `{ id }` only (tab_nested refuses a definition there; V2 and\n * the dock ignore it); one ui.group's members share one tab.\n */\nexport interface PropTab {\n id: string;\n label?: string;\n icon?: DockIconName;\n /** its place among the tabs (0–99; absent = where its first prop sits). */\n order?: number;\n}\nexport type PropUi = FieldUi & { group?: PropGroup; tab?: PropTab };\n\nexport interface ComponentSubField {\n key: string;\n label: string;\n type: ComponentSubFieldType;\n defaultValue?: unknown;\n required?: boolean;\n /** null = no help on purpose (V2 has no description); absent = the platform's auto-help. */\n helpText?: string | null;\n placeholder?: string;\n /** strings or { label, value } (subFieldOptionSchema). */\n options?: SelectOption[];\n helpMore?: string;\n advanced?: boolean;\n recommendedMax?: number;\n /** on a table's sub-field: no two rows share it; on a list: no item repeats. */\n unique?: boolean;\n openMode?: OpenMode;\n showIf?: ShowIf;\n /** the prop's ui, inline group included (V2 fieldsets nest). */\n ui?: PropUi;\n readOnly?: true | \"developer\";\n lockReason?: string;\n localized?: boolean;\n fields?: ComponentSubField[];\n config?: { fields?: ComponentSubField[]; options?: SelectOption[] } & Record<string, unknown>;\n}\n\nexport interface ComponentPropDef {\n key: string;\n label: string;\n /**\n * Where the override writes inside the component's blockJson. Binding, not schema: the V2 language has no twin, so\n * fromTypeSchema leaves it unset and the host binds it (componentize lane) before the save.\n */\n target?: { blockId: string; path: string };\n type: ComponentPropType;\n defaultValue?: unknown;\n required?: boolean;\n /** null = no help on purpose (V2 has no description); absent = the platform's auto-help. */\n helpText?: string | null;\n placeholder?: string;\n showIf?: ShowIf;\n helpMore?: string;\n advanced?: boolean;\n recommendedMax?: number;\n /** a list prop's items (a table's rows) distinct; refused on a top-level scalar (unique_prop_scope). */\n unique?: boolean;\n openMode?: OpenMode;\n readOnly?: true | \"developer\";\n lockReason?: string;\n localized?: boolean;\n config?: {\n componentIds?: string[];\n /** slot: the V2 block names it takes (`textBlock`), resolved to the project's components by the dock. */\n allow?: string[];\n /** array: the item's own settings. */\n item?: ArrayItemSettings;\n multiple?: boolean;\n minItems?: number;\n maxItems?: number;\n options?: SelectOption[];\n fields?: ComponentSubField[];\n min?: number;\n max?: number;\n step?: number;\n /** number: the error bounds (they win over min / max). */\n validation?: { min?: number; max?: number };\n /** text / url / longtext / richtext: length (richtext: its plain text). text / url / longtext: a pattern and its message. */\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n patternMessage?: string;\n /** reference / multi-reference: the target model, or polymorphic with an allowlist of model slugs. */\n contentModelId?: string;\n polymorphic?: boolean;\n allowedModelSlugs?: string[];\n /** reference / multi-reference: page / form / collection targets (backend REF_TARGET_KINDS) and a filter over the target's fields. */\n targets?: (\"page\" | \"form\" | \"collection\")[];\n filter?: string;\n /** array: what the list holds. */\n itemType?: \"text\" | \"number\" | \"date\" | \"image\" | \"link\" | \"richtext\";\n /** table with mode \"types\" (a polymorphic list): its item types, each row's `_type` naming one. */\n itemTypes?: { name: string; label?: string; fields: ComponentSubField[]; icon?: DockIconName; preview?: UiPreview }[];\n } & Record<string, unknown>;\n ui?: PropUi;\n}\n\n/** A component as the adapters read and write it. */\n/**\n * How ONE instance of a component reads as a row in a parent's slot list (backend `components.preview`, migration 0459;\n * types ComponentPreview): V2's document-level `preview`. `title` / `subtitle` / `media` each name a TOP-LEVEL prop key\n * (the API refuses any other: preview_key_unknown), `fallback` is the literal row label (trimmed, 1..120), `icon` a dock\n * icon shown while the row has no media.\n */\nexport type ComponentPreview = UiPreview;\n/** backend componentPreviewSchema: a preview slot names a key of at most this many characters */\nexport const COMPONENT_PREVIEW_KEY_MAX = 64;\n/** backend componentPreviewSchema: the row's literal fallback label, trimmed, at most this many characters */\nexport const COMPONENT_PREVIEW_FALLBACK_MAX = 120;\n\nexport interface ProdComponent {\n name: string;\n slug: string;\n description?: string;\n category?: ComponentCategory;\n props: ComponentPropDef[];\n preview?: ComponentPreview | null;\n /** The component's dock icon (backend `components.icon`, dockIconSchema): V2's block icon. */\n icon?: DockIconName | null;\n /** The V2 tabs no top-level prop sits in (backend `components.tabs`, componentTabsSchema): declared, shown by none. */\n tabs?: PropTab[] | null;\n}\n\n/* ── Stored values ───────────────────────────────────────────────────── */\nexport const LINK_RELS = [\"nofollow\", \"sponsored\", \"ugc\"] as const;\nexport type LinkRel = (typeof LINK_RELS)[number];\nexport const LINK_VALUE_TYPES = [\"url\", \"page\", \"entry\", \"email\", \"phone\", \"anchor\", \"section\", \"file\"] as const;\nexport type LinkValueType = (typeof LINK_VALUE_TYPES)[number];\n/** The F1 link object (link-value.ts). A bare href string stays valid too. */\nexport interface ProdLinkValue {\n type?: LinkValueType;\n href: string;\n title?: string;\n newTab?: boolean;\n target?: \"_self\" | \"_blank\";\n rel?: LinkRel;\n section?: string;\n /** page / entry links: the target's id. */\n ref?: string;\n}\n\nexport const BUTTON_VARIANTS = [\"primary\", \"secondary\", \"tertiary\", \"brand\", \"dark\", \"light\", \"outline\", \"link\"] as const;\nexport type ButtonVariant = (typeof BUTTON_VARIANTS)[number];\nexport const BUTTON_SIZES = [\"sm\", \"md\", \"lg\"] as const;\n/** One button as one value (button-look.ts ButtonValue). */\nexport interface ProdButtonValue {\n label: string;\n href: string | ProdLinkValue;\n variant?: ButtonVariant;\n size?: (typeof BUTTON_SIZES)[number];\n arrow?: boolean;\n icon?: DockIconName | null;\n newTab?: boolean;\n rel?: LinkRel;\n /** Stretch across the column (backend button_full_width_invalid refuses a non-boolean a write brings). */\n fullWidth?: boolean;\n}\n\n/** 0–1 fractions of the image cut from each edge. */\nexport interface ProdImageCrop {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n/** The normalized image value (field-value-normalize.ts): other keys are dropped on write. */\nexport interface ProdImageValue {\n id?: string;\n url: string;\n name?: string;\n altText?: string;\n /** 0–1 fractions. */\n focal?: { x: number; y: number };\n crop?: ProdImageCrop;\n}\n\n/** The V2 video value's object form (video-value.ts): exactly the video block's props. A bare URL string is valid too. */\nexport const VIDEO_VALUE_KEYS = [\"url\", \"poster\", \"autoplay\", \"loop\", \"transcript\"] as const;\nexport interface ProdVideoValue {\n url: string;\n poster?: string;\n autoplay?: boolean;\n loop?: boolean;\n transcript?: string;\n}\n\n/** A polymorphic reference value. */\nexport interface ProdPolymorphicRef {\n entryId: string;\n modelSlug: string;\n}\n/**\n * A page, form or collection pick on a prop reference that also takes entries (backend reference-target-config.ts\n * targetRefOf): a bare string there is read as an entry id (acceptsEntries), so a non-entry pick names its kind.\n */\nexport interface ProdTargetRef {\n kind: \"page\" | \"form\" | \"collection\";\n id: string;\n}\n/** What a `form` prop stores. */\nexport interface ProdFormRef {\n formId: string;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"prod-types.js","names":[],"sources":["../../src/adapters/prod-types.ts"],"sourcesContent":["/**\n * PROD SHAPES — the production schema language and stored values, typed locally. The caps and key rules the backend\n * and the kit must agree on come from @bettercms-ai/types (W1a, a peer of the kit since W1c): one home per constant.\n *\n * Mirrors the backend at F1 + F1.x-props + link objects + tags / rating / code (72ea2b68d), then reference props\n * (73a120c50), validation parity (dd021ceba), option meta (ab15fe893), V2 chrome keys and types (98e48b9e3, 324580b2e),\n * the V2 icon vocabulary (e126bf33d) and the localized flag (279a10490) — origin/dev 81f385ff3:\n * packages/types/src/content-model.ts, component.ts, link-value.ts, button-look.ts, dock-icon-names.ts, video-value.ts\n * src/lib/validation/schemas/content.ts (baseField, fieldUiSchema, chromeUiProblems, fieldsets, MAX_FIELD_DEPTH)\n * src/lib/validation/schemas/components.ts (componentPropDefSchema, subFieldSchema, propUiSchema, propValidationHardening)\n * src/lib/content/validation-parity.ts, src/lib/content/dock-vocabulary.ts (TAB_MAX, TAB_NAME_MAX)\n * When the backend widens, widen these and the adapters together; the round-trip test then shrinks the lossy ledger.\n */\nimport { DEPTH_MAX, HELP_CAPS, TAB_MAX as SHARED_TAB_MAX, TAB_MAX_RENDERABLE_NOW } from \"@bettercms-ai/types\";\n\n/* ── Limits the backend enforces ─────────────────────────────────────── */\n/** Field levels one schema may nest (a top-level field, or a prop, is level 1). */\nexport const MAX_FIELD_DEPTH = DEPTH_MAX;\n/** Tabs (`kind: \"tab\"` fieldsets) a model screen holds TODAY (it rises to types' TAB_MAX at F12), and a tab name's length. */\nexport const TAB_MAX = TAB_MAX_RENDERABLE_NOW;\nexport const TAB_NAME_MAX = 40;\nexport const FIELDSETS_MAX = 30;\nexport const FIELDSET_NAME_MAX = 60;\nexport const FIELDSET_DESCRIPTION_MAX = HELP_CAPS.fieldset;\nexport const FIELD_HELP_MAX = HELP_CAPS.field;\nexport const PROP_HELP_MAX = HELP_CAPS.prop;\nexport const PROP_PLACEHOLDER_MAX = HELP_CAPS.placeholder;\nexport const HELP_MORE_MAX = HELP_CAPS.helpMore;\nexport const LOCK_REASON_MAX = 200;\nexport const ITEM_LABEL_MAX = 24;\nexport const PREVIEW_FALLBACK_MAX = 60;\nexport const PROP_GROUP_LABEL_MAX = 32;\nexport const PATTERN_MAX = 200;\n/** A tags value's tag length (TAG_VALUE_MAX_LENGTH), a code value's length (CODE_MAX_LENGTH), a rating's max with none set. */\nexport const TAG_VALUE_MAX_LENGTH = 64;\nexport const CODE_MAX_LENGTH = 100_000;\nexport const RATING_DEFAULT_MAX = 5;\n/** ratingConfigSchema: config.max a whole 1–10; (max − min) / step whole and at most this many stops. */\nexport const RATING_MAX = 10;\nexport const RATING_MAX_STOPS = 100;\n/** tagsConfigSchema: config.min 0–500, config.max 1–500. */\nexport const TAGS_ITEMS_MAX = 500;\n/** A choice option's description (OPTION_DESCRIPTION_MAX): one line. */\nexport const OPTION_DESCRIPTION_MAX = HELP_CAPS.option;\n/** config.patternMessage (PATTERN_MESSAGE_MAX), config.unit on a number (NUMBER_UNIT_MAX). */\nexport const PATTERN_MESSAGE_MAX = 200;\nexport const NUMBER_UNIT_MAX = 24;\n/** fieldUiSchema: ui.rows 1–40, ui.placeholder 1–120, ui.itemTitle 1–60, ui.synced.from 1–64. */\nexport const UI_ROWS_MAX = 40;\nexport const UI_PLACEHOLDER_MAX = HELP_CAPS.placeholder;\nexport const ITEM_TITLE_MAX = 60;\nexport const SYNCED_FROM_MAX = 64;\n/** ui.itemName is an identifier: a letter, then letters, digits or _ (≤ 64). */\nexport const ITEM_NAME_RE = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;\n/** propUiSchema group: description 1–200, order 0–99. */\nexport const PROP_GROUP_DESCRIPTION_MAX = HELP_CAPS.propGroup;\nexport const PROP_GROUP_ORDER_MAX = 99;\n/** propUiSchema tab: at most 8 distinct tabs per component, an id 1–40, a label ≤ TAB_NAME_MAX trimmed, order 0–99. */\nexport const PROP_TAB_MAX = SHARED_TAB_MAX;\nexport const PROP_TAB_ID_MAX = 40;\n/** numberScaleSchema: token value 1–32, label 1–24, title 1–60, css 1–60; 1–50 steps; at most 20 presets. */\nexport const SCALE_TOKEN_VALUE_MAX = 32;\nexport const SCALE_LABEL_MAX = 24;\nexport const SCALE_TITLE_MAX = 60;\nexport const SCALE_CSS_MAX = 60;\nexport const SCALE_STEPS_MAX = 50;\nexport const SCALE_PRESETS_MAX = 20;\n/** The video block's transcript cap (VIDEO_TRANSCRIPT_MAX). */\nexport const VIDEO_TRANSCRIPT_MAX = 100_000;\n\n/* ── Icons: the closed dock vocabulary (packages/types/src/dock-icon-names.ts at e126bf33d: 472 names, Sanity's set\n * plus every distinct V2 corpus icon but `map`; copied verbatim from that generated file, regenerate from it) ── */\nexport const DOCK_ICON_NAMES = [\n \"abc\", \"access-denied\", \"activity\", \"add\", \"add-circle\", \"add-comment\", \"add-document\", \"add-user\", \"address-book\",\n \"adjustments\", \"adjustments-horizontal\", \"alarm\", \"alert-triangle\", \"align-left\", \"api\", \"app-window\", \"apple\",\n \"apps\", \"archive\", \"arrow-back-up\", \"arrow-down\", \"arrow-guide\", \"arrow-left\", \"arrow-right\", \"arrow-top-right\",\n \"arrow-up\", \"arrows-diagonal\", \"arrows-down\", \"arrows-exchange\", \"arrows-horizontal\", \"arrows-left-right\",\n \"arrows-shuffle\", \"arrows-sort\", \"article\", \"aspect-ratio\", \"asterisk\", \"award\", \"axis-x\", \"backpack\", \"badge\",\n \"badge-cc\", \"badges\", \"bar-chart\", \"basket\", \"bell\", \"bill\", \"binary-document\", \"block-content\", \"block-element\",\n \"blockquote\", \"bold\", \"bolt\", \"book\", \"book-2\", \"bookmark\", \"bookmark-filled\", \"books\", \"bottle\", \"box\",\n \"brand-dribbble\", \"brand-facebook\", \"brand-instagram\", \"brand-linkedin\", \"brand-pinterest\", \"brand-tiktok\",\n \"brand-x\", \"brand-youtube\", \"briefcase\", \"broadcast\", \"browser\", \"bug\", \"building\", \"building-skyscraper\",\n \"building-store\", \"bulb-filled\", \"bulb-outline\", \"calculator\", \"calendar\", \"calendar-dollar\", \"calendar-event\",\n \"calendar-exclamation\", \"calendar-off\", \"calendar-plus\", \"calendar-star\", \"calendar-time\", \"camera\", \"campfire\",\n \"carousel-horizontal\", \"case\", \"cash\", \"category\", \"category-2\", \"chart-area\", \"chart-arrows\", \"chart-bar\",\n \"chart-bar-popular\", \"chart-donut\", \"chart-dots\", \"chart-line\", \"chart-upward\", \"check\", \"checkbox\", \"checklist\",\n \"checkmark\", \"checkmark-circle\", \"chef-hat\", \"chevron-down\", \"chevron-left\", \"chevron-right\", \"chevron-up\",\n \"chevrons-right\", \"circle\", \"circle-check\", \"circle-dot\", \"circle-number-1\", \"circle-plus\", \"click\", \"clipboard\",\n \"clipboard-image\", \"clipboard-text\", \"clock\", \"clock-check\", \"clock-hour-4\", \"close\", \"close-circle\", \"code\",\n \"code-block\", \"cog\", \"collapse\", \"color-wheel\", \"columns\", \"columns-2\", \"columns-3\", \"comment\", \"component\",\n \"compose\", \"compose-sparkles\", \"confetti\", \"controls\", \"cookie\", \"copy\", \"credit-card\", \"crop\", \"cube\",\n \"currency-dollar\", \"dashboard\", \"database\", \"database-search\", \"desktop\", \"device-desktop\", \"device-mobile\",\n \"device-tablet\", \"devices\", \"diamond\", \"discount\", \"document\", \"document-pdf\", \"document-remove\", \"document-sheet\",\n \"document-text\", \"document-video\", \"document-word\", \"document-zip\", \"documents\", \"door-exit\", \"dot\",\n \"double-chevron-down\", \"double-chevron-left\", \"double-chevron-right\", \"double-chevron-up\", \"double-quote\",\n \"download\", \"drag-handle\", \"drop\", \"droplet\", \"droplet-half\", \"earth-americas\", \"earth-globe\", \"edit\", \"egg\",\n \"ellipsis-horizontal\", \"ellipsis-vertical\", \"empty\", \"enter\", \"enter-right\", \"envelope\", \"equal\", \"error-filled\",\n \"error-outline\", \"error-screen\", \"expand\", \"eye-closed\", \"eye-off\", \"eye-open\", \"face-happy\", \"face-indifferent\",\n \"face-sad\", \"feather\", \"feedback\", \"file\", \"file-certificate\", \"file-code\", \"file-download\", \"file-text\", \"filter\",\n \"flag\", \"flame\", \"flask\", \"focus-2\", \"folder\", \"folders\", \"forms\", \"frame\", \"generate\", \"gift\", \"git-branch\",\n \"github\", \"grid-dots\", \"groq\", \"hammer\", \"hand-finger\", \"hanger\", \"hash\", \"headphones\", \"headset\", \"heart\",\n \"heart-filled\", \"heart-handshake\", \"help-circle\", \"highlight\", \"history\", \"home\", \"hourglass\", \"ice-cream\",\n \"id-badge\", \"id-badge-2\", \"image\", \"image-remove\", \"images\", \"inbox\", \"infinity\", \"info-circle\", \"info-filled\",\n \"info-outline\", \"info-square-rounded\", \"inline\", \"inline-element\", \"input-search\", \"insert-above\", \"insert-below\",\n \"italic\", \"joystick\", \"json\", \"language\", \"launch\", \"layout\", \"layout-align-center\", \"layout-board\",\n \"layout-board-split\", \"layout-bottombar\", \"layout-bottombar-expand\", \"layout-cards\", \"layout-columns\",\n \"layout-dashboard\", \"layout-grid\", \"layout-list\", \"layout-navbar\", \"layout-rows\", \"layout-sidebar\",\n \"layout-sidebar-right\", \"leaf\", \"leave\", \"lemon\", \"library-photo\", \"lifebuoy\", \"link\", \"link-removed\", \"linkedin\",\n \"list\", \"list-check\", \"list-details\", \"list-numbers\", \"list-tree\", \"lock\", \"logo-js\", \"logo-ts\", \"mail\", \"map-2\",\n \"map-pin\", \"map-pins\", \"marker\", \"marker-removed\", \"master-detail\", \"math-function\", \"meat\", \"menu\", \"message\",\n \"message-2\", \"message-check\", \"message-circle\", \"message-circle-2\", \"message-plus\", \"message-star\", \"microphone\",\n \"microphone-slash\", \"mobile-device\", \"mood-empty\", \"moon\", \"movie\", \"news\", \"notes\", \"number\", \"ok-hand\", \"olist\",\n \"overage\", \"package\", \"packages\", \"palette\", \"panel-left\", \"panel-right\", \"paperclip\", \"pause\", \"pencil\", \"phone\",\n \"photo\", \"photo-scan\", \"photo-search\", \"pig-money\", \"pin\", \"pin-filled\", \"pin-removed\", \"play\", \"player-play\",\n \"player-track-next\", \"playlist-add\", \"plug\", \"plug-connected\", \"plus-minus\", \"point\", \"presentation\", \"printer\",\n \"progress-50\", \"progress-75\", \"projects\", \"publish\", \"qrcode\", \"quote\", \"read-only\", \"receipt\", \"recycle\", \"redo\",\n \"refresh\", \"remove\", \"remove-circle\", \"repeat\", \"reset\", \"restore\", \"retrieve\", \"retry\", \"revert\", \"robot\",\n \"rocket\", \"rosette\", \"route\", \"ruler\", \"ruler-measure\", \"salad\", \"scale\", \"schema\", \"school\", \"search\", \"section\",\n \"select\", \"send\", \"server\", \"settings\", \"share\", \"shield-check\", \"shield-lock\", \"shopping-bag\", \"shopping-cart\",\n \"shopping-cart-plus\", \"signature\", \"sitemap\", \"slideshow\", \"sort\", \"sort-descending\", \"spacing-vertical\", \"sparkle\",\n \"sparkles\", \"speakerphone\", \"spinner\", \"split-horizontal\", \"split-vertical\", \"square\", \"stack\", \"stack-2\",\n \"stack-compact\", \"stairs\", \"stairs-up\", \"star\", \"star-filled\", \"stars\", \"stop\", \"strikethrough\", \"string\",\n \"subtask\", \"sun\", \"superscript\", \"sync\", \"table\", \"table-options\", \"tablet-device\", \"tag\", \"tags\", \"target\", \"task\",\n \"template\", \"tent\", \"terminal\", \"terminal-2\", \"text\", \"th-large\", \"th-list\", \"thumb-up\", \"thumbs-down\", \"thumbs-up\",\n \"ticket\", \"tiers\", \"timeline\", \"toggle-arrow-right\", \"toggle-right\", \"token\", \"tool\", \"tools-kitchen-2\", \"transfer\",\n \"translate\", \"trash\", \"trend-upward\", \"triangle-outline\", \"trolley\", \"truck\", \"truck-delivery\", \"truncate\",\n \"twitter\", \"typography\", \"ulist\", \"unarchive\", \"underline\", \"undo\", \"unknown\", \"unlink\", \"unlock\", \"unpublish\",\n \"upload\", \"user\", \"user-circle\", \"user-plus\", \"user-search\", \"user-star\", \"users\", \"users-group\", \"versions\",\n \"video\", \"vocabulary\", \"vs\", \"warning-filled\", \"warning-outline\", \"weight\", \"world\", \"wrench\", \"zoom-question\",\n] as const;\nexport type DockIconName = (typeof DOCK_ICON_NAMES)[number];\nexport const DOCK_ICON_NAME_SET: ReadonlySet<string> = new Set<string>(DOCK_ICON_NAMES);\n\n/* ── Content model fields ────────────────────────────────────────────── */\nexport type ProdFieldType =\n | \"text\" | \"richtext\" | \"document\" | \"image\" | \"boolean\" | \"number\" | \"select\"\n | \"reference\" | \"multi-reference\" | \"multiReference\" | \"array\" | \"date\" | \"datetime\"\n | \"longtext\" | \"slug\" | \"email\" | \"phone\" | \"link\" | \"color\" | \"json\" | \"file\"\n | \"component-ref\" | \"modular\" | \"sections\" | \"location\" | \"button\" | \"multiselect\" | \"icon\" | \"object\"\n | \"tags\" | \"rating\" | \"code\"\n /** V2 video: a URL string or `{ url, poster?, autoplay?, loop?, transcript? }` (VideoValue). */\n | \"video\"\n /** Legacy input only: normalized to `array` + zones on write, still read. */\n | \"group\" | \"repeater\";\n\nexport type OpenMode = \"inline\" | \"drill\" | \"popover\" | \"dialog\";\n/** backend SHOW_IF_OPS (validation/schemas/content.ts). */\nexport type ShowIfOp = \"eq\" | \"neq\" | \"in\" | \"notIn\" | \"gt\" | \"lt\" | \"isSet\" | \"notEmpty\" | \"empty\";\nexport interface ShowIfRule {\n field: string;\n op: ShowIfOp;\n value?: string | string[];\n}\nexport interface ShowIf {\n match: \"all\" | \"any\";\n rules: ShowIfRule[];\n}\n\nexport type UiLayout = \"list\" | \"grid\" | \"table\" | \"rows\" | \"chips\" | \"gallery\";\n/** ui.control (UI_CONTROLS): the leaf controls, the V2 control layouts among them. */\nexport const UI_CONTROLS = [\"segmented\", \"slider\", \"rating\", \"dropdown\", \"radio\", \"cards\", \"grid\", \"switch\", \"checkbox\"] as const;\nexport type UiControl = (typeof UI_CONTROLS)[number];\n/** The V2 control layouts and the types each fits (CONTROL_TYPES); segmented / slider / rating have their own rules. */\nexport const CONTROL_TYPES: Readonly<Partial<Record<UiControl, readonly string[]>>> = {\n dropdown: [\"select\"],\n radio: [\"select\"],\n cards: [\"select\", \"multiselect\"],\n grid: [\"select\"],\n switch: [\"boolean\"],\n checkbox: [\"boolean\", \"multiselect\"],\n};\n/** A row preview: child keys or dotted paths (V2), a literal fallback, and an icon shown while there is no media. */\nexport interface UiPreview {\n title?: string;\n subtitle?: string;\n media?: string;\n fallback?: string;\n icon?: DockIconName;\n}\nexport interface FieldUi {\n collapsed?: boolean;\n preview?: UiPreview;\n layout?: UiLayout;\n reorderable?: boolean;\n control?: UiControl;\n icon?: DockIconName;\n itemLabel?: string;\n /** text / longtext: the lines a text box opens with (1–40). */\n rows?: number;\n /** a field's placeholder when its config is strict (a prop keeps its own `placeholder`). */\n placeholder?: string;\n /** a list's item type: its identifier and its title (V2 `of[0].name` / `title`). */\n itemName?: string;\n itemTitle?: string;\n /** the value comes from a global: an edit applies everywhere. */\n synced?: { from: string };\n /** link / image / button: a plain string or the object. */\n valueShape?: \"string\" | \"object\";\n /** V2 field access (D58): the editor gates, the backend stores. */\n access?: { view?: \"schema.view\"; edit?: \"schema.manage\" };\n /** true = never shown in the form; false ≡ absent. */\n hidden?: boolean;\n /** modular: per block slug, how a row of that block type reads (V2 `of[i].icon` / `preview`). */\n blocks?: Record<string, { icon?: DockIconName; preview?: UiPreview }>;\n input?: { name: string; writes?: string[] };\n}\n\nexport type ScaleUnit = \"px\" | \"%\" | \"rem\" | \"em\" | \"vw\" | \"vh\";\nexport interface ScaleCustomValue {\n value: number;\n unit: ScaleUnit;\n}\nexport interface ScaleTokenStep {\n value: string;\n label: string;\n title?: string;\n px?: number;\n css?: string;\n}\nexport type ScaleBound = number | Partial<Record<ScaleUnit, number>>;\n/**\n * A number's `config.scale` (CPO D41): a stepped range, numeric steps or token steps, units, presets, and the custom\n * escape hatch (a boolean, or its bounds). A token scale stores the token string; a custom value `{ value, unit }`.\n */\nexport interface NumberScale {\n steps: { min: number; max: number; step?: number } | Array<{ value: number; label?: string }> | ScaleTokenStep[];\n units?: ScaleUnit[];\n defaultUnit?: ScaleUnit;\n allowCustom?: boolean | { min?: ScaleBound; max?: ScaleBound; units?: ScaleUnit[]; step?: number };\n presets?: Array<{ label?: string; value: number | string | ScaleCustomValue }>;\n}\n\nexport interface ArrayZoneConfig {\n nonRepeatable?: ContentModelField[];\n repeatable?: { fields: ContentModelField[]; minItems?: number; maxItems?: number };\n}\n\n/** One choice: a bare value, or `{ label, value }` with optional chrome (a dock icon, one line ≤ 140 under the label). */\nexport interface ChoiceOption {\n label: string;\n value: string;\n icon?: DockIconName;\n description?: string;\n}\nexport type SelectOption = string | ChoiceOption;\n\n/**\n * A list of scalars' item settings (backend arrayItemSettingsSchema, an `array` prop's `config.item`): the V2 item field's\n * description, locale chip, required, and a text / rich text item's length (a text item's pattern).\n */\nexport interface ArrayItemSettings {\n helpText?: string;\n localized?: boolean;\n required?: boolean;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n patternMessage?: string;\n}\n\n/** The typed keys of a field's `config` bag; the bag itself stays loose on scalar types. */\nexport interface FieldConfig {\n /** primitive array: scalars, or images, links or rich text (each item judged by its own type). */\n itemType?: \"text\" | \"number\" | \"date\" | \"image\" | \"link\" | \"richtext\";\n zones?: ArrayZoneConfig;\n contentModelId?: string;\n polymorphic?: boolean;\n allowedModelSlugs?: string[];\n /** reference / multi-reference (props): the non-entry targets, and a filter over the target's fields. */\n targets?: (\"page\" | \"form\" | \"collection\")[];\n filter?: string;\n min?: number;\n max?: number;\n step?: number;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n /** text / longtext: the message shown when the pattern does not match (≤ 200, needs `pattern`). */\n patternMessage?: string;\n /** number: the error bounds (V2 validation.min / max); they win over min / max. */\n validation?: { min?: number; max?: number };\n /** number: what it counts (\"%\", \"USD\"), 1–24 characters. */\n unit?: string;\n placeholder?: string;\n includeTime?: boolean;\n /** \"site\", an IANA zone name, true (the editor picks a zone) or false (none). */\n timezone?: string | boolean;\n blockSlugs?: string[];\n minItems?: number;\n maxItems?: number;\n allowedSections?: string[];\n componentIds?: string[];\n /** slot (props): the V2 `of.allow` block names it takes, kept as written (backend slotAllowIssues). */\n allow?: string[];\n /** array (props): the item's own settings (backend arrayItemSettingsSchema). */\n item?: ArrayItemSettings;\n scale?: NumberScale;\n /** multiselect: its choices; with `allowCustom` it is free tags. tags: its suggestions. */\n options?: SelectOption[];\n allowCustom?: boolean;\n /** code: the language, and the languages an editor may pick (strict config, with tags' and rating's). */\n language?: string;\n languages?: string[];\n /**\n * text: \"url\" marks a text field the kit edits as a URL (V2 `url`). The backend keeps a text field's config as sent and\n * enforces its minLength / maxLength / pattern, which a link field would not; it reads no other meaning into the key.\n */\n inputType?: \"url\";\n [key: string]: unknown;\n}\n\nexport interface ContentModelField {\n key: string;\n label: string;\n type: ProdFieldType;\n helpText?: string;\n required?: boolean;\n unique?: boolean;\n defaultValue?: unknown;\n /** select: strings or { label, value }. */\n options?: SelectOption[];\n config?: FieldConfig | null;\n /** object (and legacy group / repeater): child fields. */\n fields?: ContentModelField[];\n openMode?: OpenMode;\n helpMore?: string;\n advanced?: boolean;\n recommendedMax?: number;\n fieldsetId?: string;\n placement?: \"cover\" | \"title\" | \"excerpt\" | \"body\" | \"inline\" | \"panel\";\n showIf?: ShowIf;\n readOnly?: true | \"developer\";\n lockReason?: string;\n /** V2 per-field localization: once any field is marked, a translation owns only its localized values. */\n localized?: boolean;\n ui?: FieldUi;\n searchable?: boolean;\n [key: string]: unknown;\n}\n\nexport type FieldsetKind = \"group\" | \"row\" | \"tab\";\nexport interface Fieldset {\n id: string;\n name: string;\n description?: string;\n kind?: FieldsetKind;\n icon?: DockIconName;\n collapsed?: boolean;\n tab?: string;\n collapsible?: boolean;\n columns?: 1 | 2;\n layout?: \"stack\" | \"breakpoints\";\n}\n\n/** A content model as the adapters read and write it (server-owned ids and timestamps left out). */\nexport interface ProdContentModel {\n name: string;\n slug: string;\n description?: string;\n kind?: \"model\" | \"block\";\n fields: ContentModelField[];\n fieldsets?: Fieldset[];\n}\n\n/* ── Component props ─────────────────────────────────────────────────── */\nexport const COMPONENT_PROP_TYPES = [\n \"text\", \"richtext\", \"image\", \"url\", \"boolean\", \"number\", \"select\", \"group\", \"table\", \"slot\", \"form\",\n \"link\", \"button\", \"date\", \"color\", \"file\", \"icon\", \"multiselect\",\n \"object\", \"datetime\", \"slug\", \"email\", \"phone\", \"json\", \"location\", \"tags\", \"rating\", \"code\",\n /** an entry id (or `{ entryId, modelSlug }`) and a list of them, hydrated on delivery; no definition default. */\n \"reference\", \"multi-reference\",\n /** a video value, a list of `config.itemType` values, multi-line text. */\n \"video\", \"array\", \"longtext\",\n] as const;\nexport type ComponentPropType = (typeof COMPONENT_PROP_TYPES)[number];\nexport type ComponentSubFieldType = Exclude<ComponentPropType, \"slot\" | \"form\">;\n\nexport const COMPONENT_CATEGORIES = [\n \"navbar\", \"footer\", \"button\", \"section\", \"slider\", \"tabs\", \"form\", \"custom\", \"hero\", \"content\", \"social-proof\", \"conversion\",\n] as const;\nexport type ComponentCategory = (typeof COMPONENT_CATEGORIES)[number];\n\nexport interface PropGroup {\n id: string;\n label?: string;\n kind?: \"group\" | \"row\";\n icon?: DockIconName;\n collapsed?: boolean;\n /** V2 fieldset keys, on the defining prop: a line under the header (≤ 200), side by side, a static header, a\n * breakpoint switcher, and its place among the groups (0–99; absent = where its first prop sits). */\n description?: string;\n columns?: 1 | 2;\n collapsible?: boolean;\n layout?: \"stack\" | \"breakpoints\";\n order?: number;\n}\n/**\n * A top-level prop's tab. Defined once: the first top-level prop with an id carries its label / icon / order, later\n * props carry `{ id }` only. A nested prop names one as `{ id }` only (tab_nested refuses a definition there; V2 and\n * the dock ignore it); one ui.group's members share one tab.\n */\nexport interface PropTab {\n id: string;\n label?: string;\n icon?: DockIconName;\n /** its place among the tabs (0–99; absent = where its first prop sits). */\n order?: number;\n}\nexport type PropUi = FieldUi & { group?: PropGroup; tab?: PropTab };\n\nexport interface ComponentSubField {\n key: string;\n label: string;\n type: ComponentSubFieldType;\n defaultValue?: unknown;\n required?: boolean;\n /** null = no help on purpose (V2 has no description); absent = the platform's auto-help. */\n helpText?: string | null;\n placeholder?: string;\n /** strings or { label, value } (subFieldOptionSchema). */\n options?: SelectOption[];\n helpMore?: string;\n advanced?: boolean;\n recommendedMax?: number;\n /** on a table's sub-field: no two rows share it; on a list: no item repeats. */\n unique?: boolean;\n openMode?: OpenMode;\n showIf?: ShowIf;\n /** the prop's ui, inline group included (V2 fieldsets nest). */\n ui?: PropUi;\n readOnly?: true | \"developer\";\n lockReason?: string;\n localized?: boolean;\n fields?: ComponentSubField[];\n config?: { fields?: ComponentSubField[]; options?: SelectOption[] } & Record<string, unknown>;\n}\n\nexport interface ComponentPropDef {\n key: string;\n label: string;\n /**\n * Where the override writes inside the component's blockJson. Binding, not schema: the V2 language has no twin, so\n * fromTypeSchema leaves it unset and the host binds it (componentize lane) before the save.\n */\n target?: { blockId: string; path: string };\n type: ComponentPropType;\n defaultValue?: unknown;\n required?: boolean;\n /** null = no help on purpose (V2 has no description); absent = the platform's auto-help. */\n helpText?: string | null;\n placeholder?: string;\n showIf?: ShowIf;\n helpMore?: string;\n advanced?: boolean;\n recommendedMax?: number;\n /** a list prop's items (a table's rows) distinct; refused on a top-level scalar (unique_prop_scope). */\n unique?: boolean;\n openMode?: OpenMode;\n readOnly?: true | \"developer\";\n lockReason?: string;\n localized?: boolean;\n config?: {\n componentIds?: string[];\n /** slot: the V2 block names it takes (`textBlock`), resolved to the project's components by the dock. */\n allow?: string[];\n /** array: the item's own settings. */\n item?: ArrayItemSettings;\n multiple?: boolean;\n minItems?: number;\n maxItems?: number;\n options?: SelectOption[];\n fields?: ComponentSubField[];\n min?: number;\n max?: number;\n step?: number;\n /** number: the error bounds (they win over min / max). */\n validation?: { min?: number; max?: number };\n /** text / url / longtext / richtext: length (richtext: its plain text). text / url / longtext: a pattern and its message. */\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n patternMessage?: string;\n /** reference / multi-reference: the target model, or polymorphic with an allowlist of model slugs. */\n contentModelId?: string;\n polymorphic?: boolean;\n allowedModelSlugs?: string[];\n /** reference / multi-reference: page / form / collection targets (backend REF_TARGET_KINDS) and a filter over the target's fields. */\n targets?: (\"page\" | \"form\" | \"collection\")[];\n filter?: string;\n /** array: what the list holds. */\n itemType?: \"text\" | \"number\" | \"date\" | \"image\" | \"link\" | \"richtext\";\n /** table with mode \"types\" (a polymorphic list): its item types, each row's `_type` naming one. */\n itemTypes?: { name: string; label?: string; fields: ComponentSubField[]; icon?: DockIconName; preview?: UiPreview }[];\n } & Record<string, unknown>;\n ui?: PropUi;\n}\n\n/** A component as the adapters read and write it. */\n/**\n * How ONE instance of a component reads as a row in a parent's slot list (backend `components.preview`, migration 0459;\n * types ComponentPreview): V2's document-level `preview`. `title` / `subtitle` / `media` each name a TOP-LEVEL prop key\n * (the API refuses any other: preview_key_unknown), `fallback` is the literal row label (trimmed, 1..120), `icon` a dock\n * icon shown while the row has no media.\n */\nexport type ComponentPreview = UiPreview;\n/** backend componentPreviewSchema: a preview slot names a key of at most this many characters */\nexport const COMPONENT_PREVIEW_KEY_MAX = 64;\n/** backend componentPreviewSchema: the row's literal fallback label, trimmed, at most this many characters */\nexport const COMPONENT_PREVIEW_FALLBACK_MAX = 120;\n\nexport interface ProdComponent {\n name: string;\n slug: string;\n description?: string;\n category?: ComponentCategory;\n props: ComponentPropDef[];\n preview?: ComponentPreview | null;\n /** The component's dock icon (backend `components.icon`, dockIconSchema): V2's block icon. */\n icon?: DockIconName | null;\n /** The V2 tabs no top-level prop sits in (backend `components.tabs`, componentTabsSchema): declared, shown by none. */\n tabs?: PropTab[] | null;\n}\n\n/* ── Stored values ───────────────────────────────────────────────────── */\nexport const LINK_RELS = [\"nofollow\", \"sponsored\", \"ugc\"] as const;\nexport type LinkRel = (typeof LINK_RELS)[number];\nexport const LINK_VALUE_TYPES = [\"url\", \"page\", \"entry\", \"email\", \"phone\", \"anchor\", \"section\", \"file\"] as const;\nexport type LinkValueType = (typeof LINK_VALUE_TYPES)[number];\n/** The F1 link object (link-value.ts). A bare href string stays valid too. */\nexport interface ProdLinkValue {\n type?: LinkValueType;\n href: string;\n title?: string;\n newTab?: boolean;\n target?: \"_self\" | \"_blank\";\n rel?: LinkRel;\n section?: string;\n /** page / entry links: the target's id. */\n ref?: string;\n}\n\nexport const BUTTON_VARIANTS = [\"primary\", \"secondary\", \"tertiary\", \"brand\", \"dark\", \"light\", \"outline\", \"link\"] as const;\nexport type ButtonVariant = (typeof BUTTON_VARIANTS)[number];\nexport const BUTTON_SIZES = [\"sm\", \"md\", \"lg\"] as const;\n/** One button as one value (button-look.ts ButtonValue). */\nexport interface ProdButtonValue {\n label: string;\n href: string | ProdLinkValue;\n variant?: ButtonVariant;\n size?: (typeof BUTTON_SIZES)[number];\n arrow?: boolean;\n icon?: DockIconName | null;\n newTab?: boolean;\n rel?: LinkRel;\n /** Stretch across the column (backend button_full_width_invalid refuses a non-boolean a write brings). */\n fullWidth?: boolean;\n}\n\n/** 0–1 fractions of the image cut from each edge. */\nexport interface ProdImageCrop {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n/** The normalized image value (field-value-normalize.ts): other keys are dropped on write. */\nexport interface ProdImageValue {\n id?: string;\n url: string;\n name?: string;\n altText?: string;\n /** 0–1 fractions. */\n focal?: { x: number; y: number };\n crop?: ProdImageCrop;\n}\n\n/** The V2 video value's object form (video-value.ts): exactly the video block's props. A bare URL string is valid too. */\nexport const VIDEO_VALUE_KEYS = [\"url\", \"poster\", \"autoplay\", \"loop\", \"transcript\"] as const;\nexport interface ProdVideoValue {\n url: string;\n poster?: string;\n autoplay?: boolean;\n loop?: boolean;\n transcript?: string;\n}\n\n/** A polymorphic reference value. */\nexport interface ProdPolymorphicRef {\n entryId: string;\n modelSlug: string;\n}\n/**\n * A page, form or collection pick on a prop reference that also takes entries (backend reference-target-config.ts\n * targetRefOf): a bare string there is read as an entry id (acceptsEntries), so a non-entry pick names its kind.\n */\nexport interface ProdTargetRef {\n kind: \"page\" | \"form\" | \"collection\";\n id: string;\n}\n/** What a `form` prop stores. */\nexport interface ProdFormRef {\n formId: string;\n}\n"],"mappings":"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"}
|
package/dist/adapters/schema.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { CATALOG, FEATURES, isHostConfigKey } from "./lossy.js";
|
|
2
|
-
import { CONTROL_TYPES, HELP_MORE_MAX, ITEM_NAME_RE, UI_CONTROLS } from "./prod-types.js";
|
|
2
|
+
import { CONTROL_TYPES, FIELDSET_DESCRIPTION_MAX, FIELD_HELP_MAX, HELP_MORE_MAX, ITEM_NAME_RE, MAX_FIELD_DEPTH, OPTION_DESCRIPTION_MAX, PROP_GROUP_DESCRIPTION_MAX, PROP_HELP_MAX, PROP_PLACEHOLDER_MAX, PROP_TAB_MAX, TAB_MAX as TAB_MAX$1, UI_CONTROLS, UI_PLACEHOLDER_MAX } from "./prod-types.js";
|
|
3
3
|
import { dockIconOf, tablerIconOf } from "./icons.js";
|
|
4
4
|
import { slotChildrenFromStored, slotChildrenToStored } from "../controls/slot-services.js";
|
|
5
5
|
import { isDataTableProp, tableConfigFromOptions, tableOptionsFromConfig } from "../controls/table/prod.js";
|
|
6
6
|
import { buttonFromProd, buttonToProd, datetimeFromProd, datetimeToProd, imageFromProd, imageToProd, isCropRect, linkFromProd, linkToProd, listFromProd, listToProd, ratingFromProd, ratingToProd, referenceFromProd, referenceToProd, scaleFromProd, scaleToProd, typedRowsFromProd, typedRowsToProd, videoFromProd, videoToProd, zoneListFromProd, zoneListToProd } from "./values.js";
|
|
7
|
+
import { BLOCK_FIELD_TYPES_RENDERABLE_NOW, KEY_FORMAT, PRIMITIVE_ARRAY_RULE, RICHTEXT_FEATURES, isReservedKey, normaliseRichTextFeatures } from "@bettercms-ai/types";
|
|
7
8
|
//#region src/adapters/schema.ts
|
|
8
9
|
var isObj = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
9
10
|
function deepEqual(a, b) {
|
|
@@ -182,24 +183,8 @@ var CATEGORY_TO_PROD = {
|
|
|
182
183
|
Content: "content",
|
|
183
184
|
Layout: "section"
|
|
184
185
|
};
|
|
185
|
-
/** The field types a kind:'block' model
|
|
186
|
-
var BLOCK_FIELD_TYPES =
|
|
187
|
-
"text",
|
|
188
|
-
"longtext",
|
|
189
|
-
"richtext",
|
|
190
|
-
"image",
|
|
191
|
-
"link",
|
|
192
|
-
"slug",
|
|
193
|
-
"email",
|
|
194
|
-
"phone",
|
|
195
|
-
"color",
|
|
196
|
-
"select",
|
|
197
|
-
"number",
|
|
198
|
-
"rating",
|
|
199
|
-
"date",
|
|
200
|
-
"datetime",
|
|
201
|
-
"boolean"
|
|
202
|
-
]);
|
|
186
|
+
/** The field types a kind:'block' model holds today: the ones a block primitive renders (types, staged to G7). */
|
|
187
|
+
var BLOCK_FIELD_TYPES = new Set(BLOCK_FIELD_TYPES_RENDERABLE_NOW);
|
|
203
188
|
/** A slot prop's config.minItems / maxItems cap (SLOT_ITEMS_CAP, componentPropDefSchema). */
|
|
204
189
|
var SLOT_ITEMS_CAP = 50;
|
|
205
190
|
/** A table prop's rows and an array prop's items: their config.minItems / maxItems cap (LIST_ITEMS_CAP). */
|
|
@@ -358,23 +343,24 @@ function shapeOf(f, lv, ctx, top, nest) {
|
|
|
358
343
|
};
|
|
359
344
|
return shape;
|
|
360
345
|
}
|
|
361
|
-
/**
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
]);
|
|
367
|
-
/** The key a model field is stored under: a reserved or malformed V2 name, renamed. */
|
|
346
|
+
/**
|
|
347
|
+
* The key a model field is stored under: a V2 name the API refuses (types' isReservedKey, the API lane: `derived`,
|
|
348
|
+
* `layout`, `page`, a forbidden key or a leading `_`; or one off KEY_FORMAT), renamed. V2 authoring follows the API
|
|
349
|
+
* lane, so `id` is a field key like any other (only the derive lane, which mints keys, reserves it).
|
|
350
|
+
*/
|
|
368
351
|
function modelKeyOf(name) {
|
|
352
|
+
if (KEY_FORMAT.test(name) && !isReservedKey(name)) return name;
|
|
369
353
|
let k = name.replace(/^_+/, "").replace(/[^A-Za-z0-9_-]/g, "");
|
|
370
354
|
if (!/^[A-Za-z]/.test(k)) k = `f${k}`;
|
|
371
|
-
return
|
|
355
|
+
return isReservedKey(k) ? `${k}Field` : k;
|
|
372
356
|
}
|
|
357
|
+
/** The config keys a model's primitive list holds (types' PRIMITIVE_ARRAY_RULE). */
|
|
358
|
+
var MODEL_LIST_KEYS = new Set(PRIMITIVE_ARRAY_RULE.configKeys);
|
|
373
359
|
/** A slot's V2 allow list as the backend keeps it: 1–50 distinct block names of 1–64 characters (slotAllowIssues). */
|
|
374
360
|
var slotAllowOk = (allow) => Array.isArray(allow) && allow.length >= 1 && allow.length <= SLOT_ALLOW_MAX && new Set(allow).size === allow.length && allow.every((n) => typeof n === "string" && n === n.trim() && n.length >= 1 && n.length <= SLOT_ALLOW_NAME_MAX);
|
|
375
361
|
function shapeOfField(f, lv, ctx, top) {
|
|
376
362
|
const props = ctx.lane === "props";
|
|
377
|
-
const deep = lv >=
|
|
363
|
+
const deep = lv >= MAX_FIELD_DEPTH;
|
|
378
364
|
const of = Array.isArray(f.of) ? f.of : void 0;
|
|
379
365
|
/** a prop reference names a content model or a page / form / collection target (refTargetNamed): with none it is stored as json */
|
|
380
366
|
const noEntry = (r) => props && !(r?.to ?? []).some((t) => ENTRY_TARGET(t) || REF_TARGET_KINDS.includes(t));
|
|
@@ -498,6 +484,36 @@ var trunc = (ctx, at, s, max, feature) => {
|
|
|
498
484
|
lose(ctx, at, feature);
|
|
499
485
|
return s.slice(0, max);
|
|
500
486
|
};
|
|
487
|
+
/** The prod field types that store a rich text and its features (config.features). */
|
|
488
|
+
var RICH_TYPES = /* @__PURE__ */ new Set(["richtext", "document"]);
|
|
489
|
+
/** Every feature, canonical: RICHTEXT_FEATURES through normaliseRichTextFeatures, so no alias is ever in it. */
|
|
490
|
+
var ALL_RICH_FEATURES = normaliseRichTextFeatures(RICHTEXT_FEATURES).features;
|
|
491
|
+
/**
|
|
492
|
+
* A rich text's features through types normaliseRichTextFeatures (its aliases expand there: `headings` is h1–h6), distinct,
|
|
493
|
+
* in the order given. `named`: something was not carried (a name outside RICHTEXT_FEATURES, a repeat, a non-list).
|
|
494
|
+
*/
|
|
495
|
+
/** A content model's id, as the backend's config.references rule reads one. */
|
|
496
|
+
var MODEL_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
497
|
+
/** A rich text's references: posts and authors, each a model id; `named` when anything else was there. */
|
|
498
|
+
function richRefs(v) {
|
|
499
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return { named: true };
|
|
500
|
+
const r = v;
|
|
501
|
+
const kept = {};
|
|
502
|
+
for (const k of ["posts", "authors"]) if (typeof r[k] === "string" && MODEL_ID.test(r[k])) kept[k] = r[k];
|
|
503
|
+
const named = Object.keys(r).some((k) => k !== "posts" && k !== "authors" || r[k] !== void 0 && kept[k] === void 0);
|
|
504
|
+
return {
|
|
505
|
+
kept: Object.keys(kept).length ? kept : void 0,
|
|
506
|
+
named
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
function richFeatures(v) {
|
|
510
|
+
const names = Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
511
|
+
const { features, unknown } = normaliseRichTextFeatures(names);
|
|
512
|
+
return {
|
|
513
|
+
kept: [...new Set(features)],
|
|
514
|
+
named: !Array.isArray(v) || names.length !== v.length || new Set(names).size !== names.length || unknown.length > 0
|
|
515
|
+
};
|
|
516
|
+
}
|
|
501
517
|
function convertField(f, at, lv, ctx, siblings, top, inTable = false, inItem = false, inSetting = false) {
|
|
502
518
|
const props = ctx.lane === "props";
|
|
503
519
|
const shape = shapeOf(f, lv, ctx, top, inTable ? "rows" : inItem ? "item" : inSetting ? "setting" : void 0);
|
|
@@ -554,15 +570,15 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false, inItem = f
|
|
|
554
570
|
case "title":
|
|
555
571
|
case "type": break;
|
|
556
572
|
case "description":
|
|
557
|
-
node.helpText = trunc(ctx, p, f.description, props ?
|
|
573
|
+
node.helpText = trunc(ctx, p, f.description, props ? PROP_HELP_MAX : FIELD_HELP_MAX, "help>limit");
|
|
558
574
|
break;
|
|
559
575
|
case "helpMore":
|
|
560
576
|
node.helpMore = trunc(ctx, p, f.helpMore, HELP_MORE_MAX, "help>limit");
|
|
561
577
|
break;
|
|
562
578
|
case "placeholder":
|
|
563
|
-
if (props) node.placeholder = trunc(ctx, p, f.placeholder,
|
|
579
|
+
if (props) node.placeholder = trunc(ctx, p, f.placeholder, PROP_PLACEHOLDER_MAX, "help>limit");
|
|
564
580
|
else if (looseConfig) node.placeholder = f.placeholder;
|
|
565
|
-
else node.ui.placeholder = trunc(ctx, p, f.placeholder,
|
|
581
|
+
else node.ui.placeholder = trunc(ctx, p, f.placeholder, UI_PLACEHOLDER_MAX, "help>limit");
|
|
566
582
|
break;
|
|
567
583
|
case "initialValue":
|
|
568
584
|
if (props && (shape.type === "reference" || shape.type === "multi-reference" || shape.kind === "slot")) cat(ctx, p, "seeded instance");
|
|
@@ -703,10 +719,27 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false, inItem = f
|
|
|
703
719
|
if (shape.kind === "leaf" && shape.type === "table") Object.assign(node.config, tableConfigFromOptions(f.table));
|
|
704
720
|
else lose(ctx, p, "type:table");
|
|
705
721
|
break;
|
|
722
|
+
case "references":
|
|
723
|
+
if (!RICH_TYPES.has(shape.type)) lose(ctx, p, "unsupported key");
|
|
724
|
+
else {
|
|
725
|
+
const { kept, named } = richRefs(f.references);
|
|
726
|
+
if (named) lose(ctx, p, "richtext references");
|
|
727
|
+
if (kept) node.config.references = kept;
|
|
728
|
+
}
|
|
729
|
+
break;
|
|
730
|
+
case "features":
|
|
731
|
+
if (!RICH_TYPES.has(shape.type)) lose(ctx, p, "unsupported key");
|
|
732
|
+
else {
|
|
733
|
+
const { kept, named } = richFeatures(f.features);
|
|
734
|
+
if (named) lose(ctx, p, "richtext features");
|
|
735
|
+
node.config.features = kept;
|
|
736
|
+
}
|
|
737
|
+
break;
|
|
706
738
|
default: lose(ctx, p, "unsupported key");
|
|
707
739
|
}
|
|
708
740
|
}
|
|
709
741
|
if (props && f.description === void 0) node.helpText = null;
|
|
742
|
+
if (RICH_TYPES.has(shape.type) && shape.kind === "leaf" && f.features === void 0) node.config.features = [...ALL_RICH_FEATURES];
|
|
710
743
|
if (f.itemNoun === void 0 && shape.kind === "zones" && node.ui.itemLabel !== void 0) cat(ctx, `${at}/itemNoun`, "itemNoun (derived)");
|
|
711
744
|
placeInSet(f, node, at, ctx, top, siblings);
|
|
712
745
|
if (f.type === "rating" && node.type === "rating" && f.numeric?.step === void 0) {
|
|
@@ -787,7 +820,7 @@ function propGroupOf(s, ctx) {
|
|
|
787
820
|
if (ctx.groupOrder) g.order = Math.min(99, ctx.propOrder.get(s.name) ?? 0);
|
|
788
821
|
return g;
|
|
789
822
|
}
|
|
790
|
-
var groupDescriptionOk = (d) => typeof d === "string" && d === d.trim() && d.length >= 1 && d.length <=
|
|
823
|
+
var groupDescriptionOk = (d) => typeof d === "string" && d === d.trim() && d.length >= 1 && d.length <= PROP_GROUP_DESCRIPTION_MAX;
|
|
791
824
|
/** The zone a datetime field fixes, if any (what lets a stored instant read back with its [Zone]). */
|
|
792
825
|
var fixedZone = (f) => typeof f.timezone === "string" && f.timezone.startsWith("fixed:") ? f.timezone.slice(6) : void 0;
|
|
793
826
|
/**
|
|
@@ -1226,7 +1259,7 @@ function optionsToProd(f, shape, node, at, ctx) {
|
|
|
1226
1259
|
}
|
|
1227
1260
|
const d = o.description;
|
|
1228
1261
|
if (d !== void 0) {
|
|
1229
|
-
if (typeof d === "string" && d.trim() !== "" && !/[\r\n]/.test(d) && d.length <=
|
|
1262
|
+
if (typeof d === "string" && d.trim() !== "" && !/[\r\n]/.test(d) && d.length <= OPTION_DESCRIPTION_MAX) out.description = d;
|
|
1230
1263
|
else lose(ctx, `${at}/${i}/description`, "option description");
|
|
1231
1264
|
}
|
|
1232
1265
|
for (const k of Object.keys(o)) if (![
|
|
@@ -1435,7 +1468,7 @@ function ofToProd(f, shape, node, at, lv, ctx) {
|
|
|
1435
1468
|
if (shape.kind === "itemType") node.config.itemType = shape.itemType;
|
|
1436
1469
|
itemIdentity(item, conventionItem(f.name, f.title), node, ip, ctx);
|
|
1437
1470
|
const settings = {};
|
|
1438
|
-
const scalars = shape.kind === "itemType" && !shape.shopify && ctx.lane === "props";
|
|
1471
|
+
const scalars = shape.kind === "itemType" && !shape.shopify && (ctx.lane === "props" || MODEL_LIST_KEYS.has("item"));
|
|
1439
1472
|
for (const k of Object.keys(item)) {
|
|
1440
1473
|
const v = item[k];
|
|
1441
1474
|
if (v === void 0) continue;
|
|
@@ -1446,7 +1479,7 @@ function ofToProd(f, shape, node, at, lv, ctx) {
|
|
|
1446
1479
|
if (shape.kind === "itemType" && item.type === "text") lose(ctx, p, "item settings");
|
|
1447
1480
|
} else if (k === "reference" && shape.kind === "refs") referenceToConfig(item.reference, node, p, ctx);
|
|
1448
1481
|
else if (k === "reference" && shape.kind === "itemType" && shape.shopify) continue;
|
|
1449
|
-
else if (scalars && k === "description" && typeof v === "string" && v.trim() === v && v.length >= 1 && v.length <=
|
|
1482
|
+
else if (scalars && k === "description" && typeof v === "string" && v.trim() === v && v.length >= 1 && v.length <= PROP_HELP_MAX) settings.helpText = v;
|
|
1450
1483
|
else if (scalars && k === "localized" && typeof v === "boolean") settings.localized = v;
|
|
1451
1484
|
else if (scalars && k === "validation") itemValidationToProd(item, shape.itemType, settings, p, ctx);
|
|
1452
1485
|
else lose(ctx, p, "item settings");
|
|
@@ -2021,7 +2054,7 @@ function fieldsetsFor(v2, ctx, out) {
|
|
|
2021
2054
|
lose(ctx, p, why);
|
|
2022
2055
|
};
|
|
2023
2056
|
if (ctx.tabs.has(g.name) || names.has(folded)) return drop("group name collision");
|
|
2024
|
-
if (out.length >=
|
|
2057
|
+
if (out.length >= TAB_MAX$1) return drop("groups>3");
|
|
2025
2058
|
names.add(folded);
|
|
2026
2059
|
const tab = {
|
|
2027
2060
|
id: g.name,
|
|
@@ -2066,7 +2099,7 @@ function fieldsetsFor(v2, ctx, out) {
|
|
|
2066
2099
|
const v = fs[k];
|
|
2067
2100
|
if (v === void 0 || k === "name" || k === "title") continue;
|
|
2068
2101
|
if (k === "description") {
|
|
2069
|
-
if (v.length <=
|
|
2102
|
+
if (v.length <= FIELDSET_DESCRIPTION_MAX) set.description = v;
|
|
2070
2103
|
else lose(ctx, `${p}/${k}`, "help>limit");
|
|
2071
2104
|
} else if (k === "collapsed" || k === "collapsible" || k === "columns" || k === "layout") set[k] = v;
|
|
2072
2105
|
else lose(ctx, `${p}/${k}`, "unsupported key");
|
|
@@ -2095,7 +2128,7 @@ function propTabsFor(v2, ctx) {
|
|
|
2095
2128
|
const label = g.title.slice(0, 40).trim();
|
|
2096
2129
|
const folded = label.toLowerCase();
|
|
2097
2130
|
if (kept.some((k) => k.g.name === g.name) || labels.has(folded)) return drop("group name collision");
|
|
2098
|
-
if (kept.length >=
|
|
2131
|
+
if (kept.length >= PROP_TAB_MAX || g.name.length < 1 || g.name.length > 40) return drop("prop tab limit");
|
|
2099
2132
|
if (!label) return drop("group title");
|
|
2100
2133
|
labels.add(folded);
|
|
2101
2134
|
const tab = {
|
|
@@ -2198,7 +2231,7 @@ function propSetsFor(v2, ctx) {
|
|
|
2198
2231
|
firstSeen.push(f.fieldset);
|
|
2199
2232
|
if (!named.has(f.fieldset)) undeclared.push(f.fieldset);
|
|
2200
2233
|
}
|
|
2201
|
-
if (lv >=
|
|
2234
|
+
if (lv >= MAX_FIELD_DEPTH) continue;
|
|
2202
2235
|
const kids = previewKids(f);
|
|
2203
2236
|
if (kids) visit(kids, lv + 1);
|
|
2204
2237
|
}
|
|
@@ -2562,6 +2595,18 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
2562
2595
|
const useUi = (...k) => k.forEach((x) => usedUi.add(x));
|
|
2563
2596
|
if (lane === "props") useUi("group");
|
|
2564
2597
|
if (lane === "props") useUi("tab");
|
|
2598
|
+
if (RICH_TYPES.has(n.type) && cfg.references !== void 0) {
|
|
2599
|
+
use("references");
|
|
2600
|
+
const { kept, named } = richRefs(cfg.references);
|
|
2601
|
+
if (named) loss("config/references", "richtext references", FEATURES["richtext references"].reason);
|
|
2602
|
+
if (kept) f.references = kept;
|
|
2603
|
+
}
|
|
2604
|
+
if (RICH_TYPES.has(n.type) && cfg.features !== void 0) {
|
|
2605
|
+
use("features");
|
|
2606
|
+
const { kept, named } = richFeatures(cfg.features);
|
|
2607
|
+
if (named) loss("config/features", "richtext features", FEATURES["richtext features"].reason);
|
|
2608
|
+
if (kept.length < ALL_RICH_FEATURES.length) f.features = kept;
|
|
2609
|
+
}
|
|
2565
2610
|
if ([
|
|
2566
2611
|
"text",
|
|
2567
2612
|
"longtext",
|