@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
@@ -2,11 +2,15 @@
2
2
  import { BUTTON_GAP_VAR, BUTTON_SCALE_EFFECT_HOVER, BUTTON_SCALE_EFFECT_PRESSED, BUTTON_SCALE_EFFECT_REST } from "../../../css-tokens/dist/index.js";
3
3
  import { mapTextVariantFixtureToValue } from "../mapTextVariantFixtureToValue.js";
4
4
  import { configurableProperties } from "../properties.js";
5
- import { filterPseudoStatesByExclusion, getExcludedPseudoStatesForComponentStateOption } from "./componentStatePseudoStates.js";
5
+ import { INTERACTIVE_ATOMICS, MODIFIER_ATOMICS, comparePriority } from "../types/StateAxis.js";
6
+ import { getExcludedPseudoStatesForComponentStateOption } from "./componentStatePseudoStates.js";
6
7
  import { generateSchemaKey } from "./generateSchemaKey.js";
8
+ import { atomicAndCompoundStateKeys, resolvePropertyStates } from "./resolvePropertyStates.js";
7
9
  import { isVariantConfigWithComponentStates, isVariantConfigWithProperties } from "./variantConfigGuards.js";
8
10
  import { findFixtureTypeForValue } from "./buildConfigSchema.js";
9
11
  import { generateDefaultClassName } from "./generateDefaultClassName.js";
12
+ import { getStateDocsClass, getStateSelector } from "./pseudoStateSelectors.js";
13
+ import { resolveSlotByCascade } from "./resolveSlotByCascade.js";
10
14
  import { isFunction, mergeWith } from "lodash-es";
11
15
  //#region ../tailwind-internal/dist/packages/automated-config/dist/utils/index.js
12
16
  /*! © 2026 Yahoo, Inc. UDS Tailwind Internal v0.0.0-development */
@@ -61,37 +65,55 @@ const COMPONENTS_WITH_SHADOW_BORDERS = [
61
65
  }
62
66
  ];
63
67
  /**
64
- * Map our "states" to pseudo-classes (hover => :hover, pressed => :active, etc.).
65
- * Adjust or extend as needed.
68
+ * Legacy state keys still used by unmigrated component configs via per-property
69
+ * `pseudoStates` arrays. They aren't in the new `StateAxis` taxonomy (so the
70
+ * resolver/StateBuilder don't auto-compose them) but they must remain in
71
+ * `KNOWN_STATE_KEYS` so the docs-mode map / configurator safelist still cover
72
+ * configs that emit them. Drop entries from this list as components migrate.
66
73
  */
