@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/dist/index.js CHANGED
@@ -44,14 +44,18 @@ __export(index_exports, {
44
44
  Menu: () => Menu,
45
45
  PalettePicker: () => PalettePicker,
46
46
  Provider: () => Provider,
47
+ SEMANTIC_BASE_COLORS: () => SEMANTIC_BASE_COLORS,
47
48
  TextInput: () => TextInput,
48
49
  ThemeSettingsContext: () => ThemeSettingsContext,
49
50
  createThemeReducer: () => createThemeReducer,
50
51
  defaultColors: () => defaultColors,
51
52
  defaultThemeSettings: () => defaultThemeSettings,
52
53
  getBlendedColor: () => getBlendedColor,
54
+ getColorRoles: () => getColorRoles,
55
+ getContrastColor: () => getContrastColor,
53
56
  getHex: () => getHex,
54
57
  getRgb: () => getRgb,
58
+ getThirdColor: () => getThirdColor,
55
59
  getTintTextColor: () => getTintTextColor,
56
60
  getTonalColor: () => getTonalColor,
57
61
  getTriadicPalette: () => getTriadicPalette,
@@ -62,8 +66,11 @@ __export(index_exports, {
62
66
  selectThemeHarmony: () => selectThemeHarmony,
63
67
  themeActions: () => themeActions,
64
68
  themeReducer: () => themeReducer,
69
+ useAutoPaperTheme: () => useAutoPaperTheme,
65
70
  useBlur: () => useBlur,
71
+ useBlurModule: () => useBlurModule,
66
72
  useComputedTheme: () => useComputedTheme,
73
+ useNavBarContext: () => useNavBarContext,
67
74
  usePaperDefaults: () => usePaperDefaults,
68
75
  useThemeSettings: () => useThemeSettings
69
76
  });
@@ -125,74 +132,35 @@ var Appbar = {
125
132
  var import_react_native_paper2 = require("react-native-paper");
126
133
  var import_jsx_runtime2 = require("react/jsx-runtime");
127
134
  var APPEARANCES = [
128
- { label: "System", value: "system", icon: "brightness-auto" },
129
- { label: "Light", value: "light", icon: "white-balance-sunny" },
130
- { label: "Dark", value: "dark", icon: "weather-night" }
135
+ { label: "System", value: "system" },
136
+ { label: "Light", value: "light" },
137
+ { label: "Dark", value: "dark" }
131
138
  ];
132
- var AppearancePicker = ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_paper2.SegmentedButtons, { value, onValueChange: (v) => onChange(v), buttons: APPEARANCES.map((a) => ({ value: a.value, label: a.label, icon: a.icon })) });
133
-
134
- // src/components/BlurView.tsx
135
- var import_react4 = require("react");
136
- var import_react_native2 = require("react-native");
137
- var import_react_native_paper3 = require("react-native-paper");
138
- var import_jsx_runtime3 = require("react/jsx-runtime");
139
- var ExpoBlurView = (() => {
140
- try {
141
- return require("expo-blur").BlurView;
142
- } catch {
143
- return null;
144
- }
145
- })();
146
- var ELEVATION_OPACITY = { 0: 0, 1: 0.05, 2: 0.08, 3: 0.11, 4: 0.12, 5: 0.14 };
147
- var VARIANT_TINT_OPACITY = { light: 0.12, dark: 0.18 };
148
- var BlurView = ({ blur = true, children, elevation, style, tintColor, tintOpacity, variant = "surface", ...props }) => {
149
- const { dark, colors } = (0, import_react_native_paper3.useTheme)();
150
- const { settings } = (0, import_react4.useContext)(ThemeSettingsContext);
151
- const surfaceColor = variant === "surfaceVariant" ? colors.surfaceVariant : colors.surface;
152
- const variantColor = variant === "primary" ? colors.primary : variant === "secondary" ? colors.secondary : variant === "tertiary" ? colors.tertiary : variant === "error" ? colors.error : void 0;
153
- const resolvedTintColor = tintColor ?? variantColor ?? (elevation !== void 0 ? colors.primary : void 0);
154
- 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);
155
- const tint = resolvedTintColor && resolvedTintOpacity > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native2.View, { style: [import_react_native2.StyleSheet.absoluteFill, { backgroundColor: resolvedTintColor, opacity: resolvedTintOpacity }] }) : null;
156
- if (blur && ExpoBlurView)
157
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(ExpoBlurView, { ...props, tint: dark ? "dark" : "light", style, children: [
158
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native2.View, { style: [import_react_native2.StyleSheet.absoluteFill, { backgroundColor: surfaceColor, opacity: settings.blurTint }] }),
159
- tint,
160
- children
161
- ] });
162
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native2.View, { ...props, style: [{ backgroundColor: surfaceColor }, style], children: [
163
- tint,
164
- children
165
- ] });
139
+ var DEFAULT_ICONS = {
140
+ system: "monitor",
141
+ light: "white-balance-sunny",
142
+ dark: "weather-night"
166
143
  };
