From 61df1abe3b10dd51f9d9f2ddf229941f3afb1aba Mon Sep 17 00:00:00 2001 From: Adrian Cotfas Date: Mon, 4 May 2026 15:54:18 +0300 Subject: [PATCH] refactor: move styles/ into src/theme/ tree --- src/components/Appbar/AppbarHeader.tsx | 2 +- src/components/Appbar/utils.ts | 2 +- src/components/Avatar/AvatarIcon.tsx | 2 +- src/components/Avatar/AvatarText.tsx | 2 +- src/components/Button/utils.tsx | 4 +- src/components/Card/CardCover.tsx | 2 +- src/components/Checkbox/CheckboxItem.tsx | 2 +- src/components/Checkbox/utils.ts | 2 +- src/components/Chip/Chip.tsx | 2 +- src/components/Chip/helpers.tsx | 2 +- src/components/Drawer/DrawerSection.tsx | 2 +- src/components/HelperText/utils.ts | 2 +- src/components/IconButton/utils.ts | 2 +- src/components/MaterialCommunityIcon.tsx | 2 +- src/components/Menu/utils.ts | 2 +- src/components/Modal.tsx | 2 +- .../RadioButton/RadioButtonItem.tsx | 2 +- src/components/SegmentedButtons/utils.ts | 2 +- src/components/Surface.tsx | 2 +- src/components/Switch/utils.ts | 2 +- src/components/TextInput/Adornment/utils.ts | 2 +- src/components/TextInput/helpers.tsx | 2 +- src/components/__tests__/AnimatedFAB.test.tsx | 2 +- .../__tests__/Appbar/Appbar.test.tsx | 2 +- src/components/__tests__/Avatar.test.tsx | 2 +- src/components/__tests__/Badge.test.tsx | 2 +- .../__tests__/BottomNavigation.test.tsx | 2 +- src/components/__tests__/Button.test.tsx | 4 +- src/components/__tests__/Card/Card.test.tsx | 2 +- .../__tests__/Checkbox/utils.test.tsx | 2 +- src/components/__tests__/Chip.test.tsx | 2 +- src/components/__tests__/IconButton.test.tsx | 4 +- .../__tests__/ListAccordion.test.tsx | 2 +- src/components/__tests__/ListItem.test.tsx | 2 +- src/components/__tests__/ListSection.test.tsx | 2 +- src/components/__tests__/MenuItem.test.tsx | 2 +- src/components/__tests__/Modal.test.tsx | 4 +- .../__tests__/SegmentedButton.test.tsx | 2 +- src/components/__tests__/Snackbar.test.tsx | 2 +- src/components/__tests__/Switch.test.tsx | 2 +- src/components/__tests__/TextInput.test.tsx | 4 +- .../__tests__/Typography/Text.test.tsx | 6 +- src/core/__tests__/PaperProvider.test.tsx | 2 +- src/core/__tests__/theming.test.tsx | 2 +- src/core/theming.tsx | 139 +------------- src/deprecated.ts | 6 +- src/index.tsx | 8 +- src/{styles => theme}/__tests__/fonts.test.js | 2 +- src/{styles/themes => theme}/colors.tsx | 0 src/{styles => theme}/fonts.tsx | 2 +- src/theme/provider.tsx | 138 ++++++++++++++ .../themes => theme/schemes}/DarkTheme.tsx | 2 +- .../schemes}/DynamicTheme.android.tsx | 0 .../themes => theme/schemes}/DynamicTheme.tsx | 0 .../themes => theme/schemes}/LightTheme.tsx | 2 +- src/{styles/themes => theme/schemes}/index.ts | 0 src/{styles => theme}/shadow.tsx | 2 +- .../tokens.tsx => theme/tokens/index.ts} | 0 src/theme/types.ts | 179 +++++++++++++++++ src/types.tsx | 180 +----------------- 60 files changed, 382 insertions(+), 380 deletions(-) rename src/{styles => theme}/__tests__/fonts.test.js (98%) rename src/{styles/themes => theme}/colors.tsx (100%) rename src/{styles => theme}/fonts.tsx (97%) create mode 100644 src/theme/provider.tsx rename src/{styles/themes => theme/schemes}/DarkTheme.tsx (98%) rename src/{styles/themes => theme/schemes}/DynamicTheme.android.tsx (100%) rename src/{styles/themes => theme/schemes}/DynamicTheme.tsx (100%) rename src/{styles/themes => theme/schemes}/LightTheme.tsx (98%) rename src/{styles/themes => theme/schemes}/index.ts (100%) rename src/{styles => theme}/shadow.tsx (96%) rename src/{styles/themes/tokens.tsx => theme/tokens/index.ts} (100%) create mode 100644 src/theme/types.ts diff --git a/src/components/Appbar/AppbarHeader.tsx b/src/components/Appbar/AppbarHeader.tsx index 9efe81bba1..ed4ecce48d 100644 --- a/src/components/Appbar/AppbarHeader.tsx +++ b/src/components/Appbar/AppbarHeader.tsx @@ -18,7 +18,7 @@ import { getAppbarBorders, } from './utils'; import { useInternalTheme } from '../../core/theming'; -import shadow from '../../styles/shadow'; +import shadow from '../../theme/shadow'; import type { ThemeProp } from '../../types'; export type Props = Omit< diff --git a/src/components/Appbar/utils.ts b/src/components/Appbar/utils.ts index fe40f1129c..fbd2e7f461 100644 --- a/src/components/Appbar/utils.ts +++ b/src/components/Appbar/utils.ts @@ -2,7 +2,7 @@ import React from 'react'; import type { ColorValue, StyleProp, ViewStyle } from 'react-native'; import { StyleSheet, Animated } from 'react-native'; -import { white } from '../../styles/themes/colors'; +import { white } from '../../theme/colors'; import type { InternalTheme, Theme, ThemeProp } from '../../types'; export type AppbarModes = 'small' | 'medium' | 'large' | 'center-aligned'; diff --git a/src/components/Avatar/AvatarIcon.tsx b/src/components/Avatar/AvatarIcon.tsx index 80ae6f68d3..44e543561a 100644 --- a/src/components/Avatar/AvatarIcon.tsx +++ b/src/components/Avatar/AvatarIcon.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'; import { useInternalTheme } from '../../core/theming'; -import { white } from '../../styles/themes/colors'; +import { white } from '../../theme/colors'; import type { ThemeProp } from '../../types'; import getContrastingColor from '../../utils/getContrastingColor'; import Icon, { IconSource } from '../Icon'; diff --git a/src/components/Avatar/AvatarText.tsx b/src/components/Avatar/AvatarText.tsx index b6bd27623a..4014dbb3b0 100644 --- a/src/components/Avatar/AvatarText.tsx +++ b/src/components/Avatar/AvatarText.tsx @@ -9,7 +9,7 @@ import { } from 'react-native'; import { useInternalTheme } from '../../core/theming'; -import { white } from '../../styles/themes/colors'; +import { white } from '../../theme/colors'; import type { ThemeProp } from '../../types'; import getContrastingColor from '../../utils/getContrastingColor'; import Text from '../Typography/Text'; diff --git a/src/components/Button/utils.tsx b/src/components/Button/utils.tsx index ff0dd218fd..37038afbd7 100644 --- a/src/components/Button/utils.tsx +++ b/src/components/Button/utils.tsx @@ -1,7 +1,7 @@ import type { ViewStyle } from 'react-native'; -import { black, white } from '../../styles/themes/colors'; -import { tokens } from '../../styles/themes/tokens'; +import { black, white } from '../../theme/colors'; +import { tokens } from '../../theme/tokens'; import type { InternalTheme, Theme } from '../../types'; import { splitStyles } from '../../utils/splitStyles'; diff --git a/src/components/Card/CardCover.tsx b/src/components/Card/CardCover.tsx index 5364c09068..43d01cd852 100644 --- a/src/components/Card/CardCover.tsx +++ b/src/components/Card/CardCover.tsx @@ -3,7 +3,7 @@ import { Image, StyleProp, StyleSheet, View, ViewStyle } from 'react-native'; import { getCardCoverStyle } from './utils'; import { useInternalTheme } from '../../core/theming'; -import { grey200 } from '../../styles/themes/colors'; +import { grey200 } from '../../theme/colors'; import type { ThemeProp } from '../../types'; import { splitStyles } from '../../utils/splitStyles'; diff --git a/src/components/Checkbox/CheckboxItem.tsx b/src/components/Checkbox/CheckboxItem.tsx index 4ad9eafa53..008f03640d 100644 --- a/src/components/Checkbox/CheckboxItem.tsx +++ b/src/components/Checkbox/CheckboxItem.tsx @@ -13,7 +13,7 @@ import Checkbox from './Checkbox'; import CheckboxAndroid from './CheckboxAndroid'; import CheckboxIOS from './CheckboxIOS'; import { useInternalTheme } from '../../core/theming'; -import { tokens } from '../../styles/themes/tokens'; +import { tokens } from '../../theme/tokens'; import type { ThemeProp, TypescaleKey } from '../../types'; import TouchableRipple, { Props as TouchableRippleProps, diff --git a/src/components/Checkbox/utils.ts b/src/components/Checkbox/utils.ts index 025717f308..626b45e1d2 100644 --- a/src/components/Checkbox/utils.ts +++ b/src/components/Checkbox/utils.ts @@ -1,4 +1,4 @@ -import { tokens } from '../../styles/themes/tokens'; +import { tokens } from '../../theme/tokens'; import type { InternalTheme } from '../../types'; const { stateOpacity } = tokens.md.ref; diff --git a/src/components/Chip/Chip.tsx b/src/components/Chip/Chip.tsx index b6e3e1d282..fe3b30ab49 100644 --- a/src/components/Chip/Chip.tsx +++ b/src/components/Chip/Chip.tsx @@ -17,7 +17,7 @@ import useLatestCallback from 'use-latest-callback'; import { ChipAvatarProps, getChipColors } from './helpers'; import { useInternalTheme } from '../../core/theming'; -import { white } from '../../styles/themes/colors'; +import { white } from '../../theme/colors'; import type { $Omit, EllipsizeProp, Theme, ThemeProp } from '../../types'; import hasTouchHandler from '../../utils/hasTouchHandler'; import type { IconSource } from '../Icon'; diff --git a/src/components/Chip/helpers.tsx b/src/components/Chip/helpers.tsx index 4990760d3c..af72870edf 100644 --- a/src/components/Chip/helpers.tsx +++ b/src/components/Chip/helpers.tsx @@ -2,7 +2,7 @@ import type { ColorValue, StyleProp, ViewStyle } from 'react-native'; import color from 'color'; -import { tokens } from '../../styles/themes/tokens'; +import { tokens } from '../../theme/tokens'; import type { InternalTheme, Theme } from '../../types'; const md3 = (theme: InternalTheme) => theme as Theme; diff --git a/src/components/Drawer/DrawerSection.tsx b/src/components/Drawer/DrawerSection.tsx index 891a5aee98..14a44dcd6f 100644 --- a/src/components/Drawer/DrawerSection.tsx +++ b/src/components/Drawer/DrawerSection.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'; import { useInternalTheme } from '../../core/theming'; -import { Palette } from '../../styles/themes/tokens'; +import { Palette } from '../../theme/tokens'; import type { ThemeProp } from '../../types'; import Divider from '../Divider'; import Text from '../Typography/Text'; diff --git a/src/components/HelperText/utils.ts b/src/components/HelperText/utils.ts index 214948c767..6c7fe16a58 100644 --- a/src/components/HelperText/utils.ts +++ b/src/components/HelperText/utils.ts @@ -1,4 +1,4 @@ -import { tokens } from '../../styles/themes/tokens'; +import { tokens } from '../../theme/tokens'; import type { InternalTheme } from '../../types'; const { stateOpacity } = tokens.md.ref; diff --git a/src/components/IconButton/utils.ts b/src/components/IconButton/utils.ts index 53586925b7..63ef8022c7 100644 --- a/src/components/IconButton/utils.ts +++ b/src/components/IconButton/utils.ts @@ -1,4 +1,4 @@ -import { tokens } from '../../styles/themes/tokens'; +import { tokens } from '../../theme/tokens'; import type { InternalTheme } from '../../types'; const { stateOpacity } = tokens.md.ref; diff --git a/src/components/MaterialCommunityIcon.tsx b/src/components/MaterialCommunityIcon.tsx index 9426be685b..8c1704a3de 100644 --- a/src/components/MaterialCommunityIcon.tsx +++ b/src/components/MaterialCommunityIcon.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { ComponentProps } from 'react'; import { StyleSheet, Text, Platform, Role, ViewProps } from 'react-native'; -import { black } from '../styles/themes/colors'; +import { black } from '../theme/colors'; export type IconProps = { name: ComponentProps['name']; diff --git a/src/components/Menu/utils.ts b/src/components/Menu/utils.ts index 4288676bbd..9d17a863e6 100644 --- a/src/components/Menu/utils.ts +++ b/src/components/Menu/utils.ts @@ -1,4 +1,4 @@ -import { tokens } from '../../styles/themes/tokens'; +import { tokens } from '../../theme/tokens'; import type { InternalTheme } from '../../types'; import type { IconSource } from '../Icon'; diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx index 368f9e245f..040c3a5706 100644 --- a/src/components/Modal.tsx +++ b/src/components/Modal.tsx @@ -14,7 +14,7 @@ import useLatestCallback from 'use-latest-callback'; import Surface from './Surface'; import { useInternalTheme } from '../core/theming'; -import { tokens } from '../styles/themes/tokens'; +import { tokens } from '../theme/tokens'; import type { ThemeProp } from '../types'; import { addEventListener } from '../utils/addEventListener'; import { BackHandler } from '../utils/BackHandler/BackHandler'; diff --git a/src/components/RadioButton/RadioButtonItem.tsx b/src/components/RadioButton/RadioButtonItem.tsx index fc67da6131..fe9b6843a8 100644 --- a/src/components/RadioButton/RadioButtonItem.tsx +++ b/src/components/RadioButton/RadioButtonItem.tsx @@ -15,7 +15,7 @@ import { RadioButtonContext, RadioButtonContextType } from './RadioButtonGroup'; import RadioButtonIOS from './RadioButtonIOS'; import { handlePress, isChecked } from './utils'; import { useInternalTheme } from '../../core/theming'; -import { tokens } from '../../styles/themes/tokens'; +import { tokens } from '../../theme/tokens'; import type { ThemeProp, TypescaleKey } from '../../types'; import TouchableRipple, { Props as TouchableRippleProps, diff --git a/src/components/SegmentedButtons/utils.ts b/src/components/SegmentedButtons/utils.ts index b2772989ae..af12651971 100644 --- a/src/components/SegmentedButtons/utils.ts +++ b/src/components/SegmentedButtons/utils.ts @@ -1,6 +1,6 @@ import { ViewStyle } from 'react-native'; -import { tokens } from '../../styles/themes/tokens'; +import { tokens } from '../../theme/tokens'; import type { InternalTheme } from '../../types'; const { stateOpacity } = tokens.md.ref; diff --git a/src/components/Surface.tsx b/src/components/Surface.tsx index 16350b8770..7dcfd0a6cd 100644 --- a/src/components/Surface.tsx +++ b/src/components/Surface.tsx @@ -10,7 +10,7 @@ import { } from 'react-native'; import { useInternalTheme } from '../core/theming'; -import shadow from '../styles/shadow'; +import shadow from '../theme/shadow'; import type { Elevation, Theme, ThemeProp } from '../types'; import { isAnimatedValue } from '../utils/animations'; import { forwardRef } from '../utils/forwardRef'; diff --git a/src/components/Switch/utils.ts b/src/components/Switch/utils.ts index 4672e2b7f0..7b05c42ee2 100644 --- a/src/components/Switch/utils.ts +++ b/src/components/Switch/utils.ts @@ -9,7 +9,7 @@ import { grey700, white, black, -} from '../../styles/themes/colors'; +} from '../../theme/colors'; import type { InternalTheme } from '../../types'; type BaseProps = { diff --git a/src/components/TextInput/Adornment/utils.ts b/src/components/TextInput/Adornment/utils.ts index aaf20a221c..40acdafbdb 100644 --- a/src/components/TextInput/Adornment/utils.ts +++ b/src/components/TextInput/Adornment/utils.ts @@ -1,4 +1,4 @@ -import { tokens } from '../../../styles/themes/tokens'; +import { tokens } from '../../../theme/tokens'; import type { InternalTheme } from '../../../types'; const { stateOpacity } = tokens.md.ref; diff --git a/src/components/TextInput/helpers.tsx b/src/components/TextInput/helpers.tsx index 24c3fe079c..633c03f279 100644 --- a/src/components/TextInput/helpers.tsx +++ b/src/components/TextInput/helpers.tsx @@ -14,7 +14,7 @@ import { MD3_OUTLINED_INPUT_OFFSET, } from './constants'; import type { TextInputLabelProp } from './types'; -import { tokens } from '../../styles/themes/tokens'; +import { tokens } from '../../theme/tokens'; import type { InternalTheme } from '../../types'; const { stateOpacity } = tokens.md.ref; diff --git a/src/components/__tests__/AnimatedFAB.test.tsx b/src/components/__tests__/AnimatedFAB.test.tsx index e2209cf424..4017f019fc 100644 --- a/src/components/__tests__/AnimatedFAB.test.tsx +++ b/src/components/__tests__/AnimatedFAB.test.tsx @@ -6,7 +6,7 @@ import { Animated, StyleSheet } from 'react-native'; import { fireEvent, render } from '@testing-library/react-native'; import { act } from 'react-test-renderer'; -import { Palette } from '../../styles/themes/tokens'; +import { Palette } from '../../theme/tokens'; import AnimatedFAB from '../FAB/AnimatedFAB'; const styles = StyleSheet.create({ diff --git a/src/components/__tests__/Appbar/Appbar.test.tsx b/src/components/__tests__/Appbar/Appbar.test.tsx index 8f8600f9bb..0419e18e57 100644 --- a/src/components/__tests__/Appbar/Appbar.test.tsx +++ b/src/components/__tests__/Appbar/Appbar.test.tsx @@ -5,7 +5,7 @@ import { act, render } from '@testing-library/react-native'; import mockSafeAreaContext from 'react-native-safe-area-context/jest/mock'; import { getTheme } from '../../../core/theming'; -import { tokens } from '../../../styles/themes/tokens'; +import { tokens } from '../../../theme/tokens'; import Appbar from '../../Appbar'; import { getAppbarBackgroundColor, diff --git a/src/components/__tests__/Avatar.test.tsx b/src/components/__tests__/Avatar.test.tsx index c339e5b95f..d21100c0db 100644 --- a/src/components/__tests__/Avatar.test.tsx +++ b/src/components/__tests__/Avatar.test.tsx @@ -3,7 +3,7 @@ import { StyleSheet } from 'react-native'; import { fireEvent, render } from '@testing-library/react-native'; -import { red500 } from '../../styles/themes/colors'; +import { red500 } from '../../theme/colors'; import * as Avatar from '../Avatar/Avatar'; const styles = StyleSheet.create({ diff --git a/src/components/__tests__/Badge.test.tsx b/src/components/__tests__/Badge.test.tsx index 8fde099736..2beabe9eae 100644 --- a/src/components/__tests__/Badge.test.tsx +++ b/src/components/__tests__/Badge.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { render } from '@testing-library/react-native'; -import { red500 } from '../../styles/themes/colors'; +import { red500 } from '../../theme/colors'; import Badge from '../Badge'; it('renders badge', () => { diff --git a/src/components/__tests__/BottomNavigation.test.tsx b/src/components/__tests__/BottomNavigation.test.tsx index be08d7fc17..496987e254 100644 --- a/src/components/__tests__/BottomNavigation.test.tsx +++ b/src/components/__tests__/BottomNavigation.test.tsx @@ -4,7 +4,7 @@ import { Animated, Easing, Platform, StyleSheet } from 'react-native'; import { act, fireEvent, render } from '@testing-library/react-native'; import { getTheme } from '../../core/theming'; -import { Palette } from '../../styles/themes/tokens'; +import { Palette } from '../../theme/tokens'; import BottomNavigation from '../BottomNavigation/BottomNavigation'; import BottomNavigationRouteScreen from '../BottomNavigation/BottomNavigationRouteScreen'; import { diff --git a/src/components/__tests__/Button.test.tsx b/src/components/__tests__/Button.test.tsx index 894d7ce8e2..a203e1d237 100644 --- a/src/components/__tests__/Button.test.tsx +++ b/src/components/__tests__/Button.test.tsx @@ -4,8 +4,8 @@ import { Animated, StyleSheet } from 'react-native'; import { act, fireEvent, render } from '@testing-library/react-native'; import { getTheme } from '../../core/theming'; -import { pink500, white } from '../../styles/themes/colors'; -import { tokens } from '../../styles/themes/tokens'; +import { pink500, white } from '../../theme/colors'; +import { tokens } from '../../theme/tokens'; import Button from '../Button/Button'; import { getButtonColors } from '../Button/utils'; diff --git a/src/components/__tests__/Card/Card.test.tsx b/src/components/__tests__/Card/Card.test.tsx index e8df99d568..fb61ca9602 100644 --- a/src/components/__tests__/Card/Card.test.tsx +++ b/src/components/__tests__/Card/Card.test.tsx @@ -4,7 +4,7 @@ import { Animated, StyleSheet, Text } from 'react-native'; import { act, render } from '@testing-library/react-native'; import { getTheme } from '../../../core/theming'; -import { Palette } from '../../../styles/themes/tokens'; +import { Palette } from '../../../theme/tokens'; import Button from '../../Button/Button'; import Card from '../../Card/Card'; import { getCardColors, getCardCoverStyle } from '../../Card/utils'; diff --git a/src/components/__tests__/Checkbox/utils.test.tsx b/src/components/__tests__/Checkbox/utils.test.tsx index eca368146b..a18dd2f78e 100644 --- a/src/components/__tests__/Checkbox/utils.test.tsx +++ b/src/components/__tests__/Checkbox/utils.test.tsx @@ -1,5 +1,5 @@ import { getTheme } from '../../../core/theming'; -import { tokens } from '../../../styles/themes/tokens'; +import { tokens } from '../../../theme/tokens'; import { getAndroidSelectionControlColor, getSelectionControlIOSColor, diff --git a/src/components/__tests__/Chip.test.tsx b/src/components/__tests__/Chip.test.tsx index 1459a9151d..82841001ff 100644 --- a/src/components/__tests__/Chip.test.tsx +++ b/src/components/__tests__/Chip.test.tsx @@ -5,7 +5,7 @@ import { act, render } from '@testing-library/react-native'; import color from 'color'; import { getTheme } from '../../core/theming'; -import { tokens } from '../../styles/themes/tokens'; +import { tokens } from '../../theme/tokens'; import Chip from '../Chip/Chip'; import { getChipColors } from '../Chip/helpers'; diff --git a/src/components/__tests__/IconButton.test.tsx b/src/components/__tests__/IconButton.test.tsx index 88faf4ab78..229b8b462e 100644 --- a/src/components/__tests__/IconButton.test.tsx +++ b/src/components/__tests__/IconButton.test.tsx @@ -4,8 +4,8 @@ import { Animated, StyleSheet } from 'react-native'; import { act, render } from '@testing-library/react-native'; import { getTheme } from '../../core/theming'; -import { pink500 } from '../../styles/themes/colors'; -import { tokens } from '../../styles/themes/tokens'; +import { pink500 } from '../../theme/colors'; +import { tokens } from '../../theme/tokens'; import IconButton from '../IconButton/IconButton'; import { getIconButtonColor } from '../IconButton/utils'; diff --git a/src/components/__tests__/ListAccordion.test.tsx b/src/components/__tests__/ListAccordion.test.tsx index fedf9670be..93e3c62bad 100644 --- a/src/components/__tests__/ListAccordion.test.tsx +++ b/src/components/__tests__/ListAccordion.test.tsx @@ -4,7 +4,7 @@ import { StyleSheet, View } from 'react-native'; import { render } from '@testing-library/react-native'; import { getTheme } from '../../core/theming'; -import { red500 } from '../../styles/themes/colors'; +import { red500 } from '../../theme/colors'; import ListAccordion from '../List/ListAccordion'; import ListAccordionGroup from '../List/ListAccordionGroup'; import ListIcon from '../List/ListIcon'; diff --git a/src/components/__tests__/ListItem.test.tsx b/src/components/__tests__/ListItem.test.tsx index 8f00f441ae..c2b7f0d88d 100644 --- a/src/components/__tests__/ListItem.test.tsx +++ b/src/components/__tests__/ListItem.test.tsx @@ -4,7 +4,7 @@ import { Text, View } from 'react-native'; import { fireEvent, render } from '@testing-library/react-native'; -import { red500 } from '../../styles/themes/colors'; +import { red500 } from '../../theme/colors'; import Chip from '../Chip/Chip'; import IconButton from '../IconButton/IconButton'; import ListIcon from '../List/ListIcon'; diff --git a/src/components/__tests__/ListSection.test.tsx b/src/components/__tests__/ListSection.test.tsx index d09a0aa4a7..91efbfc008 100644 --- a/src/components/__tests__/ListSection.test.tsx +++ b/src/components/__tests__/ListSection.test.tsx @@ -3,7 +3,7 @@ import { StyleSheet } from 'react-native'; import { render } from '@testing-library/react-native'; -import { red500 } from '../../styles/themes/colors'; +import { red500 } from '../../theme/colors'; import ListIcon from '../List/ListIcon'; import ListItem from '../List/ListItem'; import ListSection from '../List/ListSection'; diff --git a/src/components/__tests__/MenuItem.test.tsx b/src/components/__tests__/MenuItem.test.tsx index 034645d2fd..98d433723d 100644 --- a/src/components/__tests__/MenuItem.test.tsx +++ b/src/components/__tests__/MenuItem.test.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import { render } from '@testing-library/react-native'; import { getTheme } from '../../core/theming'; -import { tokens } from '../../styles/themes/tokens'; +import { tokens } from '../../theme/tokens'; import Menu from '../Menu/Menu'; import { getMenuItemColor } from '../Menu/utils'; diff --git a/src/components/__tests__/Modal.test.tsx b/src/components/__tests__/Modal.test.tsx index a7d442efe3..9fd9eef832 100644 --- a/src/components/__tests__/Modal.test.tsx +++ b/src/components/__tests__/Modal.test.tsx @@ -8,8 +8,8 @@ import { import { act, fireEvent, render } from '@testing-library/react-native'; -import { LightTheme } from '../../styles/themes'; -import { tokens } from '../../styles/themes/tokens'; +import { LightTheme } from '../../theme/schemes'; +import { tokens } from '../../theme/tokens'; import Modal from '../Modal'; const { scrimAlpha } = tokens.md.ref; diff --git a/src/components/__tests__/SegmentedButton.test.tsx b/src/components/__tests__/SegmentedButton.test.tsx index 994c26d765..06a7390626 100644 --- a/src/components/__tests__/SegmentedButton.test.tsx +++ b/src/components/__tests__/SegmentedButton.test.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import { render } from '@testing-library/react-native'; import { getTheme } from '../../core/theming'; -import { tokens } from '../../styles/themes/tokens'; +import { tokens } from '../../theme/tokens'; import SegmentedButtons from '../SegmentedButtons/SegmentedButtons'; import { getDisabledSegmentedButtonStyle, diff --git a/src/components/__tests__/Snackbar.test.tsx b/src/components/__tests__/Snackbar.test.tsx index 425b918495..a5938d516b 100644 --- a/src/components/__tests__/Snackbar.test.tsx +++ b/src/components/__tests__/Snackbar.test.tsx @@ -3,7 +3,7 @@ import { Animated, StyleSheet, Text, View } from 'react-native'; import { act, render } from '@testing-library/react-native'; -import { red200, white } from '../../styles/themes/colors'; +import { red200, white } from '../../theme/colors'; import Snackbar from '../Snackbar'; const styles = StyleSheet.create({ diff --git a/src/components/__tests__/Switch.test.tsx b/src/components/__tests__/Switch.test.tsx index c555c8ad2b..2022439d76 100644 --- a/src/components/__tests__/Switch.test.tsx +++ b/src/components/__tests__/Switch.test.tsx @@ -13,7 +13,7 @@ import { grey800, pink500, grey700, -} from '../../styles/themes/colors'; +} from '../../theme/colors'; import Switch from '../Switch/Switch'; import { getSwitchColor } from '../Switch/utils'; diff --git a/src/components/__tests__/TextInput.test.tsx b/src/components/__tests__/TextInput.test.tsx index e052755eaf..a9f06c7a8e 100644 --- a/src/components/__tests__/TextInput.test.tsx +++ b/src/components/__tests__/TextInput.test.tsx @@ -5,8 +5,8 @@ import { I18nManager, Platform, StyleSheet, Text, View } from 'react-native'; import { fireEvent, render } from '@testing-library/react-native'; import { DefaultTheme, getTheme, ThemeProvider } from '../../core/theming'; -import { red500 } from '../../styles/themes/colors'; -import { tokens } from '../../styles/themes/tokens'; +import { red500 } from '../../theme/colors'; +import { tokens } from '../../theme/tokens'; import { getFlatInputColors, getOutlinedInputColors, diff --git a/src/components/__tests__/Typography/Text.test.tsx b/src/components/__tests__/Typography/Text.test.tsx index 0e0bb64303..67f99ae94b 100644 --- a/src/components/__tests__/Typography/Text.test.tsx +++ b/src/components/__tests__/Typography/Text.test.tsx @@ -3,9 +3,9 @@ import * as React from 'react'; import { render } from '@testing-library/react-native'; import PaperProvider from '../../../core/PaperProvider'; -import configureFonts from '../../../styles/fonts'; -import { LightTheme } from '../../../styles/themes'; -import { tokens } from '../../../styles/themes/tokens'; +import configureFonts from '../../../theme/fonts'; +import { LightTheme } from '../../../theme/schemes'; +import { tokens } from '../../../theme/tokens'; import Text, { customText } from '../../Typography/Text'; const content = 'Something rendered as a child content'; diff --git a/src/core/__tests__/PaperProvider.test.tsx b/src/core/__tests__/PaperProvider.test.tsx index 6ae08641c1..1d04ec00ff 100644 --- a/src/core/__tests__/PaperProvider.test.tsx +++ b/src/core/__tests__/PaperProvider.test.tsx @@ -8,7 +8,7 @@ import { import { render, act } from '@testing-library/react-native'; -import { LightTheme, DarkTheme } from '../../styles/themes'; +import { LightTheme, DarkTheme } from '../../theme/schemes'; import type { ThemeProp } from '../../types'; import PaperProvider from '../PaperProvider'; import { useTheme } from '../theming'; diff --git a/src/core/__tests__/theming.test.tsx b/src/core/__tests__/theming.test.tsx index 0771e32650..cfca524f6f 100644 --- a/src/core/__tests__/theming.test.tsx +++ b/src/core/__tests__/theming.test.tsx @@ -1,4 +1,4 @@ -import { DarkTheme, LightTheme } from '../../styles/themes'; +import { DarkTheme, LightTheme } from '../../theme/schemes'; import { adaptNavigationTheme } from '../theming'; const NavigationLightTheme = { diff --git a/src/core/theming.tsx b/src/core/theming.tsx index 6da3aaf13f..ff478d0117 100644 --- a/src/core/theming.tsx +++ b/src/core/theming.tsx @@ -1,138 +1 @@ -import type { ComponentType } from 'react'; - -import { $DeepPartial, createTheming } from '@callstack/react-theme-provider'; - -import { DarkTheme, LightTheme } from '../styles/themes'; -import type { InternalTheme, Theme, NavigationTheme } from '../types'; - -export const DefaultTheme = LightTheme; - -export const { - ThemeProvider, - withTheme, - useTheme: useAppTheme, -} = createTheming(LightTheme); - -export function useTheme(overrides?: $DeepPartial) { - return useAppTheme(overrides); -} - -export const useInternalTheme = ( - themeOverrides: $DeepPartial | undefined -) => useAppTheme(themeOverrides); - -export const withInternalTheme = ( - WrappedComponent: ComponentType & C -) => withTheme(WrappedComponent); - -export const defaultThemes = { - light: LightTheme, - dark: DarkTheme, -}; - -export const getTheme = ( - isDark: Scheme = false as Scheme -): (typeof defaultThemes)[Scheme extends true ? 'dark' : 'light'] => { - const scheme = isDark ? 'dark' : 'light'; - - return defaultThemes[scheme]; -}; - -// eslint-disable-next-line no-redeclare -export function adaptNavigationTheme(themes: { - reactNavigationLight: T; - materialLight?: Theme; -}): { - LightTheme: NavigationTheme; -}; -// eslint-disable-next-line no-redeclare -export function adaptNavigationTheme(themes: { - reactNavigationDark: T; - materialDark?: Theme; -}): { - DarkTheme: NavigationTheme; -}; -// eslint-disable-next-line no-redeclare -export function adaptNavigationTheme< - TLight extends NavigationTheme, - TDark extends NavigationTheme ->(themes: { - reactNavigationLight: TLight; - reactNavigationDark: TDark; - materialLight?: Theme; - materialDark?: Theme; -}): { LightTheme: TLight; DarkTheme: TDark }; -// eslint-disable-next-line no-redeclare -export function adaptNavigationTheme(themes: any) { - const { - reactNavigationLight, - reactNavigationDark, - materialLight, - materialDark, - } = themes; - - const MD3Themes = { - light: materialLight || LightTheme, - dark: materialDark || DarkTheme, - }; - - const result: { LightTheme?: any; DarkTheme?: any } = {}; - - if (reactNavigationLight) { - result.LightTheme = getAdaptedTheme(reactNavigationLight, MD3Themes.light); - } - - if (reactNavigationDark) { - result.DarkTheme = getAdaptedTheme(reactNavigationDark, MD3Themes.dark); - } - - return result; -} - -const getAdaptedTheme = ( - theme: T, - materialTheme: Theme -): T => { - const base = { - ...theme, - colors: { - ...theme.colors, - primary: materialTheme.colors.primary, - background: materialTheme.colors.background, - card: materialTheme.colors.surfaceContainer, - text: materialTheme.colors.onSurface, - border: materialTheme.colors.outline, - notification: materialTheme.colors.error, - }, - }; - - if ('fonts' in theme) { - return { - ...base, - fonts: { - regular: { - fontFamily: materialTheme.fonts.bodyMedium.fontFamily, - fontWeight: materialTheme.fonts.bodyMedium.fontWeight, - letterSpacing: materialTheme.fonts.bodyMedium.letterSpacing, - }, - medium: { - fontFamily: materialTheme.fonts.titleMedium.fontFamily, - fontWeight: materialTheme.fonts.titleMedium.fontWeight, - letterSpacing: materialTheme.fonts.titleMedium.letterSpacing, - }, - bold: { - fontFamily: materialTheme.fonts.headlineSmall.fontFamily, - fontWeight: materialTheme.fonts.headlineSmall.fontWeight, - letterSpacing: materialTheme.fonts.headlineSmall.letterSpacing, - }, - heavy: { - fontFamily: materialTheme.fonts.headlineLarge.fontFamily, - fontWeight: materialTheme.fonts.headlineLarge.fontWeight, - letterSpacing: materialTheme.fonts.headlineLarge.letterSpacing, - }, - }, - }; - } - - return base; -}; +export * from '../theme/provider'; diff --git a/src/deprecated.ts b/src/deprecated.ts index 06979bdaa1..e294f6a44d 100644 --- a/src/deprecated.ts +++ b/src/deprecated.ts @@ -8,9 +8,9 @@ * Do not add anything here that isn't a deprecated alias. */ -import { DarkTheme } from './styles/themes/DarkTheme'; -import { LightTheme } from './styles/themes/LightTheme'; -import { Palette } from './styles/themes/tokens'; +import { DarkTheme } from './theme/schemes/DarkTheme'; +import { LightTheme } from './theme/schemes/LightTheme'; +import { Palette } from './theme/tokens'; import { TypescaleKey } from './types'; import type { Theme, Elevation } from './types'; diff --git a/src/index.tsx b/src/index.tsx index 536e923d4a..298658cf50 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,4 +1,4 @@ -export { Palette } from './styles/themes/tokens'; +export { Palette } from './theme/tokens'; export { useTheme, @@ -8,12 +8,12 @@ export { adaptNavigationTheme, } from './core/theming'; -export * from './styles/themes'; +export * from './theme/schemes'; export { default as Provider } from './core/PaperProvider'; export { default as PaperProvider } from './core/PaperProvider'; -export { default as shadow } from './styles/shadow'; -export { default as configureFonts } from './styles/fonts'; +export { default as shadow } from './theme/shadow'; +export { default as configureFonts } from './theme/fonts'; import * as Avatar from './components/Avatar/Avatar'; import * as Drawer from './components/Drawer/Drawer'; diff --git a/src/styles/__tests__/fonts.test.js b/src/theme/__tests__/fonts.test.js similarity index 98% rename from src/styles/__tests__/fonts.test.js rename to src/theme/__tests__/fonts.test.js index e632bdbcf0..9aafe31616 100644 --- a/src/styles/__tests__/fonts.test.js +++ b/src/theme/__tests__/fonts.test.js @@ -130,7 +130,7 @@ const loadFonts = () => { const fonts = require('../fonts'); configureFonts = fonts.default; - typescale = require('../themes/tokens').typescale; + typescale = require('../tokens').typescale; }); return { configureFonts, typescale }; diff --git a/src/styles/themes/colors.tsx b/src/theme/colors.tsx similarity index 100% rename from src/styles/themes/colors.tsx rename to src/theme/colors.tsx diff --git a/src/styles/fonts.tsx b/src/theme/fonts.tsx similarity index 97% rename from src/styles/fonts.tsx rename to src/theme/fonts.tsx index a2267fb20d..3a67d00d67 100644 --- a/src/styles/fonts.tsx +++ b/src/theme/fonts.tsx @@ -1,5 +1,5 @@ import type { TypescaleStyle, Typescale, TypescaleKey } from '../types'; -import { typescale } from './themes/tokens'; +import { typescale } from './tokens'; type FontsConfig = | { diff --git a/src/theme/provider.tsx b/src/theme/provider.tsx new file mode 100644 index 0000000000..22056d9354 --- /dev/null +++ b/src/theme/provider.tsx @@ -0,0 +1,138 @@ +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'; + +export const DefaultTheme = LightTheme; + +export const { + ThemeProvider, + withTheme, + useTheme: useAppTheme, +} = createTheming(LightTheme); + +export function useTheme(overrides?: $DeepPartial) { + return useAppTheme(overrides); +} + +export const useInternalTheme = ( + themeOverrides: $DeepPartial | undefined +) => useAppTheme(themeOverrides); + +export const withInternalTheme = ( + WrappedComponent: ComponentType & C +) => withTheme(WrappedComponent); + +export const defaultThemes = { + light: LightTheme, + dark: DarkTheme, +}; + +export const getTheme = ( + isDark: Scheme = false as Scheme +): (typeof defaultThemes)[Scheme extends true ? 'dark' : 'light'] => { + const scheme = isDark ? 'dark' : 'light'; + + return defaultThemes[scheme]; +}; + +// eslint-disable-next-line no-redeclare +export function adaptNavigationTheme(themes: { + reactNavigationLight: T; + materialLight?: Theme; +}): { + LightTheme: NavigationTheme; +}; +// eslint-disable-next-line no-redeclare +export function adaptNavigationTheme(themes: { + reactNavigationDark: T; + materialDark?: Theme; +}): { + DarkTheme: NavigationTheme; +}; +// eslint-disable-next-line no-redeclare +export function adaptNavigationTheme< + TLight extends NavigationTheme, + TDark extends NavigationTheme +>(themes: { + reactNavigationLight: TLight; + reactNavigationDark: TDark; + materialLight?: Theme; + materialDark?: Theme; +}): { LightTheme: TLight; DarkTheme: TDark }; +// eslint-disable-next-line no-redeclare +export function adaptNavigationTheme(themes: any) { + const { + reactNavigationLight, + reactNavigationDark, + materialLight, + materialDark, + } = themes; + + const MD3Themes = { + light: materialLight || LightTheme, + dark: materialDark || DarkTheme, + }; + + const result: { LightTheme?: any; DarkTheme?: any } = {}; + + if (reactNavigationLight) { + result.LightTheme = getAdaptedTheme(reactNavigationLight, MD3Themes.light); + } + + if (reactNavigationDark) { + result.DarkTheme = getAdaptedTheme(reactNavigationDark, MD3Themes.dark); + } + + return result; +} + +const getAdaptedTheme = ( + theme: T, + materialTheme: Theme +): T => { + const base = { + ...theme, + colors: { + ...theme.colors, + primary: materialTheme.colors.primary, + background: materialTheme.colors.background, + card: materialTheme.colors.surfaceContainer, + text: materialTheme.colors.onSurface, + border: materialTheme.colors.outline, + notification: materialTheme.colors.error, + }, + }; + + if ('fonts' in theme) { + return { + ...base, + fonts: { + regular: { + fontFamily: materialTheme.fonts.bodyMedium.fontFamily, + fontWeight: materialTheme.fonts.bodyMedium.fontWeight, + letterSpacing: materialTheme.fonts.bodyMedium.letterSpacing, + }, + medium: { + fontFamily: materialTheme.fonts.titleMedium.fontFamily, + fontWeight: materialTheme.fonts.titleMedium.fontWeight, + letterSpacing: materialTheme.fonts.titleMedium.letterSpacing, + }, + bold: { + fontFamily: materialTheme.fonts.headlineSmall.fontFamily, + fontWeight: materialTheme.fonts.headlineSmall.fontWeight, + letterSpacing: materialTheme.fonts.headlineSmall.letterSpacing, + }, + heavy: { + fontFamily: materialTheme.fonts.headlineLarge.fontFamily, + fontWeight: materialTheme.fonts.headlineLarge.fontWeight, + letterSpacing: materialTheme.fonts.headlineLarge.letterSpacing, + }, + }, + }; + } + + return base; +}; diff --git a/src/styles/themes/DarkTheme.tsx b/src/theme/schemes/DarkTheme.tsx similarity index 98% rename from src/styles/themes/DarkTheme.tsx rename to src/theme/schemes/DarkTheme.tsx index 693855680e..830bfec4b1 100644 --- a/src/styles/themes/DarkTheme.tsx +++ b/src/theme/schemes/DarkTheme.tsx @@ -1,8 +1,8 @@ import color from 'color'; import { LightTheme } from './LightTheme'; -import { tokens } from './tokens'; import type { Theme } from '../../types'; +import { tokens } from '../tokens'; const { palette, stateOpacity } = tokens.md.ref; diff --git a/src/styles/themes/DynamicTheme.android.tsx b/src/theme/schemes/DynamicTheme.android.tsx similarity index 100% rename from src/styles/themes/DynamicTheme.android.tsx rename to src/theme/schemes/DynamicTheme.android.tsx diff --git a/src/styles/themes/DynamicTheme.tsx b/src/theme/schemes/DynamicTheme.tsx similarity index 100% rename from src/styles/themes/DynamicTheme.tsx rename to src/theme/schemes/DynamicTheme.tsx diff --git a/src/styles/themes/LightTheme.tsx b/src/theme/schemes/LightTheme.tsx similarity index 98% rename from src/styles/themes/LightTheme.tsx rename to src/theme/schemes/LightTheme.tsx index 5566b9fadf..8d7f3854d9 100644 --- a/src/styles/themes/LightTheme.tsx +++ b/src/theme/schemes/LightTheme.tsx @@ -1,8 +1,8 @@ import color from 'color'; -import { tokens } from './tokens'; import type { Theme } from '../../types'; import configureFonts from '../fonts'; +import { tokens } from '../tokens'; const { palette, stateOpacity } = tokens.md.ref; diff --git a/src/styles/themes/index.ts b/src/theme/schemes/index.ts similarity index 100% rename from src/styles/themes/index.ts rename to src/theme/schemes/index.ts diff --git a/src/styles/shadow.tsx b/src/theme/shadow.tsx similarity index 96% rename from src/styles/shadow.tsx rename to src/theme/shadow.tsx index 32e056fa1f..58070cede8 100644 --- a/src/styles/shadow.tsx +++ b/src/theme/shadow.tsx @@ -1,6 +1,6 @@ import { Animated } from 'react-native'; -import { Palette } from './themes/tokens'; +import { Palette } from './tokens'; const SHADOW_OPACITY = 0.3; const SHADOW_COLOR = Palette.primary0; diff --git a/src/styles/themes/tokens.tsx b/src/theme/tokens/index.ts similarity index 100% rename from src/styles/themes/tokens.tsx rename to src/theme/tokens/index.ts diff --git a/src/theme/types.ts b/src/theme/types.ts new file mode 100644 index 0000000000..b424142b86 --- /dev/null +++ b/src/theme/types.ts @@ -0,0 +1,179 @@ +import type * as React from 'react'; + +import type { $DeepPartial } from '@callstack/react-theme-provider'; + +export type Font = { + fontFamily: string; + fontWeight?: + | 'normal' + | 'bold' + | '100' + | '200' + | '300' + | '400' + | '500' + | '600' + | '700' + | '800' + | '900'; + fontStyle?: 'normal' | 'italic' | undefined; +}; + +export type Fonts = { + regular: Font; + medium: Font; + light: Font; + thin: Font; +}; + +type Mode = 'adaptive' | 'exact'; + +export type ThemeColors = { + primary: string; + primaryContainer: string; + secondary: string; + secondaryContainer: string; + tertiary: string; + tertiaryContainer: string; + surface: string; + surfaceDim: string; + surfaceBright: string; + surfaceContainerLowest: string; + surfaceContainerLow: string; + surfaceContainer: string; + surfaceContainerHigh: string; + surfaceContainerHighest: string; + surfaceVariant: string; + background: string; + error: string; + errorContainer: string; + onPrimary: string; + onPrimaryContainer: string; + onSecondary: string; + onSecondaryContainer: string; + onTertiary: string; + onTertiaryContainer: string; + onSurface: string; + onSurfaceVariant: string; + onError: string; + onErrorContainer: string; + onBackground: string; + outline: string; + outlineVariant: string; + inverseSurface: string; + inverseOnSurface: string; + inversePrimary: string; + primaryFixed: string; + primaryFixedDim: string; + onPrimaryFixed: string; + onPrimaryFixedVariant: string; + secondaryFixed: string; + secondaryFixedDim: string; + onSecondaryFixed: string; + onSecondaryFixedVariant: string; + tertiaryFixed: string; + tertiaryFixedDim: string; + onTertiaryFixed: string; + onTertiaryFixedVariant: string; + shadow: string; + scrim: string; + /** Pre-computed state layer color at press opacity (0.10). + * Used for ripple effects. Avoids runtime alpha manipulation + * which is incompatible with PlatformColor on Android. + * TODO: revisit after https://github.com/facebook/react-native/pull/56395 + * @see https://m3.material.io/foundations/interaction/states/state-layers */ + stateLayerPressed: string; + elevation: ElevationColors; +}; + +export type ThemeProp = $DeepPartial; + +export type ThemeBase = { + dark: boolean; + mode?: Mode; + roundness: number; + animation: { + scale: number; + defaultAnimationDuration?: number; + }; +}; + +export type Theme = ThemeBase & { + colors: ThemeColors; + fonts: Typescale; +}; + +export type InternalTheme = Theme; + +export enum TypescaleKey { + displayLarge = 'displayLarge', + displayMedium = 'displayMedium', + displaySmall = 'displaySmall', + + headlineLarge = 'headlineLarge', + headlineMedium = 'headlineMedium', + headlineSmall = 'headlineSmall', + + titleLarge = 'titleLarge', + titleMedium = 'titleMedium', + titleSmall = 'titleSmall', + + labelLarge = 'labelLarge', + labelMedium = 'labelMedium', + labelSmall = 'labelSmall', + + bodyLarge = 'bodyLarge', + bodyMedium = 'bodyMedium', + bodySmall = 'bodySmall', +} + +export type TypescaleStyle = { + fontFamily: string; + letterSpacing: number; + fontWeight: Font['fontWeight']; + lineHeight: number; + fontSize: number; + fontStyle?: Font['fontStyle']; +}; + +export type Typescale = + | { + [key in TypescaleKey]: TypescaleStyle; + } & { + ['default']: Omit; + }; + +export type Elevation = 0 | 1 | 2 | 3 | 4 | 5; + +export enum ElevationLevels { + 'level0', + 'level1', + 'level2', + 'level3', + 'level4', + 'level5', +} + +export type ElevationColors = { + [key in keyof typeof ElevationLevels]: string; +}; + +export type $Omit = Pick>; +export type $RemoveChildren> = $Omit< + React.ComponentPropsWithoutRef, + 'children' +>; + +export type EllipsizeProp = 'head' | 'middle' | 'tail' | 'clip'; + +export type NavigationTheme = { + dark: boolean; + colors: { + primary: string; + background: string; + card: string; + text: string; + border: string; + notification: string; + }; +}; diff --git a/src/types.tsx b/src/types.tsx index b424142b86..261b55f0b3 100644 --- a/src/types.tsx +++ b/src/types.tsx @@ -1,179 +1 @@ -import type * as React from 'react'; - -import type { $DeepPartial } from '@callstack/react-theme-provider'; - -export type Font = { - fontFamily: string; - fontWeight?: - | 'normal' - | 'bold' - | '100' - | '200' - | '300' - | '400' - | '500' - | '600' - | '700' - | '800' - | '900'; - fontStyle?: 'normal' | 'italic' | undefined; -}; - -export type Fonts = { - regular: Font; - medium: Font; - light: Font; - thin: Font; -}; - -type Mode = 'adaptive' | 'exact'; - -export type ThemeColors = { - primary: string; - primaryContainer: string; - secondary: string; - secondaryContainer: string; - tertiary: string; - tertiaryContainer: string; - surface: string; - surfaceDim: string; - surfaceBright: string; - surfaceContainerLowest: string; - surfaceContainerLow: string; - surfaceContainer: string; - surfaceContainerHigh: string; - surfaceContainerHighest: string; - surfaceVariant: string; - background: string; - error: string; - errorContainer: string; - onPrimary: string; - onPrimaryContainer: string; - onSecondary: string; - onSecondaryContainer: string; - onTertiary: string; - onTertiaryContainer: string; - onSurface: string; - onSurfaceVariant: string; - onError: string; - onErrorContainer: string; - onBackground: string; - outline: string; - outlineVariant: string; - inverseSurface: string; - inverseOnSurface: string; - inversePrimary: string; - primaryFixed: string; - primaryFixedDim: string; - onPrimaryFixed: string; - onPrimaryFixedVariant: string; - secondaryFixed: string; - secondaryFixedDim: string; - onSecondaryFixed: string; - onSecondaryFixedVariant: string; - tertiaryFixed: string; - tertiaryFixedDim: string; - onTertiaryFixed: string; - onTertiaryFixedVariant: string; - shadow: string; - scrim: string; - /** Pre-computed state layer color at press opacity (0.10). - * Used for ripple effects. Avoids runtime alpha manipulation - * which is incompatible with PlatformColor on Android. - * TODO: revisit after https://github.com/facebook/react-native/pull/56395 - * @see https://m3.material.io/foundations/interaction/states/state-layers */ - stateLayerPressed: string; - elevation: ElevationColors; -}; - -export type ThemeProp = $DeepPartial; - -export type ThemeBase = { - dark: boolean; - mode?: Mode; - roundness: number; - animation: { - scale: number; - defaultAnimationDuration?: number; - }; -}; - -export type Theme = ThemeBase & { - colors: ThemeColors; - fonts: Typescale; -}; - -export type InternalTheme = Theme; - -export enum TypescaleKey { - displayLarge = 'displayLarge', - displayMedium = 'displayMedium', - displaySmall = 'displaySmall', - - headlineLarge = 'headlineLarge', - headlineMedium = 'headlineMedium', - headlineSmall = 'headlineSmall', - - titleLarge = 'titleLarge', - titleMedium = 'titleMedium', - titleSmall = 'titleSmall', - - labelLarge = 'labelLarge', - labelMedium = 'labelMedium', - labelSmall = 'labelSmall', - - bodyLarge = 'bodyLarge', - bodyMedium = 'bodyMedium', - bodySmall = 'bodySmall', -} - -export type TypescaleStyle = { - fontFamily: string; - letterSpacing: number; - fontWeight: Font['fontWeight']; - lineHeight: number; - fontSize: number; - fontStyle?: Font['fontStyle']; -}; - -export type Typescale = - | { - [key in TypescaleKey]: TypescaleStyle; - } & { - ['default']: Omit; - }; - -export type Elevation = 0 | 1 | 2 | 3 | 4 | 5; - -export enum ElevationLevels { - 'level0', - 'level1', - 'level2', - 'level3', - 'level4', - 'level5', -} - -export type ElevationColors = { - [key in keyof typeof ElevationLevels]: string; -}; - -export type $Omit = Pick>; -export type $RemoveChildren> = $Omit< - React.ComponentPropsWithoutRef, - 'children' ->; - -export type EllipsizeProp = 'head' | 'middle' | 'tail' | 'clip'; - -export type NavigationTheme = { - dark: boolean; - colors: { - primary: string; - background: string; - card: string; - text: string; - border: string; - notification: string; - }; -}; +export * from './theme/types';