haus-tokens 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -129,6 +129,44 @@ It is **pure and does no file reading**, so it runs anywhere and this package
129
129
  gains no dependency on `node:fs`. You know which files you load; it only knows
130
130
  what the contract is.
131
131
 
132
+ ### The second check: values you already have
133
+
134
+ A property you declare that this package also declares, at the value this package
135
+ already gives, is not an override. It is a copy, and it renders perfectly until
136
+ one of the two moves.
137
+
138
+ ```ts
139
+ import { findRestatedTokens } from 'haus-tokens/guard'
140
+
141
+ it('restates no value haus already ships', () => {
142
+ const copies = findRestatedTokens({
143
+ defines: [read('src/tokens/semantics.css')],
144
+ upstream: [
145
+ read('node_modules/haus-tokens/dist/primitives.css'),
146
+ read('node_modules/haus-tokens/dist/motion.css'),
147
+ read('node_modules/haus-tokens/dist/semantics.css'),
148
+ ],
149
+ })
150
+
151
+ expect(copies.map((c) => `${c.name} (${c.kind})`)).toEqual([])
152
+ })
153
+ ```
154
+
155
+ Each result is tagged. `identical` is the same declaration text on both sides.
156
+ **`resolved` is the one worth having**: the text differs and the value does not,
157
+ once `var()` chains are followed. `--haus-z-modal: 400` against our
158
+ `var(--haus-z-400)`, where `--haus-z-400` is `400`, is how a consumer opts out of
159
+ a scale while still appearing to be on it.
160
+
161
+ **Which files you pass as `upstream` decides the question.** Include `brand.css`
162
+ and you are asking *do I restate anything haus ships, its colour choices
163
+ included*. Leave it out and you are asking *do I restate anything structural*,
164
+ with your palette treated as your business. Against drift the two answers are 143
165
+ and 89, and the 54 in the gap are exactly its brand.
166
+
167
+ Overriding a role is fine and several consumers should. Overriding it to our
168
+ value is the thing this reports.
169
+
132
170
  `alsoDefined` takes properties set outside CSS, a component doing
133
171
  `style={{ '--haus-avatar-bg': v }}` defines one that no stylesheet will show.
134
172
 
package/dist/brand.css CHANGED
@@ -8,19 +8,49 @@
8
8
  meant taking haus's palette, and two products declared their own tokens rather
9
9
  than do that.
10
10
 
11
- Every entry here is required. `BrandMap` in the package's TypeScript export is
12
- generated from this file, so a brand that omits a role or misnames one fails a
13
- consumer's build instead of rendering an unresolved var().
11
+ TWO TIERS, since haus#52. The base tier is required: every product has
12
+ surfaces, text, borders and one primary colour, and a brand that omits any of
13
+ them renders unstyled. The feedback tier is optional: info, success, warning
14
+ and error are the four semantics of a notification, and a product whose
15
+ statuses are not those four should not be made to invent them.
14
16
 
15
- The default brand applies at :root, so the common case needs no attribute. A
16
- named brand applies at [data-haus-theme="<name>"] and nests, because custom
17
- properties inherit. See brands/vault.css for a complete second brand.
17
+ The optional half needs no machinery, because the cascade already does it. The
18
+ default brand applies at :root and a named brand at [data-haus-theme="<name>"],
19
+ and custom properties inherit, so a brand declaring only the base tier inherits
20
+ these feedback entries from :root. That was true before it was named. What was
21
+ missing is that nothing said so, `BrandMap` demanded all 54, and brand.test.ts
22
+ failed a brand that supplied 28. The mechanism worked and the contract around
23
+ it did not.
24
+
25
+ `BrandMap` in the package's TypeScript export is generated from this file:
26
+ base entries required, feedback entries optional, so a brand omitting a base
27
+ role fails a consumer's build instead of rendering an unresolved var().
28
+
29
+ One rule holds the optional half honest, in brand.test.ts: a brand that
30
+ supplies any entry of a status ramp supplies all of that ramp. Half a ramp is
31
+ worse than none, because the half that is missing falls back to haus's hue and
32
+ the result is a two-coloured error state nothing reports.
33
+
34
+ A THIRD TIER, form, since haus#53. Colour is not the only thing that makes two
35
+ products look different. Measured across drift and vault, the things a consumer
36
+ actually re-decides are its palette, its typeface, its shadow ramp and its
37
+ corner radii, and nothing else: neither product re-decides the spacing rhythm
38
+ or the stacking order, and drift's apparent overrides of those were the literal
39
+ values of haus's own primitives, typed out. So form is radius and elevation,
40
+ optional like feedback, and all or nothing per group for the same reason.
41
+
42
+ See brands/vault.css for a complete second brand.
18
43
  ─────────────────────────────────────────────────────────────────────────── */
19
44
 
20
45
  @layer haus.brand {
21
46
 
22
47
  :root {
23
48
 
49
+ /* ══ BASE TIER, required ═══════════════════════════════════════════════
50
+ Twenty-eight entries. Every product has these, whatever it is for. A
51
+ brand must supply all of them.
52
+ ════════════════════════════════════════════════════════════════════ */
53
+
24
54
  /* ── Surfaces ────────────────────────────────────────────────────────── */
25
55
  --haus-brand-surface-default: var(--haus-damson-0);
26
56
  --haus-brand-surface-subtle: var(--haus-damson-100);
@@ -56,6 +86,19 @@
56
86
  --haus-brand-primary-on-subtle: var(--haus-aronia-700);
57
87
  --haus-brand-primary-disabled: var(--haus-damson-200);
58
88
 
89
+ /* ── Backdrop ────────────────────────────────────────────────────────── */
90
+ --haus-brand-backdrop: oklch(from var(--haus-damson-950) l c h / var(--haus-opacity-60));
91
+
92
+ /* ══ FEEDBACK TIER, optional ═══════════════════════════════════════════
93
+ Twenty-six entries across four ramps. These are the four semantics of a
94
+ notification, and not every product has them: core's statuses are the
95
+ states of a decision, proposed, accepted, rejected, superseded and
96
+ deprecated, which are five things that are not these four. A brand may
97
+ omit this tier and inherit it from here.
98
+
99
+ All or nothing PER RAMP. Supply every entry of `warning` or none of them.
100
+ ════════════════════════════════════════════════════════════════════ */
101
+
59
102
  /* ── Info ────────────────────────────────────────────────────────────── */
60
103
  --haus-brand-info-subtle: var(--haus-elderberry-100);
61
104
  --haus-brand-info-border: var(--haus-elderberry-200);
@@ -90,8 +133,55 @@
90
133
  --haus-brand-error-on-default: var(--haus-damson-0);
91
134
  --haus-brand-error-emphasis: var(--haus-cherry-900);
92
135
 
93
- /* ── Everything else ─────────────────────────────────────────────────── */
94
- --haus-brand-backdrop: oklch(from var(--haus-damson-950) l c h / var(--haus-opacity-60));
136
+ /* ══ FORM TIER, optional ═══════════════════════════════════════════════
137
+ Seven entries. What a product re-decides that is not a colour, taken
138
+ from what drift and vault actually changed rather than from what a brand
139
+ contract could theoretically cover.
140
+
141
+ drift sits one radius step tighter than haus at all three sizes and puts
142
+ elevation on its own four-step shadow ramp, which is two of the six names
143
+ it deliberately did not rename in the 1.0 migration, because pointing them
144
+ at haus's would have changed the product's face and its shadow ramp while
145
+ every test stayed green.
146
+
147
+ Not here, deliberately: z-index, opacity, border-width and the space
148
+ ladder. drift appeared to override twelve of those and every one resolved
149
+ to the value haus's own primitive already gives, so the override was
150
+ typing rather than a decision. Nobody re-decides the spacing rhythm.
151
+
152
+ All or nothing per group.
153
+ ════════════════════════════════════════════════════════════════════ */
154
+
155
+ /* ── Radius ──────────────────────────────────────────────────────────── */
156
+ --haus-brand-radius-control: var(--haus-radius-md); /* Button, Input, Select, Textarea */
157
+ --haus-brand-radius-surface: var(--haus-radius-lg); /* Card, Toast */
158
+ --haus-brand-radius-overlay: var(--haus-radius-xl); /* Modal */
159
+ --haus-brand-radius-marker: var(--haus-radius-sm); /* Checkbox, Modal/Toast icons */
160
+
161
+ /* radius-pill stays out of the brand: it is var(--haus-radius-full), which
162
+ is not a step on a scale but "as round as the box allows". A brand that
163
+ set it to something else would not have a rounder pill, it would have a
164
+ Badge that is no longer a pill. */
165
+
166
+ /* ── Elevation ───────────────────────────────────────────────────────── */
167
+ --haus-brand-elevation-raised: var(--haus-shadow-sm); /* Toggle knob */
168
+ --haus-brand-elevation-floating: var(--haus-shadow-lg); /* Card, Toast */
169
+ --haus-brand-elevation-overlay: var(--haus-shadow-xl); /* Modal */
170
+
171
+ /* ── Modal width ─────────────────────────────────────────────────────── */
172
+ /* Modal's three sizes were 400px, 560px and 720px written into
173
+ Modal.module.css, invisible to the hardcoded-value gate because it has no
174
+ rule for width at all, the same blind spot haus#43 found for icons.
175
+
176
+ A brand entry rather than a primitive, because two products disagree and
177
+ both are right: haus's are a web app's, and vault ships four narrower
178
+ steps for a dense desktop app, 360, 420, 480 and 600. A width is a
179
+ proportion of the product's own layout, which is what makes it brand
180
+ rather than scale. vault's fourth stays vault's: a contract cannot have an
181
+ optional member. */
182
+ --haus-brand-modal-width-sm: var(--haus-overlay-width-sm); /* 400px: confirm, short form */
183
+ --haus-brand-modal-width-md: var(--haus-overlay-width-md); /* 560px: the default */
184
+ --haus-brand-modal-width-lg: var(--haus-overlay-width-lg); /* 720px: code, tables, previews */
95
185
 
96
186
  }
97
187
  }
package/dist/guard.cjs CHANGED
@@ -27,8 +27,49 @@ function findFallbackTokens(input) {
27
27
  const defined = collect(input.defines, DECLARATION);
28
28
  return [...withFallback].filter((name) => !defined.has(name)).sort();
29
29
  }
30
+ function normalise(value) {
31
+ return value.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\s+/g, " ").trim();
32
+ }
33
+ function declarations(sources) {
34
+ const out = [];
35
+ for (const css of sources) {
36
+ for (const m of css.matchAll(/(?:^|[;{])\s*(--[a-zA-Z0-9-]+)\s*:\s*([^;}]+)/gm)) {
37
+ out.push({ name: m[1], value: normalise(m[2]) });
38
+ }
39
+ }
40
+ return out;
41
+ }
42
+ function resolve(value, table, depth = 0) {
43
+ if (depth > 10) return value;
44
+ const next = value.replace(/var\(\s*(--[a-zA-Z0-9-]+)\s*\)/g, (whole, name) => {
45
+ const found = table.get(name);
46
+ return found === void 0 ? whole : found;
47
+ });
48
+ return next === value ? value : resolve(next, table, depth + 1);
49
+ }
50
+ function findRestatedTokens(input) {
51
+ const table = /* @__PURE__ */ new Map();
52
+ for (const { name, value } of declarations(input.upstream)) {
53
+ if (!table.has(name)) table.set(name, value);
54
+ }
55
+ const seen = /* @__PURE__ */ new Set();
56
+ const found = [];
57
+ for (const { name, value } of declarations(input.defines)) {
58
+ const upstream = table.get(name);
59
+ if (upstream === void 0 || seen.has(name)) continue;
60
+ let kind;
61
+ if (value === upstream) kind = "identical";
62
+ else if (resolve(value, table) === resolve(upstream, table)) kind = "resolved";
63
+ if (kind) {
64
+ seen.add(name);
65
+ found.push({ name, kind, value, upstream });
66
+ }
67
+ }
68
+ return found.sort((a, b) => a.name.localeCompare(b.name));
69
+ }
30
70
 
31
71
  exports.findFallbackTokens = findFallbackTokens;
72
+ exports.findRestatedTokens = findRestatedTokens;
32
73
  exports.findUndefinedTokens = findUndefinedTokens;
33
74
  //# sourceMappingURL=guard.cjs.map
34
75
  //# sourceMappingURL=guard.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/guard.ts"],"names":[],"mappings":";;;AAuDA,IAAM,gBAAA,GAAmB,iCAAA;AACzB,IAAM,kBAAA,GAAqB,gCAAA;AAK3B,IAAM,WAAA,GAAc,sCAAA;AAuBpB,SAAS,OAAA,CAAQ,SAAmB,OAAA,EAA8B;AAChE,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAY;AAC9B,EAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AAGzB,IAAA,OAAA,CAAQ,SAAA,GAAY,CAAA;AACpB,IAAA,KAAA,MAAW,CAAA,IAAK,IAAI,QAAA,CAAS,OAAO,GAAG,KAAA,CAAM,GAAA,CAAI,CAAA,CAAE,CAAC,CAAE,CAAA;AAAA,EACxD;AACA,EAAA,OAAO,KAAA;AACT;AASO,SAAS,oBAAoB,KAAA,EAA0C;AAC5E,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,CAAM,KAAA,EAAO,gBAAgB,CAAA;AAClD,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,KAAA,CAAM,OAAA,EAAS,WAAW,CAAA;AAClD,EAAA,KAAA,MAAW,QAAQ,KAAA,CAAM,WAAA,IAAe,EAAC,EAAG,OAAA,CAAQ,IAAI,IAAI,CAAA;AAE5D,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,CAAC,GAAG,IAAI,EAAE,MAAA,CAAO,CAAC,IAAA,KAAS,CAAC,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAC,EAAE,IAAA,EAAK;AAAA,IAC7D,IAAA,EAAM,CAAC,GAAG,IAAI,EAAE,IAAA,EAAK;AAAA,IACrB,OAAA,EAAS,CAAC,GAAG,OAAO,EAAE,IAAA;AAAK,GAC7B;AACF;AAUO,SAAS,mBAAmB,KAAA,EAA6D;AAC9F,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,KAAA,CAAM,KAAA,EAAO,kBAAkB,CAAA;AAC5D,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,KAAA,CAAM,OAAA,EAAS,WAAW,CAAA;AAClD,EAAA,OAAO,CAAC,GAAG,YAAY,CAAA,CAAE,MAAA,CAAO,CAAC,IAAA,KAAS,CAAC,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAC,EAAE,IAAA,EAAK;AACrE","file":"guard.cjs","sourcesContent":["/**\n * The token guard: every custom property a stylesheet reads must be defined\n * somewhere the consumer actually loads.\n *\n * CSS fails silently here, which is what makes this worth shipping. `var(--x)`\n * for an undefined `--x` is invalid at computed-value time: the declaration is\n * dropped and the property inherits. No console warning, no build error,\n * nothing in review: a focus ring is simply absent, and a missing duration\n * looks like a design choice.\n *\n * drift wrote this check for itself and it caught five roles before they\n * reached a screen: `--color-ink-on-primary`, `--elevation-floating`,\n * `--motion-duration-emphasis`, `--radius-marker` and `--haus-focus-ring-error`.\n * The contract is defined in this package, so the check belongs here rather\n * than being rewritten by every consumer (haus#19). Shipping it is also the\n * point: a design system that can say *you have not loaded what my components\n * read* is a different thing from one that hopes you did.\n *\n * **Pure, and it does no file reading.** It takes CSS as strings, so it runs in\n * a Vitest suite, a Node script, a build step or a browser without this package\n * growing a dependency on `node:fs`. The consumer knows which files it loads;\n * this only knows what the contract is.\n *\n * @example\n * ```ts\n * import { readFileSync } from 'node:fs'\n * import { findUndefinedTokens } from 'haus-tokens/guard'\n *\n * const read = (p: string) => readFileSync(p, 'utf8')\n *\n * it('reads no role this app does not load', () => {\n * const { missing } = findUndefinedTokens({\n * reads: [read('node_modules/haus-components/dist/styles.css')],\n * defines: [\n * read('node_modules/haus-tokens/dist/primitives.css'),\n * read('node_modules/haus-tokens/dist/semantics.css'),\n * read('node_modules/haus-tokens/dist/motion.css'),\n * read('src/tokens/overrides.css'),\n * ],\n * })\n * expect(missing).toEqual([])\n * })\n * ```\n */\n\n/**\n * `var(--x)` with no fallback.\n *\n * A reference with a fallback, `var(--x, 0.2s)`, is a real value whether or\n * not the property is set, so it cannot fail at computed-value time and is\n * excluded. It is still usually a sign the name is wrong: a fallback that never\n * loses is a hardcoded value wearing a token's clothes. `findFallbackTokens`\n * below is for looking at those deliberately, rather than failing a build on\n * something that works.\n */\nconst READ_NO_FALLBACK = /var\\(\\s*(--[a-zA-Z0-9-]+)\\s*\\)/g\nconst READ_WITH_FALLBACK = /var\\(\\s*(--[a-zA-Z0-9-]+)\\s*,/g\n// `m` is load-bearing: without it `^` only matches the start of the whole\n// string, so every declaration on its own indented line after a newline is\n// missed and only the first in each block is seen. Caught by this package's\n// own guard test: semantics.css came back with 41 undefined roles.\nconst DECLARATION = /(?:^|[;{])\\s*(--[a-zA-Z0-9-]+)\\s*:/gm\n\nexport interface TokenGuardInput {\n /** The CSS doing the reading: the component stylesheet, your own modules. */\n reads: string[]\n /** The CSS doing the defining: the token layers you load, plus your own. */\n defines: string[]\n /**\n * Names defined outside CSS. A component that sets `style={{ '--x': v }}`\n * defines the property on the element, and no stylesheet will show it.\n */\n alsoDefined?: string[]\n}\n\nexport interface TokenGuardResult {\n /** Read with no fallback and defined nowhere. Sorted, so a diff is stable. */\n missing: string[]\n /** Every property read without a fallback. */\n read: string[]\n /** Every property declared across `defines` and `alsoDefined`. */\n defined: string[]\n}\n\nfunction collect(sources: string[], pattern: RegExp): Set<string> {\n const found = new Set<string>()\n for (const css of sources) {\n // A fresh lastIndex per source: a /g regex is stateful, and reusing one\n // across inputs silently skips the start of every source after the first.\n pattern.lastIndex = 0\n for (const m of css.matchAll(pattern)) found.add(m[1]!)\n }\n return found\n}\n\n/**\n * Which properties are read but never defined.\n *\n * An empty `missing` is the assertion. The other two fields are for a consumer\n * that wants to report rather than fail: `read.length` is also worth asserting\n * as a floor, because a wrong path makes every check pass by finding nothing.\n */\nexport function findUndefinedTokens(input: TokenGuardInput): TokenGuardResult {\n const read = collect(input.reads, READ_NO_FALLBACK)\n const defined = collect(input.defines, DECLARATION)\n for (const name of input.alsoDefined ?? []) defined.add(name)\n\n return {\n missing: [...read].filter((name) => !defined.has(name)).sort(),\n read: [...read].sort(),\n defined: [...defined].sort(),\n }\n}\n\n/**\n * Which properties are only ever read with a fallback.\n *\n * Not a failure, and deliberately a separate function so it cannot be mistaken\n * for one. A fallback that never loses is a hardcoded value wearing a token's\n * clothes, and the list is worth reading occasionally rather than failing a\n * build over.\n */\nexport function findFallbackTokens(input: Pick<TokenGuardInput, 'reads' | 'defines'>): string[] {\n const withFallback = collect(input.reads, READ_WITH_FALLBACK)\n const defined = collect(input.defines, DECLARATION)\n return [...withFallback].filter((name) => !defined.has(name)).sort()\n}\n"]}
