fashionable 0.3.0 → 0.4.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 (61) hide show
  1. package/dist/calc/index.d.mts +1 -1
  2. package/dist/calc/index.mjs +1 -1
  3. package/dist/data/index.d.mts +2 -208
  4. package/dist/data/index.mjs +73 -54
  5. package/dist/data/index.mjs.map +1 -1
  6. package/dist/declaration/index.d.mts +1 -1
  7. package/dist/declaration/index.mjs +9 -28
  8. package/dist/declaration/index.mjs.map +1 -1
  9. package/dist/fontFace/index.d.mts +1 -1
  10. package/dist/property/index.d.mts +1 -1
  11. package/dist/property/index.mjs +1 -1
  12. package/dist/property/index.mjs.map +1 -1
  13. package/dist/query/index.d.mts +1 -1
  14. package/dist/rule/index.d.mts +1 -1
  15. package/dist/rule/index.mjs +45 -33
  16. package/dist/rule/index.mjs.map +1 -1
  17. package/dist/selector/index.d.mts +1 -1
  18. package/dist/selector/index.mjs +117 -21
  19. package/dist/selector/index.mjs.map +1 -1
  20. package/dist/shared/{calc-Cih4o2r7.mjs → calc-Uwbxd7CS.mjs} +233 -165
  21. package/dist/shared/calc-Uwbxd7CS.mjs.map +1 -0
  22. package/dist/shared/{color.internal-9fpSiiJk.mjs → color.internal-CxjlaRqR.mjs} +46 -11
  23. package/dist/shared/color.internal-CxjlaRqR.mjs.map +1 -0
  24. package/dist/shared/declaration-CqRm38oZ.d.mts +264 -0
  25. package/dist/shared/declaration.internal-bHzvbanA.mjs +121 -0
  26. package/dist/shared/declaration.internal-bHzvbanA.mjs.map +1 -0
  27. package/dist/shared/{fontFaceRule-DdnLAuVw.d.mts → fontFaceRule-BOgUM4PF.d.mts} +3 -3
  28. package/dist/shared/index-D-hVWDgZ.d.mts +2289 -0
  29. package/dist/shared/{mediaQuery-DsBivHi0.d.mts → mediaQuery-VDIAHnM1.d.mts} +2 -2
  30. package/dist/shared/{mediaRule-4kY2IOq-.d.mts → mediaRule-2K7Ggwe4.d.mts} +169 -105
  31. package/dist/shared/{propertyRule-B5pf7NgH.d.mts → propertyRule-B9ii0mv4.d.mts} +56 -21
  32. package/dist/shared/{propertyRule.internal-CRyFLwbn.mjs → propertyRule.internal-ncYCWUar.mjs} +31 -4
  33. package/dist/shared/propertyRule.internal-ncYCWUar.mjs.map +1 -0
  34. package/dist/shared/{ruleSet.internal-a5m40W9E.mjs → ruleSet.internal-Cj4yIYFI.mjs} +30 -17
  35. package/dist/shared/ruleSet.internal-Cj4yIYFI.mjs.map +1 -0
  36. package/dist/shared/selector-BkxnzX_6.d.mts +615 -0
  37. package/dist/shared/{selector.internal-ESe9s0IH.mjs → selector.internal-B3iu_RpX.mjs} +144 -30
  38. package/dist/shared/selector.internal-B3iu_RpX.mjs.map +1 -0
  39. package/dist/shared/{utils-BKm298I-.d.mts → utils-DpN6qr94.d.mts} +4 -4
  40. package/dist/shared/var.internal-DSxAzEFN.mjs +119 -0
  41. package/dist/shared/var.internal-DSxAzEFN.mjs.map +1 -0
  42. package/dist/stylesheet/index.d.mts +67 -53
  43. package/dist/stylesheet/index.mjs +44 -30
  44. package/dist/stylesheet/index.mjs.map +1 -1
  45. package/dist/utils.d.mts +1 -1
  46. package/dist/utils.mjs.map +1 -1
  47. package/dist/var/index.d.mts +2 -0
  48. package/dist/var/index.mjs +177 -0
  49. package/dist/var/index.mjs.map +1 -0
  50. package/package.json +8 -2
  51. package/dist/shared/calc-Cih4o2r7.mjs.map +0 -1
  52. package/dist/shared/color-BvNJ2YqL.d.mts +0 -590
  53. package/dist/shared/color.internal-9fpSiiJk.mjs.map +0 -1
  54. package/dist/shared/declaration-B-6Ykgs_.d.mts +0 -166
  55. package/dist/shared/declaration.internal-BeasYIJ0.mjs +0 -73
  56. package/dist/shared/declaration.internal-BeasYIJ0.mjs.map +0 -1
  57. package/dist/shared/index-BvtwY4FQ.d.mts +0 -841
  58. package/dist/shared/propertyRule.internal-CRyFLwbn.mjs.map +0 -1
  59. package/dist/shared/ruleSet.internal-a5m40W9E.mjs.map +0 -1
  60. package/dist/shared/selector-HZY-W6l6.d.mts +0 -346
  61. package/dist/shared/selector.internal-ESe9s0IH.mjs.map +0 -1
@@ -2,24 +2,8 @@ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
2
  import { Pipeable, dual, invariant } from "../utils.mjs";
3
3
  import { i as equals$2, n as HashTypeId, o as hashNumber, r as combine, s as hashString, t as EqualTypeId } from "./equal-U9G5LhtL.mjs";
4
4
  import { a as specFidelity, i as specEquals, r as formatWith, t as DEFAULT_FORMAT } from "./format-B9jsmCER.mjs";
5
+ import { _ as RefsTypeId, g as EMPTY_REFS, h as refsOfVar, o as fallbackOf, r as declaredTypeOf, s as isVar, u as nameOf } from "./var.internal-DSxAzEFN.mjs";
5
6
  import { i as toSpec, n as isPrecision$1, r as significant$1, t as decimals$1 } from "./precision.internal-0lv1nEpF.mjs";
