@yahoo/uds 3.156.2 → 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.
Files changed (144) hide show
  1. package/dist/automated-config/dist/generated/autoVariants.cjs +9 -4
  2. package/dist/automated-config/dist/generated/autoVariants.d.cts +2 -1
  3. package/dist/automated-config/dist/generated/autoVariants.d.ts +2 -1
  4. package/dist/automated-config/dist/generated/autoVariants.js +9 -4
  5. package/dist/automated-config/dist/generated/generatedConfigs.cjs +3011 -3038
  6. package/dist/automated-config/dist/generated/generatedConfigs.d.cts +143 -140
  7. package/dist/automated-config/dist/generated/generatedConfigs.d.ts +143 -140
  8. package/dist/automated-config/dist/generated/generatedConfigs.js +3011 -3038
  9. package/dist/automated-config/dist/generated/universalTokensConfigAuto.cjs +1227 -501
  10. package/dist/automated-config/dist/generated/universalTokensConfigAuto.js +1227 -501
  11. package/dist/automated-config/dist/properties.cjs +1 -1
  12. package/dist/automated-config/dist/properties.d.cts +15 -0
  13. package/dist/automated-config/dist/properties.d.ts +15 -0
  14. package/dist/automated-config/dist/properties.js +1 -1
  15. package/dist/automated-config/dist/types/ComponentConfig.d.cts +77 -4
  16. package/dist/automated-config/dist/types/ComponentConfig.d.ts +77 -4
  17. package/dist/automated-config/dist/types/ConfigSchema.d.cts +14 -2
  18. package/dist/automated-config/dist/types/ConfigSchema.d.ts +14 -2
  19. package/dist/automated-config/dist/types/StateAxis.cjs +90 -0
  20. package/dist/automated-config/dist/types/StateAxis.d.cts +70 -0
  21. package/dist/automated-config/dist/types/StateAxis.d.ts +70 -0
  22. package/dist/automated-config/dist/types/StateAxis.js +84 -0
  23. package/dist/automated-config/dist/utils/buildConfigSchema.cjs +98 -82
  24. package/dist/automated-config/dist/utils/buildConfigSchema.d.cts +32 -10
  25. package/dist/automated-config/dist/utils/buildConfigSchema.d.ts +32 -10
  26. package/dist/automated-config/dist/utils/buildConfigSchema.js +99 -83
  27. package/dist/automated-config/dist/utils/canonicalizeStateKey.cjs +32 -0
  28. package/dist/automated-config/dist/utils/canonicalizeStateKey.d.cts +48 -0
  29. package/dist/automated-config/dist/utils/canonicalizeStateKey.d.ts +48 -0
  30. package/dist/automated-config/dist/utils/canonicalizeStateKey.js +31 -0
  31. package/dist/automated-config/dist/utils/getConfigComponentVariant.d.cts +8 -0
  32. package/dist/automated-config/dist/utils/getConfigComponentVariant.d.ts +8 -0
  33. package/dist/automated-config/dist/utils/getConfigVariantProperties.d.cts +3 -3
  34. package/dist/automated-config/dist/utils/getConfigVariantProperties.d.ts +3 -3
  35. package/dist/automated-config/dist/utils/getConfigVariantPseudoStates.cjs +12 -5
  36. package/dist/automated-config/dist/utils/getConfigVariantPseudoStates.d.cts +8 -1
  37. package/dist/automated-config/dist/utils/getConfigVariantPseudoStates.d.ts +8 -1
  38. package/dist/automated-config/dist/utils/getConfigVariantPseudoStates.js +12 -5
  39. package/dist/automated-config/dist/utils/index.cjs +407 -97
  40. package/dist/automated-config/dist/utils/index.d.cts +66 -16
  41. package/dist/automated-config/dist/utils/index.d.ts +66 -16
  42. package/dist/automated-config/dist/utils/index.js +408 -99
  43. package/dist/automated-config/dist/utils/pseudoStateSelectors.cjs +122 -0
  44. package/dist/automated-config/dist/utils/pseudoStateSelectors.d.cts +80 -0
  45. package/dist/automated-config/dist/utils/pseudoStateSelectors.d.ts +80 -0
  46. package/dist/automated-config/dist/utils/pseudoStateSelectors.js +120 -0
  47. package/dist/automated-config/dist/utils/resolvePropertyStates.cjs +131 -0
  48. package/dist/automated-config/dist/utils/resolvePropertyStates.d.cts +49 -0
  49. package/dist/automated-config/dist/utils/resolvePropertyStates.d.ts +49 -0
  50. package/dist/automated-config/dist/utils/resolvePropertyStates.js +130 -0
  51. package/dist/automated-config/dist/utils/resolveSlotByCascade.cjs +118 -0
  52. package/dist/automated-config/dist/utils/resolveSlotByCascade.d.cts +68 -0
  53. package/dist/automated-config/dist/utils/resolveSlotByCascade.d.ts +68 -0
  54. package/dist/automated-config/dist/utils/resolveSlotByCascade.js +117 -0
  55. package/dist/automated-config/dist/utils/variantConfigGuards.d.cts +13 -0
  56. package/dist/automated-config/dist/utils/variantConfigGuards.d.ts +13 -0
  57. package/dist/components/client/Input/Input.cjs +42 -6
  58. package/dist/components/client/Input/Input.d.cts +13 -0
  59. package/dist/components/client/Input/Input.d.ts +13 -0
  60. package/dist/components/client/Input/Input.js +42 -6
  61. package/dist/config/dist/index.cjs +221 -550
  62. package/dist/config/dist/index.js +221 -550
  63. package/dist/css/dist/commands/css.cjs +1 -0
  64. package/dist/css/dist/commands/css.helpers.cjs +6 -0
  65. package/dist/css/dist/commands/css.helpers.js +6 -0
  66. package/dist/css/dist/commands/css.js +1 -0
  67. package/dist/css/dist/css/generate.cjs +4 -2
  68. package/dist/css/dist/css/generate.d.cts +28 -0
  69. package/dist/css/dist/css/generate.d.ts +28 -0
  70. package/dist/css/dist/css/generate.helpers.cjs +5 -1
  71. package/dist/css/dist/css/generate.helpers.js +6 -2
  72. package/dist/css/dist/css/generate.js +4 -2
  73. package/dist/css/dist/css/postcss.cjs +81 -0
  74. package/dist/css/dist/css/postcss.helpers.cjs +60 -0
  75. package/dist/css/dist/css/postcss.helpers.js +59 -1
  76. package/dist/css/dist/css/postcss.js +82 -2
  77. package/dist/css/dist/css/runner.cjs +12 -2
  78. package/dist/css/dist/css/runner.js +12 -2
  79. package/dist/css/dist/css/theme.d.cts +6 -0
  80. package/dist/css/dist/css/theme.d.ts +6 -0
  81. package/dist/css/dist/packages/automated-config/dist/properties.cjs +1 -1
  82. package/dist/css/dist/packages/automated-config/dist/properties.js +1 -1
  83. package/dist/css/dist/packages/automated-config/dist/utils/index.d.cts +6 -0
  84. package/dist/css/dist/packages/automated-config/dist/utils/index.d.ts +6 -0
  85. package/dist/css/dist/packages/config/dist/index.cjs +221 -550
  86. package/dist/css/dist/packages/config/dist/index.js +221 -550
  87. package/dist/css/dist/utils/optimizeCSS.cjs +59 -0
  88. package/dist/css/dist/utils/optimizeCSS.js +59 -0
  89. package/dist/index.cjs +25 -0
  90. package/dist/index.d.cts +10 -3
  91. package/dist/index.d.ts +10 -3
  92. package/dist/index.js +9 -2
  93. package/dist/styles/styler.d.cts +12 -11
  94. package/dist/styles/styler.d.ts +12 -11
  95. package/dist/styles/variants.d.cts +9 -4
  96. package/dist/styles/variants.d.ts +9 -4
  97. package/dist/tailwind-internal/dist/packages/automated-config/dist/generated/generatedConfigs.cjs +3011 -3038
  98. package/dist/tailwind-internal/dist/packages/automated-config/dist/generated/generatedConfigs.js +3011 -3038
  99. package/dist/tailwind-internal/dist/packages/automated-config/dist/properties.cjs +1 -1
  100. package/dist/tailwind-internal/dist/packages/automated-config/dist/properties.js +1 -1
  101. package/dist/tailwind-internal/dist/packages/automated-config/dist/types/StateAxis.cjs +81 -0
  102. package/dist/tailwind-internal/dist/packages/automated-config/dist/types/StateAxis.js +76 -0
  103. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/canonicalizeStateKey.cjs +33 -0
  104. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/canonicalizeStateKey.js +32 -0
  105. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/componentStatePseudoStates.cjs +0 -7
  106. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/componentStatePseudoStates.js +1 -7
  107. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/index.cjs +354 -97
  108. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/index.d.cts +6 -0
  109. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/index.d.ts +6 -0
  110. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/index.js +355 -98
  111. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/pseudoStateSelectors.cjs +122 -0
  112. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/pseudoStateSelectors.js +121 -0
  113. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/resolvePropertyStates.cjs +132 -0
  114. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/resolvePropertyStates.js +131 -0
  115. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/resolveSlotByCascade.cjs +95 -0
  116. package/dist/tailwind-internal/dist/packages/automated-config/dist/utils/resolveSlotByCascade.js +95 -0
  117. package/dist/tailwind-internal/dist/packages/config/dist/index.cjs +221 -550
  118. package/dist/tailwind-internal/dist/packages/config/dist/index.js +221 -550
  119. package/dist/tailwind-internal/dist/plugins/components.cjs +28 -24
  120. package/dist/tailwind-internal/dist/plugins/components.js +28 -24
  121. package/dist/tailwind-internal/dist/utils/composeTailwindPlugins.d.cts +3 -0
  122. package/dist/tailwind-internal/dist/utils/composeTailwindPlugins.d.ts +3 -0
  123. package/dist/tailwind-internal/dist/utils/getShadowStyles.d.cts +2 -2
  124. package/dist/tailwind-internal/dist/utils/getShadowStyles.d.ts +2 -2
  125. package/dist/tokens/automation/index.cjs +25 -0
  126. package/dist/tokens/automation/index.d.cts +9 -2
  127. package/dist/tokens/automation/index.d.ts +9 -2
  128. package/dist/tokens/automation/index.js +9 -2
  129. package/dist/tokens/index.cjs +25 -0
  130. package/dist/tokens/index.d.cts +10 -3
  131. package/dist/tokens/index.d.ts +10 -3
  132. package/dist/tokens/index.js +9 -2
  133. package/dist/tokens/types.d.cts +1 -1
  134. package/dist/tokens/types.d.ts +1 -1
  135. package/dist/uds/generated/componentData.cjs +2202 -2200
  136. package/dist/uds/generated/componentData.js +2202 -2200
  137. package/dist/uds/generated/migrationSchemaVersion.cjs +1 -1
  138. package/dist/uds/generated/migrationSchemaVersion.js +1 -1
  139. package/dist/uds/generated/tailwindPurge.cjs +79 -78
  140. package/dist/uds/generated/tailwindPurge.js +79 -78
  141. package/generated/componentData.json +2720 -2718
  142. package/generated/migrationSchemaVersion.ts +1 -1
  143. package/generated/tailwindPurge.ts +2 -2
  144. 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 };