@bettercms-ai/types 1.36.0 → 1.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +138 -5
- package/dist/index.js +63 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -129,6 +129,11 @@ interface FieldConfig {
|
|
|
129
129
|
max?: number;
|
|
130
130
|
/** date / datetime */
|
|
131
131
|
includeTime?: boolean;
|
|
132
|
+
/**
|
|
133
|
+
* date / datetime with a time: "site" (the project's own zone) or an IANA zone name. When set,
|
|
134
|
+
* a stored value must carry `Z` or a numeric offset, so it names one instant in every region.
|
|
135
|
+
*/
|
|
136
|
+
timezone?: string;
|
|
132
137
|
/** modular: SLUGS of the kind='block' models this field accepts. Non-empty. */
|
|
133
138
|
blockSlugs?: string[];
|
|
134
139
|
/** modular: bounds on how many block instances the field may hold. */
|
|
@@ -201,6 +206,20 @@ interface FieldConfig {
|
|
|
201
206
|
* field past that gate.
|
|
202
207
|
*/
|
|
203
208
|
type ContentModelFieldPlacement = "cover" | "title" | "excerpt" | "body" | "inline" | "panel";
|
|
209
|
+
/**
|
|
210
|
+
* Editor-only conditional visibility: the field (or component prop) shows only while the
|
|
211
|
+
* sibling keys its rules name hold these values. `isSet` reads no `value`: it passes once the
|
|
212
|
+
* source holds anything (`false` and `0` count; "", null and an empty list do not).
|
|
213
|
+
*/
|
|
214
|
+
interface ShowIfRule {
|
|
215
|
+
field: string;
|
|
216
|
+
op: "eq" | "neq" | "in" | "isSet";
|
|
217
|
+
value?: string | string[];
|
|
218
|
+
}
|
|
219
|
+
interface ShowIf {
|
|
220
|
+
match: "all" | "any";
|
|
221
|
+
rules: ShowIfRule[];
|
|
222
|
+
}
|
|
204
223
|
interface ContentModelField {
|
|
205
224
|
key: string;
|
|
206
225
|
label: string;
|
|
@@ -227,6 +246,18 @@ interface ContentModelField {
|
|
|
227
246
|
* Field ORDER is the array index — there is deliberately no `order` property.
|
|
228
247
|
*/
|
|
229
248
|
placement?: ContentModelFieldPlacement;
|
|
249
|
+
/** Editor-only conditional visibility; a hidden required field is not required. @see ShowIf */
|
|
250
|
+
showIf?: ShowIf;
|
|
251
|
+
/**
|
|
252
|
+
* A value another system owns (a store, job board or feed id).
|
|
253
|
+
* - `"developer"`: only a caller with schema authority (a key with `schema:manage`, a person
|
|
254
|
+
* with schema access) may change the value on an entry, or add or remove this lock. Anyone
|
|
255
|
+
* else is refused with 403 `FIELD_LOCKED`. Needs {@link lockReason}.
|
|
256
|
+
* - `true`: a marker the editor renders read-only. The API does not enforce it.
|
|
257
|
+
*/
|
|
258
|
+
readOnly?: true | "developer";
|
|
259
|
+
/** Which system owns the value; shown on the refusal. At most 200 characters. */
|
|
260
|
+
lockReason?: string;
|
|
230
261
|
/**
|
|
231
262
|
* Authoring chrome — how the field PRESENTS in the editor. Never delivered, never read by a
|
|
232
263
|
* renderer, and never able to move a value; the same contract as {@link placement}.
|
|
@@ -386,6 +417,14 @@ type ButtonSizeName = (typeof BUTTON_SIZES)[number];
|
|
|
386
417
|
* object. Only `label` and `href` are required; every look key is optional and absent reads as
|
|
387
418
|
* today's default (Primary, medium, no arrow, no icon, same tab).
|
|
388
419
|
*/
|
|
420
|
+
declare const LINK_RELS: readonly ["nofollow", "sponsored", "ugc"];
|
|
421
|
+
type LinkRel = (typeof LINK_RELS)[number];
|
|
422
|
+
/**
|
|
423
|
+
* The target and rel attributes of an anchor, as one string. A new tab keeps the `noopener
|
|
424
|
+
* noreferrer` pair; a link relation joins it in the SAME rel attribute, so an anchor never
|
|
425
|
+
* carries two.
|
|
426
|
+
*/
|
|
427
|
+
declare function anchorTargetRel(newTab: boolean, rel?: unknown): string;
|
|
389
428
|
interface ButtonValue {
|
|
390
429
|
label: string;
|
|
391
430
|
href: string;
|
|
@@ -394,14 +433,24 @@ interface ButtonValue {
|
|
|
394
433
|
arrow?: boolean;
|
|
395
434
|
icon?: ButtonIcon | null;
|
|
396
435
|
newTab?: boolean;
|
|
436
|
+
/** Sponsored, untrusted or user-generated destination. Absent ⇒ no rel beyond a new tab's own. */
|
|
437
|
+
rel?: LinkRel;
|
|
397
438
|
}
|
|
439
|
+
/** A stored button value as it renders: `rel` stays optional, every other key is filled. */
|
|
440
|
+
type ReadButtonValue = Required<Omit<ButtonValue, "rel">> & Pick<ButtonValue, "rel">;
|
|
398
441
|
/** A stored button value as it renders: every key read through the same allow-lists as a block. */
|
|
399
|
-
declare function readButtonValue(value: unknown):
|
|
442
|
+
declare function readButtonValue(value: unknown): ReadButtonValue;
|
|
400
443
|
/** Why a value is not a button, or null when it is. Look keys are checked only when present. */
|
|
401
444
|
declare function buttonValueProblem(value: unknown): string | null;
|
|
402
445
|
/** The look keys an instance of a Button component may override, beside its label and link. */
|
|
403
446
|
declare const BUTTON_LOOK_KEYS: readonly ["variant", "size", "arrow", "icon", "newTab"];
|
|
404
447
|
type ButtonLookKey = (typeof BUTTON_LOOK_KEYS)[number];
|
|
448
|
+
/**
|
|
449
|
+
* A `button` PROP's value as the `button` BLOCK props it writes, for every lane that applies an
|
|
450
|
+
* instance's overrides. `label` lands on `text`, and only the keys the value names come back, so
|
|
451
|
+
* an override carrying a label alone keeps the definition's href and look.
|
|
452
|
+
*/
|
|
453
|
+
declare function buttonBlockProps(value: unknown): Record<string, unknown>;
|
|
405
454
|
interface PropDefLike {
|
|
406
455
|
key: string;
|
|
407
456
|
label?: string;
|
|
@@ -430,7 +479,7 @@ declare function withButtonLookProps<P extends PropDefLike>(def: ComponentLike<P
|
|
|
430
479
|
* instance's overrides written onto it — for a site rendering the instance with `BcmsButton`.
|
|
431
480
|
* Null when the component is not a Button (not category `button`, or not exactly one button).
|
|
432
481
|
*/
|
|
433
|
-
declare function buttonValueOfInstance<P extends PropDefLike>(def: ComponentLike<P>, overrides: Record<string, unknown> | null | undefined):
|
|
482
|
+
declare function buttonValueOfInstance<P extends PropDefLike>(def: ComponentLike<P>, overrides: Record<string, unknown> | null | undefined): ReadButtonValue | null;
|
|
434
483
|
|
|
435
484
|
/**
|
|
436
485
|
* ContentBlock — a discriminated union of all CMS block types.
|
|
@@ -629,6 +678,8 @@ interface ButtonProps {
|
|
|
629
678
|
icon?: ButtonIcon | null;
|
|
630
679
|
/** Open the link in a new tab (`target="_blank" rel="noopener noreferrer"`). Absent ⇒ false. */
|
|
631
680
|
newTab?: boolean;
|
|
681
|
+
/** `nofollow`, `sponsored` or `ugc`; joins the anchor's rel. Absent ⇒ none. */
|
|
682
|
+
rel?: "nofollow" | "sponsored" | "ugc";
|
|
632
683
|
}
|
|
633
684
|
interface ButtonBlock {
|
|
634
685
|
type: "button";
|
|
@@ -832,6 +883,29 @@ interface CollectionProps {
|
|
|
832
883
|
/** "newest" (default) reverses the reader's created_at ordering. */
|
|
833
884
|
order?: "newest" | "oldest";
|
|
834
885
|
emptyText?: string;
|
|
886
|
+
/**
|
|
887
|
+
* List the published entries of ANOTHER model, on any page ("latest posts" on the home page).
|
|
888
|
+
* Absent: the entries of the page this block sits on, as above. A model of another project or
|
|
889
|
+
* workspace lists nothing. A sourced block is always a card list, on a detail URL too.
|
|
890
|
+
*/
|
|
891
|
+
source?: {
|
|
892
|
+
modelId: string;
|
|
893
|
+
};
|
|
894
|
+
/** Sourced lists only. The Delivery API's filter grammar; field keys are the model's own. */
|
|
895
|
+
filters?: CollectionFilter[];
|
|
896
|
+
/** Sourced lists only. The Delivery API's sort grammar (`-publishedAt,title`); wins over `order`. */
|
|
897
|
+
sort?: string;
|
|
898
|
+
/** Sourced lists only. Entry ids rendered first, in this order; counted against `limit`. */
|
|
899
|
+
pinnedIds?: string[];
|
|
900
|
+
/** Sourced lists only. On an entry's detail URL, leave that entry out ("related posts"). */
|
|
901
|
+
excludeCurrent?: boolean;
|
|
902
|
+
}
|
|
903
|
+
interface CollectionFilter {
|
|
904
|
+
/** A field key of the source model, or `slug`, `publishedAt`, `locale`. */
|
|
905
|
+
field: string;
|
|
906
|
+
op: "eq" | "ne" | "gt" | "gte" | "lt" | "lte" | "contains" | "in";
|
|
907
|
+
/** `in` takes a comma-separated list. */
|
|
908
|
+
value: string | number | boolean;
|
|
835
909
|
}
|
|
836
910
|
interface CollectionBlock {
|
|
837
911
|
type: "collection";
|
|
@@ -1101,6 +1175,41 @@ declare function splitButtonStyle(style: BlockStyle | undefined): {
|
|
|
1101
1175
|
placement: BlockStyle | undefined;
|
|
1102
1176
|
paint: Record<string, string | number> | undefined;
|
|
1103
1177
|
};
|
|
1178
|
+
/**
|
|
1179
|
+
* The style keys a PAGE FIELD takes (`pages.field_styles`, keyed by field path): its width and
|
|
1180
|
+
* placement, the space above and below it, and its text alignment, size and weight. A subset of
|
|
1181
|
+
* `BlockStyle`, so every key keeps the token set and the CSS table it already has — a field never
|
|
1182
|
+
* gets a second scale. 🔴 Twin: `FIELD_STYLE_KEYS` in the dashboard's fieldStyle.ts.
|
|
1183
|
+
*/
|
|
1184
|
+
declare const FIELD_STYLE_KEYS: readonly ["contentWidth", "contentAlign", "marginTop", "marginBottom", "align", "fontSize", "weight"];
|
|
1185
|
+
type FieldStyleKey = (typeof FIELD_STYLE_KEYS)[number];
|
|
1186
|
+
/** One field's style. */
|
|
1187
|
+
type FieldStyle = Pick<BlockStyle, FieldStyleKey>;
|
|
1188
|
+
/** A page's field styles, keyed by field path (the `data-bcms-field` address). */
|
|
1189
|
+
type FieldStyles = Record<string, FieldStyle>;
|
|
1190
|
+
/** Only the field keys of `style` (an empty object for none). */
|
|
1191
|
+
declare function pickFieldStyle(style: BlockStyle | Record<string, unknown> | null | undefined): FieldStyle;
|
|
1192
|
+
/**
|
|
1193
|
+
* A field's declarations, for its OWN element (`fieldAttrs`). Spacing, alignment, size and weight are
|
|
1194
|
+
* `blockStyleToCss`'s. The width is `blockStyleToInnerCss`'s column, drawn on the element itself —
|
|
1195
|
+
* a field has no wrapper to nest a column in — so its placement becomes left/right margins, and
|
|
1196
|
+
* the vertical margins the spacing set stay. `undefined` when nothing applies (no `style` at all).
|
|
1197
|
+
*/
|
|
1198
|
+
declare function fieldStyleToCss(style: BlockStyle | Record<string, unknown> | null | undefined): Record<string, string | number> | undefined;
|
|
1199
|
+
/**
|
|
1200
|
+
* The content column (`contentWidth` placed by `contentAlign`, falling back to `align`) as the
|
|
1201
|
+
* declarations for a box that IS the column — a site's own inner container (`sectionColumnAttrs`)
|
|
1202
|
+
* or a field's own element (`fieldStyleToCss`). Same max-width table as `blockStyleToInnerCss`;
|
|
1203
|
+
* the placement is left/right margins only, never the `margin` shorthand, so the box keeps its
|
|
1204
|
+
* own vertical margins. `undefined` when there is no column (unset, `full`, unknown).
|
|
1205
|
+
*/
|
|
1206
|
+
declare function blockStyleToColumnCss(style: BlockStyle | undefined): {
|
|
1207
|
+
maxWidth: string;
|
|
1208
|
+
marginLeft: string;
|
|
1209
|
+
marginRight: string;
|
|
1210
|
+
} | undefined;
|
|
1211
|
+
/** `fieldStyleToCss` as an inline `style` string (`paddingTop` → `padding-top`), "" when empty. */
|
|
1212
|
+
declare function fieldStyleCssText(style: BlockStyle | Record<string, unknown> | null | undefined): string;
|
|
1104
1213
|
|
|
1105
1214
|
/**
|
|
1106
1215
|
* Generated from lucide-react@1.8.0 dynamic icon names.
|
|
@@ -1520,7 +1629,7 @@ type ComponentCategory = "navbar" | "footer" | "button" | "section" | "slider" |
|
|
|
1520
1629
|
*
|
|
1521
1630
|
* Order is not semantic; append rather than re-sort, so a diff stays readable.
|
|
1522
1631
|
*/
|
|
1523
|
-
declare const COMPONENT_PROP_TYPES: readonly ["text", "richtext", "image", "url", "boolean", "number", "select", "group", "table", "slot", "form"];
|
|
1632
|
+
declare const COMPONENT_PROP_TYPES: readonly ["text", "richtext", "image", "url", "boolean", "number", "select", "group", "table", "slot", "form", "link", "button", "date", "color", "file", "icon", "multiselect"];
|
|
1524
1633
|
type ComponentPropType = (typeof COMPONENT_PROP_TYPES)[number];
|
|
1525
1634
|
/**
|
|
1526
1635
|
* The value a `form` prop STORES: just the id. The form itself is a Form document and stays the
|
|
@@ -1562,6 +1671,14 @@ interface ComponentPropDef {
|
|
|
1562
1671
|
* select → one string from `config.options`
|
|
1563
1672
|
* group → an object keyed by `config.fields`
|
|
1564
1673
|
* table → an array of such objects (slider.slides)
|
|
1674
|
+
* link → an href string (URL, internal path or #fragment)
|
|
1675
|
+
* button → ONE `ButtonValue` (button-look.ts): label, href and look as a unit, never a text prop plus
|
|
1676
|
+
* a url prop that drift apart. Targets the `props` of a `button` block.
|
|
1677
|
+
* date → `YYYY-MM-DD`
|
|
1678
|
+
* color → a hex colour (`#RGB`, `#RRGGBB`, `#RRGGBBAA`)
|
|
1679
|
+
* file → `{ url, name?, size? }`, or a bare URL string
|
|
1680
|
+
* icon → a BetterCMS icon name (`DOCK_ICON_NAMES`), or an uploaded icon as an image value
|
|
1681
|
+
* multiselect → a `string[]`, each one of `config.options`
|
|
1565
1682
|
*
|
|
1566
1683
|
* `reference` is absent on purpose: nothing resolves a content-entry id at component render
|
|
1567
1684
|
* time, so such a prop would save cleanly and render as nothing.
|
|
@@ -1584,12 +1701,23 @@ interface ComponentPropDef {
|
|
|
1584
1701
|
helpSource?: "auto" | "human" | "agent";
|
|
1585
1702
|
/** Ghost text inside a text-ish control. */
|
|
1586
1703
|
placeholder?: string;
|
|
1704
|
+
/**
|
|
1705
|
+
* Editor-only conditional visibility: show this prop's control only while sibling props (by
|
|
1706
|
+
* key) hold these values. The save schema refuses a key no prop of the component declares.
|
|
1707
|
+
*/
|
|
1708
|
+
showIf?: ShowIf;
|
|
1709
|
+
/**
|
|
1710
|
+
* The content-model field's `readOnly` / `lockReason` pair, as STORED MARKERS only: the
|
|
1711
|
+
* editor may render the prop read-only, and no write of a prop value is refused for them.
|
|
1712
|
+
*/
|
|
1713
|
+
readOnly?: true | "developer";
|
|
1714
|
+
lockReason?: string;
|
|
1587
1715
|
/** Per-type settings; the save schema enforces that each is present on the type needing it. */
|
|
1588
1716
|
config?: {
|
|
1589
1717
|
/** `slot` — a pick allowlist. */
|
|
1590
1718
|
componentIds?: string[];
|
|
1591
1719
|
/**
|
|
1592
|
-
* `select` — the choices. Required, and a default must be one of them. `{ label, value }`
|
|
1720
|
+
* `select` / `multiselect` — the choices. Required, and a default must be one of them. `{ label, value }`
|
|
1593
1721
|
* when the stored value is not what an author should read (a component id, for instance).
|
|
1594
1722
|
*/
|
|
1595
1723
|
options?: Array<string | {
|
|
@@ -2115,6 +2243,11 @@ interface DeliveryPage {
|
|
|
2115
2243
|
metaJson: PageMetaJson | null;
|
|
2116
2244
|
blocks: ContentBlock[];
|
|
2117
2245
|
layout?: DeliveredLayout | null;
|
|
2246
|
+
/**
|
|
2247
|
+
* C3 — the page's field styles, keyed by field path (`pages.published_field_styles`; the draft
|
|
2248
|
+
* copy on a preview read). Absent when the page styles no field. Feed to `fieldAttrs`.
|
|
2249
|
+
*/
|
|
2250
|
+
fieldStyles?: FieldStyles;
|
|
2118
2251
|
updatedAt: string | null;
|
|
2119
2252
|
publishedAt: string | null;
|
|
2120
2253
|
/** The page's language (`null`: the site's default) and, on a translation, the page it translates. */
|
|
@@ -2547,4 +2680,4 @@ declare function regionOf<E extends {
|
|
|
2547
2680
|
el: E;
|
|
2548
2681
|
}[], el: unknown): string | null;
|
|
2549
2682
|
|
|
2550
|
-
export { type AlignToken, type ApiError, type ApiKey, type ApiKeyPermission, type ApiKeyTokenType, type ArrayZoneConfig, type AssertEqual, type AuthResponse, type AuthSession, type AuthUser, BLOCK_BINDINGS, BUTTON_ICONS, BUTTON_ICON_NAMES, BUTTON_LOOK_KEYS, BUTTON_PLACEMENT_KEYS, BUTTON_SIZES, BUTTON_VARIANTS, type BetterCMSErrorCode, type BgToken, type BindingKind, type BlockBinding, type BlockHoverStyle, type BlockStyle, type BlockType, type ButtonBlock, type ButtonIcon, type ButtonLinkCandidate, type ButtonLookKey, type ButtonProps, type ButtonSizeName, type ButtonValue, type ButtonVariant, COMPONENT_PROP_TYPES, type CanonicalInputDefinition, type CollectionBlock, type 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, FOOTER_SECTION_ID, type FieldConfig, 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, 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 LocatorGrammar, MAIN_SELECTOR, type ManagementLayoutCommand, type MediaAsset, type MediaCaptionTrack, type MediaFieldValue, NAVIGATION_SECTION_ID, type NavLink, type NavbarBlock, type NavbarProps, PAGE_CONTENT_ANCHOR_ID, type Page, type PageLayoutOverrideDataDocument, type PageLayoutOverrideDocument, type PageLayoutOverrideState, type PageLayoutOverrideStructureDocument, type PageLayoutSectionOverride, type PageLayoutSectionStructureOverride, type PageMetaJson, type PageOnlyLayoutSection, type PageSectionPlacement, type PaginatedResult, type Perspective, type PortableTextDocument, type PortableTextNode, type PropGroup, type RadiusToken, type Redirect, type ReservedLayoutSection, type ResolvedLayoutNode, type RichTextBlock, type RichTextProps, SECTION_DOCTRINE, SECTION_SPACE_TOKENS, SPACE_BOTTOM_TOKENS, SPACE_STEP_TOKENS, type SectionBlock, type SectionProps, type SectionSpaceToken, type ShadowToken, type SignInInput, type SignUpInput, type SiteSeoDefaults, type SlideItem, type SliderBlock, type SliderProps, type SpaceStepToken, type SpaceToken, type SpacerBlock, type SpacerProps, type TabItem, type TabsBlock, type TabsProps, type TextBlock, type TextProps, type ThemeToken, type UiBefore, type UiOrigin, type VariantInputMapping, type VideoBlock, type VideoProps, type WeightToken, type Workspace, type ZoneField, blockStyleToCss, blockStyleToInnerCss, buttonIconOf, buttonIconSvg, buttonLinkPairs, buttonValueOfInstance, buttonValueProblem, buttonVariantOf, candidateRole, componentInstanceAddresses, componentPropTargetKey, derivedPairs, dockBudget, dockScreens, expandBlockBindings, formatPropsAttribute, getBlockType, headingPaintCss, isBlock, isChromeLandmark, keyWords, landmarkRegions, locatorFor, parsePropsAttribute, readButtonValue, readPath, regionOf, safeCssUrl, spaceTokenCss, splitButtonStyle, withButtonLookProps };
|
|
2683
|
+
export { type AlignToken, type ApiError, type ApiKey, type ApiKeyPermission, type ApiKeyTokenType, type ArrayZoneConfig, type AssertEqual, type AuthResponse, type AuthSession, type AuthUser, BLOCK_BINDINGS, BUTTON_ICONS, BUTTON_ICON_NAMES, BUTTON_LOOK_KEYS, BUTTON_PLACEMENT_KEYS, BUTTON_SIZES, BUTTON_VARIANTS, type BetterCMSErrorCode, type BgToken, type BindingKind, type BlockBinding, type BlockHoverStyle, type BlockStyle, type BlockType, type ButtonBlock, type ButtonIcon, type ButtonLinkCandidate, type ButtonLookKey, type ButtonProps, type ButtonSizeName, type ButtonValue, type ButtonVariant, COMPONENT_PROP_TYPES, type CanonicalInputDefinition, type CollectionBlock, type CollectionFilter, type CollectionProps, type ColorToken, type ColumnsBlock, type ColumnsProps, type Component, type ComponentBlock, type ComponentCategory, type ComponentFormPropRef, type ComponentPropDef, type ComponentPropType, type ComponentPropUi, type ComponentProps, type ComponentSubField, type ComponentVariantGroup, type Content, type ContentBlock, type ContentEntry, type ContentModel, type ContentModelField, type ContentModelFieldType, type ContentModelFieldUi, type ContentPageResult, type ContentResponse, type ContentWidthToken, type CornerToken, DIALOG_SELECTOR, DOCK_BUDGET, DOCK_ICON_NAMES, DOCK_ICON_NAME_SET, type DeepReadonly, type DeliveredLayout, type DeliveryComponent, type DeliveryEntry, type DeliveryEntrySeo, type DeliveryList, type DeliveryPage, type DerivedLocator, type DockBudget, type DockFieldLike, type DockFieldsetLike, type DockIconName, type DockInputRef, type DockLane, type DockNode, type DockPropGroupLike, type DockScreen, type ElementLike, type ExpandedBinding, FIELD_STYLE_KEYS, FOOTER_SECTION_ID, type FieldConfig, type FieldStyle, type FieldStyleKey, type FieldStyles, type Fieldset, type FieldsetKind, type FieldsetUiBefore, type FontSizeToken, type FooterBlock, type FooterColumn, type FooterProps, type Form, type FormBlock, type FormField, type FormProps, type FormSubmission, type HeadingBlock, type HeadingProps, type ImageBlock, type ImageProps, LANDMARK_SELECTOR, LAYOUT_SECTION_ICONS, LAYOUT_SECTION_ICON_SET, LINK_RELS, type LandmarkChainElement, type LandmarkElement, type LayoutComponentItem, type LayoutDataDocument, type LayoutFieldDefinition, type LayoutFieldItem, type LayoutFieldType, type LayoutScalarFieldType, type LayoutSection, type LayoutSectionIcon, type LayoutSectionItem, type LayoutStructureDocument, type LayoutZone, type LinkRel, type LocatorGrammar, MAIN_SELECTOR, type ManagementLayoutCommand, type MediaAsset, type MediaCaptionTrack, type MediaFieldValue, NAVIGATION_SECTION_ID, type NavLink, type NavbarBlock, type NavbarProps, PAGE_CONTENT_ANCHOR_ID, type Page, type PageLayoutOverrideDataDocument, type PageLayoutOverrideDocument, type PageLayoutOverrideState, type PageLayoutOverrideStructureDocument, type PageLayoutSectionOverride, type PageLayoutSectionStructureOverride, type PageMetaJson, type PageOnlyLayoutSection, type PageSectionPlacement, type PaginatedResult, type Perspective, type PortableTextDocument, type PortableTextNode, type PropGroup, type RadiusToken, type ReadButtonValue, type Redirect, type ReservedLayoutSection, type ResolvedLayoutNode, type RichTextBlock, type RichTextProps, SECTION_DOCTRINE, SECTION_SPACE_TOKENS, SPACE_BOTTOM_TOKENS, SPACE_STEP_TOKENS, type SectionBlock, type SectionProps, type SectionSpaceToken, type ShadowToken, type ShowIf, type ShowIfRule, type SignInInput, type SignUpInput, type SiteSeoDefaults, type SlideItem, type SliderBlock, type SliderProps, type SpaceStepToken, type SpaceToken, type SpacerBlock, type SpacerProps, type TabItem, type TabsBlock, type TabsProps, type TextBlock, type TextProps, type ThemeToken, type UiBefore, type UiOrigin, type VariantInputMapping, type VideoBlock, type VideoProps, type WeightToken, type Workspace, type ZoneField, anchorTargetRel, blockStyleToColumnCss, blockStyleToCss, blockStyleToInnerCss, buttonBlockProps, buttonIconOf, buttonIconSvg, buttonLinkPairs, buttonValueOfInstance, buttonValueProblem, buttonVariantOf, candidateRole, componentInstanceAddresses, componentPropTargetKey, derivedPairs, dockBudget, dockScreens, expandBlockBindings, fieldStyleCssText, fieldStyleToCss, formatPropsAttribute, getBlockType, headingPaintCss, isBlock, isChromeLandmark, keyWords, landmarkRegions, locatorFor, parsePropsAttribute, pickFieldStyle, readButtonValue, readPath, regionOf, safeCssUrl, spaceTokenCss, splitButtonStyle, withButtonLookProps };
|
package/dist/index.js
CHANGED
|
@@ -297,6 +297,30 @@ function splitButtonStyle(style) {
|
|
|
297
297
|
paint: Object.keys(paint).length ? paint : void 0
|
|
298
298
|
};
|
|
299
299
|
}
|
|
300
|
+
var FIELD_STYLE_KEYS = ["contentWidth", "contentAlign", "marginTop", "marginBottom", "align", "fontSize", "weight"];
|
|
301
|
+
var FIELD_KEY_SET = new Set(FIELD_STYLE_KEYS);
|
|
302
|
+
function pickFieldStyle(style) {
|
|
303
|
+
const out = {};
|
|
304
|
+
if (!style || typeof style !== "object") return out;
|
|
305
|
+
for (const [k, v] of Object.entries(style)) if (FIELD_KEY_SET.has(k) && v != null) out[k] = v;
|
|
306
|
+
return out;
|
|
307
|
+
}
|
|
308
|
+
function fieldStyleToCss(style) {
|
|
309
|
+
const picked = pickFieldStyle(style);
|
|
310
|
+
const css = { ...blockStyleToCss(picked) };
|
|
311
|
+
Object.assign(css, blockStyleToColumnCss(picked));
|
|
312
|
+
return Object.keys(css).length ? css : void 0;
|
|
313
|
+
}
|
|
314
|
+
function blockStyleToColumnCss(style) {
|
|
315
|
+
const column = blockStyleToInnerCss(style);
|
|
316
|
+
if (!column || !style) return void 0;
|
|
317
|
+
const placement = style.contentAlign ?? style.align;
|
|
318
|
+
return { maxWidth: column.maxWidth, marginLeft: placement === "left" ? "0" : "auto", marginRight: placement === "right" ? "0" : "auto" };
|
|
319
|
+
}
|
|
320
|
+
function fieldStyleCssText(style) {
|
|
321
|
+
const css = fieldStyleToCss(style);
|
|
322
|
+
return css ? Object.entries(css).map(([k, v]) => `${k.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)}:${v}`).join(";") : "";
|
|
323
|
+
}
|
|
300
324
|
|
|
301
325
|
// src/component.ts
|
|
302
326
|
var SECTION_DOCTRINE = "STRUCTURE (separate from schema): a page is composed of SECTIONS. NEVER build a page out of loose top-level heading/text/image/button/spacer blocks \u2014 they cannot be moved, duplicated or swapped as a unit, the visual editor cannot outline or name them, and every one of them becomes its own section in the editor. A hero of a headline, a lede and two CTAs is ONE section, not four. TWO SHAPES, and the choice is about REUSE. (1) A band that appears on more than one page, or that needs layout variants, is a COMPONENT with a `sectionType` \u2014 see create_component. Components sharing a `sectionType` are that section's VARIANTS (one Hero: 'Centered' for the home page and 'Two-column' for about, same prop keys so a swap keeps the content). This is also the only shape the editor's 'Add a section' picker can insert, and the only one that gets a family name and a variant switcher. (2) A genuinely one-off band on a single page is a `section` BLOCK whose `props.children` hold its blocks. THE TRADEOFF, stated in the present tense because it is real today: inside a component, ONLY the leaves a declared prop TARGETS are click-to-edit on the canvas \u2014 each declared prop's `target` is re-keyed to that PLACEMENT's own override address, so editing it changes this page and not the shared definition. A prop with no `target` still SHOWS as a dock control, but its override reaches no rendered slot, so editing it changes nothing on the page. Copy that no prop points at is worse still: no binding and no control, unreachable from click-to-edit AND from the dock, changeable only by editing the component definition, which rewrites every page that places it. A `section` block's children stay click-to-edit unconditionally. So when you choose a component, DECLARE A PROP \u2014 WITH A `target` \u2014 for every string, link and image a marketer will ever touch; a component with un-propped editable copy is the defect, not the component. In the dock an unset prop shows EMPTY and inherits the definition's default, so set props explicitly when you want the current copy visible there. An IMPORTED site's components are its own (read the repo); its nav, footer and modals are the Layout. On a blank site, do not hand-write a band's JSON: start from a built-in section blueprint (list_components returns locked `builtin:*` blueprints with no projectId \u2014 hero-centered, hero-split, feature-grid-three, cta-banner and nine more), each already rooted in a `section` block with its editable leaves declared as props. INLINE its blockJson as a `section` block for a one-off band; for a recurring band, materialize the blueprint with create_component so it becomes project-scoped before implementation validation, Output or publication. Direct `builtin:*` component references exist only for legacy delivery compatibility. Two consecutive call-to-action buttons are two sibling `button` blocks inside the same section \u2014 never a `columns` block, which is a `repeat(N,1fr)` grid and would stretch each CTA to half the container. Buttons are inline-level and flow side by side on their own.";
|
|
@@ -311,7 +335,16 @@ var COMPONENT_PROP_TYPES = [
|
|
|
311
335
|
"group",
|
|
312
336
|
"table",
|
|
313
337
|
"slot",
|
|
314
|
-
"form"
|
|
338
|
+
"form",
|
|
339
|
+
// The seven below each store what the same-named content-model FIELD stores (`icon` and
|
|
340
|
+
// `multiselect` have no field twin; see the value notes on ComponentPropDef.type).
|
|
341
|
+
"link",
|
|
342
|
+
"button",
|
|
343
|
+
"date",
|
|
344
|
+
"color",
|
|
345
|
+
"file",
|
|
346
|
+
"icon",
|
|
347
|
+
"multiselect"
|
|
315
348
|
];
|
|
316
349
|
|
|
317
350
|
// src/layout-lucide-icons.ts
|
|
@@ -2786,6 +2819,11 @@ function buttonIconSvg(name, cls) {
|
|
|
2786
2819
|
return iconSvg(name, cls);
|
|
2787
2820
|
}
|
|
2788
2821
|
var BUTTON_SIZES = ["sm", "md", "lg"];
|
|
2822
|
+
var LINK_RELS = ["nofollow", "sponsored", "ugc"];
|
|
2823
|
+
function anchorTargetRel(newTab, rel) {
|
|
2824
|
+
const tokens = [...newTab ? ["noopener", "noreferrer"] : [], ...LINK_RELS.includes(rel) ? [rel] : []];
|
|
2825
|
+
return `${newTab ? ' target="_blank"' : ""}${tokens.length ? ` rel="${tokens.join(" ")}"` : ""}`;
|
|
2826
|
+
}
|
|
2789
2827
|
var hrefOf = (href) => typeof href === "string" ? href : href && typeof href === "object" && typeof href.href === "string" ? href.href : null;
|
|
2790
2828
|
function readButtonValue(value) {
|
|
2791
2829
|
const v = value && typeof value === "object" ? value : {};
|
|
@@ -2796,7 +2834,8 @@ function readButtonValue(value) {
|
|
|
2796
2834
|
size: BUTTON_SIZES.includes(v.size) ? v.size : "md",
|
|
2797
2835
|
arrow: v.arrow === true,
|
|
2798
2836
|
icon: buttonIconOf(v.icon),
|
|
2799
|
-
newTab: v.newTab === true
|
|
2837
|
+
newTab: v.newTab === true,
|
|
2838
|
+
...LINK_RELS.includes(v.rel) ? { rel: v.rel } : {}
|
|
2800
2839
|
};
|
|
2801
2840
|
}
|
|
2802
2841
|
function buttonValueProblem(value) {
|
|
@@ -2808,10 +2847,21 @@ function buttonValueProblem(value) {
|
|
|
2808
2847
|
if (v.size !== void 0 && !BUTTON_SIZES.includes(v.size)) return `has an unknown size "${String(v.size)}"`;
|
|
2809
2848
|
if (v.arrow !== void 0 && typeof v.arrow !== "boolean") return "arrow must be true or false";
|
|
2810
2849
|
if (v.newTab !== void 0 && typeof v.newTab !== "boolean") return "newTab must be true or false";
|
|
2850
|
+
if (v.rel !== void 0 && !LINK_RELS.includes(v.rel)) return `has an unknown rel "${String(v.rel)}" (nofollow, sponsored or ugc)`;
|
|
2811
2851
|
if (v.icon !== void 0 && v.icon !== null && buttonIconOf(v.icon) === null) return `has an unknown icon "${String(v.icon)}"`;
|
|
2812
2852
|
return null;
|
|
2813
2853
|
}
|
|
2814
2854
|
var BUTTON_LOOK_KEYS = ["variant", "size", "arrow", "icon", "newTab"];
|
|
2855
|
+
function buttonBlockProps(value) {
|
|
2856
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
2857
|
+
const v = value;
|
|
2858
|
+
const out = {};
|
|
2859
|
+
if (typeof v.label === "string") out.text = v.label;
|
|
2860
|
+
const href = hrefOf(v.href);
|
|
2861
|
+
if (href !== null) out.href = href;
|
|
2862
|
+
for (const key of BUTTON_LOOK_KEYS) if (key in v) out[key] = v[key];
|
|
2863
|
+
return out;
|
|
2864
|
+
}
|
|
2815
2865
|
function soleButtonId(blockJson) {
|
|
2816
2866
|
const ids = [];
|
|
2817
2867
|
const walk = (list) => {
|
|
@@ -2854,8 +2904,9 @@ function buttonValueOfInstance(def, overrides) {
|
|
|
2854
2904
|
walk(def.blockJson);
|
|
2855
2905
|
const props = { ...found[0]?.props ?? {} };
|
|
2856
2906
|
for (const p of withButtonLookProps(def)) {
|
|
2857
|
-
if (p.target.blockId !== blockId || !
|
|
2858
|
-
|
|
2907
|
+
if (p.target.blockId !== blockId || !overrides || !(p.key in overrides)) continue;
|
|
2908
|
+
if (p.type === "button") Object.assign(props, buttonBlockProps(overrides[p.key]));
|
|
2909
|
+
else if (p.target.path.startsWith("props.")) props[p.target.path.slice("props.".length)] = overrides[p.key];
|
|
2859
2910
|
}
|
|
2860
2911
|
return readButtonValue({ ...props, label: props.text });
|
|
2861
2912
|
}
|
|
@@ -2933,10 +2984,12 @@ export {
|
|
|
2933
2984
|
DOCK_BUDGET,
|
|
2934
2985
|
DOCK_ICON_NAMES,
|
|
2935
2986
|
DOCK_ICON_NAME_SET,
|
|
2987
|
+
FIELD_STYLE_KEYS,
|
|
2936
2988
|
FOOTER_SECTION_ID,
|
|
2937
2989
|
LANDMARK_SELECTOR,
|
|
2938
2990
|
LAYOUT_SECTION_ICONS,
|
|
2939
2991
|
LAYOUT_SECTION_ICON_SET,
|
|
2992
|
+
LINK_RELS,
|
|
2940
2993
|
MAIN_SELECTOR,
|
|
2941
2994
|
NAVIGATION_SECTION_ID,
|
|
2942
2995
|
PAGE_CONTENT_ANCHOR_ID,
|
|
@@ -2944,8 +2997,11 @@ export {
|
|
|
2944
2997
|
SECTION_SPACE_TOKENS,
|
|
2945
2998
|
SPACE_BOTTOM_TOKENS,
|
|
2946
2999
|
SPACE_STEP_TOKENS,
|
|
3000
|
+
anchorTargetRel,
|
|
3001
|
+
blockStyleToColumnCss,
|
|
2947
3002
|
blockStyleToCss,
|
|
2948
3003
|
blockStyleToInnerCss,
|
|
3004
|
+
buttonBlockProps,
|
|
2949
3005
|
buttonIconOf,
|
|
2950
3006
|
buttonIconSvg,
|
|
2951
3007
|
buttonLinkPairs,
|
|
@@ -2959,6 +3015,8 @@ export {
|
|
|
2959
3015
|
dockBudget,
|
|
2960
3016
|
dockScreens,
|
|
2961
3017
|
expandBlockBindings,
|
|
3018
|
+
fieldStyleCssText,
|
|
3019
|
+
fieldStyleToCss,
|
|
2962
3020
|
formatPropsAttribute,
|
|
2963
3021
|
getBlockType,
|
|
2964
3022
|
headingPaintCss,
|
|
@@ -2968,6 +3026,7 @@ export {
|
|
|
2968
3026
|
landmarkRegions,
|
|
2969
3027
|
locatorFor,
|
|
2970
3028
|
parsePropsAttribute,
|
|
3029
|
+
pickFieldStyle,
|
|
2971
3030
|
readButtonValue,
|
|
2972
3031
|
readPath,
|
|
2973
3032
|
regionOf,
|