167
-
168
- // src/components/BottomNavigation.tsx
169
- var import_react7 = require("react");
170
- var import_react_native5 = require("react-native");
171
- var import_react_native_paper6 = require("react-native-paper");
172
-
173
- // src/navigation-bar.ts
174
- var navigationBar = (() => {
175
- try {
176
- return require("expo-navigation-bar");
177
- } catch {
178
- return null;
179
- }
180
- })();
181
- var setNavigationBarStyle = (dark) => {
182
- if (!navigationBar) return;
183
- navigationBar.NavigationBar.setStyle(dark ? "light" : "dark");
144
+ var AppearancePicker = ({ value, onChange, showLabels = true, icons }) => {
145
+ const resolvedIcons = { ...DEFAULT_ICONS, ...icons };
146
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_paper2.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 })) });
184
147
  };
185
148
 
186
- // src/ThemeProvider.tsx
149
+ // src/components/BlurView.tsx
187
150
  var import_react6 = require("react");
188
151
  var import_react_native4 = require("react-native");
189
152
  var import_react_native_paper5 = require("react-native-paper");
190
153
 
191
- // src/useComputedTheme.ts
154
+ // src/ThemeProvider.tsx
192
155
  var import_react5 = require("react");
193
156
  var import_react_native3 = require("react-native");
194
157
  var import_react_native_paper4 = require("react-native-paper");
195
158
 
159
+ // src/useComputedTheme.ts
160
+ var import_react4 = require("react");
161
+ var import_react_native2 = require("react-native");
162
+ var import_react_native_paper3 = require("react-native-paper");
163
+
196
164
  // src/utils/colorNames.ts
197
165
  var colorNames = {
198
166
  aliceblue: "#f0f8ff",
@@ -471,6 +439,27 @@ var getTonalColor = (color, lightness) => {
471
439
  return getHex(`rgb(${toInt(r2)}, ${toInt(g2)}, ${toInt(b2)})`) ?? color;
472
440
  };
473
441
 
442
+ // src/utils/isDarkColor.ts
443
+ var isDarkColor = (value) => {
444
+ const rgb = getRgb(value);
445
+ if (!rgb) return false;
446
+ const [r, g, b] = [rgb.r / 255, rgb.g / 255, rgb.b / 255];
447
+ const [rs, gs, bs] = [r, g, b].map((c) => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));
448
+ const luminance = 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
449
+ return luminance < 0.5;
450
+ };
451
+
452
+ // src/utils/getColorRoles.ts
453
+ var getColorRoles = (base, surface, containerAlpha = 0.15) => {
454
+ const container = getBlendedColor(base, surface, containerAlpha);
455
+ return {
456
+ color: base,
457
+ onColor: getTonalColor(base, isDarkColor(base) ? 0.95 : 0.08),
458
+ container,
459
+ onContainer: getTonalColor(base, isDarkColor(container) ? 0.92 : 0.12)
460
+ };
461
+ };
462
+
474
463
  // src/utils/getTriadicPalette.ts
475
464
  var HARMONY_OFFSETS = {
476
465
  analogous: [1 / 12, 2 / 12],
@@ -552,51 +541,71 @@ function hslToHex(h, s, l) {
552
541
  return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
553
542
  }
554
543
 
555
- // src/utils/isDarkColor.ts
556
- var isDarkColor = (value) => {
557
- const rgb = getRgb(value);
558
- if (!rgb) return false;
559
- const [r, g, b] = [rgb.r / 255, rgb.g / 255, rgb.b / 255];
560
- const [rs, gs, bs] = [r, g, b].map((c) => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));
561
- const luminance = 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
562
- return luminance < 0.5;
563
- };
564
-
565
544
  // src/useComputedTheme.ts
