@yahoo/uds-v5-wip 1.4.0 → 1.5.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 (57) hide show
  1. package/dist/config/dist/createConfig.d.ts +47 -35
  2. package/dist/config/dist/createConfig.js +136 -12
  3. package/dist/config/dist/index.d.ts +2 -0
  4. package/dist/config/dist/index.js +1 -0
  5. package/dist/config/dist/preset-merge.js +8 -1
  6. package/dist/config/dist/resolvedMappings.d.ts +22 -0
  7. package/dist/config/dist/resolvedMappings.js +43 -0
  8. package/dist/config/dist/serialize.js +14 -11
  9. package/dist/config/dist/types.d.ts +94 -0
  10. package/dist/config.d.ts +4622 -3212
  11. package/dist/config.js +2 -1
  12. package/dist/core/dist/getStyles.js +1 -1
  13. package/dist/foundational-presets/dist/boldVibrant.d.ts +4861 -3274
  14. package/dist/foundational-presets/dist/boldVibrant.js +221 -317
  15. package/dist/foundational-presets/dist/brutalist.d.ts +4861 -3274
  16. package/dist/foundational-presets/dist/brutalist.js +221 -317
  17. package/dist/foundational-presets/dist/candy.d.ts +4861 -3274
  18. package/dist/foundational-presets/dist/candy.js +221 -317
  19. package/dist/foundational-presets/dist/cleanMinimalist.d.ts +4861 -3274
  20. package/dist/foundational-presets/dist/cleanMinimalist.js +221 -317
  21. package/dist/foundational-presets/dist/corporate.d.ts +4861 -3274
  22. package/dist/foundational-presets/dist/corporate.js +221 -317
  23. package/dist/foundational-presets/dist/darkMoody.d.ts +4861 -3274
  24. package/dist/foundational-presets/dist/darkMoody.js +221 -317
  25. package/dist/foundational-presets/dist/defaultPreset.d.ts +4618 -3210
  26. package/dist/foundational-presets/dist/defaultPreset.js +1107 -1609
  27. package/dist/foundational-presets/dist/forest.d.ts +4861 -3274
  28. package/dist/foundational-presets/dist/forest.js +221 -317
  29. package/dist/foundational-presets/dist/highContrast.d.ts +4861 -3274
  30. package/dist/foundational-presets/dist/highContrast.js +221 -317
  31. package/dist/foundational-presets/dist/lavender.d.ts +4861 -3274
  32. package/dist/foundational-presets/dist/lavender.js +221 -317
  33. package/dist/foundational-presets/dist/luxury.d.ts +4861 -3274
  34. package/dist/foundational-presets/dist/luxury.js +221 -317
  35. package/dist/foundational-presets/dist/monochrome.d.ts +4861 -3274
  36. package/dist/foundational-presets/dist/monochrome.js +221 -317
  37. package/dist/foundational-presets/dist/neonCyber.d.ts +4861 -3274
  38. package/dist/foundational-presets/dist/neonCyber.js +221 -317
  39. package/dist/foundational-presets/dist/newspaper.d.ts +4861 -3274
  40. package/dist/foundational-presets/dist/newspaper.js +221 -317
  41. package/dist/foundational-presets/dist/ocean.d.ts +4861 -3274
  42. package/dist/foundational-presets/dist/ocean.js +221 -317
  43. package/dist/foundational-presets/dist/slate.d.ts +4861 -3274
  44. package/dist/foundational-presets/dist/slate.js +221 -317
  45. package/dist/foundational-presets/dist/sunset.d.ts +4861 -3274
  46. package/dist/foundational-presets/dist/sunset.js +221 -317
  47. package/dist/foundational-presets/dist/terminal.d.ts +4861 -3274
  48. package/dist/foundational-presets/dist/terminal.js +221 -317
  49. package/dist/foundational-presets/dist/warmOrganic.d.ts +4861 -3274
  50. package/dist/foundational-presets/dist/warmOrganic.js +221 -317
  51. package/dist/loader/dist/loader/dynamic-style-codegen.js +3 -2
  52. package/dist/loader/dist/loader/style-transform.js +1 -1
  53. package/dist/loader/dist/packages/core/dist/getStyles.js +1 -1
  54. package/dist/tsconfig.tsbuildinfo +1 -1
  55. package/dist/utils/dist/string-utils/cssVar.d.ts +4 -2
  56. package/dist/utils/dist/string-utils/cssVar.js +5 -3
  57. package/package.json +3 -3
@@ -1,4 +1,5 @@
1
- import { BaseModifierProp, ComponentsConfig, ConfigurableProp, MacroConfig, ModifierProp, MotionPreset, RemotionComponentDef, RemotionConfig, RemotionTransitionDef } from "@uds/types";
1
+ import { UtilitiesConfig, UtilityDef, VarsConfig } from "./types.js";
2
+ import { BaseModifierProp, ComponentsConfig, ConfigurableProp, MacroConfig, ModifierProp, MotionPreset, RemotionComponentDef, RemotionConfig, RemotionTransitionDef, StyleProp } from "@uds/types";
2
3
 
3
4
  //#region ../config/dist/createConfig.d.ts
4
5
  //#region src/createConfig.d.ts