6
- //#region src/internal/refs.ts
7
- /**
8
- * Runtime helpers for the unbound-reference sets carried by expression
9
- * values. The matching type-level machinery (the phantom `Refs` parameter
10
- * and `ApplyBindings`) lives with the public types in calc/calc.ts;
11
- * container modules extract refs from heterogeneous members with
12
- * conditionals over their member unions (`RuleSet.MemberRefs`).
13
- */
14
- /** @internal */
15
- const unionRefs = (...sets) => {
16
- const merged = /* @__PURE__ */ new Set();
17
- for (const set of sets) for (const ref of set) merged.add(ref);
18
- return merged;
19
- };
20
- /** @internal */
21
- const EMPTY_REFS = /* @__PURE__ */ new Set();
22
- //#endregion
23
7
  //#region src/calc/calc.internal.ts
24
8
  const CalcTypeId = Symbol.for("fashionable/calc");
25
9
  const isConstant = (node) => node._tag === "Constant";
@@ -219,7 +203,17 @@ const atan2Node = (y, x) => {
219
203
  const substituteNode = (node, bindings) => {
220
204
  switch (node._tag) {
221
205
  case "Constant": return node;
222
- case "Ref": return bindings[node.name] ?? node;
206
+ case "Ref": {
207
+ const bound = bindings[node.name];
208
+ if (bound !== void 0) return bound;
209
+ if (node.fallback === void 0) return node;
210
+ const fallback = substituteNode(node.fallback, bindings);
211
+ return fallback === node.fallback ? node : {
212
+ _tag: "Ref",
213
+ name: node.name,
214
+ fallback
215
+ };
216
+ }
223
217
  case "Ident": return node;
224
218
  case "Add": return addNode(node.terms.map((term) => substituteNode(term, bindings)));
225
219
  case "Subtract": return subtractNode(substituteNode(node.left, bindings), substituteNode(node.right, bindings));
@@ -244,7 +238,7 @@ const substituteNode = (node, bindings) => {
244
238
  * The units that lower with no caller-supplied ratio: `px` is the pixel base
245
239
  * (`1`), a radian is already the numeric measure of its angle (`1`), and a
246
240
  * degree is a fixed `pi / 180` of one. Every other unit is context-dependent
247
- * and must appear in the solve context.
241
+ * and must appear in the `units` section of the solve options.
248
242
  *
249
243
  * @internal
250
244
  */
@@ -254,44 +248,44 @@ const DEFAULT_RATIOS = {
254
248
  deg: Math.PI / 180
255
249
  };
256
250
  /** @internal */
257
- const evaluateNode = (node, context) => {
251
+ const evaluateNode = (node, unitRatios, identValues) => {
258
252
  switch (node._tag) {
259
253
  case "Constant": {
260
254
  if (node.unit === void 0) return node.value;
261
- const ratio = context[node.unit] ?? DEFAULT_RATIOS[node.unit];
262
- invariant(ratio !== void 0, `Cannot evaluate ${node.value}${node.unit}: no ratio for '${node.unit}' in the unit context`);
255
+ const ratio = unitRatios[node.unit] ?? DEFAULT_RATIOS[node.unit];
256
+ invariant(ratio !== void 0, `Cannot evaluate ${node.value}${node.unit}: no ratio for '${node.unit}' in the units section`);
263
257
  return node.value * ratio;
264
258
  }
265
- case "Ref": throw new Error(`Cannot evaluate non-constant reference: ${node.name}`);
259
+ case "Ref": throw new Error(`Cannot evaluate unbound variable: ${node.name}`);
266
260
  case "Ident": {
267
- const value = context[node.name];
268
- invariant(value !== void 0, `Cannot evaluate '${node.name}': no value for it in the solve context`);
261
+ const value = identValues[node.name];
262
+ invariant(value !== void 0, `Cannot evaluate '${node.name}': no value for it in the idents section`);
269
263
  return value;
270
264
  }
271
- case "Add": return node.terms.reduce((total, term) => total + evaluateNode(term, context), 0);
272
- case "Subtract": return evaluateNode(node.left, context) - evaluateNode(node.right, context);
273
- case "Multiply": return evaluateNode(node.left, context) * evaluateNode(node.right, context);
274
- case "Divide": return evaluateNode(node.left, context) / evaluateNode(node.right, context);
265
+ case "Add": return node.terms.reduce((total, term) => total + evaluateNode(term, unitRatios, identValues), 0);
266
+ case "Subtract": return evaluateNode(node.left, unitRatios, identValues) - evaluateNode(node.right, unitRatios, identValues);
267
+ case "Multiply": return evaluateNode(node.left, unitRatios, identValues) * evaluateNode(node.right, unitRatios, identValues);
268
+ case "Divide": return evaluateNode(node.left, unitRatios, identValues) / evaluateNode(node.right, unitRatios, identValues);
275
269
  case "Mod": {
276
- const dividend = evaluateNode(node.left, context);
277
- const divisor = evaluateNode(node.right, context);
270
+ const dividend = evaluateNode(node.left, unitRatios, identValues);
271
+ const divisor = evaluateNode(node.right, unitRatios, identValues);
278
272
  return dividend - divisor * Math.floor(dividend / divisor);
279
273
  }
280
- case "Pow": return evaluateNode(node.base, context) ** evaluateNode(node.exponent, context);
274
+ case "Pow": return evaluateNode(node.base, unitRatios, identValues) ** evaluateNode(node.exponent, unitRatios, identValues);
281
275
  case "SignedPow": {
282
- const base = evaluateNode(node.base, context);
283
- return Math.abs(base) ** evaluateNode(node.exponent, context) * Math.sign(base);
276
+ const base = evaluateNode(node.base, unitRatios, identValues);
277
+ return Math.abs(base) ** evaluateNode(node.exponent, unitRatios, identValues) * Math.sign(base);
284
278
  }
285
- case "Min": return Math.min(...node.args.map((arg) => evaluateNode(arg, context)));
286
- case "Max": return Math.max(...node.args.map((arg) => evaluateNode(arg, context)));
287
- case "Clamp": return Math.max(evaluateNode(node.minimum, context), Math.min(evaluateNode(node.value, context), evaluateNode(node.maximum, context)));
279
+ case "Min": return Math.min(...node.args.map((arg) => evaluateNode(arg, unitRatios, identValues)));
280
+ case "Max": return Math.max(...node.args.map((arg) => evaluateNode(arg, unitRatios, identValues)));
281
+ case "Clamp": return Math.max(evaluateNode(node.minimum, unitRatios, identValues), Math.min(evaluateNode(node.value, unitRatios, identValues), evaluateNode(node.maximum, unitRatios, identValues)));
288
282
  case "Abs":
289
283
  case "Sign":
290
284
  case "Sin":
291
285
  case "Cos":
292
286
  case "Tan":
293
- case "Acos": return UNARY[node._tag].fn(evaluateNode(node.argument, context));
294
- case "Atan2": return Math.atan2(evaluateNode(node.y, context), evaluateNode(node.x, context));
287
+ case "Acos": return UNARY[node._tag].fn(evaluateNode(node.argument, unitRatios, identValues));
288
+ case "Atan2": return Math.atan2(evaluateNode(node.y, unitRatios, identValues), evaluateNode(node.x, unitRatios, identValues));
295
289
  }
296
290
  };
297
291
  /**
@@ -308,6 +302,16 @@ const formatConstant = (node, insideMath, context) => {
308
302
  return node.unit !== void 0 ? `${text}${node.unit}` : text;
309
303
  };
310
304
  const wrapOperand = (node, serialized) => node._tag === "Add" || node._tag === "Subtract" ? `(${serialized})` : serialized;
305
+ /**
306
+ * A fallback renders under the normal top-level rules — `var()`
307
+ * substitution is token-level, so an arithmetic fallback carries its own
308
+ * nested `calc()` wrapper rather than leaning on the surrounding context.
309
+ */
310
+ const serializeFallback = (node, context) => {
311
+ const wrap = needsCalcWrap(node);
312
+ const body = serializeNode(node, wrap, context);
313
+ return wrap ? `calc(${body})` : body;
314
+ };
311
315
  const hasNegativeCoefficient = (node) => {
312
316
  if (isConstant(node)) return node.value < 0;
313
317
  if (node._tag === "Multiply" || node._tag === "Divide") return isConstant(node.left) && node.left.value < 0;
@@ -332,7 +336,7 @@ const serializeNegated = (node, insideMath, context) => {
332
336
  const serializeNode = (node, insideMath, context) => {
333
337
  switch (node._tag) {
334
338
  case "Constant": return formatConstant(node, insideMath, context);
335
- case "Ref": return `var(--${node.name})`;
339
+ case "Ref": return node.fallback === void 0 ? `var(--${node.name})` : `var(--${node.name}, ${serializeFallback(node.fallback, context)})`;
336
340
  case "Ident": return node.name;
337
341
  case "Add": {
338
342
  let out = "";
@@ -382,7 +386,11 @@ const nodeEquals = (a, b) => {
382
386
  const other = b;
383
387
  return a.value === other.value && a.unit === other.unit && specEquals(a.precision, other.precision);
384
388
  }
385
- case "Ref": return a.name === b.name;
389
+ case "Ref": {
390
+ const other = b;
391
+ if (a.name !== other.name) return false;
392
+ return a.fallback === void 0 || other.fallback === void 0 ? a.fallback === other.fallback : nodeEquals(a.fallback, other.fallback);
393
+ }
386
394
  case "Ident": return a.name === b.name;
387
395
  case "Add": return nodeArrayEquals(a.terms, b.terms);
388
396
  case "Subtract":
@@ -428,7 +436,7 @@ const nodeHash = (node) => {
428
436
  const unit = node.unit === void 0 ? 0 : hashString(node.unit);
429
437
  return combine(hashString("Constant"), combine(combine(hashNumber(node.value), precision), unit));
430
438
  }
431
- case "Ref": return combine(hashString("Ref"), hashString(node.name));
439
+ case "Ref": return combine(combine(hashString("Ref"), hashString(node.name)), node.fallback === void 0 ? 0 : nodeHash(node.fallback));
432
440
  case "Ident": return combine(hashString("Ident"), hashString(node.name));
433
441
  case "Add": return hashNodeArray("Add", node.terms);
434
442
  case "Subtract":
@@ -463,6 +471,9 @@ var CalcImpl = class extends Pipeable {
463
471
  this.node = node;
464
472
  this.refSet = refSet;
465
473
  }
474
+ get [RefsTypeId]() {
475
+ return this.refSet;
476
+ }
466
477
  [EqualTypeId](that) {
467
478
  return isCalc$1(that) && nodeEquals(this.node, nodeOf(that));
468
479
  }
@@ -483,36 +494,38 @@ const isCalc$1 = (u) => typeof u === "object" && u !== null && CalcTypeId in u;
483
494
  const nodeOf = (expr) => expr.node;
484
495
  /** @internal */
485
496
  const refsOf = (expr) => expr.refSet;
486
- const collectIdents = (node, into) => {
497
+ const collectTokens = (node, intoUnits, intoIdents) => {
487
498
  switch (node._tag) {
488
499
  case "Ident":
489
- into.add(node.name);
500
+ intoIdents?.add(node.name);
490
501
  return;
491
502
  case "Constant":
503
+ if (node.unit !== void 0) intoUnits?.add(node.unit);
504
+ return;
492
505
  case "Ref": return;
493
506
  case "Add":
494
- for (const term of node.terms) collectIdents(term, into);
507
+ for (const term of node.terms) collectTokens(term, intoUnits, intoIdents);
495
508
  return;
496
509
  case "Min":
497
510
  case "Max":
498
- for (const arg of node.args) collectIdents(arg, into);
511
+ for (const arg of node.args) collectTokens(arg, intoUnits, intoIdents);
499
512
  return;
500
513
  case "Subtract":
501
514
  case "Multiply":
502
515
  case "Divide":
503
516
  case "Mod":
504
- collectIdents(node.left, into);
505
- collectIdents(node.right, into);
517
+ collectTokens(node.left, intoUnits, intoIdents);
518
+ collectTokens(node.right, intoUnits, intoIdents);
506
519
  return;
507
520
  case "Pow":
508
521
  case "SignedPow":
509
- collectIdents(node.base, into);
510
- collectIdents(node.exponent, into);
522
+ collectTokens(node.base, intoUnits, intoIdents);
523
+ collectTokens(node.exponent, intoUnits, intoIdents);
511
524
  return;
512
525
  case "Clamp":
513
- collectIdents(node.minimum, into);
514
- collectIdents(node.value, into);
515
- collectIdents(node.maximum, into);
526
+ collectTokens(node.minimum, intoUnits, intoIdents);
527
+ collectTokens(node.value, intoUnits, intoIdents);
528
+ collectTokens(node.maximum, intoUnits, intoIdents);
516
529
  return;
517
530
  case "Abs":
518
531
  case "Sign":
@@ -520,18 +533,24 @@ const collectIdents = (node, into) => {
520
533
  case "Cos":
521
534
  case "Tan":
522
535
  case "Acos":
523
- collectIdents(node.argument, into);
536
+ collectTokens(node.argument, intoUnits, intoIdents);
524
537
  return;
525
538
  case "Atan2":
526
- collectIdents(node.y, into);
527
- collectIdents(node.x, into);
539
+ collectTokens(node.y, intoUnits, intoIdents);
540
+ collectTokens(node.x, intoUnits, intoIdents);
528
541
  return;
529
542
  }
530
543
  };
531
544
  /** @internal */
532
545
  const identsOf = (node) => {
533
546
  const set = /* @__PURE__ */ new Set();
534
- collectIdents(node, set);
547
+ collectTokens(node, void 0, set);
548
+ return set;
549
+ };
550
+ /** @internal */
551
+ const unitsOf = (node) => {
552
+ const set = /* @__PURE__ */ new Set();
553
+ collectTokens(node, set, void 0);
535
554
  return set;
536
555
  };
537
556
  const makeCalc = (node, refSet) => new CalcImpl(node, refSet);
@@ -557,16 +576,39 @@ function dimension(value, unit, kind, precision) {
557
576
  return makeCalc(constantNode(value, precision === void 0 ? void 0 : toSpec(precision), unit, kind), EMPTY_REFS);
558
577
  }
559
578
  const refCache = /* @__PURE__ */ new Map();
579
+ const lowerFallback = (fb) => {
580
+ if (typeof fb === "number") return constantNode(fb, void 0);
581
+ if (isVar(fb)) return lowerRead(fb);
582
+ invariant(isCalc$1(fb), "Calc var fallback must be a number, a Calc expression, or a Var read");
583
+ return nodeOf(fb);
584
+ };
585
+ const lowerRead = (read) => {
586
+ invariant(declaredTypeOf(read) !== "color", "A color-declared read cannot lift into calc; use Color.var");
587
+ const fb = fallbackOf(read);
588
+ return fb === void 0 ? {
589
+ _tag: "Ref",
590
+ name: nameOf(read)
591
+ } : {
592
+ _tag: "Ref",
593
+ name: nameOf(read),
594
+ fallback: lowerFallback(fb)
595
+ };
596
+ };
560
597
  /** @internal */
561
- function ref$1(name) {
562
- const cached = refCache.get(name);
598
+ function ref(read) {
599
+ if (typeof read !== "string") {
600
+ invariant(declaredTypeOf(read) !== "color", "A color-declared read cannot lift into calc; use Color.var");
601
+ if (fallbackOf(read) === void 0) return ref(nameOf(read));
602
+ return makeCalc(lowerRead(read), refsOfVar(read));
603
+ }
604
+ const cached = refCache.get(read);
563
605
  if (cached) return cached;
564
- invariant(name.length > 0, "Reference name must be a non-empty string");
606
+ invariant(read.length > 0, "Reference name must be a non-empty string");
565
607
  const expr = makeCalc({
566
608
  _tag: "Ref",
567
- name
568
- }, /* @__PURE__ */ new Set([name]));
569
- refCache.set(name, expr);
609
+ name: read
610
+ }, /* @__PURE__ */ new Set([read]));
611
+ refCache.set(read, expr);
570
612
  return expr;
571
613
  }
572
614
  /**
@@ -709,16 +751,16 @@ const bind$1 = dual(2, (expr, bindings) => {
709
751
  return makeCalc(substituteNode(nodeOf(expr), collected.nodeBindings), collected.refSet);
710
752
  });
711
753
  /** @internal */
712
- function solve$1(expr, bindings, context) {
754
+ function solve$1(expr, options) {
713
755
  let node = nodeOf(expr);
714
756
  let remaining = refsOf(expr);
715
- if (bindings !== void 0) {
716
- const collected = collectBindings(remaining, bindings);
757
+ if (options?.bindings !== void 0) {
758
+ const collected = collectBindings(remaining, options.bindings);
717
759
  node = substituteNode(node, collected.nodeBindings);
718
760
  remaining = collected.refSet;
719
761
  }
720
- invariant(remaining.size === 0, "Cannot convert expression to number: unbound references remain");
721
- return evaluateNode(node, context ?? {});
762
+ invariant(remaining.size === 0, "Cannot convert expression to number: unbound variables remain");
763
+ return evaluateNode(node, options?.units ?? {}, options?.idents ?? {});
722
764
  }
723
765
  /** @internal */
724
766
  function serialize$1(expr, options) {
@@ -731,14 +773,18 @@ function serialize$1(expr, options) {
731
773
  return serializeTop(node, precision);
732
774
  }
733
775
  /** @internal */
734
- function refs$1(expr) {
776
+ function refs(expr) {
735
777
  return refsOf(expr);
736
778
  }
737
779
  /** @internal */
738
- function channels$1(expr) {
780
+ function idents$1(expr) {
739
781
  return identsOf(nodeOf(expr));
740
782
  }
741
783
  /** @internal */
784
+ function units$1(expr) {
785
+ return unitsOf(nodeOf(expr));
786
+ }
787
+ /** @internal */
742
788
  const equals$1 = dual(2, (self, that) => equals$2(self, that));
743
789
  //#endregion
744
790
  //#region src/calc/calc.ts
@@ -748,11 +794,11 @@ var calc_exports = /* @__PURE__ */ __exportAll({
748
794
  add: () => add,
749
795
  atan2: () => atan2,
750
796
  bind: () => bind,
751
- channels: () => channels,
752
797
  clamp: () => clamp,
753
798
  cos: () => cos,
754
799
  divide: () => divide,
755
800
  equals: () => equals,
801
+ idents: () => idents,
756
802
  isCalc: () => isCalc,
757
803
  lerp: () => lerp,
758
804
  max: () => max,
@@ -761,15 +807,16 @@ var calc_exports = /* @__PURE__ */ __exportAll({
761
807
  multiply: () => multiply,
762
808
  of: () => of,
763
809
  pow: () => pow,
764
- ref: () => ref,
765
- refs: () => refs,
766
810
  serialize: () => serialize,
767
811
  sign: () => sign,
768
812
  signedPow: () => signedPow,
769
813
  sin: () => sin,
770
814
  solve: () => solve,
771
815
  subtract: () => subtract,
772
- tan: () => tan
816
+ tan: () => tan,
817
+ units: () => units,
818
+ var: () => _var,
819
+ vars: () => vars
773
820
  });
774
821
  /**
775
822
  * Checks if a value is a `Calc`.
@@ -798,29 +845,12 @@ const isCalc = isCalc$1;
798
845
  * @example
799
846
  * ```ts
800
847
  * const k = Calc.of(0.8377580409572781, Precision.significant(10))
801
- * Calc.serialize(Calc.multiply(k, Calc.ref('t'))) // 'calc(0.837758041 * var(--t))'
848
+ * Calc.serialize(Calc.multiply(k, Calc.var('t'))) // 'calc(0.837758041 * var(--t))'
802
849
  * ```
803
850
  * @since 0.1.0
804
851
  */
805
852
  const of = of$1;
806
- /**
807
- * Creates a reference to an unbound name. References serialize as
808
- * `var(--name)` and are the channel through which expressions read CSS
809
- * custom properties; `bind` replaces them with values or other
810
- * expressions.
811
- *
812
- * Repeated calls with the same name return the same instance.
813
- *
814
- * @param name - The reference name, without the `--` prefix. Must be non-empty.
815
- * @returns A `Calc` with `name` as its one unbound reference.
816
- * @throws `Error` when `name` is empty.
817
- * @example
818
- * ```ts
819
- * Calc.serialize(Calc.ref('width')) // 'var(--width)'
820
- * ```
821
- * @since 0.1.0
822
- */
823
- const ref = ref$1;
853
+ const _var = ref;
824
854
  /**
825
855
  * Adds expressions. Constant operands fold at construction.
826
856
  *
@@ -829,11 +859,11 @@ const ref = ref$1;
829
859
  * `a + (-2)` serializes as `a - 2`.
830
860
  *
831
861
  * @param a - The first operand.
832
- * @param b - The second operand.
833
- * @returns The sum, with the operands' references unioned.
862
+ * @param b - The second operand, sharing `a`'s dimension.
863
+ * @returns The sum, with the operands' variables, results, and requirements unioned.
834
864
  * @example
835
865
  * ```ts
836
- * Calc.serialize(Calc.add(Calc.ref('x'), 10)) // 'calc(var(--x) + 10)'
866
+ * Calc.serialize(Calc.add(Calc.var('x'), 10)) // 'calc(var(--x) + 10)'
837
867
  * ```
838
868
  * @since 0.1.0
839
869
  */
@@ -842,54 +872,64 @@ const add = add$1;
842
872
  * Subtracts `right` from `left`. Constant operands fold at construction.
843
873
  *
844
874
  * @param left - The minuend.
845
- * @param right - The subtrahend.
846
- * @returns The difference, with the operands' references unioned.
875
+ * @param right - The subtrahend, sharing `left`'s dimension.
876
+ * @returns The difference, with the operands' variables, results, and requirements unioned.
847
877
  * @since 0.1.0
848
878
  */
849
879
  const subtract = subtract$1;
850
880
  /**
851
881
  * The CSS `mod()` of `dividend` and `divisor` — the remainder that takes the
852
882
  * sign of the divisor (the floored modulo), so `mod(x, 360)` lands in
853
- * `[0, 360)` for a positive divisor. Same-kind operands, as `subtract`;
883
+ * `[0, 360)` for a positive divisor. Same-dimension operands, as `subtract`;
854
884
  * constant operands fold at construction.
855
885
  *
856
886
  * @param dividend - The value to reduce.
857
- * @param divisor - The modulus, sharing `dividend`'s kind.
858
- * @returns The modulo, with the operands' references unioned.
887
+ * @param divisor - The modulus, sharing `dividend`'s dimension.
888
+ * @returns The modulo, with the operands' variables, results, and requirements unioned.
859
889
  * @example
860
890
  * ```ts
861
- * Calc.serialize(Calc.mod(Calc.ref('h'), 360)) // 'mod(var(--h), 360)'
891
+ * Calc.serialize(Calc.mod(Calc.var('h'), 360)) // 'mod(var(--h), 360)'
862
892
  * ```
863
893
  * @since 0.2.0
864
894
  */
865
895
  const mod = mod$1;
866
896
  /**
867
- * Multiplies expressions. Constant operands fold at construction.
897
+ * Multiplies expressions. One factor must be a `<number>`; the dimensioned
898
+ * factor's result rides through. Constant operands fold at construction.
868
899
  *
869
900
  * Addition and subtraction operands are parenthesized when serialized
870
901
  * under a product: `(a + b) * c`.
871
902
  *
872
903
  * @param left - The first factor.
873
904
  * @param right - The second factor.
874
- * @returns The product, with the operands' references unioned.
905
+ * @returns The product, carrying the dimensioned factor's result and both operands' variables and requirements.
875
906
  * @since 0.1.0
876
907
  */
877
908
  const multiply = multiply$1;
878
909
  /**
879
910
  * Divides `left` by `right`. Constant operands fold at construction.
880
911
  *
912
+ * Dividing by a `<number>` keeps the dividend's result; dividing two
913
+ * same-dimension expressions produces a `<number>` (`Unit.None`) — the
914
+ * units cancel. The requirements discharge only where folding guarantees
915
+ * they can: a same-single-unit division always folds once bound, so its
916
+ * requirement drops; anything mixed keeps both operands'.
917
+ *
881
918
  * @param left - The dividend.
882
- * @param right - The divisor.
883
- * @returns The quotient, with the operands' references unioned.
919
+ * @param right - The divisor: a number, or an expression sharing `left`'s dimension.
920
+ * @returns The quotient, with the operands' variables unioned.
884
921
  * @since 0.1.0
885
922
  */
886
923
  const divide = divide$1;
887
924
  /**
888
- * Raises `base` to `exponent`. Serializes as the CSS `pow()` function.
925
+ * Raises `base` to `exponent`. Serializes as the CSS `pow()` function,
926
+ * whose operands are `<number>`s — so both take number-result expressions,
927
+ * which may carry identifier requirements (`pow(l, 2.2)` gamma-adjusts a
928
+ * relative-color channel).
889
929
  *
890
930
  * @param base - The base.
891
931
  * @param exponent - The exponent.
892
- * @returns The power, with the operands' references unioned.
932
+ * @returns The power, a `<number>`, with the operands' variables and requirements unioned.
893
933
  * @since 0.1.0
894
934
  */
895
935
  const pow = pow$1;
@@ -900,7 +940,7 @@ const pow = pow$1;
900
940
  *
901
941
  * @param base - The base.
902
942
  * @param exponent - The exponent.
903
- * @returns The signed power, with the operands' references unioned.
943
+ * @returns The signed power, a `<number>`, with the operands' variables and requirements unioned.
904
944
  * @since 0.1.0
905
945
  */
906
946
  const signedPow = signedPow$1;
@@ -908,8 +948,8 @@ const signedPow = signedPow$1;
908
948
  * The minimum of the operands. Serializes as the CSS `min()` function.
909
949
  *
910
950
  * @param a - The first operand.
911
- * @param b - The second operand.
912
- * @returns The minimum, with the operands' references unioned.
951
+ * @param b - The second operand, sharing `a`'s dimension.
952
+ * @returns The minimum, with the operands' variables, results, and requirements unioned.
913
953
  * @since 0.1.0
914
954
  */
915
955
  const min = min$1;
@@ -917,8 +957,8 @@ const min = min$1;
917
957
  * The maximum of the operands. Serializes as the CSS `max()` function.
918
958
  *
919
959
  * @param a - The first operand.
920
- * @param b - The second operand.
921
- * @returns The maximum, with the operands' references unioned.
960
+ * @param b - The second operand, sharing `a`'s dimension.
961
+ * @returns The maximum, with the operands' variables, results, and requirements unioned.
922
962
  * @since 0.1.0
923
963
  */
924
964
  const max = max$1;
@@ -927,12 +967,12 @@ const max = max$1;
927
967
  * `clamp()` function, with the CSS argument order `(min, value, max)`.
928
968
  *
929
969
  * @param minimum - The lower bound.
930
- * @param value - The value to clamp.
931
- * @param maximum - The upper bound.
932
- * @returns The clamped expression, with the operands' references unioned.
970
+ * @param value - The value to clamp, sharing `minimum`'s dimension.
971
+ * @param maximum - The upper bound, likewise.
972
+ * @returns The clamped expression, with the operands' variables, results, and requirements unioned.
933
973
  * @example
934
974
  * ```ts
935
- * Calc.serialize(Calc.clamp(-1, Calc.ref('u'), 1)) // 'clamp(-1, var(--u), 1)'
975
+ * Calc.serialize(Calc.clamp(-1, Calc.var('u'), 1)) // 'clamp(-1, var(--u), 1)'
936
976
  * ```
937
977
  * @since 0.1.0
938
978
  */
@@ -940,12 +980,13 @@ const clamp = clamp$1;
940
980
  /**
941
981
  * Linear interpolation from `a` to `b` by `t`. This is sugar, not a node:
942
982
  * it desugars to `(1 - t) * a + t * b`, and serializes as that expanded
943
- * form.
983
+ * form. `t` contributes its variables and requirements but never the
984
+ * result — the endpoints alone fix the dimension.
944
985
  *
945
986
  * @param a - The value at `t = 0`.
946
- * @param b - The value at `t = 1`.
947
- * @param t - The interpolation parameter.
948
- * @returns The interpolated expression, with the operands' references unioned.
987
+ * @param b - The value at `t = 1`, sharing `a`'s dimension.
988
+ * @param t - The interpolation parameter, a `<number>`.
989
+ * @returns The interpolated expression, with the operands' variables unioned.
949
990
  * @since 0.1.0
950
991
  */
951
992
  const lerp = lerp$1;
@@ -953,64 +994,68 @@ const lerp = lerp$1;
953
994
  * The absolute value. Serializes as the CSS `abs()` function.
954
995
  *
955
996
  * @param argument - The operand.
956
- * @returns The absolute value expression.
997
+ * @returns The absolute value expression, preserving the operand's result.
957
998
  * @since 0.1.0
958
999
  */
959
1000
  const abs = abs$1;
960
1001
  /**
961
- * The sign (`-1`, `0`, or `1`). Serializes as the CSS `sign()` function.
1002
+ * The sign (`-1`, `0`, or `1`). Serializes as the CSS `sign()` function,
1003
+ * which accepts a calculation of any dimension and returns a `<number>` —
1004
+ * so any operand is accepted here.
962
1005
  *
963
- * @param argument - The operand.
964
- * @returns The sign expression.
1006
+ * @param argument - The operand, of any dimension.
1007
+ * @returns The sign, a `<number>`, carrying the operand's requirements.
965
1008
  * @since 0.1.0
966
1009
  */
967
1010
  const sign = sign$1;
968
1011
  /**
969
1012
  * The sine of its argument. Serializes as the CSS `sin()` function, which
970
1013
  * accepts an `<angle>` or a plain number treated as radians — so this takes
971
- * either an angle-kind expression or a number, and returns a number.
1014
+ * either an angle expression or a number, and returns a number.
972
1015
  *
973
1016
  * @param argument - An angle, or a plain number in radians.
974
- * @returns The sine, a `<number>`, carrying the argument's units.
1017
+ * @returns The sine, a `<number>`, carrying the argument's requirements.
975
1018
  * @since 0.1.0
976
1019
  */
977
1020
  const sin = sin$1;
978
1021
  /**
979
1022
  * The cosine of its argument. Serializes as the CSS `cos()` function, which
980
1023
  * accepts an `<angle>` or a plain number treated as radians — so this takes
981
- * either an angle-kind expression or a number, and returns a number.
1024
+ * either an angle expression or a number, and returns a number.
982
1025
  *
983
1026
  * @param argument - An angle, or a plain number in radians.
984
- * @returns The cosine, a `<number>`, carrying the argument's units.
1027
+ * @returns The cosine, a `<number>`, carrying the argument's requirements.
985
1028
  * @since 0.1.0
986
1029
  */
987
1030
  const cos = cos$1;
988
1031
  /**
989
1032
  * The tangent of its argument. Serializes as the CSS `tan()` function, which
990
1033
  * accepts an `<angle>` or a plain number treated as radians. Paired with
991
- * `atan2`, `tan(atan2(a, b))` divides two same-kind dimensions to a `<number>` —
992
- * the length ratio that works where `a / b` does not, since Firefox does not
993
- * yet support `<length> / <length>` in `calc()`.
1034
+ * `atan2`, `tan(atan2(a, b))` divides two same-dimension expressions to a
1035
+ * `<number>` — the length ratio that works where `a / b` does not, since
1036
+ * Firefox does not yet support `<length> / <length>` in `calc()`.
994
1037
  *
995
1038
  * @param argument - An angle, or a plain number in radians.
996
- * @returns The tangent, a `<number>`, carrying the argument's units.
1039
+ * @returns The tangent, a `<number>`, carrying the argument's requirements.
997
1040
  * @since 0.2.0
998
1041
  */
999
1042
  const tan = tan$1;
1000
1043
  /**
1001
- * The arccosine of a value in `[-1, 1]`, an `<angle>` in radians (CSS's
1002
- * `acos()` returns an `<angle>`). Solving evaluates `Math.acos`, in radians.
1044
+ * The arccosine of a value in `[-1, 1]`, an `<angle>` in radians — the
1045
+ * result is `Unit.Rad`, matching what solving evaluates (`Math.acos`) and
1046
+ * what constant folding emits (`rad` constants); CSS's `acos()` returns an
1047
+ * `<angle>` and serialization is unchanged.
1003
1048
  *
1004
- * Because the result is angle-kind, it composes only with other angles: divide
1049
+ * Because the result is an angle, it composes only with other angles: divide
1005
1050
  * or scale it by a number, and add or subtract an `Angle.rad(...)` phase. A
1006
1051
  * plain number added to it is a type error — supply the phase as an angle.
1007
1052
  *
1008
1053
  * @param argument - The cosine value, in `[-1, 1]`.
1009
- * @returns The arccosine, an `<angle>`, carrying the argument's units.
1054
+ * @returns The arccosine in radians, carrying the argument's requirements.
1010
1055
  * @example
1011
1056
  * ```ts
1012
1057
  * const phase = Angle.rad(2.0943951)
1013
- * Calc.serialize(Calc.cos(Calc.subtract(Calc.divide(Calc.acos(Calc.ref('u')), 3), phase)))
1058
+ * Calc.serialize(Calc.cos(Calc.subtract(Calc.divide(Calc.acos(Calc.var('u')), 3), phase)))
1014
1059
  * // 'cos(acos(var(--u)) / 3 - 2.0944rad)'
1015
1060
  * ```
1016
1061
  * @since 0.1.0
@@ -1018,14 +1063,15 @@ const tan = tan$1;
1018
1063
  const acos = acos$1;
1019
1064
  /**
1020
1065
  * The angle, in radians, of the vector from the origin to `(x, y)` — CSS's
1021
- * `atan2()`, which returns an `<angle>`. The operands must share a kind (two
1022
- * numbers, two lengths, two angles); their units cancel in the ratio, so
1023
- * `tan(atan2(a, b))` recovers `a / b` as a `<number>` and is the portable way to
1024
- * divide two `<length>`s.
1066
+ * `atan2()`, which returns an `<angle>`; the result is `Unit.Rad`, as
1067
+ * `acos`. The operands must share a dimension (two numbers, two lengths,
1068
+ * two angles); their units cancel in the ratio, so `tan(atan2(a, b))`
1069
+ * recovers `a / b` as a `<number>` and is the portable way to divide two
1070
+ * `<length>`s.
1025
1071
  *
1026
1072
  * @param y - The vertical component.
1027
- * @param x - The horizontal component, sharing `y`'s kind.
1028
- * @returns The angle, an `<angle>`, with the operands' units unioned.
1073
+ * @param x - The horizontal component, sharing `y`'s dimension.
1074
+ * @returns The angle in radians, with the operands' variables and requirements unioned.
1029
1075
  * @example
1030
1076
  * ```ts
1031
1077
  * const ratio = Calc.tan(Calc.atan2(Calc.subtract(Length.vw(100), Length.px(320)), Length.px(160)))
@@ -1039,11 +1085,11 @@ const solve = solve$1;
1039
1085
  /**
1040
1086
  * Renders an expression as CSS text. Arithmetic gets a `calc()` wrapper;
1041
1087
  * function forms (`min`, `clamp`, `sin`, ...) and leaves stand alone.
1042
- * References render as `var(--name)`.
1088
+ * Variables render as `var(--name)`.
1043
1089
  *
1044
1090
  * Bindings in `options` are applied first and may be partial — this is
1045
1091
  * the serialize half of the solve/serialize duality, and unbound
1046
- * references are the values left for the browser. Constants render with
1092
+ * variables are the values left for the browser. Constants render with
1047
1093
  * their annotated precision, or the context `precision` option (default
1048
1094
  * `Precision.decimals(5)`). Constants equal to pi render as the CSS
1049
1095
  * constant `pi` where a math function surrounds them.
@@ -1053,7 +1099,7 @@ const solve = solve$1;
1053
1099
  * @returns Deterministic CSS text.
1054
1100
  * @example
1055
1101
  * ```ts
1056
- * const fluid = Calc.add(10, Calc.ref('runtime'))
1102
+ * const fluid = Calc.add(10, Calc.var('runtime'))
1057
1103
  * Calc.serialize(fluid) // 'calc(10 + var(--runtime))'
1058
1104
  * Calc.serialize(fluid, { bindings: { runtime: 4 } }) // '14'
1059
1105
  * ```
@@ -1061,35 +1107,57 @@ const solve = solve$1;
1061
1107
  */
1062
1108
  const serialize = serialize$1;
1063
1109
  /**
1064
- * The expression's unbound reference names.
1110
+ * The expression's unbound variable names — bare names, the value-level
1111
+ * mirror of the read identities in `Vars`. A fallback chain's names are
1112
+ * included: `var(--x, var(--y))` reads both.
1065
1113
  *
1066
1114
  * @param expr - The expression to inspect.
1067
- * @returns The set of unbound reference names.
1115
+ * @returns The set of unbound variable names.
1068
1116
  * @since 0.1.0
1069
1117
  */
1070
- const refs = refs$1;
1118
+ const vars = refs;
1071
1119
  /**
1072
- * The channel-keyword tokens the expression reads — the `Channel` keywords a
1073
- * relative color introduces (`l`, `c`, `h`, ...). Empty for an expression with
1074
- * no channel keywords.
1120
+ * The bare-identifier tokens the expression reads — leaves that serialize
1121
+ * as themselves (`l`, not `var(--l)`) and are resolved by the CSS construct
1122
+ * around them, the `Channel` keywords being the only source today. Empty
1123
+ * for an expression with none.
1075
1124
  *
1076
- * This is the runtime companion to the `Leaves`-level scoping that `solve`'s
1077
- * context requires: `channels` reports which values a context must supply,
1078
- * exactly as `refs` reports the custom properties a binding must, and — unlike
1079
- * a `Calc`'s `Kind`/`Leaves` type — survives on a `Calc<Refs, Kind, unknown>`
1080
- * whose leaves have been erased. Channel keywords are not references, so `refs`
1081
- * never lists them and they never reach a `Stylesheet`'s dependency report.
1125
+ * The runtime mirror of the `Ident` brands in `Requires`: it reports which
1126
+ * values the `idents` section of `solve`'s options must supply, exactly as
1127
+ * `vars` reports what `bindings` must and, unlike the type parameter, it
1128
+ * survives on a `Calc<Vars, Unit.Any, unknown>` whose requirements have
1129
+ * been erased. Identifiers are not variables, so `vars` never lists them
1130
+ * and they never reach a `Stylesheet`'s dependency report.
1082
1131
  *
1083
1132
  * @param expr - The expression to inspect.
1084
- * @returns The set of channel-keyword tokens the expression reads.
1133
+ * @returns The set of bare-identifier tokens the expression reads.
1085
1134
  * @example
1086
1135
  * ```ts
1087
- * Calc.channels(Calc.multiply(Channel.L, 0.8)) // Set { 'l' }
1088
- * Calc.channels(Calc.ref('x')) // Set {}
1136
+ * Calc.idents(Calc.multiply(Channel.L, 0.8)) // Set { 'l' }
1137
+ * Calc.idents(Calc.var('x')) // Set {}
1089
1138
  * ```
1090
1139
  * @since 0.2.0
1091
1140
  */
1092
- const channels = channels$1;
1141
+ const idents = idents$1;
1142
+ /**
1143
+ * The unit tokens the expression's dimensioned constants carry (`'vw'`,
1144
+ * `'px'`, `'%'`). Empty for a unit-free expression.
1145
+ *
1146
+ * The runtime mirror of the `Unit` brands in `Requires`: it reports which
1147
+ * ratios the `units` section of `solve`'s options may need to supply, and —
1148
+ * unlike the type parameter — it survives on a `Calc<Vars, Unit.Any, unknown>`
1149
+ * whose requirements have been erased. Pre-satisfied units (`px`, `rad`,
1150
+ * `deg`) are reported too; they lower with no entry.
1151
+ *
1152
+ * @param expr - The expression to inspect.
1153
+ * @returns The set of unit tokens the expression's constants carry.
1154
+ * @example
1155
+ * ```ts
1156
+ * Calc.units(Calc.subtract(Length.vw(100), Length.px(320))) // Set { 'vw', 'px' }
1157
+ * ```
1158
+ * @since 0.4.0
1159
+ */
1160
+ const units = units$1;
1093
1161
  const equals = equals$1;
1094
1162
  //#endregion
1095
1163
  //#region src/calc/precision.ts
@@ -1140,6 +1208,6 @@ const decimals = decimals$1;
1140
1208
  */
1141
1209
  const significant = significant$1;
1142
1210
  //#endregion
1143
- export { EMPTY_REFS as C, toCalc as S, nodeOf as _, multiply as a, serializeNode as b, bind$1 as c, ident as d, identsOf as f, nodeHash as g, nodeEquals as h, mod as i, collectBindings as l, needsCalcWrap as m, add as n, sign as o, isCalc$1 as p, calc_exports as r, subtract as s, precision_exports as t, dimension as u, refsOf as v, unionRefs as w, substituteNode as x, serialize$1 as y };
1211
+ export { toCalc as S, nodeOf as _, multiply as a, serializeNode as b, bind$1 as c, ident as d, identsOf as f, nodeHash as g, nodeEquals as h, mod as i, collectBindings as l, needsCalcWrap as m, add as n, sign as o, isCalc$1 as p, calc_exports as r, subtract as s, precision_exports as t, dimension as u, refsOf as v, substituteNode as x, serialize$1 as y };
1144
1212
 
1145
- //# sourceMappingURL=calc-Cih4o2r7.mjs.map
1213
+ //# sourceMappingURL=calc-Uwbxd7CS.mjs.map