@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 +189 -0
- package/dist/index.d.mts +76 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.js +2011 -0
- package/dist/index.mjs +1967 -0
- package/package.json +83 -0
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
|
package/dist/index.d.mts
ADDED
|
@@ -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 };
|
package/dist/index.d.ts
ADDED
|
@@ -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 };
|