@@ -72,22 +73,30 @@ interface AtomicToken<M extends ModifierNameShape = ModifierNameShape> {
72
73
  */
73
74
  cssPrefix?: string;
74
75
  }
75
- /** Helper to extract all modifier keys from AtomicToken array */
76
- type ExtractModifierKeys<T> = T extends readonly AtomicToken<infer M>[] ? M : never;
77
- /** Helper to check if all modifiers in the tokens are valid */
78
- type ValidateModifiers<Tokens extends readonly AtomicToken<any>[], ValidModifiers extends ModifierNameShape> = ExtractModifierKeys<Tokens> extends ValidModifiers ? Tokens : never;
79
- /** Extract property keys from atomic tokens */
80
- type ExtractProperties<T extends readonly AtomicToken<any>[]> = T[number]['properties'][number];
81
- /** Distributive helper: for each token group U, yield its token names if P is one of its properties */
82
- type TokenNamesForProperty<U, P extends ConfigurableProp> = U extends AtomicToken<any> ? P extends U['properties'][number] ? U['tokens'][number]['name'] : never : never;
83
- /** Build token structure for a specific property */
84
- type BuildTokensForProperty<T extends readonly AtomicToken<any>[], P extends ConfigurableProp> = { [K in TokenNamesForProperty<T[number], P>]: string };
85
- /** Extract token names from atomic tokens array */
86
- type ExtractTokenNames<T extends readonly AtomicToken<any>[]> = { [P in ExtractProperties<T>]: BuildTokensForProperty<T, P> };
87
76
  /** Merge two token structures */
88
77
  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 };
78
+ /**
79
+ * Given a VarsConfig and a single utility `values` string (e.g. `'{fontWeight}'`),
80
+ * extract the token-name keys from the referenced namespace.
81
+ */
82
+ type ExtractNsTokens<TVars extends VarsConfig, Ref extends string> = Ref extends `{${infer NS}}` ? NS extends keyof TVars ? { [K in keyof TVars[NS]]: string } : Record<string, string> : Record<string, string>;
83
+ /** Collapse a union into an intersection so multi-namespace token maps are merged. */
84
+ type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends ((x: infer I) => void) ? I : never;
85
+ /**
86
+ * Derive the token map shape (`{ propName: { tokenName: string } }`) that
87
+ * `defineUtilities` adds to `TTokens`, based on the accumulated `TVars` and the
88
+ * concrete utilities config type.
89
+ *
90
+ * Only `values: '{namespace}'` references produce typed tokens; literal-values
91
+ * and boolean utilities fall through to `Record<string, string>`.
92
+ */
93
+ type ExtractVarsTokens<TVars extends VarsConfig, TUtils extends Record<string, unknown>> = { [P in keyof TUtils]: TUtils[P] extends {
94
+ values: infer V;
95
+ } ? V extends string ? ExtractNsTokens<TVars, V> : V extends readonly string[] ? UnionToIntersection<ExtractNsTokens<TVars, V[number]>> : Record<string, string> : Record<string, string> };
89
96
  /** Empty tokens type for initial state */
90
97
  type EmptyTokens = {};
98
+ /** Empty vars type for initial state */
99
+ type EmptyVars = {};
91
100
  /** Build a structured token reference object from atomic tokens */
92
101
  declare function buildTokenReference(atomic: AtomicToken<ModifierNameShape>[], configPrefix: string): Record<ConfigurableProp, Record<string, string>>;
93
102
  /** Build a structured macro reference object for use in defineModifiers context */
@@ -126,6 +135,8 @@ interface UdsConfigData {
126
135
  buildOptions?: BuildOptions;
127
136
  examples?: Record<string, ExampleDef>;
128
137
  designPrinciples?: string[];
138
+ vars?: VarsConfig;
139
+ utilities?: UtilitiesConfig;
129
140
  }
