@oxyhq/bloom 0.1.30 → 0.1.31
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 +23 -18
- package/lib/commonjs/theme/BloomThemeProvider.js.map +1 -1
- package/lib/module/theme/BloomThemeProvider.js +24 -19
- package/lib/module/theme/BloomThemeProvider.js.map +1 -1
- package/lib/typescript/commonjs/theme/BloomThemeProvider.d.ts +0 -2
- package/lib/typescript/commonjs/theme/BloomThemeProvider.d.ts.map +1 -1
- package/lib/typescript/module/theme/BloomThemeProvider.d.ts +0 -2
- package/lib/typescript/module/theme/BloomThemeProvider.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/theme/BloomThemeProvider.tsx +23 -18
|
@@ -18,13 +18,13 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
18
18
|
function hslVarToCSS(value) {
|
|
19
19
|
const parts = value.split('/').map(s => s.trim());
|
|
20
20
|
if (parts.length === 2) {
|
|
21
|
-
const alpha = parseFloat(parts[1]) / 100;
|
|
22
|
-
return `hsla(${parts[0].replace(/ /g, ', ')}, ${alpha})`;
|
|
21
|
+
const alpha = parseFloat(parts[1] ?? '100') / 100;
|
|
22
|
+
return `hsla(${(parts[0] ?? '').replace(/ /g, ', ')}, ${alpha})`;
|
|
23
23
|
}
|
|
24
24
|
return `hsl(${value.replace(/ /g, ', ')})`;
|
|
25
25
|
}
|
|
26
26
|
function extractHue(hslVar) {
|
|
27
|
-
return parseInt(hslVar.split(' ')[0], 10);
|
|
27
|
+
return parseInt(hslVar.split(' ')[0] ?? '0', 10);
|
|
28
28
|
}
|
|
29
29
|
function hsl(h, s, l) {
|
|
30
30
|
return `hsl(${h}, ${s}%, ${l}%)`;
|
|
@@ -43,20 +43,20 @@ function buildTheme(appColor, resolved, isAdaptive = false) {
|
|
|
43
43
|
if (!themeColors) {
|
|
44
44
|
const preset = _colorPresets.APP_COLOR_PRESETS[appColor];
|
|
45
45
|
const vars = resolved === 'light' ? preset.light : preset.dark;
|
|
46
|
-
const primaryHue = extractHue(vars['--primary']);
|
|
47
|
-
const destructiveHue = extractHue(vars['--destructive']);
|
|
48
|
-
const surface = hslVarToCSS(vars['--surface']);
|
|
49
|
-
const background = hslVarToCSS(vars['--background']);
|
|
50
|
-
const mutedForeground = hslVarToCSS(vars['--muted-foreground']);
|
|
46
|
+
const primaryHue = extractHue(vars['--primary'] ?? '0 0% 0%');
|
|
47
|
+
const destructiveHue = extractHue(vars['--destructive'] ?? '0 0% 0%');
|
|
48
|
+
const surface = hslVarToCSS(vars['--surface'] ?? '0 0% 0%');
|
|
49
|
+
const background = hslVarToCSS(vars['--background'] ?? '0 0% 0%');
|
|
50
|
+
const mutedForeground = hslVarToCSS(vars['--muted-foreground'] ?? '0 0% 50%');
|
|
51
51
|
themeColors = {
|
|
52
52
|
background,
|
|
53
53
|
backgroundSecondary: surface,
|
|
54
|
-
backgroundTertiary: hslVarToCSS(vars['--muted']),
|
|
55
|
-
text: hslVarToCSS(vars['--foreground']),
|
|
54
|
+
backgroundTertiary: hslVarToCSS(vars['--muted'] ?? '0 0% 0%'),
|
|
55
|
+
text: hslVarToCSS(vars['--foreground'] ?? '0 0% 100%'),
|
|
56
56
|
textSecondary: mutedForeground,
|
|
57
57
|
textTertiary: mutedForeground,
|
|
58
|
-
border: hslVarToCSS(vars['--border']),
|
|
59
|
-
borderLight: hslVarToCSS(vars['--input']),
|
|
58
|
+
border: hslVarToCSS(vars['--border'] ?? '0 0% 20%'),
|
|
59
|
+
borderLight: hslVarToCSS(vars['--input'] ?? '0 0% 20%'),
|
|
60
60
|
primary: preset.hex,
|
|
61
61
|
primaryLight: surface,
|
|
62
62
|
primaryDark: background,
|
|
@@ -97,8 +97,6 @@ function BloomThemeProvider({
|
|
|
97
97
|
}) {
|
|
98
98
|
const rnScheme = (0, _reactNative.useColorScheme)();
|
|
99
99
|
const [internalPreset, setInternalPreset] = (0, _react.useState)(controlledPreset ?? 'oxy');
|
|
100
|
-
|
|
101
|
-
// Sync internal state when controlled prop changes
|
|
102
100
|
if (controlledPreset !== undefined && controlledPreset !== internalPreset) {
|
|
103
101
|
setInternalPreset(controlledPreset);
|
|
104
102
|
}
|
|
@@ -107,10 +105,19 @@ function BloomThemeProvider({
|
|
|
107
105
|
const isAdaptive = mode === 'adaptive';
|
|
108
106
|
const effectiveMode = isAdaptive ? 'system' : mode;
|
|
109
107
|
const resolved = effectiveMode === 'system' ? rnScheme === 'dark' ? 'dark' : 'light' : effectiveMode;
|
|
110
|
-
|
|
108
|
+
|
|
109
|
+
// Apply native color scheme and CSS vars synchronously on first render
|
|
110
|
+
// and whenever the resolved mode or preset changes. Using a ref to track
|
|
111
|
+
// the last-applied values avoids calling side effects on every render
|
|
112
|
+
// while still applying them before the first paint.
|
|
113
|
+
const lastApplied = (0, _react.useRef)('');
|
|
114
|
+
const applyKey = `${resolved}:${appColor}`;
|
|
115
|
+
if (lastApplied.current !== applyKey) {
|
|
116
|
+
lastApplied.current = applyKey;
|
|
117
|
+
(0, _setColorSchemeSafe.setColorSchemeSafe)(effectiveMode);
|
|
111
118
|
(0, _applyDarkClass.applyDarkClass)(resolved);
|
|
112
119
|
(0, _applyDarkClass.applyColorPresetVars)(appColor, resolved);
|
|
113
|
-
}
|
|
120
|
+
}
|
|
114
121
|
const setMode = (0, _react.useCallback)(newMode => {
|
|
115
122
|
(0, _setColorSchemeSafe.setColorSchemeSafe)(newMode);
|
|
116
123
|
onModeChange?.(newMode);
|
|
@@ -138,8 +145,6 @@ function BloomThemeProvider({
|
|
|
138
145
|
/**
|
|
139
146
|
* Scoped color override for a subtree.
|
|
140
147
|
* Inherits mode/dark from the parent BloomThemeProvider but overrides the color preset.
|
|
141
|
-
* Use this to tint a section of the UI (e.g. a visited user's profile) without
|
|
142
|
-
* affecting the rest of the app.
|
|
143
148
|
*/
|
|
144
149
|
|
|
145
150
|
function BloomColorScope({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_colorPresets","_adaptiveColors","_applyDarkClass","_setColorSchemeSafe","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","hslVarToCSS","value","parts","split","map","s","trim","length","alpha","parseFloat","replace","extractHue","hslVar","parseInt","hsl","h","l","buildTheme","appColor","resolved","isAdaptive","isDark","themeColors","Platform","OS","adaptive","getAdaptiveColors","preset","APP_COLOR_PRESETS","vars","light","dark","primaryHue","destructiveHue","surface","background","mutedForeground","backgroundSecondary","backgroundTertiary","text","textSecondary","textTertiary","border","borderLight","primary","hex","primaryLight","primaryDark","secondary","tint","icon","iconActive","success","error","warning","info","primarySubtle","primarySubtleForeground","negative","negativeForeground","negativeSubtle","negativeSubtleForeground","contrast50","card","shadow","overlay","mode","colors","isLight","BloomThemeContext","exports","createContext","BloomThemeProvider","controlledMode","colorPreset","controlledPreset","onModeChange","onColorPresetChange","children","rnScheme","useRNColorScheme","internalPreset","setInternalPreset","useState","undefined","effectiveMode","
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_colorPresets","_adaptiveColors","_applyDarkClass","_setColorSchemeSafe","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","hslVarToCSS","value","parts","split","map","s","trim","length","alpha","parseFloat","replace","extractHue","hslVar","parseInt","hsl","h","l","buildTheme","appColor","resolved","isAdaptive","isDark","themeColors","Platform","OS","adaptive","getAdaptiveColors","preset","APP_COLOR_PRESETS","vars","light","dark","primaryHue","destructiveHue","surface","background","mutedForeground","backgroundSecondary","backgroundTertiary","text","textSecondary","textTertiary","border","borderLight","primary","hex","primaryLight","primaryDark","secondary","tint","icon","iconActive","success","error","warning","info","primarySubtle","primarySubtleForeground","negative","negativeForeground","negativeSubtle","negativeSubtleForeground","contrast50","card","shadow","overlay","mode","colors","isLight","BloomThemeContext","exports","createContext","BloomThemeProvider","controlledMode","colorPreset","controlledPreset","onModeChange","onColorPresetChange","children","rnScheme","useRNColorScheme","internalPreset","setInternalPreset","useState","undefined","effectiveMode","lastApplied","useRef","applyKey","current","setColorSchemeSafe","applyDarkClass","applyColorPresetVars","setMode","useCallback","newMode","setColorPreset","contextValue","useMemo","theme","jsx","Provider","BloomColorScope","parent","useContext","Error"],"sourceRoot":"../../../src","sources":["theme/BloomThemeProvider.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import React, { createContext, useCallback, useContext,
|
|
3
|
+
import React, { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { useColorScheme as useRNColorScheme, Platform } from 'react-native';
|
|
5
5
|
import { APP_COLOR_PRESETS } from "./color-presets.js";
|
|
6
6
|
import { getAdaptiveColors } from './adaptive-colors';
|
|
@@ -10,13 +10,13 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
10
10
|
function hslVarToCSS(value) {
|
|
11
11
|
const parts = value.split('/').map(s => s.trim());
|
|
12
12
|
if (parts.length === 2) {
|
|
13
|
-
const alpha = parseFloat(parts[1]) / 100;
|
|
14
|
-
return `hsla(${parts[0].replace(/ /g, ', ')}, ${alpha})`;
|
|
13
|
+
const alpha = parseFloat(parts[1] ?? '100') / 100;
|
|
14
|
+
return `hsla(${(parts[0] ?? '').replace(/ /g, ', ')}, ${alpha})`;
|
|
15
15
|
}
|
|
16
16
|
return `hsl(${value.replace(/ /g, ', ')})`;
|
|
17
17
|
}
|
|
18
18
|
function extractHue(hslVar) {
|
|
19
|
-
return parseInt(hslVar.split(' ')[0], 10);
|
|
19
|
+
return parseInt(hslVar.split(' ')[0] ?? '0', 10);
|
|
20
20
|
}
|
|
21
21
|
function hsl(h, s, l) {
|
|
22
22
|
return `hsl(${h}, ${s}%, ${l}%)`;
|
|
@@ -35,20 +35,20 @@ export function buildTheme(appColor, resolved, isAdaptive = false) {
|
|
|
35
35
|
if (!themeColors) {
|
|
36
36
|
const preset = APP_COLOR_PRESETS[appColor];
|
|
37
37
|
const vars = resolved === 'light' ? preset.light : preset.dark;
|
|
38
|
-
const primaryHue = extractHue(vars['--primary']);
|
|
39
|
-
const destructiveHue = extractHue(vars['--destructive']);
|
|
40
|
-
const surface = hslVarToCSS(vars['--surface']);
|
|
41
|
-
const background = hslVarToCSS(vars['--background']);
|
|
42
|
-
const mutedForeground = hslVarToCSS(vars['--muted-foreground']);
|
|
38
|
+
const primaryHue = extractHue(vars['--primary'] ?? '0 0% 0%');
|
|
39
|
+
const destructiveHue = extractHue(vars['--destructive'] ?? '0 0% 0%');
|
|
40
|
+
const surface = hslVarToCSS(vars['--surface'] ?? '0 0% 0%');
|
|
41
|
+
const background = hslVarToCSS(vars['--background'] ?? '0 0% 0%');
|
|
42
|
+
const mutedForeground = hslVarToCSS(vars['--muted-foreground'] ?? '0 0% 50%');
|
|
43
43
|
themeColors = {
|
|
44
44
|
background,
|
|
45
45
|
backgroundSecondary: surface,
|
|
46
|
-
backgroundTertiary: hslVarToCSS(vars['--muted']),
|
|
47
|
-
text: hslVarToCSS(vars['--foreground']),
|
|
46
|
+
backgroundTertiary: hslVarToCSS(vars['--muted'] ?? '0 0% 0%'),
|
|
47
|
+
text: hslVarToCSS(vars['--foreground'] ?? '0 0% 100%'),
|
|
48
48
|
textSecondary: mutedForeground,
|
|
49
49
|
textTertiary: mutedForeground,
|
|
50
|
-
border: hslVarToCSS(vars['--border']),
|
|
51
|
-
borderLight: hslVarToCSS(vars['--input']),
|
|
50
|
+
border: hslVarToCSS(vars['--border'] ?? '0 0% 20%'),
|
|
51
|
+
borderLight: hslVarToCSS(vars['--input'] ?? '0 0% 20%'),
|
|
52
52
|
primary: preset.hex,
|
|
53
53
|
primaryLight: surface,
|
|
54
54
|
primaryDark: background,
|
|
@@ -89,8 +89,6 @@ export function BloomThemeProvider({
|
|
|
89
89
|
}) {
|
|
90
90
|
const rnScheme = useRNColorScheme();
|
|
91
91
|
const [internalPreset, setInternalPreset] = useState(controlledPreset ?? 'oxy');
|
|
92
|
-
|
|
93
|
-
// Sync internal state when controlled prop changes
|
|
94
92
|
if (controlledPreset !== undefined && controlledPreset !== internalPreset) {
|
|
95
93
|
setInternalPreset(controlledPreset);
|
|
96
94
|
}
|
|
@@ -99,10 +97,19 @@ export function BloomThemeProvider({
|
|
|
99
97
|
const isAdaptive = mode === 'adaptive';
|
|
100
98
|
const effectiveMode = isAdaptive ? 'system' : mode;
|
|
101
99
|
const resolved = effectiveMode === 'system' ? rnScheme === 'dark' ? 'dark' : 'light' : effectiveMode;
|
|
102
|
-
|
|
100
|
+
|
|
101
|
+
// Apply native color scheme and CSS vars synchronously on first render
|
|
102
|
+
// and whenever the resolved mode or preset changes. Using a ref to track
|
|
103
|
+
// the last-applied values avoids calling side effects on every render
|
|
104
|
+
// while still applying them before the first paint.
|
|
105
|
+
const lastApplied = useRef('');
|
|
106
|
+
const applyKey = `${resolved}:${appColor}`;
|
|
107
|
+
if (lastApplied.current !== applyKey) {
|
|
108
|
+
lastApplied.current = applyKey;
|
|
109
|
+
setColorSchemeSafe(effectiveMode);
|
|
103
110
|
applyDarkClass(resolved);
|
|
104
111
|
applyColorPresetVars(appColor, resolved);
|
|
105
|
-
}
|
|
112
|
+
}
|
|
106
113
|
const setMode = useCallback(newMode => {
|
|
107
114
|
setColorSchemeSafe(newMode);
|
|
108
115
|
onModeChange?.(newMode);
|
|
@@ -130,8 +137,6 @@ export function BloomThemeProvider({
|
|
|
130
137
|
/**
|
|
131
138
|
* Scoped color override for a subtree.
|
|
132
139
|
* Inherits mode/dark from the parent BloomThemeProvider but overrides the color preset.
|
|
133
|
-
* Use this to tint a section of the UI (e.g. a visited user's profile) without
|
|
134
|
-
* affecting the rest of the app.
|
|
135
140
|
*/
|
|
136
141
|
|
|
137
142
|
export function BloomColorScope({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","createContext","useCallback","useContext","
|
|
1
|
+
{"version":3,"names":["React","createContext","useCallback","useContext","useMemo","useRef","useState","useColorScheme","useRNColorScheme","Platform","APP_COLOR_PRESETS","getAdaptiveColors","applyDarkClass","applyColorPresetVars","setColorSchemeSafe","jsx","_jsx","hslVarToCSS","value","parts","split","map","s","trim","length","alpha","parseFloat","replace","extractHue","hslVar","parseInt","hsl","h","l","buildTheme","appColor","resolved","isAdaptive","isDark","themeColors","OS","adaptive","preset","vars","light","dark","primaryHue","destructiveHue","surface","background","mutedForeground","backgroundSecondary","backgroundTertiary","text","textSecondary","textTertiary","border","borderLight","primary","hex","primaryLight","primaryDark","secondary","tint","icon","iconActive","success","error","warning","info","primarySubtle","primarySubtleForeground","negative","negativeForeground","negativeSubtle","negativeSubtleForeground","contrast50","card","shadow","overlay","mode","colors","isLight","BloomThemeContext","BloomThemeProvider","controlledMode","colorPreset","controlledPreset","onModeChange","onColorPresetChange","children","rnScheme","internalPreset","setInternalPreset","undefined","effectiveMode","lastApplied","applyKey","current","setMode","newMode","setColorPreset","contextValue","theme","Provider","BloomColorScope","parent","Error"],"sourceRoot":"../../../src","sources":["theme/BloomThemeProvider.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -22,8 +22,6 @@ export declare function BloomThemeProvider({ mode: controlledMode, colorPreset:
|
|
|
22
22
|
/**
|
|
23
23
|
* Scoped color override for a subtree.
|
|
24
24
|
* Inherits mode/dark from the parent BloomThemeProvider but overrides the color preset.
|
|
25
|
-
* Use this to tint a section of the UI (e.g. a visited user's profile) without
|
|
26
|
-
* affecting the rest of the app.
|
|
27
25
|
*/
|
|
28
26
|
export interface BloomColorScopeProps {
|
|
29
27
|
colorPreset: AppColorName;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BloomThemeProvider.d.ts","sourceRoot":"","sources":["../../../../src/theme/BloomThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"BloomThemeProvider.d.ts","sourceRoot":"","sources":["../../../../src/theme/BloomThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4E,MAAM,OAAO,CAAC;AAEjG,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAIvE,OAAO,KAAK,EAAE,KAAK,EAAe,SAAS,EAAE,MAAM,SAAS,CAAC;AAmB7D,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,EAAE,UAAU,GAAE,OAAe,GAAG,KAAK,CAqEjH;AAED,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;CAChD;AAED,eAAO,MAAM,iBAAiB,8CAAqD,CAAC;AAEpF,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACzC,mBAAmB,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IACrD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,gBAAgB,EAC7B,YAAY,EACZ,mBAAmB,EACnB,QAAQ,GACT,EAAE,uBAAuB,2CAyDzB;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,2CAoB9E"}
|
|
@@ -22,8 +22,6 @@ export declare function BloomThemeProvider({ mode: controlledMode, colorPreset:
|
|
|
22
22
|
/**
|
|
23
23
|
* Scoped color override for a subtree.
|
|
24
24
|
* Inherits mode/dark from the parent BloomThemeProvider but overrides the color preset.
|
|
25
|
-
* Use this to tint a section of the UI (e.g. a visited user's profile) without
|
|
26
|
-
* affecting the rest of the app.
|
|
27
25
|
*/
|
|
28
26
|
export interface BloomColorScopeProps {
|
|
29
27
|
colorPreset: AppColorName;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BloomThemeProvider.d.ts","sourceRoot":"","sources":["../../../../src/theme/BloomThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"BloomThemeProvider.d.ts","sourceRoot":"","sources":["../../../../src/theme/BloomThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4E,MAAM,OAAO,CAAC;AAEjG,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAIvE,OAAO,KAAK,EAAE,KAAK,EAAe,SAAS,EAAE,MAAM,SAAS,CAAC;AAmB7D,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,EAAE,UAAU,GAAE,OAAe,GAAG,KAAK,CAqEjH;AAED,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;CAChD;AAED,eAAO,MAAM,iBAAiB,8CAAqD,CAAC;AAEpF,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACzC,mBAAmB,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IACrD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,gBAAgB,EAC7B,YAAY,EACZ,mBAAmB,EACnB,QAAQ,GACT,EAAE,uBAAuB,2CAyDzB;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,2CAoB9E"}
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useCallback, useContext,
|
|
1
|
+
import React, { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import { useColorScheme as useRNColorScheme, Platform } from 'react-native';
|
|
3
3
|
import { APP_COLOR_PRESETS, type AppColorName } from './color-presets';
|
|
4
4
|
import { getAdaptiveColors } from './adaptive-colors';
|
|
@@ -9,14 +9,14 @@ import type { Theme, ThemeColors, ThemeMode } from './types';
|
|
|
9
9
|
function hslVarToCSS(value: string): string {
|
|
10
10
|
const parts = value.split('/').map((s) => s.trim());
|
|
11
11
|
if (parts.length === 2) {
|
|
12
|
-
const alpha = parseFloat(parts[1]
|
|
13
|
-
return `hsla(${parts[0]
|
|
12
|
+
const alpha = parseFloat(parts[1] ?? '100') / 100;
|
|
13
|
+
return `hsla(${(parts[0] ?? '').replace(/ /g, ', ')}, ${alpha})`;
|
|
14
14
|
}
|
|
15
15
|
return `hsl(${value.replace(/ /g, ', ')})`;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
function extractHue(hslVar: string): number {
|
|
19
|
-
return parseInt(hslVar.split(' ')[0]
|
|
19
|
+
return parseInt(hslVar.split(' ')[0] ?? '0', 10);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function hsl(h: number, s: number, l: number): string {
|
|
@@ -39,24 +39,24 @@ export function buildTheme(appColor: AppColorName, resolved: 'light' | 'dark', i
|
|
|
39
39
|
if (!themeColors) {
|
|
40
40
|
const preset = APP_COLOR_PRESETS[appColor];
|
|
41
41
|
const vars = resolved === 'light' ? preset.light : preset.dark;
|
|
42
|
-
const primaryHue = extractHue(vars['--primary']
|
|
43
|
-
const destructiveHue = extractHue(vars['--destructive']
|
|
42
|
+
const primaryHue = extractHue(vars['--primary'] ?? '0 0% 0%');
|
|
43
|
+
const destructiveHue = extractHue(vars['--destructive'] ?? '0 0% 0%');
|
|
44
44
|
|
|
45
|
-
const surface = hslVarToCSS(vars['--surface']
|
|
46
|
-
const background = hslVarToCSS(vars['--background']
|
|
47
|
-
const mutedForeground = hslVarToCSS(vars['--muted-foreground']
|
|
45
|
+
const surface = hslVarToCSS(vars['--surface'] ?? '0 0% 0%');
|
|
46
|
+
const background = hslVarToCSS(vars['--background'] ?? '0 0% 0%');
|
|
47
|
+
const mutedForeground = hslVarToCSS(vars['--muted-foreground'] ?? '0 0% 50%');
|
|
48
48
|
|
|
49
49
|
themeColors = {
|
|
50
50
|
background,
|
|
51
51
|
backgroundSecondary: surface,
|
|
52
|
-
backgroundTertiary: hslVarToCSS(vars['--muted']
|
|
52
|
+
backgroundTertiary: hslVarToCSS(vars['--muted'] ?? '0 0% 0%'),
|
|
53
53
|
|
|
54
|
-
text: hslVarToCSS(vars['--foreground']
|
|
54
|
+
text: hslVarToCSS(vars['--foreground'] ?? '0 0% 100%'),
|
|
55
55
|
textSecondary: mutedForeground,
|
|
56
56
|
textTertiary: mutedForeground,
|
|
57
57
|
|
|
58
|
-
border: hslVarToCSS(vars['--border']
|
|
59
|
-
borderLight: hslVarToCSS(vars['--input']
|
|
58
|
+
border: hslVarToCSS(vars['--border'] ?? '0 0% 20%'),
|
|
59
|
+
borderLight: hslVarToCSS(vars['--input'] ?? '0 0% 20%'),
|
|
60
60
|
|
|
61
61
|
primary: preset.hex,
|
|
62
62
|
primaryLight: surface,
|
|
@@ -123,7 +123,6 @@ export function BloomThemeProvider({
|
|
|
123
123
|
const rnScheme = useRNColorScheme();
|
|
124
124
|
const [internalPreset, setInternalPreset] = useState<AppColorName>(controlledPreset ?? 'oxy');
|
|
125
125
|
|
|
126
|
-
// Sync internal state when controlled prop changes
|
|
127
126
|
if (controlledPreset !== undefined && controlledPreset !== internalPreset) {
|
|
128
127
|
setInternalPreset(controlledPreset);
|
|
129
128
|
}
|
|
@@ -138,10 +137,18 @@ export function BloomThemeProvider({
|
|
|
138
137
|
? (rnScheme === 'dark' ? 'dark' : 'light')
|
|
139
138
|
: effectiveMode;
|
|
140
139
|
|
|
141
|
-
|
|
140
|
+
// Apply native color scheme and CSS vars synchronously on first render
|
|
141
|
+
// and whenever the resolved mode or preset changes. Using a ref to track
|
|
142
|
+
// the last-applied values avoids calling side effects on every render
|
|
143
|
+
// while still applying them before the first paint.
|
|
144
|
+
const lastApplied = useRef<string>('');
|
|
145
|
+
const applyKey = `${resolved}:${appColor}`;
|
|
146
|
+
if (lastApplied.current !== applyKey) {
|
|
147
|
+
lastApplied.current = applyKey;
|
|
148
|
+
setColorSchemeSafe(effectiveMode);
|
|
142
149
|
applyDarkClass(resolved);
|
|
143
150
|
applyColorPresetVars(appColor, resolved);
|
|
144
|
-
}
|
|
151
|
+
}
|
|
145
152
|
|
|
146
153
|
const setMode = useCallback(
|
|
147
154
|
(newMode: ThemeMode) => {
|
|
@@ -174,8 +181,6 @@ export function BloomThemeProvider({
|
|
|
174
181
|
/**
|
|
175
182
|
* Scoped color override for a subtree.
|
|
176
183
|
* Inherits mode/dark from the parent BloomThemeProvider but overrides the color preset.
|
|
177
|
-
* Use this to tint a section of the UI (e.g. a visited user's profile) without
|
|
178
|
-
* affecting the rest of the app.
|
|
179
184
|
*/
|
|
180
185
|
export interface BloomColorScopeProps {
|
|
181
186
|
colorPreset: AppColorName;
|