545
+ function normalizeExplicitColor(value) {
546
+ if (!getRgb(value)) throw new Error(`Invalid color format: ${value}`);
547
+ return getHex(value) ?? value;
548
+ }
549
+ var SEMANTIC_BASE_COLORS = {
550
+ success: "#2E7D32",
551
+ warning: "#A15C00",
552
+ danger: "#B00020"
553
+ };
566
554
  function useComputedTheme(appearance, color, harmony = "split-complementary") {
567
- const [theme, setTheme] = (0, import_react5.useState)(null);
568
- const computeTheme = (0, import_react5.useCallback)(() => {
555
+ const [theme, setTheme] = (0, import_react4.useState)(null);
556
+ const primaryInput = typeof color === "string" ? color : color.primary;
557
+ const secondaryInput = typeof color === "string" ? null : color.secondary;
558
+ const tertiaryInput = typeof color === "string" ? null : color.tertiary;
559
+ const computeTheme = (0, import_react4.useCallback)(() => {
569
560
  let resolved = appearance;
570
- if (resolved === "system") resolved = import_react_native3.Appearance.getColorScheme();
561
+ if (resolved === "system") resolved = import_react_native2.Appearance.getColorScheme();
571
562
  if (resolved === "no-preference" || !resolved) resolved = "light";
572
- const base = resolved === "dark" ? import_react_native_paper4.MD3DarkTheme : import_react_native_paper4.MD3LightTheme;
563
+ const base = resolved === "dark" ? import_react_native_paper3.MD3DarkTheme : import_react_native_paper3.MD3LightTheme;
564
+ const surface = base.colors.surface;
565
+ const successRoles = getColorRoles(SEMANTIC_BASE_COLORS.success, surface);
566
+ const warningRoles = getColorRoles(SEMANTIC_BASE_COLORS.warning, surface);
567
+ const dangerRoles = getColorRoles(SEMANTIC_BASE_COLORS.danger, surface);
573
568
  const _theme = {
574
569
  ...base,
575
570
  colors: {
576
571
  ...base.colors,
577
- elevation: { ...base.colors.elevation }
572
+ elevation: { ...base.colors.elevation },
573
+ success: successRoles.color,
574
+ onSuccess: successRoles.onColor,
575
+ successContainer: successRoles.container,
576
+ onSuccessContainer: successRoles.onContainer,
577
+ warning: warningRoles.color,
578
+ onWarning: warningRoles.onColor,
579
+ warningContainer: warningRoles.container,
580
+ onWarningContainer: warningRoles.onContainer,
581
+ danger: dangerRoles.color,
582
+ onDanger: dangerRoles.onColor,
583
+ dangerContainer: dangerRoles.container,
584
+ onDangerContainer: dangerRoles.onContainer
578
585
  }
579
586
  };
580
- const palette = getTriadicPalette(color, harmony);
581
- const surface = base.colors.surface;
582
- _theme.colors.primary = palette.primary;
583
- _theme.colors.onPrimary = getTonalColor(palette.primary, isDarkColor(palette.primary) ? 0.95 : 0.08);
584
- _theme.colors.primaryContainer = getBlendedColor(palette.primary, surface, 0.15);
585
- _theme.colors.onPrimaryContainer = getTonalColor(palette.primary, isDarkColor(_theme.colors.primaryContainer) ? 0.92 : 0.12);
586
- _theme.colors.secondary = palette.secondary;
587
- _theme.colors.onSecondary = getTonalColor(palette.secondary, isDarkColor(palette.secondary) ? 0.95 : 0.08);
588
- _theme.colors.secondaryContainer = getBlendedColor(palette.secondary, surface, 0.15);
589
- _theme.colors.onSecondaryContainer = getTonalColor(palette.secondary, isDarkColor(_theme.colors.secondaryContainer) ? 0.92 : 0.12);
590
- _theme.colors.tertiary = palette.tertiary;
591
- _theme.colors.onTertiary = getTonalColor(palette.tertiary, isDarkColor(palette.tertiary) ? 0.95 : 0.08);
592
- _theme.colors.tertiaryContainer = getBlendedColor(palette.tertiary, surface, 0.15);
593
- _theme.colors.onTertiaryContainer = getTonalColor(palette.tertiary, isDarkColor(_theme.colors.tertiaryContainer) ? 0.92 : 0.12);
594
- const blended = getBlendedColor(color, palette.secondary, 0.5);
587
+ const palette = secondaryInput !== null && tertiaryInput !== null ? { primary: normalizeExplicitColor(primaryInput), secondary: normalizeExplicitColor(secondaryInput), tertiary: normalizeExplicitColor(tertiaryInput) } : getTriadicPalette(primaryInput, harmony);
588
+ const primaryRoles = getColorRoles(palette.primary, surface);
589
+ _theme.colors.primary = primaryRoles.color;
590
+ _theme.colors.onPrimary = primaryRoles.onColor;
591
+ _theme.colors.primaryContainer = primaryRoles.container;
592
+ _theme.colors.onPrimaryContainer = primaryRoles.onContainer;
593
+ const secondaryRoles = getColorRoles(palette.secondary, surface);
594
+ _theme.colors.secondary = secondaryRoles.color;
595
+ _theme.colors.onSecondary = secondaryRoles.onColor;
596
+ _theme.colors.secondaryContainer = secondaryRoles.container;
597
+ _theme.colors.onSecondaryContainer = secondaryRoles.onContainer;
598
+ const tertiaryRoles = getColorRoles(palette.tertiary, surface);
599
+ _theme.colors.tertiary = tertiaryRoles.color;
600
+ _theme.colors.onTertiary = tertiaryRoles.onColor;
601
+ _theme.colors.tertiaryContainer = tertiaryRoles.container;
602
+ _theme.colors.onTertiaryContainer = tertiaryRoles.onContainer;
603
+ const blended = getBlendedColor(palette.primary, palette.secondary, 0.5);
595
604
  const tintSurface = (alpha) => getBlendedColor(blended, surface, alpha);
596
605
  _theme.colors.background = base.dark ? "#0F0F0F" : "#F0F0F0";
597
606
  _theme.colors.surface = surface;
598
607
  _theme.colors.surfaceVariant = tintSurface(0.2);
599
- _theme.colors.outline = getBlendedColor(color, base.colors.outline, 0.45);
608
+ _theme.colors.outline = getBlendedColor(palette.primary, base.colors.outline, 0.45);
600
609
  const grey = base.dark ? "#424242" : "#c2c2c2";
601
610
  const blendedGrey = getBlendedColor(blended, grey, 0.05);
602
611
  _theme.colors.elevation = {
@@ -608,63 +617,101 @@ function useComputedTheme(appearance, color, harmony = "split-complementary") {
608
617
  level5: getBlendedColor(blendedGrey, _theme.colors.surface, 0.7)
609
618
  };
610
619
  setTheme(_theme);
611
- }, [appearance, color, harmony]);
612
- (0, import_react5.useEffect)(() => {
620
+ }, [appearance, primaryInput, secondaryInput, tertiaryInput, harmony]);
621
+ (0, import_react4.useEffect)(() => {
613
622
  computeTheme();
614
623
  }, [computeTheme]);
615
- (0, import_react5.useEffect)(() => {
616
- const subscription = import_react_native3.Appearance.addChangeListener(computeTheme);
624
+ (0, import_react4.useEffect)(() => {
625
+ const subscription = import_react_native2.Appearance.addChangeListener(computeTheme);
617
626
  return subscription.remove;
618
627
  }, [computeTheme]);
619
628
  return theme;
620
629
  }
621
630
 
622
631
  // src/ThemeProvider.tsx
623
- var import_jsx_runtime4 = require("react/jsx-runtime");
624
- var NavBarContext = (0, import_react6.createContext)({});
625
- var useNavBarContext = () => (0, import_react6.useContext)(NavBarContext);
626
- function Provider({ initialValue, onChange, children, defaults, onNavBarChange, onReady, statusBarProps, style }) {
627
- const [settings, setSettings] = (0, import_react6.useState)(() => ({ ...defaultThemeSettings, ...initialValue }));
628
- const set = (0, import_react6.useCallback)((patch) => {
632
+ var import_jsx_runtime3 = require("react/jsx-runtime");
633
+ var NavBarContext = (0, import_react5.createContext)({});
634
+ var useNavBarContext = () => (0, import_react5.useContext)(NavBarContext);
635
+ var BlurModuleContext = (0, import_react5.createContext)(void 0);
636
+ var useBlurModule = () => (0, import_react5.useContext)(BlurModuleContext);
637
+ function Provider({ children, defaults, expoBlur, initialValue, navigationBar, onChange, onNavBarChange, onReady, statusBarProps, style }) {
638
+ const [settings, setSettings] = (0, import_react5.useState)(() => ({ ...defaultThemeSettings, ...initialValue }));
639
+ const set = (0, import_react5.useCallback)((patch) => {
629
640
  setSettings((prev) => ({ ...prev, ...patch }));
630
641
  }, []);
631
- const onChangeRef = (0, import_react6.useRef)(onChange);
642
+ const onChangeRef = (0, import_react5.useRef)(onChange);
632
643
  onChangeRef.current = onChange;
633
- const prevSettings = (0, import_react6.useRef)(settings);
634
- (0, import_react6.useEffect)(() => {
644
+ const prevSettings = (0, import_react5.useRef)(settings);
645
+ (0, import_react5.useEffect)(() => {
635
646
  if (prevSettings.current !== settings) {
636
647
  prevSettings.current = settings;
637
648
  onChangeRef.current?.(settings);
638
649
  }
639
650
  }, [settings]);
640
651
  const theme = useComputedTheme(settings.appearance, settings.color, settings.harmony);
641
- const called = (0, import_react6.useRef)(false);
642
- (0, import_react6.useEffect)(() => {
652
+ const called = (0, import_react5.useRef)(false);
653
+ (0, import_react5.useEffect)(() => {
643
654
  if (theme && !called.current) {
644
655
  called.current = true;
645
656
  onReady?.();
646
657
  }
647
658
  }, [theme, onReady]);
648
659
  if (!theme) return null;
649
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ThemeSettingsContext.Provider, { value: { settings, set }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native_paper5.Provider, { theme, children: [
650
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native4.StatusBar, { backgroundColor: theme.colors.background, barStyle: theme.dark ? "light-content" : "dark-content", ...statusBarProps }),
651
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PaperDefaultsContext.Provider, { value: defaults ?? {}, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NavBarContext.Provider, { value: { onNavBarChange }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native4.View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style], children }) }) })
660
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ThemeSettingsContext.Provider, { value: { settings, set }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native_paper4.Provider, { theme, children: [
661
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.StatusBar, { backgroundColor: theme.colors.background, barStyle: theme.dark ? "light-content" : "dark-content", ...statusBarProps }),
662
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PaperDefaultsContext.Provider, { value: defaults ?? {}, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NavBarContext.Provider, { value: { navigationBar, onNavBarChange }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BlurModuleContext.Provider, { value: expoBlur, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style], children }) }) }) })
652
663
  ] }) });
653
664
  }