1
+ {"version":3,"sources":["../src/guard.ts"],"names":[],"mappings":"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","file":"guard.cjs","sourcesContent":["/**\n * The token guard: every custom property a stylesheet reads must be defined\n * somewhere the consumer actually loads.\n *\n * CSS fails silently here, which is what makes this worth shipping. `var(--x)`\n * for an undefined `--x` is invalid at computed-value time: the declaration is\n * dropped and the property inherits. No console warning, no build error,\n * nothing in review: a focus ring is simply absent, and a missing duration\n * looks like a design choice.\n *\n * drift wrote this check for itself and it caught five roles before they\n * reached a screen: `--color-ink-on-primary`, `--elevation-floating`,\n * `--motion-duration-emphasis`, `--radius-marker` and `--haus-focus-ring-error`.\n * The contract is defined in this package, so the check belongs here rather\n * than being rewritten by every consumer (haus#19). Shipping it is also the\n * point: a design system that can say *you have not loaded what my components\n * read* is a different thing from one that hopes you did.\n *\n * **Pure, and it does no file reading.** It takes CSS as strings, so it runs in\n * a Vitest suite, a Node script, a build step or a browser without this package\n * growing a dependency on `node:fs`. The consumer knows which files it loads;\n * this only knows what the contract is.\n *\n * @example\n * ```ts\n * import { readFileSync } from 'node:fs'\n * import { findUndefinedTokens } from 'haus-tokens/guard'\n *\n * const read = (p: string) => readFileSync(p, 'utf8')\n *\n * it('reads no role this app does not load', () => {\n * const { missing } = findUndefinedTokens({\n * reads: [read('node_modules/haus-components/dist/styles.css')],\n * defines: [\n * read('node_modules/haus-tokens/dist/primitives.css'),\n * read('node_modules/haus-tokens/dist/semantics.css'),\n * read('node_modules/haus-tokens/dist/motion.css'),\n * read('src/tokens/overrides.css'),\n * ],\n * })\n * expect(missing).toEqual([])\n * })\n * ```\n */\n\n/**\n * `var(--x)` with no fallback.\n *\n * A reference with a fallback, `var(--x, 0.2s)`, is a real value whether or\n * not the property is set, so it cannot fail at computed-value time and is\n * excluded. It is still usually a sign the name is wrong: a fallback that never\n * loses is a hardcoded value wearing a token's clothes. `findFallbackTokens`\n * below is for looking at those deliberately, rather than failing a build on\n * something that works.\n */\nconst READ_NO_FALLBACK = /var\\(\\s*(--[a-zA-Z0-9-]+)\\s*\\)/g\nconst READ_WITH_FALLBACK = /var\\(\\s*(--[a-zA-Z0-9-]+)\\s*,/g\n// `m` is load-bearing: without it `^` only matches the start of the whole\n// string, so every declaration on its own indented line after a newline is\n// missed and only the first in each block is seen. Caught by this package's\n// own guard test: semantics.css came back with 41 undefined roles.\nconst DECLARATION = /(?:^|[;{])\\s*(--[a-zA-Z0-9-]+)\\s*:/gm\n\nexport interface TokenGuardInput {\n /** The CSS doing the reading: the component stylesheet, your own modules. */\n reads: string[]\n /** The CSS doing the defining: the token layers you load, plus your own. */\n defines: string[]\n /**\n * Names defined outside CSS. A component that sets `style={{ '--x': v }}`\n * defines the property on the element, and no stylesheet will show it.\n */\n alsoDefined?: string[]\n}\n\nexport interface TokenGuardResult {\n /** Read with no fallback and defined nowhere. Sorted, so a diff is stable. */\n missing: string[]\n /** Every property read without a fallback. */\n read: string[]\n /** Every property declared across `defines` and `alsoDefined`. */\n defined: string[]\n}\n\nfunction collect(sources: string[], pattern: RegExp): Set<string> {\n const found = new Set<string>()\n for (const css of sources) {\n // A fresh lastIndex per source: a /g regex is stateful, and reusing one\n // across inputs silently skips the start of every source after the first.\n pattern.lastIndex = 0\n for (const m of css.matchAll(pattern)) found.add(m[1]!)\n }\n return found\n}\n\n/**\n * Which properties are read but never defined.\n *\n * An empty `missing` is the assertion. The other two fields are for a consumer\n * that wants to report rather than fail: `read.length` is also worth asserting\n * as a floor, because a wrong path makes every check pass by finding nothing.\n */\nexport function findUndefinedTokens(input: TokenGuardInput): TokenGuardResult {\n const read = collect(input.reads, READ_NO_FALLBACK)\n const defined = collect(input.defines, DECLARATION)\n for (const name of input.alsoDefined ?? []) defined.add(name)\n\n return {\n missing: [...read].filter((name) => !defined.has(name)).sort(),\n read: [...read].sort(),\n defined: [...defined].sort(),\n }\n}\n\n/**\n * Which properties are only ever read with a fallback.\n *\n * Not a failure, and deliberately a separate function so it cannot be mistaken\n * for one. A fallback that never loses is a hardcoded value wearing a token's\n * clothes, and the list is worth reading occasionally rather than failing a\n * build over.\n */\nexport function findFallbackTokens(input: Pick<TokenGuardInput, 'reads' | 'defines'>): string[] {\n const withFallback = collect(input.reads, READ_WITH_FALLBACK)\n const defined = collect(input.defines, DECLARATION)\n return [...withFallback].filter((name) => !defined.has(name)).sort()\n}\n\n/* ─── Restatement: a consumer keeping its own copy of a value we ship ────────\n *\n * The second failure this package can see and a consumer cannot. An unresolved\n * var() at least renders wrong; a restated value renders perfectly, and is only\n * wrong from the moment one of the two sides moves.\n *\n * vault carried 141 of them and closed it as `vault#25`, then wrote this rule by\n * hand so it could not come back. drift has 89 and never had the rule: it was\n * written in the repository next door and never ported, which is why it ships\n * from here now (haus#53).\n *\n * TWO KINDS, and the second is the one a hand-written version missed.\n *\n * identical the declaration is the same text on both sides.\n * `--haus-space-inset-md: var(--haus-space-4)` written twice.\n * 77 of drift's.\n *\n * resolved the text differs and the value does not. `--haus-z-modal: 400`\n * against this package's `var(--haus-z-400)`, where `--haus-z-400`\n * is `400`. 12 of drift's, and vault's hand-written rule compares\n * declaration text so it would have found none of them.\n *\n * The second kind is worth the resolver: hardcoding the number a token resolves\n * to is how a consumer opts out of a scale while appearing to be on it.\n */\n\n/** One `--x: value` declaration, in source order. */\ntype Declaration = { name: string; value: string }\n\n/** Comments out, whitespace flattened, so two spellings of one value compare equal. */\nfunction normalise(value: string): string {\n return value\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\nfunction declarations(sources: string[]): Declaration[] {\n const out: Declaration[] = []\n for (const css of sources) {\n for (const m of css.matchAll(/(?:^|[;{])\\s*(--[a-zA-Z0-9-]+)\\s*:\\s*([^;}]+)/gm)) {\n out.push({ name: m[1]!, value: normalise(m[2]!) })\n }\n }\n return out\n}\n\n/**\n * Follow `var()` references until nothing is left to follow.\n *\n * Depth-limited rather than cycle-tracked: a token graph is shallow, and a\n * limit is one line where a visited-set is five. Hitting the limit returns the\n * partially resolved value, which compares unequal and so reports nothing,\n * because a guard that guesses is worse than one that misses.\n */\nfunction resolve(value: string, table: Map<string, string>, depth = 0): string {\n if (depth > 10) return value\n const next = value.replace(/var\\(\\s*(--[a-zA-Z0-9-]+)\\s*\\)/g, (whole, name: string) => {\n const found = table.get(name)\n return found === undefined ? whole : found\n })\n return next === value ? value : resolve(next, table, depth + 1)\n}\n\nexport interface Restatement {\n /** The custom property the consumer declares. */\n name: string\n /** `identical` if the declaration matches ours as text, `resolved` if only the value does. */\n kind: 'identical' | 'resolved'\n /** What the consumer wrote. */\n value: string\n /** What this package already says, as written. */\n upstream: string\n}\n\nexport interface RestatementInput {\n /** The consumer's own token CSS: the file where it overrides or adds. */\n defines: string[]\n /** This package's layers, as the consumer actually loads them. */\n upstream: string[]\n}\n\n/**\n * Which of a consumer's declarations this package already ships.\n *\n * An empty array is the assertion. A consumer may override any role it likes,\n * and several should: what it may not do is override a role to the value the\n * package already gives, because that is not an override, it is a copy, and a\n * copy is correct only until one side moves.\n *\n * Read the package from `node_modules` rather than a fixture. The point is to\n * compare against the value that will actually load.\n *\n * WHICH FILES TO PASS AS `upstream`, because it changes the question asked.\n *\n * Include `brand.css` and the answer is *does this consumer restate anything we\n * ship, including our brand's choices*. Leave it out and the answer is *does it\n * restate anything structural*, with its own colour choices treated as its\n * business.\n *\n * Measured against drift, whose colour overrides are a brand written as role\n * overrides: **143 with `brand.css`, 89 without.** The 54 in the gap are exactly\n * its brand. So a consumer that has a brand file, or intends one, leaves\n * `brand.css` out and gets only the copies; a consumer with no brand of its own\n * puts it in and is told that its colour overrides agree with ours, which is a\n * different and also useful thing to know.\n *\n * @example\n * ```ts\n * import { findRestatedTokens } from 'haus-tokens/guard'\n *\n * it('restates no value haus already ships', () => {\n * const copies = findRestatedTokens({\n * defines: [read('src/tokens/semantics.css')],\n * upstream: HAUS_FILES.map(read),\n * })\n * expect(copies.map((c) => `${c.name} (${c.kind})`)).toEqual([])\n * })\n * ```\n */\nexport function findRestatedTokens(input: RestatementInput): Restatement[] {\n const table = new Map<string, string>()\n for (const { name, value } of declarations(input.upstream)) {\n // First declaration wins, matching the cascade order the consumer loads in.\n if (!table.has(name)) table.set(name, value)\n }\n\n const seen = new Set<string>()\n const found: Restatement[] = []\n for (const { name, value } of declarations(input.defines)) {\n const upstream = table.get(name)\n if (upstream === undefined || seen.has(name)) continue\n\n let kind: Restatement['kind'] | undefined\n if (value === upstream) kind = 'identical'\n else if (resolve(value, table) === resolve(upstream, table)) kind = 'resolved'\n\n if (kind) {\n seen.add(name)\n found.push({ name, kind, value, upstream })\n }\n }\n return found.sort((a, b) => a.name.localeCompare(b.name))\n}\n"]}
package/dist/guard.d.cts CHANGED
@@ -78,5 +78,60 @@ declare function findUndefinedTokens(input: TokenGuardInput): TokenGuardResult;
78
78
  * build over.
79
79
  */
80
80
  declare function findFallbackTokens(input: Pick<TokenGuardInput, 'reads' | 'defines'>): string[];
81
+ interface Restatement {
82
+ /** The custom property the consumer declares. */
83
+ name: string;
84
+ /** `identical` if the declaration matches ours as text, `resolved` if only the value does. */
85
+ kind: 'identical' | 'resolved';
86
+ /** What the consumer wrote. */
87
+ value: string;
88
+ /** What this package already says, as written. */
89
+ upstream: string;
90
+ }
91
+ interface RestatementInput {
92
+ /** The consumer's own token CSS: the file where it overrides or adds. */
93
+ defines: string[];
94
+ /** This package's layers, as the consumer actually loads them. */
95
+ upstream: string[];
96
+ }
97
+ /**
98
+ * Which of a consumer's declarations this package already ships.
99
+ *
100
+ * An empty array is the assertion. A consumer may override any role it likes,
101
+ * and several should: what it may not do is override a role to the value the
102
+ * package already gives, because that is not an override, it is a copy, and a
103
+ * copy is correct only until one side moves.
104
+ *
105
+ * Read the package from `node_modules` rather than a fixture. The point is to
106
+ * compare against the value that will actually load.
107
+ *
108
+ * WHICH FILES TO PASS AS `upstream`, because it changes the question asked.
109
+ *
110
+ * Include `brand.css` and the answer is *does this consumer restate anything we
111
+ * ship, including our brand's choices*. Leave it out and the answer is *does it
112
+ * restate anything structural*, with its own colour choices treated as its
113
+ * business.
114
+ *
115
+ * Measured against drift, whose colour overrides are a brand written as role
116
+ * overrides: **143 with `brand.css`, 89 without.** The 54 in the gap are exactly
117
+ * its brand. So a consumer that has a brand file, or intends one, leaves
118
+ * `brand.css` out and gets only the copies; a consumer with no brand of its own
119
+ * puts it in and is told that its colour overrides agree with ours, which is a
120
+ * different and also useful thing to know.
121
+ *
122
+ * @example
123
+ * ```ts
124
+ * import { findRestatedTokens } from 'haus-tokens/guard'
125
+ *
126
+ * it('restates no value haus already ships', () => {
127
+ * const copies = findRestatedTokens({
128
+ * defines: [read('src/tokens/semantics.css')],
129
+ * upstream: HAUS_FILES.map(read),
130
+ * })
131
+ * expect(copies.map((c) => `${c.name} (${c.kind})`)).toEqual([])
132
+ * })
133
+ * ```
134
+ */
135
+ declare function findRestatedTokens(input: RestatementInput): Restatement[];
81
136
 
82
- export { type TokenGuardInput, type TokenGuardResult, findFallbackTokens, findUndefinedTokens };
137
+ export { type Restatement, type RestatementInput, type TokenGuardInput, type TokenGuardResult, findFallbackTokens, findRestatedTokens, findUndefinedTokens };
package/dist/guard.d.ts CHANGED
@@ -78,5 +78,60 @@ declare function findUndefinedTokens(input: TokenGuardInput): TokenGuardResult;
78
78
  * build over.
79
79
  */
80
80
  declare function findFallbackTokens(input: Pick<TokenGuardInput, 'reads' | 'defines'>): string[];
81
+ interface Restatement {
82
+ /** The custom property the consumer declares. */
83
+ name: string;
84
+ /** `identical` if the declaration matches ours as text, `resolved` if only the value does. */
85
+ kind: 'identical' | 'resolved';
86
+ /** What the consumer wrote. */
87
+ value: string;
88
+ /** What this package already says, as written. */
89
+ upstream: string;
90
+ }
91
+ interface RestatementInput {
92
+ /** The consumer's own token CSS: the file where it overrides or adds. */
93
+ defines: string[];
94
+ /** This package's layers, as the consumer actually loads them. */
95
+ upstream: string[];
96
+ }
97
+ /**
98
+ * Which of a consumer's declarations this package already ships.
99
+ *
100
+ * An empty array is the assertion. A consumer may override any role it likes,
101
+ * and several should: what it may not do is override a role to the value the
102
+ * package already gives, because that is not an override, it is a copy, and a
103
+ * copy is correct only until one side moves.
104
+ *
105
+ * Read the package from `node_modules` rather than a fixture. The point is to
106
+ * compare against the value that will actually load.
107
+ *
108
+ * WHICH FILES TO PASS AS `upstream`, because it changes the question asked.
109
+ *
110
+ * Include `brand.css` and the answer is *does this consumer restate anything we
111
+ * ship, including our brand's choices*. Leave it out and the answer is *does it
112
+ * restate anything structural*, with its own colour choices treated as its
113
+ * business.
114
+ *
115
+ * Measured against drift, whose colour overrides are a brand written as role
116
+ * overrides: **143 with `brand.css`, 89 without.** The 54 in the gap are exactly
117
+ * its brand. So a consumer that has a brand file, or intends one, leaves
118
+ * `brand.css` out and gets only the copies; a consumer with no brand of its own
119
+ * puts it in and is told that its colour overrides agree with ours, which is a
120
+ * different and also useful thing to know.
121
+ *
122
+ * @example
123
+ * ```ts
124
+ * import { findRestatedTokens } from 'haus-tokens/guard'
125
+ *
126
+ * it('restates no value haus already ships', () => {
127
+ * const copies = findRestatedTokens({
128
+ * defines: [read('src/tokens/semantics.css')],
129
+ * upstream: HAUS_FILES.map(read),
130
+ * })
131
+ * expect(copies.map((c) => `${c.name} (${c.kind})`)).toEqual([])
132
+ * })
133
+ * ```
134
+ */
135
+ declare function findRestatedTokens(input: RestatementInput): Restatement[];
81
136
 
82
- export { type TokenGuardInput, type TokenGuardResult, findFallbackTokens, findUndefinedTokens };
137
+ export { type Restatement, type RestatementInput, type TokenGuardInput, type TokenGuardResult, findFallbackTokens, findRestatedTokens, findUndefinedTokens };
package/dist/guard.js CHANGED
@@ -25,7 +25,47 @@ function findFallbackTokens(input) {
25
25
  const defined = collect(input.defines, DECLARATION);
26
26
  return [...withFallback].filter((name) => !defined.has(name)).sort();
27
27
  }
