@rific/auto-paper 0.13.4 → 0.14.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
@@ -51,15 +51,19 @@ __export(index_exports, {
51
51
  SEMANTIC_BASE_COLORS: () => SEMANTIC_BASE_COLORS,
52
52
  TextInput: () => TextInput,
53
53
  ThemeSettingsContext: () => ThemeSettingsContext,
54
+ createChalkboardTone: () => createChalkboardTone,
54
55
  createThemeReducer: () => createThemeReducer,
55
56
  defaultColors: () => defaultColors,
56
57
  defaultThemeSettings: () => defaultThemeSettings,
57
58
  getBlendedColor: () => getBlendedColor,
59
+ getChalkboardColor: () => getChalkboardColor,
58
60
  getColorRoles: () => getColorRoles,
59
61
  getContrastColor: () => getContrastColor,
60
62
  getContrastRatio: () => getContrastRatio,
61
63
  getHex: () => getHex,
62
64
  getLuminance: () => getLuminance,
65
+ getOklch: () => getOklch,
66
+ getOklchHex: () => getOklchHex,
63
67
  getRgb: () => getRgb,
64
68
  getThirdColor: () => getThirdColor,
65
69
  getTintTextColor: () => getTintTextColor,
@@ -79,6 +83,7 @@ __export(index_exports, {
79
83
  useComputedTheme: () => useComputedTheme,
80
84
  useMaskedViewModule: () => useMaskedViewModule,
81
85
  useNavBarContext: () => useNavBarContext,
86
+ usePaletteTone: () => usePaletteTone,
82
87
  usePaperDefaults: () => usePaperDefaults,
83
88
  useReanimatedModule: () => useReanimatedModule,
84
89
  useThemeBridgeProps: () => useThemeBridgeProps,
@@ -332,13 +337,13 @@ var getRgb = (value) => {
332
337
  var getHex = (value) => {
333
338
  const rgb = getRgb(value);
334
339
  if (!rgb) return null;
335
- const toHex = (n) => {
340
+ const toHex2 = (n) => {
336
341
  const hex = Math.round(n).toString(16);
337
342
  return hex.length === 1 ? "0" + hex : hex;
338
343
  };
339
- const hexString = `#${toHex(rgb.r)}${toHex(rgb.g)}${toHex(rgb.b)}`;
344
+ const hexString = `#${toHex2(rgb.r)}${toHex2(rgb.g)}${toHex2(rgb.b)}`;
340
345
  if (rgb.a !== void 0) {
341
- return `${hexString}${toHex(rgb.a * 255)}`;
346
+ return `${hexString}${toHex2(rgb.a * 255)}`;
342
347
  }
343
348
  return hexString;
344
349
  };
@@ -520,11 +525,11 @@ function hslToHex(h, s, l) {
520
525
  g = 0;
521
526
  b = x;
522
527
  }
523
- const toHex = (value) => {
528
+ const toHex2 = (value) => {
524
529
  const hex = Math.round((value + m) * 255).toString(16);
525
530
  return hex.length === 1 ? `0${hex}` : hex;
526
531
  };
527
- return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
532
+ return `#${toHex2(r)}${toHex2(g)}${toHex2(b)}`;
528
533
  }
529
534
 
530
535
  // src/useComputedTheme.ts
@@ -537,7 +542,7 @@ var SEMANTIC_BASE_COLORS = {
537
542
  warning: "#A15C00",
538
543
  danger: "#B00020"
539
544
  };
540
- function useComputedTheme(appearance, color, harmony = "split-complementary") {
545
+ function useComputedTheme(appearance, color, harmony = "split-complementary", paletteTone) {
541
546
  const [theme, setTheme] = (0, import_react3.useState)(null);
542
547
  const primaryInput = typeof color === "string" ? color : color.primary;
543
548
  const secondaryInput = typeof color === "string" ? null : color.secondary;
@@ -570,7 +575,8 @@ function useComputedTheme(appearance, color, harmony = "split-complementary") {
570
575
  onDangerContainer: dangerRoles.onContainer
571
576
  }
572
577
  };
573
- const palette = secondaryInput !== null && tertiaryInput !== null ? { primary: normalizeExplicitColor(primaryInput), secondary: normalizeExplicitColor(secondaryInput), tertiary: normalizeExplicitColor(tertiaryInput) } : getTriadicPalette(primaryInput, harmony);
578
+ const untoned = secondaryInput !== null && tertiaryInput !== null ? { primary: normalizeExplicitColor(primaryInput), secondary: normalizeExplicitColor(secondaryInput), tertiary: normalizeExplicitColor(tertiaryInput) } : getTriadicPalette(primaryInput, harmony);
579
+ const palette = paletteTone ? { primary: paletteTone(untoned.primary, base.dark), secondary: paletteTone(untoned.secondary, base.dark), tertiary: paletteTone(untoned.tertiary, base.dark) } : untoned;
574
580
  const primaryRoles = getColorRoles(palette.primary, surface);
575
581
  _theme.colors.primary = primaryRoles.color;
576
582
  _theme.colors.onPrimary = primaryRoles.onColor;
@@ -603,7 +609,7 @@ function useComputedTheme(appearance, color, harmony = "split-complementary") {
603
609
  level5: getBlendedColor(blendedGrey, _theme.colors.surface, 0.7)
604
610
  };
605
611
  setTheme(_theme);
606
- }, [appearance, primaryInput, secondaryInput, tertiaryInput, harmony]);
612
+ }, [appearance, primaryInput, secondaryInput, tertiaryInput, harmony, paletteTone]);
607
613
  (0, import_react3.useEffect)(() => {
608
614
  computeTheme();
609
615
  }, [computeTheme]);
@@ -624,15 +630,17 @@ var ReanimatedModuleContext = (0, import_react4.createContext)(void 0);
624
630
  var useReanimatedModule = () => (0, import_react4.useContext)(ReanimatedModuleContext);
625
631
  var MaskedViewModuleContext = (0, import_react4.createContext)(void 0);
626
632
  var useMaskedViewModule = () => (0, import_react4.useContext)(MaskedViewModuleContext);
633
+ var PaletteToneContext = (0, import_react4.createContext)(void 0);
634
+ var usePaletteTone = () => (0, import_react4.useContext)(PaletteToneContext);
627
635
  var StatusBarEnabledContext = (0, import_react4.createContext)(true);
628
636
  var useStatusBarEnabled = () => (0, import_react4.useContext)(StatusBarEnabledContext);
629
- function Provider({ children, defaults, expoBlur, fontFamily, initialValue, maskedView, navigationBar, onChange, onNavBarChange, onReady, reanimated, statusBar, statusBarProps, style }) {
630
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeSettingsProvider, { initialValue, onChange, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeProviderBody, { defaults, expoBlur, fontFamily, maskedView, navigationBar, onNavBarChange, onReady, reanimated, statusBar, statusBarProps, style, children }) });
637
+ function Provider({ children, defaults, expoBlur, fontFamily, initialValue, maskedView, navigationBar, onChange, onNavBarChange, onReady, paletteTone, reanimated, statusBar, statusBarProps, style }) {
638
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeSettingsProvider, { initialValue, onChange, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeProviderBody, { defaults, expoBlur, fontFamily, maskedView, navigationBar, onNavBarChange, onReady, paletteTone, reanimated, statusBar, statusBarProps, style, children }) });
631
639
  }