654
- var styles = import_react_native4.StyleSheet.create({
665
+ var styles = import_react_native3.StyleSheet.create({
655
666
  flex: { flex: 1 }
656
667
  });
657
668
 
669
+ // src/components/BlurView.tsx
670
+ var import_jsx_runtime4 = require("react/jsx-runtime");
671
+ var ELEVATION_OPACITY = { 0: 0, 1: 0.05, 2: 0.08, 3: 0.11, 4: 0.12, 5: 0.14 };
672
+ var VARIANT_TINT_OPACITY = { light: 0.12, dark: 0.18 };
673
+ var BlurView = ({ blur = true, children, elevation, style, tintColor, tintOpacity, variant = "surface", ...props }) => {
674
+ const { dark, colors } = (0, import_react_native_paper5.useTheme)();
675
+ const { settings } = (0, import_react6.useContext)(ThemeSettingsContext);
676
+ const expoBlur = useBlurModule();
677
+ const surfaceColor = variant === "surfaceVariant" ? colors.surfaceVariant : colors.surface;
678
+ const variantColor = variant === "primary" ? colors.primary : variant === "secondary" ? colors.secondary : variant === "tertiary" ? colors.tertiary : variant === "error" ? colors.error : void 0;
679
+ const resolvedTintColor = tintColor ?? variantColor ?? (elevation !== void 0 ? colors.primary : void 0);
680
+ 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);
681
+ const tint = resolvedTintColor && resolvedTintOpacity > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native4.View, { style: [import_react_native4.StyleSheet.absoluteFill, { backgroundColor: resolvedTintColor, opacity: resolvedTintOpacity }] }) : null;
682
+ if (blur && expoBlur)
683
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(expoBlur.BlurView, { ...props, tint: dark ? "dark" : "light", style, children: [
684
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native4.View, { style: [import_react_native4.StyleSheet.absoluteFill, { backgroundColor: surfaceColor, opacity: settings.blurTint }] }),
685
+ tint,
686
+ children
687
+ ] });
688
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native4.View, { ...props, style: [{ backgroundColor: surfaceColor }, style], children: [
689
+ tint,
690
+ children
691
+ ] });
692
+ };
693
+
694
+ // src/components/BottomNavigation.tsx
695
+ var import_react7 = require("react");
696
+ var import_react_native5 = require("react-native");
697
+ var import_react_native_paper6 = require("react-native-paper");
698
+
699
+ // src/navigation-bar.ts
700
+ var setNavigationBarStyle = (navigationBar, dark) => {
701
+ if (!navigationBar) return;
702
+ navigationBar.NavigationBar.setStyle(dark ? "light" : "dark");
703
+ };
704
+
658
705
  // src/components/BottomNavigation.tsx
