11import * as React from 'react' ;
2- import {
3- AccessibilityInfo ,
4- Appearance ,
5- ColorSchemeName ,
6- NativeEventSubscription ,
7- } from 'react-native' ;
2+ import { Appearance , ColorSchemeName } from 'react-native' ;
83
94import SafeAreaProviderCompat from './SafeAreaProviderCompat' ;
105import { Provider as SettingsProvider , Settings } from './settings' ;
116import { defaultThemes , ThemeProvider } from './theming' ;
127import MaterialCommunityIcon from '../components/MaterialCommunityIcon' ;
138import PortalHost from '../components/Portal/PortalHost' ;
14- import type { ThemeProp } from '../types' ;
15- import { addEventListener } from '../utils/addEventListener' ;
9+ import { ReduceMotionContext } from '../theme/accessibility/ReduceMotionContext' ;
10+ import {
11+ useResolvedReduceMotion ,
12+ type ReduceMotionPreference ,
13+ } from '../theme/accessibility/useResolvedReduceMotion' ;
14+ import type { Theme , ThemeProp } from '../types' ;
1615
1716export type Props = {
1817 children : React . ReactNode ;
1918 theme ?: ThemeProp ;
2019 settings ?: Settings ;
20+ reduceMotion ?: ReduceMotionPreference ;
2121} ;
2222
2323const PaperProvider = ( props : Props ) => {
24+ const { reduceMotion = 'auto' } = props ;
25+
2426 const colorSchemeName =
2527 ( ! props . theme && Appearance ?. getColorScheme ( ) ) || 'light' ;
2628
27- const [ reduceMotionEnabled , setReduceMotionEnabled ] =
28- React . useState < boolean > ( false ) ;
2929 const [ colorScheme , setColorScheme ] =
3030 React . useState < ColorSchemeName > ( colorSchemeName ) ;
3131
32+ const resolvedReduceMotion = useResolvedReduceMotion ( reduceMotion ) ;
33+
3234 const handleAppearanceChange = (
3335 preferences : Appearance . AppearancePreferences
3436 ) => {
@@ -37,28 +39,13 @@ const PaperProvider = (props: Props) => {
3739 } ;
3840
3941 React . useEffect ( ( ) => {
40- let subscription : NativeEventSubscription | undefined ;
41-
42- if ( ! props . theme ) {
43- subscription = addEventListener (
44- AccessibilityInfo ,
45- 'reduceMotionChanged' ,
46- setReduceMotionEnabled
47- ) ;
48- }
49- return ( ) => {
50- if ( ! props . theme ) {
51- subscription ?. remove ( ) ;
52- }
53- } ;
54- } , [ props . theme ] ) ;
55-
56- React . useEffect ( ( ) => {
57- let appearanceSubscription : NativeEventSubscription | undefined ;
42+ let appearanceSubscription :
43+ | ReturnType < typeof Appearance . addChangeListener >
44+ | undefined ;
5845 if ( ! props . theme ) {
5946 appearanceSubscription = Appearance ?. addChangeListener (
6047 handleAppearanceChange
61- ) as NativeEventSubscription | undefined ;
48+ ) as typeof appearanceSubscription ;
6249 }
6350 return ( ) => {
6451 if ( ! props . theme ) {
@@ -72,19 +59,18 @@ const PaperProvider = (props: Props) => {
7259 } ;
7360 } , [ props . theme ] ) ;
7461
75- const theme = React . useMemo ( ( ) => {
62+ const theme = React . useMemo < Theme > ( ( ) => {
7663 const scheme = colorScheme === 'dark' ? 'dark' : 'light' ;
77- const defaultThemeBase = defaultThemes [ scheme ] ;
78-
64+ const base = defaultThemes [ scheme ] ;
7965 return {
80- ...defaultThemeBase ,
66+ ...base ,
8167 ...props . theme ,
8268 animation : {
8369 ...props . theme ?. animation ,
84- scale : reduceMotionEnabled ? 0 : 1 ,
70+ scale : resolvedReduceMotion ? 0 : props . theme ?. animation ?. scale ?? 1 ,
8571 } ,
86- } ;
87- } , [ colorScheme , props . theme , reduceMotionEnabled ] ) ;
72+ } as Theme ;
73+ } , [ colorScheme , props . theme , resolvedReduceMotion ] ) ;
8874
8975 const { children, settings } = props ;
9076
@@ -101,7 +87,9 @@ const PaperProvider = (props: Props) => {
10187 < SafeAreaProviderCompat >
10288 < PortalHost >
10389 < SettingsProvider value = { settingsValue } >
104- < ThemeProvider theme = { theme } > { children } </ ThemeProvider >
90+ < ReduceMotionContext . Provider value = { resolvedReduceMotion } >
91+ < ThemeProvider theme = { theme } > { children } </ ThemeProvider >
92+ </ ReduceMotionContext . Provider >
10593 </ SettingsProvider >
10694 </ PortalHost >
10795 </ SafeAreaProviderCompat >
0 commit comments