@oxyhq/bloom 0.7.2 → 0.7.4

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.
@@ -17,6 +17,29 @@ export interface BloomThemeContextValue {
17
17
  */
18
18
  resetTheme: () => void;
19
19
  }
20
+ declare global {
21
+ var __oxyhq_bloom_theme_context__: React.Context<BloomThemeContextValue | null> | undefined;
22
+ }
23
+ /**
24
+ * `BloomThemeContext` is a `globalThis`-guarded singleton so that every physical
25
+ * copy of this module returns the SAME React context object.
26
+ *
27
+ * Why this is required: `package.json`'s `exports["./theme"]` ships a
28
+ * `react-native` → `./src/...` condition alongside the `import` → `./lib/module/...`
29
+ * and `require` → `./lib/commonjs/...` forks, so up to three physical copies of the
30
+ * theme module can coexist in a single bundle. A bundler can resolve them through
31
+ * DIFFERENT conditions across import paths — e.g. an app importing `@oxyhq/bloom/theme`
32
+ * lands on the `src` copy while `@oxyhq/bloom/toast`'s `Toast.tsx` imports
33
+ * `../theme/use-theme` relatively and lands on a different physical copy. With a plain
34
+ * module-level `createContext(...)`, each copy creates its OWN context object: the
35
+ * mounted `<BloomThemeProvider>` writes into context A while `useTheme`/`useBloomTheme`/
36
+ * `Toast`/`Dialog` read context B, so `useContext` returns `null` and they throw
37
+ * "must be used within a <BloomThemeProvider>" even when correctly wrapped. This is the
38
+ * same src-vs-lib dual-instance class react-native-css guards its `StyleCollection`/
39
+ * root-variable families against. Anchoring the context on `globalThis` (keyed by the
40
+ * `__oxyhq_bloom_theme_context__` property) collapses all copies onto one object. The
41
+ * `??=` runs `createContext` at most once per process.
42
+ */
20
43
  export declare const BloomThemeContext: React.Context<BloomThemeContextValue | null>;
