@yahoo/uds-create-config 5.76.0 → 5.77.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.
|
@@ -1,19 +1,59 @@
|
|
|
1
1
|
import { isRef, pathOf } from "../framework/utils/refs.js";
|
|
2
2
|
import { className, renderStyleValue, resolveComponentProps, resolveTokenValue, stylePropEntries } from "../framework/projections.js";
|
|
3
3
|
import { intoName, routesContent, routesIntoText } from "../framework/prop-surface.js";
|
|
4
|
-
import { componentLayerClass, componentRuleClasses, stylePropClasses } from "../framework/class-names.js";
|
|
4
|
+
import { arbitraryClassName, componentLayerClass, componentRuleClasses, stylePropClasses } from "../framework/class-names.js";
|
|
5
5
|
//#region src/capture/class-grammar.ts
|
|
6
6
|
const VIEWPORT_UNIT = /\d(vh|vw|dvh|dvw|svh|svw|lvh|lvw|vmin|vmax)\b/;
|
|
7
7
|
/** `0px` → `0`, collapsed spaces, lowercase keywords; what two spellings of one value share. */
|
|
8
|
+
/** CSS properties whose value is a colour. */
|
|
9
|
+
const COLOR_PROPERTY = /(^|-)(color|fill|stroke)$|^background$/;
|
|
10
|
+
/** Whether an off-scale value is a colour (`#f00`, `rgb(…)`, a named colour), not a length or a number. */
|
|
11
|
+
function isColorValue(value) {
|
|
12
|
+
const v = value.trim().toLowerCase();
|
|
13
|
+
if (/^(#|rgba?\(|hsla?\(|oklch\(|oklab\(|lab\(|lch\(|color\(|color-mix\()/.test(v)) return true;
|
|
14
|
+
if (/^(color|colour):/.test(v)) return true;
|
|
15
|
+
if (/^[-\d.]/.test(v) || /^(calc|min|max|clamp|var)\(/.test(v)) return false;
|
|
16
|
+
return /^[a-z]+$/.test(v) && v !== "auto" && v !== "none";
|
|
17
|
+
}
|
|
8
18
|
function normalizeCssValue(value) {
|
|
9
19
|
return value.trim().replace(/\s+/g, " ").replace(/(^|[\s,(])0(?:px|rem|em|%)(?=$|[\s,)])/g, "$10").toLowerCase();
|
|
10
20
|
}
|
|
11
21
|
function classGrammar(config) {
|
|
12
22
|
const styleProps = /* @__PURE__ */ new Map();
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
leaf
|
|
16
|
-
|
|
23
|
+
const arbitraryStems = /* @__PURE__ */ new Map();
|
|
24
|
+
for (const entity of config.list("style-property")) {
|
|
25
|
+
for (const [leaf, cls] of stylePropClasses(config, entity.path)) if (!styleProps.has(cls)) styleProps.set(cls, {
|
|
26
|
+
path: entity.path,
|
|
27
|
+
leaf
|
|
28
|
+
});
|
|
29
|
+
if (entity.toJSON().arbitrary) {
|
|
30
|
+
const stem = arbitraryClassName({
|
|
31
|
+
config,
|
|
32
|
+
path: entity.path,
|
|
33
|
+
value: "[x]"
|
|
34
|
+
}).slice(0, -3);
|
|
35
|
+
arbitraryStems.set(stem, [...arbitraryStems.get(stem) ?? [], entity.path]);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const arbitraryMatch = (cls) => {
|
|
39
|
+
const open = cls.indexOf("[");
|
|
40
|
+
if (open <= 0) return void 0;
|
|
41
|
+
const close = cls.indexOf("]", open);
|
|
42
|
+
if (close === -1) return void 0;
|
|
43
|
+
const rest = cls.slice(close + 1);
|
|
44
|
+
if (rest !== "" && !/^\/(?:\[[^\]]+\]|[\w.-]+)$/.test(rest)) return void 0;
|
|
45
|
+
const paths = arbitraryStems.get(cls.slice(0, open)) ?? [];
|
|
46
|
+
const inner = cls.slice(open + 1, close);
|
|
47
|
+
if (!inner || paths.length === 0) return void 0;
|
|
48
|
+
return {
|
|
49
|
+
path: paths.length === 1 ? paths[0] : paths.find((each) => writesColor(each) === isColorValue(inner)) ?? paths[0],
|
|
50
|
+
leaf: `[${inner}]`
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
function writesColor(path) {
|
|
54
|
+
const { properties = [] } = config.resolve("style-property", path)?.toJSON() ?? {};
|
|
55
|
+
return properties.some((property) => COLOR_PROPERTY.test(property));
|
|
56
|
+
}
|
|
17
57
|
const composites = config.list("composite").map((entity) => ({
|
|
18
58
|
path: entity.path,
|
|
19
59
|
cls: className(config, "composite", entity.path)
|
|
@@ -126,7 +166,7 @@ function classGrammar(config) {
|
|
|
126
166
|
};
|
|
127
167
|
};
|
|
128
168
|
return {
|
|
129
|
-
styleProp: (cls) => styleProps.get(cls),
|
|
169
|
+
styleProp: (cls) => styleProps.get(cls) ?? arbitraryMatch(cls),
|
|
130
170
|
stylePropsFor: (cssProperty) => byCss.get(cssProperty.toLowerCase()) ?? [],
|
|
131
171
|
viewportLeaf(path, leaf) {
|
|
132
172
|
return (valuesOf(path).get(leaf) ?? []).some((v) => VIEWPORT_UNIT.test(v));
|
|
@@ -2183,7 +2183,7 @@ const ComponentEntity = defineEntity({
|
|
|
2183
2183
|
input: z.object({ path: pathInput("component") }),
|
|
2184
2184
|
readOnly: false,
|
|
2185
2185
|
label: "Create blank",
|
|
2186
|
-
description: "Create an empty component at a new qualified `path`, to design on the canvas first: one `div` root layer and the node that renders it, with no props, no variants, no slot, no styles and no preview content. This is exactly what
|
|
2186
|
+
description: "Create an empty component at a new qualified `path`, to design on the canvas first: one `div` root layer and the node that renders it, with no props, no variants, no slot, no styles and no preview content. This is exactly what Create's \"+\" creates. Takes only `path`. Use it for \"a new component\", \"a blank component\" or \"start a component from nothing\"; `create` is for a component whose body is already known.",
|
|
2187
2187
|
scope: "item",
|
|
2188
2188
|
creates: true,
|
|
2189
2189
|
title: (entity) => `Create blank ${entity}`,
|
|
@@ -2202,7 +2202,7 @@ const ComponentEntity = defineEntity({
|
|
|
2202
2202
|
example: ({ config }) => forwardsCreateExample(config)
|
|
2203
2203
|
},
|
|
2204
2204
|
"sub-upsert/forwards": { description: `Set what one layer forwards, added when absent and replaced whole when present. ${FORWARDS_DESCRIPTION}` },
|
|
2205
|
-
"sub-update/forwards": { description: `Replace what one layer forwards: the member is
|
|
2205
|
+
"sub-update/forwards": { description: `Replace what one layer forwards: the member is a list of prop names, so \`data\` is the whole new list. ${FORWARDS_DESCRIPTION}` },
|
|
2206
2206
|
/**
|
|
2207
2207
|
* Add an element to a composition — a layer and the node that targets it, together.
|
|
2208
2208
|
*
|
|
@@ -2500,7 +2500,7 @@ count: z.number().int().min(1).max(50).optional() }).prefault({})
|
|
|
2500
2500
|
}),
|
|
2501
2501
|
readOnly: false,
|
|
2502
2502
|
label: "Forward layer props",
|
|
2503
|
-
description: "Expose a layer's props at the component's top level (\"forward
|
|
2503
|
+
description: "Expose a layer's props at the component's top level (\"also forward width\", \"forward onClick from the root\"): `props` is a list of prop names, added to what the layer forwards now, or replacing it with `replace`. A prop the element lacks, one the component declares itself, and one a sibling layer already forwards are refused. Read `component/get` for what a layer forwards now.",
|
|
2504
2504
|
scope: "item",
|
|
2505
2505
|
title: (entity) => `Forward ${entity} layer props`,
|
|
2506
2506
|
handler: (input, config) => {
|
|
@@ -14,7 +14,7 @@ import { z } from "zod";
|
|
|
14
14
|
* non-serializable projection (a zod schema, a function). Each fn declares its own provenance.
|
|
15
15
|
*
|
|
16
16
|
* A derived kind self-derives on registration, sourcing from the config it's registered into;
|
|
17
|
-
* `Config.register` routes it by whether the
|
|
17
|
+
* `Config.register` routes it by whether the kind is derived.
|
|
18
18
|
*/
|
|
19
19
|
/** What `extend` accepts. Checked at runtime because `extend` is shadowed: an unrecognized key is a
|
|
20
20
|
* typo, or a zod raw shape reaching this method expecting zod's `extend`. Either should say so
|
package/dist/index.js
CHANGED
|
@@ -66,11 +66,11 @@ import { styleSetEdits } from "./entities/system/component-style-set.js";
|
|
|
66
66
|
import { convertLinkedTokenValue, prepareLinkedTokenBody } from "./entities/system/linked-token-values.js";
|
|
67
67
|
import { Token, defineOverride, overrideCondition, overrideKey, overrideKeyModifiers, overrideModifiers } from "./entities/system/Token.js";
|
|
68
68
|
import { Component, SLOT_CODE_FORMS, blankComponentBody, canonicalWhen, forwardedNames, layerRef, ownValues, ownsItsValues, valueRef } from "./entities/system/Component.js";
|
|
69
|
+
import { Icon, iconVariantAs } from "./entities/system/Icon.js";
|
|
70
|
+
import { glyphExportNames, glyphType, iconCategories, iconLibraries, iconLibrary, iconToolLibraries, isDeclaredElementProp, librariesBoundBy, libraryHolding, memberVariantOptions, placedGlyphElement, resolveIconLibraries } from "./entities/system/icon-library.js";
|
|
69
71
|
import { CapturedNode, capturedFromDom, elementFromCaptured } from "./capture/captured-tree.js";
|
|
70
72
|
import { classGrammar } from "./capture/class-grammar.js";
|
|
71
73
|
import { specFromCapture } from "./capture/capture-to-spec.js";
|
|
72
|
-
import { Icon, iconVariantAs } from "./entities/system/Icon.js";
|
|
73
|
-
import { glyphExportNames, glyphType, iconCategories, iconLibraries, iconLibrary, iconToolLibraries, isDeclaredElementProp, librariesBoundBy, libraryHolding, memberVariantOptions, placedGlyphElement, resolveIconLibraries } from "./entities/system/icon-library.js";
|
|
74
74
|
import { glyphSourcesOf, iconResolver, nameIconsInTree } from "./capture/icon-resolver.js";
|
|
75
75
|
import { PLACED_NODE_KEY, specToNodePatches } from "./entities/canvas/node-patches.js";
|
|
76
76
|
import { Device } from "./entities/system/Device.js";
|