659
706
  var import_jsx_runtime5 = require("react/jsx-runtime");
660
707
  function useNavigationBarSync() {
661
708
  const theme = (0, import_react_native_paper6.useTheme)();
662
- const { onNavBarChange } = useNavBarContext();
709
+ const { navigationBar, onNavBarChange } = useNavBarContext();
663
710
  (0, import_react7.useEffect)(() => {
664
711
  if (import_react_native5.Platform.OS !== "android") return;
665
712
  if (onNavBarChange) onNavBarChange(theme.colors.surface, theme.dark);
666
- else if (navigationBar) setNavigationBarStyle(theme.dark);
667
- }, [theme, onNavBarChange]);
713
+ else if (navigationBar) setNavigationBarStyle(navigationBar, theme.dark);
714
+ }, [theme, onNavBarChange, navigationBar]);
668
715
  }
669
716
  function BottomNavigationComponent(props) {
670
717
  const defaults = usePaperDefaults();
@@ -714,6 +761,15 @@ function useSwatchSize(fallback) {
714
761
  return { onLayout, size };
715
762
  }
716
763
 
764
+ // src/utils/getSwatchContrast.ts
765
+ var RING_WIDTH = 1;
766
+ var SELECTED_RING_WIDTH = 3;
767
+ var getContrastColor = (color) => isDarkColor(color) ? "#ffffff" : "#000000";
768
+ var getSwatchRing = (color, selected, outlineColor) => ({
769
+ borderColor: selected ? getContrastColor(color) : outlineColor,
770
+ borderWidth: selected ? SELECTED_RING_WIDTH : RING_WIDTH
771
+ });
772
+
717
773
  // src/components/Dialog.tsx
718
774
  var import_react9 = __toESM(require("react"));
719
775
  var import_react_native6 = require("react-native");
@@ -805,10 +861,11 @@ var defaultColors = [
805
861
  ];
806
862
  var ColorPicker = ({ value, onChange, colors = defaultColors, blur: blurProp }) => {
807
863
  const blur = useBlur(blurProp);
864
+ const { colors: themeColors } = (0, import_react_native_paper10.useTheme)();
808
865
  const [open, setOpen] = (0, import_react10.useState)(false);
809
866
  const { onLayout, size } = useSwatchSize(SIZE);
810
867
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
811
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper10.TouchableRipple, { onPress: () => setOpen(true), style: [styles3.trigger, { backgroundColor: value }], borderless: true, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper10.Icon, { source: "palette", size: 20, color: "white" }) }),
868
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper10.TouchableRipple, { onPress: () => setOpen(true), style: [styles3.trigger, { backgroundColor: value }, getSwatchRing(value, false, themeColors.outlineVariant)], borderless: true, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper10.Icon, { source: "palette", size: 20, color: getContrastColor(value) }) }),
812
869
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Dialog, { blur, visible: open, onDismiss: () => setOpen(false), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Dialog.Content, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native7.View, { style: styles3.swatches, onLayout, children: colors.map(({ value: hex }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
813
870
  import_react_native7.TouchableOpacity,
814
871
  {
@@ -816,15 +873,14 @@ var ColorPicker = ({ value, onChange, colors = defaultColors, blur: blurProp })
816
873
  onChange(hex);
817
874
  setOpen(false);
818
875
  },
819
- style: [styles3.swatch, { backgroundColor: hex, borderRadius: size / 2, height: size, width: size }, value === hex && styles3.selected],
820
- children: value === hex && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper10.Icon, { source: "check", size: 20, color: "white" })
876
+ style: [styles3.swatch, { backgroundColor: hex, borderRadius: size / 2, height: size, width: size }, getSwatchRing(hex, value === hex, themeColors.outlineVariant)],
877
+ children: value === hex && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper10.Icon, { source: "check", size: 20, color: getContrastColor(hex) })
821
878
  },
822
879
  hex
823
880
  )) }) }) })