21
44
  export interface BloomThemeProviderProps {
22
45
  /** Controlled mode. Omit to use Bloom's internal state (with optional persistence). */
@@ -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;AACf,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAOtB,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGpD,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;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAE1C,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,kBAAkB,EAClB,QAAQ,GACT,EAAE,uBAAuB,2CAwFzB"}
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;AACf,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAOtB,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGpD,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,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,6BAA6B,EAC7B,KAAK,CAAC,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,GAC5C,SAAS,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAEpB,CAAC;AAExD,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;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAE1C,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,kBAAkB,EAClB,QAAQ,GACT,EAAE,uBAAuB,2CAwFzB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxyhq/bloom",
3
- "version": "0.7.2",
3
+ "version": "0.7.4",
4
4
  "description": "Bloom UI — Oxy ecosystem component library for React Native + Expo + Web",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -81,7 +81,32 @@ function createPortalGroup() {
81
81
  return { Provider, Outlet, Portal };
82
82
  }
83
83
 
84
- const DefaultPortal = createPortalGroup();
84
+ type PortalGroup = ReturnType<typeof createPortalGroup>;
85
+
86
+ declare global {
87
+ // eslint-disable-next-line no-var
88
+ var __oxyhq_bloom_portal_group__: PortalGroup | undefined;
89
+ }
90
+
91
+ /**
92
+ * `DefaultPortal` is a `globalThis`-guarded singleton so that every physical copy of
93
+ * this module shares ONE portal group (one `Context`, one `Provider`/`Outlet`/`Portal`
94
+ * triple).
95
+ *
96
+ * Why this is required: like the theme module, `exports["./portal"]` ships a
97
+ * `react-native` → `./src/...` condition alongside the `lib/module` / `lib/commonjs`
98
+ * forks, and the `Portal` component is consumed cross-subpath from `./tooltip`,
99
+ * `./prompt-input`, `./dialog`, `./select`, `./menu`, `./context-menu`, and `./popover`
100
+ * while the `Provider`/`Outlet` are mounted once at the app root via `@oxyhq/bloom/portal`.
101
+ * A bundler can resolve those subpaths through different export conditions, so without a
102
+ * guard each physical copy runs its own `createPortalGroup()` and a `<Portal>` from copy
103
+ * A would register against the `Provider`'s map in copy B — its content would never reach
104
+ * the `Outlet`. Anchoring the group on `globalThis` (keyed by `__oxyhq_bloom_portal_group__`)
105
+ * collapses all copies onto one group. Same src-vs-lib dual-instance class as
106
+ * `BloomThemeContext`.
107
+ */
108
+ const DefaultPortal: PortalGroup = (globalThis.__oxyhq_bloom_portal_group__ ??=
109
+ createPortalGroup());
85
110
 
86
111
  export const Provider = DefaultPortal.Provider;
87
112
  export const Outlet = memo(DefaultPortal.Outlet);
@@ -58,7 +58,36 @@ export interface BloomThemeContextValue {
58
58
  resetTheme: () => void;
59
59
  }
60
60
 
61
- export const BloomThemeContext = createContext<BloomThemeContextValue | null>(null);
61
+ declare global {
62
+ // eslint-disable-next-line no-var
63
+ var __oxyhq_bloom_theme_context__:
64
+ | React.Context<BloomThemeContextValue | null>
65
+ | undefined;
66
+ }
67
+
68
+ /**
69
+ * `BloomThemeContext` is a `globalThis`-guarded singleton so that every physical
70
+ * copy of this module returns the SAME React context object.
71
+ *
72
+ * Why this is required: `package.json`'s `exports["./theme"]` ships a
73
+ * `react-native` → `./src/...` condition alongside the `import` → `./lib/module/...`
74
+ * and `require` → `./lib/commonjs/...` forks, so up to three physical copies of the
75
+ * theme module can coexist in a single bundle. A bundler can resolve them through
76
+ * DIFFERENT conditions across import paths — e.g. an app importing `@oxyhq/bloom/theme`
77
+ * lands on the `src` copy while `@oxyhq/bloom/toast`'s `Toast.tsx` imports
78
+ * `../theme/use-theme` relatively and lands on a different physical copy. With a plain
79
+ * module-level `createContext(...)`, each copy creates its OWN context object: the
80
+ * mounted `<BloomThemeProvider>` writes into context A while `useTheme`/`useBloomTheme`/
81
+ * `Toast`/`Dialog` read context B, so `useContext` returns `null` and they throw
82
+ * "must be used within a <BloomThemeProvider>" even when correctly wrapped. This is the
83
+ * same src-vs-lib dual-instance class react-native-css guards its `StyleCollection`/
84
+ * root-variable families against. Anchoring the context on `globalThis` (keyed by the
85
+ * `__oxyhq_bloom_theme_context__` property) collapses all copies onto one object. The
86
+ * `??=` runs `createContext` at most once per process.
87
+ */
88
+ export const BloomThemeContext: React.Context<BloomThemeContextValue | null> =
89
+ (globalThis.__oxyhq_bloom_theme_context__ ??=
90
+ createContext<BloomThemeContextValue | null>(null));
62
91
 
63
92
  export interface BloomThemeProviderProps {
64
93
  /** Controlled mode. Omit to use Bloom's internal state (with optional persistence). */
@@ -53,25 +53,25 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
53
53
  name: 'teal',
54
54
  hex: '#005c67',
55
55
  light: {
56
- '--background': '185 8% 99%',
56
+ '--background': '185 55% 96%',
57
57
  '--foreground': '0 0% 12%',
58
- '--surface': '185 14% 97%',
58
+ '--surface': '185 58% 94%',
59
59
  '--surface-foreground': '0 0% 12%',
60
- '--popover': '185 12% 99%',
60
+ '--popover': '185 55% 97%',
61
61
  '--popover-foreground': '0 0% 12%',
62
62
  '--primary': '185 100% 20%',
63
63
  '--primary-foreground': '0 0% 100%',
64
- '--secondary': '185 12% 95%',
64
+ '--secondary': '185 55% 92%',
65
65
  '--secondary-foreground': '0 0% 12%',
66
- '--muted': '185 12% 95%',
66
+ '--muted': '185 55% 92%',
67
67
  '--muted-foreground': '185 5% 42%',
68
- '--accent': '185 12% 95%',
68
+ '--accent': '185 55% 92%',
69
69
  '--accent-foreground': '0 0% 12%',
70
70
  '--destructive': '0 84% 60%',
71
- '--border': '185 14% 88%',
72
- '--input': '185 14% 88%',
71
+ '--border': '185 40% 87%',
72
+ '--input': '185 40% 87%',
73
73
  '--ring': '185 100% 20%',
74
- '--sidebar': '185 14% 97%',
74
+ '--sidebar': '185 58% 94%',
75
75
  },
76
76
  dark: {
77
77
  '--background': '185 50% 5%',
@@ -100,25 +100,25 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
100
100
  name: 'blue',
101
101
  hex: '#1D9BF0',
102
102
  light: {
103
- '--background': '205 8% 99%',
103
+ '--background': '205 55% 96%',
104
104
  '--foreground': '0 0% 12%',
105
- '--surface': '205 14% 97%',
105
+ '--surface': '205 58% 94%',
106
106
  '--surface-foreground': '0 0% 12%',
107
- '--popover': '205 12% 99%',
107
+ '--popover': '205 55% 97%',
108
108
  '--popover-foreground': '0 0% 12%',
109
109
  '--primary': '205 87% 53%',
110
110
  '--primary-foreground': '0 0% 100%',
111
- '--secondary': '205 12% 95%',
111
+ '--secondary': '205 55% 92%',
112
112
  '--secondary-foreground': '0 0% 12%',
113
- '--muted': '205 12% 95%',
113
+ '--muted': '205 55% 92%',
114
114
  '--muted-foreground': '205 5% 42%',
115
- '--accent': '205 12% 95%',
115
+ '--accent': '205 55% 92%',
116
116
  '--accent-foreground': '0 0% 12%',
117
117
  '--destructive': '0 84% 60%',
118
- '--border': '205 14% 88%',
119
- '--input': '205 14% 88%',
118
+ '--border': '205 40% 87%',
119
+ '--input': '205 40% 87%',
120
120
  '--ring': '205 87% 53%',
121
- '--sidebar': '205 14% 97%',
121
+ '--sidebar': '205 58% 94%',
122
122
  },
123
123
  dark: {
124
124
  '--background': '205 50% 5%',
@@ -147,25 +147,25 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
147
147
  name: 'green',
148
148
  hex: '#10B981',
149
149
  light: {
150
- '--background': '160 8% 99%',
150
+ '--background': '160 55% 96%',
151
151
  '--foreground': '0 0% 12%',
152
- '--surface': '160 14% 97%',
152
+ '--surface': '160 58% 94%',
153
153
  '--surface-foreground': '0 0% 12%',
154
- '--popover': '160 12% 99%',
154
+ '--popover': '160 55% 97%',
155
155
  '--popover-foreground': '0 0% 12%',
156
156
  '--primary': '160 84% 39%',
157
157
  '--primary-foreground': '0 0% 100%',
158
- '--secondary': '160 12% 95%',
158
+ '--secondary': '160 55% 92%',
159
159
  '--secondary-foreground': '0 0% 12%',
160
- '--muted': '160 12% 95%',
160
+ '--muted': '160 55% 92%',
161
161
  '--muted-foreground': '160 5% 42%',
162
- '--accent': '160 12% 95%',
162
+ '--accent': '160 55% 92%',
163
163
  '--accent-foreground': '0 0% 12%',
164
164
  '--destructive': '0 84% 60%',
165
- '--border': '160 14% 88%',
166
- '--input': '160 14% 88%',
165
+ '--border': '160 40% 87%',
166
+ '--input': '160 40% 87%',
167
167
  '--ring': '160 84% 39%',
168
- '--sidebar': '160 14% 97%',
168
+ '--sidebar': '160 58% 94%',
169
169
  },
170
170
  dark: {
171
171
  '--background': '160 50% 5%',
@@ -194,25 +194,25 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
194
194
  name: 'amber',
195
195
  hex: '#F59E0B',
196
196
  light: {
197
- '--background': '38 8% 99%',
197
+ '--background': '38 55% 96%',
198
198
  '--foreground': '0 0% 12%',
199
- '--surface': '38 14% 97%',
199
+ '--surface': '38 58% 94%',
200
200
  '--surface-foreground': '0 0% 12%',
201
- '--popover': '38 12% 99%',
201
+ '--popover': '38 55% 97%',
202
202
  '--popover-foreground': '0 0% 12%',
203
203
  '--primary': '38 92% 50%',
204
204
  '--primary-foreground': '0 0% 0%',
205
- '--secondary': '38 12% 95%',
205
+ '--secondary': '38 55% 92%',
206
206
  '--secondary-foreground': '0 0% 12%',
207
- '--muted': '38 12% 95%',
207
+ '--muted': '38 55% 92%',
208
208
  '--muted-foreground': '38 5% 42%',
209
- '--accent': '38 12% 95%',
209
+ '--accent': '38 55% 92%',
210
210
  '--accent-foreground': '0 0% 12%',
211
211
  '--destructive': '0 84% 60%',
212
- '--border': '38 14% 88%',
213
- '--input': '38 14% 88%',
212
+ '--border': '38 40% 87%',
213
+ '--input': '38 40% 87%',
214
214
  '--ring': '38 92% 50%',
215
- '--sidebar': '38 14% 97%',
215
+ '--sidebar': '38 58% 94%',
216
216
  },
217
217
  dark: {
218
218
  '--background': '38 50% 5%',
@@ -241,25 +241,25 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
241
241
  name: 'yellow',
242
242
  hex: '#ffc300',
243
243
  light: {
244
- '--background': '46 8% 99%',
244
+ '--background': '46 55% 96%',
245
245
  '--foreground': '0 0% 12%',
246
- '--surface': '46 14% 97%',
246
+ '--surface': '46 58% 94%',
247
247
  '--surface-foreground': '0 0% 12%',
248
- '--popover': '46 12% 99%',
248
+ '--popover': '46 55% 97%',
249
249
  '--popover-foreground': '0 0% 12%',
250
250
  '--primary': '46 100% 50%',
251
251
  '--primary-foreground': '0 0% 0%',
252
- '--secondary': '46 12% 95%',
252
+ '--secondary': '46 55% 92%',
253
253
  '--secondary-foreground': '0 0% 12%',
254
- '--muted': '46 12% 95%',
254
+ '--muted': '46 55% 92%',
255
255
  '--muted-foreground': '46 5% 42%',
256
- '--accent': '46 12% 95%',
256
+ '--accent': '46 55% 92%',
257
257
  '--accent-foreground': '0 0% 12%',
258
258
  '--destructive': '0 84% 60%',
259
- '--border': '46 14% 88%',
260
- '--input': '46 14% 88%',
259
+ '--border': '46 40% 87%',
260
+ '--input': '46 40% 87%',
261
261
  '--ring': '46 100% 50%',
262
- '--sidebar': '46 14% 97%',
262
+ '--sidebar': '46 58% 94%',
263
263
  },
264
264
  dark: {
265
265
  '--background': '46 50% 5%',
@@ -288,25 +288,25 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
288
288
  name: 'red',
289
289
  hex: '#EF4444',
290
290
  light: {
291
- '--background': '0 8% 99%',
291
+ '--background': '0 55% 96%',
292
292
  '--foreground': '0 0% 12%',
293
- '--surface': '0 14% 97%',
293
+ '--surface': '0 58% 94%',
294
294
  '--surface-foreground': '0 0% 12%',
295
- '--popover': '0 12% 99%',
295
+ '--popover': '0 55% 97%',
296
296
  '--popover-foreground': '0 0% 12%',
297
297
  '--primary': '0 84% 60%',
298
298
  '--primary-foreground': '0 0% 100%',
299
- '--secondary': '0 12% 95%',
299
+ '--secondary': '0 55% 92%',
300
300
  '--secondary-foreground': '0 0% 12%',
301
- '--muted': '0 12% 95%',
301
+ '--muted': '0 55% 92%',
302
302
  '--muted-foreground': '0 5% 42%',
303
- '--accent': '0 12% 95%',
303
+ '--accent': '0 55% 92%',
304
304
  '--accent-foreground': '0 0% 12%',
305
305
  '--destructive': '0 84% 60%',
306
- '--border': '0 14% 88%',
307
- '--input': '0 14% 88%',
306
+ '--border': '0 40% 87%',
307
+ '--input': '0 40% 87%',
308
308
  '--ring': '0 84% 60%',
309
- '--sidebar': '0 14% 97%',
309
+ '--sidebar': '0 58% 94%',
310
310
  },
311
311
  dark: {
312
312
  '--background': '0 50% 5%',
@@ -335,25 +335,25 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
335
335
  name: 'purple',
336
336
  hex: '#8B5CF6',
337
337
  light: {
338
- '--background': '258 8% 99%',
338
+ '--background': '258 55% 96%',
339
339
  '--foreground': '0 0% 12%',
340
- '--surface': '258 14% 97%',
340
+ '--surface': '258 58% 94%',
341
341
  '--surface-foreground': '0 0% 12%',
342
- '--popover': '258 12% 99%',
342
+ '--popover': '258 55% 97%',
343
343
  '--popover-foreground': '0 0% 12%',
344
344
  '--primary': '258 90% 66%',
345
345
  '--primary-foreground': '0 0% 100%',
346
- '--secondary': '258 12% 95%',
346
+ '--secondary': '258 55% 92%',
347
347
  '--secondary-foreground': '0 0% 12%',
348
- '--muted': '258 12% 95%',
348
+ '--muted': '258 55% 92%',
349
349
  '--muted-foreground': '258 5% 42%',
350
- '--accent': '258 12% 95%',
350
+ '--accent': '258 55% 92%',
351
351
  '--accent-foreground': '0 0% 12%',
352
352
  '--destructive': '0 84% 60%',
353
- '--border': '258 14% 88%',
354
- '--input': '258 14% 88%',
353
+ '--border': '258 40% 87%',
354
+ '--input': '258 40% 87%',
355
355
  '--ring': '258 90% 66%',
356
- '--sidebar': '258 14% 97%',
356
+ '--sidebar': '258 58% 94%',
357
357
  },
358
358
  dark: {
359
359
  '--background': '258 50% 5%',
@@ -382,25 +382,25 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
382
382
  name: 'pink',
383
383
  hex: '#EC4899',
384
384
  light: {
385
- '--background': '330 8% 99%',
385
+ '--background': '330 55% 96%',
386
386
  '--foreground': '0 0% 12%',
387
- '--surface': '330 14% 97%',
387
+ '--surface': '330 58% 94%',
388
388
  '--surface-foreground': '0 0% 12%',
389
- '--popover': '330 12% 99%',
389
+ '--popover': '330 55% 97%',
390
390
  '--popover-foreground': '0 0% 12%',
391
391
  '--primary': '330 81% 60%',
392
392
  '--primary-foreground': '0 0% 100%',
393
- '--secondary': '330 12% 95%',
393
+ '--secondary': '330 55% 92%',
394
394
  '--secondary-foreground': '0 0% 12%',
395
- '--muted': '330 12% 95%',
395
+ '--muted': '330 55% 92%',
396
396
  '--muted-foreground': '330 5% 42%',
397
- '--accent': '330 12% 95%',
397
+ '--accent': '330 55% 92%',
398
398
  '--accent-foreground': '0 0% 12%',
399
399
  '--destructive': '0 84% 60%',
400
- '--border': '330 14% 88%',
401
- '--input': '330 14% 88%',
400
+ '--border': '330 40% 87%',
401
+ '--input': '330 40% 87%',
402
402
  '--ring': '330 81% 60%',
403
- '--sidebar': '330 14% 97%',
403
+ '--sidebar': '330 58% 94%',
404
404
  },
405
405
  dark: {
406
406
  '--background': '330 50% 5%',
@@ -429,25 +429,25 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
429
429
  name: 'sky',
430
430
  hex: '#0EA5E9',
431
431
  light: {
432
- '--background': '199 8% 99%',
432
+ '--background': '199 55% 96%',
433
433
  '--foreground': '0 0% 12%',
434
- '--surface': '199 14% 97%',
434
+ '--surface': '199 58% 94%',
435
435
  '--surface-foreground': '0 0% 12%',
436
- '--popover': '199 12% 99%',
436
+ '--popover': '199 55% 97%',
437
437
  '--popover-foreground': '0 0% 12%',
438
438
  '--primary': '199 89% 48%',
439
439
  '--primary-foreground': '0 0% 100%',
440
- '--secondary': '199 12% 95%',
440
+ '--secondary': '199 55% 92%',
441
441
  '--secondary-foreground': '0 0% 12%',
442
- '--muted': '199 12% 95%',
442
+ '--muted': '199 55% 92%',
443
443
  '--muted-foreground': '199 5% 42%',
444
- '--accent': '199 12% 95%',
444
+ '--accent': '199 55% 92%',
445
445
  '--accent-foreground': '0 0% 12%',
446
446
  '--destructive': '0 84% 60%',
447
- '--border': '199 14% 88%',
448
- '--input': '199 14% 88%',
447
+ '--border': '199 40% 87%',
448
+ '--input': '199 40% 87%',
449
449
  '--ring': '199 89% 48%',
450
- '--sidebar': '199 14% 97%',
450
+ '--sidebar': '199 58% 94%',
451
451
  },
452
452
  dark: {
453
453
  '--background': '199 50% 5%',
@@ -476,25 +476,25 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
476
476
  name: 'orange',
477
477
  hex: '#F97316',
478
478
  light: {
479
- '--background': '25 8% 99%',
479
+ '--background': '25 55% 96%',
480
480
  '--foreground': '0 0% 12%',
481
- '--surface': '25 14% 97%',
481
+ '--surface': '25 58% 94%',
482
482
  '--surface-foreground': '0 0% 12%',
483
- '--popover': '25 12% 99%',
483
+ '--popover': '25 55% 97%',
484
484
  '--popover-foreground': '0 0% 12%',
485
485
  '--primary': '25 95% 53%',
486
486
  '--primary-foreground': '0 0% 100%',
487
- '--secondary': '25 12% 95%',
487
+ '--secondary': '25 55% 92%',
488
488
  '--secondary-foreground': '0 0% 12%',
489
- '--muted': '25 12% 95%',
489
+ '--muted': '25 55% 92%',
490
490
  '--muted-foreground': '25 5% 42%',
491
- '--accent': '25 12% 95%',
491
+ '--accent': '25 55% 92%',
492
492
  '--accent-foreground': '0 0% 12%',
493
493
  '--destructive': '0 84% 60%',
494
- '--border': '25 14% 88%',
495
- '--input': '25 14% 88%',
494
+ '--border': '25 40% 87%',
495
+ '--input': '25 40% 87%',
496
496
  '--ring': '25 95% 53%',
497
- '--sidebar': '25 14% 97%',
497
+ '--sidebar': '25 58% 94%',
498
498
  },
499
499
  dark: {
500
500
  '--background': '25 50% 5%',
@@ -523,25 +523,25 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
523
523
  name: 'mint',
524
524
  hex: '#14B8A6',
525
525
  light: {
526
- '--background': '173 8% 99%',
526
+ '--background': '173 55% 96%',
527
527
  '--foreground': '0 0% 12%',
528
- '--surface': '173 14% 97%',
528
+ '--surface': '173 58% 94%',
529
529
  '--surface-foreground': '0 0% 12%',
530
- '--popover': '173 12% 99%',
530
+ '--popover': '173 55% 97%',
531
531
  '--popover-foreground': '0 0% 12%',
532
532
  '--primary': '173 80% 40%',
533
533
  '--primary-foreground': '0 0% 100%',
534
- '--secondary': '173 12% 95%',
534
+ '--secondary': '173 55% 92%',
535
535
  '--secondary-foreground': '0 0% 12%',
536
- '--muted': '173 12% 95%',
536
+ '--muted': '173 55% 92%',
537
537
  '--muted-foreground': '173 5% 42%',
538
- '--accent': '173 12% 95%',
538
+ '--accent': '173 55% 92%',
539
539
  '--accent-foreground': '0 0% 12%',
540
540
  '--destructive': '0 84% 60%',
541
- '--border': '173 14% 88%',
542
- '--input': '173 14% 88%',
541
+ '--border': '173 40% 87%',
542
+ '--input': '173 40% 87%',
543
543
  '--ring': '173 80% 40%',
544
- '--sidebar': '173 14% 97%',
544
+ '--sidebar': '173 58% 94%',
545
545
  },
546
546
  dark: {
547
547
  '--background': '173 50% 5%',
@@ -570,25 +570,25 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
570
570
  name: 'oxy',
571
571
  hex: '#c46ede',
572
572
  light: {
573
- '--background': '277 8% 99%',
573
+ '--background': '277 55% 96%',
574
574
  '--foreground': '0 0% 12%',
575
- '--surface': '277 14% 97%',
575
+ '--surface': '277 58% 94%',
576
576
  '--surface-foreground': '0 0% 12%',
577
- '--popover': '277 12% 99%',
577
+ '--popover': '277 55% 97%',
578
578
  '--popover-foreground': '0 0% 12%',
579
579
  '--primary': '277 66% 56%',
580
580
  '--primary-foreground': '0 0% 100%',
581
- '--secondary': '277 12% 95%',
581
+ '--secondary': '277 55% 92%',
582
582
  '--secondary-foreground': '0 0% 12%',
583
- '--muted': '277 12% 95%',
583
+ '--muted': '277 55% 92%',
584
584
  '--muted-foreground': '277 5% 42%',
585
- '--accent': '277 12% 95%',
585
+ '--accent': '277 55% 92%',
586
586
  '--accent-foreground': '0 0% 12%',
587
587
  '--destructive': '0 84% 60%',
588
- '--border': '277 14% 88%',
589
- '--input': '277 14% 88%',
588
+ '--border': '277 40% 87%',
589
+ '--input': '277 40% 87%',
590
590
  '--ring': '277 66% 56%',
591
- '--sidebar': '277 14% 97%',
591
+ '--sidebar': '277 58% 94%',
592
592
  },
593
593
  dark: {
594
594
  '--background': '277 50% 5%',
@@ -616,25 +616,25 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
616
616
  name: 'faircoin',
617
617
  hex: '#9ffb50',
618
618
  light: {
619
- '--background': '92 8% 99%',
619
+ '--background': '92 55% 96%',
620
620
  '--foreground': '0 0% 12%',
621
- '--surface': '92 16% 95%',
621
+ '--surface': '92 58% 94%',
622
622
  '--surface-foreground': '0 0% 12%',
623
- '--popover': '92 12% 99%',
623
+ '--popover': '92 55% 97%',
624
624
  '--popover-foreground': '0 0% 12%',
625
625
  '--primary': '92 90% 25%',
626
626
  '--primary-foreground': '0 0% 100%',
627
- '--secondary': '92 14% 92%',
627
+ '--secondary': '92 55% 92%',
628
628
  '--secondary-foreground': '0 0% 12%',
629
- '--muted': '92 12% 93%',
629
+ '--muted': '92 55% 92%',
630
630
  '--muted-foreground': '92 5% 40%',
631
- '--accent': '92 14% 92%',
631
+ '--accent': '92 55% 92%',
632
632
  '--accent-foreground': '0 0% 12%',
633
633
  '--destructive': '0 84% 60%',
634
- '--border': '92 12% 85%',
635
- '--input': '92 12% 85%',
634
+ '--border': '92 40% 87%',
635
+ '--input': '92 40% 87%',
636
636
  '--ring': '92 90% 25%',
637
- '--sidebar': '92 16% 95%',
637
+ '--sidebar': '92 58% 94%',
638
638
  },
639
639
  dark: {
640
640
  '--background': '69 54% 8%',
@@ -148,10 +148,10 @@ export function getPresetVars(
148
148
 
149
149
  const extended: PresetTokens = {
150
150
  ...base,
151
- // Light cards carry the same faint preset tint as `--popover` (H 12% 99%)
151
+ // Light cards carry the same bold preset tint as `--popover` (H 55% 97%)
152
152
  // so they read as part of the preset family rather than a pure-white slab —
153
153
  // mirroring how dark cards (H 30% 10%) carry the accent hue into near-black.
154
- '--card': isDark ? `${hue} 30% 10%` : `${hue} 12% 99%`,
154
+ '--card': isDark ? `${hue} 30% 10%` : `${hue} 55% 97%`,
155
155
  '--card-foreground': foreground,
156
156
  '--chart-1': `${hue} ${sat}% 85%`,
157
157
  '--chart-2': `${hue} ${sat}% 75%`,