@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 CHANGED
@@ -1,12 +1,15 @@
1
1
  # @rific/auto-paper
2
2
 
3
- Adaptive theming for [`react-native-paper`](https://callstack.github.io/react-native-paper/). Give it one color and an appearance setting — it generates an MD3 palette and handles light/dark/system mode automatically.
3
+ Adaptive theming for [`react-native-paper`](https://callstack.github.io/react-native-paper/). Give it one color and an appearance setting, and it generates an MD3 palette and handles light/dark/system mode automatically.
4
4
 
5
5
  ## Features
6
6
 
7
- - Color harmony palette from a single seed color (primary → secondary → tertiary) — 6 harmony modes available, defaulting to `split-complementary`
7
+ - Color harmony palette from a single seed color (primary → secondary → tertiary), with 6 harmony modes available, defaulting to `split-complementary`
8
+ - Or supply an explicit `{ primary, secondary, tertiary }` triad directly, bypassing harmony math entirely
9
+ - `getThirdColor(colorA, colorB)` derives a third color maximally distinct in hue from two arbitrary inputs, handy for pairing with the explicit triad above when you have two colors and need a third that won't clash with either
8
10
  - System/light/dark appearance with live updates via `Appearance` API
9
11
  - Tinted surface, surfaceVariant, outline, and elevation levels derived from the seed
12
+ - Fixed `success`/`warning`/`danger` semantic color roles (each with `on*`/`*Container` variants) alongside MD3's built-in `error`
10
13
  - Optional Redux slice for wiring appearance and color into your store
11
14
  - Wrapper components (`Appbar`, `AppearancePicker`, `BlurView`, `BottomNavigation`, `Button`, `Chip`, `ColorPicker`, `Dialog`, `FAB`, `HarmonyPicker`, `IconButton`, `Menu`, `PalettePicker`, `TextInput`) with prop defaults via context
12
15
  - All color utilities exported for standalone use
@@ -26,11 +29,13 @@ npm install react-native-paper
26
29
  Optional peer dependencies:
27
30
 
28
31
  ```bash
29
- npm install expo-blur # frosted-glass BlurView; without it BlurView renders its solid (non-blur) fallback
32
+ npm install expo-blur # frosted-glass BlurView
30
33
  npm install expo-navigation-bar # (>= 56.0.0, SDK 54+) auto-syncs Android nav bar icon style to the theme when BottomNavigation is mounted
31
34
  ```
32
35
 
33
- The exported Redux slice has no dependency on `@reduxjs/toolkit` — it works with RTK stores, vanilla Redux, or no Redux at all.
36
+ Neither is auto-detected: pass them to `Provider` (`expoBlur`, `navigationBar`, see the prop table below) and `BlurView`/`BottomNavigation` pick them up automatically. Omit either and you get a working fallback instead: `BlurView` renders its solid (non-blur) look, and the Android nav bar simply isn't synced.
37
+
38
+ The exported Redux slice has no dependency on `@reduxjs/toolkit`: it works with RTK stores, vanilla Redux, or no Redux at all.
34
39
 
35
40
  ## Usage
36
41
 
@@ -48,7 +53,7 @@ export default function App() {
48
53
  }
49
54
  ```
50
55
 
51
- `Provider` renders `null` on the first render while the theme computes, then wraps your app in `PaperProvider` with the computed theme, a matching `StatusBar`, and a background `View`. Use `onReady` to hook into that moment — e.g. to dismiss a splash screen:
56
+ `Provider` renders `null` on the first render while the theme computes, then wraps your app in `PaperProvider` with the computed theme, a matching `StatusBar`, and a background `View`. Use `onReady` to hook into that moment, e.g. to dismiss a splash screen:
52
57
 
53
58
  ```tsx
54
59
  <AutoPaperProvider initialValue={{ appearance: 'system', color: '#6750a4' }} onReady={SplashScreen.hideAsync}>
@@ -74,7 +79,7 @@ function SettingsScreen() {
74
79
 
75
80
  ### Choosing a color harmony
76
81
 
77
- The `harmony` prop controls how secondary and tertiary colors are derived from your seed. The default is `split-complementary`, which works well for most apps — it keeps secondary and tertiary close together in hue so they feel like a family of accents rather than three competing dominant colors.
82
+ The `harmony` prop controls how secondary and tertiary colors are derived from your seed. The default is `split-complementary`, which works well for most apps: it keeps secondary and tertiary close together in hue so they feel like a family of accents rather than three competing dominant colors.
78
83
 
79
84
  ```tsx
80
85
  <AutoPaperProvider initialValue={{ appearance: 'system', color: '#6750a4', harmony: 'split-complementary' }}>
@@ -82,12 +87,44 @@ The `harmony` prop controls how secondary and tertiary colors are derived from y
82
87
 
83
88
  | Harmony | Offsets | Character |
84
89
  |---|---|---|
85
- | `split-complementary` *(default)* | 0°, +150°, +210° | Harmonious contrast — flanks the complement by ±30° |
86
- | `triadic` | 0°, +120°, +240° | Equilateral — maximum variety, three equal-weight colors |
87
- | `analogous` | 0°, +30°, +60° | Cohesive, natural — neighboring hues |
88
- | `square` | 0°, +90°, +270° | Balanced, structured — right-angle symmetry |
89
- | `complementary` | 0°, +90°, +180° | Bold — accent at 90° plus true opposite |
90
- | `double-split` | 0°, +30°, +330° | Tight — flanks the primary by ±30° |
90
+ | `split-complementary` *(default)* | 0°, +150°, +210° | Harmonious contrast: flanks the complement by ±30° |
91
+ | `triadic` | 0°, +120°, +240° | Equilateral: maximum variety, three equal-weight colors |
92
+ | `analogous` | 0°, +30°, +60° | Cohesive, natural: neighboring hues |
93
+ | `square` | 0°, +90°, +270° | Balanced, structured: right-angle symmetry |
94
+ | `complementary` | 0°, +90°, +180° | Bold: accent at 90° plus true opposite |
95
+ | `double-split` | 0°, +30°, +330° | Tight: flanks the primary by ±30° |
96
+
97
+ ### Explicit triad (bypassing harmony)
98
+
99
+ Instead of a single seed color, `color` also accepts a `{ primary, secondary, tertiary }` object (`TriadicPalette`). Each field is assigned directly, through `getColorRoles`, with no hue math, and `harmony` is ignored entirely. Useful whenever you already have three colors that matter individually, rather than one seed to expand.
100
+
101
+ ```tsx
102
+ <AutoPaperProvider
103
+ initialValue={{
104
+ appearance: 'system',
105
+ color: { primary: '#e53935', secondary: '#1e88e5', tertiary: '#43a047' }
106
+ }}
107
+ >
108
+ ```
109
+
110
+ A common case is deriving the third color from two you already have: any two arbitrary colors, from user picks to brand colors to data-driven values.
111
+
112
+ ```tsx
113
+ import { getThirdColor, Provider as AutoPaperProvider } from '@rific/auto-paper'
114
+
115
+ const colorA = '#e53935'
116
+ const colorB = '#1e88e5'
117
+
118
+ <AutoPaperProvider
119
+ initialValue={{
120
+ color: {
121
+ primary: colorA,
122
+ secondary: colorB,
123
+ tertiary: getThirdColor(colorA, colorB) // → '#59e52a'
124
+ }
125
+ }}
126
+ >
127
+ ```
91
128
 
92
129
  ### With component defaults
93
130
 
@@ -157,7 +194,7 @@ dispatch(themeActions.setAppearance('dark'))
157
194
 
158
195
  ### With `useComputedTheme`
159
196
 
160
- Use the hook directly when you need to extend the theme before passing it to `PaperProvider` — for example, to merge in a navigation theme or add custom color keys:
197
+ Use the hook directly when you need to extend the theme before passing it to `PaperProvider`, for example to merge in a navigation theme or add custom color keys:
161
198
 
162
199
  ```tsx
163
200
  import { useComputedTheme } from '@rific/auto-paper'
@@ -193,11 +230,13 @@ export default function App() {
193
230
 
194
231
  | Prop | Type | Description |
195
232
  |---|---|---|
196
- | `initialValue` | `Partial<ThemeSettings>` | Initial theme settings — `appearance`, `color`, `harmony`, `blur`, `blurTint`. Defaults from `defaultThemeSettings` fill any omitted fields. |
233
+ | `initialValue` | `Partial<ThemeSettings>` | Initial theme settings: `appearance`, `color`, `harmony`, `blur`, `blurTint`. Defaults from `defaultThemeSettings` fill any omitted fields. |
197
234
  | `onChange` | `(settings: ThemeSettings) => void` | Called whenever settings change via `useThemeSettings().set()` |
198
235
  | `children` | `ReactNode` | |
199
236
  | `defaults` | `PaperDefaults` | Prop defaults for wrapper components (see below) |
200
- | `onNavBarChange` | `(color: string, dark: boolean) => void` | Overrides the built-in nav bar sync: called on Android when the theme changes while a `BottomNavigation` is mounted, instead of the automatic `expo-navigation-bar` icon-style sync |
237
+ | `expoBlur` | `ExpoBlurModule` | Injects `expo-blur` (`import * as ExpoBlur from 'expo-blur'`) so `<BlurView>` renders the real frosted-glass effect. Omit to always render its solid fallback. |
238
+ | `navigationBar` | `ExpoNavigationBarModule` | Injects `expo-navigation-bar` (`import * as ExpoNavigationBar from 'expo-navigation-bar'`) so the Android nav bar icon style auto-syncs with the theme while a `BottomNavigation` is mounted. Omit (and don't pass `onNavBarChange`) to skip nav bar syncing entirely. |
239
+ | `onNavBarChange` | `(color: string, dark: boolean) => void` | Overrides the built-in nav bar sync: called on Android when the theme changes while a `BottomNavigation` is mounted, instead of the automatic `navigationBar`-driven icon-style sync |
201
240
  | `onReady` | `() => void` | Called once when the theme first resolves |
202
241
  | `statusBarProps` | `StatusBarProps` | Spread over the auto-derived `StatusBar` defaults |
203
242
  | `style` | `StyleProp<ViewStyle>` | Applied to the wrapper `View` |
@@ -207,8 +246,8 @@ export default function App() {
207
246
  | Field | Type | Default |
208
247
  |---|---|---|
209
248
  | `appearance` | `'system' \| 'light' \| 'dark'` | `'system'` |
210
- | `color` | `string` | `'#6750a4'` |
211
- | `harmony` | `ColorHarmony` | `'split-complementary'` |
249
+ | `color` | `string \| TriadicPalette` | `'#6750a4'` |
250
+ | `harmony` | `ColorHarmony` | `'split-complementary'` (ignored when `color` is a `TriadicPalette`) |
212
251
  | `blur` | `boolean` | `true` |
213
252
  | `blurTint` | `number` | `0.2` |
214
253
 
@@ -228,13 +267,63 @@ set({ harmony: 'triadic' })
228
267
 
229
268
  ### `useComputedTheme(appearance, color, harmony?)`
230
269
 
231
- Returns `MD3Theme | null`. `null` on the first render while the theme computes.
270
+ Returns `AutoPaperTheme | null`: `MD3Theme` plus `success`/`warning`/`danger` color roles (see below). `null` on the first render while the theme computes.
271
+
272
+ `color` accepts either a single seed string (expanded into `primary`/`secondary`/`tertiary` via `harmony`) or an explicit `{ primary, secondary, tertiary }` triad (`TriadicPalette`), which assigns each field directly and ignores `harmony`. Either way, the resulting `primary` also drives `outline`/`surfaceVariant`/elevation tinting.
232
273
 
233
274
  ```ts
234
275
  const theme = useComputedTheme('system', '#6750a4')
235
276
  const theme = useComputedTheme('system', '#6750a4', 'triadic')
277
+ const theme = useComputedTheme('system', { primary: '#e53935', secondary: '#1e88e5', tertiary: '#43a047' }) // harmony ignored
278
+ ```
279
+
280
+ Alongside the standard MD3 `primary`/`secondary`/`tertiary` roles derived from the seed color, `theme.colors` also carries three fixed semantic roles, each with the usual `color`/`onColor`/`Container`/`onContainer` quadruple (`success`, `onSuccess`, `successContainer`, `onSuccessContainer`, and likewise for `warning` and `danger`):
281
+
282
+ | Role | Base color |
283
+ |---|---|
284
+ | `success` | `SEMANTIC_BASE_COLORS.success` (`#2E7D32`) |
285
+ | `warning` | `SEMANTIC_BASE_COLORS.warning` (`#A15C00`) |
286
+ | `danger` | `SEMANTIC_BASE_COLORS.danger` (`#B00020`) |
287
+
288
+ These are fixed brand colors (like MD3's own `error`, which is left untouched), not derived from the seed; only their container blending adapts to light/dark mode. `danger` is deliberately separate from `error`: `react-native-paper` components (`TextInput`'s error state, `HelperText`, `Badge`) read `colors.error`/`colors.onError` directly, so redefining `error` itself would change form-validation colors app-wide.
289
+
290
+ ```ts
291
+ import { SEMANTIC_BASE_COLORS } from '@rific/auto-paper'
292
+ import type { AutoPaperTheme, SemanticColorRoles } from '@rific/auto-paper'
293
+ ```
294
+
295
+ ### `useAutoPaperTheme()`
296
+
297
+ A typed alternative to `react-native-paper`'s own `useTheme()` that returns `AutoPaperTheme`: the same theme, with `colors.success`/`warning`/`danger` (and their `on*`/`*Container` variants) typed in, so you get autocomplete without redeclaring the generic yourself at every call site.
298
+
299
+ ```tsx
300
+ import { useAutoPaperTheme } from '@rific/auto-paper'
301
+
302
+ const { colors } = useAutoPaperTheme()
303
+
304
+ <Text style={{ color: colors.warning }}>Check your connection</Text>
236
305
  ```
237
306
 
307
+ ### `AppearancePicker`
308
+
309
+ A thin wrapper around `react-native-paper`'s `SegmentedButtons` for switching between `system`/`light`/`dark` appearance.
310
+
311
+ ```tsx
312
+ import { AppearancePicker, useThemeSettings } from '@rific/auto-paper'
313
+
314
+ function SettingsScreen() {
315
+ const { settings: { appearance }, set } = useThemeSettings()
316
+ return <AppearancePicker value={appearance} onChange={(a) => set({ appearance: a })} />
317
+ }
318
+ ```
319
+
320
+ | Prop | Type | Description |
321
+ |---|---|---|
322
+ | `value` | `ThemeAppearance` | Currently selected appearance |
323
+ | `onChange` | `(appearance: ThemeAppearance) => void` | Called when a segment is tapped |
324
+ | `showLabels` | `boolean` | Set `false` for icon-only segments, useful in tight layouts where "System" would truncate. `accessibilityLabel` is always set regardless, so screen readers still announce the full word. Defaults to `true` |
325
+ | `icons` | `AppearanceIcons` | Per-value icon overrides: pass just the ones you want to change (e.g. `{ system: 'theme-light-dark' }`), merged over the defaults (`monitor` / `white-balance-sunny` / `weather-night`) |
326
+
238
327
  ### `Appbar`
239
328
 
240
329
  A thin wrapper around `react-native-paper`'s `Appbar` that automatically syncs `StatusBar` background color and bar style to the current theme surface color.
@@ -249,11 +338,11 @@ import { Appbar } from '@rific/auto-paper'
249
338
  </Appbar.Header>
250
339
  ```
251
340
 
252
- `Appbar.Content`, `Appbar.Action`, and `Appbar.BackAction` are re-exported directly from `react-native-paper`. Only `Appbar.Header` is wrapped — it applies `AppbarHeader` defaults from context and renders the synced `StatusBar`.
341
+ `Appbar.Content`, `Appbar.Action`, and `Appbar.BackAction` are re-exported directly from `react-native-paper`. Only `Appbar.Header` is wrapped: it applies `AppbarHeader` defaults from context and renders the synced `StatusBar`.
253
342
 
254
343
  ### `BottomNavigation`
255
344
 
256
- A thin wrapper around `react-native-paper`'s `BottomNavigation` that keeps the Android system navigation bar icons readable: when the optional `expo-navigation-bar` peer is installed, the icon style automatically follows the theme's darkness (edge-to-edge safe — no background color calls). Pass `onNavBarChange` to the `Provider` to take full control instead; with neither, it silently no-ops.
345
+ A thin wrapper around `react-native-paper`'s `BottomNavigation` that keeps the Android system navigation bar icons readable: when `navigationBar` is injected into `Provider`, the icon style automatically follows the theme's darkness (edge-to-edge safe, no background color calls). Pass `onNavBarChange` to the `Provider` to take full control instead; with neither, it silently no-ops.
257
346
 
258
347
  ```tsx
259
348
  import { BottomNavigation } from '@rific/auto-paper'
@@ -305,13 +394,13 @@ import { IconButton } from '@rific/auto-paper'
305
394
  | Prop | Type | Description |
306
395
  |---|---|---|
307
396
  | `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'surface'` | Sets `containerColor` and `iconColor` from the matching theme color pair |
308
- | ...all `IconButtonProps` | | All props from `react-native-paper`'s `IconButton` are supported — explicit `containerColor` or `iconColor` override the variant |
397
+ | ...all `IconButtonProps` | | All props from `react-native-paper`'s `IconButton` are supported; explicit `containerColor` or `iconColor` override the variant |
309
398
 
310
399
  `IconButtonProps` is exported from `@rific/auto-paper` and extends `react-native-paper`'s `IconButtonProps` with the `variant` field. Use `PaperIconButtonProps` if you need the base paper type.
311
400
 
312
401
  ### `PalettePicker`
313
402
 
314
- Like `ColorPicker`, but each swatch — and the trigger itself — renders the seed's full triadic palette as a 3-wedge pie instead of a flat color, so you see the whole result before picking.
403
+ Like `ColorPicker`, but each swatch (and the trigger itself) renders the seed's full triadic palette as a 3-wedge pie instead of a flat color, so you see the whole result before picking.
315
404
 
316
405
  ```tsx
317
406
  import { PalettePicker, useThemeSettings } from '@rific/auto-paper'
@@ -327,7 +416,7 @@ function SettingsScreen() {
327
416
  | `value` | `string` | Currently selected seed color |
328
417
  | `onChange` | `(color: string) => void` | Called with the seed color when a swatch is tapped |
329
418
  | `harmony` | `ColorHarmony` | Harmony used to compute each swatch's preview palette. Defaults to `'split-complementary'` |
330
- | `weights` | `PaletteWeights` | Relative size of each wedge — `{ primary, secondary, tertiary }`. Defaults to `{ primary: 2, secondary: 1, tertiary: 1 }` (primary half the pie, secondary/tertiary a quarter each). Values are normalized, so any positive ratio works; keep each share at or under half the total so its wedge stays a single slice |
419
+ | `weights` | `PaletteWeights` | Relative size of each wedge: `{ primary, secondary, tertiary }`. Defaults to `{ primary: 2, secondary: 1, tertiary: 1 }` (primary half the pie, secondary/tertiary a quarter each). Values are normalized, so any positive ratio works; keep each share at or under half the total so its wedge stays a single slice |
331
420
  | `colors` | `SeedColor[]` | Seed color swatches to offer. Defaults to the same set as `ColorPicker` |
332
421
  | `blur` | `boolean` | Overrides the ambient blur setting for this component's dialog |
333
422
 
@@ -375,10 +464,10 @@ import type { ThemeState, ThemeAppearance } from '@rific/auto-paper'
375
464
  | `initialize` | `Partial<ThemeState>` |
376
465
  | `setAppearance` | `ThemeAppearance` |
377
466
  | `setBlur` | `boolean` |
378
- | `setColor` | `string` |
467
+ | `setColor` | `string \| TriadicPalette` |
379
468
  | `setHarmony` | `ColorHarmony` |
380
469
 
381
- Selectors accept `ThemeState` directly — compose them with your root state selector:
470
+ Selectors accept `ThemeState` directly; compose them with your root state selector:
382
471
 
383
472
  ```ts
384
473
  const appearance = useSelector((state: RootState) => selectThemeAppearance(state.theme))
@@ -387,8 +476,8 @@ const appearance = useSelector((state: RootState) => selectThemeAppearance(state
387
476
  ### Color utilities
388
477
 
389
478
  ```ts
390
- import { getTriadicPalette, getBlendedColor, isDarkColor, getRgb, getHex, getTonalColor, getTintTextColor } from '@rific/auto-paper'
391
- import type { ColorHarmony } from '@rific/auto-paper'
479
+ import { getTriadicPalette, getThirdColor, getBlendedColor, getColorRoles, getContrastColor, isDarkColor, getRgb, getHex, getTonalColor, getTintTextColor } from '@rific/auto-paper'
480
+ import type { ColorHarmony, TriadicPalette } from '@rific/auto-paper'
392
481
 
393
482
  getTriadicPalette('#6750a4') // split-complementary (default)
394
483
  getTriadicPalette('#6750a4', 'triadic') // → { primary, secondary, tertiary }
@@ -397,7 +486,11 @@ getTriadicPalette('#6750a4', 'square')
397
486
  getTriadicPalette('#6750a4', 'complementary')
398
487
  getTriadicPalette('#6750a4', 'double-split')
399
488
 
400
- getBlendedColor('#ff0000', '#0000ff', 0.5) // → '#800080'
489
+ getThirdColor('#e53935', '#1e88e5') // → '#59e52a' (hue maximally distant from both inputs; s/l averaged from both)
490
+
491
+ getBlendedColor('#ff0000', '#0000ff', 0.5) // → '#800080'
492
+ getColorRoles('#6750a4', '#fffbfe') // → { color, onColor, container, onContainer }: the MD3 color/onColor/container/onContainer math, generalized (this is what useComputedTheme uses internally for every role)
493
+ getContrastColor('#6750a4') // → '#ffffff' (black/white pick for content sitting on a fully saturated fill)
401
494
  isDarkColor('#6750a4') // → true
402
495
  getRgb('coral') // → { r: 255, g: 127, b: 80 }
403
496
  getHex('rgb(255, 0, 0)') // → '#ff0000'
package/dist/index.d.mts CHANGED
@@ -5,7 +5,7 @@ import * as react_native_paper from 'react-native-paper';
5
5
  import { AppbarHeaderProps, MD3Theme, BottomNavigationRoute, BottomNavigationProps, BottomNavigation as BottomNavigation$1, ButtonProps, ChipProps as ChipProps$1, DialogProps as DialogProps$1, DialogTitleProps, DialogContentProps, DialogActionsProps, DialogScrollAreaProps, FABProps, IconButtonProps as IconButtonProps$1, MenuProps as MenuProps$1, MenuItemProps, TextInputProps } from 'react-native-paper';
6
6
  export { AppbarHeaderProps, BottomNavigationProps, BottomNavigationRoute, ButtonProps, FABProps, ChipProps as PaperChipProps, DialogProps as PaperDialogProps, IconButtonProps as PaperIconButtonProps, MenuProps as PaperMenuProps, TextInputProps } from 'react-native-paper';
7
7
  import * as react from 'react';
8
- import react__default, { RefObject, ReactNode } from 'react';
8
+ import react__default, { RefObject, ReactNode, ComponentType } from 'react';
9
9
 
10
10
  declare function useBlur(override?: boolean): boolean;
11
11
 
@@ -29,14 +29,47 @@ type TriadicPalette = {
29
29
  declare function getTriadicPalette(primaryColor: string, harmony?: ColorHarmony): TriadicPalette;
30
30
 
31
31
  type ThemeAppearance = 'system' | 'light' | 'dark';
32
- declare function useComputedTheme(appearance: ThemeAppearance, color: string, harmony?: ColorHarmony): MD3Theme | null;
32
+ declare const SEMANTIC_BASE_COLORS: {
33
+ success: string;
34
+ warning: string;
35
+ danger: string;
36
+ };
37
+ type SemanticColorRoles = {
38
+ success: string;
39
+ onSuccess: string;
40
+ successContainer: string;
41
+ onSuccessContainer: string;
42
+ warning: string;
43
+ onWarning: string;
44
+ warningContainer: string;
45
+ onWarningContainer: string;
46
+ danger: string;
47
+ onDanger: string;
48
+ dangerContainer: string;
49
+ onDangerContainer: string;
50
+ };
51
+ type AutoPaperTheme = Omit<MD3Theme, 'colors'> & {
52
+ colors: MD3Theme['colors'] & SemanticColorRoles;
53
+ };
54
+ declare function useComputedTheme(appearance: ThemeAppearance, color: string | TriadicPalette, harmony?: ColorHarmony): AutoPaperTheme | null;
33
55
 
56
+ type AppearanceIcons = Partial<Record<ThemeAppearance, string>>;
34
57
  type Props$3 = {
35
58
  value: ThemeAppearance;
36
59
  onChange: (appearance: ThemeAppearance) => void;
60
+ showLabels?: boolean;
61
+ icons?: AppearanceIcons;
37
62
  };
38
- declare const AppearancePicker: ({ value, onChange }: Props$3) => react.JSX.Element;
63
+ declare const AppearancePicker: ({ value, onChange, showLabels, icons }: Props$3) => react.JSX.Element;
39
64
 
65
+ interface ExpoBlurModule {
66
+ BlurView: ComponentType<{
67
+ children?: ReactNode;
68
+ style?: StyleProp<ViewStyle>;
69
+ tint?: any;
70
+ [key: string]: unknown;
71
+ }>;
72
+ }
40
73
  type ExpoBlurTint = 'light' | 'dark' | 'default' | 'extraLight' | 'regular' | 'prominent' | 'systemUltraThinMaterial' | 'systemThinMaterial' | 'systemMaterial' | 'systemThickMaterial' | 'systemChromeMaterial' | 'systemUltraThinMaterialLight' | 'systemThinMaterialLight' | 'systemMaterialLight' | 'systemThickMaterialLight' | 'systemChromeMaterialLight' | 'systemUltraThinMaterialDark' | 'systemThinMaterialDark' | 'systemMaterialDark' | 'systemThickMaterialDark' | 'systemChromeMaterialDark';
41
74
  type ExpoBlurMethod = 'none' | 'dimezisBlurView' | 'dimezisBlurViewSdk31Plus';
42
75
  type ExpoBlurViewProps = {
@@ -145,6 +178,12 @@ declare const PalettePicker: ({ value, onChange, harmony, weights, colors, blur:
145
178
 
146
179
  declare const TextInput: react.ForwardRefExoticComponent<Omit<TextInputProps, "ref"> & react.RefAttributes<TextInput$1>>;
147
180
 
181
+ interface ExpoNavigationBarModule {
182
+ NavigationBar: {
183
+ setStyle: (style: 'light' | 'dark') => void;
184
+ };
185
+ }
186
+
148
187
  type PaperDefaults = {
149
188
  AppbarHeader?: Partial<AppbarHeaderProps>;
150
189
  BottomNavigation?: Partial<BottomNavigationProps<BottomNavigationRoute>>;
@@ -159,7 +198,7 @@ declare function usePaperDefaults(): PaperDefaults;
159
198
  type ThemeState = {
160
199
  appearance: ThemeAppearance;
161
200
  blur: boolean;
162
- color: string;
201
+ color: string | TriadicPalette;
163
202
  harmony: ColorHarmony;
164
203
  };
165
204
  type PayloadAction<P> = {
@@ -189,11 +228,11 @@ declare const themeActions: {
189
228
  }): action is PayloadAction<boolean>;
190
229
  };
191
230
  setColor: {
192
- (payload: string): PayloadAction<string>;
231
+ (payload: string | TriadicPalette): PayloadAction<string | TriadicPalette>;
193
232
  type: string;
194
233
  match(action: {
195
234
  type: string;
196
- }): action is PayloadAction<string>;
235
+ }): action is PayloadAction<string | TriadicPalette>;
197
236
  };
198
237
  setHarmony: {
199
238
  (payload: ColorHarmony): PayloadAction<ColorHarmony>;
@@ -211,14 +250,14 @@ declare const themeReducer: (state: ThemeState | undefined, action: {
211
250
  }) => ThemeState;
212
251
  declare const selectThemeAppearance: (state: ThemeState) => ThemeAppearance;
213
252
  declare const selectThemeBlur: (state: ThemeState) => boolean;
214
- declare const selectThemeColor: (state: ThemeState) => string;
253
+ declare const selectThemeColor: (state: ThemeState) => string | TriadicPalette;
215
254
  declare const selectThemeHarmony: (state: ThemeState) => ColorHarmony;
216
255
 
217
256
  type ThemeSettings = {
218
257
  appearance: ThemeAppearance;
219
258
  blur: boolean;
220
259
  blurTint: number;
221
- color: string;
260
+ color: string | TriadicPalette;
222
261
  harmony: ColorHarmony;
223
262
  };
224
263
  declare const defaultThemeSettings: ThemeSettings;
@@ -228,22 +267,42 @@ type ThemeSettingsContextType = {
228
267
  };
229
268
  declare const ThemeSettingsContext: react.Context<ThemeSettingsContextType>;
230
269
 
270
+ type NavBarContextType = {
271
+ navigationBar?: ExpoNavigationBarModule;
272
+ onNavBarChange?: (color: string, dark: boolean) => void;
273
+ };
274
+ declare const useNavBarContext: () => NavBarContextType;
275
+ declare const useBlurModule: () => ExpoBlurModule | undefined;
231
276
  type ProviderProps = {
232
- initialValue?: Partial<ThemeSettings>;
233
- onChange?: (settings: ThemeSettings) => void;
234
277
  children: ReactNode;
235
278
  defaults?: PaperDefaults;
279
+ /** Injects expo-blur for `<BlurView>`. Pass `import * as ExpoBlur from 'expo-blur'`; omit to always render BlurView's solid fallback. */
280
+ expoBlur?: ExpoBlurModule;
281
+ initialValue?: Partial<ThemeSettings>;
282
+ /** 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. */
283
+ navigationBar?: ExpoNavigationBarModule;
284
+ onChange?: (settings: ThemeSettings) => void;
236
285
  onNavBarChange?: (color: string, dark: boolean) => void;
237
286
  onReady?: () => void;
238
287
  statusBarProps?: StatusBarProps;
239
288
  style?: StyleProp<ViewStyle>;
240
289
  };
241
- declare function Provider({ initialValue, onChange, children, defaults, onNavBarChange, onReady, statusBarProps, style }: ProviderProps): react.JSX.Element | null;
290
+ declare function Provider({ children, defaults, expoBlur, initialValue, navigationBar, onChange, onNavBarChange, onReady, statusBarProps, style }: ProviderProps): react.JSX.Element | null;
291
+
292
+ declare const useAutoPaperTheme: () => AutoPaperTheme;
242
293
 
243
294
  declare const useThemeSettings: () => ThemeSettingsContextType;
244
295
 
245
296
  declare const getBlendedColor: (foreground: string, background: string, alpha: number) => string;
246
297
 
298
+ type ColorRoles = {
299
+ color: string;
300
+ onColor: string;
301
+ container: string;
302
+ onContainer: string;
303
+ };
304
+ declare const getColorRoles: (base: string, surface: string, containerAlpha?: number) => ColorRoles;
305
+
247
306
  declare const getHex: (value: string) => string | null;
248
307
 
249
308
  type RGB = {
@@ -254,10 +313,14 @@ type RGB = {
254
313
  };
255
314
  declare const getRgb: (value: string) => RGB | null;
256
315
 
316
+ declare const getContrastColor: (color: string) => string;
317
+
318
+ declare function getThirdColor(colorA: string, colorB: string): string;
319
+
257
320
  declare const getTintTextColor: (tintColor: string, backdropColor: string, tintOpacity: number) => string;
258
321
 
259
322
  declare const getTonalColor: (color: string, lightness: number) => string;
260
323
 
261
324
  declare const isDarkColor: (value: string) => boolean;
262
325
 
263
- export { Appbar, AppearancePicker, BlurView, type BlurViewProps, BottomNavigation, Button, Chip, type ChipProps, type ColorHarmony, ColorPicker, Dialog, type DialogProps, FAB, HarmonyPicker, IconButton, type IconButtonProps, Menu, type MenuProps, PalettePicker, type PaletteWeights, type PaperDefaults, Provider, type ProviderProps, type RGB, type SeedColor, TextInput, type ThemeAppearance, type ThemeSettings, ThemeSettingsContext, type ThemeSettingsContextType, type ThemeState, type TriadicPalette, createThemeReducer, defaultColors, defaultThemeSettings, getBlendedColor, getHex, getRgb, getTintTextColor, getTonalColor, getTriadicPalette, isDarkColor, selectThemeAppearance, selectThemeBlur, selectThemeColor, selectThemeHarmony, themeActions, themeReducer, useBlur, useComputedTheme, usePaperDefaults, useThemeSettings };
326
+ export { Appbar, type AppearanceIcons, AppearancePicker, type AutoPaperTheme, BlurView, type BlurViewProps, BottomNavigation, Button, Chip, type ChipProps, type ColorHarmony, ColorPicker, type ColorRoles, Dialog, type DialogProps, type ExpoBlurModule, type ExpoNavigationBarModule, FAB, HarmonyPicker, IconButton, type IconButtonProps, Menu, type MenuProps, PalettePicker, type PaletteWeights, type PaperDefaults, Provider, type ProviderProps, type RGB, SEMANTIC_BASE_COLORS, type SeedColor, type SemanticColorRoles, TextInput, type ThemeAppearance, type ThemeSettings, ThemeSettingsContext, type ThemeSettingsContextType, type ThemeState, type TriadicPalette, createThemeReducer, defaultColors, defaultThemeSettings, getBlendedColor, getColorRoles, getContrastColor, getHex, getRgb, getThirdColor, getTintTextColor, getTonalColor, getTriadicPalette, isDarkColor, selectThemeAppearance, selectThemeBlur, selectThemeColor, selectThemeHarmony, themeActions, themeReducer, useAutoPaperTheme, useBlur, useBlurModule, useComputedTheme, useNavBarContext, usePaperDefaults, useThemeSettings };
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ import * as react_native_paper from 'react-native-paper';
5
5
  import { AppbarHeaderProps, MD3Theme, BottomNavigationRoute, BottomNavigationProps, BottomNavigation as BottomNavigation$1, ButtonProps, ChipProps as ChipProps$1, DialogProps as DialogProps$1, DialogTitleProps, DialogContentProps, DialogActionsProps, DialogScrollAreaProps, FABProps, IconButtonProps as IconButtonProps$1, MenuProps as MenuProps$1, MenuItemProps, TextInputProps } from 'react-native-paper';
6
6
  export { AppbarHeaderProps, BottomNavigationProps, BottomNavigationRoute, ButtonProps, FABProps, ChipProps as PaperChipProps, DialogProps as PaperDialogProps, IconButtonProps as PaperIconButtonProps, MenuProps as PaperMenuProps, TextInputProps } from 'react-native-paper';
7
7
  import * as react from 'react';
8
- import react__default, { RefObject, ReactNode } from 'react';
8
+ import react__default, { RefObject, ReactNode, ComponentType } from 'react';
9
9
 
10
10
  declare function useBlur(override?: boolean): boolean;
11
11
 
@@ -29,14 +29,47 @@ type TriadicPalette = {
29
29
  declare function getTriadicPalette(primaryColor: string, harmony?: ColorHarmony): TriadicPalette;
30
30
 
31
31
  type ThemeAppearance = 'system' | 'light' | 'dark';
32
- declare function useComputedTheme(appearance: ThemeAppearance, color: string, harmony?: ColorHarmony): MD3Theme | null;
32
+ declare const SEMANTIC_BASE_COLORS: {
33
+ success: string;
34
+ warning: string;
35
+ danger: string;
36
+ };
37
+ type SemanticColorRoles = {
38
+ success: string;
39
+ onSuccess: string;
40
+ successContainer: string;
41
+ onSuccessContainer: string;
42
+ warning: string;
43
+ onWarning: string;
44
+ warningContainer: string;
45
+ onWarningContainer: string;
46
+ danger: string;
47
+ onDanger: string;
48
+ dangerContainer: string;
49
+ onDangerContainer: string;
50
+ };
51
+ type AutoPaperTheme = Omit<MD3Theme, 'colors'> & {
52
+ colors: MD3Theme['colors'] & SemanticColorRoles;
53
+ };
54
+ declare function useComputedTheme(appearance: ThemeAppearance, color: string | TriadicPalette, harmony?: ColorHarmony): AutoPaperTheme | null;
33
55
 
56
+ type AppearanceIcons = Partial<Record<ThemeAppearance, string>>;
34
57
  type Props$3 = {
35
58
  value: ThemeAppearance;
36
59
  onChange: (appearance: ThemeAppearance) => void;
60
+ showLabels?: boolean;
61
+ icons?: AppearanceIcons;
37
62
  };
38
- declare const AppearancePicker: ({ value, onChange }: Props$3) => react.JSX.Element;
63
+ declare const AppearancePicker: ({ value, onChange, showLabels, icons }: Props$3) => react.JSX.Element;
39
64
 
65
+ interface ExpoBlurModule {
66
+ BlurView: ComponentType<{
67
+ children?: ReactNode;
68
+ style?: StyleProp<ViewStyle>;
69
+ tint?: any;
70
+ [key: string]: unknown;
71
+ }>;
72
+ }
40
73
  type ExpoBlurTint = 'light' | 'dark' | 'default' | 'extraLight' | 'regular' | 'prominent' | 'systemUltraThinMaterial' | 'systemThinMaterial' | 'systemMaterial' | 'systemThickMaterial' | 'systemChromeMaterial' | 'systemUltraThinMaterialLight' | 'systemThinMaterialLight' | 'systemMaterialLight' | 'systemThickMaterialLight' | 'systemChromeMaterialLight' | 'systemUltraThinMaterialDark' | 'systemThinMaterialDark' | 'systemMaterialDark' | 'systemThickMaterialDark' | 'systemChromeMaterialDark';
41
74
  type ExpoBlurMethod = 'none' | 'dimezisBlurView' | 'dimezisBlurViewSdk31Plus';
42
75
  type ExpoBlurViewProps = {
@@ -145,6 +178,12 @@ declare const PalettePicker: ({ value, onChange, harmony, weights, colors, blur:
145
178
 
146
179
  declare const TextInput: react.ForwardRefExoticComponent<Omit<TextInputProps, "ref"> & react.RefAttributes<TextInput$1>>;
147
180
 
181
+ interface ExpoNavigationBarModule {
182
+ NavigationBar: {
183
+ setStyle: (style: 'light' | 'dark') => void;
184
+ };
185
+ }
186
+
148
187
  type PaperDefaults = {
149
188
  AppbarHeader?: Partial<AppbarHeaderProps>;
150
189
  BottomNavigation?: Partial<BottomNavigationProps<BottomNavigationRoute>>;
@@ -159,7 +198,7 @@ declare function usePaperDefaults(): PaperDefaults;
159
198
  type ThemeState = {
160
199
  appearance: ThemeAppearance;
161
200
  blur: boolean;
162
- color: string;
201
+ color: string | TriadicPalette;
163
202
  harmony: ColorHarmony;
164
203
  };
165
204
  type PayloadAction<P> = {
@@ -189,11 +228,11 @@ declare const themeActions: {
189
228
  }): action is PayloadAction<boolean>;
190
229
  };
191
230
  setColor: {
192
- (payload: string): PayloadAction<string>;
231
+ (payload: string | TriadicPalette): PayloadAction<string | TriadicPalette>;
193
232
  type: string;
194
233
  match(action: {
195
234
  type: string;
196
- }): action is PayloadAction<string>;
235
+ }): action is PayloadAction<string | TriadicPalette>;
197
236
  };
198
237
  setHarmony: {
199
238
  (payload: ColorHarmony): PayloadAction<ColorHarmony>;
@@ -211,14 +250,14 @@ declare const themeReducer: (state: ThemeState | undefined, action: {
211
250
  }) => ThemeState;
212
251
  declare const selectThemeAppearance: (state: ThemeState) => ThemeAppearance;
213
252
  declare const selectThemeBlur: (state: ThemeState) => boolean;
214
- declare const selectThemeColor: (state: ThemeState) => string;
253
+ declare const selectThemeColor: (state: ThemeState) => string | TriadicPalette;
215
254
  declare const selectThemeHarmony: (state: ThemeState) => ColorHarmony;
216
255
 
217
256
  type ThemeSettings = {
218
257
  appearance: ThemeAppearance;
219
258
  blur: boolean;
220
259
  blurTint: number;
221
- color: string;
260
+ color: string | TriadicPalette;
222
261
  harmony: ColorHarmony;
223
262
  };
224
263
  declare const defaultThemeSettings: ThemeSettings;
@@ -228,22 +267,42 @@ type ThemeSettingsContextType = {
228
267
  };
229
268
  declare const ThemeSettingsContext: react.Context<ThemeSettingsContextType>;
230
269
 
270
+ type NavBarContextType = {
271
+ navigationBar?: ExpoNavigationBarModule;
272
+ onNavBarChange?: (color: string, dark: boolean) => void;
273
+ };
274
+ declare const useNavBarContext: () => NavBarContextType;
275
+ declare const useBlurModule: () => ExpoBlurModule | undefined;
231
276
  type ProviderProps = {
232
- initialValue?: Partial<ThemeSettings>;
233
- onChange?: (settings: ThemeSettings) => void;
234
277
  children: ReactNode;
235
278
  defaults?: PaperDefaults;
279
+ /** Injects expo-blur for `<BlurView>`. Pass `import * as ExpoBlur from 'expo-blur'`; omit to always render BlurView's solid fallback. */
280
+ expoBlur?: ExpoBlurModule;
281
+ initialValue?: Partial<ThemeSettings>;
282
+ /** 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. */
283
+ navigationBar?: ExpoNavigationBarModule;
284
+ onChange?: (settings: ThemeSettings) => void;
236
285
  onNavBarChange?: (color: string, dark: boolean) => void;
237
286
  onReady?: () => void;
238
287
  statusBarProps?: StatusBarProps;
239
288
  style?: StyleProp<ViewStyle>;
240
289
  };
241
- declare function Provider({ initialValue, onChange, children, defaults, onNavBarChange, onReady, statusBarProps, style }: ProviderProps): react.JSX.Element | null;
290
+ declare function Provider({ children, defaults, expoBlur, initialValue, navigationBar, onChange, onNavBarChange, onReady, statusBarProps, style }: ProviderProps): react.JSX.Element | null;
291
+
292
+ declare const useAutoPaperTheme: () => AutoPaperTheme;
242
293
 
243
294
  declare const useThemeSettings: () => ThemeSettingsContextType;
244
295
 
245
296
  declare const getBlendedColor: (foreground: string, background: string, alpha: number) => string;
246
297
 
298
+ type ColorRoles = {
299
+ color: string;
300
+ onColor: string;
301
+ container: string;
302
+ onContainer: string;
303
+ };
304
+ declare const getColorRoles: (base: string, surface: string, containerAlpha?: number) => ColorRoles;
305
+
247
306
  declare const getHex: (value: string) => string | null;
248
307
 
249
308
  type RGB = {
@@ -254,10 +313,14 @@ type RGB = {
254
313
  };
255
314
  declare const getRgb: (value: string) => RGB | null;
256
315
 
316
+ declare const getContrastColor: (color: string) => string;
317
+
318
+ declare function getThirdColor(colorA: string, colorB: string): string;
319
+
257
320
  declare const getTintTextColor: (tintColor: string, backdropColor: string, tintOpacity: number) => string;
258
321
 
259
322
  declare const getTonalColor: (color: string, lightness: number) => string;
260
323
 
261
324
  declare const isDarkColor: (value: string) => boolean;
262
325
 
263
- export { Appbar, AppearancePicker, BlurView, type BlurViewProps, BottomNavigation, Button, Chip, type ChipProps, type ColorHarmony, ColorPicker, Dialog, type DialogProps, FAB, HarmonyPicker, IconButton, type IconButtonProps, Menu, type MenuProps, PalettePicker, type PaletteWeights, type PaperDefaults, Provider, type ProviderProps, type RGB, type SeedColor, TextInput, type ThemeAppearance, type ThemeSettings, ThemeSettingsContext, type ThemeSettingsContextType, type ThemeState, type TriadicPalette, createThemeReducer, defaultColors, defaultThemeSettings, getBlendedColor, getHex, getRgb, getTintTextColor, getTonalColor, getTriadicPalette, isDarkColor, selectThemeAppearance, selectThemeBlur, selectThemeColor, selectThemeHarmony, themeActions, themeReducer, useBlur, useComputedTheme, usePaperDefaults, useThemeSettings };
326
+ export { Appbar, type AppearanceIcons, AppearancePicker, type AutoPaperTheme, BlurView, type BlurViewProps, BottomNavigation, Button, Chip, type ChipProps, type ColorHarmony, ColorPicker, type ColorRoles, Dialog, type DialogProps, type ExpoBlurModule, type ExpoNavigationBarModule, FAB, HarmonyPicker, IconButton, type IconButtonProps, Menu, type MenuProps, PalettePicker, type PaletteWeights, type PaperDefaults, Provider, type ProviderProps, type RGB, SEMANTIC_BASE_COLORS, type SeedColor, type SemanticColorRoles, TextInput, type ThemeAppearance, type ThemeSettings, ThemeSettingsContext, type ThemeSettingsContextType, type ThemeState, type TriadicPalette, createThemeReducer, defaultColors, defaultThemeSettings, getBlendedColor, getColorRoles, getContrastColor, getHex, getRgb, getThirdColor, getTintTextColor, getTonalColor, getTriadicPalette, isDarkColor, selectThemeAppearance, selectThemeBlur, selectThemeColor, selectThemeHarmony, themeActions, themeReducer, useAutoPaperTheme, useBlur, useBlurModule, useComputedTheme, useNavBarContext, usePaperDefaults, useThemeSettings };