28
+ function normalise(value) {
29
+ return value.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\s+/g, " ").trim();
30
+ }
31
+ function declarations(sources) {
32
+ const out = [];
33
+ for (const css of sources) {
34
+ for (const m of css.matchAll(/(?:^|[;{])\s*(--[a-zA-Z0-9-]+)\s*:\s*([^;}]+)/gm)) {
35
+ out.push({ name: m[1], value: normalise(m[2]) });
36
+ }
37
+ }
38
+ return out;
39
+ }
40
+ function resolve(value, table, depth = 0) {
41
+ if (depth > 10) return value;
42
+ const next = value.replace(/var\(\s*(--[a-zA-Z0-9-]+)\s*\)/g, (whole, name) => {
43
+ const found = table.get(name);
44
+ return found === void 0 ? whole : found;
45
+ });
46
+ return next === value ? value : resolve(next, table, depth + 1);
47
+ }
48
+ function findRestatedTokens(input) {
49
+ const table = /* @__PURE__ */ new Map();
50
+ for (const { name, value } of declarations(input.upstream)) {
51
+ if (!table.has(name)) table.set(name, value);
52
+ }
53
+ const seen = /* @__PURE__ */ new Set();
54
+ const found = [];
55
+ for (const { name, value } of declarations(input.defines)) {
56
+ const upstream = table.get(name);
57
+ if (upstream === void 0 || seen.has(name)) continue;
58
+ let kind;
59
+ if (value === upstream) kind = "identical";
60
+ else if (resolve(value, table) === resolve(upstream, table)) kind = "resolved";
61
+ if (kind) {
62
+ seen.add(name);
63
+ found.push({ name, kind, value, upstream });
64
+ }
65
+ }
66
+ return found.sort((a, b) => a.name.localeCompare(b.name));
67
+ }
28
68
 
29
- export { findFallbackTokens, findUndefinedTokens };
69
+ export { findFallbackTokens, findRestatedTokens, findUndefinedTokens };
30
70
  //# sourceMappingURL=guard.js.map
31
71
  //# sourceMappingURL=guard.js.map
