@yahoo/uds 3.156.1 → 3.157.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/automated-config/dist/generated/autoVariants.cjs +9 -4
- package/dist/automated-config/dist/generated/autoVariants.d.cts +2 -1
- package/dist/automated-config/dist/generated/autoVariants.d.ts +2 -1
- package/dist/automated-config/dist/generated/autoVariants.js +9 -4
- package/dist/automated-config/dist/generated/generatedConfigs.cjs +3011 -3038
- package/dist/automated-config/dist/generated/generatedConfigs.d.cts +143 -140
- package/dist/automated-config/dist/generated/generatedConfigs.d.ts +143 -140
- package/dist/automated-config/dist/generated/generatedConfigs.js +3011 -3038
- package/dist/automated-config/dist/generated/universalTokensConfigAuto.cjs +1227 -501
- package/dist/automated-config/dist/generated/universalTokensConfigAuto.js +1227 -501
- package/dist/automated-config/dist/properties.cjs +1 -1
- package/dist/automated-config/dist/properties.d.cts +15 -0
- package/dist/automated-config/dist/properties.d.ts +15 -0
- package/dist/automated-config/dist/properties.js +1 -1
- package/dist/automated-config/dist/types/ComponentConfig.d.cts +77 -4
- package/dist/automated-config/dist/types/ComponentConfig.d.ts +77 -4
- package/dist/automated-config/dist/types/ConfigSchema.d.cts +14 -2
- package/dist/automated-config/dist/types/ConfigSchema.d.ts +14 -2
- package/dist/automated-config/dist/types/StateAxis.cjs +90 -0
- package/dist/automated-config/dist/types/StateAxis.d.cts +70 -0
- package/dist/automated-config/dist/types/StateAxis.d.ts +70 -0
- package/dist/automated-config/dist/types/StateAxis.js +84 -0
- package/dist/automated-config/dist/utils/buildConfigSchema.cjs +98 -82
- package/dist/automated-config/dist/utils/buildConfigSchema.d.cts +32 -10
- package/dist/automated-config/dist/utils/buildConfigSchema.d.ts +32 -10
- package/dist/automated-config/dist/utils/buildConfigSchema.js +99 -83
- package/dist/automated-config/dist/utils/canonicalizeStateKey.cjs +32 -0
- package/dist/automated-config/dist/utils/canonicalizeStateKey.d.cts +48 -0
- package/dist/automated-config/dist/utils/canonicalizeStateKey.d.ts +48 -0
- package/dist/automated-config/dist/utils/canonicalizeStateKey.js +31 -0
- package/dist/automated-config/dist/utils/getConfigComponentVariant.d.cts +8 -0
- package/dist/automated-config/dist/utils/getConfigComponentVariant.d.ts +8 -0
- package/dist/automated-config/dist/utils/getConfigVariantProperties.d.cts +3 -3
- package/dist/automated-config/dist/utils/getConfigVariantProperties.d.ts +3 -3
- package/dist/automated-config/dist/utils/getConfigVariantPseudoStates.cjs +12 -5
- package/dist/automated-config/dist/utils/getConfigVariantPseudoStates.d.cts +8 -1
- package/dist/automated-config/dist/utils/getConfigVariantPseudoStates.d.ts +8 -1
- package/dist/automated-config/dist/utils/getConfigVariantPseudoStates.js +12 -5
- package/dist/automated-config/dist/utils/getPaginationControlWidthPx.cjs +1 -1
- package/dist/automated-config/dist/utils/getPaginationControlWidthPx.js +1 -1
- package/dist/automated-config/dist/utils/index.cjs +407 -97
- package/dist/automated-config/dist/utils/index.d.cts +66 -16
- package/dist/automated-config/dist/utils/index.d.ts +66 -16
- package/dist/automated-config/dist/utils/index.js +408 -99
- package/dist/automated-config/dist/utils/pseudoStateSelectors.cjs +122 -0
- package/dist/automated-config/dist/utils/pseudoStateSelectors.d.cts +80 -0
- package/dist/automated-config/dist/utils/pseudoStateSelectors.d.ts +80 -0
- package/dist/automated-config/dist/utils/pseudoStateSelectors.js +120 -0
- package/dist/automated-config/dist/utils/resolvePropertyStates.cjs +131 -0
- package/dist/automated-config/dist/utils/resolvePropertyStates.d.cts +49 -0
- package/dist/automated-config/dist/utils/resolvePropertyStates.d.ts +49 -0
- package/dist/automated-config/dist/utils/resolvePropertyStates.js +130 -0
- package/dist/automated-config/dist/utils/resolveSlotByCascade.cjs +118 -0
- package/dist/automated-config/dist/utils/resolveSlotByCascade.d.cts +68 -0
- package/dist/automated-config/dist/utils/resolveSlotByCascade.d.ts +68 -0
- package/dist/automated-config/dist/utils/resolveSlotByCascade.js +117 -0
- package/dist/automated-config/dist/utils/variantConfigGuards.d.cts +13 -0
- package/dist/automated-config/dist/utils/variantConfigGuards.d.ts +13 -0
- package/dist/components/client/Input/Input.cjs +42 -6
- package/dist/components/client/Input/Input.d.cts +13 -0
- package/dist/components/client/Input/Input.d.ts +13 -0
- package/dist/components/client/Input/Input.js +42 -6
- package/dist/config/dist/index.cjs +221 -550
- package/dist/config/dist/index.js +221 -550
- package/dist/css/dist/commands/css.cjs +1 -0
- package/dist/css/dist/commands/css.helpers.cjs +6 -0
- package/dist/css/dist/commands/css.helpers.js +6 -0
- package/dist/css/dist/commands/css.js +1 -0
- package/dist/css/dist/css/generate.cjs +4 -2
- package/dist/css/dist/css/generate.d.cts +28 -0
- package/dist/css/dist/css/generate.d.ts +28 -0
- package/dist/css/dist/css/generate.helpers.cjs +5 -1
- package/dist/css/dist/css/generate.helpers.js +6 -2
- package/dist/css/dist/css/generate.js +4 -2
- package/dist/css/dist/css/postcss.cjs +81 -0
- package/dist/css/dist/css/postcss.helpers.cjs +60 -0
- package/dist/css/dist/css/postcss.helpers.js +59 -1
- package/dist/css/dist/css/postcss.js +82 -2
- package/dist/css/dist/css/runner.cjs +12 -2
- package/dist/css/dist/css/runner.js +12 -2
- package/dist/css/dist/css/theme.d.cts +6 -0
- package/dist/css/dist/css/theme.d.ts +6 -0
- package/dist/css/dist/packages/automated-config/dist/properties.cjs +1 -1
- package/dist/css/dist/packages/automated-config/dist/properties.js +1 -1
- package/dist/css/dist/packages/automated-config/dist/utils/index.d.cts +6 -0
- package/dist/css/dist/packages/automated-config/dist/utils/index.d.ts +6 -0
- package/dist/css/dist/packages/config/dist/index.cjs +221 -550
- package/dist/css/dist/packages/config/dist/index.js +221 -550
- package/dist/css/dist/utils/optimizeCSS.cjs +59 -0
- package/dist/css/dist/utils/optimizeCSS.js +59 -0
- package/dist/index.cjs +25 -0
- package/dist/index.d.cts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +9 -2
- package/dist/styles/styler.d.cts +14 -13
- package/dist/styles/styler.d.ts +14 -13
- package/dist/styles/variants.d.cts +9 -4
- package/dist/styles/variants.d.ts +9 -4
- package/dist/tailwind-internal/dist/packages/automated-config/dist/generated/generatedConfigs.cjs +3011 -3038
- package/dist/tailwind-internal/dist/packages/automated-config/dist/generated/generatedConfigs.js +3011 -3038
- package/dist/tailwind-internal/dist/packages/automated-config/dist/properties.cjs +1 -1
- package/dist/tailwind-internal/dist/packages/automated-config/dist/properties.js +1 -1
- package/dist/tailwind-internal/dist/packages/automated-config/dist/types/StateAxis.cjs +81 -0
- package/dist/tailwind-internal/dist/packages/automated-config/dist/types/StateAxis.js +76 -0
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/canonicalizeStateKey.cjs +33 -0
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/canonicalizeStateKey.js +32 -0
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/componentStatePseudoStates.cjs +0 -7
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/componentStatePseudoStates.js +1 -7
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/index.cjs +354 -97
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/index.d.cts +6 -0
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/index.d.ts +6 -0
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/index.js +355 -98
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/pseudoStateSelectors.cjs +122 -0
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/pseudoStateSelectors.js +121 -0
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/resolvePropertyStates.cjs +132 -0
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/resolvePropertyStates.js +131 -0
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/resolveSlotByCascade.cjs +95 -0
- package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/resolveSlotByCascade.js +95 -0
- package/dist/tailwind-internal/dist/packages/config/dist/index.cjs +221 -550
- package/dist/tailwind-internal/dist/packages/config/dist/index.js +221 -550
- package/dist/tailwind-internal/dist/plugins/components.cjs +28 -24
- package/dist/tailwind-internal/dist/plugins/components.js +28 -24
- package/dist/tailwind-internal/dist/utils/composeTailwindPlugins.d.cts +3 -0
- package/dist/tailwind-internal/dist/utils/composeTailwindPlugins.d.ts +3 -0
- package/dist/tokens/automation/index.cjs +25 -0
- package/dist/tokens/automation/index.d.cts +9 -2
- package/dist/tokens/automation/index.d.ts +9 -2
- package/dist/tokens/automation/index.js +9 -2
- package/dist/tokens/index.cjs +25 -0
- package/dist/tokens/index.d.cts +10 -3
- package/dist/tokens/index.d.ts +10 -3
- package/dist/tokens/index.js +9 -2
- package/dist/tokens/types.d.cts +1 -1
- package/dist/tokens/types.d.ts +1 -1
- package/dist/uds/generated/componentData.cjs +2010 -2008
- package/dist/uds/generated/componentData.js +2010 -2008
- package/dist/uds/generated/migrationSchemaVersion.cjs +1 -1
- package/dist/uds/generated/migrationSchemaVersion.js +1 -1
- package/dist/uds/generated/tailwindPurge.cjs +79 -78
- package/dist/uds/generated/tailwindPurge.js +79 -78
- package/generated/componentData.json +2553 -2551
- package/generated/migrationSchemaVersion.ts +1 -1
- package/generated/tailwindPurge.ts +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
|
|
2
|
+
const require_StateAxis = require("../types/StateAxis.cjs");
|
|
3
|
+
const require_canonicalizeStateKey = require("./canonicalizeStateKey.cjs");
|
|
4
|
+
//#region ../automated-config/dist/utils/pseudoStateSelectors.js
|
|
5
|
+
/*! © 2026 Yahoo, Inc. UDS Default Config v0.0.0-development */
|
|
6
|
+
const LEGACY_STATE_ATOMS = new Set([
|
|
7
|
+
"disabled",
|
|
8
|
+
"focused",
|
|
9
|
+
"focused-keyboard"
|
|
10
|
+
]);
|
|
11
|
+
function isKnownStateAtom(atom) {
|
|
12
|
+
return require_StateAxis.isAtomicState(atom) || LEGACY_STATE_ATOMS.has(atom);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Each atom selector contributes exactly (0,1,0) to specificity. The base
|
|
16
|
+
* component class adds another (0,1,0), so a full rule's specificity is
|
|
17
|
+
* `(0, 1 + atom-count, 0)`:
|
|
18
|
+
*
|
|
19
|
+
* rest → (0,1,0) e.g. `.uds-input-...root`
|
|
20
|
+
* 1-atom → (0,2,0) e.g. `.uds-input-...root:hover...`
|
|
21
|
+
* 2-atom → (0,3,0) e.g. `.uds-input-...root:has(...):hover...`
|
|
22
|
+
* 3-atom → (0,4,0)
|
|
23
|
+
* 4-atom → (0,5,0)
|
|
24
|
+
*
|
|
25
|
+
* Cross-rank cascade (compound beats atom beats rest) is therefore encoded
|
|
26
|
+
* in CSS class-count specificity, not source order — making the cascade-
|
|
27
|
+
* cancellation feature robust to any tool that reorders rules within a
|
|
28
|
+
* stylesheet. Within a rank (e.g. `:hover` vs `:focus-visible`, both
|
|
29
|
+
* (0,2,0)) source order still arbitrates; the resolver computes intra-rank
|
|
30
|
+
* order inline from `STATE_PRIORITY`. See {@link resolvePropertyStates}.
|
|
31
|
+
*
|
|
32
|
+
* Why each entry is (0,1,0):
|
|
33
|
+
*
|
|
34
|
+
* - `:hover` / `:active` / `:focus*` / `:visited` are single pseudo-classes,
|
|
35
|
+
* each (0,1,0).
|
|
36
|
+
* - `:hover` and `:active` carry a `:where(:not(...))` blocker so the rule
|
|
37
|
+
* doesn't match when the element is also active/disabled. The outer
|
|
38
|
+
* `:where()` zeros the `:not(...)` contribution, leaving the bare pseudo-
|
|
39
|
+
* class's (0,1,0) as the only contributor.
|
|
40
|
+
* - `:is(:disabled, :has(:disabled))` takes the max specificity of its
|
|
41
|
+
* args; both are (0,1,0), so the whole is (0,1,0).
|
|
42
|
+
* - `:has(...)` selectors take the specificity of their arg's most specific
|
|
43
|
+
* complex selector. Arguments are pseudo-classes or attribute selectors at
|
|
44
|
+
* (0,1,0); where a form-control scope is also needed (e.g. `readonly` —
|
|
45
|
+
* non-form-control elements default to `:read-only` per spec, so a bare
|
|
46
|
+
* `:has(:read-only)` matches any container with DIV/SPAN children), the
|
|
47
|
+
* scope goes inside `:where(...)` so its (0,0,1) type-selector contribution
|
|
48
|
+
* is zeroed.
|
|
49
|
+
*
|
|
50
|
+
* **Consumer override ergonomics:** a plain `.my-input:hover` is (0,2,0),
|
|
51
|
+
* which ties library 1-atom rules at (0,2,0); source order decides. To
|
|
52
|
+
* unconditionally beat the library, consumers need (0,3,0) (e.g.
|
|
53
|
+
* `.scope .my-input:hover` or `.my-input.my-input:hover`).
|
|
54
|
+
*/
|
|
55
|
+
const ATOMIC_SELECTORS = {
|
|
56
|
+
hover: ":hover:where(:not(:active, :disabled, :has(:disabled)))",
|
|
57
|
+
pressed: ":active:where(:not(:disabled, :has(:disabled)))",
|
|
58
|
+
disabled: ":is(:disabled, :has(:disabled))",
|
|
59
|
+
visited: ":visited",
|
|
60
|
+
focused: ":focus",
|
|
61
|
+
"focus-within": ":focus-within",
|
|
62
|
+
"focus-visible": ":focus-visible",
|
|
63
|
+
"focused-keyboard": ":focus-visible",
|
|
64
|
+
readonly: ":has(:read-only:where(input, textarea))",
|
|
65
|
+
invalid: ":has([aria-invalid=\"true\"])",
|
|
66
|
+
"placeholder-shown": ":has(:placeholder-shown)",
|
|
67
|
+
autofill: ":has(:autofill, :-webkit-autofill)"
|
|
68
|
+
};
|
|
69
|
+
const ATOMIC_DOCS_CLASSES = {
|
|
70
|
+
hover: "hover",
|
|
71
|
+
pressed: "active",
|
|
72
|
+
disabled: "has-disabled",
|
|
73
|
+
visited: "visited",
|
|
74
|
+
focused: "focus",
|
|
75
|
+
"focus-within": "focus-within",
|
|
76
|
+
"focus-visible": "focus-visible",
|
|
77
|
+
"focused-keyboard": "focus-visible",
|
|
78
|
+
readonly: "input-readonly",
|
|
79
|
+
invalid: "has-input-invalid",
|
|
80
|
+
"placeholder-shown": "has-input-placeholder-shown",
|
|
81
|
+
autofill: "has-input-autofill"
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Returns the CSS pseudo-selector string for a state key.
|
|
85
|
+
*
|
|
86
|
+
* - `'rest'`, `''`, and fully-unknown keys return `''`. An unknown atom inside
|
|
87
|
+
* an otherwise-known compound is skipped (the known atoms still contribute) —
|
|
88
|
+
* but callers only pass canonical validated keys, so that case doesn't arise
|
|
89
|
+
* in practice.
|
|
90
|
+
* - Atomic keys return their entry from {@link ATOMIC_SELECTORS}.
|
|
91
|
+
* - Compound keys (`'a&b'`) return the concatenation of each atomic selector
|
|
92
|
+
* in the order they appear in the key.
|
|
93
|
+
*/
|
|
94
|
+
function getStateSelector(stateKey) {
|
|
95
|
+
const atoms = require_canonicalizeStateKey.splitStateKey(stateKey);
|
|
96
|
+
if (atoms.length === 0) return "";
|
|
97
|
+
let selector = "";
|
|
98
|
+
for (const atom of atoms) if (isKnownStateAtom(atom)) selector += ATOMIC_SELECTORS[atom];
|
|
99
|
+
return selector;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Returns the docs-mode class name for a state key, used to force-trigger
|
|
103
|
+
* pseudo-states in docs/Storybook previews.
|
|
104
|
+
*
|
|
105
|
+
* - `'rest'`, `''`, and fully-unknown keys return `''`. An unknown atom inside
|
|
106
|
+
* an otherwise-known compound is skipped (the known atoms still contribute) —
|
|
107
|
+
* but callers only pass canonical validated keys, so that case doesn't arise
|
|
108
|
+
* in practice.
|
|
109
|
+
* - Atomic keys return their entry from {@link ATOMIC_DOCS_CLASSES}.
|
|
110
|
+
* - Compound keys join atomic docs classes with `'-and-'`.
|
|
111
|
+
*/
|
|
112
|
+
function getStateDocsClass(stateKey) {
|
|
113
|
+
const atoms = require_canonicalizeStateKey.splitStateKey(stateKey);
|
|
114
|
+
if (atoms.length === 0) return "";
|
|
115
|
+
const parts = [];
|
|
116
|
+
for (const atom of atoms) if (isKnownStateAtom(atom)) parts.push(ATOMIC_DOCS_CLASSES[atom]);
|
|
117
|
+
return parts.join("-and-");
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
120
|
+
exports.getStateDocsClass = getStateDocsClass;
|
|
121
|
+
exports.getStateSelector = getStateSelector;
|
|
122
|
+
exports.isKnownStateAtom = isKnownStateAtom;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
|
|
2
|
+
import { AtomicState } from "../types/StateAxis.cjs";
|
|
3
|
+
|
|
4
|
+
//#region ../automated-config/dist/utils/pseudoStateSelectors.d.ts
|
|
5
|
+
//#region src/utils/pseudoStateSelectors.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Legacy atom names accepted by the CSS generator + docs-mode map for
|
|
8
|
+
* unmigrated configs. They aren't composable through `StateAxis`, so the new
|
|
9
|
+
* resolver/StateBuilder never emit them.
|
|
10
|
+
*/
|
|
11
|
+
type LegacyStateAtom = 'disabled' | 'focused' | 'focused-keyboard';
|
|
12
|
+
type KnownStateAtom = AtomicState | LegacyStateAtom;
|
|
13
|
+
declare function isKnownStateAtom(atom: string): atom is KnownStateAtom;
|
|
14
|
+
/**
|
|
15
|
+
* Each atom selector contributes exactly (0,1,0) to specificity. The base
|
|
16
|
+
* component class adds another (0,1,0), so a full rule's specificity is
|
|
17
|
+
* `(0, 1 + atom-count, 0)`:
|
|
18
|
+
*
|
|
19
|
+
* rest → (0,1,0) e.g. `.uds-input-...root`
|
|
20
|
+
* 1-atom → (0,2,0) e.g. `.uds-input-...root:hover...`
|
|
21
|
+
* 2-atom → (0,3,0) e.g. `.uds-input-...root:has(...):hover...`
|
|
22
|
+
* 3-atom → (0,4,0)
|
|
23
|
+
* 4-atom → (0,5,0)
|
|
24
|
+
*
|
|
25
|
+
* Cross-rank cascade (compound beats atom beats rest) is therefore encoded
|
|
26
|
+
* in CSS class-count specificity, not source order — making the cascade-
|
|
27
|
+
* cancellation feature robust to any tool that reorders rules within a
|
|
28
|
+
* stylesheet. Within a rank (e.g. `:hover` vs `:focus-visible`, both
|
|
29
|
+
* (0,2,0)) source order still arbitrates; the resolver computes intra-rank
|
|
30
|
+
* order inline from `STATE_PRIORITY`. See {@link resolvePropertyStates}.
|
|
31
|
+
*
|
|
32
|
+
* Why each entry is (0,1,0):
|
|
33
|
+
*
|
|
34
|
+
* - `:hover` / `:active` / `:focus*` / `:visited` are single pseudo-classes,
|
|
35
|
+
* each (0,1,0).
|
|
36
|
+
* - `:hover` and `:active` carry a `:where(:not(...))` blocker so the rule
|
|
37
|
+
* doesn't match when the element is also active/disabled. The outer
|
|
38
|
+
* `:where()` zeros the `:not(...)` contribution, leaving the bare pseudo-
|
|
39
|
+
* class's (0,1,0) as the only contributor.
|
|
40
|
+
* - `:is(:disabled, :has(:disabled))` takes the max specificity of its
|
|
41
|
+
* args; both are (0,1,0), so the whole is (0,1,0).
|
|
42
|
+
* - `:has(...)` selectors take the specificity of their arg's most specific
|
|
43
|
+
* complex selector. Arguments are pseudo-classes or attribute selectors at
|
|
44
|
+
* (0,1,0); where a form-control scope is also needed (e.g. `readonly` —
|
|
45
|
+
* non-form-control elements default to `:read-only` per spec, so a bare
|
|
46
|
+
* `:has(:read-only)` matches any container with DIV/SPAN children), the
|
|
47
|
+
* scope goes inside `:where(...)` so its (0,0,1) type-selector contribution
|
|
48
|
+
* is zeroed.
|
|
49
|
+
*
|
|
50
|
+
* **Consumer override ergonomics:** a plain `.my-input:hover` is (0,2,0),
|
|
51
|
+
* which ties library 1-atom rules at (0,2,0); source order decides. To
|
|
52
|
+
* unconditionally beat the library, consumers need (0,3,0) (e.g.
|
|
53
|
+
* `.scope .my-input:hover` or `.my-input.my-input:hover`).
|
|
54
|
+
*/
|
|
55
|
+
/**
|
|
56
|
+
* Returns the CSS pseudo-selector string for a state key.
|
|
57
|
+
*
|
|
58
|
+
* - `'rest'`, `''`, and fully-unknown keys return `''`. An unknown atom inside
|
|
59
|
+
* an otherwise-known compound is skipped (the known atoms still contribute) —
|
|
60
|
+
* but callers only pass canonical validated keys, so that case doesn't arise
|
|
61
|
+
* in practice.
|
|
62
|
+
* - Atomic keys return their entry from {@link ATOMIC_SELECTORS}.
|
|
63
|
+
* - Compound keys (`'a&b'`) return the concatenation of each atomic selector
|
|
64
|
+
* in the order they appear in the key.
|
|
65
|
+
*/
|
|
66
|
+
declare function getStateSelector(stateKey: string): string;
|
|
67
|
+
/**
|
|
68
|
+
* Returns the docs-mode class name for a state key, used to force-trigger
|
|
69
|
+
* pseudo-states in docs/Storybook previews.
|
|
70
|
+
*
|
|
71
|
+
* - `'rest'`, `''`, and fully-unknown keys return `''`. An unknown atom inside
|
|
72
|
+
* an otherwise-known compound is skipped (the known atoms still contribute) —
|
|
73
|
+
* but callers only pass canonical validated keys, so that case doesn't arise
|
|
74
|
+
* in practice.
|
|
75
|
+
* - Atomic keys return their entry from {@link ATOMIC_DOCS_CLASSES}.
|
|
76
|
+
* - Compound keys join atomic docs classes with `'-and-'`.
|
|
77
|
+
*/
|
|
78
|
+
declare function getStateDocsClass(stateKey: string): string; //#endregion
|
|
79
|
+
//#endregion
|
|
80
|
+
export { getStateDocsClass, getStateSelector, isKnownStateAtom };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
|
|
2
|
+
import { AtomicState } from "../types/StateAxis.js";
|
|
3
|
+
|
|
4
|
+
//#region ../automated-config/dist/utils/pseudoStateSelectors.d.ts
|
|
5
|
+
//#region src/utils/pseudoStateSelectors.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Legacy atom names accepted by the CSS generator + docs-mode map for
|
|
8
|
+
* unmigrated configs. They aren't composable through `StateAxis`, so the new
|
|
9
|
+
* resolver/StateBuilder never emit them.
|
|
10
|
+
*/
|
|
11
|
+
type LegacyStateAtom = 'disabled' | 'focused' | 'focused-keyboard';
|
|
12
|
+
type KnownStateAtom = AtomicState | LegacyStateAtom;
|
|
13
|
+
declare function isKnownStateAtom(atom: string): atom is KnownStateAtom;
|
|
14
|
+
/**
|
|
15
|
+
* Each atom selector contributes exactly (0,1,0) to specificity. The base
|
|
16
|
+
* component class adds another (0,1,0), so a full rule's specificity is
|
|
17
|
+
* `(0, 1 + atom-count, 0)`:
|
|
18
|
+
*
|
|
19
|
+
* rest → (0,1,0) e.g. `.uds-input-...root`
|
|
20
|
+
* 1-atom → (0,2,0) e.g. `.uds-input-...root:hover...`
|
|
21
|
+
* 2-atom → (0,3,0) e.g. `.uds-input-...root:has(...):hover...`
|
|
22
|
+
* 3-atom → (0,4,0)
|
|
23
|
+
* 4-atom → (0,5,0)
|
|
24
|
+
*
|
|
25
|
+
* Cross-rank cascade (compound beats atom beats rest) is therefore encoded
|
|
26
|
+
* in CSS class-count specificity, not source order — making the cascade-
|
|
27
|
+
* cancellation feature robust to any tool that reorders rules within a
|
|
28
|
+
* stylesheet. Within a rank (e.g. `:hover` vs `:focus-visible`, both
|
|
29
|
+
* (0,2,0)) source order still arbitrates; the resolver computes intra-rank
|
|
30
|
+
* order inline from `STATE_PRIORITY`. See {@link resolvePropertyStates}.
|
|
31
|
+
*
|
|
32
|
+
* Why each entry is (0,1,0):
|
|
33
|
+
*
|
|
34
|
+
* - `:hover` / `:active` / `:focus*` / `:visited` are single pseudo-classes,
|
|
35
|
+
* each (0,1,0).
|
|
36
|
+
* - `:hover` and `:active` carry a `:where(:not(...))` blocker so the rule
|
|
37
|
+
* doesn't match when the element is also active/disabled. The outer
|
|
38
|
+
* `:where()` zeros the `:not(...)` contribution, leaving the bare pseudo-
|
|
39
|
+
* class's (0,1,0) as the only contributor.
|
|
40
|
+
* - `:is(:disabled, :has(:disabled))` takes the max specificity of its
|
|
41
|
+
* args; both are (0,1,0), so the whole is (0,1,0).
|
|
42
|
+
* - `:has(...)` selectors take the specificity of their arg's most specific
|
|
43
|
+
* complex selector. Arguments are pseudo-classes or attribute selectors at
|
|
44
|
+
* (0,1,0); where a form-control scope is also needed (e.g. `readonly` —
|
|
45
|
+
* non-form-control elements default to `:read-only` per spec, so a bare
|
|
46
|
+
* `:has(:read-only)` matches any container with DIV/SPAN children), the
|
|
47
|
+
* scope goes inside `:where(...)` so its (0,0,1) type-selector contribution
|
|
48
|
+
* is zeroed.
|
|
49
|
+
*
|
|
50
|
+
* **Consumer override ergonomics:** a plain `.my-input:hover` is (0,2,0),
|
|
51
|
+
* which ties library 1-atom rules at (0,2,0); source order decides. To
|
|
52
|
+
* unconditionally beat the library, consumers need (0,3,0) (e.g.
|
|
53
|
+
* `.scope .my-input:hover` or `.my-input.my-input:hover`).
|
|
54
|
+
*/
|
|
55
|
+
/**
|
|
56
|
+
* Returns the CSS pseudo-selector string for a state key.
|
|
57
|
+
*
|
|
58
|
+
* - `'rest'`, `''`, and fully-unknown keys return `''`. An unknown atom inside
|
|
59
|
+
* an otherwise-known compound is skipped (the known atoms still contribute) —
|
|
60
|
+
* but callers only pass canonical validated keys, so that case doesn't arise
|
|
61
|
+
* in practice.
|
|
62
|
+
* - Atomic keys return their entry from {@link ATOMIC_SELECTORS}.
|
|
63
|
+
* - Compound keys (`'a&b'`) return the concatenation of each atomic selector
|
|
64
|
+
* in the order they appear in the key.
|
|
65
|
+
*/
|
|
66
|
+
declare function getStateSelector(stateKey: string): string;
|
|
67
|
+
/**
|
|
68
|
+
* Returns the docs-mode class name for a state key, used to force-trigger
|
|
69
|
+
* pseudo-states in docs/Storybook previews.
|
|
70
|
+
*
|
|
71
|
+
* - `'rest'`, `''`, and fully-unknown keys return `''`. An unknown atom inside
|
|
72
|
+
* an otherwise-known compound is skipped (the known atoms still contribute) —
|
|
73
|
+
* but callers only pass canonical validated keys, so that case doesn't arise
|
|
74
|
+
* in practice.
|
|
75
|
+
* - Atomic keys return their entry from {@link ATOMIC_DOCS_CLASSES}.
|
|
76
|
+
* - Compound keys join atomic docs classes with `'-and-'`.
|
|
77
|
+
*/
|
|
78
|
+
declare function getStateDocsClass(stateKey: string): string; //#endregion
|
|
79
|
+
//#endregion
|
|
80
|
+
export { getStateDocsClass, getStateSelector, isKnownStateAtom };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
|
|
2
|
+
import { isAtomicState } from "../types/StateAxis.js";
|
|
3
|
+
import { splitStateKey } from "./canonicalizeStateKey.js";
|
|
4
|
+
//#region ../automated-config/dist/utils/pseudoStateSelectors.js
|
|
5
|
+
/*! © 2026 Yahoo, Inc. UDS Default Config v0.0.0-development */
|
|
6
|
+
const LEGACY_STATE_ATOMS = new Set([
|
|
7
|
+
"disabled",
|
|
8
|
+
"focused",
|
|
9
|
+
"focused-keyboard"
|
|
10
|
+
]);
|
|
11
|
+
function isKnownStateAtom(atom) {
|
|
12
|
+
return isAtomicState(atom) || LEGACY_STATE_ATOMS.has(atom);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Each atom selector contributes exactly (0,1,0) to specificity. The base
|
|
16
|
+
* component class adds another (0,1,0), so a full rule's specificity is
|
|
17
|
+
* `(0, 1 + atom-count, 0)`:
|
|
18
|
+
*
|
|
19
|
+
* rest → (0,1,0) e.g. `.uds-input-...root`
|
|
20
|
+
* 1-atom → (0,2,0) e.g. `.uds-input-...root:hover...`
|
|
21
|
+
* 2-atom → (0,3,0) e.g. `.uds-input-...root:has(...):hover...`
|
|
22
|
+
* 3-atom → (0,4,0)
|
|
23
|
+
* 4-atom → (0,5,0)
|
|
24
|
+
*
|
|
25
|
+
* Cross-rank cascade (compound beats atom beats rest) is therefore encoded
|
|
26
|
+
* in CSS class-count specificity, not source order — making the cascade-
|
|
27
|
+
* cancellation feature robust to any tool that reorders rules within a
|
|
28
|
+
* stylesheet. Within a rank (e.g. `:hover` vs `:focus-visible`, both
|
|
29
|
+
* (0,2,0)) source order still arbitrates; the resolver computes intra-rank
|
|
30
|
+
* order inline from `STATE_PRIORITY`. See {@link resolvePropertyStates}.
|
|
31
|
+
*
|
|
32
|
+
* Why each entry is (0,1,0):
|
|
33
|
+
*
|
|
34
|
+
* - `:hover` / `:active` / `:focus*` / `:visited` are single pseudo-classes,
|
|
35
|
+
* each (0,1,0).
|
|
36
|
+
* - `:hover` and `:active` carry a `:where(:not(...))` blocker so the rule
|
|
37
|
+
* doesn't match when the element is also active/disabled. The outer
|
|
38
|
+
* `:where()` zeros the `:not(...)` contribution, leaving the bare pseudo-
|
|
39
|
+
* class's (0,1,0) as the only contributor.
|
|
40
|
+
* - `:is(:disabled, :has(:disabled))` takes the max specificity of its
|
|
41
|
+
* args; both are (0,1,0), so the whole is (0,1,0).
|
|
42
|
+
* - `:has(...)` selectors take the specificity of their arg's most specific
|
|
43
|
+
* complex selector. Arguments are pseudo-classes or attribute selectors at
|
|
44
|
+
* (0,1,0); where a form-control scope is also needed (e.g. `readonly` —
|
|
45
|
+
* non-form-control elements default to `:read-only` per spec, so a bare
|
|
46
|
+
* `:has(:read-only)` matches any container with DIV/SPAN children), the
|
|
47
|
+
* scope goes inside `:where(...)` so its (0,0,1) type-selector contribution
|
|
48
|
+
* is zeroed.
|
|
49
|
+
*
|
|
50
|
+
* **Consumer override ergonomics:** a plain `.my-input:hover` is (0,2,0),
|
|
51
|
+
* which ties library 1-atom rules at (0,2,0); source order decides. To
|
|
52
|
+
* unconditionally beat the library, consumers need (0,3,0) (e.g.
|
|
53
|
+
* `.scope .my-input:hover` or `.my-input.my-input:hover`).
|
|
54
|
+
*/
|
|
55
|
+
const ATOMIC_SELECTORS = {
|
|
56
|
+
hover: ":hover:where(:not(:active, :disabled, :has(:disabled)))",
|
|
57
|
+
pressed: ":active:where(:not(:disabled, :has(:disabled)))",
|
|
58
|
+
disabled: ":is(:disabled, :has(:disabled))",
|
|
59
|
+
visited: ":visited",
|
|
60
|
+
focused: ":focus",
|
|
61
|
+
"focus-within": ":focus-within",
|
|
62
|
+
"focus-visible": ":focus-visible",
|
|
63
|
+
"focused-keyboard": ":focus-visible",
|
|
64
|
+
readonly: ":has(:read-only:where(input, textarea))",
|
|
65
|
+
invalid: ":has([aria-invalid=\"true\"])",
|
|
66
|
+
"placeholder-shown": ":has(:placeholder-shown)",
|
|
67
|
+
autofill: ":has(:autofill, :-webkit-autofill)"
|
|
68
|
+
};
|
|
69
|
+
const ATOMIC_DOCS_CLASSES = {
|
|
70
|
+
hover: "hover",
|
|
71
|
+
pressed: "active",
|
|
72
|
+
disabled: "has-disabled",
|
|
73
|
+
visited: "visited",
|
|
74
|
+
focused: "focus",
|
|
75
|
+
"focus-within": "focus-within",
|
|
76
|
+
"focus-visible": "focus-visible",
|
|
77
|
+
"focused-keyboard": "focus-visible",
|
|
78
|
+
readonly: "input-readonly",
|
|
79
|
+
invalid: "has-input-invalid",
|
|
80
|
+
"placeholder-shown": "has-input-placeholder-shown",
|
|
81
|
+
autofill: "has-input-autofill"
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Returns the CSS pseudo-selector string for a state key.
|
|
85
|
+
*
|
|
86
|
+
* - `'rest'`, `''`, and fully-unknown keys return `''`. An unknown atom inside
|
|
87
|
+
* an otherwise-known compound is skipped (the known atoms still contribute) —
|
|
88
|
+
* but callers only pass canonical validated keys, so that case doesn't arise
|
|
89
|
+
* in practice.
|
|
90
|
+
* - Atomic keys return their entry from {@link ATOMIC_SELECTORS}.
|
|
91
|
+
* - Compound keys (`'a&b'`) return the concatenation of each atomic selector
|
|
92
|
+
* in the order they appear in the key.
|
|
93
|
+
*/
|
|
94
|
+
function getStateSelector(stateKey) {
|
|
95
|
+
const atoms = splitStateKey(stateKey);
|
|
96
|
+
if (atoms.length === 0) return "";
|
|
97
|
+
let selector = "";
|
|
98
|
+
for (const atom of atoms) if (isKnownStateAtom(atom)) selector += ATOMIC_SELECTORS[atom];
|
|
99
|
+
return selector;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Returns the docs-mode class name for a state key, used to force-trigger
|
|
103
|
+
* pseudo-states in docs/Storybook previews.
|
|
104
|
+
*
|
|
105
|
+
* - `'rest'`, `''`, and fully-unknown keys return `''`. An unknown atom inside
|
|
106
|
+
* an otherwise-known compound is skipped (the known atoms still contribute) —
|
|
107
|
+
* but callers only pass canonical validated keys, so that case doesn't arise
|
|
108
|
+
* in practice.
|
|
109
|
+
* - Atomic keys return their entry from {@link ATOMIC_DOCS_CLASSES}.
|
|
110
|
+
* - Compound keys join atomic docs classes with `'-and-'`.
|
|
111
|
+
*/
|
|
112
|
+
function getStateDocsClass(stateKey) {
|
|
113
|
+
const atoms = splitStateKey(stateKey);
|
|
114
|
+
if (atoms.length === 0) return "";
|
|
115
|
+
const parts = [];
|
|
116
|
+
for (const atom of atoms) if (isKnownStateAtom(atom)) parts.push(ATOMIC_DOCS_CLASSES[atom]);
|
|
117
|
+
return parts.join("-and-");
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
120
|
+
export { getStateDocsClass, getStateSelector, isKnownStateAtom };
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
|
|
2
|
+
const require_StateAxis = require("../types/StateAxis.cjs");
|
|
3
|
+
const require_canonicalizeStateKey = require("./canonicalizeStateKey.cjs");
|
|
4
|
+
//#region ../automated-config/dist/utils/resolvePropertyStates.js
|
|
5
|
+
/*! © 2026 Yahoo, Inc. UDS Default Config v0.0.0-development */
|
|
6
|
+
/**
|
|
7
|
+
* Yields every modifier subset of size 1..maxSize, preserving input order
|
|
8
|
+
* within each subset. Used by both the resolver and the docs-class
|
|
9
|
+
* enumeration so the depth they support stays in lock-step.
|
|
10
|
+
*
|
|
11
|
+
* Generic over the element type so callers passing `ModifierAtomic[]` get
|
|
12
|
+
* `Generator<readonly ModifierAtomic[]>` back — keeps the inferred type chain
|
|
13
|
+
* tight enough for downstream consumers to avoid widening to `string`.
|
|
14
|
+
*/
|
|
15
|
+
function* modifierSubsets(modifiers, maxSize) {
|
|
16
|
+
const indices = [];
|
|
17
|
+
function* recurse(start) {
|
|
18
|
+
if (indices.length > 0) yield indices.map((i) => modifiers[i]);
|
|
19
|
+
if (indices.length === maxSize) return;
|
|
20
|
+
for (let i = start; i < modifiers.length; i++) {
|
|
21
|
+
indices.push(i);
|
|
22
|
+
yield* recurse(i + 1);
|
|
23
|
+
indices.pop();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
yield* recurse(0);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Yields the interactive subsets that can be simultaneously active on one
|
|
30
|
+
* element, in `modifierSubsets` order. `hover` and `pressed` are mutually
|
|
31
|
+
* exclusive — the `hover` selector carries `:where(:not(:active …))`, so a
|
|
32
|
+
* `hover&pressed` rule could never match — so any subset containing BOTH is
|
|
33
|
+
* dropped. Every other subset is kept (notably `focus-within`/`focus-visible`
|
|
34
|
+
* CAN coexist with a pointer state: you can hover or press a focused element).
|
|
35
|
+
*
|
|
36
|
+
* `interactives` MUST already be sorted by `comparePriority`.
|
|
37
|
+
*/
|
|
38
|
+
function* coOccurringInteractiveSubsets(interactives) {
|
|
39
|
+
for (const subset of modifierSubsets(interactives, interactives.length)) {
|
|
40
|
+
if (subset.includes("hover") && subset.includes("pressed")) continue;
|
|
41
|
+
yield subset;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Yields a property's atomic + compound state keys in cascade order from a
|
|
46
|
+
* priority-sorted atomic set:
|
|
47
|
+
*
|
|
48
|
+
* atoms (in the given order)
|
|
49
|
+
* → for each modifier subset: the pure-modifier compound (size ≥ 2) then each
|
|
50
|
+
* modifier-subset × SINGLE-interactive compound
|
|
51
|
+
* → each pure interactive-pair compound (size ≥ 2, co-occurring)
|
|
52
|
+
* → each modifier-subset × interactive-PAIR compound
|
|
53
|
+
*
|
|
54
|
+
* The interactive-pair compounds are APPENDED after the original keys so every
|
|
55
|
+
* pre-existing key keeps its rank — `resolveSlotByCascade`'s tie-break and
|
|
56
|
+
* Figma's published values for already-declared states are therefore unchanged;
|
|
57
|
+
* only genuinely new co-occurring combinations (e.g. `focus-within&hover`) gain
|
|
58
|
+
* a key. Each is a real declared state with its own rule, so a property whose
|
|
59
|
+
* `focus-within` and `hover` resolve to different values renders the
|
|
60
|
+
* per-property-correct blend at `(0, 1+atomCount, 0)` specificity in BOTH emit
|
|
61
|
+
* modes — closing the only exhaustive/selective divergence (two interactives
|
|
62
|
+
* co-occurring with no compound to arbitrate them). `hover&pressed` pairs are
|
|
63
|
+
* never generated (they can't co-occur; see `coOccurringInteractiveSubsets`).
|
|
64
|
+
*
|
|
65
|
+
* `'rest'` is NOT included — callers prepend it (and decide whether to, e.g.
|
|
66
|
+
* `skipRestState`). `atomics` MUST already be sorted by `comparePriority`
|
|
67
|
+
* (weakest first) so the strongest atom emits last and wins on intra-rank
|
|
68
|
+
* source-order ties.
|
|
69
|
+
*
|
|
70
|
+
* Shared by `resolvePropertyStates` (the CSS-emission source of truth) and
|
|
71
|
+
* `resolveSlotByCascade`'s cascade-rank computation, so the emission order —
|
|
72
|
+
* and therefore the cascade tie-break it implies — stays identical across both.
|
|
73
|
+
* Change emission order here, not in either caller.
|
|
74
|
+
*/
|
|
75
|
+
function* atomicAndCompoundStateKeys(atomics) {
|
|
76
|
+
for (const atom of atomics) yield atom;
|
|
77
|
+
const modifiers = atomics.filter(require_StateAxis.isModifierAtomic);
|
|
78
|
+
const interactives = atomics.filter(require_StateAxis.isInteractiveAtomic);
|
|
79
|
+
for (const subset of modifierSubsets(modifiers, 3)) {
|
|
80
|
+
if (subset.length >= 2) yield require_canonicalizeStateKey.canonicalizeStateKey(subset);
|
|
81
|
+
for (const interactive of interactives) yield require_canonicalizeStateKey.canonicalizeStateKey([...subset, interactive]);
|
|
82
|
+
}
|
|
83
|
+
const interactivePairs = [...coOccurringInteractiveSubsets(interactives)].filter((subset) => subset.length >= 2);
|
|
84
|
+
for (const interactiveSubset of interactivePairs) yield require_canonicalizeStateKey.canonicalizeStateKey(interactiveSubset);
|
|
85
|
+
for (const subset of modifierSubsets(modifiers, 3)) for (const interactiveSubset of interactivePairs) yield require_canonicalizeStateKey.canonicalizeStateKey([...subset, ...interactiveSubset]);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Returns all canonical state keys a property reacts to, in cascade order:
|
|
89
|
+
*
|
|
90
|
+
* rest → atomics (sorted by global `STATE_PRIORITY`, weakest first)
|
|
91
|
+
* → 2-atom compounds → 3-atom compounds → ...
|
|
92
|
+
*
|
|
93
|
+
* Cross-rank ordering (atom < 2-atom compound < 3-atom compound < ...) is
|
|
94
|
+
* enforced by CSS class-count specificity. Each atom selector contributes
|
|
95
|
+
* (0,1,0), so a 2-atom compound at (0,3,0) strictly beats a 1-atom rule at
|
|
96
|
+
* (0,2,0) — the cascade-cancellation feature is encoded in the selector
|
|
97
|
+
* itself rather than rule source order.
|
|
98
|
+
*
|
|
99
|
+
* Intra-rank ties (which atom wins among the priority-sorted set, or which
|
|
100
|
+
* 2-atom compound wins among siblings of the same size) fall through to
|
|
101
|
+
* source order at the same specificity. Emission order follows the global
|
|
102
|
+
* `STATE_PRIORITY` array — to change which atom wins between any two
|
|
103
|
+
* simultaneously-matching atoms, reorder that array.
|
|
104
|
+
*
|
|
105
|
+
* Resolution sources, in order of precedence:
|
|
106
|
+
*
|
|
107
|
+
* 1. The new system: `layer.atomicStates` declares the atoms this layer can
|
|
108
|
+
* compose; `property.excludeAtomics` opts the property out of selected
|
|
109
|
+
* atoms. Compounds are auto-generated from the resulting set via
|
|
110
|
+
* modifier × interactive expansion.
|
|
111
|
+
* 2. The legacy system: `property.pseudoStates` (no compound generation; the
|
|
112
|
+
* array is used verbatim). Used when `layer.atomicStates` is absent so
|
|
113
|
+
* unmigrated component configs continue to behave exactly as before.
|
|
114
|
+
*
|
|
115
|
+
* `'rest'` is always included unless the property has `skipRestState: true`.
|
|
116
|
+
*/
|
|
117
|
+
function resolvePropertyStates(layer, property) {
|
|
118
|
+
const states = [];
|
|
119
|
+
if (!(property.skipRestState === true)) states.push("rest");
|
|
120
|
+
if (layer.atomicStates && layer.atomicStates.length > 0) {
|
|
121
|
+
const exclude = new Set(property.excludeAtomics ?? []);
|
|
122
|
+
const atomics = [...layer.atomicStates].filter((atom) => !exclude.has(atom)).sort(require_StateAxis.comparePriority);
|
|
123
|
+
for (const stateKey of atomicAndCompoundStateKeys(atomics)) states.push(stateKey);
|
|
124
|
+
return states;
|
|
125
|
+
}
|
|
126
|
+
if (property.pseudoStates) for (const s of property.pseudoStates) states.push(s);
|
|
127
|
+
return states;
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
exports.atomicAndCompoundStateKeys = atomicAndCompoundStateKeys;
|
|
131
|
+
exports.resolvePropertyStates = resolvePropertyStates;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
import { ConfigurablePropertiesName, SelectedConfigurableProperty } from "../properties.cjs";
|
|
3
|
+
import { LayerConfig, PossibleStatesWithRest } from "../types/ComponentConfig.cjs";
|
|
4
|
+
|
|
5
|
+
//#region ../automated-config/dist/utils/resolvePropertyStates.d.ts
|
|
6
|
+
//#region src/utils/resolvePropertyStates.d.ts
|
|
7
|
+
type AnyProperty = SelectedConfigurableProperty<ConfigurablePropertiesName, string>;
|
|
8
|
+
/**
|
|
9
|
+
* Yields every modifier subset of size 1..maxSize, preserving input order
|
|
10
|
+
* within each subset. Used by both the resolver and the docs-class
|
|
11
|
+
* enumeration so the depth they support stays in lock-step.
|
|
12
|
+
*
|
|
13
|
+
* Generic over the element type so callers passing `ModifierAtomic[]` get
|
|
14
|
+
* `Generator<readonly ModifierAtomic[]>` back — keeps the inferred type chain
|
|
15
|
+
* tight enough for downstream consumers to avoid widening to `string`.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Returns all canonical state keys a property reacts to, in cascade order:
|
|
19
|
+
*
|
|
20
|
+
* rest → atomics (sorted by global `STATE_PRIORITY`, weakest first)
|
|
21
|
+
* → 2-atom compounds → 3-atom compounds → ...
|
|
22
|
+
*
|
|
23
|
+
* Cross-rank ordering (atom < 2-atom compound < 3-atom compound < ...) is
|
|
24
|
+
* enforced by CSS class-count specificity. Each atom selector contributes
|
|
25
|
+
* (0,1,0), so a 2-atom compound at (0,3,0) strictly beats a 1-atom rule at
|
|
26
|
+
* (0,2,0) — the cascade-cancellation feature is encoded in the selector
|
|
27
|
+
* itself rather than rule source order.
|
|
28
|
+
*
|
|
29
|
+
* Intra-rank ties (which atom wins among the priority-sorted set, or which
|
|
30
|
+
* 2-atom compound wins among siblings of the same size) fall through to
|
|
31
|
+
* source order at the same specificity. Emission order follows the global
|
|
32
|
+
* `STATE_PRIORITY` array — to change which atom wins between any two
|
|
33
|
+
* simultaneously-matching atoms, reorder that array.
|
|
34
|
+
*
|
|
35
|
+
* Resolution sources, in order of precedence:
|
|
36
|
+
*
|
|
37
|
+
* 1. The new system: `layer.atomicStates` declares the atoms this layer can
|
|
38
|
+
* compose; `property.excludeAtomics` opts the property out of selected
|
|
39
|
+
* atoms. Compounds are auto-generated from the resulting set via
|
|
40
|
+
* modifier × interactive expansion.
|
|
41
|
+
* 2. The legacy system: `property.pseudoStates` (no compound generation; the
|
|
42
|
+
* array is used verbatim). Used when `layer.atomicStates` is absent so
|
|
43
|
+
* unmigrated component configs continue to behave exactly as before.
|
|
44
|
+
*
|
|
45
|
+
* `'rest'` is always included unless the property has `skipRestState: true`.
|
|
46
|
+
*/
|
|
47
|
+
declare function resolvePropertyStates(layer: LayerConfig, property: AnyProperty): PossibleStatesWithRest[]; //#endregion
|
|
48
|
+
//#endregion
|
|
49
|
+
export { resolvePropertyStates };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
import { ConfigurablePropertiesName, SelectedConfigurableProperty } from "../properties.js";
|
|
3
|
+
import { LayerConfig, PossibleStatesWithRest } from "../types/ComponentConfig.js";
|
|
4
|
+
|
|
5
|
+
//#region ../automated-config/dist/utils/resolvePropertyStates.d.ts
|
|
6
|
+
//#region src/utils/resolvePropertyStates.d.ts
|
|
7
|
+
type AnyProperty = SelectedConfigurableProperty<ConfigurablePropertiesName, string>;
|
|
8
|
+
/**
|
|
9
|
+
* Yields every modifier subset of size 1..maxSize, preserving input order
|
|
10
|
+
* within each subset. Used by both the resolver and the docs-class
|
|
11
|
+
* enumeration so the depth they support stays in lock-step.
|
|
12
|
+
*
|
|
13
|
+
* Generic over the element type so callers passing `ModifierAtomic[]` get
|
|
14
|
+
* `Generator<readonly ModifierAtomic[]>` back — keeps the inferred type chain
|
|
15
|
+
* tight enough for downstream consumers to avoid widening to `string`.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Returns all canonical state keys a property reacts to, in cascade order:
|
|
19
|
+
*
|
|
20
|
+
* rest → atomics (sorted by global `STATE_PRIORITY`, weakest first)
|
|
21
|
+
* → 2-atom compounds → 3-atom compounds → ...
|
|
22
|
+
*
|
|
23
|
+
* Cross-rank ordering (atom < 2-atom compound < 3-atom compound < ...) is
|
|
24
|
+
* enforced by CSS class-count specificity. Each atom selector contributes
|
|
25
|
+
* (0,1,0), so a 2-atom compound at (0,3,0) strictly beats a 1-atom rule at
|
|
26
|
+
* (0,2,0) — the cascade-cancellation feature is encoded in the selector
|
|
27
|
+
* itself rather than rule source order.
|
|
28
|
+
*
|
|
29
|
+
* Intra-rank ties (which atom wins among the priority-sorted set, or which
|
|
30
|
+
* 2-atom compound wins among siblings of the same size) fall through to
|
|
31
|
+
* source order at the same specificity. Emission order follows the global
|
|
32
|
+
* `STATE_PRIORITY` array — to change which atom wins between any two
|
|
33
|
+
* simultaneously-matching atoms, reorder that array.
|
|
34
|
+
*
|
|
35
|
+
* Resolution sources, in order of precedence:
|
|
36
|
+
*
|
|
37
|
+
* 1. The new system: `layer.atomicStates` declares the atoms this layer can
|
|
38
|
+
* compose; `property.excludeAtomics` opts the property out of selected
|
|
39
|
+
* atoms. Compounds are auto-generated from the resulting set via
|
|
40
|
+
* modifier × interactive expansion.
|
|
41
|
+
* 2. The legacy system: `property.pseudoStates` (no compound generation; the
|
|
42
|
+
* array is used verbatim). Used when `layer.atomicStates` is absent so
|
|
43
|
+
* unmigrated component configs continue to behave exactly as before.
|
|
44
|
+
*
|
|
45
|
+
* `'rest'` is always included unless the property has `skipRestState: true`.
|
|
46
|
+
*/
|
|
47
|
+
declare function resolvePropertyStates(layer: LayerConfig, property: AnyProperty): PossibleStatesWithRest[]; //#endregion
|
|
48
|
+
//#endregion
|
|
49
|
+
export { resolvePropertyStates };
|