@yahoo/uds-v5-wip 1.35.0 → 1.36.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +13 -0
  2. package/dist/config/dist/component-resolution.d.ts +1 -1
  3. package/dist/config/dist/component-resolution.js +1 -1
  4. package/dist/config/dist/consts/defaultColors.d.ts +1 -2
  5. package/dist/config/dist/createConfig.d.ts +55 -87
  6. package/dist/config/dist/createConfig.js +82 -158
  7. package/dist/config/dist/defineStyleProp.d.ts +45 -0
  8. package/dist/config/dist/defineStyleProp.js +25 -0
  9. package/dist/config/dist/index.d.ts +4 -2
  10. package/dist/config/dist/index.js +4 -3
  11. package/dist/config/dist/preset-merge.js +0 -12
  12. package/dist/config/dist/propertyAcceptedTypes.js +81 -9
  13. package/dist/config/dist/propertyGroups.d.ts +1 -11
  14. package/dist/config/dist/propertyGroups.js +1 -19
  15. package/dist/config/dist/resolveStyleProp.d.ts +55 -1
  16. package/dist/config/dist/resolveStyleProp.js +197 -2
  17. package/dist/config/dist/serialize.d.ts +11 -4
  18. package/dist/config/dist/serialize.js +3 -3
  19. package/dist/config/dist/types/css-values.d.ts +60 -0
  20. package/dist/config/dist/types.d.ts +1 -2
  21. package/dist/config.d.ts +184 -184
  22. package/dist/core/dist/color-opacity-map.d.ts +13 -0
  23. package/dist/core/dist/color-opacity-map.js +33 -0
  24. package/dist/core/dist/configurable-prop-helpers.d.ts +32 -0
  25. package/dist/core/dist/configurable-prop-helpers.js +61 -0
  26. package/dist/core/dist/getStyles.js +3 -1
  27. package/dist/core/dist/index.d.ts +4 -1
  28. package/dist/core/dist/index.js +4 -1
  29. package/dist/core/dist/modifier-mappings.d.ts +13 -0
  30. package/dist/core/dist/modifier-mappings.js +61 -0
  31. package/dist/core/dist/style-prop-data.d.ts +33 -0
  32. package/dist/{loader/dist/packages/core/dist/propMappings.js → core/dist/style-prop-data.js} +2 -93
  33. package/dist/core.d.ts +4 -1
  34. package/dist/core.js +4 -1
  35. package/dist/fixtures.d.ts +3 -1
  36. package/dist/fixtures.js +3 -1
  37. package/dist/foundational-presets/dist/boldVibrant.d.ts +573 -224
  38. package/dist/foundational-presets/dist/brutalist.d.ts +573 -224
  39. package/dist/foundational-presets/dist/candy.d.ts +573 -224
  40. package/dist/foundational-presets/dist/cleanMinimalist.d.ts +573 -224
  41. package/dist/foundational-presets/dist/corporate.d.ts +573 -224
  42. package/dist/foundational-presets/dist/darkMoody.d.ts +573 -224
  43. package/dist/foundational-presets/dist/defaultPreset.d.ts +197 -198
  44. package/dist/foundational-presets/dist/defaultPreset.js +2 -312
  45. package/dist/foundational-presets/dist/forest.d.ts +573 -224
  46. package/dist/foundational-presets/dist/highContrast.d.ts +573 -224
  47. package/dist/foundational-presets/dist/lavender.d.ts +573 -224
  48. package/dist/foundational-presets/dist/luxury.d.ts +573 -224
  49. package/dist/foundational-presets/dist/monochrome.d.ts +573 -224
  50. package/dist/foundational-presets/dist/motion.d.ts +1 -2
  51. package/dist/foundational-presets/dist/neonCyber.d.ts +573 -224
  52. package/dist/foundational-presets/dist/newspaper.d.ts +573 -224
  53. package/dist/foundational-presets/dist/ocean.d.ts +573 -224
  54. package/dist/foundational-presets/dist/slate.d.ts +573 -224
  55. package/dist/foundational-presets/dist/style-props.js +1384 -0
  56. package/dist/foundational-presets/dist/sunset.d.ts +573 -224
  57. package/dist/foundational-presets/dist/terminal.d.ts +573 -224
  58. package/dist/foundational-presets/dist/warmOrganic.d.ts +573 -224
  59. package/dist/loader/dist/loader/style-transform.js +2 -1
  60. package/dist/loader/dist/loader.d.ts +1 -2
  61. package/dist/loader/dist/next.d.ts +1 -2
  62. package/dist/loader/dist/packages/core/dist/color-opacity-map.js +33 -0
  63. package/dist/loader/dist/packages/core/dist/getStyles.js +3 -1
  64. package/dist/loader/dist/packages/core/dist/modifier-mappings.js +61 -0
  65. package/dist/{core/dist/propMappings.js → loader/dist/packages/core/dist/style-prop-data.js} +2 -150
  66. package/dist/presets/dist/boldVibrant.d.ts +1 -2
  67. package/dist/presets/dist/brutalist.d.ts +1 -2
  68. package/dist/presets/dist/candy.d.ts +1 -2
  69. package/dist/presets/dist/cleanMinimalist.d.ts +1 -2
  70. package/dist/presets/dist/corporate.d.ts +1 -2
  71. package/dist/presets/dist/darkMoody.d.ts +1 -2
  72. package/dist/presets/dist/defaultPreset.d.ts +1 -2
  73. package/dist/presets/dist/forest.d.ts +1 -2
  74. package/dist/presets/dist/highContrast.d.ts +1 -2
  75. package/dist/presets/dist/lavender.d.ts +1 -2
  76. package/dist/presets/dist/luxury.d.ts +1 -2
  77. package/dist/presets/dist/monochrome.d.ts +1 -2
  78. package/dist/presets/dist/neonCyber.d.ts +1 -2
  79. package/dist/presets/dist/newspaper.d.ts +1 -2
  80. package/dist/presets/dist/ocean.d.ts +1 -2
  81. package/dist/presets/dist/slate.d.ts +1 -2
  82. package/dist/presets/dist/sunset.d.ts +1 -2
  83. package/dist/presets/dist/terminal.d.ts +1 -2
  84. package/dist/presets/dist/warmOrganic.d.ts +1 -2
  85. package/dist/remotion/dist/components/image-slide.d.ts +1 -2
  86. package/dist/remotion/dist/components/lower-third.d.ts +1 -2
  87. package/dist/remotion/dist/components/quote-card.d.ts +1 -2
  88. package/dist/remotion/dist/components/split-screen.d.ts +1 -2
  89. package/dist/remotion/dist/components/stat-card.d.ts +1 -2
  90. package/dist/remotion/dist/components/text-overlay.d.ts +1 -2
  91. package/dist/remotion/dist/components/title-card.d.ts +1 -2
  92. package/dist/remotion/dist/components/typing-text.d.ts +1 -2
  93. package/dist/tsconfig.tsbuildinfo +1 -1
  94. package/package.json +3 -3
  95. package/dist/core/dist/propMappings.d.ts +0 -77
