fashionable 0.0.0 → 0.2.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 (67) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +276 -0
  3. package/dist/calc/index.d.mts +2 -0
  4. package/dist/calc/index.mjs +2 -0
  5. package/dist/data/index.d.mts +208 -0
  6. package/dist/data/index.mjs +696 -0
  7. package/dist/data/index.mjs.map +1 -0
  8. package/dist/declaration/index.d.mts +2 -0
  9. package/dist/declaration/index.mjs +74 -0
  10. package/dist/declaration/index.mjs.map +1 -0
  11. package/dist/fontFace/index.d.mts +2 -0
  12. package/dist/fontFace/index.mjs +102 -0
  13. package/dist/fontFace/index.mjs.map +1 -0
  14. package/dist/property/index.d.mts +2 -0
  15. package/dist/property/index.mjs +293 -0
  16. package/dist/property/index.mjs.map +1 -0
  17. package/dist/query/index.d.mts +2 -0
  18. package/dist/query/index.mjs +62 -0
  19. package/dist/query/index.mjs.map +1 -0
  20. package/dist/rule/index.d.mts +2 -0
  21. package/dist/rule/index.mjs +234 -0
  22. package/dist/rule/index.mjs.map +1 -0
  23. package/dist/selector/index.d.mts +2 -0
  24. package/dist/selector/index.mjs +178 -0
  25. package/dist/selector/index.mjs.map +1 -0
  26. package/dist/shared/calc-Cih4o2r7.mjs +1145 -0
  27. package/dist/shared/calc-Cih4o2r7.mjs.map +1 -0
  28. package/dist/shared/color-BvNJ2YqL.d.mts +590 -0
  29. package/dist/shared/color.internal-Dts5ycTm.mjs +450 -0
  30. package/dist/shared/color.internal-Dts5ycTm.mjs.map +1 -0
  31. package/dist/shared/declaration-1DlO_ltT.d.mts +166 -0
  32. package/dist/shared/declaration.internal-wLB4ssxC.mjs +73 -0
  33. package/dist/shared/declaration.internal-wLB4ssxC.mjs.map +1 -0
  34. package/dist/shared/equal-U9G5LhtL.mjs +71 -0
  35. package/dist/shared/equal-U9G5LhtL.mjs.map +1 -0
  36. package/dist/shared/fontFaceRule-C7nYgH6X.d.mts +294 -0
  37. package/dist/shared/fontFaceRule.internal-D5u48TUO.mjs +214 -0
  38. package/dist/shared/fontFaceRule.internal-D5u48TUO.mjs.map +1 -0
  39. package/dist/shared/format-B9jsmCER.mjs +53 -0
  40. package/dist/shared/format-B9jsmCER.mjs.map +1 -0
  41. package/dist/shared/index-BvtwY4FQ.d.mts +841 -0
  42. package/dist/shared/mediaQuery-BYR1z-iD.d.mts +145 -0
  43. package/dist/shared/mediaQuery.internal-B6iuMd75.mjs +100 -0
  44. package/dist/shared/mediaQuery.internal-B6iuMd75.mjs.map +1 -0
  45. package/dist/shared/mediaRule-BDB4WCYy.d.mts +558 -0
  46. package/dist/shared/precision.internal-0lv1nEpF.mjs +40 -0
  47. package/dist/shared/precision.internal-0lv1nEpF.mjs.map +1 -0
  48. package/dist/shared/propertyRule-BbkFh9b9.d.mts +466 -0
  49. package/dist/shared/propertyRule.internal-Bc_HrfcL.mjs +246 -0
  50. package/dist/shared/propertyRule.internal-Bc_HrfcL.mjs.map +1 -0
  51. package/dist/shared/render-BqcFH9Vr.mjs +9 -0
  52. package/dist/shared/render-BqcFH9Vr.mjs.map +1 -0
  53. package/dist/shared/rolldown-runtime-D7D4PA-g.mjs +13 -0
  54. package/dist/shared/ruleSet.internal-DodzVMUU.mjs +218 -0
  55. package/dist/shared/ruleSet.internal-DodzVMUU.mjs.map +1 -0
  56. package/dist/shared/selector-HZY-W6l6.d.mts +346 -0
  57. package/dist/shared/selector.internal-ESe9s0IH.mjs +290 -0
  58. package/dist/shared/selector.internal-ESe9s0IH.mjs.map +1 -0
  59. package/dist/shared/utils-BKm298I-.d.mts +179 -0
  60. package/dist/stylesheet/index.d.mts +316 -0
  61. package/dist/stylesheet/index.mjs +296 -0
  62. package/dist/stylesheet/index.mjs.map +1 -0
  63. package/dist/utils.d.mts +2 -0
  64. package/dist/utils.mjs +131 -0
  65. package/dist/utils.mjs.map +1 -0
  66. package/package.json +96 -8
  67. package/index.js +0 -1
