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,166 @@
1
+ import { a as Kind, c as Precision, n as Bindings, r as Calc, t as ApplyBindings } from "./index-BvtwY4FQ.mjs";
2
+ import { t as Pipeable } from "./utils-BKm298I-.mjs";
3
+ import { t as Color } from "./color-BvNJ2YqL.mjs";
4
+ import { n as RenderOptions$1 } from "./mediaQuery-BYR1z-iD.mjs";
5
+ //#region src/declaration/declaration.internal.d.ts
6
+ declare const DeclarationTypeId: unique symbol;
7
+ type DeclarationTypeId = typeof DeclarationTypeId;
8
+ declare namespace declaration_d_exports {
9
+ export { Declaration, RenderOptions, Value, bind, equals, isDeclaration, make, refs, render };
10
+ }
11
+ /**
12
+ * A CSS declaration: a property name paired with a value.
13
+ *
14
+ * This is the seam where the library's two halves meet — the value is
15
+ * either literal CSS text, passed through verbatim, or a value-layer
16
+ * expression (`Calc` or `Color`) serialized when the declaration renders.
17
+ * A `Calc` of any dimension is accepted: a `<number>`, or a `<length>` /
18
+ * `<angle>` built from `fashionable/data`, which carries its own units.
19
+ *
20
+ * The `Refs` parameter carries the value's unbound reference names, as on
21
+ * `Calc`; literal text binds nothing and a text-valued declaration is a
22
+ * `Declaration<never>`.
23
+ *
24
+ * Construct via `make`.
25
+ *
26
+ * @since 0.1.0
27
+ */
28
+ interface Declaration<out Refs extends string = string> extends Pipeable {
29
+ readonly [DeclarationTypeId]: DeclarationTypeId;
30
+ /**
31
+ * The property name, exactly as it renders — `font-size`, or `--depth`
32
+ * for a custom property.
33
+ */
34
+ readonly name: string;
35
+ /**
36
+ * The declaration's value: literal CSS text or a value-layer expression.
37
+ */
38
+ readonly value: Value<Refs>;
39
+ }
40
+ /**
41
+ * The value forms a declaration can hold: literal CSS text, a `Calc`
42
+ * expression of any dimension, or a `Color` expression.
43
+ *
44
+ * @since 0.1.0
45
+ */
46
+ type Value<Refs extends string = string> = string | Calc<Refs, Kind, unknown> | Color<Refs>;
47
+ /**
48
+ * Checks if a value is a `Declaration`.
49
+ *
50
+ * True only for values built by this module's constructors, which carry
51
+ * the brand.
52
+ *
53
+ * @param u - The value to check.
54
+ * @returns `true` if the value is a `Declaration`, `false` otherwise.
55
+ * @since 0.1.0
56
+ */
57
+ declare const isDeclaration: (u: unknown) => u is Declaration<string>;
58
+ /**
59
+ * Creates a declaration.
60
+ *
61
+ * Literal text is stored verbatim — no parsing, no escaping. A bare
62
+ * number is coerced to an unannotated constant expression, as anywhere
63
+ * else an expression is accepted, so it serializes under the precision
64
+ * context rather than as raw text.
65
+ *
66
+ * @param name - The property name, exactly as it renders (`--x` keeps its dashes). Must be non-empty.
67
+ * @param value - Literal CSS text, a number, or a `Calc`/`Color` expression.
68
+ * @returns A `Declaration` carrying the value's reference names — `Declaration<never>` for text and numbers.
69
+ * @throws `Error` when `name` is empty, or `value` is a non-finite number.
70
+ * @example
71
+ * ```ts
72
+ * Declaration.make('color', 'red')
73
+ * Declaration.make('--fluid', Calc.add(14, Calc.multiply(Calc.ref('vw'), 0.01)))
74
+ * ```
75
+ * @since 0.1.0
76
+ */
77
+ declare const make: <Refs extends string = never>(name: string, value: Value<Refs> | number) => Declaration<Refs>;
78
+ declare const bind: {
79
+ /**
80
+ * Returns a function that binds the given names in a declaration's
81
+ * value.
82
+ *
83
+ * @param bindings - Reference names to values or expressions.
84
+ * @returns A function replacing bound references in its argument's value.
85
+ * @since 0.1.0
86
+ */
87
+ <const B extends Bindings>(bindings: B): <Refs extends string>(declaration: Declaration<Refs>) => Declaration<ApplyBindings<Refs, B>>;
88
+ /**
89
+ * Replaces references in the declaration's value with values or other
90
+ * expressions, re-folding constant subtrees. Semantics match
91
+ * `Calc.bind`: unreferenced names and `undefined` values are ignored,
92
+ * and expression-valued bindings contribute their own references. A
93
+ * literal-text value binds nothing; the declaration is returned as-is.
94
+ *
95
+ * @param declaration - The declaration to bind.
96
+ * @param bindings - Reference names to values or expressions.
97
+ * @returns The bound declaration.
98
+ * @since 0.1.0
99
+ */
100
+ <Refs extends string, const B extends Bindings>(declaration: Declaration<Refs>, bindings: B): Declaration<ApplyBindings<Refs, B>>;
101
+ };
102
+ /**
103
+ * The declaration's unbound reference names — empty for literal text,
104
+ * the value's references otherwise.
105
+ *
106
+ * @param declaration - The declaration to inspect.
107
+ * @returns The set of unbound reference names.
108
+ * @since 0.1.0
109
+ */
110
+ declare const refs: <Refs extends string>(declaration: Declaration<Refs>) => ReadonlySet<Refs>;
111
+ /**
112
+ * Options for `render`, extending `MediaQuery.RenderOptions` — the
113
+ * render-options family's base — with the precision context.
114
+ *
115
+ * @since 0.1.0
116
+ */
117
+ interface RenderOptions extends RenderOptions$1 {
118
+ /**
119
+ * The precision for expression constants that carry no annotation of
120
+ * their own. Defaults to `Precision.decimals(5)`, as in
121
+ * `Calc.serialize`.
122
+ */
123
+ readonly precision?: Precision;
124
+ }
125
+ /**
126
+ * Renders the declaration as one CSS declaration, semicolon included:
127
+ * `name: value;`. Literal text passes through verbatim; expression
128
+ * values serialize as `Calc.serialize`/`Color.serialize` would, with
129
+ * unbound references rendering as `var(--name)`.
130
+ *
131
+ * @param declaration - The declaration to render.
132
+ * @param options - Optional precision context for expression values.
133
+ * @returns Deterministic CSS text.
134
+ * @example
135
+ * ```ts
136
+ * Declaration.render(Declaration.make('--indent', Calc.multiply(Calc.ref('depth'), 8)))
137
+ * // '--indent: calc(var(--depth) * 8);'
138
+ * ```
139
+ * @since 0.1.0
140
+ */
141
+ declare const render: (declaration: Declaration<string>, options?: RenderOptions) => string;
142
+ declare const equals: {
143
+ /**
144
+ * Returns a function that checks structural equality against `that`.
145
+ *
146
+ * @param that - The declaration to compare against.
147
+ * @returns A function testing its argument for structural equality with `that`.
148
+ * @since 0.1.0
149
+ */
150
+ (that: Declaration<string>): (self: Declaration<string>) => boolean;
151
+ /**
152
+ * Structural equality: names compare as text, expression values as
153
+ * expression trees (`Calc.equals` semantics, precision annotations
154
+ * included). Literal text never equals an expression, even one that
155
+ * would serialize to the same characters.
156
+ *
157
+ * @param self - The first declaration.
158
+ * @param that - The second declaration.
159
+ * @returns `true` if the declarations are structurally equal.
160
+ * @since 0.1.0
161
+ */
162
+ (self: Declaration<string>, that: Declaration<string>): boolean;
163
+ };
164
+ //#endregion
165
+ export { RenderOptions as n, declaration_d_exports as r, Declaration as t };
166
+ //# sourceMappingURL=declaration-1DlO_ltT.d.mts.map
@@ -0,0 +1,73 @@
1
+ import { Pipeable, dual, invariant } from "../utils.mjs";
2
+ import { a as hash, i as equals$1, n as HashTypeId, r as combine, s as hashString, t as EqualTypeId } from "./equal-U9G5LhtL.mjs";
3
+ import { C as EMPTY_REFS, S as toCalc, c as bind$1, p as isCalc, v as refsOf$1, y as serialize } from "./calc-Cih4o2r7.mjs";
4
+ import { f as refsOf$2, p as serialize$1, t as bind$2 } from "./color.internal-Dts5ycTm.mjs";
5
+ //#region src/declaration/declaration.internal.ts
6
+ const DeclarationTypeId = Symbol.for("fashionable/declaration");
7
+ const valueEquals = (a, b) => typeof a === "string" || typeof b === "string" ? a === b : equals$1(a, b);
8
+ const valueHash = (value) => typeof value === "string" ? hashString(value) : hash(value);
9
+ const serializeValue = (value, precision) => {
10
+ if (typeof value === "string") return value;
11
+ const options = precision === void 0 ? {} : { precision };
12
+ return isCalc(value) ? serialize(value, options) : serialize$1(value, options);
13
+ };
14
+ var DeclarationImpl = class extends Pipeable {
15
+ [DeclarationTypeId] = DeclarationTypeId;
16
+ name;
17
+ value;
18
+ refSet;
19
+ #hash;
20
+ constructor(name, value) {
21
+ super();
22
+ this.name = name;
23
+ this.value = value;
24
+ this.refSet = typeof value === "string" ? EMPTY_REFS : isCalc(value) ? refsOf$1(value) : refsOf$2(value);
25
+ }
26
+ [EqualTypeId](that) {
27
+ return isDeclaration(that) && this.name === that.name && valueEquals(this.value, that.value);
28
+ }
29
+ [HashTypeId]() {
30
+ if (this.#hash === void 0) {
31
+ let h = hashString("fashionable/declaration");
32
+ h = combine(h, hashString(this.name));
33
+ h = combine(h, valueHash(this.value));
34
+ this.#hash = h;
35
+ }
36
+ return this.#hash;
37
+ }
38
+ get [Symbol.toStringTag]() {
39
+ return `Declaration(${this.name}: ${serializeValue(this.value)})`;
40
+ }
41
+ get [Symbol.for("nodejs.util.inspect.custom")]() {
42
+ return this[Symbol.toStringTag];
43
+ }
44
+ };
45
+ /** @internal */
46
+ const isDeclaration = (u) => typeof u === "object" && u !== null && DeclarationTypeId in u;
47
+ /** @internal */
48
+ const refsOf = (declaration) => declaration.refSet;
49
+ /** @internal */
50
+ function make(name, value) {
51
+ invariant(name.length > 0, "Declaration name must be a non-empty string");
52
+ return new DeclarationImpl(name, typeof value === "number" ? toCalc(value) : value);
53
+ }
54
+ /** @internal */
55
+ const bind = dual(2, (declaration, bindings) => {
56
+ const value = declaration.value;
57
+ if (typeof value === "string") return declaration;
58
+ return new DeclarationImpl(declaration.name, isCalc(value) ? bind$1(value, bindings) : bind$2(value, bindings));
59
+ });
60
+ /** @internal */
61
+ function refs(declaration) {
62
+ return refsOf(declaration);
63
+ }
64
+ /** @internal */
65
+ const renderWith = (declaration, precision) => `${declaration.name}: ${serializeValue(declaration.value, precision)};`;
66
+ /** @internal */
67
+ const render = (declaration, options) => renderWith(declaration, options?.precision);
68
+ /** @internal */
69
+ const equals = dual(2, (self, that) => equals$1(self, that));
70
+ //#endregion
71
+ export { refs as a, renderWith as c, make as i, equals as n, refsOf as o, isDeclaration as r, render as s, bind as t };
72
+
73
+ //# sourceMappingURL=declaration.internal-wLB4ssxC.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declaration.internal-wLB4ssxC.mjs","names":["Equal.equals","Equal.hashString","Equal.hash","serializeCalc","serializeColor","calcRefsOf","colorRefsOf","Equal.EqualTypeId","Equal.HashTypeId","#hash","Equal.combine","bindCalc","bindColor"],"sources":["../../src/declaration/declaration.internal.ts"],"sourcesContent":["import type { ApplyBindings, Bindings, Input } from '#calc/calc'\nimport {\n bind as bindCalc,\n isCalc,\n refsOf as calcRefsOf,\n serialize as serializeCalc,\n toCalc,\n} from '#calc/calc.internal'\nimport type { Precision } from '#calc/precision'\nimport {\n bind as bindColor,\n refsOf as colorRefsOf,\n serialize as serializeColor,\n} from '#data/color.internal'\nimport * as Equal from '#internal/equal'\nimport { EMPTY_REFS } from '#internal/refs'\nimport { dual, invariant, Pipeable } from '#util'\nimport type { Declaration, RenderOptions, Value } from './declaration.ts'\n\nexport const DeclarationTypeId = Symbol.for('fashionable/declaration')\nexport type DeclarationTypeId = typeof DeclarationTypeId\n\nconst valueEquals = (a: Value<string>, b: Value<string>): boolean =>\n typeof a === 'string' || typeof b === 'string' ? a === b : Equal.equals(a, b)\n\nconst valueHash = (value: Value<string>): number =>\n typeof value === 'string' ? Equal.hashString(value) : Equal.hash(value)\n\nconst serializeValue = (value: Value<string>, precision?: Precision): string => {\n if (typeof value === 'string') {\n return value\n }\n const options = precision === undefined ? {} : { precision }\n return isCalc(value) ? serializeCalc(value, options) : serializeColor(value, options)\n}\n\nclass DeclarationImpl extends Pipeable implements Declaration<string>, Equal.Equal {\n readonly [DeclarationTypeId]: DeclarationTypeId = DeclarationTypeId\n\n readonly name: string\n readonly value: Value<string>\n readonly refSet: ReadonlySet<string>\n #hash: number | undefined\n\n constructor(name: string, value: Value<string>) {\n super()\n this.name = name\n this.value = value\n this.refSet =\n typeof value === 'string'\n ? EMPTY_REFS\n : isCalc(value)\n ? calcRefsOf(value)\n : colorRefsOf(value)\n }\n\n [Equal.EqualTypeId](that: unknown): boolean {\n return isDeclaration(that) && this.name === that.name && valueEquals(this.value, that.value)\n }\n\n [Equal.HashTypeId](): number {\n if (this.#hash === undefined) {\n let h = Equal.hashString('fashionable/declaration')\n h = Equal.combine(h, Equal.hashString(this.name))\n h = Equal.combine(h, valueHash(this.value))\n this.#hash = h\n }\n return this.#hash\n }\n\n get [Symbol.toStringTag]() {\n return `Declaration(${this.name}: ${serializeValue(this.value)})`\n }\n\n get [Symbol.for('nodejs.util.inspect.custom')]() {\n return this[Symbol.toStringTag]\n }\n}\n\n/** @internal */\nexport const isDeclaration = (u: unknown): u is Declaration<string> =>\n typeof u === 'object' && u !== null && DeclarationTypeId in u\n\n/** @internal */\nexport const refsOf = <R extends string>(declaration: Declaration<R>): ReadonlySet<R> =>\n (declaration as unknown as DeclarationImpl).refSet as ReadonlySet<R>\n\n/** @internal */\nexport function make<Refs extends string = never>(\n name: string,\n value: Value<Refs> | number,\n): Declaration<Refs> {\n invariant(name.length > 0, 'Declaration name must be a non-empty string')\n return new DeclarationImpl(\n name,\n typeof value === 'number' ? toCalc(value) : value,\n ) as Declaration<Refs>\n}\n\n/** @internal */\nexport const bind: {\n <const B extends Bindings>(\n bindings: B,\n ): <Refs extends string>(declaration: Declaration<Refs>) => Declaration<ApplyBindings<Refs, B>>\n <Refs extends string, const B extends Bindings>(\n declaration: Declaration<Refs>,\n bindings: B,\n ): Declaration<ApplyBindings<Refs, B>>\n} = dual(\n 2,\n (\n declaration: Declaration<string>,\n bindings: Record<string, Input<string>>,\n ): Declaration<string> => {\n const value = declaration.value\n if (typeof value === 'string') {\n return declaration\n }\n return new DeclarationImpl(\n declaration.name,\n isCalc(value) ? bindCalc(value, bindings) : bindColor(value, bindings),\n )\n },\n)\n\n/** @internal */\nexport function refs<Refs extends string>(declaration: Declaration<Refs>): ReadonlySet<Refs> {\n return refsOf(declaration)\n}\n\n/** @internal */\nexport const renderWith = (declaration: Declaration<string>, precision?: Precision): string =>\n `${declaration.name}: ${serializeValue(declaration.value, precision)};`\n\n/** @internal */\nexport const render = (declaration: Declaration<string>, options?: RenderOptions): string =>\n renderWith(declaration, options?.precision)\n\n/** @internal */\nexport const equals = dual<\n (that: Declaration<string>) => (self: Declaration<string>) => boolean,\n (self: Declaration<string>, that: Declaration<string>) => boolean\n>(2, (self: Declaration<string>, that: Declaration<string>): boolean => Equal.equals(self, that))\n"],"mappings":";;;;;AAmBA,MAAa,oBAAoB,OAAO,IAAI,yBAAyB;AAGrE,MAAM,eAAe,GAAkB,MACrC,OAAO,MAAM,YAAY,OAAO,MAAM,WAAW,MAAM,IAAIA,SAAa,GAAG,CAAC;AAE9E,MAAM,aAAa,UACjB,OAAO,UAAU,WAAWC,WAAiB,KAAK,IAAIC,KAAW,KAAK;AAExE,MAAM,kBAAkB,OAAsB,cAAkC;CAC9E,IAAI,OAAO,UAAU,UACnB,OAAO;CAET,MAAM,UAAU,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU;CAC3D,OAAO,OAAO,KAAK,IAAIC,UAAc,OAAO,OAAO,IAAIC,YAAe,OAAO,OAAO;AACtF;AAEA,IAAM,kBAAN,cAA8B,SAAqD;CACjF,CAAU,qBAAwC;CAElD;CACA;CACA;CACA;CAEA,YAAY,MAAc,OAAsB;EAC9C,MAAM;EACN,KAAK,OAAO;EACZ,KAAK,QAAQ;EACb,KAAK,SACH,OAAO,UAAU,WACb,aACA,OAAO,KAAK,IACVC,SAAW,KAAK,IAChBC,SAAY,KAAK;CAC3B;CAEA,CAACC,aAAmB,MAAwB;EAC1C,OAAO,cAAc,IAAI,KAAK,KAAK,SAAS,KAAK,QAAQ,YAAY,KAAK,OAAO,KAAK,KAAK;CAC7F;CAEA,CAACC,cAA4B;EAC3B,IAAI,KAAKC,UAAU,KAAA,GAAW;GAC5B,IAAI,IAAIR,WAAiB,yBAAyB;GAClD,IAAIS,QAAc,GAAGT,WAAiB,KAAK,IAAI,CAAC;GAChD,IAAIS,QAAc,GAAG,UAAU,KAAK,KAAK,CAAC;GAC1C,KAAKD,QAAQ;EACf;EACA,OAAO,KAAKA;CACd;CAEA,KAAK,OAAO,eAAe;EACzB,OAAO,eAAe,KAAK,KAAK,IAAI,eAAe,KAAK,KAAK,EAAE;CACjE;CAEA,KAAK,OAAO,IAAI,4BAA4B,KAAK;EAC/C,OAAO,KAAK,OAAO;CACrB;AACF;;AAGA,MAAa,iBAAiB,MAC5B,OAAO,MAAM,YAAY,MAAM,QAAQ,qBAAqB;;AAG9D,MAAa,UAA4B,gBACtC,YAA2C;;AAG9C,SAAgB,KACd,MACA,OACmB;CACnB,UAAU,KAAK,SAAS,GAAG,6CAA6C;CACxE,OAAO,IAAI,gBACT,MACA,OAAO,UAAU,WAAW,OAAO,KAAK,IAAI,KAC9C;AACF;;AAGA,MAAa,OAQT,KACF,IAEE,aACA,aACwB;CACxB,MAAM,QAAQ,YAAY;CAC1B,IAAI,OAAO,UAAU,UACnB,OAAO;CAET,OAAO,IAAI,gBACT,YAAY,MACZ,OAAO,KAAK,IAAIE,OAAS,OAAO,QAAQ,IAAIC,OAAU,OAAO,QAAQ,CACvE;AACF,CACF;;AAGA,SAAgB,KAA0B,aAAmD;CAC3F,OAAO,OAAO,WAAW;AAC3B;;AAGA,MAAa,cAAc,aAAkC,cAC3D,GAAG,YAAY,KAAK,IAAI,eAAe,YAAY,OAAO,SAAS,EAAE;;AAGvE,MAAa,UAAU,aAAkC,YACvD,WAAW,aAAa,SAAS,SAAS;;AAG5C,MAAa,SAAS,KAGpB,IAAI,MAA2B,SAAuCZ,SAAa,MAAM,IAAI,CAAC"}
@@ -0,0 +1,71 @@
1
+ //#region src/internal/equal.ts
2
+ /**
3
+ * A minimal structural equality and hashing protocol, modeled on Effect-TS's
4
+ * Equal and Hash modules but reduced to what this library needs: value types
5
+ * implement the two symbol methods on their Impl classes, and `equals` uses
6
+ * the hash as a fast-path reject before dispatching to the symbol method.
7
+ *
8
+ * The protocol is internal. Each public namespace exposes a typed `equals`
9
+ * that delegates here.
10
+ */
11
+ const EqualTypeId = Symbol.for("fashionable/Equal");
12
+ const HashTypeId = Symbol.for("fashionable/Hash");
13
+ /** @internal */
14
+ const isEqual = (u) => typeof u === "object" && u !== null && EqualTypeId in u;
15
+ /** @internal */
16
+ const equals = (a, b) => {
17
+ if (a === b) return true;
18
+ if (isEqual(a) && isEqual(b)) {
19
+ if (a[HashTypeId]() !== b[HashTypeId]()) return false;
20
+ return a[EqualTypeId](b);
21
+ }
22
+ return false;
23
+ };
24
+ /** @internal */
25
+ const hash = (u) => {
26
+ switch (typeof u) {
27
+ case "number": return hashNumber(u);
28
+ case "string": return hashString(u);
29
+ case "boolean": return u ? 1231 : 1237;
30
+ case "undefined": return -1640531527;
31
+ case "object":
32
+ if (u === null) return -2048144789;
33
+ if (isEqual(u)) return u[HashTypeId]();
34
+ return 0;
35
+ default: return 0;
36
+ }
37
+ };
38
+ /**
39
+ * Combines two hashes into one, order-sensitively (boost hash_combine).
40
+ *
41
+ * @internal
42
+ */
43
+ const combine = (a, b) => a ^ b + 2654435769 + (a << 6) + (a >>> 2) | 0;
44
+ /**
45
+ * FNV-1a over UTF-16 code units.
46
+ *
47
+ * @internal
48
+ */
49
+ const hashString = (s) => {
50
+ let h = -2128831035;
51
+ for (let i = 0; i < s.length; i++) {
52
+ h ^= s.charCodeAt(i);
53
+ h = Math.imul(h, 16777619);
54
+ }
55
+ return h | 0;
56
+ };
57
+ const numberBits = /* @__PURE__ */ new DataView(/* @__PURE__ */ new ArrayBuffer(8));
58
+ /**
59
+ * Hashes a number by its float64 bit pattern. Negative zero is normalized
60
+ * to positive zero first so values that compare equal hash equally.
61
+ *
62
+ * @internal
63
+ */
64
+ const hashNumber = (n) => {
65
+ numberBits.setFloat64(0, n === 0 ? 0 : n);
66
+ return combine(numberBits.getInt32(0), numberBits.getInt32(4));
67
+ };
68
+ //#endregion
69
+ export { hash as a, equals as i, HashTypeId as n, hashNumber as o, combine as r, hashString as s, EqualTypeId as t };
70
+
71
+ //# sourceMappingURL=equal-U9G5LhtL.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"equal-U9G5LhtL.mjs","names":[],"sources":["../../src/internal/equal.ts"],"sourcesContent":["/**\n * A minimal structural equality and hashing protocol, modeled on Effect-TS's\n * Equal and Hash modules but reduced to what this library needs: value types\n * implement the two symbol methods on their Impl classes, and `equals` uses\n * the hash as a fast-path reject before dispatching to the symbol method.\n *\n * The protocol is internal. Each public namespace exposes a typed `equals`\n * that delegates here.\n */\n\nexport const EqualTypeId: unique symbol = Symbol.for('fashionable/Equal')\nexport type EqualTypeId = typeof EqualTypeId\n\nexport const HashTypeId: unique symbol = Symbol.for('fashionable/Hash')\nexport type HashTypeId = typeof HashTypeId\n\n/** @internal */\nexport interface Equal {\n [EqualTypeId](that: unknown): boolean\n [HashTypeId](): number\n}\n\n/** @internal */\nexport const isEqual = (u: unknown): u is Equal =>\n typeof u === 'object' && u !== null && EqualTypeId in u\n\n/** @internal */\nexport const equals = (a: unknown, b: unknown): boolean => {\n if (a === b) {\n return true\n }\n if (isEqual(a) && isEqual(b)) {\n if (a[HashTypeId]() !== b[HashTypeId]()) {\n return false\n }\n return a[EqualTypeId](b)\n }\n return false\n}\n\n/** @internal */\nexport const hash = (u: unknown): number => {\n switch (typeof u) {\n case 'number':\n return hashNumber(u)\n case 'string':\n return hashString(u)\n case 'boolean':\n return u ? 1231 : 1237\n case 'undefined':\n return 0x9e3779b9 | 0\n case 'object':\n if (u === null) {\n return 0x85ebca6b | 0\n }\n if (isEqual(u)) {\n return u[HashTypeId]()\n }\n return 0\n default:\n return 0\n }\n}\n\n/**\n * Combines two hashes into one, order-sensitively (boost hash_combine).\n *\n * @internal\n */\nexport const combine = (a: number, b: number): number =>\n (a ^ (b + 0x9e3779b9 + (a << 6) + (a >>> 2))) | 0\n\n/**\n * FNV-1a over UTF-16 code units.\n *\n * @internal\n */\nexport const hashString = (s: string): number => {\n let h = 0x811c9dc5 | 0\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i)\n h = Math.imul(h, 0x01000193)\n }\n return h | 0\n}\n\nconst numberBits = new DataView(new ArrayBuffer(8))\n\n/**\n * Hashes a number by its float64 bit pattern. Negative zero is normalized\n * to positive zero first so values that compare equal hash equally.\n *\n * @internal\n */\nexport const hashNumber = (n: number): number => {\n numberBits.setFloat64(0, n === 0 ? 0 : n)\n return combine(numberBits.getInt32(0), numberBits.getInt32(4))\n}\n\n/** @internal */\nexport const hashArray = (values: ReadonlyArray<unknown>): number => {\n let h = 0x811c9dc5 | 0\n for (const value of values) {\n h = combine(h, hash(value))\n }\n return h\n}\n"],"mappings":";;;;;;;;;;AAUA,MAAa,cAA6B,OAAO,IAAI,mBAAmB;AAGxE,MAAa,aAA4B,OAAO,IAAI,kBAAkB;;AAUtE,MAAa,WAAW,MACtB,OAAO,MAAM,YAAY,MAAM,QAAQ,eAAe;;AAGxD,MAAa,UAAU,GAAY,MAAwB;CACzD,IAAI,MAAM,GACR,OAAO;CAET,IAAI,QAAQ,CAAC,KAAK,QAAQ,CAAC,GAAG;EAC5B,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,GACpC,OAAO;EAET,OAAO,EAAE,YAAY,CAAC,CAAC;CACzB;CACA,OAAO;AACT;;AAGA,MAAa,QAAQ,MAAuB;CAC1C,QAAQ,OAAO,GAAf;EACE,KAAK,UACH,OAAO,WAAW,CAAC;EACrB,KAAK,UACH,OAAO,WAAW,CAAC;EACrB,KAAK,WACH,OAAO,IAAI,OAAO;EACpB,KAAK,aACH,OAAO;EACT,KAAK;GACH,IAAI,MAAM,MACR,OAAO;GAET,IAAI,QAAQ,CAAC,GACX,OAAO,EAAE,WAAW,CAAC;GAEvB,OAAO;EACT,SACE,OAAO;CACX;AACF;;;;;;AAOA,MAAa,WAAW,GAAW,MAChC,IAAK,IAAI,cAAc,KAAK,MAAM,MAAM,KAAO;;;;;;AAOlD,MAAa,cAAc,MAAsB;CAC/C,IAAI,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;EACjC,KAAK,EAAE,WAAW,CAAC;EACnB,IAAI,KAAK,KAAK,GAAG,QAAU;CAC7B;CACA,OAAO,IAAI;AACb;AAEA,MAAM,6BAAa,IAAI,yBAAS,IAAI,YAAY,CAAC,CAAC;;;;;;;AAQlD,MAAa,cAAc,MAAsB;CAC/C,WAAW,WAAW,GAAG,MAAM,IAAI,IAAI,CAAC;CACxC,OAAO,QAAQ,WAAW,SAAS,CAAC,GAAG,WAAW,SAAS,CAAC,CAAC;AAC/D"}
@@ -0,0 +1,294 @@
1
+ import { t as Pipeable } from "./utils-BKm298I-.mjs";
2
+ import { n as RenderOptions$1 } from "./declaration-1DlO_ltT.mjs";
3
+ //#region src/fontFace/fontFaceRule.internal.d.ts
4
+ declare const FontFaceRuleTypeId: unique symbol;
5
+ type FontFaceRuleTypeId = typeof FontFaceRuleTypeId;
6
+ declare const SourceTypeId: unique symbol;
7
+ type SourceTypeId = typeof SourceTypeId;
8
+ declare namespace fontFaceRule_d_exports {
9
+ export { Descriptors, Display, FontFaceRule, RenderOptions, Source, Style, UnicodeRange, Weight, equals, isFontFaceRule, isSource, local, make, render, url };
10
+ }
11
+ /**
12
+ * An `@font-face` rule: a font family, its sources, and the optional
13
+ * descriptors that scope and adjust the face.
14
+ *
15
+ * A declaration-block at-rule lives at the top level of a stylesheet —
16
+ * it is deliberately not a rule-block member, so it cannot nest. All
17
+ * fields are plain data: nothing in `@font-face` takes an expression.
18
+ *
19
+ * Construct via `make`.
20
+ *
21
+ * @since 0.1.0
22
+ */
23
+ interface FontFaceRule extends Pipeable {
24
+ readonly [FontFaceRuleTypeId]: FontFaceRuleTypeId;
25
+ /**
26
+ * The `font-family` descriptor: the name the face binds to, quoted when
27
+ * rendered.
28
+ */
29
+ readonly family: string;
30
+ /**
31
+ * The `src` descriptor's sources, in authored order — the browser uses
32
+ * the first it supports.
33
+ */
34
+ readonly src: ReadonlyArray<Source>;
35
+ /**
36
+ * The `font-weight` descriptor: one weight or an ordered
37
+ * `[min, max]` range, in `[1, 1000]`.
38
+ */
39
+ readonly weight: Weight | undefined;
40
+ /**
41
+ * The `font-style` descriptor keyword.
42
+ */
43
+ readonly style: Style | undefined;
44
+ /**
45
+ * The `font-display` descriptor keyword.
46
+ */
47
+ readonly display: Display | undefined;
48
+ /**
49
+ * The `unicode-range` descriptor's ranges, canonically ordered (by
50
+ * start, then end) with exact duplicates dropped.
51
+ */
52
+ readonly unicodeRange: ReadonlyArray<UnicodeRange> | undefined;
53
+ /**
54
+ * The `ascent-override` metric, as a percentage number (`90` renders
55
+ * `90%`).
56
+ */
57
+ readonly ascentOverride: number | undefined;
58
+ /**
59
+ * The `descent-override` metric, as a percentage number.
60
+ */
61
+ readonly descentOverride: number | undefined;
62
+ /**
63
+ * The `line-gap-override` metric, as a percentage number.
64
+ */
65
+ readonly lineGapOverride: number | undefined;
66
+ /**
67
+ * The `size-adjust` metric, as a percentage number.
68
+ */
69
+ readonly sizeAdjust: number | undefined;
70
+ }
71
+ /**
72
+ * One entry of an `@font-face` `src` list: a downloadable `url(...)`
73
+ * (optionally with a `format(...)` hint) or a `local(...)` lookup.
74
+ *
75
+ * Construct via `url` and `local`.
76
+ *
77
+ * @since 0.1.0
78
+ */
79
+ interface Source extends Pipeable {
80
+ readonly [SourceTypeId]: SourceTypeId;
81
+ }
82
+ /**
83
+ * A `font-weight` descriptor value: a single weight, or an ordered
84
+ * `[min, max]` range (`[100, 900]` renders `100 900`) for variable faces.
85
+ *
86
+ * @since 0.1.0
87
+ */
88
+ type Weight = number | readonly [number, number];
89
+ /**
90
+ * The `font-style` descriptor keywords. Oblique angle ranges are a later
91
+ * extension when a consumer needs them.
92
+ *
93
+ * @since 0.1.0
94
+ */
95
+ type Style = 'normal' | 'italic' | 'oblique';
96
+ /**
97
+ * The `font-display` descriptor keywords.
98
+ *
99
+ * @since 0.1.0
100
+ */
101
+ type Display = 'auto' | 'block' | 'swap' | 'fallback' | 'optional';
102
+ /**
103
+ * One `unicode-range` descriptor entry: a single codepoint (`0x400`
104
+ * renders `U+400`) or an inclusive `[start, end]` range (`[0x400, 0x4ff]`
105
+ * renders `U+400-4FF`), each in `[0x0, 0x10FFFF]`.
106
+ *
107
+ * The wildcard spelling (`U+4??`) is range sugar and is not modeled.
108
+ *
109
+ * @since 0.2.0
110
+ */
111
+ type UnicodeRange = number | readonly [start: number, end: number];
112
+ /**
113
+ * The descriptors accepted by `make`.
114
+ *
115
+ * Metrics-adjusted fallback faces are the expected use: a face whose sole
116
+ * source is `local(...)`, carrying overrides computed from the primary
117
+ * face's metrics.
118
+ *
119
+ * @since 0.1.0
120
+ */
121
+ interface Descriptors {
122
+ /**
123
+ * The `font-family` descriptor: the name the face binds to. Required.
124
+ */
125
+ readonly family: string;
126
+ /**
127
+ * The `src` descriptor's sources, tried in the order given — the
128
+ * browser uses the first it supports. Required and non-empty.
129
+ */
130
+ readonly src: ReadonlyArray<Source>;
131
+ /**
132
+ * The `font-weight` descriptor: one weight or an ordered `[min, max]`
133
+ * range, each in `[1, 1000]`.
134
+ */
135
+ readonly weight?: Weight;
136
+ /**
137
+ * The `font-style` descriptor keyword.
138
+ */
139
+ readonly style?: Style;
140
+ /**
141
+ * The `font-display` descriptor keyword.
142
+ */
143
+ readonly display?: Display;
144
+ /**
145
+ * The `unicode-range` descriptor: the codepoints the face applies to,
146
+ * as single codepoints and inclusive `[start, end]` ranges. Non-empty
147
+ * when given. The descriptor is a set union, so entries canonicalize —
148
+ * sorted by start then end, exact duplicates dropped — and
149
+ * construction order never matters.
150
+ */
151
+ readonly unicodeRange?: ReadonlyArray<UnicodeRange>;
152
+ /**
153
+ * The `ascent-override` metric, as a percentage number (`90` means
154
+ * `90%`).
155
+ */
156
+ readonly ascentOverride?: number;
157
+ /**
158
+ * The `descent-override` metric, as a percentage number.
159
+ */
160
+ readonly descentOverride?: number;
161
+ /**
162
+ * The `line-gap-override` metric, as a percentage number.
163
+ */
164
+ readonly lineGapOverride?: number;
165
+ /**
166
+ * The `size-adjust` metric, as a percentage number.
167
+ */
168
+ readonly sizeAdjust?: number;
169
+ }
170
+ /**
171
+ * Options for `render`, in the render-options family rooted at
172
+ * `MediaQuery.RenderOptions` (via `Declaration.RenderOptions`). This
173
+ * renderer consumes `indent` and the inherited `precision` (for the
174
+ * weight and metric-override numbers); `mediaSyntax` is accepted and
175
+ * ignored, so one options object composes across the library.
176
+ *
177
+ * @since 0.1.0
178
+ */
179
+ interface RenderOptions extends RenderOptions$1 {
180
+ /**
181
+ * The indentation unit for the block's declarations. Defaults to a tab.
182
+ */
183
+ readonly indent?: string;
184
+ }
185
+ /**
186
+ * Checks if a value is a `FontFaceRule`.
187
+ *
188
+ * True only for values built by this module's constructors, which carry
189
+ * the brand.
190
+ *
191
+ * @param u - The value to check.
192
+ * @returns `true` if the value is a `FontFaceRule`, `false` otherwise.
193
+ * @since 0.1.0
194
+ */
195
+ declare const isFontFaceRule: (u: unknown) => u is FontFaceRule;
196
+ /**
197
+ * Checks if a value is a font `Source`.
198
+ *
199
+ * True only for values built by `url` and `local`, which carry the brand.
200
+ *
201
+ * @param u - The value to check.
202
+ * @returns `true` if the value is a `Source`, `false` otherwise.
203
+ * @since 0.1.0
204
+ */
205
+ declare const isSource: (u: unknown) => u is Source;
206
+ /**
207
+ * Creates a downloadable font source, rendered `url('href')` — with a
208
+ * `format('...')` hint appended when `format` is given.
209
+ *
210
+ * @param href - The URL the face loads from. Must be non-empty; rendered single-quoted with embedded quotes and backslashes escaped.
211
+ * @param format - The optional format hint (`woff2`, `woff`, ...). Must be non-empty when given.
212
+ * @returns A `Source` for `Descriptors.src`.
213
+ * @throws `Error` when `href` is empty, or `format` is given but empty.
214
+ * @since 0.1.0
215
+ */
216
+ declare const url: (href: string, format?: string) => Source;
217
+ /**
218
+ * Creates a local font lookup, rendered `local('name')` — the expected
219
+ * sole source of a metrics-adjusted fallback face.
220
+ *
221
+ * @param name - The locally installed family name. Must be non-empty; rendered single-quoted with embedded quotes and backslashes escaped.
222
+ * @returns A `Source` for `Descriptors.src`.
223
+ * @throws `Error` when `name` is empty.
224
+ * @since 0.1.0
225
+ */
226
+ declare const local: (name: string) => Source;
227
+ /**
228
+ * Creates an `@font-face` rule.
229
+ *
230
+ * @param descriptors - The face's descriptors; `family` and `src` are required.
231
+ * @returns A `FontFaceRule`.
232
+ * @throws `Error` when `family` is empty, `src` is empty, a weight is outside `[1, 1000]` or a range is out of order, a unicode-range entry is empty, out of order, or outside `[0x0, 0x10FFFF]`, or a metric override is negative or non-finite.
233
+ * @example
234
+ * ```ts
235
+ * FontFaceRule.make({
236
+ * family: 'Inter',
237
+ * weight: [100, 900],
238
+ * style: 'normal',
239
+ * display: 'swap',
240
+ * src: [FontFaceRule.url('/fonts/inter-variable.woff2', 'woff2')],
241
+ * })
242
+ * ```
243
+ * @since 0.1.0
244
+ */
245
+ declare const make: (descriptors: Descriptors) => FontFaceRule;
246
+ /**
247
+ * Renders the rule as a complete `@font-face { ... }` block.
248
+ *
249
+ * Descriptors render in a fixed order — `font-family`, `font-weight`,
250
+ * `font-style`, `font-display`, `src`, `unicode-range`, then the metric
251
+ * overrides — one per line. A single-source `src` stays inline; multiple
252
+ * sources render one per line at double indent, comma-separated.
253
+ * Unicode ranges render uppercase-hex (`U+400, U+500-5FF`), in canonical
254
+ * order. Numbers format at the `precision` context (default
255
+ * `Precision.decimals(5)`); the metric descriptors append `%`.
256
+ *
257
+ * @param rule - The rule to render.
258
+ * @param options - Optional indentation unit and precision context.
259
+ * @returns Deterministic CSS text.
260
+ * @example
261
+ * ```ts
262
+ * FontFaceRule.render(
263
+ * FontFaceRule.make({ family: 'Inter', src: [FontFaceRule.url('/inter.woff2', 'woff2')] }),
264
+ * )
265
+ * // "@font-face {\n\tfont-family: 'Inter';\n\tsrc: url('/inter.woff2') format('woff2');\n}"
266
+ * ```
267
+ * @since 0.1.0
268
+ */
269
+ declare const render: (rule: FontFaceRule, options?: RenderOptions) => string;
270
+ declare const equals: {
271
+ /**
272
+ * Returns a function that checks structural equality against `that`.
273
+ *
274
+ * @param that - The rule to compare against.
275
+ * @returns A function testing its argument for structural equality with `that`.
276
+ * @since 0.1.0
277
+ */
278
+ (that: FontFaceRule): (self: FontFaceRule) => boolean;
279
+ /**
280
+ * Structural equality over descriptors. `src` order participates (it is
281
+ * fallback order); `unicode-range` order does not (entries canonicalize
282
+ * at construction); a single weight or codepoint never equals a range,
283
+ * even a degenerate one.
284
+ *
285
+ * @param self - The first rule.
286
+ * @param that - The second rule.
287
+ * @returns `true` if the rules are structurally equal.
288
+ * @since 0.1.0
289
+ */
290
+ (self: FontFaceRule, that: FontFaceRule): boolean;
291
+ };
292
+ //#endregion
293
+ export { fontFaceRule_d_exports as n, FontFaceRule as t };
294
+ //# sourceMappingURL=fontFaceRule-C7nYgH6X.d.mts.map