@@ -0,0 +1,13 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
+ return target;
11
+ };
12
+ //#endregion
13
+ export { __exportAll };
@@ -1 +1 @@
1
- export { };
1
+ import { ComponentsConfig } from "@uds/types";
@@ -1,4 +1,4 @@
1
- import { propMappings } from "../../core/dist/propMappings.js";
1
+ import { propMappings } from "../../core/dist/style-prop-data.js";
2
2
  import "../../core/dist/index.js";
3
3
  //#region ../config/dist/component-resolution.js
4
4
  /**
@@ -1,5 +1,4 @@
1
1
  //#region ../config/dist/consts/defaultColors.d.ts
2
- //#region src/consts/defaultColors.d.ts
3
2
  declare const defaultColors: {
4
3
  inherit: string;
5
4
  current: string;
@@ -248,6 +247,6 @@ declare const defaultColors: {
248
247
  'rose-800': string;
249
248
  'rose-900': string;
250
249
  'rose-950': string;
251
- }; //#endregion
250
+ };
252
251
  //#endregion
253
252
  export { defaultColors };
@@ -1,9 +1,9 @@
1
- import { PropertyGroupId } from "./propertyGroups.js";
1
+ import { AnyStyleProp } from "./defineStyleProp.js";
2
+ import { ResolvedStyleProp } from "./resolveStyleProp.js";
2
3
  import { TokenType, VarsConfig } from "./types.js";
3
- import { BaseModifierProp, ComponentsConfig, CompositeStylesConfig, ConfigurableProp, ModifierProp, MotionPreset, RemotionComponentDef, RemotionConfig, RemotionTransitionDef, StyleProp } from "@uds/types";
4
+ import { BaseModifierProp, ComponentsConfig, CompositeStylesConfig, ConfigurableProp, ModifierProp, MotionPreset, RemotionComponentDef, RemotionConfig, RemotionTransitionDef } from "@uds/types";
4
5
 
5
6
  //#region ../config/dist/createConfig.d.ts
6
- //#region src/createConfig.d.ts
7
7
  type MotionPresetsDef = Record<string, MotionPreset>;
8
8
  type MotionAliasValue<TMotion> = TMotion extends Record<string, infer V> ? Extract<V, string> : never;
9
9
  type EmptyMotion = {};
@@ -76,22 +76,12 @@ type GetModifierFromInput<I extends ModesInput> = { [SetKey in keyof I]: { [OptK
76
76
  } ? M extends ModifierNameShape ? M : never : OptKey extends string ? `_${OptKey}` : never }[keyof I[SetKey]['options']] }[keyof I];
77
77
  /** Reject any input whose derived/explicit modifiers collide with reserved names. */
78
78
  type CheckForReservedModifiersInput<I extends ModesInput> = true extends HasReservedModifier<GetModifierFromInput<I>> ? 'ERROR: Cannot use reserved modifier names from ModifierProp. Please use a different modifier name.' : I;
79
- /**
80
- * Convert the authored object-keyed input into the internal `ModeGroup[]` shape.
81
- * Derives `_${optionKey}` modifiers when no explicit `modifier` is provided.
82
- * Never sets `default: true` — the new API has no concept of a default option;
83
- * downstream consumers treat "no option active" as the implicit default.
84
- */
85
79
  interface ModifierDef {
86
80
  modifier: ModifierNameShape;
87
81
  selector: string;
88
82
  /** Description for AI prompt generation (e.g. "Apply styles on elevation-1 surfaces") */
89
83
  description?: string;
90
84
  }
