@yahoo/uds-create-config 4.0.3 → 4.0.5
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/react-native-system.js +2 -0
- package/dist/configs/system.js +2 -0
- package/dist/entities/system/Component.d.ts +8 -0
- package/dist/entities/system/Component.js +26 -1
- package/dist/entities/system/component-module.d.ts +5 -2
- package/dist/entities/system/component-module.js +10 -3
- package/dist/framework/Config.d.ts +1 -1
- package/dist/framework/Config.js +1 -1
- package/dist/framework/render-spec.d.ts +21 -2
- package/dist/framework/render-spec.js +86 -9
- 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/20260918161049_anatomy_node_actions.d.ts +14 -0
- package/dist/migrations/20260918161049_anatomy_node_actions.js +10 -0
- package/dist/renderer/wrappers/event-bridge.js +11 -2
- package/dist/spec/index.d.ts +2 -2
- package/dist/spec/index.js +2 -2
- package/dist/spec/rewrite-refs.d.ts +13 -1
- package/dist/spec/rewrite-refs.js +74 -11
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { useStateStore } from "@json-render/react";
|
|
3
|
+
import { resolveActionParam } from "@json-render/core";
|
|
3
4
|
//#region src/renderer/wrappers/event-bridge.tsx
|
|
4
5
|
/**
|
|
5
6
|
* Map json-render `on.*` event bindings to React callback prop names.
|
|
@@ -21,6 +22,14 @@ const EVENT_TO_CALLBACKS = {
|
|
|
21
22
|
valueCommit: ["onValueCommit"],
|
|
22
23
|
dismiss: ["onDismiss"]
|
|
23
24
|
};
|
|
25
|
+
/** `checkedChange` → `onCheckedChange`, `selectedChange` → `onSelectedChange`: the callback a
|
|
26
|
+
* controlled prop's change is reported through, by the convention every UDS control follows. */
|
|
27
|
+
function changeCallbackOf(eventName) {
|
|
28
|
+
const match = /^([a-z][A-Za-z0-9]*)Change$/.exec(eventName);
|
|
29
|
+
if (!match?.[1]) return void 0;
|
|
30
|
+
const prop = match[1];
|
|
31
|
+
return [`on${prop[0]?.toUpperCase()}${prop.slice(1)}Change`];
|
|
32
|
+
}
|
|
24
33
|
/**
|
|
25
34
|
* Bridge json-render's `on.*` event bindings to React callback props.
|
|
26
35
|
*
|
|
@@ -44,7 +53,7 @@ function wrapEventBridge(reg) {
|
|
|
44
53
|
if (!on) return React.createElement(Comp, renderProps);
|
|
45
54
|
const callbackProps = {};
|
|
46
55
|
for (const [eventName, binding] of Object.entries(on)) {
|
|
47
|
-
const callbackNames = EVENT_TO_CALLBACKS[eventName];
|
|
56
|
+
const callbackNames = EVENT_TO_CALLBACKS[eventName] ?? changeCallbackOf(eventName);
|
|
48
57
|
if (!callbackNames) continue;
|
|
49
58
|
const bindings = Array.isArray(binding) ? binding : [binding];
|
|
50
59
|
const handler = (...args) => {
|
|
@@ -52,7 +61,7 @@ function wrapEventBridge(reg) {
|
|
|
52
61
|
for (const b of bindings) {
|
|
53
62
|
const action = b;
|
|
54
63
|
if (action.action === "setState" && action.params?.statePath) {
|
|
55
|
-
const val = "value" in (action.params ?? {}) ? action.params.value : callbackValue;
|
|
64
|
+
const val = "value" in (action.params ?? {}) ? resolveActionParam(action.params.value, { stateModel: stateStore.getSnapshot() }) : callbackValue;
|
|
56
65
|
stateStore.set(action.params.statePath, val);
|
|
57
66
|
} else emit(eventName);
|
|
58
67
|
}
|
package/dist/spec/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AcceptsChildNodes, ChildNodesClassification, ClassifyChildNodes, buildAcceptsChildNodes, buildClassifyChildNodes, namedSlotTargets, stripInjectedSlots, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots } from "./empty-node-slots.js";
|
|
2
2
|
import { GraftableElement, GraftableSpec, PreviewElement, PreviewSpecNode, PreviewValue, graftPreviewElements, hasPreviewElementDeep, isPreviewElement, previewElementNodes, previewElementType } from "./preview-elements.js";
|
|
3
|
-
import { DocumentRename, RewritableSpec, SpecRewrite, rewriteSpecRefs } from "./rewrite-refs.js";
|
|
3
|
+
import { DocumentRename, RewritableSpec, SpecRewrite, documentRenamesFromPatches, rewriteSpecRefs } from "./rewrite-refs.js";
|
|
4
4
|
import { applyForcedModifiers, collectForcedModifierProps } from "./apply-forced-modifiers.js";
|
|
5
5
|
import { AssetComponentMap, AssetJsxForm, AssetNodeResolver, assetJsxForm, jsxIdentifier, parseAssetType } from "./asset-jsx.js";
|
|
6
6
|
import { CollapseTextLabelsResult, CollapsedTextLabel, collapseWrappedTextLabels } from "./collapse-text-labels.js";
|
|
@@ -26,4 +26,4 @@ import { SpecToJsxOptions, SpecToJsxResult, specToJsx } from "./specToJsx.js";
|
|
|
26
26
|
* element, without changing the rendered layer hierarchy. */
|
|
27
27
|
declare const SYNTHETIC_TEXT_SLOT_PROP = "data-uds-synthetic-text-slot";
|
|
28
28
|
//#endregion
|
|
29
|
-
export { type AcceptsChildNodes, type AssetComponentMap, type AssetJsxForm, type AssetNodeResolver, type ChildNodesClassification, type ClassifyChildNodes, type CollapseTextLabelsResult, type CollapsedTextLabel, type DocumentRename, type GraftableElement, type GraftableSpec, type JsxToSpecOptions, type PreviewElement, type PreviewSpecNode, type PreviewValue, type RewritableSpec, SYNTHETIC_TEXT_SLOT_PROP, type SpecRewrite, type SpecToJsxOptions, type SpecToJsxResult, UNRESOLVED, applyForcedModifiers, assetJsxForm, buildAcceptsChildNodes, buildClassifyChildNodes, collapseWrappedTextLabels, collectForcedModifierProps, graftPreviewElements, hasPreviewElementDeep, hasUnresolvedProps, isPreviewElement, jsxIdentifier, jsxToSpec, namedSlotTargets, parseAssetType, previewElementNodes, previewElementType, rewriteSpecRefs, specToJsx, stripInjectedSlots, stripUnresolvedProps, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots };
|
|
29
|
+
export { type AcceptsChildNodes, type AssetComponentMap, type AssetJsxForm, type AssetNodeResolver, type ChildNodesClassification, type ClassifyChildNodes, type CollapseTextLabelsResult, type CollapsedTextLabel, type DocumentRename, type GraftableElement, type GraftableSpec, type JsxToSpecOptions, type PreviewElement, type PreviewSpecNode, type PreviewValue, type RewritableSpec, SYNTHETIC_TEXT_SLOT_PROP, type SpecRewrite, type SpecToJsxOptions, type SpecToJsxResult, UNRESOLVED, applyForcedModifiers, assetJsxForm, buildAcceptsChildNodes, buildClassifyChildNodes, collapseWrappedTextLabels, collectForcedModifierProps, documentRenamesFromPatches, graftPreviewElements, hasPreviewElementDeep, hasUnresolvedProps, isPreviewElement, jsxIdentifier, jsxToSpec, namedSlotTargets, parseAssetType, previewElementNodes, previewElementType, rewriteSpecRefs, specToJsx, stripInjectedSlots, stripUnresolvedProps, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots };
|
package/dist/spec/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { buildAcceptsChildNodes, buildClassifyChildNodes, namedSlotTargets, stri
|
|
|
4
4
|
import { applyForcedModifiers, collectForcedModifierProps } from "./apply-forced-modifiers.js";
|
|
5
5
|
import { collapseWrappedTextLabels } from "./collapse-text-labels.js";
|
|
6
6
|
import { UNRESOLVED, hasUnresolvedProps, jsxToSpec, stripUnresolvedProps } from "./jsxToSpec.js";
|
|
7
|
-
import { rewriteSpecRefs } from "./rewrite-refs.js";
|
|
7
|
+
import { documentRenamesFromPatches, rewriteSpecRefs } from "./rewrite-refs.js";
|
|
8
8
|
import { specToJsx } from "./specToJsx.js";
|
|
9
9
|
//#region src/spec/index.ts
|
|
10
10
|
/**
|
|
@@ -25,4 +25,4 @@ import { specToJsx } from "./specToJsx.js";
|
|
|
25
25
|
* element, without changing the rendered layer hierarchy. */
|
|
26
26
|
const SYNTHETIC_TEXT_SLOT_PROP = "data-uds-synthetic-text-slot";
|
|
27
27
|
//#endregion
|
|
28
|
-
export { SYNTHETIC_TEXT_SLOT_PROP, UNRESOLVED, applyForcedModifiers, assetJsxForm, buildAcceptsChildNodes, buildClassifyChildNodes, collapseWrappedTextLabels, collectForcedModifierProps, graftPreviewElements, hasPreviewElementDeep, hasUnresolvedProps, isPreviewElement, jsxIdentifier, jsxToSpec, namedSlotTargets, parseAssetType, previewElementNodes, previewElementType, rewriteSpecRefs, specToJsx, stripInjectedSlots, stripUnresolvedProps, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots };
|
|
28
|
+
export { SYNTHETIC_TEXT_SLOT_PROP, UNRESOLVED, applyForcedModifiers, assetJsxForm, buildAcceptsChildNodes, buildClassifyChildNodes, collapseWrappedTextLabels, collectForcedModifierProps, documentRenamesFromPatches, graftPreviewElements, hasPreviewElementDeep, hasUnresolvedProps, isPreviewElement, jsxIdentifier, jsxToSpec, namedSlotTargets, parseAssetType, previewElementNodes, previewElementType, rewriteSpecRefs, specToJsx, stripInjectedSlots, stripUnresolvedProps, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots };
|
|
@@ -35,6 +35,18 @@ type DocumentRename = /** A component's path — `element.type` and a node's own
|
|
|
35
35
|
readonly from: string;
|
|
36
36
|
readonly to: string;
|
|
37
37
|
};
|
|
38
|
+
/**
|
|
39
|
+
* The renames a list of patches recorded, oldest first — the only source that names both halves of every case.
|
|
40
|
+
*
|
|
41
|
+
* A renamed prop, variant value, layer, style property, token or modifier leaves no trace in the set of paths a
|
|
42
|
+
* config holds, and a component renamed to an unrelated name is indistinguishable from a delete plus a create.
|
|
43
|
+
* The patch says what happened, so nothing here has to infer it. That makes this the one place a rename becomes
|
|
44
|
+
* a document rewrite, whatever recorded the patch: a config's own pending edits, or a branch's stored rows.
|
|
45
|
+
*
|
|
46
|
+
* Replay order is preserved because renames compose — a component renamed twice in one draft only lands on the
|
|
47
|
+
* last name if the pairs are applied in the order they were made.
|
|
48
|
+
*/
|
|
49
|
+
declare function documentRenamesFromPatches(patches: readonly Record<string, unknown>[]): DocumentRename[];
|
|
38
50
|
/** A spec as this reads it: the structural subset, loose because the rows are whatever was written months ago. */
|
|
39
51
|
interface RewritableSpec {
|
|
40
52
|
elements?: Record<string, {
|
|
@@ -55,4 +67,4 @@ interface SpecRewrite {
|
|
|
55
67
|
*/
|
|
56
68
|
declare function rewriteSpecRefs(config: Config, spec: RewritableSpec, renames: readonly DocumentRename[]): SpecRewrite;
|
|
57
69
|
//#endregion
|
|
58
|
-
export { DocumentRename, RewritableSpec, SpecRewrite, rewriteSpecRefs };
|
|
70
|
+
export { DocumentRename, RewritableSpec, SpecRewrite, documentRenamesFromPatches, rewriteSpecRefs };
|
|
@@ -12,36 +12,99 @@ import { Component } from "../entities/system/Component.js";
|
|
|
12
12
|
* the config cascades through `cascadeRename` — which walks the ref index — and reaches none of the documents,
|
|
13
13
|
* because a document holds no ref that index can see.
|
|
14
14
|
*
|
|
15
|
-
* So the rename has to be applied here, and the difficulty is that a spec's positions are
|
|
15
|
+
* So the rename has to be applied here, and the difficulty is that a spec's positions are context-dependent:
|
|
16
16
|
*
|
|
17
17
|
* - `props.variant` is `Button`'s own prop only on elements whose type is `Button`. Rewriting the key wherever
|
|
18
18
|
* it appears would rename an unrelated component's `variant` too.
|
|
19
|
-
* - `props.bg` is the `bg`
|
|
19
|
+
* - `props.bg` is the `bg` style property — unless the element's component declares its own `bg`, in which case
|
|
20
20
|
* the component's declaration wins and a style-property rename must leave it alone.
|
|
21
|
-
* - `props.bg = 'primary'` is a token
|
|
21
|
+
* - `props.bg = 'primary'` is a token leaf inside whatever group the `bg` style property draws from, so a token
|
|
22
22
|
* rename only touches values on props that draw from that token's group.
|
|
23
23
|
*
|
|
24
24
|
* Every one of those questions is answered by the config (`resolveComponentProps`, the prop's declaration, the
|
|
25
25
|
* style property's own `values`), which is why this takes one and resolves rather than matching strings.
|
|
26
26
|
*
|
|
27
|
-
* A
|
|
27
|
+
* A modifier is the one position that answers for itself. `_hover` is a prop bag keyed by a modifier's path, and
|
|
28
28
|
* nothing else in a spec is `_`-prefixed — a component can't declare such a prop, and both the style resolver and
|
|
29
29
|
* the prop validator skip the prefix on sight. So a modifier rename moves the key unconditionally, with no
|
|
30
|
-
* component to scope it by.
|
|
31
|
-
* every other rename here descends into it: `_hover: { bg: 'accent' }` sets the same style property and the
|
|
32
|
-
* token as the bag around it, and stopping at the top level would leave the conditional half of a component
|
|
30
|
+
* component to scope it by. The block it prefixes contains a second props bag against the same element, which is
|
|
31
|
+
* why every other rename here descends into it: `_hover: { bg: 'accent' }` sets the same style property and the
|
|
32
|
+
* same token as the bag around it, and stopping at the top level would leave the conditional half of a component
|
|
33
33
|
* stale while the base half moved.
|
|
34
34
|
*
|
|
35
|
-
* `layerProps` is the same shape with one twist: its keys are the component's
|
|
36
|
-
* belongs to what that layer
|
|
35
|
+
* `layerProps` is the same shape with one twist: its keys are the component's layer names, and each bag under one
|
|
36
|
+
* belongs to what that layer renders rather than to the component around it. So a layer rename moves the key —
|
|
37
37
|
* scoped to its component, since `text` on one component is a different layer from `text` on another — and every
|
|
38
38
|
* other rename descends with the layer's own declarations, because `layerProps.text.variant` is `Text`'s variant.
|
|
39
39
|
* A layer that renders a component can itself be overridden through `layerProps`, and that nests the same way.
|
|
40
40
|
*
|
|
41
|
-
* Renames arrive
|
|
41
|
+
* Renames arrive typed and exact, from the patch that recorded them, never inferred. The config supports a
|
|
42
42
|
* rename op per kind and a sub-rename for a component's `props` and `props/value`, so the patch log names both
|
|
43
43
|
* halves of every case below.
|
|
44
44
|
*/
|
|
45
|
+
/**
|
|
46
|
+
* The renames a list of patches recorded, oldest first — the only source that names both halves of every case.
|
|
47
|
+
*
|
|
48
|
+
* A renamed prop, variant value, layer, style property, token or modifier leaves no trace in the set of paths a
|
|
49
|
+
* config holds, and a component renamed to an unrelated name is indistinguishable from a delete plus a create.
|
|
50
|
+
* The patch says what happened, so nothing here has to infer it. That makes this the one place a rename becomes
|
|
51
|
+
* a document rewrite, whatever recorded the patch: a config's own pending edits, or a branch's stored rows.
|
|
52
|
+
*
|
|
53
|
+
* Replay order is preserved because renames compose — a component renamed twice in one draft only lands on the
|
|
54
|
+
* last name if the pairs are applied in the order they were made.
|
|
55
|
+
*/
|
|
56
|
+
function documentRenamesFromPatches(patches) {
|
|
57
|
+
const renames = [];
|
|
58
|
+
for (const patch of patches) {
|
|
59
|
+
const { kind, operation, path, to, field, key } = patch;
|
|
60
|
+
if (typeof to !== "string" || typeof path !== "string") continue;
|
|
61
|
+
if (operation === "rename") {
|
|
62
|
+
if (kind === "component" && path !== to) renames.push({
|
|
63
|
+
kind: "component",
|
|
64
|
+
from: path,
|
|
65
|
+
to
|
|
66
|
+
});
|
|
67
|
+
else if (kind === "style-property" && path !== to) renames.push({
|
|
68
|
+
kind: "style-property",
|
|
69
|
+
from: path,
|
|
70
|
+
to
|
|
71
|
+
});
|
|
72
|
+
else if (kind === "token" && path !== to) renames.push({
|
|
73
|
+
kind: "token",
|
|
74
|
+
from: path,
|
|
75
|
+
to
|
|
76
|
+
});
|
|
77
|
+
else if (kind === "modifier" && path !== to) renames.push({
|
|
78
|
+
kind: "modifier",
|
|
79
|
+
from: path,
|
|
80
|
+
to
|
|
81
|
+
});
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (operation === "sub-rename" && kind === "component") {
|
|
85
|
+
if (field === "props" && typeof key === "string" && key !== to) renames.push({
|
|
86
|
+
kind: "component-prop",
|
|
87
|
+
component: path,
|
|
88
|
+
from: key,
|
|
89
|
+
to
|
|
90
|
+
});
|
|
91
|
+
else if (field === "layers" && typeof key === "string" && key !== to) renames.push({
|
|
92
|
+
kind: "layer",
|
|
93
|
+
component: path,
|
|
94
|
+
from: key,
|
|
95
|
+
to
|
|
96
|
+
});
|
|
97
|
+
else if (field === "props/value" && typeof key === "string" && typeof patch.prop === "string" && key !== to) renames.push({
|
|
98
|
+
kind: "variant-value",
|
|
99
|
+
component: path,
|
|
100
|
+
prop: patch.prop,
|
|
101
|
+
from: key,
|
|
102
|
+
to
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return renames;
|
|
107
|
+
}
|
|
45
108
|
/** Whether a stored `type` names this component path, in either form it may be written in. */
|
|
46
109
|
function namesComponent(type, path) {
|
|
47
110
|
if (typeof type !== "string") return false;
|
|
@@ -247,4 +310,4 @@ function rewriteSpecRefs(config, spec, renames) {
|
|
|
247
310
|
};
|
|
248
311
|
}
|
|
249
312
|
//#endregion
|
|
250
|
-
export { rewriteSpecRefs };
|
|
313
|
+
export { documentRenamesFromPatches, rewriteSpecRefs };
|