@rific/auto-paper 0.9.0 → 0.9.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 +33 -1
- package/dist/index.d.mts +14 -3
- package/dist/index.d.ts +14 -3
- package/dist/index.js +9 -4
- package/dist/index.mjs +8 -4
- package/package.json +5 -5
- package/src/ThemeProvider.tsx +10 -2
- package/src/components/Dialog.tsx +35 -7
- package/src/index.ts +2 -2
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ npm install expo-blur # frosted-glass BlurView
|
|
|
33
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
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
These integrations are opt-in: pass them to `Provider` (`expoBlur`, `navigationBar`, and `reanimated` — see the prop table below), and the relevant wrappers pick them up automatically. Omit them and you still get working fallbacks: `BlurView` renders its solid (non-blur) look, `BottomNavigation` simply skips nav-bar syncing, and `Dialog` treats `animatedStyle` as a no-op unless a reanimated module is injected.
|
|
37
37
|
|
|
38
38
|
The exported Redux slice has no dependency on `@reduxjs/toolkit`: it works with RTK stores, vanilla Redux, or no Redux at all.
|
|
39
39
|
|
|
@@ -238,6 +238,7 @@ export default function App() {
|
|
|
238
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
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 |
|
|
240
240
|
| `onReady` | `() => void` | Called once when the theme first resolves |
|
|
241
|
+
| `reanimated` | `ReanimatedModule` | Injects `react-native-reanimated` (for example `import Reanimated from 'react-native-reanimated'`) so `<Dialog animatedStyle={...}>` can animate its card on the UI thread. Omit to keep `animatedStyle` as a no-op. |
|
|
241
242
|
| `statusBarProps` | `StatusBarProps` | Spread over the auto-derived `StatusBar` defaults |
|
|
242
243
|
| `style` | `StyleProp<ViewStyle>` | Applied to the wrapper `View` |
|
|
243
244
|
|
|
@@ -255,6 +256,8 @@ export default function App() {
|
|
|
255
256
|
|
|
256
257
|
Returns `{ settings: ThemeSettings, set: (patch: Partial<ThemeSettings>) => void }`. Use this hook from any component inside `Provider` to read or update the current theme settings.
|
|
257
258
|
|
|
259
|
+
`useReanimatedModule()` is also available inside the provider tree when you need to read the injected reanimated module directly; it returns `undefined` unless `Provider` was given a `reanimated` prop.
|
|
260
|
+
|
|
258
261
|
```tsx
|
|
259
262
|
import { useThemeSettings } from '@rific/auto-paper'
|
|
260
263
|
|
|
@@ -377,6 +380,35 @@ import { Chip } from '@rific/auto-paper'
|
|
|
377
380
|
|
|
378
381
|
`ChipProps` is exported from `@rific/auto-paper` and extends `react-native-paper`'s `ChipProps` with the `variant` field. Use `PaperChipProps` if you need the base paper type.
|
|
379
382
|
|
|
383
|
+
### `Dialog`
|
|
384
|
+
|
|
385
|
+
A thin wrapper around `react-native-paper`'s `Dialog` with built-in blur support and optional UI-thread animation hooks. `blur` overrides the ambient blur setting for that dialog, and `animatedStyle` can be used to animate the card wrapper when a reanimated module has been injected into `Provider`.
|
|
386
|
+
|
|
387
|
+
```tsx
|
|
388
|
+
import { Dialog, Provider } from '@rific/auto-paper'
|
|
389
|
+
import Reanimated, { useAnimatedStyle } from 'react-native-reanimated'
|
|
390
|
+
|
|
391
|
+
function SettingsDialog({ visible }: { visible: boolean }) {
|
|
392
|
+
const animatedStyle = useAnimatedStyle(() => ({ opacity: 1 }))
|
|
393
|
+
|
|
394
|
+
return (
|
|
395
|
+
<Provider initialValue={{ appearance: 'system', color: '#6750a4' }} reanimated={Reanimated}>
|
|
396
|
+
<Dialog visible={visible} onDismiss={() => {}} animatedStyle={animatedStyle} blur>
|
|
397
|
+
{/* dialog contents */}
|
|
398
|
+
</Dialog>
|
|
399
|
+
</Provider>
|
|
400
|
+
)
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
| Prop | Type | Description |
|
|
405
|
+
|---|---|---|
|
|
406
|
+
| `blur` | `boolean` | Overrides the ambient blur setting for this component's dialog |
|
|
407
|
+
| `animatedStyle` | `unknown` | Applied to the card's outer wrapper when a reanimated module has been injected; otherwise ignored |
|
|
408
|
+
| ...all `DialogProps` | | All props from `react-native-paper`'s `Dialog` are supported |
|
|
409
|
+
|
|
410
|
+
`DialogProps` is exported from `@rific/auto-paper` and extends `react-native-paper`'s `DialogProps` with the `blur` and `animatedStyle` fields. Use `PaperDialogProps` if you need the base paper type.
|
|
411
|
+
|
|
380
412
|
### `IconButton`
|
|
381
413
|
|
|
382
414
|
A thin wrapper around `react-native-paper`'s `IconButton` that adds a `variant` prop for applying theme-derived container and icon colors.
|
package/dist/index.d.mts
CHANGED
|
@@ -127,11 +127,19 @@ type Props$2 = {
|
|
|
127
127
|
};
|
|
128
128
|
declare const ColorPicker: ({ value, onChange, colors, blur: blurProp }: Props$2) => react.JSX.Element;
|
|
129
129
|
|
|
130
|
+
interface ReanimatedModule {
|
|
131
|
+
View: ComponentType<{
|
|
132
|
+
children?: ReactNode;
|
|
133
|
+
style?: any;
|
|
134
|
+
testID?: string;
|
|
135
|
+
}>;
|
|
136
|
+
}
|
|
130
137
|
type DialogProps = Omit<DialogProps$1, 'style'> & {
|
|
131
138
|
blur?: boolean;
|
|
132
139
|
style?: StyleProp<ViewStyle>;
|
|
140
|
+
animatedStyle?: unknown;
|
|
133
141
|
};
|
|
134
|
-
declare function DialogComponent({ blur: blurProp, dismissable, dismissableBackButton, visible, onDismiss, children, style, testID }: DialogProps): react__default.JSX.Element | null;
|
|
142
|
+
declare function DialogComponent({ animatedStyle, blur: blurProp, dismissable, dismissableBackButton, visible, onDismiss, children, style, testID }: DialogProps): react__default.JSX.Element | null;
|
|
135
143
|
declare namespace DialogComponent {
|
|
136
144
|
var Title: react__default.FC<DialogTitleProps>;
|
|
137
145
|
var Content: react__default.FC<DialogContentProps>;
|
|
@@ -273,6 +281,7 @@ type NavBarContextType = {
|
|
|
273
281
|
};
|
|
274
282
|
declare const useNavBarContext: () => NavBarContextType;
|
|
275
283
|
declare const useBlurModule: () => ExpoBlurModule | undefined;
|
|
284
|
+
declare const useReanimatedModule: () => ReanimatedModule | undefined;
|
|
276
285
|
type ProviderProps = {
|
|
277
286
|
children: ReactNode;
|
|
278
287
|
defaults?: PaperDefaults;
|
|
@@ -284,10 +293,12 @@ type ProviderProps = {
|
|
|
284
293
|
onChange?: (settings: ThemeSettings) => void;
|
|
285
294
|
onNavBarChange?: (color: string, dark: boolean) => void;
|
|
286
295
|
onReady?: () => void;
|
|
296
|
+
/** Injects react-native-reanimated so `<Dialog animatedStyle={...}>` (e.g. from `useAnimatedStyle()`) can animate its card on the UI thread. Pass `import Reanimated from 'react-native-reanimated'`; omit to keep Dialog's `animatedStyle` prop a no-op. */
|
|
297
|
+
reanimated?: ReanimatedModule;
|
|
287
298
|
statusBarProps?: StatusBarProps;
|
|
288
299
|
style?: StyleProp<ViewStyle>;
|
|
289
300
|
};
|
|
290
|
-
declare function Provider({ children, defaults, expoBlur, initialValue, navigationBar, onChange, onNavBarChange, onReady, statusBarProps, style }: ProviderProps): react.JSX.Element | null;
|
|
301
|
+
declare function Provider({ children, defaults, expoBlur, initialValue, navigationBar, onChange, onNavBarChange, onReady, reanimated, statusBarProps, style }: ProviderProps): react.JSX.Element | null;
|
|
291
302
|
|
|
292
303
|
declare const useAutoPaperTheme: () => AutoPaperTheme;
|
|
293
304
|
|
|
@@ -323,4 +334,4 @@ declare const getTonalColor: (color: string, lightness: number) => string;
|
|
|
323
334
|
|
|
324
335
|
declare const isDarkColor: (value: string) => boolean;
|
|
325
336
|
|
|
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 };
|
|
337
|
+
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, 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, selectThemeAppearance, selectThemeBlur, selectThemeColor, selectThemeHarmony, themeActions, themeReducer, useAutoPaperTheme, useBlur, useBlurModule, useComputedTheme, useNavBarContext, usePaperDefaults, useReanimatedModule, useThemeSettings };
|
package/dist/index.d.ts
CHANGED
|
@@ -127,11 +127,19 @@ type Props$2 = {
|
|
|
127
127
|
};
|
|
128
128
|
declare const ColorPicker: ({ value, onChange, colors, blur: blurProp }: Props$2) => react.JSX.Element;
|
|
129
129
|
|
|
130
|
+
interface ReanimatedModule {
|
|
131
|
+
View: ComponentType<{
|
|
132
|
+
children?: ReactNode;
|
|
133
|
+
style?: any;
|
|
134
|
+
testID?: string;
|
|
135
|
+
}>;
|
|
136
|
+
}
|
|
130
137
|
type DialogProps = Omit<DialogProps$1, 'style'> & {
|
|
131
138
|
blur?: boolean;
|
|
132
139
|
style?: StyleProp<ViewStyle>;
|
|
140
|
+
animatedStyle?: unknown;
|
|
133
141
|
};
|
|
134
|
-
declare function DialogComponent({ blur: blurProp, dismissable, dismissableBackButton, visible, onDismiss, children, style, testID }: DialogProps): react__default.JSX.Element | null;
|
|
142
|
+
declare function DialogComponent({ animatedStyle, blur: blurProp, dismissable, dismissableBackButton, visible, onDismiss, children, style, testID }: DialogProps): react__default.JSX.Element | null;
|
|
135
143
|
declare namespace DialogComponent {
|
|
136
144
|
var Title: react__default.FC<DialogTitleProps>;
|
|
137
145
|
var Content: react__default.FC<DialogContentProps>;
|
|
@@ -273,6 +281,7 @@ type NavBarContextType = {
|
|
|
273
281
|
};
|
|
274
282
|
declare const useNavBarContext: () => NavBarContextType;
|
|
275
283
|
declare const useBlurModule: () => ExpoBlurModule | undefined;
|
|
284
|
+
declare const useReanimatedModule: () => ReanimatedModule | undefined;
|
|
276
285
|
type ProviderProps = {
|
|
277
286
|
children: ReactNode;
|
|
278
287
|
defaults?: PaperDefaults;
|
|
@@ -284,10 +293,12 @@ type ProviderProps = {
|
|
|
284
293
|
onChange?: (settings: ThemeSettings) => void;
|
|
285
294
|
onNavBarChange?: (color: string, dark: boolean) => void;
|
|
286
295
|
onReady?: () => void;
|
|
296
|
+
/** Injects react-native-reanimated so `<Dialog animatedStyle={...}>` (e.g. from `useAnimatedStyle()`) can animate its card on the UI thread. Pass `import Reanimated from 'react-native-reanimated'`; omit to keep Dialog's `animatedStyle` prop a no-op. */
|
|
297
|
+
reanimated?: ReanimatedModule;
|
|
287
298
|
statusBarProps?: StatusBarProps;
|
|
288
299
|
style?: StyleProp<ViewStyle>;
|
|
289
300
|
};
|
|
290
|
-
declare function Provider({ children, defaults, expoBlur, initialValue, navigationBar, onChange, onNavBarChange, onReady, statusBarProps, style }: ProviderProps): react.JSX.Element | null;
|
|
301
|
+
declare function Provider({ children, defaults, expoBlur, initialValue, navigationBar, onChange, onNavBarChange, onReady, reanimated, statusBarProps, style }: ProviderProps): react.JSX.Element | null;
|
|
291
302
|
|
|
292
303
|
declare const useAutoPaperTheme: () => AutoPaperTheme;
|
|
293
304
|
|
|
@@ -323,4 +334,4 @@ declare const getTonalColor: (color: string, lightness: number) => string;
|
|
|
323
334
|
|
|
324
335
|
declare const isDarkColor: (value: string) => boolean;
|
|
325
336
|
|
|
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 };
|
|
337
|
+
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, 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, selectThemeAppearance, selectThemeBlur, selectThemeColor, selectThemeHarmony, themeActions, themeReducer, useAutoPaperTheme, useBlur, useBlurModule, useComputedTheme, useNavBarContext, usePaperDefaults, useReanimatedModule, useThemeSettings };
|
package/dist/index.js
CHANGED
|
@@ -72,6 +72,7 @@ __export(index_exports, {
|
|
|
72
72
|
useComputedTheme: () => useComputedTheme,
|
|
73
73
|
useNavBarContext: () => useNavBarContext,
|
|
74
74
|
usePaperDefaults: () => usePaperDefaults,
|
|
75
|
+
useReanimatedModule: () => useReanimatedModule,
|
|
75
76
|
useThemeSettings: () => useThemeSettings
|
|
76
77
|
});
|
|
77
78
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -634,7 +635,9 @@ var NavBarContext = (0, import_react5.createContext)({});
|
|
|
634
635
|
var useNavBarContext = () => (0, import_react5.useContext)(NavBarContext);
|
|
635
636
|
var BlurModuleContext = (0, import_react5.createContext)(void 0);
|
|
636
637
|
var useBlurModule = () => (0, import_react5.useContext)(BlurModuleContext);
|
|
637
|
-
|
|
638
|
+
var ReanimatedModuleContext = (0, import_react5.createContext)(void 0);
|
|
639
|
+
var useReanimatedModule = () => (0, import_react5.useContext)(ReanimatedModuleContext);
|
|
640
|
+
function Provider({ children, defaults, expoBlur, initialValue, navigationBar, onChange, onNavBarChange, onReady, reanimated, statusBarProps, style }) {
|
|
638
641
|
const [settings, setSettings] = (0, import_react5.useState)(() => ({ ...defaultThemeSettings, ...initialValue }));
|
|
639
642
|
const set = (0, import_react5.useCallback)((patch) => {
|
|
640
643
|
setSettings((prev) => ({ ...prev, ...patch }));
|
|
@@ -659,7 +662,7 @@ function Provider({ children, defaults, expoBlur, initialValue, navigationBar, o
|
|
|
659
662
|
if (!theme) return null;
|
|
660
663
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ThemeSettingsContext.Provider, { value: { settings, set }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native_paper4.Provider, { theme, children: [
|
|
661
664
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.StatusBar, { backgroundColor: theme.colors.background, barStyle: theme.dark ? "light-content" : "dark-content", ...statusBarProps }),
|
|
662
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PaperDefaultsContext.Provider, { value: defaults ?? {}, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NavBarContext.Provider, { value: { navigationBar, onNavBarChange }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BlurModuleContext.Provider, { value: expoBlur, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style], children }) }) }) })
|
|
665
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PaperDefaultsContext.Provider, { value: defaults ?? {}, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NavBarContext.Provider, { value: { navigationBar, onNavBarChange }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BlurModuleContext.Provider, { value: expoBlur, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ReanimatedModuleContext.Provider, { value: reanimated, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style], children }) }) }) }) })
|
|
663
666
|
] }) });
|
|
664
667
|
}
|
|
665
668
|
var styles = import_react_native3.StyleSheet.create({
|
|
@@ -778,8 +781,9 @@ var import_react_native_safe_area_context = require("react-native-safe-area-cont
|
|
|
778
781
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
779
782
|
var ANIMATION_DURATION = 220;
|
|
780
783
|
var DIALOG_MARGIN = 32;
|
|
781
|
-
function DialogComponent({ blur: blurProp, dismissable = true, dismissableBackButton = dismissable, visible, onDismiss, children, style, testID = "dialog" }) {
|
|
784
|
+
function DialogComponent({ animatedStyle, blur: blurProp, dismissable = true, dismissableBackButton = dismissable, visible, onDismiss, children, style, testID = "dialog" }) {
|
|
782
785
|
const blur = useBlur(blurProp);
|
|
786
|
+
const reanimated = useReanimatedModule();
|
|
783
787
|
const theme = (0, import_react_native_paper9.useTheme)();
|
|
784
788
|
const { colors, isV3, roundness } = theme;
|
|
785
789
|
const { scale } = theme.animation;
|
|
@@ -820,7 +824,7 @@ function DialogComponent({ blur: blurProp, dismissable = true, dismissableBackBu
|
|
|
820
824
|
const borderRadius = (isV3 ? 7 : 1) * roundness;
|
|
821
825
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper9.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native6.Animated.View, { accessibilityLiveRegion: "polite", accessibilityViewIsModal: true, pointerEvents: visible ? "box-none" : "none", style: [import_react_native6.StyleSheet.absoluteFill, { opacity }], testID, children: [
|
|
822
826
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native6.Pressable, { accessibilityLabel: "Close modal", accessibilityRole: "button", disabled: !dismissable, onPress: dismissable ? onDismiss : void 0, style: [import_react_native6.StyleSheet.absoluteFill, { backgroundColor: colors.backdrop }], testID: `${testID}-backdrop` }),
|
|
823
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native6.View, { pointerEvents: "box-none", style: [styles2.wrapper, { marginBottom: bottom, marginTop: top, paddingHorizontal: Math.max(left, right, DIALOG_MARGIN) }], testID: `${testID}-wrapper`, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BlurView, { blur, style: [styles2.card, { borderRadius }, style], testID: `${testID}-surface`, children: content }) })
|
|
827
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native6.View, { pointerEvents: "box-none", style: [styles2.wrapper, { marginBottom: bottom, marginTop: top, paddingHorizontal: Math.max(left, right, DIALOG_MARGIN) }], testID: `${testID}-wrapper`, children: reanimated && animatedStyle ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(reanimated.View, { style: animatedStyle, testID: `${testID}-animated-wrapper`, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BlurView, { blur, style: [styles2.card, { borderRadius }, style], testID: `${testID}-surface`, children: content }) }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BlurView, { blur, style: [styles2.card, { borderRadius }, style], testID: `${testID}-surface`, children: content }) })
|
|
824
828
|
] }) });
|
|
825
829
|
}
|
|
826
830
|
DialogComponent.Title = import_react_native_paper9.Dialog.Title;
|
|
@@ -1200,5 +1204,6 @@ var getTintTextColor = (tintColor, backdropColor, tintOpacity) => {
|
|
|
1200
1204
|
useComputedTheme,
|
|
1201
1205
|
useNavBarContext,
|
|
1202
1206
|
usePaperDefaults,
|
|
1207
|
+
useReanimatedModule,
|
|
1203
1208
|
useThemeSettings
|
|
1204
1209
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -556,7 +556,9 @@ var NavBarContext = createContext3({});
|
|
|
556
556
|
var useNavBarContext = () => useContext3(NavBarContext);
|
|
557
557
|
var BlurModuleContext = createContext3(void 0);
|
|
558
558
|
var useBlurModule = () => useContext3(BlurModuleContext);
|
|
559
|
-
|
|
559
|
+
var ReanimatedModuleContext = createContext3(void 0);
|
|
560
|
+
var useReanimatedModule = () => useContext3(ReanimatedModuleContext);
|
|
561
|
+
function Provider({ children, defaults, expoBlur, initialValue, navigationBar, onChange, onNavBarChange, onReady, reanimated, statusBarProps, style }) {
|
|
560
562
|
const [settings, setSettings] = useState2(() => ({ ...defaultThemeSettings, ...initialValue }));
|
|
561
563
|
const set = useCallback2((patch) => {
|
|
562
564
|
setSettings((prev) => ({ ...prev, ...patch }));
|
|
@@ -581,7 +583,7 @@ function Provider({ children, defaults, expoBlur, initialValue, navigationBar, o
|
|
|
581
583
|
if (!theme) return null;
|
|
582
584
|
return /* @__PURE__ */ jsx3(ThemeSettingsContext.Provider, { value: { settings, set }, children: /* @__PURE__ */ jsxs2(PaperProvider, { theme, children: [
|
|
583
585
|
/* @__PURE__ */ jsx3(StatusBar2, { backgroundColor: theme.colors.background, barStyle: theme.dark ? "light-content" : "dark-content", ...statusBarProps }),
|
|
584
|
-
/* @__PURE__ */ jsx3(PaperDefaultsContext.Provider, { value: defaults ?? {}, children: /* @__PURE__ */ jsx3(NavBarContext.Provider, { value: { navigationBar, onNavBarChange }, children: /* @__PURE__ */ jsx3(BlurModuleContext.Provider, { value: expoBlur, children: /* @__PURE__ */ jsx3(View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style], children }) }) }) })
|
|
586
|
+
/* @__PURE__ */ jsx3(PaperDefaultsContext.Provider, { value: defaults ?? {}, children: /* @__PURE__ */ jsx3(NavBarContext.Provider, { value: { navigationBar, onNavBarChange }, children: /* @__PURE__ */ jsx3(BlurModuleContext.Provider, { value: expoBlur, children: /* @__PURE__ */ jsx3(ReanimatedModuleContext.Provider, { value: reanimated, children: /* @__PURE__ */ jsx3(View, { style: [styles.flex, { backgroundColor: theme.colors.background }, style], children }) }) }) }) })
|
|
585
587
|
] }) });
|
|
586
588
|
}
|
|
587
589
|
var styles = StyleSheet.create({
|
|
@@ -700,8 +702,9 @@ import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
|
700
702
|
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
701
703
|
var ANIMATION_DURATION = 220;
|
|
702
704
|
var DIALOG_MARGIN = 32;
|
|
703
|
-
function DialogComponent({ blur: blurProp, dismissable = true, dismissableBackButton = dismissable, visible, onDismiss, children, style, testID = "dialog" }) {
|
|
705
|
+
function DialogComponent({ animatedStyle, blur: blurProp, dismissable = true, dismissableBackButton = dismissable, visible, onDismiss, children, style, testID = "dialog" }) {
|
|
704
706
|
const blur = useBlur(blurProp);
|
|
707
|
+
const reanimated = useReanimatedModule();
|
|
705
708
|
const theme = useTheme5();
|
|
706
709
|
const { colors, isV3, roundness } = theme;
|
|
707
710
|
const { scale } = theme.animation;
|
|
@@ -742,7 +745,7 @@ function DialogComponent({ blur: blurProp, dismissable = true, dismissableBackBu
|
|
|
742
745
|
const borderRadius = (isV3 ? 7 : 1) * roundness;
|
|
743
746
|
return /* @__PURE__ */ jsx8(Portal, { children: /* @__PURE__ */ jsxs4(Animated.View, { accessibilityLiveRegion: "polite", accessibilityViewIsModal: true, pointerEvents: visible ? "box-none" : "none", style: [StyleSheet3.absoluteFill, { opacity }], testID, children: [
|
|
744
747
|
/* @__PURE__ */ jsx8(Pressable, { accessibilityLabel: "Close modal", accessibilityRole: "button", disabled: !dismissable, onPress: dismissable ? onDismiss : void 0, style: [StyleSheet3.absoluteFill, { backgroundColor: colors.backdrop }], testID: `${testID}-backdrop` }),
|
|
745
|
-
/* @__PURE__ */ jsx8(View3, { pointerEvents: "box-none", style: [styles2.wrapper, { marginBottom: bottom, marginTop: top, paddingHorizontal: Math.max(left, right, DIALOG_MARGIN) }], testID: `${testID}-wrapper`, children: /* @__PURE__ */ jsx8(BlurView, { blur, style: [styles2.card, { borderRadius }, style], testID: `${testID}-surface`, children: content }) })
|
|
748
|
+
/* @__PURE__ */ jsx8(View3, { pointerEvents: "box-none", style: [styles2.wrapper, { marginBottom: bottom, marginTop: top, paddingHorizontal: Math.max(left, right, DIALOG_MARGIN) }], testID: `${testID}-wrapper`, children: reanimated && animatedStyle ? /* @__PURE__ */ jsx8(reanimated.View, { style: animatedStyle, testID: `${testID}-animated-wrapper`, children: /* @__PURE__ */ jsx8(BlurView, { blur, style: [styles2.card, { borderRadius }, style], testID: `${testID}-surface`, children: content }) }) : /* @__PURE__ */ jsx8(BlurView, { blur, style: [styles2.card, { borderRadius }, style], testID: `${testID}-surface`, children: content }) })
|
|
746
749
|
] }) });
|
|
747
750
|
}
|
|
748
751
|
DialogComponent.Title = PaperDialog.Title;
|
|
@@ -1121,5 +1124,6 @@ export {
|
|
|
1121
1124
|
useComputedTheme,
|
|
1122
1125
|
useNavBarContext,
|
|
1123
1126
|
usePaperDefaults,
|
|
1127
|
+
useReanimatedModule,
|
|
1124
1128
|
useThemeSettings
|
|
1125
1129
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rific/auto-paper",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.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",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"type": "commonjs",
|
|
32
32
|
"exports": {
|
|
33
33
|
".": {
|
|
34
|
-
"react-native": "./
|
|
34
|
+
"react-native": "./src/index.ts",
|
|
35
35
|
"types": "./dist/index.d.ts",
|
|
36
36
|
"import": "./dist/index.mjs",
|
|
37
37
|
"require": "./dist/index.js"
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"main": "dist/index.js",
|
|
41
41
|
"module": "dist/index.mjs",
|
|
42
|
-
"react-native": "
|
|
42
|
+
"react-native": "src/index.ts",
|
|
43
43
|
"types": "dist/index.d.ts",
|
|
44
44
|
"files": [
|
|
45
45
|
"dist",
|
|
@@ -95,9 +95,9 @@
|
|
|
95
95
|
"typescript-eslint": "^8.59.3"
|
|
96
96
|
},
|
|
97
97
|
"peerDependencies": {
|
|
98
|
-
"expo-blur": ">=
|
|
98
|
+
"expo-blur": ">=56.0.0",
|
|
99
99
|
"expo-navigation-bar": ">=56.0.0",
|
|
100
|
-
"react": ">=
|
|
100
|
+
"react": ">=19.0.0",
|
|
101
101
|
"react-native": ">=0.76.0",
|
|
102
102
|
"react-native-paper": ">=5.0.0",
|
|
103
103
|
"react-native-safe-area-context": "*"
|
package/src/ThemeProvider.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import { StatusBar, type StatusBarProps, type StyleProp, StyleSheet, View, type
|
|
|
3
3
|
import { Provider as PaperProvider } from 'react-native-paper'
|
|
4
4
|
|
|
5
5
|
import type { ExpoBlurModule } from './components/BlurView'
|
|
6
|
+
import type { ReanimatedModule } from './components/Dialog'
|
|
6
7
|
import type { ExpoNavigationBarModule } from './navigation-bar'
|
|
7
8
|
import { type PaperDefaults, PaperDefaultsContext } from './PaperDefaultsContext'
|
|
8
9
|
import { defaultThemeSettings, type ThemeSettings, ThemeSettingsContext } from './ThemeSettingsContext'
|
|
@@ -20,6 +21,9 @@ export const useNavBarContext = () => useContext(NavBarContext)
|
|
|
20
21
|
const BlurModuleContext = createContext<ExpoBlurModule | undefined>(undefined)
|
|
21
22
|
export const useBlurModule = () => useContext(BlurModuleContext)
|
|
22
23
|
|
|
24
|
+
const ReanimatedModuleContext = createContext<ReanimatedModule | undefined>(undefined)
|
|
25
|
+
export const useReanimatedModule = () => useContext(ReanimatedModuleContext)
|
|
26
|
+
|
|
23
27
|
export type ProviderProps = {
|
|
24
28
|
children: ReactNode
|
|
25
29
|
defaults?: PaperDefaults
|
|
@@ -31,11 +35,13 @@ export type ProviderProps = {
|
|
|
31
35
|
onChange?: (settings: ThemeSettings) => void
|
|
32
36
|
onNavBarChange?: (color: string, dark: boolean) => void
|
|
33
37
|
onReady?: () => void
|
|
38
|
+
/** Injects react-native-reanimated so `<Dialog animatedStyle={...}>` (e.g. from `useAnimatedStyle()`) can animate its card on the UI thread. Pass `import Reanimated from 'react-native-reanimated'`; omit to keep Dialog's `animatedStyle` prop a no-op. */
|
|
39
|
+
reanimated?: ReanimatedModule
|
|
34
40
|
statusBarProps?: StatusBarProps
|
|
35
41
|
style?: StyleProp<ViewStyle>
|
|
36
42
|
}
|
|
37
43
|
|
|
38
|
-
export function Provider({ children, defaults, expoBlur, initialValue, navigationBar, onChange, onNavBarChange, onReady, statusBarProps, style }: ProviderProps) {
|
|
44
|
+
export function Provider({ children, defaults, expoBlur, initialValue, navigationBar, onChange, onNavBarChange, onReady, reanimated, statusBarProps, style }: ProviderProps) {
|
|
39
45
|
const [settings, setSettings] = useState<ThemeSettings>(() => ({ ...defaultThemeSettings, ...initialValue }))
|
|
40
46
|
|
|
41
47
|
const set = useCallback((patch: Partial<ThemeSettings>) => {
|
|
@@ -71,7 +77,9 @@ export function Provider({ children, defaults, expoBlur, initialValue, navigatio
|
|
|
71
77
|
<PaperDefaultsContext.Provider value={defaults ?? {}}>
|
|
72
78
|
<NavBarContext.Provider value={{ navigationBar, onNavBarChange }}>
|
|
73
79
|
<BlurModuleContext.Provider value={expoBlur}>
|
|
74
|
-
<
|
|
80
|
+
<ReanimatedModuleContext.Provider value={reanimated}>
|
|
81
|
+
<View style={[styles.flex, { backgroundColor: theme.colors.background }, style]}>{children}</View>
|
|
82
|
+
</ReanimatedModuleContext.Provider>
|
|
75
83
|
</BlurModuleContext.Provider>
|
|
76
84
|
</NavBarContext.Provider>
|
|
77
85
|
</PaperDefaultsContext.Provider>
|
|
@@ -1,16 +1,35 @@
|
|
|
1
|
-
import React, { useEffect, useRef, useState } from 'react'
|
|
1
|
+
import React, { type ComponentType, type ReactNode, useEffect, useRef, useState } from 'react'
|
|
2
2
|
import { Animated, BackHandler, Easing, Pressable, type StyleProp, StyleSheet, View, type ViewStyle } from 'react-native'
|
|
3
3
|
import { Dialog as PaperDialog, type DialogActionsProps, type DialogContentProps, type DialogProps as PaperDialogProps, type DialogScrollAreaProps, type DialogTitleProps, Portal, useTheme } from 'react-native-paper'
|
|
4
4
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
5
5
|
|
|
6
6
|
import { useBlur } from '../BlurContext'
|
|
7
|
+
import { useReanimatedModule } from '../ThemeProvider'
|
|
7
8
|
import { BlurView } from './BlurView'
|
|
8
9
|
|
|
9
|
-
//
|
|
10
|
-
//
|
|
10
|
+
// Minimal local mirror of react-native-reanimated's Animated.View — same reasoning as BlurView's
|
|
11
|
+
// ExpoBlurModule: Metro doesn't rewrite a require()-in-try/catch call into its module graph inside
|
|
12
|
+
// an ESM build, so the already-imported peer module is injected via <Provider reanimated={...}>
|
|
13
|
+
// (see ThemeProvider.tsx) instead of required directly. Only `View` is needed here. `style: any`,
|
|
14
|
+
// not a real style type — reanimated's actual AnimatedView only accepts its own branded
|
|
15
|
+
// AnimatedStyle shape, which this package never imports (no reanimated dependency at all), so `any`
|
|
16
|
+
// is the only type that both sides (this interface and the real component passed in) can agree on.
|
|
17
|
+
export interface ReanimatedModule {
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
View: ComponentType<{ children?: ReactNode; style?: any; testID?: string }>
|
|
20
|
+
}
|
|
21
|
+
|
|
11
22
|
export type DialogProps = Omit<PaperDialogProps, 'style'> & {
|
|
12
23
|
blur?: boolean
|
|
13
24
|
style?: StyleProp<ViewStyle>
|
|
25
|
+
// Applied to the card's outer wrapper instead of the card itself, and only takes effect once a
|
|
26
|
+
// reanimated module has been injected via <Provider reanimated={...}> — otherwise ignored. `style`
|
|
27
|
+
// above is a plain object read once per render, so a fast-changing value (e.g. tracking the
|
|
28
|
+
// keyboard height every frame) driven through it needs a full JS re-render per update to paint at
|
|
29
|
+
// all; wiring the same value through `animatedStyle` (e.g. the result of Reanimated's
|
|
30
|
+
// useAnimatedStyle()) instead paints on the UI thread with no JS round-trip, which is the whole
|
|
31
|
+
// difference between a smooth follow and a laggy snap.
|
|
32
|
+
animatedStyle?: unknown
|
|
14
33
|
}
|
|
15
34
|
|
|
16
35
|
// Matches react-native-paper's Modal: DEFAULT_DURATION * theme.animation.scale, eased the same way,
|
|
@@ -20,8 +39,9 @@ const ANIMATION_DURATION = 220
|
|
|
20
39
|
// Minimum breathing room between the card and the screen edge, clamped up from safe-area insets.
|
|
21
40
|
const DIALOG_MARGIN = 32
|
|
22
41
|
|
|
23
|
-
function DialogComponent({ blur: blurProp, dismissable = true, dismissableBackButton = dismissable, visible, onDismiss, children, style, testID = 'dialog' }: DialogProps) {
|
|
42
|
+
function DialogComponent({ animatedStyle, blur: blurProp, dismissable = true, dismissableBackButton = dismissable, visible, onDismiss, children, style, testID = 'dialog' }: DialogProps) {
|
|
24
43
|
const blur = useBlur(blurProp)
|
|
44
|
+
const reanimated = useReanimatedModule()
|
|
25
45
|
const theme = useTheme()
|
|
26
46
|
const { colors, isV3, roundness } = theme
|
|
27
47
|
const { scale } = theme.animation
|
|
@@ -75,9 +95,17 @@ function DialogComponent({ blur: blurProp, dismissable = true, dismissableBackBu
|
|
|
75
95
|
<Animated.View accessibilityLiveRegion='polite' accessibilityViewIsModal pointerEvents={visible ? 'box-none' : 'none'} style={[StyleSheet.absoluteFill, { opacity }]} testID={testID}>
|
|
76
96
|
<Pressable accessibilityLabel='Close modal' accessibilityRole='button' disabled={!dismissable} onPress={dismissable ? onDismiss : undefined} style={[StyleSheet.absoluteFill, { backgroundColor: colors.backdrop }]} testID={`${testID}-backdrop`} />
|
|
77
97
|
<View pointerEvents='box-none' style={[styles.wrapper, { marginBottom: bottom, marginTop: top, paddingHorizontal: Math.max(left, right, DIALOG_MARGIN) }]} testID={`${testID}-wrapper`}>
|
|
78
|
-
|
|
79
|
-
{
|
|
80
|
-
|
|
98
|
+
{reanimated && animatedStyle ? (
|
|
99
|
+
<reanimated.View style={animatedStyle} testID={`${testID}-animated-wrapper`}>
|
|
100
|
+
<BlurView blur={blur} style={[styles.card, { borderRadius }, style]} testID={`${testID}-surface`}>
|
|
101
|
+
{content}
|
|
102
|
+
</BlurView>
|
|
103
|
+
</reanimated.View>
|
|
104
|
+
) : (
|
|
105
|
+
<BlurView blur={blur} style={[styles.card, { borderRadius }, style]} testID={`${testID}-surface`}>
|
|
106
|
+
{content}
|
|
107
|
+
</BlurView>
|
|
108
|
+
)}
|
|
81
109
|
</View>
|
|
82
110
|
</Animated.View>
|
|
83
111
|
</Portal>
|
package/src/index.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type { ChipProps } from './components/Chip'
|
|
|
10
10
|
export { Chip } from './components/Chip'
|
|
11
11
|
export type { SeedColor } from './components/ColorPicker'
|
|
12
12
|
export { ColorPicker, defaultColors } from './components/ColorPicker'
|
|
13
|
-
export type { DialogProps } from './components/Dialog'
|
|
13
|
+
export type { DialogProps, ReanimatedModule } from './components/Dialog'
|
|
14
14
|
export { Dialog } from './components/Dialog'
|
|
15
15
|
export { FAB } from './components/FAB'
|
|
16
16
|
export { HarmonyPicker } from './components/HarmonyPicker'
|
|
@@ -27,7 +27,7 @@ export { usePaperDefaults } from './PaperDefaultsContext'
|
|
|
27
27
|
export type { ThemeState } from './redux/themeSlice'
|
|
28
28
|
export { createThemeReducer, selectThemeAppearance, selectThemeBlur, selectThemeColor, selectThemeHarmony, themeActions, themeReducer } from './redux/themeSlice'
|
|
29
29
|
export type { ProviderProps } from './ThemeProvider'
|
|
30
|
-
export { Provider, useBlurModule, useNavBarContext } from './ThemeProvider'
|
|
30
|
+
export { Provider, useBlurModule, useNavBarContext, useReanimatedModule } from './ThemeProvider'
|
|
31
31
|
export type { ThemeSettings, ThemeSettingsContextType } from './ThemeSettingsContext'
|
|
32
32
|
export { defaultThemeSettings, ThemeSettingsContext } from './ThemeSettingsContext'
|
|
33
33
|
export type { AutoPaperTheme, SemanticColorRoles, ThemeAppearance } from './useComputedTheme'
|