@craft-ts/style 0.7.0-beta.15

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 (73) hide show
  1. package/package.json +41 -0
  2. package/src/index.d.ts +18 -0
  3. package/src/index.d.ts.map +1 -0
  4. package/src/index.js +18 -0
  5. package/src/index.js.map +1 -0
  6. package/src/lib/axes/define.d.ts +115 -0
  7. package/src/lib/axes/define.d.ts.map +1 -0
  8. package/src/lib/axes/define.js +81 -0
  9. package/src/lib/axes/define.js.map +1 -0
  10. package/src/lib/axes/index.d.ts +4 -0
  11. package/src/lib/axes/index.d.ts.map +1 -0
  12. package/src/lib/axes/index.js +4 -0
  13. package/src/lib/axes/index.js.map +1 -0
  14. package/src/lib/axes/standard.d.ts +85 -0
  15. package/src/lib/axes/standard.d.ts.map +1 -0
  16. package/src/lib/axes/standard.js +109 -0
  17. package/src/lib/axes/standard.js.map +1 -0
  18. package/src/lib/axes/types.d.ts +67 -0
  19. package/src/lib/axes/types.d.ts.map +1 -0
  20. package/src/lib/axes/types.js +21 -0
  21. package/src/lib/axes/types.js.map +1 -0
  22. package/src/lib/css-vars.d.ts +100 -0
  23. package/src/lib/css-vars.d.ts.map +1 -0
  24. package/src/lib/css-vars.js +96 -0
  25. package/src/lib/css-vars.js.map +1 -0
  26. package/src/lib/kinds.d.ts +84 -0
  27. package/src/lib/kinds.d.ts.map +1 -0
  28. package/src/lib/kinds.js +44 -0
  29. package/src/lib/kinds.js.map +1 -0
  30. package/src/lib/obligations.d.ts +99 -0
  31. package/src/lib/obligations.d.ts.map +1 -0
  32. package/src/lib/obligations.js +69 -0
  33. package/src/lib/obligations.js.map +1 -0
  34. package/src/lib/props/factory.d.ts +61 -0
  35. package/src/lib/props/factory.d.ts.map +1 -0
  36. package/src/lib/props/factory.js +35 -0
  37. package/src/lib/props/factory.js.map +1 -0
  38. package/src/lib/props/generated.d.ts +974 -0
  39. package/src/lib/props/generated.d.ts.map +1 -0
  40. package/src/lib/props/generated.js +2478 -0
  41. package/src/lib/props/generated.js.map +1 -0
  42. package/src/lib/props/index.d.ts +37 -0
  43. package/src/lib/props/index.d.ts.map +1 -0
  44. package/src/lib/props/index.js +27 -0
  45. package/src/lib/props/index.js.map +1 -0
  46. package/src/lib/styles.d.ts +201 -0
  47. package/src/lib/styles.d.ts.map +1 -0
  48. package/src/lib/styles.js +247 -0
  49. package/src/lib/styles.js.map +1 -0
  50. package/src/lib/tokens/index.d.ts +4 -0
  51. package/src/lib/tokens/index.d.ts.map +1 -0
  52. package/src/lib/tokens/index.js +4 -0
  53. package/src/lib/tokens/index.js.map +1 -0
  54. package/src/lib/tokens/palette.d.ts +97 -0
  55. package/src/lib/tokens/palette.d.ts.map +1 -0
  56. package/src/lib/tokens/palette.js +61 -0
  57. package/src/lib/tokens/palette.js.map +1 -0
  58. package/src/lib/tokens/scales.d.ts +47 -0
  59. package/src/lib/tokens/scales.d.ts.map +1 -0
  60. package/src/lib/tokens/scales.js +51 -0
  61. package/src/lib/tokens/scales.js.map +1 -0
  62. package/src/lib/tokens/units.d.ts +114 -0
  63. package/src/lib/tokens/units.d.ts.map +1 -0
  64. package/src/lib/tokens/units.js +54 -0
  65. package/src/lib/tokens/units.js.map +1 -0
  66. package/src/plugin/emit.d.ts +64 -0
  67. package/src/plugin/emit.d.ts.map +1 -0
  68. package/src/plugin/emit.js +134 -0
  69. package/src/plugin/emit.js.map +1 -0
  70. package/src/plugin/vite.d.ts +66 -0
  71. package/src/plugin/vite.d.ts.map +1 -0
  72. package/src/plugin/vite.js +150 -0
  73. package/src/plugin/vite.js.map +1 -0
