Bluesky app fork with some witchin' additions 馃挮
at main 137 lines 3.0 kB view raw
1import {type ReactNode, useMemo} from 'react' 2import {createContext, useContext} from 'react' 3import {type TextStyle, type ViewStyle} from 'react-native' 4import {type ThemeName} from '@bsky.app/alf' 5 6import {useThemePrefs} from '#/state/shell/color-mode' 7import {hueShifter, type SchemeType, selectScheme} from '#/alf' 8import {themes} from '#/alf/themes' 9import {darkTheme, defaultTheme, dimTheme} from './themes' 10 11export type ColorScheme = 'light' | 'dark' 12 13export type PaletteColorName = 14 | 'default' 15 | 'primary' 16 | 'secondary' 17 | 'inverted' 18 | 'error' 19export type PaletteColor = { 20 background: string 21 backgroundLight: string 22 text: string 23 textLight: string 24 textInverted: string 25 link: string 26 border: string 27 borderDark: string 28 icon: string 29 [k: string]: string 30} 31export type Palette = Record<PaletteColorName, PaletteColor> 32 33export type ShapeName = 'button' | 'bigButton' | 'smallButton' 34export type Shapes = Record<ShapeName, ViewStyle> 35 36/** 37 * @deprecated use typography atoms from `#/alf` 38 */ 39export type TypographyVariant = 40 | '2xl-thin' 41 | '2xl' 42 | '2xl-medium' 43 | '2xl-bold' 44 | '2xl-heavy' 45 | 'xl-thin' 46 | 'xl' 47 | 'xl-medium' 48 | 'xl-bold' 49 | 'xl-heavy' 50 | 'lg-thin' 51 | 'lg' 52 | 'lg-medium' 53 | 'lg-bold' 54 | 'lg-heavy' 55 | 'md-thin' 56 | 'md' 57 | 'md-medium' 58 | 'md-bold' 59 | 'md-heavy' 60 | 'sm-thin' 61 | 'sm' 62 | 'sm-medium' 63 | 'sm-bold' 64 | 'sm-heavy' 65 | 'xs-thin' 66 | 'xs' 67 | 'xs-medium' 68 | 'xs-bold' 69 | 'xs-heavy' 70 | 'title-2xl' 71 | 'title-xl' 72 | 'title-lg' 73 | 'title' 74 | 'title-sm' 75 | 'post-text-lg' 76 | 'post-text' 77 | 'button' 78 | 'button-lg' 79 | 'mono' 80export type Typography = Record<TypographyVariant, TextStyle> 81 82export interface Theme { 83 colorScheme: ColorScheme 84 palette: Palette 85 shapes: Shapes 86 typography: Typography 87} 88 89export interface ThemeProviderProps { 90 children?: ReactNode 91 theme: ThemeName 92} 93 94export const ThemeContext = createContext<Theme>( 95 defaultTheme({ 96 lightPalette: themes.lightPalette, 97 darkPalette: themes.darkPalette, 98 }), 99) 100ThemeContext.displayName = 'ThemeContext' 101 102export const useTheme = () => useContext(ThemeContext) 103 104function getTheme(themeName: ThemeName, scheme: SchemeType) { 105 const paletteOptions = { 106 lightPalette: scheme.lightPalette, 107 darkPalette: scheme.darkPalette, 108 dimPalette: scheme.dimPalette, 109 } 110 111 switch (themeName) { 112 case 'light': 113 return defaultTheme(paletteOptions) 114 case 'dim': 115 return dimTheme(paletteOptions) 116 case 'dark': 117 return darkTheme(paletteOptions) 118 default: 119 return defaultTheme(paletteOptions) 120 } 121} 122 123export const ThemeProvider: React.FC<ThemeProviderProps> = ({ 124 theme, 125 children, 126}) => { 127 const {colorScheme, hue} = useThemePrefs() 128 129 const themeValue = useMemo(() => { 130 const currentScheme = hueShifter(selectScheme(colorScheme), hue) 131 return getTheme(theme, currentScheme) 132 }, [theme, colorScheme, hue]) 133 134 return ( 135 <ThemeContext.Provider value={themeValue}>{children}</ThemeContext.Provider> 136 ) 137}