91
- interface ArbitraryTokenGroup {
92
- properties: string[];
93
- pattern: string | string[];
94
- }
95
85
  type AtomicTokenValue<M extends ModifierNameShape> = {
96
86
  name: string;
97
87
  value: string;
@@ -151,29 +141,20 @@ interface AtomicToken<M extends ModifierNameShape = ModifierNameShape> {
151
141
  */
152
142
  cssPrefix?: string;
153
143
  }
154
- /** Merge two token structures */
155
- type MergeTokens<A, B> = { [K in keyof A | keyof B]: K extends keyof B ? K extends keyof A ? A[K] & B[K] : B[K] : K extends keyof A ? A[K] : never };
156
- /**
157
- * Derive token types directly from defineVars namespaces. Each var namespace
158
- * key becomes a property on `tokens.*` with the namespace's token names.
159
- *
160
- * NOTE: We intentionally do NOT add a `Record<string, Record<string, string>>`
161
- * index-signature fallback here. The fallback used to support property-name
162
- * access (e.g. `tokens.borderRadius.*` for the `radius` namespace scoped to
163
- * `borderRadius`), but it caused TypeScript to silently widen every
164
- * `tokens.<ns>.<name>` access to `string` — typos like
165
- * `tokens.borderColor.aksjdf` would not be flagged. With the fallback removed,
166
- * accesses must use the defineVars namespace key (e.g. `tokens.radius.full`,
167
- * not `tokens.borderRadius.full`); both forms remain valid at runtime.
168
- */
169
- type VarsToTokens<TVars extends VarsConfig> = { [K in keyof TVars]: { [T in Exclude<keyof TVars[K], '$type' | '$description'>]: string } };
170
144
  /** Empty tokens type for initial state */
171
145
  type EmptyTokens = {};
172
146
  /** Empty vars type for initial state */
173
147
  type EmptyVars = {};
148
+ /**
149
+ * Derive the runtime `tokens` accessor type from a `defineVars` map. Each
150
+ * namespace becomes `tokens[ns][tokenName] = string`. `$type` /
151
+ * `$description` keys are excluded — they're authoring metadata, not tokens.
152
+ */
153
+ type VarsToTokens<TVars extends VarsConfig> = { [K in keyof TVars]: { [T in Exclude<keyof TVars[K], '$type' | '$description'>]: string } };
154
+ /** Shallow merge of two token-shape records (later wins on collisions). */
155
+ type MergeTokens<A, B> = { [K in keyof A | keyof B]: K extends keyof B ? K extends keyof A ? A[K] & B[K] : B[K] : K extends keyof A ? A[K] : never };
174
156
  /** Build a structured token reference object from atomic tokens */
175
157
  declare function buildTokenReference(atomic: AtomicToken<ModifierNameShape>[], configPrefix: string): Record<string, Record<string, string>>;
176
- /** Build a structured composite-styles reference object for use in defineModifiers context */
177
158
  /** Global styles definition — CSS selector → style props */
178
159
  type GlobalStylesDef = Record<string, Record<string, any>>;
179
160
  /** CSS properties for the example wrapper element */
@@ -203,23 +184,10 @@ interface UdsConfigData {
203
184
  preflight: boolean;
204
185
  prefix: string;
205
186
  remotion?: RemotionConfig;
206
- arbitraryTokens?: ArbitraryTokenGroup[];
207
187
  buildOptions?: BuildOptions;
208
188
  examples?: Record<string, ExampleDef>;
209
189
  designPrinciples?: string[];
210
190
  vars?: VarsConfig;
211
- /**
212
- * Map each ConfigurableProp to its generated CSS class prefix.
213
- * Set via `defineClassNames()`. Falls back to kebab-case of the property name.
214
- */
215
- classNames?: Record<string, string>;
216
- /**
217
- * Map each var namespace to the property group IDs it feeds.
218
- * Set via `defineScopes()`. This is the canonical source for
219
- * "which tokens can this property use" — the Studio UI reads and
220
- * edits this via draft patches.
221
- */
222
- scopes?: Record<string, string[]>;
223
191
  /**
224
192
  * Token names contributed by any composed preset, keyed by namespace.
225
193
  *
@@ -232,6 +200,23 @@ interface UdsConfigData {
232
200
  * perspective.
233
201
  */
234
202
  presetTokenNames?: Record<string, string[]>;
203
+ /**
204
+ * Style props registered via `.registerStyleProps([...])`. Authored
205
+ * elsewhere via `defineStyleProp(...)` and imported into the config.
206
+ * The canonical input for codegen + runtime in the new architecture.
207
+ *
208
+ * Map keyed by JSX prop name (e.g. `bg`, `padding`); each value is the
209
+ * style-prop record carrying `cssProperty`, `classPrefix`, `values`, etc.
210
+ */
211
+ styleProps?: Record<string, AnyStyleProp>;
212
+ /**
213
+ * Resolved style props — every registered style prop run through
214
+ * `resolveStyleProp(propName, prop, config)` at `resolveConfig` time.
215
+ * Each entry carries the prop's filtered token list, literal keywords,
216
+ * arbitrary spec, and metadata. Codegen + runtime consume this instead
217
+ * of walking the raw style-prop records.
218
+ */
219
+ resolvedStyleProps?: ResolvedStyleProp[];
235
220
  }
236
221
  interface ComponentConfig<TComponents extends ComponentsConfig<string> = ComponentsConfig<string>, TMotion extends MotionPresetsDef | undefined = MotionPresetsDef | undefined> {
237
222
  name?: string;
@@ -273,7 +258,31 @@ interface UdsConfig<TModifier extends ModifierNameShape = ModifierProp, TTokens
273
258
  defineCompositeStyles<const M extends CompositeStylesConfig>(params: M | ((ctx: {
274
259
  tokens: TTokens;
275
260
  }) => M)): ConfigResult<TModifier, TTokens, TMotion, TExt, TCompositeStyles & M, TModeModifiers, TVars>;
276
- defineArbitraryTokens(params: ArbitraryTokenGroup[]): ConfigResult<TModifier, TTokens, TMotion, TExt, TCompositeStyles, TModeModifiers, TVars>;
261
+ /**
262
+ * Register style props, keyed by the JSX prop name consumers will use.
263
+ * Calls accumulate — later `.registerStyleProps({...})` calls merge into
264
+ * the existing map (later keys overwrite earlier ones with the same name).
265
+ *
266
+ * @example
267
+ * ```ts
268
+ * uds.registerStyleProps({
269
+ * bg: {
270
+ * cssProperty: 'background-color',
271
+ * classPrefix: 'bg',
272
+ * values: ['{global}', '{spectrum}', '{bg}'],
273
+ * label: 'Background',
274
+ * },
275
+ * padding: {
276
+ * cssProperty: 'padding',
277
+ * classPrefix: 'p',
278
+ * arbitrary: 'length-percentage',
279
+ * values: ['{spacing}'],
280
+ * label: 'Padding',
281
+ * },
282
+ * });
283
+ * ```
284
+ */
285
+ registerStyleProps<const Props extends Record<string, AnyStyleProp>>(props: Props): ConfigResult<TModifier, TTokens, TMotion, TExt, TCompositeStyles, TModeModifiers, TVars>;
277
286
  defineMotion<const M extends MotionPresetsDef>(presets: M | ((tokens: TTokens) => M)): ConfigResult<TModifier, TTokens, { [K in keyof M]: string }, TExt, TCompositeStyles, TModeModifiers, TVars>;
278
287
  defineComponents(params: ComponentsConfig<MotionAliasValue<TMotion> | string> | ((ctx: {
279
288
  tokens: TTokens;
@@ -299,52 +308,11 @@ interface UdsConfig<TModifier extends ModifierNameShape = ModifierProp, TTokens
299
308
  defineRemotionTransitions(params: Record<string, RemotionTransitionDef> | ((ctx: {
300
309
  tokens: TTokens;
301
310
  }) => Record<string, RemotionTransitionDef>)): ConfigResult<TModifier, TTokens, TMotion, TExt, TCompositeStyles, TModeModifiers, TVars>;
302
- defineVars<const TVarsNew extends VarsConfig<[TModeModifiers] extends [never] ? `_${string}` : TModeModifiers>>(vars: TVarsNew): ConfigResult<TModifier, TTokens, TMotion, TExt, TCompositeStyles, TModeModifiers, TVars & TVarsNew>;
303
- /**
304
- * Map each ConfigurableProp to a CSS class prefix.
305
- * Falls back to kebab-case of the property name when not specified.
306
- * Typically called once by the foundational preset — consumers rarely touch this.
307
- *
308
- * @example
309
- * ```ts
310
- * uds.defineClassNames({
311
- * color: 'text',
312
- * bg: 'bg',
313
- * borderColor: 'border-color',
314
- * spacing: 'p',
315
- * gap: 'gap',
316
- * borderRadius: 'rounded',
317
- * })
318
- * ```
319
- */
320
- defineClassNames(classNames: { [K in StyleProp]?: string }): ConfigResult<TModifier, TTokens, TMotion, TExt, TCompositeStyles, TModeModifiers, TVars>;
321
- /**
322
- * Map var namespaces to property groups, defining which tokens each property
323
- * group can reference. This is the canonical scope definition — the Studio UI
324
- * renders it as checkboxes per token group.
325
- *
326
- * @example
327
- * ```ts
328
- * uds
329
- * .defineVars({
330
- * color: { brand: { value: '#1167f4' } },
331
- * spacing: { sm: { value: '4px' } },
332
- * })
333
- * .defineScopes({
334
- * color: ['textColor', 'background', 'borderColor', 'ringColor'],
335
- * spacing: ['padding', 'gap', 'margin'],
336
- * })
337
- * ```
338
- */
339
- defineScopes(scopes: [keyof TVars] extends [never] ? Record<string, PropertyGroupId[]> : { [K in keyof TVars]?: PropertyGroupId[] }): ConfigResult<TModifier, MergeTokens<TTokens, VarsToTokens<TVars>>, TMotion, TExt, TCompositeStyles, TModeModifiers, TVars>;
311
+ defineVars<const TVarsNew extends VarsConfig<[TModeModifiers] extends [never] ? `_${string}` : TModeModifiers>>(vars: TVarsNew): ConfigResult<TModifier, MergeTokens<TTokens, VarsToTokens<TVars & TVarsNew>>, TMotion, TExt, TCompositeStyles, TModeModifiers, TVars & TVarsNew>;
340
312
  }
341
313
  type AnyUdsConfig = UdsConfig<ModifierNameShape, any, any, any, any, any, any>;
342
314
  /** Extract the raw config data from a builder instance */
343
315
  declare function resolveConfig(config: AnyUdsConfig): UdsConfigData;
344
- /**
345
- * Resolve configuration with all token references replaced by their raw values.
346
- * Useful for tools that need the actual values (e.g. anatomy generation).
347
- */
348
316
  declare function createConfigBuilder<TModifier extends ModifierNameShape = ModifierProp, TTokens = EmptyTokens, TMotion = EmptyMotion, TExt extends Record<string, any> = {}, TCompositeStyles = EmptyCompositeStyles, TModeModifiers extends ModifierNameShape = never, TVars extends VarsConfig = EmptyVars>(data: UdsConfigData, extensions?: TExt): UdsConfig<TModifier, TTokens, TMotion, TExt, TCompositeStyles, TModeModifiers, TVars> & TExt;
349
317
  interface InterpolateMarker {
350
318
  __type: 'interpolate';
@@ -354,4 +322,4 @@ interface InterpolateMarker {
354
322
  declare function darker(color: string, amount: number): string;
355
323
  declare function lighter(color: string, amount: number): string;
356
324
  //#endregion
357
- export { ArbitraryTokenGroup, AtomicToken, BuildOptions, CheckForReservedModifiersInput, ComponentConfig, DefineComponentInput, DefineComponentMotionInput, ExampleDef, ExampleEntryDef, ExampleLayoutStyles, GetModifierFromInput, GlobalStylesDef, InterpolateMarker, ModeGroup, ModeOption, ModeOptionInput, ModeSetInput, ModesInput, ModifierDef, MotionPresetsDef, UdsConfig, UdsConfigData, buildTokenReference, createConfigBuilder, darker, lighter, resolveConfig };
325
+ export { AtomicToken, BuildOptions, CheckForReservedModifiersInput, ComponentConfig, DefineComponentInput, DefineComponentMotionInput, ExampleDef, ExampleEntryDef, ExampleLayoutStyles, GetModifierFromInput, GlobalStylesDef, InterpolateMarker, ModeGroup, ModeOption, ModeOptionInput, ModeSetInput, ModesInput, ModifierDef, MotionPresetsDef, UdsConfig, UdsConfigData, buildTokenReference, createConfigBuilder, darker, lighter, resolveConfig };
@@ -1,11 +1,11 @@
1
1
  import { kebabCase } from "../../utils/dist/string-utils/kebabCase.js";
2
2
  import { safeTokenName } from "../../utils/dist/string-utils/cssVar.js";
3
3
  import "../../utils/dist/index.js";
4
- import { getConfigurablePropMapping } from "../../core/dist/propMappings.js";
4
+ import { getConfigurablePropMapping } from "../../core/dist/configurable-prop-helpers.js";
5
5
  import "../../core/dist/index.js";
6
6
  import { buildMotionReference, resolveComponentMotionAliases, validateComponentVariants } from "./component-resolution.js";
7
- import { expandPropertyGroups } from "./propertyGroups.js";
8
7
  import { resolveTokenType, sniffTokenTypeFromValue } from "./resolveTokenTypes.js";
8
+ import { resolveStyleProp } from "./resolveStyleProp.js";
9
9
  import { applyPresetToData, deepMerge, mergeAtomic } from "./preset-merge.js";
10
10
  //#region ../config/dist/createConfig.js
11
11
  /** biome-ignore-all lint/suspicious/noExplicitAny: necessary for dynamic builder to work correctly */
@@ -138,44 +138,59 @@ function varGroupToTokens(varGroup, knownModifiers) {
138
138
  };
139
139
  }
140
140
  /**
141
- * Sort properties so the one matching the cssPrefix comes last.
142
- * `buildVarToTokenMap` uses "last wins", so this ensures e.g. `color.brand`
143
- * beats `shadowColor.brand` when both reference `var(--uds-color-brand)`.
141
+ * For each var namespace, derive the list of style-prop names that consume
142
+ * it by inverting `registerStyleProps(...).values`. A styleProp with
143
+ * `values: ['{bg}', '{global}']` is recorded as consuming `bg` and `global`;
144
+ * a `{ ref: '{bg}', namespace: 'background' }` namespaced ref counts the
145
+ * same. Token-key refs like `'{spacing.4}'` also count toward `spacing`.
144
146
  */
145
- function sortPropertiesByPrefixMatch(properties, namespace, cssPfx) {
146
- return properties.slice().sort((a, b) => {
147
- return (a === namespace || kebabCase(a) === cssPfx ? 1 : 0) - (b === namespace || kebabCase(b) === cssPfx ? 1 : 0);
148
- });
147
+ function buildNamespaceConsumers(styleProps) {
148
+ const result = /* @__PURE__ */ new Map();
149
+ if (!styleProps) return result;
150
+ const refRe = /^\{([^.{}]+)/;
151
+ const addConsumer = (namespace, propName) => {
152
+ const list = result.get(namespace);
153
+ if (!list) {
154
+ result.set(namespace, [propName]);
155
+ return;
156
+ }
157
+ if (!list.includes(propName)) list.push(propName);
158
+ };
159
+ for (const [propName, prop] of Object.entries(styleProps)) for (const entry of prop.values ?? []) {
160
+ let raw;
161
+ if (typeof entry === "string") raw = entry;
162
+ else if (entry !== null && typeof entry === "object" && "ref" in entry && typeof entry.ref === "string") raw = entry.ref;
163
+ if (!raw) continue;
164
+ const match = refRe.exec(raw);
165
+ if (!match || !match[1]) continue;
166
+ addConsumer(match[1], propName);
167
+ }
168
+ return result;
149
169
  }
150
170
  /**
151
- * Synthesize AtomicToken[] from defineScopes + defineVars data.
152
- *
153
- * For each namespace in `scopes`, expands property group IDs into
154
- * ConfigurableProps, extracts tokens from the matching var namespace,
155
- * and produces an AtomicToken group.
171
+ * Synthesize AtomicToken[] from defineVars + registerStyleProps data. For
172
+ * each var namespace, emits an AtomicToken group whose `properties` list is
173
+ * the set of style props that reference that namespace (or any key inside
174
+ * it) via their `values` field. Replaces the older
175
+ * `synthesizeAtomicFromScopesAndVars` once a config has retired
176
+ * `defineScopes` in favor of per-prop `defineStyleProp({ values })`.
156
177
  */
157
- function synthesizeAtomicFromScopesAndVars(vars, scopes, modes) {
178
+ function synthesizeAtomicFromVarsAndStyleProps(vars, styleProps, modes) {
158
179
  const knownModifiers = /* @__PURE__ */ new Set();
159
180
  for (const mode of modes) for (const option of mode.options) knownModifiers.add(option.modifier);
181
+ const consumers = buildNamespaceConsumers(styleProps);
160
182
  const result = [];
161
- for (const [namespace, groupIds] of Object.entries(scopes)) {
162
- const varGroup = vars[namespace];
163
- if (!varGroup) continue;
164
- const properties = expandPropertyGroups(groupIds);
165
- if (properties.length === 0) continue;
183
+ for (const [namespace, varGroup] of Object.entries(vars)) {
166
184
  const { tokens, groupType, groupDescription } = varGroupToTokens(varGroup, knownModifiers);
167
- const cssPfx = (properties.includes(namespace) ? getConfigurablePropMapping(namespace) : void 0)?.defaultVarPrefix ?? kebabCase(namespace);
168
- const sorted = sortPropertiesByPrefixMatch(properties, namespace, cssPfx);
169
- const resolvedGroupType = resolveTokenType({
170
- explicit: groupType,
171
- scopes: groupIds
172
- });
185
+ const properties = consumers.get(namespace) ?? [];
186
+ const cssPfx = kebabCase(namespace);
187
+ const resolvedGroupType = resolveTokenType({ explicit: groupType });
173
188
  if (resolvedGroupType && resolvedGroupType !== "string") for (const token of tokens) {
174
189
  if (token.type) continue;
175
190
  if (sniffTokenTypeFromValue(token.value) === "string") token.type = "string";
176
191
  }
177
192
  result.push({
178
- properties: sorted,
193
+ properties,
179
194
  tokens,
180
195
  namespace,
181
196
  cssPrefix: cssPfx,
@@ -183,65 +198,6 @@ function synthesizeAtomicFromScopesAndVars(vars, scopes, modes) {
183
198
  ...groupDescription ? { description: groupDescription } : {}
184
199
  });
185
200
  }
186
- return disambiguateOverlappingProperties(result, scopes);
187
- }
188
- /**
189
- * When multiple scope namespaces reference the **same** property group
190
- * (e.g. `rotate`, `scale`, `skew`, `translate` all mapping to `['transform']`),
191
- * each namespace's AtomicToken gets ALL properties from that group, causing
192
- * last-write-wins collisions in CSS generation.
193
- *
194
- * This function partitions those shared-group properties among namespaces
195
- * using longest camelCase prefix matching. Cross-group overlaps (e.g.
196
- * `color` and `bg` both including the `bg` property via different groups)
197
- * are intentional cascading and left untouched.
198
- */
199
- function disambiguateOverlappingProperties(tokens, scopes) {
200
- const groupToNamespaces = /* @__PURE__ */ new Map();
201
- for (const [ns, groupIds] of Object.entries(scopes)) for (const gid of groupIds) {
202
- const list = groupToNamespaces.get(gid) ?? [];
203
- list.push(ns);
204
- groupToNamespaces.set(gid, list);
205
- }
206
- const contestedGroups = /* @__PURE__ */ new Map();
207
- for (const [gid, nsList] of groupToNamespaces) if (nsList.length > 1) contestedGroups.set(gid, nsList);
208
- if (contestedGroups.size === 0) return tokens;
209
- const propOwner = /* @__PURE__ */ new Map();
210
- for (const [gid, nsList] of contestedGroups) {
211
- const groupProps = expandPropertyGroups([gid]);
212
- const assignments = /* @__PURE__ */ new Map();
213
- const nsWithMatch = /* @__PURE__ */ new Set();
214
- for (const prop of groupProps) {
215
- let bestNs = "";
216
- let bestLen = 0;
217
- for (const ns of nsList) if (prop === ns || prop.startsWith(ns) && prop.length > ns.length) {
218
- if (ns.length > bestLen) {
219
- bestNs = ns;
220
- bestLen = ns.length;
221
- }
222
- }
223
- if (bestNs) {
224
- assignments.set(prop, bestNs);
225
- nsWithMatch.add(bestNs);
226
- }
227
- }
228
- if (nsWithMatch.size < 2) continue;
229
- for (const [prop, ns] of assignments) propOwner.set(prop, ns);
230
- }
231
- if (propOwner.size === 0) return tokens;
232
- const namespaces = Object.keys(scopes);
233
- const result = [];
234
- for (const token of tokens) {
235
- const ns = namespaces.find((n) => token.cssPrefix === kebabCase(n)) ?? "";
236
- const filtered = token.properties.filter((prop) => {
237
- const owner = propOwner.get(prop);
238
- return !owner || owner === ns;
239
- });
240
- if (filtered.length > 0) result.push({
241
- ...token,
242
- properties: filtered
243
- });
244
- }
245
201
  return result;
246
202
  }
247
203
  /** Extract the raw config data from a builder instance */
@@ -258,24 +214,32 @@ function resolveConfig(config) {
258
214
  globalStyles: config.globalStyles ?? {},
259
215
  preflight: config.preflight ?? true,
260
216
  prefix: config.prefix ?? "uds",
261
- arbitraryTokens: config.arbitraryTokens,
262
217
  remotion: config.remotion,
263
218
  buildOptions: config.buildOptions,
264
219
  examples: config.examples,
265
220
  designPrinciples: config.designPrinciples,
266
221
  vars: config.vars,
267
- classNames: config.classNames,
268
- scopes: config.scopes,
269
- presetTokenNames: config.presetTokenNames
222
+ presetTokenNames: config.presetTokenNames,
223
+ styleProps: config.styleProps
270
224
  };
271
- if (configData.vars && configData.scopes) {
272
- const synthesized = synthesizeAtomicFromScopesAndVars(configData.vars, configData.scopes, configData.modes);
225
+ if (configData.vars) {
226
+ const synthesized = synthesizeAtomicFromVarsAndStyleProps(configData.vars, configData.styleProps, configData.modes);
273
227
  const atomic = mergeAtomic(configData.atomic, synthesized, "merge");
274
228
  configData = {
275
229
  ...configData,
276
230
  atomic
277
231
  };
278
232
  }
233
+ if (configData.styleProps) {
234
+ const entries = Object.entries(configData.styleProps);
235
+ if (entries.length > 0) {
236
+ const resolved = entries.map(([propName, prop]) => resolveStyleProp(propName, prop, configData));
237
+ configData = {
238
+ ...configData,
239
+ resolvedStyleProps: resolved
240
+ };
241
+ }
242
+ }
279
243
  return configData;
280
244
  }
281
245
  function mergeRemotionConfig(existing, incoming) {
@@ -321,13 +285,10 @@ function resolvePresetData(input) {
321
285
  globalStyles: input.globalStyles ?? {},
322
286
  preflight: input.preflight ?? true,
323
287
  prefix: input.prefix ?? "uds",
324
- arbitraryTokens: input.arbitraryTokens,
325
288
  remotion: input.remotion,
326
289
  examples: input.examples,
327
290
  designPrinciples: input.designPrinciples,
328
291
  vars: input.vars,
329
- classNames: input.classNames,
330
- scopes: input.scopes,
331
292
  presetTokenNames: input.presetTokenNames
332
293
  };
333
294
  }
@@ -335,52 +296,32 @@ function extractVarReferences(value) {
335
296
  if (typeof value !== "string") return [];
336
297
  return value.match(/var\([^()]+\)/g) ?? [];
337
298
  }
338
- function collectRequiredTokensFromObject(value, varToToken, out) {
299
+ function collectRequiredTokensFromObject(value, out) {
339
300
  if (value == null) return;
340
301
  if (typeof value === "string") {
341
302
  const refs = extractVarReferences(value);
342
- for (const ref of refs) {
343
- const token = varToToken.get(ref);
344
- if (token) out.add(token);
345
- }
303
+ for (const ref of refs) out.add(ref);
346
304
  return;
347
305
  }
348
306
  if (Array.isArray(value)) {
349
- for (const item of value) collectRequiredTokensFromObject(item, varToToken, out);
307
+ for (const item of value) collectRequiredTokensFromObject(item, out);
350
308
  return;
351
309
  }
352
- if (typeof value === "object") for (const child of Object.values(value)) collectRequiredTokensFromObject(child, varToToken, out);
353
- }
354
- function buildVarToTokenMap(data) {
355
- const tokenReference = buildTokenReference(data.atomic, data.prefix);
356
- const map = /* @__PURE__ */ new Map();
357
- for (const [prop, tokens] of Object.entries(tokenReference)) for (const [tokenName, tokenRef] of Object.entries(tokens)) map.set(tokenRef, `${prop}.${tokenName}`);
358
- return map;
310
+ if (typeof value === "object") for (const child of Object.values(value)) collectRequiredTokensFromObject(child, out);
359
311
  }
360
- function collectRequiredTokens(sourceData, components, motion) {
312
+ /**
313
+ * Collect the set of `var(--uds-X-Y)` references a component preset uses, so
314
+ * downstream `compose()` calls can verify the target config emits those
315
+ * variables. Storing raw var refs (instead of `propName.tokenKey` pairs)
316
+ * decouples the check from prop/namespace association lookups — only the
317
+ * actual CSS variable surface needs to be compatible.
318
+ */
319
+ function collectRequiredTokens(_sourceData, components, motion) {
361
320
  const out = /* @__PURE__ */ new Set();
362
- const varToToken = buildVarToTokenMap(sourceData);
363
- collectRequiredTokensFromObject(components, varToToken, out);
364
- if (motion) collectRequiredTokensFromObject(motion, varToToken, out);
321
+ collectRequiredTokensFromObject(components, out);
322
+ if (motion) collectRequiredTokensFromObject(motion, out);
365
323
  return Array.from(out).sort();
366
324
  }
367
- function availableTokenNames(data) {
368
- const names = /* @__PURE__ */ new Set();
369
- for (const group of data.atomic) for (const token of group.tokens) {
370
- for (const prop of group.properties) names.add(`${prop}.${token.name}`);
371
- if (group.cssPrefix) names.add(`${group.cssPrefix}.${token.name}`);
372
- if (group.namespace && group.namespace !== group.cssPrefix) names.add(`${group.namespace}.${token.name}`);
373
- }
374
- return names;
375
- }
376
- function validatePresetRequiredTokens(base, preset) {
377
- if (preset.requiredTokens.length === 0) return;
378
- const available = availableTokenNames(base);
379
- const missing = preset.requiredTokens.filter((name) => !available.has(name));
380
- if (missing.length === 0) return;
381
- const presetLabel = preset.name ? `"${preset.name}"` : "component preset";
382
- throw new Error(`Cannot compose ${presetLabel}: missing required tokens in current preset: ${missing.join(", ")}`);
383
- }
384
325
  function buildComponentsAccessor(components) {
385
326
  const accessor = {};
386
327
  for (const [name, config] of Object.entries(components)) {
@@ -477,8 +418,14 @@ function createConfigBuilder(data, extensions) {
477
418
  }
478
419
  }, extensions);
479
420
  },
480
- defineArbitraryTokens(params) {
481
- return next({ arbitraryTokens: [...data.arbitraryTokens ?? [], ...params] });
421
+ registerStyleProps(props) {
422
+ const mergedStyleProps = {
423
+ ...data.styleProps ?? {},
424
+ ...props
425
+ };
426
+ const updates = { styleProps: mergedStyleProps };
427
+ if (data.vars) updates.atomic = mergeAtomic([], synthesizeAtomicFromVarsAndStyleProps(data.vars, mergedStyleProps, data.modes ?? []), "override");
428
+ return next(updates);
482
429
  },
483
430
  defineMotion(presets) {
484
431
  const tokenReference = buildTokenReference(data.atomic, data.prefix);
@@ -532,7 +479,6 @@ function createConfigBuilder(data, extensions) {
532
479
  },
533
480
  compose(...presets) {
534
481
  return createConfigBuilder(presets.reduce((acc, preset) => {
535
- if (isComponentDefinition(preset)) validatePresetRequiredTokens(acc, preset);
536
482
  return applyPresetToData(acc, resolvePresetData(preset));
537
483
  }, data), extensions);
538
484
  },
@@ -572,7 +518,6 @@ function createConfigBuilder(data, extensions) {
572
518
  globalStyles: input.globalStyles ?? data.globalStyles,
573
519
  preflight: input.preflight ?? data.preflight,
574
520
  prefix: input.prefix ?? data.prefix,
575
- arbitraryTokens: input.arbitraryTokens ?? data.arbitraryTokens,
576
521
  examples: input.examples ?? data.examples,
577
522
  designPrinciples: input.designPrinciples ?? data.designPrinciples,
578
523
  vars: input.vars ?? data.vars,
@@ -655,32 +600,11 @@ function createConfigBuilder(data, extensions) {
655
600
  ...merged[namespace] ?? {},
656
601
  ...group
657
602
  };
658
- const updates = { vars: merged };
659
- if (data.scopes && Object.keys(data.scopes).length > 0) {
660
- const synthesized = synthesizeAtomicFromScopesAndVars(merged, data.scopes, data.modes ?? []);
661
- updates.atomic = mergeAtomic(data.atomic, synthesized, "merge");
662
- }
663
- return createConfigBuilder({
664
- ...data,
665
- ...updates
666
- }, extensions);
667
- },
668
- defineClassNames(classNames) {
669
- return next({ classNames: {
670
- ...data.classNames,
671
- ...classNames
672
- } });
673
- },
674
- defineScopes(scopes) {
675
- const mergedScopes = {
676
- ...data.scopes,
677
- ...scopes
603
+ const synthesized = synthesizeAtomicFromVarsAndStyleProps(merged, data.styleProps, data.modes ?? []);
604
+ const updates = {
605
+ vars: merged,
606
+ atomic: mergeAtomic(data.atomic, synthesized, "merge")
678
607
  };
679
- const updates = { scopes: mergedScopes };
680
- if (data.vars && Object.keys(data.vars).length > 0) {
681
- const synthesized = synthesizeAtomicFromScopesAndVars(data.vars, mergedScopes, data.modes ?? []);
682
- updates.atomic = mergeAtomic(data.atomic ?? [], synthesized, "merge");
683
- }
684
608
  return createConfigBuilder({
685
609
  ...data,
686
610
  ...updates
@@ -0,0 +1,45 @@
1
+ import { CssValue, CssValueTypeName } from "./types/css-values.js";
2
+
3
+ //#region ../config/dist/defineStyleProp.d.ts
4
+ /** Runtime input type for `toCss` based on the entry's `type`. */
5
+ type ArbitraryRuntimeValue<T extends CssValueTypeName> = T extends 'integer' | 'number' ? number : string;
6
+ /**
7
+ * One entry in a multi-shape `arbitrary` array. The first entry whose `type`
8
+ * (or `pattern`, for `'regex'`) matches the runtime value wins.
9
+ */
10
+ type ArbitraryEntry = { [T in CssValueTypeName]: {
11
+ type: T;
12
+ toCss?: (value: ArbitraryRuntimeValue<T>) => string;
13
+ } }[CssValueTypeName] | {
14
+ type: 'regex';
15
+ pattern: RegExp;
16
+ toCss?: (value: string) => string;
17
+ };
18
+ /**
19
+ * Shape of the `arbitrary` field on a style prop:
20
+ * - A bare value-type name (`'length-percentage'`, `'color'`, etc.) for the
21
+ * single-shape case.
22
+ * - An array of {@link ArbitraryEntry} for multi-shape acceptance.
23
+ */
24
+ type ArbitrarySpec = CssValueTypeName | readonly ArbitraryEntry[];
25
+ type StylePropMetadata = {
26
+ label?: string;
27
+ description?: string;
28
+ };
29
+ /**
30
+ * Structurally-loose form of {@link StyleProp}. Any concrete `StyleProp<P>`
31
+ * is assignable to this. Used at registration / resolution boundaries where
32
+ * the generic `P` would otherwise cause TS2590 by re-expanding
33
+ * `ValuesEntry<P>` across the full property union.
34
+ */
35
+ interface AnyStyleProp {
36
+ readonly kind: 'styleProp';
37
+ readonly cssProperty: string;
38
+ readonly classPrefix: string;
39
+ readonly values: readonly unknown[];
40
+ readonly arbitrary?: ArbitrarySpec;
41
+ readonly cssType?: CssValueTypeName;
42
+ readonly metadata: StylePropMetadata;
43
+ }
44
+ //#endregion
45
+ export { AnyStyleProp, ArbitraryEntry, ArbitrarySpec, StylePropMetadata };