@yahoo/uds-create-config 1.1.1
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/AssetGroup.d.ts +77 -0
- package/dist/AssetGroup.js +125 -0
- package/dist/Component.d.ts +308 -0
- package/dist/Component.js +896 -0
- package/dist/ComponentGroup.d.ts +20 -0
- package/dist/ComponentGroup.js +46 -0
- package/dist/CompositeStyle.d.ts +27 -0
- package/dist/CompositeStyle.js +52 -0
- package/dist/Config.d.ts +423 -0
- package/dist/Config.js +1429 -0
- package/dist/Mode.d.ts +41 -0
- package/dist/Mode.js +81 -0
- package/dist/Modifier.d.ts +51 -0
- package/dist/Modifier.js +97 -0
- package/dist/MotionDef.d.ts +49 -0
- package/dist/MotionDef.js +97 -0
- package/dist/Props.d.ts +317 -0
- package/dist/Props.js +35 -0
- package/dist/Provider.d.ts +20 -0
- package/dist/Provider.js +14 -0
- package/dist/StyleProp.d.ts +112 -0
- package/dist/StyleProp.js +197 -0
- package/dist/Token.d.ts +55 -0
- package/dist/Token.js +112 -0
- package/dist/TokenGroup.d.ts +32 -0
- package/dist/TokenGroup.js +68 -0
- package/dist/asset-kind.d.ts +55 -0
- package/dist/asset-kind.js +29 -0
- package/dist/brands.d.ts +30 -0
- package/dist/brands.js +20 -0
- package/dist/captureCallerPath.d.ts +48 -0
- package/dist/captureCallerPath.js +95 -0
- package/dist/colorExpressions.d.ts +131 -0
- package/dist/colorExpressions.js +148 -0
- package/dist/defineAssetGroup.d.ts +166 -0
- package/dist/defineAssetGroup.js +264 -0
- package/dist/defineProvider.d.ts +29 -0
- package/dist/defineProvider.js +60 -0
- package/dist/element-marker.d.ts +54 -0
- package/dist/element-marker.js +113 -0
- package/dist/entity-utils.d.ts +56 -0
- package/dist/entity-utils.js +105 -0
- package/dist/factories.d.ts +707 -0
- package/dist/factories.js +393 -0
- package/dist/foreign-component-name.d.ts +21 -0
- package/dist/foreign-component-name.js +42 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +28 -0
- package/dist/interpolate.d.ts +20 -0
- package/dist/interpolate.js +10 -0
- package/dist/jsx/__fixtures__/cross-component-preview.d.ts +3 -0
- package/dist/jsx/__fixtures__/cross-component-preview.js +15 -0
- package/dist/jsx/jsx-dev-runtime.d.ts +15 -0
- package/dist/jsx/jsx-dev-runtime.js +11 -0
- package/dist/jsx/jsx-runtime.d.ts +48 -0
- package/dist/jsx/jsx-runtime.js +305 -0
- package/dist/markers.d.ts +217 -0
- package/dist/markers.js +67 -0
- package/dist/refs.d.ts +158 -0
- package/dist/refs.js +104 -0
- package/dist/renderer/RendererErrorBoundary.d.ts +26 -0
- package/dist/renderer/RendererErrorBoundary.js +30 -0
- package/dist/renderer/UdsRenderer.d.ts +80 -0
- package/dist/renderer/UdsRenderer.js +33 -0
- package/dist/renderer/assetRenderable.d.ts +13 -0
- package/dist/renderer/assetRenderable.js +13 -0
- package/dist/renderer/index.d.ts +14 -0
- package/dist/renderer/index.js +14 -0
- package/dist/renderer/makeRegistry.d.ts +34 -0
- package/dist/renderer/makeRegistry.js +52 -0
- package/dist/renderer/makeUdsRenderer.d.ts +29 -0
- package/dist/renderer/makeUdsRenderer.js +35 -0
- package/dist/renderer/primitives/FragmentRenderer.d.ts +12 -0
- package/dist/renderer/primitives/FragmentRenderer.js +11 -0
- package/dist/renderer/primitives/SlotRenderer.d.ts +21 -0
- package/dist/renderer/primitives/SlotRenderer.js +20 -0
- package/dist/renderer/wrapRegistry.d.ts +64 -0
- package/dist/renderer/wrapRegistry.js +39 -0
- package/dist/renderer/wrappers/component-slots.d.ts +41 -0
- package/dist/renderer/wrappers/component-slots.js +66 -0
- package/dist/renderer/wrappers/event-bridge.d.ts +20 -0
- package/dist/renderer/wrappers/event-bridge.js +78 -0
- package/dist/renderer/wrappers/hex-normalize.d.ts +14 -0
- package/dist/renderer/wrappers/hex-normalize.js +35 -0
- package/dist/renderer/wrappers/html-aliases.d.ts +24 -0
- package/dist/renderer/wrappers/html-aliases.js +62 -0
- package/dist/renderer/wrappers/inline-styles.d.ts +16 -0
- package/dist/renderer/wrappers/inline-styles.js +104 -0
- package/dist/renderer/wrappers/slot-resolution.d.ts +25 -0
- package/dist/renderer/wrappers/slot-resolution.js +68 -0
- package/dist/renderer/wrappers/void-elements.d.ts +23 -0
- package/dist/renderer/wrappers/void-elements.js +28 -0
- package/dist/spec/apply-forced-modifiers.d.ts +19 -0
- package/dist/spec/apply-forced-modifiers.js +49 -0
- package/dist/spec/asset-jsx.d.ts +48 -0
- package/dist/spec/asset-jsx.js +48 -0
- package/dist/spec/collapse-text-labels.d.ts +44 -0
- package/dist/spec/collapse-text-labels.js +107 -0
- package/dist/spec/empty-node-slots.d.ts +51 -0
- package/dist/spec/empty-node-slots.js +141 -0
- package/dist/spec/index.d.ts +10 -0
- package/dist/spec/index.js +10 -0
- package/dist/spec/jsxToSpec.d.ts +48 -0
- package/dist/spec/jsxToSpec.js +506 -0
- package/dist/spec/layer-props.d.ts +52 -0
- package/dist/spec/layer-props.js +149 -0
- package/dist/spec/preview-controls.d.ts +44 -0
- package/dist/spec/preview-controls.js +139 -0
- package/dist/spec/slot-refs.d.ts +39 -0
- package/dist/spec/slot-refs.js +56 -0
- package/dist/spec/specToJsx.d.ts +35 -0
- package/dist/spec/specToJsx.js +127 -0
- package/dist/token-override-rows.d.ts +66 -0
- package/dist/token-override-rows.js +223 -0
- package/dist/tokenValueType.d.ts +34 -0
- package/dist/tokenValueType.js +138 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/css-properties.d.ts +232 -0
- package/dist/types/css-properties.js +14 -0
- package/dist/types/css-property-keywords.d.ts +156 -0
- package/dist/types/css-property-keywords.js +616 -0
- package/dist/types/css-values.d.ts +63 -0
- package/dist/types/css-values.js +16 -0
- package/dist/types.d.ts +708 -0
- package/dist/types.js +12 -0
- package/dist/units.d.ts +14 -0
- package/dist/units.js +16 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +4 -0
- package/package.json +81 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { foreignComponentName } from "../foreign-component-name.js";
|
|
2
|
+
//#region src/jsx/jsx-runtime.ts
|
|
3
|
+
const Fragment = Symbol.for("react.fragment");
|
|
4
|
+
let configContext = null;
|
|
5
|
+
function setConfigContext(config) {
|
|
6
|
+
configContext = config;
|
|
7
|
+
}
|
|
8
|
+
function getConfigContext() {
|
|
9
|
+
return configContext;
|
|
10
|
+
}
|
|
11
|
+
let counter = 0;
|
|
12
|
+
function nextKey() {
|
|
13
|
+
return `el${counter++}`;
|
|
14
|
+
}
|
|
15
|
+
const pendingRefs = /* @__PURE__ */ new Map();
|
|
16
|
+
let refCounter = 0;
|
|
17
|
+
function nextRefId() {
|
|
18
|
+
return `__udsRef_${refCounter++}`;
|
|
19
|
+
}
|
|
20
|
+
let renderScope = null;
|
|
21
|
+
let wrapperCounter = 0;
|
|
22
|
+
const TRANSPARENT_WRAPPERS = new Set([
|
|
23
|
+
"AnimatePresence",
|
|
24
|
+
"MotionConfig",
|
|
25
|
+
"LazyMotion"
|
|
26
|
+
]);
|
|
27
|
+
/**
|
|
28
|
+
* Scope subsequent wrapper-type resolution to `componentName` (or clear it
|
|
29
|
+
* with `null`). Resets the per-component wrapper index so stamped names are
|
|
30
|
+
* stable across runs regardless of global element-key state.
|
|
31
|
+
*/
|
|
32
|
+
function setRenderExtractionContext(componentName) {
|
|
33
|
+
renderScope = componentName;
|
|
34
|
+
wrapperCounter = 0;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Reset all module-level state — element key counter, pending-ref
|
|
38
|
+
* registry, ref counter, and render-extraction scope. Called by tests
|
|
39
|
+
* asserting specific keys and by the extractor before each top-level
|
|
40
|
+
* evaluation.
|
|
41
|
+
*/
|
|
42
|
+
function __resetKeyCounterForTesting() {
|
|
43
|
+
counter = 0;
|
|
44
|
+
pendingRefs.clear();
|
|
45
|
+
refCounter = 0;
|
|
46
|
+
renderScope = null;
|
|
47
|
+
wrapperCounter = 0;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Drain and return the pending-ref registry. Called by the extractor
|
|
51
|
+
* after `import()`-ing a bundle to rewrite `__udsRef_N` placeholders to
|
|
52
|
+
* the component names that `registerComponents` has now stamped onto
|
|
53
|
+
* each builder.
|
|
54
|
+
*/
|
|
55
|
+
function __drainPendingRefs() {
|
|
56
|
+
const drained = new Map(pendingRefs);
|
|
57
|
+
pendingRefs.clear();
|
|
58
|
+
refCounter = 0;
|
|
59
|
+
return drained;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* JSX automatic-runtime entry for a single static child. Compilers pick
|
|
63
|
+
* this signature when the JSX expression has zero or one child.
|
|
64
|
+
*/
|
|
65
|
+
function jsx(type, props) {
|
|
66
|
+
return buildSpec(type, props);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* JSX automatic-runtime entry for static children — same semantics as
|
|
70
|
+
* `jsx`, the distinction is purely a compiler hint that `props.children`
|
|
71
|
+
* is an array literal.
|
|
72
|
+
*/
|
|
73
|
+
function jsxs(type, props) {
|
|
74
|
+
return buildSpec(type, props);
|
|
75
|
+
}
|
|
76
|
+
function collectChildren(childList, parentTypeName) {
|
|
77
|
+
const mergedElements = {};
|
|
78
|
+
const childKeys = [];
|
|
79
|
+
let textBuffer = "";
|
|
80
|
+
let hasText = false;
|
|
81
|
+
let hasElementChildren = false;
|
|
82
|
+
for (const child of childList) {
|
|
83
|
+
if (child === null || child === void 0 || typeof child === "boolean") continue;
|
|
84
|
+
if (typeof child === "string") {
|
|
85
|
+
textBuffer += child;
|
|
86
|
+
hasText = true;
|
|
87
|
+
} else if (typeof child === "number") {
|
|
88
|
+
textBuffer += String(child);
|
|
89
|
+
hasText = true;
|
|
90
|
+
} else if (isSpec(child)) {
|
|
91
|
+
const inlineText = parentTypeName === "Text" ? plainTextContent(child) : null;
|
|
92
|
+
if (inlineText !== null) {
|
|
93
|
+
textBuffer += inlineText;
|
|
94
|
+
hasText = true;
|
|
95
|
+
} else {
|
|
96
|
+
for (const [k, el] of Object.entries(child.elements)) mergedElements[k] = el;
|
|
97
|
+
childKeys.push(child.root);
|
|
98
|
+
hasElementChildren = true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
mergedElements,
|
|
104
|
+
childKeys,
|
|
105
|
+
textBuffer,
|
|
106
|
+
hasText,
|
|
107
|
+
hasElementChildren
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* True when `type` is a third-party composition wrapper to elide from a
|
|
112
|
+
* captured render spec. A UDS component (carries `__componentName`), a
|
|
113
|
+
* `Fragment`, and an intrinsic tag (passed as a string) are real anatomy and
|
|
114
|
+
* never elided. Among the rest, a node with a `render` target (the
|
|
115
|
+
* ariakit/Radix `asChild` pattern) or with meaningful children is plumbing
|
|
116
|
+
* that wraps real content; a node with neither is a genuine visual leaf (an
|
|
117
|
+
* icon) and stays. Caller gates this on render-extraction scope.
|
|
118
|
+
*/
|
|
119
|
+
function isElidableWrapper(type, restProps, childList) {
|
|
120
|
+
if (type === Fragment) return false;
|
|
121
|
+
if (typeof type !== "object" && typeof type !== "function") return false;
|
|
122
|
+
if (typeof type.__componentName === "string") return false;
|
|
123
|
+
const hasRenderTarget = isSpec(restProps.render);
|
|
124
|
+
const hasMeaningfulChildren = childList.some((c) => c !== null && c !== void 0 && typeof c !== "boolean");
|
|
125
|
+
return hasRenderTarget || hasMeaningfulChildren;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Collapse an elided wrapper into its real content. With a `render` target
|
|
129
|
+
* (ariakit/Radix `asChild`), the wrapper renders *as* that UDS element, so we
|
|
130
|
+
* surface the target as the node and fold the wrapper's own children into it —
|
|
131
|
+
* faithful to how those libraries compose. Without one (a pure context
|
|
132
|
+
* provider like ariakit's `MenuProvider`), it collapses to a `Fragment` so its
|
|
133
|
+
* children render through. Either way no foreign type reaches the spec.
|
|
134
|
+
*/
|
|
135
|
+
function elideWrapper(renderValue, childList) {
|
|
136
|
+
const { mergedElements, childKeys, textBuffer, hasText, hasElementChildren } = collectChildren(childList, "");
|
|
137
|
+
if (isSpec(renderValue)) {
|
|
138
|
+
const elements = {
|
|
139
|
+
...renderValue.elements,
|
|
140
|
+
...mergedElements
|
|
141
|
+
};
|
|
142
|
+
const target = elements[renderValue.root];
|
|
143
|
+
const foldedChildren = [...target.children ?? [], ...childKeys];
|
|
144
|
+
const updated = { ...target };
|
|
145
|
+
if (foldedChildren.length > 0) updated.children = foldedChildren;
|
|
146
|
+
if (hasText && !hasElementChildren) updated.props = {
|
|
147
|
+
...target.props,
|
|
148
|
+
children: textBuffer
|
|
149
|
+
};
|
|
150
|
+
elements[renderValue.root] = updated;
|
|
151
|
+
return {
|
|
152
|
+
root: renderValue.root,
|
|
153
|
+
elements
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
const element = {
|
|
157
|
+
type: "Fragment",
|
|
158
|
+
props: {}
|
|
159
|
+
};
|
|
160
|
+
if (hasElementChildren) element.children = childKeys;
|
|
161
|
+
if (hasText && !hasElementChildren) element.props = { children: textBuffer };
|
|
162
|
+
const key = nextKey();
|
|
163
|
+
mergedElements[key] = element;
|
|
164
|
+
return {
|
|
165
|
+
root: key,
|
|
166
|
+
elements: mergedElements
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Inline a dynamically-resolved leaf component into a captured render spec.
|
|
171
|
+
* Icon's `.render()` picks a glyph by name (`const Glyph = UdsIcons[name]`) and
|
|
172
|
+
* mounts `<Glyph .../>`; the glyph is a plain function component, so it would
|
|
173
|
+
* otherwise be stamped a synthetic `<scope>:<base>:<n>` type nothing resolves —
|
|
174
|
+
* it isn't registered, and a dynamic namespace lookup can't be traced to a
|
|
175
|
+
* `foreign:` import. Invoking it here (it returns a `Spec` through this same
|
|
176
|
+
* runtime, since the captured module is compiled against it) splices its real
|
|
177
|
+
* output — the `<path>` subtree — into the spec, so the Internals view paints
|
|
178
|
+
* the actual glyph instead of a blank node.
|
|
179
|
+
*
|
|
180
|
+
* Render-extraction only (gated by the caller on `renderScope`), and
|
|
181
|
+
* best-effort: a function that throws when invoked outside React (hooks,
|
|
182
|
+
* context) or returns a non-`Spec` (a context provider returning `null`, a
|
|
183
|
+
* glyph with no matching variant) yields `null`, and the caller falls back to
|
|
184
|
+
* the synthetic type — no worse than today.
|
|
185
|
+
*/
|
|
186
|
+
function tryInlineDynamicLeaf(type, props) {
|
|
187
|
+
if (typeof type !== "function") return null;
|
|
188
|
+
const named = type;
|
|
189
|
+
if (typeof named.__componentName === "string") return null;
|
|
190
|
+
let base = "";
|
|
191
|
+
if (typeof named.displayName === "string" && named.displayName.length > 0) base = named.displayName;
|
|
192
|
+
else if (typeof named.name === "string" && named.name.length > 0) base = named.name;
|
|
193
|
+
if (TRANSPARENT_WRAPPERS.has(base)) return null;
|
|
194
|
+
try {
|
|
195
|
+
const result = type(props);
|
|
196
|
+
return isSpec(result) ? result : null;
|
|
197
|
+
} catch {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function buildSpec(type, props) {
|
|
202
|
+
const { children, ...restProps } = props;
|
|
203
|
+
const childList = normalizeChildren(children);
|
|
204
|
+
if (renderScope !== null && isElidableWrapper(type, restProps, childList)) return elideWrapper(restProps.render, childList);
|
|
205
|
+
if (renderScope !== null) {
|
|
206
|
+
const inlined = tryInlineDynamicLeaf(type, props);
|
|
207
|
+
if (inlined) return inlined;
|
|
208
|
+
}
|
|
209
|
+
const typeName = resolveTypeName(type);
|
|
210
|
+
const collected = collectChildren(childList, typeName);
|
|
211
|
+
const { mergedElements } = collected;
|
|
212
|
+
const { childKeys, textBuffer, hasText } = collected;
|
|
213
|
+
let { hasElementChildren } = collected;
|
|
214
|
+
const elementProps = { ...restProps };
|
|
215
|
+
if (hasText && !hasElementChildren) elementProps.children = textBuffer;
|
|
216
|
+
for (const [propName, value] of Object.entries(elementProps)) {
|
|
217
|
+
if (isSpec(value)) {
|
|
218
|
+
for (const [k, el] of Object.entries(value.elements)) mergedElements[k] = el;
|
|
219
|
+
childKeys.push(value.root);
|
|
220
|
+
hasElementChildren = true;
|
|
221
|
+
elementProps[propName] = { $slot: value.root };
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (Array.isArray(value) && value.length > 0 && value.every(isSpec)) {
|
|
225
|
+
const refs = [];
|
|
226
|
+
for (const spec of value) {
|
|
227
|
+
for (const [k, el] of Object.entries(spec.elements)) mergedElements[k] = el;
|
|
228
|
+
childKeys.push(spec.root);
|
|
229
|
+
refs.push(spec.root);
|
|
230
|
+
}
|
|
231
|
+
hasElementChildren = true;
|
|
232
|
+
elementProps[propName] = { $slot: refs };
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (childKeys.length === 1 && mergedElements[childKeys[0]]?.type === "Slot") elementProps.children = { $slot: childKeys[0] };
|
|
236
|
+
const element = {
|
|
237
|
+
type: typeName,
|
|
238
|
+
props: elementProps
|
|
239
|
+
};
|
|
240
|
+
if (hasElementChildren) element.children = childKeys;
|
|
241
|
+
const key = nextKey();
|
|
242
|
+
mergedElements[key] = element;
|
|
243
|
+
return {
|
|
244
|
+
root: key,
|
|
245
|
+
elements: mergedElements
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function normalizeChildren(children) {
|
|
249
|
+
if (children === void 0 || children === null) return [];
|
|
250
|
+
if (Array.isArray(children)) return children.flat(Number.POSITIVE_INFINITY);
|
|
251
|
+
return [children];
|
|
252
|
+
}
|
|
253
|
+
function resolveTypeName(type) {
|
|
254
|
+
if (type === Fragment) return "Fragment";
|
|
255
|
+
if (typeof type === "string") return type;
|
|
256
|
+
const isObjectOrFn = type !== null && (typeof type === "object" || typeof type === "function");
|
|
257
|
+
if (isObjectOrFn) {
|
|
258
|
+
const named = type;
|
|
259
|
+
if (typeof named.__componentName === "string") return named.__componentName;
|
|
260
|
+
}
|
|
261
|
+
const foreign = foreignComponentName(type);
|
|
262
|
+
if (foreign !== null) return `foreign:${foreign}`;
|
|
263
|
+
if (typeof type === "function") {
|
|
264
|
+
const fn = type;
|
|
265
|
+
let base = null;
|
|
266
|
+
if (typeof fn.displayName === "string" && fn.displayName.length > 0) base = fn.displayName;
|
|
267
|
+
else if (typeof fn.name === "string" && fn.name.length > 0) base = fn.name;
|
|
268
|
+
if (base !== null) {
|
|
269
|
+
if (TRANSPARENT_WRAPPERS.has(base)) return "Fragment";
|
|
270
|
+
if (renderScope === null) return base;
|
|
271
|
+
return `${renderScope}:${base}:${wrapperCounter++}`;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (isObjectOrFn) {
|
|
275
|
+
const id = nextRefId();
|
|
276
|
+
pendingRefs.set(id, type);
|
|
277
|
+
return id;
|
|
278
|
+
}
|
|
279
|
+
return "Unknown";
|
|
280
|
+
}
|
|
281
|
+
function isSpec(value) {
|
|
282
|
+
if (typeof value !== "object" || value === null) return false;
|
|
283
|
+
const candidate = value;
|
|
284
|
+
return typeof candidate.root === "string" && typeof candidate.elements === "object" && candidate.elements !== null;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* If `spec` is a self-contained `Text` node carrying only string content,
|
|
288
|
+
* return that string; otherwise `null`. This is the shape the extractor
|
|
289
|
+
* synthesises for a string/number slot default. A real authored text layer
|
|
290
|
+
* carries `data-uds-layer` (and is never collapsed); the synthetic slot node
|
|
291
|
+
* never does, so absence of that marker — plus a single element whose only
|
|
292
|
+
* prop is the string `children` — identifies it precisely.
|
|
293
|
+
*/
|
|
294
|
+
function plainTextContent(spec) {
|
|
295
|
+
if (Object.keys(spec.elements).length !== 1) return null;
|
|
296
|
+
const el = spec.elements[spec.root];
|
|
297
|
+
if (!el || el.type !== "Text") return null;
|
|
298
|
+
if (el.children && el.children.length > 0) return null;
|
|
299
|
+
const props = el.props ?? {};
|
|
300
|
+
if (typeof props.children !== "string") return null;
|
|
301
|
+
if (Object.keys(props).some((k) => k !== "children")) return null;
|
|
302
|
+
return props.children;
|
|
303
|
+
}
|
|
304
|
+
//#endregion
|
|
305
|
+
export { Fragment, __drainPendingRefs, __resetKeyCounterForTesting, getConfigContext, jsx, jsxs, setConfigContext, setRenderExtractionContext };
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { AssetGroupRef } from "./refs.js";
|
|
2
|
+
import { ComponentDefinition } from "./types.js";
|
|
3
|
+
|
|
4
|
+
//#region src/markers.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* A slot's `.accepts(...)` argument: a registered component definition, or a
|
|
7
|
+
* placeable asset group returned by `defineAssetGroup(...).config(...)` (it
|
|
8
|
+
* carries the `AssetGroupRef` tag). The two are kept distinct downstream —
|
|
9
|
+
* component names land on `SlotInfo.accepts`, the asset-group slug on
|
|
10
|
+
* `SlotInfo.acceptsAssetGroup` — so the designer panel can pick the right
|
|
11
|
+
* picker. Non-placeable groups (fonts) are admitted by the type but rejected
|
|
12
|
+
* at config load.
|
|
13
|
+
*/
|
|
14
|
+
type SlotAccepts = ComponentDefinition | AssetGroupRef;
|
|
15
|
+
/**
|
|
16
|
+
* Brand applied to a marker by `.required()`. Lives alongside the
|
|
17
|
+
* marker interfaces so the slot factories (whose `.required()`
|
|
18
|
+
* implementation is co-located with `.accepts()` rather than going
|
|
19
|
+
* through `attachRequired`) can return the brand-narrowed type via
|
|
20
|
+
* the interface signature.
|
|
21
|
+
*
|
|
22
|
+
* `RenderPropsFromConfig` reads this brand to decide whether a render-
|
|
23
|
+
* fn destructure entry is optional (`T | undefined`) or non-optional
|
|
24
|
+
* (`T`). Distinct from `__required?: boolean` on the marker bodies —
|
|
25
|
+
* that field is the runtime flag codegen reads; the brand is the
|
|
26
|
+
* compile-time signal the render-arg type-flow keys on.
|
|
27
|
+
*/
|
|
28
|
+
type RequiredBrand = {
|
|
29
|
+
__required: true;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Author-declared slot value kind. A slot holds renderable content; the only
|
|
33
|
+
* explicit kind is text:
|
|
34
|
+
*
|
|
35
|
+
* - `'string'` — plain text content (e.g. Button's `children` label).
|
|
36
|
+
*
|
|
37
|
+
* An open `slot()` is a node container (`ReactNode`) by default — it accepts
|
|
38
|
+
* dropped layers and is narrowed to specific components via `.accepts(...)`;
|
|
39
|
+
* `'string'` instead marks a text surface, so tools like the Studio canvas
|
|
40
|
+
* inline-edit it rather than treat it as a reparent target. Scalars like
|
|
41
|
+
* boolean and number are *not* slots — use the dedicated `bool()` / `number()`
|
|
42
|
+
* markers. (A `'string'` slot still *resolves* to `SlotValueKind: 'ReactNode'`,
|
|
43
|
+
* since a string is a valid `ReactNode`; `authoredType` records the intent.)
|
|
44
|
+
*
|
|
45
|
+
* - `'component'` — the slot resolves to a `FunctionComponent`, not rendered
|
|
46
|
+
* content. Used by the aliased `Icon` pattern (`name: slot({ type:
|
|
47
|
+
* 'component' }).accepts(icons)`), where the render fn receives the icon
|
|
48
|
+
* component itself (`({ name: SvgIcon }) => <SvgIcon … />`) and the saved
|
|
49
|
+
* value is the inline asset-name string (`"Trophy"`), not a `$slot` ref.
|
|
50
|
+
* A `'component'` slot *requires* an asset-group `.accepts(...)` — config
|
|
51
|
+
* load throws otherwise.
|
|
52
|
+
*/
|
|
53
|
+
type SlotValueType = 'string' | 'component';
|
|
54
|
+
/**
|
|
55
|
+
* Open-slot marker — `slot()` with no arguments. Codegen treats it as
|
|
56
|
+
* `ReactNode` accepted at the component's own children. Carries no
|
|
57
|
+
* cross-reference; `__accepts` / `__required` may still be set via the
|
|
58
|
+
* chain methods to constrain the slot's children or mark it required.
|
|
59
|
+
* `__valueType` records an explicit `slot({ type })` override (absent ⇒
|
|
60
|
+
* the default `ReactNode`).
|
|
61
|
+
*/
|
|
62
|
+
interface SlotMarker {
|
|
63
|
+
readonly __kind: 'slot';
|
|
64
|
+
readonly __required?: boolean;
|
|
65
|
+
readonly __accepts?: readonly SlotAccepts[];
|
|
66
|
+
readonly __valueType?: SlotValueType;
|
|
67
|
+
/**
|
|
68
|
+
* Stamp `__required: true` on the marker. Codegen reads this per-prop
|
|
69
|
+
* and emits the JSX prop without a trailing `?`, so the slot becomes
|
|
70
|
+
* mandatory at call sites. The return type also intersects
|
|
71
|
+
* `RequiredBrand` so `RenderPropsFromConfig` narrows the render-fn
|
|
72
|
+
* destructure entry to non-optional.
|
|
73
|
+
*/
|
|
74
|
+
required(): SlotMarker & RequiredBrand;
|
|
75
|
+
/**
|
|
76
|
+
* Constrain the slot's accepted children to one or more registered
|
|
77
|
+
* components, or to a placeable asset group (`slot().accepts(icons)`).
|
|
78
|
+
*/
|
|
79
|
+
accepts(component: SlotAccepts | readonly SlotAccepts[]): SlotMarker;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* A `slot({ type: 'component' })` marker — the aliased `Icon` pattern. Carries
|
|
83
|
+
* the literal `__valueType: 'component'` so `ResolveMarker` resolves the prop
|
|
84
|
+
* to a `ComponentType` (the render fn receives the icon component itself), and
|
|
85
|
+
* narrows `.accepts(...)` to asset groups only (a component-typed slot must
|
|
86
|
+
* accept an asset group). The chained `.accepts(...)` preserves this type so
|
|
87
|
+
* the literal survives to the render-fn inference.
|
|
88
|
+
*/
|
|
89
|
+
interface ComponentSlotMarker extends SlotMarker {
|
|
90
|
+
readonly __valueType: 'component';
|
|
91
|
+
accepts(group: AssetGroupRef | readonly AssetGroupRef[]): ComponentSlotMarker;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Layer-targeting slot ref — `slot('layer')`, `slot('layer/prop')`, or
|
|
95
|
+
* `slot('layer', { prop })`. Routes a JSX prop into the named layer's
|
|
96
|
+
* `layerProp` (defaults to `'children'` when only a layer is given).
|
|
97
|
+
* The `layer` field is the cross-reference — that's what makes this a
|
|
98
|
+
* Ref rather than a Marker.
|
|
99
|
+
*/
|
|
100
|
+
interface SlotRef<TLayer extends string = string, TAs extends string = string> {
|
|
101
|
+
readonly __kind: 'slot';
|
|
102
|
+
readonly layer: TLayer;
|
|
103
|
+
readonly layerProp: TAs;
|
|
104
|
+
readonly __required?: boolean;
|
|
105
|
+
readonly __accepts?: readonly SlotAccepts[];
|
|
106
|
+
/** Output adapter set via `.transform(fn)` — codegen wraps the
|
|
107
|
+
* layer's prop so the consumer-facing handler receives `fn(arg)`
|
|
108
|
+
* instead of the raw layer value (e.g. an input event → its
|
|
109
|
+
* string value). Must be self-contained (no closure over outer
|
|
110
|
+
* scope) since codegen lifts it into the generated module. */
|
|
111
|
+
readonly __transform?: (arg: never) => unknown;
|
|
112
|
+
readonly __valueType?: SlotValueType;
|
|
113
|
+
required(): SlotRef<TLayer, TAs> & RequiredBrand;
|
|
114
|
+
accepts(component: SlotAccepts | readonly SlotAccepts[]): SlotRef<TLayer, TAs>;
|
|
115
|
+
transform<Out>(fn: (arg: unknown) => Out): SlotRef<TLayer, TAs> & {
|
|
116
|
+
readonly __transformOut: Out;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Runtime guard for any slot binding (open marker or layered ref).
|
|
121
|
+
* Callers that need to distinguish the two forms narrow further by
|
|
122
|
+
* checking for the `layer` field — `'layer' in value`.
|
|
123
|
+
*/
|
|
124
|
+
declare function isSlotMarker(value: unknown): value is SlotMarker | SlotRef;
|
|
125
|
+
interface BooleanMarker {
|
|
126
|
+
readonly __kind: 'boolean';
|
|
127
|
+
readonly __required?: boolean;
|
|
128
|
+
readonly values?: {
|
|
129
|
+
true?: Record<string, Record<string, unknown>>;
|
|
130
|
+
false?: Record<string, Record<string, unknown>>;
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
declare function isBoolMarker(value: unknown): value is BooleanMarker;
|
|
134
|
+
interface VariantMarkerObject<V extends Record<string, Record<string, unknown>> = Record<string, Record<string, unknown>>> {
|
|
135
|
+
readonly __kind: 'variant';
|
|
136
|
+
readonly __required?: boolean;
|
|
137
|
+
readonly values: V;
|
|
138
|
+
readonly default?: keyof V & string;
|
|
139
|
+
}
|
|
140
|
+
interface VariantMarkerArray<V extends readonly (string | number)[] = readonly (string | number)[]> {
|
|
141
|
+
readonly __kind: 'variant';
|
|
142
|
+
readonly __required?: boolean;
|
|
143
|
+
readonly values: V;
|
|
144
|
+
readonly default?: V[number];
|
|
145
|
+
}
|
|
146
|
+
type VariantMarker<V = unknown> = V extends readonly (string | number)[] ? VariantMarkerArray<V> : V extends Record<string, Record<string, unknown>> ? VariantMarkerObject<V> : VariantMarkerObject | VariantMarkerArray;
|
|
147
|
+
declare function isVariantMarker(value: unknown): value is VariantMarker;
|
|
148
|
+
/**
|
|
149
|
+
* Distinguish the two variant forms. `Array.isArray(marker.values)` is the
|
|
150
|
+
* single source of truth — every downstream consumer that branches on
|
|
151
|
+
* the form goes through this helper rather than duplicating the check.
|
|
152
|
+
*/
|
|
153
|
+
declare function isVariantArrayMarker(value: VariantMarker): value is VariantMarkerArray;
|
|
154
|
+
interface StringMarker {
|
|
155
|
+
readonly __kind: 'string';
|
|
156
|
+
readonly __required?: boolean;
|
|
157
|
+
}
|
|
158
|
+
interface NumberMarker {
|
|
159
|
+
readonly __kind: 'number';
|
|
160
|
+
readonly __required?: boolean;
|
|
161
|
+
}
|
|
162
|
+
declare function isStringMarker(value: unknown): value is StringMarker;
|
|
163
|
+
declare function isNumberMarker(value: unknown): value is NumberMarker;
|
|
164
|
+
interface LayerMarker {
|
|
165
|
+
readonly __kind: 'layer';
|
|
166
|
+
readonly layer: string;
|
|
167
|
+
readonly styles: Record<string, unknown>;
|
|
168
|
+
}
|
|
169
|
+
declare function isLayerMarker(value: unknown): value is LayerMarker;
|
|
170
|
+
/**
|
|
171
|
+
* One conditional override for a `props` axis: apply `props` to the cell
|
|
172
|
+
* when every key in `when` matches the cell's other-axis values. A rule
|
|
173
|
+
* with no `when` always applies (the base). Later matching rules win.
|
|
174
|
+
*/
|
|
175
|
+
interface PreviewPropsRule {
|
|
176
|
+
readonly when?: Readonly<Record<string, unknown>>;
|
|
177
|
+
readonly props: Readonly<Record<string, unknown>>;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Synthetic discriminator state a `props` axis compiles to, per axis side.
|
|
181
|
+
* The entry's label is the value. Codegen keys the merged spec's `$cond`
|
|
182
|
+
* on this, and the studio seeds it per cell — both derive it here so they
|
|
183
|
+
* never drift. (`columns`/`rows` entries are concatenated as sibling
|
|
184
|
+
* values of one dimension, so one key per side suffices.)
|
|
185
|
+
*/
|
|
186
|
+
declare const PREVIEW_SEED_KEY: {
|
|
187
|
+
readonly row: "__previewSeedRow";
|
|
188
|
+
readonly column: "__previewSeedCol";
|
|
189
|
+
};
|
|
190
|
+
/** True when every key in `when` equals the cell coordinate's value. */
|
|
191
|
+
declare function matchesPreviewWhen(when: Readonly<Record<string, unknown>> | undefined, coord: Readonly<Record<string, unknown>>): boolean;
|
|
192
|
+
/**
|
|
193
|
+
* Merge the `props` of every rule whose `when` matches `coord` (in order,
|
|
194
|
+
* so later matching rules win). Shared by codegen's combo enumeration and
|
|
195
|
+
* the studio's cell assembly so a `props` axis resolves identically.
|
|
196
|
+
*/
|
|
197
|
+
declare function resolvePreviewRules(rules: readonly PreviewPropsRule[], coord: Readonly<Record<string, unknown>>): Record<string, unknown>;
|
|
198
|
+
interface PreviewAxisMarker {
|
|
199
|
+
readonly __kind: 'previewAxis';
|
|
200
|
+
/** Axis name — either a prop name or a `_${string}` modifier. */
|
|
201
|
+
readonly prop?: string;
|
|
202
|
+
readonly modifier?: string;
|
|
203
|
+
/**
|
|
204
|
+
* `props` axis rules — per-cell prop-override bags, optionally guarded
|
|
205
|
+
* by `when` against the other axes' values. Lets a preview vary
|
|
206
|
+
* render-extra data per cell (e.g. sample `value`) without declaring a
|
|
207
|
+
* config prop. Resolved against the cell coordinate by the studio and
|
|
208
|
+
* by codegen's combo enumeration.
|
|
209
|
+
*/
|
|
210
|
+
readonly rules?: readonly PreviewPropsRule[];
|
|
211
|
+
readonly kind: 'prop' | 'modifier' | 'props';
|
|
212
|
+
readonly nested?: PreviewAxisMarker;
|
|
213
|
+
nest(child: PreviewAxisMarker): PreviewAxisMarker;
|
|
214
|
+
}
|
|
215
|
+
declare function isPreviewAxisMarker(value: unknown): value is PreviewAxisMarker;
|
|
216
|
+
//#endregion
|
|
217
|
+
export { BooleanMarker, ComponentSlotMarker, LayerMarker, NumberMarker, PREVIEW_SEED_KEY, PreviewAxisMarker, PreviewPropsRule, RequiredBrand, SlotMarker, SlotRef, SlotValueType, StringMarker, VariantMarker, VariantMarkerArray, VariantMarkerObject, isBoolMarker, isLayerMarker, isNumberMarker, isPreviewAxisMarker, isSlotMarker, isStringMarker, isVariantArrayMarker, isVariantMarker, matchesPreviewWhen, resolvePreviewRules };
|
package/dist/markers.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
//#region src/markers.ts
|
|
2
|
+
/**
|
|
3
|
+
* Runtime guard for any slot binding (open marker or layered ref).
|
|
4
|
+
* Callers that need to distinguish the two forms narrow further by
|
|
5
|
+
* checking for the `layer` field — `'layer' in value`.
|
|
6
|
+
*/
|
|
7
|
+
function isSlotMarker(value) {
|
|
8
|
+
return typeof value === "object" && value !== null && value.__kind === "slot";
|
|
9
|
+
}
|
|
10
|
+
function isBoolMarker(value) {
|
|
11
|
+
return typeof value === "object" && value !== null && value.__kind === "boolean";
|
|
12
|
+
}
|
|
13
|
+
function isVariantMarker(value) {
|
|
14
|
+
if (typeof value !== "object" || value === null) return false;
|
|
15
|
+
const v = value;
|
|
16
|
+
if (v.__kind !== "variant") return false;
|
|
17
|
+
return Array.isArray(v.values) || typeof v.values === "object";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Distinguish the two variant forms. `Array.isArray(marker.values)` is the
|
|
21
|
+
* single source of truth — every downstream consumer that branches on
|
|
22
|
+
* the form goes through this helper rather than duplicating the check.
|
|
23
|
+
*/
|
|
24
|
+
function isVariantArrayMarker(value) {
|
|
25
|
+
return Array.isArray(value.values);
|
|
26
|
+
}
|
|
27
|
+
function isStringMarker(value) {
|
|
28
|
+
return typeof value === "object" && value !== null && value.__kind === "string";
|
|
29
|
+
}
|
|
30
|
+
function isNumberMarker(value) {
|
|
31
|
+
return typeof value === "object" && value !== null && value.__kind === "number";
|
|
32
|
+
}
|
|
33
|
+
function isLayerMarker(value) {
|
|
34
|
+
return typeof value === "object" && value !== null && value.__kind === "layer";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Synthetic discriminator state a `props` axis compiles to, per axis side.
|
|
38
|
+
* The entry's label is the value. Codegen keys the merged spec's `$cond`
|
|
39
|
+
* on this, and the studio seeds it per cell — both derive it here so they
|
|
40
|
+
* never drift. (`columns`/`rows` entries are concatenated as sibling
|
|
41
|
+
* values of one dimension, so one key per side suffices.)
|
|
42
|
+
*/
|
|
43
|
+
const PREVIEW_SEED_KEY = {
|
|
44
|
+
row: "__previewSeedRow",
|
|
45
|
+
column: "__previewSeedCol"
|
|
46
|
+
};
|
|
47
|
+
/** True when every key in `when` equals the cell coordinate's value. */
|
|
48
|
+
function matchesPreviewWhen(when, coord) {
|
|
49
|
+
if (!when) return true;
|
|
50
|
+
for (const key of Object.keys(when)) if (coord[key] !== when[key]) return false;
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Merge the `props` of every rule whose `when` matches `coord` (in order,
|
|
55
|
+
* so later matching rules win). Shared by codegen's combo enumeration and
|
|
56
|
+
* the studio's cell assembly so a `props` axis resolves identically.
|
|
57
|
+
*/
|
|
58
|
+
function resolvePreviewRules(rules, coord) {
|
|
59
|
+
const out = {};
|
|
60
|
+
for (const rule of rules) if (matchesPreviewWhen(rule.when, coord)) Object.assign(out, rule.props);
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
function isPreviewAxisMarker(value) {
|
|
64
|
+
return typeof value === "object" && value !== null && value.__kind === "previewAxis";
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
export { PREVIEW_SEED_KEY, isBoolMarker, isLayerMarker, isNumberMarker, isPreviewAxisMarker, isSlotMarker, isStringMarker, isVariantArrayMarker, isVariantMarker, matchesPreviewWhen, resolvePreviewRules };
|