@eos-ui/tokens 0.0.0-stage → 0.1.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.
- package/LICENSE +21 -0
- package/README.md +40 -2
- package/dist/color.d.ts +22 -0
- package/dist/color.js +98 -0
- package/dist/generated/defaults.d.ts +85 -0
- package/dist/generated/defaults.js +279 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/theme.d.ts +83 -0
- package/dist/theme.js +278 -0
- package/dist/tokens.css +75 -0
- package/package.json +56 -3
- package/src/tokens.json +544 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eos contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,41 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @eos-ui/tokens
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The design tokens behind Eos (colour, spacing, radius, shadow, type, size, motion, layering) as CSS custom properties, typed values, and `defineTheme()`, which builds a theme from a brand colour and checks every promised contrast pair.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @eos-ui/tokens
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { defineTheme } from "@eos-ui/tokens";
|
|
11
|
+
|
|
12
|
+
const theme = defineTheme({ name: "clinic", brand: "#8a2be2", accent: "#2e7d32", radius: "round" });
|
|
13
|
+
theme.issues; // contrast pairs that fail (empty when sound)
|
|
14
|
+
theme.css(); // the theme as CSS custom properties, for the server
|
|
15
|
+
theme.apply(document.documentElement); // or set them in the browser
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
```css
|
|
19
|
+
/* the default tokens as a stylesheet */
|
|
20
|
+
@import "@eos-ui/tokens/tokens.css";
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
All variables are prefixed `--e-` (`--e-primary`, `--e-space-4`). Documentation: https://eos.dame.gg. MIT licensed.
|
|
24
|
+
|
|
25
|
+
## Inputs
|
|
26
|
+
|
|
27
|
+
`defineTheme()` takes 15 inputs and emits every token. Any token can also be set by name in `tokens`, which wins over everything derived. `name` labels the theme (`data-e-theme`), and `strict` throws on a contrast failure instead of listing it in `issues`.
|
|
28
|
+
|
|
29
|
+
| Input | Derives |
|
|
30
|
+
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------- |
|
|
31
|
+
| `brand`, `accent` | `primary`, `secondary`, their tints and `surface-tint` |
|
|
32
|
+
| `danger`, `warning` | `danger`, `on-danger`, `danger-soft`; `warning-strong`, `warning-soft` |
|
|
33
|
+
| `background`, `surface`, `foreground` | the grounds, `ink`, `muted`, `border`, `border-strong`; a dark surface lifts the action colours |
|
|
34
|
+
| `fonts`, `radius` | `font-sans`, `font-mono`; `radius-sm` to `radius-lg` |
|
|
35
|
+
| `textScale`, `spaceScale` | `text-xs` to `text-4xl`; `space-1` to `space-8` (1 is the default) |
|
|
36
|
+
| `strokes` `{ hair, focus }` | `stroke-hair`, `stroke-edge`, `stroke-focus`, `focus-gap`, `focus-gap-field` |
|
|
37
|
+
| `motion` `"default" \| "snappy" \| "gentle" \| "none"` | `duration-tap`, `duration-move`, `easing-out` |
|
|
38
|
+
| `elevation` `"outline" \| "lifted" \| "bold"` | `edge`, `well`, `float`; shadow tint follows `background` |
|
|
39
|
+
| `controlHeight` | `control-height`, `chip-height` |
|
|
40
|
+
|
|
41
|
+
`derivedFrom`, `constants` and `inputTokens` say which input drives each token and which tokens are fixed. Fixed tokens include `depth`, the thickness of a raised or pressed edge.
|
package/dist/color.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Colour maths for contrast checks and brand derivation. Hex in, hex out; sRGB with WCAG 2.x relative luminance and OKLCH for lightness steps. */
|
|
2
|
+
export type RGB = [number, number, number];
|
|
3
|
+
export declare function parseHex(hex: string): RGB;
|
|
4
|
+
export declare function toHex([r, g, b]: RGB): string;
|
|
5
|
+
export declare function luminance(hex: string): number;
|
|
6
|
+
/** WCAG 2.x contrast ratio, 1 to 21. */
|
|
7
|
+
export declare function contrast(a: string, b: string): number;
|
|
8
|
+
export interface OKLCH {
|
|
9
|
+
l: number;
|
|
10
|
+
c: number;
|
|
11
|
+
h: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function toOklch(hex: string): OKLCH;
|
|
14
|
+
export declare function fromOklch({ l, c, h }: OKLCH): string;
|
|
15
|
+
/** The colour nearest `hex` (same hue and chroma, stepping lightness) whose contrast with `against` reaches `target`. Darkens when `against` is light, lightens when it is dark. */
|
|
16
|
+
export declare function reachContrast(hex: string, against: string, target: number): string;
|
|
17
|
+
/** A very light tint of `hex`'s hue, for soft backgrounds. */
|
|
18
|
+
export declare function tint(hex: string, lightness?: number, chroma?: number): string;
|
|
19
|
+
/** The colour nearest `hex` (same hue and chroma, lightness stepped toward `against`) that still holds a contrast of `target` with `against`. Softens as far as the target allows; returns `hex` unchanged when it is already under the target. */
|
|
20
|
+
export declare function settleContrast(hex: string, against: string, target: number): string;
|
|
21
|
+
/** `hex` moved to OKLCH lightness `l`, optionally with a new chroma and hue, clamped to the sRGB gamut. */
|
|
22
|
+
export declare function withLightness(hex: string, l: number, chroma?: number, hue?: number): string;
|
package/dist/color.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** Colour maths for contrast checks and brand derivation. Hex in, hex out; sRGB with WCAG 2.x relative luminance and OKLCH for lightness steps. */
|
|
2
|
+
export function parseHex(hex) {
|
|
3
|
+
const m = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex.trim());
|
|
4
|
+
if (!m)
|
|
5
|
+
throw new Error(`Not a hex colour: ${hex}`);
|
|
6
|
+
let h = m[1];
|
|
7
|
+
if (h.length === 3)
|
|
8
|
+
h = [...h].map((c) => c + c).join("");
|
|
9
|
+
return [0, 2, 4].map((i) => parseInt(h.slice(i, i + 2), 16));
|
|
10
|
+
}
|
|
11
|
+
export function toHex([r, g, b]) {
|
|
12
|
+
return ("#" +
|
|
13
|
+
[r, g, b]
|
|
14
|
+
.map((v) => Math.round(Math.min(255, Math.max(0, v)))
|
|
15
|
+
.toString(16)
|
|
16
|
+
.padStart(2, "0"))
|
|
17
|
+
.join(""));
|
|
18
|
+
}
|
|
19
|
+
const lin = (c) => {
|
|
20
|
+
const s = c / 255;
|
|
21
|
+
return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
22
|
+
};
|
|
23
|
+
const gam = (c) => 255 * (c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055);
|
|
24
|
+
export function luminance(hex) {
|
|
25
|
+
const [r, g, b] = parseHex(hex).map(lin);
|
|
26
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
27
|
+
}
|
|
28
|
+
/** WCAG 2.x contrast ratio, 1 to 21. */
|
|
29
|
+
export function contrast(a, b) {
|
|
30
|
+
const la = luminance(a);
|
|
31
|
+
const lb = luminance(b);
|
|
32
|
+
return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
|
|
33
|
+
}
|
|
34
|
+
export function toOklch(hex) {
|
|
35
|
+
const [r, g, b] = parseHex(hex).map(lin);
|
|
36
|
+
const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
|
|
37
|
+
const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
|
|
38
|
+
const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
|
|
39
|
+
const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s;
|
|
40
|
+
const A = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;
|
|
41
|
+
const B = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;
|
|
42
|
+
return { l: L, c: Math.hypot(A, B), h: (Math.atan2(B, A) * 180) / Math.PI };
|
|
43
|
+
}
|
|
44
|
+
export function fromOklch({ l, c, h }) {
|
|
45
|
+
const A = c * Math.cos((h * Math.PI) / 180);
|
|
46
|
+
const B = c * Math.sin((h * Math.PI) / 180);
|
|
47
|
+
const l_ = (l + 0.3963377774 * A + 0.2158037573 * B) ** 3;
|
|
48
|
+
const m_ = (l - 0.1055613458 * A - 0.0638541728 * B) ** 3;
|
|
49
|
+
const s_ = (l - 0.0894841775 * A - 1.291485548 * B) ** 3;
|
|
50
|
+
const r = 4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_;
|
|
51
|
+
const g = -1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_;
|
|
52
|
+
const bl = -0.0041960863 * l_ - 0.7034186147 * m_ + 1.707614701 * s_;
|
|
53
|
+
return toHex([gam(r), gam(g), gam(bl)]);
|
|
54
|
+
}
|
|
55
|
+
/** The colour nearest `hex` (same hue and chroma, stepping lightness) whose contrast with `against` reaches `target`. Darkens when `against` is light, lightens when it is dark. */
|
|
56
|
+
export function reachContrast(hex, against, target) {
|
|
57
|
+
const start = toOklch(hex);
|
|
58
|
+
const darken = luminance(against) > 0.4;
|
|
59
|
+
let best = hex;
|
|
60
|
+
for (let step = 0; step <= 100; step++) {
|
|
61
|
+
const l = darken ? start.l - step * 0.01 : start.l + step * 0.01;
|
|
62
|
+
if (l < 0 || l > 1)
|
|
63
|
+
break;
|
|
64
|
+
best = fromOklch({ ...start, l });
|
|
65
|
+
if (contrast(best, against) >= target)
|
|
66
|
+
return best;
|
|
67
|
+
}
|
|
68
|
+
return best;
|
|
69
|
+
}
|
|
70
|
+
/** A very light tint of `hex`'s hue, for soft backgrounds. */
|
|
71
|
+
export function tint(hex, lightness = 0.955, chroma = 0.025) {
|
|
72
|
+
const { h } = toOklch(hex);
|
|
73
|
+
return fromOklch({ l: lightness, c: chroma, h });
|
|
74
|
+
}
|
|
75
|
+
/** The colour nearest `hex` (same hue and chroma, lightness stepped toward `against`) that still holds a contrast of `target` with `against`. Softens as far as the target allows; returns `hex` unchanged when it is already under the target. */
|
|
76
|
+
export function settleContrast(hex, against, target) {
|
|
77
|
+
const start = toOklch(hex);
|
|
78
|
+
const goal = toOklch(against).l;
|
|
79
|
+
const dir = goal >= start.l ? 1 : -1;
|
|
80
|
+
let best = hex;
|
|
81
|
+
if (contrast(hex, against) < target)
|
|
82
|
+
return best;
|
|
83
|
+
for (let step = 1; step <= 400; step++) {
|
|
84
|
+
const l = start.l + dir * step * 0.0025;
|
|
85
|
+
if ((dir > 0 && l > goal) || (dir < 0 && l < goal))
|
|
86
|
+
break;
|
|
87
|
+
const next = fromOklch({ ...start, l });
|
|
88
|
+
if (contrast(next, against) < target)
|
|
89
|
+
break;
|
|
90
|
+
best = next;
|
|
91
|
+
}
|
|
92
|
+
return best;
|
|
93
|
+
}
|
|
94
|
+
/** `hex` moved to OKLCH lightness `l`, optionally with a new chroma and hue, clamped to the sRGB gamut. */
|
|
95
|
+
export function withLightness(hex, l, chroma, hue) {
|
|
96
|
+
const o = toOklch(hex);
|
|
97
|
+
return fromOklch({ l: Math.min(1, Math.max(0, l)), c: chroma ?? o.c, h: hue ?? o.h });
|
|
98
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export declare const defaults: {
|
|
2
|
+
readonly "brand-blue": "#2c95b4";
|
|
3
|
+
readonly "brand-green": "#72c451";
|
|
4
|
+
readonly primary: "#17586d";
|
|
5
|
+
readonly "on-primary": "#ffffff";
|
|
6
|
+
readonly secondary: "#2b5c1b";
|
|
7
|
+
readonly "on-secondary": "#ffffff";
|
|
8
|
+
readonly "secondary-soft": "#e8f5e1";
|
|
9
|
+
readonly danger: "#962019";
|
|
10
|
+
readonly "on-danger": "#ffffff";
|
|
11
|
+
readonly "danger-soft": "#fbe9e7";
|
|
12
|
+
readonly "warning-strong": "#714a00";
|
|
13
|
+
readonly "warning-soft": "#fdf3dc";
|
|
14
|
+
readonly background: "#ffffff";
|
|
15
|
+
readonly surface: "#ffffff";
|
|
16
|
+
readonly "surface-tint": "#eaf4f8";
|
|
17
|
+
readonly ink: "#000000";
|
|
18
|
+
readonly scrim: "rgb(11 40 52 / 0.55)";
|
|
19
|
+
readonly muted: "#515151";
|
|
20
|
+
readonly border: "#7f8f96";
|
|
21
|
+
readonly "border-strong": "#767676";
|
|
22
|
+
readonly "focus-ring": "var(--e-ink)";
|
|
23
|
+
readonly "focus-field": "var(--e-primary)";
|
|
24
|
+
readonly "space-1": "4px";
|
|
25
|
+
readonly "space-2": "8px";
|
|
26
|
+
readonly "space-3": "12px";
|
|
27
|
+
readonly "space-4": "16px";
|
|
28
|
+
readonly "space-6": "24px";
|
|
29
|
+
readonly "space-8": "32px";
|
|
30
|
+
readonly "radius-sm": "4px";
|
|
31
|
+
readonly "radius-md": "8px";
|
|
32
|
+
readonly "radius-lg": "16px";
|
|
33
|
+
readonly "radius-pill": "999px";
|
|
34
|
+
readonly edge: "0 0 0 1px #7f8f96";
|
|
35
|
+
readonly well: "inset 0 2px 0 0 rgba(0, 0, 0, 0.1)";
|
|
36
|
+
readonly float: "0 0 0 1px #7f8f96, 0 1px 2px 0px rgba(36, 36, 36, 0.08), 0 4px 8px -2px rgba(36, 36, 36, 0.1), 0 12px 24px -6px rgba(36, 36, 36, 0.14), 0 24px 48px -12px rgba(36, 36, 36, 0.18)";
|
|
37
|
+
readonly "text-xs": "12px";
|
|
38
|
+
readonly "text-sm": "14px";
|
|
39
|
+
readonly "text-md": "16px";
|
|
40
|
+
readonly "text-lg": "18px";
|
|
41
|
+
readonly "text-xl": "20px";
|
|
42
|
+
readonly "text-2xl": "24px";
|
|
43
|
+
readonly "text-3xl": "30px";
|
|
44
|
+
readonly "text-4xl": "36px";
|
|
45
|
+
readonly "control-height": "48px";
|
|
46
|
+
readonly "chip-height": "24px";
|
|
47
|
+
readonly measure: "62ch";
|
|
48
|
+
readonly "stroke-hair": "1px";
|
|
49
|
+
readonly "stroke-card": "1px";
|
|
50
|
+
readonly "stroke-edge": "1.5px";
|
|
51
|
+
readonly "stroke-focus": "2px";
|
|
52
|
+
readonly "focus-gap": "2px";
|
|
53
|
+
readonly "focus-gap-field": "-1px";
|
|
54
|
+
readonly depth: "2px";
|
|
55
|
+
readonly "duration-tap": "80ms";
|
|
56
|
+
readonly "duration-move": "220ms";
|
|
57
|
+
readonly "easing-out": "cubic-bezier(0.2, 0.8, 0.2, 1)";
|
|
58
|
+
readonly "z-raised": "1";
|
|
59
|
+
readonly "z-sticky": "5";
|
|
60
|
+
readonly "z-tooltip": "55";
|
|
61
|
+
readonly "z-modal": "40";
|
|
62
|
+
readonly "z-popover": "45";
|
|
63
|
+
readonly "z-toast": "50";
|
|
64
|
+
readonly "font-sans": "\"Jost\", Futura, \"Century Gothic\", \"Avenir Next\", system-ui, sans-serif";
|
|
65
|
+
readonly "font-mono": "\"Spline Sans Mono\", ui-monospace, Menlo, Consolas, monospace";
|
|
66
|
+
};
|
|
67
|
+
export declare const groups: {
|
|
68
|
+
readonly color: readonly ["brand-blue", "brand-green", "primary", "on-primary", "secondary", "on-secondary", "secondary-soft", "danger", "on-danger", "danger-soft", "warning-strong", "warning-soft", "background", "surface", "surface-tint", "ink", "scrim", "muted", "border", "border-strong", "focus-ring", "focus-field"];
|
|
69
|
+
readonly spacing: readonly ["space-1", "space-2", "space-3", "space-4", "space-6", "space-8"];
|
|
70
|
+
readonly radius: readonly ["radius-sm", "radius-md", "radius-lg", "radius-pill"];
|
|
71
|
+
readonly shadow: readonly ["edge", "well", "float"];
|
|
72
|
+
readonly fontSize: readonly ["text-xs", "text-sm", "text-md", "text-lg", "text-xl", "text-2xl", "text-3xl", "text-4xl"];
|
|
73
|
+
readonly size: readonly ["control-height", "chip-height", "measure"];
|
|
74
|
+
readonly stroke: readonly ["stroke-hair", "stroke-card", "stroke-edge", "stroke-focus", "focus-gap", "focus-gap-field", "depth"];
|
|
75
|
+
readonly duration: readonly ["duration-tap", "duration-move"];
|
|
76
|
+
readonly easing: readonly ["easing-out"];
|
|
77
|
+
readonly zIndex: readonly ["z-raised", "z-sticky", "z-tooltip", "z-modal", "z-popover", "z-toast"];
|
|
78
|
+
readonly font: readonly ["font-sans", "font-mono"];
|
|
79
|
+
};
|
|
80
|
+
export declare const usage: Record<string, string>;
|
|
81
|
+
export declare const derivedFrom: Record<string, string>;
|
|
82
|
+
export declare const constants: string[];
|
|
83
|
+
export declare const inputTokens: string[];
|
|
84
|
+
export type TokenName = keyof typeof defaults;
|
|
85
|
+
export declare const colorNames: ReadonlySet<string>;
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
// Generated by scripts/generate.mjs from src/tokens.json. Do not edit.
|
|
2
|
+
export const defaults = {
|
|
3
|
+
"brand-blue": "#2c95b4",
|
|
4
|
+
"brand-green": "#72c451",
|
|
5
|
+
"primary": "#17586d",
|
|
6
|
+
"on-primary": "#ffffff",
|
|
7
|
+
"secondary": "#2b5c1b",
|
|
8
|
+
"on-secondary": "#ffffff",
|
|
9
|
+
"secondary-soft": "#e8f5e1",
|
|
10
|
+
"danger": "#962019",
|
|
11
|
+
"on-danger": "#ffffff",
|
|
12
|
+
"danger-soft": "#fbe9e7",
|
|
13
|
+
"warning-strong": "#714a00",
|
|
14
|
+
"warning-soft": "#fdf3dc",
|
|
15
|
+
"background": "#ffffff",
|
|
16
|
+
"surface": "#ffffff",
|
|
17
|
+
"surface-tint": "#eaf4f8",
|
|
18
|
+
"ink": "#000000",
|
|
19
|
+
"scrim": "rgb(11 40 52 / 0.55)",
|
|
20
|
+
"muted": "#515151",
|
|
21
|
+
"border": "#7f8f96",
|
|
22
|
+
"border-strong": "#767676",
|
|
23
|
+
"focus-ring": "var(--e-ink)",
|
|
24
|
+
"focus-field": "var(--e-primary)",
|
|
25
|
+
"space-1": "4px",
|
|
26
|
+
"space-2": "8px",
|
|
27
|
+
"space-3": "12px",
|
|
28
|
+
"space-4": "16px",
|
|
29
|
+
"space-6": "24px",
|
|
30
|
+
"space-8": "32px",
|
|
31
|
+
"radius-sm": "4px",
|
|
32
|
+
"radius-md": "8px",
|
|
33
|
+
"radius-lg": "16px",
|
|
34
|
+
"radius-pill": "999px",
|
|
35
|
+
"edge": "0 0 0 1px #7f8f96",
|
|
36
|
+
"well": "inset 0 2px 0 0 rgba(0, 0, 0, 0.1)",
|
|
37
|
+
"float": "0 0 0 1px #7f8f96, 0 1px 2px 0px rgba(36, 36, 36, 0.08), 0 4px 8px -2px rgba(36, 36, 36, 0.1), 0 12px 24px -6px rgba(36, 36, 36, 0.14), 0 24px 48px -12px rgba(36, 36, 36, 0.18)",
|
|
38
|
+
"text-xs": "12px",
|
|
39
|
+
"text-sm": "14px",
|
|
40
|
+
"text-md": "16px",
|
|
41
|
+
"text-lg": "18px",
|
|
42
|
+
"text-xl": "20px",
|
|
43
|
+
"text-2xl": "24px",
|
|
44
|
+
"text-3xl": "30px",
|
|
45
|
+
"text-4xl": "36px",
|
|
46
|
+
"control-height": "48px",
|
|
47
|
+
"chip-height": "24px",
|
|
48
|
+
"measure": "62ch",
|
|
49
|
+
"stroke-hair": "1px",
|
|
50
|
+
"stroke-card": "1px",
|
|
51
|
+
"stroke-edge": "1.5px",
|
|
52
|
+
"stroke-focus": "2px",
|
|
53
|
+
"focus-gap": "2px",
|
|
54
|
+
"focus-gap-field": "-1px",
|
|
55
|
+
"depth": "2px",
|
|
56
|
+
"duration-tap": "80ms",
|
|
57
|
+
"duration-move": "220ms",
|
|
58
|
+
"easing-out": "cubic-bezier(0.2, 0.8, 0.2, 1)",
|
|
59
|
+
"z-raised": "1",
|
|
60
|
+
"z-sticky": "5",
|
|
61
|
+
"z-tooltip": "55",
|
|
62
|
+
"z-modal": "40",
|
|
63
|
+
"z-popover": "45",
|
|
64
|
+
"z-toast": "50",
|
|
65
|
+
"font-sans": "\"Jost\", Futura, \"Century Gothic\", \"Avenir Next\", system-ui, sans-serif",
|
|
66
|
+
"font-mono": "\"Spline Sans Mono\", ui-monospace, Menlo, Consolas, monospace"
|
|
67
|
+
};
|
|
68
|
+
export const groups = {
|
|
69
|
+
"color": [
|
|
70
|
+
"brand-blue",
|
|
71
|
+
"brand-green",
|
|
72
|
+
"primary",
|
|
73
|
+
"on-primary",
|
|
74
|
+
"secondary",
|
|
75
|
+
"on-secondary",
|
|
76
|
+
"secondary-soft",
|
|
77
|
+
"danger",
|
|
78
|
+
"on-danger",
|
|
79
|
+
"danger-soft",
|
|
80
|
+
"warning-strong",
|
|
81
|
+
"warning-soft",
|
|
82
|
+
"background",
|
|
83
|
+
"surface",
|
|
84
|
+
"surface-tint",
|
|
85
|
+
"ink",
|
|
86
|
+
"scrim",
|
|
87
|
+
"muted",
|
|
88
|
+
"border",
|
|
89
|
+
"border-strong",
|
|
90
|
+
"focus-ring",
|
|
91
|
+
"focus-field"
|
|
92
|
+
],
|
|
93
|
+
"spacing": [
|
|
94
|
+
"space-1",
|
|
95
|
+
"space-2",
|
|
96
|
+
"space-3",
|
|
97
|
+
"space-4",
|
|
98
|
+
"space-6",
|
|
99
|
+
"space-8"
|
|
100
|
+
],
|
|
101
|
+
"radius": [
|
|
102
|
+
"radius-sm",
|
|
103
|
+
"radius-md",
|
|
104
|
+
"radius-lg",
|
|
105
|
+
"radius-pill"
|
|
106
|
+
],
|
|
107
|
+
"shadow": [
|
|
108
|
+
"edge",
|
|
109
|
+
"well",
|
|
110
|
+
"float"
|
|
111
|
+
],
|
|
112
|
+
"fontSize": [
|
|
113
|
+
"text-xs",
|
|
114
|
+
"text-sm",
|
|
115
|
+
"text-md",
|
|
116
|
+
"text-lg",
|
|
117
|
+
"text-xl",
|
|
118
|
+
"text-2xl",
|
|
119
|
+
"text-3xl",
|
|
120
|
+
"text-4xl"
|
|
121
|
+
],
|
|
122
|
+
"size": [
|
|
123
|
+
"control-height",
|
|
124
|
+
"chip-height",
|
|
125
|
+
"measure"
|
|
126
|
+
],
|
|
127
|
+
"stroke": [
|
|
128
|
+
"stroke-hair",
|
|
129
|
+
"stroke-card",
|
|
130
|
+
"stroke-edge",
|
|
131
|
+
"stroke-focus",
|
|
132
|
+
"focus-gap",
|
|
133
|
+
"focus-gap-field",
|
|
134
|
+
"depth"
|
|
135
|
+
],
|
|
136
|
+
"duration": [
|
|
137
|
+
"duration-tap",
|
|
138
|
+
"duration-move"
|
|
139
|
+
],
|
|
140
|
+
"easing": [
|
|
141
|
+
"easing-out"
|
|
142
|
+
],
|
|
143
|
+
"zIndex": [
|
|
144
|
+
"z-raised",
|
|
145
|
+
"z-sticky",
|
|
146
|
+
"z-tooltip",
|
|
147
|
+
"z-modal",
|
|
148
|
+
"z-popover",
|
|
149
|
+
"z-toast"
|
|
150
|
+
],
|
|
151
|
+
"font": [
|
|
152
|
+
"font-sans",
|
|
153
|
+
"font-mono"
|
|
154
|
+
]
|
|
155
|
+
};
|
|
156
|
+
export const usage = {
|
|
157
|
+
"brand-blue": "The logo blue, exact. Decorative and brand surfaces only (the cover, illustrations). Never carries text: black on it is 6.1:1 but only APCA Lc 42, and white on it is 3.5:1. Use `primary` for anything interactive.",
|
|
158
|
+
"brand-green": "The logo green, exact. Decorative and brand surfaces only. Never carries text: white on it is 2.2:1.",
|
|
159
|
+
"primary": "Action blue: the fill of the primary Button and of every selected or checked state (selected day, page, segment, time slot, checkbox, switch), with `on-primary` (white) text at 7.9:1. Also small blue text and links on `surface` and `surface-tint` (7.9:1 and 7.1:1), the information tone, and the filled part of progress and loading bars. A deep teal derived from the logo blue (`brand-blue`) so that white text passes WCAG AAA.",
|
|
160
|
+
"on-primary": "White text and icons on `primary` fills (7.9:1).",
|
|
161
|
+
"secondary": "Action green: the fill of the secondary Button (a positive action), with `on-secondary` (white) text at 7.9:1. Also the success tone's text and outline. Derived from the logo green (`brand-green`).",
|
|
162
|
+
"on-secondary": "White text and icons on `secondary` fills (7.9:1).",
|
|
163
|
+
"secondary-soft": "Tinted backdrop of a paid chip or notice.",
|
|
164
|
+
"danger": "Danger red: the fill of the danger Button, with `on-danger` (white) text at 8.3:1. Also the danger tone's text and outline, error text and invalid input edges, on `surface` (8.3:1) and `danger-soft` (7.1:1). Derived from the `danger` input of `defineTheme`: deepened until `on-danger` text reaches 7:1.",
|
|
165
|
+
"on-danger": "White text and icons on `danger` fills (8.3:1).",
|
|
166
|
+
"danger-soft": "Tinted backdrop of a danger chip, stamp, notice or toast.",
|
|
167
|
+
"warning-strong": "Small amber text on `surface` (7.8:1) and `warning-soft` (7.1:1): AAA. Derived from the `warning` input of `defineTheme`.",
|
|
168
|
+
"warning-soft": "Tinted backdrop of a warning chip, stamp, notice or toast.",
|
|
169
|
+
"background": "The page ground: the colour behind everything, painted by the app shell and the page. White by default, the same as `surface`. The `background` input of `defineTheme` sets it; when only `surface` is given the page ground follows the surface.",
|
|
170
|
+
"surface": "What sits on the page: cards, fields, popovers, dialogs, panels and headers. Every screen starts on white. The `surface` input of `defineTheme` sets it, and with it derives `surface-tint`, the soft tone backdrops and, on a dark surface, the light action colours.",
|
|
171
|
+
"surface-tint": "The surface's second step: wells, hovered rows, table headers, footers, empty slots and the information tone's tint. Derived from `surface` by shifting its lightness 0.045 toward the foreground (0.06 the other way on a dark surface) in the brand hue. About 1.1:1 against white, so never a boundary on its own.",
|
|
172
|
+
"ink": "Body copy, headings and icons on `surface`, `surface-tint`, `primary`, `secondary`, `danger` and the soft tints. Also the neutral chip colour. Set by the `foreground` input of `defineTheme`, which also drives `muted`, `border` and `border-strong`.",
|
|
173
|
+
"scrim": "The dimmed backdrop behind a dialog or drawer.",
|
|
174
|
+
"muted": "Secondary text, kickers and captions on `surface` (7.9:1) and `surface-tint` (7.1:1): AAA. Close to the grey of the logo's tagline. From a `foreground` input, `ink` softened toward `surface` until it just holds 7:1.",
|
|
175
|
+
"border": "Hairlines between rows, the outline of cards and popovers, and the underside of clickable rows. 3.4:1 on `surface` and 3.0:1 on `surface-tint`, so every edge is visible on white. Control edges use `border-strong`. From a `foreground` input, `ink` softened toward `surface` until it just holds 3.4:1.",
|
|
176
|
+
"border-strong": "Input, checkbox and other control borders on `surface` (4.5:1, above the 3:1 floor). From a `foreground` input, `ink` softened toward `surface` until it just holds 4.5:1.",
|
|
177
|
+
"focus-ring": "Solid 2px focus outline with 2px offset on buttons, links, tabs, rows and every control that is not a text input; 3:1 or better on every surface and fill.",
|
|
178
|
+
"focus-field": "The focus outline and edge of text inputs and everything built on them (Field, Select, Combobox, DatePicker, NumberField, SearchBar, OtpField). Primary teal, 7.9:1 on `surface`. An invalid input keeps `danger`. Buttons and links use `focus-ring`.",
|
|
179
|
+
"space-1": "Icon-to-text gaps, gap inside a chip.",
|
|
180
|
+
"space-2": "Tight stacks, chip padding.",
|
|
181
|
+
"space-3": "Control padding, compact rows.",
|
|
182
|
+
"space-4": "Card padding, default gap, side gutter.",
|
|
183
|
+
"space-6": "Between related groups and parts of a statement.",
|
|
184
|
+
"space-8": "Section padding.",
|
|
185
|
+
"radius-sm": "Stamps and tags.",
|
|
186
|
+
"radius-md": "Buttons, inputs, cards, notices.",
|
|
187
|
+
"radius-lg": "Dialogs.",
|
|
188
|
+
"radius-pill": "Chips and round buttons, echoing the logo's round caps.",
|
|
189
|
+
"edge": "The flat outline of everything that is not clickable: cards, summaries, the SearchBar. A 1px `border` ring (3.4:1 on white), no depth.",
|
|
190
|
+
"well": "Inputs, meters and empty slots pressed into the page.",
|
|
191
|
+
"float": "Popovers, menus and toasts: the surfaces that float over the page. Four stacked, low-opacity shadows of growing size read as one soft shadow, so it never looks like a hard black edge. Nothing in the flow of the page uses it.",
|
|
192
|
+
"text-xs": "Kickers, chips, stamps, micro labels and other mono labels. Never smaller.",
|
|
193
|
+
"text-sm": "Secondary copy, table cells, helper text, small buttons.",
|
|
194
|
+
"text-md": "Body copy, input text and button labels. Inputs must stay at 16px or more so phones do not zoom in on focus.",
|
|
195
|
+
"text-lg": "The deck: a one-sentence reading of a statement. Calendar headings.",
|
|
196
|
+
"text-xl": "Card and panel titles (h3).",
|
|
197
|
+
"text-2xl": "Section titles (h2).",
|
|
198
|
+
"text-3xl": "The one amount a statement leads with.",
|
|
199
|
+
"text-4xl": "Page titles (h1).",
|
|
200
|
+
"control-height": "Height of every control that can be tapped: buttons, inputs, selects, date fields, slots, and one row of a multi-select. One height everywhere, so a Button beside an input lines up and a field never shifts when it changes type.",
|
|
201
|
+
"chip-height": "Height of a Chip or a small Stamp.",
|
|
202
|
+
"measure": "Longest comfortable line of copy.",
|
|
203
|
+
"stroke-hair": "Dividers and the rule between rows.",
|
|
204
|
+
"stroke-card": "The outline of a card, panel, table or other container that is not clickable, and of a chip or stamp. Follows the hairline; a bold elevation draws it at 2px.",
|
|
205
|
+
"stroke-edge": "The outline of a control, chip or stamp.",
|
|
206
|
+
"stroke-focus": "The focus outline.",
|
|
207
|
+
"focus-gap": "Space between a button or link and its focus outline.",
|
|
208
|
+
"focus-gap-field": "Space between a text input and its focus outline: a 1px overlap, so the outline sits over the border with no seam.",
|
|
209
|
+
"depth": "How far a raised or pressed edge reaches. A button, a statement row and a selected time slot stand out by this much of extra thickness on the bottom edge; a pressed button, the selected item of a list or segmented control and a notice are pressed in by the same amount on the top edge.",
|
|
210
|
+
"duration-tap": "Hover and press feedback.",
|
|
211
|
+
"duration-move": "Things that move: a progress fill, a drawer.",
|
|
212
|
+
"easing-out": "Fast start, soft landing. The only easing in the system.",
|
|
213
|
+
"z-raised": "A part that must sit above its sibling inside one component.",
|
|
214
|
+
"z-sticky": "Sticky table headers and columns.",
|
|
215
|
+
"z-tooltip": "Tooltip bubbles: above everything, including dialogs, popovers and toasts.",
|
|
216
|
+
"z-modal": "Dialogs and drawers with their scrim.",
|
|
217
|
+
"z-popover": "Popovers, menus and option lists. Above modals, so a Select inside a Dialog opens over it.",
|
|
218
|
+
"z-toast": "The toast region: above modals and popovers."
|
|
219
|
+
};
|
|
220
|
+
export const derivedFrom = {
|
|
221
|
+
"font-sans": "fonts",
|
|
222
|
+
"font-mono": "fonts",
|
|
223
|
+
"brand-blue": "brand",
|
|
224
|
+
"brand-green": "accent",
|
|
225
|
+
"primary": "brand,surface",
|
|
226
|
+
"on-primary": "surface",
|
|
227
|
+
"secondary": "accent,surface",
|
|
228
|
+
"on-secondary": "surface",
|
|
229
|
+
"secondary-soft": "accent,surface",
|
|
230
|
+
"danger": "danger,surface",
|
|
231
|
+
"on-danger": "danger,surface",
|
|
232
|
+
"danger-soft": "danger,surface",
|
|
233
|
+
"warning-strong": "warning,surface",
|
|
234
|
+
"warning-soft": "warning,surface",
|
|
235
|
+
"background": "background,surface",
|
|
236
|
+
"surface": "surface",
|
|
237
|
+
"surface-tint": "surface,brand",
|
|
238
|
+
"ink": "foreground,surface",
|
|
239
|
+
"scrim": "surface",
|
|
240
|
+
"muted": "foreground,surface",
|
|
241
|
+
"border": "foreground,surface",
|
|
242
|
+
"border-strong": "foreground,surface",
|
|
243
|
+
"focus-ring": "foreground",
|
|
244
|
+
"focus-field": "brand",
|
|
245
|
+
"space-1": "spaceScale",
|
|
246
|
+
"space-2": "spaceScale",
|
|
247
|
+
"space-3": "spaceScale",
|
|
248
|
+
"space-4": "spaceScale",
|
|
249
|
+
"space-6": "spaceScale",
|
|
250
|
+
"space-8": "spaceScale",
|
|
251
|
+
"radius-sm": "radius",
|
|
252
|
+
"radius-md": "radius",
|
|
253
|
+
"radius-lg": "radius",
|
|
254
|
+
"edge": "elevation,strokes,foreground,background",
|
|
255
|
+
"well": "elevation,surface",
|
|
256
|
+
"float": "elevation,strokes,foreground,surface,background",
|
|
257
|
+
"text-xs": "textScale",
|
|
258
|
+
"text-sm": "textScale",
|
|
259
|
+
"text-md": "textScale",
|
|
260
|
+
"text-lg": "textScale",
|
|
261
|
+
"text-xl": "textScale",
|
|
262
|
+
"text-2xl": "textScale",
|
|
263
|
+
"text-3xl": "textScale",
|
|
264
|
+
"text-4xl": "textScale",
|
|
265
|
+
"control-height": "controlHeight",
|
|
266
|
+
"chip-height": "controlHeight",
|
|
267
|
+
"stroke-hair": "strokes",
|
|
268
|
+
"stroke-card": "strokes,elevation",
|
|
269
|
+
"stroke-edge": "strokes",
|
|
270
|
+
"stroke-focus": "strokes",
|
|
271
|
+
"focus-gap": "strokes",
|
|
272
|
+
"focus-gap-field": "strokes",
|
|
273
|
+
"duration-tap": "motion",
|
|
274
|
+
"duration-move": "motion",
|
|
275
|
+
"easing-out": "motion"
|
|
276
|
+
};
|
|
277
|
+
export const constants = ["radius-pill", "measure", "depth", "z-raised", "z-sticky", "z-tooltip", "z-modal", "z-popover", "z-toast"];
|
|
278
|
+
export const inputTokens = ["font-sans", "font-mono", "brand-blue", "brand-green", "background", "surface", "ink", "control-height", "stroke-hair", "stroke-focus"];
|
|
279
|
+
export const colorNames = new Set(["brand-blue", "brand-green", "primary", "on-primary", "secondary", "on-secondary", "secondary-soft", "danger", "on-danger", "danger-soft", "warning-strong", "warning-soft", "background", "surface", "surface-tint", "ink", "scrim", "muted", "border", "border-strong", "focus-ring", "focus-field"]);
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { defineTheme, checkContrast, LAYER_ORDER, defaults, groups } from "./theme.js";
|
|
2
|
+
export type { Theme, ThemeInput, MotionPreset, ElevationPreset, TokenValues, ContrastIssue, CssOptions, TokenName, } from "./theme.js";
|
|
3
|
+
export { contrast, luminance, reachContrast, settleContrast, withLightness, tint, toOklch, fromOklch, parseHex, toHex, } from "./color.js";
|
|
4
|
+
export { usage, derivedFrom, constants, inputTokens } from "./generated/defaults.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { defineTheme, checkContrast, LAYER_ORDER, defaults, groups } from "./theme.js";
|
|
2
|
+
export { contrast, luminance, reachContrast, settleContrast, withLightness, tint, toOklch, fromOklch, parseHex, toHex, } from "./color.js";
|
|
3
|
+
export { usage, derivedFrom, constants, inputTokens } from "./generated/defaults.js";
|
package/dist/theme.d.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { defaults, groups, type TokenName } from "./generated/defaults.js";
|
|
2
|
+
export type TokenValues = Partial<Record<TokenName, string>>;
|
|
3
|
+
export type MotionPreset = "default" | "snappy" | "gentle" | "none";
|
|
4
|
+
export type ElevationPreset = "outline" | "lifted" | "bold";
|
|
5
|
+
export interface ThemeInput {
|
|
6
|
+
/** Identifies the theme. It becomes the value of `data-e-theme` when the theme is scoped to an element. */
|
|
7
|
+
name?: string;
|
|
8
|
+
/** The brand colour. The deep action colour (`primary`) is derived from it so white text on it reaches 7:1; the tinted ground follows. */
|
|
9
|
+
brand?: string;
|
|
10
|
+
/** A second brand colour for positive actions (`secondary`), derived the same way. */
|
|
11
|
+
accent?: string;
|
|
12
|
+
/** The page ground: the colour behind everything. Sets `background`. When `surface` is given and this is not, the page ground follows the surface. */
|
|
13
|
+
background?: string;
|
|
14
|
+
/** Anything that sits on the page: cards, fields, popovers, panels. Sets `surface` and derives `surface-tint` (the second ground) and the soft tone backdrops from its lightness. A dark surface also switches the action colours and their `on-*` text to light variants. */
|
|
15
|
+
surface?: string;
|
|
16
|
+
/** Text and lines. Sets `ink` and derives `muted` (softened until it just holds 7:1 on the surface), `border` (3.4:1) and `border-strong` (4.5:1). Without it, a given `surface` picks black or white. */
|
|
17
|
+
foreground?: string;
|
|
18
|
+
/** The destructive action colour. Derives `danger` (deepened until `on-danger` text reaches 7:1, and 4.5:1 on the surface and on `danger-soft`), `on-danger` and `danger-soft`. */
|
|
19
|
+
danger?: string;
|
|
20
|
+
/** The caution colour. Derives `warning-strong` (4.5:1 or more on the surface and on `warning-soft`) and `warning-soft`. */
|
|
21
|
+
warning?: string;
|
|
22
|
+
/** Font stacks for body and mono text. Fonts are never bundled: load them yourself or import `@eos-ui/vue/fonts.css`. */
|
|
23
|
+
fonts?: {
|
|
24
|
+
sans?: string;
|
|
25
|
+
mono?: string;
|
|
26
|
+
};
|
|
27
|
+
/** Corner style: a preset or explicit values. */
|
|
28
|
+
radius?: "sharp" | "default" | "round" | {
|
|
29
|
+
sm?: string;
|
|
30
|
+
md?: string;
|
|
31
|
+
lg?: string;
|
|
32
|
+
};
|
|
33
|
+
/** Multiplier for the type scale, `text-xs` to `text-4xl`. 1 is the default scale; non-finite or non-positive values are ignored. */
|
|
34
|
+
textScale?: number;
|
|
35
|
+
/** Multiplier for the spacing scale, `space-1` to `space-8`. 1 is the default scale; non-finite or non-positive values are ignored. */
|
|
36
|
+
spaceScale?: number;
|
|
37
|
+
/** Line weights in px. `hair` sets `stroke-hair` and `stroke-edge` (1.5 times it); `focus` sets `stroke-focus`, `focus-gap` (the same) and `focus-gap-field` (a 1px overlap: a field's focus outline sits over its border). */
|
|
38
|
+
strokes?: {
|
|
39
|
+
hair?: number;
|
|
40
|
+
focus?: number;
|
|
41
|
+
};
|
|
42
|
+
/** How state changes feel: sets `duration-tap`, `duration-move` and `easing-out`. */
|
|
43
|
+
motion?: MotionPreset;
|
|
44
|
+
/** How depth is drawn: sets `edge`, `well` and `float` from the border, ink and hairline. `outline` is flat rings, `lifted` adds soft drops, `bold` uses heavy rings and a hard offset shadow. */
|
|
45
|
+
elevation?: ElevationPreset;
|
|
46
|
+
/** Height in px of every tappable control. Sets `control-height` and derives `chip-height` at half of it, rounded to an even number. */
|
|
47
|
+
controlHeight?: number;
|
|
48
|
+
/** Anything else, by token name. Wins over everything derived. */
|
|
49
|
+
tokens?: TokenValues;
|
|
50
|
+
/** Throw on a contrast failure instead of reporting it in `issues`. */
|
|
51
|
+
strict?: boolean;
|
|
52
|
+
}
|
|
53
|
+
export interface ContrastIssue {
|
|
54
|
+
pair: [string, string];
|
|
55
|
+
ratio: number;
|
|
56
|
+
min: number;
|
|
57
|
+
role: string;
|
|
58
|
+
}
|
|
59
|
+
export interface CssOptions {
|
|
60
|
+
/** Selector the tokens apply to. Default `:root`. */
|
|
61
|
+
selector?: string;
|
|
62
|
+
/** Wrap in `@layer e.tokens`, the layer the components expect. Default true. */
|
|
63
|
+
layer?: boolean;
|
|
64
|
+
/** Prepend the layer order statement and a generated-file comment. */
|
|
65
|
+
header?: boolean;
|
|
66
|
+
}
|
|
67
|
+
export interface Theme {
|
|
68
|
+
name: string;
|
|
69
|
+
/** Every token, by name without the leading `--`. */
|
|
70
|
+
tokens: Record<string, string>;
|
|
71
|
+
/** Failures of the contrast pairs the system promises (text 4.5, non-text 3). Empty when the theme is sound. */
|
|
72
|
+
issues: ContrastIssue[];
|
|
73
|
+
/** The theme as CSS custom properties on a selector, in the token layer. Render it into `<head>` on the server. */
|
|
74
|
+
css(options?: CssOptions): string;
|
|
75
|
+
/** Sets the tokens on an element as inline custom properties and marks it `data-e-theme`. Browser only. */
|
|
76
|
+
apply(el?: HTMLElement): void;
|
|
77
|
+
}
|
|
78
|
+
/** Cascade order of the library. Later layers win, and each layer only builds on the ones before it. */
|
|
79
|
+
export declare const LAYER_ORDER = "e.reset, e.tokens, e.base, e.primitives, e.blocks, e.controls, e.composites, e.containers, e.account, e.page";
|
|
80
|
+
export declare function checkContrast(tokens: Record<string, string>): ContrastIssue[];
|
|
81
|
+
export declare function defineTheme(input?: ThemeInput): Theme;
|
|
82
|
+
export { defaults, groups };
|
|
83
|
+
export type { TokenName };
|