@oxyhq/bloom 0.6.14 → 0.6.16
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/lib/commonjs/theme/BloomThemeProvider.js +16 -2
- package/lib/commonjs/theme/BloomThemeProvider.js.map +1 -1
- package/lib/commonjs/theme/color-presets.js +4 -1
- package/lib/commonjs/theme/color-presets.js.map +1 -1
- package/lib/commonjs/theme/index.js +19 -0
- package/lib/commonjs/theme/index.js.map +1 -1
- package/lib/commonjs/theme/persistence.js +20 -0
- package/lib/commonjs/theme/persistence.js.map +1 -1
- package/lib/commonjs/theme/preset-vars.js +98 -0
- package/lib/commonjs/theme/preset-vars.js.map +1 -0
- package/lib/module/theme/BloomThemeProvider.js +17 -3
- package/lib/module/theme/BloomThemeProvider.js.map +1 -1
- package/lib/module/theme/color-presets.js +3 -0
- package/lib/module/theme/color-presets.js.map +1 -1
- package/lib/module/theme/index.js +2 -1
- package/lib/module/theme/index.js.map +1 -1
- package/lib/module/theme/persistence.js +19 -0
- package/lib/module/theme/persistence.js.map +1 -1
- package/lib/module/theme/preset-vars.js +93 -0
- package/lib/module/theme/preset-vars.js.map +1 -0
- package/lib/typescript/commonjs/theme/BloomThemeProvider.d.ts +6 -0
- package/lib/typescript/commonjs/theme/BloomThemeProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/color-presets.d.ts +2 -0
- package/lib/typescript/commonjs/theme/color-presets.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/index.d.ts +3 -1
- package/lib/typescript/commonjs/theme/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/persistence.d.ts +2 -0
- package/lib/typescript/commonjs/theme/persistence.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/preset-vars.d.ts +28 -0
- package/lib/typescript/commonjs/theme/preset-vars.d.ts.map +1 -0
- package/lib/typescript/module/theme/BloomThemeProvider.d.ts +6 -0
- package/lib/typescript/module/theme/BloomThemeProvider.d.ts.map +1 -1
- package/lib/typescript/module/theme/color-presets.d.ts +2 -0
- package/lib/typescript/module/theme/color-presets.d.ts.map +1 -1
- package/lib/typescript/module/theme/index.d.ts +3 -1
- package/lib/typescript/module/theme/index.d.ts.map +1 -1
- package/lib/typescript/module/theme/persistence.d.ts +2 -0
- package/lib/typescript/module/theme/persistence.d.ts.map +1 -1
- package/lib/typescript/module/theme/preset-vars.d.ts +28 -0
- package/lib/typescript/module/theme/preset-vars.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/BloomThemeProvider.persistence.test.tsx +104 -0
- package/src/__tests__/preset-vars.test.ts +58 -0
- package/src/theme/BloomThemeProvider.tsx +35 -3
- package/src/theme/color-presets.ts +3 -0
- package/src/theme/index.ts +6 -0
- package/src/theme/persistence.ts +25 -0
- package/src/theme/preset-vars.ts +115 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Platform","APP_COLOR_NAMES","VALID_PRESETS","Set","VALID_MODES","isValidMode","value","has","isValidPreset","parsePersistedTheme","raw","parsed","JSON","parse","obj","mode","undefined","colorPreset","isThenable","then","readPersistedThemeSync","persistKey","storage","kind","getItem","state","readPersistedTheme","writePersistedTheme","payload","setItem","stringify","webLocalStorage","OS","globalThis","ls","localStorage","key"],"sourceRoot":"../../../src","sources":["theme/persistence.ts"],"mappings":";;AAAA,SAASA,QAAQ,QAAQ,cAAc;AACvC,SAASC,eAAe,QAA2B,oBAAiB;AAGpE,MAAMC,aAAa,GAAG,IAAIC,GAAG,CAASF,eAAe,CAAC;AACtD,MAAMG,WAAW,GAAG,IAAID,GAAG,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;;AAE5E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;
|
|
1
|
+
{"version":3,"names":["Platform","APP_COLOR_NAMES","VALID_PRESETS","Set","VALID_MODES","isValidMode","value","has","isValidPreset","parsePersistedTheme","raw","parsed","JSON","parse","obj","mode","undefined","colorPreset","isThenable","then","readPersistedThemeSync","persistKey","storage","kind","getItem","state","readPersistedTheme","writePersistedTheme","payload","setItem","stringify","removePersistedTheme","removeItem","webLocalStorage","OS","globalThis","ls","localStorage","key"],"sourceRoot":"../../../src","sources":["theme/persistence.ts"],"mappings":";;AAAA,SAASA,QAAQ,QAAQ,cAAc;AACvC,SAASC,eAAe,QAA2B,oBAAiB;AAGpE,MAAMC,aAAa,GAAG,IAAIC,GAAG,CAASF,eAAe,CAAC;AACtD,MAAMG,WAAW,GAAG,IAAID,GAAG,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;;AAE5E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAYA,MAAME,WAAW,GAAIC,KAAc,IACjC,OAAOA,KAAK,KAAK,QAAQ,IAAIF,WAAW,CAACG,GAAG,CAACD,KAAK,CAAC;AAErD,MAAME,aAAa,GAAIF,KAAc,IACnC,OAAOA,KAAK,KAAK,QAAQ,IAAIJ,aAAa,CAACK,GAAG,CAACD,KAAK,CAAC;AAEvD,SAASG,mBAAmBA,CAACC,GAAY,EAA8B;EACrE,IAAI,OAAOA,GAAG,KAAK,QAAQ,EAAE,OAAO,IAAI;EAExC,IAAIC,MAAe;EACnB,IAAI;IACFA,MAAM,GAAGC,IAAI,CAACC,KAAK,CAACH,GAAG,CAAC;EAC1B,CAAC,CAAC,MAAM;IACN,OAAO,IAAI;EACb;EAEA,IAAI,CAACC,MAAM,IAAI,OAAOA,MAAM,KAAK,QAAQ,EAAE,OAAO,IAAI;EACtD,MAAMG,GAAG,GAAGH,MAAmD;EAE/D,MAAMI,IAAI,GAAGV,WAAW,CAACS,GAAG,CAACC,IAAI,CAAC,GAAGD,GAAG,CAACC,IAAI,GAAGC,SAAS;EACzD,MAAMC,WAAW,GAAGT,aAAa,CAACM,GAAG,CAACG,WAAW,CAAC,GAAGH,GAAG,CAACG,WAAW,GAAGD,SAAS;EAEhF,IAAI,CAACD,IAAI,IAAI,CAACE,WAAW,EAAE,OAAO,IAAI;EACtC,OAAO;IAAEF,IAAI;IAAEE;EAAY,CAAC;AAC9B;AAOA,MAAMC,UAAU,GAAIZ,KAAc,IAChC,CAAC,CAACA,KAAK,IAAI,OAAQA,KAAK,CAAwBa,IAAI,KAAK,UAAU;;AAErE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,sBAAsBA,CACpCC,UAA8B,EAC9BC,OAAsC,EACtB;EAChB,IAAI,CAACD,UAAU,IAAI,CAACC,OAAO,EAAE,OAAO;IAAEC,IAAI,EAAE;EAAO,CAAC;EAEpD,IAAIb,GAA2C;EAC/C,IAAI;IACFA,GAAG,GAAGY,OAAO,CAACE,OAAO,CAACH,UAAU,CAAC;EACnC,CAAC,CAAC,MAAM;IACN,OAAO;MAAEE,IAAI,EAAE,MAAM;MAAEE,KAAK,EAAE;IAAK,CAAC;EACtC;EAEA,IAAIP,UAAU,CAACR,GAAG,CAAC,EAAE,OAAO;IAAEa,IAAI,EAAE;EAAQ,CAAC;EAC7C,OAAO;IAAEA,IAAI,EAAE,MAAM;IAAEE,KAAK,EAAEhB,mBAAmB,CAACC,GAAG;EAAE,CAAC;AAC1D;AAEA,OAAO,eAAegB,kBAAkBA,CACtCL,UAA8B,EAC9BC,OAAsC,EACD;EACrC,IAAI,CAACD,UAAU,IAAI,CAACC,OAAO,EAAE,OAAO,IAAI;EAExC,IAAI;IACF,MAAMZ,GAAG,GAAG,MAAMY,OAAO,CAACE,OAAO,CAACH,UAAU,CAAC;IAC7C,OAAOZ,mBAAmB,CAACC,GAAG,CAAC;EACjC,CAAC,CAAC,MAAM;IACN,OAAO,IAAI;EACb;AACF;AAEA,OAAO,eAAeiB,mBAAmBA,CACvCN,UAA8B,EAC9BC,OAAsC,EACtCG,KAA0B,EACX;EACf,IAAI,CAACJ,UAAU,IAAI,CAACC,OAAO,EAAE;EAE7B,MAAMM,OAA4B,GAAG,CAAC,CAAC;EACvC,IAAIH,KAAK,CAACV,IAAI,KAAKC,SAAS,EAAEY,OAAO,CAACb,IAAI,GAAGU,KAAK,CAACV,IAAI;EACvD,IAAIU,KAAK,CAACR,WAAW,KAAKD,SAAS,EAAEY,OAAO,CAACX,WAAW,GAAGQ,KAAK,CAACR,WAAW;EAE5E,IAAI;IACF,MAAMK,OAAO,CAACO,OAAO,CAACR,UAAU,EAAET,IAAI,CAACkB,SAAS,CAACF,OAAO,CAAC,CAAC;EAC5D,CAAC,CAAC,MAAM;IACN;EAAA;AAEJ;AAEA,OAAO,eAAeG,oBAAoBA,CACxCV,UAA8B,EAC9BC,OAAsC,EACvB;EACf,IAAI,CAACD,UAAU,IAAI,CAACC,OAAO,EAAE;EAE7B,IAAI;IACF,IAAI,OAAOA,OAAO,CAACU,UAAU,KAAK,UAAU,EAAE;MAC5C,MAAMV,OAAO,CAACU,UAAU,CAACX,UAAU,CAAC;MACpC;IACF;IACA,MAAMC,OAAO,CAACO,OAAO,CAACR,UAAU,EAAE,EAAE,CAAC;EACvC,CAAC,CAAC,MAAM;IACN;EAAA;AAEJ;;AAEA;AACA;AACA;AACA;AACA,OAAO,MAAMY,eAA8C,GAAG,CAAC,MAAM;EACnE,IAAIjC,QAAQ,CAACkC,EAAE,KAAK,KAAK,EAAE,OAAOlB,SAAS;EAC3C,IAAI,OAAOmB,UAAU,KAAK,WAAW,EAAE,OAAOnB,SAAS;EACvD,IAAI,EAAE,cAAc,IAAImB,UAAU,CAAC,EAAE,OAAOnB,SAAS;EAErD,MAAMoB,EAAE,GAAID,UAAU,CAA+BE,YAAY;EAEjE,OAAO;IACLb,OAAO,EAAGc,GAAG,IAAK;MAChB,IAAI;QACF,OAAOF,EAAE,CAACZ,OAAO,CAACc,GAAG,CAAC;MACxB,CAAC,CAAC,MAAM;QACN,OAAO,IAAI;MACb;IACF,CAAC;IACDT,OAAO,EAAEA,CAACS,GAAG,EAAEhC,KAAK,KAAK;MACvB,IAAI;QACF8B,EAAE,CAACP,OAAO,CAACS,GAAG,EAAEhC,KAAK,CAAC;MACxB,CAAC,CAAC,MAAM;QACN;MAAA;IAEJ,CAAC;IACD0B,UAAU,EAAGM,GAAG,IAAK;MACnB,IAAI;QACFF,EAAE,CAACJ,UAAU,CAACM,GAAG,CAAC;MACpB,CAAC,CAAC,MAAM;QACN;MAAA;IAEJ;EACF,CAAC;AACH,CAAC,EAAE,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { Platform } from 'react-native';
|
|
4
|
+
import { APP_COLOR_PRESETS } from "./color-presets.js";
|
|
5
|
+
function extractHue(hslVar) {
|
|
6
|
+
return parseInt(hslVar.split(' ')[0] ?? '0', 10);
|
|
7
|
+
}
|
|
8
|
+
function extractSat(hslVar) {
|
|
9
|
+
return parseInt(hslVar.split(' ')[1] ?? '0', 10);
|
|
10
|
+
}
|
|
11
|
+
const RESOLVED_COLOR_MAP = {
|
|
12
|
+
'--background': '--color-background',
|
|
13
|
+
'--foreground': '--color-foreground',
|
|
14
|
+
'--primary': '--color-primary',
|
|
15
|
+
'--primary-foreground': '--color-primary-foreground',
|
|
16
|
+
'--secondary': '--color-secondary',
|
|
17
|
+
'--secondary-foreground': '--color-secondary-foreground',
|
|
18
|
+
'--muted': '--color-muted',
|
|
19
|
+
'--muted-foreground': '--color-muted-foreground',
|
|
20
|
+
'--accent': '--color-accent',
|
|
21
|
+
'--accent-foreground': '--color-accent-foreground',
|
|
22
|
+
'--destructive': '--color-destructive',
|
|
23
|
+
'--border': '--color-border',
|
|
24
|
+
'--input': '--color-input',
|
|
25
|
+
'--ring': '--color-ring',
|
|
26
|
+
'--popover': '--color-popover',
|
|
27
|
+
'--popover-foreground': '--color-popover-foreground',
|
|
28
|
+
'--surface': '--color-surface',
|
|
29
|
+
'--surface-foreground': '--color-surface-foreground',
|
|
30
|
+
'--card': '--color-card',
|
|
31
|
+
'--card-foreground': '--color-card-foreground'
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Bloom's base preset tokens extended with the surface/card/chart/sidebar
|
|
35
|
+
* tokens that apps layer on top of the core shadcn palette. Synthesized from
|
|
36
|
+
* the preset's primary hue so every preset stays in sync automatically.
|
|
37
|
+
*
|
|
38
|
+
* This is the single source of truth for extended theming vars — consumer apps
|
|
39
|
+
* must not redefine these per-app.
|
|
40
|
+
*/
|
|
41
|
+
export function getPresetVars(colorName, mode, options = {}) {
|
|
42
|
+
const preset = APP_COLOR_PRESETS[colorName];
|
|
43
|
+
const base = mode === 'light' ? preset.light : preset.dark;
|
|
44
|
+
const get = key => base[key] ?? '0 0% 0%';
|
|
45
|
+
const primary = get('--primary');
|
|
46
|
+
const foreground = get('--foreground');
|
|
47
|
+
const hue = extractHue(primary);
|
|
48
|
+
const sat = Math.min(extractSat(primary), 80);
|
|
49
|
+
const isDark = mode === 'dark';
|
|
50
|
+
const extended = {
|
|
51
|
+
...base,
|
|
52
|
+
'--card': isDark ? `${hue} 30% 10%` : '0 0% 100%',
|
|
53
|
+
'--card-foreground': foreground,
|
|
54
|
+
'--chart-1': `${hue} ${sat}% 85%`,
|
|
55
|
+
'--chart-2': `${hue} ${sat}% 75%`,
|
|
56
|
+
'--chart-3': `${hue} ${sat}% 65%`,
|
|
57
|
+
'--chart-4': `${hue} ${sat}% ${isDark ? 55 : 75}%`,
|
|
58
|
+
'--chart-5': `${hue} ${sat}% ${isDark ? 45 : 65}%`,
|
|
59
|
+
'--content-area': isDark ? `${hue} 30% 8%` : get('--surface'),
|
|
60
|
+
'--sidebar-foreground': foreground,
|
|
61
|
+
'--sidebar-primary': primary,
|
|
62
|
+
'--sidebar-primary-foreground': get('--primary-foreground'),
|
|
63
|
+
'--sidebar-accent': isDark ? get('--sidebar') : get('--accent'),
|
|
64
|
+
'--sidebar-accent-foreground': isDark ? foreground : get('--accent-foreground'),
|
|
65
|
+
'--sidebar-border': get('--border'),
|
|
66
|
+
'--sidebar-ring': get('--ring')
|
|
67
|
+
};
|
|
68
|
+
if (!options.includeResolvedColorVars) return extended;
|
|
69
|
+
const resolved = {
|
|
70
|
+
...extended
|
|
71
|
+
};
|
|
72
|
+
for (const [rawKey, colorKey] of Object.entries(RESOLVED_COLOR_MAP)) {
|
|
73
|
+
const value = extended[rawKey];
|
|
74
|
+
if (value) resolved[colorKey] = `hsl(${value})`;
|
|
75
|
+
}
|
|
76
|
+
return resolved;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Apply a preset's extended vars to `document.documentElement`. Web-only no-op
|
|
81
|
+
* on native. `BloomThemeProvider` already writes the base preset vars on web;
|
|
82
|
+
* call this only when an app needs the extended (card/chart/sidebar) tokens on
|
|
83
|
+
* the document root.
|
|
84
|
+
*/
|
|
85
|
+
export function applyPresetVarsToDocument(colorName, mode, options) {
|
|
86
|
+
if (Platform.OS !== 'web' || typeof document === 'undefined') return;
|
|
87
|
+
const vars = getPresetVars(colorName, mode, options);
|
|
88
|
+
const root = document.documentElement.style;
|
|
89
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
90
|
+
root.setProperty(key, value);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=preset-vars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Platform","APP_COLOR_PRESETS","extractHue","hslVar","parseInt","split","extractSat","RESOLVED_COLOR_MAP","getPresetVars","colorName","mode","options","preset","base","light","dark","get","key","primary","foreground","hue","sat","Math","min","isDark","extended","includeResolvedColorVars","resolved","rawKey","colorKey","Object","entries","value","applyPresetVarsToDocument","OS","document","vars","root","documentElement","style","setProperty"],"sourceRoot":"../../../src","sources":["theme/preset-vars.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -9,6 +9,12 @@ export interface BloomThemeContextValue {
|
|
|
9
9
|
colorPreset: AppColorName;
|
|
10
10
|
setMode: (mode: ThemeMode) => void;
|
|
11
11
|
setColorPreset: (preset: AppColorName) => void;
|
|
12
|
+
/**
|
|
13
|
+
* Restore mode and color preset to the provider defaults
|
|
14
|
+
* (`defaultMode` / `defaultColorPreset`) and clear the persisted entry.
|
|
15
|
+
* Use this when signing out or otherwise resetting per-user state.
|
|
16
|
+
*/
|
|
17
|
+
resetTheme: () => void;
|
|
12
18
|
}
|
|
13
19
|
export declare const BloomThemeContext: React.Context<BloomThemeContextValue | null>;
|
|
14
20
|
export interface BloomThemeProviderProps {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BloomThemeProvider.d.ts","sourceRoot":"","sources":["../../../../src/theme/BloomThemeProvider.tsx"],"names":[],"mappings":"AAIA,OAAO,oBAAoB,CAAC;AAE5B,OAAO,KAQN,MAAM,OAAO,CAAC;AAQf,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,
|
|
1
|
+
{"version":3,"file":"BloomThemeProvider.d.ts","sourceRoot":"","sources":["../../../../src/theme/BloomThemeProvider.tsx"],"names":[],"mappings":"AAIA,OAAO,oBAAoB,CAAC;AAE5B,OAAO,KAQN,MAAM,OAAO,CAAC;AAQf,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAKL,KAAK,iBAAiB,EAEvB,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAKhD,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW,EAAE,YAAY,CAAC;IAC1B,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACnC,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/C;;;;OAIG;IACH,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,iBAAiB,8CAAqD,CAAC;AAEpF,MAAM,WAAW,uBAAuB;IACtC,uFAAuF;IACvF,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,mEAAmE;IACnE,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,mEAAmE;IACnE,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,YAAY,CAAC;IAElC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACzC,mBAAmB,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAErD;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iDAAiD;IACjD,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE9B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,wDAAwD;IACxD,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAkJD,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,gBAAgB,EAC7B,WAA0B,EAC1B,kBAAmC,EACnC,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACV,OAAO,EACP,cAAc,EACd,WAAW,EACX,KAAY,EACZ,cAAc,EACd,QAAQ,GACT,EAAE,uBAAuB,2CAkDzB;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,YAAY,CAAC;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,oBAAoB,2CAc9E"}
|
|
@@ -21,6 +21,8 @@ export interface AppColorPreset {
|
|
|
21
21
|
dark: PresetTokens;
|
|
22
22
|
}
|
|
23
23
|
export declare const APP_COLOR_NAMES: readonly AppColorName[];
|
|
24
|
+
/** Premium-exclusive presets, hidden from the standard color picker. */
|
|
25
|
+
export declare const PREMIUM_COLOR_NAMES: readonly AppColorName[];
|
|
24
26
|
export declare const HEX_TO_APP_COLOR: Record<string, AppColorName>;
|
|
25
27
|
export declare function hexToAppColorName(hex: string): AppColorName;
|
|
26
28
|
export declare const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color-presets.d.ts","sourceRoot":"","sources":["../../../../src/theme/color-presets.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,CAAC;AAEvJ;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,YAAY,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,YAAY,EAAsH,CAAC;AAE1K,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAczD,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAE3D;AAED,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,YAAY,EAAE,cAAc,CAkmBlE,CAAC"}
|
|
1
|
+
{"version":3,"file":"color-presets.d.ts","sourceRoot":"","sources":["../../../../src/theme/color-presets.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,CAAC;AAEvJ;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,YAAY,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,YAAY,EAAsH,CAAC;AAE1K,wEAAwE;AACxE,eAAO,MAAM,mBAAmB,EAAE,SAAS,YAAY,EAAwB,CAAC;AAEhF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAczD,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAE3D;AAED,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,YAAY,EAAE,cAAc,CAkmBlE,CAAC"}
|
|
@@ -4,7 +4,9 @@ export { buildTheme, STATUS_COLORS } from './build-theme';
|
|
|
4
4
|
export { useTheme, useThemeColor, useBloomTheme } from './use-theme';
|
|
5
5
|
export type { Theme, ThemeColors, ThemeMode } from './types';
|
|
6
6
|
export type { AppColorName, AppColorPreset, PresetTokens } from './color-presets';
|
|
7
|
-
export { APP_COLOR_NAMES, APP_COLOR_PRESETS, HEX_TO_APP_COLOR, hexToAppColorName, } from './color-presets';
|
|
7
|
+
export { APP_COLOR_NAMES, PREMIUM_COLOR_NAMES, APP_COLOR_PRESETS, HEX_TO_APP_COLOR, hexToAppColorName, } from './color-presets';
|
|
8
|
+
export { getPresetVars, applyPresetVarsToDocument, } from './preset-vars';
|
|
9
|
+
export type { PresetVarsOptions } from './preset-vars';
|
|
8
10
|
export { applyDarkClass } from './apply-dark-class';
|
|
9
11
|
export { setColorSchemeSafe } from './set-color-scheme-safe';
|
|
10
12
|
export { initCssInteropDarkMode } from './init-css-interop';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/theme/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC3E,YAAY,EACV,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7D,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/theme/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC3E,YAAY,EACV,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7D,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,aAAa,EACb,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -15,6 +15,7 @@ import type { ThemeMode } from './types';
|
|
|
15
15
|
export interface BloomThemeStorage {
|
|
16
16
|
getItem(key: string): string | null | Promise<string | null>;
|
|
17
17
|
setItem(key: string, value: string): void | Promise<void>;
|
|
18
|
+
removeItem?(key: string): void | Promise<void>;
|
|
18
19
|
}
|
|
19
20
|
export interface PersistedThemeState {
|
|
20
21
|
mode?: ThemeMode;
|
|
@@ -40,6 +41,7 @@ export type SyncReadResult = {
|
|
|
40
41
|
export declare function readPersistedThemeSync(persistKey: string | undefined, storage: BloomThemeStorage | undefined): SyncReadResult;
|
|
41
42
|
export declare function readPersistedTheme(persistKey: string | undefined, storage: BloomThemeStorage | undefined): Promise<PersistedThemeState | null>;
|
|
42
43
|
export declare function writePersistedTheme(persistKey: string | undefined, storage: BloomThemeStorage | undefined, state: PersistedThemeState): Promise<void>;
|
|
44
|
+
export declare function removePersistedTheme(persistKey: string | undefined, storage: BloomThemeStorage | undefined): Promise<void>;
|
|
43
45
|
/**
|
|
44
46
|
* `localStorage`-backed storage adapter. Only defined on web; on native the
|
|
45
47
|
* export is `undefined` so consumers pass an `AsyncStorage` adapter explicitly.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../../../src/theme/persistence.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAKzC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../../../src/theme/persistence.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAKzC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,UAAU,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,YAAY,CAAC;CAC5B;AA4BD,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAKrB;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,iBAAiB,GAAG,SAAS,GACrC,cAAc,CAYhB;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,iBAAiB,GAAG,SAAS,GACrC,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CASrC;AAED,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,iBAAiB,GAAG,SAAS,GACrC,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,iBAAiB,GAAG,SA8B9C,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type AppColorName, type PresetTokens } from './color-presets';
|
|
2
|
+
export interface PresetVarsOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Also emit Tailwind v4 resolved `--color-*` vars (wrapped in `hsl(...)`)
|
|
5
|
+
* alongside the raw HSL triples. Needed when scoping a subtree where
|
|
6
|
+
* Tailwind's `@theme` block has already precomputed `--color-*` at `:root`,
|
|
7
|
+
* so overriding `--background` alone wouldn't cascade to `bg-background`.
|
|
8
|
+
* Default `false`.
|
|
9
|
+
*/
|
|
10
|
+
includeResolvedColorVars?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Bloom's base preset tokens extended with the surface/card/chart/sidebar
|
|
14
|
+
* tokens that apps layer on top of the core shadcn palette. Synthesized from
|
|
15
|
+
* the preset's primary hue so every preset stays in sync automatically.
|
|
16
|
+
*
|
|
17
|
+
* This is the single source of truth for extended theming vars — consumer apps
|
|
18
|
+
* must not redefine these per-app.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getPresetVars(colorName: AppColorName, mode: 'light' | 'dark', options?: PresetVarsOptions): PresetTokens;
|
|
21
|
+
/**
|
|
22
|
+
* Apply a preset's extended vars to `document.documentElement`. Web-only no-op
|
|
23
|
+
* on native. `BloomThemeProvider` already writes the base preset vars on web;
|
|
24
|
+
* call this only when an app needs the extended (card/chart/sidebar) tokens on
|
|
25
|
+
* the document root.
|
|
26
|
+
*/
|
|
27
|
+
export declare function applyPresetVarsToDocument(colorName: AppColorName, mode: 'light' | 'dark', options?: PresetVarsOptions): void;
|
|
28
|
+
//# sourceMappingURL=preset-vars.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preset-vars.d.ts","sourceRoot":"","sources":["../../../../src/theme/preset-vars.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAiC1F,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,YAAY,EACvB,IAAI,EAAE,OAAO,GAAG,MAAM,EACtB,OAAO,GAAE,iBAAsB,GAC9B,YAAY,CAqCd;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,YAAY,EACvB,IAAI,EAAE,OAAO,GAAG,MAAM,EACtB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,IAAI,CAQN"}
|
|
@@ -9,6 +9,12 @@ export interface BloomThemeContextValue {
|
|
|
9
9
|
colorPreset: AppColorName;
|
|
10
10
|
setMode: (mode: ThemeMode) => void;
|
|
11
11
|
setColorPreset: (preset: AppColorName) => void;
|
|
12
|
+
/**
|
|
13
|
+
* Restore mode and color preset to the provider defaults
|
|
14
|
+
* (`defaultMode` / `defaultColorPreset`) and clear the persisted entry.
|
|
15
|
+
* Use this when signing out or otherwise resetting per-user state.
|
|
16
|
+
*/
|
|
17
|
+
resetTheme: () => void;
|
|
12
18
|
}
|
|
13
19
|
export declare const BloomThemeContext: React.Context<BloomThemeContextValue | null>;
|
|
14
20
|
export interface BloomThemeProviderProps {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BloomThemeProvider.d.ts","sourceRoot":"","sources":["../../../../src/theme/BloomThemeProvider.tsx"],"names":[],"mappings":"AAIA,OAAO,oBAAoB,CAAC;AAE5B,OAAO,KAQN,MAAM,OAAO,CAAC;AAQf,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,
|
|
1
|
+
{"version":3,"file":"BloomThemeProvider.d.ts","sourceRoot":"","sources":["../../../../src/theme/BloomThemeProvider.tsx"],"names":[],"mappings":"AAIA,OAAO,oBAAoB,CAAC;AAE5B,OAAO,KAQN,MAAM,OAAO,CAAC;AAQf,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAKL,KAAK,iBAAiB,EAEvB,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAKhD,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW,EAAE,YAAY,CAAC;IAC1B,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACnC,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/C;;;;OAIG;IACH,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,iBAAiB,8CAAqD,CAAC;AAEpF,MAAM,WAAW,uBAAuB;IACtC,uFAAuF;IACvF,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,mEAAmE;IACnE,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,mEAAmE;IACnE,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,YAAY,CAAC;IAElC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACzC,mBAAmB,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAErD;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iDAAiD;IACjD,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE9B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,wDAAwD;IACxD,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAkJD,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,gBAAgB,EAC7B,WAA0B,EAC1B,kBAAmC,EACnC,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACV,OAAO,EACP,cAAc,EACd,WAAW,EACX,KAAY,EACZ,cAAc,EACd,QAAQ,GACT,EAAE,uBAAuB,2CAkDzB;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,YAAY,CAAC;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,oBAAoB,2CAc9E"}
|
|
@@ -21,6 +21,8 @@ export interface AppColorPreset {
|
|
|
21
21
|
dark: PresetTokens;
|
|
22
22
|
}
|
|
23
23
|
export declare const APP_COLOR_NAMES: readonly AppColorName[];
|
|
24
|
+
/** Premium-exclusive presets, hidden from the standard color picker. */
|
|
25
|
+
export declare const PREMIUM_COLOR_NAMES: readonly AppColorName[];
|
|
24
26
|
export declare const HEX_TO_APP_COLOR: Record<string, AppColorName>;
|
|
25
27
|
export declare function hexToAppColorName(hex: string): AppColorName;
|
|
26
28
|
export declare const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color-presets.d.ts","sourceRoot":"","sources":["../../../../src/theme/color-presets.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,CAAC;AAEvJ;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,YAAY,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,YAAY,EAAsH,CAAC;AAE1K,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAczD,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAE3D;AAED,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,YAAY,EAAE,cAAc,CAkmBlE,CAAC"}
|
|
1
|
+
{"version":3,"file":"color-presets.d.ts","sourceRoot":"","sources":["../../../../src/theme/color-presets.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,CAAC;AAEvJ;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,YAAY,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,YAAY,EAAsH,CAAC;AAE1K,wEAAwE;AACxE,eAAO,MAAM,mBAAmB,EAAE,SAAS,YAAY,EAAwB,CAAC;AAEhF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAczD,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAE3D;AAED,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,YAAY,EAAE,cAAc,CAkmBlE,CAAC"}
|
|
@@ -4,7 +4,9 @@ export { buildTheme, STATUS_COLORS } from './build-theme';
|
|
|
4
4
|
export { useTheme, useThemeColor, useBloomTheme } from './use-theme';
|
|
5
5
|
export type { Theme, ThemeColors, ThemeMode } from './types';
|
|
6
6
|
export type { AppColorName, AppColorPreset, PresetTokens } from './color-presets';
|
|
7
|
-
export { APP_COLOR_NAMES, APP_COLOR_PRESETS, HEX_TO_APP_COLOR, hexToAppColorName, } from './color-presets';
|
|
7
|
+
export { APP_COLOR_NAMES, PREMIUM_COLOR_NAMES, APP_COLOR_PRESETS, HEX_TO_APP_COLOR, hexToAppColorName, } from './color-presets';
|
|
8
|
+
export { getPresetVars, applyPresetVarsToDocument, } from './preset-vars';
|
|
9
|
+
export type { PresetVarsOptions } from './preset-vars';
|
|
8
10
|
export { applyDarkClass } from './apply-dark-class';
|
|
9
11
|
export { setColorSchemeSafe } from './set-color-scheme-safe';
|
|
10
12
|
export { initCssInteropDarkMode } from './init-css-interop';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/theme/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC3E,YAAY,EACV,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7D,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/theme/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC3E,YAAY,EACV,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7D,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,aAAa,EACb,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -15,6 +15,7 @@ import type { ThemeMode } from './types';
|
|
|
15
15
|
export interface BloomThemeStorage {
|
|
16
16
|
getItem(key: string): string | null | Promise<string | null>;
|
|
17
17
|
setItem(key: string, value: string): void | Promise<void>;
|
|
18
|
+
removeItem?(key: string): void | Promise<void>;
|
|
18
19
|
}
|
|
19
20
|
export interface PersistedThemeState {
|
|
20
21
|
mode?: ThemeMode;
|
|
@@ -40,6 +41,7 @@ export type SyncReadResult = {
|
|
|
40
41
|
export declare function readPersistedThemeSync(persistKey: string | undefined, storage: BloomThemeStorage | undefined): SyncReadResult;
|
|
41
42
|
export declare function readPersistedTheme(persistKey: string | undefined, storage: BloomThemeStorage | undefined): Promise<PersistedThemeState | null>;
|
|
42
43
|
export declare function writePersistedTheme(persistKey: string | undefined, storage: BloomThemeStorage | undefined, state: PersistedThemeState): Promise<void>;
|
|
44
|
+
export declare function removePersistedTheme(persistKey: string | undefined, storage: BloomThemeStorage | undefined): Promise<void>;
|
|
43
45
|
/**
|
|
44
46
|
* `localStorage`-backed storage adapter. Only defined on web; on native the
|
|
45
47
|
* export is `undefined` so consumers pass an `AsyncStorage` adapter explicitly.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../../../src/theme/persistence.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAKzC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../../../src/theme/persistence.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAKzC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,UAAU,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,YAAY,CAAC;CAC5B;AA4BD,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAKrB;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,iBAAiB,GAAG,SAAS,GACrC,cAAc,CAYhB;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,iBAAiB,GAAG,SAAS,GACrC,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CASrC;AAED,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,iBAAiB,GAAG,SAAS,GACrC,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,iBAAiB,GAAG,SA8B9C,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type AppColorName, type PresetTokens } from './color-presets';
|
|
2
|
+
export interface PresetVarsOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Also emit Tailwind v4 resolved `--color-*` vars (wrapped in `hsl(...)`)
|
|
5
|
+
* alongside the raw HSL triples. Needed when scoping a subtree where
|
|
6
|
+
* Tailwind's `@theme` block has already precomputed `--color-*` at `:root`,
|
|
7
|
+
* so overriding `--background` alone wouldn't cascade to `bg-background`.
|
|
8
|
+
* Default `false`.
|
|
9
|
+
*/
|
|
10
|
+
includeResolvedColorVars?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Bloom's base preset tokens extended with the surface/card/chart/sidebar
|
|
14
|
+
* tokens that apps layer on top of the core shadcn palette. Synthesized from
|
|
15
|
+
* the preset's primary hue so every preset stays in sync automatically.
|
|
16
|
+
*
|
|
17
|
+
* This is the single source of truth for extended theming vars — consumer apps
|
|
18
|
+
* must not redefine these per-app.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getPresetVars(colorName: AppColorName, mode: 'light' | 'dark', options?: PresetVarsOptions): PresetTokens;
|
|
21
|
+
/**
|
|
22
|
+
* Apply a preset's extended vars to `document.documentElement`. Web-only no-op
|
|
23
|
+
* on native. `BloomThemeProvider` already writes the base preset vars on web;
|
|
24
|
+
* call this only when an app needs the extended (card/chart/sidebar) tokens on
|
|
25
|
+
* the document root.
|
|
26
|
+
*/
|
|
27
|
+
export declare function applyPresetVarsToDocument(colorName: AppColorName, mode: 'light' | 'dark', options?: PresetVarsOptions): void;
|
|
28
|
+
//# sourceMappingURL=preset-vars.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preset-vars.d.ts","sourceRoot":"","sources":["../../../../src/theme/preset-vars.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAiC1F,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,YAAY,EACvB,IAAI,EAAE,OAAO,GAAG,MAAM,EACtB,OAAO,GAAE,iBAAsB,GAC9B,YAAY,CAqCd;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,YAAY,EACvB,IAAI,EAAE,OAAO,GAAG,MAAM,EACtB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,IAAI,CAQN"}
|
package/package.json
CHANGED
|
@@ -29,6 +29,9 @@ function createSyncStorage(initial?: PersistedThemeState): BloomThemeStorage & {
|
|
|
29
29
|
setItem: (key, value) => {
|
|
30
30
|
store[key] = value;
|
|
31
31
|
},
|
|
32
|
+
removeItem: (key) => {
|
|
33
|
+
delete store[key];
|
|
34
|
+
},
|
|
32
35
|
};
|
|
33
36
|
}
|
|
34
37
|
|
|
@@ -215,3 +218,104 @@ describe('BloomThemeProvider — persistence', () => {
|
|
|
215
218
|
expect(getByTestId('preset').props.children).toBe('oxy');
|
|
216
219
|
});
|
|
217
220
|
});
|
|
221
|
+
|
|
222
|
+
describe('BloomThemeProvider — resetTheme', () => {
|
|
223
|
+
function Harness({ onReady }: { onReady: (reset: () => void) => void }) {
|
|
224
|
+
const ctx = useBloomTheme();
|
|
225
|
+
React.useEffect(() => {
|
|
226
|
+
onReady(ctx.resetTheme);
|
|
227
|
+
}, [ctx.resetTheme, onReady]);
|
|
228
|
+
return (
|
|
229
|
+
<>
|
|
230
|
+
<Text testID="mode">{ctx.mode}</Text>
|
|
231
|
+
<Text testID="preset">{ctx.colorPreset}</Text>
|
|
232
|
+
</>
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
it('restores defaults and clears the persisted entry', async () => {
|
|
237
|
+
const storage = createSyncStorage({ mode: 'dark', colorPreset: 'blue' });
|
|
238
|
+
expect(storage.store['bloom-theme']).toBeDefined();
|
|
239
|
+
|
|
240
|
+
let resetFn: (() => void) | undefined;
|
|
241
|
+
|
|
242
|
+
const { getByTestId } = render(
|
|
243
|
+
<BloomThemeProvider
|
|
244
|
+
persistKey="bloom-theme"
|
|
245
|
+
storage={storage}
|
|
246
|
+
defaultMode="system"
|
|
247
|
+
defaultColorPreset="oxy"
|
|
248
|
+
>
|
|
249
|
+
<Harness onReady={(reset) => { resetFn = reset; }} />
|
|
250
|
+
</BloomThemeProvider>,
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
expect(getByTestId('mode').props.children).toBe('dark');
|
|
254
|
+
expect(getByTestId('preset').props.children).toBe('blue');
|
|
255
|
+
|
|
256
|
+
await act(async () => {
|
|
257
|
+
resetFn?.();
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
expect(getByTestId('mode').props.children).toBe('system');
|
|
261
|
+
expect(getByTestId('preset').props.children).toBe('oxy');
|
|
262
|
+
|
|
263
|
+
await waitFor(() => {
|
|
264
|
+
expect(storage.store['bloom-theme']).toBeUndefined();
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('uses removeItem when the adapter provides it', async () => {
|
|
269
|
+
const removeItem = jest.fn();
|
|
270
|
+
const storage: BloomThemeStorage = {
|
|
271
|
+
getItem: () => JSON.stringify({ mode: 'dark', colorPreset: 'blue' }),
|
|
272
|
+
setItem: () => undefined,
|
|
273
|
+
removeItem,
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
let resetFn: (() => void) | undefined;
|
|
277
|
+
|
|
278
|
+
render(
|
|
279
|
+
<BloomThemeProvider
|
|
280
|
+
persistKey="bloom-theme"
|
|
281
|
+
storage={storage}
|
|
282
|
+
defaultMode="system"
|
|
283
|
+
defaultColorPreset="oxy"
|
|
284
|
+
>
|
|
285
|
+
<Harness onReady={(reset) => { resetFn = reset; }} />
|
|
286
|
+
</BloomThemeProvider>,
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
await act(async () => {
|
|
290
|
+
resetFn?.();
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
await waitFor(() => {
|
|
294
|
+
expect(removeItem).toHaveBeenCalledWith('bloom-theme');
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('does nothing when mode is controlled', async () => {
|
|
299
|
+
const storage = createSyncStorage({ mode: 'dark', colorPreset: 'blue' });
|
|
300
|
+
let resetFn: (() => void) | undefined;
|
|
301
|
+
|
|
302
|
+
const { getByTestId } = render(
|
|
303
|
+
<BloomThemeProvider
|
|
304
|
+
persistKey="bloom-theme"
|
|
305
|
+
storage={storage}
|
|
306
|
+
mode="dark"
|
|
307
|
+
defaultMode="system"
|
|
308
|
+
defaultColorPreset="oxy"
|
|
309
|
+
>
|
|
310
|
+
<Harness onReady={(reset) => { resetFn = reset; }} />
|
|
311
|
+
</BloomThemeProvider>,
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
await act(async () => {
|
|
315
|
+
resetFn?.();
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
expect(getByTestId('mode').props.children).toBe('dark');
|
|
319
|
+
expect(getByTestId('preset').props.children).toBe('oxy');
|
|
320
|
+
});
|
|
321
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { APP_COLOR_NAMES, APP_COLOR_PRESETS } from '../theme/color-presets';
|
|
2
|
+
import { getPresetVars } from '../theme/preset-vars';
|
|
3
|
+
|
|
4
|
+
const EXTENDED_KEYS = [
|
|
5
|
+
'--card',
|
|
6
|
+
'--card-foreground',
|
|
7
|
+
'--chart-1',
|
|
8
|
+
'--chart-2',
|
|
9
|
+
'--chart-3',
|
|
10
|
+
'--chart-4',
|
|
11
|
+
'--chart-5',
|
|
12
|
+
'--content-area',
|
|
13
|
+
'--sidebar-foreground',
|
|
14
|
+
'--sidebar-primary',
|
|
15
|
+
'--sidebar-primary-foreground',
|
|
16
|
+
'--sidebar-accent',
|
|
17
|
+
'--sidebar-accent-foreground',
|
|
18
|
+
'--sidebar-border',
|
|
19
|
+
'--sidebar-ring',
|
|
20
|
+
] as const;
|
|
21
|
+
|
|
22
|
+
describe('getPresetVars', () => {
|
|
23
|
+
it('includes every base preset token plus extended tokens for all presets and modes', () => {
|
|
24
|
+
for (const name of APP_COLOR_NAMES) {
|
|
25
|
+
for (const mode of ['light', 'dark'] as const) {
|
|
26
|
+
const vars = getPresetVars(name, mode);
|
|
27
|
+
const base = mode === 'light' ? APP_COLOR_PRESETS[name].light : APP_COLOR_PRESETS[name].dark;
|
|
28
|
+
|
|
29
|
+
for (const key of Object.keys(base)) {
|
|
30
|
+
expect(vars[key]).toBe(base[key]);
|
|
31
|
+
}
|
|
32
|
+
for (const key of EXTENDED_KEYS) {
|
|
33
|
+
expect(vars[key]).toBeDefined();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('derives chart/sidebar hue from the preset primary', () => {
|
|
40
|
+
const vars = getPresetVars('blue', 'light');
|
|
41
|
+
const primary = APP_COLOR_PRESETS.blue.light['--primary'] ?? '';
|
|
42
|
+
const primaryHue = primary.split(' ')[0] ?? '';
|
|
43
|
+
const chart1 = vars['--chart-1'] ?? '';
|
|
44
|
+
expect(chart1.startsWith(`${primaryHue} `)).toBe(true);
|
|
45
|
+
expect(vars['--sidebar-primary']).toBe(primary);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('does not emit resolved --color-* vars by default', () => {
|
|
49
|
+
const vars = getPresetVars('green', 'dark');
|
|
50
|
+
expect(vars['--color-primary']).toBeUndefined();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('emits resolved --color-* vars wrapped in hsl() when requested', () => {
|
|
54
|
+
const vars = getPresetVars('green', 'dark', { includeResolvedColorVars: true });
|
|
55
|
+
expect(vars['--color-primary']).toBe(`hsl(${APP_COLOR_PRESETS.green.dark['--primary']})`);
|
|
56
|
+
expect(vars['--color-card']).toBe(`hsl(${vars['--card']})`);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -24,6 +24,7 @@ import { type AppColorName } from './color-presets';
|
|
|
24
24
|
import {
|
|
25
25
|
readPersistedTheme,
|
|
26
26
|
readPersistedThemeSync,
|
|
27
|
+
removePersistedTheme,
|
|
27
28
|
writePersistedTheme,
|
|
28
29
|
type BloomThemeStorage,
|
|
29
30
|
type SyncReadResult,
|
|
@@ -41,6 +42,12 @@ export interface BloomThemeContextValue {
|
|
|
41
42
|
colorPreset: AppColorName;
|
|
42
43
|
setMode: (mode: ThemeMode) => void;
|
|
43
44
|
setColorPreset: (preset: AppColorName) => void;
|
|
45
|
+
/**
|
|
46
|
+
* Restore mode and color preset to the provider defaults
|
|
47
|
+
* (`defaultMode` / `defaultColorPreset`) and clear the persisted entry.
|
|
48
|
+
* Use this when signing out or otherwise resetting per-user state.
|
|
49
|
+
*/
|
|
50
|
+
resetTheme: () => void;
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
export const BloomThemeContext = createContext<BloomThemeContextValue | null>(null);
|
|
@@ -103,6 +110,7 @@ interface ThemeStateResult {
|
|
|
103
110
|
colorPreset: AppColorName;
|
|
104
111
|
setMode: (mode: ThemeMode) => void;
|
|
105
112
|
setColorPreset: (preset: AppColorName) => void;
|
|
113
|
+
resetTheme: () => void;
|
|
106
114
|
hydrated: boolean;
|
|
107
115
|
}
|
|
108
116
|
|
|
@@ -204,7 +212,30 @@ function useThemeState({
|
|
|
204
212
|
[setPresetInternal, onColorPresetChange, persistKey, storage],
|
|
205
213
|
);
|
|
206
214
|
|
|
207
|
-
|
|
215
|
+
const resetTheme = useCallback(() => {
|
|
216
|
+
if (controlledMode === undefined) {
|
|
217
|
+
setModeInternal(defaultMode);
|
|
218
|
+
onModeChange?.(defaultMode);
|
|
219
|
+
}
|
|
220
|
+
if (controlledPreset === undefined) {
|
|
221
|
+
setPresetInternal(defaultPreset);
|
|
222
|
+
onColorPresetChange?.(defaultPreset);
|
|
223
|
+
}
|
|
224
|
+
void removePersistedTheme(persistKey, storage);
|
|
225
|
+
}, [
|
|
226
|
+
controlledMode,
|
|
227
|
+
controlledPreset,
|
|
228
|
+
defaultMode,
|
|
229
|
+
defaultPreset,
|
|
230
|
+
setModeInternal,
|
|
231
|
+
setPresetInternal,
|
|
232
|
+
onModeChange,
|
|
233
|
+
onColorPresetChange,
|
|
234
|
+
persistKey,
|
|
235
|
+
storage,
|
|
236
|
+
]);
|
|
237
|
+
|
|
238
|
+
return { mode, colorPreset, setMode, setColorPreset, resetTheme, hydrated };
|
|
208
239
|
}
|
|
209
240
|
|
|
210
241
|
export function BloomThemeProvider({
|
|
@@ -224,7 +255,7 @@ export function BloomThemeProvider({
|
|
|
224
255
|
}: BloomThemeProviderProps) {
|
|
225
256
|
const rnScheme = useRNColorScheme();
|
|
226
257
|
|
|
227
|
-
const { mode, colorPreset, setMode, setColorPreset, hydrated } = useThemeState({
|
|
258
|
+
const { mode, colorPreset, setMode, setColorPreset, resetTheme, hydrated } = useThemeState({
|
|
228
259
|
controlledMode,
|
|
229
260
|
controlledPreset,
|
|
230
261
|
defaultMode,
|
|
@@ -256,8 +287,9 @@ export function BloomThemeProvider({
|
|
|
256
287
|
colorPreset,
|
|
257
288
|
setMode,
|
|
258
289
|
setColorPreset,
|
|
290
|
+
resetTheme,
|
|
259
291
|
}),
|
|
260
|
-
[colorPreset, resolved, isAdaptive, mode, setMode, setColorPreset],
|
|
292
|
+
[colorPreset, resolved, isAdaptive, mode, setMode, setColorPreset, resetTheme],
|
|
261
293
|
);
|
|
262
294
|
|
|
263
295
|
const shouldAwait = awaitHydration ?? Boolean(persistKey && storage);
|