130
141
  interface ComponentConfig<TComponents extends ComponentsConfig<string> = ComponentsConfig<string>, TMotion extends MotionPresetsDef | undefined = MotionPresetsDef | undefined> {
131
142
  name?: string;
@@ -151,58 +162,59 @@ type RemotionComponentInput<TTokens, TMotion> = RemotionComponentDef | ((ctx: {
151
162
  components: Record<string, any>;
152
163
  }) => RemotionComponentDef);
153
164
  /** Helper type: builder result includes both the UdsConfig interface and any extensions */
154
- type ConfigResult<TModifier extends ModifierNameShape, TTokens, TMotion, TExt extends Record<string, any> = {}, TMacros = EmptyMacros> = UdsConfig<TModifier, TTokens, TMotion, TExt, TMacros> & TExt;
155
- interface UdsConfig<TModifier extends ModifierNameShape = ModifierProp, TTokens = EmptyTokens, TMotion = EmptyMotion, TExt extends Record<string, any> = {}, TMacros = EmptyMacros> {
165
+ type ConfigResult<TModifier extends ModifierNameShape, TTokens, TMotion, TExt extends Record<string, any> = {}, TMacros = EmptyMacros, TModeModifiers extends ModifierNameShape = never, TVars extends VarsConfig = EmptyVars> = UdsConfig<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars> & TExt;
166
+ interface UdsConfig<TModifier extends ModifierNameShape = ModifierProp, TTokens = EmptyTokens, TMotion = EmptyMotion, TExt extends Record<string, any> = {}, TMacros = EmptyMacros, TModeModifiers extends ModifierNameShape = never, TVars extends VarsConfig = EmptyVars> {
156
167
  modes: ModeGroup[];
157
168
  atomic: AtomicToken<ModifierNameShape>[];
158
169
  components: ComponentsConfig;
159
- preflight(enabled?: boolean): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros>;
160
- prefix(value: string): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros>;
161
- buildOptions(options: BuildOptions): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros>;
162
- defineModes<const NewModes extends readonly ModeGroup[]>(params: CheckForReservedModifiers<NewModes>): ConfigResult<TModifier | GetModifierName<NewModes>, TTokens, TMotion, TExt, TMacros>;
170
+ preflight(enabled?: boolean): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars>;
171
+ prefix(value: string): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars>;
172
+ buildOptions(options: BuildOptions): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars>;
173
+ defineModes<const NewModes extends readonly ModeGroup[]>(params: CheckForReservedModifiers<NewModes>): ConfigResult<TModifier | GetModifierName<NewModes>, TTokens, TMotion, TExt, TMacros, TModeModifiers | GetModifierName<NewModes>, TVars>;
163
174
  defineModifiers<const Defs extends readonly ModifierDef[]>(params: Defs | ((ctx: {
164
175
  tokens: TTokens;
165
176
  macros: MacroReference<TMacros>;
166
- }) => Defs)): ConfigResult<TModifier | Defs[number]['modifier'], TTokens, TMotion, TExt, TMacros>;
177
+ }) => Defs)): ConfigResult<TModifier | Defs[number]['modifier'], TTokens, TMotion, TExt, TMacros, TModeModifiers | Defs[number]['modifier'], TVars>;
167
178
  defineMacro<const M extends MacroConfig>(params: M | ((ctx: {
168
179
  tokens: TTokens;
169
- }) => M)): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros & M>;
170
- defineAtomicTokens<const Tokens extends readonly AtomicToken<any>[]>(params: [TModifier] extends [ModifierProp] ? Tokens : ValidateModifiers<Tokens, TModifier>): ConfigResult<TModifier, MergeTokens<TTokens, ExtractTokenNames<Tokens>>, TMotion, TExt, TMacros>;
171
- defineArbitraryTokens(params: ArbitraryTokenGroup[]): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros>;
172
- defineMotion<const M extends MotionPresetsDef>(presets: M | ((tokens: TTokens) => M)): ConfigResult<TModifier, TTokens, { [K in keyof M]: string }, TExt, TMacros>;
180
+ }) => M)): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros & M, TModeModifiers, TVars>;
181
+ defineArbitraryTokens(params: ArbitraryTokenGroup[]): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars>;
182
+ defineMotion<const M extends MotionPresetsDef>(presets: M | ((tokens: TTokens) => M)): ConfigResult<TModifier, TTokens, { [K in keyof M]: string }, TExt, TMacros, TModeModifiers, TVars>;
173
183
  defineComponents(params: ComponentsConfig<MotionAliasValue<TMotion> | string> | ((ctx: {
174
184
  tokens: TTokens;
175
185
  motion: TMotion;
176
186
  components: Record<string, any>;
177
- }) => ComponentsConfig<MotionAliasValue<TMotion> | string>)): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros>;
178
- defineGlobalStyles(params: GlobalStylesDef | ((tokens: TTokens) => GlobalStylesDef)): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros>;
179
- defineDesignPrinciples(principles: string[]): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros>;
180
- defineExample(name: string, examples: ExampleDef): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros>;
181
- compose(...presets: (ComponentConfig | UdsConfig | Partial<UdsConfigData>)[]): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros>;
187
+ }) => ComponentsConfig<MotionAliasValue<TMotion> | string>)): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars>;
188
+ defineGlobalStyles(params: GlobalStylesDef | ((tokens: TTokens) => GlobalStylesDef)): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars>;
189
+ defineDesignPrinciples(principles: string[]): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars>;
190
+ defineExample(name: string, examples: ExampleDef): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars>;
191
+ compose(...presets: (ComponentConfig | UdsConfig | Partial<UdsConfigData>)[]): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars>;
182
192
  defineComponent<const TName extends string, const TComponent extends SingleComponentDef<MotionAliasValue<TMotion> | string>, const TPresetMotion extends MotionPresetsDef = EmptyMotionPresetsDef>(name: TName, component: DefineComponentInput<TTokens, TMotion, TComponent>, motion?: DefineComponentMotionInput<TTokens, TPresetMotion>): ComponentConfig<SingleComponentDefinitionRecord<TName, TComponent>, TPresetMotion>;