824
881
  ] });
825
882
  };
826
883
  var styles3 = import_react_native7.StyleSheet.create({
827
- selected: { borderColor: "white", borderWidth: 3 },
828
884
  swatch: { alignItems: "center", justifyContent: "center" },
829
885
  swatches: { flexDirection: "row", flexWrap: "wrap", gap: SWATCH_GRID_GAP, paddingTop: 12 },
830
886
  trigger: { alignItems: "center", alignSelf: "flex-start", borderRadius: SIZE / 2, height: SIZE, justifyContent: "center", width: SIZE }
@@ -926,12 +982,13 @@ var buildWedges = (weights) => {
926
982
  var Pie = ({ palette, weights = defaultWeights, size = SIZE2 }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native9.View, { style: [styles5.pie, { borderRadius: size / 2, height: size, width: size }], children: buildWedges(weights).map(({ key, rotate, share }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native9.View, { style: [styles5.rotator, { transform: [{ rotate: `${rotate}deg` }] }], children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native9.View, { style: styles5.halfMask, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native9.View, { style: [styles5.innerRotator, { transform: [{ rotate: `${share - 180}deg` }] }], children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native9.View, { style: [styles5.wedgeFill, { backgroundColor: palette[key] }] }) }) }) }, key)) });
927
983
  var PalettePicker = ({ value, onChange, harmony = "split-complementary", weights, colors = defaultColors, blur: blurProp }) => {
928
984
  const blur = useBlur(blurProp);
985
+ const { colors: themeColors } = (0, import_react_native_paper15.useTheme)();
929
986
  const [open, setOpen] = (0, import_react12.useState)(false);
930
987
  const { onLayout, size } = useSwatchSize(SIZE2);
931
988
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
932
989
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper15.TouchableRipple, { onPress: () => setOpen(true), style: styles5.trigger, borderless: true, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native9.View, { style: styles5.triggerContent, children: [
933
990
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Pie, { palette: getTriadicPalette(value, harmony), weights }),
934
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native9.View, { pointerEvents: "none", style: styles5.triggerIcon, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper15.Icon, { source: "palette", size: 20, color: "white" }) })
991
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native9.View, { pointerEvents: "none", style: [styles5.triggerIcon, { borderRadius: SIZE2 / 2 }, getSwatchRing(value, false, themeColors.outlineVariant)], children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper15.Icon, { source: "palette", size: 20, color: getContrastColor(value) }) })
935
992
  ] }) }),
