@rific/auto-paper 0.1.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 ADDED
@@ -0,0 +1,189 @@
1
+ # @rific/auto-paper
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 a triadic MD3 palette and handles light/dark/system mode automatically.
4
+
5
+ ## Features
6
+
7
+ - Triadic color palette from a single seed color (primary → secondary → tertiary, 120° apart on the color wheel)
8
+ - System/light/dark appearance with live updates via `Appearance` API
9
+ - Tinted surface, surfaceVariant, outline, and elevation levels derived from the seed
10
+ - SplashScreen gate — hides splash only once the theme is ready
11
+ - Optional Redux slice (`themeReducer`, `themeActions`) for wiring into your store
12
+ - All color utilities exported for standalone use
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @rific/auto-paper
18
+ ```
19
+
20
+ Peer dependencies:
21
+
22
+ ```bash
23
+ npm install react-native react-native-paper
24
+ # optional — only needed if using splashScreen:
25
+ npm install expo-splash-screen
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ### ThemeProvider (simplest)
31
+
32
+ Call `configureSplashScreen` at your app entry point before any components mount, then wrap your tree:
33
+
34
+ ```tsx
35
+ // index.ts / App.tsx top-level
36
+ import { configureSplashScreen } from '@rific/auto-paper'
37
+ configureSplashScreen({ duration: 500, fade: true })
38
+
39
+ // App.tsx
40
+ import { ThemeProvider } from '@rific/auto-paper'
41
+
42
+ export default function App() {
43
+ const [appearance, setAppearance] = useState<'system' | 'light' | 'dark'>('system')
44
+ const [color, setColor] = useState('#6750a4')
45
+
46
+ return (
47
+ <ThemeProvider appearance={appearance} color={color}>
48
+ {/* your app */}
49
+ </ThemeProvider>
50
+ )
51
+ }
52
+ ```
53
+
54
+ `ThemeProvider` renders `null` (keeping the splash screen visible) until the theme is computed on first mount.
55
+
56
+ ### With React Navigation
57
+
58
+ Use the `useComputedTheme` hook directly to integrate with Navigation's `ThemeProvider`:
59
+
60
+ ```tsx
61
+ import { useComputedTheme } from '@rific/auto-paper'
62
+ import { DarkTheme, DefaultTheme, ThemeProvider as NavThemeProvider } from '@react-navigation/native'
63
+ import { Provider as PaperProvider } from 'react-native-paper'
64
+
65
+ export default function App() {
66
+ const theme = useComputedTheme('system', '#6750a4')
67
+ if (!theme) return null
68
+
69
+ const navTheme = {
70
+ ...(theme.dark ? DarkTheme : DefaultTheme),
71
+ colors: {
72
+ ...(theme.dark ? DarkTheme : DefaultTheme).colors,
73
+ background: theme.colors.background,
74
+ card: theme.colors.background
75
+ }
76
+ }
77
+
78
+ return (
79
+ <NavThemeProvider value={navTheme}>
80
+ <PaperProvider theme={theme}>
81
+ {/* your app */}
82
+ </PaperProvider>
83
+ </NavThemeProvider>
84
+ )
85
+ }
86
+ ```
87
+
88
+ ### With Redux
89
+
90
+ The package exports an optional Redux slice. Add it to your store and dispatch actions to update appearance or color from settings screens:
91
+
92
+ ```ts
93
+ // store.ts
94
+ import { themeReducer } from '@rific/auto-paper'
95
+
96
+ export const store = configureStore({
97
+ reducer: {
98
+ theme: themeReducer,
99
+ // ...
100
+ }
101
+ })
102
+ ```
103
+
104
+ ```tsx
105
+ // App.tsx
106
+ import { useSelector } from 'react-redux'
107
+ import { ThemeProvider } from '@rific/auto-paper'
108
+
109
+ export default function App() {
110
+ const { appearance, color } = useSelector((state) => state.theme)
111
+ return (
112
+ <ThemeProvider appearance={appearance} color={color}>
113
+ {/* your app */}
114
+ </ThemeProvider>
115
+ )
116
+ }
117
+ ```
118
+
119
+ ```tsx
120
+ // SettingsScreen.tsx
121
+ import { themeActions } from '@rific/auto-paper'
122
+ import { useDispatch } from 'react-redux'
123
+
124
+ dispatch(themeActions.setColor('#e91e63'))
125
+ dispatch(themeActions.setAppearance('dark'))
126
+ ```
127
+
128
+ The slice's initial color is `#6750a4` (MD3 default purple). Override it at startup:
129
+
130
+ ```ts
131
+ store.dispatch(themeActions.initialize({ color: myStoredColor }))
132
+ ```
133
+
134
+ ## API
135
+
136
+ ### `ThemeProvider`
137
+
138
+ | Prop | Type | Default | Description |
139
+ |---|---|---|---|
140
+ | `appearance` | `'system' \| 'light' \| 'dark'` | — | Appearance mode |
141
+ | `color` | `string` | — | Seed color (hex, rgb, or CSS name) |
142
+ | `splashScreen` | `boolean` | `true` | Hide expo-splash-screen when theme is ready |
143
+ | `children` | `ReactNode` | — | |
144
+
145
+ ### `useComputedTheme(appearance, color, options?)`
146
+
147
+ Returns `MD3Theme | null`. `null` means the theme hasn't been computed yet (first render).
148
+
149
+ ```ts
150
+ const theme = useComputedTheme('system', '#6750a4', { splashScreen: false })
151
+ ```
152
+
153
+ ### `configureSplashScreen(options?)`
154
+
155
+ Call once at app entry. Wraps `SplashScreen.preventAutoHideAsync()` + `SplashScreen.setOptions()`.
156
+
157
+ ```ts
158
+ configureSplashScreen({ duration: 500, fade: true })
159
+ ```
160
+
161
+ ### Color utilities
162
+
163
+ ```ts
164
+ import { getTriadicPalette, getBlendedColor, isDarkColor, getRgb, getHex } from '@rific/auto-paper'
165
+
166
+ getTriadicPalette('#ff0000')
167
+ // → { primary: '#ff0000', secondary: '#00ff00', tertiary: '#0000ff' }
168
+
169
+ getBlendedColor('#ff0000', '#0000ff', 0.5) // → '#800080'
170
+ isDarkColor('#6750a4') // → true
171
+ getRgb('coral') // → { r: 255, g: 127, b: 80 }
172
+ getHex('rgb(255, 0, 0)') // → '#ff0000'
173
+ ```
174
+
175
+ ### Redux slice
176
+
177
+ ```ts
178
+ import { themeReducer, themeActions, ThemeState, ThemeAppearance } from '@rific/auto-paper'
179
+ ```
180
+
181
+ | Action | Payload |
182
+ |---|---|
183
+ | `initialize` | `Partial<ThemeState>` |
184
+ | `setAppearance` | `ThemeAppearance` |
185
+ | `setColor` | `string` |
186
+
187
+ ## License
188
+
189
+ MIT
@@ -0,0 +1,76 @@
1
+ import * as redux from 'redux';
2
+ import * as _reduxjs_toolkit from '@reduxjs/toolkit';
3
+ import { PayloadAction } from '@reduxjs/toolkit';
4
+ import { MD3Theme } from 'react-native-paper';
5
+ import * as react from 'react';
6
+ import { ReactNode } from 'react';
7
+
8
+ type ThemeAppearance = 'system' | 'light' | 'dark';
9
+ type ComputedThemeOptions = {
10
+ splashScreen?: boolean;
11
+ };
12
+ declare function useComputedTheme(appearance: ThemeAppearance, color: string, options?: ComputedThemeOptions): MD3Theme | null;
13
+
14
+ type ThemeState = {
15
+ appearance: ThemeAppearance;
16
+ color: string;
17
+ };
18
+ declare const themeActions: _reduxjs_toolkit.CaseReducerActions<{
19
+ initialize: (state: {
20
+ appearance: ThemeAppearance;
21
+ color: string;
22
+ }, action: PayloadAction<Partial<ThemeState>>) => {
23
+ appearance: ThemeAppearance;
24
+ color: string;
25
+ };
26
+ setAppearance: (state: {
27
+ appearance: ThemeAppearance;
28
+ color: string;
29
+ }, action: PayloadAction<ThemeAppearance>) => {
30
+ appearance: ThemeAppearance;
31
+ color: string;
32
+ };
33
+ setColor: (state: {
34
+ appearance: ThemeAppearance;
35
+ color: string;
36
+ }, action: PayloadAction<string>) => {
37
+ color: string;
38
+ appearance: ThemeAppearance;
39
+ };
40
+ }, "theme">;
41
+ declare const themeReducer: redux.Reducer<ThemeState>;
42
+
43
+ type ThemeProviderProps = {
44
+ appearance: ThemeAppearance;
45
+ color: string;
46
+ splashScreen?: boolean;
47
+ children: ReactNode;
48
+ };
49
+ declare function configureSplashScreen(options?: {
50
+ duration?: number;
51
+ fade?: boolean;
52
+ }): void;
53
+ declare function ThemeProvider({ appearance, color, splashScreen, children }: ThemeProviderProps): react.JSX.Element | null;
54
+
55
+ declare const getBlendedColor: (foreground: string, background: string, alpha: number) => string;
56
+
57
+ declare const getHex: (value: string) => string | null;
58
+
59
+ type RGB = {
60
+ r: number;
61
+ g: number;
62
+ b: number;
63
+ a?: number;
64
+ };
65
+ declare const getRgb: (value: string) => RGB | null;
66
+
67
+ type TriadicPalette = {
68
+ primary: string;
69
+ secondary: string;
70
+ tertiary: string;
71
+ };
72
+ declare function getTriadicPalette(primaryColor: string): TriadicPalette;
73
+
74
+ declare const isDarkColor: (value: string) => boolean;
75
+
76
+ export { type ComputedThemeOptions, type RGB, type ThemeAppearance, ThemeProvider, type ThemeProviderProps, type ThemeState, type TriadicPalette, configureSplashScreen, getBlendedColor, getHex, getRgb, getTriadicPalette, isDarkColor, themeActions, themeReducer, useComputedTheme };
@@ -0,0 +1,76 @@
1
+ import * as redux from 'redux';
2
+ import * as _reduxjs_toolkit from '@reduxjs/toolkit';
3
+ import { PayloadAction } from '@reduxjs/toolkit';
4
+ import { MD3Theme } from 'react-native-paper';
5
+ import * as react from 'react';
6
+ import { ReactNode } from 'react';
7
+
8
+ type ThemeAppearance = 'system' | 'light' | 'dark';
9
+ type ComputedThemeOptions = {
10
+ splashScreen?: boolean;
11
+ };
12
+ declare function useComputedTheme(appearance: ThemeAppearance, color: string, options?: ComputedThemeOptions): MD3Theme | null;
13
+
14
+ type ThemeState = {
15
+ appearance: ThemeAppearance;
16
+ color: string;
17
+ };
18
+ declare const themeActions: _reduxjs_toolkit.CaseReducerActions<{
19
+ initialize: (state: {
20
+ appearance: ThemeAppearance;
21
+ color: string;
22
+ }, action: PayloadAction<Partial<ThemeState>>) => {
23
+ appearance: ThemeAppearance;
24
+ color: string;
25
+ };
26
+ setAppearance: (state: {
27
+ appearance: ThemeAppearance;
28
+ color: string;
29
+ }, action: PayloadAction<ThemeAppearance>) => {
30
+ appearance: ThemeAppearance;
31
+ color: string;
32
+ };
33
+ setColor: (state: {
34
+ appearance: ThemeAppearance;
35
+ color: string;
36
+ }, action: PayloadAction<string>) => {
37
+ color: string;
38
+ appearance: ThemeAppearance;
39
+ };
40
+ }, "theme">;
41
+ declare const themeReducer: redux.Reducer<ThemeState>;
42
+
43
+ type ThemeProviderProps = {
44
+ appearance: ThemeAppearance;
45
+ color: string;
46
+ splashScreen?: boolean;
47
+ children: ReactNode;
48
+ };
49
+ declare function configureSplashScreen(options?: {
50
+ duration?: number;
51
+ fade?: boolean;
52
+ }): void;
53
+ declare function ThemeProvider({ appearance, color, splashScreen, children }: ThemeProviderProps): react.JSX.Element | null;
54
+
55
+ declare const getBlendedColor: (foreground: string, background: string, alpha: number) => string;
56
+
57
+ declare const getHex: (value: string) => string | null;
58
+
59
+ type RGB = {
60
+ r: number;
61
+ g: number;
62
+ b: number;
63
+ a?: number;
64
+ };
65
+ declare const getRgb: (value: string) => RGB | null;
66
+
67
+ type TriadicPalette = {
68
+ primary: string;
69
+ secondary: string;
70
+ tertiary: string;
71
+ };
72
+ declare function getTriadicPalette(primaryColor: string): TriadicPalette;
73
+
74
+ declare const isDarkColor: (value: string) => boolean;
75
+
76
+ export { type ComputedThemeOptions, type RGB, type ThemeAppearance, ThemeProvider, type ThemeProviderProps, type ThemeState, type TriadicPalette, configureSplashScreen, getBlendedColor, getHex, getRgb, getTriadicPalette, isDarkColor, themeActions, themeReducer, useComputedTheme };