@schemavaults/theme 0.26.1 → 0.27.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
@@ -83,6 +83,42 @@ export default config;
83
83
  In the above example, local `.js`/`.ts`/`.jsx`/`.tsx` paths will be resolved in the app that `@schemavaults/theme` config factory is running in. Also, `@schemavaults/*` scoped packages will be resolved from `node_modules`.
84
84
 
85
85
 
86
+ ### Theming a deployment (overriding the tokens)
87
+
88
+ `globals.css` declares every design token through an *override variable* with the stock value as its fallback:
89
+
90
+ ```css
91
+ :root { --background: var(--sv-theme-light-background, 0 0% 100%); }
92
+ .dark { --background: var(--sv-theme-dark-background, 222.2 84% 4.9%); }
93
+ :root { --radius: var(--sv-theme-radius, 0.5rem); }
94
+ ```
95
+
96
+ So a white-labelled deployment re-themes itself by setting `--sv-theme-light-*`, `--sv-theme-dark-*` and (for tokens shared by both modes) `--sv-theme-*` on the `<html>` element — no fork of `globals.css`, and the stylesheet's defaults keep applying to whatever is not set. A light override only affects light mode; the `.dark` block reads its own variables.
97
+
98
+ `@schemavaults/theme/tokens` (safe to import from browser bundles and client components — it has no Node.js dependencies, unlike the config factory at the package root) ships the manifest and the helpers:
99
+
100
+ ```typescript
101
+ import {
102
+ THEME_TOKENS, // every token: id, css variable, format, group, label, description, light/dark defaults
103
+ createThemeOverrideStyle, // ThemeOverrides -> { "--sv-theme-light-background": "210 40% 98%", ... }
104
+ renderThemeOverrideCss, // ThemeOverrides -> ":root{--sv-theme-light-background:210 40% 98%;}"
105
+ resolveThemeTokens, // every token with default + override + effective value, for a settings page
106
+ themeOverridesFromEnvironment, // reads THEME_LIGHT_BACKGROUND, THEME_DARK_BACKGROUND, THEME_RADIUS, ...
107
+ } from "@schemavaults/theme/tokens";
108
+
109
+ // e.g. in a Next.js root layout
110
+ const { overrides, problems } = themeOverridesFromEnvironment(process.env, { prefix: "THEME" });
111
+ // problems: variables set to a value the token cannot take; they keep the default
112
+ const style = createThemeOverrideStyle(overrides);
113
+ // <html style={style}> ... </html>
114
+ ```
115
+
116
+ Values are validated and normalised before they are emitted. Tokens whose format is `hsl-channels` (the shadcn/ui component colours the Tailwind theme wraps in `hsl()`) accept bare channels (`222.2 84% 4.9%`), a hex colour, or an opaque `rgb()`/`hsl()`, and are stored as channels; `css-color` tokens (the brand colours, `warning` and the sidebar) take any CSS colour; `radius` takes a CSS length. A value that could break the stylesheet or escape an attribute is refused with a reason you can show an administrator.
117
+
118
+ Environment variable names follow the token id: `<PREFIX>_LIGHT_<TOKEN>`, `<PREFIX>_DARK_<TOKEN>` and `<PREFIX>_<TOKEN>` for shared tokens, upper-cased with hyphens as underscores (`sidebar-primary-foreground` → `THEME_DARK_SIDEBAR_PRIMARY_FOREGROUND`); `themeTokenEnvironmentVariable()` returns the name for a token and scope.
119
+
120
+ The generated Tailwind config safelists the `dark` class so the `.dark` token block survives Tailwind's purge in applications that only add the class at runtime.
121
+
86
122
  ### CommonJS
87
123
 
88
124
  Note that currently CommonJS is not supported. I believe that I was struggling to get `tailwindcss-animate` working from CJS, then decided not to support it. Change your `tailwind.config.cjs` files to `tailwind.config.ts` or `tailwind.config.mjs` to use TypeScript or ES modules instead.
@@ -255,6 +255,12 @@ export class SchemaVaultsTailwindConfigFactory {
255
255
  theme: { extend },
256
256
  plugins,
257
257
  darkMode: "class",
258
+ // globals.css declares the dark-mode tokens under `.dark` inside
259
+ // `@layer base`, and Tailwind drops a layered rule whose class it
260
+ // never sees in `content`. An application that adds the class at
261
+ // runtime (a theme toggle, a `dark` set from a preference) has no
262
+ // literal "dark" in its source, so the block is kept explicitly.
263
+ safelist: ["dark"],
258
264
  };
259
265
  console.assert(config.content.length >= 1, "Failed to load any 'content' search blobs to generate TailwindCSS classes for!");
