@oxyhq/bloom 0.6.17 → 0.6.19
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 +13 -4
- package/lib/commonjs/theme/BloomThemeProvider.js.map +1 -1
- package/lib/commonjs/theme/apply-dark-class.js +10 -7
- package/lib/commonjs/theme/apply-dark-class.js.map +1 -1
- package/lib/commonjs/theme/color-scope/index.js +21 -14
- package/lib/commonjs/theme/color-scope/index.js.map +1 -1
- package/lib/commonjs/theme/color-scope/index.web.js +29 -8
- package/lib/commonjs/theme/color-scope/index.web.js.map +1 -1
- package/lib/commonjs/theme/color-scope/style-builder.js +18 -0
- package/lib/commonjs/theme/color-scope/style-builder.js.map +1 -1
- package/lib/module/theme/BloomThemeProvider.js +14 -5
- package/lib/module/theme/BloomThemeProvider.js.map +1 -1
- package/lib/module/theme/apply-dark-class.js +10 -7
- package/lib/module/theme/apply-dark-class.js.map +1 -1
- package/lib/module/theme/color-scope/index.js +23 -16
- package/lib/module/theme/color-scope/index.js.map +1 -1
- package/lib/module/theme/color-scope/index.web.js +30 -9
- package/lib/module/theme/color-scope/index.web.js.map +1 -1
- package/lib/module/theme/color-scope/style-builder.js +17 -0
- package/lib/module/theme/color-scope/style-builder.js.map +1 -1
- package/lib/typescript/commonjs/icons/common.d.ts +8 -8
- package/lib/typescript/commonjs/theme/BloomThemeProvider.d.ts +8 -1
- package/lib/typescript/commonjs/theme/BloomThemeProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/apply-dark-class.d.ts +5 -4
- package/lib/typescript/commonjs/theme/apply-dark-class.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/color-scope/index.d.ts +4 -4
- package/lib/typescript/commonjs/theme/color-scope/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/color-scope/index.web.d.ts +6 -7
- package/lib/typescript/commonjs/theme/color-scope/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/color-scope/style-builder.d.ts +8 -0
- package/lib/typescript/commonjs/theme/color-scope/style-builder.d.ts.map +1 -1
- package/lib/typescript/module/icons/common.d.ts +8 -8
- package/lib/typescript/module/theme/BloomThemeProvider.d.ts +8 -1
- package/lib/typescript/module/theme/BloomThemeProvider.d.ts.map +1 -1
- package/lib/typescript/module/theme/apply-dark-class.d.ts +5 -4
- package/lib/typescript/module/theme/apply-dark-class.d.ts.map +1 -1
- package/lib/typescript/module/theme/color-scope/index.d.ts +4 -4
- package/lib/typescript/module/theme/color-scope/index.d.ts.map +1 -1
- package/lib/typescript/module/theme/color-scope/index.web.d.ts +6 -7
- package/lib/typescript/module/theme/color-scope/index.web.d.ts.map +1 -1
- package/lib/typescript/module/theme/color-scope/style-builder.d.ts +8 -0
- package/lib/typescript/module/theme/color-scope/style-builder.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/BloomColorScope.test.tsx +27 -3
- package/src/theme/BloomThemeProvider.tsx +32 -4
- package/src/theme/apply-dark-class.ts +8 -8
- package/src/theme/color-scope/index.tsx +28 -26
- package/src/theme/color-scope/index.web.tsx +35 -16
- package/src/theme/color-scope/style-builder.ts +25 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Platform } from 'react-native';
|
|
2
2
|
import { APP_COLOR_PRESETS, type AppColorName } from './color-presets';
|
|
3
|
+
import { getPresetVars } from './preset-vars';
|
|
3
4
|
|
|
4
5
|
export function applyDarkClass(resolved: 'light' | 'dark') {
|
|
5
6
|
if (Platform.OS === 'web' && typeof document !== 'undefined') {
|
|
@@ -11,18 +12,17 @@ export function applyDarkClass(resolved: 'light' | 'dark') {
|
|
|
11
12
|
* Apply a color preset's CSS custom properties to the document root.
|
|
12
13
|
* No-op on native — only affects web.
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* `hsl(var(--primary))
|
|
17
|
-
*
|
|
15
|
+
* Writes both the raw HSL triples (e.g. `--primary: 185 100% 20%`) and the
|
|
16
|
+
* resolved `--color-*` vars (`--color-primary: hsl(185 100% 20%)`) so both
|
|
17
|
+
* shadcn-style `hsl(var(--primary))` plumbing and Tailwind v4 `@theme`
|
|
18
|
+
* utilities resolve consistently. Includes extended tokens (card, chart-*,
|
|
19
|
+
* content-area, sidebar-*) so consumer apps don't need to synthesize them.
|
|
18
20
|
*/
|
|
19
21
|
export function applyColorPresetVars(preset: AppColorName, resolved: 'light' | 'dark') {
|
|
20
22
|
if (Platform.OS !== 'web' || typeof document === 'undefined') return;
|
|
23
|
+
if (!APP_COLOR_PRESETS[preset]) return;
|
|
21
24
|
|
|
22
|
-
const
|
|
23
|
-
if (!config) return;
|
|
24
|
-
|
|
25
|
-
const vars = resolved === 'dark' ? config.dark : config.light;
|
|
25
|
+
const vars = getPresetVars(preset, resolved, { includeResolvedColorVars: true });
|
|
26
26
|
const root = document.documentElement.style;
|
|
27
27
|
|
|
28
28
|
for (const [key, value] of Object.entries(vars)) {
|
|
@@ -1,37 +1,28 @@
|
|
|
1
|
-
import React, { useContext, useMemo } from 'react';
|
|
1
|
+
import React, { Children, cloneElement, isValidElement, useContext, useMemo } from 'react';
|
|
2
2
|
import { View, type StyleProp, type ViewStyle } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import { BloomThemeContext, type BloomThemeContextValue } from '../BloomThemeProvider';
|
|
5
5
|
import { buildTheme } from '../build-theme';
|
|
6
6
|
import type { AppColorName } from '../color-presets';
|
|
7
|
-
import {
|
|
8
|
-
import { buildScopeVars } from './style-builder';
|
|
9
|
-
|
|
10
|
-
interface NativeWindVarsModule {
|
|
11
|
-
vars: (record: Record<string, string>) => StyleProp<ViewStyle>;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const getNativeWindVars = lazyRequire<NativeWindVarsModule>('nativewind');
|
|
15
|
-
|
|
16
|
-
function presetStyle(colorPreset: AppColorName, mode: 'light' | 'dark'): StyleProp<ViewStyle> {
|
|
17
|
-
const module = getNativeWindVars();
|
|
18
|
-
if (!module || typeof module.vars !== 'function') return undefined;
|
|
19
|
-
return module.vars(buildScopeVars(colorPreset, mode));
|
|
20
|
-
}
|
|
7
|
+
import { buildNativePresetStyle } from './style-builder';
|
|
21
8
|
|
|
22
9
|
export interface BloomColorScopeProps {
|
|
23
10
|
/** Preset to apply within this subtree. */
|
|
24
11
|
colorPreset: AppColorName;
|
|
25
12
|
/**
|
|
26
|
-
* When `true`, do not render a wrapping `<View>`. The
|
|
27
|
-
*
|
|
13
|
+
* When `true`, do not render a wrapping `<View>`. The single child is cloned
|
|
14
|
+
* with the scope's CSS vars merged into its `style` prop (Radix-style).
|
|
28
15
|
*/
|
|
29
16
|
asChild?: boolean;
|
|
30
|
-
/** Additional style applied to the wrapping `<View
|
|
17
|
+
/** Additional style applied to the wrapping `<View>` (or merged into the cloned child with `asChild`). */
|
|
31
18
|
style?: StyleProp<ViewStyle>;
|
|
32
19
|
children: React.ReactNode;
|
|
33
20
|
}
|
|
34
21
|
|
|
22
|
+
interface StyleableProps {
|
|
23
|
+
style?: StyleProp<ViewStyle>;
|
|
24
|
+
}
|
|
25
|
+
|
|
35
26
|
export function BloomColorScope({
|
|
36
27
|
colorPreset,
|
|
37
28
|
asChild = false,
|
|
@@ -51,21 +42,32 @@ export function BloomColorScope({
|
|
|
51
42
|
}, [colorPreset, resolvedMode, parent]);
|
|
52
43
|
|
|
53
44
|
const varsStyle = useMemo(
|
|
54
|
-
() =>
|
|
45
|
+
() => buildNativePresetStyle(colorPreset, resolvedMode),
|
|
55
46
|
[colorPreset, resolvedMode],
|
|
56
47
|
);
|
|
57
48
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
49
|
+
let content: React.ReactNode;
|
|
50
|
+
if (asChild) {
|
|
51
|
+
const child = Children.only(children);
|
|
52
|
+
if (!isValidElement<StyleableProps>(child)) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
'BloomColorScope with `asChild` requires a single React element child that accepts a `style` prop.',
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
const childStyle = child.props.style;
|
|
58
|
+
const mergedStyle: StyleProp<ViewStyle> = [varsStyle, style, childStyle];
|
|
59
|
+
content = cloneElement(child, { style: mergedStyle });
|
|
60
|
+
} else {
|
|
61
|
+
content = <View style={[{ flex: 1 }, varsStyle, style]}>{children}</View>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return <BloomThemeContext.Provider value={contextValue}>{content}</BloomThemeContext.Provider>;
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
/**
|
|
66
68
|
* Escape hatch for advanced cases where the wrapping element is owned by the
|
|
67
69
|
* caller. Returns a stable native style object carrying the preset's CSS vars.
|
|
68
|
-
* Returns `undefined` when nativewind is not installed.
|
|
70
|
+
* Returns `undefined` on web or when `nativewind` is not installed.
|
|
69
71
|
*/
|
|
70
72
|
export function useColorScopeStyle(colorPreset: AppColorName): StyleProp<ViewStyle> {
|
|
71
73
|
const parent = useContext(BloomThemeContext);
|
|
@@ -74,7 +76,7 @@ export function useColorScopeStyle(colorPreset: AppColorName): StyleProp<ViewSty
|
|
|
74
76
|
}
|
|
75
77
|
const resolvedMode = parent.theme.mode;
|
|
76
78
|
return useMemo(
|
|
77
|
-
() =>
|
|
79
|
+
() => buildNativePresetStyle(colorPreset, resolvedMode),
|
|
78
80
|
[colorPreset, resolvedMode],
|
|
79
81
|
);
|
|
80
82
|
}
|
|
@@ -1,24 +1,33 @@
|
|
|
1
|
-
import React, { useContext, useMemo } from 'react';
|
|
1
|
+
import React, { Children, cloneElement, isValidElement, useContext, useMemo } from 'react';
|
|
2
2
|
|
|
3
|
-
import { BloomThemeContext } from '../BloomThemeProvider';
|
|
3
|
+
import { BloomThemeContext, type BloomThemeContextValue } from '../BloomThemeProvider';
|
|
4
4
|
import { buildTheme } from '../build-theme';
|
|
5
5
|
import type { AppColorName } from '../color-presets';
|
|
6
|
-
import { BloomThemeContextValue } from '../BloomThemeProvider';
|
|
7
6
|
import { buildScopeVars } from './style-builder';
|
|
8
7
|
|
|
9
8
|
export interface BloomColorScopeProps {
|
|
10
9
|
/** Preset to apply within this subtree. */
|
|
11
10
|
colorPreset: AppColorName;
|
|
12
11
|
/**
|
|
13
|
-
* When `true`, do not render a wrapping
|
|
14
|
-
*
|
|
15
|
-
* CSS vars (via `useColorScopeStyle`).
|
|
12
|
+
* When `true`, do not render a wrapping `<div>`. The single child is cloned
|
|
13
|
+
* with the scope's CSS vars merged into its `style` prop (Radix-style).
|
|
16
14
|
*/
|
|
17
15
|
asChild?: boolean;
|
|
16
|
+
/** Additional style applied to the wrapping `<div>` (or merged into the cloned child with `asChild`). */
|
|
17
|
+
style?: React.CSSProperties;
|
|
18
18
|
children: React.ReactNode;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
interface StyleableProps {
|
|
22
|
+
style?: React.CSSProperties;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function BloomColorScope({
|
|
26
|
+
colorPreset,
|
|
27
|
+
asChild = false,
|
|
28
|
+
style,
|
|
29
|
+
children,
|
|
30
|
+
}: BloomColorScopeProps) {
|
|
22
31
|
const parent = useContext(BloomThemeContext);
|
|
23
32
|
if (!parent) {
|
|
24
33
|
throw new Error('BloomColorScope must be used within a <BloomThemeProvider>');
|
|
@@ -31,23 +40,33 @@ export function BloomColorScope({ colorPreset, asChild = false, children }: Bloo
|
|
|
31
40
|
return { ...parent, theme, colorPreset };
|
|
32
41
|
}, [colorPreset, resolvedMode, parent]);
|
|
33
42
|
|
|
34
|
-
const
|
|
43
|
+
const varsStyle = useMemo(
|
|
35
44
|
() => buildScopeVars(colorPreset, resolvedMode) as React.CSSProperties,
|
|
36
45
|
[colorPreset, resolvedMode],
|
|
37
46
|
);
|
|
38
47
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
let content: React.ReactNode;
|
|
49
|
+
if (asChild) {
|
|
50
|
+
const child = Children.only(children);
|
|
51
|
+
if (!isValidElement<StyleableProps>(child)) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
'BloomColorScope with `asChild` requires a single React element child that accepts a `style` prop.',
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
const childStyle = child.props.style;
|
|
57
|
+
const mergedStyle: React.CSSProperties = { ...varsStyle, ...style, ...childStyle };
|
|
58
|
+
content = cloneElement(child, { style: mergedStyle });
|
|
59
|
+
} else {
|
|
60
|
+
const mergedStyle: React.CSSProperties = { ...varsStyle, ...style };
|
|
61
|
+
content = <div style={mergedStyle}>{children}</div>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return <BloomThemeContext.Provider value={contextValue}>{content}</BloomThemeContext.Provider>;
|
|
44
65
|
}
|
|
45
66
|
|
|
46
67
|
/**
|
|
47
68
|
* Escape hatch for advanced cases where the wrapping element is owned by the
|
|
48
|
-
* caller
|
|
49
|
-
* prop). Returns a stable React `style` object carrying every CSS custom
|
|
50
|
-
* property of the preset.
|
|
69
|
+
* caller. Returns a stable React style object carrying the preset's CSS vars.
|
|
51
70
|
*/
|
|
52
71
|
export function useColorScopeStyle(colorPreset: AppColorName): React.CSSProperties {
|
|
53
72
|
const parent = useContext(BloomThemeContext);
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
+
import { Platform, type StyleProp, type ViewStyle } from 'react-native';
|
|
2
|
+
|
|
1
3
|
import { getPresetVars } from '../preset-vars';
|
|
2
4
|
import type { AppColorName } from '../color-presets';
|
|
5
|
+
import { lazyRequire } from '../../utils/lazy-require';
|
|
6
|
+
|
|
7
|
+
interface NativeWindVarsModule {
|
|
8
|
+
vars: (record: Record<string, string>) => StyleProp<ViewStyle>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const getNativeWindVars = lazyRequire<NativeWindVarsModule>('nativewind');
|
|
3
12
|
|
|
4
13
|
/**
|
|
5
14
|
* Build the CSS custom-property map for a preset, ready to be applied to a
|
|
@@ -12,3 +21,19 @@ export function buildScopeVars(
|
|
|
12
21
|
): Record<string, string> {
|
|
13
22
|
return getPresetVars(colorPreset, mode, { includeResolvedColorVars: true });
|
|
14
23
|
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Build a native style object carrying every CSS var of the preset, using
|
|
27
|
+
* NativeWind's `vars()` when available. Returns `undefined` on web (where the
|
|
28
|
+
* provider writes vars to `documentElement` instead) or when `nativewind` is
|
|
29
|
+
* not installed.
|
|
30
|
+
*/
|
|
31
|
+
export function buildNativePresetStyle(
|
|
32
|
+
colorPreset: AppColorName,
|
|
33
|
+
mode: 'light' | 'dark',
|
|
34
|
+
): StyleProp<ViewStyle> {
|
|
35
|
+
if (Platform.OS === 'web') return undefined;
|
|
36
|
+
const module = getNativeWindVars();
|
|
37
|
+
if (!module || typeof module.vars !== 'function') return undefined;
|
|
38
|
+
return module.vars(buildScopeVars(colorPreset, mode));
|
|
39
|
+
}
|