@rific/auto-paper 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +121 -28
- package/dist/index.d.mts +75 -12
- package/dist/index.d.ts +75 -12
- package/dist/index.js +260 -116
- package/dist/index.mjs +241 -111
- package/package.json +5 -4
- package/src/ThemeProvider.tsx +22 -6
- package/src/ThemeSettingsContext.ts +2 -2
- package/src/components/AppearancePicker.tsx +25 -5
- package/src/components/BlurView.tsx +14 -17
- package/src/components/BottomNavigation.tsx +5 -5
- package/src/components/ColorPicker.tsx +7 -6
- package/src/components/PalettePicker.tsx +11 -11
- package/src/index.ts +11 -4
- package/src/navigation-bar.ts +3 -11
- package/src/redux/themeSlice.ts +4 -4
- package/src/useComputedTheme.ts +104 -24
- package/src/useSwatchGrid.ts +1 -1
- package/src/useTheme.ts +11 -0
- package/src/utils/getColorRoles.ts +29 -0
- package/src/utils/getSwatchContrast.ts +26 -0
- package/src/utils/getThirdColor.ts +103 -0
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
1
|
// src/BlurContext.tsx
|
|
9
2
|
import { useContext } from "react";
|
|
10
3
|
|
|
@@ -61,67 +54,28 @@ var Appbar = {
|
|
|
61
54
|
import { SegmentedButtons } from "react-native-paper";
|
|
62
55
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
63
56
|
var APPEARANCES = [
|
|
64
|
-
{ label: "System", value: "system"
|
|
65
|
-
{ label: "Light", value: "light"
|
|
66
|
-
{ label: "Dark", value: "dark"
|
|
57
|
+
{ label: "System", value: "system" },
|
|
58
|
+
{ label: "Light", value: "light" },
|
|
59
|
+
{ label: "Dark", value: "dark" }
|
|
67
60
|
];
|
|
68
|
-
var
|
|
61
|
+
var DEFAULT_ICONS = {
|
|
62
|
+
system: "monitor",
|
|
63
|
+
light: "white-balance-sunny",
|
|
64
|
+
dark: "weather-night"
|
|
65
|
+
};
|
|
66
|
+
var AppearancePicker = ({ value, onChange, showLabels = true, icons }) => {
|
|
67
|
+
const resolvedIcons = { ...DEFAULT_ICONS, ...icons };
|
|
68
|
+
return /* @__PURE__ */ jsx2(SegmentedButtons, { value, onValueChange: (v) => onChange(v), buttons: APPEARANCES.map((a) => ({ value: a.value, label: showLabels ? a.label : void 0, icon: resolvedIcons[a.value], accessibilityLabel: a.label })) });
|
|
69
|
+
};
|
|
69
70
|
|
|
70
71
|
// src/components/BlurView.tsx
|
|
71
|
-
import { useContext as
|
|
72
|
-
import { StyleSheet, View } from "react-native";
|
|
72
|
+
import { useContext as useContext4 } from "react";
|
|
73
|
+
import { StyleSheet as StyleSheet2, View as View2 } from "react-native";
|
|
73
74
|
import { useTheme as useTheme2 } from "react-native-paper";
|
|
74
|
-
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
75
|
-
var ExpoBlurView = (() => {
|
|
76
|
-
try {
|
|
77
|
-
return __require("expo-blur").BlurView;
|
|
78
|
-
} catch {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
})();
|
|
82
|
-
var ELEVATION_OPACITY = { 0: 0, 1: 0.05, 2: 0.08, 3: 0.11, 4: 0.12, 5: 0.14 };
|
|
83
|
-
var VARIANT_TINT_OPACITY = { light: 0.12, dark: 0.18 };
|
|
84
|
-
var BlurView = ({ blur = true, children, elevation, style, tintColor, tintOpacity, variant = "surface", ...props }) => {
|
|
85
|
-
const { dark, colors } = useTheme2();
|
|
86
|
-
const { settings } = useContext3(ThemeSettingsContext);
|
|
87
|
-
const surfaceColor = variant === "surfaceVariant" ? colors.surfaceVariant : colors.surface;
|
|
88
|
-
const variantColor = variant === "primary" ? colors.primary : variant === "secondary" ? colors.secondary : variant === "tertiary" ? colors.tertiary : variant === "error" ? colors.error : void 0;
|
|
89
|
-
const resolvedTintColor = tintColor ?? variantColor ?? (elevation !== void 0 ? colors.primary : void 0);
|
|
90
|
-
const resolvedTintOpacity = tintOpacity ?? (tintColor ? dark ? 0.24 : 0.16 : variantColor ? dark ? VARIANT_TINT_OPACITY.dark : VARIANT_TINT_OPACITY.light : elevation !== void 0 ? ELEVATION_OPACITY[elevation] : 0);
|
|
91
|
-
const tint = resolvedTintColor && resolvedTintOpacity > 0 ? /* @__PURE__ */ jsx3(View, { style: [StyleSheet.absoluteFill, { backgroundColor: resolvedTintColor, opacity: resolvedTintOpacity }] }) : null;
|
|
92
|
-
if (blur && ExpoBlurView)
|
|
93
|
-
return /* @__PURE__ */ jsxs2(ExpoBlurView, { ...props, tint: dark ? "dark" : "light", style, children: [
|
|
94
|
-
/* @__PURE__ */ jsx3(View, { style: [StyleSheet.absoluteFill, { backgroundColor: surfaceColor, opacity: settings.blurTint }] }),
|
|
95
|
-
tint,
|
|
96
|
-
children
|
|
97
|
-
] });
|
|
98
|
-
return /* @__PURE__ */ jsxs2(View, { ...props, style: [{ backgroundColor: surfaceColor }, style], children: [
|
|
99
|
-
tint,
|
|
100
|
-
children
|
|
101
|
-
] });
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
// src/components/BottomNavigation.tsx
|
|
105
|
-
import { useEffect as useEffect3 } from "react";
|
|
106
|
-
import { Platform } from "react-native";
|
|
107
|
-
import { BottomNavigation as PaperBottomNavigation, useTheme as useTheme3 } from "react-native-paper";
|
|
108
|
-
|
|
109
|
-
// src/navigation-bar.ts
|
|
110
|
-
var navigationBar = (() => {
|
|
111
|
-
try {
|
|
112
|
-
return __require("expo-navigation-bar");
|
|
113
|
-
} catch {
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
})();
|
|
117
|
-
var setNavigationBarStyle = (dark) => {
|
|
118
|
-
if (!navigationBar) return;
|
|
119
|
-
navigationBar.NavigationBar.setStyle(dark ? "light" : "dark");
|
|
120
|
-
};
|
|
121
75
|
|
|
122
76
|
// src/ThemeProvider.tsx
|
|
123
|
-
import { createContext as createContext3, useCallback as useCallback2, useContext as
|
|
124
|
-
import { StatusBar as StatusBar2, StyleSheet
|
|
77
|
+
import { createContext as createContext3, useCallback as useCallback2, useContext as useContext3, useEffect as useEffect2, useRef, useState as useState2 } from "react";
|
|
78
|
+
import { StatusBar as StatusBar2, StyleSheet, View } from "react-native";
|
|
125
79
|
import { Provider as PaperProvider } from "react-native-paper";
|
|
126
80
|
|
|
127
81
|
// src/useComputedTheme.ts
|
|
@@ -407,6 +361,27 @@ var getTonalColor = (color, lightness) => {
|
|
|
407
361
|
return getHex(`rgb(${toInt(r2)}, ${toInt(g2)}, ${toInt(b2)})`) ?? color;
|
|
408
362
|
};
|
|
409
363
|
|
|
364
|
+
// src/utils/isDarkColor.ts
|
|
365
|
+
var isDarkColor = (value) => {
|
|
366
|
+
const rgb = getRgb(value);
|
|
367
|
+
if (!rgb) return false;
|
|
368
|
+
const [r, g, b] = [rgb.r / 255, rgb.g / 255, rgb.b / 255];
|
|
369
|
+
const [rs, gs, bs] = [r, g, b].map((c) => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));
|
|
370
|
+
const luminance = 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
|
|
371
|
+
return luminance < 0.5;
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
// src/utils/getColorRoles.ts
|
|
375
|
+
var getColorRoles = (base, surface, containerAlpha = 0.15) => {
|
|
376
|
+
const container = getBlendedColor(base, surface, containerAlpha);
|
|
377
|
+
return {
|
|
378
|
+
color: base,
|
|
379
|
+
onColor: getTonalColor(base, isDarkColor(base) ? 0.95 : 0.08),
|
|
380
|
+
container,
|
|
381
|
+
onContainer: getTonalColor(base, isDarkColor(container) ? 0.92 : 0.12)
|
|
382
|
+
};
|
|
383
|
+
};
|
|
384
|
+
|
|
410
385
|
// src/utils/getTriadicPalette.ts
|
|
411
386
|
var HARMONY_OFFSETS = {
|
|
412
387
|
analogous: [1 / 12, 2 / 12],
|
|
@@ -488,51 +463,71 @@ function hslToHex(h, s, l) {
|
|
|
488
463
|
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
489
464
|
}
|
|
490
465
|
|
|
491
|
-
// src/utils/isDarkColor.ts
|
|
492
|
-
var isDarkColor = (value) => {
|
|
493
|
-
const rgb = getRgb(value);
|
|
494
|
-
if (!rgb) return false;
|
|
495
|
-
const [r, g, b] = [rgb.r / 255, rgb.g / 255, rgb.b / 255];
|
|
496
|
-
const [rs, gs, bs] = [r, g, b].map((c) => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));
|
|
497
|
-
const luminance = 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
|
|
498
|
-
return luminance < 0.5;
|
|
499
|
-
};
|
|
500
|
-
|
|
501
466
|
// src/useComputedTheme.ts
|
|
467
|
+
function normalizeExplicitColor(value) {
|
|
468
|
+
if (!getRgb(value)) throw new Error(`Invalid color format: ${value}`);
|
|
469
|
+
return getHex(value) ?? value;
|
|
470
|
+
}
|
|
471
|
+
var SEMANTIC_BASE_COLORS = {
|
|
472
|
+
success: "#2E7D32",
|
|
473
|
+
warning: "#A15C00",
|
|
474
|
+
danger: "#B00020"
|
|
475
|
+
};
|
|
502
476
|
function useComputedTheme(appearance, color, harmony = "split-complementary") {
|
|
503
477
|
const [theme, setTheme] = useState(null);
|
|
478
|
+
const primaryInput = typeof color === "string" ? color : color.primary;
|
|
479
|
+
const secondaryInput = typeof color === "string" ? null : color.secondary;
|
|
480
|
+
const tertiaryInput = typeof color === "string" ? null : color.tertiary;
|
|
504
481
|
const computeTheme = useCallback(() => {
|
|
505
482
|
let resolved = appearance;
|
|
506
483
|
if (resolved === "system") resolved = Appearance.getColorScheme();
|
|
507
484
|
if (resolved === "no-preference" || !resolved) resolved = "light";
|
|
508
485
|
const base = resolved === "dark" ? MD3DarkTheme : MD3LightTheme;
|
|
486
|
+
const surface = base.colors.surface;
|
|
487
|
+
const successRoles = getColorRoles(SEMANTIC_BASE_COLORS.success, surface);
|
|
488
|
+
const warningRoles = getColorRoles(SEMANTIC_BASE_COLORS.warning, surface);
|
|
489
|
+
const dangerRoles = getColorRoles(SEMANTIC_BASE_COLORS.danger, surface);
|
|
509
490
|
const _theme = {
|
|
510
491
|
...base,
|
|
511
492
|
colors: {
|
|
512
493
|
...base.colors,
|
|
513
|
-
elevation: { ...base.colors.elevation }
|
|
494
|
+
elevation: { ...base.colors.elevation },
|
|
495
|
+
success: successRoles.color,
|
|
496
|
+
onSuccess: successRoles.onColor,
|
|
497
|
+
successContainer: successRoles.container,
|
|
498
|
+
onSuccessContainer: successRoles.onContainer,
|
|
499
|
+
warning: warningRoles.color,
|
|
500
|
+
onWarning: warningRoles.onColor,
|
|
501
|
+
warningContainer: warningRoles.container,
|
|
502
|
+
onWarningContainer: warningRoles.onContainer,
|
|
503
|
+
danger: dangerRoles.color,
|
|
504
|
+
onDanger: dangerRoles.onColor,
|
|
505
|
+
dangerContainer: dangerRoles.container,
|
|
506
|
+
onDangerContainer: dangerRoles.onContainer
|
|
514
507
|
}
|
|
515
508
|
};
|
|
516
|
-
const palette = getTriadicPalette(
|
|
517
|
-
const
|
|
518
|
-
_theme.colors.primary =
|
|
519
|
-
_theme.colors.onPrimary =
|
|
520
|
-
_theme.colors.primaryContainer =
|
|
521
|
-
_theme.colors.onPrimaryContainer =
|
|
522
|
-
|
|
523
|
-
_theme.colors.
|
|
524
|
-
_theme.colors.
|
|
525
|
-
_theme.colors.
|
|
526
|
-
_theme.colors.
|
|
527
|
-
|
|
528
|
-
_theme.colors.
|
|
529
|
-
_theme.colors.
|
|
530
|
-
|
|
509
|
+
const palette = secondaryInput !== null && tertiaryInput !== null ? { primary: normalizeExplicitColor(primaryInput), secondary: normalizeExplicitColor(secondaryInput), tertiary: normalizeExplicitColor(tertiaryInput) } : getTriadicPalette(primaryInput, harmony);
|
|
510
|
+
const primaryRoles = getColorRoles(palette.primary, surface);
|
|
511
|
+
_theme.colors.primary = primaryRoles.color;
|
|
512
|
+
_theme.colors.onPrimary = primaryRoles.onColor;
|
|
513
|
+
_theme.colors.primaryContainer = primaryRoles.container;
|
|
514
|
+
_theme.colors.onPrimaryContainer = primaryRoles.onContainer;
|
|
515
|
+
const secondaryRoles = getColorRoles(palette.secondary, surface);
|
|
516
|
+
_theme.colors.secondary = secondaryRoles.color;
|
|
517
|
+
_theme.colors.onSecondary = secondaryRoles.onColor;
|
|
518
|
+
_theme.colors.secondaryContainer = secondaryRoles.container;
|
|
519
|
+
_theme.colors.onSecondaryContainer = secondaryRoles.onContainer;
|
|
520
|
+
const tertiaryRoles = getColorRoles(palette.tertiary, surface);
|
|
521
|
+
_theme.colors.tertiary = tertiaryRoles.color;
|
|
522
|
+
_theme.colors.onTertiary = tertiaryRoles.onColor;
|
|
523
|
+
_theme.colors.tertiaryContainer = tertiaryRoles.container;
|
|
524
|
+
_theme.colors.onTertiaryContainer = tertiaryRoles.onContainer;
|
|
525
|
+
const blended = getBlendedColor(palette.primary, palette.secondary, 0.5);
|
|
531
526
|
const tintSurface = (alpha) => getBlendedColor(blended, surface, alpha);
|
|
532
527
|
_theme.colors.background = base.dark ? "#0F0F0F" : "#F0F0F0";
|
|
533
528
|
_theme.colors.surface = surface;
|
|
534
529
|
_theme.colors.surfaceVariant = tintSurface(0.2);
|
|
535
|
-
_theme.colors.outline = getBlendedColor(
|
|
530
|
+
_theme.colors.outline = getBlendedColor(palette.primary, base.colors.outline, 0.45);
|
|
536
531
|
const grey = base.dark ? "#424242" : "#c2c2c2";
|
|
537
532
|
const blendedGrey = getBlendedColor(blended, grey, 0.05);
|
|
538
533
|
_theme.colors.elevation = {
|
|
@@ -544,7 +539,7 @@ function useComputedTheme(appearance, color, harmony = "split-complementary") {
|
|
|
544
539
|
level5: getBlendedColor(blendedGrey, _theme.colors.surface, 0.7)
|
|
545
540
|
};
|
|
546
541
|
setTheme(_theme);
|
|
547
|
-
}, [appearance,
|
|
542
|
+
}, [appearance, primaryInput, secondaryInput, tertiaryInput, harmony]);
|
|
548
543
|
useEffect(() => {
|
|
549
544
|
computeTheme();
|
|
550
545
|
}, [computeTheme]);
|
|
@@ -556,10 +551,12 @@ function useComputedTheme(appearance, color, harmony = "split-complementary") {
|
|
|
556
551
|
}
|
|
557
552
|
|
|
558
553
|
// src/ThemeProvider.tsx
|
|
559
|
-
import { jsx as
|
|
554
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
560
555
|
var NavBarContext = createContext3({});
|
|
561
|
-
var useNavBarContext = () =>
|
|
562
|
-
|
|
556
|
+
var useNavBarContext = () => useContext3(NavBarContext);
|
|
557
|
+
var BlurModuleContext = createContext3(void 0);
|
|
558
|
+
var useBlurModule = () => useContext3(BlurModuleContext);
|
|
559
|
+
function Provider({ children, defaults, expoBlur, initialValue, navigationBar, onChange, onNavBarChange, onReady, statusBarProps, style }) {
|
|
563
560
|
const [settings, setSettings] = useState2(() => ({ ...defaultThemeSettings, ...initialValue }));
|
|
564
561
|
const set = useCallback2((patch) => {
|
|
565
562
|
setSettings((prev) => ({ ...prev, ...patch }));
|
|
@@ -582,25 +579,61 @@ function Provider({ initialValue, onChange, children, defaults, onNavBarChange,
|
|
|
582
579
|
}
|
|
583
580
|
}, [theme, onReady]);
|
|
584
581
|
if (!theme) return null;
|
|
585
|
-
return /* @__PURE__ */
|
|
586
|
-
/* @__PURE__ */
|
|
587
|
-
/* @__PURE__ */
|
|
582
|
+
return /* @__PURE__ */ jsx3(ThemeSettingsContext.Provider, { value: { settings, set }, children: /* @__PURE__ */ jsxs2(PaperProvider, { theme, children: [
|
|
583
|
+
/* @__PURE__ */ jsx3(StatusBar2, { backgroundColor: theme.colors.background, barStyle: theme.dark ? "light-content" : "dark-content", ...statusBarProps }),
|
|
584
|
+
/* @__PURE__ */ jsx3(PaperDefaultsContext.Provider, { value: defaults ?? {}, children: /* @__PURE__ */ jsx3(NavBarContext.Provider, { value: { navigationBar, onNavBarChange }, children: /* @__PURE__ */ jsx3(BlurModuleContext.Provider, { value: expoBlur, children: /* @__PURE__ */ jsx3(View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style], children }) }) }) })
|
|
588
585
|
] }) });
|
|
589
586
|
}
|
|
590
|
-
var styles =
|
|
587
|
+
var styles = StyleSheet.create({
|
|
591
588
|
flex: { flex: 1 }
|
|
592
589
|
});
|
|
593
590
|
|
|
591
|
+
// src/components/BlurView.tsx
|
|
592
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
593
|
+
var ELEVATION_OPACITY = { 0: 0, 1: 0.05, 2: 0.08, 3: 0.11, 4: 0.12, 5: 0.14 };
|
|
594
|
+
var VARIANT_TINT_OPACITY = { light: 0.12, dark: 0.18 };
|
|
595
|
+
var BlurView = ({ blur = true, children, elevation, style, tintColor, tintOpacity, variant = "surface", ...props }) => {
|
|
596
|
+
const { dark, colors } = useTheme2();
|
|
597
|
+
const { settings } = useContext4(ThemeSettingsContext);
|
|
598
|
+
const expoBlur = useBlurModule();
|
|
599
|
+
const surfaceColor = variant === "surfaceVariant" ? colors.surfaceVariant : colors.surface;
|
|
600
|
+
const variantColor = variant === "primary" ? colors.primary : variant === "secondary" ? colors.secondary : variant === "tertiary" ? colors.tertiary : variant === "error" ? colors.error : void 0;
|
|
601
|
+
const resolvedTintColor = tintColor ?? variantColor ?? (elevation !== void 0 ? colors.primary : void 0);
|
|
602
|
+
const resolvedTintOpacity = tintOpacity ?? (tintColor ? dark ? 0.24 : 0.16 : variantColor ? dark ? VARIANT_TINT_OPACITY.dark : VARIANT_TINT_OPACITY.light : elevation !== void 0 ? ELEVATION_OPACITY[elevation] : 0);
|
|
603
|
+
const tint = resolvedTintColor && resolvedTintOpacity > 0 ? /* @__PURE__ */ jsx4(View2, { style: [StyleSheet2.absoluteFill, { backgroundColor: resolvedTintColor, opacity: resolvedTintOpacity }] }) : null;
|
|
604
|
+
if (blur && expoBlur)
|
|
605
|
+
return /* @__PURE__ */ jsxs3(expoBlur.BlurView, { ...props, tint: dark ? "dark" : "light", style, children: [
|
|
606
|
+
/* @__PURE__ */ jsx4(View2, { style: [StyleSheet2.absoluteFill, { backgroundColor: surfaceColor, opacity: settings.blurTint }] }),
|
|
607
|
+
tint,
|
|
608
|
+
children
|
|
609
|
+
] });
|
|
610
|
+
return /* @__PURE__ */ jsxs3(View2, { ...props, style: [{ backgroundColor: surfaceColor }, style], children: [
|
|
611
|
+
tint,
|
|
612
|
+
children
|
|
613
|
+
] });
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
// src/components/BottomNavigation.tsx
|
|
617
|
+
import { useEffect as useEffect3 } from "react";
|
|
618
|
+
import { Platform } from "react-native";
|
|
619
|
+
import { BottomNavigation as PaperBottomNavigation, useTheme as useTheme3 } from "react-native-paper";
|
|
620
|
+
|
|
621
|
+
// src/navigation-bar.ts
|
|
622
|
+
var setNavigationBarStyle = (navigationBar, dark) => {
|
|
623
|
+
if (!navigationBar) return;
|
|
624
|
+
navigationBar.NavigationBar.setStyle(dark ? "light" : "dark");
|
|
625
|
+
};
|
|
626
|
+
|
|
594
627
|
// src/components/BottomNavigation.tsx
|
|
595
628
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
596
629
|
function useNavigationBarSync() {
|
|
597
630
|
const theme = useTheme3();
|
|
598
|
-
const { onNavBarChange } = useNavBarContext();
|
|
631
|
+
const { navigationBar, onNavBarChange } = useNavBarContext();
|
|
599
632
|
useEffect3(() => {
|
|
600
633
|
if (Platform.OS !== "android") return;
|
|
601
634
|
if (onNavBarChange) onNavBarChange(theme.colors.surface, theme.dark);
|
|
602
|
-
else if (navigationBar) setNavigationBarStyle(theme.dark);
|
|
603
|
-
}, [theme, onNavBarChange]);
|
|
635
|
+
else if (navigationBar) setNavigationBarStyle(navigationBar, theme.dark);
|
|
636
|
+
}, [theme, onNavBarChange, navigationBar]);
|
|
604
637
|
}
|
|
605
638
|
function BottomNavigationComponent(props) {
|
|
606
639
|
const defaults = usePaperDefaults();
|
|
@@ -637,7 +670,7 @@ function Chip({ variant, style, selectedColor, ...props }) {
|
|
|
637
670
|
// src/components/ColorPicker.tsx
|
|
638
671
|
import { useState as useState5 } from "react";
|
|
639
672
|
import { StyleSheet as StyleSheet4, TouchableOpacity, View as View4 } from "react-native";
|
|
640
|
-
import { Icon, TouchableRipple } from "react-native-paper";
|
|
673
|
+
import { Icon, TouchableRipple, useTheme as useTheme6 } from "react-native-paper";
|
|
641
674
|
|
|
642
675
|
// src/useSwatchGrid.ts
|
|
643
676
|
import { useState as useState3 } from "react";
|
|
@@ -650,6 +683,15 @@ function useSwatchSize(fallback) {
|
|
|
650
683
|
return { onLayout, size };
|
|
651
684
|
}
|
|
652
685
|
|
|
686
|
+
// src/utils/getSwatchContrast.ts
|
|
687
|
+
var RING_WIDTH = 1;
|
|
688
|
+
var SELECTED_RING_WIDTH = 3;
|
|
689
|
+
var getContrastColor = (color) => isDarkColor(color) ? "#ffffff" : "#000000";
|
|
690
|
+
var getSwatchRing = (color, selected, outlineColor) => ({
|
|
691
|
+
borderColor: selected ? getContrastColor(color) : outlineColor,
|
|
692
|
+
borderWidth: selected ? SELECTED_RING_WIDTH : RING_WIDTH
|
|
693
|
+
});
|
|
694
|
+
|
|
653
695
|
// src/components/Dialog.tsx
|
|
654
696
|
import React2, { useEffect as useEffect4, useRef as useRef2, useState as useState4 } from "react";
|
|
655
697
|
import { Animated, BackHandler, Easing, Pressable, StyleSheet as StyleSheet3, View as View3 } from "react-native";
|
|
@@ -741,10 +783,11 @@ var defaultColors = [
|
|
|
741
783
|
];
|
|
742
784
|
var ColorPicker = ({ value, onChange, colors = defaultColors, blur: blurProp }) => {
|
|
743
785
|
const blur = useBlur(blurProp);
|
|
786
|
+
const { colors: themeColors } = useTheme6();
|
|
744
787
|
const [open, setOpen] = useState5(false);
|
|
745
788
|
const { onLayout, size } = useSwatchSize(SIZE);
|
|
746
789
|
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
747
|
-
/* @__PURE__ */ jsx9(TouchableRipple, { onPress: () => setOpen(true), style: [styles3.trigger, { backgroundColor: value }], borderless: true, children: /* @__PURE__ */ jsx9(Icon, { source: "palette", size: 20, color:
|
|
790
|
+
/* @__PURE__ */ jsx9(TouchableRipple, { onPress: () => setOpen(true), style: [styles3.trigger, { backgroundColor: value }, getSwatchRing(value, false, themeColors.outlineVariant)], borderless: true, children: /* @__PURE__ */ jsx9(Icon, { source: "palette", size: 20, color: getContrastColor(value) }) }),
|
|
748
791
|
/* @__PURE__ */ jsx9(Dialog, { blur, visible: open, onDismiss: () => setOpen(false), children: /* @__PURE__ */ jsx9(Dialog.Content, { children: /* @__PURE__ */ jsx9(View4, { style: styles3.swatches, onLayout, children: colors.map(({ value: hex }) => /* @__PURE__ */ jsx9(
|
|
749
792
|
TouchableOpacity,
|
|
750
793
|
{
|
|
@@ -752,15 +795,14 @@ var ColorPicker = ({ value, onChange, colors = defaultColors, blur: blurProp })
|
|
|
752
795
|
onChange(hex);
|
|
753
796
|
setOpen(false);
|
|
754
797
|
},
|
|
755
|
-
style: [styles3.swatch, { backgroundColor: hex, borderRadius: size / 2, height: size, width: size }, value === hex
|
|
756
|
-
children: value === hex && /* @__PURE__ */ jsx9(Icon, { source: "check", size: 20, color:
|
|
798
|
+
style: [styles3.swatch, { backgroundColor: hex, borderRadius: size / 2, height: size, width: size }, getSwatchRing(hex, value === hex, themeColors.outlineVariant)],
|
|
799
|
+
children: value === hex && /* @__PURE__ */ jsx9(Icon, { source: "check", size: 20, color: getContrastColor(hex) })
|
|
757
800
|
},
|
|
758
801
|
hex
|
|
759
802
|
)) }) }) })
|
|
760
803
|
] });
|
|
761
804
|
};
|
|
762
805
|
var styles3 = StyleSheet4.create({
|
|
763
|
-
selected: { borderColor: "white", borderWidth: 3 },
|
|
764
806
|
swatch: { alignItems: "center", justifyContent: "center" },
|
|
765
807
|
swatches: { flexDirection: "row", flexWrap: "wrap", gap: SWATCH_GRID_GAP, paddingTop: 12 },
|
|
766
808
|
trigger: { alignItems: "center", alignSelf: "flex-start", borderRadius: SIZE / 2, height: SIZE, justifyContent: "center", width: SIZE }
|
|
@@ -831,11 +873,11 @@ var HarmonyPicker = ({ value, onChange, blur: blurProp }) => {
|
|
|
831
873
|
};
|
|
832
874
|
|
|
833
875
|
// src/components/IconButton.tsx
|
|
834
|
-
import { IconButton as PaperIconButton, useTheme as
|
|
876
|
+
import { IconButton as PaperIconButton, useTheme as useTheme7 } from "react-native-paper";
|
|
835
877
|
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
836
878
|
function IconButton({ variant, iconColor, containerColor, ...props }) {
|
|
837
879
|
const defaults = usePaperDefaults();
|
|
838
|
-
const { colors } =
|
|
880
|
+
const { colors } = useTheme7();
|
|
839
881
|
const variantContainerColor = variant === "primary" ? colors.primaryContainer : variant === "secondary" ? colors.secondaryContainer : variant === "tertiary" ? colors.tertiaryContainer : variant === "surface" ? colors.surface : void 0;
|
|
840
882
|
const variantIconColor = variant === "primary" ? colors.onPrimaryContainer : variant === "secondary" ? colors.onSecondaryContainer : variant === "tertiary" ? colors.onTertiaryContainer : variant === "surface" ? colors.onSurface : void 0;
|
|
841
883
|
return /* @__PURE__ */ jsx13(PaperIconButton, { ...defaults.IconButton, containerColor: containerColor ?? variantContainerColor, iconColor: iconColor ?? variantIconColor, ...props });
|
|
@@ -844,7 +886,7 @@ function IconButton({ variant, iconColor, containerColor, ...props }) {
|
|
|
844
886
|
// src/components/PalettePicker.tsx
|
|
845
887
|
import { useState as useState7 } from "react";
|
|
846
888
|
import { StyleSheet as StyleSheet6, TouchableOpacity as TouchableOpacity2, View as View5 } from "react-native";
|
|
847
|
-
import { Icon as Icon2, TouchableRipple as TouchableRipple2 } from "react-native-paper";
|
|
889
|
+
import { Icon as Icon2, TouchableRipple as TouchableRipple2, useTheme as useTheme8 } from "react-native-paper";
|
|
848
890
|
import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
849
891
|
var SIZE2 = 48;
|
|
850
892
|
var defaultWeights = { primary: 2, secondary: 1, tertiary: 1 };
|
|
@@ -862,12 +904,13 @@ var buildWedges = (weights) => {
|
|
|
862
904
|
var Pie = ({ palette, weights = defaultWeights, size = SIZE2 }) => /* @__PURE__ */ jsx14(View5, { style: [styles5.pie, { borderRadius: size / 2, height: size, width: size }], children: buildWedges(weights).map(({ key, rotate, share }) => /* @__PURE__ */ jsx14(View5, { style: [styles5.rotator, { transform: [{ rotate: `${rotate}deg` }] }], children: /* @__PURE__ */ jsx14(View5, { style: styles5.halfMask, children: /* @__PURE__ */ jsx14(View5, { style: [styles5.innerRotator, { transform: [{ rotate: `${share - 180}deg` }] }], children: /* @__PURE__ */ jsx14(View5, { style: [styles5.wedgeFill, { backgroundColor: palette[key] }] }) }) }) }, key)) });
|
|
863
905
|
var PalettePicker = ({ value, onChange, harmony = "split-complementary", weights, colors = defaultColors, blur: blurProp }) => {
|
|
864
906
|
const blur = useBlur(blurProp);
|
|
907
|
+
const { colors: themeColors } = useTheme8();
|
|
865
908
|
const [open, setOpen] = useState7(false);
|
|
866
909
|
const { onLayout, size } = useSwatchSize(SIZE2);
|
|
867
910
|
return /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
868
911
|
/* @__PURE__ */ jsx14(TouchableRipple2, { onPress: () => setOpen(true), style: styles5.trigger, borderless: true, children: /* @__PURE__ */ jsxs6(View5, { style: styles5.triggerContent, children: [
|
|
869
912
|
/* @__PURE__ */ jsx14(Pie, { palette: getTriadicPalette(value, harmony), weights }),
|
|
870
|
-
/* @__PURE__ */ jsx14(View5, { pointerEvents: "none", style: styles5.triggerIcon, children: /* @__PURE__ */ jsx14(Icon2, { source: "palette", size: 20, color:
|
|
913
|
+
/* @__PURE__ */ jsx14(View5, { pointerEvents: "none", style: [styles5.triggerIcon, { borderRadius: SIZE2 / 2 }, getSwatchRing(value, false, themeColors.outlineVariant)], children: /* @__PURE__ */ jsx14(Icon2, { source: "palette", size: 20, color: getContrastColor(value) }) })
|
|
871
914
|
] }) }),
|
|
872
915
|
/* @__PURE__ */ jsx14(Dialog, { blur, visible: open, onDismiss: () => setOpen(false), children: /* @__PURE__ */ jsx14(Dialog.Content, { children: /* @__PURE__ */ jsx14(View5, { style: styles5.swatches, onLayout, children: colors.map(({ value: hex }) => /* @__PURE__ */ jsxs6(
|
|
873
916
|
TouchableOpacity2,
|
|
@@ -879,7 +922,7 @@ var PalettePicker = ({ value, onChange, harmony = "split-complementary", weights
|
|
|
879
922
|
style: [styles5.swatch, { height: size, width: size }],
|
|
880
923
|
children: [
|
|
881
924
|
/* @__PURE__ */ jsx14(Pie, { palette: getTriadicPalette(hex, harmony), weights, size }),
|
|
882
|
-
|
|
925
|
+
/* @__PURE__ */ jsx14(View5, { pointerEvents: "none", style: [styles5.ring, { borderRadius: size / 2 }, getSwatchRing(hex, value === hex, themeColors.outlineVariant)], children: value === hex && /* @__PURE__ */ jsx14(Icon2, { source: "check", size: 20, color: getContrastColor(hex) }) })
|
|
883
926
|
]
|
|
884
927
|
},
|
|
885
928
|
hex
|
|
@@ -891,7 +934,7 @@ var styles5 = StyleSheet6.create({
|
|
|
891
934
|
innerRotator: { height: "100%", left: "-100%", overflow: "hidden", position: "absolute", top: 0, width: "200%" },
|
|
892
935
|
pie: { overflow: "hidden" },
|
|
893
936
|
rotator: { height: "100%", left: 0, overflow: "hidden", position: "absolute", top: 0, width: "100%" },
|
|
894
|
-
|
|
937
|
+
ring: { alignItems: "center", bottom: 0, justifyContent: "center", left: 0, position: "absolute", right: 0, top: 0 },
|
|
895
938
|
swatch: { alignItems: "center", justifyContent: "center" },
|
|
896
939
|
swatches: { flexDirection: "row", flexWrap: "wrap", gap: SWATCH_GRID_GAP, paddingTop: 12 },
|
|
897
940
|
trigger: { alignItems: "center", alignSelf: "flex-start", borderRadius: SIZE2 / 2, height: SIZE2, justifyContent: "center", width: SIZE2 },
|
|
@@ -946,10 +989,90 @@ var selectThemeBlur = (state) => state.blur;
|
|
|
946
989
|
var selectThemeColor = (state) => state.color;
|
|
947
990
|
var selectThemeHarmony = (state) => state.harmony;
|
|
948
991
|
|
|
992
|
+
// src/useTheme.ts
|
|
993
|
+
import { useTheme as usePaperTheme } from "react-native-paper";
|
|
994
|
+
var useAutoPaperTheme = () => usePaperTheme();
|
|
995
|
+
|
|
949
996
|
// src/useThemeSettings.ts
|
|
950
997
|
import { useContext as useContext5 } from "react";
|
|
951
998
|
var useThemeSettings = () => useContext5(ThemeSettingsContext);
|
|
952
999
|
|
|
1000
|
+
// src/utils/getThirdColor.ts
|
|
1001
|
+
function rgbToHsl(r, g, b) {
|
|
1002
|
+
r /= 255;
|
|
1003
|
+
g /= 255;
|
|
1004
|
+
b /= 255;
|
|
1005
|
+
const max = Math.max(r, g, b);
|
|
1006
|
+
const min = Math.min(r, g, b);
|
|
1007
|
+
const delta = max - min;
|
|
1008
|
+
let h = 0;
|
|
1009
|
+
if (delta !== 0) {
|
|
1010
|
+
if (max === r) h = (g - b) / delta % 6;
|
|
1011
|
+
else if (max === g) h = (b - r) / delta + 2;
|
|
1012
|
+
else h = (r - g) / delta + 4;
|
|
1013
|
+
h = (h * 60 + 360) % 360;
|
|
1014
|
+
}
|
|
1015
|
+
const l = (max + min) / 2;
|
|
1016
|
+
const s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
|
|
1017
|
+
return { h, s, l };
|
|
1018
|
+
}
|
|
1019
|
+
function hslToHex2(h, s, l) {
|
|
1020
|
+
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
1021
|
+
const x = c * (1 - Math.abs(h / 60 % 2 - 1));
|
|
1022
|
+
const m = l - c / 2;
|
|
1023
|
+
let r = 0;
|
|
1024
|
+
let g = 0;
|
|
1025
|
+
let b = 0;
|
|
1026
|
+
if (h < 60) {
|
|
1027
|
+
r = c;
|
|
1028
|
+
g = x;
|
|
1029
|
+
b = 0;
|
|
1030
|
+
} else if (h < 120) {
|
|
1031
|
+
r = x;
|
|
1032
|
+
g = c;
|
|
1033
|
+
b = 0;
|
|
1034
|
+
} else if (h < 180) {
|
|
1035
|
+
r = 0;
|
|
1036
|
+
g = c;
|
|
1037
|
+
b = x;
|
|
1038
|
+
} else if (h < 240) {
|
|
1039
|
+
r = 0;
|
|
1040
|
+
g = x;
|
|
1041
|
+
b = c;
|
|
1042
|
+
} else if (h < 300) {
|
|
1043
|
+
r = x;
|
|
1044
|
+
g = 0;
|
|
1045
|
+
b = c;
|
|
1046
|
+
} else {
|
|
1047
|
+
r = c;
|
|
1048
|
+
g = 0;
|
|
1049
|
+
b = x;
|
|
1050
|
+
}
|
|
1051
|
+
const toInt = (value) => Math.round((value + m) * 255);
|
|
1052
|
+
return getHex(`rgb(${toInt(r)}, ${toInt(g)}, ${toInt(b)})`) ?? "#000000";
|
|
1053
|
+
}
|
|
1054
|
+
var toRad = (deg) => deg * Math.PI / 180;
|
|
1055
|
+
var toDeg = (rad) => rad * 180 / Math.PI;
|
|
1056
|
+
function thirdHue(hA, hB) {
|
|
1057
|
+
const x = Math.cos(toRad(hA)) + Math.cos(toRad(hB));
|
|
1058
|
+
const y = Math.sin(toRad(hA)) + Math.sin(toRad(hB));
|
|
1059
|
+
if (Math.abs(x) < 1e-9 && Math.abs(y) < 1e-9) return (hA + 90) % 360;
|
|
1060
|
+
const meanHue = (toDeg(Math.atan2(y, x)) + 360) % 360;
|
|
1061
|
+
return (meanHue + 180) % 360;
|
|
1062
|
+
}
|
|
1063
|
+
function getThirdColor(colorA, colorB) {
|
|
1064
|
+
const rgbA = getRgb(colorA);
|
|
1065
|
+
const rgbB = getRgb(colorB);
|
|
1066
|
+
if (!rgbA) throw new Error(`Invalid color format: ${colorA}`);
|
|
1067
|
+
if (!rgbB) throw new Error(`Invalid color format: ${colorB}`);
|
|
1068
|
+
const hslA = rgbToHsl(rgbA.r, rgbA.g, rgbA.b);
|
|
1069
|
+
const hslB = rgbToHsl(rgbB.r, rgbB.g, rgbB.b);
|
|
1070
|
+
const h = thirdHue(hslA.h, hslB.h);
|
|
1071
|
+
const s = (hslA.s + hslB.s) / 2;
|
|
1072
|
+
const l = (hslA.l + hslB.l) / 2;
|
|
1073
|
+
return hslToHex2(h, s, l);
|
|
1074
|
+
}
|
|
1075
|
+
|
|
953
1076
|
// src/utils/getTintTextColor.ts
|
|
954
1077
|
var getTintTextColor = (tintColor, backdropColor, tintOpacity) => {
|
|
955
1078
|
const blended = getBlendedColor(tintColor, backdropColor, tintOpacity);
|
|
@@ -970,14 +1093,18 @@ export {
|
|
|
970
1093
|
Menu,
|
|
971
1094
|
PalettePicker,
|
|
972
1095
|
Provider,
|
|
1096
|
+
SEMANTIC_BASE_COLORS,
|
|
973
1097
|
TextInput,
|
|
974
1098
|
ThemeSettingsContext,
|
|
975
1099
|
createThemeReducer,
|
|
976
1100
|
defaultColors,
|
|
977
1101
|
defaultThemeSettings,
|
|
978
1102
|
getBlendedColor,
|
|
1103
|
+
getColorRoles,
|
|
1104
|
+
getContrastColor,
|
|
979
1105
|
getHex,
|
|
980
1106
|
getRgb,
|
|
1107
|
+
getThirdColor,
|
|
981
1108
|
getTintTextColor,
|
|
982
1109
|
getTonalColor,
|
|
983
1110
|
getTriadicPalette,
|
|
@@ -988,8 +1115,11 @@ export {
|
|
|
988
1115
|
selectThemeHarmony,
|
|
989
1116
|
themeActions,
|
|
990
1117
|
themeReducer,
|
|
1118
|
+
useAutoPaperTheme,
|
|
991
1119
|
useBlur,
|
|
1120
|
+
useBlurModule,
|
|
992
1121
|
useComputedTheme,
|
|
1122
|
+
useNavBarContext,
|
|
993
1123
|
usePaperDefaults,
|
|
994
1124
|
useThemeSettings
|
|
995
1125
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rific/auto-paper",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Adaptive react-native-paper theming: triadic palette from a seed color + system/light/dark appearance",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -31,14 +31,15 @@
|
|
|
31
31
|
"type": "commonjs",
|
|
32
32
|
"exports": {
|
|
33
33
|
".": {
|
|
34
|
-
"react-native": "./dist/index.
|
|
34
|
+
"react-native": "./dist/index.mjs",
|
|
35
35
|
"types": "./dist/index.d.ts",
|
|
36
|
-
"import": "./dist/index.
|
|
36
|
+
"import": "./dist/index.mjs",
|
|
37
37
|
"require": "./dist/index.js"
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"main": "dist/index.js",
|
|
41
|
-
"module": "dist/index.
|
|
41
|
+
"module": "dist/index.mjs",
|
|
42
|
+
"react-native": "dist/index.mjs",
|
|
42
43
|
"types": "dist/index.d.ts",
|
|
43
44
|
"files": [
|
|
44
45
|
"dist",
|
package/src/ThemeProvider.tsx
CHANGED
|
@@ -2,26 +2,40 @@ import { createContext, type ReactNode, useCallback, useContext, useEffect, useR
|
|
|
2
2
|
import { StatusBar, type StatusBarProps, type StyleProp, StyleSheet, View, type ViewStyle } from 'react-native'
|
|
3
3
|
import { Provider as PaperProvider } from 'react-native-paper'
|
|
4
4
|
|
|
5
|
+
import type { ExpoBlurModule } from './components/BlurView'
|
|
6
|
+
import type { ExpoNavigationBarModule } from './navigation-bar'
|
|
5
7
|
import { type PaperDefaults, PaperDefaultsContext } from './PaperDefaultsContext'
|
|
6
8
|
import { defaultThemeSettings, type ThemeSettings, ThemeSettingsContext } from './ThemeSettingsContext'
|
|
7
9
|
import { useComputedTheme } from './useComputedTheme'
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
// expo-navigation-bar/expo-blur are no longer auto-detected via require() - Metro doesn't
|
|
12
|
+
// rewrite a require()-in-try/catch call into its module graph inside an ESM (.mjs) build, so
|
|
13
|
+
// the module-level detection this package used to do silently broke as soon as consumers'
|
|
14
|
+
// bundlers resolved this package's ESM entry point. <Provider navigationBar={...} expoBlur={...}>
|
|
15
|
+
// receives the already-imported modules directly instead.
|
|
16
|
+
type NavBarContextType = { navigationBar?: ExpoNavigationBarModule; onNavBarChange?: (color: string, dark: boolean) => void }
|
|
10
17
|
const NavBarContext = createContext<NavBarContextType>({})
|
|
11
18
|
export const useNavBarContext = () => useContext(NavBarContext)
|
|
12
19
|
|
|
20
|
+
const BlurModuleContext = createContext<ExpoBlurModule | undefined>(undefined)
|
|
21
|
+
export const useBlurModule = () => useContext(BlurModuleContext)
|
|
22
|
+
|
|
13
23
|
export type ProviderProps = {
|
|
14
|
-
initialValue?: Partial<ThemeSettings>
|
|
15
|
-
onChange?: (settings: ThemeSettings) => void
|
|
16
24
|
children: ReactNode
|
|
17
25
|
defaults?: PaperDefaults
|
|
26
|
+
/** Injects expo-blur for `<BlurView>`. Pass `import * as ExpoBlur from 'expo-blur'`; omit to always render BlurView's solid fallback. */
|
|
27
|
+
expoBlur?: ExpoBlurModule
|
|
28
|
+
initialValue?: Partial<ThemeSettings>
|
|
29
|
+
/** Injects expo-navigation-bar so the Android nav bar icon style auto-syncs with the theme. Pass `import * as ExpoNavigationBar from 'expo-navigation-bar'`; omit (and don't pass onNavBarChange) to skip nav bar syncing entirely. */
|
|
30
|
+
navigationBar?: ExpoNavigationBarModule
|
|
31
|
+
onChange?: (settings: ThemeSettings) => void
|
|
18
32
|
onNavBarChange?: (color: string, dark: boolean) => void
|
|
19
33
|
onReady?: () => void
|
|
20
34
|
statusBarProps?: StatusBarProps
|
|
21
35
|
style?: StyleProp<ViewStyle>
|
|
22
36
|
}
|
|
23
37
|
|
|
24
|
-
export function Provider({
|
|
38
|
+
export function Provider({ children, defaults, expoBlur, initialValue, navigationBar, onChange, onNavBarChange, onReady, statusBarProps, style }: ProviderProps) {
|
|
25
39
|
const [settings, setSettings] = useState<ThemeSettings>(() => ({ ...defaultThemeSettings, ...initialValue }))
|
|
26
40
|
|
|
27
41
|
const set = useCallback((patch: Partial<ThemeSettings>) => {
|
|
@@ -55,8 +69,10 @@ export function Provider({ initialValue, onChange, children, defaults, onNavBarC
|
|
|
55
69
|
<PaperProvider theme={theme}>
|
|
56
70
|
<StatusBar backgroundColor={theme.colors.background} barStyle={theme.dark ? 'light-content' : 'dark-content'} {...statusBarProps} />
|
|
57
71
|
<PaperDefaultsContext.Provider value={defaults ?? {}}>
|
|
58
|
-
<NavBarContext.Provider value={{ onNavBarChange }}>
|
|
59
|
-
<
|
|
72
|
+
<NavBarContext.Provider value={{ navigationBar, onNavBarChange }}>
|
|
73
|
+
<BlurModuleContext.Provider value={expoBlur}>
|
|
74
|
+
<View style={[styles.flex, { backgroundColor: theme.colors.background }, style]}>{children}</View>
|
|
75
|
+
</BlurModuleContext.Provider>
|
|
60
76
|
</NavBarContext.Provider>
|
|
61
77
|
</PaperDefaultsContext.Provider>
|
|
62
78
|
</PaperProvider>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createContext } from 'react'
|
|
2
2
|
|
|
3
3
|
import type { ThemeAppearance } from './useComputedTheme'
|
|
4
|
-
import type { ColorHarmony } from './utils/getTriadicPalette'
|
|
4
|
+
import type { ColorHarmony, TriadicPalette } from './utils/getTriadicPalette'
|
|
5
5
|
|
|
6
6
|
export type ThemeSettings = {
|
|
7
7
|
appearance: ThemeAppearance
|
|
8
8
|
blur: boolean
|
|
9
9
|
blurTint: number
|
|
10
|
-
color: string
|
|
10
|
+
color: string | TriadicPalette
|
|
11
11
|
harmony: ColorHarmony
|
|
12
12
|
}
|
|
13
13
|
|