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