@animus-ui/system 0.1.0-next.v7 → 0.1.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 (78) hide show
  1. package/README.md +148 -0
  2. package/dist/Animus.d.ts +36 -30
  3. package/dist/Animus.d.ts.map +1 -1
  4. package/dist/AnimusExtended.d.ts +32 -27
  5. package/dist/AnimusExtended.d.ts.map +1 -1
  6. package/dist/SystemBuilder.d.ts +38 -32
  7. package/dist/SystemBuilder.d.ts.map +1 -1
  8. package/dist/compose.d.ts +24 -0
  9. package/dist/compose.d.ts.map +1 -0
  10. package/dist/compose.js +36 -0
  11. package/dist/composeWithContext.d.ts +30 -0
  12. package/dist/composeWithContext.d.ts.map +1 -0
  13. package/dist/composeWithContext.js +79 -0
  14. package/dist/createComposedFamily-BsyI6rBc.js +230 -0
  15. package/dist/groups/index.d.ts +455 -359
  16. package/dist/groups/index.d.ts.map +1 -1
  17. package/dist/groups/index.js +139 -55
  18. package/dist/index.d.ts +14 -7
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +708 -102
  21. package/dist/keyframes.d.ts +45 -0
  22. package/dist/keyframes.d.ts.map +1 -0
  23. package/dist/runtime/createClassResolver.d.ts +10 -0
  24. package/dist/runtime/createClassResolver.d.ts.map +1 -0
  25. package/dist/runtime/createComposedFamily.d.ts +16 -0
  26. package/dist/runtime/createComposedFamily.d.ts.map +1 -0
  27. package/dist/runtime/index.d.ts +26 -0
  28. package/dist/runtime/index.d.ts.map +1 -0
  29. package/dist/runtime/resolveClasses.d.ts +59 -0
  30. package/dist/runtime/resolveClasses.d.ts.map +1 -0
  31. package/dist/runtime-entry.d.ts +10 -0
  32. package/dist/runtime-entry.d.ts.map +1 -0
  33. package/dist/runtime-entry.js +2 -0
  34. package/dist/selectors.d.ts +40 -0
  35. package/dist/selectors.d.ts.map +1 -0
  36. package/dist/size-CusLCguT.js +97 -0
  37. package/dist/theme/createTheme.d.ts +59 -0
  38. package/dist/theme/createTheme.d.ts.map +1 -0
  39. package/dist/theme/flattenScale.d.ts +21 -0
  40. package/dist/theme/flattenScale.d.ts.map +1 -0
  41. package/dist/theme/index.d.ts +5 -0
  42. package/dist/theme/index.d.ts.map +1 -0
  43. package/dist/theme/serializeTokens.d.ts +8 -0
  44. package/dist/theme/serializeTokens.d.ts.map +1 -0
  45. package/dist/theme/types.d.ts +42 -0
  46. package/dist/theme/types.d.ts.map +1 -0
  47. package/dist/theme/utils.d.ts +28 -0
  48. package/dist/theme/utils.d.ts.map +1 -0
  49. package/dist/transforms/border.d.ts +4 -0
  50. package/dist/transforms/border.d.ts.map +1 -1
  51. package/dist/transforms/createTransform.d.ts +3 -1
  52. package/dist/transforms/createTransform.d.ts.map +1 -1
  53. package/dist/transforms/grid.d.ts +12 -2
  54. package/dist/transforms/grid.d.ts.map +1 -1
  55. package/dist/transforms/index.d.ts +0 -1
  56. package/dist/transforms/index.d.ts.map +1 -1
  57. package/dist/transforms/size.d.ts +8 -0
  58. package/dist/transforms/size.d.ts.map +1 -1
  59. package/dist/types/component.d.ts +148 -24
  60. package/dist/types/component.d.ts.map +1 -1
  61. package/dist/types/config.d.ts +54 -7
  62. package/dist/types/config.d.ts.map +1 -1
  63. package/dist/types/properties.d.ts +5 -7
  64. package/dist/types/properties.d.ts.map +1 -1
  65. package/dist/types/props.d.ts +13 -25
  66. package/dist/types/props.d.ts.map +1 -1
  67. package/dist/types/shared.d.ts +0 -1
  68. package/dist/types/shared.d.ts.map +1 -1
  69. package/dist/types/theme.d.ts +77 -11
  70. package/dist/types/theme.d.ts.map +1 -1
  71. package/dist/utils/deepMerge.d.ts +5 -0
  72. package/dist/utils/deepMerge.d.ts.map +1 -0
  73. package/package.json +46 -17
  74. package/dist/PropertyBuilder.d.ts +0 -11
  75. package/dist/PropertyBuilder.d.ts.map +0 -1
  76. package/dist/size-Dge_rsuz.js +0 -70
  77. package/dist/transforms/utils.d.ts +0 -3
  78. package/dist/transforms/utils.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -1,13 +1,18 @@
1
- import { a as borderShorthand, c as numericOrStringScale, i as gridItemRatio, l as numericScale, n as size, o as createTransform, r as gridItem, s as createScale, t as percentageOrAbsolute, u as stringScale } from "./size-Dge_rsuz.js";
2
- import { createComponent } from "@animus-ui/runtime";
3
- import { createTheme } from "@animus-ui/theming";
4
- //#region src/AnimusExtended.ts
5
- function deepMerge$1(target, source) {
1
+ import { n as createClassResolver, r as createComponent, t as createComposedFamily } from "./createComposedFamily-BsyI6rBc.js";
2
+ import { compose } from "./compose.js";
3
+ import { a as borderShorthand, c as numericOrStringScale, i as gridItemRatio, l as numericScale, n as size, o as createTransform, r as gridItem, s as createScale, t as percentageOrAbsolute, u as stringScale } from "./size-CusLCguT.js";
4
+ //#region src/utils/deepMerge.ts
5
+ /**
6
+ * Deep merge utility — replaces lodash.merge for variant accumulation.
7
+ */
8
+ function deepMerge(target, source) {
6
9
  const result = { ...target };
7
- for (const key of Object.keys(source)) if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key]) && target[key] && typeof target[key] === "object" && !Array.isArray(target[key])) result[key] = deepMerge$1(target[key], source[key]);
10
+ for (const key of Object.keys(source)) if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key]) && target[key] && typeof target[key] === "object" && !Array.isArray(target[key])) result[key] = deepMerge(target[key], source[key]);
8
11
  else result[key] = source[key];
9
12
  return result;
10
13
  }