183
- from(data: Partial<UdsConfigData>): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros>;
184
- extend<const NewExt extends Record<string, any>>(ext: NewExt): ConfigResult<TModifier, TTokens, TMotion, TExt & NewExt, TMacros>;
193
+ from(data: Partial<UdsConfigData>): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars>;
194
+ extend<const NewExt extends Record<string, any>>(ext: NewExt): ConfigResult<TModifier, TTokens, TMotion, TExt & NewExt, TMacros, TModeModifiers, TVars>;
185
195
  defineRemotionComponents(params: RemotionConfig | ((ctx: {
186
196
  tokens: TTokens;
187
197
  motion: TMotion;
188
198
  components: Record<string, any>;
189
- }) => RemotionConfig)): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros>;
199
+ }) => RemotionConfig)): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars>;
190
200
  defineRemotionComponent<const TName extends string, const TComponent extends SingleComponentDef<MotionAliasValue<TMotion> | string>, const TPresetMotion extends MotionPresetsDef = EmptyMotionPresetsDef>(name: TName, def: RemotionComponentInput<TTokens, TMotion>, motion?: DefineComponentMotionInput<TTokens, TPresetMotion>): ComponentConfig<SingleComponentDefinitionRecord<TName, TComponent>, TPresetMotion>;
191
201
  defineRemotionTransition(name: string, def: RemotionTransitionDef | ((ctx: {
192
202
  tokens: TTokens;
193
203
  }) => RemotionTransitionDef)): ComponentConfig;
194
204
  defineRemotionTransitions(params: Record<string, RemotionTransitionDef> | ((ctx: {
195
205
  tokens: TTokens;
196
- }) => Record<string, RemotionTransitionDef>)): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros>;
206
+ }) => Record<string, RemotionTransitionDef>)): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars>;
207
+ defineVars<const TVarsNew extends VarsConfig<[TModeModifiers] extends [never] ? `_${string}` : TModeModifiers>>(vars: TVarsNew): ConfigResult<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars & TVarsNew>;
208
+ defineUtilities<const TUtils extends { [K in keyof TUtils]: K extends StyleProp ? UtilityDef : never }>(utilities: TUtils): ConfigResult<TModifier, MergeTokens<TTokens, ExtractVarsTokens<TVars, TUtils>>, TMotion, TExt, TMacros, TModeModifiers, TVars>;
197
209
  }
198
- type AnyUdsConfig = UdsConfig<ModifierNameShape, any, any, any, any>;
210
+ type AnyUdsConfig = UdsConfig<ModifierNameShape, any, any, any, any, any, any>;
199
211
  /** Extract the raw config data from a builder instance */
200
212
  declare function resolveConfig(config: AnyUdsConfig): UdsConfigData;
201
213
  /**
202
214
  * Resolve configuration with all token references replaced by their raw values.
203
215
  * Useful for tools that need the actual values (e.g. anatomy generation).
204
216
  */
205
- declare function createConfigBuilder<TModifier extends ModifierNameShape = ModifierProp, TTokens = EmptyTokens, TMotion = EmptyMotion, TExt extends Record<string, any> = {}, TMacros = EmptyMacros>(data: UdsConfigData, extensions?: TExt): UdsConfig<TModifier, TTokens, TMotion, TExt, TMacros> & TExt;
217
+ declare function createConfigBuilder<TModifier extends ModifierNameShape = ModifierProp, TTokens = EmptyTokens, TMotion = EmptyMotion, TExt extends Record<string, any> = {}, TMacros = EmptyMacros, TModeModifiers extends ModifierNameShape = never, TVars extends VarsConfig = EmptyVars>(data: UdsConfigData, extensions?: TExt): UdsConfig<TModifier, TTokens, TMotion, TExt, TMacros, TModeModifiers, TVars> & TExt;
206
218
  interface InterpolateMarker {
207
219
  __type: 'interpolate';
208
220
  output: number[];
@@ -1,3 +1,4 @@
1
+ import { kebabCase } from "../../utils/dist/string-utils/kebabCase.js";
1
2
  import { safeTokenName } from "../../utils/dist/string-utils/cssVar.js";
2
3
  import "../../utils/dist/index.js";
3
4
  import { getConfigurablePropMapping } from "../../core/dist/propMappings.js";
@@ -29,10 +30,94 @@ function buildMacroReference(macros) {
29
30
  }
30
31
  return result;
31
32
  }