632
640
  var ThemeSettingsProvider = themeSettingsProvider;
633
- function ThemeProviderBody({ children, defaults, expoBlur, fontFamily, maskedView, navigationBar, onNavBarChange, onReady, reanimated, statusBar = true, statusBarProps, style }) {
641
+ function ThemeProviderBody({ children, defaults, expoBlur, fontFamily, maskedView, navigationBar, onNavBarChange, onReady, paletteTone, reanimated, statusBar = true, statusBarProps, style }) {
634
642
  const { settings } = useThemeSettingsInternal();
635
- const computedTheme = useComputedTheme(settings.appearance, settings.color, settings.harmony);
643
+ const computedTheme = useComputedTheme(settings.appearance, settings.color, settings.harmony, paletteTone);
636
644
  const theme = (0, import_react4.useMemo)(() => {
637
645
  if (!computedTheme) return null;
638
646
  if (!fontFamily) return computedTheme;
@@ -648,7 +656,7 @@ function ThemeProviderBody({ children, defaults, expoBlur, fontFamily, maskedVie
648
656
  if (!theme) return null;
649
657
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native_paper2.Provider, { theme, children: [
650
658
  statusBar && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.StatusBar, { barStyle: theme.dark ? "light-content" : "dark-content", ...statusBarProps }),
651
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBarEnabledContext.Provider, { value: statusBar, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PaperDefaultsContext.Provider, { value: defaults ?? {}, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NavBarContext.Provider, { value: { navigationBar, onNavBarChange }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BlurModuleContext.Provider, { value: expoBlur, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReanimatedModuleContext.Provider, { value: reanimated, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MaskedViewModuleContext.Provider, { value: maskedView, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native_paper2.Portal.Host, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style], children }) }) }) }) }) }) }) })
659
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBarEnabledContext.Provider, { value: statusBar, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PaperDefaultsContext.Provider, { value: defaults ?? {}, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NavBarContext.Provider, { value: { navigationBar, onNavBarChange }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BlurModuleContext.Provider, { value: expoBlur, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReanimatedModuleContext.Provider, { value: reanimated, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MaskedViewModuleContext.Provider, { value: maskedView, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PaletteToneContext.Provider, { value: paletteTone, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native_paper2.Portal.Host, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style], children }) }) }) }) }) }) }) }) })
652
660
  ] });
