@rific/auto-paper 0.1.1 → 0.1.2

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
@@ -7,7 +7,7 @@ Adaptive theming for [`react-native-paper`](https://callstack.github.io/react-na
7
7
  - Triadic color palette from a single seed color (primary → secondary → tertiary, 120° apart on the color wheel)
8
8
  - System/light/dark appearance with live updates via `Appearance` API
9
9
  - Tinted surface, surfaceVariant, outline, and elevation levels derived from the seed
10
- - Optional Redux slice (`themeReducer`, `themeActions`, `selectThemeAppearance`, `selectThemeColor`) for wiring into your store
10
+ - Optional Redux slice for wiring appearance and color into your store
11
11
  - All color utilities exported for standalone use
12
12
 
13
13
  ## Installation
@@ -24,85 +24,60 @@ npm install react-native react-native-paper
24
24
 
25
25
  ## Usage
26
26
 
27
- ### ThemeProvider (simplest)
27
+ ### Provider (simplest)
28
28
 
29
29
  ```tsx
30
- import { ThemeProvider } from '@rific/auto-paper'
30
+ import { Provider as AutoPaperProvider } from '@rific/auto-paper'
31
31
 
32
32
  export default function App() {
33
33
  const [appearance, setAppearance] = useState<'system' | 'light' | 'dark'>('system')
34
34
  const [color, setColor] = useState('#6750a4')
35
35
 
36
36
  return (
37
- <ThemeProvider appearance={appearance} color={color}>
37
+ <AutoPaperProvider appearance={appearance} color={color}>
38
38
  {/* your app */}
39
- </ThemeProvider>
39
+ </AutoPaperProvider>
40
40
  )
41
41
  }
42
42
  ```
43
43
 
44
- `ThemeProvider` renders `null` on the first render while the theme computes. If you use `expo-splash-screen`, gate `SplashScreen.hideAsync()` on the theme being ready in your own component.
45
-
46
- ### With React Navigation
47
-
48
- Use the `useComputedTheme` hook directly to integrate with Navigation's `ThemeProvider`:
44
+ `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:
49
45
 
50
46
  ```tsx
51
- import { useComputedTheme } from '@rific/auto-paper'
52
- import { DarkTheme, DefaultTheme, ThemeProvider as NavThemeProvider } from '@react-navigation/native'
53
- import { Provider as PaperProvider } from 'react-native-paper'
54
-
55
- export default function App() {
56
- const theme = useComputedTheme('system', '#6750a4')
57
- if (!theme) return null
58
-
59
- const navTheme = {
60
- ...(theme.dark ? DarkTheme : DefaultTheme),
61
- colors: {
62
- ...(theme.dark ? DarkTheme : DefaultTheme).colors,
63
- background: theme.colors.background,
64
- card: theme.colors.background
65
- }
66
- }
67
-
68
- return (
69
- <NavThemeProvider value={navTheme}>
70
- <PaperProvider theme={theme}>
71
- {/* your app */}
72
- </PaperProvider>
73
- </NavThemeProvider>
74
- )
75
- }
47
+ <AutoPaperProvider appearance={appearance} color={color} onReady={SplashScreen.hideAsync}>
48
+ {/* your app */}
49
+ </AutoPaperProvider>
76
50
  ```
77
51
 
78
52
  ### With Redux
79
53
 
80
- The package exports an optional Redux slice. Add it to your store and dispatch actions to update appearance or color from settings screens:
54
+ The package exports an optional Redux slice. Use `createThemeReducer` to register it in your store with a custom initial color:
81
55
 
82
56
  ```ts
83
57
  // store.ts
84
- import { themeReducer } from '@rific/auto-paper'
58
+ import { createThemeReducer, themeActions } from '@rific/auto-paper'
85
59
 
86
60
  export const store = configureStore({
87
61
  reducer: {
88
- theme: themeReducer,
62
+ theme: createThemeReducer({ color: '#4caf50' }),
89
63
  // ...
90
64
  }
91
65
  })
92
66
  ```
93
67
 
68
+ Then read from the store and pass into `Provider`:
69
+
94
70
  ```tsx
95
71
  // App.tsx
96
72
  import { useSelector } from 'react-redux'
97
- import { ThemeProvider, selectThemeAppearance, selectThemeColor } from '@rific/auto-paper'
73
+ import { Provider as AutoPaperProvider } from '@rific/auto-paper'
98
74
 
99
75
  export default function App() {
100
- const appearance = useSelector((state: RootState) => selectThemeAppearance(state.theme))
101
- const color = useSelector((state: RootState) => selectThemeColor(state.theme))
76
+ const { appearance, color } = useSelector((state: RootState) => state.theme)
102
77
  return (
103
- <ThemeProvider appearance={appearance} color={color}>
78
+ <AutoPaperProvider appearance={appearance} color={color} onReady={SplashScreen.hideAsync}>
104
79
  {/* your app */}
105
- </ThemeProvider>
80
+ </AutoPaperProvider>
106
81
  )
107
82
  }
108
83
  ```
@@ -116,21 +91,50 @@ dispatch(themeActions.setColor('#e91e63'))
116
91
  dispatch(themeActions.setAppearance('dark'))
117
92
  ```
118
93
 
119
- The slice's initial color is `#6750a4` (MD3 default purple). Override it at startup:
94
+ ### With `useComputedTheme`
120
95
 
121
- ```ts
122
- store.dispatch(themeActions.initialize({ color: myStoredColor }))
96
+ 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:
97
+
98
+ ```tsx
99
+ import { useComputedTheme } from '@rific/auto-paper'
100
+ import { DarkTheme, DefaultTheme, ThemeProvider as NavThemeProvider } from '@react-navigation/native'
101
+ import { Provider as PaperProvider } from 'react-native-paper'
102
+
103
+ export default function App() {
104
+ const theme = useComputedTheme('system', '#6750a4')
105
+ if (!theme) return null
106
+
107
+ const navTheme = {
108
+ ...(theme.dark ? DarkTheme : DefaultTheme),
109
+ colors: {
110
+ ...(theme.dark ? DarkTheme : DefaultTheme).colors,
111
+ background: theme.colors.background,
112
+ card: theme.colors.background
113
+ }
114
+ }
115
+
116
+ return (
117
+ <NavThemeProvider value={navTheme}>
118
+ <PaperProvider theme={theme}>
119
+ {/* your app */}
120
+ </PaperProvider>
121
+ </NavThemeProvider>
122
+ )
123
+ }
123
124
  ```
124
125
 
125
126
  ## API
126
127
 
127
- ### `ThemeProvider`
128
+ ### `Provider`
128
129
 
129
- | Prop | Type | Default | Description |
130
- |---|---|---|---|
131
- | `appearance` | `'system' \| 'light' \| 'dark'` | — | Appearance mode |
132
- | `color` | `string` | — | Seed color (hex, rgb, or CSS name) |
133
- | `children` | `ReactNode` | — | |
130
+ | Prop | Type | Description |
131
+ |---|---|---|
132
+ | `appearance` | `'system' \| 'light' \| 'dark'` | Appearance mode |
133
+ | `color` | `string` | Seed color (hex, rgb, or CSS name) |
134
+ | `children` | `ReactNode` | |
135
+ | `onReady` | `() => void` | Called once when the theme first resolves |
136
+ | `statusBarProps` | `StatusBarProps` | Spread over the auto-derived `StatusBar` defaults |
137
+ | `style` | `StyleProp<ViewStyle>` | Applied to the wrapper `View` |
134
138
 
135
139
  ### `useComputedTheme(appearance, color)`
136
140
 
@@ -140,24 +144,19 @@ Returns `MD3Theme | null`. `null` on the first render while the theme computes.
140
144
  const theme = useComputedTheme('system', '#6750a4')
141
145
  ```
142
146
 
143
- ### Color utilities
144
-
145
- ```ts
146
- import { getTriadicPalette, getBlendedColor, isDarkColor, getRgb, getHex } from '@rific/auto-paper'
147
+ ### `createThemeReducer(initialState?)`
147
148
 
148
- getTriadicPalette('#ff0000')
149
- // → { primary: '#ff0000', secondary: '#00ff00', tertiary: '#0000ff' }
149
+ Returns a Redux reducer with an optional initial state override. Useful for setting a custom default color without dispatching an action at startup.
150
150
 
151
- getBlendedColor('#ff0000', '#0000ff', 0.5) // → '#800080'
152
- isDarkColor('#6750a4') // → true
153
- getRgb('coral') // → { r: 255, g: 127, b: 80 }
154
- getHex('rgb(255, 0, 0)') // → '#ff0000'
151
+ ```ts
152
+ createThemeReducer({ color: '#4caf50' })
155
153
  ```
156
154
 
157
- ### Redux slice
155
+ ### Redux exports
158
156
 
159
157
  ```ts
160
- import { themeReducer, themeActions, selectThemeAppearance, selectThemeColor, ThemeState, ThemeAppearance } from '@rific/auto-paper'
158
+ import { themeReducer, themeActions, selectThemeAppearance, selectThemeColor } from '@rific/auto-paper'
159
+ import type { ThemeState, ThemeAppearance } from '@rific/auto-paper'
161
160
  ```
162
161
 
163
162
  | Action | Payload |
@@ -166,17 +165,26 @@ import { themeReducer, themeActions, selectThemeAppearance, selectThemeColor, Th
166
165
  | `setAppearance` | `ThemeAppearance` |
167
166
  | `setColor` | `string` |
168
167
 
169
- | Selector | Returns |
170
- |---|---|
171
- | `selectThemeAppearance` | `ThemeAppearance` |
172
- | `selectThemeColor` | `string` |
173
-
174
168
  Selectors accept `ThemeState` directly — compose them with your root state selector:
175
169
 
176
170
  ```ts
177
171
  const appearance = useSelector((state: RootState) => selectThemeAppearance(state.theme))
178
172
  ```
179
173
 
174
+ ### Color utilities
175
+
176
+ ```ts
177
+ import { getTriadicPalette, getBlendedColor, isDarkColor, getRgb, getHex } from '@rific/auto-paper'
178
+
179
+ getTriadicPalette('#ff0000')
180
+ // → { primary: '#ff0000', secondary: '#00ff00', tertiary: '#0000ff' }
181
+
182
+ getBlendedColor('#ff0000', '#0000ff', 0.5) // → '#800080'
183
+ isDarkColor('#6750a4') // → true
184
+ getRgb('coral') // → { r: 255, g: 127, b: 80 }
185
+ getHex('rgb(255, 0, 0)') // → '#ff0000'
186
+ ```
187
+
180
188
  ## License
181
189
 
182
190
  MIT
package/dist/index.d.mts CHANGED
@@ -1,9 +1,10 @@
1
- import * as redux from 'redux';
2
1
  import * as _reduxjs_toolkit from '@reduxjs/toolkit';
3
2
  import { PayloadAction } from '@reduxjs/toolkit';
3
+ import * as redux from 'redux';
4
4
  import { MD3Theme } from 'react-native-paper';
5
5
  import * as react from 'react';
6
6
  import { ReactNode } from 'react';
7
+ import { StatusBarProps, StyleProp, ViewStyle } from 'react-native';
7
8
 
8
9
  type ThemeAppearance = 'system' | 'light' | 'dark';
9
10
  declare function useComputedTheme(appearance: ThemeAppearance, color: string): MD3Theme | null;
@@ -12,25 +13,20 @@ type ThemeState = {
12
13
  appearance: ThemeAppearance;
13
14
  color: string;
14
15
  };
16
+ declare function createThemeReducer(initialState?: Partial<ThemeState>): redux.Reducer<{
17
+ appearance: ThemeAppearance;
18
+ color: string;
19
+ }>;
15
20
  declare const themeActions: _reduxjs_toolkit.CaseReducerActions<{
16
- initialize: (state: {
17
- appearance: ThemeAppearance;
18
- color: string;
19
- }, action: PayloadAction<Partial<ThemeState>>) => {
21
+ initialize: (state: ThemeState, action: PayloadAction<Partial<ThemeState>>) => {
20
22
  appearance: ThemeAppearance;
21
23
  color: string;
22
24
  };
23
- setAppearance: (state: {
24
- appearance: ThemeAppearance;
25
- color: string;
26
- }, action: PayloadAction<ThemeAppearance>) => {
25
+ setAppearance: (state: ThemeState, action: PayloadAction<ThemeAppearance>) => {
27
26
  appearance: ThemeAppearance;
28
27
  color: string;
29
28
  };
30
- setColor: (state: {
31
- appearance: ThemeAppearance;
32
- color: string;
33
- }, action: PayloadAction<string>) => {
29
+ setColor: (state: ThemeState, action: PayloadAction<string>) => {
34
30
  color: string;
35
31
  appearance: ThemeAppearance;
36
32
  };
@@ -39,12 +35,15 @@ declare const themeReducer: redux.Reducer<ThemeState>;
39
35
  declare const selectThemeAppearance: (state: ThemeState) => ThemeAppearance;
40
36
  declare const selectThemeColor: (state: ThemeState) => string;
41
37
 
42
- type ThemeProviderProps = {
38
+ type ProviderProps = {
43
39
  appearance: ThemeAppearance;
44
40
  color: string;
45
41
  children: ReactNode;
42
+ onReady?: () => void;
43
+ statusBarProps?: StatusBarProps;
44
+ style?: StyleProp<ViewStyle>;
46
45
  };
47
- declare function ThemeProvider({ appearance, color, children }: ThemeProviderProps): react.JSX.Element | null;
46
+ declare function Provider({ appearance, color, children, onReady, statusBarProps, style }: ProviderProps): react.JSX.Element | null;
48
47
 
49
48
  declare const getBlendedColor: (foreground: string, background: string, alpha: number) => string;
50
49
 
@@ -67,4 +66,4 @@ declare function getTriadicPalette(primaryColor: string): TriadicPalette;
67
66
 
68
67
  declare const isDarkColor: (value: string) => boolean;
69
68
 
70
- export { type RGB, type ThemeAppearance, ThemeProvider, type ThemeProviderProps, type ThemeState, type TriadicPalette, getBlendedColor, getHex, getRgb, getTriadicPalette, isDarkColor, selectThemeAppearance, selectThemeColor, themeActions, themeReducer, useComputedTheme };
69
+ export { Provider, type ProviderProps, type RGB, type ThemeAppearance, type ThemeState, type TriadicPalette, createThemeReducer, getBlendedColor, getHex, getRgb, getTriadicPalette, isDarkColor, selectThemeAppearance, selectThemeColor, themeActions, themeReducer, useComputedTheme };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- import * as redux from 'redux';
2
1
  import * as _reduxjs_toolkit from '@reduxjs/toolkit';
3
2
  import { PayloadAction } from '@reduxjs/toolkit';
3
+ import * as redux from 'redux';
4
4
  import { MD3Theme } from 'react-native-paper';
5
5
  import * as react from 'react';
6
6
  import { ReactNode } from 'react';
7
+ import { StatusBarProps, StyleProp, ViewStyle } from 'react-native';
7
8
 
8
9
  type ThemeAppearance = 'system' | 'light' | 'dark';
9
10
  declare function useComputedTheme(appearance: ThemeAppearance, color: string): MD3Theme | null;
@@ -12,25 +13,20 @@ type ThemeState = {
12
13
  appearance: ThemeAppearance;
13
14
  color: string;
14
15
  };
16
+ declare function createThemeReducer(initialState?: Partial<ThemeState>): redux.Reducer<{
17
+ appearance: ThemeAppearance;
18
+ color: string;
19
+ }>;
15
20
  declare const themeActions: _reduxjs_toolkit.CaseReducerActions<{
16
- initialize: (state: {
17
- appearance: ThemeAppearance;
18
- color: string;
19
- }, action: PayloadAction<Partial<ThemeState>>) => {
21
+ initialize: (state: ThemeState, action: PayloadAction<Partial<ThemeState>>) => {
20
22
  appearance: ThemeAppearance;
21
23
  color: string;
22
24
  };
23
- setAppearance: (state: {
24
- appearance: ThemeAppearance;
25
- color: string;
26
- }, action: PayloadAction<ThemeAppearance>) => {
25
+ setAppearance: (state: ThemeState, action: PayloadAction<ThemeAppearance>) => {
27
26
  appearance: ThemeAppearance;
28
27
  color: string;
29
28
  };
30
- setColor: (state: {
31
- appearance: ThemeAppearance;
32
- color: string;
33
- }, action: PayloadAction<string>) => {
29
+ setColor: (state: ThemeState, action: PayloadAction<string>) => {
34
30
  color: string;
35
31
  appearance: ThemeAppearance;
36
32
  };
@@ -39,12 +35,15 @@ declare const themeReducer: redux.Reducer<ThemeState>;
39
35
  declare const selectThemeAppearance: (state: ThemeState) => ThemeAppearance;
40
36
  declare const selectThemeColor: (state: ThemeState) => string;
41
37
 
42
- type ThemeProviderProps = {
38
+ type ProviderProps = {
43
39
  appearance: ThemeAppearance;
44
40
  color: string;
45
41
  children: ReactNode;
42
+ onReady?: () => void;
43
+ statusBarProps?: StatusBarProps;
44
+ style?: StyleProp<ViewStyle>;
46
45
  };
47
- declare function ThemeProvider({ appearance, color, children }: ThemeProviderProps): react.JSX.Element | null;
46
+ declare function Provider({ appearance, color, children, onReady, statusBarProps, style }: ProviderProps): react.JSX.Element | null;
48
47
 
49
48
  declare const getBlendedColor: (foreground: string, background: string, alpha: number) => string;
50
49
 
@@ -67,4 +66,4 @@ declare function getTriadicPalette(primaryColor: string): TriadicPalette;
67
66
 
68
67
  declare const isDarkColor: (value: string) => boolean;
69
68
 
70
- export { type RGB, type ThemeAppearance, ThemeProvider, type ThemeProviderProps, type ThemeState, type TriadicPalette, getBlendedColor, getHex, getRgb, getTriadicPalette, isDarkColor, selectThemeAppearance, selectThemeColor, themeActions, themeReducer, useComputedTheme };
69
+ export { Provider, type ProviderProps, type RGB, type ThemeAppearance, type ThemeState, type TriadicPalette, createThemeReducer, getBlendedColor, getHex, getRgb, getTriadicPalette, isDarkColor, selectThemeAppearance, selectThemeColor, themeActions, themeReducer, useComputedTheme };
package/dist/index.js CHANGED
@@ -22,7 +22,8 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
22
22
  // src/index.ts
23
23
  var index_exports = {};
24
24
  __export(index_exports, {
25
- ThemeProvider: () => ThemeProvider,
25
+ Provider: () => Provider,
26
+ createThemeReducer: () => createThemeReducer,
26
27
  getBlendedColor: () => getBlendedColor,
27
28
  getHex: () => getHex,
28
29
  getRgb: () => getRgb,
@@ -960,18 +961,18 @@ function executeReducerBuilderCallback(builderCallback) {
960
961
  actionsMap[type] = reducer;
961
962
  return builder;
962
963
  },
963
- addAsyncThunk(asyncThunk, reducers) {
964
+ addAsyncThunk(asyncThunk, reducers2) {
964
965
  if (process.env.NODE_ENV !== "production") {
965
966
  if (defaultCaseReducer) {
966
967
  throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(43) : "`builder.addAsyncThunk` should only be called before calling `builder.addDefaultCase`");
967
968
  }
968
969
  }
969
- if (reducers.pending) actionsMap[asyncThunk.pending.type] = reducers.pending;
970
- if (reducers.rejected) actionsMap[asyncThunk.rejected.type] = reducers.rejected;
971
- if (reducers.fulfilled) actionsMap[asyncThunk.fulfilled.type] = reducers.fulfilled;
972
- if (reducers.settled) actionMatchers.push({
970
+ if (reducers2.pending) actionsMap[asyncThunk.pending.type] = reducers2.pending;
971
+ if (reducers2.rejected) actionsMap[asyncThunk.rejected.type] = reducers2.rejected;
972
+ if (reducers2.fulfilled) actionsMap[asyncThunk.fulfilled.type] = reducers2.fulfilled;
973
+ if (reducers2.settled) actionMatchers.push({
973
974
  matcher: asyncThunk.settled,
974
- reducer: reducers.settled
975
+ reducer: reducers2.settled
975
976
  });
976
977
  return builder;
977
978
  },
@@ -1003,7 +1004,7 @@ function executeReducerBuilderCallback(builderCallback) {
1003
1004
  function isStateFunction(x) {
1004
1005
  return typeof x === "function";
1005
1006
  }
1006
- function createReducer(initialState2, mapOrBuilderCallback) {
1007
+ function createReducer(initialState, mapOrBuilderCallback) {
1007
1008
  if (process.env.NODE_ENV !== "production") {
1008
1009
  if (typeof mapOrBuilderCallback === "object") {
1009
1010
  throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(8) : "The object notation for `createReducer` has been removed. Please use the 'builder callback' notation instead: https://redux-toolkit.js.org/api/createReducer");
@@ -1011,10 +1012,10 @@ function createReducer(initialState2, mapOrBuilderCallback) {
1011
1012
  }
1012
1013
  let [actionsMap, finalActionMatchers, finalDefaultCaseReducer] = executeReducerBuilderCallback(mapOrBuilderCallback);
1013
1014
  let getInitialState;
1014
- if (isStateFunction(initialState2)) {
1015
- getInitialState = () => freezeDraftable(initialState2());
1015
+ if (isStateFunction(initialState)) {
1016
+ getInitialState = () => freezeDraftable(initialState());
1016
1017
  } else {
1017
- const frozenInitialState = freezeDraftable(initialState2);
1018
+ const frozenInitialState = freezeDraftable(initialState);
1018
1019
  getInitialState = () => frozenInitialState;
1019
1020
  }
1020
1021
  function reducer(state = getInitialState(), action) {
@@ -1279,8 +1280,8 @@ var asyncThunkSymbol = /* @__PURE__ */ Symbol.for("rtk-slice-createasyncthunk");
1279
1280
  var asyncThunkCreator = {
1280
1281
  [asyncThunkSymbol]: createAsyncThunk
1281
1282
  };
1282
- function getType(slice2, actionKey) {
1283
- return `${slice2}/${actionKey}`;
1283
+ function getType(slice, actionKey) {
1284
+ return `${slice}/${actionKey}`;
1284
1285
  }
1285
1286
  function buildCreateSlice({
1286
1287
  creators
@@ -1299,8 +1300,8 @@ function buildCreateSlice({
1299
1300
  console.error("You must provide an `initialState` value that is not `undefined`. You may have misspelled `initialState`");
1300
1301
  }
1301
1302
  }
1302
- const reducers = (typeof options.reducers === "function" ? options.reducers(buildReducerCreators()) : options.reducers) || {};
1303
- const reducerNames = Object.keys(reducers);
1303
+ const reducers2 = (typeof options.reducers === "function" ? options.reducers(buildReducerCreators()) : options.reducers) || {};
1304
+ const reducerNames = Object.keys(reducers2);
1304
1305
  const context = {
1305
1306
  sliceCaseReducersByName: {},
1306
1307
  sliceCaseReducersByType: {},
@@ -1336,7 +1337,7 @@ function buildCreateSlice({
1336
1337
  }
1337
1338
  };
1338
1339
  reducerNames.forEach((reducerName) => {
1339
- const reducerDefinition = reducers[reducerName];
1340
+ const reducerDefinition = reducers2[reducerName];
1340
1341
  const reducerDetails = {
1341
1342
  reducerName,
1342
1343
  type: getType(name, reducerName),
@@ -1417,7 +1418,7 @@ function buildCreateSlice({
1417
1418
  selectSlice
1418
1419
  };
1419
1420
  }
1420
- const slice2 = {
1421
+ const slice = {
1421
1422
  name,
1422
1423
  reducer,
1423
1424
  actions: context.actionCreators,
@@ -1434,12 +1435,12 @@ function buildCreateSlice({
1434
1435
  reducer
1435
1436
  }, config);
1436
1437
  return {
1437
- ...slice2,
1438
+ ...slice,
1438
1439
  ...makeSelectorProps(newReducerPath, true)
1439
1440
  };
1440
1441
  }
1441
1442
  };
1442
- return slice2;
1443
+ return slice;
1443
1444
  };
1444
1445
  }
1445
1446
  function wrapSelector(selector, selectState, getInitialState, injected) {
@@ -1575,25 +1576,34 @@ function formatProdErrorMessage(code) {
1575
1576
  }
1576
1577
 
1577
1578
  // src/redux/themeSlice.ts
1578
- var initialState = {
1579
+ var defaultInitialState = {
1579
1580
  appearance: "system",
1580
1581
  color: "#6750a4"
1581
1582
  };
1582
- var slice = createSlice({
1583
+ var reducers = {
1584
+ initialize: (state, action) => ({ ...state, ...action.payload }),
1585
+ setAppearance: (state, action) => ({ ...state, appearance: action.payload }),
1586
+ setColor: (state, action) => ({ ...state, color: action.payload })
1587
+ };
1588
+ function createThemeReducer(initialState) {
1589
+ return createSlice({
1590
+ name: "theme",
1591
+ initialState: { ...defaultInitialState, ...initialState },
1592
+ reducers
1593
+ }).reducer;
1594
+ }
1595
+ var defaultSlice = createSlice({
1583
1596
  name: "theme",
1584
- initialState,
1585
- reducers: {
1586
- initialize: (state, action) => ({ ...state, ...action.payload }),
1587
- setAppearance: (state, action) => ({ ...state, appearance: action.payload }),
1588
- setColor: (state, action) => ({ ...state, color: action.payload })
1589
- }
1597
+ initialState: defaultInitialState,
1598
+ reducers
1590
1599
  });
1591
- var themeActions = slice.actions;
1592
- var themeReducer = slice.reducer;
1600
+ var themeActions = defaultSlice.actions;
1601
+ var themeReducer = defaultSlice.reducer;
1593
1602
  var selectThemeAppearance = (state) => state.appearance;
1594
1603
  var selectThemeColor = (state) => state.color;
1595
1604
 
1596
1605
  // src/ThemeProvider.tsx
1606
+ var import_react2 = require("react");
1597
1607
  var import_react_native2 = require("react-native");
1598
1608
  var import_react_native_paper2 = require("react-native-paper");
1599
1609
 
@@ -1966,17 +1976,25 @@ function useComputedTheme(appearance, color) {
1966
1976
  }
1967
1977
 
1968
1978
  // src/ThemeProvider.tsx
1969
- function ThemeProvider({ appearance, color, children }) {
1979
+ function Provider({ appearance, color, children, onReady, statusBarProps, style }) {
1970
1980
  const theme = useComputedTheme(appearance, color);
1981
+ const called = (0, import_react2.useRef)(false);
1982
+ (0, import_react2.useEffect)(() => {
1983
+ if (theme && !called.current) {
1984
+ called.current = true;
1985
+ onReady?.();
1986
+ }
1987
+ }, [theme, onReady]);
1971
1988
  if (!theme) return null;
1972
- return /* @__PURE__ */ React.createElement(import_react_native_paper2.Provider, { theme }, /* @__PURE__ */ React.createElement(import_react_native2.StatusBar, { backgroundColor: theme.colors.background, barStyle: theme.dark ? "light-content" : "dark-content" }), /* @__PURE__ */ React.createElement(import_react_native2.View, { style: styles.flex }, children));
1989
+ return /* @__PURE__ */ React.createElement(import_react_native_paper2.Provider, { theme }, /* @__PURE__ */ React.createElement(import_react_native2.StatusBar, { backgroundColor: theme.colors.background, barStyle: theme.dark ? "light-content" : "dark-content", ...statusBarProps }), /* @__PURE__ */ React.createElement(import_react_native2.View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style] }, children));
1973
1990
  }
1974
1991
  var styles = import_react_native2.StyleSheet.create({
1975
1992
  flex: { flex: 1 }
1976
1993
  });
1977
1994
  // Annotate the CommonJS export names for ESM import in node:
1978
1995
  0 && (module.exports = {
1979
- ThemeProvider,
1996
+ Provider,
1997
+ createThemeReducer,
1980
1998
  getBlendedColor,
1981
1999
  getHex,
1982
2000
  getRgb,
package/dist/index.mjs CHANGED
@@ -926,18 +926,18 @@ function executeReducerBuilderCallback(builderCallback) {
926
926
  actionsMap[type] = reducer;
927
927
  return builder;
928
928
  },
929
- addAsyncThunk(asyncThunk, reducers) {
929
+ addAsyncThunk(asyncThunk, reducers2) {
930
930
  if (process.env.NODE_ENV !== "production") {
931
931
  if (defaultCaseReducer) {
932
932
  throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(43) : "`builder.addAsyncThunk` should only be called before calling `builder.addDefaultCase`");
933
933
  }
934
934
  }
935
- if (reducers.pending) actionsMap[asyncThunk.pending.type] = reducers.pending;
936
- if (reducers.rejected) actionsMap[asyncThunk.rejected.type] = reducers.rejected;
937
- if (reducers.fulfilled) actionsMap[asyncThunk.fulfilled.type] = reducers.fulfilled;
938
- if (reducers.settled) actionMatchers.push({
935
+ if (reducers2.pending) actionsMap[asyncThunk.pending.type] = reducers2.pending;
936
+ if (reducers2.rejected) actionsMap[asyncThunk.rejected.type] = reducers2.rejected;
937
+ if (reducers2.fulfilled) actionsMap[asyncThunk.fulfilled.type] = reducers2.fulfilled;
938
+ if (reducers2.settled) actionMatchers.push({
939
939
  matcher: asyncThunk.settled,
940
- reducer: reducers.settled
940
+ reducer: reducers2.settled
941
941
  });
942
942
  return builder;
943
943
  },
@@ -969,7 +969,7 @@ function executeReducerBuilderCallback(builderCallback) {
969
969
  function isStateFunction(x) {
970
970
  return typeof x === "function";
971
971
  }
972
- function createReducer(initialState2, mapOrBuilderCallback) {
972
+ function createReducer(initialState, mapOrBuilderCallback) {
973
973
  if (process.env.NODE_ENV !== "production") {
974
974
  if (typeof mapOrBuilderCallback === "object") {
975
975
  throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(8) : "The object notation for `createReducer` has been removed. Please use the 'builder callback' notation instead: https://redux-toolkit.js.org/api/createReducer");
@@ -977,10 +977,10 @@ function createReducer(initialState2, mapOrBuilderCallback) {
977
977
  }
978
978
  let [actionsMap, finalActionMatchers, finalDefaultCaseReducer] = executeReducerBuilderCallback(mapOrBuilderCallback);
979
979
  let getInitialState;
980
- if (isStateFunction(initialState2)) {
981
- getInitialState = () => freezeDraftable(initialState2());
980
+ if (isStateFunction(initialState)) {
981
+ getInitialState = () => freezeDraftable(initialState());
982
982
  } else {
983
- const frozenInitialState = freezeDraftable(initialState2);
983
+ const frozenInitialState = freezeDraftable(initialState);
984
984
  getInitialState = () => frozenInitialState;
985
985
  }
986
986
  function reducer(state = getInitialState(), action) {
@@ -1245,8 +1245,8 @@ var asyncThunkSymbol = /* @__PURE__ */ Symbol.for("rtk-slice-createasyncthunk");
1245
1245
  var asyncThunkCreator = {
1246
1246
  [asyncThunkSymbol]: createAsyncThunk
1247
1247
  };
1248
- function getType(slice2, actionKey) {
1249
- return `${slice2}/${actionKey}`;
1248
+ function getType(slice, actionKey) {
1249
+ return `${slice}/${actionKey}`;
1250
1250
  }
1251
1251
  function buildCreateSlice({
1252
1252
  creators
@@ -1265,8 +1265,8 @@ function buildCreateSlice({
1265
1265
  console.error("You must provide an `initialState` value that is not `undefined`. You may have misspelled `initialState`");
1266
1266
  }
1267
1267
  }
1268
- const reducers = (typeof options.reducers === "function" ? options.reducers(buildReducerCreators()) : options.reducers) || {};
1269
- const reducerNames = Object.keys(reducers);
1268
+ const reducers2 = (typeof options.reducers === "function" ? options.reducers(buildReducerCreators()) : options.reducers) || {};
1269
+ const reducerNames = Object.keys(reducers2);
1270
1270
  const context = {
1271
1271
  sliceCaseReducersByName: {},
1272
1272
  sliceCaseReducersByType: {},
@@ -1302,7 +1302,7 @@ function buildCreateSlice({
1302
1302
  }
1303
1303
  };
1304
1304
  reducerNames.forEach((reducerName) => {
1305
- const reducerDefinition = reducers[reducerName];
1305
+ const reducerDefinition = reducers2[reducerName];
1306
1306
  const reducerDetails = {
1307
1307
  reducerName,
1308
1308
  type: getType(name, reducerName),
@@ -1383,7 +1383,7 @@ function buildCreateSlice({
1383
1383
  selectSlice
1384
1384
  };
1385
1385
  }
1386
- const slice2 = {
1386
+ const slice = {
1387
1387
  name,
1388
1388
  reducer,
1389
1389
  actions: context.actionCreators,
@@ -1400,12 +1400,12 @@ function buildCreateSlice({
1400
1400
  reducer
1401
1401
  }, config);
1402
1402
  return {
1403
- ...slice2,
1403
+ ...slice,
1404
1404
  ...makeSelectorProps(newReducerPath, true)
1405
1405
  };
1406
1406
  }
1407
1407
  };
1408
- return slice2;
1408
+ return slice;
1409
1409
  };
1410
1410
  }
1411
1411
  function wrapSelector(selector, selectState, getInitialState, injected) {
@@ -1541,25 +1541,34 @@ function formatProdErrorMessage(code) {
1541
1541
  }
1542
1542
 
1543
1543
  // src/redux/themeSlice.ts
1544
- var initialState = {
1544
+ var defaultInitialState = {
1545
1545
  appearance: "system",
1546
1546
  color: "#6750a4"
1547
1547
  };
1548
- var slice = createSlice({
1548
+ var reducers = {
1549
+ initialize: (state, action) => ({ ...state, ...action.payload }),
1550
+ setAppearance: (state, action) => ({ ...state, appearance: action.payload }),
1551
+ setColor: (state, action) => ({ ...state, color: action.payload })
1552
+ };
1553
+ function createThemeReducer(initialState) {
1554
+ return createSlice({
1555
+ name: "theme",
1556
+ initialState: { ...defaultInitialState, ...initialState },
1557
+ reducers
1558
+ }).reducer;
1559
+ }
1560
+ var defaultSlice = createSlice({
1549
1561
  name: "theme",
1550
- initialState,
1551
- reducers: {
1552
- initialize: (state, action) => ({ ...state, ...action.payload }),
1553
- setAppearance: (state, action) => ({ ...state, appearance: action.payload }),
1554
- setColor: (state, action) => ({ ...state, color: action.payload })
1555
- }
1562
+ initialState: defaultInitialState,
1563
+ reducers
1556
1564
  });
1557
- var themeActions = slice.actions;
1558
- var themeReducer = slice.reducer;
1565
+ var themeActions = defaultSlice.actions;
1566
+ var themeReducer = defaultSlice.reducer;
1559
1567
  var selectThemeAppearance = (state) => state.appearance;
1560
1568
  var selectThemeColor = (state) => state.color;
1561
1569
 
1562
1570
  // src/ThemeProvider.tsx
1571
+ import { useEffect as useEffect2, useRef } from "react";
1563
1572
  import { StatusBar, StyleSheet, View } from "react-native";
1564
1573
  import { Provider as PaperProvider } from "react-native-paper";
1565
1574
 
@@ -1932,16 +1941,24 @@ function useComputedTheme(appearance, color) {
1932
1941
  }
1933
1942
 
1934
1943
  // src/ThemeProvider.tsx
1935
- function ThemeProvider({ appearance, color, children }) {
1944
+ function Provider({ appearance, color, children, onReady, statusBarProps, style }) {
1936
1945
  const theme = useComputedTheme(appearance, color);
1946
+ const called = useRef(false);
1947
+ useEffect2(() => {
1948
+ if (theme && !called.current) {
1949
+ called.current = true;
1950
+ onReady?.();
1951
+ }
1952
+ }, [theme, onReady]);
1937
1953
  if (!theme) return null;
1938
- return /* @__PURE__ */ React.createElement(PaperProvider, { theme }, /* @__PURE__ */ React.createElement(StatusBar, { backgroundColor: theme.colors.background, barStyle: theme.dark ? "light-content" : "dark-content" }), /* @__PURE__ */ React.createElement(View, { style: styles.flex }, children));
1954
+ return /* @__PURE__ */ React.createElement(PaperProvider, { theme }, /* @__PURE__ */ React.createElement(StatusBar, { backgroundColor: theme.colors.background, barStyle: theme.dark ? "light-content" : "dark-content", ...statusBarProps }), /* @__PURE__ */ React.createElement(View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style] }, children));
1939
1955
  }
1940
1956
  var styles = StyleSheet.create({
1941
1957
  flex: { flex: 1 }
1942
1958
  });
1943
1959
  export {
1944
- ThemeProvider,
1960
+ Provider,
1961
+ createThemeReducer,
1945
1962
  getBlendedColor,
1946
1963
  getHex,
1947
1964
  getRgb,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rific/auto-paper",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Adaptive react-native-paper theming: triadic palette from a seed color + system/light/dark appearance",
5
5
  "keywords": [
6
6
  "react-native",