33
+ /**
34
+ * Parse a `'{namespace}'` reference string, returning the namespace name
35
+ * or `undefined` if the string is not a valid reference.
36
+ */
37
+ function parseVarsReference(ref) {
38
+ return ref.match(/^\{(.+)\}$/)?.[1];
39
+ }
40
+ /** Normalize values to an array of string refs, filtering out non-string forms. */
41
+ function normalizeValuesRefs(values) {
42
+ if (!values) return [];
43
+ if (typeof values === "string") return [values];
44
+ if (Array.isArray(values)) return values;
45
+ return [];
46
+ }
47
+ /** Convert a VarGroupDef into AtomicToken tokens, extracting modifier overrides. */
48
+ function varGroupToTokens(varGroup, knownModifiers) {
49
+ const tokens = [];
50
+ for (const [tokenName, tokenDef] of Object.entries(varGroup)) {
51
+ const modifiers = {};
52
+ for (const [key, val] of Object.entries(tokenDef)) {
53
+ if (key === "value" || val === void 0) continue;
54
+ if (key.startsWith("_") && knownModifiers.has(key)) modifiers[key] = val;
55
+ }
56
+ tokens.push({
57
+ name: tokenName,
58
+ value: tokenDef.value,
59
+ ...Object.keys(modifiers).length > 0 ? { modifiers } : {}
60
+ });
61
+ }
62
+ return tokens;
63
+ }
64
+ /**
65
+ * Bridge: synthesize AtomicToken[] from defineVars + defineUtilities data.
66
+ *
67
+ * For each utility, resolves its `values` references (single or array) to var
68
+ * namespaces. Each (namespace, property) pair produces a separate AtomicToken
69
+ * group with `cssPrefix` = namespace name, so CSS custom properties land in
70
+ * the correct `--prefix-namespace-token` space.
71
+ *
72
+ * When `values` is an array (`['{color}', '{bg}']`), tokens from all referenced
73
+ * namespaces are included. Name collisions are resolved by the existing
74
+ * `mergeAtomic` logic (last group wins within the same property+cssPrefix key).
75
+ */
76
+ function synthesizeAtomicFromVarsAndUtilities(vars, utilities, modes) {
77
+ const knownModifiers = /* @__PURE__ */ new Set();
78
+ for (const mode of modes) for (const option of mode.options) knownModifiers.add(option.modifier);
79
+ const pairs = /* @__PURE__ */ new Map();
80
+ for (const [propName, utilDef] of Object.entries(utilities)) {
81
+ if (!utilDef) continue;
82
+ const refs = normalizeValuesRefs(utilDef.values);
83
+ for (const ref of refs) {
84
+ const namespace = parseVarsReference(ref);
85
+ if (!namespace || !vars[namespace]) continue;
86
+ const key = `${namespace}|${propName}`;
87
+ pairs.set(key, {
88
+ namespace,
89
+ property: propName
90
+ });
91
+ }
92
+ }
93
+ const namespaceGroups = /* @__PURE__ */ new Map();
94
+ for (const { namespace, property } of pairs.values()) {
95
+ const props = namespaceGroups.get(namespace) ?? /* @__PURE__ */ new Set();
96
+ props.add(property);
97
+ namespaceGroups.set(namespace, props);
98
+ }
99
+ const result = [];
100
+ for (const [namespace, propertySet] of namespaceGroups) {
101
+ const varGroup = vars[namespace];
102
+ if (!varGroup) continue;
103
+ const tokens = varGroupToTokens(varGroup, knownModifiers);
104
+ const cssPfx = (propertySet.has(namespace) ? getConfigurablePropMapping(namespace) : void 0)?.defaultVarPrefix ?? kebabCase(namespace);
105
+ const properties = Array.from(propertySet).sort((a, b) => {
106
+ return (a === namespace || kebabCase(a) === cssPfx ? 1 : 0) - (b === namespace || kebabCase(b) === cssPfx ? 1 : 0);
107
+ });
108
+ result.push({
109
+ properties,
110
+ tokens,
111
+ cssPrefix: cssPfx
112
+ });
113
+ }
114
+ return result;
115
+ }
32
116
  /** Extract the raw config data from a builder instance */
33
117
  function resolveConfig(config) {
34
- if (config._data) return config._data;
35
- return {
118
+ let configData;
119
+ if (config._data) configData = config._data;
120
+ else configData = {
36
121
  modes: config.modes ?? [],
37
122
  modifiers: config.modifiers ?? [],
38
123
  atomic: config.atomic ?? [],
@@ -46,8 +131,18 @@ function resolveConfig(config) {
46
131
  remotion: config.remotion,
47
132
  buildOptions: config.buildOptions,
48
133
  examples: config.examples,
49
- designPrinciples: config.designPrinciples
134
+ designPrinciples: config.designPrinciples,
135
+ vars: config.vars,
136
+ utilities: config.utilities
50
137
  };
138
+ if (configData.vars && configData.utilities) {
139
+ const synthesized = synthesizeAtomicFromVarsAndUtilities(configData.vars, configData.utilities, configData.modes);
140
+ configData = {
141
+ ...configData,
142
+ atomic: mergeAtomic(configData.atomic, synthesized, "merge")
143
+ };
144
+ }
145
+ return configData;
51
146
  }
52
147
  function mergeRemotionConfig(existing, incoming) {
53
148
  return {
@@ -81,7 +176,7 @@ function resolvePresetData(input) {
81
176
  prefix: "uds",
82
177
  remotion: input.remotion
83
178
  };
84
- if ("defineAtomicTokens" in input) return resolveConfig(input);
179
+ if ("defineVars" in input) return resolveConfig(input);
85
180
  return {
86
181
  modes: input.modes ?? [],
87
182
  modifiers: input.modifiers ?? [],
@@ -95,7 +190,9 @@ function resolvePresetData(input) {
95
190
  arbitraryTokens: input.arbitraryTokens,
96
191
  remotion: input.remotion,
97
192
  examples: input.examples,
98
- designPrinciples: input.designPrinciples
193
+ designPrinciples: input.designPrinciples,
194
+ vars: input.vars,
195
+ utilities: input.utilities
99
196
  };
100
197
  }
101
198
  function extractVarReferences(value) {
@@ -239,12 +336,6 @@ function createConfigBuilder(data, extensions) {
239
336
  }
240
337
  }, extensions);
241
338
  },
242
- defineAtomicTokens(params) {
243
- return createConfigBuilder({
244
- ...data,
245
- atomic: mergeAtomic(data.atomic, params, "merge")
246
- }, extensions);
247
- },
248
339
  defineArbitraryTokens(params) {
249
340
  return next({ arbitraryTokens: [...data.arbitraryTokens ?? [], ...params] });
250
341
  },
@@ -342,7 +433,9 @@ function createConfigBuilder(data, extensions) {
342
433
  prefix: input.prefix ?? data.prefix,
343
434
  arbitraryTokens: input.arbitraryTokens ?? data.arbitraryTokens,
344
435
  examples: input.examples ?? data.examples,
345
- designPrinciples: input.designPrinciples ?? data.designPrinciples
436
+ designPrinciples: input.designPrinciples ?? data.designPrinciples,
437
+ vars: input.vars ?? data.vars,
438
+ utilities: input.utilities ?? data.utilities
346
439
  }, extensions);
347
440
  },
