@rific/auto-paper 0.11.0 → 0.12.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 +35 -0
- package/dist/index.d.mts +42 -1
- package/dist/index.d.ts +42 -1
- package/dist/index.js +10 -1
- package/dist/index.mjs +9 -1
- package/package.json +5 -5
- package/src/components/PalettePicker.tsx +1 -1
- package/src/index.ts +2 -0
- package/src/useThemeBridgeProps.ts +48 -0
package/README.md
CHANGED
|
@@ -201,6 +201,26 @@ dispatch(themeActions.setColor('#e91e63'))
|
|
|
201
201
|
dispatch(themeActions.setAppearance('dark'))
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
+
The `App.tsx` example above hand-builds the `initialValue`/`onReady` prop pair inline. Once you also need `onChange` wired back to `dispatch`, reach for `useThemeBridgeProps` instead of re-deriving that same three-field object by hand: it takes your already-resolved `settings`/`onChange`/`onReady` and reshapes them into the exact, memoized prop bag `Provider` expects.
|
|
205
|
+
|
|
206
|
+
```tsx
|
|
207
|
+
// Theme.tsx
|
|
208
|
+
import { Provider as AutoPaperProvider, useThemeBridgeProps } from '@rific/auto-paper'
|
|
209
|
+
import { useCallback } from 'react'
|
|
210
|
+
import { shallowEqual, useDispatch, useSelector } from 'react-redux'
|
|
211
|
+
|
|
212
|
+
export function Theme({ children }: { children: React.ReactNode }) {
|
|
213
|
+
const settings = useSelector((state: RootState) => state.theme, shallowEqual)
|
|
214
|
+
const dispatch = useDispatch()
|
|
215
|
+
const onChange = useCallback((next: ThemeSettings) => dispatch(themeActions.initialize(next)), [dispatch])
|
|
216
|
+
const bridgeProps = useThemeBridgeProps({ initialValue: settings, onChange, onReady: SplashScreen.hideAsync })
|
|
217
|
+
|
|
218
|
+
return <AutoPaperProvider {...bridgeProps}>{children}</AutoPaperProvider>
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Keep the scope honest: this only replaces the final `<Provider initialValue={...} onChange={...} onReady={...}>` prop list with `<Provider {...bridgeProps}>`. It doesn't do the `useSelector`/`useDispatch` wiring above it — that's still yours to write, since `RootState`'s shape is app-local and this package has no opinion on it (or on state management being Redux at all; `useThemeBridgeProps` takes plain values and callbacks, not a `dispatch` function).
|
|
223
|
+
|
|
204
224
|
### With `useComputedTheme`
|
|
205
225
|
|
|
206
226
|
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:
|
|
@@ -262,6 +282,21 @@ export default function App() {
|
|
|
262
282
|
| `blur` | `boolean` | `true` |
|
|
263
283
|
| `blurTint` | `number` | `0.2` |
|
|
264
284
|
|
|
285
|
+
### `useThemeBridgeProps({ initialValue, onChange, onReady })`
|
|
286
|
+
|
|
287
|
+
Reshapes already-resolved values into the exact `Pick<ProviderProps, 'initialValue' | 'onChange' | 'onReady'>` shape `Provider` expects, memoized on those three fields so the returned object is referentially stable across re-renders until an input actually changes. Meant for a consuming app's own Redux-backed "Theme" component — see "With Redux" above — but takes plain values and callbacks rather than a `dispatch` function or anything Redux-specific, so it works with any state management, or none.
|
|
288
|
+
|
|
289
|
+
It only replaces the final prop list handed to `Provider`; it does not do any `useSelector`/`dispatch` wiring itself, and `onReady` is threaded through unchanged.
|
|
290
|
+
|
|
291
|
+
```ts
|
|
292
|
+
import { useThemeBridgeProps } from '@rific/auto-paper'
|
|
293
|
+
|
|
294
|
+
const bridgeProps = useThemeBridgeProps({ initialValue: settings, onChange, onReady })
|
|
295
|
+
// → { initialValue, onChange, onReady }
|
|
296
|
+
|
|
297
|
+
<Provider {...bridgeProps}>{children}</Provider>
|
|
298
|
+
```
|
|
299
|
+
|
|
265
300
|
### `useThemeSettings()`
|
|
266
301
|
|
|
267
302
|
Returns `{ settings: ThemeSettings, set: (patch: Partial<ThemeSettings>) => void }`. Use this hook from any component inside `Provider` to read or update the current theme settings.
|
package/dist/index.d.mts
CHANGED
|
@@ -318,6 +318,47 @@ declare function Provider({ children, defaults, expoBlur, fontFamily, initialVal
|
|
|
318
318
|
|
|
319
319
|
declare const useAutoPaperTheme: () => AutoPaperTheme;
|
|
320
320
|
|
|
321
|
+
/**
|
|
322
|
+
* The subset of ProviderProps a consuming app's own Redux-backed "Theme" component is responsible
|
|
323
|
+
* for supplying. Every field here has an identically-named counterpart on ProviderProps itself
|
|
324
|
+
* (see ThemeProvider.tsx) - deliberately not renamed, so wiring this up needs no new vocabulary
|
|
325
|
+
* beyond the provider's own.
|
|
326
|
+
*/
|
|
327
|
+
type ThemeBridgeProps = Pick<ProviderProps, 'initialValue' | 'onChange' | 'onReady'>;
|
|
328
|
+
/**
|
|
329
|
+
* Reshapes an app's own Redux-sourced theme state and callbacks into the exact prop object
|
|
330
|
+
* `<Provider>` expects, so a consuming app's own "Theme" component - every game in the fleet
|
|
331
|
+
* defines one, reading `state.theme` from its own store via `useSelector(..., shallowEqual)` and
|
|
332
|
+
* dispatching `themeActions.initialize` on change - can hand its own `useSelector`/`dispatch`
|
|
333
|
+
* results straight to this hook instead of re-deriving the same three-prop shape by hand in every
|
|
334
|
+
* app:
|
|
335
|
+
*
|
|
336
|
+
* ```tsx
|
|
337
|
+
* export function Theme({ children }: Props) {
|
|
338
|
+
* const settings = useSelector((state: RootState) => state.theme, shallowEqual)
|
|
339
|
+
* const dispatch = useDispatch()
|
|
340
|
+
* const onChange = useCallback((next: ThemeSettings) => dispatch(themeActions.initialize(next)), [dispatch])
|
|
341
|
+
* const onReady = useCallback(() => markSplashReady('theme'), [])
|
|
342
|
+
* const bridgeProps = useThemeBridgeProps({ initialValue: settings, onChange, onReady })
|
|
343
|
+
* return <Provider {...bridgeProps}>{children}</Provider>
|
|
344
|
+
* }
|
|
345
|
+
* ```
|
|
346
|
+
*
|
|
347
|
+
* Deliberately takes plain values and callbacks rather than a `dispatch` function or any
|
|
348
|
+
* Redux-specific type: this package has no opinion on any app's own RootState shape, or even that
|
|
349
|
+
* state management is Redux at all - the app does its own `useSelector`/`dispatch` wiring and
|
|
350
|
+
* passes just the results in.
|
|
351
|
+
*
|
|
352
|
+
* `onReady` is threaded through completely unchanged, never recomputed or wrapped here - it fires
|
|
353
|
+
* exactly once, the first time `<Provider>` itself reports its computed theme is ready, which is
|
|
354
|
+
* the timing a consuming app's own splash-gate mark depends on. A wrong `onReady` callback (e.g.
|
|
355
|
+
* one that marks the gate ready before `<Provider>` actually is) is a bug in the app's own
|
|
356
|
+
* callback, not something this hook can catch or fix - see BoxHockey's and LightCycles' own history
|
|
357
|
+
* of hand-fixing exactly that "marked ready before Provider was actually ready" bug in their own
|
|
358
|
+
* Theme.tsx before this hook existed.
|
|
359
|
+
*/
|
|
360
|
+
declare function useThemeBridgeProps(props: ThemeBridgeProps): ThemeBridgeProps;
|
|
361
|
+
|
|
321
362
|
declare const useThemeSettings: () => _rific_core.SettingsContextValue<ThemeSettings>;
|
|
322
363
|
|
|
323
364
|
declare const getBlendedColor: (foreground: string, background: string, alpha: number) => string;
|
|
@@ -352,4 +393,4 @@ declare const isDarkColor: (value: string) => boolean;
|
|
|
352
393
|
|
|
353
394
|
declare const resolveSeedColor: (color: string | TriadicPalette) => string;
|
|
354
395
|
|
|
355
|
-
export { Appbar, type AppearanceIcons, AppearancePicker, AutoAppearancePicker, AutoPalettePicker, 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, type ReanimatedModule, 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, resolveSeedColor, selectThemeAppearance, selectThemeBlur, selectThemeColor, selectThemeHarmony, themeActions, themeReducer, useAutoPaperTheme, useBlur, useBlurModule, useComputedTheme, useNavBarContext, usePaperDefaults, useReanimatedModule, useThemeSettings };
|
|
396
|
+
export { Appbar, type AppearanceIcons, AppearancePicker, AutoAppearancePicker, AutoPalettePicker, 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, type ReanimatedModule, SEMANTIC_BASE_COLORS, type SeedColor, type SemanticColorRoles, TextInput, type ThemeAppearance, type ThemeBridgeProps, type ThemeSettings, ThemeSettingsContext, type ThemeSettingsContextType, type ThemeState, type TriadicPalette, createThemeReducer, defaultColors, defaultThemeSettings, getBlendedColor, getColorRoles, getContrastColor, getHex, getRgb, getThirdColor, getTintTextColor, getTonalColor, getTriadicPalette, isDarkColor, resolveSeedColor, selectThemeAppearance, selectThemeBlur, selectThemeColor, selectThemeHarmony, themeActions, themeReducer, useAutoPaperTheme, useBlur, useBlurModule, useComputedTheme, useNavBarContext, usePaperDefaults, useReanimatedModule, useThemeBridgeProps, useThemeSettings };
|
package/dist/index.d.ts
CHANGED
|
@@ -318,6 +318,47 @@ declare function Provider({ children, defaults, expoBlur, fontFamily, initialVal
|
|
|
318
318
|
|
|
319
319
|
declare const useAutoPaperTheme: () => AutoPaperTheme;
|
|
320
320
|
|
|
321
|
+
/**
|
|
322
|
+
* The subset of ProviderProps a consuming app's own Redux-backed "Theme" component is responsible
|
|
323
|
+
* for supplying. Every field here has an identically-named counterpart on ProviderProps itself
|
|
324
|
+
* (see ThemeProvider.tsx) - deliberately not renamed, so wiring this up needs no new vocabulary
|
|
325
|
+
* beyond the provider's own.
|
|
326
|
+
*/
|
|
327
|
+
type ThemeBridgeProps = Pick<ProviderProps, 'initialValue' | 'onChange' | 'onReady'>;
|
|
328
|
+
/**
|
|
329
|
+
* Reshapes an app's own Redux-sourced theme state and callbacks into the exact prop object
|
|
330
|
+
* `<Provider>` expects, so a consuming app's own "Theme" component - every game in the fleet
|
|
331
|
+
* defines one, reading `state.theme` from its own store via `useSelector(..., shallowEqual)` and
|
|
332
|
+
* dispatching `themeActions.initialize` on change - can hand its own `useSelector`/`dispatch`
|
|
333
|
+
* results straight to this hook instead of re-deriving the same three-prop shape by hand in every
|
|
334
|
+
* app:
|
|
335
|
+
*
|
|
336
|
+
* ```tsx
|
|
337
|
+
* export function Theme({ children }: Props) {
|
|
338
|
+
* const settings = useSelector((state: RootState) => state.theme, shallowEqual)
|
|
339
|
+
* const dispatch = useDispatch()
|
|
340
|
+
* const onChange = useCallback((next: ThemeSettings) => dispatch(themeActions.initialize(next)), [dispatch])
|
|
341
|
+
* const onReady = useCallback(() => markSplashReady('theme'), [])
|
|
342
|
+
* const bridgeProps = useThemeBridgeProps({ initialValue: settings, onChange, onReady })
|
|
343
|
+
* return <Provider {...bridgeProps}>{children}</Provider>
|
|
344
|
+
* }
|
|
345
|
+
* ```
|
|
346
|
+
*
|
|
347
|
+
* Deliberately takes plain values and callbacks rather than a `dispatch` function or any
|
|
348
|
+
* Redux-specific type: this package has no opinion on any app's own RootState shape, or even that
|
|
349
|
+
* state management is Redux at all - the app does its own `useSelector`/`dispatch` wiring and
|
|
350
|
+
* passes just the results in.
|
|
351
|
+
*
|
|
352
|
+
* `onReady` is threaded through completely unchanged, never recomputed or wrapped here - it fires
|
|
353
|
+
* exactly once, the first time `<Provider>` itself reports its computed theme is ready, which is
|
|
354
|
+
* the timing a consuming app's own splash-gate mark depends on. A wrong `onReady` callback (e.g.
|
|
355
|
+
* one that marks the gate ready before `<Provider>` actually is) is a bug in the app's own
|
|
356
|
+
* callback, not something this hook can catch or fix - see BoxHockey's and LightCycles' own history
|
|
357
|
+
* of hand-fixing exactly that "marked ready before Provider was actually ready" bug in their own
|
|
358
|
+
* Theme.tsx before this hook existed.
|
|
359
|
+
*/
|
|
360
|
+
declare function useThemeBridgeProps(props: ThemeBridgeProps): ThemeBridgeProps;
|
|
361
|
+
|
|
321
362
|
declare const useThemeSettings: () => _rific_core.SettingsContextValue<ThemeSettings>;
|
|
322
363
|
|
|
323
364
|
declare const getBlendedColor: (foreground: string, background: string, alpha: number) => string;
|
|
@@ -352,4 +393,4 @@ declare const isDarkColor: (value: string) => boolean;
|
|
|
352
393
|
|
|
353
394
|
declare const resolveSeedColor: (color: string | TriadicPalette) => string;
|
|
354
395
|
|
|
355
|
-
export { Appbar, type AppearanceIcons, AppearancePicker, AutoAppearancePicker, AutoPalettePicker, 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, type ReanimatedModule, 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, resolveSeedColor, selectThemeAppearance, selectThemeBlur, selectThemeColor, selectThemeHarmony, themeActions, themeReducer, useAutoPaperTheme, useBlur, useBlurModule, useComputedTheme, useNavBarContext, usePaperDefaults, useReanimatedModule, useThemeSettings };
|
|
396
|
+
export { Appbar, type AppearanceIcons, AppearancePicker, AutoAppearancePicker, AutoPalettePicker, 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, type ReanimatedModule, SEMANTIC_BASE_COLORS, type SeedColor, type SemanticColorRoles, TextInput, type ThemeAppearance, type ThemeBridgeProps, type ThemeSettings, ThemeSettingsContext, type ThemeSettingsContextType, type ThemeState, type TriadicPalette, createThemeReducer, defaultColors, defaultThemeSettings, getBlendedColor, getColorRoles, getContrastColor, getHex, getRgb, getThirdColor, getTintTextColor, getTonalColor, getTriadicPalette, isDarkColor, resolveSeedColor, selectThemeAppearance, selectThemeBlur, selectThemeColor, selectThemeHarmony, themeActions, themeReducer, useAutoPaperTheme, useBlur, useBlurModule, useComputedTheme, useNavBarContext, usePaperDefaults, useReanimatedModule, useThemeBridgeProps, useThemeSettings };
|
package/dist/index.js
CHANGED
|
@@ -76,6 +76,7 @@ __export(index_exports, {
|
|
|
76
76
|
useNavBarContext: () => useNavBarContext,
|
|
77
77
|
usePaperDefaults: () => usePaperDefaults,
|
|
78
78
|
useReanimatedModule: () => useReanimatedModule,
|
|
79
|
+
useThemeBridgeProps: () => useThemeBridgeProps,
|
|
79
80
|
useThemeSettings: () => useThemeSettings
|
|
80
81
|
});
|
|
81
82
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -939,8 +940,8 @@ var styles4 = import_react_native7.StyleSheet.create({
|
|
|
939
940
|
harmonyRow: { marginBottom: 4 },
|
|
940
941
|
innerRotator: { height: "100%", left: "-100%", overflow: "hidden", position: "absolute", top: 0, width: "200%" },
|
|
941
942
|
pie: { overflow: "hidden" },
|
|
942
|
-
rotator: { height: "100%", left: 0, overflow: "hidden", position: "absolute", top: 0, width: "100%" },
|
|
943
943
|
ring: { alignItems: "center", bottom: 0, justifyContent: "center", left: 0, position: "absolute", right: 0, top: 0 },
|
|
944
|
+
rotator: { height: "100%", left: 0, overflow: "hidden", position: "absolute", top: 0, width: "100%" },
|
|
944
945
|
swatch: { alignItems: "center", justifyContent: "center" },
|
|
945
946
|
swatches: { flexDirection: "row", flexWrap: "wrap", gap: SWATCH_GRID_GAP, paddingTop: 12 },
|
|
946
947
|
trigger: { alignItems: "center", alignSelf: "flex-start", borderRadius: SIZE2 / 2, height: SIZE2, justifyContent: "center", width: SIZE2 },
|
|
@@ -1078,6 +1079,13 @@ var selectThemeHarmony = themeSlice.selectors.selectHarmony;
|
|
|
1078
1079
|
var import_react_native_paper17 = require("react-native-paper");
|
|
1079
1080
|
var useAutoPaperTheme = () => (0, import_react_native_paper17.useTheme)();
|
|
1080
1081
|
|
|
1082
|
+
// src/useThemeBridgeProps.ts
|
|
1083
|
+
var import_react12 = require("react");
|
|
1084
|
+
function useThemeBridgeProps(props) {
|
|
1085
|
+
const { initialValue, onChange, onReady } = props;
|
|
1086
|
+
return (0, import_react12.useMemo)(() => ({ initialValue, onChange, onReady }), [initialValue, onChange, onReady]);
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1081
1089
|
// src/utils/getThirdColor.ts
|
|
1082
1090
|
function rgbToHsl(r, g, b) {
|
|
1083
1091
|
r /= 255;
|
|
@@ -1207,5 +1215,6 @@ var getTintTextColor = (tintColor, backdropColor, tintOpacity) => {
|
|
|
1207
1215
|
useNavBarContext,
|
|
1208
1216
|
usePaperDefaults,
|
|
1209
1217
|
useReanimatedModule,
|
|
1218
|
+
useThemeBridgeProps,
|
|
1210
1219
|
useThemeSettings
|
|
1211
1220
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -857,8 +857,8 @@ var styles4 = StyleSheet5.create({
|
|
|
857
857
|
harmonyRow: { marginBottom: 4 },
|
|
858
858
|
innerRotator: { height: "100%", left: "-100%", overflow: "hidden", position: "absolute", top: 0, width: "200%" },
|
|
859
859
|
pie: { overflow: "hidden" },
|
|
860
|
-
rotator: { height: "100%", left: 0, overflow: "hidden", position: "absolute", top: 0, width: "100%" },
|
|
861
860
|
ring: { alignItems: "center", bottom: 0, justifyContent: "center", left: 0, position: "absolute", right: 0, top: 0 },
|
|
861
|
+
rotator: { height: "100%", left: 0, overflow: "hidden", position: "absolute", top: 0, width: "100%" },
|
|
862
862
|
swatch: { alignItems: "center", justifyContent: "center" },
|
|
863
863
|
swatches: { flexDirection: "row", flexWrap: "wrap", gap: SWATCH_GRID_GAP, paddingTop: 12 },
|
|
864
864
|
trigger: { alignItems: "center", alignSelf: "flex-start", borderRadius: SIZE2 / 2, height: SIZE2, justifyContent: "center", width: SIZE2 },
|
|
@@ -996,6 +996,13 @@ var selectThemeHarmony = themeSlice.selectors.selectHarmony;
|
|
|
996
996
|
import { useTheme as usePaperTheme } from "react-native-paper";
|
|
997
997
|
var useAutoPaperTheme = () => usePaperTheme();
|
|
998
998
|
|
|
999
|
+
// src/useThemeBridgeProps.ts
|
|
1000
|
+
import { useMemo as useMemo2 } from "react";
|
|
1001
|
+
function useThemeBridgeProps(props) {
|
|
1002
|
+
const { initialValue, onChange, onReady } = props;
|
|
1003
|
+
return useMemo2(() => ({ initialValue, onChange, onReady }), [initialValue, onChange, onReady]);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
999
1006
|
// src/utils/getThirdColor.ts
|
|
1000
1007
|
function rgbToHsl(r, g, b) {
|
|
1001
1008
|
r /= 255;
|
|
@@ -1124,5 +1131,6 @@ export {
|
|
|
1124
1131
|
useNavBarContext,
|
|
1125
1132
|
usePaperDefaults,
|
|
1126
1133
|
useReanimatedModule,
|
|
1134
|
+
useThemeBridgeProps,
|
|
1127
1135
|
useThemeSettings
|
|
1128
1136
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rific/auto-paper",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
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",
|
|
@@ -68,11 +68,11 @@
|
|
|
68
68
|
"esbuild": "0.28.1"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@infinitetoken/eslint-config": "
|
|
72
|
-
"@infinitetoken/jest-config": "^0.
|
|
73
|
-
"@infinitetoken/tsconfig": "^0.
|
|
71
|
+
"@infinitetoken/eslint-config": "0.2.0",
|
|
72
|
+
"@infinitetoken/jest-config": "^0.4.0",
|
|
73
|
+
"@infinitetoken/tsconfig": "^0.5.0",
|
|
74
74
|
"@reduxjs/toolkit": "^2.0.0",
|
|
75
|
-
"@rific/core": "^0.
|
|
75
|
+
"@rific/core": "^0.2.0",
|
|
76
76
|
"@testing-library/dom": "^10.4.1",
|
|
77
77
|
"@testing-library/react": "^16.0.0",
|
|
78
78
|
"@types/jest": "^30.0.0",
|
|
@@ -119,8 +119,8 @@ const styles = StyleSheet.create({
|
|
|
119
119
|
harmonyRow: { marginBottom: 4 },
|
|
120
120
|
innerRotator: { height: '100%', left: '-100%', overflow: 'hidden', position: 'absolute', top: 0, width: '200%' },
|
|
121
121
|
pie: { overflow: 'hidden' },
|
|
122
|
-
rotator: { height: '100%', left: 0, overflow: 'hidden', position: 'absolute', top: 0, width: '100%' },
|
|
123
122
|
ring: { alignItems: 'center', bottom: 0, justifyContent: 'center', left: 0, position: 'absolute', right: 0, top: 0 },
|
|
123
|
+
rotator: { height: '100%', left: 0, overflow: 'hidden', position: 'absolute', top: 0, width: '100%' },
|
|
124
124
|
swatch: { alignItems: 'center', justifyContent: 'center' },
|
|
125
125
|
swatches: { flexDirection: 'row', flexWrap: 'wrap', gap: SWATCH_GRID_GAP, paddingTop: 12 },
|
|
126
126
|
trigger: { alignItems: 'center', alignSelf: 'flex-start', borderRadius: SIZE / 2, height: SIZE, justifyContent: 'center', width: SIZE },
|
package/src/index.ts
CHANGED
|
@@ -35,6 +35,8 @@ export { defaultThemeSettings, ThemeSettingsContext } from './ThemeSettingsConte
|
|
|
35
35
|
export type { AutoPaperTheme, SemanticColorRoles, ThemeAppearance } from './useComputedTheme'
|
|
36
36
|
export { SEMANTIC_BASE_COLORS, useComputedTheme } from './useComputedTheme'
|
|
37
37
|
export { useAutoPaperTheme } from './useTheme'
|
|
38
|
+
export type { ThemeBridgeProps } from './useThemeBridgeProps'
|
|
39
|
+
export { useThemeBridgeProps } from './useThemeBridgeProps'
|
|
38
40
|
export { useThemeSettings } from './useThemeSettings'
|
|
39
41
|
export { getBlendedColor } from './utils/getBlendedColor'
|
|
40
42
|
export type { ColorRoles } from './utils/getColorRoles'
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { useMemo } from 'react'
|
|
2
|
+
|
|
3
|
+
import type { ProviderProps } from './ThemeProvider'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The subset of ProviderProps a consuming app's own Redux-backed "Theme" component is responsible
|
|
7
|
+
* for supplying. Every field here has an identically-named counterpart on ProviderProps itself
|
|
8
|
+
* (see ThemeProvider.tsx) - deliberately not renamed, so wiring this up needs no new vocabulary
|
|
9
|
+
* beyond the provider's own.
|
|
10
|
+
*/
|
|
11
|
+
export type ThemeBridgeProps = Pick<ProviderProps, 'initialValue' | 'onChange' | 'onReady'>
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Reshapes an app's own Redux-sourced theme state and callbacks into the exact prop object
|
|
15
|
+
* `<Provider>` expects, so a consuming app's own "Theme" component - every game in the fleet
|
|
16
|
+
* defines one, reading `state.theme` from its own store via `useSelector(..., shallowEqual)` and
|
|
17
|
+
* dispatching `themeActions.initialize` on change - can hand its own `useSelector`/`dispatch`
|
|
18
|
+
* results straight to this hook instead of re-deriving the same three-prop shape by hand in every
|
|
19
|
+
* app:
|
|
20
|
+
*
|
|
21
|
+
* ```tsx
|
|
22
|
+
* export function Theme({ children }: Props) {
|
|
23
|
+
* const settings = useSelector((state: RootState) => state.theme, shallowEqual)
|
|
24
|
+
* const dispatch = useDispatch()
|
|
25
|
+
* const onChange = useCallback((next: ThemeSettings) => dispatch(themeActions.initialize(next)), [dispatch])
|
|
26
|
+
* const onReady = useCallback(() => markSplashReady('theme'), [])
|
|
27
|
+
* const bridgeProps = useThemeBridgeProps({ initialValue: settings, onChange, onReady })
|
|
28
|
+
* return <Provider {...bridgeProps}>{children}</Provider>
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* Deliberately takes plain values and callbacks rather than a `dispatch` function or any
|
|
33
|
+
* Redux-specific type: this package has no opinion on any app's own RootState shape, or even that
|
|
34
|
+
* state management is Redux at all - the app does its own `useSelector`/`dispatch` wiring and
|
|
35
|
+
* passes just the results in.
|
|
36
|
+
*
|
|
37
|
+
* `onReady` is threaded through completely unchanged, never recomputed or wrapped here - it fires
|
|
38
|
+
* exactly once, the first time `<Provider>` itself reports its computed theme is ready, which is
|
|
39
|
+
* the timing a consuming app's own splash-gate mark depends on. A wrong `onReady` callback (e.g.
|
|
40
|
+
* one that marks the gate ready before `<Provider>` actually is) is a bug in the app's own
|
|
41
|
+
* callback, not something this hook can catch or fix - see BoxHockey's and LightCycles' own history
|
|
42
|
+
* of hand-fixing exactly that "marked ready before Provider was actually ready" bug in their own
|
|
43
|
+
* Theme.tsx before this hook existed.
|
|
44
|
+
*/
|
|
45
|
+
export function useThemeBridgeProps(props: ThemeBridgeProps): ThemeBridgeProps {
|
|
46
|
+
const { initialValue, onChange, onReady } = props
|
|
47
|
+
return useMemo(() => ({ initialValue, onChange, onReady }), [initialValue, onChange, onReady])
|
|
48
|
+
}
|