14
+ //#endregion
15
+ //#region src/AnimusExtended.ts
11
16
  var AnimusExtendedWithAll = class {
12
17
  propRegistry = {};
13
18
  groupRegistry = {};
@@ -16,7 +21,8 @@ var AnimusExtendedWithAll = class {
16
21
  variants = {};
17
22
  activeGroups = {};
18
23
  custom = {};
19
- constructor(props, groups, base, variants, states, activeGroups, custom) {
24
+ compounds = [];
25
+ constructor(props, groups, base, variants, states, activeGroups, custom, compounds = []) {
20
26
  this.propRegistry = props;
21
27
  this.groupRegistry = groups;
22
28
  this.baseStyles = base;
@@ -24,9 +30,10 @@ var AnimusExtendedWithAll = class {
24
30
  this.statesConfig = states;
25
31
  this.activeGroups = activeGroups;
26
32
  this.custom = custom;
33
+ this.compounds = compounds;
27
34
  }
28
35
  extend() {
29
- return new AnimusExtended(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, this.activeGroups, this.custom);
36
+ return new AnimusExtended(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, this.activeGroups, this.custom, this.compounds);
30
37
  }
31
38
  asElement(component) {
32
39
  const Component = createComponent(component, "", this._buildComponentConfig());
@@ -38,8 +45,8 @@ var AnimusExtendedWithAll = class {
38
45
  const extendFn = this.extend.bind(this);
39
46
  return Object.assign(Component, { extend: extendFn });
40
47
  }
41
- build() {
42
- return Object.assign((() => ({})), { extend: this.extend.bind(this) });
48
+ asClass() {
49
+ return createClassResolver("", this._buildComponentConfig());
43
50
  }
44
51
  _buildComponentConfig() {
45
52
  const variantConfig = {};
@@ -61,45 +68,50 @@ var AnimusExtendedWithAll = class {
61
68
  };
62
69
  var AnimusExtendedWithSystem = class extends AnimusExtendedWithAll {
63
70
  props(config) {
64
- return new AnimusExtendedWithAll(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, this.activeGroups, deepMerge$1({}, config));
71
+ return new AnimusExtendedWithAll(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, this.activeGroups, deepMerge({}, config), this.compounds);
65
72
  }
66
73
  };
67
74
  var AnimusExtendedWithStates = class extends AnimusExtendedWithSystem {
68
- groups(config) {
69
- return new AnimusExtendedWithSystem(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, deepMerge$1(this.activeGroups, config), this.custom);
75
+ system(config) {
76
+ return new AnimusExtendedWithSystem(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, deepMerge(this.activeGroups, config), this.custom, this.compounds);
70
77
  }
71
78
  };
72
- var AnimusExtendedWithVariants = class AnimusExtendedWithVariants extends AnimusExtendedWithStates {
73
- variant(options) {
74
- const prop = options.prop || "variant";
75
- return new AnimusExtendedWithVariants(this.propRegistry, this.groupRegistry, this.baseStyles, deepMerge$1(this.variants, { [prop]: options }), this.statesConfig, this.activeGroups, this.custom);
79
+ var AnimusExtendedWithCompounds = class AnimusExtendedWithCompounds extends AnimusExtendedWithStates {
80
+ compound(condition, styles) {
81
+ return new AnimusExtendedWithCompounds(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, this.activeGroups, this.custom, [...this.compounds, {
82
+ condition,
83
+ styles
84
+ }]);
76
85
  }
77
86
  states(config) {
78
- return new AnimusExtendedWithStates(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, deepMerge$1(this.statesConfig, config), this.activeGroups, this.custom);
87
+ return new AnimusExtendedWithStates(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, deepMerge(this.statesConfig, config), this.activeGroups, this.custom, this.compounds);
88
+ }
89
+ };
90
+ var AnimusExtendedWithVariants = class AnimusExtendedWithVariants extends AnimusExtendedWithCompounds {
91
+ compound(condition, styles) {
92
+ return new AnimusExtendedWithCompounds(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, this.activeGroups, this.custom, [...this.compounds, {
93
+ condition,
94
+ styles
95
+ }]);
96
+ }
97
+ variant(options) {
98
+ const prop = options.prop || "variant";
99
+ return new AnimusExtendedWithVariants(this.propRegistry, this.groupRegistry, this.baseStyles, deepMerge(this.variants, { [prop]: options }), this.statesConfig, this.activeGroups, this.custom, this.compounds);
79
100
  }
80
101
  };
81
102
  var AnimusExtendedWithBase = class extends AnimusExtendedWithVariants {
82
103
  variant(options) {
83
104
  const prop = options.prop || "variant";
84
- return new AnimusExtendedWithVariants(this.propRegistry, this.groupRegistry, this.baseStyles, deepMerge$1(this.variants, { [prop]: options }), this.statesConfig, this.activeGroups, this.custom);
105
+ return new AnimusExtendedWithVariants(this.propRegistry, this.groupRegistry, this.baseStyles, deepMerge(this.variants, { [prop]: options }), this.statesConfig, this.activeGroups, this.custom, this.compounds);
85
106
  }
86
107
  };
87
108
  var AnimusExtended = class extends AnimusExtendedWithBase {
88
109
  styles(config) {
89
- return new AnimusExtendedWithBase(this.propRegistry, this.groupRegistry, deepMerge$1(this.baseStyles, config), this.variants, this.statesConfig, this.activeGroups, this.custom);
110
+ return new AnimusExtendedWithBase(this.propRegistry, this.groupRegistry, deepMerge(this.baseStyles, config), this.variants, this.statesConfig, this.activeGroups, this.custom, this.compounds);
90
111
  }
91
112
  };
92
113
  //#endregion
93
114
  //#region src/Animus.ts
94
- /**
95
- * Deep merge utility — replaces lodash.merge for variant accumulation.
96
- */
97
- function deepMerge(target, source) {
98
- const result = { ...target };
99
- for (const key of Object.keys(source)) if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key]) && target[key] && typeof target[key] === "object" && !Array.isArray(target[key])) result[key] = deepMerge(target[key], source[key]);
100
- else result[key] = source[key];
101
- return result;
102
- }
103
115
  var AnimusWithAll = class {
104
116
  propRegistry = {};
105
117
  groupRegistry = {};
@@ -108,7 +120,8 @@ var AnimusWithAll = class {
108
120
  variants = {};
109
121
  activeGroups = {};
110
122
  custom = {};
111
- constructor(props, groups, base, variants, states, activeGroups, custom) {
123
+ compounds = [];
124
+ constructor(props, groups, base, variants, states, activeGroups, custom, compounds = []) {
112
125
  this.propRegistry = props;
113
126
  this.groupRegistry = groups;
114
127
  this.baseStyles = base;
@@ -116,9 +129,10 @@ var AnimusWithAll = class {
116
129
  this.statesConfig = states;
117
130
  this.activeGroups = activeGroups;
118
131
  this.custom = custom;
132
+ this.compounds = compounds;
119
133
  }
120
134
  extend() {
121
- return new AnimusExtended(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, this.activeGroups, this.custom);
135
+ return new AnimusExtended(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, this.activeGroups, this.custom, this.compounds);
122
136
  }
123
137
  asElement(component) {
124
138
  const Component = createComponent(component, "", this._buildComponentConfig());
@@ -130,8 +144,8 @@ var AnimusWithAll = class {
130
144
  const extendFn = this.extend.bind(this);
131
145
  return Object.assign(Component, { extend: extendFn });
132
146
  }
133
- build() {
134
- return Object.assign((() => ({})), { extend: this.extend.bind(this) });
147
+ asClass() {
148
+ return createClassResolver("", this._buildComponentConfig());
135
149
  }
136
150
  _buildComponentConfig() {
137
151
  const variantConfig = {};
@@ -152,31 +166,48 @@ var AnimusWithAll = class {
152
166
  }
153
167
  };
154
168
  var AnimusWithSystem = class extends AnimusWithAll {
155
- constructor(props, groups, base, variants, states, activeGroups) {
156
- super(props, groups, base, variants, states, activeGroups, {});
169
+ constructor(props, groups, base, variants, states, activeGroups, compounds = []) {
170
+ super(props, groups, base, variants, states, activeGroups, {}, compounds);
157
171
  }
158
172
  props(config) {
159
- return new AnimusWithAll(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, this.activeGroups, config);
173
+ return new AnimusWithAll(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, this.activeGroups, config, this.compounds);
160
174
  }
161
175
  };
162
176
  var AnimusWithStates = class extends AnimusWithSystem {
163
- constructor(props, groups, base, variants, states) {
164
- super(props, groups, base, variants, states, {});
177
+ constructor(props, groups, base, variants, states, compounds = []) {
178
+ super(props, groups, base, variants, states, {}, compounds);
165
179
  }
166
- groups(config) {
167
- return new AnimusWithSystem(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, config);
180
+ system(config) {
181
+ return new AnimusWithSystem(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, this.statesConfig, config, this.compounds);
168
182
  }
169
183
  };
170
- var AnimusWithVariants = class AnimusWithVariants extends AnimusWithStates {
171
- constructor(props, groups, base, variants) {
172
- super(props, groups, base, variants, {});
184
+ var AnimusWithCompounds = class AnimusWithCompounds extends AnimusWithStates {
185
+ constructor(props, groups, base, variants, compounds = []) {
186
+ super(props, groups, base, variants, {}, compounds);
187
+ }
188
+ compound(condition, styles) {
189
+ return new AnimusWithCompounds(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, [...this.compounds, {
190
+ condition,
191
+ styles
192
+ }]);
173
193
  }
174
194
  states(config) {
175
- return new AnimusWithStates(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, config);
195
+ return new AnimusWithStates(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, config, this.compounds);
196
+ }
197
+ };
198
+ var AnimusWithVariants = class AnimusWithVariants extends AnimusWithCompounds {
199
+ constructor(props, groups, base, variants, compounds = []) {
200
+ super(props, groups, base, variants, compounds);
201
+ }
202
+ compound(condition, styles) {
203
+ return new AnimusWithCompounds(this.propRegistry, this.groupRegistry, this.baseStyles, this.variants, [...this.compounds, {
204
+ condition,
205
+ styles
206
+ }]);
176
207
  }
177
208
  variant(options) {
178
209
  const prop = options.prop || "variant";
179
- return new AnimusWithVariants(this.propRegistry, this.groupRegistry, this.baseStyles, deepMerge(this.variants, { [prop]: options }));
210
+ return new AnimusWithVariants(this.propRegistry, this.groupRegistry, this.baseStyles, deepMerge(this.variants, { [prop]: options }), this.compounds);
180
211
  }
181
212
  };
182
213
  var AnimusWithBase = class extends AnimusWithVariants {
@@ -185,7 +216,7 @@ var AnimusWithBase = class extends AnimusWithVariants {
185
216
  }
186
217
  variant(options) {
187
218
  const prop = options.prop || "variant";
188
- return new AnimusWithVariants(this.propRegistry, this.groupRegistry, this.baseStyles, deepMerge(this.variants, { [prop]: options }));
219
+ return new AnimusWithVariants(this.propRegistry, this.groupRegistry, this.baseStyles, deepMerge(this.variants, { [prop]: options }), this.compounds);
189
220
  }
190
221
  };
191
222
  var Animus = class extends AnimusWithBase {
@@ -197,78 +228,275 @@ var Animus = class extends AnimusWithBase {
197
228
  }
198
229
  };
199
230
  //#endregion
200
- //#region src/PropertyBuilder.ts
201
- var PropertyBuilder = class PropertyBuilder {
202
- #props;
203
- #groups;
204
- constructor(props, groups) {
205
- this.#props = props || {};
206
- this.#groups = groups || {};
231
+ //#region src/keyframes.ts
232
+ const fnv1a = (input) => {
233
+ let hash = 2166136261;
234
+ for (let i = 0; i < input.length; i++) {
235
+ hash ^= input.charCodeAt(i);
236
+ hash = hash + ((hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24)) >>> 0;
237
+ }
238
+ return hash.toString(36);
239
+ };
240
+ const serializeFrames = (frames) => {
241
+ return Object.keys(frames).sort().map((stop) => {
242
+ const frame = frames[stop] ?? {};
243
+ return `${stop}{${Object.keys(frame).sort().map((p) => `${p}:${String(frame[p])}`).join(";")}}`;
244
+ }).join("|");
245
+ };
246
+ const generateName = (frames) => `animus-kf-${fnv1a(serializeFrames(frames))}`;
247
+ const createRef = (name, resolvedName) => ({
248
+ __brand: "KeyframeRef",
249
+ __name: name,
250
+ toString() {
251
+ return resolvedName;
252
+ },
253
+ valueOf() {
254
+ return resolvedName;
255
+ }
256
+ });
257
+ function keyframes(map) {
258
+ const frameData = {};
259
+ const refs = {};
260
+ for (const key of Object.keys(map)) {
261
+ const frames = map[key];
262
+ const resolvedName = generateName(frames);
263
+ frameData[key] = {
264
+ name: resolvedName,
265
+ frames
266
+ };
267
+ refs[key] = createRef(key, resolvedName);
207
268
  }
208
- addGroup(name, config) {
209
- const newGroup = { [name]: Object.keys(config) };
210
- return new PropertyBuilder({
211
- ...this.#props,
212
- ...config
213
- }, {
214
- ...this.#groups,
215
- ...newGroup
216
- });
269
+ return {
270
+ __brand: "Keyframes",
271
+ __frames: frameData,
272
+ ...refs
273
+ };
274
+ }
275
+ //#endregion
276
+ //#region src/selectors.ts
277
+ /**
278
+ * Built-in selector aliases.
279
+ *
280
+ * Compound selectors (e.g. `_disabled`) target multiple CSS selectors
281
+ * via comma-separation to cover native, ARIA, and data attribute conventions.
282
+ */
283
+ const BUILT_IN_SELECTORS = {
284
+ _link: {
285
+ selector: "&:link",
286
+ order: 10
287
+ },
288
+ _visited: {
289
+ selector: "&:visited",
290
+ order: 20
291
+ },
292
+ _hover: {
293
+ selector: "&:hover",
294
+ order: 30
295
+ },
296
+ _focusWithin: {
297
+ selector: "&:focus-within",
298
+ order: 40
299
+ },
300
+ _focus: {
301
+ selector: "&:focus",
302
+ order: 50
303
+ },
304
+ _focusVisible: {
305
+ selector: "&:focus-visible",
306
+ order: 60
307
+ },
308
+ _active: {
309
+ selector: "&:active",
310
+ order: 70
311
+ },
312
+ _target: {
313
+ selector: "&:target",
314
+ order: 80
315
+ },
316
+ _checked: {
317
+ selector: "&:checked, &[aria-checked=\"true\"], &[data-checked]",
318
+ order: 100
319
+ },
320
+ _invalid: {
321
+ selector: "&:invalid, &[aria-invalid=\"true\"], &[data-invalid]",
322
+ order: 110
323
+ },
324
+ _required: {
325
+ selector: "&:required, &[aria-required=\"true\"]",
326
+ order: 120
327
+ },
328
+ _readOnly: {
329
+ selector: "&:read-only, &[aria-readonly=\"true\"], &[data-readonly]",
330
+ order: 130
331
+ },
332
+ _expanded: {
333
+ selector: "&[aria-expanded=\"true\"], &[data-expanded]",
334
+ order: 140
335
+ },
336
+ _selected: {
337
+ selector: "&[aria-selected=\"true\"], &[data-selected]",
338
+ order: 150
339
+ },
340
+ _pressed: {
341
+ selector: "&[aria-pressed=\"true\"], &[data-pressed]",
342
+ order: 160
343
+ },
344
+ _disabled: {
345
+ selector: "&:disabled, &[disabled], &[aria-disabled=\"true\"], &[data-disabled]",
346
+ order: 200
347
+ },
348
+ _before: {
349
+ selector: "&::before",
350
+ order: 300
351
+ },
352
+ _after: {
353
+ selector: "&::after",
354
+ order: 310
355
+ },
356
+ _placeholder: {
357
+ selector: "&::placeholder",
358
+ order: 320
359
+ },
360
+ _selection: {
361
+ selector: "&::selection",
362
+ order: 330
363
+ },
364
+ _first: {
365
+ selector: "&:first-child",
366
+ order: 400
367
+ },
368
+ _last: {
369
+ selector: "&:last-child",
370
+ order: 410
371
+ },
372
+ _even: {
373
+ selector: "&:nth-child(even)",
374
+ order: 420
375
+ },
376
+ _odd: {
377
+ selector: "&:nth-child(odd)",
378
+ order: 430
379
+ },
380
+ _empty: {
381
+ selector: "&:empty",
382
+ order: 440
217
383
  }
218
- build() {
219
- return {
220
- propRegistry: this.#props,
221
- groupRegistry: this.#groups
384
+ };
385
+ /**
386
+ * Merge user-provided selectors with built-in defaults.
387
+ * User selectors override built-in aliases of the same name.
388
+ * New aliases get an order value based on their position (500+).
389
+ */
390
+ function mergeSelectors(base, custom) {
391
+ const merged = { ...base };
392
+ let nextOrder = 500;
393
+ for (const [key, selector] of Object.entries(custom)) if (key in merged) merged[key] = {
394
+ selector,
395
+ order: merged[key].order
396
+ };
397
+ else {
398
+ merged[key] = {
399
+ selector,
400
+ order: nextOrder
222
401
  };
402
+ nextOrder += 10;
223
403
  }
224
- };
404
+ return merged;
405
+ }
406
+ /** Get the sorted alias keys for deterministic cascade ordering. */
407
+ function getSortedAliasKeys(map) {
408
+ return Object.keys(map).sort((a, b) => map[a].order - map[b].order);
409
+ }
410
+ /**
411
+ * Serialize the selector map for the extraction pipeline.
412
+ * Emits a flat `Record<string, string>` (alias → selector) plus
413
+ * the ordered key list for cascade determinism.
414
+ */
415
+ function serializeSelectorMap(map) {
416
+ const selectors = {};
417
+ const order = getSortedAliasKeys(map);
418
+ for (const key of order) selectors[key] = map[key].selector;
419
+ return {
420
+ selectors,
421
+ order
422
+ };
423
+ }
225
424
  //#endregion
226
425
  //#region src/SystemBuilder.ts
227
426
  var SystemBuilder = class SystemBuilder {
228
- #tokens;
229
427
  #propRegistry;
230
428
  #groupRegistry;
231
- #globalStyles;
232
- constructor(tokens, propRegistry, groupRegistry, globalStyles) {
233
- this.#tokens = tokens || {};
429
+ #selectorRegistry;
430
+ #includesRegistry;
431
+ constructor(propRegistry, groupRegistry, selectorRegistry, includesRegistry) {
234
432
  this.#propRegistry = propRegistry || {};
235
433
  this.#groupRegistry = groupRegistry || {};
236
- this.#globalStyles = globalStyles;
434
+ this.#selectorRegistry = selectorRegistry || { ...BUILT_IN_SELECTORS };
435
+ this.#includesRegistry = includesRegistry || [];
237
436
  }
238
- withTokens(cb) {
239
- return new SystemBuilder(cb(createTheme({ breakpoints: {
240
- xs: 0,
241
- sm: 0,
242
- md: 0,
243
- lg: 0,
244
- xl: 0
245
- } })), this.#propRegistry, this.#groupRegistry, this.#globalStyles);
437
+ addSelectors(selectors) {
438
+ const merged = mergeSelectors(this.#selectorRegistry, selectors);
439
+ return new SystemBuilder(this.#propRegistry, this.#groupRegistry, merged, this.#includesRegistry);
246
440
  }
247
- withProperties(cb) {
248
- const result = cb(new PropertyBuilder());
249
- return new SystemBuilder(this.#tokens, result.propRegistry, result.groupRegistry, this.#globalStyles);
250
- }
251
- withGlobalStyles(styles) {
252
- return new SystemBuilder(this.#tokens, this.#propRegistry, this.#groupRegistry, styles);
441
+ addGroup(name, config) {
442
+ if (name in this.#propRegistry) throw new Error(`Group name "${name}" collides with an existing prop name. Group names and prop names must be disjoint.`);
443
+ for (const key of Object.keys(config)) if (key in this.#propRegistry) {
444
+ const existing = this.#propRegistry[key];
445
+ const incoming = config[key];
446
+ if (existing.property !== incoming.property || existing.scale !== incoming.scale || existing.transform !== incoming.transform || existing.negative !== incoming.negative) throw new Error(`Prop "${key}" already registered with a different definition. Existing: property="${existing.property}", scale="${String(existing.scale)}". Incoming: property="${incoming.property}", scale="${String(incoming.scale)}".`);
447
+ }
448
+ const nextProps = {
449
+ ...this.#propRegistry,
450
+ ...config
451
+ };
452
+ const newGroup = { [name]: Object.keys(config) };
453
+ return new SystemBuilder(nextProps, {
454
+ ...this.#groupRegistry,
455
+ ...newGroup
456
+ }, this.#selectorRegistry, this.#includesRegistry);
457
+ }
458
+ addProps(config) {
459
+ for (const key of Object.keys(config)) if (key in this.#groupRegistry) throw new Error(`Prop name "${key}" collides with an existing group name. Group names and prop names must be disjoint.`);
460
+ for (const key of Object.keys(config)) if (key in this.#propRegistry) {
461
+ const existing = this.#propRegistry[key];
462
+ const incoming = config[key];
463
+ if (existing.property !== incoming.property || existing.scale !== incoming.scale || existing.transform !== incoming.transform || existing.negative !== incoming.negative) throw new Error(`Prop "${key}" already registered with a different definition.`);
464
+ }
465
+ return new SystemBuilder({
466
+ ...this.#propRegistry,
467
+ ...config
468
+ }, this.#groupRegistry, this.#selectorRegistry, this.#includesRegistry);
253
469
  }
254
470
  build() {
255
471
  const animus = new Animus(this.#propRegistry, this.#groupRegistry);
256
- const globalStyles = this.#globalStyles;
257
- return Object.assign(animus, {
258
- tokens: this.#tokens,
259
- serialize: () => {
260
- return serializeInstance(this.#tokens, this.#propRegistry, this.#groupRegistry, globalStyles);
261
- }
262
- });
472
+ const propRegistry = this.#propRegistry;
473
+ const groupRegistry = this.#groupRegistry;
474
+ const selectorRegistry = this.#selectorRegistry;
475
+ const system = Object.assign(animus, { toConfig: () => {
476
+ return serializeInstance(propRegistry, groupRegistry, selectorRegistry);
477
+ } });
478
+ const createGlobalStyles = ((styles) => ({
479
+ __brand: "GlobalStyleBlock",
480
+ styles
481
+ }));
482
+ const createKeyframes = ((frames) => keyframes(frames));
483
+ return {
484
+ system,
485
+ createGlobalStyles,
486
+ createKeyframes
487
+ };
263
488
  }
264
489
  };
265
- function serializeInstance(tokens, propRegistry, groupRegistry, globalStyles) {
490
+ function serializeInstance(propRegistry, groupRegistry, selectorRegistry) {
266
491
  const serialized = {};
267
492
  const transforms = {};
268
493
  for (const [propName, entry] of Object.entries(propRegistry)) {
269
494
  const s = { property: entry.property };
270
495
  if (entry.properties && entry.properties.length > 0) s.properties = [...entry.properties];
271
- if (typeof entry.scale === "string") s.scale = entry.scale;
496
+ const scale = entry.scale;
497
+ if (typeof scale === "string") s.scale = scale;
498
+ else if (scale && typeof scale === "object") s.scale = scale;
499
+ if (entry.negative) s.negative = true;
272
500
  if (entry.transform) {
273
501
  const fn = entry.transform;
274
502
  const name = fn.transformName ?? fn.name;
@@ -277,19 +505,397 @@ function serializeInstance(tokens, propRegistry, groupRegistry, globalStyles) {
277
505
  transforms[name] = fn;
278
506
  }
279
507
  }
508
+ if (entry.currentVar) s.currentVar = entry.currentVar;
280
509
  serialized[propName] = s;
281
510
  }
282
- const result = {
283
- tokens,
511
+ const { selectors, order } = serializeSelectorMap(selectorRegistry);
512
+ return {
284
513
  propConfig: JSON.stringify(serialized),
285
514
  groupRegistry: JSON.stringify(groupRegistry),
286
- transforms
515
+ transforms,
516
+ selectorAliases: JSON.stringify(selectors),
517
+ selectorOrder: JSON.stringify(order)
287
518
  };
288
- if (globalStyles) result.globalStyles = globalStyles;
519
+ }
520
+ function createSystem(config) {
521
+ return new SystemBuilder(void 0, void 0, void 0, config?.includes ?? []);
522
+ }
523
+ //#endregion
524
+ //#region src/theme/utils.ts
525
+ /** Type guard: true for non-null, non-array objects */
526
+ function isObject(value) {
527
+ return value !== null && typeof value === "object" && !Array.isArray(value);
528
+ }
529
+ function merge(target, ...sources) {
530
+ for (const source of sources) {
531
+ if (!source) continue;
532
+ for (const key of Object.keys(source)) {
533
+ const targetVal = target[key];
534
+ const sourceVal = source[key];
535
+ if (isObject(targetVal) && isObject(sourceVal)) target[key] = merge(targetVal, sourceVal);
536
+ else target[key] = sourceVal;
537
+ }
538
+ }
539
+ return target;
540
+ }
541
+ /**
542
+ * Resolve a dot-path string against a nested object.
543
+ * walkDotPath({ gray: { 50: '#fafafa' } }, 'gray.50') → '#fafafa'
544
+ * The `_` identity key is handled: 'primary' resolves to obj.primary._ if obj.primary is an object with _.
545
+ */
546
+ function walkDotPath(obj, path) {
547
+ const parts = path.split(".");
548
+ let current = obj;
549
+ for (const part of parts) {
550
+ if (!isObject(current)) return void 0;
551
+ current = current[part];
552
+ }
553
+ return current;
554
+ }
555
+ /**
556
+ * Flatten a nested object into a flat Record with dot-path keys.
557
+ * The `_` key is an identity marker — it produces the parent key without suffix.
558
+ * { gray: { 50: '#fafafa' } } → { 'gray.50': '#fafafa' }
559
+ * { primary: { _: 'ember', hover: 'x' } } → { 'primary': 'ember', 'primary.hover': 'x' }
560
+ * CSS variable names use dash-join, computed at the serialization boundary (not here).
561
+ */
562
+ function flattenToDotPaths(object, path) {
563
+ const result = {};
564
+ for (const key of Object.keys(object)) {
565
+ const nextKey = path ? key === "_" ? path : `${path}.${key}` : key;
566
+ const current = object[key];
567
+ if (isObject(current)) Object.assign(result, flattenToDotPaths(current, nextKey));
568
+ else result[nextKey] = current;
569
+ }
289
570
  return result;
290
571
  }
291
- function createSystem() {
292
- return new SystemBuilder();
572
+ /**
573
+ * Convert a dot-path key to a dash-join key for CSS variable naming.
574
+ * 'gray.50' → 'gray-50'
575
+ * 'primary.hover' → 'primary-hover'
576
+ */
577
+ function dotToDash(dotPath) {
578
+ return dotPath.replace(/\./g, "-");
579
+ }
580
+ /** Map over object values — matches lodash.mapValues overload signatures */
581
+ //#endregion
582
+ //#region src/theme/createTheme.ts
583
+ const COLOR_FUNCTION_PREFIXES = [
584
+ "rgb(",
585
+ "rgba(",
586
+ "hsl(",
587
+ "hsla(",
588
+ "oklch(",
589
+ "oklab(",
590
+ "lch(",
591
+ "lab(",
592
+ "color(",
593
+ "color-mix("
594
+ ];
595
+ /** Validate that a value is a valid CSS <color>. */
596
+ function isValidCSSColor(value) {
597
+ if (typeof value !== "string") return false;
598
+ const v = value.trim();
599
+ if (v === "") return false;
600
+ if (v === "transparent" || v === "currentColor" || v === "currentcolor") return true;
601
+ if (v.startsWith("#") && /^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(v)) return true;
602
+ for (const prefix of COLOR_FUNCTION_PREFIXES) if (v.startsWith(prefix) && v.endsWith(")")) return true;
603
+ if (/^[a-zA-Z]+$/.test(v)) return true;
604
+ return false;
605
+ }
606
+ /**
607
+ * Validate that mode aliases reference existing color keys via dot-path traversal.
608
+ * Aliases are dot-path strings like 'gray.50' that must resolve in the nested color structure.
609
+ */
610
+ function validateModeAliases(modeName, aliases, nestedColors, flatColorKeys, prefix) {
611
+ for (const [key, value] of Object.entries(aliases)) {
612
+ const aliasPath = prefix ? `${prefix}.${key}` : key;
613
+ if (key === "_") {
614
+ if (typeof value === "string") {
615
+ if (walkDotPath(nestedColors, value) === void 0) throw new Error(`addColorModes: mode '${modeName}' references unknown color '${value}' for alias '${prefix || key}'. Available colors: ${flatColorKeys.slice(0, 10).join(", ")}${flatColorKeys.length > 10 ? ", ..." : ""}`);
616
+ } else if (isObject(value)) validateModeAliases(modeName, value, nestedColors, flatColorKeys, prefix);
617
+ } else if (typeof value === "string") {
618
+ if (walkDotPath(nestedColors, value) === void 0) throw new Error(`addColorModes: mode '${modeName}' references unknown color '${value}' for alias '${aliasPath}'. Available colors: ${flatColorKeys.slice(0, 10).join(", ")}${flatColorKeys.length > 10 ? ", ..." : ""}`);
619
+ } else if (isObject(value)) validateModeAliases(modeName, value, nestedColors, flatColorKeys, aliasPath);
620
+ }
621
+ }
622
+ /** Validate all color entries, throwing on invalid values. */
623
+ function validateColors(colors) {
624
+ for (const [key, value] of Object.entries(colors)) if (isObject(value)) validateColors(value);
625
+ else if (!isValidCSSColor(value)) throw new Error(`addColors: '${String(value)}' is not a valid CSS <color> value for key '${key}'. Expected hex (#fff), rgb(), hsl(), oklch(), named color, transparent, or currentColor.`);
626
+ }
627
+ function createState(theme) {
628
+ return {
629
+ theme: theme || { breakpoints: {} },
630
+ emittedScales: /* @__PURE__ */ new Set(),
631
+ contextualVars: /* @__PURE__ */ new Map()
632
+ };
633
+ }
634
+ function copyState(state, nextTheme) {
635
+ const next = {
636
+ theme: nextTheme,
637
+ emittedScales: new Set(state.emittedScales),
638
+ contextualVars: /* @__PURE__ */ new Map()
639
+ };
640
+ for (const [scale, vars] of state.contextualVars) next.contextualVars.set(scale, [...vars]);
641
+ return next;
642
+ }
643
+ /**
644
+ * ThemeScales — the final phase. Has addScale, extendScale, declareContextualVars, build.
645
+ * Also allows addColors and addColorModes for augmentation.
646
+ */
647
+ var ThemeBuilder = class ThemeBuilder {
648
+ /** @internal */ _state;
649
+ constructor(state) {
650
+ this._state = state;
651
+ }
652
+ addBreakpoints(breakpoints) {
653
+ for (const [key, value] of Object.entries(breakpoints)) if (typeof value !== "number" || value < 0) throw new Error(`addBreakpoints: breakpoint '${key}' must be a non-negative number, got ${JSON.stringify(value)}`);
654
+ const nextTheme = merge({}, this._state.theme, { breakpoints });
655
+ return new ThemeBuilder(copyState(this._state, nextTheme));
656
+ }
657
+ from(builtTheme) {
658
+ const raw = {};
659
+ for (const key of Object.keys(builtTheme)) {
660
+ const val = builtTheme[key];
661
+ if (typeof val !== "function") raw[key] = val;
662
+ }
663
+ const nextTheme = merge({}, this._state.theme, raw);
664
+ const next = new ThemeBuilder(copyState(this._state, nextTheme));
665
+ const manifest = builtTheme.manifest;
666
+ if (manifest?.variableMap) for (const tokenPath of Object.keys(manifest.variableMap)) {
667
+ const scale = tokenPath.split(".")[0];
668
+ next._state.emittedScales.add(scale === "colors" ? "colors" : scale);
669
+ }
670
+ if (manifest?.contextualVars) for (const [scale, vars] of Object.entries(manifest.contextualVars)) next._state.contextualVars.set(scale, [...vars]);
671
+ return next;
672
+ }
673
+ addColors(colors) {
674
+ validateColors(colors);
675
+ const nextTheme = merge({}, this._state.theme, { colors });
676
+ const next = new ThemeBuilder(copyState(this._state, nextTheme));
677
+ next._state.emittedScales.add("colors");
678
+ return next;
679
+ }
680
+ addColorModes(initialMode, modeConfig) {
681
+ const nestedColors = this._state.theme.colors || {};
682
+ const flatColors = flattenToDotPaths(nestedColors);
683
+ const flatColorKeys = Object.keys(flatColors);
684
+ for (const [modeName, modeAliases] of Object.entries(modeConfig)) validateModeAliases(modeName, modeAliases, nestedColors, flatColorKeys, "");
685
+ const nextTheme = merge({}, this._state.theme, {
686
+ modes: modeConfig,
687
+ mode: initialMode
688
+ });
689
+ return new ThemeBuilder(copyState(this._state, nextTheme));
690
+ }
691
+ addScale(config) {
692
+ const { name, values, emit } = config;
693
+ const nextTheme = merge({}, this._state.theme, { [name]: values });
694
+ const next = new ThemeBuilder(copyState(this._state, nextTheme));
695
+ if (emit) next._state.emittedScales.add(name);
696
+ return next;
697
+ }
698
+ declareContextualVars(vars) {
699
+ for (const scale of Object.keys(vars)) if (!(scale in this._state.theme)) throw new Error(`declareContextualVars: scale '${scale}' not found — call addColors or addScale first`);
700
+ const next = new ThemeBuilder(copyState(this._state, this._state.theme));
701
+ for (const [scale, names] of Object.entries(vars)) {
702
+ const existing = next._state.contextualVars.get(scale) || [];
703
+ next._state.contextualVars.set(scale, [...existing, ...names]);
704
+ }
705
+ return next;
706
+ }
707
+ extendScale(key, updateFn) {
708
+ const nextTheme = merge({}, this._state.theme, { [key]: updateFn(this._state.theme[key]) });
709
+ return new ThemeBuilder(copyState(this._state, nextTheme));
710
+ }
711
+ /**
712
+ * Finalize the theme build.
713
+ * Flattens nested data at the boundary — produces manifest and serialize().
714
+ */
715
+ build() {
716
+ const theme = merge({}, this._state.theme);
717
+ const emittedScales = this._state.emittedScales;
718
+ const contextualVars = this._state.contextualVars;
719
+ const { tokenMap, variableMap, variables, modeVariables, modeTokens } = flattenTheme(theme, emittedScales);
720
+ resolveTokenRefs(tokenMap, variableMap, emittedScales);
721
+ const bpVariables = {};
722
+ if (theme.breakpoints && isObject(theme.breakpoints)) for (const [key, value] of Object.entries(theme.breakpoints)) bpVariables[`--breakpoint-${key}`] = `${value}px`;
723
+ let contextualVarsSerialized;
724
+ if (contextualVars.size > 0) {
725
+ contextualVarsSerialized = {};
726
+ for (const [scale, vars] of contextualVars) contextualVarsSerialized[scale] = vars;
727
+ }
728
+ const variableCss = buildVariableCss(variables, bpVariables, modeVariables);
729
+ const manifest = {
730
+ tokenMap: {
731
+ ...tokenMap,
732
+ ...Object.fromEntries(Object.entries(theme.breakpoints || {}).map(([k, v]) => [`breakpoints.${k}`, String(v)]))
733
+ },
734
+ variableMap,
735
+ modes: modeTokens,
736
+ variableCss,
737
+ ...contextualVarsSerialized ? { contextualVars: contextualVarsSerialized } : {}
738
+ };
739
+ Object.defineProperty(theme, "manifest", {
740
+ value: manifest,
741
+ enumerable: false,
742
+ configurable: false,
743
+ writable: false
744
+ });
745
+ Object.defineProperty(theme, "serialize", {
746
+ value: () => ({
747
+ scalesJson: JSON.stringify(manifest.tokenMap),
748
+ variableMapJson: JSON.stringify(manifest.variableMap),
749
+ variableCss: manifest.variableCss,
750
+ contextualVarsJson: JSON.stringify(manifest.contextualVars ?? {})
751
+ }),
752
+ enumerable: false,
753
+ configurable: false,
754
+ writable: false
755
+ });
756
+ Object.defineProperty(theme, "varRef", {
757
+ value: (tokenPath) => {
758
+ const varName = variableMap[tokenPath];
759
+ if (varName) return `var(${varName})`;
760
+ const dotIdx = tokenPath.indexOf(".");
761
+ if (dotIdx === -1) return void 0;
762
+ const scale = tokenPath.slice(0, dotIdx);
763
+ const key = tokenPath.slice(dotIdx + 1);
764
+ const scaleObj = theme[scale];
765
+ if (!isObject(scaleObj)) return void 0;
766
+ const val = walkDotPath(scaleObj, key);
767
+ return val !== void 0 ? String(val) : void 0;
768
+ },
769
+ enumerable: false,
770
+ configurable: false,
771
+ writable: false
772
+ });
773
+ return theme;
774
+ }
775
+ };
776
+ function createTheme() {
777
+ return new ThemeBuilder(createState());
778
+ }
779
+ /** Token ref pattern: {scale.key} or {scale.key.sub} */
780
+ const TOKEN_REF_RE = /\{([^}]+)\}/g;
781
+ /**
782
+ * Flatten the nested theme into dot-path keyed token map and CSS variable declarations.
783
+ * This is the ONLY place where flattening happens.
784
+ */
785
+ function flattenTheme(theme, emittedScales) {
786
+ const tokenMap = {};
787
+ const variableMap = {};
788
+ const variables = {};
789
+ const modeVariables = {};
790
+ const modeTokens = {};
791
+ for (const [scaleName, scaleValue] of Object.entries(theme)) {
792
+ if (scaleName.startsWith("_")) continue;
793
+ if (scaleName === "breakpoints" || scaleName === "mode" || scaleName === "modes") continue;
794
+ if (typeof scaleValue === "function") continue;
795
+ if (!isObject(scaleValue)) continue;
796
+ const flat = flattenToDotPaths(scaleValue);
797
+ const isEmitted = emittedScales.has(scaleName);
798
+ for (const [dotKey, rawValue] of Object.entries(flat)) {
799
+ const tokenPath = `${scaleName}.${dotKey}`;
800
+ const dashKey = dotToDash(dotKey);
801
+ const varName = `--${scaleName === "colors" ? "color" : scaleName}-${dashKey}`;
802
+ if (isEmitted) {
803
+ tokenMap[tokenPath] = `var(${varName})`;
804
+ variableMap[tokenPath] = varName;
805
+ variables[varName] = String(rawValue);
806
+ } else tokenMap[tokenPath] = String(rawValue);
807
+ }
808
+ }
809
+ if (theme.modes && isObject(theme.modes) && theme.colors && isObject(theme.colors)) {
810
+ const flatColors = flattenToDotPaths(theme.colors);
811
+ for (const [modeName, modeAliases] of Object.entries(theme.modes)) {
812
+ if (!isObject(modeAliases)) continue;
813
+ const flatAliases = flattenToDotPaths(modeAliases);
814
+ const modeVars = {};
815
+ const modeVals = {};
816
+ for (const [aliasDotKey, colorRef] of Object.entries(flatAliases)) {
817
+ if (typeof colorRef !== "string") continue;
818
+ const varName = `--color-${dotToDash(aliasDotKey)}`;
819
+ const rawValue = flatColors[colorRef];
820
+ modeVals[`colors.${aliasDotKey}`] = rawValue !== void 0 ? String(rawValue) : String(colorRef);
821
+ modeVars[varName] = rawValue !== void 0 ? String(rawValue) : String(colorRef);
822
+ }
823
+ modeVariables[modeName] = modeVars;
824
+ modeTokens[modeName] = modeVals;
825
+ }
826
+ const initialMode = theme.mode;
827
+ if (initialMode && modeVariables[initialMode]) {
828
+ const initialModeVars = {};
829
+ const flatInitialAliases = flattenToDotPaths(theme.modes[initialMode]);
830
+ for (const [aliasDotKey, colorRef] of Object.entries(flatInitialAliases)) {
831
+ if (typeof colorRef !== "string") continue;
832
+ const varName = `--color-${dotToDash(aliasDotKey)}`;
833
+ const paletteVarName = variableMap[`colors.${colorRef}`];
834
+ if (paletteVarName) initialModeVars[varName] = `var(${paletteVarName})`;
835
+ tokenMap[`colors.${aliasDotKey}`] = `var(${varName})`;
836
+ variableMap[`colors.${aliasDotKey}`] = varName;
837
+ }
838
+ Object.assign(variables, initialModeVars);
839
+ }
840
+ }
841
+ return {
842
+ tokenMap,
843
+ variableMap,
844
+ variables,
845
+ modeVariables,
846
+ modeTokens
847
+ };
848
+ }
849
+ /**
850
+ * Resolve token refs ({scale.key}) in all flattened token values.
851
+ * Operates on the flattened tokenMap — does NOT mutate the nested theme.
852
+ */
853
+ function resolveTokenRefs(tokenMap, _variableMap, _emittedScales) {
854
+ for (const [tokenPath, value] of Object.entries(tokenMap)) {
855
+ if (typeof value !== "string") continue;
856
+ if (!value.includes("{")) continue;
857
+ if (value.startsWith("var(")) continue;
858
+ const scaleName = tokenPath.split(".")[0];
859
+ const resolved = value.replace(TOKEN_REF_RE, (match, ref) => {
860
+ if (ref.split(".")[0] === scaleName) {
861
+ console.warn(`[animus] Self-referential token ref {${ref}} in scale '${scaleName}' — skipped`);
862
+ return match;
863
+ }
864
+ let lookupPath = ref;
865
+ let opacity;
866
+ const slashIdx = ref.indexOf("/");
867
+ if (slashIdx !== -1) {
868
+ lookupPath = ref.slice(0, slashIdx);
869
+ opacity = ref.slice(slashIdx + 1);
870
+ }
871
+ const refValue = tokenMap[lookupPath];
872
+ if (refValue === void 0) {
873
+ console.warn(`[animus] Token ref {${ref}} — path '${lookupPath}' not found in token map`);
874
+ return match;
875
+ }
876
+ if (opacity) {
877
+ const alpha = Number.parseInt(opacity, 10);
878
+ if (alpha === 0) return "transparent";
879
+ if (alpha !== 100) return `color-mix(in srgb, ${refValue} ${alpha}%, transparent)`;
880
+ }
881
+ return refValue;
882
+ });
883
+ if (resolved !== value) tokenMap[tokenPath] = resolved;
884
+ }
885
+ }
886
+ /** Build CSS variable blocks from flattened data. */
887
+ function buildVariableCss(rootVariables, breakpointVariables, modeVariables) {
888
+ const parts = [];
889
+ const rootLines = [];
890
+ for (const [varName, value] of Object.entries(rootVariables)) rootLines.push(` ${varName}: ${value};`);
891
+ for (const [varName, value] of Object.entries(breakpointVariables)) rootLines.push(` ${varName}: ${value};`);
892
+ if (rootLines.length > 0) parts.push(`:root {\n${rootLines.join("\n")}\n}`);
893
+ for (const [modeName, modeVars] of Object.entries(modeVariables)) {
894
+ const modeLines = [];
895
+ for (const [varName, value] of Object.entries(modeVars)) modeLines.push(` ${varName}: ${value};`);
896
+ if (modeLines.length > 0) parts.push(`[data-color-mode="${modeName}"] {\n${modeLines.join("\n")}\n}`);
897
+ }
898
+ return parts.join("\n\n");
293
899
  }
294
900
  //#endregion
295
- export { Animus, AnimusExtended, AnimusExtendedWithAll, AnimusWithAll, PropertyBuilder, SystemBuilder, borderShorthand, createScale, createSystem, createTransform, gridItem, gridItemRatio, numericOrStringScale, numericScale, percentageOrAbsolute, size, stringScale };
901
+ export { Animus, AnimusExtended, AnimusExtendedWithAll, AnimusWithAll, BUILT_IN_SELECTORS, SystemBuilder, ThemeBuilder, borderShorthand, compose, createClassResolver, createComponent, createComposedFamily, createScale, createSystem, createTheme, createTransform, gridItem, gridItemRatio, numericOrStringScale, numericScale, percentageOrAbsolute, size, stringScale };