348
441
  extend(ext) {
@@ -414,6 +507,37 @@ function createConfigBuilder(data, extensions) {
414
507
  components: {},
415
508
  transitions: resolved
416
509
  }) });
510
+ },
511
+ defineVars(vars) {
512
+ const merged = { ...data.vars };
513
+ for (const [namespace, group] of Object.entries(vars)) merged[namespace] = {
514
+ ...merged[namespace] ?? {},
515
+ ...group
516
+ };
517
+ const updates = { vars: merged };
518
+ if (data.utilities && Object.keys(data.utilities).length > 0) {
519
+ const synthesized = synthesizeAtomicFromVarsAndUtilities(merged, data.utilities, data.modes ?? []);
520
+ updates.atomic = mergeAtomic(data.atomic, synthesized, "merge");
521
+ }
522
+ return createConfigBuilder({
523
+ ...data,
524
+ ...updates
525
+ }, extensions);
526
+ },
527
+ defineUtilities(utilities) {
528
+ const merged = {
529
+ ...data.utilities,
530
+ ...utilities
531
+ };
532
+ const updates = { utilities: merged };
533
+ if (data.vars && Object.keys(data.vars).length > 0) {
534
+ const synthesized = synthesizeAtomicFromVarsAndUtilities(data.vars, merged, data.modes ?? []);
535
+ updates.atomic = mergeAtomic(data.atomic ?? [], synthesized, "merge");
536
+ }
537
+ return createConfigBuilder({
538
+ ...data,
539
+ ...updates
540
+ }, extensions);
417
541
  }
418
542
  };
419
543
  }
@@ -1,5 +1,7 @@
1
1
  import { defaultColors } from "./consts/defaultColors.js";
2
+ import { UtilitiesConfig, UtilityDef, VarGroupDef, VarTokenDef, VarsConfig } from "./types.js";
2
3
  import { ArbitraryTokenGroup, AtomicToken, BuildOptions, ComponentConfig, DefineComponentInput, DefineComponentMotionInput, ExampleDef, ExampleEntryDef, ExampleLayoutStyles, GlobalStylesDef, InterpolateMarker, ModeGroup, ModifierDef, MotionPresetsDef, UdsConfig, UdsConfigData, buildTokenReference, createConfigBuilder, darker, lighter, resolveConfig } from "./createConfig.js";
4
+ import { ResolvedUtilityMapping, resolveUtilityMappings } from "./resolvedMappings.js";
3
5
  import { SerializedConfig, TokenRef, buildReverseMap, deserializeConfig, serializeConfig } from "./serialize.js";
4
6
  import { ComponentsConfig as ComponentsConfig$1 } from "@uds/types";
5
7
  export { type ComponentsConfig$1 as ComponentsConfig };
@@ -1,4 +1,5 @@
1
1
  import "./consts/defaultColors.js";
2
2
  import "./component-resolution.js";
3
3
  import "./createConfig.js";
4
+ import "./resolvedMappings.js";
4
5
  import "./serialize.js";