@@ -0,0 +1,21 @@
1
+ /**
2
+ * What an axis is made of.
3
+ *
4
+ * An axis is a **closed** set of points, shipped by the library or built by
5
+ * `defineBreakpoints` / `defineAxis` / `defineStateAxis` / `defineContainer`.
6
+ * Never a string: `scrollState.stuck.blockEnd`, not
7
+ * `scrollState.stuck('block-end')`. A key that does not exist is a compile
8
+ * error, not CSS the browser ignores.
9
+ *
10
+ * Every point carries its **driver**. An axis without one would be worse than a
11
+ * missing axis: the matrix would enumerate scenarios nothing can reach and
12
+ * render identical captures, which is false coverage rather than no coverage.
13
+ */
14
+ export const axisPoint = (axis, name, open, driver, extra = {}) => ({
15
+ axis,
16
+ point: name,
17
+ open,
18
+ driver,
19
+ ...extra,
20
+ });
21
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../libs/style/src/lib/axes/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA6DH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,IAAU,EACV,IAAW,EACX,IAAY,EACZ,MAAc,EACd,QAA2E,EAAE,EACrD,EAAE,CAAC,CAAC;IAC5B,IAAI;IACJ,KAAK,EAAE,IAAI;IACX,IAAI;IACJ,MAAM;IACN,GAAG,KAAK;CACT,CAAC,CAAC","sourcesContent":["/**\n * What an axis is made of.\n *\n * An axis is a **closed** set of points, shipped by the library or built by\n * `defineBreakpoints` / `defineAxis` / `defineStateAxis` / `defineContainer`.\n * Never a string: `scrollState.stuck.blockEnd`, not\n * `scrollState.stuck('block-end')`. A key that does not exist is a compile\n * error, not CSS the browser ignores.\n *\n * Every point carries its **driver**. An axis without one would be worse than a\n * missing axis: the matrix would enumerate scenarios nothing can reach and\n * render identical captures, which is false coverage rather than no coverage.\n */\n\n/** How a test reaches a point. There is no `'none'`: every point is reachable. */\nexport type Driver =\n | {\n readonly kind: 'emulateMedia';\n readonly feature:\n | 'prefers-color-scheme'\n | 'prefers-reduced-motion'\n | 'forced-colors'\n | 'prefers-contrast';\n readonly value: string;\n }\n | { readonly kind: 'resize'; readonly minInlineSize: string }\n | {\n readonly kind: 'resizeContainer';\n readonly container: string;\n readonly minInlineSize: string;\n }\n | {\n readonly kind: 'setAttribute';\n readonly name: string;\n readonly value: string;\n }\n | { readonly kind: 'scroll'; readonly to: 'start' | 'end' | 'snap' }\n | {\n readonly kind: 'descendantState';\n readonly state: 'user-invalid' | 'focus-visible' | 'checked';\n };\n\nexport interface AxisPoint<Axis extends string, Point extends string> {\n readonly axis: Axis;\n readonly point: Point;\n /** The at-rule or selector fragment the emitter wraps around the rule. */\n readonly open: string;\n readonly driver: Driver;\n /**\n * Ordered axes only — viewport and container. Two points of the same axis\n * with an order can be compared, which is what makes a dead rule detectable\n * and what lets the matrix reduce by interval instead of by product.\n */\n readonly order?: number;\n /**\n * Set when the point is a lower bound (`above`) or an upper bound (`below`).\n * A plain breakpoint is a lower bound.\n */\n readonly bound?: 'above' | 'below';\n /**\n * The container this point queries, when it is not the viewport. A container\n * axis does not propagate above the element that resolves it.\n */\n readonly container?: string;\n /**\n * Custom properties this axis is allowed to write, by kind syntax. Empty\n * means unconstrained. See `defineAxis(..., { writes })`.\n */\n readonly writes?: readonly string[];\n}\n\nexport type AnyAxisPoint = AxisPoint<string, string>;\n\nexport const axisPoint = <Axis extends string, Point extends string>(\n axis: Axis,\n name: Point,\n open: string,\n driver: Driver,\n extra: Omit<Partial<AnyAxisPoint>, 'axis' | 'point' | 'open' | 'driver'> = {},\n): AxisPoint<Axis, Point> => ({\n axis,\n point: name,\n open,\n driver,\n ...extra,\n});\n"]}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * CSS custom properties, typed by the `@property` grammar.
3
+ *
4
+ * Static → a class at build time. Dynamic → a typed custom property. No class
5
+ * is ever computed at runtime: a value that depends on a signal goes through
6
+ * `assign(v.x, …)`, never through a concatenated class string. That split is
7
+ * what keeps the visual matrix finite — a variable is not an axis.
8
+ */
9
+ import type { AnyKind, CssVarRole, CssVarSpec, ValueOf } from './kinds.ts';
10
+ export interface CssVarDeclaration {
11
+ readonly name: `--${string}`;
12
+ readonly syntax: string;
13
+ readonly inherits: boolean;
14
+ readonly initialValue: string;
15
+ readonly role: CssVarRole;
16
+ }
17
+ declare const VAR_VALUE: unique symbol;
18
+ declare const VAR_SYNTAX: unique symbol;
19
+ export declare const VAR_WRITE: unique symbol;
20
+ /**
21
+ * A declaration that writes a custom property, carrying the kind it writes.
22
+ *
23
+ * The syntax rides on the type so that an axis constrained to `<color>` can be
24
+ * checked at the call site of `when`, instead of by reading the emitted CSS
25
+ * afterwards and hoping.
26
+ */
27
+ export type VarWrite<Syntax extends string = string> = {
28
+ readonly property: string;
29
+ readonly value: string;
30
+ readonly unproven: string;
31
+ /**
32
+ * **Required**, not optional. An optional marker brands nothing: a plain
33
+ * declaration would satisfy `VarWrite<'<color>'>` structurally, and an axis
34
+ * constrained to colours would accept `p(space(6))` while looking correct.
35
+ * The same trap as an optional phantom on a primitive base, one level up.
36
+ */
37
+ readonly [VAR_WRITE]: Syntax;
38
+ };
39
+ /**
40
+ * A variable token **carries its kind's brand**: the token of a `<color>`
41
+ * variable is a `ColorValue`, so `color(v.ink)` needs no conversion and
42
+ * `p(v.ink)` does not compile. It is not a generic bag of strings.
43
+ */
44
+ export type CssVarToken<Value, Syntax extends string = string> = Value & {
45
+ readonly declaration: CssVarDeclaration;
46
+ /** Inference site for `assign`; nothing reads it at runtime. */
47
+ readonly [VAR_VALUE]?: Value;
48
+ /** Inference site for the axis write constraint. */
49
+ readonly [VAR_SYNTAX]?: Syntax;
50
+ /** The fallback is typed against the same kind: `.or(space(4))` will not compile. */
51
+ or(fallback: Value): Value;
52
+ };
53
+ export type AnySpec = CssVarSpec<string, any>;
54
+ export type CssVarTokens<Specs extends Readonly<Record<string, AnySpec>>> = {
55
+ readonly [Key in keyof Specs]: CssVarToken<Specs[Key]['initial'], Specs[Key]['syntax']>;
56
+ };
57
+ /** Every custom property declared so far — the emitter's `@property` input. */
58
+ export declare const registeredVars: () => readonly CssVarDeclaration[];
59
+ /** Test-only: the registry is module state, and a spec must be able to reset it. */
60
+ export declare const resetCssVarRegistry: () => void;
61
+ /**
62
+ * The name `--{prefix}-{key}` is **derived**, never retyped — which is what
63
+ * makes a mismatch between the declared name and the read name impossible.
64
+ *
65
+ * Two sheets sharing a prefix is an error rather than a merge: silently
66
+ * merging would let one component's `--card-bg` be redefined by another's,
67
+ * which is exactly the class of bug this package exists to remove.
68
+ */
69
+ export declare function cssVars<const Specs extends Readonly<Record<string, AnySpec>>>(prefix: string, specs: Specs): CssVarTokens<Specs>;
70
+ /** The `@property` block for one declaration, for the emitter. */
71
+ export declare const propertyRule: (declaration: CssVarDeclaration) => string;
72
+ /**
73
+ * Writes a variable **statically**, as part of a sheet.
74
+ *
75
+ * This is how an axis paints: `when(tone.danger, [set(v.bg, palette.accent.danger)])`
76
+ * emits one atomic rule that assigns the custom property, and the base rule
77
+ * that reads it never changes. The alternative — a class per tone per property —
78
+ * multiplies the atoms by the number of tones for no gain.
79
+ */
80
+ export declare function set<Value, Syntax extends string>(token: {
81
+ readonly [VAR_VALUE]?: Value;
82
+ readonly [VAR_SYNTAX]?: Syntax;
83
+ readonly declaration: CssVarDeclaration;
84
+ }, value: Value & {
85
+ readonly css: string;
86
+ readonly unproven?: string;
87
+ }): VarWrite<Syntax>;
88
+ /**
89
+ * The single gateway to the dynamic side. Returns an inline style object, to be
90
+ * bound to `style:` — readable by the existing renderer with no change, and
91
+ * invisible to the visual matrix, because a variable is not an axis.
92
+ */
93
+ export declare function assign<Value>(token: {
94
+ readonly [VAR_VALUE]?: Value;
95
+ readonly declaration: CssVarDeclaration;
96
+ }, value: Value & {
97
+ readonly css: string;
98
+ }): Readonly<Record<`--${string}`, string>>;
99
+ export type { CssVarRole, ValueOf, AnyKind };
100
+ //# sourceMappingURL=css-vars.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css-vars.d.ts","sourceRoot":"","sources":["../../../../../libs/style/src/lib/css-vars.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Units a registered `initial-value` may not use.
3
+ *
4
+ * `@property` requires the initial value to be **computationally independent**:
5
+ * it must not depend on the font size or the viewport. `initial-value: 1rem`
6
+ * therefore makes the whole `@property` rule invalid, and the browser drops it
7
+ * *silently* — the variable stops being registered, `var(--x)` resolves to
8
+ * nothing, and the declaration that reads it computes to zero. Every test stays
9
+ * green because nothing threw.
10
+ *
11
+ * Found the hard way on the design-system demo: the colours were registered and
12
+ * the lengths were not, and the only symptom was buttons with no padding.
13
+ */
14
+ const RELATIVE_UNIT = /\d\s*(r?em|ex|ch|cap|ic|r?lh|[sld]?v(w|h|i|b|min|max))\b/i;
15
+ const declared = new Map();
16
+ const prefixes = new Set();
17
+ /** Every custom property declared so far — the emitter's `@property` input. */
18
+ export const registeredVars = () => [
19
+ ...declared.values(),
20
+ ];
21
+ /** Test-only: the registry is module state, and a spec must be able to reset it. */
22
+ export const resetCssVarRegistry = () => {
23
+ declared.clear();
24
+ prefixes.clear();
25
+ };
26
+ /**
27
+ * The name `--{prefix}-{key}` is **derived**, never retyped — which is what
28
+ * makes a mismatch between the declared name and the read name impossible.
29
+ *
30
+ * Two sheets sharing a prefix is an error rather than a merge: silently
31
+ * merging would let one component's `--card-bg` be redefined by another's,
32
+ * which is exactly the class of bug this package exists to remove.
33
+ */
34
+ export function cssVars(prefix, specs) {
35
+ if (prefixes.has(prefix)) {
36
+ throw new Error(`cssVars: prefix '${prefix}' is already declared. Two sheets sharing a prefix would redefine each other's variables; pick a prefix per sheet.`);
37
+ }
38
+ prefixes.add(prefix);
39
+ const tokens = Object.entries(specs).map(([key, spec]) => {
40
+ const name = `--${prefix}-${key}`;
41
+ const initialValue = String(spec.initial.css ?? spec.initial);
42
+ if (spec.syntax.includes('length') && RELATIVE_UNIT.test(initialValue)) {
43
+ throw new Error(`cssVars: '${name}' registers a <length> with the initial value '${initialValue}', which is not computationally independent. @property refuses relative units there, and the browser drops the whole registration without a word — the variable then resolves to nothing wherever it is read. Give the initial value an absolute unit (unit.px(...)) and keep the relative one for what writes the variable.`);
44
+ }
45
+ const declaration = {
46
+ name,
47
+ syntax: spec.syntax,
48
+ inherits: spec.inherits,
49
+ initialValue,
50
+ role: spec.role,
51
+ };
52
+ declared.set(name, declaration);
53
+ const token = {
54
+ ...spec.initial,
55
+ css: `var(${name})`,
56
+ declaration,
57
+ or: (fallback) => ({
58
+ ...spec.initial,
59
+ css: `var(${name}, ${fallback.css})`,
60
+ }),
61
+ };
62
+ return [key, token];
63
+ });
64
+ return Object.fromEntries(tokens);
65
+ }
66
+ /** The `@property` block for one declaration, for the emitter. */
67
+ export const propertyRule = (declaration) => `@property ${declaration.name} { syntax: "${declaration.syntax}"; inherits: ${declaration.inherits}; initial-value: ${declaration.initialValue}; }`;
68
+ /**
69
+ * Writes a variable **statically**, as part of a sheet.
70
+ *
71
+ * This is how an axis paints: `when(tone.danger, [set(v.bg, palette.accent.danger)])`
72
+ * emits one atomic rule that assigns the custom property, and the base rule
73
+ * that reads it never changes. The alternative — a class per tone per property —
74
+ * multiplies the atoms by the number of tones for no gain.
75
+ */
76
+ export function set(token, value) {
77
+ // The marker is a declared symbol: nothing is written at runtime, and the
78
+ // object stays an ordinary declaration the sheet walker already understands.
79
+ return {
80
+ property: token.declaration.name,
81
+ value: value.css,
82
+ unproven: value.unproven ?? '',
83
+ };
84
+ }
85
+ /**
86
+ * The single gateway to the dynamic side. Returns an inline style object, to be
87
+ * bound to `style:` — readable by the existing renderer with no change, and
88
+ * invisible to the visual matrix, because a variable is not an axis.
89
+ */
90
+ export function assign(token, value) {
91
+ // The key type is narrow on purpose: the renderer's `style:` binding accepts
92
+ // a record of custom properties, and a plain `Record<string, string>` would
93
+ // widen into "any CSS property", which is not what this returns.
94
+ return { [token.declaration.name]: value.css };
95
+ }
96
+ //# sourceMappingURL=css-vars.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css-vars.js","sourceRoot":"","sources":["../../../../../libs/style/src/lib/css-vars.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * CSS custom properties, typed by the `@property` grammar.\n *\n * Static → a class at build time. Dynamic → a typed custom property. No class\n * is ever computed at runtime: a value that depends on a signal goes through\n * `assign(v.x, …)`, never through a concatenated class string. That split is\n * what keeps the visual matrix finite — a variable is not an axis.\n */\nimport type { AnyKind, CssVarRole, CssVarSpec, ValueOf } from './kinds.ts';\n\nexport interface CssVarDeclaration {\n readonly name: `--${string}`;\n readonly syntax: string;\n readonly inherits: boolean;\n readonly initialValue: string;\n readonly role: CssVarRole;\n}\n\ndeclare const VAR_VALUE: unique symbol;\ndeclare const VAR_SYNTAX: unique symbol;\nexport declare const VAR_WRITE: unique symbol;\n\n/**\n * A declaration that writes a custom property, carrying the kind it writes.\n *\n * The syntax rides on the type so that an axis constrained to `<color>` can be\n * checked at the call site of `when`, instead of by reading the emitted CSS\n * afterwards and hoping.\n */\nexport type VarWrite<Syntax extends string = string> = {\n readonly property: string;\n readonly value: string;\n readonly unproven: string;\n /**\n * **Required**, not optional. An optional marker brands nothing: a plain\n * declaration would satisfy `VarWrite<'<color>'>` structurally, and an axis\n * constrained to colours would accept `p(space(6))` while looking correct.\n * The same trap as an optional phantom on a primitive base, one level up.\n */\n readonly [VAR_WRITE]: Syntax;\n};\n\n/**\n * A variable token **carries its kind's brand**: the token of a `<color>`\n * variable is a `ColorValue`, so `color(v.ink)` needs no conversion and\n * `p(v.ink)` does not compile. It is not a generic bag of strings.\n */\nexport type CssVarToken<Value, Syntax extends string = string> = Value & {\n readonly declaration: CssVarDeclaration;\n /** Inference site for `assign`; nothing reads it at runtime. */\n readonly [VAR_VALUE]?: Value;\n /** Inference site for the axis write constraint. */\n readonly [VAR_SYNTAX]?: Syntax;\n /** The fallback is typed against the same kind: `.or(space(4))` will not compile. */\n or(fallback: Value): Value;\n};\n\nexport type AnySpec = CssVarSpec<string, any>;\n\nexport type CssVarTokens<Specs extends Readonly<Record<string, AnySpec>>> = {\n readonly [Key in keyof Specs]: CssVarToken<\n Specs[Key]['initial'],\n Specs[Key]['syntax']\n >;\n};\n\n/**\n * Units a registered `initial-value` may not use.\n *\n * `@property` requires the initial value to be **computationally independent**:\n * it must not depend on the font size or the viewport. `initial-value: 1rem`\n * therefore makes the whole `@property` rule invalid, and the browser drops it\n * *silently* — the variable stops being registered, `var(--x)` resolves to\n * nothing, and the declaration that reads it computes to zero. Every test stays\n * green because nothing threw.\n *\n * Found the hard way on the design-system demo: the colours were registered and\n * the lengths were not, and the only symptom was buttons with no padding.\n */\nconst RELATIVE_UNIT =\n /\\d\\s*(r?em|ex|ch|cap|ic|r?lh|[sld]?v(w|h|i|b|min|max))\\b/i;\n\nconst declared = new Map<string, CssVarDeclaration>();\nconst prefixes = new Set<string>();\n\n/** Every custom property declared so far — the emitter's `@property` input. */\nexport const registeredVars = (): readonly CssVarDeclaration[] => [\n ...declared.values(),\n];\n\n/** Test-only: the registry is module state, and a spec must be able to reset it. */\nexport const resetCssVarRegistry = (): void => {\n declared.clear();\n prefixes.clear();\n};\n\n/**\n * The name `--{prefix}-{key}` is **derived**, never retyped — which is what\n * makes a mismatch between the declared name and the read name impossible.\n *\n * Two sheets sharing a prefix is an error rather than a merge: silently\n * merging would let one component's `--card-bg` be redefined by another's,\n * which is exactly the class of bug this package exists to remove.\n */\nexport function cssVars<const Specs extends Readonly<Record<string, AnySpec>>>(\n prefix: string,\n specs: Specs,\n): CssVarTokens<Specs> {\n if (prefixes.has(prefix)) {\n throw new Error(\n `cssVars: prefix '${prefix}' is already declared. Two sheets sharing a prefix would redefine each other's variables; pick a prefix per sheet.`,\n );\n }\n prefixes.add(prefix);\n\n const tokens = Object.entries(specs).map(([key, spec]) => {\n const name = `--${prefix}-${key}` as `--${string}`;\n const initialValue = String(\n (spec.initial as { readonly css?: unknown }).css ?? spec.initial,\n );\n if (spec.syntax.includes('length') && RELATIVE_UNIT.test(initialValue)) {\n throw new Error(\n `cssVars: '${name}' registers a <length> with the initial value '${initialValue}', which is not computationally independent. @property refuses relative units there, and the browser drops the whole registration without a word — the variable then resolves to nothing wherever it is read. Give the initial value an absolute unit (unit.px(...)) and keep the relative one for what writes the variable.`,\n );\n }\n const declaration: CssVarDeclaration = {\n name,\n syntax: spec.syntax,\n inherits: spec.inherits,\n initialValue,\n role: spec.role,\n };\n declared.set(name, declaration);\n\n const token = {\n ...(spec.initial as object),\n css: `var(${name})`,\n declaration,\n or: (fallback: { readonly css: string }) => ({\n ...(spec.initial as object),\n css: `var(${name}, ${fallback.css})`,\n }),\n };\n return [key, token] as const;\n });\n\n return Object.fromEntries(tokens) as unknown as CssVarTokens<Specs>;\n}\n\n/** The `@property` block for one declaration, for the emitter. */\nexport const propertyRule = (declaration: CssVarDeclaration): string =>\n `@property ${declaration.name} { syntax: \"${declaration.syntax}\"; inherits: ${declaration.inherits}; initial-value: ${declaration.initialValue}; }`;\n\n/**\n * Writes a variable **statically**, as part of a sheet.\n *\n * This is how an axis paints: `when(tone.danger, [set(v.bg, palette.accent.danger)])`\n * emits one atomic rule that assigns the custom property, and the base rule\n * that reads it never changes. The alternative — a class per tone per property —\n * multiplies the atoms by the number of tones for no gain.\n */\nexport function set<Value, Syntax extends string>(\n token: {\n readonly [VAR_VALUE]?: Value;\n readonly [VAR_SYNTAX]?: Syntax;\n readonly declaration: CssVarDeclaration;\n },\n value: Value & { readonly css: string; readonly unproven?: string },\n): VarWrite<Syntax> {\n // The marker is a declared symbol: nothing is written at runtime, and the\n // object stays an ordinary declaration the sheet walker already understands.\n return {\n property: token.declaration.name,\n value: value.css,\n unproven: value.unproven ?? '',\n } as unknown as VarWrite<Syntax>;\n}\n\n/**\n * The single gateway to the dynamic side. Returns an inline style object, to be\n * bound to `style:` — readable by the existing renderer with no change, and\n * invisible to the visual matrix, because a variable is not an axis.\n */\nexport function assign<Value>(\n token: {\n readonly [VAR_VALUE]?: Value;\n readonly declaration: CssVarDeclaration;\n },\n value: Value & { readonly css: string },\n): Readonly<Record<`--${string}`, string>> {\n // The key type is narrow on purpose: the renderer's `style:` binding accepts\n // a record of custom properties, and a plain `Record<string, string>` would\n // widen into \"any CSS property\", which is not what this returns.\n return { [token.declaration.name]: value.css };\n}\n\nexport type { CssVarRole, ValueOf, AnyKind };\n"]}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Custom-property kinds, modelled after the `@property` grammar itself.
3
+ *
4
+ * A kind is not an invention: it is exactly what CSS knows how to register
5
+ * (`<color>`, `<length>`, `<length-percentage>`, `+`, `#`, `|`). Inventing a
6
+ * kind `@property` does not know would break the runtime half of the
7
+ * guarantee — the browser would stop validating the value, and a variable
8
+ * assigned a length where a colour was expected would simply paint nothing.
9
+ *
10
+ * A kind is **callable**: `kind.color(palette.text.strong)` builds the spec
11
+ * `cssVars` wants, while `kind.color` on its own is the grammar that `many`,
12
+ * `csv` and the axis `writes` constraint operate on. One name for one concept,
13
+ * used in both positions.
14
+ *
15
+ * The assignability lattice is **not** a second table kept in sync with the
16
+ * brands. It reads the brands: an integer carries the number brand, so
17
+ * `<integer>` flows into `<number>`; `<length-percentage>` is a union, so
18
+ * `<length>` flows into it and not the other way round. A table would be one
19
+ * more thing that can silently disagree with reality.
20
+ */
21
+ import type { AngleValue, ColorRole, ColorValue, CssStringValue, IdentValue, IntegerValue, LengthPercentageValue, LengthValue, NumberValue, PercentValue, TimeValue, UrlValue } from './tokens/units.ts';
22
+ export type CssVarRole = ColorRole;
23
+ export interface CssVarOptions {
24
+ readonly role?: CssVarRole;
25
+ /**
26
+ * `false` by default: it bounds invalidation when the variable is rewritten
27
+ * at runtime instead of making the whole subtree recompute.
28
+ */
29
+ readonly inherits?: boolean;
30
+ }
31
+ export interface CssVarSpec<Syntax extends string, Value> {
32
+ readonly syntax: Syntax;
33
+ readonly initial: Value;
34
+ readonly role: CssVarRole;
35
+ readonly inherits: boolean;
36
+ }
37
+ export interface CssVarKind<Syntax extends string, Value> {
38
+ (initial: Value, options?: CssVarOptions): CssVarSpec<Syntax, Value>;
39
+ readonly syntax: Syntax;
40
+ /** Type-only inference site; nothing reads it at runtime. */
41
+ readonly __value?: Value;
42
+ }
43
+ export declare const kind: {
44
+ readonly color: CssVarKind<"<color>", ColorValue>;
45
+ readonly length: CssVarKind<"<length>", LengthValue>;
46
+ readonly percentage: CssVarKind<"<percentage>", PercentValue>;
47
+ readonly lengthPercentage: CssVarKind<"<length-percentage>", LengthPercentageValue>;
48
+ readonly number: CssVarKind<"<number>", NumberValue>;
49
+ readonly integer: CssVarKind<"<integer>", IntegerValue>;
50
+ readonly angle: CssVarKind<"<angle>", AngleValue>;
51
+ readonly time: CssVarKind<"<time>", TimeValue>;
52
+ readonly ident: CssVarKind<"<custom-ident>", IdentValue>;
53
+ readonly string: CssVarKind<"<string>", CssStringValue>;
54
+ readonly url: CssVarKind<"<url>", UrlValue>;
55
+ };
56
+ export type AnyKind = CssVarKind<string, any>;
57
+ export type ValueOf<Kind> = Kind extends CssVarKind<string, infer Value> ? Value : never;
58
+ export type SyntaxOf<Kind> = Kind extends CssVarKind<infer Syntax, any> ? Syntax : never;
59
+ /**
60
+ * `<a>+` — a space-separated list of at least one.
61
+ *
62
+ * The value type is a non-empty tuple rather than an array so that `many(kind.length)`
63
+ * cannot be satisfied by `[]`, which registers as an invalid value at runtime.
64
+ */
65
+ export declare const many: <Kind extends AnyKind>(of: Kind) => CssVarKind<`${SyntaxOf<Kind>}+`, readonly [ValueOf<Kind>, ...ValueOf<Kind>[]]>;
66
+ /** `<a>#` — a comma-separated list of at least one. */
67
+ export declare const csv: <Kind extends AnyKind>(of: Kind) => CssVarKind<`${SyntaxOf<Kind>}#`, readonly [ValueOf<Kind>, ...ValueOf<Kind>[]]>;
68
+ /**
69
+ * `a | b | c` — a closed keyword set, registered as such.
70
+ *
71
+ * The keywords are the *values*: `oneOf('auto', 'none')` accepts `'auto'` and
72
+ * nothing else. This is the one place a string literal is a legitimate value,
73
+ * because the grammar itself is a set of literals and the union is closed.
74
+ */
75
+ export declare const oneOf: <const Keywords extends readonly [string, ...string[]]>(...keywords: Keywords) => CssVarKind<string, Keywords[number]>;
76
+ /**
77
+ * Can a value of kind `From` be written into a variable of kind `To`?
78
+ *
79
+ * Read off the brands, so it cannot drift from what the values actually are.
80
+ */
81
+ export type Assignable<From extends AnyKind, To extends AnyKind> = [
82
+ ValueOf<From>
83
+ ] extends [ValueOf<To>] ? true : false;
84
+ //# sourceMappingURL=kinds.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kinds.d.ts","sourceRoot":"","sources":["../../../../../libs/style/src/lib/kinds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,cAAc,EACd,UAAU,EACV,YAAY,EACZ,qBAAqB,EACrB,WAAW,EACX,WAAW,EACX,YAAY,EACZ,SAAS,EACT,QAAQ,EACT,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,UAAU,GAAG,SAAS,CAAC;AAEnC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU,CAAC,MAAM,SAAS,MAAM,EAAE,KAAK;IACtD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU,CAAC,MAAM,SAAS,MAAM,EAAE,KAAK;IACtD,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC;CAC1B;AAmBD,eAAO,MAAM,IAAI;;;;;;;;;;;;CAcP,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE9C,MAAM,MAAM,OAAO,CAAC,IAAI,IACtB,IAAI,SAAS,UAAU,CAAC,MAAM,EAAE,MAAM,KAAK,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC;AAE/D,MAAM,MAAM,QAAQ,CAAC,IAAI,IACvB,IAAI,SAAS,UAAU,CAAC,MAAM,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC;AAE9D;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,IAAI,SAAS,OAAO,EACvC,IAAI,IAAI,KACP,UAAU,CACX,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EACpB,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CACT,CAAC;AAEtC,uDAAuD;AACvD,eAAO,MAAM,GAAG,GAAI,IAAI,SAAS,OAAO,EACtC,IAAI,IAAI,KACP,UAAU,CACX,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EACpB,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CACT,CAAC;AAEtC;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,GAAI,KAAK,CAAC,QAAQ,SAAS,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EACzE,GAAG,UAAU,QAAQ,KACpB,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAiC,CAAC;AAExE;;;;GAIG;AACH,MAAM,MAAM,UAAU,CAAC,IAAI,SAAS,OAAO,EAAE,EAAE,SAAS,OAAO,IAAI;IACjE,OAAO,CAAC,IAAI,CAAC;CACd,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,GACnB,IAAI,GACJ,KAAK,CAAC"}
@@ -0,0 +1,44 @@
1
+ const roleOf = (initial) => {
2
+ const role = initial?.role;
3
+ return role ?? 'none';
4
+ };
5
+ function kindOf(syntax) {
6
+ const build = (initial, options) => ({
7
+ syntax,
8
+ initial,
9
+ role: options?.role ?? roleOf(initial),
10
+ inherits: options?.inherits ?? false,
11
+ });
12
+ return Object.assign(build, { syntax });
13
+ }
14
+ export const kind = {
15
+ color: kindOf('<color>'),
16
+ length: kindOf('<length>'),
17
+ percentage: kindOf('<percentage>'),
18
+ lengthPercentage: kindOf('<length-percentage>'),
19
+ number: kindOf('<number>'),
20
+ integer: kindOf('<integer>'),
21
+ angle: kindOf('<angle>'),
22
+ time: kindOf('<time>'),
23
+ ident: kindOf('<custom-ident>'),
24
+ string: kindOf('<string>'),
25
+ url: kindOf('<url>'),
26
+ };
27
+ /**
28
+ * `<a>+` — a space-separated list of at least one.
29
+ *
30
+ * The value type is a non-empty tuple rather than an array so that `many(kind.length)`
31
+ * cannot be satisfied by `[]`, which registers as an invalid value at runtime.
32
+ */
33
+ export const many = (of) => kindOf(`${of.syntax}+`);
34
+ /** `<a>#` — a comma-separated list of at least one. */
35
+ export const csv = (of) => kindOf(`${of.syntax}#`);
36
+ /**
37
+ * `a | b | c` — a closed keyword set, registered as such.
38
+ *
39
+ * The keywords are the *values*: `oneOf('auto', 'none')` accepts `'auto'` and
40
+ * nothing else. This is the one place a string literal is a legitimate value,
41
+ * because the grammar itself is a set of literals and the union is closed.
42
+ */
43
+ export const oneOf = (...keywords) => kindOf(keywords.join(' | '));
44
+ //# sourceMappingURL=kinds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kinds.js","sourceRoot":"","sources":["../../../../../libs/style/src/lib/kinds.ts"],"names":[],"mappings":"AA4DA,MAAM,MAAM,GAAG,CAAC,OAAgB,EAAc,EAAE;IAC9C,MAAM,IAAI,GAAI,OAAiD,EAAE,IAAI,CAAC;IACtE,OAAO,IAAI,IAAI,MAAM,CAAC;AACxB,CAAC,CAAC;AAEF,SAAS,MAAM,CACb,MAAc;IAEd,MAAM,KAAK,GAAG,CAAC,OAAc,EAAE,OAAuB,EAAE,EAAE,CAAC,CAAC;QAC1D,MAAM;QACN,OAAO;QACP,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC;QACtC,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,KAAK;KACrC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,CAA8B,CAAC;AACvE,CAAC;AAED,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,KAAK,EAAE,MAAM,CAAwB,SAAS,CAAC;IAC/C,MAAM,EAAE,MAAM,CAA0B,UAAU,CAAC;IACnD,UAAU,EAAE,MAAM,CAA+B,cAAc,CAAC;IAChE,gBAAgB,EAAE,MAAM,CACtB,qBAAqB,CACtB;IACD,MAAM,EAAE,MAAM,CAA0B,UAAU,CAAC;IACnD,OAAO,EAAE,MAAM,CAA4B,WAAW,CAAC;IACvD,KAAK,EAAE,MAAM,CAAwB,SAAS,CAAC;IAC/C,IAAI,EAAE,MAAM,CAAsB,QAAQ,CAAC;IAC3C,KAAK,EAAE,MAAM,CAA+B,gBAAgB,CAAC;IAC7D,MAAM,EAAE,MAAM,CAA6B,UAAU,CAAC;IACtD,GAAG,EAAE,MAAM,CAAoB,OAAO,CAAC;CAC/B,CAAC;AAUX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,EAAQ,EAIR,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,GAAG,CAAU,CAAC;AAEtC,uDAAuD;AACvD,MAAM,CAAC,MAAM,GAAG,GAAG,CACjB,EAAQ,EAIR,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,GAAG,CAAU,CAAC;AAEtC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,GAAG,QAAkB,EACiB,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC","sourcesContent":["/**\n * Custom-property kinds, modelled after the `@property` grammar itself.\n *\n * A kind is not an invention: it is exactly what CSS knows how to register\n * (`<color>`, `<length>`, `<length-percentage>`, `+`, `#`, `|`). Inventing a\n * kind `@property` does not know would break the runtime half of the\n * guarantee — the browser would stop validating the value, and a variable\n * assigned a length where a colour was expected would simply paint nothing.\n *\n * A kind is **callable**: `kind.color(palette.text.strong)` builds the spec\n * `cssVars` wants, while `kind.color` on its own is the grammar that `many`,\n * `csv` and the axis `writes` constraint operate on. One name for one concept,\n * used in both positions.\n *\n * The assignability lattice is **not** a second table kept in sync with the\n * brands. It reads the brands: an integer carries the number brand, so\n * `<integer>` flows into `<number>`; `<length-percentage>` is a union, so\n * `<length>` flows into it and not the other way round. A table would be one\n * more thing that can silently disagree with reality.\n */\nimport type {\n AngleValue,\n ColorRole,\n ColorValue,\n CssStringValue,\n IdentValue,\n IntegerValue,\n LengthPercentageValue,\n LengthValue,\n NumberValue,\n PercentValue,\n TimeValue,\n UrlValue,\n} from './tokens/units.ts';\n\nexport type CssVarRole = ColorRole;\n\nexport interface CssVarOptions {\n readonly role?: CssVarRole;\n /**\n * `false` by default: it bounds invalidation when the variable is rewritten\n * at runtime instead of making the whole subtree recompute.\n */\n readonly inherits?: boolean;\n}\n\nexport interface CssVarSpec<Syntax extends string, Value> {\n readonly syntax: Syntax;\n readonly initial: Value;\n readonly role: CssVarRole;\n readonly inherits: boolean;\n}\n\nexport interface CssVarKind<Syntax extends string, Value> {\n (initial: Value, options?: CssVarOptions): CssVarSpec<Syntax, Value>;\n readonly syntax: Syntax;\n /** Type-only inference site; nothing reads it at runtime. */\n readonly __value?: Value;\n}\n\nconst roleOf = (initial: unknown): CssVarRole => {\n const role = (initial as { readonly role?: CssVarRole } | null)?.role;\n return role ?? 'none';\n};\n\nfunction kindOf<Syntax extends string, Value>(\n syntax: Syntax,\n): CssVarKind<Syntax, Value> {\n const build = (initial: Value, options?: CssVarOptions) => ({\n syntax,\n initial,\n role: options?.role ?? roleOf(initial),\n inherits: options?.inherits ?? false,\n });\n return Object.assign(build, { syntax }) as CssVarKind<Syntax, Value>;\n}\n\nexport const kind = {\n color: kindOf<'<color>', ColorValue>('<color>'),\n length: kindOf<'<length>', LengthValue>('<length>'),\n percentage: kindOf<'<percentage>', PercentValue>('<percentage>'),\n lengthPercentage: kindOf<'<length-percentage>', LengthPercentageValue>(\n '<length-percentage>',\n ),\n number: kindOf<'<number>', NumberValue>('<number>'),\n integer: kindOf<'<integer>', IntegerValue>('<integer>'),\n angle: kindOf<'<angle>', AngleValue>('<angle>'),\n time: kindOf<'<time>', TimeValue>('<time>'),\n ident: kindOf<'<custom-ident>', IdentValue>('<custom-ident>'),\n string: kindOf<'<string>', CssStringValue>('<string>'),\n url: kindOf<'<url>', UrlValue>('<url>'),\n} as const;\n\nexport type AnyKind = CssVarKind<string, any>;\n\nexport type ValueOf<Kind> =\n Kind extends CssVarKind<string, infer Value> ? Value : never;\n\nexport type SyntaxOf<Kind> =\n Kind extends CssVarKind<infer Syntax, any> ? Syntax : never;\n\n/**\n * `<a>+` — a space-separated list of at least one.\n *\n * The value type is a non-empty tuple rather than an array so that `many(kind.length)`\n * cannot be satisfied by `[]`, which registers as an invalid value at runtime.\n */\nexport const many = <Kind extends AnyKind>(\n of: Kind,\n): CssVarKind<\n `${SyntaxOf<Kind>}+`,\n readonly [ValueOf<Kind>, ...ValueOf<Kind>[]]\n> => kindOf(`${of.syntax}+`) as never;\n\n/** `<a>#` — a comma-separated list of at least one. */\nexport const csv = <Kind extends AnyKind>(\n of: Kind,\n): CssVarKind<\n `${SyntaxOf<Kind>}#`,\n readonly [ValueOf<Kind>, ...ValueOf<Kind>[]]\n> => kindOf(`${of.syntax}#`) as never;\n\n/**\n * `a | b | c` — a closed keyword set, registered as such.\n *\n * The keywords are the *values*: `oneOf('auto', 'none')` accepts `'auto'` and\n * nothing else. This is the one place a string literal is a legitimate value,\n * because the grammar itself is a set of literals and the union is closed.\n */\nexport const oneOf = <const Keywords extends readonly [string, ...string[]]>(\n ...keywords: Keywords\n): CssVarKind<string, Keywords[number]> => kindOf(keywords.join(' | '));\n\n/**\n * Can a value of kind `From` be written into a variable of kind `To`?\n *\n * Read off the brands, so it cannot drift from what the values actually are.\n */\nexport type Assignable<From extends AnyKind, To extends AnyKind> = [\n ValueOf<From>,\n] extends [ValueOf<To>]\n ? true\n : false;\n"]}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Les obligations de contexte : ce qu'une classe exige de ses ancêtres.
3
+ *
4
+ * Le cœur du dispositif tient en une ligne : **`provides(scrollPort.block)`
5
+ * retourne l'effet CSS et la décharge dans le même objet**. Comme `overflow`
6
+ * n'existe pas dans la table de propriétés, c'est l'unique chemin vers
7
+ * `overflow: auto`. Le mauvais correctif — poser un `overflow` au hasard sur le
8
+ * parent le plus proche — n'est pas découragé, il est inexprimable.
9
+ */
10
+ import type { CraftRequirement } from '@craft-ts/core';
11
+ import type { Declaration } from './props/factory.ts';
12
+ /**
13
+ * The payload the channel carries. An obligation and its discharge share the
14
+ * **same** type — that is what makes `Exclude` cancel them in the core.
15
+ *
16
+ * It is a `CraftRequirement`, so the id and the explanation travel with it and
17
+ * the sealing error can quote both. The core reads two opaque strings; every
18
+ * word of CSS meaning in them is written here.
19
+ */
20
+ export type Obligation<Id extends string, Explain extends string = string> = CraftRequirement<Id, Explain>;
21
+ export interface ObligationSpec<Id extends string, Explain extends string = string> {
22
+ readonly id: Id;
23
+ /** The CSS a provider must lay down, inseparable from the discharge. */
24
+ readonly effect: readonly Declaration[];
25
+ readonly explain: Explain;
26
+ }
27
+ export declare const scrollPort: {
28
+ readonly block: ObligationSpec<"scrollPort.block", "declare it on the layout component that owns the scrollable area. An overflow on the direct parent would create a second scroll port, and the sticky element would stick to the wrong container.">;
29
+ readonly inline: ObligationSpec<"scrollPort.inline", "declare it on the layout component that owns the scrollable area.">;
30
+ };
31
+ export declare const noClipping: {
32
+ readonly block: ObligationSpec<"noClipping.block", "no ancestor between this node and its container may clip the block axis.">;
33
+ readonly inline: ObligationSpec<"noClipping.inline", "no ancestor between this node and its container may clip the inline axis.">;
34
+ };
35
+ export declare const containerType: {
36
+ readonly inlineSize: ObligationSpec<"containerType.inlineSize", "declare it on the element whose inline size the container queries read.">;
37
+ readonly size: ObligationSpec<"containerType.size", "declare it on the element whose size the container queries read.">;
38
+ readonly scrollState: ObligationSpec<"containerType.scrollState", "declare it on the element whose scroll state must be queryable.">;
39
+ };
40
+ /**
41
+ * Ce qu'une classe **exige**. S'attache à la classe qui en dépend, pas à la
42
+ * feuille entière : c'est la classe précise qui porte la demande, sinon
43
+ * l'erreur désigne un fichier au lieu d'une règle.
44
+ */
45
+ export declare const requires: <const Id extends string, const Explain extends string>(spec: ObligationSpec<Id, Explain>) => {
46
+ readonly kind: "requires";
47
+ readonly spec: ObligationSpec<Id, Explain>;
48
+ };
49
+ /**
50
+ * Ce qu'un ancêtre **fournit**. Émet l'effet CSS ET la décharge. Il n'existe
51
+ * pas de constructeur littéral de décharge : on ne peut pas prétendre avoir
52
+ * fourni sans poser le CSS correspondant.
53
+ */
54
+ export declare const provides: <const Id extends string, const Explain extends string>(spec: ObligationSpec<Id, Explain>) => {
55
+ readonly kind: "provides";
56
+ readonly spec: ObligationSpec<Id, Explain>;
57
+ };
58
+ /**
59
+ * Rogne l'overflow — et **déclare le faire**. Une classe qui clippe traverse
60
+ * le canal `violates` : si une obligation `noClipping` reste ouverte sous elle,
61
+ * le chemin est en faute et le typage le dit.
62
+ */
63
+ export declare const clipOverflow: {
64
+ readonly block: {
65
+ readonly kind: "violates";
66
+ readonly spec: ObligationSpec<"noClipping.block", "this node clips the block axis.">;
67
+ };
68
+ readonly inline: {
69
+ readonly kind: "violates";
70
+ readonly spec: ObligationSpec<"noClipping.inline", "this node clips the inline axis.">;
71
+ };
72
+ };
73
+ /**
74
+ * Discharges an obligation **without** laying down the CSS — for the cases the
75
+ * model cannot see, such as a scroll port owned by a third-party shell.
76
+ *
77
+ * It is the marked escape hatch, not a loophole: `unproven` travels with it, so
78
+ * the graph counts it as debt. An escape hatch that did not bubble up would be
79
+ * a design bug, not a convenience.
80
+ */
81
+ export declare const unsafeAssume: <const Id extends string, const Explain extends string, Reason extends string>(spec: ObligationSpec<Id, Explain>, reason: Reason) => {
82
+ readonly kind: "provides";
83
+ readonly spec: {
84
+ readonly effect: readonly Declaration[];
85
+ readonly id: Id;
86
+ readonly explain: Explain;
87
+ };
88
+ readonly unproven: Reason;
89
+ };
90
+ /**
91
+ * Declares that a class *is* the thing an obligation asks for, without being
92
+ * the one that asks. Reserved for the layout primitives that own a region.
93
+ */
94
+ export declare const declares: <const Id extends string, const Explain extends string>(spec: ObligationSpec<Id, Explain>) => {
95
+ readonly kind: "provides";
96
+ readonly spec: ObligationSpec<Id, Explain>;
97
+ };
98
+ export type ObligationEntry = ReturnType<typeof requires> | ReturnType<typeof provides> | ReturnType<typeof unsafeAssume> | typeof clipOverflow.block | typeof clipOverflow.inline;
99
+ //# sourceMappingURL=obligations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obligations.d.ts","sourceRoot":"","sources":["../../../../../libs/style/src/lib/obligations.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,OAAO,SAAS,MAAM,GAAG,MAAM,IACvE,gBAAgB,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AAEhC,MAAM,WAAW,cAAc,CAC7B,EAAE,SAAS,MAAM,EACjB,OAAO,SAAS,MAAM,GAAG,MAAM;IAE/B,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAcD,eAAO,MAAM,UAAU;;;CAcb,CAAC;AAEX,eAAO,MAAM,UAAU;;;CAWb,CAAC;AAEX,eAAO,MAAM,aAAa;;;;CAgBhB,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,KAAK,CAAC,OAAO,SAAS,MAAM,EAC5E,MAAM,cAAc,CAAC,EAAE,EAAE,OAAO,CAAC;;;CACO,CAAC;AAE3C;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,KAAK,CAAC,OAAO,SAAS,MAAM,EAC5E,MAAM,cAAc,CAAC,EAAE,EAAE,OAAO,CAAC;;;CACO,CAAC;AAE3C;;;;GAIG;AACH,eAAO,MAAM,YAAY;;;;;;;;;CAiBf,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,GACvB,KAAK,CAAC,EAAE,SAAS,MAAM,EACvB,KAAK,CAAC,OAAO,SAAS,MAAM,EAC5B,MAAM,SAAS,MAAM,EAErB,MAAM,cAAc,CAAC,EAAE,EAAE,OAAO,CAAC,EACjC,QAAQ,MAAM;;;yBAImB,SAAS,WAAW,EAAE;;;;;CAE5C,CAAC;AAEd;;;GAGG;AACH,eAAO,MAAM,QAAQ,SAtDU,EAAE,SAAS,MAAM,QAAQ,OAAO,SAAS,MAAM,QACtE,cAAc,CAAC,EAAE,EAAE,OAAO,CAAC;;;CAqDH,CAAC;AAEjC,MAAM,MAAM,eAAe,GACvB,UAAU,CAAC,OAAO,QAAQ,CAAC,GAC3B,UAAU,CAAC,OAAO,QAAQ,CAAC,GAC3B,UAAU,CAAC,OAAO,YAAY,CAAC,GAC/B,OAAO,YAAY,CAAC,KAAK,GACzB,OAAO,YAAY,CAAC,MAAM,CAAC"}
@@ -0,0 +1,69 @@
1
+ const obligation = (id, effect, explain) => ({ id, effect, explain });
2
+ const d = (property, value) => ({
3
+ property,
4
+ value,
5
+ unproven: '',
6
+ });
7
+ export const scrollPort = {
8
+ block: obligation('scrollPort.block',
9
+ // Les deux déclarations partent ensemble. `min-block-size: 0` sans
10
+ // `overflow-block` ne sert à rien, et l'inverse produit un port qui ne
11
+ // rétrécit jamais — c'est précisément le bug que ce couplage évite.
12
+ [d('overflow-block', 'auto'), d('min-block-size', '0')], 'declare it on the layout component that owns the scrollable area. An overflow on the direct parent would create a second scroll port, and the sticky element would stick to the wrong container.'),
13
+ inline: obligation('scrollPort.inline', [d('overflow-inline', 'auto'), d('min-inline-size', '0')], 'declare it on the layout component that owns the scrollable area.'),
14
+ };
15
+ export const noClipping = {
16
+ block: obligation('noClipping.block', [d('overflow-block', 'visible')], 'no ancestor between this node and its container may clip the block axis.'),
17
+ inline: obligation('noClipping.inline', [d('overflow-inline', 'visible')], 'no ancestor between this node and its container may clip the inline axis.'),
18
+ };
19
+ export const containerType = {
20
+ inlineSize: obligation('containerType.inlineSize', [d('container-type', 'inline-size')], 'declare it on the element whose inline size the container queries read.'),
21
+ size: obligation('containerType.size', [d('container-type', 'size')], 'declare it on the element whose size the container queries read.'),
22
+ scrollState: obligation('containerType.scrollState', [d('container-type', 'scroll-state')], 'declare it on the element whose scroll state must be queryable.'),
23
+ };
24
+ /**
25
+ * Ce qu'une classe **exige**. S'attache à la classe qui en dépend, pas à la
26
+ * feuille entière : c'est la classe précise qui porte la demande, sinon
27
+ * l'erreur désigne un fichier au lieu d'une règle.
28
+ */
29
+ export const requires = (spec) => ({ kind: 'requires', spec });
30
+ /**
31
+ * Ce qu'un ancêtre **fournit**. Émet l'effet CSS ET la décharge. Il n'existe
32
+ * pas de constructeur littéral de décharge : on ne peut pas prétendre avoir
33
+ * fourni sans poser le CSS correspondant.
34
+ */
35
+ export const provides = (spec) => ({ kind: 'provides', spec });
36
+ /**
37
+ * Rogne l'overflow — et **déclare le faire**. Une classe qui clippe traverse
38
+ * le canal `violates` : si une obligation `noClipping` reste ouverte sous elle,
39
+ * le chemin est en faute et le typage le dit.
40
+ */
41
+ export const clipOverflow = {
42
+ block: {
43
+ kind: 'violates',
44
+ spec: obligation('noClipping.block', [d('overflow-block', 'clip')], 'this node clips the block axis.'),
45
+ },
46
+ inline: {
47
+ kind: 'violates',
48
+ spec: obligation('noClipping.inline', [d('overflow-inline', 'clip')], 'this node clips the inline axis.'),
49
+ },
50
+ };
51
+ /**
52
+ * Discharges an obligation **without** laying down the CSS — for the cases the
53
+ * model cannot see, such as a scroll port owned by a third-party shell.
54
+ *
55
+ * It is the marked escape hatch, not a loophole: `unproven` travels with it, so
56
+ * the graph counts it as debt. An escape hatch that did not bubble up would be
57
+ * a design bug, not a convenience.
58
+ */
59
+ export const unsafeAssume = (spec, reason) => ({
60
+ kind: 'provides',
61
+ spec: { ...spec, effect: [] },
62
+ unproven: reason,
63
+ });
64
+ /**
65
+ * Declares that a class *is* the thing an obligation asks for, without being
66
+ * the one that asks. Reserved for the layout primitives that own a region.
67
+ */
68
+ export const declares = provides;
69
+ //# sourceMappingURL=obligations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obligations.js","sourceRoot":"","sources":["../../../../../libs/style/src/lib/obligations.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Les obligations de contexte : ce qu'une classe exige de ses ancêtres.\n *\n * Le cœur du dispositif tient en une ligne : **`provides(scrollPort.block)`\n * retourne l'effet CSS et la décharge dans le même objet**. Comme `overflow`\n * n'existe pas dans la table de propriétés, c'est l'unique chemin vers\n * `overflow: auto`. Le mauvais correctif — poser un `overflow` au hasard sur le\n * parent le plus proche — n'est pas découragé, il est inexprimable.\n */\nimport type { CraftRequirement } from '@craft-ts/core';\nimport type { Declaration } from './props/factory.ts';\n\n/**\n * The payload the channel carries. An obligation and its discharge share the\n * **same** type — that is what makes `Exclude` cancel them in the core.\n *\n * It is a `CraftRequirement`, so the id and the explanation travel with it and\n * the sealing error can quote both. The core reads two opaque strings; every\n * word of CSS meaning in them is written here.\n */\nexport type Obligation<Id extends string, Explain extends string = string> =\n CraftRequirement<Id, Explain>;\n\nexport interface ObligationSpec<\n Id extends string,\n Explain extends string = string,\n> {\n readonly id: Id;\n /** The CSS a provider must lay down, inseparable from the discharge. */\n readonly effect: readonly Declaration[];\n readonly explain: Explain;\n}\n\nconst obligation = <const Id extends string, const Explain extends string>(\n id: Id,\n effect: readonly Declaration[],\n explain: Explain,\n): ObligationSpec<Id, Explain> => ({ id, effect, explain });\n\nconst d = (property: string, value: string): Declaration => ({\n property,\n value,\n unproven: '',\n});\n\nexport const scrollPort = {\n block: obligation(\n 'scrollPort.block',\n // Les deux déclarations partent ensemble. `min-block-size: 0` sans\n // `overflow-block` ne sert à rien, et l'inverse produit un port qui ne\n // rétrécit jamais — c'est précisément le bug que ce couplage évite.\n [d('overflow-block', 'auto'), d('min-block-size', '0')],\n 'declare it on the layout component that owns the scrollable area. An overflow on the direct parent would create a second scroll port, and the sticky element would stick to the wrong container.',\n ),\n inline: obligation(\n 'scrollPort.inline',\n [d('overflow-inline', 'auto'), d('min-inline-size', '0')],\n 'declare it on the layout component that owns the scrollable area.',\n ),\n} as const;\n\nexport const noClipping = {\n block: obligation(\n 'noClipping.block',\n [d('overflow-block', 'visible')],\n 'no ancestor between this node and its container may clip the block axis.',\n ),\n inline: obligation(\n 'noClipping.inline',\n [d('overflow-inline', 'visible')],\n 'no ancestor between this node and its container may clip the inline axis.',\n ),\n} as const;\n\nexport const containerType = {\n inlineSize: obligation(\n 'containerType.inlineSize',\n [d('container-type', 'inline-size')],\n 'declare it on the element whose inline size the container queries read.',\n ),\n size: obligation(\n 'containerType.size',\n [d('container-type', 'size')],\n 'declare it on the element whose size the container queries read.',\n ),\n scrollState: obligation(\n 'containerType.scrollState',\n [d('container-type', 'scroll-state')],\n 'declare it on the element whose scroll state must be queryable.',\n ),\n} as const;\n\n/**\n * Ce qu'une classe **exige**. S'attache à la classe qui en dépend, pas à la\n * feuille entière : c'est la classe précise qui porte la demande, sinon\n * l'erreur désigne un fichier au lieu d'une règle.\n */\nexport const requires = <const Id extends string, const Explain extends string>(\n spec: ObligationSpec<Id, Explain>,\n) => ({ kind: 'requires', spec }) as const;\n\n/**\n * Ce qu'un ancêtre **fournit**. Émet l'effet CSS ET la décharge. Il n'existe\n * pas de constructeur littéral de décharge : on ne peut pas prétendre avoir\n * fourni sans poser le CSS correspondant.\n */\nexport const provides = <const Id extends string, const Explain extends string>(\n spec: ObligationSpec<Id, Explain>,\n) => ({ kind: 'provides', spec }) as const;\n\n/**\n * Rogne l'overflow — et **déclare le faire**. Une classe qui clippe traverse\n * le canal `violates` : si une obligation `noClipping` reste ouverte sous elle,\n * le chemin est en faute et le typage le dit.\n */\nexport const clipOverflow = {\n block: {\n kind: 'violates',\n spec: obligation(\n 'noClipping.block',\n [d('overflow-block', 'clip')],\n 'this node clips the block axis.',\n ),\n },\n inline: {\n kind: 'violates',\n spec: obligation(\n 'noClipping.inline',\n [d('overflow-inline', 'clip')],\n 'this node clips the inline axis.',\n ),\n },\n} as const;\n\n/**\n * Discharges an obligation **without** laying down the CSS — for the cases the\n * model cannot see, such as a scroll port owned by a third-party shell.\n *\n * It is the marked escape hatch, not a loophole: `unproven` travels with it, so\n * the graph counts it as debt. An escape hatch that did not bubble up would be\n * a design bug, not a convenience.\n */\nexport const unsafeAssume = <\n const Id extends string,\n const Explain extends string,\n Reason extends string,\n>(\n spec: ObligationSpec<Id, Explain>,\n reason: Reason,\n) =>\n ({\n kind: 'provides',\n spec: { ...spec, effect: [] as readonly Declaration[] },\n unproven: reason,\n }) as const;\n\n/**\n * Declares that a class *is* the thing an obligation asks for, without being\n * the one that asks. Reserved for the layout primitives that own a region.\n */\nexport const declares = provides;\n\nexport type ObligationEntry =\n | ReturnType<typeof requires>\n | ReturnType<typeof provides>\n | ReturnType<typeof unsafeAssume>\n | typeof clipOverflow.block\n | typeof clipOverflow.inline;\n"]}