@yahoo/uds-create-config 3.1.0 → 3.2.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/configs/CanvasConfig.d.ts +66 -3
- package/dist/configs/react-native-system.d.ts +44 -2
- package/dist/configs/react-native-system.js +2 -0
- package/dist/configs/system.d.ts +44 -2
- package/dist/configs/system.js +2 -0
- package/dist/entities/system/Component.d.ts +40 -2
- package/dist/entities/system/Component.js +40 -2
- package/dist/framework/Config.d.ts +1 -1
- package/dist/framework/Config.js +1 -1
- package/dist/framework/schema-version.d.ts +1 -1
- package/dist/framework/schema-version.js +5 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/migrations/2.0.0/v1-artifact.d.ts +22 -1
- package/dist/migrations/20260914155048_component_create_blank_op.d.ts +13 -0
- package/dist/migrations/20260914155048_component_create_blank_op.js +8 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -382,7 +382,7 @@ declare const Node: EntityClass<z.ZodObject<{
|
|
|
382
382
|
}, z.core.$strip>>;
|
|
383
383
|
export: z.ZodOptional<z.ZodString>;
|
|
384
384
|
}, z.core.$strict>;
|
|
385
|
-
readonly description: "Create a component at a new qualified `path`. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
385
|
+
readonly description: "Create a component at a new qualified `path`. For a component with nothing in it yet, one to design on the canvas before it has props or variants, use `create-blank` with only a `path` instead of authoring a minimal body here. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
386
386
|
readonly example: ({
|
|
387
387
|
config
|
|
388
388
|
}: {
|
|
@@ -394,6 +394,27 @@ declare const Node: EntityClass<z.ZodObject<{
|
|
|
394
394
|
data: Record<string, unknown>;
|
|
395
395
|
};
|
|
396
396
|
};
|
|
397
|
+
readonly 'create-blank': {
|
|
398
|
+
readonly input: z.ZodObject<{
|
|
399
|
+
path: z.ZodType<string, string | undefined, z.core.$ZodTypeInternals<string, string | undefined>>;
|
|
400
|
+
}, z.core.$strip>;
|
|
401
|
+
readonly readOnly: false;
|
|
402
|
+
readonly label: "Create blank";
|
|
403
|
+
readonly description: "Create an empty component at a new qualified `path`, to design on the canvas first: one `div` root layer and the node that renders it, with no props, no variants, no slot, no styles and no preview content. This is exactly what Studio's \"+\" creates. Takes only `path`. Use it for \"a new component\", \"a blank component\" or \"start a component from nothing\"; `create` is for a component whose body is already known.";
|
|
404
|
+
readonly scope: "item";
|
|
405
|
+
readonly creates: true;
|
|
406
|
+
readonly title: (entity: string) => string;
|
|
407
|
+
readonly example: ({
|
|
408
|
+
config
|
|
409
|
+
}: {
|
|
410
|
+
config: Config;
|
|
411
|
+
kind: string;
|
|
412
|
+
path: string;
|
|
413
|
+
}) => {
|
|
414
|
+
path: string;
|
|
415
|
+
};
|
|
416
|
+
readonly handler: (input: Record<string, unknown>, config: Config) => Config;
|
|
417
|
+
};
|
|
397
418
|
readonly 'sub-create/anatomy': {
|
|
398
419
|
readonly description: "Add one anatomy node (`key` + `data`) to a component. In a batch, create child nodes before a parent whose `children` or `slots` names them; each referenced node must already exist when this operation runs.";
|
|
399
420
|
};
|
|
@@ -1248,7 +1269,7 @@ declare const CanvasConfig: ConfigClass<{
|
|
|
1248
1269
|
}, z.core.$strip>>;
|
|
1249
1270
|
export: z.ZodOptional<z.ZodString>;
|
|
1250
1271
|
}, z.core.$strict>;
|
|
1251
|
-
readonly description: "Create a component at a new qualified `path`. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
1272
|
+
readonly description: "Create a component at a new qualified `path`. For a component with nothing in it yet, one to design on the canvas before it has props or variants, use `create-blank` with only a `path` instead of authoring a minimal body here. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
1252
1273
|
readonly example: ({
|
|
1253
1274
|
config
|
|
1254
1275
|
}: {
|
|
@@ -1260,6 +1281,27 @@ declare const CanvasConfig: ConfigClass<{
|
|
|
1260
1281
|
data: Record<string, unknown>;
|
|
1261
1282
|
};
|
|
1262
1283
|
};
|
|
1284
|
+
readonly 'create-blank': {
|
|
1285
|
+
readonly input: z.ZodObject<{
|
|
1286
|
+
path: z.ZodType<string, string | undefined, z.core.$ZodTypeInternals<string, string | undefined>>;
|
|
1287
|
+
}, z.core.$strip>;
|
|
1288
|
+
readonly readOnly: false;
|
|
1289
|
+
readonly label: "Create blank";
|
|
1290
|
+
readonly description: "Create an empty component at a new qualified `path`, to design on the canvas first: one `div` root layer and the node that renders it, with no props, no variants, no slot, no styles and no preview content. This is exactly what Studio's \"+\" creates. Takes only `path`. Use it for \"a new component\", \"a blank component\" or \"start a component from nothing\"; `create` is for a component whose body is already known.";
|
|
1291
|
+
readonly scope: "item";
|
|
1292
|
+
readonly creates: true;
|
|
1293
|
+
readonly title: (entity: string) => string;
|
|
1294
|
+
readonly example: ({
|
|
1295
|
+
config
|
|
1296
|
+
}: {
|
|
1297
|
+
config: Config;
|
|
1298
|
+
kind: string;
|
|
1299
|
+
path: string;
|
|
1300
|
+
}) => {
|
|
1301
|
+
path: string;
|
|
1302
|
+
};
|
|
1303
|
+
readonly handler: (input: Record<string, unknown>, config: Config) => Config;
|
|
1304
|
+
};
|
|
1263
1305
|
readonly 'sub-create/anatomy': {
|
|
1264
1306
|
readonly description: "Add one anatomy node (`key` + `data`) to a component. In a batch, create child nodes before a parent whose `children` or `slots` names them; each referenced node must already exist when this operation runs.";
|
|
1265
1307
|
};
|
|
@@ -2379,7 +2421,7 @@ declare function createCanvasConfig(system: AnySystemConfig): ConfigInstance<{
|
|
|
2379
2421
|
}, z.core.$strip>>;
|
|
2380
2422
|
export: z.ZodOptional<z.ZodString>;
|
|
2381
2423
|
}, z.core.$strict>;
|
|
2382
|
-
readonly description: "Create a component at a new qualified `path`. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
2424
|
+
readonly description: "Create a component at a new qualified `path`. For a component with nothing in it yet, one to design on the canvas before it has props or variants, use `create-blank` with only a `path` instead of authoring a minimal body here. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
2383
2425
|
readonly example: ({
|
|
2384
2426
|
config
|
|
2385
2427
|
}: {
|
|
@@ -2391,6 +2433,27 @@ declare function createCanvasConfig(system: AnySystemConfig): ConfigInstance<{
|
|
|
2391
2433
|
data: Record<string, unknown>;
|
|
2392
2434
|
};
|
|
2393
2435
|
};
|
|
2436
|
+
readonly 'create-blank': {
|
|
2437
|
+
readonly input: z.ZodObject<{
|
|
2438
|
+
path: z.ZodType<string, string | undefined, z.core.$ZodTypeInternals<string, string | undefined>>;
|
|
2439
|
+
}, z.core.$strip>;
|
|
2440
|
+
readonly readOnly: false;
|
|
2441
|
+
readonly label: "Create blank";
|
|
2442
|
+
readonly description: "Create an empty component at a new qualified `path`, to design on the canvas first: one `div` root layer and the node that renders it, with no props, no variants, no slot, no styles and no preview content. This is exactly what Studio's \"+\" creates. Takes only `path`. Use it for \"a new component\", \"a blank component\" or \"start a component from nothing\"; `create` is for a component whose body is already known.";
|
|
2443
|
+
readonly scope: "item";
|
|
2444
|
+
readonly creates: true;
|
|
2445
|
+
readonly title: (entity: string) => string;
|
|
2446
|
+
readonly example: ({
|
|
2447
|
+
config
|
|
2448
|
+
}: {
|
|
2449
|
+
config: Config;
|
|
2450
|
+
kind: string;
|
|
2451
|
+
path: string;
|
|
2452
|
+
}) => {
|
|
2453
|
+
path: string;
|
|
2454
|
+
};
|
|
2455
|
+
readonly handler: (input: Record<string, unknown>, config: Config) => Config;
|
|
2456
|
+
};
|
|
2394
2457
|
readonly 'sub-create/anatomy': {
|
|
2395
2458
|
readonly description: "Add one anatomy node (`key` + `data`) to a component. In a batch, create child nodes before a parent whose `children` or `slots` names them; each referenced node must already exist when this operation runs.";
|
|
2396
2459
|
};
|
|
@@ -309,7 +309,7 @@ declare const ReactNativeSystem: ConfigClass<{
|
|
|
309
309
|
}, _$zod_v4_core0.$strip>>;
|
|
310
310
|
export: _$zod.ZodOptional<_$zod.ZodString>;
|
|
311
311
|
}, _$zod_v4_core0.$strict>;
|
|
312
|
-
readonly description: "Create a component at a new qualified `path`. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
312
|
+
readonly description: "Create a component at a new qualified `path`. For a component with nothing in it yet, one to design on the canvas before it has props or variants, use `create-blank` with only a `path` instead of authoring a minimal body here. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
313
313
|
readonly example: ({
|
|
314
314
|
config
|
|
315
315
|
}: {
|
|
@@ -321,6 +321,27 @@ declare const ReactNativeSystem: ConfigClass<{
|
|
|
321
321
|
data: Record<string, unknown>;
|
|
322
322
|
};
|
|
323
323
|
};
|
|
324
|
+
readonly 'create-blank': {
|
|
325
|
+
readonly input: _$zod.ZodObject<{
|
|
326
|
+
path: _$zod.ZodType<string, string | undefined, _$zod_v4_core0.$ZodTypeInternals<string, string | undefined>>;
|
|
327
|
+
}, _$zod_v4_core0.$strip>;
|
|
328
|
+
readonly readOnly: false;
|
|
329
|
+
readonly label: "Create blank";
|
|
330
|
+
readonly description: "Create an empty component at a new qualified `path`, to design on the canvas first: one `div` root layer and the node that renders it, with no props, no variants, no slot, no styles and no preview content. This is exactly what Studio's \"+\" creates. Takes only `path`. Use it for \"a new component\", \"a blank component\" or \"start a component from nothing\"; `create` is for a component whose body is already known.";
|
|
331
|
+
readonly scope: "item";
|
|
332
|
+
readonly creates: true;
|
|
333
|
+
readonly title: (entity: string) => string;
|
|
334
|
+
readonly example: ({
|
|
335
|
+
config
|
|
336
|
+
}: {
|
|
337
|
+
config: Config;
|
|
338
|
+
kind: string;
|
|
339
|
+
path: string;
|
|
340
|
+
}) => {
|
|
341
|
+
path: string;
|
|
342
|
+
};
|
|
343
|
+
readonly handler: (input: Record<string, unknown>, config: Config) => Config;
|
|
344
|
+
};
|
|
324
345
|
readonly 'sub-create/anatomy': {
|
|
325
346
|
readonly description: "Add one anatomy node (`key` + `data`) to a component. In a batch, create child nodes before a parent whose `children` or `slots` names them; each referenced node must already exist when this operation runs.";
|
|
326
347
|
};
|
|
@@ -1812,7 +1833,7 @@ declare const ReactNativeSystem: ConfigClass<{
|
|
|
1812
1833
|
}, _$zod_v4_core0.$strip>>;
|
|
1813
1834
|
export: _$zod.ZodOptional<_$zod.ZodString>;
|
|
1814
1835
|
}, _$zod_v4_core0.$strict>;
|
|
1815
|
-
readonly description: "Create a component at a new qualified `path`. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
1836
|
+
readonly description: "Create a component at a new qualified `path`. For a component with nothing in it yet, one to design on the canvas before it has props or variants, use `create-blank` with only a `path` instead of authoring a minimal body here. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
1816
1837
|
readonly example: ({
|
|
1817
1838
|
config
|
|
1818
1839
|
}: {
|
|
@@ -1824,6 +1845,27 @@ declare const ReactNativeSystem: ConfigClass<{
|
|
|
1824
1845
|
data: Record<string, unknown>;
|
|
1825
1846
|
};
|
|
1826
1847
|
};
|
|
1848
|
+
readonly 'create-blank': {
|
|
1849
|
+
readonly input: _$zod.ZodObject<{
|
|
1850
|
+
path: _$zod.ZodType<string, string | undefined, _$zod_v4_core0.$ZodTypeInternals<string, string | undefined>>;
|
|
1851
|
+
}, _$zod_v4_core0.$strip>;
|
|
1852
|
+
readonly readOnly: false;
|
|
1853
|
+
readonly label: "Create blank";
|
|
1854
|
+
readonly description: "Create an empty component at a new qualified `path`, to design on the canvas first: one `div` root layer and the node that renders it, with no props, no variants, no slot, no styles and no preview content. This is exactly what Studio's \"+\" creates. Takes only `path`. Use it for \"a new component\", \"a blank component\" or \"start a component from nothing\"; `create` is for a component whose body is already known.";
|
|
1855
|
+
readonly scope: "item";
|
|
1856
|
+
readonly creates: true;
|
|
1857
|
+
readonly title: (entity: string) => string;
|
|
1858
|
+
readonly example: ({
|
|
1859
|
+
config
|
|
1860
|
+
}: {
|
|
1861
|
+
config: Config;
|
|
1862
|
+
kind: string;
|
|
1863
|
+
path: string;
|
|
1864
|
+
}) => {
|
|
1865
|
+
path: string;
|
|
1866
|
+
};
|
|
1867
|
+
readonly handler: (input: Record<string, unknown>, config: Config) => Config;
|
|
1868
|
+
};
|
|
1827
1869
|
readonly 'sub-create/anatomy': {
|
|
1828
1870
|
readonly description: "Add one anatomy node (`key` + `data`) to a component. In a batch, create child nodes before a parent whose `children` or `slots` names them; each referenced node must already exist when this operation runs.";
|
|
1829
1871
|
};
|
|
@@ -17,6 +17,7 @@ import { settingsAsKindMigration } from "../migrations/20260908171448_settings_a
|
|
|
17
17
|
import { visibleStatePointerMigration } from "../migrations/20260908194245_visible_state_pointer.js";
|
|
18
18
|
import { iconKnockoutVariantsMigration } from "../migrations/20260909183001_icon_knockout_variants.js";
|
|
19
19
|
import { linkedSystemLinkOpsMigration } from "../migrations/20260910212453_linked_system_link_ops.js";
|
|
20
|
+
import { componentCreateBlankOpMigration } from "../migrations/20260914155048_component_create_blank_op.js";
|
|
20
21
|
import { NativeModifier } from "../entities/native/NativeModifier.js";
|
|
21
22
|
import { NativeSettings } from "../entities/native/NativeSettings.js";
|
|
22
23
|
import { NativeStyleProperty } from "../entities/native/NativeStyleProperty.js";
|
|
@@ -60,5 +61,6 @@ if (!registeredSchemaMigrations().has(20260908171448)) registerSchemaMigrations(
|
|
|
60
61
|
if (!registeredSchemaMigrations().has(20260908194245)) registerSchemaMigrations(visibleStatePointerMigration);
|
|
61
62
|
if (!registeredSchemaMigrations().has(20260909183001)) registerSchemaMigrations(iconKnockoutVariantsMigration);
|
|
62
63
|
if (!registeredSchemaMigrations().has(20260910212453)) registerSchemaMigrations(linkedSystemLinkOpsMigration);
|
|
64
|
+
if (!registeredSchemaMigrations().has(20260914155048)) registerSchemaMigrations(componentCreateBlankOpMigration);
|
|
63
65
|
//#endregion
|
|
64
66
|
export { ReactNativeSystem };
|
package/dist/configs/system.d.ts
CHANGED
|
@@ -298,7 +298,7 @@ declare const System: ConfigClass<{
|
|
|
298
298
|
}, _$zod_v4_core0.$strip>>;
|
|
299
299
|
export: _$zod.ZodOptional<_$zod.ZodString>;
|
|
300
300
|
}, _$zod_v4_core0.$strict>;
|
|
301
|
-
readonly description: "Create a component at a new qualified `path`. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
301
|
+
readonly description: "Create a component at a new qualified `path`. For a component with nothing in it yet, one to design on the canvas before it has props or variants, use `create-blank` with only a `path` instead of authoring a minimal body here. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
302
302
|
readonly example: ({
|
|
303
303
|
config
|
|
304
304
|
}: {
|
|
@@ -310,6 +310,27 @@ declare const System: ConfigClass<{
|
|
|
310
310
|
data: Record<string, unknown>;
|
|
311
311
|
};
|
|
312
312
|
};
|
|
313
|
+
readonly 'create-blank': {
|
|
314
|
+
readonly input: _$zod.ZodObject<{
|
|
315
|
+
path: _$zod.ZodType<string, string | undefined, _$zod_v4_core0.$ZodTypeInternals<string, string | undefined>>;
|
|
316
|
+
}, _$zod_v4_core0.$strip>;
|
|
317
|
+
readonly readOnly: false;
|
|
318
|
+
readonly label: "Create blank";
|
|
319
|
+
readonly description: "Create an empty component at a new qualified `path`, to design on the canvas first: one `div` root layer and the node that renders it, with no props, no variants, no slot, no styles and no preview content. This is exactly what Studio's \"+\" creates. Takes only `path`. Use it for \"a new component\", \"a blank component\" or \"start a component from nothing\"; `create` is for a component whose body is already known.";
|
|
320
|
+
readonly scope: "item";
|
|
321
|
+
readonly creates: true;
|
|
322
|
+
readonly title: (entity: string) => string;
|
|
323
|
+
readonly example: ({
|
|
324
|
+
config
|
|
325
|
+
}: {
|
|
326
|
+
config: Config;
|
|
327
|
+
kind: string;
|
|
328
|
+
path: string;
|
|
329
|
+
}) => {
|
|
330
|
+
path: string;
|
|
331
|
+
};
|
|
332
|
+
readonly handler: (input: Record<string, unknown>, config: Config) => Config;
|
|
333
|
+
};
|
|
313
334
|
readonly 'sub-create/anatomy': {
|
|
314
335
|
readonly description: "Add one anatomy node (`key` + `data`) to a component. In a batch, create child nodes before a parent whose `children` or `slots` names them; each referenced node must already exist when this operation runs.";
|
|
315
336
|
};
|
|
@@ -1685,7 +1706,7 @@ declare const System: ConfigClass<{
|
|
|
1685
1706
|
}, _$zod_v4_core0.$strip>>;
|
|
1686
1707
|
export: _$zod.ZodOptional<_$zod.ZodString>;
|
|
1687
1708
|
}, _$zod_v4_core0.$strict>;
|
|
1688
|
-
readonly description: "Create a component at a new qualified `path`. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
1709
|
+
readonly description: "Create a component at a new qualified `path`. For a component with nothing in it yet, one to design on the canvas before it has props or variants, use `create-blank` with only a `path` instead of authoring a minimal body here. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
1689
1710
|
readonly example: ({
|
|
1690
1711
|
config
|
|
1691
1712
|
}: {
|
|
@@ -1697,6 +1718,27 @@ declare const System: ConfigClass<{
|
|
|
1697
1718
|
data: Record<string, unknown>;
|
|
1698
1719
|
};
|
|
1699
1720
|
};
|
|
1721
|
+
readonly 'create-blank': {
|
|
1722
|
+
readonly input: _$zod.ZodObject<{
|
|
1723
|
+
path: _$zod.ZodType<string, string | undefined, _$zod_v4_core0.$ZodTypeInternals<string, string | undefined>>;
|
|
1724
|
+
}, _$zod_v4_core0.$strip>;
|
|
1725
|
+
readonly readOnly: false;
|
|
1726
|
+
readonly label: "Create blank";
|
|
1727
|
+
readonly description: "Create an empty component at a new qualified `path`, to design on the canvas first: one `div` root layer and the node that renders it, with no props, no variants, no slot, no styles and no preview content. This is exactly what Studio's \"+\" creates. Takes only `path`. Use it for \"a new component\", \"a blank component\" or \"start a component from nothing\"; `create` is for a component whose body is already known.";
|
|
1728
|
+
readonly scope: "item";
|
|
1729
|
+
readonly creates: true;
|
|
1730
|
+
readonly title: (entity: string) => string;
|
|
1731
|
+
readonly example: ({
|
|
1732
|
+
config
|
|
1733
|
+
}: {
|
|
1734
|
+
config: Config;
|
|
1735
|
+
kind: string;
|
|
1736
|
+
path: string;
|
|
1737
|
+
}) => {
|
|
1738
|
+
path: string;
|
|
1739
|
+
};
|
|
1740
|
+
readonly handler: (input: Record<string, unknown>, config: Config) => Config;
|
|
1741
|
+
};
|
|
1700
1742
|
readonly 'sub-create/anatomy': {
|
|
1701
1743
|
readonly description: "Add one anatomy node (`key` + `data`) to a component. In a batch, create child nodes before a parent whose `children` or `slots` names them; each referenced node must already exist when this operation runs.";
|
|
1702
1744
|
};
|
package/dist/configs/system.js
CHANGED
|
@@ -27,6 +27,7 @@ import { iconKnockoutVariantsMigration } from "../migrations/20260909183001_icon
|
|
|
27
27
|
import { linkedSystemLinkOpsMigration } from "../migrations/20260910212453_linked_system_link_ops.js";
|
|
28
28
|
import { previewConditionsMigration } from "../migrations/20260912161840_preview_conditions.js";
|
|
29
29
|
import { fontVariableMigration } from "../migrations/20260912164927_font_variable.js";
|
|
30
|
+
import { componentCreateBlankOpMigration } from "../migrations/20260914155048_component_create_blank_op.js";
|
|
30
31
|
//#region src/configs/system.ts
|
|
31
32
|
/**
|
|
32
33
|
* `System` — the design-system config TYPE. Declares the exact kinds a design system owns (tokens,
|
|
@@ -74,5 +75,6 @@ if (!registeredSchemaMigrations().has(20260909183001)) registerSchemaMigrations(
|
|
|
74
75
|
if (!registeredSchemaMigrations().has(20260910212453)) registerSchemaMigrations(linkedSystemLinkOpsMigration);
|
|
75
76
|
if (!registeredSchemaMigrations().has(20260912161840)) registerSchemaMigrations(previewConditionsMigration);
|
|
76
77
|
if (!registeredSchemaMigrations().has(20260912164927)) registerSchemaMigrations(fontVariableMigration);
|
|
78
|
+
if (!registeredSchemaMigrations().has(20260914155048)) registerSchemaMigrations(componentCreateBlankOpMigration);
|
|
77
79
|
//#endregion
|
|
78
80
|
export { System };
|
|
@@ -438,6 +438,17 @@ declare const componentFields: z.ZodObject<{
|
|
|
438
438
|
* a surface that needs a field the schema doesn't declare is a gap in the schema, not a cast.
|
|
439
439
|
*/
|
|
440
440
|
type ComponentBody = z.infer<typeof componentFields>;
|
|
441
|
+
/**
|
|
442
|
+
* The body a blank component is created with: one intrinsic `div` layer and the anatomy node that
|
|
443
|
+
* renders it, nothing else. Studio's "+" and the `create-blank` op both write exactly this.
|
|
444
|
+
*
|
|
445
|
+
* Both halves are needed. The kind requires a `root` layer, but layers alone project the component
|
|
446
|
+
* rendering itself, a painting with nothing to compose into; the node is what puts a real `div`
|
|
447
|
+
* carrying the editor's selection markers on the canvas. `div` is an intrinsic tag rather than a
|
|
448
|
+
* system component, so no system is without it. Anything more (a `children` slot, preview content, a
|
|
449
|
+
* style rule) makes the component authored rather than blank, and the editor's drop frame stands down.
|
|
450
|
+
*/
|
|
451
|
+
declare function blankComponentBody(): ComponentBody;
|
|
441
452
|
declare const ComponentEntity: EntityClass<z.ZodObject<{
|
|
442
453
|
layers: SubEntityClass<z.ZodUnion<readonly [z.ZodString, z.ZodLazy<z.ZodType<Ref, unknown, z.core.$ZodTypeInternals<Ref, unknown>>>, EntityClass<z.ZodObject<{
|
|
443
454
|
version: z.ZodOptional<z.ZodString>;
|
|
@@ -671,7 +682,7 @@ declare const ComponentEntity: EntityClass<z.ZodObject<{
|
|
|
671
682
|
}, z.core.$strip>>;
|
|
672
683
|
export: z.ZodOptional<z.ZodString>;
|
|
673
684
|
}, z.core.$strict>;
|
|
674
|
-
readonly description: "Create a component at a new qualified `path`. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
685
|
+
readonly description: "Create a component at a new qualified `path`. For a component with nothing in it yet, one to design on the canvas before it has props or variants, use `create-blank` with only a `path` instead of authoring a minimal body here. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.";
|
|
675
686
|
readonly example: ({
|
|
676
687
|
config
|
|
677
688
|
}: {
|
|
@@ -683,6 +694,33 @@ declare const ComponentEntity: EntityClass<z.ZodObject<{
|
|
|
683
694
|
data: Record<string, unknown>;
|
|
684
695
|
};
|
|
685
696
|
};
|
|
697
|
+
/**
|
|
698
|
+
* A component with nothing in it yet, as Studio's "+" makes one. Its own op because `create`
|
|
699
|
+
* teaches the full grammar, and a model asked for a blank component authors a `children` slot and
|
|
700
|
+
* preview content from it, at which point the component is no longer blank. Decomposes into the one
|
|
701
|
+
* `create` patch the rail writes, so the changes list and undo read both gestures alike.
|
|
702
|
+
*/
|
|
703
|
+
readonly 'create-blank': {
|
|
704
|
+
readonly input: z.ZodObject<{
|
|
705
|
+
path: z.ZodType<string, string | undefined, z.core.$ZodTypeInternals<string, string | undefined>>;
|
|
706
|
+
}, z.core.$strip>;
|
|
707
|
+
readonly readOnly: false;
|
|
708
|
+
readonly label: "Create blank";
|
|
709
|
+
readonly description: "Create an empty component at a new qualified `path`, to design on the canvas first: one `div` root layer and the node that renders it, with no props, no variants, no slot, no styles and no preview content. This is exactly what Studio's \"+\" creates. Takes only `path`. Use it for \"a new component\", \"a blank component\" or \"start a component from nothing\"; `create` is for a component whose body is already known.";
|
|
710
|
+
readonly scope: "item";
|
|
711
|
+
readonly creates: true;
|
|
712
|
+
readonly title: (entity: string) => string;
|
|
713
|
+
readonly example: ({
|
|
714
|
+
config
|
|
715
|
+
}: {
|
|
716
|
+
config: Config;
|
|
717
|
+
kind: string;
|
|
718
|
+
path: string;
|
|
719
|
+
}) => {
|
|
720
|
+
path: string;
|
|
721
|
+
};
|
|
722
|
+
readonly handler: (input: Record<string, unknown>, config: Config) => Config;
|
|
723
|
+
};
|
|
686
724
|
readonly 'sub-create/anatomy': {
|
|
687
725
|
readonly description: "Add one anatomy node (`key` + `data`) to a component. In a batch, create child nodes before a parent whose `children` or `slots` names them; each referenced node must already exist when this operation runs.";
|
|
688
726
|
};
|
|
@@ -1297,4 +1335,4 @@ declare const Component: Omit<typeof ComponentEntity, "ref"> & {
|
|
|
1297
1335
|
ref<const Path extends PathOf<"component">>(path: Path): ComponentReference<ComponentContractOf<Path>>;
|
|
1298
1336
|
};
|
|
1299
1337
|
//#endregion
|
|
1300
|
-
export { AuthoredPropBody, Component, ComponentBody, ComponentElementBody, ComponentPropBody, ComponentReference, ComponentStyleBody, ElementVisibility, ElementVisibilityInput, ExtendedComponentRef, ProjectedVisibility, VariantValueBody, VariantValues, canonicalWhen, forwardedNames, layerRef, ownValues, ownsItsValues, valueRef };
|
|
1338
|
+
export { AuthoredPropBody, Component, ComponentBody, ComponentElementBody, ComponentPropBody, ComponentReference, ComponentStyleBody, ElementVisibility, ElementVisibilityInput, ExtendedComponentRef, ProjectedVisibility, VariantValueBody, VariantValues, blankComponentBody, canonicalWhen, forwardedNames, layerRef, ownValues, ownsItsValues, valueRef };
|
|
@@ -1249,6 +1249,22 @@ const componentFields = z.strictObject({
|
|
|
1249
1249
|
}
|
|
1250
1250
|
});
|
|
1251
1251
|
/**
|
|
1252
|
+
* The body a blank component is created with: one intrinsic `div` layer and the anatomy node that
|
|
1253
|
+
* renders it, nothing else. Studio's "+" and the `create-blank` op both write exactly this.
|
|
1254
|
+
*
|
|
1255
|
+
* Both halves are needed. The kind requires a `root` layer, but layers alone project the component
|
|
1256
|
+
* rendering itself, a painting with nothing to compose into; the node is what puts a real `div`
|
|
1257
|
+
* carrying the editor's selection markers on the canvas. `div` is an intrinsic tag rather than a
|
|
1258
|
+
* system component, so no system is without it. Anything more (a `children` slot, preview content, a
|
|
1259
|
+
* style rule) makes the component authored rather than blank, and the editor's drop frame stands down.
|
|
1260
|
+
*/
|
|
1261
|
+
function blankComponentBody() {
|
|
1262
|
+
return {
|
|
1263
|
+
layers: { root: "div" },
|
|
1264
|
+
anatomy: { root: { element: { __ref: "layer:root" } } }
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1252
1268
|
* Where a component keeps its bags: each style rule's per-layer bag, each anatomy node's props, and
|
|
1253
1269
|
* the component's own defaults.
|
|
1254
1270
|
*
|
|
@@ -1314,7 +1330,7 @@ slots: ({ config, path, member }) => {
|
|
|
1314
1330
|
schemas: {
|
|
1315
1331
|
create: {
|
|
1316
1332
|
data: componentFields,
|
|
1317
|
-
description: "Create a component at a new qualified `path`. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.",
|
|
1333
|
+
description: "Create a component at a new qualified `path`. For a component with nothing in it yet, one to design on the canvas before it has props or variants, use `create-blank` with only a `path` instead of authoring a minimal body here. When its complete body is known, include all layers, anatomy, props, defaults, and styles in this one operation. `data.layers` maps each stable layer name to the element it renders and must include `root` — a tag for a primitive (`{ \"layers\": { \"root\": \"div\" } }`), and for anything built on top, a ref to a primitive (`{ \"root\": { \"__ref\": \"component:Box\" }, \"label\": { \"__ref\": \"component:Text\" } }`), which is what lets the layer take that primitive's style props. A primitive exposes style props as `{ \"type\": \"styleProperty\", \"value\": { \"__ref\": \"style-property:bg\" } }` and declares `children: { \"type\": \"slot\", \"text\": true }` when it holds content — without the slot, nothing nested inside it renders. A composed component exposes a layer's props at its own top level through `forwards`, keyed by layer: `{ \"forwards\": { \"root\": \"*\" } }` passes every prop the root's element takes (so `<Button width=\"full\">` reaches the root's `width`), and a list of member refs (`[{ \"__ref\": \"component:Box#props/width\" }]`, each naming the component that declares the prop) passes only those. A prop a layer already exposes is forwarded, never redeclared in `props`; a `props` entry of `{ \"type\": \"forward\" }` is the reverse route, one of this component's props into a layer's. `anatomy` is the tree the build would read off a render: each node renders a layer (`{ \"__ref\": \"layer:<name>\" }`), an intrinsic tag, or `Slot` (`{ \"element\": \"Slot\", \"props\": { \"name\": \"children\" } }`, where a slot prop's content lands — but a declared slot fills `root` by default, so a primitive still declares its `children` slot prop yet needs no `Slot` node or `children` entry for it, and a `Slot` node is only for landing that content in a nested layer); `children` lists sibling node keys from the `root` node, never a prop name; `text` is a fixed string; `visible` is a condition on a prop (`{ \"$state\": \"<prop>\" }`, or with `eq`); content shown in a nested layer is a route, `children: { \"type\": \"forward\", \"target\": \"label/children\" }`. `$state` appears only in `visible` and in an `element` a prop chooses, never as a prop value. A glyph is a node of its own, `{ \"element\": { \"__ref\": \"icon:<library>/<Name>\" } }`, listed in the `children` of the layer node that holds it, never a prop value. Text a prop supplies to a text layer is never a node either: declare the prop `{ \"type\": \"forward\", \"target\": \"<layer>/children\" }` and the layer shows it; a `Slot` node goes only under a layer that takes nodes. A style rule is `\"styles\": { \"*\": { \"when\": null, \"layers\": { \"root\": { \"bg\": \"surface\" } } } }`, keyed by a name, with each layer's bag under `layers`. A composed component carries its own styles: give it an unconditional (`\"*\"`) rule that lays out and surfaces it through the system's style properties — spacing, alignment and gap on the container, a background and color where it has one — rather than leaning on the bare primitives, which paint flat. Style a layer only with the style props the primitive it renders exposes, set to the values those props accept: `component/get` on the primitive lists both, so read it and choose from that rather than reaching for a CSS name or value the system has no style property for. Set `previewProps` (or `defaultProps`) so the component previews with content; a root that takes children renders empty otherwise. A style rule's layer bag is keyed by style-prop name (`fontWeight`, `color`), never by CSS property name, and each value is one of that prop's values.",
|
|
1318
1334
|
example: ({ config }) => {
|
|
1319
1335
|
const path = freeExamplePath(config);
|
|
1320
1336
|
const composed = composedCreateExample(config, path);
|
|
@@ -1355,6 +1371,28 @@ slots: ({ config, path, member }) => {
|
|
|
1355
1371
|
};
|
|
1356
1372
|
}
|
|
1357
1373
|
},
|
|
1374
|
+
/**
|
|
1375
|
+
* A component with nothing in it yet, as Studio's "+" makes one. Its own op because `create`
|
|
1376
|
+
* teaches the full grammar, and a model asked for a blank component authors a `children` slot and
|
|
1377
|
+
* preview content from it, at which point the component is no longer blank. Decomposes into the one
|
|
1378
|
+
* `create` patch the rail writes, so the changes list and undo read both gestures alike.
|
|
1379
|
+
*/
|
|
1380
|
+
"create-blank": {
|
|
1381
|
+
input: z.object({ path: pathInput("component") }),
|
|
1382
|
+
readOnly: false,
|
|
1383
|
+
label: "Create blank",
|
|
1384
|
+
description: "Create an empty component at a new qualified `path`, to design on the canvas first: one `div` root layer and the node that renders it, with no props, no variants, no slot, no styles and no preview content. This is exactly what Studio's \"+\" creates. Takes only `path`. Use it for \"a new component\", \"a blank component\" or \"start a component from nothing\"; `create` is for a component whose body is already known.",
|
|
1385
|
+
scope: "item",
|
|
1386
|
+
creates: true,
|
|
1387
|
+
title: (entity) => `Create blank ${entity}`,
|
|
1388
|
+
example: ({ config }) => ({ path: freeExamplePath(config) }),
|
|
1389
|
+
handler: (input, config) => config.apply({
|
|
1390
|
+
kind: "component",
|
|
1391
|
+
operation: "create",
|
|
1392
|
+
path: String(input.path),
|
|
1393
|
+
data: blankComponentBody()
|
|
1394
|
+
})
|
|
1395
|
+
},
|
|
1358
1396
|
"sub-create/anatomy": { description: "Add one anatomy node (`key` + `data`) to a component. In a batch, create child nodes before a parent whose `children` or `slots` names them; each referenced node must already exist when this operation runs." },
|
|
1359
1397
|
"sub-create/props": { description: "Declare a prop this component owns (`key` + `data`): a `variant`, a `slot`, a `styleProperty` or `composite` on a primitive, a `forward` routing this prop into a layer's (`{ \"type\": \"forward\", \"target\": \"<layer>/<prop>\" }`), or `null` to drop a forwarded prop from the surface. A prop one of its layers already exposes — `width` on a root that renders `Box` — is not declared here; `sub-create/forwards` exposes it at the top level." },
|
|
1360
1398
|
"sub-create/forwards": {
|
|
@@ -1843,4 +1881,4 @@ function exampleProps(config, componentPath) {
|
|
|
1843
1881
|
return {};
|
|
1844
1882
|
}
|
|
1845
1883
|
//#endregion
|
|
1846
|
-
export { Component, canonicalWhen, forwardedNames, layerRef, ownValues, ownsItsValues, valueRef };
|
|
1884
|
+
export { Component, blankComponentBody, canonicalWhen, forwardedNames, layerRef, ownValues, ownsItsValues, valueRef };
|
|
@@ -72,7 +72,7 @@ interface RecordedSource {
|
|
|
72
72
|
* The dense-counter `2` a short-lived scheme stamped before the chain existed reads as the mint
|
|
73
73
|
* that replaced it (see `detectedWireVersion`).
|
|
74
74
|
*/
|
|
75
|
-
declare const SERIALIZED_CONFIG_VERSION =
|
|
75
|
+
declare const SERIALIZED_CONFIG_VERSION = 20260914155048;
|
|
76
76
|
interface SerializedConfig {
|
|
77
77
|
/** See {@link SERIALIZED_CONFIG_VERSION}. Always written; a stored artifact may lack it. */
|
|
78
78
|
readonly version: number;
|
package/dist/framework/Config.js
CHANGED
|
@@ -4715,7 +4715,7 @@ var Config = class Config {
|
|
|
4715
4715
|
* links from the provided sources. A declared `linkedKind` with no provided source throws. */
|
|
4716
4716
|
hydrateFrom(stored, options) {
|
|
4717
4717
|
const claimed = schemaVersionOf(stored);
|
|
4718
|
-
if (claimed >
|
|
4718
|
+
if (claimed > 20260914155048) throw new SchemaVersionTooNew(claimed);
|
|
4719
4719
|
const wire = upgradeSerializedConfig(stored);
|
|
4720
4720
|
if (!Array.isArray(wire.ownedKinds) || typeof wire.items !== "object" || wire.items === null) throw new ConfigFormatError(`Config "${stored.name ?? "system-config"}" cannot be hydrated: this is not a serialized config-v2 config (no "ownedKinds"/"items"). A pre-cutover build artifact converts through the registered cutover migration — import the config type's module (e.g. \`configs/system\`) before hydrating, or port the repo once with \`uds migrate\`.`);
|
|
4721
4721
|
const leftover = wire.options;
|
|
@@ -15,7 +15,7 @@ import { Patch, SerializedConfig } from "./Config.js";
|
|
|
15
15
|
* sets this constant to its own older timestamp; the merge ref then carries a registered migration
|
|
16
16
|
* newer than the constant, and the assertion fails until the author re-mints.
|
|
17
17
|
*/
|
|
18
|
-
declare const CURRENT_SCHEMA_VERSION =
|
|
18
|
+
declare const CURRENT_SCHEMA_VERSION = 20260914155048;
|
|
19
19
|
/** What the walkers need to see of an envelope — loose on purpose, so a typed `SerializedConfig`
|
|
20
20
|
* and a raw old-shape record both flow in without casts. */
|
|
21
21
|
interface VersionStamped {
|