@hanzo/design 0.4.13 → 0.5.1

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.
@@ -0,0 +1,30 @@
1
+ /** The palette a brand declares. Every field is optional: an undeclared key
2
+ * leaves the design system's own value standing rather than overwriting it. */
3
+ export interface BrandTheme {
4
+ surface1?: string;
5
+ surface2?: string;
6
+ surface3?: string;
7
+ neutral1?: string;
8
+ neutral2?: string;
9
+ neutral3?: string;
10
+ accent1?: string;
11
+ accent2?: string;
12
+ accent3?: string;
13
+ border?: string;
14
+ success?: string;
15
+ warning?: string;
16
+ error?: string;
17
+ }
18
+ /**
19
+ * The tokens a brand's theme sets, as `{ '--background': '#000', … }`.
20
+ *
21
+ * Only ground, ink, accent and the edges drawn on them. The radius scale, the
22
+ * type ramp, spacing, motion and z are NOT here and must not be: they are the
23
+ * system's grammar rather than a brand's voice, and a brand that redefines them
24
+ * is a fork wearing a stylesheet.
25
+ */
26
+ export declare function themeToTokens(theme: BrandTheme): Record<string, string>;
27
+ /** Apply a brand's theme to a live document — for an app that resolves its brand
28
+ * at runtime and so cannot import a build-time stylesheet. */
29
+ export declare function applyBrandTheme(theme: BrandTheme, el: HTMLElement): void;
30
+ //# sourceMappingURL=brand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brand.d.ts","sourceRoot":"","sources":["../src/brand.ts"],"names":[],"mappings":"AAaA;gFACgF;AAChF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAmBD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWvE;AAED;+DAC+D;AAC/D,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CAIxE"}
package/dist/brand.js ADDED
@@ -0,0 +1,58 @@
1
+ // A brand's declared theme, projected onto the semantic tokens.
2
+ //
3
+ // A brand package (@luxfi/brand, @zooai/brand) carries its own light and dark
4
+ // theme in brand.json. This is the ONE place that says which semantic token each
5
+ // of those answers for — the design system owns the token contract, a brand owns
6
+ // the values, and neither holds a copy of the other.
7
+ //
8
+ // It exists because that mapping was about to be written twice: once in each
9
+ // brand package to generate a stylesheet, and once in every app that resolves its
10
+ // brand at runtime and cannot import a build-time stylesheet. Two copies of a
11
+ // mapping is how a brand comes to look like itself in one surface and not
12
+ // another.
13
+ /** theme key → the semantic tokens it answers for. */
14
+ const OWNS = {
15
+ surface1: ['--background'],
16
+ surface2: ['--card', '--popover', '--muted'],
17
+ surface3: ['--accent'],
18
+ neutral1: ['--foreground', '--card-foreground', '--popover-foreground', '--accent-foreground'],
19
+ neutral2: ['--muted-foreground'],
20
+ neutral3: [],
21
+ accent1: ['--primary'],
22
+ accent2: [],
23
+ accent3: [],
24
+ border: ['--border'],
25
+ success: ['--state-success'],
26
+ warning: ['--state-warning'],
27
+ error: ['--state-error'],
28
+ };
29
+ /**
30
+ * The tokens a brand's theme sets, as `{ '--background': '#000', … }`.
31
+ *
32
+ * Only ground, ink, accent and the edges drawn on them. The radius scale, the
33
+ * type ramp, spacing, motion and z are NOT here and must not be: they are the
34
+ * system's grammar rather than a brand's voice, and a brand that redefines them
35
+ * is a fork wearing a stylesheet.
36
+ */
37
+ export function themeToTokens(theme) {
38
+ const out = {};
39
+ for (const [key, tokens] of Object.entries(OWNS)) {
40
+ const value = theme[key];
41
+ if (!value)
42
+ continue;
43
+ for (const token of tokens)
44
+ out[token] = value;
45
+ }
46
+ // --primary carries ink on top of it, so the accent names its own contrast
47
+ // partner rather than leaving whatever the previous theme set.
48
+ if (theme.accent1 && theme.surface1)
49
+ out['--primary-foreground'] = theme.surface1;
50
+ return out;
51
+ }
52
+ /** Apply a brand's theme to a live document — for an app that resolves its brand
53
+ * at runtime and so cannot import a build-time stylesheet. */
54
+ export function applyBrandTheme(theme, el) {
55
+ for (const [name, value] of Object.entries(themeToTokens(theme))) {
56
+ el.style.setProperty(name, value);
57
+ }
58
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './tokens.gen.js';
2
+ export * from './brand.js';
2
3
  import { type CssVarName } from './tokens.gen.js';
3
4
  /** A token name with the leading `--` omitted: `'background'` for `'--background'`. */
4
5
  export type TokenName = CssVarName extends `--${infer N}` ? N : never;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EAAW,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE1D,uFAAuF;AACvF,MAAM,MAAM,SAAS,GAAG,UAAU,SAAS,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAA;AAErE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAI9E;AAED,oFAAoF;AACpF,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAE/D;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQlD;AAKD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACzE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAW,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE1D,uFAAuF;AACvF,MAAM,MAAM,SAAS,GAAG,UAAU,SAAS,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAA;AAErE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAI9E;AAED,oFAAoF;AACpF,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAE/D;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQlD;AAKD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACzE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@
10
10
  // import { colors, spacing, radius, cssVar } from '@hanzo/design' // the code layer
11
11
  //
12
12
  export * from './tokens.gen.js';
13
+ export * from './brand.js';
13
14
  import { cssVars } from './tokens.gen.js';
14
15
  /**
15
16
  * A `var(--name, <authored literal>)` reference to a token — the ONE way code
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/design",
3
- "version": "0.4.13",
3
+ "version": "0.5.1",
4
4
  "packageManager": "pnpm@11.17.0",
5
5
  "description": "Hanzo Design System \u2014 monochrome, dark-default tokens + components + brand assets, the single source of truth for every Hanzo surface. CSS + typed programmatic tokens.",
6
6
  "license": "MIT OR Apache-2.0",
package/src/brand.ts ADDED
@@ -0,0 +1,76 @@
1
+ // A brand's declared theme, projected onto the semantic tokens.
2
+ //
3
+ // A brand package (@luxfi/brand, @zooai/brand) carries its own light and dark
4
+ // theme in brand.json. This is the ONE place that says which semantic token each
5
+ // of those answers for — the design system owns the token contract, a brand owns
6
+ // the values, and neither holds a copy of the other.
7
+ //
8
+ // It exists because that mapping was about to be written twice: once in each
9
+ // brand package to generate a stylesheet, and once in every app that resolves its
10
+ // brand at runtime and cannot import a build-time stylesheet. Two copies of a
11
+ // mapping is how a brand comes to look like itself in one surface and not
12
+ // another.
13
+
14
+ /** The palette a brand declares. Every field is optional: an undeclared key
15
+ * leaves the design system's own value standing rather than overwriting it. */
16
+ export interface BrandTheme {
17
+ surface1?: string
18
+ surface2?: string
19
+ surface3?: string
20
+ neutral1?: string
21
+ neutral2?: string
22
+ neutral3?: string
23
+ accent1?: string
24
+ accent2?: string
25
+ accent3?: string
26
+ border?: string
27
+ success?: string
28
+ warning?: string
29
+ error?: string
30
+ }
31
+
32
+ /** theme key → the semantic tokens it answers for. */
33
+ const OWNS: Record<keyof BrandTheme, readonly string[]> = {
34
+ surface1: ['--background'],
35
+ surface2: ['--card', '--popover', '--muted'],
36
+ surface3: ['--accent'],
37
+ neutral1: ['--foreground', '--card-foreground', '--popover-foreground', '--accent-foreground'],
38
+ neutral2: ['--muted-foreground'],
39
+ neutral3: [],
40
+ accent1: ['--primary'],
41
+ accent2: [],
42
+ accent3: [],
43
+ border: ['--border'],
44
+ success: ['--state-success'],
45
+ warning: ['--state-warning'],
46
+ error: ['--state-error'],
47
+ }
48
+
49
+ /**
50
+ * The tokens a brand's theme sets, as `{ '--background': '#000', … }`.
51
+ *
52
+ * Only ground, ink, accent and the edges drawn on them. The radius scale, the
53
+ * type ramp, spacing, motion and z are NOT here and must not be: they are the
54
+ * system's grammar rather than a brand's voice, and a brand that redefines them
55
+ * is a fork wearing a stylesheet.
56
+ */
57
+ export function themeToTokens(theme: BrandTheme): Record<string, string> {
58
+ const out: Record<string, string> = {}
59
+ for (const [key, tokens] of Object.entries(OWNS) as [keyof BrandTheme, readonly string[]][]) {
60
+ const value = theme[key]
61
+ if (!value) continue
62
+ for (const token of tokens) out[token] = value
63
+ }
64
+ // --primary carries ink on top of it, so the accent names its own contrast
65
+ // partner rather than leaving whatever the previous theme set.
66
+ if (theme.accent1 && theme.surface1) out['--primary-foreground'] = theme.surface1
67
+ return out
68
+ }
69
+
70
+ /** Apply a brand's theme to a live document — for an app that resolves its brand
71
+ * at runtime and so cannot import a build-time stylesheet. */
72
+ export function applyBrandTheme(theme: BrandTheme, el: HTMLElement): void {
73
+ for (const [name, value] of Object.entries(themeToTokens(theme))) {
74
+ el.style.setProperty(name, value)
75
+ }
76
+ }
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@
10
10
  // import { colors, spacing, radius, cssVar } from '@hanzo/design' // the code layer
11
11
  //
12
12
  export * from './tokens.gen.js'
13
+ export * from './brand.js'
13
14
  import { cssVars, type CssVarName } from './tokens.gen.js'
14
15
 
15
16
  /** A token name with the leading `--` omitted: `'background'` for `'--background'`. */