653
661
  }
654
662
  var styles = import_react_native2.StyleSheet.create({
@@ -701,6 +709,10 @@ var AutoAppearancePicker = (props) => {
701
709
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AppearancePicker, { ...props, value: settings.appearance, onChange: (appearance) => set({ appearance }) });
702
710
  };
703
711
 
712
+ // src/components/AutoPalettePicker.tsx
713
+ var import_react10 = require("react");
714
+ var import_react_native_paper10 = require("react-native-paper");
715
+
704
716
  // src/utils/resolveSeedColor.ts
705
717
  var resolveSeedColor = (color) => typeof color === "string" ? color : color.primary;
706
718
 
@@ -951,19 +963,25 @@ var buildWedges = (weights) => {
951
963
  ];
952
964
  };
953
965
  var Pie = ({ palette, weights = defaultWeights, size = SIZE2 }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native7.View, { style: [styles4.pie, { borderRadius: size / 2, height: size, width: size }], children: buildWedges(weights).map(({ key, rotate, share }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native7.View, { style: [styles4.rotator, { transform: [{ rotate: `${rotate}deg` }] }], children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native7.View, { style: styles4.halfMask, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native7.View, { style: [styles4.innerRotator, { transform: [{ rotate: `${share - 180}deg` }] }], children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native7.View, { style: [styles4.wedgeFill, { backgroundColor: palette[key] }] }) }) }) }, key)) });
954
- var PalettePicker = ({ value, onChange, harmony = "split-complementary", onHarmonyChange, weights, colors = defaultColors, blur: blurProp }) => {
966
+ var PalettePicker = ({ value, onChange, harmony = "split-complementary", onHarmonyChange, weights, colors = defaultColors, blur: blurProp, previewColor }) => {
955
967
  const blur = useBlur(blurProp);
956
968
  const { colors: themeColors } = (0, import_react_native_paper9.useTheme)();
957
969
  const [open, setOpen] = (0, import_react9.useState)(false);
958
970
  const { onLayout, size } = useSwatchSize(SIZE2);
971
+ const shade = (0, import_react9.useMemo)(
972
+ () => (palette) => previewColor ? { primary: previewColor(palette.primary), secondary: previewColor(palette.secondary), tertiary: previewColor(palette.tertiary) } : palette,
973
+ [previewColor]
974
+ );
975
+ const triggerPalette = shade(getTriadicPalette(value, harmony));
976
+ const swatchPalettes = (0, import_react9.useMemo)(() => colors.map(({ value: hex }) => shade(getTriadicPalette(hex, harmony))), [colors, harmony, shade]);
959
977
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
960
978
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper9.TouchableRipple, { onPress: () => setOpen(true), style: styles4.trigger, borderless: true, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native7.View, { style: styles4.triggerContent, children: [
961
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Pie, { palette: getTriadicPalette(value, harmony), weights }),
962
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native7.View, { pointerEvents: "none", style: [styles4.triggerIcon, { borderRadius: SIZE2 / 2 }, getSwatchRing(value, false, themeColors.outlineVariant)], children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper9.Icon, { source: "palette", size: 20, color: getContrastColor(value) }) })
979
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Pie, { palette: triggerPalette, weights }),
980
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native7.View, { pointerEvents: "none", style: [styles4.triggerIcon, { borderRadius: SIZE2 / 2 }, getSwatchRing(triggerPalette.primary, false, themeColors.outlineVariant)], children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper9.Icon, { source: "palette", size: 20, color: getContrastColor(triggerPalette.primary) }) })
963
981
  ] }) }),