260
266
  if (!config.content.every((blob) => typeof blob === "string")) {
@@ -1 +1 @@
1
- {"version":3,"file":"TailwindConfigFactory.js","sourceRoot":"","sources":["../src/TailwindConfigFactory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TailwindConfigFactory.js","sourceRoot":"","sources":["../src/TailwindConfigFactory.ts"],"names":[],"mappings":"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"}
@@ -18,7 +18,7 @@ export const componentColors = {
18
18
  },
19
19
  warning: {
20
20
  DEFAULT: "var(--warning)",
21
- foreground: "var(--destructive-foreground)",
21
+ foreground: "var(--warning-foreground)",
22
22
  },
23
23
  muted: {
24
24
  DEFAULT: "hsl(var(--muted))",
@@ -1 +1 @@
1
- {"version":3,"file":"component_colors.js","sourceRoot":"","sources":["../src/component_colors.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,eAAe,GAAe;IACzC,MAAM,EAAE,oBAAoB;IAC5B,KAAK,EAAE,mBAAmB;IAC1B,IAAI,EAAE,kBAAkB;IACxB,UAAU,EAAE,wBAAwB;IACpC,UAAU,EAAE,wBAAwB;IACpC,OAAO,EAAE;QACP,OAAO,EAAE,qBAAqB;QAC9B,UAAU,EAAE,gCAAgC;KAC7C;IACD,SAAS,EAAE;QACT,OAAO,EAAE,uBAAuB;QAChC,UAAU,EAAE,kCAAkC;KAC/C;IACD,WAAW,EAAE;QACX,OAAO,EAAE,yBAAyB;QAClC,UAAU,EAAE,oCAAoC;KACjD;IACD,OAAO,EAAE;QACP,OAAO,EAAE,gBAAgB;QACzB,UAAU,EAAE,+BAA+B;KAC5C;IACD,KAAK,EAAE;QACL,OAAO,EAAE,mBAAmB;QAC5B,UAAU,EAAE,8BAA8B;KAC3C;IACD,MAAM,EAAE;QACN,OAAO,EAAE,oBAAoB;QAC7B,UAAU,EAAE,+BAA+B;KAC5C;IACD,OAAO,EAAE;QACP,OAAO,EAAE,qBAAqB;QAC9B,UAAU,EAAE,gCAAgC;KAC7C;IACD,IAAI,EAAE;QACJ,OAAO,EAAE,kBAAkB;QAC3B,UAAU,EAAE,6BAA6B;KAC1C;CACF,CAAC"}
1
+ {"version":3,"file":"component_colors.js","sourceRoot":"","sources":["../src/component_colors.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,eAAe,GAAe;IACzC,MAAM,EAAE,oBAAoB;IAC5B,KAAK,EAAE,mBAAmB;IAC1B,IAAI,EAAE,kBAAkB;IACxB,UAAU,EAAE,wBAAwB;IACpC,UAAU,EAAE,wBAAwB;IACpC,OAAO,EAAE;QACP,OAAO,EAAE,qBAAqB;QAC9B,UAAU,EAAE,gCAAgC;KAC7C;IACD,SAAS,EAAE;QACT,OAAO,EAAE,uBAAuB;QAChC,UAAU,EAAE,kCAAkC;KAC/C;IACD,WAAW,EAAE;QACX,OAAO,EAAE,yBAAyB;QAClC,UAAU,EAAE,oCAAoC;KACjD;IACD,OAAO,EAAE;QACP,OAAO,EAAE,gBAAgB;QACzB,UAAU,EAAE,2BAA2B;KACxC;IACD,KAAK,EAAE;QACL,OAAO,EAAE,mBAAmB;QAC5B,UAAU,EAAE,8BAA8B;KAC3C;IACD,MAAM,EAAE;QACN,OAAO,EAAE,oBAAoB;QAC7B,UAAU,EAAE,+BAA+B;KAC5C;IACD,OAAO,EAAE;QACP,OAAO,EAAE,qBAAqB;QAC9B,UAAU,EAAE,gCAAgC;KAC7C;IACD,IAAI,EAAE;QACJ,OAAO,EAAE,kBAAkB;QAC3B,UAAU,EAAE,6BAA6B;KAC1C;CACF,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Converts a CSS colour to the space-separated HSL channels the
3
+ * `hsl-channels` tokens expect (`222.2 84% 4.9%`), so a deployment can
4
+ * configure `#1e293b` rather than work the channels out by hand.
5
+ *
6
+ * Accepted inputs: bare channels, `#rgb`, `#rrggbb` (and their 4/8-digit
7
+ * forms when fully opaque), `rgb()` and `hsl()` with comma or space
8
+ * separators. Anything translucent is rejected — the channels carry no
9
+ * alpha, and silently dropping it would render a different colour.
10
+ */
11
+ /** Red, green and blue in 0–255 to HSL channels in degrees and percentages. */
12
+ export declare function rgbToHslChannels(red: number, green: number, blue: number): string;
13
+ /**
14
+ * The HSL channels for a CSS colour, or null when the input is not a colour
15
+ * this understands (a named colour, an `oklch()`, anything translucent).
16
+ */
17
+ export declare function toHslChannels(input: string): string | null;
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Converts a CSS colour to the space-separated HSL channels the
3
+ * `hsl-channels` tokens expect (`222.2 84% 4.9%`), so a deployment can
4
+ * configure `#1e293b` rather than work the channels out by hand.
5
+ *
6
+ * Accepted inputs: bare channels, `#rgb`, `#rrggbb` (and their 4/8-digit
7
+ * forms when fully opaque), `rgb()` and `hsl()` with comma or space
8
+ * separators. Anything translucent is rejected — the channels carry no
9
+ * alpha, and silently dropping it would render a different colour.
10
+ */
11
+ const NUMBER = "-?(?:\\d+\\.?\\d*|\\.\\d+)";
12
+ const BARE_CHANNELS = new RegExp(`^(${NUMBER})(?:deg)?\\s+(${NUMBER})%\\s+(${NUMBER})%$`);
13
+ const HEX = /^#([0-9a-f]{3,8})$/i;
14
+ const FUNCTIONAL = /^(rgba?|hsla?)\(\s*([^)]*?)\s*\)$/i;
15
+ function formatChannel(value) {
16
+ const rounded = Math.round(value * 10) / 10;
17
+ return Number.isInteger(rounded) ? String(rounded) : rounded.toFixed(1);
18
+ }
19
+ function formatChannels(hue, saturation, lightness) {
20
+ const h = ((hue % 360) + 360) % 360;
21
+ return `${formatChannel(h)} ${formatChannel(saturation)}% ${formatChannel(lightness)}%`;
22
+ }
23
+ /** Red, green and blue in 0–255 to HSL channels in degrees and percentages. */
24
+ export function rgbToHslChannels(red, green, blue) {
25
+ const r = red / 255;
26
+ const g = green / 255;
27
+ const b = blue / 255;
28
+ const max = Math.max(r, g, b);
29
+ const min = Math.min(r, g, b);
30
+ const delta = max - min;
31
+ const lightness = (max + min) / 2;
32
+ let hue = 0;
33
+ let saturation = 0;
34
+ if (delta !== 0) {
35
+ saturation = delta / (1 - Math.abs(2 * lightness - 1));
36
+ if (max === r)
37
+ hue = ((g - b) / delta) % 6;
38
+ else if (max === g)
39
+ hue = (b - r) / delta + 2;
40
+ else
41
+ hue = (r - g) / delta + 4;
42
+ hue *= 60;
43
+ }
44
+ return formatChannels(hue, saturation * 100, lightness * 100);
45
+ }
46
+ function isOpaqueAlpha(alpha) {
47
+ if (alpha === undefined)
48
+ return true;
49
+ if (alpha.endsWith("%"))
50
+ return Number(alpha.slice(0, -1)) === 100;
51
+ return Number(alpha) === 1;
52
+ }
53
+ function parseHex(digits) {
54
+ let expanded;
55
+ if (digits.length === 3 || digits.length === 4) {
56
+ expanded = digits
57
+ .split("")
58
+ .map((d) => d + d)
59
+ .join("");
60
+ }
61
+ else if (digits.length === 6 || digits.length === 8) {
62
+ expanded = digits;
63
+ }
64
+ else {
65
+ return null;
66
+ }
67
+ if (expanded.length === 8) {
68
+ if (expanded.slice(6).toLowerCase() !== "ff")
69
+ return null;
70
+ expanded = expanded.slice(0, 6);
71
+ }
72
+ const red = parseInt(expanded.slice(0, 2), 16);
73
+ const green = parseInt(expanded.slice(2, 4), 16);
74
+ const blue = parseInt(expanded.slice(4, 6), 16);
75
+ return rgbToHslChannels(red, green, blue);
76
+ }
77
+ function parseRgbComponent(component) {
78
+ if (component.endsWith("%")) {
79
+ const percent = Number(component.slice(0, -1));
80
+ return Number.isFinite(percent) ? (percent / 100) * 255 : null;
81
+ }
82
+ const value = Number(component);
83
+ return Number.isFinite(value) ? value : null;
84
+ }
85
+ function parseFunctional(name, body) {
86
+ // "r, g, b", "r g b", "r g b / a" and "r, g, b, a" all split the same way.
87
+ const parts = body.split(/\s*[,/]\s*|\s+/).filter((part) => part.length > 0);
88
+ if (parts.length < 3 || parts.length > 4)
89
+ return null;
90
+ const [first, second, third, alpha] = parts;
91
+ if (!isOpaqueAlpha(alpha))
92
+ return null;
93
+ if (name.startsWith("rgb")) {
94
+ const red = parseRgbComponent(first);
95
+ const green = parseRgbComponent(second);
96
+ const blue = parseRgbComponent(third);
97
+ if (red === null || green === null || blue === null)
98
+ return null;
99
+ const clamp = (v) => Math.min(255, Math.max(0, v));
100
+ return rgbToHslChannels(clamp(red), clamp(green), clamp(blue));
101
+ }
102
+ const hue = Number(first.replace(/deg$/i, ""));
103
+ if (!second.endsWith("%") || !third.endsWith("%"))
104
+ return null;
105
+ const saturation = Number(second.slice(0, -1));
106
+ const lightness = Number(third.slice(0, -1));
107
+ if (![hue, saturation, lightness].every(Number.isFinite))
108
+ return null;
109
+ return formatChannels(hue, saturation, lightness);
110
+ }
111
+ /**
112
+ * The HSL channels for a CSS colour, or null when the input is not a colour
113
+ * this understands (a named colour, an `oklch()`, anything translucent).
114
+ */
115
+ export function toHslChannels(input) {
116
+ const value = input.trim();
117
+ if (value.length === 0)
118
+ return null;
119
+ const bare = BARE_CHANNELS.exec(value);
120
+ if (bare) {
121
+ const [, hue, saturation, lightness] = bare;
122
+ return formatChannels(Number(hue), Number(saturation), Number(lightness));
123
+ }
124
+ const hex = HEX.exec(value);
125
+ if (hex)
126
+ return parseHex(hex[1]);
127
+ const functional = FUNCTIONAL.exec(value);
128
+ if (functional) {
129
+ return parseFunctional(functional[1].toLowerCase(), functional[2]);
130
+ }
131
+ return null;
132
+ }
133
+ //# sourceMappingURL=hsl_channels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hsl_channels.js","sourceRoot":"","sources":["../src/hsl_channels.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -4,3 +4,4 @@ export type { SchemaVaultsBrandColor } from "./brand_colors";
4
4
  export { getSchemaVaultsBrandColor, brandColors } from "./brand_colors";
5
5
  export { getScreenBreakpoint, listScreenBreakpoints, isValidScreenBreakpoint, } from "./ScreenBreakpoints";
6
6
  export type { ScreenBreakpointID } from "./ScreenBreakpoints";
7
+ export * from "./tokens";
package/dist/index.js CHANGED
@@ -2,4 +2,7 @@ export { SchemaVaultsTailwindConfigFactory, SchemaVaultsTailwindConfigFactory as
2
2
  export { default as withSchemaVaultsTailwindTheme } from "./withSchemaVaultsTailwindTheme";
3
3
  export { getSchemaVaultsBrandColor, brandColors } from "./brand_colors";
4
4
  export { getScreenBreakpoint, listScreenBreakpoints, isValidScreenBreakpoint, } from "./ScreenBreakpoints";
5
+ // The token manifest and per-deployment override helpers; also available
6
+ // without the Node.js-only config factory from "@schemavaults/theme/tokens".
7
+ export * from "./tokens";
5
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iCAAiC,EACjC,iCAAiC,IAAI,OAAO,GAC7C,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,OAAO,IAAI,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAG3F,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAExE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iCAAiC,EACjC,iCAAiC,IAAI,OAAO,GAC7C,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,OAAO,IAAI,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAG3F,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAExE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAG7B,yEAAyE;AACzE,6EAA6E;AAC7E,cAAc,UAAU,CAAC"}
@@ -0,0 +1,112 @@
1
+ import { type ThemeToken, type ThemeTokenID, type ThemeTokenScope } from "./theme_tokens";
2
+ /**
3
+ * Overriding the stylesheet's tokens for one deployment.
4
+ *
5
+ * `globals.css` reads every token through an override variable:
6
+ * `--background: var(--sv-theme-light-background, 0 0% 100%)`.
7
+ * The helpers here turn a `ThemeOverrides` object into those variables — as
8
+ * a style object for a framework's `<html style={…}>`, or as CSS text for a
9
+ * `<style>` element — after checking and normalising each value, so a hex
10
+ * colour becomes the HSL channels an `hsl-channels` token needs, and a
11
+ * value that would break the stylesheet (or escape an attribute) is
12
+ * refused rather than shipped.
13
+ *
14
+ * Values must be set only for the scopes a token has: `radius` is shared by
15
+ * both modes (`overrides.shared.radius`), every colour has a `light` and a
16
+ * `dark` value. A scope left out keeps the stylesheet default.
17
+ */
18
+ /** Which tokens to override, per scope, keyed by token id. Values are raw: hex colours are fine. */
19
+ export interface ThemeOverrides {
20
+ light?: Partial<Record<ThemeTokenID, string>>;
21
+ dark?: Partial<Record<ThemeTokenID, string>>;
22
+ shared?: Partial<Record<ThemeTokenID, string>>;
23
+ }
24
+ export declare const THEME_OVERRIDE_VARIABLE_PREFIX: "--sv-theme";
25
+ /** The custom property `globals.css` reads a token's override from, e.g. `--sv-theme-dark-background`. */
26
+ export declare function themeOverrideVariable(id: ThemeTokenID, scope: ThemeTokenScope): `--${string}`;
27
+ /** Thrown for a value the token cannot take; `reason` is safe to show to an administrator. */
28
+ export declare class ThemeTokenValueError extends Error {
29
+ readonly tokenId: ThemeTokenID;
30
+ readonly scope: ThemeTokenScope;
31
+ readonly value: string;
32
+ readonly reason: string;
33
+ constructor(tokenId: ThemeTokenID, scope: ThemeTokenScope, value: string, reason: string);
34
+ }
35
+ /**
36
+ * The value as `globals.css` should receive it, or a `ThemeTokenValueError`.
37
+ * `hsl-channels` tokens accept any opaque colour `toHslChannels` understands
38
+ * and come back as channels; the other formats are checked and trimmed.
39
+ */
40
+ export declare function normalizeThemeTokenValue(token: ThemeToken, scope: ThemeTokenScope, rawValue: string): string;
41
+ /**
42
+ * The override variables as a style object — `{ "--sv-theme-light-background": "210 40% 98%" }` —
43
+ * for the <html> element's `style` attribute (React passes custom properties
44
+ * through as given). Only the tokens set in `overrides` appear; a stylesheet
45
+ * default is never restated, so it keeps applying wherever nothing is set.
46
+ * Throws `ThemeTokenValueError` for a value a token cannot take.
47
+ */
48
+ export declare function createThemeOverrideStyle(overrides: ThemeOverrides): Record<`--${string}`, string>;
49
+ /**
50
+ * The same declarations as one CSS rule for a `<style>` element:
51
+ * `:root{--sv-theme-light-background:210 40% 98%;}`. Empty when nothing is
52
+ * overridden. `selector` should be the <html> element (`:root`) so the
53
+ * variables are inherited by the `.dark` block wherever the class is placed.
54
+ */
55
+ export declare function renderThemeOverrideCss(overrides: ThemeOverrides, selector?: string): string;
56
+ /** The token's effective value in one scope, for a settings page. */
57
+ export interface ResolvedThemeTokenValue {
58
+ scope: ThemeTokenScope;
59
+ /** The stylesheet default. */
60
+ defaultValue: string;
61
+ /** The normalised override, or null when the default applies. */
62
+ override: string | null;
63
+ /** What the token renders as: the override when set, the default otherwise. */
64
+ value: string;
65
+ /** The custom property an override is delivered through. */
66
+ overrideVariable: `--${string}`;
67
+ }
68
+ export interface ResolvedThemeToken {
69
+ token: ThemeToken;
70
+ /** One entry per scope the token has: light and dark, or shared. */
71
+ values: ResolvedThemeTokenValue[];
72
+ }
73
+ /**
74
+ * Every token with its defaults and the overrides applied, in stylesheet
75
+ * order: the rows of a "theme" settings page. Throws for an invalid value,
76
+ * like `createThemeOverrideStyle`; validate with `themeOverridesFromEnvironment`
77
+ * (or catch `ThemeTokenValueError`) first when the values are untrusted.
78
+ */
79
+ export declare function resolveThemeTokens(overrides?: ThemeOverrides): ResolvedThemeToken[];
80
+ export interface ThemeEnvironmentOptions {
81
+ /** The variable name prefix; `THEME` reads `THEME_LIGHT_BACKGROUND`, `THEME_DARK_BACKGROUND` and `THEME_RADIUS`. */
82
+ prefix?: string;
83
+ }
84
+ /**
85
+ * The environment variable that configures a token in one scope:
86
+ * `<PREFIX>_<SCOPE>_<TOKEN>` for light and dark values and `<PREFIX>_<TOKEN>`
87
+ * for shared ones, with the token id upper-cased and hyphens turned into
88
+ * underscores (`sidebar-primary-foreground` → `THEME_LIGHT_SIDEBAR_PRIMARY_FOREGROUND`).
89
+ */
90
+ export declare function themeTokenEnvironmentVariable(id: ThemeTokenID, scope: ThemeTokenScope, options?: ThemeEnvironmentOptions): string;
91
+ /** A variable whose value was refused, with the reason to show an administrator. */
92
+ export interface ThemeOverrideProblem {
93
+ variable: string;
94
+ tokenId: ThemeTokenID;
95
+ scope: ThemeTokenScope;
96
+ value: string;
97
+ reason: string;
98
+ }
99
+ export interface ThemeOverridesFromEnvironment {
100
+ /** The valid overrides, normalised; safe to pass to `createThemeOverrideStyle`. */
101
+ overrides: ThemeOverrides;
102
+ /** Variables that were set to something the token cannot take; those keep their defaults. */
103
+ problems: ThemeOverrideProblem[];
104
+ }
105
+ /**
106
+ * Reads every token's override from environment variables named by
107
+ * `themeTokenEnvironmentVariable`. A variable that is unset or blank leaves
108
+ * the default alone; an invalid value is reported in `problems` and skipped
109
+ * rather than thrown, so one typo in a deployment's configuration cannot
110
+ * take its pages down.
111
+ */
112
+ export declare function themeOverridesFromEnvironment(env: Readonly<Record<string, string | undefined>>, options?: ThemeEnvironmentOptions): ThemeOverridesFromEnvironment;
@@ -0,0 +1,171 @@
1
+ import { toHslChannels } from "./hsl_channels";
2
+ import { getThemeToken, isThemeTokenId, listThemeTokens, themeTokenDefault, themeTokenHasScope, } from "./theme_tokens";
3
+ export const THEME_OVERRIDE_VARIABLE_PREFIX = "--sv-theme";
4
+ /** The custom property `globals.css` reads a token's override from, e.g. `--sv-theme-dark-background`. */
5
+ export function themeOverrideVariable(id, scope) {
6
+ return scope === "shared"
7
+ ? `${THEME_OVERRIDE_VARIABLE_PREFIX}-${id}`
8
+ : `${THEME_OVERRIDE_VARIABLE_PREFIX}-${scope}-${id}`;
9
+ }
10
+ /** Thrown for a value the token cannot take; `reason` is safe to show to an administrator. */
11
+ export class ThemeTokenValueError extends Error {
12
+ tokenId;
13
+ scope;
14
+ value;
15
+ reason;
16
+ constructor(tokenId, scope, value, reason) {
17
+ super(`Invalid ${scope} value for theme token '${tokenId}' (${JSON.stringify(value)}): ${reason}`);
18
+ this.name = "ThemeTokenValueError";
19
+ this.tokenId = tokenId;
20
+ this.scope = scope;
21
+ this.value = value;
22
+ this.reason = reason;
23
+ }
24
+ }
25
+ // Characters that could end the declaration, the rule or the attribute the
26
+ // value is written into. No colour or length legitimately contains them.
27
+ const UNSAFE_CHARACTERS = /[;{}<>"'\\\x00-\x1f]|\/\*/;
28
+ const CSS_COLOR = /^(#[0-9a-f]{3,8}|[a-z]+|[a-z-]+\([\w\s.,%/+-]*\))$/i;
29
+ const CSS_LENGTH = /^(0|-?(?:\d+\.?\d*|\.\d+)(px|rem|em|%|vh|vw|vmin|vmax|ch|ex))$/i;
30
+ /**
31
+ * The value as `globals.css` should receive it, or a `ThemeTokenValueError`.
32
+ * `hsl-channels` tokens accept any opaque colour `toHslChannels` understands
33
+ * and come back as channels; the other formats are checked and trimmed.
34
+ */
35
+ export function normalizeThemeTokenValue(token, scope, rawValue) {
36
+ const value = rawValue.trim();
37
+ if (!themeTokenHasScope(token, scope)) {
38
+ throw new ThemeTokenValueError(token.id, scope, rawValue, `the token has no ${scope} value; it takes ${token.scopes.map((s) => `'${s}'`).join(" and ")}`);
39
+ }
40
+ if (value.length === 0) {
41
+ throw new ThemeTokenValueError(token.id, scope, rawValue, "the value is empty");
42
+ }
43
+ if (UNSAFE_CHARACTERS.test(value)) {
44
+ throw new ThemeTokenValueError(token.id, scope, rawValue, "the value contains characters a CSS value cannot");
45
+ }
46
+ switch (token.format) {
47
+ case "hsl-channels": {
48
+ const channels = toHslChannels(value);
49
+ if (channels === null) {
50
+ throw new ThemeTokenValueError(token.id, scope, rawValue, "expected HSL channels ('222.2 84% 4.9%'), a hex colour, or an opaque rgb()/hsl() colour");
51
+ }
52
+ return channels;
53
+ }
54
+ case "css-color": {
55
+ if (!CSS_COLOR.test(value)) {
56
+ throw new ThemeTokenValueError(token.id, scope, rawValue, "expected a CSS colour such as '#60a5fa' or 'oklch(0.985 0 0)'");
57
+ }
58
+ return value;
59
+ }
60
+ case "length": {
61
+ if (!CSS_LENGTH.test(value)) {
62
+ throw new ThemeTokenValueError(token.id, scope, rawValue, "expected a CSS length such as '0.5rem' or '8px'");
63
+ }
64
+ return value;
65
+ }
66
+ }
67
+ }
68
+ function assertThemeTokenId(maybeId, scope) {
69
+ if (!isThemeTokenId(maybeId)) {
70
+ throw new Error(`Unknown theme token '${maybeId}' in the ${scope} overrides!`);
71
+ }
72
+ return maybeId;
73
+ }
74
+ function* eachOverride(overrides) {
75
+ for (const scope of ["light", "dark", "shared"]) {
76
+ const values = overrides[scope];
77
+ if (!values)
78
+ continue;
79
+ for (const [maybeId, rawValue] of Object.entries(values)) {
80
+ if (rawValue === undefined || rawValue === null)
81
+ continue;
82
+ const id = assertThemeTokenId(maybeId, scope);
83
+ yield [getThemeToken(id), scope, rawValue];
84
+ }
85
+ }
86
+ }
87
+ /**
88
+ * The override variables as a style object — `{ "--sv-theme-light-background": "210 40% 98%" }` —
89
+ * for the <html> element's `style` attribute (React passes custom properties
90
+ * through as given). Only the tokens set in `overrides` appear; a stylesheet
91
+ * default is never restated, so it keeps applying wherever nothing is set.
92
+ * Throws `ThemeTokenValueError` for a value a token cannot take.
93
+ */
94
+ export function createThemeOverrideStyle(overrides) {
95
+ const style = {};
96
+ for (const [token, scope, rawValue] of eachOverride(overrides)) {
97
+ style[themeOverrideVariable(token.id, scope)] = normalizeThemeTokenValue(token, scope, rawValue);
98
+ }
99
+ return style;
100
+ }
101
+ /**
102
+ * The same declarations as one CSS rule for a `<style>` element:
103
+ * `:root{--sv-theme-light-background:210 40% 98%;}`. Empty when nothing is
104
+ * overridden. `selector` should be the <html> element (`:root`) so the
105
+ * variables are inherited by the `.dark` block wherever the class is placed.
106
+ */
107
+ export function renderThemeOverrideCss(overrides, selector = ":root") {
108
+ const declarations = Object.entries(createThemeOverrideStyle(overrides)).map(([variable, value]) => `${variable}:${value};`);
109
+ if (declarations.length === 0)
110
+ return "";
111
+ return `${selector}{${declarations.join("")}}`;
112
+ }
113
+ /**
114
+ * Every token with its defaults and the overrides applied, in stylesheet
115
+ * order: the rows of a "theme" settings page. Throws for an invalid value,
116
+ * like `createThemeOverrideStyle`; validate with `themeOverridesFromEnvironment`
117
+ * (or catch `ThemeTokenValueError`) first when the values are untrusted.
118
+ */
119
+ export function resolveThemeTokens(overrides = {}) {
120
+ const style = createThemeOverrideStyle(overrides);
121
+ return listThemeTokens().map((token) => ({
122
+ token,
123
+ values: token.scopes.map((scope) => {
124
+ const overrideVariable = themeOverrideVariable(token.id, scope);
125
+ const defaultValue = themeTokenDefault(token, scope);
126
+ const override = style[overrideVariable] ?? null;
127
+ return { scope, defaultValue, override, value: override ?? defaultValue, overrideVariable };
128
+ }),
129
+ }));
130
+ }
131
+ const DEFAULT_ENVIRONMENT_PREFIX = "THEME";
132
+ /**
133
+ * The environment variable that configures a token in one scope:
134
+ * `<PREFIX>_<SCOPE>_<TOKEN>` for light and dark values and `<PREFIX>_<TOKEN>`
135
+ * for shared ones, with the token id upper-cased and hyphens turned into
136
+ * underscores (`sidebar-primary-foreground` → `THEME_LIGHT_SIDEBAR_PRIMARY_FOREGROUND`).
137
+ */
138
+ export function themeTokenEnvironmentVariable(id, scope, options = {}) {
139
+ const prefix = options.prefix ?? DEFAULT_ENVIRONMENT_PREFIX;
140
+ const suffix = id.toUpperCase().replace(/-/g, "_");
141
+ return scope === "shared" ? `${prefix}_${suffix}` : `${prefix}_${scope.toUpperCase()}_${suffix}`;
142
+ }
143
+ /**
144
+ * Reads every token's override from environment variables named by
145
+ * `themeTokenEnvironmentVariable`. A variable that is unset or blank leaves
146
+ * the default alone; an invalid value is reported in `problems` and skipped
147
+ * rather than thrown, so one typo in a deployment's configuration cannot
148
+ * take its pages down.
149
+ */
150
+ export function themeOverridesFromEnvironment(env, options = {}) {
151
+ const overrides = {};
152
+ const problems = [];
153
+ for (const token of listThemeTokens()) {
154
+ for (const scope of token.scopes) {
155
+ const variable = themeTokenEnvironmentVariable(token.id, scope, options);
156
+ const rawValue = env[variable];
157
+ if (rawValue === undefined || rawValue.trim().length === 0)
158
+ continue;
159
+ try {
160
+ const value = normalizeThemeTokenValue(token, scope, rawValue);
161
+ (overrides[scope] ??= {})[token.id] = value;
162
+ }
163
+ catch (error) {
164
+ const reason = error instanceof ThemeTokenValueError ? error.reason : String(error);
165
+ problems.push({ variable, tokenId: token.id, scope, value: rawValue, reason });
166
+ }
167
+ }
168
+ }
169
+ return { overrides, problems };
170
+ }
171
+ //# sourceMappingURL=theme_overrides.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme_overrides.js","sourceRoot":"","sources":["../src/theme_overrides.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * The design tokens `globals.css` declares, as data: which CSS variable each
3
+ * one is, the value format it expects, its light and dark defaults, and a
4
+ * label and description an application can show on a theming settings page.
5
+ *
6
+ * `globals.css` declares every token as
7
+ * `--token: var(--sv-theme-<scope>-<id>, <default>)`,
8
+ * so an application overrides a token by setting the override variable on
9
+ * the <html> element; see `theme_overrides.ts`. A unit test checks that the
10
+ * stylesheet and this manifest agree.
11
+ */
12
+ /** Which stylesheet block a value belongs to: the light `:root`, the `.dark` class, or both. */
13
+ export type ThemeTokenScope = "light" | "dark" | "shared";
14
+ /** The two colour modes the stylesheet declares tokens for. */
15
+ export type ThemeMode = Exclude<ThemeTokenScope, "shared">;
16
+ /**
17
+ * How a token's value is written.
18
+ * - `hsl-channels`: the three space-separated channels of an HSL colour
19
+ * (`222.2 84% 4.9%`), which the Tailwind theme wraps in `hsl()`.
20
+ * - `css-color`: any CSS `<color>` (`#60a5fa`, `oklch(0.985 0 0)`, `rgb(…)`).
21
+ * - `length`: a CSS `<length>` such as `0.5rem`.
22
+ */
23
+ export type ThemeTokenFormat = "hsl-channels" | "css-color" | "length";
24
+ /** A heading a settings page can group tokens under. */
25
+ export type ThemeTokenGroup = "brand" | "page" | "surfaces" | "actions" | "states" | "outlines" | "shape" | "sidebar";
26
+ interface ThemeTokenBase {
27
+ /** The CSS variable the token is read from, e.g. `--background`. */
28
+ readonly cssVariable: `--${string}`;
29
+ readonly format: ThemeTokenFormat;
30
+ readonly group: ThemeTokenGroup;
31
+ /** A short human-readable name, e.g. "Page background". */
32
+ readonly label: string;
33
+ /** Where the token shows up, for a settings page. */
34
+ readonly description: string;
35
+ }
36
+ /** A token with a separate value in light and dark mode. */
37
+ export interface ModeThemeToken extends ThemeTokenBase {
38
+ readonly id: ModeThemeTokenID;
39
+ readonly scopes: readonly ["light", "dark"];
40
+ readonly defaults: {
41
+ readonly light: string;
42
+ readonly dark: string;
43
+ };
44
+ }
45
+ /** A token declared once, for both modes. */
46
+ export interface SharedThemeToken extends ThemeTokenBase {
47
+ readonly id: SharedThemeTokenID;
48
+ readonly scopes: readonly ["shared"];
49
+ readonly defaults: {
50
+ readonly shared: string;
51
+ };
52
+ }
53
+ export type ThemeToken = ModeThemeToken | SharedThemeToken;
54
+ declare const MODE_THEME_TOKEN_IDS: readonly ["brand-blue", "brand-red", "background", "foreground", "card", "card-foreground", "popover", "popover-foreground", "primary", "primary-foreground", "secondary", "secondary-foreground", "muted", "muted-foreground", "accent", "accent-foreground", "destructive", "destructive-foreground", "warning", "warning-foreground", "border", "input", "ring", "sidebar", "sidebar-foreground", "sidebar-primary", "sidebar-primary-foreground", "sidebar-accent", "sidebar-accent-foreground", "sidebar-border", "sidebar-ring"];
55
+ declare const SHARED_THEME_TOKEN_IDS: readonly ["radius"];
56
+ export type ModeThemeTokenID = (typeof MODE_THEME_TOKEN_IDS)[number];
57
+ export type SharedThemeTokenID = (typeof SHARED_THEME_TOKEN_IDS)[number];
58
+ export type ThemeTokenID = ModeThemeTokenID | SharedThemeTokenID;
59
+ /**
60
+ * Every token, in the order `globals.css` declares them. Tokens whose format
61
+ * is `hsl-channels` are the shadcn/ui component colours the Tailwind theme
62
+ * exposes as `bg-background`, `text-primary-foreground` and so on.
63
+ */
64
+ export declare const THEME_TOKENS: readonly ThemeToken[];
65
+ /** Every token, in stylesheet order. */
66
+ export declare function listThemeTokens(): readonly ThemeToken[];
67
+ /** The ids of every token, in stylesheet order. */
68
+ export declare function listThemeTokenIds(): readonly ThemeTokenID[];
69
+ export declare function isThemeTokenId(maybeId: string): maybeId is ThemeTokenID;
70
+ export declare function getThemeToken(id: ThemeTokenID): ThemeToken;
71
+ /** Whether the token has a value in the given scope (`radius` has none in `light`). */
72
+ export declare function themeTokenHasScope(token: ThemeToken, scope: ThemeTokenScope): boolean;
73
+ /** The stylesheet's default for the token in a scope, or undefined when the scope does not apply. */
74
+ export declare function themeTokenDefault(token: ThemeToken, scope: ThemeTokenScope): string | undefined;
75
+ export {};
@@ -0,0 +1,149 @@
1
+ /**
2
+ * The design tokens `globals.css` declares, as data: which CSS variable each
3
+ * one is, the value format it expects, its light and dark defaults, and a
4
+ * label and description an application can show on a theming settings page.
5
+ *
6
+ * `globals.css` declares every token as
7
+ * `--token: var(--sv-theme-<scope>-<id>, <default>)`,
8
+ * so an application overrides a token by setting the override variable on
9
+ * the <html> element; see `theme_overrides.ts`. A unit test checks that the
10
+ * stylesheet and this manifest agree.
11
+ */
12
+ const MODE_THEME_TOKEN_IDS = [
13
+ "brand-blue",
14
+ "brand-red",
15
+ "background",
16
+ "foreground",
17
+ "card",
18
+ "card-foreground",
19
+ "popover",
20
+ "popover-foreground",
21
+ "primary",
22
+ "primary-foreground",
23
+ "secondary",
24
+ "secondary-foreground",
25
+ "muted",
26
+ "muted-foreground",
27
+ "accent",
28
+ "accent-foreground",
29
+ "destructive",
30
+ "destructive-foreground",
31
+ "warning",
32
+ "warning-foreground",
33
+ "border",
34
+ "input",
35
+ "ring",
36
+ "sidebar",
37
+ "sidebar-foreground",
38
+ "sidebar-primary",
39
+ "sidebar-primary-foreground",
40
+ "sidebar-accent",
41
+ "sidebar-accent-foreground",
42
+ "sidebar-border",
43
+ "sidebar-ring",
44
+ ];
45
+ const SHARED_THEME_TOKEN_IDS = ["radius"];
46
+ const MODE_SCOPES = ["light", "dark"];
47
+ const SHARED_SCOPES = ["shared"];
48
+ function hsl(id, group, label, description, light, dark) {
49
+ return {
50
+ id,
51
+ cssVariable: `--${id}`,
52
+ format: "hsl-channels",
53
+ group,
54
+ label,
55
+ description,
56
+ scopes: MODE_SCOPES,
57
+ defaults: { light, dark },
58
+ };
59
+ }
60
+ function color(id, cssVariable, group, label, description, light, dark) {
61
+ return {
62
+ id,
63
+ cssVariable,
64
+ format: "css-color",
65
+ group,
66
+ label,
67
+ description,
68
+ scopes: MODE_SCOPES,
69
+ defaults: { light, dark },
70
+ };
71
+ }
72
+ /**
73
+ * Every token, in the order `globals.css` declares them. Tokens whose format
74
+ * is `hsl-channels` are the shadcn/ui component colours the Tailwind theme
75
+ * exposes as `bg-background`, `text-primary-foreground` and so on.
76
+ */
77
+ export const THEME_TOKENS = [
78
+ color("brand-blue", "--schemavaults-brand-blue", "brand", "Brand blue", "The SchemaVaults brand blue, available as the `schemavaults-brand-blue` Tailwind colour.", "#60a5fa", "#60a5fa"),
79
+ color("brand-red", "--schemavaults-brand-red", "brand", "Brand red", "The SchemaVaults brand red, available as the `schemavaults-brand-red` Tailwind colour.", "#dc2626", "#dc2626"),
80
+ hsl("background", "page", "Page background", "The background of the page body.", "0 0% 100%", "222.2 84% 4.9%"),
81
+ hsl("foreground", "page", "Page text", "The default text colour on the page background.", "222.2 84% 4.9%", "210 40% 98%"),
82
+ hsl("card", "surfaces", "Card background", "The background of cards and panels.", "0 0% 100%", "222.2 84% 4.9%"),
83
+ hsl("card-foreground", "surfaces", "Card text", "Text on a card.", "222.2 84% 4.9%", "210 40% 98%"),
84
+ hsl("popover", "surfaces", "Popover background", "The background of dropdown menus, popovers and tooltips.", "0 0% 100%", "222.2 84% 4.9%"),
85
+ hsl("popover-foreground", "surfaces", "Popover text", "Text in a popover.", "222.2 84% 4.9%", "210 40% 98%"),
86
+ hsl("primary", "actions", "Primary", "Primary buttons, links and selected controls.", "222.2 47.4% 11.2%", "210 40% 98%"),
87
+ hsl("primary-foreground", "actions", "Primary text", "Text on a primary-coloured control.", "210 40% 98%", "222.2 47.4% 11.2%"),
88
+ hsl("secondary", "actions", "Secondary", "Secondary buttons and badges.", "210 40% 96.1%", "217.2 32.6% 17.5%"),
89
+ hsl("secondary-foreground", "actions", "Secondary text", "Text on a secondary-coloured control.", "222.2 47.4% 11.2%", "210 40% 98%"),
90
+ hsl("muted", "actions", "Muted", "Subdued backgrounds: table stripes, disabled controls, skeletons.", "210 40% 96.1%", "217.2 32.6% 17.5%"),
91
+ hsl("muted-foreground", "actions", "Muted text", "Secondary text such as descriptions and captions.", "215.4 16.3% 46.9%", "215 20.2% 65.1%"),
92
+ hsl("accent", "actions", "Accent", "Hover and focus backgrounds of menu items and list rows.", "210 40% 96.1%", "217.2 32.6% 17.5%"),
93
+ hsl("accent-foreground", "actions", "Accent text", "Text on an accent background.", "222.2 47.4% 11.2%", "210 40% 98%"),
94
+ hsl("destructive", "states", "Destructive", "Delete buttons and error states.", "0 84.2% 60.2%", "0 62.8% 30.6%"),
95
+ hsl("destructive-foreground", "states", "Destructive text", "Text on a destructive-coloured control.", "210 40% 98%", "210 40% 98%"),
96
+ color("warning", "--warning", "states", "Warning", "Warning callouts and badges.", "oklch(82% 0.189 84.429)", "oklch(82% 0.189 84.429)"),
97
+ color("warning-foreground", "--warning-foreground", "states", "Warning text", "Text on a warning background.", "oklch(41% 0.112 45.904)", "oklch(41% 0.112 45.904)"),
98
+ hsl("border", "outlines", "Border", "The default border colour of every element.", "214.3 31.8% 91.4%", "217.2 32.6% 17.5%"),
99
+ hsl("input", "outlines", "Input border", "The border of text inputs, selects and textareas.", "214.3 31.8% 91.4%", "217.2 32.6% 17.5%"),
100
+ hsl("ring", "outlines", "Focus ring", "The outline drawn around a focused control.", "222.2 84% 4.9%", "212.7 26.8% 83.9%"),
101
+ {
102
+ id: "radius",
103
+ cssVariable: "--radius",
104
+ format: "length",
105
+ group: "shape",
106
+ label: "Corner radius",
107
+ description: "The rounding of buttons, inputs and cards (`rounded-lg`); `rounded-md` and `rounded-sm` are derived from it.",
108
+ scopes: SHARED_SCOPES,
109
+ defaults: { shared: "0.5rem" },
110
+ },
111
+ color("sidebar", "--sidebar", "sidebar", "Sidebar background", "The background of the navigation sidebar.", "oklch(0.985 0 0)", "oklch(0.205 0 0)"),
112
+ color("sidebar-foreground", "--sidebar-foreground", "sidebar", "Sidebar text", "Text in the sidebar.", "oklch(0.145 0 0)", "oklch(0.985 0 0)"),
113
+ color("sidebar-primary", "--sidebar-primary", "sidebar", "Sidebar primary", "The active navigation item's background.", "oklch(0.205 0 0)", "oklch(0.488 0.243 264.376)"),
114
+ color("sidebar-primary-foreground", "--sidebar-primary-foreground", "sidebar", "Sidebar primary text", "Text of the active navigation item.", "oklch(0.985 0 0)", "oklch(0.985 0 0)"),
115
+ color("sidebar-accent", "--sidebar-accent", "sidebar", "Sidebar accent", "The hovered navigation item's background.", "oklch(0.97 0 0)", "oklch(0.269 0 0)"),
116
+ color("sidebar-accent-foreground", "--sidebar-accent-foreground", "sidebar", "Sidebar accent text", "Text of a hovered navigation item.", "oklch(0.205 0 0)", "oklch(0.985 0 0)"),
117
+ color("sidebar-border", "--sidebar-border", "sidebar", "Sidebar border", "The sidebar's edge and separators.", "oklch(0.922 0 0)", "oklch(1 0 0 / 10%)"),
118
+ color("sidebar-ring", "--sidebar-ring", "sidebar", "Sidebar focus ring", "The outline around a focused sidebar item.", "oklch(0.708 0 0)", "oklch(0.439 0 0)"),
119
+ ];
120
+ const THEME_TOKENS_BY_ID = new Map(THEME_TOKENS.map((token) => [token.id, token]));
121
+ /** Every token, in stylesheet order. */
122
+ export function listThemeTokens() {
123
+ return THEME_TOKENS;
124
+ }
125
+ /** The ids of every token, in stylesheet order. */
126
+ export function listThemeTokenIds() {
127
+ return THEME_TOKENS.map((token) => token.id);
128
+ }
129
+ export function isThemeTokenId(maybeId) {
130
+ return THEME_TOKENS_BY_ID.has(maybeId);
131
+ }
132
+ export function getThemeToken(id) {
133
+ const token = THEME_TOKENS_BY_ID.get(id);
134
+ if (!token) {
135
+ throw new Error(`Unknown theme token '${id}'! Valid tokens: ${listThemeTokenIds()
136
+ .map((k) => `'${k}'`)
137
+ .join(", ")}`);
138
+ }
139
+ return token;
140
+ }
141
+ /** Whether the token has a value in the given scope (`radius` has none in `light`). */
142
+ export function themeTokenHasScope(token, scope) {
143
+ return token.scopes.includes(scope);
144
+ }
145
+ /** The stylesheet's default for the token in a scope, or undefined when the scope does not apply. */
146
+ export function themeTokenDefault(token, scope) {
147
+ return token.defaults[scope];
148
+ }
149
+ //# sourceMappingURL=theme_tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme_tokens.js","sourceRoot":"","sources":["../src/theme_tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAuDH,MAAM,oBAAoB,GAAG;IAC3B,YAAY;IACZ,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,MAAM;IACN,iBAAiB;IACjB,SAAS;IACT,oBAAoB;IACpB,SAAS;IACT,oBAAoB;IACpB,WAAW;IACX,sBAAsB;IACtB,OAAO;IACP,kBAAkB;IAClB,QAAQ;IACR,mBAAmB;IACnB,aAAa;IACb,wBAAwB;IACxB,SAAS;IACT,oBAAoB;IACpB,QAAQ;IACR,OAAO;IACP,MAAM;IACN,SAAS;IACT,oBAAoB;IACpB,iBAAiB;IACjB,4BAA4B;IAC5B,gBAAgB;IAChB,2BAA2B;IAC3B,gBAAgB;IAChB,cAAc;CACsB,CAAC;AAEvC,MAAM,sBAAsB,GAAG,CAAC,QAAQ,CAAsC,CAAC;AAM/E,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,MAAM,CAAU,CAAC;AAC/C,MAAM,aAAa,GAAG,CAAC,QAAQ,CAAU,CAAC;AAE1C,SAAS,GAAG,CACV,EAAoB,EACpB,KAAsB,EACtB,KAAa,EACb,WAAmB,EACnB,KAAa,EACb,IAAY;IAEZ,OAAO;QACL,EAAE;QACF,WAAW,EAAE,KAAK,EAAE,EAAE;QACtB,MAAM,EAAE,cAAc;QACtB,KAAK;QACL,KAAK;QACL,WAAW;QACX,MAAM,EAAE,WAAW;QACnB,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;KAC1B,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CACZ,EAAoB,EACpB,WAA0B,EAC1B,KAAsB,EACtB,KAAa,EACb,WAAmB,EACnB,KAAa,EACb,IAAY;IAEZ,OAAO;QACL,EAAE;QACF,WAAW;QACX,MAAM,EAAE,WAAW;QACnB,KAAK;QACL,KAAK;QACL,WAAW;QACX,MAAM,EAAE,WAAW;QACnB,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;KAC1B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAA0B;IACjD,KAAK,CACH,YAAY,EACZ,2BAA2B,EAC3B,OAAO,EACP,YAAY,EACZ,0FAA0F,EAC1F,SAAS,EACT,SAAS,CACV;IACD,KAAK,CACH,WAAW,EACX,0BAA0B,EAC1B,OAAO,EACP,WAAW,EACX,wFAAwF,EACxF,SAAS,EACT,SAAS,CACV;IAED,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,iBAAiB,EAAE,kCAAkC,EAAE,WAAW,EAAE,gBAAgB,CAAC;IAC/G,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,iDAAiD,EAAE,gBAAgB,EAAE,aAAa,CAAC;IAE1H,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,qCAAqC,EAAE,WAAW,EAAE,gBAAgB,CAAC;IAChH,GAAG,CAAC,iBAAiB,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,aAAa,CAAC;IACnG,GAAG,CAAC,SAAS,EAAE,UAAU,EAAE,oBAAoB,EAAE,0DAA0D,EAAE,WAAW,EAAE,gBAAgB,CAAC;IAC3I,GAAG,CAAC,oBAAoB,EAAE,UAAU,EAAE,cAAc,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,aAAa,CAAC;IAE5G,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,+CAA+C,EAAE,mBAAmB,EAAE,aAAa,CAAC;IACzH,GAAG,CAAC,oBAAoB,EAAE,SAAS,EAAE,cAAc,EAAE,qCAAqC,EAAE,aAAa,EAAE,mBAAmB,CAAC;IAC/H,GAAG,CAAC,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,+BAA+B,EAAE,eAAe,EAAE,mBAAmB,CAAC;IAC/G,GAAG,CAAC,sBAAsB,EAAE,SAAS,EAAE,gBAAgB,EAAE,uCAAuC,EAAE,mBAAmB,EAAE,aAAa,CAAC;IACrI,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,mEAAmE,EAAE,eAAe,EAAE,mBAAmB,CAAC;IAC3I,GAAG,CAAC,kBAAkB,EAAE,SAAS,EAAE,YAAY,EAAE,mDAAmD,EAAE,mBAAmB,EAAE,iBAAiB,CAAC;IAC7I,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,0DAA0D,EAAE,eAAe,EAAE,mBAAmB,CAAC;IACpI,GAAG,CAAC,mBAAmB,EAAE,SAAS,EAAE,aAAa,EAAE,+BAA+B,EAAE,mBAAmB,EAAE,aAAa,CAAC;IAEvH,GAAG,CAAC,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,kCAAkC,EAAE,eAAe,EAAE,eAAe,CAAC;IACjH,GAAG,CAAC,wBAAwB,EAAE,QAAQ,EAAE,kBAAkB,EAAE,yCAAyC,EAAE,aAAa,EAAE,aAAa,CAAC;IACpI,KAAK,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,8BAA8B,EAAE,yBAAyB,EAAE,yBAAyB,CAAC;IACxI,KAAK,CAAC,oBAAoB,EAAE,sBAAsB,EAAE,QAAQ,EAAE,cAAc,EAAE,+BAA+B,EAAE,yBAAyB,EAAE,yBAAyB,CAAC;IAEpK,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,6CAA6C,EAAE,mBAAmB,EAAE,mBAAmB,CAAC;IAC5H,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,mDAAmD,EAAE,mBAAmB,EAAE,mBAAmB,CAAC;IACvI,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,6CAA6C,EAAE,gBAAgB,EAAE,mBAAmB,CAAC;IAE3H;QACE,EAAE,EAAE,QAAQ;QACZ,WAAW,EAAE,UAAU;QACvB,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,8GAA8G;QAC3H,MAAM,EAAE,aAAa;QACrB,QAAQ,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;KAC/B;IAED,KAAK,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,oBAAoB,EAAE,2CAA2C,EAAE,kBAAkB,EAAE,kBAAkB,CAAC;IACnJ,KAAK,CAAC,oBAAoB,EAAE,sBAAsB,EAAE,SAAS,EAAE,cAAc,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,kBAAkB,CAAC;IAC9I,KAAK,CAAC,iBAAiB,EAAE,mBAAmB,EAAE,SAAS,EAAE,iBAAiB,EAAE,0CAA0C,EAAE,kBAAkB,EAAE,4BAA4B,CAAC;IACzK,KAAK,CAAC,4BAA4B,EAAE,8BAA8B,EAAE,SAAS,EAAE,sBAAsB,EAAE,qCAAqC,EAAE,kBAAkB,EAAE,kBAAkB,CAAC;IACrL,KAAK,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,SAAS,EAAE,gBAAgB,EAAE,2CAA2C,EAAE,iBAAiB,EAAE,kBAAkB,CAAC;IAC5J,KAAK,CAAC,2BAA2B,EAAE,6BAA6B,EAAE,SAAS,EAAE,qBAAqB,EAAE,oCAAoC,EAAE,kBAAkB,EAAE,kBAAkB,CAAC;IACjL,KAAK,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,SAAS,EAAE,gBAAgB,EAAE,oCAAoC,EAAE,kBAAkB,EAAE,oBAAoB,CAAC;IACxJ,KAAK,CAAC,cAAc,EAAE,gBAAgB,EAAE,SAAS,EAAE,oBAAoB,EAAE,4CAA4C,EAAE,kBAAkB,EAAE,kBAAkB,CAAC;CAC/J,CAAC;AAEF,MAAM,kBAAkB,GAA0C,IAAI,GAAG,CACvE,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAC/C,CAAC;AAEF,wCAAwC;AACxC,MAAM,UAAU,eAAe;IAC7B,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,iBAAiB;IAC/B,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO,kBAAkB,CAAC,GAAG,CAAC,OAAuB,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAgB;IAC5C,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,wBAAwB,EAAE,oBAAoB,iBAAiB,EAAE;aAC9D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;aACpB,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,kBAAkB,CAAC,KAAiB,EAAE,KAAsB;IAC1E,OAAQ,KAAK,CAAC,MAAqC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACtE,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,iBAAiB,CAAC,KAAiB,EAAE,KAAsB;IACzE,OAAQ,KAAK,CAAC,QAAqD,CAAC,KAAK,CAAC,CAAC;AAC7E,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * "@schemavaults/theme/tokens": the token manifest and the override helpers.
3
+ * Everything here is plain data and pure functions with no Node.js
4
+ * dependencies, so it can be imported from browser bundles and client
5
+ * components — unlike the package root, whose Tailwind config factory reads
6
+ * the filesystem.
7
+ */
8
+ export { THEME_TOKENS, listThemeTokens, listThemeTokenIds, isThemeTokenId, getThemeToken, themeTokenHasScope, themeTokenDefault, } from "./theme_tokens";
9
+ export type { ThemeToken, ModeThemeToken, SharedThemeToken, ThemeTokenID, ModeThemeTokenID, SharedThemeTokenID, ThemeTokenScope, ThemeMode, ThemeTokenFormat, ThemeTokenGroup, } from "./theme_tokens";
10
+ export { THEME_OVERRIDE_VARIABLE_PREFIX, ThemeTokenValueError, themeOverrideVariable, normalizeThemeTokenValue, createThemeOverrideStyle, renderThemeOverrideCss, resolveThemeTokens, themeTokenEnvironmentVariable, themeOverridesFromEnvironment, } from "./theme_overrides";
11
+ export type { ThemeOverrides, ResolvedThemeToken, ResolvedThemeTokenValue, ThemeEnvironmentOptions, ThemeOverrideProblem, ThemeOverridesFromEnvironment, } from "./theme_overrides";
12
+ export { toHslChannels, rgbToHslChannels } from "./hsl_channels";
package/dist/tokens.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * "@schemavaults/theme/tokens": the token manifest and the override helpers.
3
+ * Everything here is plain data and pure functions with no Node.js
4
+ * dependencies, so it can be imported from browser bundles and client
5
+ * components — unlike the package root, whose Tailwind config factory reads
6
+ * the filesystem.
7
+ */
8
+ export { THEME_TOKENS, listThemeTokens, listThemeTokenIds, isThemeTokenId, getThemeToken, themeTokenHasScope, themeTokenDefault, } from "./theme_tokens";
9
+ export { THEME_OVERRIDE_VARIABLE_PREFIX, ThemeTokenValueError, themeOverrideVariable, normalizeThemeTokenValue, createThemeOverrideStyle, renderThemeOverrideCss, resolveThemeTokens, themeTokenEnvironmentVariable, themeOverridesFromEnvironment, } from "./theme_overrides";
10
+ export { toHslChannels, rgbToHslChannels } from "./hsl_channels";
11
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAcxB,OAAO,EACL,8BAA8B,EAC9B,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,kBAAkB,EAClB,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAU3B,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
package/globals.css CHANGED
@@ -2,97 +2,112 @@
2
2
  @tailwind components;
3
3
  @tailwind utilities;
4
4
 
5
+ /*
6
+ * Every design token below is declared as
7
+ * --token: var(--sv-theme-<mode>-<token>, <default>);
8
+ * so an application can re-theme a deployment without replacing this file:
9
+ * set the `--sv-theme-light-*` / `--sv-theme-dark-*` (or, for tokens shared by
10
+ * both modes, `--sv-theme-*`) custom properties on the <html> element — as an
11
+ * inline style attribute, or from a <style> element — and the matching token
12
+ * picks the value up in that mode only. An override variable that is not set
13
+ * leaves the default in place.
14
+ *
15
+ * `createThemeOverrideStyle()` / `renderThemeOverrideCss()` from
16
+ * "@schemavaults/theme/tokens" build those declarations, and
17
+ * `THEME_TOKENS` lists every token, its format and its defaults; a test keeps
18
+ * that manifest and this file in step.
19
+ */
5
20
  @layer base {
6
21
  :root {
7
- --schemavaults-brand-blue: #60a5fa;
8
- --schemavaults-brand-red: #dc2626;
22
+ --schemavaults-brand-blue: var(--sv-theme-light-brand-blue, #60a5fa);
23
+ --schemavaults-brand-red: var(--sv-theme-light-brand-red, #dc2626);
9
24
 
10
- --background: 0 0% 100%;
11
- --foreground: 222.2 84% 4.9%;
25
+ --background: var(--sv-theme-light-background, 0 0% 100%);
26
+ --foreground: var(--sv-theme-light-foreground, 222.2 84% 4.9%);
12
27
 
13
- --card: 0 0% 100%;
14
- --card-foreground: 222.2 84% 4.9%;
28
+ --card: var(--sv-theme-light-card, 0 0% 100%);
29
+ --card-foreground: var(--sv-theme-light-card-foreground, 222.2 84% 4.9%);
15
30
 
16
- --popover: 0 0% 100%;
17
- --popover-foreground: 222.2 84% 4.9%;
31
+ --popover: var(--sv-theme-light-popover, 0 0% 100%);
32
+ --popover-foreground: var(--sv-theme-light-popover-foreground, 222.2 84% 4.9%);
18
33
 
19
- --primary: 222.2 47.4% 11.2%;
20
- --primary-foreground: 210 40% 98%;
34
+ --primary: var(--sv-theme-light-primary, 222.2 47.4% 11.2%);
35
+ --primary-foreground: var(--sv-theme-light-primary-foreground, 210 40% 98%);
21
36
 
22
- --secondary: 210 40% 96.1%;
23
- --secondary-foreground: 222.2 47.4% 11.2%;
37
+ --secondary: var(--sv-theme-light-secondary, 210 40% 96.1%);
38
+ --secondary-foreground: var(--sv-theme-light-secondary-foreground, 222.2 47.4% 11.2%);
24
39
 
25
- --muted: 210 40% 96.1%;
26
- --muted-foreground: 215.4 16.3% 46.9%;
40
+ --muted: var(--sv-theme-light-muted, 210 40% 96.1%);
41
+ --muted-foreground: var(--sv-theme-light-muted-foreground, 215.4 16.3% 46.9%);
27
42
 
28
- --accent: 210 40% 96.1%;
29
- --accent-foreground: 222.2 47.4% 11.2%;
43
+ --accent: var(--sv-theme-light-accent, 210 40% 96.1%);
44
+ --accent-foreground: var(--sv-theme-light-accent-foreground, 222.2 47.4% 11.2%);
30
45
 
31
- --destructive: 0 84.2% 60.2%;
32
- --destructive-foreground: 210 40% 98%;
46
+ --destructive: var(--sv-theme-light-destructive, 0 84.2% 60.2%);
47
+ --destructive-foreground: var(--sv-theme-light-destructive-foreground, 210 40% 98%);
33
48
 
34
- --warning: oklch(82% 0.189 84.429);
35
- --warning-foreground: oklch(41% 0.112 45.904);
49
+ --warning: var(--sv-theme-light-warning, oklch(82% 0.189 84.429));
50
+ --warning-foreground: var(--sv-theme-light-warning-foreground, oklch(41% 0.112 45.904));
36
51
 
37
- --border: 214.3 31.8% 91.4%;
38
- --input: 214.3 31.8% 91.4%;
39
- --ring: 222.2 84% 4.9%;
52
+ --border: var(--sv-theme-light-border, 214.3 31.8% 91.4%);
53
+ --input: var(--sv-theme-light-input, 214.3 31.8% 91.4%);
54
+ --ring: var(--sv-theme-light-ring, 222.2 84% 4.9%);
40
55
 
41
- --radius: 0.5rem;
56
+ --radius: var(--sv-theme-radius, 0.5rem);
42
57
 
43
- --sidebar: oklch(0.985 0 0);
44
- --sidebar-foreground: oklch(0.145 0 0);
45
- --sidebar-primary: oklch(0.205 0 0);
46
- --sidebar-primary-foreground: oklch(0.985 0 0);
47
- --sidebar-accent: oklch(0.97 0 0);
48
- --sidebar-accent-foreground: oklch(0.205 0 0);
49
- --sidebar-border: oklch(0.922 0 0);
50
- --sidebar-ring: oklch(0.708 0 0);
58
+ --sidebar: var(--sv-theme-light-sidebar, oklch(0.985 0 0));
59
+ --sidebar-foreground: var(--sv-theme-light-sidebar-foreground, oklch(0.145 0 0));
60
+ --sidebar-primary: var(--sv-theme-light-sidebar-primary, oklch(0.205 0 0));
61
+ --sidebar-primary-foreground: var(--sv-theme-light-sidebar-primary-foreground, oklch(0.985 0 0));
62
+ --sidebar-accent: var(--sv-theme-light-sidebar-accent, oklch(0.97 0 0));
63
+ --sidebar-accent-foreground: var(--sv-theme-light-sidebar-accent-foreground, oklch(0.205 0 0));
64
+ --sidebar-border: var(--sv-theme-light-sidebar-border, oklch(0.922 0 0));
65
+ --sidebar-ring: var(--sv-theme-light-sidebar-ring, oklch(0.708 0 0));
51
66
  }
52
67
 
53
68
  .dark {
54
- --schemavaults-brand-blue: #60a5fa;
55
- --schemavaults-brand-red: #dc2626;
69
+ --schemavaults-brand-blue: var(--sv-theme-dark-brand-blue, #60a5fa);
70
+ --schemavaults-brand-red: var(--sv-theme-dark-brand-red, #dc2626);
56
71
 
57
- --background: 222.2 84% 4.9%;
58
- --foreground: 210 40% 98%;
72
+ --background: var(--sv-theme-dark-background, 222.2 84% 4.9%);
73
+ --foreground: var(--sv-theme-dark-foreground, 210 40% 98%);
59
74
 
60
- --card: 222.2 84% 4.9%;
61
- --card-foreground: 210 40% 98%;
75
+ --card: var(--sv-theme-dark-card, 222.2 84% 4.9%);
76
+ --card-foreground: var(--sv-theme-dark-card-foreground, 210 40% 98%);
62
77
 
63
- --popover: 222.2 84% 4.9%;
64
- --popover-foreground: 210 40% 98%;
78
+ --popover: var(--sv-theme-dark-popover, 222.2 84% 4.9%);
79
+ --popover-foreground: var(--sv-theme-dark-popover-foreground, 210 40% 98%);
65
80
 
66
- --primary: 210 40% 98%;
67
- --primary-foreground: 222.2 47.4% 11.2%;
81
+ --primary: var(--sv-theme-dark-primary, 210 40% 98%);
82
+ --primary-foreground: var(--sv-theme-dark-primary-foreground, 222.2 47.4% 11.2%);
68
83
 
69
- --secondary: 217.2 32.6% 17.5%;
70
- --secondary-foreground: 210 40% 98%;
84
+ --secondary: var(--sv-theme-dark-secondary, 217.2 32.6% 17.5%);
85
+ --secondary-foreground: var(--sv-theme-dark-secondary-foreground, 210 40% 98%);
71
86
 
72
- --muted: 217.2 32.6% 17.5%;
73
- --muted-foreground: 215 20.2% 65.1%;
87
+ --muted: var(--sv-theme-dark-muted, 217.2 32.6% 17.5%);
88
+ --muted-foreground: var(--sv-theme-dark-muted-foreground, 215 20.2% 65.1%);
74
89
 
75
- --accent: 217.2 32.6% 17.5%;
76
- --accent-foreground: 210 40% 98%;
90
+ --accent: var(--sv-theme-dark-accent, 217.2 32.6% 17.5%);
91
+ --accent-foreground: var(--sv-theme-dark-accent-foreground, 210 40% 98%);
77
92
 
78
- --destructive: 0 62.8% 30.6%;
79
- --destructive-foreground: 210 40% 98%;
93
+ --destructive: var(--sv-theme-dark-destructive, 0 62.8% 30.6%);
94
+ --destructive-foreground: var(--sv-theme-dark-destructive-foreground, 210 40% 98%);
80
95
 
81
- --warning: oklch(82% 0.189 84.429);
82
- --warning-foreground: oklch(41% 0.112 45.904);
96
+ --warning: var(--sv-theme-dark-warning, oklch(82% 0.189 84.429));
97
+ --warning-foreground: var(--sv-theme-dark-warning-foreground, oklch(41% 0.112 45.904));
83
98
 
84
- --border: 217.2 32.6% 17.5%;
85
- --input: 217.2 32.6% 17.5%;
86
- --ring: 212.7 26.8% 83.9%;
99
+ --border: var(--sv-theme-dark-border, 217.2 32.6% 17.5%);
100
+ --input: var(--sv-theme-dark-input, 217.2 32.6% 17.5%);
101
+ --ring: var(--sv-theme-dark-ring, 212.7 26.8% 83.9%);
87
102
 
88
- --sidebar: oklch(0.205 0 0);
89
- --sidebar-foreground: oklch(0.985 0 0);
90
- --sidebar-primary: oklch(0.488 0.243 264.376);
91
- --sidebar-primary-foreground: oklch(0.985 0 0);
92
- --sidebar-accent: oklch(0.269 0 0);
93
- --sidebar-accent-foreground: oklch(0.985 0 0);
94
- --sidebar-border: oklch(1 0 0 / 10%);
95
- --sidebar-ring: oklch(0.439 0 0);
103
+ --sidebar: var(--sv-theme-dark-sidebar, oklch(0.205 0 0));
104
+ --sidebar-foreground: var(--sv-theme-dark-sidebar-foreground, oklch(0.985 0 0));
105
+ --sidebar-primary: var(--sv-theme-dark-sidebar-primary, oklch(0.488 0.243 264.376));
106
+ --sidebar-primary-foreground: var(--sv-theme-dark-sidebar-primary-foreground, oklch(0.985 0 0));
107
+ --sidebar-accent: var(--sv-theme-dark-sidebar-accent, oklch(0.269 0 0));
108
+ --sidebar-accent-foreground: var(--sv-theme-dark-sidebar-accent-foreground, oklch(0.985 0 0));
109
+ --sidebar-border: var(--sv-theme-dark-sidebar-border, oklch(1 0 0 / 10%));
110
+ --sidebar-ring: var(--sv-theme-dark-sidebar-ring, oklch(0.439 0 0));
96
111
  }
97
112
  }
98
113
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@schemavaults/theme",
3
3
  "description": "TailwindCSS theme shared by different SchemaVaults applications",
4
- "version": "0.26.1",
4
+ "version": "0.27.0",
5
5
  "private": false,
6
6
  "license": "UNLICENSED",
7
7
  "repository": {
@@ -57,6 +57,12 @@
57
57
  "node": "./dist/brand_colors.js",
58
58
  "import": "./dist/brand_colors.js"
59
59
  },
60
+ "./tokens": {
61
+ "types": "./dist/tokens.d.ts",
62
+ "require": "./dist/tokens.js",
63
+ "node": "./dist/tokens.js",
64
+ "import": "./dist/tokens.js"
65
+ },
60
66
  ".": {
61
67
  "types": "./dist/index.d.ts",
62
68
  "require": "./dist/index.js",