936
993
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Dialog, { blur, visible: open, onDismiss: () => setOpen(false), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Dialog.Content, { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native9.View, { style: styles5.swatches, onLayout, children: colors.map(({ value: hex }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
937
994
  import_react_native9.TouchableOpacity,
@@ -943,7 +1000,7 @@ var PalettePicker = ({ value, onChange, harmony = "split-complementary", weights
943
1000
  style: [styles5.swatch, { height: size, width: size }],
944
1001
  children: [
945
1002
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Pie, { palette: getTriadicPalette(hex, harmony), weights, size }),
946
- value === hex && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native9.View, { pointerEvents: "none", style: [styles5.selectedRing, { borderRadius: size / 2 }], children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper15.Icon, { source: "check", size: 20, color: "white" }) })
1003
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native9.View, { pointerEvents: "none", style: [styles5.ring, { borderRadius: size / 2 }, getSwatchRing(hex, value === hex, themeColors.outlineVariant)], children: value === hex && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper15.Icon, { source: "check", size: 20, color: getContrastColor(hex) }) })
947
1004
  ]
948
1005
  },
949
1006
  hex
@@ -955,7 +1012,7 @@ var styles5 = import_react_native9.StyleSheet.create({
955
1012
  innerRotator: { height: "100%", left: "-100%", overflow: "hidden", position: "absolute", top: 0, width: "200%" },
956
1013
  pie: { overflow: "hidden" },
957
1014
  rotator: { height: "100%", left: 0, overflow: "hidden", position: "absolute", top: 0, width: "100%" },
958
- selectedRing: { alignItems: "center", borderColor: "white", borderWidth: 3, bottom: 0, justifyContent: "center", left: 0, position: "absolute", right: 0, top: 0 },
1015
+ ring: { alignItems: "center", bottom: 0, justifyContent: "center", left: 0, position: "absolute", right: 0, top: 0 },
959
1016
  swatch: { alignItems: "center", justifyContent: "center" },
960
1017
  swatches: { flexDirection: "row", flexWrap: "wrap", gap: SWATCH_GRID_GAP, paddingTop: 12 },
961
1018
  trigger: { alignItems: "center", alignSelf: "flex-start", borderRadius: SIZE2 / 2, height: SIZE2, justifyContent: "center", width: SIZE2 },
@@ -1010,10 +1067,90 @@ var selectThemeBlur = (state) => state.blur;
1010
1067
  var selectThemeColor = (state) => state.color;
1011
1068
  var selectThemeHarmony = (state) => state.harmony;
1012
1069
 
1070
+ // src/useTheme.ts
1071
+ var import_react_native_paper17 = require("react-native-paper");
1072
+ var useAutoPaperTheme = () => (0, import_react_native_paper17.useTheme)();
1073
+
1013
1074
  // src/useThemeSettings.ts
1014
1075
  var import_react14 = require("react");
1015
1076
  var useThemeSettings = () => (0, import_react14.useContext)(ThemeSettingsContext);
1016
1077
 
1078
+ // src/utils/getThirdColor.ts
1079
+ function rgbToHsl(r, g, b) {
1080
+ r /= 255;
1081
+ g /= 255;
1082
+ b /= 255;
1083
+ const max = Math.max(r, g, b);
1084
+ const min = Math.min(r, g, b);
1085
+ const delta = max - min;
1086
+ let h = 0;
1087
+ if (delta !== 0) {
1088
+ if (max === r) h = (g - b) / delta % 6;
1089
+ else if (max === g) h = (b - r) / delta + 2;
1090
+ else h = (r - g) / delta + 4;
1091
+ h = (h * 60 + 360) % 360;
1092
+ }
1093
+ const l = (max + min) / 2;
1094
+ const s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
1095
+ return { h, s, l };
1096
+ }
1097
+ function hslToHex2(h, s, l) {
1098
+ const c = (1 - Math.abs(2 * l - 1)) * s;
1099
+ const x = c * (1 - Math.abs(h / 60 % 2 - 1));
1100
+ const m = l - c / 2;
1101
+ let r = 0;
1102
+ let g = 0;
1103
+ let b = 0;
1104
+ if (h < 60) {
1105
+ r = c;
1106
+ g = x;
1107
+ b = 0;
1108
+ } else if (h < 120) {
1109
+ r = x;
1110
+ g = c;
1111
+ b = 0;
1112
+ } else if (h < 180) {
1113
+ r = 0;
1114
+ g = c;
1115
+ b = x;
1116
+ } else if (h < 240) {
1117
+ r = 0;
1118
+ g = x;
1119
+ b = c;
1120
+ } else if (h < 300) {
1121
+ r = x;
1122
+ g = 0;
1123
+ b = c;
1124
+ } else {
1125
+ r = c;
1126
+ g = 0;
1127
+ b = x;
1128
+ }
1129
+ const toInt = (value) => Math.round((value + m) * 255);
1130
+ return getHex(`rgb(${toInt(r)}, ${toInt(g)}, ${toInt(b)})`) ?? "#000000";
1131
+ }
1132
+ var toRad = (deg) => deg * Math.PI / 180;
1133
+ var toDeg = (rad) => rad * 180 / Math.PI;
1134
+ function thirdHue(hA, hB) {
1135
+ const x = Math.cos(toRad(hA)) + Math.cos(toRad(hB));
1136
+ const y = Math.sin(toRad(hA)) + Math.sin(toRad(hB));
1137
+ if (Math.abs(x) < 1e-9 && Math.abs(y) < 1e-9) return (hA + 90) % 360;
1138
+ const meanHue = (toDeg(Math.atan2(y, x)) + 360) % 360;
1139
+ return (meanHue + 180) % 360;
1140
+ }
1141
+ function getThirdColor(colorA, colorB) {
1142
+ const rgbA = getRgb(colorA);
1143
+ const rgbB = getRgb(colorB);
1144
+ if (!rgbA) throw new Error(`Invalid color format: ${colorA}`);
1145
+ if (!rgbB) throw new Error(`Invalid color format: ${colorB}`);
1146
+ const hslA = rgbToHsl(rgbA.r, rgbA.g, rgbA.b);
1147
+ const hslB = rgbToHsl(rgbB.r, rgbB.g, rgbB.b);
1148
+ const h = thirdHue(hslA.h, hslB.h);
1149
+ const s = (hslA.s + hslB.s) / 2;
1150
+ const l = (hslA.l + hslB.l) / 2;
1151
+ return hslToHex2(h, s, l);
1152
+ }
1153
+
1017
1154
  // src/utils/getTintTextColor.ts
1018
1155
  var getTintTextColor = (tintColor, backdropColor, tintOpacity) => {
1019
1156
  const blended = getBlendedColor(tintColor, backdropColor, tintOpacity);
@@ -1035,14 +1172,18 @@ var getTintTextColor = (tintColor, backdropColor, tintOpacity) => {
1035
1172
  Menu,
1036
1173
  PalettePicker,
1037
1174
  Provider,
1175
+ SEMANTIC_BASE_COLORS,
1038
1176
  TextInput,
1039
1177
  ThemeSettingsContext,
1040
1178
  createThemeReducer,
1041
1179
  defaultColors,
1042
1180
  defaultThemeSettings,
1043
1181
  getBlendedColor,
1182
+ getColorRoles,
1183
+ getContrastColor,
1044
1184
  getHex,
1045
1185
  getRgb,
1186
+ getThirdColor,
1046
1187
  getTintTextColor,
1047
1188
  getTonalColor,
1048
1189
  getTriadicPalette,
@@ -1053,8 +1194,11 @@ var getTintTextColor = (tintColor, backdropColor, tintOpacity) => {
1053
1194
  selectThemeHarmony,
1054
1195
  themeActions,
1055
1196
  themeReducer,
1197
+ useAutoPaperTheme,
1056
1198
  useBlur,
1199
+ useBlurModule,
1057
1200
  useComputedTheme,
1201
+ useNavBarContext,
1058
1202
  usePaperDefaults,
1059
1203
  useThemeSettings
1060
1204
  });