Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/babel/__fixtures__/rewrite-imports/output.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ import { MD3Colors } from "react-native-paper/lib/module/deprecated";
import { NonExistent, NonExistentSecond as Stuff } from "react-native-paper/lib/module/index.js";
import { ThemeProvider } from "react-native-paper/lib/module/core/theming";
import { withTheme } from "react-native-paper/lib/module/core/theming";
import { DefaultTheme } from "react-native-paper/lib/module/core/theming";
import { DefaultTheme } from "react-native-paper/lib/module/deprecated";
31 changes: 27 additions & 4 deletions src/core/PaperProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import { defaultThemes, ThemeProvider } from './theming';
import MaterialCommunityIcon from '../components/MaterialCommunityIcon';
import PortalHost from '../components/Portal/PortalHost';
import { useAccessibleTheme } from '../theme/accessibility';
import {
isDynamicColorSupported,
lightDynamicColors,
darkDynamicColors,
} from '../theme/schemes/DynamicTheme';
import type { Theme, ThemeProp } from '../types';

export type Props = {
Expand All @@ -19,10 +24,17 @@ export type Props = {
* accessibility in your own code.
*/
accessibilityAdapters?: boolean;
/**
* Whether to use Android Material You (dynamic) colors from the system wallpaper seed.
* When `true`, dynamic colors override `theme.colors` on Android API 31+.
* Falls back silently on unsupported platforms and API levels.
* Set to `false` (default) when providing a fully custom color theme.
*/
dynamicColor?: boolean;
};

const PaperProvider = (props: Props) => {
const { accessibilityAdapters = true } = props;
const { accessibilityAdapters = true, dynamicColor = false } = props;

const colorSchemeName =
(!props.theme && Appearance?.getColorScheme()) || 'light';
Expand Down Expand Up @@ -59,17 +71,28 @@ const PaperProvider = (props: Props) => {
}, [props.theme]);

const rawTheme = React.useMemo(() => {
const scheme = colorScheme === 'dark' ? 'dark' : 'light';
const effectiveDark = props.theme?.dark ?? colorScheme === 'dark';
const scheme = effectiveDark ? 'dark' : 'light';
const base = defaultThemes[scheme];
const isDynamic = dynamicColor && isDynamicColorSupported;
const dynamicColors = isDynamic
? scheme === 'dark'
? darkDynamicColors
: lightDynamicColors
: null;
return {
...base,
...props.theme,
...(dynamicColors
? { colors: { ...base.colors, ...dynamicColors } }
: {}),
animation: {
...props.theme?.animation,
scale: props.theme?.animation?.scale ?? 1,
},
} as Theme;
}, [colorScheme, props.theme]);
dynamic: isDynamic,
} as unknown as Theme;
}, [colorScheme, props.theme, dynamicColor]);

const theme = useAccessibleTheme(rawTheme, accessibilityAdapters !== false);

Expand Down
12 changes: 7 additions & 5 deletions src/core/__tests__/PaperProvider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ const createProvider = (theme?: ThemeProp) => {
);
};

const ExtendedLightTheme = { ...LightTheme } as ThemeProp;
const ExtendedDarkTheme = { ...DarkTheme } as ThemeProp;
const ExtendedLightTheme = { ...LightTheme, dynamic: false } as ThemeProp;
const ExtendedDarkTheme = { ...DarkTheme, dynamic: false } as ThemeProp;

describe('PaperProvider', () => {
beforeEach(() => {
Expand Down Expand Up @@ -134,6 +134,7 @@ describe('PaperProvider', () => {
expect(getByTestId('provider-child-view').props.theme).toStrictEqual({
...LightTheme,
animation: { scale: 1, defaultAnimationDuration: 250 },
dynamic: false,
});
});

Expand Down Expand Up @@ -229,8 +230,9 @@ describe('PaperProvider', () => {
},
} as ThemeProp;
const { getByTestId } = render(createProvider(customTheme));
expect(getByTestId('provider-child-view').props.theme).toStrictEqual(
customTheme
);
expect(getByTestId('provider-child-view').props.theme).toStrictEqual({
...customTheme,
dynamic: false,
});
});
});
11 changes: 11 additions & 0 deletions src/deprecated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Do not add anything here that isn't a deprecated alias.
*/

import { useTheme } from './core/theming';
import { DarkTheme } from './theme/schemes/DarkTheme';
import { LightTheme } from './theme/schemes/LightTheme';
import { Palette } from './theme/tokens';
Expand Down Expand Up @@ -45,3 +46,13 @@ export type MD3Theme = Theme;
* @deprecated Use `Elevation` instead. Will be removed in a future version.
*/
export type MD3Elevation = Elevation;

/**
* @deprecated Use `LightTheme` instead. Will be removed in a future version.
*/
export const DefaultTheme = LightTheme;

/**
* @deprecated Use `useTheme` instead. Will be removed in a future version.
*/
export { useTheme as useAppTheme };
3 changes: 2 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ export {
useTheme,
withTheme,
ThemeProvider,
DefaultTheme,
adaptNavigationTheme,
} from './core/theming';

Expand Down Expand Up @@ -168,4 +167,6 @@ export {
MD3TypescaleKey,
type MD3Theme,
type MD3Elevation,
DefaultTheme,
useAppTheme,
} from './deprecated';
10 changes: 5 additions & 5 deletions src/theme/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { ComponentType } from 'react';
import { $DeepPartial, createTheming } from '@callstack/react-theme-provider';

import { DarkTheme, LightTheme } from './schemes';
import type { InternalTheme, Theme, NavigationTheme } from '../types';
import type { Theme, NavigationTheme } from '../types';

export const DefaultTheme = LightTheme;

Expand All @@ -18,11 +18,11 @@ export function useTheme<T = Theme>(overrides?: $DeepPartial<T>) {
}

export const useInternalTheme = (
themeOverrides: $DeepPartial<InternalTheme> | undefined
) => useAppTheme<InternalTheme>(themeOverrides);
themeOverrides: $DeepPartial<Theme> | undefined
) => useAppTheme<Theme>(themeOverrides);

export const withInternalTheme = <Props extends { theme: InternalTheme }, C>(
WrappedComponent: ComponentType<Props & { theme: InternalTheme }> & C
export const withInternalTheme = <Props extends { theme: Theme }, C>(
WrappedComponent: ComponentType<Props & { theme: Theme }> & C
) => withTheme<Props, C>(WrappedComponent);

export const defaultThemes = {
Expand Down
Loading
Loading