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 { useAccessibleTheme } from '../theme/accessibility ' ;
10+ import type { Theme , ThemeProp } from '../types ' ;
1611
1712export type Props = {
1813 children : React . ReactNode ;
1914 theme ?: ThemeProp ;
2015 settings ?: Settings ;
16+ /**
17+ * Controls whether OS-level accessibility preferences (reduce motion,
18+ * bold text on iOS) are automatically reflected in the theme.
19+ * - `'auto'` (default) — PaperProvider subscribes to OS events and adapts
20+ * `theme.motion` and `theme.fonts` accordingly.
21+ * - `'off'` — no adaptation; handle accessibility in your own code.
22+ */
23+ accessibilityAdapters ?: 'auto' | 'off' ;
2124} ;
2225
2326const PaperProvider = ( props : Props ) => {
27+ const { accessibilityAdapters = 'auto' } = props ;
28+
2429 const colorSchemeName =
2530 ( ! props . theme && Appearance ?. getColorScheme ( ) ) || 'light' ;
2631
27- const [ reduceMotionEnabled , setReduceMotionEnabled ] =
28- React . useState < boolean > ( false ) ;
2932 const [ colorScheme , setColorScheme ] =
3033 React . useState < ColorSchemeName > ( colorSchemeName ) ;
3134
@@ -37,28 +40,13 @@ const PaperProvider = (props: Props) => {
3740 } ;
3841
3942 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 ;
43+ let appearanceSubscription :
44+ | ReturnType < typeof Appearance . addChangeListener >
45+ | undefined ;
5846 if ( ! props . theme ) {
5947 appearanceSubscription = Appearance ?. addChangeListener (
6048 handleAppearanceChange
61- ) as NativeEventSubscription | undefined ;
49+ ) as typeof appearanceSubscription ;
6250 }
6351 return ( ) => {
6452 if ( ! props . theme ) {
@@ -72,19 +60,20 @@ const PaperProvider = (props: Props) => {
7260 } ;
7361 } , [ props . theme ] ) ;
7462
75- const theme = React . useMemo ( ( ) => {
63+ const rawTheme = React . useMemo ( ( ) => {
7664 const scheme = colorScheme === 'dark' ? 'dark' : 'light' ;
77- const defaultThemeBase = defaultThemes [ scheme ] ;
78-
65+ const base = defaultThemes [ scheme ] ;
7966 return {
80- ...defaultThemeBase ,
67+ ...base ,
8168 ...props . theme ,
8269 animation : {
8370 ...props . theme ?. animation ,
84- scale : reduceMotionEnabled ? 0 : 1 ,
71+ scale : props . theme ?. animation ?. scale ?? 1 ,
8572 } ,
86- } ;
87- } , [ colorScheme , props . theme , reduceMotionEnabled ] ) ;
73+ } as Theme ;
74+ } , [ colorScheme , props . theme ] ) ;
75+
76+ const theme = useAccessibleTheme ( rawTheme , accessibilityAdapters === 'auto' ) ;
8877
8978 const { children, settings } = props ;
9079
0 commit comments