@yahoo/uds-create-config 4.6.0 → 4.8.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 +900 -80
- package/dist/configs/react-native-system.d.ts +603 -55
- package/dist/configs/system.d.ts +603 -55
- package/dist/configs/system.js +7 -1
- package/dist/entities/system/Component.d.ts +480 -39
- package/dist/entities/system/Component.js +264 -93
- package/dist/entities/system/File.d.ts +1 -1
- package/dist/entities/system/LinkedSystem.d.ts +2 -2
- package/dist/entities/system/Operation.d.ts +1 -1
- package/dist/entities/system/StyleProperty.d.ts +8 -0
- package/dist/entities/system/StyleProperty.js +12 -1
- package/dist/entities/system/Tool.d.ts +1 -1
- package/dist/entities/system/component-module.js +1 -1
- package/dist/entities/system/defineComponent.d.ts +45 -7
- package/dist/entities/system/defineComponent.js +52 -25
- package/dist/framework/Config.d.ts +2 -2
- package/dist/framework/Config.js +59 -7
- package/dist/framework/class-names.d.ts +4 -2
- package/dist/framework/class-names.js +56 -17
- package/dist/framework/defineDerivedEntity.d.ts +1 -1
- package/dist/framework/defineEntity.d.ts +2 -2
- package/dist/framework/defineSubEntity.d.ts +3 -2
- package/dist/framework/preview-store.d.ts +19 -0
- package/dist/framework/preview-store.js +18 -0
- package/dist/framework/projections.d.ts +28 -8
- package/dist/framework/projections.js +50 -16
- package/dist/framework/prop-surface.d.ts +21 -1
- package/dist/framework/prop-surface.js +99 -21
- package/dist/framework/render-spec.d.ts +103 -3
- package/dist/framework/render-spec.js +285 -37
- package/dist/framework/schema-version.d.ts +1 -1
- package/dist/framework/schema-version.js +5 -5
- package/dist/framework/utils/refs.js +10 -1
- package/dist/framework/validate-spec.d.ts +2 -0
- package/dist/framework/validate-spec.js +13 -0
- package/dist/index.d.ts +14 -11
- package/dist/index.js +6 -5
- package/dist/migrations/2.0.0/v1-artifact.d.ts +305 -29
- package/dist/migrations/20260919051027_prop_conditions_and_anatomy_positions_at_rest.d.ts +22 -0
- package/dist/migrations/20260919051027_prop_conditions_and_anatomy_positions_at_rest.js +10 -0
- package/dist/migrations/20260920004019_preview_conditions_keyed.d.ts +27 -0
- package/dist/migrations/20260920004019_preview_conditions_keyed.js +148 -0
- package/dist/migrations/20260920161309_prefixed_token_group.d.ts +12 -0
- package/dist/migrations/20260920161309_prefixed_token_group.js +10 -0
- package/dist/renderer/wrapRegistry.js +8 -2
- package/dist/renderer/wrappers/component-refs.d.ts +14 -0
- package/dist/renderer/wrappers/component-refs.js +79 -0
- package/dist/renderer/wrappers/hex-normalize.d.ts +5 -7
- package/dist/renderer/wrappers/hex-normalize.js +11 -10
- package/dist/spec/cell.d.ts +171 -0
- package/dist/spec/cell.js +361 -0
- package/dist/spec/detach.d.ts +125 -0
- package/dist/spec/detach.js +511 -0
- package/dist/spec/empty-node-slots.d.ts +11 -23
- package/dist/spec/empty-node-slots.js +12 -39
- package/dist/spec/index.d.ts +5 -3
- package/dist/spec/index.js +3 -3
- package/dist/spec/instance.d.ts +77 -0
- package/dist/spec/instance.js +80 -0
- package/dist/spec/preview-content.d.ts +95 -0
- package/dist/spec/preview-content.js +149 -0
- package/dist/spec/preview-elements.d.ts +54 -15
- package/dist/spec/preview-elements.js +109 -29
- package/dist/spec/prop-conditions.d.ts +28 -0
- package/dist/spec/prop-conditions.js +39 -0
- package/dist/spec/slot.d.ts +206 -0
- package/dist/spec/slot.js +542 -0
- package/dist/spec/visibility.d.ts +82 -0
- package/dist/spec/visibility.js +109 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -2
|
@@ -1,18 +1,46 @@
|
|
|
1
|
+
import { kindOf } from "../framework/utils/refs.js";
|
|
1
2
|
//#region src/spec/preview-elements.ts
|
|
3
|
+
/**
|
|
4
|
+
* A preview element is the JSON-safe form of JSX stored in a component's preview props.
|
|
5
|
+
*
|
|
6
|
+
* It is authoring data, not a React element and not yet a json-render node. The helpers in this file
|
|
7
|
+
* own the conversion into the UDS spec dialect so every render host receives the same shape.
|
|
8
|
+
*/
|
|
2
9
|
/** Whether a stored value names an element to render. */
|
|
3
10
|
function isPreviewElement(value) {
|
|
4
11
|
if (typeof value !== "object" || value === null) return false;
|
|
5
12
|
const { element } = value;
|
|
6
13
|
return typeof element === "string" || typeof element === "object" && element !== null && typeof element.__ref === "string";
|
|
7
14
|
}
|
|
15
|
+
/** Whether a stored value is a bare `{ __ref }` and nothing else, whatever kind it names. */
|
|
16
|
+
function isPreviewRef(value) {
|
|
17
|
+
if (typeof value !== "object" || value === null) return false;
|
|
18
|
+
const keys = Object.keys(value);
|
|
19
|
+
return keys.length === 1 && keys[0] === "__ref" && typeof value.__ref === "string";
|
|
20
|
+
}
|
|
21
|
+
/** The ref kinds a registry keys a renderer under. */
|
|
22
|
+
const RENDERABLE_KINDS = new Set([
|
|
23
|
+
"component",
|
|
24
|
+
"icon",
|
|
25
|
+
"package",
|
|
26
|
+
"file"
|
|
27
|
+
]);
|
|
28
|
+
/**
|
|
29
|
+
* Whether a stored value names a component to hand over. A `token:` or `value:` ref is data a prop
|
|
30
|
+
* carries and has the same bare shape, so the kind is what tells them apart.
|
|
31
|
+
*/
|
|
32
|
+
function isComponentRef(value) {
|
|
33
|
+
return isPreviewRef(value) && RENDERABLE_KINDS.has(kindOf(value.__ref));
|
|
34
|
+
}
|
|
8
35
|
/**
|
|
9
|
-
* Whether anything under a value is a stored preview element
|
|
10
|
-
* through their owner Fiber reaches a
|
|
36
|
+
* Whether anything under a value is a stored preview element or component ref, so a reviver knows
|
|
37
|
+
* the bag needs work. Stops at live React elements: walking through their owner Fiber reaches a
|
|
38
|
+
* circular structure.
|
|
11
39
|
*/
|
|
12
40
|
function hasPreviewElementDeep(value) {
|
|
13
41
|
if (typeof value !== "object" || value === null) return false;
|
|
14
42
|
if ("$$typeof" in value) return false;
|
|
15
|
-
if (isPreviewElement(value)) return true;
|
|
43
|
+
if (isPreviewElement(value) || isComponentRef(value)) return true;
|
|
16
44
|
return (Array.isArray(value) ? value : Object.values(value)).some(hasPreviewElementDeep);
|
|
17
45
|
}
|
|
18
46
|
/** The json-render `type` a stored element names. */
|
|
@@ -28,13 +56,19 @@ function previewElementNodes(root, rootKey, taken = /* @__PURE__ */ new Set()) {
|
|
|
28
56
|
while (used.has(key)) key = `${key}_`;
|
|
29
57
|
used.add(key);
|
|
30
58
|
const children = (node.children ?? []).map((child, index) => add(child, `${key}_${index}`));
|
|
59
|
+
const props = {};
|
|
60
|
+
const slots = {};
|
|
61
|
+
for (const [prop, value] of Object.entries(node.props ?? {})) if (isPreviewElement(value)) slots[prop] = [add(value, `${key}_${prop}`)];
|
|
62
|
+
else if (Array.isArray(value) && value.every(isPreviewElement)) slots[prop] = value.map((held, index) => add(held, `${key}_${prop}_${index}`));
|
|
63
|
+
else props[prop] = value;
|
|
31
64
|
elements[key] = {
|
|
32
65
|
type: previewElementType(node.element),
|
|
33
66
|
props: {
|
|
34
|
-
...
|
|
67
|
+
...props,
|
|
35
68
|
...node.text !== void 0 ? { children: node.text } : {}
|
|
36
69
|
},
|
|
37
|
-
...children.length > 0 ? { children } : {}
|
|
70
|
+
...children.length > 0 ? { children } : {},
|
|
71
|
+
...Object.keys(slots).length > 0 ? { slots } : {}
|
|
38
72
|
};
|
|
39
73
|
return key;
|
|
40
74
|
};
|
|
@@ -48,11 +82,52 @@ function isElementValue(value) {
|
|
|
48
82
|
return isPreviewElement(value) || Array.isArray(value) && value.some(isPreviewElement);
|
|
49
83
|
}
|
|
50
84
|
/**
|
|
51
|
-
*
|
|
85
|
+
* Graft a slot's content under its host: the elements join the spec's keyed element map as
|
|
86
|
+
* `<host>__<prop>__<index>` subtrees, and the host's `slots[into]` names their roots — json-render
|
|
87
|
+
* traverses `slots` itself, so the keys join neither `props` nor `children`. What an earlier graft
|
|
88
|
+
* of the same slot put there goes first, so the same keys are minted again for the content this
|
|
89
|
+
* pass holds and nothing stale is left for the next key to collide with. The spec comes back
|
|
90
|
+
* unchanged, by reference, when the grafted content is already what is there.
|
|
52
91
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
|
|
92
|
+
* Every host that grafts slot content goes through here: the tile projection, the matrix cell and
|
|
93
|
+
* the cell panel, so their keys agree and the layers rail and the drop hit-test read one scheme.
|
|
94
|
+
*/
|
|
95
|
+
function graftSlotContent({ spec, hostKey, prop, into, elements: content }) {
|
|
96
|
+
const host = spec.elements[hostKey];
|
|
97
|
+
if (!host) return spec;
|
|
98
|
+
const prefix = `${hostKey}__${prop}__`;
|
|
99
|
+
const kept = Object.fromEntries(Object.entries(spec.elements).filter(([key]) => !key.startsWith(prefix)));
|
|
100
|
+
const grafted = {};
|
|
101
|
+
const used = new Set(Object.keys(kept));
|
|
102
|
+
const roots = content.map((node, index) => {
|
|
103
|
+
const built = previewElementNodes(node, `${prefix}${index}`, used);
|
|
104
|
+
for (const [key, element] of Object.entries(built.elements)) {
|
|
105
|
+
grafted[key] = element;
|
|
106
|
+
used.add(key);
|
|
107
|
+
}
|
|
108
|
+
return built.root;
|
|
109
|
+
});
|
|
110
|
+
const current = host.slots?.[into];
|
|
111
|
+
if (current !== void 0 && current.length === roots.length && roots.every((root, index) => current[index] === root) && Object.keys(spec.elements).filter((key) => key.startsWith(prefix)).length === Object.keys(grafted).length && Object.entries(grafted).every(([key, element]) => JSON.stringify(spec.elements[key]) === JSON.stringify(element))) return spec;
|
|
112
|
+
return {
|
|
113
|
+
...spec,
|
|
114
|
+
elements: {
|
|
115
|
+
...kept,
|
|
116
|
+
...grafted,
|
|
117
|
+
[hostKey]: {
|
|
118
|
+
...host,
|
|
119
|
+
slots: {
|
|
120
|
+
...host.slots,
|
|
121
|
+
[into]: roots
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Lower the root's direct element-valued props into json-render's native slot form, one
|
|
129
|
+
* {@link graftSlotContent} per prop, under the prop's own name. Plain values — including text in
|
|
130
|
+
* `props.children` — remain props.
|
|
56
131
|
*
|
|
57
132
|
* Elements nested inside arbitrary structured data are deliberately left for runtime marker
|
|
58
133
|
* revival. A `slots` entry identifies a component prop, not a path inside an opaque application
|
|
@@ -61,29 +136,34 @@ function isElementValue(value) {
|
|
|
61
136
|
function graftPreviewElements(spec, values) {
|
|
62
137
|
const entries = Object.entries(values).filter(([, value]) => isElementValue(value));
|
|
63
138
|
if (entries.length === 0) return spec;
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const rootElement = elements[rootKey];
|
|
68
|
-
if (!rootElement) return spec;
|
|
69
|
-
const used = new Set(Object.keys(elements));
|
|
70
|
-
const rootProps = { ...rootElement.props ?? {} };
|
|
71
|
-
const rootSlots = { ...rootElement.slots ?? {} };
|
|
139
|
+
const rootKey = spec.root;
|
|
140
|
+
if (!spec.elements[rootKey]) return spec;
|
|
141
|
+
let next = spec;
|
|
72
142
|
for (const [prop, value] of entries) {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
143
|
+
const content = Array.isArray(value) ? value.filter(isPreviewElement) : [value];
|
|
144
|
+
next = graftSlotContent({
|
|
145
|
+
spec: next,
|
|
146
|
+
hostKey: rootKey,
|
|
147
|
+
prop,
|
|
148
|
+
into: prop,
|
|
149
|
+
elements: content
|
|
80
150
|
});
|
|
81
|
-
|
|
82
|
-
|
|
151
|
+
const root = next.elements[rootKey];
|
|
152
|
+
if (root?.props && prop in root.props) {
|
|
153
|
+
const { [prop]: _lowered, ...rest } = root.props;
|
|
154
|
+
next = {
|
|
155
|
+
...next,
|
|
156
|
+
elements: {
|
|
157
|
+
...next.elements,
|
|
158
|
+
[rootKey]: {
|
|
159
|
+
...root,
|
|
160
|
+
props: rest
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
83
165
|
}
|
|
84
|
-
rootElement.props = rootProps;
|
|
85
|
-
rootElement.slots = rootSlots;
|
|
86
166
|
return next;
|
|
87
167
|
}
|
|
88
168
|
//#endregion
|
|
89
|
-
export { graftPreviewElements, hasPreviewElementDeep, isPreviewElement, previewElementNodes, previewElementType };
|
|
169
|
+
export { graftPreviewElements, graftSlotContent, hasPreviewElementDeep, isComponentRef, isPreviewElement, isPreviewRef, previewElementNodes, previewElementType };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Config } from "../framework/Config.js";
|
|
2
|
+
|
|
3
|
+
//#region src/spec/prop-conditions.d.ts
|
|
4
|
+
/** A sibling a prop's condition may name, with the values the condition may hold it at. A boolean
|
|
5
|
+
* offers `true`/`false` as the strings a form works in; a number offers no list, since any number
|
|
6
|
+
* is a value. */
|
|
7
|
+
interface ConditionableProp {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly kind: 'variant' | 'boolean' | 'number';
|
|
10
|
+
readonly values: readonly string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The siblings a condition on one of a component's props may name: its own declared props that are
|
|
14
|
+
* a closed axis or a scalar the condition schema coerces. A name exposed only through `forwards` is
|
|
15
|
+
* not one, since `when` is validated against the component's own declarations. `except` leaves out
|
|
16
|
+
* the prop being conditioned.
|
|
17
|
+
*/
|
|
18
|
+
declare function conditionableProps({
|
|
19
|
+
config,
|
|
20
|
+
path,
|
|
21
|
+
except
|
|
22
|
+
}: {
|
|
23
|
+
config: Config;
|
|
24
|
+
path: string;
|
|
25
|
+
except?: string;
|
|
26
|
+
}): ConditionableProp[];
|
|
27
|
+
//#endregion
|
|
28
|
+
export { ConditionableProp, conditionableProps };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { surfaceProps } from "../framework/prop-surface.js";
|
|
2
|
+
import { Component } from "../entities/system/Component.js";
|
|
3
|
+
//#region src/spec/prop-conditions.ts
|
|
4
|
+
/**
|
|
5
|
+
* What a prop's `when` may name, for the form that authors one.
|
|
6
|
+
*/
|
|
7
|
+
const BOOLEAN_CONDITION_VALUES = ["true", "false"];
|
|
8
|
+
/**
|
|
9
|
+
* The siblings a condition on one of a component's props may name: its own declared props that are
|
|
10
|
+
* a closed axis or a scalar the condition schema coerces. A name exposed only through `forwards` is
|
|
11
|
+
* not one, since `when` is validated against the component's own declarations. `except` leaves out
|
|
12
|
+
* the prop being conditioned.
|
|
13
|
+
*/
|
|
14
|
+
function conditionableProps({ config, path, except }) {
|
|
15
|
+
const own = Component.get(config, path)?.props ?? {};
|
|
16
|
+
const out = [];
|
|
17
|
+
for (const prop of surfaceProps(config, path)) {
|
|
18
|
+
if (prop.name === except) continue;
|
|
19
|
+
if (own[prop.name] === null || own[prop.name] === void 0) continue;
|
|
20
|
+
if (prop.kind === "variant") out.push({
|
|
21
|
+
name: prop.name,
|
|
22
|
+
kind: "variant",
|
|
23
|
+
values: prop.values
|
|
24
|
+
});
|
|
25
|
+
else if (prop.kind === "boolean") out.push({
|
|
26
|
+
name: prop.name,
|
|
27
|
+
kind: "boolean",
|
|
28
|
+
values: BOOLEAN_CONDITION_VALUES
|
|
29
|
+
});
|
|
30
|
+
else if (prop.kind === "number") out.push({
|
|
31
|
+
name: prop.name,
|
|
32
|
+
kind: "number",
|
|
33
|
+
values: []
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { conditionableProps };
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { ConfigEdit } from "../framework/config-op.js";
|
|
2
|
+
import { Ref } from "../framework/utils/refs.js";
|
|
3
|
+
import { Config } from "../framework/Config.js";
|
|
4
|
+
import { SlotTarget } from "../framework/render-spec.js";
|
|
5
|
+
import { PreviewElement } from "./preview-elements.js";
|
|
6
|
+
import { PreviewContentAddress, PreviewValueSource } from "./preview-content.js";
|
|
7
|
+
|
|
8
|
+
//#region src/spec/slot.d.ts
|
|
9
|
+
/** A cell's coordinate: the axis values it pins. Empty for the component's own row. */
|
|
10
|
+
type SlotCell = Readonly<Record<string, unknown>>;
|
|
11
|
+
/** What one slot is, apart from the config it is read over. */
|
|
12
|
+
interface SlotFacts extends SlotTarget {
|
|
13
|
+
readonly accepts: readonly string[];
|
|
14
|
+
}
|
|
15
|
+
declare class Slot implements SlotTarget {
|
|
16
|
+
private readonly config;
|
|
17
|
+
/** The component that declares the slot. */
|
|
18
|
+
readonly component: string;
|
|
19
|
+
/** The prop the content arrives as on the instance (`children`, `startIcon`). */
|
|
20
|
+
readonly from: string;
|
|
21
|
+
/** The layer that holds the content. */
|
|
22
|
+
readonly layer: string;
|
|
23
|
+
/** The prop the content lands under on the layer's element. */
|
|
24
|
+
readonly into: string;
|
|
25
|
+
/** The refs the slot accepts (`component:X`, `icon:phosphor`); empty when unconstrained. */
|
|
26
|
+
readonly accepts: readonly string[];
|
|
27
|
+
/** Built by {@link listSlots}; a surface reaches one through `Component.slots` or `Component.slot`. */
|
|
28
|
+
constructor(config: Config, component: string, facts: SlotFacts);
|
|
29
|
+
/** Whether this is the component's `children`, positioned inside one of its layers. */
|
|
30
|
+
get isChildren(): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Whether the slot takes an element: anything when it accepts nothing in particular, else an
|
|
33
|
+
* element whose ref one of the accepted refs names, exactly or as a member of a group the ref
|
|
34
|
+
* names (`icon:phosphor` takes `icon:phosphor/StarIcon`). A `@source` marker on either side is
|
|
35
|
+
* not part of the name. `element` is a spec type, a bare component path, or the ref a preview
|
|
36
|
+
* element stores.
|
|
37
|
+
*/
|
|
38
|
+
takes(element: string | Ref): boolean;
|
|
39
|
+
/** The stored field a cell reads the slot's content from, or `undefined` when nothing is stored. */
|
|
40
|
+
source(cell: SlotCell): PreviewValueSource | undefined;
|
|
41
|
+
/** The elements a cell shows in the slot, in order. */
|
|
42
|
+
content(cell: SlotCell): PreviewElement[];
|
|
43
|
+
/**
|
|
44
|
+
* Append `element` to the content under `cell`: the entry keyed on exactly that coordinate, `*`
|
|
45
|
+
* for none, created where none spells it yet and seeded with the list the coordinate shows, so the
|
|
46
|
+
* cells it covers gain the element and every other cell keeps what it had.
|
|
47
|
+
*/
|
|
48
|
+
append({
|
|
49
|
+
cell,
|
|
50
|
+
element
|
|
51
|
+
}: {
|
|
52
|
+
cell: SlotCell;
|
|
53
|
+
element: PreviewElement;
|
|
54
|
+
}): ConfigEdit[];
|
|
55
|
+
/**
|
|
56
|
+
* The content shown under `cell` with `element` placed at `address`: at `index` of the list when
|
|
57
|
+
* the path is empty, past the end appending; otherwise inside the element at `index`, where a
|
|
58
|
+
* number step is the position among that element's children and a string step the element-valued
|
|
59
|
+
* prop it becomes. `undefined` when the address names another slot or a path that reaches nothing.
|
|
60
|
+
* What a surface paints while a drop is still being decided, and what {@link insertAt} writes.
|
|
61
|
+
*/
|
|
62
|
+
placed({
|
|
63
|
+
cell,
|
|
64
|
+
address,
|
|
65
|
+
element
|
|
66
|
+
}: {
|
|
67
|
+
cell: SlotCell;
|
|
68
|
+
address: PreviewContentAddress;
|
|
69
|
+
element: PreviewElement;
|
|
70
|
+
}): PreviewElement[] | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* The element at `from` moved to `to`, both in this slot's content under `cell`, on the entry the
|
|
73
|
+
* cell reads the content from. `to` names a position in the content with the moved element
|
|
74
|
+
* already taken out, the way a drop between the remaining elements resolves it. Empty when either
|
|
75
|
+
* address names nothing, or `to` reaches inside the moved element.
|
|
76
|
+
*/
|
|
77
|
+
moveAt({
|
|
78
|
+
cell,
|
|
79
|
+
from,
|
|
80
|
+
to
|
|
81
|
+
}: {
|
|
82
|
+
cell: SlotCell;
|
|
83
|
+
from: PreviewContentAddress;
|
|
84
|
+
to: PreviewContentAddress;
|
|
85
|
+
}): ConfigEdit[];
|
|
86
|
+
/** The element at `address` in the content shown under `cell`, or `undefined` when it names nothing. */
|
|
87
|
+
elementAt({
|
|
88
|
+
cell,
|
|
89
|
+
address
|
|
90
|
+
}: {
|
|
91
|
+
cell: SlotCell;
|
|
92
|
+
address: PreviewContentAddress;
|
|
93
|
+
}): PreviewElement | undefined;
|
|
94
|
+
/**
|
|
95
|
+
* A copy of the element at `address`, placed right after it: the next index of the list, or the
|
|
96
|
+
* next position among its parent's children. Written on the entry the cell reads the content
|
|
97
|
+
* from, like {@link replaceAt}, so a copy made in a conditional cell of `*` content is every
|
|
98
|
+
* cell's. An element held as a prop has no "after", so it is not duplicated. Empty when the
|
|
99
|
+
* address names nothing.
|
|
100
|
+
*/
|
|
101
|
+
duplicateAt({
|
|
102
|
+
cell,
|
|
103
|
+
address
|
|
104
|
+
}: {
|
|
105
|
+
cell: SlotCell;
|
|
106
|
+
address: PreviewContentAddress;
|
|
107
|
+
}): ConfigEdit[];
|
|
108
|
+
/** Write the content {@link placed} gives, onto the cell's own entry the way `append` writes.
|
|
109
|
+
* Empty when nothing is placed. */
|
|
110
|
+
insertAt({
|
|
111
|
+
cell,
|
|
112
|
+
address,
|
|
113
|
+
element
|
|
114
|
+
}: {
|
|
115
|
+
cell: SlotCell;
|
|
116
|
+
address: PreviewContentAddress;
|
|
117
|
+
element: PreviewElement;
|
|
118
|
+
}): ConfigEdit[];
|
|
119
|
+
/**
|
|
120
|
+
* Swap the element at `address` for `element`, on the entry the cell reads the content from —
|
|
121
|
+
* `*` included, so a `*` value shown in a conditional cell changes for every cell rather than
|
|
122
|
+
* being copied into a new keyed entry. Empty when the address names nothing.
|
|
123
|
+
*/
|
|
124
|
+
replaceAt({
|
|
125
|
+
cell,
|
|
126
|
+
address,
|
|
127
|
+
element
|
|
128
|
+
}: {
|
|
129
|
+
cell: SlotCell;
|
|
130
|
+
address: PreviewContentAddress;
|
|
131
|
+
element: PreviewElement;
|
|
132
|
+
}): ConfigEdit[];
|
|
133
|
+
/**
|
|
134
|
+
* Take the element at `address` out, on the entry the cell reads the content from. A list emptied
|
|
135
|
+
* this way clears the prop, and an entry left with no props goes with it. Empty when the address
|
|
136
|
+
* names nothing.
|
|
137
|
+
*/
|
|
138
|
+
removeAt({
|
|
139
|
+
cell,
|
|
140
|
+
address
|
|
141
|
+
}: {
|
|
142
|
+
cell: SlotCell;
|
|
143
|
+
address: PreviewContentAddress;
|
|
144
|
+
}): ConfigEdit[];
|
|
145
|
+
/**
|
|
146
|
+
* Store `elements` as the whole content under `cell`: one `sub-update` on the `preview` entry
|
|
147
|
+
* keyed on the coordinate, `*` for none, created where none spells it and joined where one does.
|
|
148
|
+
* What a picker that shows the whole list writes; the verbs above build on it.
|
|
149
|
+
*/
|
|
150
|
+
set({
|
|
151
|
+
cell,
|
|
152
|
+
elements
|
|
153
|
+
}: {
|
|
154
|
+
cell: SlotCell;
|
|
155
|
+
elements: readonly PreviewElement[];
|
|
156
|
+
}): ConfigEdit[];
|
|
157
|
+
private stored;
|
|
158
|
+
/** `replaceAt` and `removeAt`: one element rewritten or dropped, written back where it was read. */
|
|
159
|
+
private rewrite;
|
|
160
|
+
/** The edits that store `content` on `source`: the field the content came from, cleared when the
|
|
161
|
+
* list is empty, and the entry it leaves with nothing else going with it. */
|
|
162
|
+
private writeSource;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Every slot of a component that content can be placed in: its named node slots, and its `children`
|
|
166
|
+
* when a layer of several positions them. A text slot is typed in place rather than filled, so it is
|
|
167
|
+
* not one; nor is `children` landing on the root, which is the open hole every container has. The
|
|
168
|
+
* same array comes back for the same config.
|
|
169
|
+
*/
|
|
170
|
+
declare function listSlots({
|
|
171
|
+
config,
|
|
172
|
+
path
|
|
173
|
+
}: {
|
|
174
|
+
config: Config;
|
|
175
|
+
path: string;
|
|
176
|
+
}): readonly Slot[];
|
|
177
|
+
/** The named node slots alone: what a design node's render injects an empty placeholder for. */
|
|
178
|
+
declare function namedSlots({
|
|
179
|
+
config,
|
|
180
|
+
path
|
|
181
|
+
}: {
|
|
182
|
+
config: Config;
|
|
183
|
+
path: string;
|
|
184
|
+
}): readonly Slot[];
|
|
185
|
+
/** The slot a prop names, or `undefined` when the prop is not a slot content is placed in. */
|
|
186
|
+
declare function slotOf({
|
|
187
|
+
config,
|
|
188
|
+
path,
|
|
189
|
+
slot
|
|
190
|
+
}: {
|
|
191
|
+
config: Config;
|
|
192
|
+
path: string;
|
|
193
|
+
slot: string;
|
|
194
|
+
}): Slot | undefined;
|
|
195
|
+
/** The slot whose content lands in `layer`, or `undefined` when the layer hosts none. */
|
|
196
|
+
declare function slotHostedBy({
|
|
197
|
+
config,
|
|
198
|
+
path,
|
|
199
|
+
layer
|
|
200
|
+
}: {
|
|
201
|
+
config: Config;
|
|
202
|
+
path: string;
|
|
203
|
+
layer: string;
|
|
204
|
+
}): Slot | undefined;
|
|
205
|
+
//#endregion
|
|
206
|
+
export { Slot, SlotCell, listSlots, namedSlots, slotHostedBy, slotOf };
|