@@ -141,6 +141,11 @@ function applyPresetToData(base, preset, strategy) {
141
141
  const mergedExamples = base.examples || preset.examples ? mergeRecordByKey(base.examples ?? {}, preset.examples ?? {}, s.examples) : void 0;
142
142
  const mergedPrinciples = base.designPrinciples || preset.designPrinciples ? [...base.designPrinciples ?? [], ...preset.designPrinciples ?? []] : void 0;
143
143
  const mergedArbitraryTokens = base.arbitraryTokens || preset.arbitraryTokens ? [...base.arbitraryTokens ?? [], ...preset.arbitraryTokens ?? []] : void 0;
144
+ const mergedVars = base.vars || preset.vars ? mergeRecordByKey(base.vars ?? {}, preset.vars ?? {}, "merge") : void 0;
145
+ const mergedUtilities = base.utilities || preset.utilities ? {
146
+ ...base.utilities,
147
+ ...preset.utilities
148
+ } : void 0;
144
149
  const merged = {
145
150
  ...base,
146
151
  modes: mergeModes(base.modes, preset.modes, s.modes),
@@ -156,7 +161,9 @@ function applyPresetToData(base, preset, strategy) {
156
161
  remotion: mergeRemotionConfig(base.remotion, preset.remotion),
157
162
  arbitraryTokens: mergedArbitraryTokens,
158
163
  examples: mergedExamples,
159
- designPrinciples: mergedPrinciples
164
+ designPrinciples: mergedPrinciples,
165
+ vars: mergedVars,
166
+ utilities: mergedUtilities
160
167
  };
161
168
  validateComponentVariants(merged.components);
162
169
  return merged;
@@ -0,0 +1,22 @@
1
+ import { UtilitiesConfig } from "./types.js";
2
+
3
+ //#region ../config/dist/resolvedMappings.d.ts
4
+ //#region src/resolvedMappings.d.ts
5
+ interface ResolvedUtilityMapping {
6
+ classPrefix: string;
7
+ cssProperty?: string;
8
+ defaultVarPrefix?: string;
9
+ literalValues?: string[];
10
+ }
11
+ /**
12
+ * Derive PropMapping-equivalent data from a defineUtilities config.
13
+ *
14
+ * For each utility:
15
+ * - `className` → `classPrefix`
16
+ * - `values: '{ns}'` → `defaultVarPrefix = ns`
17
+ * - `transform('__probe__')` → inspect returned CSS property keys → `cssProperty` (first key)
18
+ * - `literalValues` → passed through
19
+ */
20
+ declare function resolveUtilityMappings(utilities: UtilitiesConfig): Record<string, ResolvedUtilityMapping>; //#endregion
21
+ //#endregion
22
+ export { ResolvedUtilityMapping, resolveUtilityMappings };
@@ -0,0 +1,43 @@
1
+ import { kebabCase } from "../../utils/dist/string-utils/kebabCase.js";
2
+ import "../../utils/dist/index.js";
3
+ //#region ../config/dist/resolvedMappings.js
4
+ /**
5
+ * Resolve utility mappings from a defineUtilities config into PropMapping-equivalent data.
6
+ *
7
+ * When `config.utilities` is present, this derives the same shape that `propMappings`
8
+ * provides — `classPrefix`, `cssProperty`, `defaultVarPrefix`, `literalValues` — by
9
+ * inspecting each utility definition. Falls back to the hardcoded `propMappings` from
10
+ * `@uds/core` when no utilities config exists.
11
+ */
12
+ const PROBE_VALUE = "__probe__";
13
+ /**
14
+ * Derive PropMapping-equivalent data from a defineUtilities config.
15
+ *
16
+ * For each utility:
17
+ * - `className` → `classPrefix`
18
+ * - `values: '{ns}'` → `defaultVarPrefix = ns`
19
+ * - `transform('__probe__')` → inspect returned CSS property keys → `cssProperty` (first key)
20
+ * - `literalValues` → passed through
21
+ */
22
+ function resolveUtilityMappings(utilities) {
23
+ const result = {};
24
+ for (const [propName, utilDef] of Object.entries(utilities)) {
25
+ const mapping = { classPrefix: utilDef.className };
26
+ if (utilDef.transform) try {
27
+ const noopToken = (ref) => `var(--${ref.replace(".", "-")})`;
28
+ const cssOutput = utilDef.transform(PROBE_VALUE, { token: noopToken });
29
+ const cssProps = Object.keys(cssOutput);
30
+ if (cssProps.length > 0) mapping.cssProperty = cssProps[0];
31
+ } catch {}
32
+ const valuesRef = Array.isArray(utilDef.values) ? utilDef.values[utilDef.values.length - 1] : typeof utilDef.values === "string" ? utilDef.values : void 0;
33
+ if (valuesRef) {
34
+ const match = valuesRef.match(/^\{(.+)\}$/);
35
+ if (match) mapping.defaultVarPrefix = kebabCase(match[1]);
36
+ }
37
+ if (utilDef.literalValues) mapping.literalValues = utilDef.literalValues;
38
+ result[propName] = mapping;
39
+ }
40
+ return result;
41
+ }
42
+ //#endregion
43
+ export { resolveUtilityMappings };
@@ -2,7 +2,7 @@ import { safeTokenName } from "../../utils/dist/string-utils/cssVar.js";
2
2
  import "../../utils/dist/index.js";
3
3
  import { getConfigurablePropMapping } from "../../core/dist/propMappings.js";
4
4
  import "../../core/dist/index.js";
5
- import { buildTokenReference, resolveConfig, uds } from "./createConfig.js";
5
+ import { buildTokenReference, createConfigBuilder, resolveConfig } from "./createConfig.js";
6
6
  //#region ../config/dist/serialize.js
7
7
  /**
8
8
  * Config serialization for lossless round-tripping through a database.
@@ -131,16 +131,19 @@ function deserializeConfig(data) {
131
131
  if (compConfig.defaultVariants) resolved.defaultVariants = compConfig.defaultVariants;
132
132
  components[compName] = resolved;
133
133
  }
134
- let config = uds;
135
- if (data.prefix) config = config.prefix(data.prefix);
136
- config = config.preflight(data.preflight);
137
- if (data.modes.length > 0) config = config.defineModes(data.modes);
138
- if (data.modifiers && data.modifiers.length > 0) config = config.defineModifiers(data.modifiers);
139
- if (data.atomic.length > 0) config = config.defineAtomicTokens(data.atomic);
140
- if (data.arbitraryTokens && data.arbitraryTokens.length > 0) config = config.defineArbitraryTokens(data.arbitraryTokens);
141
- if (data.macros && Object.keys(data.macros).length > 0) config = config.defineMacro(data.macros);
142
- if (data.motion && Object.keys(data.motion).length > 0) config = config.defineMotion(data.motion);
143
- if (Object.keys(components).length > 0) config = config.defineComponents(components);
134
+ let config = createConfigBuilder({
135
+ modes: data.modes,
136
+ modifiers: data.modifiers ?? [],
137
+ atomic: data.atomic,
138
+ macros: data.macros ?? {},
139
+ motion: data.motion ?? {},
140
+ components,
141
+ preflight: data.preflight,
142
+ prefix: data.prefix ?? "uds",
143
+ arbitraryTokens: data.arbitraryTokens,
144
+ remotion: void 0,
145
+ globalStyles: {}
146
+ });
144
147
  if (data.globalStyles && Object.keys(data.globalStyles).length > 0) {
145
148
  const globalStyles = {};
146
149
  for (const [selector, styles] of Object.entries(data.globalStyles)) globalStyles[selector] = resolveRefs(styles, tokenRef);
@@ -0,0 +1,94 @@
1
+ import { StyleProp } from "@uds/types";
2
+
3
+ //#region ../config/dist/types.d.ts
4
+ //#region src/types.d.ts
5
+ /**
6
+ * A single design token definition with a base value and optional modifier overrides.
7
+ * Modifier keys use the `_` prefix convention (e.g., `_dark`, `_hover`).
8
+ *
9
+ * When `M` is narrowed (e.g., `'_dark' | '_light'`), only those modifier keys are
10
+ * accepted — TypeScript will flag unknown modifiers like `_eggs` at compile time.
11
+ *
12
+ * @example
13
+ * { value: '#1167f4', _dark: '#88bcfb' }
14
+ */
15
+ type VarTokenDef<M extends `_${string}` = `_${string}`> = {
16
+ value: string;
17
+ } & { [K in M]?: string };
18
+ /**
19
+ * A group of named tokens within a var namespace.
20
+ *
21
+ * @example
22
+ * { brand: { value: '#1167f4', _dark: '#88bcfb' }, accent: { value: '#7c3aed' } }
23
+ */
24
+ type VarGroupDef<M extends `_${string}` = `_${string}`> = Record<string, VarTokenDef<M>>;
25
+ /**
26
+ * Top-level vars config — namespaces to groups of tokens.
27
+ *
28
+ * @example
29
+ * {
30
+ * color: { brand: { value: '#1167f4', _dark: '#88bcfb' } },
31
+ * spacing: { 1: { value: '0.25rem' }, 2: { value: '0.5rem' } },
32
+ * }
33
+ */
34
+ type VarsConfig<M extends `_${string}` = `_${string}`> = Record<string, VarGroupDef<M>>;
35
+ /**
36
+ * A single utility definition mapping a style prop to CSS output.
37
+ *
38
+ * @example
39
+ * {
40
+ * className: 'bg',
41
+ * values: '{bg}',
42
+ * transform(value) { return { 'background-color': value } },
43
+ * }
44
+ */
45
+ interface UtilityDef {
46
+ /** Class name prefix for runtime generation. Empty string means value IS the class. */
47
+ className: string;
48
+ /**
49
+ * Reference to defineVars namespace(s). Tokens from referenced namespaces become allowed values.
50
+ *
51
+ * - Single: `'{namespace}'` — tokens from one namespace
52
+ * - Array: `['{ns1}', '{ns2}']` — tokens from multiple namespaces, last entry wins on name collision
53
+ *
54
+ * The namespace name determines the CSS custom property prefix (e.g., `'{color}'` → `--uds-color-*`).
55
+ */
56
+ values?: string | string[] | {
57
+ type: 'boolean';
58
+ };
59
+ /** Literal enum values (e.g., `['block', 'flex', 'grid']`). */
60
+ literalValues?: string[];
61
+ /** Transform a token/literal value into CSS property declarations.
62
+ * Optional for Phase 0 — only needed by resolveUtilityMappings() to derive cssProperty. */
63
+ transform?: (value: string, ctx: {
64
+ token: (ref: string) => string;
65
+ }) => Record<string, string>;
66
+ }
67
+ /**
68
+ * Internal utilities config — used for resolved/stored data.
69
+ * Keys are plain strings so internal iteration (Object.entries, etc.) stays clean.
70
+ *
71
+ * @example
72
+ * {
73
+ * bg: { className: 'bg', values: '{bg}', transform(v) { return { 'background-color': v } } },
74
+ * display: { className: '', literalValues: ['block', 'flex'], transform(v) { return { display: v } } },
75
+ * }
76
+ */
77
+ type UtilitiesConfig = Record<string, UtilityDef>;
78
+ /**
79
+ * Input type for `defineUtilities()` — keys must be valid UDS style prop names (`StyleProp`).
80
+ *
81
+ * This is the public-facing constraint used by the builder method. It ensures callers
82
+ * only map props that exist in the UDS component style API. Unlike `UtilitiesConfig`
83
+ * (which uses `Record<string, ...>` for clean internal iteration), this type enforces
84
+ * named keys at the call site.
85
+ *
86
+ * @example
87
+ * {
88
+ * color: { className: 'text', values: '{color}' },
89
+ * bg: { className: 'bg', values: ['{color}', '{bg}'] },
90
+ * display: { className: '', literalValues: ['block', 'flex', 'grid'] },
91
+ * }
92
+ */
93
+ //#endregion
94
+ export { UtilitiesConfig, UtilityDef, VarGroupDef, VarTokenDef, VarsConfig };