67
- const statePseudoMap = {
68
- rest: "",
69
- hover: ":hover:not(:active, :disabled, :has(:disabled))",
70
- pressed: ":active:not(:disabled, :has(:disabled))",
71
- disabled: ":is(:disabled, :has(:disabled))",
72
- visited: ":visited",
73
- focused: ":focus",
74
- "focus-within": ":focus-within",
75
- "focused-keyboard": ":focus-visible",
76
- readonly: ":has(input:read-only)",
77
- invalid: ":has(input[aria-invalid=\"true\"])",
78
- "invalid&hover": ":has(input[aria-invalid=\"true\"]):hover:not(:active, :disabled, :has(:disabled))",
79
- "invalid&pressed": ":has(input[aria-invalid=\"true\"]):active:not(:disabled, :has(:disabled))"
80
- };
81
- const statePseudoMapDocsMode = {
82
- rest: "",
83
- hover: "hover",
84
- pressed: "active",
85
- disabled: "has-disabled",
86
- visited: "visited",
87
- focused: "focus",
88
- "focus-within": "focus-within",
89
- "focused-keyboard": "focus-visible",
90
- readonly: "input-readonly",
91
- invalid: "has-input-invalid",
92
- "invalid&hover": "has-input-invalid-and-hover",
93
- "invalid&pressed": "has-input-invalid-and-active"
94
- };
74
+ const LEGACY_STATE_KEYS = [
75
+ "disabled",
76
+ "focused",
77
+ "focused-keyboard"
78
+ ];
79
+ /**
80
+ * Enumerates every canonical state key the system supports: rest, every atom,
81
+ * every modifier-subset (up to {@link MAX_MODIFIERS_PER_COMPOUND}) on its own
82
+ * and combined with each interactive, plus any legacy keys still in use.
83
+ *
84
+ * Mirrors `resolvePropertyStates` exactly so what the resolver pre-emits in
85
+ * the schema, what the StateBuilder lets users compose, and what the docs
86
+ * map / configurator safelist preserve are all the same set.
87
+ */
88
+ function enumerateAllStateKeys() {
89
+ const states = ["rest"];
90
+ const atoms = [...INTERACTIVE_ATOMICS, ...MODIFIER_ATOMICS].sort(comparePriority);
91
+ for (const stateKey of atomicAndCompoundStateKeys(atoms)) states.push(stateKey);
92
+ for (const legacy of LEGACY_STATE_KEYS) states.push(legacy);
93
+ return states;
94
+ }
95
+ const KNOWN_STATE_KEYS = enumerateAllStateKeys();
96
+ /**
97
+ * Lookup of every known state key to its index in `KNOWN_STATE_KEYS` — i.e. the
98
+ * resolver's emission order. The CSS generator iterates property-state maps
99
+ * in this order (instead of the alphabetical insertion order produced by
100
+ * `syncYosConfig`'s `normalizeConfig`), so cascade tie-breaking under the
101
+ * uniform per-atom specificity actually follows the priority chain. Unknown
102
+ * keys sort to the end.
103
+ */
104
+ const KNOWN_STATE_RANK = new Map(KNOWN_STATE_KEYS.map((key, index) => [key, index]));
105
+ function compareStateKeys(a, b) {
106
+ const ra = KNOWN_STATE_RANK.get(a) ?? Number.POSITIVE_INFINITY;
107
+ const rb = KNOWN_STATE_RANK.get(b) ?? Number.POSITIVE_INFINITY;
108
+ if (ra === rb) return a < b ? -1 : a > b ? 1 : 0;
109
+ return ra - rb;
110
+ }
111
+ function buildStateRecord(transform) {
112
+ const record = {};
113
+ for (const key of KNOWN_STATE_KEYS) record[key] = transform(key);
114
+ return record;
115
+ }
116
+ buildStateRecord(getStateDocsClass);
95
117
  /**
96
118
  * Generates button line-height with icon size minimum.
97
119
  * Ensures button line-height is at least as tall as the icon to prevent clipping.
@@ -234,7 +256,57 @@ const getTheCssPropertyValue = (schema, theme, propertyName, schemaStateValue, e
234
256
  if (propertyConfig.concatenate && existingValue) return `${existingValue}${propertyConfig.concatenationDelimiter || ", "}${newValue}`;
235
257
  return newValue;
236
258
  };
237
- function generateDeclaration({ componentName, subComponentName, variantKey, variantValue, layer, layerOptionalPseudoSelector, componentStateKey, componentStateValue, schema, propertyKey, originalPropertyDefinition, theme, currentStyles, previewOptions, excludedPseudoStates = [] }) {
259
+ /**
260
+ * Builds the per-state resolution map for a per-componentState OVERRIDE in
261
+ * exhaustive mode: the universal layer's state map with the override's ENABLED
262
+ * (and `rest`) slots layered on top. An unset or disabled override slot defers
263
+ * to the universal layer's value, so `resolveSlotByCascade` picks the
264
+ * most-specific *enabled* slot across both layers (override winning ties) rather
265
+ * than collapsing every unset state to the override's own `rest`.
266
+ */
267
+ function mergeUniversalUnderOverride(universal, override) {
268
+ const merged = { ...universal };
269
+ const overrideRecord = override;
270
+ for (const state of Object.keys(overrideRecord)) {
271
+ const slot = overrideRecord[state];
272
+ if (state === "rest" && slot?.isEnabled !== false || slot?.isEnabled === true) merged[state] = slot;
273
+ }
274
+ return merged;
275
+ }
276
+ /**
277
+ * Replays SELECTIVE emission for a STANDALONE atomicStates layer (no universal
278
+ * fallback) and returns the sparse set of slots it would emit: `rest`, every
279
+ * explicitly-enabled state, and every cascade-correction. Mirrors the inline
280
+ * selective decision in `generateDeclaration` — keep the two in lock-step.
281
+ *
282
+ * The override path seeds its own correction accumulator with this for the
283
+ * UNIVERSAL layer. Universal layers are emitted in a separate pass at the SAME
284
+ * specificity tier as their per-option overrides (see `bumpRootSpecificity`), so
285
+ * at runtime a universal rule wins wherever the override emits nothing. Without
286
+ * this seed, an override that flattens a state to `rest` (e.g. a `filled` help
287
+ * text that's `muted` everywhere) silently inherits the universal's brighter
288
+ * rule for that state in selective mode — a divergence from exhaustive, where
289
+ * the override emits every state explicitly. Seeding makes the override emit a
290
+ * correction whenever the universal would otherwise render a different value.
291
+ */
292
+ function selectiveEmittedStates(stateMap, orderedStateKeys, emittableStates) {
293
+ const emitted = { rest: stateMap.rest };
294
+ for (const stateKey of orderedStateKeys) {
295
+ if (stateKey === "rest" || !emittableStates.has(stateKey)) continue;
296
+ const value = resolveSlotByCascade(stateKey, stateMap);
297
+ if (!value) continue;
298
+ if (!(stateMap[stateKey]?.isEnabled === true)) {
299
+ if (resolveSlotByCascade(stateKey, emitted)?.value === value.value) continue;
300
+ }
301
+ emitted[stateKey] = {
302
+ ...value,
303
+ isEnabled: true
304
+ };
305
+ }
306
+ return emitted;
307
+ }
308
+ function generateDeclaration({ componentName, subComponentName, variantKey, variantValue, layer, layerOptionalPseudoSelector, componentStateKey, componentStateValue, schema, propertyKey, originalPropertyDefinition, declaredStates, layerUsesAtomicStates, theme, currentStyles, previewOptions, excludedPseudoStates = [], emit, fallbackStateMap, bumpRootSpecificity }) {
309
+ const shouldUseExhaustive = (emit ?? "exhaustive") === "exhaustive" && layerUsesAtomicStates;
238
310
  const schemaKey = generateSchemaKey({
239
311
  variantKey,
240
312
  variantValue,
@@ -255,14 +327,29 @@ function generateDeclaration({ componentName, subComponentName, variantKey, vari
255
327
  const propertyStateMap = schema.variables?.[schemaKey]?.[propertyKey];
256
328
  if (!propertyStateMap) throw new Error(`Prop definition (${componentName} - ${schemaKey} - ${propertyKey}) not found, this is not expected, please report the bug to the UDS team`);
257
329
  const styles = {};
258
- const skipRestForProperty = originalPropertyDefinition.skipRestState === true;
259
- const declaredPseudoStates = filterPseudoStatesByExclusion(originalPropertyDefinition.pseudoStates, excludedPseudoStates);
260
- const declaredPropertyStates = new Set([...skipRestForProperty ? [] : ["rest"], ...declaredPseudoStates]);
261
- for (const propStateStr in propertyStateMap) {
262
- if (!declaredPropertyStates.has(propStateStr)) continue;
330
+ const excludedStateSet = new Set(excludedPseudoStates);
331
+ const emittableStates = new Set([...declaredStates].filter((state) => !excludedStateSet.has(state)));
332
+ const orderedStateKeys = (shouldUseExhaustive || layerUsesAtomicStates ? [...emittableStates] : Object.keys(propertyStateMap)).sort(compareStateKeys);
333
+ const resolutionStates = fallbackStateMap ? mergeUniversalUnderOverride(fallbackStateMap, propertyStateMap) : propertyStateMap;
334
+ const emittedForSelective = layerUsesAtomicStates && !shouldUseExhaustive ? fallbackStateMap ? selectiveEmittedStates(fallbackStateMap, orderedStateKeys, emittableStates) : { rest: resolutionStates.rest } : {};
335
+ for (const propStateStr of orderedStateKeys) {
336
+ if (!emittableStates.has(propStateStr)) continue;
263
337
  const propertyState = propStateStr;
264
- const propertyStateSelector = statePseudoMap[propertyState] ?? "";
265
- const schemaValueForState = propertyStateMap[propertyState];
338
+ const propertyStateSelector = getStateSelector(propertyState);
339
+ const schemaValueForState = shouldUseExhaustive || layerUsesAtomicStates ? resolveSlotByCascade(propStateStr, resolutionStates) : propertyStateMap[propertyState];
340
+ if (!schemaValueForState) continue;
341
+ if (!shouldUseExhaustive) {
342
+ if (layerUsesAtomicStates) {
343
+ const isExplicitlyEnabled = propertyStateMap[propertyState]?.isEnabled === true;
344
+ if (propStateStr !== "rest" && !isExplicitlyEnabled) {
345
+ if (resolveSlotByCascade(propStateStr, emittedForSelective)?.value === schemaValueForState.value) continue;
346
+ }
347
+ emittedForSelective[propStateStr] = {
348
+ ...schemaValueForState,
349
+ isEnabled: true
350
+ };
351
+ } else if (schemaValueForState.isEnabled === false) continue;
352
+ }
266
353
  let fullClassName = ``;
267
354
  if (layer === "root") if (componentStateKey && componentStateValue) {
268
355
  const rootVariantClass = generateClassName({
@@ -281,7 +368,7 @@ function generateDeclaration({ componentName, subComponentName, variantKey, vari
281
368
  componentStateValue
282
369
  });
283
370
  fullClassName = `.${rootVariantClass}${propertyStateSelector}.${className}`;
284
- } else fullClassName = `.${className}${propertyStateSelector}`;
371
+ } else fullClassName = bumpRootSpecificity ? `.${className}.${className}${propertyStateSelector}` : `.${className}${propertyStateSelector}`;
285
372
  else {
286
373
  const rootVariantClassName = generateClassName({
287
374
  componentName,
@@ -308,7 +395,17 @@ function generateDeclaration({ componentName, subComponentName, variantKey, vari
308
395
  subComponentName
309
396
  });
310
397
  fullClassName = `.${rootVariantClassName}${propertyStateSelector}.${rootVariantClassNameWithComponentState} .${className}`;
311
- } else fullClassName = `.${rootVariantClassName}${propertyStateSelector} .${className}`;
398
+ } else {
399
+ className = generateClassName({
400
+ componentName,
401
+ variantKey,
402
+ variantValue,
403
+ layer,
404
+ layerOptionalPseudoSelector,
405
+ subComponentName
406
+ });
407
+ fullClassName = bumpRootSpecificity ? `.${rootVariantClassName}.${rootVariantClassName}${propertyStateSelector} .${className}` : `.${rootVariantClassName}${propertyStateSelector} .${className}`;
408
+ }
312
409
  }
313
410
  const { cssProperties, extendedProperties: extendedPropertiesGetter } = configurableProperties[originalPropertyDefinition.name];
314
411
  const cssDeclarations = {};
@@ -450,7 +547,7 @@ function generateDeclaration({ componentName, subComponentName, variantKey, vari
450
547
  ...styles[fullClassName]
451
548
  };
452
549
  if (previewOptions?.generatePseudoStateClassModifier) {
453
- const pseudoPrefixClass = statePseudoMapDocsMode[propertyState] ?? "";
550
+ const pseudoPrefixClass = getStateDocsClass(propertyState);
454
551
  if (pseudoPrefixClass.length) {
455
552
  const importantCssDeclarations = Object.fromEntries(Object.entries(cssDeclarations).map(([prop, value]) => {
456
553
  const strValue = String(value).trimEnd().replace(/;$/, "");
@@ -466,12 +563,137 @@ function generateDeclaration({ componentName, subComponentName, variantKey, vari
466
563
  }
467
564
  return styles;
468
565
  }
469
- function generateConfigStyles(config, schema, theme, previewOptions) {
566
+ /**
567
+ * Emit CSS for per-state schema entries that target a variant's universal
568
+ * layers — the "override" path. Per-state schema entries can be authored by
569
+ * the Configurator (via `setConfigPseudoStateVariable`) or written by data
570
+ * migrations; they aren't declared in source configs.
571
+ *
572
+ * Iterates the cartesian product of `componentStates.X.options × universal
573
+ * layers × universal properties`. For each combination, calls
574
+ * `generateDeclaration` with the universal property's metadata plus the
575
+ * componentState key/value — the existing schema lookup inside
576
+ * `generateDeclaration` picks up the override slot if one exists and skips
577
+ * the property otherwise.
578
+ */
579
+ function emitSchemaOverrideStyles({ componentName, subComponentName, variantKey, variantOption, variantConfig, schema, theme, previewOptions, emit, currentStyles }) {
580
+ let styles = currentStyles;
581
+ const universalLayers = variantConfig.layers;
582
+ const componentStates = variantConfig.componentStates;
583
+ if (!universalLayers || !componentStates) return styles;
584
+ const variables = schema.variables;
585
+ if (!variables) return styles;
586
+ for (const componentStateKey in componentStates) {
587
+ const componentState = componentStates[componentStateKey];
588
+ for (const componentStateOption of componentState.options) for (const layerKey in universalLayers) {
589
+ const universalLayer = universalLayers[layerKey];
590
+ const schemaEntry = variables[generateSchemaKey({
591
+ variantKey,
592
+ variantValue: variantOption,
593
+ componentStateKey,
594
+ componentStateValue: componentStateOption,
595
+ layer: layerKey,
596
+ subComponentName
597
+ })];
598
+ if (!schemaEntry) continue;
599
+ for (const propertyKey in universalLayer.properties) {
600
+ if (!schemaEntry[propertyKey]) continue;
601
+ const originalPropertyDefinition = universalLayer.properties[propertyKey];
602
+ const fallbackStateMap = variables[generateSchemaKey({
603
+ variantKey,
604
+ variantValue: variantOption,
605
+ layer: layerKey,
606
+ subComponentName
607
+ })]?.[propertyKey];
608
+ const declarations = generateDeclaration({
609
+ componentName,
610
+ subComponentName,
611
+ variantKey,
612
+ variantValue: variantOption,
613
+ componentStateKey,
614
+ componentStateValue: componentStateOption,
615
+ layer: layerKey,
616
+ layerOptionalPseudoSelector: universalLayer.pseudoSelector,
617
+ propertyKey,
618
+ originalPropertyDefinition,
619
+ declaredStates: new Set(resolvePropertyStates(universalLayer, originalPropertyDefinition)),
620
+ layerUsesAtomicStates: (universalLayer.atomicStates?.length ?? 0) > 0,
621
+ theme,
622
+ schema,
623
+ currentStyles: styles,
624
+ previewOptions,
625
+ emit,
626
+ fallbackStateMap
627
+ });
628
+ styles = deepMerge(styles, declarations);
629
+ }
630
+ }
631
+ }
632
+ return styles;
633
+ }
634
+ /**
635
+ * Emit CSS for a set of layers without a component-state segment in the
636
+ * selector. Used by both `VariantConfigWithProperties` (where layers are the
637
+ * only source of styles) and `VariantConfigWithComponentStates` (where these
638
+ * layers express the variant's universal baseline, with per-state overrides
639
+ * winning via class-compound specificity).
640
+ */
641
+ function emitUniversalLayers({ componentName, subComponentName, variantKey, variantOption, layers, schema, theme, previewOptions, emit, currentStyles, bumpRootSpecificity }) {
642
+ let styles = currentStyles;
643
+ const variables = schema.variables;
644
+ for (const layerKey in layers) {
645
+ const layer = layers[layerKey];
646
+ const schemaKey = generateSchemaKey({
647
+ variantKey,
648
+ variantValue: variantOption,
649
+ layer: layerKey,
650
+ subComponentName
651
+ });
652
+ const schemaEntry = variables?.[schemaKey];
653
+ for (const propertyKey in layer.properties) {
654
+ if (!schemaEntry || !schemaEntry[propertyKey]) continue;
655
+ const originalPropertyDefinition = layer.properties[propertyKey];
656
+ const declarations = generateDeclaration({
657
+ componentName,
658
+ subComponentName,
659
+ variantKey,
660
+ variantValue: variantOption,
661
+ layer: layerKey,
662
+ layerOptionalPseudoSelector: layer.pseudoSelector,
663
+ propertyKey,
664
+ originalPropertyDefinition,
665
+ declaredStates: new Set(resolvePropertyStates(layer, originalPropertyDefinition)),
666
+ layerUsesAtomicStates: (layer.atomicStates?.length ?? 0) > 0,
667
+ theme,
668
+ schema,
669
+ currentStyles: styles,
670
+ previewOptions,
671
+ emit,
672
+ bumpRootSpecificity
673
+ });
674
+ styles = deepMerge(styles, declarations);
675
+ }
676
+ }
677
+ return styles;
678
+ }
679
+ function generateConfigStyles(config, schema, theme, previewOptions, emit) {
470
680
  const componentName = config.label.toLowerCase();
471
681
  let styles = {};
472
682
  for (const variantKey in config.variants) {
473
683
  const variantConfig = config.variants[variantKey];
474
684
  for (const variantOption of variantConfig.options) if (isVariantConfigWithComponentStates(variantConfig)) {
685
+ if (variantConfig.layers) styles = emitUniversalLayers({
686
+ componentName,
687
+ variantKey,
688
+ variantOption,
689
+ layers: variantConfig.layers,
690
+ schema,
691
+ theme,
692
+ previewOptions,
693
+ emit,
694
+ currentStyles: styles,
695
+ bumpRootSpecificity: true
696
+ });
475
697
  const componentStates = variantConfig.componentStates;
476
698
  for (const componentStateKey in componentStates) {
477
699
  const componentState = componentStates[componentStateKey];
@@ -491,46 +713,61 @@ function generateConfigStyles(config, schema, theme, previewOptions) {
491
713
  layerOptionalPseudoSelector: layer.pseudoSelector,
492
714
  propertyKey,
493
715
  originalPropertyDefinition,
716
+ declaredStates: new Set(resolvePropertyStates(layer, originalPropertyDefinition)),
717
+ layerUsesAtomicStates: (layer.atomicStates?.length ?? 0) > 0,
494
718
  theme,
495
719
  schema,
496
720
  currentStyles: styles,
497
721
  previewOptions,
498
- excludedPseudoStates
722
+ excludedPseudoStates,
723
+ emit
499
724
  });
500
725
  styles = deepMerge(styles, declarations);
501
726
  }
502
727
  }
503
728
  }
504
729
  }
505
- } else if (isVariantConfigWithProperties(variantConfig)) {
506
- const layers = variantConfig.layers;
507
- for (const layerKey in layers) {
508
- const layer = layers[layerKey];
509
- for (const propertyKey in layer.properties) {
510
- const originalPropertyDefinition = layer.properties[propertyKey];
511
- const declarations = generateDeclaration({
512
- componentName,
513
- variantKey,
514
- variantValue: variantOption,
515
- layer: layerKey,
516
- layerOptionalPseudoSelector: layer.pseudoSelector,
517
- propertyKey,
518
- originalPropertyDefinition,
519
- theme,
520
- schema,
521
- currentStyles: styles,
522
- previewOptions
523
- });
524
- styles = deepMerge(styles, declarations);
525
- }
526
- }
527
- }
730
+ styles = emitSchemaOverrideStyles({
731
+ componentName,
732
+ variantKey,
733
+ variantOption,
734
+ variantConfig,
735
+ schema,
736
+ theme,
737
+ previewOptions,
738
+ emit,
739
+ currentStyles: styles
740
+ });
741
+ } else if (isVariantConfigWithProperties(variantConfig)) styles = emitUniversalLayers({
742
+ componentName,
743
+ variantKey,
744
+ variantOption,
745
+ layers: variantConfig.layers,
746
+ schema,
747
+ theme,
748
+ previewOptions,
749
+ emit,
750
+ currentStyles: styles
751
+ });
528
752
  }
529
753
  if (config.subComponents) {
530
754
  const { subComponents } = config;
531
755
  for (const subComponentKey in subComponents) for (const variantKey in subComponents[subComponentKey].variants) {
532
756
  const variantConfig = subComponents[subComponentKey].variants[variantKey];
533
757
  for (const variantOption of variantConfig.options) if (isVariantConfigWithComponentStates(variantConfig)) {
758
+ if (variantConfig.layers) styles = emitUniversalLayers({
759
+ componentName,
760
+ subComponentName: subComponentKey,
761
+ variantKey,
762
+ variantOption,
763
+ layers: variantConfig.layers,
764
+ schema,
765
+ theme,
766
+ previewOptions,
767
+ emit,
768
+ currentStyles: styles,
769
+ bumpRootSpecificity: true
770
+ });
534
771
  const componentStates = variantConfig.componentStates;
535
772
  for (const componentStateKey in componentStates) {
536
773
  const componentState = componentStates[componentStateKey];
@@ -551,41 +788,44 @@ function generateConfigStyles(config, schema, theme, previewOptions) {
551
788
  layerOptionalPseudoSelector: layer.pseudoSelector,
552
789
  propertyKey,
553
790
  originalPropertyDefinition,
791
+ declaredStates: new Set(resolvePropertyStates(layer, originalPropertyDefinition)),
792
+ layerUsesAtomicStates: (layer.atomicStates?.length ?? 0) > 0,
554
793
  theme,
555
794
  schema,
556
795
  currentStyles: styles,
557
796
  previewOptions,
558
- excludedPseudoStates
797
+ excludedPseudoStates,
798
+ emit
559
799
  });
560
800
  styles = deepMerge(styles, declarations);
561
801
  }
562
802
  }
563
803
  }
564
804
  }
565
- } else if (isVariantConfigWithProperties(variantConfig)) {
566
- const layers = variantConfig.layers;
567
- for (const layerKey in layers) {
568
- const layer = layers[layerKey];
569
- for (const propertyKey in layer.properties) {
570
- const originalPropertyDefinition = layer.properties[propertyKey];
571
- const declarations = generateDeclaration({
572
- componentName,
573
- subComponentName: subComponentKey,
574
- variantKey,
575
- variantValue: variantOption,
576
- layer: layerKey,
577
- layerOptionalPseudoSelector: layer.pseudoSelector,
578
- propertyKey,
579
- originalPropertyDefinition,
580
- theme,
581
- schema,
582
- currentStyles: styles,
583
- previewOptions
584
- });
585
- styles = deepMerge(styles, declarations);
586
- }
587
- }
588
- }
805
+ styles = emitSchemaOverrideStyles({
806
+ componentName,
807
+ subComponentName: subComponentKey,
808
+ variantKey,
809
+ variantOption,
810
+ variantConfig,
811
+ schema,
812
+ theme,
813
+ previewOptions,
814
+ emit,
815
+ currentStyles: styles
816
+ });
817
+ } else if (isVariantConfigWithProperties(variantConfig)) styles = emitUniversalLayers({
818
+ componentName,
819
+ subComponentName: subComponentKey,
820
+ variantKey,
821
+ variantOption,
822
+ layers: variantConfig.layers,
823
+ schema,
824
+ theme,
825
+ previewOptions,
826
+ emit,
827
+ currentStyles: styles
828
+ });
589
829
  }
590
830
  }
591
831
  /**
@@ -618,8 +858,8 @@ function generateConfigStyles(config, schema, theme, previewOptions) {
618
858
  * @param previewOptions - Options for generating preview mode class modifiers
619
859
  * @returns CSS styles object with grouped selectors for default aliases
620
860
  */
621
- const generateStyles = (config, schema, theme, previewOptions) => {
622
- const styles = generateConfigStyles(config, schema, theme, previewOptions);
861
+ const generateStylesInner = (config, schema, theme, previewOptions) => {
862
+ const styles = generateConfigStyles(config, schema, theme, previewOptions, previewOptions.emit ?? "exhaustive");
623
863
  if (!config.variants && !config.subComponents) return styles;
624
864
  const componentName = config.label.toLowerCase();
625
865
  if (componentName !== "button" && componentName !== "iconbutton") return styles;
@@ -627,14 +867,15 @@ const generateStyles = (config, schema, theme, previewOptions) => {
627
867
  /**
628
868
  * Helper: Extract all layer keys from a variant configuration
629
869
  * Handles both simple variants (with direct layers) and variants with component states
870
+ * (which may additionally declare top-level universal layers).
630
871
  */
631
872
  const getLayerKeys = (variantConfig) => {
632
- if (isVariantConfigWithProperties(variantConfig)) return Object.keys(variantConfig.layers);
633
- else if (isVariantConfigWithComponentStates(variantConfig)) {
873
+ if (isVariantConfigWithComponentStates(variantConfig)) {
634
874
  const layerKeysSet = /* @__PURE__ */ new Set();
635
- for (const componentStateConfig of Object.values(variantConfig.componentStates)) Object.keys(componentStateConfig.layers).forEach((key) => layerKeysSet.add(key));
875
+ for (const componentStateConfig of Object.values(variantConfig.componentStates)) Object.keys(componentStateConfig.layers ?? {}).forEach((key) => layerKeysSet.add(key));
876
+ if (variantConfig.layers) Object.keys(variantConfig.layers).forEach((key) => layerKeysSet.add(key));
636
877
  return Array.from(layerKeysSet);
637
- }
878
+ } else if (isVariantConfigWithProperties(variantConfig)) return Object.keys(variantConfig.layers);
638
879
  return [];
639
880
  };
640
881
  /**
@@ -684,5 +925,21 @@ const generateStyles = (config, schema, theme, previewOptions) => {
684
925
  }
685
926
  return finalStyles;
686
927
  };
928
+ /**
929
+ * Public entry point. Generates a component's CSS, emitting each declared state
930
+ * as its own rule (one selector per rule) so the cascade is carried entirely by
931
+ * per-rule specificity — which CSS minifiers preserve.
932
+ *
933
+ * An earlier optimization merged rules sharing a declaration block into a single
934
+ * comma-separated selector list (to avoid repeating invariant declarations per
935
+ * state). It was removed: a minifier's forgiving-`:is()` rewrite — applied to a
936
+ * comma-separated list that contains `:has()` when targeting browsers without
937
+ * native `:has()` support — collapses the list to its single highest
938
+ * specificity, inflating the weakest selector (`rest`) above genuinely
939
+ * customized states and corrupting the cascade. Separate rules never form such a
940
+ * list, so minifiers leave their specificity intact. (gzip already collapses the
941
+ * repeated declaration blocks, so the shipped-size cost is minimal.)
942
+ */
943
+ const generateStyles = (config, schema, theme, previewOptions) => generateStylesInner(config, schema, theme, previewOptions);
687
944
  //#endregion
688
945
  export { generateStyles };