package/dist/guard.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/guard.ts"],"names":[],"mappings":";AAuDA,IAAM,gBAAA,GAAmB,iCAAA;AACzB,IAAM,kBAAA,GAAqB,gCAAA;AAK3B,IAAM,WAAA,GAAc,sCAAA;AAuBpB,SAAS,OAAA,CAAQ,SAAmB,OAAA,EAA8B;AAChE,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAY;AAC9B,EAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AAGzB,IAAA,OAAA,CAAQ,SAAA,GAAY,CAAA;AACpB,IAAA,KAAA,MAAW,CAAA,IAAK,IAAI,QAAA,CAAS,OAAO,GAAG,KAAA,CAAM,GAAA,CAAI,CAAA,CAAE,CAAC,CAAE,CAAA;AAAA,EACxD;AACA,EAAA,OAAO,KAAA;AACT;AASO,SAAS,oBAAoB,KAAA,EAA0C;AAC5E,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,CAAM,KAAA,EAAO,gBAAgB,CAAA;AAClD,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,KAAA,CAAM,OAAA,EAAS,WAAW,CAAA;AAClD,EAAA,KAAA,MAAW,QAAQ,KAAA,CAAM,WAAA,IAAe,EAAC,EAAG,OAAA,CAAQ,IAAI,IAAI,CAAA;AAE5D,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,CAAC,GAAG,IAAI,EAAE,MAAA,CAAO,CAAC,IAAA,KAAS,CAAC,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAC,EAAE,IAAA,EAAK;AAAA,IAC7D,IAAA,EAAM,CAAC,GAAG,IAAI,EAAE,IAAA,EAAK;AAAA,IACrB,OAAA,EAAS,CAAC,GAAG,OAAO,EAAE,IAAA;AAAK,GAC7B;AACF;AAUO,SAAS,mBAAmB,KAAA,EAA6D;AAC9F,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,KAAA,CAAM,KAAA,EAAO,kBAAkB,CAAA;AAC5D,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,KAAA,CAAM,OAAA,EAAS,WAAW,CAAA;AAClD,EAAA,OAAO,CAAC,GAAG,YAAY,CAAA,CAAE,MAAA,CAAO,CAAC,IAAA,KAAS,CAAC,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAC,EAAE,IAAA,EAAK;AACrE","file":"guard.js","sourcesContent":["/**\n * The token guard: every custom property a stylesheet reads must be defined\n * somewhere the consumer actually loads.\n *\n * CSS fails silently here, which is what makes this worth shipping. `var(--x)`\n * for an undefined `--x` is invalid at computed-value time: the declaration is\n * dropped and the property inherits. No console warning, no build error,\n * nothing in review: a focus ring is simply absent, and a missing duration\n * looks like a design choice.\n *\n * drift wrote this check for itself and it caught five roles before they\n * reached a screen: `--color-ink-on-primary`, `--elevation-floating`,\n * `--motion-duration-emphasis`, `--radius-marker` and `--haus-focus-ring-error`.\n * The contract is defined in this package, so the check belongs here rather\n * than being rewritten by every consumer (haus#19). Shipping it is also the\n * point: a design system that can say *you have not loaded what my components\n * read* is a different thing from one that hopes you did.\n *\n * **Pure, and it does no file reading.** It takes CSS as strings, so it runs in\n * a Vitest suite, a Node script, a build step or a browser without this package\n * growing a dependency on `node:fs`. The consumer knows which files it loads;\n * this only knows what the contract is.\n *\n * @example\n * ```ts\n * import { readFileSync } from 'node:fs'\n * import { findUndefinedTokens } from 'haus-tokens/guard'\n *\n * const read = (p: string) => readFileSync(p, 'utf8')\n *\n * it('reads no role this app does not load', () => {\n * const { missing } = findUndefinedTokens({\n * reads: [read('node_modules/haus-components/dist/styles.css')],\n * defines: [\n * read('node_modules/haus-tokens/dist/primitives.css'),\n * read('node_modules/haus-tokens/dist/semantics.css'),\n * read('node_modules/haus-tokens/dist/motion.css'),\n * read('src/tokens/overrides.css'),\n * ],\n * })\n * expect(missing).toEqual([])\n * })\n * ```\n */\n\n/**\n * `var(--x)` with no fallback.\n *\n * A reference with a fallback, `var(--x, 0.2s)`, is a real value whether or\n * not the property is set, so it cannot fail at computed-value time and is\n * excluded. It is still usually a sign the name is wrong: a fallback that never\n * loses is a hardcoded value wearing a token's clothes. `findFallbackTokens`\n * below is for looking at those deliberately, rather than failing a build on\n * something that works.\n */\nconst READ_NO_FALLBACK = /var\\(\\s*(--[a-zA-Z0-9-]+)\\s*\\)/g\nconst READ_WITH_FALLBACK = /var\\(\\s*(--[a-zA-Z0-9-]+)\\s*,/g\n// `m` is load-bearing: without it `^` only matches the start of the whole\n// string, so every declaration on its own indented line after a newline is\n// missed and only the first in each block is seen. Caught by this package's\n// own guard test: semantics.css came back with 41 undefined roles.\nconst DECLARATION = /(?:^|[;{])\\s*(--[a-zA-Z0-9-]+)\\s*:/gm\n\nexport interface TokenGuardInput {\n /** The CSS doing the reading: the component stylesheet, your own modules. */\n reads: string[]\n /** The CSS doing the defining: the token layers you load, plus your own. */\n defines: string[]\n /**\n * Names defined outside CSS. A component that sets `style={{ '--x': v }}`\n * defines the property on the element, and no stylesheet will show it.\n */\n alsoDefined?: string[]\n}\n\nexport interface TokenGuardResult {\n /** Read with no fallback and defined nowhere. Sorted, so a diff is stable. */\n missing: string[]\n /** Every property read without a fallback. */\n read: string[]\n /** Every property declared across `defines` and `alsoDefined`. */\n defined: string[]\n}\n\nfunction collect(sources: string[], pattern: RegExp): Set<string> {\n const found = new Set<string>()\n for (const css of sources) {\n // A fresh lastIndex per source: a /g regex is stateful, and reusing one\n // across inputs silently skips the start of every source after the first.\n pattern.lastIndex = 0\n for (const m of css.matchAll(pattern)) found.add(m[1]!)\n }\n return found\n}\n\n/**\n * Which properties are read but never defined.\n *\n * An empty `missing` is the assertion. The other two fields are for a consumer\n * that wants to report rather than fail: `read.length` is also worth asserting\n * as a floor, because a wrong path makes every check pass by finding nothing.\n */\nexport function findUndefinedTokens(input: TokenGuardInput): TokenGuardResult {\n const read = collect(input.reads, READ_NO_FALLBACK)\n const defined = collect(input.defines, DECLARATION)\n for (const name of input.alsoDefined ?? []) defined.add(name)\n\n return {\n missing: [...read].filter((name) => !defined.has(name)).sort(),\n read: [...read].sort(),\n defined: [...defined].sort(),\n }\n}\n\n/**\n * Which properties are only ever read with a fallback.\n *\n * Not a failure, and deliberately a separate function so it cannot be mistaken\n * for one. A fallback that never loses is a hardcoded value wearing a token's\n * clothes, and the list is worth reading occasionally rather than failing a\n * build over.\n */\nexport function findFallbackTokens(input: Pick<TokenGuardInput, 'reads' | 'defines'>): string[] {\n const withFallback = collect(input.reads, READ_WITH_FALLBACK)\n const defined = collect(input.defines, DECLARATION)\n return [...withFallback].filter((name) => !defined.has(name)).sort()\n}\n"]}
1
+ {"version":3,"sources":["../src/guard.ts"],"names":[],"mappings":"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","file":"guard.js","sourcesContent":["/**\n * The token guard: every custom property a stylesheet reads must be defined\n * somewhere the consumer actually loads.\n *\n * CSS fails silently here, which is what makes this worth shipping. `var(--x)`\n * for an undefined `--x` is invalid at computed-value time: the declaration is\n * dropped and the property inherits. No console warning, no build error,\n * nothing in review: a focus ring is simply absent, and a missing duration\n * looks like a design choice.\n *\n * drift wrote this check for itself and it caught five roles before they\n * reached a screen: `--color-ink-on-primary`, `--elevation-floating`,\n * `--motion-duration-emphasis`, `--radius-marker` and `--haus-focus-ring-error`.\n * The contract is defined in this package, so the check belongs here rather\n * than being rewritten by every consumer (haus#19). Shipping it is also the\n * point: a design system that can say *you have not loaded what my components\n * read* is a different thing from one that hopes you did.\n *\n * **Pure, and it does no file reading.** It takes CSS as strings, so it runs in\n * a Vitest suite, a Node script, a build step or a browser without this package\n * growing a dependency on `node:fs`. The consumer knows which files it loads;\n * this only knows what the contract is.\n *\n * @example\n * ```ts\n * import { readFileSync } from 'node:fs'\n * import { findUndefinedTokens } from 'haus-tokens/guard'\n *\n * const read = (p: string) => readFileSync(p, 'utf8')\n *\n * it('reads no role this app does not load', () => {\n * const { missing } = findUndefinedTokens({\n * reads: [read('node_modules/haus-components/dist/styles.css')],\n * defines: [\n * read('node_modules/haus-tokens/dist/primitives.css'),\n * read('node_modules/haus-tokens/dist/semantics.css'),\n * read('node_modules/haus-tokens/dist/motion.css'),\n * read('src/tokens/overrides.css'),\n * ],\n * })\n * expect(missing).toEqual([])\n * })\n * ```\n */\n\n/**\n * `var(--x)` with no fallback.\n *\n * A reference with a fallback, `var(--x, 0.2s)`, is a real value whether or\n * not the property is set, so it cannot fail at computed-value time and is\n * excluded. It is still usually a sign the name is wrong: a fallback that never\n * loses is a hardcoded value wearing a token's clothes. `findFallbackTokens`\n * below is for looking at those deliberately, rather than failing a build on\n * something that works.\n */\nconst READ_NO_FALLBACK = /var\\(\\s*(--[a-zA-Z0-9-]+)\\s*\\)/g\nconst READ_WITH_FALLBACK = /var\\(\\s*(--[a-zA-Z0-9-]+)\\s*,/g\n// `m` is load-bearing: without it `^` only matches the start of the whole\n// string, so every declaration on its own indented line after a newline is\n// missed and only the first in each block is seen. Caught by this package's\n// own guard test: semantics.css came back with 41 undefined roles.\nconst DECLARATION = /(?:^|[;{])\\s*(--[a-zA-Z0-9-]+)\\s*:/gm\n\nexport interface TokenGuardInput {\n /** The CSS doing the reading: the component stylesheet, your own modules. */\n reads: string[]\n /** The CSS doing the defining: the token layers you load, plus your own. */\n defines: string[]\n /**\n * Names defined outside CSS. A component that sets `style={{ '--x': v }}`\n * defines the property on the element, and no stylesheet will show it.\n */\n alsoDefined?: string[]\n}\n\nexport interface TokenGuardResult {\n /** Read with no fallback and defined nowhere. Sorted, so a diff is stable. */\n missing: string[]\n /** Every property read without a fallback. */\n read: string[]\n /** Every property declared across `defines` and `alsoDefined`. */\n defined: string[]\n}\n\nfunction collect(sources: string[], pattern: RegExp): Set<string> {\n const found = new Set<string>()\n for (const css of sources) {\n // A fresh lastIndex per source: a /g regex is stateful, and reusing one\n // across inputs silently skips the start of every source after the first.\n pattern.lastIndex = 0\n for (const m of css.matchAll(pattern)) found.add(m[1]!)\n }\n return found\n}\n\n/**\n * Which properties are read but never defined.\n *\n * An empty `missing` is the assertion. The other two fields are for a consumer\n * that wants to report rather than fail: `read.length` is also worth asserting\n * as a floor, because a wrong path makes every check pass by finding nothing.\n */\nexport function findUndefinedTokens(input: TokenGuardInput): TokenGuardResult {\n const read = collect(input.reads, READ_NO_FALLBACK)\n const defined = collect(input.defines, DECLARATION)\n for (const name of input.alsoDefined ?? []) defined.add(name)\n\n return {\n missing: [...read].filter((name) => !defined.has(name)).sort(),\n read: [...read].sort(),\n defined: [...defined].sort(),\n }\n}\n\n/**\n * Which properties are only ever read with a fallback.\n *\n * Not a failure, and deliberately a separate function so it cannot be mistaken\n * for one. A fallback that never loses is a hardcoded value wearing a token's\n * clothes, and the list is worth reading occasionally rather than failing a\n * build over.\n */\nexport function findFallbackTokens(input: Pick<TokenGuardInput, 'reads' | 'defines'>): string[] {\n const withFallback = collect(input.reads, READ_WITH_FALLBACK)\n const defined = collect(input.defines, DECLARATION)\n return [...withFallback].filter((name) => !defined.has(name)).sort()\n}\n\n/* ─── Restatement: a consumer keeping its own copy of a value we ship ────────\n *\n * The second failure this package can see and a consumer cannot. An unresolved\n * var() at least renders wrong; a restated value renders perfectly, and is only\n * wrong from the moment one of the two sides moves.\n *\n * vault carried 141 of them and closed it as `vault#25`, then wrote this rule by\n * hand so it could not come back. drift has 89 and never had the rule: it was\n * written in the repository next door and never ported, which is why it ships\n * from here now (haus#53).\n *\n * TWO KINDS, and the second is the one a hand-written version missed.\n *\n * identical the declaration is the same text on both sides.\n * `--haus-space-inset-md: var(--haus-space-4)` written twice.\n * 77 of drift's.\n *\n * resolved the text differs and the value does not. `--haus-z-modal: 400`\n * against this package's `var(--haus-z-400)`, where `--haus-z-400`\n * is `400`. 12 of drift's, and vault's hand-written rule compares\n * declaration text so it would have found none of them.\n *\n * The second kind is worth the resolver: hardcoding the number a token resolves\n * to is how a consumer opts out of a scale while appearing to be on it.\n */\n\n/** One `--x: value` declaration, in source order. */\ntype Declaration = { name: string; value: string }\n\n/** Comments out, whitespace flattened, so two spellings of one value compare equal. */\nfunction normalise(value: string): string {\n return value\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\nfunction declarations(sources: string[]): Declaration[] {\n const out: Declaration[] = []\n for (const css of sources) {\n for (const m of css.matchAll(/(?:^|[;{])\\s*(--[a-zA-Z0-9-]+)\\s*:\\s*([^;}]+)/gm)) {\n out.push({ name: m[1]!, value: normalise(m[2]!) })\n }\n }\n return out\n}\n\n/**\n * Follow `var()` references until nothing is left to follow.\n *\n * Depth-limited rather than cycle-tracked: a token graph is shallow, and a\n * limit is one line where a visited-set is five. Hitting the limit returns the\n * partially resolved value, which compares unequal and so reports nothing,\n * because a guard that guesses is worse than one that misses.\n */\nfunction resolve(value: string, table: Map<string, string>, depth = 0): string {\n if (depth > 10) return value\n const next = value.replace(/var\\(\\s*(--[a-zA-Z0-9-]+)\\s*\\)/g, (whole, name: string) => {\n const found = table.get(name)\n return found === undefined ? whole : found\n })\n return next === value ? value : resolve(next, table, depth + 1)\n}\n\nexport interface Restatement {\n /** The custom property the consumer declares. */\n name: string\n /** `identical` if the declaration matches ours as text, `resolved` if only the value does. */\n kind: 'identical' | 'resolved'\n /** What the consumer wrote. */\n value: string\n /** What this package already says, as written. */\n upstream: string\n}\n\nexport interface RestatementInput {\n /** The consumer's own token CSS: the file where it overrides or adds. */\n defines: string[]\n /** This package's layers, as the consumer actually loads them. */\n upstream: string[]\n}\n\n/**\n * Which of a consumer's declarations this package already ships.\n *\n * An empty array is the assertion. A consumer may override any role it likes,\n * and several should: what it may not do is override a role to the value the\n * package already gives, because that is not an override, it is a copy, and a\n * copy is correct only until one side moves.\n *\n * Read the package from `node_modules` rather than a fixture. The point is to\n * compare against the value that will actually load.\n *\n * WHICH FILES TO PASS AS `upstream`, because it changes the question asked.\n *\n * Include `brand.css` and the answer is *does this consumer restate anything we\n * ship, including our brand's choices*. Leave it out and the answer is *does it\n * restate anything structural*, with its own colour choices treated as its\n * business.\n *\n * Measured against drift, whose colour overrides are a brand written as role\n * overrides: **143 with `brand.css`, 89 without.** The 54 in the gap are exactly\n * its brand. So a consumer that has a brand file, or intends one, leaves\n * `brand.css` out and gets only the copies; a consumer with no brand of its own\n * puts it in and is told that its colour overrides agree with ours, which is a\n * different and also useful thing to know.\n *\n * @example\n * ```ts\n * import { findRestatedTokens } from 'haus-tokens/guard'\n *\n * it('restates no value haus already ships', () => {\n * const copies = findRestatedTokens({\n * defines: [read('src/tokens/semantics.css')],\n * upstream: HAUS_FILES.map(read),\n * })\n * expect(copies.map((c) => `${c.name} (${c.kind})`)).toEqual([])\n * })\n * ```\n */\nexport function findRestatedTokens(input: RestatementInput): Restatement[] {\n const table = new Map<string, string>()\n for (const { name, value } of declarations(input.upstream)) {\n // First declaration wins, matching the cascade order the consumer loads in.\n if (!table.has(name)) table.set(name, value)\n }\n\n const seen = new Set<string>()\n const found: Restatement[] = []\n for (const { name, value } of declarations(input.defines)) {\n const upstream = table.get(name)\n if (upstream === undefined || seen.has(name)) continue\n\n let kind: Restatement['kind'] | undefined\n if (value === upstream) kind = 'identical'\n else if (resolve(value, table) === resolve(upstream, table)) kind = 'resolved'\n\n if (kind) {\n seen.add(name)\n found.push({ name, kind, value, upstream })\n }\n }\n return found.sort((a, b) => a.name.localeCompare(b.name))\n}\n"]}
package/dist/index.cjs CHANGED
@@ -29,6 +29,7 @@ var brandRoles = [
29
29
  "--haus-brand-primary-subtle",
30
30
  "--haus-brand-primary-on-subtle",
31
31
  "--haus-brand-primary-disabled",
32
+ "--haus-brand-backdrop",
32
33
  "--haus-brand-info-subtle",
33
34
  "--haus-brand-info-border",
34
35
  "--haus-brand-info-default",
@@ -55,7 +56,16 @@ var brandRoles = [
55
56
  "--haus-brand-error-on-subtle",
56
57
  "--haus-brand-error-on-default",
57
58
  "--haus-brand-error-emphasis",
58
- "--haus-brand-backdrop"
59
+ "--haus-brand-radius-control",
60
+ "--haus-brand-radius-surface",
61
+ "--haus-brand-radius-overlay",
62
+ "--haus-brand-radius-marker",
63
+ "--haus-brand-elevation-raised",
64
+ "--haus-brand-elevation-floating",
65
+ "--haus-brand-elevation-overlay",
66
+ "--haus-brand-modal-width-sm",
67
+ "--haus-brand-modal-width-md",
68
+ "--haus-brand-modal-width-lg"
59
69
  ];
60
70
 
61
71
  // src/index.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/brand.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/* ─── haus / primitives ──────────────────────────────────────────────────────\n Raw values only. No component or semantic meaning.\n Nothing outside this file should define raw values.\n Components must never reference these directly. Use semantics.css.\n\n GENERATED FROM src/tokens.json. Do not edit.\n Regenerate with `npm run tokens`; `npm run tokens:check` fails CI if stale.\n ─────────────────────────────────────────────────────────────────────────── */\n\n/**\n * Every entry a brand must supply, generated from brand.css.\n *\n * A brand file is CSS, so this cannot check it directly. What it does check is\n * the object form: build a brand in TypeScript, satisfy this type, and a missing\n * or misspelled role is a compile error rather than an unresolved var() that\n * drops a declaration with no warning at all.\n */\nexport interface BrandMap {\n '--haus-brand-surface-default': string\n '--haus-brand-surface-subtle': string\n '--haus-brand-surface-raised': string\n '--haus-brand-surface-overlay': string\n '--haus-brand-surface-sunken': string\n '--haus-brand-surface-inverse': string\n '--haus-brand-surface-disabled': string\n '--haus-brand-surface-inverse-hover': string\n '--haus-brand-ink-primary': string\n '--haus-brand-ink-secondary': string\n '--haus-brand-ink-tertiary': string\n '--haus-brand-ink-disabled': string\n '--haus-brand-ink-inverse': string\n '--haus-brand-ink-link': string\n '--haus-brand-ink-on-primary': string\n '--haus-brand-border-subtle': string\n '--haus-brand-border-default': string\n '--haus-brand-border-strong': string\n '--haus-brand-border-disabled': string\n '--haus-brand-border-inverse': string\n '--haus-brand-border-inverse-hover': string\n '--haus-brand-primary-default': string\n '--haus-brand-primary-hover': string\n '--haus-brand-primary-pressed': string\n '--haus-brand-primary-subtle': string\n '--haus-brand-primary-on-subtle': string\n '--haus-brand-primary-disabled': string\n '--haus-brand-info-subtle': string\n '--haus-brand-info-border': string\n '--haus-brand-info-default': string\n '--haus-brand-info-on-subtle': string\n '--haus-brand-info-on-default': string\n '--haus-brand-info-emphasis': string\n '--haus-brand-success-subtle': string\n '--haus-brand-success-border': string\n '--haus-brand-success-default': string\n '--haus-brand-success-on-subtle': string\n '--haus-brand-success-on-default': string\n '--haus-brand-success-solid': string\n '--haus-brand-success-emphasis': string\n '--haus-brand-warning-subtle': string\n '--haus-brand-warning-border': string\n '--haus-brand-warning-default': string\n '--haus-brand-warning-on-subtle': string\n '--haus-brand-warning-on-default': string\n '--haus-brand-warning-solid': string\n '--haus-brand-warning-emphasis': string\n '--haus-brand-error-subtle': string\n '--haus-brand-error-border': string\n '--haus-brand-error-default': string\n '--haus-brand-error-on-subtle': string\n '--haus-brand-error-on-default': string\n '--haus-brand-error-emphasis': string\n '--haus-brand-backdrop': string\n}\n\n/** The role names themselves, for anyone generating a brand rather than writing one. */\nexport const brandRoles = [\n '--haus-brand-surface-default',\n '--haus-brand-surface-subtle',\n '--haus-brand-surface-raised',\n '--haus-brand-surface-overlay',\n '--haus-brand-surface-sunken',\n '--haus-brand-surface-inverse',\n '--haus-brand-surface-disabled',\n '--haus-brand-surface-inverse-hover',\n '--haus-brand-ink-primary',\n '--haus-brand-ink-secondary',\n '--haus-brand-ink-tertiary',\n '--haus-brand-ink-disabled',\n '--haus-brand-ink-inverse',\n '--haus-brand-ink-link',\n '--haus-brand-ink-on-primary',\n '--haus-brand-border-subtle',\n '--haus-brand-border-default',\n '--haus-brand-border-strong',\n '--haus-brand-border-disabled',\n '--haus-brand-border-inverse',\n '--haus-brand-border-inverse-hover',\n '--haus-brand-primary-default',\n '--haus-brand-primary-hover',\n '--haus-brand-primary-pressed',\n '--haus-brand-primary-subtle',\n '--haus-brand-primary-on-subtle',\n '--haus-brand-primary-disabled',\n '--haus-brand-info-subtle',\n '--haus-brand-info-border',\n '--haus-brand-info-default',\n '--haus-brand-info-on-subtle',\n '--haus-brand-info-on-default',\n '--haus-brand-info-emphasis',\n '--haus-brand-success-subtle',\n '--haus-brand-success-border',\n '--haus-brand-success-default',\n '--haus-brand-success-on-subtle',\n '--haus-brand-success-on-default',\n '--haus-brand-success-solid',\n '--haus-brand-success-emphasis',\n '--haus-brand-warning-subtle',\n '--haus-brand-warning-border',\n '--haus-brand-warning-default',\n '--haus-brand-warning-on-subtle',\n '--haus-brand-warning-on-default',\n '--haus-brand-warning-solid',\n '--haus-brand-warning-emphasis',\n '--haus-brand-error-subtle',\n '--haus-brand-error-border',\n '--haus-brand-error-default',\n '--haus-brand-error-on-subtle',\n '--haus-brand-error-on-default',\n '--haus-brand-error-emphasis',\n '--haus-brand-backdrop',\n] as const\n","/* ─── haus / tokens ──────────────────────────────────────────────────────────\n Typed constants for the primitive layer.\n\n The CSS custom properties are the runtime form; this exists for the places\n they cannot reach: @media conditions, build config, style-in-JS. Semantic\n tokens are deliberately absent: their whole job is to be swappable at\n runtime, which freezing them into a constant would defeat.\n\n GENERATED FROM src/tokens.json. Do not edit.\n Regenerate with `npm run tokens`; `npm run tokens:check` fails CI if stale.\n ─────────────────────────────────────────────────────────────────────────── */\n\nexport const tokens = {\n color: {\n aronia: {\n \"100\": \"oklch(97% 0.012 300)\",\n \"200\": \"oklch(92% 0.028 300)\",\n \"300\": \"oklch(84% 0.058 300)\",\n \"400\": \"oklch(72% 0.100 300)\",\n \"500\": \"oklch(52% 0.138 300)\",\n \"600\": \"oklch(43% 0.125 300)\",\n \"700\": \"oklch(35% 0.105 300)\",\n \"800\": \"oklch(26% 0.080 300)\",\n \"850\": \"oklch(22% 0.066 300)\",\n \"900\": \"oklch(18% 0.052 300)\",\n \"950\": \"oklch(12% 0.032 300)\",\n },\n damson: {\n \"0\": \"oklch(100% 0 0)\",\n \"50\": \"oklch(99% 0.003 290)\",\n \"100\": \"oklch(97% 0.006 290)\",\n \"200\": \"oklch(93% 0.008 290)\",\n \"300\": \"oklch(86% 0.010 290)\",\n \"400\": \"oklch(74% 0.010 290)\",\n \"500\": \"oklch(60% 0.008 290)\",\n \"600\": \"oklch(48% 0.007 290)\",\n \"700\": \"oklch(37% 0.006 290)\",\n \"800\": \"oklch(27% 0.005 290)\",\n \"900\": \"oklch(18% 0.003 290)\",\n \"950\": \"oklch(11% 0.002 290)\",\n },\n elderberry: {\n \"100\": \"oklch(97% 0.020 265)\",\n \"200\": \"oklch(93% 0.040 265)\",\n \"500\": \"oklch(55% 0.200 265)\",\n \"700\": \"oklch(42% 0.160 265)\",\n \"900\": \"oklch(30% 0.120 265)\",\n },\n greengage: {\n \"100\": \"oklch(97% 0.030 148)\",\n \"200\": \"oklch(93% 0.055 148)\",\n \"500\": \"oklch(58% 0.185 148)\",\n \"700\": \"oklch(45% 0.150 148)\",\n \"900\": \"oklch(33% 0.110 148)\",\n },\n mango: {\n \"100\": \"oklch(97% 0.025 65)\",\n \"200\": \"oklch(93% 0.045 65)\",\n \"500\": \"oklch(60% 0.175 65)\",\n \"700\": \"oklch(47% 0.142 65)\",\n \"900\": \"oklch(38% 0.110 65)\",\n },\n cherry: {\n \"100\": \"oklch(97% 0.030 27)\",\n \"200\": \"oklch(93% 0.055 27)\",\n \"500\": \"oklch(58% 0.200 27)\",\n \"700\": \"oklch(44% 0.168 27)\",\n \"900\": \"oklch(33% 0.110 27)\",\n },\n },\n font: {\n family: {\n sans: \"'Manrope', system-ui, sans-serif\",\n mono: \"'Fira Code', ui-monospace, monospace\",\n },\n size: {\n \"11\": \"0.6875rem\",\n \"12\": \"0.75rem\",\n \"13\": \"0.8125rem\",\n \"14\": \"0.875rem\",\n \"16\": \"1rem\",\n \"20\": \"1.25rem\",\n \"24\": \"1.5rem\",\n \"30\": \"1.875rem\",\n },\n weight: {\n regular: 400,\n medium: 500,\n semibold: 600,\n bold: 700,\n },\n lineHeight: {\n tight: 1.15,\n tighter: 1.2,\n snug: 1.25,\n compact: 1.3,\n normal: 1.4,\n relaxed: 1.5,\n loose: 1.6,\n },\n tracking: {\n tightest: \"-0.03em\",\n tighter: \"-0.02em\",\n tight: \"-0.01em\",\n normal: \"0em\",\n wide: \"0.02em\",\n wider: \"0.04em\",\n widest: \"0.08em\",\n },\n },\n spacing: {\n \"1\": \"0.25rem\",\n \"2\": \"0.5rem\",\n \"3\": \"0.75rem\",\n \"4\": \"1rem\",\n \"5\": \"1.25rem\",\n \"6\": \"1.5rem\",\n \"7\": \"1.75rem\",\n \"8\": \"2rem\",\n \"10\": \"2.5rem\",\n \"12\": \"3rem\",\n \"16\": \"4rem\",\n \"20\": \"5rem\",\n },\n radius: {\n none: \"0\",\n sm: \"0.25rem\",\n md: \"0.5rem\",\n lg: \"0.75rem\",\n xl: \"1rem\",\n \"2xl\": \"1.5rem\",\n full: \"9999px\",\n },\n duration: {\n instant: \"50ms\",\n fast: \"100ms\",\n normal: \"200ms\",\n moderate: \"300ms\",\n slow: \"500ms\",\n reduced: \"0ms\",\n },\n easing: {\n enter: \"cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n exit: \"cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n move: \"cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n spring: \"cubic-bezier(0.34, 1.56, 0.64, 1.00)\",\n linear: \"linear\",\n },\n motion: {\n \"fade-in\": \"200ms cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n \"fade-out\": \"100ms cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n \"slide-in\": \"300ms cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n \"slide-out\": \"100ms cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n micro: \"100ms cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n interactive: \"200ms cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n },\n shadow: {\n none: \"none\",\n sm: \"0 1px 2px oklch(18% 0.003 290 / 0.06)\",\n md: \"0 4px 6px -1px oklch(18% 0.003 290 / 0.10), 0 2px 4px -2px oklch(18% 0.003 290 / 0.10)\",\n lg: \"0 10px 15px -3px oklch(18% 0.003 290 / 0.10), 0 4px 6px -4px oklch(18% 0.003 290 / 0.07)\",\n xl: \"0 20px 25px -5px oklch(18% 0.003 290 / 0.10), 0 8px 10px -6px oklch(18% 0.003 290 / 0.10)\",\n },\n controlHeight: {\n sm: \"1.75rem\",\n md: \"2.25rem\",\n lg: \"2.75rem\",\n },\n zIndex: {\n \"0\": 0,\n \"10\": 10,\n \"100\": 100,\n \"200\": 200,\n \"300\": 300,\n \"400\": 400,\n \"500\": 500,\n \"600\": 600,\n },\n borderWidth: {\n \"1\": \"1px\",\n \"2\": \"2px\",\n },\n opacity: {\n \"40\": 0.4,\n \"60\": 0.6,\n },\n iconSize: {\n xs: \"0.75rem\",\n sm: \"1rem\",\n md: \"1.25rem\",\n lg: \"1.5rem\",\n xl: \"2rem\",\n },\n breakpoint: {\n sm: \"640px\",\n md: \"768px\",\n lg: \"1024px\",\n xl: \"1280px\",\n \"2xl\": \"1536px\",\n },\n} as const\n\nexport type Tokens = typeof tokens\n\n/* The brand map's type and role list, generated from brand.css. Re-exported here\n so a consumer has one entry point rather than two. */\nexport type { BrandMap } from './brand'\nexport { brandRoles } from './brand'\n"]}
1
+ {"version":3,"sources":["../src/brand.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/* ─── haus / primitives ──────────────────────────────────────────────────────\n Raw values only. No component or semantic meaning.\n Nothing outside this file should define raw values.\n Components must never reference these directly. Use semantics.css.\n\n GENERATED FROM src/tokens.json. Do not edit.\n Regenerate with `npm run tokens`; `npm run tokens:check` fails CI if stale.\n ─────────────────────────────────────────────────────────────────────────── */\n\n/**\n * The entries every brand must supply, generated from brand.css.\n *\n * A brand file is CSS, so this cannot check it directly. What it does check is\n * the object form: build a brand in TypeScript, satisfy this type, and a missing\n * or misspelled role is a compile error rather than an unresolved var() that\n * drops a declaration with no warning at all.\n */\nexport interface BrandMapBase {\n '--haus-brand-surface-default': string\n '--haus-brand-surface-subtle': string\n '--haus-brand-surface-raised': string\n '--haus-brand-surface-overlay': string\n '--haus-brand-surface-sunken': string\n '--haus-brand-surface-inverse': string\n '--haus-brand-surface-disabled': string\n '--haus-brand-surface-inverse-hover': string\n '--haus-brand-ink-primary': string\n '--haus-brand-ink-secondary': string\n '--haus-brand-ink-tertiary': string\n '--haus-brand-ink-disabled': string\n '--haus-brand-ink-inverse': string\n '--haus-brand-ink-link': string\n '--haus-brand-ink-on-primary': string\n '--haus-brand-border-subtle': string\n '--haus-brand-border-default': string\n '--haus-brand-border-strong': string\n '--haus-brand-border-disabled': string\n '--haus-brand-border-inverse': string\n '--haus-brand-border-inverse-hover': string\n '--haus-brand-primary-default': string\n '--haus-brand-primary-hover': string\n '--haus-brand-primary-pressed': string\n '--haus-brand-primary-subtle': string\n '--haus-brand-primary-on-subtle': string\n '--haus-brand-primary-disabled': string\n '--haus-brand-backdrop': string\n}\n\n/**\n * The optional half: info, success, warning and error.\n *\n * A product whose statuses are not those four semantics omits this tier and\n * inherits haus's from :root, because custom properties inherit and a named\n * brand only overrides what it declares. Optional here, and all-or-nothing per\n * ramp in brand.test.ts, which types cannot express.\n */\nexport interface BrandMapFeedback {\n '--haus-brand-info-subtle': string\n '--haus-brand-info-border': string\n '--haus-brand-info-default': string\n '--haus-brand-info-on-subtle': string\n '--haus-brand-info-on-default': string\n '--haus-brand-info-emphasis': string\n '--haus-brand-success-subtle': string\n '--haus-brand-success-border': string\n '--haus-brand-success-default': string\n '--haus-brand-success-on-subtle': string\n '--haus-brand-success-on-default': string\n '--haus-brand-success-solid': string\n '--haus-brand-success-emphasis': string\n '--haus-brand-warning-subtle': string\n '--haus-brand-warning-border': string\n '--haus-brand-warning-default': string\n '--haus-brand-warning-on-subtle': string\n '--haus-brand-warning-on-default': string\n '--haus-brand-warning-solid': string\n '--haus-brand-warning-emphasis': string\n '--haus-brand-error-subtle': string\n '--haus-brand-error-border': string\n '--haus-brand-error-default': string\n '--haus-brand-error-on-subtle': string\n '--haus-brand-error-on-default': string\n '--haus-brand-error-emphasis': string\n}\n\n/**\n * The other optional half: what a product re-decides that is not a colour.\n *\n * Radius and elevation, taken from what drift and vault actually changed. Not\n * z-index, opacity, border-width or spacing: nobody re-decides those, and the\n * overrides that looked like it were the literal values of haus's own\n * primitives typed out. All-or-nothing per group, in brand.test.ts.\n */\nexport interface BrandMapForm {\n '--haus-brand-radius-control': string\n '--haus-brand-radius-surface': string\n '--haus-brand-radius-overlay': string\n '--haus-brand-radius-marker': string\n '--haus-brand-elevation-raised': string\n '--haus-brand-elevation-floating': string\n '--haus-brand-elevation-overlay': string\n '--haus-brand-modal-width-sm': string\n '--haus-brand-modal-width-md': string\n '--haus-brand-modal-width-lg': string\n}\n\n/** A complete brand: the base tier, and as much of the optional tiers as applies. */\nexport type BrandMap = BrandMapBase & Partial<BrandMapFeedback> & Partial<BrandMapForm>\n\n/** The role names themselves, for anyone generating a brand rather than writing one. */\nexport const brandRoles = [\n '--haus-brand-surface-default',\n '--haus-brand-surface-subtle',\n '--haus-brand-surface-raised',\n '--haus-brand-surface-overlay',\n '--haus-brand-surface-sunken',\n '--haus-brand-surface-inverse',\n '--haus-brand-surface-disabled',\n '--haus-brand-surface-inverse-hover',\n '--haus-brand-ink-primary',\n '--haus-brand-ink-secondary',\n '--haus-brand-ink-tertiary',\n '--haus-brand-ink-disabled',\n '--haus-brand-ink-inverse',\n '--haus-brand-ink-link',\n '--haus-brand-ink-on-primary',\n '--haus-brand-border-subtle',\n '--haus-brand-border-default',\n '--haus-brand-border-strong',\n '--haus-brand-border-disabled',\n '--haus-brand-border-inverse',\n '--haus-brand-border-inverse-hover',\n '--haus-brand-primary-default',\n '--haus-brand-primary-hover',\n '--haus-brand-primary-pressed',\n '--haus-brand-primary-subtle',\n '--haus-brand-primary-on-subtle',\n '--haus-brand-primary-disabled',\n '--haus-brand-backdrop',\n '--haus-brand-info-subtle',\n '--haus-brand-info-border',\n '--haus-brand-info-default',\n '--haus-brand-info-on-subtle',\n '--haus-brand-info-on-default',\n '--haus-brand-info-emphasis',\n '--haus-brand-success-subtle',\n '--haus-brand-success-border',\n '--haus-brand-success-default',\n '--haus-brand-success-on-subtle',\n '--haus-brand-success-on-default',\n '--haus-brand-success-solid',\n '--haus-brand-success-emphasis',\n '--haus-brand-warning-subtle',\n '--haus-brand-warning-border',\n '--haus-brand-warning-default',\n '--haus-brand-warning-on-subtle',\n '--haus-brand-warning-on-default',\n '--haus-brand-warning-solid',\n '--haus-brand-warning-emphasis',\n '--haus-brand-error-subtle',\n '--haus-brand-error-border',\n '--haus-brand-error-default',\n '--haus-brand-error-on-subtle',\n '--haus-brand-error-on-default',\n '--haus-brand-error-emphasis',\n '--haus-brand-radius-control',\n '--haus-brand-radius-surface',\n '--haus-brand-radius-overlay',\n '--haus-brand-radius-marker',\n '--haus-brand-elevation-raised',\n '--haus-brand-elevation-floating',\n '--haus-brand-elevation-overlay',\n '--haus-brand-modal-width-sm',\n '--haus-brand-modal-width-md',\n '--haus-brand-modal-width-lg',\n] as const\n\n/** The required half. A brand supplying fewer than these renders unstyled. */\nexport const brandRolesBase = [\n '--haus-brand-surface-default',\n '--haus-brand-surface-subtle',\n '--haus-brand-surface-raised',\n '--haus-brand-surface-overlay',\n '--haus-brand-surface-sunken',\n '--haus-brand-surface-inverse',\n '--haus-brand-surface-disabled',\n '--haus-brand-surface-inverse-hover',\n '--haus-brand-ink-primary',\n '--haus-brand-ink-secondary',\n '--haus-brand-ink-tertiary',\n '--haus-brand-ink-disabled',\n '--haus-brand-ink-inverse',\n '--haus-brand-ink-link',\n '--haus-brand-ink-on-primary',\n '--haus-brand-border-subtle',\n '--haus-brand-border-default',\n '--haus-brand-border-strong',\n '--haus-brand-border-disabled',\n '--haus-brand-border-inverse',\n '--haus-brand-border-inverse-hover',\n '--haus-brand-primary-default',\n '--haus-brand-primary-hover',\n '--haus-brand-primary-pressed',\n '--haus-brand-primary-subtle',\n '--haus-brand-primary-on-subtle',\n '--haus-brand-primary-disabled',\n '--haus-brand-backdrop',\n] as const\n\n/** The optional colour half, grouped by the ramp that has to be complete or absent. */\nexport const brandRolesFeedback = [\n '--haus-brand-info-subtle',\n '--haus-brand-info-border',\n '--haus-brand-info-default',\n '--haus-brand-info-on-subtle',\n '--haus-brand-info-on-default',\n '--haus-brand-info-emphasis',\n '--haus-brand-success-subtle',\n '--haus-brand-success-border',\n '--haus-brand-success-default',\n '--haus-brand-success-on-subtle',\n '--haus-brand-success-on-default',\n '--haus-brand-success-solid',\n '--haus-brand-success-emphasis',\n '--haus-brand-warning-subtle',\n '--haus-brand-warning-border',\n '--haus-brand-warning-default',\n '--haus-brand-warning-on-subtle',\n '--haus-brand-warning-on-default',\n '--haus-brand-warning-solid',\n '--haus-brand-warning-emphasis',\n '--haus-brand-error-subtle',\n '--haus-brand-error-border',\n '--haus-brand-error-default',\n '--haus-brand-error-on-subtle',\n '--haus-brand-error-on-default',\n '--haus-brand-error-emphasis',\n] as const\n\n/** The optional non-colour half: radius and elevation. */\nexport const brandRolesForm = [\n '--haus-brand-radius-control',\n '--haus-brand-radius-surface',\n '--haus-brand-radius-overlay',\n '--haus-brand-radius-marker',\n '--haus-brand-elevation-raised',\n '--haus-brand-elevation-floating',\n '--haus-brand-elevation-overlay',\n '--haus-brand-modal-width-sm',\n '--haus-brand-modal-width-md',\n '--haus-brand-modal-width-lg',\n] as const\n","/* ─── haus / tokens ──────────────────────────────────────────────────────────\n Typed constants for the primitive layer.\n\n The CSS custom properties are the runtime form; this exists for the places\n they cannot reach: @media conditions, build config, style-in-JS. Semantic\n tokens are deliberately absent: their whole job is to be swappable at\n runtime, which freezing them into a constant would defeat.\n\n GENERATED FROM src/tokens.json. Do not edit.\n Regenerate with `npm run tokens`; `npm run tokens:check` fails CI if stale.\n ─────────────────────────────────────────────────────────────────────────── */\n\nexport const tokens = {\n color: {\n aronia: {\n \"100\": \"oklch(97% 0.012 300)\",\n \"200\": \"oklch(92% 0.028 300)\",\n \"300\": \"oklch(84% 0.058 300)\",\n \"400\": \"oklch(72% 0.100 300)\",\n \"500\": \"oklch(52% 0.138 300)\",\n \"600\": \"oklch(43% 0.125 300)\",\n \"700\": \"oklch(35% 0.105 300)\",\n \"800\": \"oklch(26% 0.080 300)\",\n \"850\": \"oklch(22% 0.066 300)\",\n \"900\": \"oklch(18% 0.052 300)\",\n \"950\": \"oklch(12% 0.032 300)\",\n },\n damson: {\n \"0\": \"oklch(100% 0 0)\",\n \"50\": \"oklch(99% 0.003 290)\",\n \"100\": \"oklch(97% 0.006 290)\",\n \"200\": \"oklch(93% 0.008 290)\",\n \"300\": \"oklch(86% 0.010 290)\",\n \"400\": \"oklch(74% 0.010 290)\",\n \"500\": \"oklch(60% 0.008 290)\",\n \"600\": \"oklch(48% 0.007 290)\",\n \"700\": \"oklch(37% 0.006 290)\",\n \"800\": \"oklch(27% 0.005 290)\",\n \"900\": \"oklch(18% 0.003 290)\",\n \"950\": \"oklch(11% 0.002 290)\",\n },\n elderberry: {\n \"100\": \"oklch(97% 0.020 265)\",\n \"200\": \"oklch(93% 0.040 265)\",\n \"500\": \"oklch(55% 0.200 265)\",\n \"700\": \"oklch(42% 0.160 265)\",\n \"900\": \"oklch(30% 0.120 265)\",\n },\n greengage: {\n \"100\": \"oklch(97% 0.030 148)\",\n \"200\": \"oklch(93% 0.055 148)\",\n \"500\": \"oklch(58% 0.185 148)\",\n \"700\": \"oklch(45% 0.150 148)\",\n \"900\": \"oklch(33% 0.110 148)\",\n },\n mango: {\n \"100\": \"oklch(97% 0.025 65)\",\n \"200\": \"oklch(93% 0.045 65)\",\n \"500\": \"oklch(60% 0.175 65)\",\n \"700\": \"oklch(47% 0.142 65)\",\n \"900\": \"oklch(38% 0.110 65)\",\n },\n cherry: {\n \"100\": \"oklch(97% 0.030 27)\",\n \"200\": \"oklch(93% 0.055 27)\",\n \"500\": \"oklch(58% 0.200 27)\",\n \"700\": \"oklch(44% 0.168 27)\",\n \"900\": \"oklch(33% 0.110 27)\",\n },\n },\n font: {\n family: {\n sans: \"'Manrope', system-ui, sans-serif\",\n mono: \"'Fira Code', ui-monospace, monospace\",\n },\n size: {\n \"11\": \"0.6875rem\",\n \"12\": \"0.75rem\",\n \"13\": \"0.8125rem\",\n \"14\": \"0.875rem\",\n \"16\": \"1rem\",\n \"20\": \"1.25rem\",\n \"24\": \"1.5rem\",\n \"30\": \"1.875rem\",\n },\n weight: {\n regular: 400,\n medium: 500,\n semibold: 600,\n bold: 700,\n },\n lineHeight: {\n tight: 1.15,\n tighter: 1.2,\n snug: 1.25,\n compact: 1.3,\n normal: 1.4,\n relaxed: 1.5,\n loose: 1.6,\n },\n tracking: {\n tightest: \"-0.03em\",\n tighter: \"-0.02em\",\n tight: \"-0.01em\",\n normal: \"0em\",\n wide: \"0.02em\",\n wider: \"0.04em\",\n widest: \"0.08em\",\n },\n },\n spacing: {\n \"1\": \"0.25rem\",\n \"2\": \"0.5rem\",\n \"3\": \"0.75rem\",\n \"4\": \"1rem\",\n \"5\": \"1.25rem\",\n \"6\": \"1.5rem\",\n \"7\": \"1.75rem\",\n \"8\": \"2rem\",\n \"10\": \"2.5rem\",\n \"12\": \"3rem\",\n \"16\": \"4rem\",\n \"20\": \"5rem\",\n },\n radius: {\n none: \"0\",\n sm: \"0.25rem\",\n md: \"0.5rem\",\n lg: \"0.75rem\",\n xl: \"1rem\",\n \"2xl\": \"1.5rem\",\n full: \"9999px\",\n },\n duration: {\n instant: \"50ms\",\n fast: \"100ms\",\n normal: \"200ms\",\n moderate: \"300ms\",\n slow: \"500ms\",\n reduced: \"0ms\",\n },\n easing: {\n enter: \"cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n exit: \"cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n move: \"cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n spring: \"cubic-bezier(0.34, 1.56, 0.64, 1.00)\",\n linear: \"linear\",\n },\n motion: {\n \"fade-in\": \"200ms cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n \"fade-out\": \"100ms cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n \"slide-in\": \"300ms cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n \"slide-out\": \"100ms cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n micro: \"100ms cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n interactive: \"200ms cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n },\n shadow: {\n none: \"none\",\n sm: \"0 1px 2px oklch(18% 0.003 290 / 0.06)\",\n md: \"0 4px 6px -1px oklch(18% 0.003 290 / 0.10), 0 2px 4px -2px oklch(18% 0.003 290 / 0.10)\",\n lg: \"0 10px 15px -3px oklch(18% 0.003 290 / 0.10), 0 4px 6px -4px oklch(18% 0.003 290 / 0.07)\",\n xl: \"0 20px 25px -5px oklch(18% 0.003 290 / 0.10), 0 8px 10px -6px oklch(18% 0.003 290 / 0.10)\",\n },\n controlHeight: {\n sm: \"1.75rem\",\n md: \"2.25rem\",\n lg: \"2.75rem\",\n },\n zIndex: {\n \"0\": 0,\n \"10\": 10,\n \"100\": 100,\n \"200\": 200,\n \"300\": 300,\n \"400\": 400,\n \"500\": 500,\n \"600\": 600,\n },\n borderWidth: {\n \"1\": \"1px\",\n \"2\": \"2px\",\n },\n opacity: {\n \"40\": 0.4,\n \"60\": 0.6,\n },\n iconSize: {\n xs: \"0.75rem\",\n sm: \"1rem\",\n md: \"1.25rem\",\n lg: \"1.5rem\",\n xl: \"2rem\",\n },\n breakpoint: {\n sm: \"640px\",\n md: \"768px\",\n lg: \"1024px\",\n xl: \"1280px\",\n \"2xl\": \"1536px\",\n },\n} as const\n\nexport type Tokens = typeof tokens\n\n/* The brand map's type and role list, generated from brand.css. Re-exported here\n so a consumer has one entry point rather than two. */\nexport type { BrandMap } from './brand'\nexport { brandRoles } from './brand'\n"]}
package/dist/index.d.cts CHANGED
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Every entry a brand must supply, generated from brand.css.
2
+ * The entries every brand must supply, generated from brand.css.
3
3
  *
4
4
  * A brand file is CSS, so this cannot check it directly. What it does check is
5
5
  * the object form: build a brand in TypeScript, satisfy this type, and a missing
6
6
  * or misspelled role is a compile error rather than an unresolved var() that
7
7
  * drops a declaration with no warning at all.
8
8
  */
9
- interface BrandMap {
9
+ interface BrandMapBase {
10
10
  '--haus-brand-surface-default': string;
11
11
  '--haus-brand-surface-subtle': string;
12
12
  '--haus-brand-surface-raised': string;
@@ -34,6 +34,17 @@ interface BrandMap {
34
34
  '--haus-brand-primary-subtle': string;
35
35
  '--haus-brand-primary-on-subtle': string;
36
36
  '--haus-brand-primary-disabled': string;
37
+ '--haus-brand-backdrop': string;
38
+ }
39
+ /**
40
+ * The optional half: info, success, warning and error.
41
+ *
42
+ * A product whose statuses are not those four semantics omits this tier and
43
+ * inherits haus's from :root, because custom properties inherit and a named
44
+ * brand only overrides what it declares. Optional here, and all-or-nothing per
45
+ * ramp in brand.test.ts, which types cannot express.
46
+ */
47
+ interface BrandMapFeedback {
37
48
  '--haus-brand-info-subtle': string;
38
49
  '--haus-brand-info-border': string;
39
50
  '--haus-brand-info-default': string;
@@ -60,10 +71,31 @@ interface BrandMap {
60
71
  '--haus-brand-error-on-subtle': string;
61
72
  '--haus-brand-error-on-default': string;
62
73
  '--haus-brand-error-emphasis': string;
63
- '--haus-brand-backdrop': string;
64
74
  }
75
+ /**
76
+ * The other optional half: what a product re-decides that is not a colour.
77
+ *
78
+ * Radius and elevation, taken from what drift and vault actually changed. Not
79
+ * z-index, opacity, border-width or spacing: nobody re-decides those, and the
80
+ * overrides that looked like it were the literal values of haus's own
81
+ * primitives typed out. All-or-nothing per group, in brand.test.ts.
82
+ */
83
+ interface BrandMapForm {
84
+ '--haus-brand-radius-control': string;
85
+ '--haus-brand-radius-surface': string;
86
+ '--haus-brand-radius-overlay': string;
87
+ '--haus-brand-radius-marker': string;
88
+ '--haus-brand-elevation-raised': string;
89
+ '--haus-brand-elevation-floating': string;
90
+ '--haus-brand-elevation-overlay': string;
91
+ '--haus-brand-modal-width-sm': string;
92
+ '--haus-brand-modal-width-md': string;
93
+ '--haus-brand-modal-width-lg': string;
94
+ }
95
+ /** A complete brand: the base tier, and as much of the optional tiers as applies. */
96
+ type BrandMap = BrandMapBase & Partial<BrandMapFeedback> & Partial<BrandMapForm>;
65
97
  /** The role names themselves, for anyone generating a brand rather than writing one. */
66
- declare const brandRoles: readonly ["--haus-brand-surface-default", "--haus-brand-surface-subtle", "--haus-brand-surface-raised", "--haus-brand-surface-overlay", "--haus-brand-surface-sunken", "--haus-brand-surface-inverse", "--haus-brand-surface-disabled", "--haus-brand-surface-inverse-hover", "--haus-brand-ink-primary", "--haus-brand-ink-secondary", "--haus-brand-ink-tertiary", "--haus-brand-ink-disabled", "--haus-brand-ink-inverse", "--haus-brand-ink-link", "--haus-brand-ink-on-primary", "--haus-brand-border-subtle", "--haus-brand-border-default", "--haus-brand-border-strong", "--haus-brand-border-disabled", "--haus-brand-border-inverse", "--haus-brand-border-inverse-hover", "--haus-brand-primary-default", "--haus-brand-primary-hover", "--haus-brand-primary-pressed", "--haus-brand-primary-subtle", "--haus-brand-primary-on-subtle", "--haus-brand-primary-disabled", "--haus-brand-info-subtle", "--haus-brand-info-border", "--haus-brand-info-default", "--haus-brand-info-on-subtle", "--haus-brand-info-on-default", "--haus-brand-info-emphasis", "--haus-brand-success-subtle", "--haus-brand-success-border", "--haus-brand-success-default", "--haus-brand-success-on-subtle", "--haus-brand-success-on-default", "--haus-brand-success-solid", "--haus-brand-success-emphasis", "--haus-brand-warning-subtle", "--haus-brand-warning-border", "--haus-brand-warning-default", "--haus-brand-warning-on-subtle", "--haus-brand-warning-on-default", "--haus-brand-warning-solid", "--haus-brand-warning-emphasis", "--haus-brand-error-subtle", "--haus-brand-error-border", "--haus-brand-error-default", "--haus-brand-error-on-subtle", "--haus-brand-error-on-default", "--haus-brand-error-emphasis", "--haus-brand-backdrop"];
98
+ declare const brandRoles: readonly ["--haus-brand-surface-default", "--haus-brand-surface-subtle", "--haus-brand-surface-raised", "--haus-brand-surface-overlay", "--haus-brand-surface-sunken", "--haus-brand-surface-inverse", "--haus-brand-surface-disabled", "--haus-brand-surface-inverse-hover", "--haus-brand-ink-primary", "--haus-brand-ink-secondary", "--haus-brand-ink-tertiary", "--haus-brand-ink-disabled", "--haus-brand-ink-inverse", "--haus-brand-ink-link", "--haus-brand-ink-on-primary", "--haus-brand-border-subtle", "--haus-brand-border-default", "--haus-brand-border-strong", "--haus-brand-border-disabled", "--haus-brand-border-inverse", "--haus-brand-border-inverse-hover", "--haus-brand-primary-default", "--haus-brand-primary-hover", "--haus-brand-primary-pressed", "--haus-brand-primary-subtle", "--haus-brand-primary-on-subtle", "--haus-brand-primary-disabled", "--haus-brand-backdrop", "--haus-brand-info-subtle", "--haus-brand-info-border", "--haus-brand-info-default", "--haus-brand-info-on-subtle", "--haus-brand-info-on-default", "--haus-brand-info-emphasis", "--haus-brand-success-subtle", "--haus-brand-success-border", "--haus-brand-success-default", "--haus-brand-success-on-subtle", "--haus-brand-success-on-default", "--haus-brand-success-solid", "--haus-brand-success-emphasis", "--haus-brand-warning-subtle", "--haus-brand-warning-border", "--haus-brand-warning-default", "--haus-brand-warning-on-subtle", "--haus-brand-warning-on-default", "--haus-brand-warning-solid", "--haus-brand-warning-emphasis", "--haus-brand-error-subtle", "--haus-brand-error-border", "--haus-brand-error-default", "--haus-brand-error-on-subtle", "--haus-brand-error-on-default", "--haus-brand-error-emphasis", "--haus-brand-radius-control", "--haus-brand-radius-surface", "--haus-brand-radius-overlay", "--haus-brand-radius-marker", "--haus-brand-elevation-raised", "--haus-brand-elevation-floating", "--haus-brand-elevation-overlay", "--haus-brand-modal-width-sm", "--haus-brand-modal-width-md", "--haus-brand-modal-width-lg"];
67
99
 
68
100
  declare const tokens: {
69
101
  readonly color: {
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Every entry a brand must supply, generated from brand.css.
2
+ * The entries every brand must supply, generated from brand.css.
3
3
  *
4
4
  * A brand file is CSS, so this cannot check it directly. What it does check is
5
5
  * the object form: build a brand in TypeScript, satisfy this type, and a missing
6
6
  * or misspelled role is a compile error rather than an unresolved var() that
7
7
  * drops a declaration with no warning at all.
8
8
  */
9
- interface BrandMap {
9
+ interface BrandMapBase {
10
10
  '--haus-brand-surface-default': string;
11
11
  '--haus-brand-surface-subtle': string;
12
12
  '--haus-brand-surface-raised': string;
@@ -34,6 +34,17 @@ interface BrandMap {
34
34
  '--haus-brand-primary-subtle': string;
35
35
  '--haus-brand-primary-on-subtle': string;
36
36
  '--haus-brand-primary-disabled': string;
37
+ '--haus-brand-backdrop': string;
38
+ }
39
+ /**
40
+ * The optional half: info, success, warning and error.
41
+ *
42
+ * A product whose statuses are not those four semantics omits this tier and
43
+ * inherits haus's from :root, because custom properties inherit and a named
44
+ * brand only overrides what it declares. Optional here, and all-or-nothing per
45
+ * ramp in brand.test.ts, which types cannot express.
46
+ */
47
+ interface BrandMapFeedback {
37
48
  '--haus-brand-info-subtle': string;
38
49
  '--haus-brand-info-border': string;
39
50
  '--haus-brand-info-default': string;
@@ -60,10 +71,31 @@ interface BrandMap {
60
71
  '--haus-brand-error-on-subtle': string;
61
72
  '--haus-brand-error-on-default': string;
62
73
  '--haus-brand-error-emphasis': string;
63
- '--haus-brand-backdrop': string;
64
74
  }
75
+ /**
76
+ * The other optional half: what a product re-decides that is not a colour.
77
+ *
78
+ * Radius and elevation, taken from what drift and vault actually changed. Not
79
+ * z-index, opacity, border-width or spacing: nobody re-decides those, and the
80
+ * overrides that looked like it were the literal values of haus's own
81
+ * primitives typed out. All-or-nothing per group, in brand.test.ts.
82
+ */
83
+ interface BrandMapForm {
84
+ '--haus-brand-radius-control': string;
85
+ '--haus-brand-radius-surface': string;
86
+ '--haus-brand-radius-overlay': string;
87
+ '--haus-brand-radius-marker': string;
88
+ '--haus-brand-elevation-raised': string;
89
+ '--haus-brand-elevation-floating': string;
90
+ '--haus-brand-elevation-overlay': string;
91
+ '--haus-brand-modal-width-sm': string;
92
+ '--haus-brand-modal-width-md': string;
93
+ '--haus-brand-modal-width-lg': string;
94
+ }
95
+ /** A complete brand: the base tier, and as much of the optional tiers as applies. */
96
+ type BrandMap = BrandMapBase & Partial<BrandMapFeedback> & Partial<BrandMapForm>;
65
97
  /** The role names themselves, for anyone generating a brand rather than writing one. */
66
- declare const brandRoles: readonly ["--haus-brand-surface-default", "--haus-brand-surface-subtle", "--haus-brand-surface-raised", "--haus-brand-surface-overlay", "--haus-brand-surface-sunken", "--haus-brand-surface-inverse", "--haus-brand-surface-disabled", "--haus-brand-surface-inverse-hover", "--haus-brand-ink-primary", "--haus-brand-ink-secondary", "--haus-brand-ink-tertiary", "--haus-brand-ink-disabled", "--haus-brand-ink-inverse", "--haus-brand-ink-link", "--haus-brand-ink-on-primary", "--haus-brand-border-subtle", "--haus-brand-border-default", "--haus-brand-border-strong", "--haus-brand-border-disabled", "--haus-brand-border-inverse", "--haus-brand-border-inverse-hover", "--haus-brand-primary-default", "--haus-brand-primary-hover", "--haus-brand-primary-pressed", "--haus-brand-primary-subtle", "--haus-brand-primary-on-subtle", "--haus-brand-primary-disabled", "--haus-brand-info-subtle", "--haus-brand-info-border", "--haus-brand-info-default", "--haus-brand-info-on-subtle", "--haus-brand-info-on-default", "--haus-brand-info-emphasis", "--haus-brand-success-subtle", "--haus-brand-success-border", "--haus-brand-success-default", "--haus-brand-success-on-subtle", "--haus-brand-success-on-default", "--haus-brand-success-solid", "--haus-brand-success-emphasis", "--haus-brand-warning-subtle", "--haus-brand-warning-border", "--haus-brand-warning-default", "--haus-brand-warning-on-subtle", "--haus-brand-warning-on-default", "--haus-brand-warning-solid", "--haus-brand-warning-emphasis", "--haus-brand-error-subtle", "--haus-brand-error-border", "--haus-brand-error-default", "--haus-brand-error-on-subtle", "--haus-brand-error-on-default", "--haus-brand-error-emphasis", "--haus-brand-backdrop"];
98
+ declare const brandRoles: readonly ["--haus-brand-surface-default", "--haus-brand-surface-subtle", "--haus-brand-surface-raised", "--haus-brand-surface-overlay", "--haus-brand-surface-sunken", "--haus-brand-surface-inverse", "--haus-brand-surface-disabled", "--haus-brand-surface-inverse-hover", "--haus-brand-ink-primary", "--haus-brand-ink-secondary", "--haus-brand-ink-tertiary", "--haus-brand-ink-disabled", "--haus-brand-ink-inverse", "--haus-brand-ink-link", "--haus-brand-ink-on-primary", "--haus-brand-border-subtle", "--haus-brand-border-default", "--haus-brand-border-strong", "--haus-brand-border-disabled", "--haus-brand-border-inverse", "--haus-brand-border-inverse-hover", "--haus-brand-primary-default", "--haus-brand-primary-hover", "--haus-brand-primary-pressed", "--haus-brand-primary-subtle", "--haus-brand-primary-on-subtle", "--haus-brand-primary-disabled", "--haus-brand-backdrop", "--haus-brand-info-subtle", "--haus-brand-info-border", "--haus-brand-info-default", "--haus-brand-info-on-subtle", "--haus-brand-info-on-default", "--haus-brand-info-emphasis", "--haus-brand-success-subtle", "--haus-brand-success-border", "--haus-brand-success-default", "--haus-brand-success-on-subtle", "--haus-brand-success-on-default", "--haus-brand-success-solid", "--haus-brand-success-emphasis", "--haus-brand-warning-subtle", "--haus-brand-warning-border", "--haus-brand-warning-default", "--haus-brand-warning-on-subtle", "--haus-brand-warning-on-default", "--haus-brand-warning-solid", "--haus-brand-warning-emphasis", "--haus-brand-error-subtle", "--haus-brand-error-border", "--haus-brand-error-default", "--haus-brand-error-on-subtle", "--haus-brand-error-on-default", "--haus-brand-error-emphasis", "--haus-brand-radius-control", "--haus-brand-radius-surface", "--haus-brand-radius-overlay", "--haus-brand-radius-marker", "--haus-brand-elevation-raised", "--haus-brand-elevation-floating", "--haus-brand-elevation-overlay", "--haus-brand-modal-width-sm", "--haus-brand-modal-width-md", "--haus-brand-modal-width-lg"];
67
99
 
68
100
  declare const tokens: {
69
101
  readonly color: {
package/dist/index.js CHANGED
@@ -27,6 +27,7 @@ var brandRoles = [
27
27
  "--haus-brand-primary-subtle",
28
28
  "--haus-brand-primary-on-subtle",
29
29
  "--haus-brand-primary-disabled",
30
+ "--haus-brand-backdrop",
30
31
  "--haus-brand-info-subtle",
31
32
  "--haus-brand-info-border",
32
33
  "--haus-brand-info-default",
@@ -53,7 +54,16 @@ var brandRoles = [
53
54
  "--haus-brand-error-on-subtle",
54
55
  "--haus-brand-error-on-default",
55
56
  "--haus-brand-error-emphasis",
56
- "--haus-brand-backdrop"
57
+ "--haus-brand-radius-control",
58
+ "--haus-brand-radius-surface",
59
+ "--haus-brand-radius-overlay",
60
+ "--haus-brand-radius-marker",
61
+ "--haus-brand-elevation-raised",
62
+ "--haus-brand-elevation-floating",
63
+ "--haus-brand-elevation-overlay",
64
+ "--haus-brand-modal-width-sm",
65
+ "--haus-brand-modal-width-md",
66
+ "--haus-brand-modal-width-lg"
57
67
  ];
58
68
 
59
69
  // src/index.ts
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/brand.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/* ─── haus / primitives ──────────────────────────────────────────────────────\n Raw values only. No component or semantic meaning.\n Nothing outside this file should define raw values.\n Components must never reference these directly. Use semantics.css.\n\n GENERATED FROM src/tokens.json. Do not edit.\n Regenerate with `npm run tokens`; `npm run tokens:check` fails CI if stale.\n ─────────────────────────────────────────────────────────────────────────── */\n\n/**\n * Every entry a brand must supply, generated from brand.css.\n *\n * A brand file is CSS, so this cannot check it directly. What it does check is\n * the object form: build a brand in TypeScript, satisfy this type, and a missing\n * or misspelled role is a compile error rather than an unresolved var() that\n * drops a declaration with no warning at all.\n */\nexport interface BrandMap {\n '--haus-brand-surface-default': string\n '--haus-brand-surface-subtle': string\n '--haus-brand-surface-raised': string\n '--haus-brand-surface-overlay': string\n '--haus-brand-surface-sunken': string\n '--haus-brand-surface-inverse': string\n '--haus-brand-surface-disabled': string\n '--haus-brand-surface-inverse-hover': string\n '--haus-brand-ink-primary': string\n '--haus-brand-ink-secondary': string\n '--haus-brand-ink-tertiary': string\n '--haus-brand-ink-disabled': string\n '--haus-brand-ink-inverse': string\n '--haus-brand-ink-link': string\n '--haus-brand-ink-on-primary': string\n '--haus-brand-border-subtle': string\n '--haus-brand-border-default': string\n '--haus-brand-border-strong': string\n '--haus-brand-border-disabled': string\n '--haus-brand-border-inverse': string\n '--haus-brand-border-inverse-hover': string\n '--haus-brand-primary-default': string\n '--haus-brand-primary-hover': string\n '--haus-brand-primary-pressed': string\n '--haus-brand-primary-subtle': string\n '--haus-brand-primary-on-subtle': string\n '--haus-brand-primary-disabled': string\n '--haus-brand-info-subtle': string\n '--haus-brand-info-border': string\n '--haus-brand-info-default': string\n '--haus-brand-info-on-subtle': string\n '--haus-brand-info-on-default': string\n '--haus-brand-info-emphasis': string\n '--haus-brand-success-subtle': string\n '--haus-brand-success-border': string\n '--haus-brand-success-default': string\n '--haus-brand-success-on-subtle': string\n '--haus-brand-success-on-default': string\n '--haus-brand-success-solid': string\n '--haus-brand-success-emphasis': string\n '--haus-brand-warning-subtle': string\n '--haus-brand-warning-border': string\n '--haus-brand-warning-default': string\n '--haus-brand-warning-on-subtle': string\n '--haus-brand-warning-on-default': string\n '--haus-brand-warning-solid': string\n '--haus-brand-warning-emphasis': string\n '--haus-brand-error-subtle': string\n '--haus-brand-error-border': string\n '--haus-brand-error-default': string\n '--haus-brand-error-on-subtle': string\n '--haus-brand-error-on-default': string\n '--haus-brand-error-emphasis': string\n '--haus-brand-backdrop': string\n}\n\n/** The role names themselves, for anyone generating a brand rather than writing one. */\nexport const brandRoles = [\n '--haus-brand-surface-default',\n '--haus-brand-surface-subtle',\n '--haus-brand-surface-raised',\n '--haus-brand-surface-overlay',\n '--haus-brand-surface-sunken',\n '--haus-brand-surface-inverse',\n '--haus-brand-surface-disabled',\n '--haus-brand-surface-inverse-hover',\n '--haus-brand-ink-primary',\n '--haus-brand-ink-secondary',\n '--haus-brand-ink-tertiary',\n '--haus-brand-ink-disabled',\n '--haus-brand-ink-inverse',\n '--haus-brand-ink-link',\n '--haus-brand-ink-on-primary',\n '--haus-brand-border-subtle',\n '--haus-brand-border-default',\n '--haus-brand-border-strong',\n '--haus-brand-border-disabled',\n '--haus-brand-border-inverse',\n '--haus-brand-border-inverse-hover',\n '--haus-brand-primary-default',\n '--haus-brand-primary-hover',\n '--haus-brand-primary-pressed',\n '--haus-brand-primary-subtle',\n '--haus-brand-primary-on-subtle',\n '--haus-brand-primary-disabled',\n '--haus-brand-info-subtle',\n '--haus-brand-info-border',\n '--haus-brand-info-default',\n '--haus-brand-info-on-subtle',\n '--haus-brand-info-on-default',\n '--haus-brand-info-emphasis',\n '--haus-brand-success-subtle',\n '--haus-brand-success-border',\n '--haus-brand-success-default',\n '--haus-brand-success-on-subtle',\n '--haus-brand-success-on-default',\n '--haus-brand-success-solid',\n '--haus-brand-success-emphasis',\n '--haus-brand-warning-subtle',\n '--haus-brand-warning-border',\n '--haus-brand-warning-default',\n '--haus-brand-warning-on-subtle',\n '--haus-brand-warning-on-default',\n '--haus-brand-warning-solid',\n '--haus-brand-warning-emphasis',\n '--haus-brand-error-subtle',\n '--haus-brand-error-border',\n '--haus-brand-error-default',\n '--haus-brand-error-on-subtle',\n '--haus-brand-error-on-default',\n '--haus-brand-error-emphasis',\n '--haus-brand-backdrop',\n] as const\n","/* ─── haus / tokens ──────────────────────────────────────────────────────────\n Typed constants for the primitive layer.\n\n The CSS custom properties are the runtime form; this exists for the places\n they cannot reach: @media conditions, build config, style-in-JS. Semantic\n tokens are deliberately absent: their whole job is to be swappable at\n runtime, which freezing them into a constant would defeat.\n\n GENERATED FROM src/tokens.json. Do not edit.\n Regenerate with `npm run tokens`; `npm run tokens:check` fails CI if stale.\n ─────────────────────────────────────────────────────────────────────────── */\n\nexport const tokens = {\n color: {\n aronia: {\n \"100\": \"oklch(97% 0.012 300)\",\n \"200\": \"oklch(92% 0.028 300)\",\n \"300\": \"oklch(84% 0.058 300)\",\n \"400\": \"oklch(72% 0.100 300)\",\n \"500\": \"oklch(52% 0.138 300)\",\n \"600\": \"oklch(43% 0.125 300)\",\n \"700\": \"oklch(35% 0.105 300)\",\n \"800\": \"oklch(26% 0.080 300)\",\n \"850\": \"oklch(22% 0.066 300)\",\n \"900\": \"oklch(18% 0.052 300)\",\n \"950\": \"oklch(12% 0.032 300)\",\n },\n damson: {\n \"0\": \"oklch(100% 0 0)\",\n \"50\": \"oklch(99% 0.003 290)\",\n \"100\": \"oklch(97% 0.006 290)\",\n \"200\": \"oklch(93% 0.008 290)\",\n \"300\": \"oklch(86% 0.010 290)\",\n \"400\": \"oklch(74% 0.010 290)\",\n \"500\": \"oklch(60% 0.008 290)\",\n \"600\": \"oklch(48% 0.007 290)\",\n \"700\": \"oklch(37% 0.006 290)\",\n \"800\": \"oklch(27% 0.005 290)\",\n \"900\": \"oklch(18% 0.003 290)\",\n \"950\": \"oklch(11% 0.002 290)\",\n },\n elderberry: {\n \"100\": \"oklch(97% 0.020 265)\",\n \"200\": \"oklch(93% 0.040 265)\",\n \"500\": \"oklch(55% 0.200 265)\",\n \"700\": \"oklch(42% 0.160 265)\",\n \"900\": \"oklch(30% 0.120 265)\",\n },\n greengage: {\n \"100\": \"oklch(97% 0.030 148)\",\n \"200\": \"oklch(93% 0.055 148)\",\n \"500\": \"oklch(58% 0.185 148)\",\n \"700\": \"oklch(45% 0.150 148)\",\n \"900\": \"oklch(33% 0.110 148)\",\n },\n mango: {\n \"100\": \"oklch(97% 0.025 65)\",\n \"200\": \"oklch(93% 0.045 65)\",\n \"500\": \"oklch(60% 0.175 65)\",\n \"700\": \"oklch(47% 0.142 65)\",\n \"900\": \"oklch(38% 0.110 65)\",\n },\n cherry: {\n \"100\": \"oklch(97% 0.030 27)\",\n \"200\": \"oklch(93% 0.055 27)\",\n \"500\": \"oklch(58% 0.200 27)\",\n \"700\": \"oklch(44% 0.168 27)\",\n \"900\": \"oklch(33% 0.110 27)\",\n },\n },\n font: {\n family: {\n sans: \"'Manrope', system-ui, sans-serif\",\n mono: \"'Fira Code', ui-monospace, monospace\",\n },\n size: {\n \"11\": \"0.6875rem\",\n \"12\": \"0.75rem\",\n \"13\": \"0.8125rem\",\n \"14\": \"0.875rem\",\n \"16\": \"1rem\",\n \"20\": \"1.25rem\",\n \"24\": \"1.5rem\",\n \"30\": \"1.875rem\",\n },\n weight: {\n regular: 400,\n medium: 500,\n semibold: 600,\n bold: 700,\n },\n lineHeight: {\n tight: 1.15,\n tighter: 1.2,\n snug: 1.25,\n compact: 1.3,\n normal: 1.4,\n relaxed: 1.5,\n loose: 1.6,\n },\n tracking: {\n tightest: \"-0.03em\",\n tighter: \"-0.02em\",\n tight: \"-0.01em\",\n normal: \"0em\",\n wide: \"0.02em\",\n wider: \"0.04em\",\n widest: \"0.08em\",\n },\n },\n spacing: {\n \"1\": \"0.25rem\",\n \"2\": \"0.5rem\",\n \"3\": \"0.75rem\",\n \"4\": \"1rem\",\n \"5\": \"1.25rem\",\n \"6\": \"1.5rem\",\n \"7\": \"1.75rem\",\n \"8\": \"2rem\",\n \"10\": \"2.5rem\",\n \"12\": \"3rem\",\n \"16\": \"4rem\",\n \"20\": \"5rem\",\n },\n radius: {\n none: \"0\",\n sm: \"0.25rem\",\n md: \"0.5rem\",\n lg: \"0.75rem\",\n xl: \"1rem\",\n \"2xl\": \"1.5rem\",\n full: \"9999px\",\n },\n duration: {\n instant: \"50ms\",\n fast: \"100ms\",\n normal: \"200ms\",\n moderate: \"300ms\",\n slow: \"500ms\",\n reduced: \"0ms\",\n },\n easing: {\n enter: \"cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n exit: \"cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n move: \"cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n spring: \"cubic-bezier(0.34, 1.56, 0.64, 1.00)\",\n linear: \"linear\",\n },\n motion: {\n \"fade-in\": \"200ms cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n \"fade-out\": \"100ms cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n \"slide-in\": \"300ms cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n \"slide-out\": \"100ms cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n micro: \"100ms cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n interactive: \"200ms cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n },\n shadow: {\n none: \"none\",\n sm: \"0 1px 2px oklch(18% 0.003 290 / 0.06)\",\n md: \"0 4px 6px -1px oklch(18% 0.003 290 / 0.10), 0 2px 4px -2px oklch(18% 0.003 290 / 0.10)\",\n lg: \"0 10px 15px -3px oklch(18% 0.003 290 / 0.10), 0 4px 6px -4px oklch(18% 0.003 290 / 0.07)\",\n xl: \"0 20px 25px -5px oklch(18% 0.003 290 / 0.10), 0 8px 10px -6px oklch(18% 0.003 290 / 0.10)\",\n },\n controlHeight: {\n sm: \"1.75rem\",\n md: \"2.25rem\",\n lg: \"2.75rem\",\n },\n zIndex: {\n \"0\": 0,\n \"10\": 10,\n \"100\": 100,\n \"200\": 200,\n \"300\": 300,\n \"400\": 400,\n \"500\": 500,\n \"600\": 600,\n },\n borderWidth: {\n \"1\": \"1px\",\n \"2\": \"2px\",\n },\n opacity: {\n \"40\": 0.4,\n \"60\": 0.6,\n },\n iconSize: {\n xs: \"0.75rem\",\n sm: \"1rem\",\n md: \"1.25rem\",\n lg: \"1.5rem\",\n xl: \"2rem\",\n },\n breakpoint: {\n sm: \"640px\",\n md: \"768px\",\n lg: \"1024px\",\n xl: \"1280px\",\n \"2xl\": \"1536px\",\n },\n} as const\n\nexport type Tokens = typeof tokens\n\n/* The brand map's type and role list, generated from brand.css. Re-exported here\n so a consumer has one entry point rather than two. */\nexport type { BrandMap } from './brand'\nexport { brandRoles } from './brand'\n"]}
1
+ {"version":3,"sources":["../src/brand.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/* ─── haus / primitives ──────────────────────────────────────────────────────\n Raw values only. No component or semantic meaning.\n Nothing outside this file should define raw values.\n Components must never reference these directly. Use semantics.css.\n\n GENERATED FROM src/tokens.json. Do not edit.\n Regenerate with `npm run tokens`; `npm run tokens:check` fails CI if stale.\n ─────────────────────────────────────────────────────────────────────────── */\n\n/**\n * The entries every brand must supply, generated from brand.css.\n *\n * A brand file is CSS, so this cannot check it directly. What it does check is\n * the object form: build a brand in TypeScript, satisfy this type, and a missing\n * or misspelled role is a compile error rather than an unresolved var() that\n * drops a declaration with no warning at all.\n */\nexport interface BrandMapBase {\n '--haus-brand-surface-default': string\n '--haus-brand-surface-subtle': string\n '--haus-brand-surface-raised': string\n '--haus-brand-surface-overlay': string\n '--haus-brand-surface-sunken': string\n '--haus-brand-surface-inverse': string\n '--haus-brand-surface-disabled': string\n '--haus-brand-surface-inverse-hover': string\n '--haus-brand-ink-primary': string\n '--haus-brand-ink-secondary': string\n '--haus-brand-ink-tertiary': string\n '--haus-brand-ink-disabled': string\n '--haus-brand-ink-inverse': string\n '--haus-brand-ink-link': string\n '--haus-brand-ink-on-primary': string\n '--haus-brand-border-subtle': string\n '--haus-brand-border-default': string\n '--haus-brand-border-strong': string\n '--haus-brand-border-disabled': string\n '--haus-brand-border-inverse': string\n '--haus-brand-border-inverse-hover': string\n '--haus-brand-primary-default': string\n '--haus-brand-primary-hover': string\n '--haus-brand-primary-pressed': string\n '--haus-brand-primary-subtle': string\n '--haus-brand-primary-on-subtle': string\n '--haus-brand-primary-disabled': string\n '--haus-brand-backdrop': string\n}\n\n/**\n * The optional half: info, success, warning and error.\n *\n * A product whose statuses are not those four semantics omits this tier and\n * inherits haus's from :root, because custom properties inherit and a named\n * brand only overrides what it declares. Optional here, and all-or-nothing per\n * ramp in brand.test.ts, which types cannot express.\n */\nexport interface BrandMapFeedback {\n '--haus-brand-info-subtle': string\n '--haus-brand-info-border': string\n '--haus-brand-info-default': string\n '--haus-brand-info-on-subtle': string\n '--haus-brand-info-on-default': string\n '--haus-brand-info-emphasis': string\n '--haus-brand-success-subtle': string\n '--haus-brand-success-border': string\n '--haus-brand-success-default': string\n '--haus-brand-success-on-subtle': string\n '--haus-brand-success-on-default': string\n '--haus-brand-success-solid': string\n '--haus-brand-success-emphasis': string\n '--haus-brand-warning-subtle': string\n '--haus-brand-warning-border': string\n '--haus-brand-warning-default': string\n '--haus-brand-warning-on-subtle': string\n '--haus-brand-warning-on-default': string\n '--haus-brand-warning-solid': string\n '--haus-brand-warning-emphasis': string\n '--haus-brand-error-subtle': string\n '--haus-brand-error-border': string\n '--haus-brand-error-default': string\n '--haus-brand-error-on-subtle': string\n '--haus-brand-error-on-default': string\n '--haus-brand-error-emphasis': string\n}\n\n/**\n * The other optional half: what a product re-decides that is not a colour.\n *\n * Radius and elevation, taken from what drift and vault actually changed. Not\n * z-index, opacity, border-width or spacing: nobody re-decides those, and the\n * overrides that looked like it were the literal values of haus's own\n * primitives typed out. All-or-nothing per group, in brand.test.ts.\n */\nexport interface BrandMapForm {\n '--haus-brand-radius-control': string\n '--haus-brand-radius-surface': string\n '--haus-brand-radius-overlay': string\n '--haus-brand-radius-marker': string\n '--haus-brand-elevation-raised': string\n '--haus-brand-elevation-floating': string\n '--haus-brand-elevation-overlay': string\n '--haus-brand-modal-width-sm': string\n '--haus-brand-modal-width-md': string\n '--haus-brand-modal-width-lg': string\n}\n\n/** A complete brand: the base tier, and as much of the optional tiers as applies. */\nexport type BrandMap = BrandMapBase & Partial<BrandMapFeedback> & Partial<BrandMapForm>\n\n/** The role names themselves, for anyone generating a brand rather than writing one. */\nexport const brandRoles = [\n '--haus-brand-surface-default',\n '--haus-brand-surface-subtle',\n '--haus-brand-surface-raised',\n '--haus-brand-surface-overlay',\n '--haus-brand-surface-sunken',\n '--haus-brand-surface-inverse',\n '--haus-brand-surface-disabled',\n '--haus-brand-surface-inverse-hover',\n '--haus-brand-ink-primary',\n '--haus-brand-ink-secondary',\n '--haus-brand-ink-tertiary',\n '--haus-brand-ink-disabled',\n '--haus-brand-ink-inverse',\n '--haus-brand-ink-link',\n '--haus-brand-ink-on-primary',\n '--haus-brand-border-subtle',\n '--haus-brand-border-default',\n '--haus-brand-border-strong',\n '--haus-brand-border-disabled',\n '--haus-brand-border-inverse',\n '--haus-brand-border-inverse-hover',\n '--haus-brand-primary-default',\n '--haus-brand-primary-hover',\n '--haus-brand-primary-pressed',\n '--haus-brand-primary-subtle',\n '--haus-brand-primary-on-subtle',\n '--haus-brand-primary-disabled',\n '--haus-brand-backdrop',\n '--haus-brand-info-subtle',\n '--haus-brand-info-border',\n '--haus-brand-info-default',\n '--haus-brand-info-on-subtle',\n '--haus-brand-info-on-default',\n '--haus-brand-info-emphasis',\n '--haus-brand-success-subtle',\n '--haus-brand-success-border',\n '--haus-brand-success-default',\n '--haus-brand-success-on-subtle',\n '--haus-brand-success-on-default',\n '--haus-brand-success-solid',\n '--haus-brand-success-emphasis',\n '--haus-brand-warning-subtle',\n '--haus-brand-warning-border',\n '--haus-brand-warning-default',\n '--haus-brand-warning-on-subtle',\n '--haus-brand-warning-on-default',\n '--haus-brand-warning-solid',\n '--haus-brand-warning-emphasis',\n '--haus-brand-error-subtle',\n '--haus-brand-error-border',\n '--haus-brand-error-default',\n '--haus-brand-error-on-subtle',\n '--haus-brand-error-on-default',\n '--haus-brand-error-emphasis',\n '--haus-brand-radius-control',\n '--haus-brand-radius-surface',\n '--haus-brand-radius-overlay',\n '--haus-brand-radius-marker',\n '--haus-brand-elevation-raised',\n '--haus-brand-elevation-floating',\n '--haus-brand-elevation-overlay',\n '--haus-brand-modal-width-sm',\n '--haus-brand-modal-width-md',\n '--haus-brand-modal-width-lg',\n] as const\n\n/** The required half. A brand supplying fewer than these renders unstyled. */\nexport const brandRolesBase = [\n '--haus-brand-surface-default',\n '--haus-brand-surface-subtle',\n '--haus-brand-surface-raised',\n '--haus-brand-surface-overlay',\n '--haus-brand-surface-sunken',\n '--haus-brand-surface-inverse',\n '--haus-brand-surface-disabled',\n '--haus-brand-surface-inverse-hover',\n '--haus-brand-ink-primary',\n '--haus-brand-ink-secondary',\n '--haus-brand-ink-tertiary',\n '--haus-brand-ink-disabled',\n '--haus-brand-ink-inverse',\n '--haus-brand-ink-link',\n '--haus-brand-ink-on-primary',\n '--haus-brand-border-subtle',\n '--haus-brand-border-default',\n '--haus-brand-border-strong',\n '--haus-brand-border-disabled',\n '--haus-brand-border-inverse',\n '--haus-brand-border-inverse-hover',\n '--haus-brand-primary-default',\n '--haus-brand-primary-hover',\n '--haus-brand-primary-pressed',\n '--haus-brand-primary-subtle',\n '--haus-brand-primary-on-subtle',\n '--haus-brand-primary-disabled',\n '--haus-brand-backdrop',\n] as const\n\n/** The optional colour half, grouped by the ramp that has to be complete or absent. */\nexport const brandRolesFeedback = [\n '--haus-brand-info-subtle',\n '--haus-brand-info-border',\n '--haus-brand-info-default',\n '--haus-brand-info-on-subtle',\n '--haus-brand-info-on-default',\n '--haus-brand-info-emphasis',\n '--haus-brand-success-subtle',\n '--haus-brand-success-border',\n '--haus-brand-success-default',\n '--haus-brand-success-on-subtle',\n '--haus-brand-success-on-default',\n '--haus-brand-success-solid',\n '--haus-brand-success-emphasis',\n '--haus-brand-warning-subtle',\n '--haus-brand-warning-border',\n '--haus-brand-warning-default',\n '--haus-brand-warning-on-subtle',\n '--haus-brand-warning-on-default',\n '--haus-brand-warning-solid',\n '--haus-brand-warning-emphasis',\n '--haus-brand-error-subtle',\n '--haus-brand-error-border',\n '--haus-brand-error-default',\n '--haus-brand-error-on-subtle',\n '--haus-brand-error-on-default',\n '--haus-brand-error-emphasis',\n] as const\n\n/** The optional non-colour half: radius and elevation. */\nexport const brandRolesForm = [\n '--haus-brand-radius-control',\n '--haus-brand-radius-surface',\n '--haus-brand-radius-overlay',\n '--haus-brand-radius-marker',\n '--haus-brand-elevation-raised',\n '--haus-brand-elevation-floating',\n '--haus-brand-elevation-overlay',\n '--haus-brand-modal-width-sm',\n '--haus-brand-modal-width-md',\n '--haus-brand-modal-width-lg',\n] as const\n","/* ─── haus / tokens ──────────────────────────────────────────────────────────\n Typed constants for the primitive layer.\n\n The CSS custom properties are the runtime form; this exists for the places\n they cannot reach: @media conditions, build config, style-in-JS. Semantic\n tokens are deliberately absent: their whole job is to be swappable at\n runtime, which freezing them into a constant would defeat.\n\n GENERATED FROM src/tokens.json. Do not edit.\n Regenerate with `npm run tokens`; `npm run tokens:check` fails CI if stale.\n ─────────────────────────────────────────────────────────────────────────── */\n\nexport const tokens = {\n color: {\n aronia: {\n \"100\": \"oklch(97% 0.012 300)\",\n \"200\": \"oklch(92% 0.028 300)\",\n \"300\": \"oklch(84% 0.058 300)\",\n \"400\": \"oklch(72% 0.100 300)\",\n \"500\": \"oklch(52% 0.138 300)\",\n \"600\": \"oklch(43% 0.125 300)\",\n \"700\": \"oklch(35% 0.105 300)\",\n \"800\": \"oklch(26% 0.080 300)\",\n \"850\": \"oklch(22% 0.066 300)\",\n \"900\": \"oklch(18% 0.052 300)\",\n \"950\": \"oklch(12% 0.032 300)\",\n },\n damson: {\n \"0\": \"oklch(100% 0 0)\",\n \"50\": \"oklch(99% 0.003 290)\",\n \"100\": \"oklch(97% 0.006 290)\",\n \"200\": \"oklch(93% 0.008 290)\",\n \"300\": \"oklch(86% 0.010 290)\",\n \"400\": \"oklch(74% 0.010 290)\",\n \"500\": \"oklch(60% 0.008 290)\",\n \"600\": \"oklch(48% 0.007 290)\",\n \"700\": \"oklch(37% 0.006 290)\",\n \"800\": \"oklch(27% 0.005 290)\",\n \"900\": \"oklch(18% 0.003 290)\",\n \"950\": \"oklch(11% 0.002 290)\",\n },\n elderberry: {\n \"100\": \"oklch(97% 0.020 265)\",\n \"200\": \"oklch(93% 0.040 265)\",\n \"500\": \"oklch(55% 0.200 265)\",\n \"700\": \"oklch(42% 0.160 265)\",\n \"900\": \"oklch(30% 0.120 265)\",\n },\n greengage: {\n \"100\": \"oklch(97% 0.030 148)\",\n \"200\": \"oklch(93% 0.055 148)\",\n \"500\": \"oklch(58% 0.185 148)\",\n \"700\": \"oklch(45% 0.150 148)\",\n \"900\": \"oklch(33% 0.110 148)\",\n },\n mango: {\n \"100\": \"oklch(97% 0.025 65)\",\n \"200\": \"oklch(93% 0.045 65)\",\n \"500\": \"oklch(60% 0.175 65)\",\n \"700\": \"oklch(47% 0.142 65)\",\n \"900\": \"oklch(38% 0.110 65)\",\n },\n cherry: {\n \"100\": \"oklch(97% 0.030 27)\",\n \"200\": \"oklch(93% 0.055 27)\",\n \"500\": \"oklch(58% 0.200 27)\",\n \"700\": \"oklch(44% 0.168 27)\",\n \"900\": \"oklch(33% 0.110 27)\",\n },\n },\n font: {\n family: {\n sans: \"'Manrope', system-ui, sans-serif\",\n mono: \"'Fira Code', ui-monospace, monospace\",\n },\n size: {\n \"11\": \"0.6875rem\",\n \"12\": \"0.75rem\",\n \"13\": \"0.8125rem\",\n \"14\": \"0.875rem\",\n \"16\": \"1rem\",\n \"20\": \"1.25rem\",\n \"24\": \"1.5rem\",\n \"30\": \"1.875rem\",\n },\n weight: {\n regular: 400,\n medium: 500,\n semibold: 600,\n bold: 700,\n },\n lineHeight: {\n tight: 1.15,\n tighter: 1.2,\n snug: 1.25,\n compact: 1.3,\n normal: 1.4,\n relaxed: 1.5,\n loose: 1.6,\n },\n tracking: {\n tightest: \"-0.03em\",\n tighter: \"-0.02em\",\n tight: \"-0.01em\",\n normal: \"0em\",\n wide: \"0.02em\",\n wider: \"0.04em\",\n widest: \"0.08em\",\n },\n },\n spacing: {\n \"1\": \"0.25rem\",\n \"2\": \"0.5rem\",\n \"3\": \"0.75rem\",\n \"4\": \"1rem\",\n \"5\": \"1.25rem\",\n \"6\": \"1.5rem\",\n \"7\": \"1.75rem\",\n \"8\": \"2rem\",\n \"10\": \"2.5rem\",\n \"12\": \"3rem\",\n \"16\": \"4rem\",\n \"20\": \"5rem\",\n },\n radius: {\n none: \"0\",\n sm: \"0.25rem\",\n md: \"0.5rem\",\n lg: \"0.75rem\",\n xl: \"1rem\",\n \"2xl\": \"1.5rem\",\n full: \"9999px\",\n },\n duration: {\n instant: \"50ms\",\n fast: \"100ms\",\n normal: \"200ms\",\n moderate: \"300ms\",\n slow: \"500ms\",\n reduced: \"0ms\",\n },\n easing: {\n enter: \"cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n exit: \"cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n move: \"cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n spring: \"cubic-bezier(0.34, 1.56, 0.64, 1.00)\",\n linear: \"linear\",\n },\n motion: {\n \"fade-in\": \"200ms cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n \"fade-out\": \"100ms cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n \"slide-in\": \"300ms cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n \"slide-out\": \"100ms cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n micro: \"100ms cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n interactive: \"200ms cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n },\n shadow: {\n none: \"none\",\n sm: \"0 1px 2px oklch(18% 0.003 290 / 0.06)\",\n md: \"0 4px 6px -1px oklch(18% 0.003 290 / 0.10), 0 2px 4px -2px oklch(18% 0.003 290 / 0.10)\",\n lg: \"0 10px 15px -3px oklch(18% 0.003 290 / 0.10), 0 4px 6px -4px oklch(18% 0.003 290 / 0.07)\",\n xl: \"0 20px 25px -5px oklch(18% 0.003 290 / 0.10), 0 8px 10px -6px oklch(18% 0.003 290 / 0.10)\",\n },\n controlHeight: {\n sm: \"1.75rem\",\n md: \"2.25rem\",\n lg: \"2.75rem\",\n },\n zIndex: {\n \"0\": 0,\n \"10\": 10,\n \"100\": 100,\n \"200\": 200,\n \"300\": 300,\n \"400\": 400,\n \"500\": 500,\n \"600\": 600,\n },\n borderWidth: {\n \"1\": \"1px\",\n \"2\": \"2px\",\n },\n opacity: {\n \"40\": 0.4,\n \"60\": 0.6,\n },\n iconSize: {\n xs: \"0.75rem\",\n sm: \"1rem\",\n md: \"1.25rem\",\n lg: \"1.5rem\",\n xl: \"2rem\",\n },\n breakpoint: {\n sm: \"640px\",\n md: \"768px\",\n lg: \"1024px\",\n xl: \"1280px\",\n \"2xl\": \"1536px\",\n },\n} as const\n\nexport type Tokens = typeof tokens\n\n/* The brand map's type and role list, generated from brand.css. Re-exported here\n so a consumer has one entry point rather than two. */\nexport type { BrandMap } from './brand'\nexport { brandRoles } from './brand'\n"]}
@@ -163,5 +163,17 @@
163
163
  --haus-icon-lg: 1.5rem; /* 24px, with heading */
164
164
  --haus-icon-xl: 2rem; /* 32px, standalone or decorative */
165
165
 
166
+ /* ── Overlay widths ──────────────────────────────────────────────────────── */
167
+ /* How wide a floating surface may get. A proportion of the product's own layout, which is why Modal's three are a brand entry. */
168
+ --haus-overlay-width-xs: 22.5rem; /* 360px, Toast. One value, and a plain role rather than a brand entry because no consumer has disagreed with it yet. */
169
+ --haus-overlay-width-sm: 25rem; /* 400px, Modal sm. Confirm and short form. */
170
+ --haus-overlay-width-md: 35rem; /* 560px, Modal md, the default. */
171
+ --haus-overlay-width-lg: 45rem; /* 720px, Modal lg. Code, tables and previews. */
172
+
173
+ /* ── Component geometry ──────────────────────────────────────────────────── */
174
+ /* On no ladder and not spacing. Literals inside components until haus#53 put width and height into the hardcoded-value rule. */
175
+ --haus-size-marker-dot: 0.375rem; /* 6px. Badge's status dot and Radio's centre, the same value written twice with no name, which is haus#34's signal. */
176
+ --haus-size-toggle-track: 2.25rem; /* 36px. Reads as control-height-md by coincidence and is not one: it is two thumbs and the travel between them. */
177
+
166
178
  }
167
179
  }
@@ -6,19 +6,22 @@
6
6
  radius, elevation and motion. Two kinds of primitive read remain in the
7
7
  components, both deliberate:
8
8
 
9
- · 31 declarations take a size off the space ladder, on height, width,
9
+ · 29 declarations take a size off the space ladder, on height, width,
10
10
  min/max and transform offsets: the avatar sizes and its status dot, the
11
11
  checkbox and radio boxes, the toggle track and thumb and the thumb's
12
- travel, the modal's close button and max height, the toast and modal
13
- entry offsets, the textarea's minimum height and the select chevron's
14
- offset. A size is a value, not a role, and calling a 16px checkbox
15
- --haus-space-inset-md would say something untrue.
16
- · 40 read a primitive that has no alias here because its own name already
17
- is the role: 32 --haus-font-sans, five control heights and three
18
- --haus-icon-sm. A font family is not a role and there is no honest alias
19
- to invent for it. Button used to read --haus-tracking-normal here too;
20
- haus#37 moved it onto --haus-type-label-tracking, so tracking is a role
21
- everywhere now and no component reads the primitive ladder.
12
+ travel, the modal's max height, the toast and modal entry offsets, the
13
+ textarea's minimum height and the select chevron's offset. A size is a
14
+ value, not a role, and calling a 16px checkbox --haus-space-inset-md
15
+ would say something untrue.
16
+ · 50 read a primitive that has no alias here because its own name already
17
+ is the role: 32 --haus-font-sans, five control heights, and thirteen icon
18
+ sizes (three --haus-icon-sm, four --haus-icon-lg, six --haus-icon-xs). A
19
+ font family is not a role and there is no honest alias to invent for it.
20
+ Button used to read --haus-tracking-normal here too; haus#37 moved it onto
21
+ --haus-type-label-tracking, so tracking is a role everywhere and no
22
+ component reads the tracking ladder. haus#43 added the icon reads: the
23
+ chevron and the two close buttons bind their box and glyph to the icon
24
+ scale rather than a raw size.
22
25
 
23
26
  This was 71 before haus#27. Stacking, border width and opacity used to be
24
27
  primitives wearing role names, so a product that wanted the stacking order
@@ -143,6 +146,19 @@
143
146
  --haus-type-label-xs-leading: var(--haus-leading-normal);
144
147
  --haus-type-label-xs-tracking: var(--haus-tracking-widest);
145
148
 
149
+ /* Caption: the hint and error text under a form control. haus#40, and the
150
+ same shape as haus#34 and the eyebrow one role over. Eleven blocks across
151
+ six components read label-xs's size and leading and set neither its weight
152
+ nor its tracking, so they rendered 11px regular with no tracking against a
153
+ role that says medium and 0.08em, which Badge is the only real consumer
154
+ of. Caption is the role they were reaching for: 11px, regular, normal
155
+ tracking, the voice a control explains itself in. The colour is not part
156
+ of it, so a hint stays ink-secondary and an error message error. */
157
+ --haus-type-caption-size: var(--haus-text-11);
158
+ --haus-type-caption-weight: var(--haus-weight-regular);
159
+ --haus-type-caption-leading: var(--haus-leading-normal);
160
+ --haus-type-caption-tracking: var(--haus-tracking-normal);
161
+
146
162
  --haus-type-label-sm-size: var(--haus-text-12);
147
163
  --haus-type-label-sm-weight: var(--haus-weight-medium);
148
164
  --haus-type-label-sm-leading: var(--haus-leading-normal);
@@ -319,17 +335,29 @@
319
335
  /* ── Radius ──────────────────────────────────────────────────────────────
320
336
  Named for what is rounded, so a component asks for the shape of the
321
337
  thing rather than a size off the ramp. */
322
- --haus-radius-control: var(--haus-radius-md); /* Button, Input, Select, Textarea */
323
- --haus-radius-surface: var(--haus-radius-lg); /* Card, Toast */
324
- --haus-radius-overlay: var(--haus-radius-xl); /* Modal */
325
- --haus-radius-marker: var(--haus-radius-sm); /* Checkbox, Modal/Toast icons */
338
+ --haus-radius-control: var(--haus-brand-radius-control); /* Button, Input, Select, Textarea */
339
+ --haus-radius-surface: var(--haus-brand-radius-surface); /* Card, Toast */
340
+ --haus-radius-overlay: var(--haus-brand-radius-overlay); /* Modal */
341
+ --haus-radius-marker: var(--haus-brand-radius-marker); /* Checkbox, Modal/Toast icons */
326
342
  --haus-radius-pill: var(--haus-radius-full); /* Badge, Toggle track */
327
343
 
328
344
  /* ── Elevation ───────────────────────────────────────────────────────────
329
345
  Named for how high the thing sits, rather than how large its shadow is. */
330
- --haus-elevation-raised: var(--haus-shadow-sm); /* Toggle knob */
331
- --haus-elevation-floating: var(--haus-shadow-lg); /* Card, Toast */
332
- --haus-elevation-overlay: var(--haus-shadow-xl); /* Modal */
346
+ --haus-elevation-raised: var(--haus-brand-elevation-raised); /* Toggle knob */
347
+ --haus-elevation-floating: var(--haus-brand-elevation-floating); /* Card, Toast */
348
+ --haus-elevation-overlay: var(--haus-brand-elevation-overlay); /* Modal */
349
+ }
350
+
351
+ /* ── Overlay width ─────────────────────────────────────────────────────────
352
+ Modal's three sizes, which lived as literals in the component until haus#53.
353
+ A role rather than a primitive because a width is a proportion of the
354
+ product's own layout: haus's suit a web app and vault's four are narrower
355
+ for a dense desktop one. */
356
+ :root,
357
+ [data-haus-theme] {
358
+ --haus-modal-width-sm: var(--haus-brand-modal-width-sm);
359
+ --haus-modal-width-md: var(--haus-brand-modal-width-md);
360
+ --haus-modal-width-lg: var(--haus-brand-modal-width-lg);
333
361
 
334
362
  /* ── Stacking ────────────────────────────────────────────────────────────
335
363
  Named for what sits at each height, rather than for the number. The
@@ -371,7 +399,23 @@
371
399
  Control heights are not on that ladder at all: 36px and 44px are not
372
400
  steps of it. They are their own primitive scale, --haus-control-height-sm,
373
401
  -md and -lg, whose names are already the role, so they are read direct
374
- like --haus-border-width-default. */
402
+ like --haus-border-width-default.
403
+
404
+ Three values were on no ladder and had no name, found by haus#53 when
405
+ width and height joined the hardcoded-value rule. Each was written into a
406
+ component and invisible, which is the haus#43 blind spot again: the rule
407
+ held min-height and not width. */
408
+ --haus-toast-width: var(--haus-overlay-width-xs); /* 360px. Modal's widths are a brand
409
+ entry because two products disagree;
410
+ this is a plain role because none
411
+ has yet. Promote it if one does. */
412
+ --haus-toggle-track-width: var(--haus-size-toggle-track); /* 36px. Reads as control-height-md by
413
+ coincidence and is not one: it is
414
+ two thumbs and the travel between. */
415
+ --haus-marker-dot: var(--haus-size-marker-dot); /* 6px. Badge's status dot and Radio's
416
+ inner circle, the same value twice
417
+ with no name, which is haus#34's
418
+ signal. */
375
419
 
376
420
 
377
421
  }
package/dist/tokens.json CHANGED
@@ -488,6 +488,10 @@
488
488
  "primary-disabled": {
489
489
  "$value": "{color.damson.200}"
490
490
  },
491
+ "backdrop": {
492
+ "$value": "oklch(from var(--haus-damson-950) l c h / var(--haus-opacity-60))",
493
+ "$description": "Modal scrim, applied at --opacity-overlay (0.6) in CSS"
494
+ },
491
495
  "info-subtle": {
492
496
  "$value": "{color.elderberry.100}"
493
497
  },
@@ -570,9 +574,35 @@
570
574
  "error-emphasis": {
571
575
  "$value": "{color.cherry.900}"
572
576
  },
573
- "backdrop": {
574
- "$value": "oklch(from var(--haus-damson-950) l c h / var(--haus-opacity-60))",
575
- "$description": "Modal scrim, applied at --opacity-overlay (0.6) in CSS"
577
+ "radius-control": {
578
+ "$value": "var(--haus-radius-md)"
579
+ },
580
+ "radius-surface": {
581
+ "$value": "var(--haus-radius-lg)"
582
+ },
583
+ "radius-overlay": {
584
+ "$value": "var(--haus-radius-xl)"
585
+ },
586
+ "radius-marker": {
587
+ "$value": "var(--haus-radius-sm)"
588
+ },
589
+ "elevation-raised": {
590
+ "$value": "var(--haus-shadow-sm)"
591
+ },
592
+ "elevation-floating": {
593
+ "$value": "var(--haus-shadow-lg)"
594
+ },
595
+ "elevation-overlay": {
596
+ "$value": "var(--haus-shadow-xl)"
597
+ },
598
+ "modal-width-sm": {
599
+ "$value": "var(--haus-overlay-width-sm)"
600
+ },
601
+ "modal-width-md": {
602
+ "$value": "var(--haus-overlay-width-md)"
603
+ },
604
+ "modal-width-lg": {
605
+ "$value": "var(--haus-overlay-width-lg)"
576
606
  }
577
607
  }
578
608
  },
@@ -845,5 +875,37 @@
845
875
  "$value": "1536px",
846
876
  "$description": "Large screens"
847
877
  }
878
+ },
879
+ "overlayWidth": {
880
+ "$type": "dimension",
881
+ "$description": "How wide a floating surface is allowed to get. Not a step off the spacing ladder: these are proportions of a product's own layout, which is why the modal three are a brand entry and a consumer may restate them.",
882
+ "xs": {
883
+ "$value": "22.5rem",
884
+ "$description": "360px, Toast. One value, and a plain role rather than a brand entry because no consumer has disagreed with it yet."
885
+ },
886
+ "sm": {
887
+ "$value": "25rem",
888
+ "$description": "400px, Modal sm. Confirm and short form."
889
+ },
890
+ "md": {
891
+ "$value": "35rem",
892
+ "$description": "560px, Modal md, the default."
893
+ },
894
+ "lg": {
895
+ "$value": "45rem",
896
+ "$description": "720px, Modal lg. Code, tables and previews."
897
+ }
898
+ },
899
+ "size": {
900
+ "$type": "dimension",
901
+ "$description": "Component geometry that is on no ladder and is not spacing. Each was a literal inside a component until haus#53 put width and height into the hardcoded-value rule, which had held min-height and not width since haus#43 first noted the gap.",
902
+ "marker-dot": {
903
+ "$value": "0.375rem",
904
+ "$description": "6px. Badge's status dot and Radio's centre, the same value written twice with no name, which is haus#34's signal."
905
+ },
906
+ "toggle-track": {
907
+ "$value": "2.25rem",
908
+ "$description": "36px. Reads as control-height-md by coincidence and is not one: it is two thumbs and the travel between them."
909
+ }
848
910
  }
849
911
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haus-tokens",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "haus design tokens: OKLCH colour, type, spacing, radius, shadow and motion, as W3C-DTCG JSON, CSS custom properties, and typed JS constants.",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -58,7 +58,7 @@
58
58
  "tsup": "^8.5.1",
59
59
  "tsx": "^4.23.12",
60
60
  "typescript": "^5.4.5",
61
- "vitest": "^4.1.11",
61
+ "vitest": "^5.0.0",
62
62
  "haus-colour-utils": "^1.0.0"
63
63
  },
64
64
  "scripts": {