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