964
982
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Dialog, { blur, visible: open, onDismiss: () => setOpen(false), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Dialog.Content, { children: [
965
983
  onHarmonyChange && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native7.View, { style: styles4.harmonyRow, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(HarmonyPicker, { value: harmony, onChange: onHarmonyChange, showLabels: false }) }),
966
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native7.View, { style: styles4.swatches, onLayout, children: colors.map(({ value: hex }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
984
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native7.View, { style: styles4.swatches, onLayout, children: colors.map(({ value: hex }, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
967
985
  import_react_native7.TouchableOpacity,
968
986
  {
969
987
  onPress: () => {
@@ -972,8 +990,8 @@ var PalettePicker = ({ value, onChange, harmony = "split-complementary", onHarmo
972
990
  },
973
991
  style: [styles4.swatch, { height: size, width: size }],
974
992
  children: [
975
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Pie, { palette: getTriadicPalette(hex, harmony), weights, size }),
976
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native7.View, { pointerEvents: "none", style: [styles4.ring, { borderRadius: size / 2 }, getSwatchRing(hex, value === hex, themeColors.outlineVariant)], children: value === hex && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper9.Icon, { source: "check", size: 20, color: getContrastColor(hex) }) })
993
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Pie, { palette: swatchPalettes[index], weights, size }),
994
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native7.View, { pointerEvents: "none", style: [styles4.ring, { borderRadius: size / 2 }, getSwatchRing(swatchPalettes[index].primary, value === hex, themeColors.outlineVariant)], children: value === hex && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper9.Icon, { source: "check", size: 20, color: getContrastColor(swatchPalettes[index].primary) }) })
977
995
  ]
978
996
  },
979
997
  hex
@@ -1000,13 +1018,16 @@ var styles4 = import_react_native7.StyleSheet.create({
1000
1018
  var import_jsx_runtime10 = require("react/jsx-runtime");
1001
1019
  var AutoPalettePicker = (props) => {
1002
1020
  const { settings, set } = useThemeSettings();
1003
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PalettePicker, { ...props, value: resolveSeedColor(settings.color), onChange: (color) => set({ color }), harmony: settings.harmony, onHarmonyChange: (harmony) => set({ harmony }) });
1021
+ const tone = usePaletteTone();
1022
+ const { dark } = (0, import_react_native_paper10.useTheme)();
1023
+ const toned = (0, import_react10.useCallback)((color) => tone(color, dark), [tone, dark]);
1024
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PalettePicker, { ...props, value: resolveSeedColor(settings.color), onChange: (color) => set({ color }), harmony: settings.harmony, onHarmonyChange: (harmony) => set({ harmony }), previewColor: tone ? toned : void 0 });
1004
1025
  };
1005
1026
 
1006
1027
  // src/components/BottomNavigation.tsx
1007
- var import_react10 = require("react");
1028
+ var import_react11 = require("react");
1008
1029
  var import_react_native8 = require("react-native");
1009
- var import_react_native_paper10 = require("react-native-paper");
1030
+ var import_react_native_paper11 = require("react-native-paper");
1010
1031
 
1011
1032
  // src/navigation-bar.ts
1012
1033
  var setNavigationBarStyle = (navigationBar, dark) => {
@@ -1017,9 +1038,9 @@ var setNavigationBarStyle = (navigationBar, dark) => {
1017
1038
  // src/components/BottomNavigation.tsx
1018
1039
  var import_jsx_runtime11 = require("react/jsx-runtime");
1019
1040
  function useNavigationBarSync() {
1020
- const theme = (0, import_react_native_paper10.useTheme)();
1041
+ const theme = (0, import_react_native_paper11.useTheme)();
1021
1042
  const { navigationBar, onNavBarChange } = useNavBarContext();
1022
- (0, import_react10.useEffect)(() => {
1043
+ (0, import_react11.useEffect)(() => {
1023
1044
  if (import_react_native8.Platform.OS !== "android") return;
1024
1045
  if (onNavBarChange) onNavBarChange(theme.colors.surface, theme.dark);
1025
1046
  else if (navigationBar) setNavigationBarStyle(navigationBar, theme.dark);
@@ -1028,53 +1049,53 @@ function useNavigationBarSync() {
1028
1049
  function BottomNavigationComponent(props) {
1029
1050
  const defaults = usePaperDefaults();
1030
1051
  useNavigationBarSync();
1031
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native_paper10.BottomNavigation, { ...defaults.BottomNavigation, ...props });
1052
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native_paper11.BottomNavigation, { ...defaults.BottomNavigation, ...props });
1032
1053
  }
1033
1054
  function Bar(props) {
1034
1055
  useNavigationBarSync();
1035
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native_paper10.BottomNavigation.Bar, { ...props });
1056
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native_paper11.BottomNavigation.Bar, { ...props });
1036
1057
  }
1037
1058
  BottomNavigationComponent.Bar = Bar;
1038
- BottomNavigationComponent.SceneMap = import_react_native_paper10.BottomNavigation?.SceneMap;
1059
+ BottomNavigationComponent.SceneMap = import_react_native_paper11.BottomNavigation?.SceneMap;
1039
1060
  var BottomNavigation = BottomNavigationComponent;
1040
1061
 
1041
1062
  // src/components/Button.tsx
1042
- var import_react_native_paper11 = require("react-native-paper");
1063
+ var import_react_native_paper12 = require("react-native-paper");
1043
1064
  var import_jsx_runtime12 = require("react/jsx-runtime");
1044
1065
  function Button(props) {
1045
1066
  const defaults = usePaperDefaults();
1046
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native_paper11.Button, { ...defaults.Button, ...props });
1067
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native_paper12.Button, { ...defaults.Button, ...props });
1047
1068
  }
1048
1069
 
1049
1070
  // src/components/Chip.tsx
1050
- var import_react_native_paper12 = require("react-native-paper");
1071
+ var import_react_native_paper13 = require("react-native-paper");
1051
1072
  var import_jsx_runtime13 = require("react/jsx-runtime");
1052
1073
  function Chip({ variant, style, selectedColor, ...props }) {
1053
1074
  const defaults = usePaperDefaults();
1054
- const { colors } = (0, import_react_native_paper12.useTheme)();
1075
+ const { colors } = (0, import_react_native_paper13.useTheme)();
1055
1076
  const variantStyle = variant === "primary" ? { backgroundColor: colors.primaryContainer } : variant === "secondary" ? { backgroundColor: colors.secondaryContainer } : variant === "tertiary" ? { backgroundColor: colors.tertiaryContainer } : variant === "surface" ? { backgroundColor: colors.surface } : void 0;
1056
1077
  const variantSelectedColor = variant === "primary" ? colors.onPrimaryContainer : variant === "secondary" ? colors.onSecondaryContainer : variant === "tertiary" ? colors.onTertiaryContainer : variant === "surface" ? colors.onSurface : void 0;
1057
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native_paper12.Chip, { ...defaults.Chip, selectedColor: selectedColor ?? variantSelectedColor, ...props, style: [variantStyle, style] });
1078
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native_paper13.Chip, { ...defaults.Chip, selectedColor: selectedColor ?? variantSelectedColor, ...props, style: [variantStyle, style] });
1058
1079
  }
1059
1080
 
1060
1081
  // src/components/FAB.tsx
1061
- var import_react_native_paper13 = require("react-native-paper");
1082
+ var import_react_native_paper14 = require("react-native-paper");
1062
1083
  var import_jsx_runtime14 = require("react/jsx-runtime");
1063
1084
  function FAB(props) {
1064
1085
  const defaults = usePaperDefaults();
1065
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper13.FAB, { ...defaults.FAB, ...props });
1086
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper14.FAB, { ...defaults.FAB, ...props });
1066
1087
  }
1067
1088
 
1068
1089
  // src/components/FadingScrollView.tsx
1069
- var import_react11 = require("react");
1090
+ var import_react12 = require("react");
1070
1091
  var import_react_native9 = require("react-native");
1071
1092
  var import_jsx_runtime15 = require("react/jsx-runtime");
1072
1093
  var SCROLL_FADE_HEIGHT = 24;
1073
1094
  function FadingScrollView({ style, fadeHeight = SCROLL_FADE_HEIGHT, onScroll, onLayout, onContentSizeChange, scrollEventThrottle = 16, children, ...rest }) {
1074
1095
  const MaskedView = useMaskedViewModule();
1075
- const sizes = (0, import_react11.useRef)({ viewport: 0, content: 0, offset: 0 });
1076
- const [edges, setEdges] = (0, import_react11.useState)(NO_EDGES);
1077
- const update = (0, import_react11.useCallback)(() => {
1096
+ const sizes = (0, import_react12.useRef)({ viewport: 0, content: 0, offset: 0 });
1097
+ const [edges, setEdges] = (0, import_react12.useState)(NO_EDGES);
1098
+ const update = (0, import_react12.useCallback)(() => {
1078
1099
  const { viewport, content, offset } = sizes.current;
1079
1100
  const above = offset > 1;
1080
1101
  const below = content - viewport - offset > 1;
@@ -1148,20 +1169,20 @@ var styles5 = import_react_native9.StyleSheet.create({
1148
1169
  });
1149
1170
 
1150
1171
  // src/components/IconButton.tsx
1151
- var import_react_native_paper14 = require("react-native-paper");
1172
+ var import_react_native_paper15 = require("react-native-paper");
1152
1173
  var import_jsx_runtime16 = require("react/jsx-runtime");
1153
1174
  function IconButton({ variant, iconColor, containerColor, ...props }) {
1154
1175
  const defaults = usePaperDefaults();
1155
- const { colors } = (0, import_react_native_paper14.useTheme)();
1176
+ const { colors } = (0, import_react_native_paper15.useTheme)();
1156
1177
  const variantContainerColor = variant === "primary" ? colors.primaryContainer : variant === "secondary" ? colors.secondaryContainer : variant === "tertiary" ? colors.tertiaryContainer : variant === "surface" ? colors.surface : void 0;
1157
1178
  const variantIconColor = variant === "primary" ? colors.onPrimaryContainer : variant === "secondary" ? colors.onSecondaryContainer : variant === "tertiary" ? colors.onTertiaryContainer : variant === "surface" ? colors.onSurface : void 0;
1158
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native_paper14.IconButton, { ...defaults.IconButton, containerColor: containerColor ?? variantContainerColor, iconColor: iconColor ?? variantIconColor, ...props });
1179
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native_paper15.IconButton, { ...defaults.IconButton, containerColor: containerColor ?? variantContainerColor, iconColor: iconColor ?? variantIconColor, ...props });
1159
1180
  }
1160
1181
 
1161
1182
  // src/components/Menu.tsx
1162
- var import_react12 = require("react");
1183
+ var import_react13 = require("react");
1163
1184
  var import_react_native10 = require("react-native");
1164
- var import_react_native_paper15 = require("react-native-paper");
1185
+ var import_react_native_paper16 = require("react-native-paper");
1165
1186
  var import_jsx_runtime17 = require("react/jsx-runtime");
1166
1187
  var ANIMATION_DURATION2 = 250;
1167
1188
  var EASING = import_react_native10.Easing.bezier(0.4, 0, 0.2, 1);
@@ -1170,11 +1191,11 @@ var SHADOW_HEIGHT = [0, 1, 2, 4, 6, 8];
1170
1191
  var SHADOW_RADIUS = [0, 3, 6, 8, 10, 12];
1171
1192
  var AnimatedBlurView2 = import_react_native10.Animated.createAnimatedComponent(BlurView);
1172
1193
  var FadingBlurView = ({ blur, children, elevation, theme: themeOverrides, visible }) => {
1173
- const { animation, roundness } = (0, import_react_native_paper15.useTheme)(themeOverrides);
1174
- const [opacity] = (0, import_react12.useState)(() => new import_react_native10.Animated.Value(0));
1175
- const [closing, setClosing] = (0, import_react12.useState)(false);
1194
+ const { animation, roundness } = (0, import_react_native_paper16.useTheme)(themeOverrides);
1195
+ const [opacity] = (0, import_react13.useState)(() => new import_react_native10.Animated.Value(0));
1196
+ const [closing, setClosing] = (0, import_react13.useState)(false);
1176
1197
  if (!visible && !closing) setClosing(true);
1177
- (0, import_react12.useEffect)(() => {
1198
+ (0, import_react13.useEffect)(() => {
1178
1199
  import_react_native10.Animated.timing(opacity, { duration: animation.scale * ANIMATION_DURATION2, easing: EASING, toValue: closing ? 0 : 1, useNativeDriver: false }).start();
1179
1200
  }, [animation.scale, closing, opacity]);
1180
1201
  const shadow = elevation > 0 ? { shadowColor: "#000000", shadowOffset: { height: SHADOW_HEIGHT[elevation], width: 0 }, shadowOpacity: 0.3, shadowRadius: SHADOW_RADIUS[elevation] } : null;
@@ -1183,10 +1204,10 @@ var FadingBlurView = ({ blur, children, elevation, theme: themeOverrides, visibl
1183
1204
  var MenuComponent = ({ blur: blurProp, children, ...props }) => {
1184
1205
  const blur = useBlur(blurProp);
1185
1206
  const web = import_react_native10.Platform.OS === "web";
1186
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native_paper15.Menu, { ...props, contentStyle: [styles6.content, web && styles6.webSurface, props.contentStyle], children: web ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FadingBlurView, { blur, elevation: props.mode === "flat" ? 0 : props.elevation ?? DEFAULT_ELEVATION, theme: props.theme, visible: props.visible, children }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(BlurView, { blur, children }) });
1207
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native_paper16.Menu, { ...props, contentStyle: [styles6.content, web && styles6.webSurface, props.contentStyle], children: web ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FadingBlurView, { blur, elevation: props.mode === "flat" ? 0 : props.elevation ?? DEFAULT_ELEVATION, theme: props.theme, visible: props.visible, children }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(BlurView, { blur, children }) });
1187
1208
  };
1188
1209
  var Menu = Object.assign(MenuComponent, {
1189
- Item: import_react_native_paper15.Menu.Item
1210
+ Item: import_react_native_paper16.Menu.Item
1190
1211
  });
1191
1212
  var styles6 = import_react_native10.StyleSheet.create({
1192
1213
  content: { backgroundColor: "transparent", paddingVertical: 0 },
@@ -1194,12 +1215,12 @@ var styles6 = import_react_native10.StyleSheet.create({
1194
1215
  });
1195
1216
 
1196
1217
  // src/components/TextInput.tsx
1197
- var import_react13 = require("react");
1198
- var import_react_native_paper16 = require("react-native-paper");
1218
+ var import_react14 = require("react");
1219
+ var import_react_native_paper17 = require("react-native-paper");
1199
1220
  var import_jsx_runtime18 = require("react/jsx-runtime");
1200
- var TextInput = (0, import_react13.forwardRef)(function TextInput2(props, ref) {
1221
+ var TextInput = (0, import_react14.forwardRef)(function TextInput2(props, ref) {
1201
1222
  const defaults = usePaperDefaults();
1202
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native_paper16.TextInput, { ref, ...defaults.TextInput, ...props });
1223
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native_paper17.TextInput, { ref, ...defaults.TextInput, ...props });
1203
1224
  });
1204
1225
 
1205
1226
  // src/redux/themeSlice.ts
@@ -1224,16 +1245,99 @@ var selectThemeColor = themeSlice.selectors.selectColor;
1224
1245
  var selectThemeHarmony = themeSlice.selectors.selectHarmony;
1225
1246
 
1226
1247
  // src/useTheme.ts
1227
- var import_react_native_paper17 = require("react-native-paper");
1228
- var useAutoPaperTheme = () => (0, import_react_native_paper17.useTheme)();
1248
+ var import_react_native_paper18 = require("react-native-paper");
1249
+ var useAutoPaperTheme = () => (0, import_react_native_paper18.useTheme)();
1229
1250
 
1230
1251
  // src/useThemeBridgeProps.ts
1231
- var import_react14 = require("react");
1252
+ var import_react15 = require("react");
1232
1253
  function useThemeBridgeProps(props) {
1233
1254
  const { initialValue, onChange, onReady } = props;
1234
- return (0, import_react14.useMemo)(() => ({ initialValue, onChange, onReady }), [initialValue, onChange, onReady]);
1255
+ return (0, import_react15.useMemo)(() => ({ initialValue, onChange, onReady }), [initialValue, onChange, onReady]);
1235
1256
  }
1236
1257
 
1258
+ // src/utils/getOklch.ts
1259
+ var toLinear = (c) => c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
1260
+ var toGamma = (c) => c <= 31308e-7 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055;
1261
+ var linearToOklab = ([r, g, b]) => {
1262
+ const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
1263
+ const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
1264
+ const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
1265
+ return [0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s, 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s, 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s];
1266
+ };
1267
+ var oklabToLinear = ([L, a, b]) => {
1268
+ const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;
1269
+ const m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;
1270
+ const s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;
1271
+ return [4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s, -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s, -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s];
1272
+ };
1273
+ var inGamut = (rgb) => rgb.every((v) => v >= -1e-6 && v <= 1 + 1e-6);
1274
+ var clamp01 = (v) => Math.min(1, Math.max(0, v));
1275
+ var toHex = (rgb) => `#${rgb.map(
1276
+ (v) => Math.round(clamp01(toGamma(clamp01(v))) * 255).toString(16).padStart(2, "0")
1277
+ ).join("")}`;
1278
+ var getOklch = (value) => {
1279
+ const rgb = getRgb(value);
1280
+ if (!rgb) return null;
1281
+ const [l, a, b] = linearToOklab([toLinear(rgb.r / 255), toLinear(rgb.g / 255), toLinear(rgb.b / 255)]);
1282
+ return { l, c: Math.hypot(a, b), h: (Math.atan2(b, a) * 180 / Math.PI + 360) % 360 };
1283
+ };
1284
+ var getOklchHex = ({ l, c, h }) => {
1285
+ const lightness = Math.min(1, Math.max(0, l));
1286
+ const radians = h * Math.PI / 180;
1287
+ const atChroma = (chroma) => oklabToLinear([lightness, chroma * Math.cos(radians), chroma * Math.sin(radians)]);
1288
+ const direct = atChroma(Math.max(0, c));
1289
+ if (inGamut(direct)) return toHex(direct);
1290
+ let low = 0;
1291
+ let high = c;
1292
+ for (let i = 0; i < 24; i++) {
1293
+ const mid = (low + high) / 2;
1294
+ if (inGamut(atChroma(mid))) low = mid;
1295
+ else high = mid;
1296
+ }
1297
+ return toHex(atChroma(low));
1298
+ };
1299
+
1300
+ // src/utils/getChalkboardColor.ts
1301
+ var MARKER = { maxLightness: 0.6, chroma: 0.85 };
1302
+ var CHALK = { lightness: 0.86, lift: 0.5, chroma: 0.8, minLuminance: 0.5 };
1303
+ var CACHE_LIMIT = 512;
1304
+ var createChalkboardTone = (options = {}) => {
1305
+ const marker = { ...MARKER, ...options.marker };
1306
+ const chalk = { ...CHALK, ...options.chalk };
1307
+ const cache = /* @__PURE__ */ new Map();
1308
+ const toMarker = (color) => {
1309
+ const oklch = getOklch(color);
1310
+ if (!oklch) return color;
1311
+ return getOklchHex({ l: Math.min(oklch.l, marker.maxLightness), c: oklch.c * marker.chroma, h: oklch.h });
1312
+ };
1313
+ const toChalk = (color) => {
1314
+ const oklch = getOklch(color);
1315
+ if (!oklch) return color;
1316
+ const c = oklch.c * chalk.chroma;
1317
+ const lifted = oklch.l < chalk.lightness ? oklch.l + (chalk.lightness - oklch.l) * chalk.lift : oklch.l;
1318
+ const result = getOklchHex({ l: lifted, c, h: oklch.h });
1319
+ if (getLuminance(result) >= chalk.minLuminance) return result;
1320
+ let low = lifted;
1321
+ let high = 1;
1322
+ for (let i = 0; i < 20; i++) {
1323
+ const mid = (low + high) / 2;
1324
+ if (getLuminance(getOklchHex({ l: mid, c, h: oklch.h })) >= chalk.minLuminance) high = mid;
1325
+ else low = mid;
1326
+ }
1327
+ return getOklchHex({ l: high, c, h: oklch.h });
1328
+ };
1329
+ return (color, dark) => {
1330
+ const key = `${dark ? "d" : "l"}${color}`;
1331
+ const cached = cache.get(key);
1332
+ if (cached !== void 0) return cached;
1333
+ const result = dark ? toChalk(color) : toMarker(color);
1334
+ if (cache.size >= CACHE_LIMIT) cache.clear();
1335
+ cache.set(key, result);
1336
+ return result;
1337
+ };
1338
+ };
1339
+ var getChalkboardColor = createChalkboardTone();
1340
+
1237
1341
  // src/utils/getThirdColor.ts
1238
1342
  function rgbToHsl(r, g, b) {
1239
1343
  r /= 255;
@@ -1338,15 +1442,19 @@ var getTintTextColor = (tintColor, backdropColor, tintOpacity) => {
1338
1442
  SEMANTIC_BASE_COLORS,
1339
1443
  TextInput,
1340
1444
  ThemeSettingsContext,
1445
+ createChalkboardTone,
1341
1446
  createThemeReducer,
1342
1447
  defaultColors,
1343
1448
  defaultThemeSettings,
1344
1449
  getBlendedColor,
1450
+ getChalkboardColor,
1345
1451
  getColorRoles,
1346
1452
  getContrastColor,
1347
1453
  getContrastRatio,
1348
1454
  getHex,
1349
1455
  getLuminance,
1456
+ getOklch,
1457
+ getOklchHex,
1350
1458
  getRgb,
1351
1459
  getThirdColor,
1352
1460
  getTintTextColor,
@@ -1366,6 +1474,7 @@ var getTintTextColor = (tintColor, backdropColor, tintOpacity) => {
1366
1474
  useComputedTheme,
1367
1475
  useMaskedViewModule,
1368
1476
  useNavBarContext,
1477
+ usePaletteTone,
1369
1478
  usePaperDefaults,
1370
1479
  useReanimatedModule,
1371
1480
  useThemeBridgeProps,