@@ -0,0 +1,1145 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import { Pipeable, dual, invariant } from "../utils.mjs";
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
+ import { a as specFidelity, i as specEquals, r as formatWith, t as DEFAULT_FORMAT } from "./format-B9jsmCER.mjs";
5
+ 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
+ //#region src/calc/calc.internal.ts
24
+ const CalcTypeId = Symbol.for("fashionable/calc");
25
+ const isConstant = (node) => node._tag === "Constant";
26
+ const constantNode = (value, precision, unit = void 0, kind = "number") => {
27
+ invariant(Number.isFinite(value), `Constant value must be a finite number, got ${value}`);
28
+ return {
29
+ _tag: "Constant",
30
+ value,
31
+ precision,
32
+ unit,
33
+ kind
34
+ };
35
+ };
36
+ /**
37
+ * The shared (unit, kind) of a run of constants, or `undefined` when they mix
38
+ * units and so cannot fold to a single constant (`10px + 5vw` stays symbolic).
39
+ */
40
+ const commonDimension = (nodes) => {
41
+ const first = nodes[0];
42
+ if (first === void 0) return {
43
+ unit: void 0,
44
+ kind: "number"
45
+ };
46
+ for (const node of nodes) if (node.unit !== first.unit) return;
47
+ return {
48
+ unit: first.unit,
49
+ kind: first.kind
50
+ };
51
+ };
52
+ const bestPrecision = (nodes) => {
53
+ let best;
54
+ for (const node of nodes) if (specFidelity(node.precision) > specFidelity(best)) best = node.precision;
55
+ return best;
56
+ };
57
+ const addNode = (terms) => {
58
+ if (terms.every(isConstant)) {
59
+ const dim = commonDimension(terms);
60
+ if (dim !== void 0) return constantNode(terms.reduce((total, term) => total + term.value, 0), bestPrecision(terms), dim.unit, dim.kind);
61
+ }
62
+ return {
63
+ _tag: "Add",
64
+ terms
65
+ };
66
+ };
67
+ const subtractNode = (left, right) => {
68
+ if (isConstant(left) && isConstant(right) && left.unit === right.unit) return constantNode(left.value - right.value, bestPrecision([left, right]), left.unit, left.kind);
69
+ return {
70
+ _tag: "Subtract",
71
+ left,
72
+ right
73
+ };
74
+ };
75
+ const multiplyNode = (left, right) => {
76
+ if (isConstant(left) && isConstant(right)) {
77
+ if (left.unit === void 0) return constantNode(left.value * right.value, bestPrecision([left, right]), right.unit, right.kind);
78
+ if (right.unit === void 0) return constantNode(left.value * right.value, bestPrecision([left, right]), left.unit, left.kind);
79
+ }
80
+ return {
81
+ _tag: "Multiply",
82
+ left,
83
+ right
84
+ };
85
+ };
86
+ const divideNode = (left, right) => {
87
+ if (isConstant(left) && isConstant(right)) {
88
+ if (left.unit === right.unit) return constantNode(left.value / right.value, bestPrecision([left, right]));
89
+ if (right.unit === void 0) return constantNode(left.value / right.value, bestPrecision([left, right]), left.unit, left.kind);
90
+ }
91
+ return {
92
+ _tag: "Divide",
93
+ left,
94
+ right
95
+ };
96
+ };
97
+ const modNode = (left, right) => {
98
+ if (isConstant(left) && isConstant(right) && left.unit === right.unit) return constantNode(left.value - right.value * Math.floor(left.value / right.value), bestPrecision([left, right]), left.unit, left.kind);
99
+ return {
100
+ _tag: "Mod",
101
+ left,
102
+ right
103
+ };
104
+ };
105
+ const powNode = (base, exponent) => {
106
+ if (isConstant(base) && isConstant(exponent)) return constantNode(base.value ** exponent.value, bestPrecision([base, exponent]));
107
+ return {
108
+ _tag: "Pow",
109
+ base,
110
+ exponent
111
+ };
112
+ };
113
+ const signedPowNode = (base, exponent) => {
114
+ if (isConstant(base) && isConstant(exponent)) return constantNode(Math.abs(base.value) ** exponent.value * Math.sign(base.value), bestPrecision([base, exponent]));
115
+ return {
116
+ _tag: "SignedPow",
117
+ base,
118
+ exponent
119
+ };
120
+ };
121
+ const naryNode = (tag, compute) => (args) => {
122
+ if (args.every(isConstant)) {
123
+ const dim = commonDimension(args);
124
+ if (dim !== void 0) return constantNode(compute(args.map((arg) => arg.value)), bestPrecision(args), dim.unit, dim.kind);
125
+ }
126
+ return {
127
+ _tag: tag,
128
+ args
129
+ };
130
+ };
131
+ const minNode = naryNode("Min", (values) => Math.min(...values));
132
+ const maxNode = naryNode("Max", (values) => Math.max(...values));
133
+ const clampNode = (minimum, value, maximum) => {
134
+ if (isConstant(minimum) && isConstant(value) && isConstant(maximum)) {
135
+ const dim = commonDimension([
136
+ minimum,
137
+ value,
138
+ maximum
139
+ ]);
140
+ if (dim !== void 0) return constantNode(Math.max(minimum.value, Math.min(value.value, maximum.value)), bestPrecision([
141
+ minimum,
142
+ value,
143
+ maximum
144
+ ]), dim.unit, dim.kind);
145
+ }
146
+ return {
147
+ _tag: "Clamp",
148
+ minimum,
149
+ value,
150
+ maximum
151
+ };
152
+ };
153
+ /**
154
+ * Per-function data for the unary math nodes — the single source of truth the
155
+ * fold constructor, the evaluator, and the serializer all read:
156
+ *
157
+ * - `fn` both folds a constant operand and lowers the node under `solve`, so the
158
+ * construction-time and solve-time numerics can never drift.
159
+ * - `css` is the math-function name serialization emits.
160
+ * - `result` is the folded constant's dimension: `sign`/`sin`/`cos`/`tan`
161
+ * produce a plain `number`; `abs` preserves the operand's; `acos` returns
162
+ * radians, so its constant composes with `Angle.rad` terms and stays valid CSS
163
+ * with no plain-number-beside-angle hack.
164
+ */
165
+ const UNARY = {
166
+ Abs: {
167
+ fn: Math.abs,
168
+ css: "abs",
169
+ result: "preserve"
170
+ },
171
+ Sign: {
172
+ fn: Math.sign,
173
+ css: "sign",
174
+ result: "number"
175
+ },
176
+ Sin: {
177
+ fn: Math.sin,
178
+ css: "sin",
179
+ result: "number"
180
+ },
181
+ Cos: {
182
+ fn: Math.cos,
183
+ css: "cos",
184
+ result: "number"
185
+ },
186
+ Tan: {
187
+ fn: Math.tan,
188
+ css: "tan",
189
+ result: "number"
190
+ },
191
+ Acos: {
192
+ fn: Math.acos,
193
+ css: "acos",
194
+ result: "rad"
195
+ }
196
+ };
197
+ const foldUnary = (tag, argument) => {
198
+ if (!isConstant(argument)) return {
199
+ _tag: tag,
200
+ argument
201
+ };
202
+ const { fn, result } = UNARY[tag];
203
+ const value = fn(argument.value);
204
+ switch (result) {
205
+ case "number": return constantNode(value, argument.precision);
206
+ case "preserve": return constantNode(value, argument.precision, argument.unit, argument.kind);
207
+ case "rad": return constantNode(value, argument.precision, "rad", "angle");
208
+ }
209
+ };
210
+ const atan2Node = (y, x) => {
211
+ if (isConstant(y) && isConstant(x) && y.unit === x.unit) return constantNode(Math.atan2(y.value, x.value), bestPrecision([y, x]), "rad", "angle");
212
+ return {
213
+ _tag: "Atan2",
214
+ y,
215
+ x
216
+ };
217
+ };
218
+ /** @internal */
219
+ const substituteNode = (node, bindings) => {
220
+ switch (node._tag) {
221
+ case "Constant": return node;
222
+ case "Ref": return bindings[node.name] ?? node;
223
+ case "Ident": return node;
224
+ case "Add": return addNode(node.terms.map((term) => substituteNode(term, bindings)));
225
+ case "Subtract": return subtractNode(substituteNode(node.left, bindings), substituteNode(node.right, bindings));
226
+ case "Multiply": return multiplyNode(substituteNode(node.left, bindings), substituteNode(node.right, bindings));
227
+ case "Divide": return divideNode(substituteNode(node.left, bindings), substituteNode(node.right, bindings));
228
+ case "Mod": return modNode(substituteNode(node.left, bindings), substituteNode(node.right, bindings));
229
+ case "Pow": return powNode(substituteNode(node.base, bindings), substituteNode(node.exponent, bindings));
230
+ case "SignedPow": return signedPowNode(substituteNode(node.base, bindings), substituteNode(node.exponent, bindings));
231
+ case "Min": return minNode(node.args.map((arg) => substituteNode(arg, bindings)));
232
+ case "Max": return maxNode(node.args.map((arg) => substituteNode(arg, bindings)));
233
+ case "Clamp": return clampNode(substituteNode(node.minimum, bindings), substituteNode(node.value, bindings), substituteNode(node.maximum, bindings));
234
+ case "Abs":
235
+ case "Sign":
236
+ case "Sin":
237
+ case "Cos":
238
+ case "Tan":
239
+ case "Acos": return foldUnary(node._tag, substituteNode(node.argument, bindings));
240
+ case "Atan2": return atan2Node(substituteNode(node.y, bindings), substituteNode(node.x, bindings));
241
+ }
242
+ };
243
+ /**
244
+ * The units that lower with no caller-supplied ratio: `px` is the pixel base
245
+ * (`1`), a radian is already the numeric measure of its angle (`1`), and a
246
+ * degree is a fixed `pi / 180` of one. Every other unit is context-dependent
247
+ * and must appear in the solve context.
248
+ *
249
+ * @internal
250
+ */
251
+ const DEFAULT_RATIOS = {
252
+ px: 1,
253
+ rad: 1,
254
+ deg: Math.PI / 180
255
+ };
256
+ /** @internal */
257
+ const evaluateNode = (node, context) => {
258
+ switch (node._tag) {
259
+ case "Constant": {
260
+ 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`);
263
+ return node.value * ratio;
264
+ }
265
+ case "Ref": throw new Error(`Cannot evaluate non-constant reference: ${node.name}`);
266
+ 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`);
269
+ return value;
270
+ }
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);
275
+ case "Mod": {
276
+ const dividend = evaluateNode(node.left, context);
277
+ const divisor = evaluateNode(node.right, context);
278
+ return dividend - divisor * Math.floor(dividend / divisor);
279
+ }
280
+ case "Pow": return evaluateNode(node.base, context) ** evaluateNode(node.exponent, context);
281
+ case "SignedPow": {
282
+ const base = evaluateNode(node.base, context);
283
+ return Math.abs(base) ** evaluateNode(node.exponent, context) * Math.sign(base);
284
+ }
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)));
288
+ case "Abs":
289
+ case "Sign":
290
+ case "Sin":
291
+ case "Cos":
292
+ 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));
295
+ }
296
+ };
297
+ /**
298
+ * True for the arithmetic forms that need a `calc()` wrapper when they
299
+ * stand alone; function forms and leaves never do.
300
+ *
301
+ * @internal
302
+ */
303
+ const needsCalcWrap = (node) => node._tag === "Add" || node._tag === "Subtract" || node._tag === "Multiply" || node._tag === "Divide" || node._tag === "SignedPow";
304
+ const PI_TOLERANCE = 1e-10;
305
+ const formatConstant = (node, insideMath, context) => {
306
+ if (node.unit === void 0 && insideMath && Math.abs(node.value - Math.PI) < PI_TOLERANCE) return "pi";
307
+ const text = formatWith(node.value, node.precision ?? context.precision);
308
+ return node.unit !== void 0 ? `${text}${node.unit}` : text;
309
+ };
310
+ const wrapOperand = (node, serialized) => node._tag === "Add" || node._tag === "Subtract" ? `(${serialized})` : serialized;
311
+ const hasNegativeCoefficient = (node) => {
312
+ if (isConstant(node)) return node.value < 0;
313
+ if (node._tag === "Multiply" || node._tag === "Divide") return isConstant(node.left) && node.left.value < 0;
314
+ return false;
315
+ };
316
+ /**
317
+ * Serializes the negation of a term whose leading coefficient is a
318
+ * negative constant, so `a + (-k * x)` renders as `a - k * x`.
319
+ */
320
+ const serializeNegated = (node, insideMath, context) => {
321
+ if (isConstant(node)) return formatConstant(constantNode(-node.value, node.precision, node.unit, node.kind), insideMath, context);
322
+ const binary = node;
323
+ const left = binary.left;
324
+ const negated = {
325
+ _tag: binary._tag,
326
+ left: constantNode(-left.value, left.precision, left.unit, left.kind),
327
+ right: binary.right
328
+ };
329
+ return serializeNode(negated, insideMath, context);
330
+ };
331
+ /** @internal */
332
+ const serializeNode = (node, insideMath, context) => {
333
+ switch (node._tag) {
334
+ case "Constant": return formatConstant(node, insideMath, context);
335
+ case "Ref": return `var(--${node.name})`;
336
+ case "Ident": return node.name;
337
+ case "Add": {
338
+ let out = "";
339
+ for (const [index, term] of node.terms.entries()) if (index === 0) out = serializeNode(term, insideMath, context);
340
+ else if (hasNegativeCoefficient(term)) out += ` - ${serializeNegated(term, insideMath, context)}`;
341
+ else out += ` + ${serializeNode(term, insideMath, context)}`;
342
+ return out;
343
+ }
344
+ case "Subtract": {
345
+ const left = serializeNode(node.left, insideMath, context);
346
+ if (hasNegativeCoefficient(node.right)) return `${left} + ${serializeNegated(node.right, insideMath, context)}`;
347
+ return `${left} - ${serializeNode(node.right, insideMath, context)}`;
348
+ }
349
+ case "Multiply": return `${wrapOperand(node.left, serializeNode(node.left, insideMath, context))} * ${wrapOperand(node.right, serializeNode(node.right, insideMath, context))}`;
350
+ case "Divide": return `${wrapOperand(node.left, serializeNode(node.left, insideMath, context))} / ${wrapOperand(node.right, serializeNode(node.right, insideMath, context))}`;
351
+ case "Mod": return `mod(${serializeNode(node.left, true, context)}, ${serializeNode(node.right, true, context)})`;
352
+ case "Pow": return `pow(${serializeNode(node.base, true, context)}, ${serializeNode(node.exponent, true, context)})`;
353
+ case "SignedPow": {
354
+ const base = serializeNode(node.base, true, context);
355
+ return `pow(abs(${base}), ${serializeNode(node.exponent, true, context)}) * sign(${base})`;
356
+ }
357
+ case "Min": return `min(${node.args.map((arg) => serializeNode(arg, true, context)).join(", ")})`;
358
+ case "Max": return `max(${node.args.map((arg) => serializeNode(arg, true, context)).join(", ")})`;
359
+ case "Clamp": return `clamp(${serializeNode(node.minimum, true, context)}, ${serializeNode(node.value, true, context)}, ${serializeNode(node.maximum, true, context)})`;
360
+ case "Abs":
361
+ case "Sign":
362
+ case "Sin":
363
+ case "Cos":
364
+ case "Tan":
365
+ case "Acos": return `${UNARY[node._tag].css}(${serializeNode(node.argument, true, context)})`;
366
+ case "Atan2": return `atan2(${serializeNode(node.y, true, context)}, ${serializeNode(node.x, true, context)})`;
367
+ }
368
+ };
369
+ /** @internal */
370
+ const serializeTop = (node, precision) => {
371
+ const wrap = needsCalcWrap(node);
372
+ const body = serializeNode(node, wrap, { precision });
373
+ return wrap ? `calc(${body})` : body;
374
+ };
375
+ const nodeArrayEquals = (a, b) => a.length === b.length && a.every((node, index) => nodeEquals(node, b[index]));
376
+ /** @internal */
377
+ const nodeEquals = (a, b) => {
378
+ if (a === b) return true;
379
+ if (a._tag !== b._tag) return false;
380
+ switch (a._tag) {
381
+ case "Constant": {
382
+ const other = b;
383
+ return a.value === other.value && a.unit === other.unit && specEquals(a.precision, other.precision);
384
+ }
385
+ case "Ref": return a.name === b.name;
386
+ case "Ident": return a.name === b.name;
387
+ case "Add": return nodeArrayEquals(a.terms, b.terms);
388
+ case "Subtract":
389
+ case "Multiply":
390
+ case "Divide":
391
+ case "Mod": {
392
+ const other = b;
393
+ return nodeEquals(a.left, other.left) && nodeEquals(a.right, other.right);
394
+ }
395
+ case "Pow":
396
+ case "SignedPow": {
397
+ const other = b;
398
+ return nodeEquals(a.base, other.base) && nodeEquals(a.exponent, other.exponent);
399
+ }
400
+ case "Min":
401
+ case "Max": return nodeArrayEquals(a.args, b.args);
402
+ case "Clamp": {
403
+ const other = b;
404
+ return nodeEquals(a.minimum, other.minimum) && nodeEquals(a.value, other.value) && nodeEquals(a.maximum, other.maximum);
405
+ }
406
+ case "Abs":
407
+ case "Sign":
408
+ case "Sin":
409
+ case "Cos":
410
+ case "Tan":
411
+ case "Acos": return nodeEquals(a.argument, b.argument);
412
+ case "Atan2": {
413
+ const other = b;
414
+ return nodeEquals(a.y, other.y) && nodeEquals(a.x, other.x);
415
+ }
416
+ }
417
+ };
418
+ const hashNodeArray = (tag, nodes) => {
419
+ let h = hashString(tag);
420
+ for (const node of nodes) h = combine(h, nodeHash(node));
421
+ return h;
422
+ };
423
+ /** @internal */
424
+ const nodeHash = (node) => {
425
+ switch (node._tag) {
426
+ case "Constant": {
427
+ const precision = node.precision === void 0 ? 0 : combine(hashString(node.precision.mode), node.precision.digits | 0);
428
+ const unit = node.unit === void 0 ? 0 : hashString(node.unit);
429
+ return combine(hashString("Constant"), combine(combine(hashNumber(node.value), precision), unit));
430
+ }
431
+ case "Ref": return combine(hashString("Ref"), hashString(node.name));
432
+ case "Ident": return combine(hashString("Ident"), hashString(node.name));
433
+ case "Add": return hashNodeArray("Add", node.terms);
434
+ case "Subtract":
435
+ case "Multiply":
436
+ case "Divide":
437
+ case "Mod": return hashNodeArray(node._tag, [node.left, node.right]);
438
+ case "Pow":
439
+ case "SignedPow": return hashNodeArray(node._tag, [node.base, node.exponent]);
440
+ case "Min":
441
+ case "Max": return hashNodeArray(node._tag, node.args);
442
+ case "Clamp": return hashNodeArray("Clamp", [
443
+ node.minimum,
444
+ node.value,
445
+ node.maximum
446
+ ]);
447
+ case "Abs":
448
+ case "Sign":
449
+ case "Sin":
450
+ case "Cos":
451
+ case "Tan":
452
+ case "Acos": return hashNodeArray(node._tag, [node.argument]);
453
+ case "Atan2": return hashNodeArray("Atan2", [node.y, node.x]);
454
+ }
455
+ };
456
+ var CalcImpl = class extends Pipeable {
457
+ [CalcTypeId] = CalcTypeId;
458
+ node;
459
+ refSet;
460
+ #hash;
461
+ constructor(node, refSet) {
462
+ super();
463
+ this.node = node;
464
+ this.refSet = refSet;
465
+ }
466
+ [EqualTypeId](that) {
467
+ return isCalc$1(that) && nodeEquals(this.node, nodeOf(that));
468
+ }
469
+ [HashTypeId]() {
470
+ this.#hash ??= combine(hashString("fashionable/calc"), nodeHash(this.node));
471
+ return this.#hash;
472
+ }
473
+ get [Symbol.toStringTag]() {
474
+ return `Calc(${serializeTop(this.node, DEFAULT_FORMAT)})`;
475
+ }
476
+ get [Symbol.for("nodejs.util.inspect.custom")]() {
477
+ return this[Symbol.toStringTag];
478
+ }
479
+ };
480
+ /** @internal */
481
+ const isCalc$1 = (u) => typeof u === "object" && u !== null && CalcTypeId in u;
482
+ /** @internal */
483
+ const nodeOf = (expr) => expr.node;
484
+ /** @internal */
485
+ const refsOf = (expr) => expr.refSet;
486
+ const collectIdents = (node, into) => {
487
+ switch (node._tag) {
488
+ case "Ident":
489
+ into.add(node.name);
490
+ return;
491
+ case "Constant":
492
+ case "Ref": return;
493
+ case "Add":
494
+ for (const term of node.terms) collectIdents(term, into);
495
+ return;
496
+ case "Min":
497
+ case "Max":
498
+ for (const arg of node.args) collectIdents(arg, into);
499
+ return;
500
+ case "Subtract":
501
+ case "Multiply":
502
+ case "Divide":
503
+ case "Mod":
504
+ collectIdents(node.left, into);
505
+ collectIdents(node.right, into);
506
+ return;
507
+ case "Pow":
508
+ case "SignedPow":
509
+ collectIdents(node.base, into);
510
+ collectIdents(node.exponent, into);
511
+ return;
512
+ case "Clamp":
513
+ collectIdents(node.minimum, into);
514
+ collectIdents(node.value, into);
515
+ collectIdents(node.maximum, into);
516
+ return;
517
+ case "Abs":
518
+ case "Sign":
519
+ case "Sin":
520
+ case "Cos":
521
+ case "Tan":
522
+ case "Acos":
523
+ collectIdents(node.argument, into);
524
+ return;
525
+ case "Atan2":
526
+ collectIdents(node.y, into);
527
+ collectIdents(node.x, into);
528
+ return;
529
+ }
530
+ };
531
+ /** @internal */
532
+ const identsOf = (node) => {
533
+ const set = /* @__PURE__ */ new Set();
534
+ collectIdents(node, set);
535
+ return set;
536
+ };
537
+ const makeCalc = (node, refSet) => new CalcImpl(node, refSet);
538
+ /** @internal */
539
+ const toCalc = (input) => typeof input === "number" ? of$1(input) : input;
540
+ const mergeRefs = (exprs) => {
541
+ const merged = /* @__PURE__ */ new Set();
542
+ for (const expr of exprs) for (const name of refsOf(expr)) merged.add(name);
543
+ return merged;
544
+ };
545
+ /** @internal */
546
+ function of$1(value, precision) {
547
+ return makeCalc(constantNode(value, precision === void 0 ? void 0 : toSpec(precision)), EMPTY_REFS);
548
+ }
549
+ /**
550
+ * Builds a dimensioned constant. The `data` module's `Length`/`Angle`
551
+ * constructors call this and cast the result to the precise leaf-branded type;
552
+ * the calc core stays unit-agnostic, carrying `unit` and `kind` as given.
553
+ *
554
+ * @internal
555
+ */
556
+ function dimension(value, unit, kind, precision) {
557
+ return makeCalc(constantNode(value, precision === void 0 ? void 0 : toSpec(precision), unit, kind), EMPTY_REFS);
558
+ }
559
+ const refCache = /* @__PURE__ */ new Map();
560
+ /** @internal */
561
+ function ref$1(name) {
562
+ const cached = refCache.get(name);
563
+ if (cached) return cached;
564
+ invariant(name.length > 0, "Reference name must be a non-empty string");
565
+ const expr = makeCalc({
566
+ _tag: "Ref",
567
+ name
568
+ }, /* @__PURE__ */ new Set([name]));
569
+ refCache.set(name, expr);
570
+ return expr;
571
+ }
572
+ /**
573
+ * Builds a bare-identifier constant — a leaf serializing as `name`, carrying no
574
+ * references. The `data` module's `Channel` keywords call this; the identifier
575
+ * text is opaque to the calc core, resolved by whatever CSS context surrounds
576
+ * it (a relative-color function today).
577
+ *
578
+ * @internal
579
+ */
580
+ function ident(name) {
581
+ invariant(name.length > 0, "Identifier name must be a non-empty string");
582
+ return makeCalc({
583
+ _tag: "Ident",
584
+ name
585
+ }, EMPTY_REFS);
586
+ }
587
+ const liftNary = (construct) => (args) => {
588
+ const exprs = args.map(toCalc);
589
+ return makeCalc(construct(exprs.map(nodeOf)), mergeRefs(exprs));
590
+ };
591
+ const addImpl = liftNary(addNode);
592
+ const minImpl = liftNary(minNode);
593
+ const maxImpl = liftNary(maxNode);
594
+ const naryCombinator = (impl) => ((...args) => impl(args));
595
+ /** @internal */
596
+ const add$1 = naryCombinator(addImpl);
597
+ /** @internal */
598
+ const min$1 = naryCombinator(minImpl);
599
+ /** @internal */
600
+ const max$1 = naryCombinator(maxImpl);
601
+ const liftBinary = (construct) => (left, right) => {
602
+ const l = toCalc(left);
603
+ const r = toCalc(right);
604
+ return makeCalc(construct(nodeOf(l), nodeOf(r)), mergeRefs([l, r]));
605
+ };
606
+ const subtractImpl = liftBinary(subtractNode);
607
+ const multiplyImpl = liftBinary(multiplyNode);
608
+ const divideImpl = liftBinary(divideNode);
609
+ const modImpl = liftBinary(modNode);
610
+ const powImpl = liftBinary(powNode);
611
+ const signedPowImpl = liftBinary(signedPowNode);
612
+ const atan2Impl = liftBinary(atan2Node);
613
+ /** @internal */
614
+ function subtract$1(left, right) {
615
+ return subtractImpl(left, right);
616
+ }
617
+ /** @internal */
618
+ function multiply$1(left, right) {
619
+ return multiplyImpl(left, right);
620
+ }
621
+ /** @internal */
622
+ function mod$1(left, right) {
623
+ return modImpl(left, right);
624
+ }
625
+ /** @internal */
626
+ function divide$1(left, right) {
627
+ return divideImpl(left, right);
628
+ }
629
+ /** @internal */
630
+ function pow$1(base, exponent) {
631
+ return powImpl(base, exponent);
632
+ }
633
+ /** @internal */
634
+ function signedPow$1(base, exponent) {
635
+ return signedPowImpl(base, exponent);
636
+ }
637
+ const liftUnary = (construct) => (argument) => {
638
+ const arg = toCalc(argument);
639
+ return makeCalc(construct(nodeOf(arg)), refsOf(arg));
640
+ };
641
+ const absImpl = liftUnary((argument) => foldUnary("Abs", argument));
642
+ const signImpl = liftUnary((argument) => foldUnary("Sign", argument));
643
+ const sinImpl = liftUnary((argument) => foldUnary("Sin", argument));
644
+ const cosImpl = liftUnary((argument) => foldUnary("Cos", argument));
645
+ const tanImpl = liftUnary((argument) => foldUnary("Tan", argument));
646
+ const acosImpl = liftUnary((argument) => foldUnary("Acos", argument));
647
+ /** @internal */
648
+ function abs$1(argument) {
649
+ return absImpl(argument);
650
+ }
651
+ /** @internal */
652
+ function sign$1(argument) {
653
+ return signImpl(argument);
654
+ }
655
+ /** @internal */
656
+ function sin$1(argument) {
657
+ return sinImpl(argument);
658
+ }
659
+ /** @internal */
660
+ function cos$1(argument) {
661
+ return cosImpl(argument);
662
+ }
663
+ /** @internal */
664
+ function tan$1(argument) {
665
+ return tanImpl(argument);
666
+ }
667
+ /** @internal */
668
+ function acos$1(argument) {
669
+ return acosImpl(argument);
670
+ }
671
+ /** @internal */
672
+ function atan2$1(y, x) {
673
+ return atan2Impl(y, x);
674
+ }
675
+ /** @internal */
676
+ function clamp$1(minimum, value, maximum) {
677
+ const lo = toCalc(minimum);
678
+ const mid = toCalc(value);
679
+ const hi = toCalc(maximum);
680
+ return makeCalc(clampNode(nodeOf(lo), nodeOf(mid), nodeOf(hi)), mergeRefs([
681
+ lo,
682
+ mid,
683
+ hi
684
+ ]));
685
+ }
686
+ /** @internal */
687
+ function lerp$1(a, b, t) {
688
+ return add$1(multiply$1(subtract$1(1, t), a), multiply$1(t, b));
689
+ }
690
+ /** @internal */
691
+ const collectBindings = (refSet, bindings) => {
692
+ const nodeBindings = {};
693
+ const newRefs = new Set(refSet);
694
+ for (const [key, value] of Object.entries(bindings)) {
695
+ if (value === void 0 || !refSet.has(key)) continue;
696
+ const expr = toCalc(value);
697
+ nodeBindings[key] = nodeOf(expr);
698
+ newRefs.delete(key);
699
+ for (const name of refsOf(expr)) newRefs.add(name);
700
+ }
701
+ return {
702
+ nodeBindings,
703
+ refSet: newRefs
704
+ };
705
+ };
706
+ /** @internal */
707
+ const bind$1 = dual(2, (expr, bindings) => {
708
+ const collected = collectBindings(refsOf(expr), bindings);
709
+ return makeCalc(substituteNode(nodeOf(expr), collected.nodeBindings), collected.refSet);
710
+ });
711
+ /** @internal */
712
+ function solve$1(expr, bindings, context) {
713
+ let node = nodeOf(expr);
714
+ let remaining = refsOf(expr);
715
+ if (bindings !== void 0) {
716
+ const collected = collectBindings(remaining, bindings);
717
+ node = substituteNode(node, collected.nodeBindings);
718
+ remaining = collected.refSet;
719
+ }
720
+ invariant(remaining.size === 0, "Cannot convert expression to number: unbound references remain");
721
+ return evaluateNode(node, context ?? {});
722
+ }
723
+ /** @internal */
724
+ function serialize$1(expr, options) {
725
+ let node = nodeOf(expr);
726
+ if (options?.bindings !== void 0) {
727
+ const collected = collectBindings(refsOf(expr), options.bindings);
728
+ node = substituteNode(node, collected.nodeBindings);
729
+ }
730
+ const precision = options?.precision === void 0 ? DEFAULT_FORMAT : toSpec(options.precision);
731
+ return serializeTop(node, precision);
732
+ }
733
+ /** @internal */
734
+ function refs$1(expr) {
735
+ return refsOf(expr);
736
+ }
737
+ /** @internal */
738
+ function channels$1(expr) {
739
+ return identsOf(nodeOf(expr));
740
+ }
741
+ /** @internal */
742
+ const equals$1 = dual(2, (self, that) => equals$2(self, that));
743
+ //#endregion
744
+ //#region src/calc/calc.ts
745
+ var calc_exports = /* @__PURE__ */ __exportAll({
746
+ abs: () => abs,
747
+ acos: () => acos,
748
+ add: () => add,
749
+ atan2: () => atan2,
750
+ bind: () => bind,
751
+ channels: () => channels,
752
+ clamp: () => clamp,
753
+ cos: () => cos,
754
+ divide: () => divide,
755
+ equals: () => equals,
756
+ isCalc: () => isCalc,
757
+ lerp: () => lerp,
758
+ max: () => max,
759
+ min: () => min,
760
+ mod: () => mod,
761
+ multiply: () => multiply,
762
+ of: () => of,
763
+ pow: () => pow,
764
+ ref: () => ref,
765
+ refs: () => refs,
766
+ serialize: () => serialize,
767
+ sign: () => sign,
768
+ signedPow: () => signedPow,
769
+ sin: () => sin,
770
+ solve: () => solve,
771
+ subtract: () => subtract,
772
+ tan: () => tan
773
+ });
774
+ /**
775
+ * Checks if a value is a `Calc`.
776
+ *
777
+ * True only for values built by this module's constructors, which carry
778
+ * the brand.
779
+ *
780
+ * @param u - The value to check.
781
+ * @returns `true` if the value is a `Calc`, `false` otherwise.
782
+ * @since 0.1.0
783
+ */
784
+ const isCalc = isCalc$1;
785
+ /**
786
+ * Creates a constant expression, optionally annotated with a serialization
787
+ * precision that overrides the context default wherever the constant lands
788
+ * — including in constants produced by folding it with others (the
789
+ * highest-fidelity operand annotation wins).
790
+ *
791
+ * Bare numbers passed to combinators become unannotated constants; `of`
792
+ * exists to name a value or pin its precision.
793
+ *
794
+ * @param value - The constant value. Must be finite.
795
+ * @param precision - Optional precision annotation.
796
+ * @returns A constant `Calc<never>`.
797
+ * @throws `Error` when `value` is not finite.
798
+ * @example
799
+ * ```ts
800
+ * const k = Calc.of(0.8377580409572781, Precision.significant(10))
801
+ * Calc.serialize(Calc.multiply(k, Calc.ref('t'))) // 'calc(0.837758041 * var(--t))'
802
+ * ```
803
+ * @since 0.1.0
804
+ */
805
+ 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;
824
+ /**
825
+ * Adds expressions. Constant operands fold at construction.
826
+ *
827
+ * Serializes as `a + b + ...` inside a `calc()` wrapper; negative constant
828
+ * terms (and products led by a negative constant) render subtractively:
829
+ * `a + (-2)` serializes as `a - 2`.
830
+ *
831
+ * @param a - The first operand.
832
+ * @param b - The second operand.
833
+ * @returns The sum, with the operands' references unioned.
834
+ * @example
835
+ * ```ts
836
+ * Calc.serialize(Calc.add(Calc.ref('x'), 10)) // 'calc(var(--x) + 10)'
837
+ * ```
838
+ * @since 0.1.0
839
+ */
840
+ const add = add$1;
841
+ /**
842
+ * Subtracts `right` from `left`. Constant operands fold at construction.
843
+ *
844
+ * @param left - The minuend.
845
+ * @param right - The subtrahend.
846
+ * @returns The difference, with the operands' references unioned.
847
+ * @since 0.1.0
848
+ */
849
+ const subtract = subtract$1;
850
+ /**
851
+ * The CSS `mod()` of `dividend` and `divisor` — the remainder that takes the
852
+ * 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`;
854
+ * constant operands fold at construction.
855
+ *
856
+ * @param dividend - The value to reduce.
857
+ * @param divisor - The modulus, sharing `dividend`'s kind.
858
+ * @returns The modulo, with the operands' references unioned.
859
+ * @example
860
+ * ```ts
861
+ * Calc.serialize(Calc.mod(Calc.ref('h'), 360)) // 'mod(var(--h), 360)'
862
+ * ```
863
+ * @since 0.2.0
864
+ */
865
+ const mod = mod$1;
866
+ /**
867
+ * Multiplies expressions. Constant operands fold at construction.
868
+ *
869
+ * Addition and subtraction operands are parenthesized when serialized
870
+ * under a product: `(a + b) * c`.
871
+ *
872
+ * @param left - The first factor.
873
+ * @param right - The second factor.
874
+ * @returns The product, with the operands' references unioned.
875
+ * @since 0.1.0
876
+ */
877
+ const multiply = multiply$1;
878
+ /**
879
+ * Divides `left` by `right`. Constant operands fold at construction.
880
+ *
881
+ * @param left - The dividend.
882
+ * @param right - The divisor.
883
+ * @returns The quotient, with the operands' references unioned.
884
+ * @since 0.1.0
885
+ */
886
+ const divide = divide$1;
887
+ /**
888
+ * Raises `base` to `exponent`. Serializes as the CSS `pow()` function.
889
+ *
890
+ * @param base - The base.
891
+ * @param exponent - The exponent.
892
+ * @returns The power, with the operands' references unioned.
893
+ * @since 0.1.0
894
+ */
895
+ const pow = pow$1;
896
+ /**
897
+ * Sign-preserving power: `abs(base) ^ exponent * sign(base)`. Unlike
898
+ * `pow`, well-defined for negative bases with fractional exponents.
899
+ * Serializes as `pow(abs(base), exponent) * sign(base)`.
900
+ *
901
+ * @param base - The base.
902
+ * @param exponent - The exponent.
903
+ * @returns The signed power, with the operands' references unioned.
904
+ * @since 0.1.0
905
+ */
906
+ const signedPow = signedPow$1;
907
+ /**
908
+ * The minimum of the operands. Serializes as the CSS `min()` function.
909
+ *
910
+ * @param a - The first operand.
911
+ * @param b - The second operand.
912
+ * @returns The minimum, with the operands' references unioned.
913
+ * @since 0.1.0
914
+ */
915
+ const min = min$1;
916
+ /**
917
+ * The maximum of the operands. Serializes as the CSS `max()` function.
918
+ *
919
+ * @param a - The first operand.
920
+ * @param b - The second operand.
921
+ * @returns The maximum, with the operands' references unioned.
922
+ * @since 0.1.0
923
+ */
924
+ const max = max$1;
925
+ /**
926
+ * Clamps `value` between `minimum` and `maximum`. Serializes as the CSS
927
+ * `clamp()` function, with the CSS argument order `(min, value, max)`.
928
+ *
929
+ * @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.
933
+ * @example
934
+ * ```ts
935
+ * Calc.serialize(Calc.clamp(-1, Calc.ref('u'), 1)) // 'clamp(-1, var(--u), 1)'
936
+ * ```
937
+ * @since 0.1.0
938
+ */
939
+ const clamp = clamp$1;
940
+ /**
941
+ * Linear interpolation from `a` to `b` by `t`. This is sugar, not a node:
942
+ * it desugars to `(1 - t) * a + t * b`, and serializes as that expanded
943
+ * form.
944
+ *
945
+ * @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.
949
+ * @since 0.1.0
950
+ */
951
+ const lerp = lerp$1;
952
+ /**
953
+ * The absolute value. Serializes as the CSS `abs()` function.
954
+ *
955
+ * @param argument - The operand.
956
+ * @returns The absolute value expression.
957
+ * @since 0.1.0
958
+ */
959
+ const abs = abs$1;
960
+ /**
961
+ * The sign (`-1`, `0`, or `1`). Serializes as the CSS `sign()` function.
962
+ *
963
+ * @param argument - The operand.
964
+ * @returns The sign expression.
965
+ * @since 0.1.0
966
+ */
967
+ const sign = sign$1;
968
+ /**
969
+ * The sine of its argument. Serializes as the CSS `sin()` function, which
970
+ * 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.
972
+ *
973
+ * @param argument - An angle, or a plain number in radians.
974
+ * @returns The sine, a `<number>`, carrying the argument's units.
975
+ * @since 0.1.0
976
+ */
977
+ const sin = sin$1;
978
+ /**
979
+ * The cosine of its argument. Serializes as the CSS `cos()` function, which
980
+ * 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.
982
+ *
983
+ * @param argument - An angle, or a plain number in radians.
984
+ * @returns The cosine, a `<number>`, carrying the argument's units.
985
+ * @since 0.1.0
986
+ */
987
+ const cos = cos$1;
988
+ /**
989
+ * The tangent of its argument. Serializes as the CSS `tan()` function, which
990
+ * 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()`.
994
+ *
995
+ * @param argument - An angle, or a plain number in radians.
996
+ * @returns The tangent, a `<number>`, carrying the argument's units.
997
+ * @since 0.2.0
998
+ */
999
+ const tan = tan$1;
1000
+ /**
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.
1003
+ *
1004
+ * Because the result is angle-kind, it composes only with other angles: divide
1005
+ * or scale it by a number, and add or subtract an `Angle.rad(...)` phase. A
1006
+ * plain number added to it is a type error — supply the phase as an angle.
1007
+ *
1008
+ * @param argument - The cosine value, in `[-1, 1]`.
1009
+ * @returns The arccosine, an `<angle>`, carrying the argument's units.
1010
+ * @example
1011
+ * ```ts
1012
+ * const phase = Angle.rad(2.0943951)
1013
+ * Calc.serialize(Calc.cos(Calc.subtract(Calc.divide(Calc.acos(Calc.ref('u')), 3), phase)))
1014
+ * // 'cos(acos(var(--u)) / 3 - 2.0944rad)'
1015
+ * ```
1016
+ * @since 0.1.0
1017
+ */
1018
+ const acos = acos$1;
1019
+ /**
1020
+ * 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.
1025
+ *
1026
+ * @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.
1029
+ * @example
1030
+ * ```ts
1031
+ * const ratio = Calc.tan(Calc.atan2(Calc.subtract(Length.vw(100), Length.px(320)), Length.px(160)))
1032
+ * Calc.serialize(ratio) // 'tan(atan2(100vw - 320px, 160px))'
1033
+ * ```
1034
+ * @since 0.2.0
1035
+ */
1036
+ const atan2 = atan2$1;
1037
+ const bind = bind$1;
1038
+ const solve = solve$1;
1039
+ /**
1040
+ * Renders an expression as CSS text. Arithmetic gets a `calc()` wrapper;
1041
+ * function forms (`min`, `clamp`, `sin`, ...) and leaves stand alone.
1042
+ * References render as `var(--name)`.
1043
+ *
1044
+ * Bindings in `options` are applied first and may be partial — this is
1045
+ * the serialize half of the solve/serialize duality, and unbound
1046
+ * references are the values left for the browser. Constants render with
1047
+ * their annotated precision, or the context `precision` option (default
1048
+ * `Precision.decimals(5)`). Constants equal to pi render as the CSS
1049
+ * constant `pi` where a math function surrounds them.
1050
+ *
1051
+ * @param expr - The expression to render.
1052
+ * @param options - Optional bindings and precision context.
1053
+ * @returns Deterministic CSS text.
1054
+ * @example
1055
+ * ```ts
1056
+ * const fluid = Calc.add(10, Calc.ref('runtime'))
1057
+ * Calc.serialize(fluid) // 'calc(10 + var(--runtime))'
1058
+ * Calc.serialize(fluid, { bindings: { runtime: 4 } }) // '14'
1059
+ * ```
1060
+ * @since 0.1.0
1061
+ */
1062
+ const serialize = serialize$1;
1063
+ /**
1064
+ * The expression's unbound reference names.
1065
+ *
1066
+ * @param expr - The expression to inspect.
1067
+ * @returns The set of unbound reference names.
1068
+ * @since 0.1.0
1069
+ */
1070
+ const refs = refs$1;
1071
+ /**
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.
1075
+ *
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.
1082
+ *
1083
+ * @param expr - The expression to inspect.
1084
+ * @returns The set of channel-keyword tokens the expression reads.
1085
+ * @example
1086
+ * ```ts
1087
+ * Calc.channels(Calc.multiply(Channel.L, 0.8)) // Set { 'l' }
1088
+ * Calc.channels(Calc.ref('x')) // Set {}
1089
+ * ```
1090
+ * @since 0.2.0
1091
+ */
1092
+ const channels = channels$1;
1093
+ const equals = equals$1;
1094
+ //#endregion
1095
+ //#region src/calc/precision.ts
1096
+ var precision_exports = /* @__PURE__ */ __exportAll({
1097
+ decimals: () => decimals,
1098
+ isPrecision: () => isPrecision,
1099
+ significant: () => significant
1100
+ });
1101
+ /**
1102
+ * Checks if a value is a `Precision`.
1103
+ *
1104
+ * True only for values built by `decimals` or `significant`, which carry
1105
+ * the brand.
1106
+ *
1107
+ * @param u - The value to check.
1108
+ * @returns `true` if the value is a `Precision`, `false` otherwise.
1109
+ * @since 0.1.0
1110
+ */
1111
+ const isPrecision = isPrecision$1;
1112
+ /**
1113
+ * Creates a `Precision` fixing the count of digits after the decimal
1114
+ * point. The library default for unannotated constants is `decimals(5)`.
1115
+ *
1116
+ * @param digits - Digits after the decimal point. Must be an integer in `[0, 100]`.
1117
+ * @returns A `Precision` in `decimals` mode.
1118
+ * @throws `Error` when `digits` is not an integer in `[0, 100]`.
1119
+ * @example
1120
+ * ```ts
1121
+ * Calc.serialize(Calc.of(1 / 3), { precision: Precision.decimals(2) }) // '0.33'
1122
+ * ```
1123
+ * @since 0.1.0
1124
+ */
1125
+ const decimals = decimals$1;
1126
+ /**
1127
+ * Creates a `Precision` fixing the count of significant digits. Use it for
1128
+ * unit-free constants whose error is amplified downstream — solved curve
1129
+ * coefficients, for example — where fixed decimal places would truncate.
1130
+ *
1131
+ * @param digits - Significant digits. Must be an integer in `[1, 100]`.
1132
+ * @returns A `Precision` in `significant` mode.
1133
+ * @throws `Error` when `digits` is not an integer in `[1, 100]`.
1134
+ * @example
1135
+ * ```ts
1136
+ * const k = Calc.of(0.8377580409572781, Precision.significant(10))
1137
+ * Calc.serialize(k) // '0.837758041'
1138
+ * ```
1139
+ * @since 0.1.0
1140
+ */
1141
+ const significant = significant$1;
1142
+ //#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 };
1144
+
1145
+ //# sourceMappingURL=calc-Cih4o2r7.mjs.map