@yahoo/uds-create-config 4.12.1 → 4.14.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 +1063 -91
- package/dist/configs/react-native-system.d.ts +696 -48
- package/dist/configs/system.d.ts +696 -48
- package/dist/configs/system.js +2 -0
- package/dist/entities/system/Component.d.ts +467 -32
- package/dist/entities/system/Component.js +24 -13
- package/dist/entities/system/element.d.ts +0 -11
- package/dist/entities/system/element.js +11 -2
- package/dist/framework/Config.d.ts +1 -1
- package/dist/framework/Config.js +1 -1
- package/dist/framework/projections.js +14 -5
- package/dist/framework/prop-surface.d.ts +24 -1
- package/dist/framework/prop-surface.js +42 -9
- package/dist/framework/render-spec.d.ts +53 -4
- package/dist/framework/render-spec.js +163 -27
- package/dist/framework/schema-version.d.ts +1 -1
- package/dist/framework/schema-version.js +5 -5
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/migrations/2.0.0/v1-artifact.d.ts +348 -24
- package/dist/migrations/20260923112910_computed_values_and_repeated_nodes.d.ts +17 -0
- package/dist/migrations/20260923112910_computed_values_and_repeated_nodes.js +10 -0
- package/dist/renderer/UdsRenderer.js +2 -1
- package/dist/renderer/computed.d.ts +16 -0
- package/dist/renderer/computed.js +21 -0
- package/dist/renderer/index.d.ts +2 -1
- package/dist/renderer/index.js +2 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { canonicalCondition, isRef, kindOf,
|
|
2
|
-
import { childrenPolicy } from "./element.js";
|
|
1
|
+
import { canonicalCondition, isRef, kindOf, pathOf, ref, refLeaf, refSchema, splitRef } from "../../framework/utils/refs.js";
|
|
2
|
+
import { childrenPolicy, forwardedPropName } from "./element.js";
|
|
3
3
|
import { reject, rejectData } from "../../framework/rejection.js";
|
|
4
4
|
import { isPlainObject } from "../../framework/utils/field-path.js";
|
|
5
5
|
import { pathInput } from "../../framework/schemas.js";
|
|
@@ -213,14 +213,6 @@ const Layer = defineSubEntity({
|
|
|
213
213
|
* name this component, so a rename cascades and a delete is refused. `'*'` holds no ref and so
|
|
214
214
|
* cannot rot — it tracks a rename for free.
|
|
215
215
|
*/
|
|
216
|
-
/** The prop name a forwarding member ref identifies, or `undefined` for any other ref shape. */
|
|
217
|
-
function forwardedPropName(value) {
|
|
218
|
-
if (!isRef(value) || kindOf(value.__ref) !== "component") return void 0;
|
|
219
|
-
const member = memberOf(value);
|
|
220
|
-
if (!member?.startsWith("props/")) return void 0;
|
|
221
|
-
const name = member.slice(6);
|
|
222
|
-
return name && !name.includes("/") ? name : void 0;
|
|
223
|
-
}
|
|
224
216
|
const forwardedPropRef = refSchema.check((ctx) => {
|
|
225
217
|
if (forwardedPropName(ctx.value) !== void 0) return;
|
|
226
218
|
ctx.issues.push({
|
|
@@ -1033,7 +1025,22 @@ const stateCondition = z.strictObject({
|
|
|
1033
1025
|
...test,
|
|
1034
1026
|
$state: test.$state.startsWith("/") ? test.$state : `/${test.$state}`
|
|
1035
1027
|
}));
|
|
1036
|
-
const
|
|
1028
|
+
const itemCondition = z.strictObject({
|
|
1029
|
+
$item: z.string(),
|
|
1030
|
+
...comparisonOperands,
|
|
1031
|
+
not: z.literal(true).optional()
|
|
1032
|
+
});
|
|
1033
|
+
const indexCondition = z.strictObject({
|
|
1034
|
+
$index: z.literal(true),
|
|
1035
|
+
...comparisonOperands,
|
|
1036
|
+
not: z.literal(true).optional()
|
|
1037
|
+
});
|
|
1038
|
+
const singleCondition = z.union([
|
|
1039
|
+
stateCondition,
|
|
1040
|
+
itemCondition,
|
|
1041
|
+
indexCondition
|
|
1042
|
+
]);
|
|
1043
|
+
const orCondition = z.strictObject({ $or: z.array(z.union([singleCondition, z.array(singleCondition)])) });
|
|
1037
1044
|
/**
|
|
1038
1045
|
* The flat condition an editor collects — `{ variant: 'solid' }` — compiled to the grammar above.
|
|
1039
1046
|
*
|
|
@@ -1072,9 +1079,9 @@ const flatCondition = z.record(z.string(), z.union([
|
|
|
1072
1079
|
return conditions.length === 1 ? conditions[0] : conditions;
|
|
1073
1080
|
});
|
|
1074
1081
|
const visibility = z.union([
|
|
1075
|
-
|
|
1082
|
+
singleCondition,
|
|
1076
1083
|
orCondition,
|
|
1077
|
-
z.array(z.union([
|
|
1084
|
+
z.array(z.union([singleCondition, orCondition])),
|
|
1078
1085
|
z.literal(false),
|
|
1079
1086
|
flatCondition
|
|
1080
1087
|
], { error: "a condition is `{ \"$state\": \"<prop>\" }` for a prop that is set, `{ \"$state\": \"<prop>\", \"eq\": \"<value>\" }` for one value of it (`neq`, `gt`, `gte`, `lt`, `lte` and `not: true` also work), `{ \"$or\": [ … ] }` for any of several, a list of conditions that must all hold, or `false` for a position only an interaction shows" });
|
|
@@ -1232,6 +1239,10 @@ const AnatomyNode = defineSubEntity({
|
|
|
1232
1239
|
values: anatomyPropValue
|
|
1233
1240
|
}) : z.record(z.string(), anatomyPropValue)).optional().describe("Props passed to what the node renders, keyed by prop or style-property name, as literal values. Content is not set here: a `slot` prop's content lands where a `{ \"element\": \"Slot\", \"props\": { \"name\": \"<prop>\" } }` node sits among a parent's `children` (on the root when there is none), and a `forward` prop (`{ \"type\": \"forward\", \"target\": \"label/children\" }`) routes it into that layer with no node entry. `$state` belongs to `visible` and to an `element` a prop chooses."),
|
|
1234
1241
|
text: z.string().optional().describe("Literal text content, for a node that renders a fixed string."),
|
|
1242
|
+
repeat: z.strictObject({
|
|
1243
|
+
source: z.unknown(),
|
|
1244
|
+
group: z.string().optional()
|
|
1245
|
+
}).optional().describe("The node renders once per item of a list: `source` is a prop binding (`{ \"$state\": \"/stops\" }`) or a computed value (`{ \"$computed\": \"<function ref>\", \"args\": { … } }`). Inside the node, `{ \"$item\": \"<field>\" }` reads the current item (`\"\"` for the whole item) and `{ \"$index\": true }` its position."),
|
|
1235
1246
|
on: nodeActions.optional().describe("What an event on the node does to the state model, in json-render's `on` grammar: `{ \"press\": [{ \"action\": \"setState\", \"params\": { \"statePath\": \"/checked\", \"value\": … } }] }`. Read off the render's own handlers; a preview runs them so the composition responds as the component does.")
|
|
1236
1247
|
};
|
|
1237
1248
|
if (!config || !body) return z.object({
|
|
@@ -1,17 +1,6 @@
|
|
|
1
1
|
import { Config } from "../../framework/Config.js";
|
|
2
2
|
|
|
3
3
|
//#region src/entities/system/element.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* A component's forwarded layers, as `{ [layer]: '*' | Ref[] }` — the ONE reader of the field.
|
|
6
|
-
*
|
|
7
|
-
* A field read directly is a field that has to be found again when its shape changes; there were six
|
|
8
|
-
* such callers once, and three read it raw.
|
|
9
|
-
*
|
|
10
|
-
* It used to fall back to `inherits`, the pre-migration spelling, read as `{ [layer]: '*' }`. That
|
|
11
|
-
* reader is gone: `v1-artifact` folds a v1 config straight to `forwards`, so nothing mints the old
|
|
12
|
-
* field, and a stored config still carrying it now forwards nothing rather than being quietly
|
|
13
|
-
* translated. Deliberate — one name for one concept beats two where the second is invisible.
|
|
14
|
-
*/
|
|
15
4
|
declare function forwardsOf(body: {
|
|
16
5
|
forwards?: Record<string, unknown> | undefined;
|
|
17
6
|
}): Record<string, unknown>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { memberOf, splitRef } from "../../framework/utils/refs.js";
|
|
1
|
+
import { isRef, kindOf, memberOf, splitRef } from "../../framework/utils/refs.js";
|
|
2
2
|
//#region src/entities/system/element.ts
|
|
3
3
|
/** The path a value points at when it's a ref to a component, else `undefined`. */
|
|
4
4
|
function componentPathOf(value) {
|
|
@@ -18,6 +18,15 @@ function componentPathOf(value) {
|
|
|
18
18
|
* field, and a stored config still carrying it now forwards nothing rather than being quietly
|
|
19
19
|
* translated. Deliberate — one name for one concept beats two where the second is invisible.
|
|
20
20
|
*/
|
|
21
|
+
/** The prop name a forwarding member ref identifies (`component:Input#props/disabled` → `disabled`),
|
|
22
|
+
* or `undefined` for any other ref shape. */
|
|
23
|
+
function forwardedPropName(value) {
|
|
24
|
+
if (!isRef(value) || kindOf(value.__ref) !== "component") return void 0;
|
|
25
|
+
const member = memberOf(value);
|
|
26
|
+
if (!member?.startsWith("props/")) return void 0;
|
|
27
|
+
const name = member.slice(6);
|
|
28
|
+
return name && !name.includes("/") ? name : void 0;
|
|
29
|
+
}
|
|
21
30
|
function forwardsOf(body) {
|
|
22
31
|
return body.forwards ?? {};
|
|
23
32
|
}
|
|
@@ -170,4 +179,4 @@ function partsOf(config, path) {
|
|
|
170
179
|
return config.list("component").filter((item) => ownerOf(config, item.path) === path).map((item) => item.path);
|
|
171
180
|
}
|
|
172
181
|
//#endregion
|
|
173
|
-
export { VOID_ELEMENTS, childrenPolicy, forwardsOf, ownerOf, partsOf, renderedElement, renderedTarget, rootLayerOf };
|
|
182
|
+
export { VOID_ELEMENTS, childrenPolicy, forwardedPropName, forwardsOf, ownerOf, partsOf, renderedElement, renderedTarget, rootLayerOf };
|
|
@@ -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 = 20260923112910;
|
|
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
|
@@ -4836,7 +4836,7 @@ var Config = class Config {
|
|
|
4836
4836
|
* links from the provided sources. A declared `linkedKind` with no provided source throws. */
|
|
4837
4837
|
hydrateFrom(stored, options) {
|
|
4838
4838
|
const claimed = schemaVersionOf(stored);
|
|
4839
|
-
if (claimed >
|
|
4839
|
+
if (claimed > 20260923112910) throw new SchemaVersionTooNew(claimed);
|
|
4840
4840
|
const wire = upgradeSerializedConfig(stored);
|
|
4841
4841
|
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\`.`);
|
|
4842
4842
|
const leftover = wire.options;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isRef, kindOf, memberOf, pathOf, ref, refLeaf, sourceOf, splitRef } from "./utils/refs.js";
|
|
2
|
-
import { forwardsOf } from "../entities/system/element.js";
|
|
2
|
+
import { forwardedPropName, forwardsOf } from "../entities/system/element.js";
|
|
3
3
|
import { classPrefixOf, varPrefixOf } from "../entities/system/Settings.js";
|
|
4
4
|
import { isDerivedColor, isGradient, renderDerivedColor, renderGradient } from "../entities/system/color.js";
|
|
5
5
|
import { fontFamilyStack } from "../entities/system/Font.js";
|
|
@@ -799,13 +799,22 @@ function computeComponentProps(config, path, seen) {
|
|
|
799
799
|
const element = body.layers?.[layer];
|
|
800
800
|
if (!isRef(element)) continue;
|
|
801
801
|
const exposed = resolveComponentProps(config, pathOf(element.__ref), new Set(seen));
|
|
802
|
-
|
|
803
|
-
|
|
802
|
+
for (const [name, decl] of Object.entries(takenByForward({
|
|
803
|
+
entry,
|
|
804
|
+
exposed
|
|
805
|
+
}))) if (!(name in merged)) merged[name] = decl;
|
|
804
806
|
}
|
|
805
807
|
for (const [name, prop] of Object.entries(body.props ?? {})) if (prop === null) delete merged[name];
|
|
806
808
|
else merged[name] = prop;
|
|
807
809
|
return merged;
|
|
808
810
|
}
|
|
811
|
+
/** The props a `forwards` entry takes from what its element exposes: `'*'` is the whole surface, a
|
|
812
|
+
* list is an allowlist of the names it spells. A list never subtracts, which is what a `null` own
|
|
813
|
+
* prop is for. */
|
|
814
|
+
function takenByForward({ entry, exposed }) {
|
|
815
|
+
if (entry === "*") return exposed;
|
|
816
|
+
return Object.fromEntries((Array.isArray(entry) ? entry : []).map(forwardedPropName).filter((name) => !!name && name in exposed).map((name) => [name, exposed[name]]));
|
|
817
|
+
}
|
|
809
818
|
/**
|
|
810
819
|
* Which component actually declared one of a component's resolved props — its ultimate owner.
|
|
811
820
|
*
|
|
@@ -835,7 +844,7 @@ function propOwner(config, path, prop, seen = /* @__PURE__ */ new Set()) {
|
|
|
835
844
|
for (const [layer, entry] of Object.entries(forwardsOf(body))) {
|
|
836
845
|
const element = body.layers?.[layer];
|
|
837
846
|
if (!isRef(element)) continue;
|
|
838
|
-
if (Array.isArray(entry) && !entry.some((r) =>
|
|
847
|
+
if (Array.isArray(entry) && !entry.some((r) => forwardedPropName(r) === prop)) continue;
|
|
839
848
|
const owner = propOwner(config, pathOf(element.__ref), prop, new Set(seen));
|
|
840
849
|
if (owner) return owner;
|
|
841
850
|
}
|
|
@@ -1210,4 +1219,4 @@ function declaredPropDefaults(props) {
|
|
|
1210
1219
|
return out;
|
|
1211
1220
|
}
|
|
1212
1221
|
//#endregion
|
|
1213
|
-
export { authoredBag, authoredValue, className, cssPropValue, cssVar, cssVarRef, declaredPropDefaults, declaredPropRouting, glyphComponentOf, glyphLibrariesOf, glyphPropsOf, glyphPropsOfBody, holdingPreviewConditions, iconToolAxisOptions, iconToolOf, keyedPreviewConditions, memberFromLeaf, memberLeaves, negatedCssValue, opacityPercentage, previewConditionalProps, previewConditions, previewDefaults, previewMatrix, propOwner, propValueDomain, propValueFromAxis, refListOf, renderStyleValue, resolveComponentProps, resolveFieldValue, resolveTokenValue, resolveTokenValueUnder, routedBag, sourceVarPrefix, styleAliasesOf, styleDeclarations, stylePropEntries, stylePropLeafForToken, stylePropNegates, stylePropTokenGroup, stylePropTokenPath, stylePropTokenValues, stylePropValueFromLeaf, stylePropValueLeaves, stylePropValues, stylePropertiesWriting, stylePropertyAccepts, stylePropertyFor, stylePropertyPathFor, validateComponentProps };
|
|
1222
|
+
export { authoredBag, authoredValue, className, cssPropValue, cssVar, cssVarRef, declaredPropDefaults, declaredPropRouting, glyphComponentOf, glyphLibrariesOf, glyphPropsOf, glyphPropsOfBody, holdingPreviewConditions, iconToolAxisOptions, iconToolOf, keyedPreviewConditions, memberFromLeaf, memberLeaves, negatedCssValue, opacityPercentage, previewConditionalProps, previewConditions, previewDefaults, previewMatrix, propOwner, propValueDomain, propValueFromAxis, refListOf, renderStyleValue, resolveComponentProps, resolveFieldValue, resolveTokenValue, resolveTokenValueUnder, routedBag, sourceVarPrefix, styleAliasesOf, styleDeclarations, stylePropEntries, stylePropLeafForToken, stylePropNegates, stylePropTokenGroup, stylePropTokenPath, stylePropTokenValues, stylePropValueFromLeaf, stylePropValueLeaves, stylePropValues, stylePropertiesWriting, stylePropertyAccepts, stylePropertyFor, stylePropertyPathFor, takenByForward, validateComponentProps };
|
|
@@ -147,7 +147,30 @@ interface ForwardClaims {
|
|
|
147
147
|
readonly own: ReadonlySet<string>;
|
|
148
148
|
/** Forwarded name → the layer whose entry delivers it. The first entry in key order wins an overlap. */
|
|
149
149
|
readonly forwarded: ReadonlyMap<string, string>;
|
|
150
|
+
/** Own declarations that change the type of a name a forwards entry offers, one row per prop. */
|
|
151
|
+
readonly shadowed: readonly ShadowedForward[];
|
|
152
|
+
}
|
|
153
|
+
interface ShadowedForward {
|
|
154
|
+
readonly component: string;
|
|
155
|
+
readonly prop: string;
|
|
156
|
+
/** The layer whose entry would have delivered the prop, and that layer's element with its source. */
|
|
157
|
+
readonly layer: string;
|
|
158
|
+
readonly element: string;
|
|
159
|
+
/** How this component declares the prop (`variant`, `string`, …). */
|
|
160
|
+
readonly declared: string;
|
|
161
|
+
/** How the layer's element declares it. */
|
|
162
|
+
readonly forwarded: string;
|
|
150
163
|
}
|
|
151
164
|
declare function forwardClaims(config: Config, componentPath: string): ForwardClaims;
|
|
165
|
+
/** A component's own props that redeclare, as another type, a name a `forwards` entry offers. The
|
|
166
|
+
* own declaration wins, so the element's prop of that name is unreachable through this component
|
|
167
|
+
* and a call site's value means something else than it does on the element. */
|
|
168
|
+
declare function shadowedForwards({
|
|
169
|
+
config,
|
|
170
|
+
path
|
|
171
|
+
}: {
|
|
172
|
+
readonly config: Config;
|
|
173
|
+
readonly path: string;
|
|
174
|
+
}): ShadowedForward[];
|
|
152
175
|
//#endregion
|
|
153
|
-
export { ForwardClaims, SurfaceCompositeProp, SurfaceProp, SurfacePropCondition, SurfacePropKind, SurfaceScalarProp, SurfaceSlotProp, SurfaceStylePropertyProp, SurfaceVariantProp, forwardClaims, forwardedLayers, intoName, propApplies, propRegistryRef, routedProp, routedPropIn, routesContent, surfaceProp, surfaceProps };
|
|
176
|
+
export { ForwardClaims, ShadowedForward, SurfaceCompositeProp, SurfaceProp, SurfacePropCondition, SurfacePropKind, SurfaceScalarProp, SurfaceSlotProp, SurfaceStylePropertyProp, SurfaceVariantProp, forwardClaims, forwardedLayers, intoName, propApplies, propRegistryRef, routedProp, routedPropIn, routesContent, shadowedForwards, surfaceProp, surfaceProps };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { isRef, kindOf, memberOf, pathOf, refLeaf } from "./utils/refs.js";
|
|
1
|
+
import { isRef, kindOf, memberOf, pathOf, refLeaf, splitRef } from "./utils/refs.js";
|
|
2
2
|
import { forwardsOf, rootLayerOf } from "../entities/system/element.js";
|
|
3
|
-
import { propValueDomain, refListOf, resolveComponentProps } from "./projections.js";
|
|
3
|
+
import { propValueDomain, refListOf, resolveComponentProps, takenByForward } from "./projections.js";
|
|
4
4
|
import { Component } from "../entities/system/Component.js";
|
|
5
5
|
//#region src/framework/prop-surface.ts
|
|
6
6
|
/**
|
|
@@ -302,9 +302,12 @@ function computeForwardClaims(config, componentPath) {
|
|
|
302
302
|
const body = Component.get(config, componentPath)?.toJSON();
|
|
303
303
|
const own = /* @__PURE__ */ new Set();
|
|
304
304
|
const forwarded = /* @__PURE__ */ new Map();
|
|
305
|
+
const shadowed = [];
|
|
306
|
+
const seenShadow = /* @__PURE__ */ new Set();
|
|
305
307
|
if (!body) return {
|
|
306
308
|
own,
|
|
307
309
|
forwarded,
|
|
310
|
+
shadowed,
|
|
308
311
|
rootLayer: void 0
|
|
309
312
|
};
|
|
310
313
|
const { layers = {}, props = {}, forwards } = body;
|
|
@@ -313,19 +316,42 @@ function computeForwardClaims(config, componentPath) {
|
|
|
313
316
|
for (const [layer, entry] of Object.entries(forwardsOf({ forwards }))) {
|
|
314
317
|
const element = layers[layer];
|
|
315
318
|
if (!isRef(element)) continue;
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
319
|
+
const taken = takenByForward({
|
|
320
|
+
entry,
|
|
321
|
+
exposed: resolveComponentProps(config, pathOf(element.__ref))
|
|
322
|
+
});
|
|
323
|
+
for (const [name, theirs] of Object.entries(taken)) {
|
|
324
|
+
if (own.has(name)) {
|
|
325
|
+
if (seenShadow.has(name)) continue;
|
|
326
|
+
seenShadow.add(name);
|
|
327
|
+
const declared = declaredTypeOf(props[name]);
|
|
328
|
+
const forwardedType = declaredTypeOf(theirs);
|
|
329
|
+
if (props[name] === null || declared === "forward" || declared === forwardedType) continue;
|
|
330
|
+
shadowed.push({
|
|
331
|
+
component: componentPath,
|
|
332
|
+
prop: name,
|
|
333
|
+
layer,
|
|
334
|
+
element: splitRef(element.__ref).qualifiedPath,
|
|
335
|
+
declared,
|
|
336
|
+
forwarded: forwardedType
|
|
337
|
+
});
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
if (forwarded.has(name)) continue;
|
|
320
341
|
forwarded.set(name, layer);
|
|
321
342
|
}
|
|
322
343
|
}
|
|
323
344
|
return {
|
|
324
345
|
own,
|
|
325
346
|
forwarded,
|
|
347
|
+
shadowed,
|
|
326
348
|
rootLayer
|
|
327
349
|
};
|
|
328
350
|
}
|
|
351
|
+
function declaredTypeOf(decl) {
|
|
352
|
+
const type = decl?.type;
|
|
353
|
+
return typeof type === "string" ? type : "unknown";
|
|
354
|
+
}
|
|
329
355
|
/**
|
|
330
356
|
* Each non-root layer a component forwards to, and the sorted prop names each one receives — the
|
|
331
357
|
* emitter's view, which writes a literal key set per layer. Root is absent on purpose: it takes
|
|
@@ -344,11 +370,18 @@ function forwardedLayers(config, componentPath) {
|
|
|
344
370
|
return out;
|
|
345
371
|
}
|
|
346
372
|
function forwardClaims(config, componentPath) {
|
|
347
|
-
const { own, forwarded } = computeForwardClaims(config, componentPath);
|
|
373
|
+
const { own, forwarded, shadowed } = computeForwardClaims(config, componentPath);
|
|
348
374
|
return {
|
|
349
375
|
own,
|
|
350
|
-
forwarded
|
|
376
|
+
forwarded,
|
|
377
|
+
shadowed
|
|
351
378
|
};
|
|
352
379
|
}
|
|
380
|
+
/** A component's own props that redeclare, as another type, a name a `forwards` entry offers. The
|
|
381
|
+
* own declaration wins, so the element's prop of that name is unreachable through this component
|
|
382
|
+
* and a call site's value means something else than it does on the element. */
|
|
383
|
+
function shadowedForwards({ config, path }) {
|
|
384
|
+
return computeForwardClaims(config, path).shadowed;
|
|
385
|
+
}
|
|
353
386
|
//#endregion
|
|
354
|
-
export { forwardClaims, forwardedLayers, intoName, propApplies, propRegistryRef, routedProp, routedPropIn, routesContent, routesIntoText, surfaceProp, surfaceProps };
|
|
387
|
+
export { forwardClaims, forwardedLayers, intoName, propApplies, propRegistryRef, routedProp, routedPropIn, routesContent, routesIntoText, shadowedForwards, surfaceProp, surfaceProps };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Config } from "./Config.js";
|
|
2
|
-
import { StateCondition } from "@json-render/core";
|
|
2
|
+
import { ComputedFunction, StateCondition } from "@json-render/core";
|
|
3
3
|
|
|
4
4
|
//#region src/framework/render-spec.d.ts
|
|
5
5
|
/** A node in a flat render spec — json-render's own shape, which is what a canvas paints.
|
|
@@ -30,6 +30,44 @@ interface ComponentSpecs {
|
|
|
30
30
|
readonly render?: RenderSpec;
|
|
31
31
|
readonly preview?: RenderSpec;
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* A node the render writes once per item of a list (`visiblePages.map((item, index) => …)`).
|
|
35
|
+
* `source` is the list: a prop's binding (`{ $state: '/stops' }`) or a value a module-scope function
|
|
36
|
+
* computes from props (`{ $computed, args }`). `group` names the `.map` the node came from, so the
|
|
37
|
+
* arms of one map (`item === 'ellipsis' ? <Gap/> : <Cell/>`) unroll together in item order. Inside
|
|
38
|
+
* the node, `{ $item: '<field>' }` reads the current item (`''` for the whole item) and
|
|
39
|
+
* `{ $index: true }` its position, in json-render's own grammar. Where the expansion cannot settle
|
|
40
|
+
* the list, the node emits once as the example row.
|
|
41
|
+
*/
|
|
42
|
+
interface RepeatSpec {
|
|
43
|
+
readonly source: unknown;
|
|
44
|
+
readonly group?: string;
|
|
45
|
+
}
|
|
46
|
+
/** A value a module-scope function computes at paint time from values the cell supplies: json-render's
|
|
47
|
+
* `$computed`, naming the function by ref (`file:src/…/pagination.tsx#computeVisiblePages`). `args`
|
|
48
|
+
* are keyed by the function's parameter names and resolved before the call. */
|
|
49
|
+
interface ComputedValue {
|
|
50
|
+
readonly $computed: string;
|
|
51
|
+
readonly args?: Record<string, unknown>;
|
|
52
|
+
}
|
|
53
|
+
/** The functions `$computed` values call, by ref — what a preview bundle registers and an
|
|
54
|
+
* expansion or renderer is handed. */
|
|
55
|
+
type ComputedFunctions = Record<string, ComputedFunction>;
|
|
56
|
+
/** The current item of a repeated node while its row is emitted. */
|
|
57
|
+
interface RepeatRow {
|
|
58
|
+
readonly item: unknown;
|
|
59
|
+
readonly index: number;
|
|
60
|
+
}
|
|
61
|
+
/** What settling a value needs beyond the prop bag: the functions `$computed` may call and, inside
|
|
62
|
+
* a repeated node, the current row. */
|
|
63
|
+
interface ResolveContext {
|
|
64
|
+
readonly functions?: ComputedFunctions;
|
|
65
|
+
readonly row?: RepeatRow;
|
|
66
|
+
/** Read a bare `$state` binding as its value. Off for an element's props, where a binding is
|
|
67
|
+
* left for the renderer (and where fill routing reads it); on inside a `$computed`'s arguments
|
|
68
|
+
* and a repeat's source, which have to be values before the call. */
|
|
69
|
+
readonly settle?: boolean;
|
|
70
|
+
}
|
|
33
71
|
/**
|
|
34
72
|
* The registry key of an element rendered THROUGH a package factory — `motion.create(Box)`, spelled
|
|
35
73
|
* `package:motion/react#motion(component:Box)`.
|
|
@@ -165,6 +203,9 @@ interface ExpandOptions {
|
|
|
165
203
|
* with no registry to consult gets.
|
|
166
204
|
*/
|
|
167
205
|
readonly rendered?: ReadonlySet<string>;
|
|
206
|
+
/** The functions `$computed` values call. Absent, a computed value stays on the element for the
|
|
207
|
+
* renderer, and a node repeated over a computed list emits once. */
|
|
208
|
+
readonly functions?: ComputedFunctions;
|
|
168
209
|
}
|
|
169
210
|
interface ExpansionResult {
|
|
170
211
|
readonly spec: RenderSpec;
|
|
@@ -190,7 +231,8 @@ interface ExpansionResult {
|
|
|
190
231
|
* A condition that does not resolve is left exactly as it was, so nothing is claimed about it.
|
|
191
232
|
*/
|
|
192
233
|
declare function specWithResolvedVisibility(spec: RenderSpec, state: Record<string, unknown>, options?: {
|
|
193
|
-
/** Props the renderer keeps deciding at paint time — a choice reading one is left as it is. */readonly live?: ReadonlySet<string>;
|
|
234
|
+
/** Props the renderer keeps deciding at paint time — a choice reading one is left as it is. */readonly live?: ReadonlySet<string>; /** The functions `$computed` values call; absent, a computed value is left for the renderer. */
|
|
235
|
+
readonly functions?: ComputedFunctions;
|
|
194
236
|
}): RenderSpec;
|
|
195
237
|
/** The comparison a `$state` test can make: json-render's own operator set, minus the state pointer
|
|
196
238
|
* and the `not` modifier. Typed off the library so an operator it adds is a typecheck failure here
|
|
@@ -254,7 +296,14 @@ declare function anatomyElementComponent({
|
|
|
254
296
|
}): string | undefined;
|
|
255
297
|
/** A value in json-render's `visible` grammar, resolved against a prop bag. `undefined` when this
|
|
256
298
|
* reader can't settle it, which leaves the condition on the element for the renderer to judge. */
|
|
257
|
-
declare function resolveVisibility(condition: unknown, state: Record<string, unknown
|
|
299
|
+
declare function resolveVisibility(condition: unknown, state: Record<string, unknown>, context?: ResolveContext): boolean | undefined;
|
|
300
|
+
/**
|
|
301
|
+
* A value settled against a prop bag as far as this reader can: a `$state` reads the bag, `$item`
|
|
302
|
+
* and `$index` the current row, `$cond` picks its arm, `$computed` calls its function when the
|
|
303
|
+
* expansion has it and every argument settled, and a plain object or list settles member by member.
|
|
304
|
+
* Whatever cannot be settled is returned as written, for the renderer.
|
|
305
|
+
*/
|
|
306
|
+
declare function resolveValue(value: unknown, state: Record<string, unknown>, context?: ResolveContext): unknown;
|
|
258
307
|
/**
|
|
259
308
|
* Which PROPS a `visible` condition reads, in the order they appear.
|
|
260
309
|
*
|
|
@@ -424,4 +473,4 @@ declare function expandSpec(config: Config, spec: RenderSpec, options?: ExpandOp
|
|
|
424
473
|
*/
|
|
425
474
|
declare function expandComponent(config: Config, path: string, props?: Record<string, unknown>, options?: ExpandOptions): ExpansionResult;
|
|
426
475
|
//#endregion
|
|
427
|
-
export { ANATOMY_MARKER, ComponentSpec, ComponentSpecs, ExpandOptions, ExpansionResult, RenderElement, RenderSpec, SlotTarget, VisibilityOperator, VisibilityTerm, anatomyElementComponent, anatomyTextProp, boundElementType, componentSpec, deriveSpec, entryKeyOf, expandComponent, expandSpec, instanceSpec, layerTextProp, liveStateProps, previewSpec, propInto, propsIntoLayer, readStatePointer, resolveVisibility, routeOf, slotTargetsOf, specWithResolvedVisibility, statePointerProp, valueForwardsOf, visibilityStateProps, visibilityTerms, withoutTruthyTerm, wrappedElementKey };
|
|
476
|
+
export { ANATOMY_MARKER, ComponentSpec, ComponentSpecs, ComputedFunctions, ComputedValue, ExpandOptions, ExpansionResult, RenderElement, RenderSpec, RepeatRow, RepeatSpec, ResolveContext, SlotTarget, VisibilityOperator, VisibilityTerm, anatomyElementComponent, anatomyTextProp, boundElementType, componentSpec, deriveSpec, entryKeyOf, expandComponent, expandSpec, instanceSpec, layerTextProp, liveStateProps, previewSpec, propInto, propsIntoLayer, readStatePointer, resolveValue, resolveVisibility, routeOf, slotTargetsOf, specWithResolvedVisibility, statePointerProp, valueForwardsOf, visibilityStateProps, visibilityTerms, withoutTruthyTerm, wrappedElementKey };
|