tangled mirror of catsky-馃惐 Soothing soft social-app fork with all the niche toggles! (Unofficial); for issues and PRs please put them on github:NekoDrone/catsky-social
1import React from 'react'
2
3import {
4 computeFontScaleMultiplier,
5 getFontFamily,
6 getFontScale,
7 setFontFamily as persistFontFamily,
8 setFontScale as persistFontScale,
9} from '#/alf/fonts'
10import {createThemes, defaultTheme} from '#/alf/themes'
11import {type Theme, type ThemeName} from '#/alf/types'
12import {BLUE_HUE, GREEN_HUE, RED_HUE} from '#/alf/util/colorGeneration'
13import {type Device} from '#/storage'
14
15export {atoms} from '#/alf/atoms'
16export * from '#/alf/breakpoints'
17export * from '#/alf/fonts'
18export * as tokens from '#/alf/tokens'
19export * from '#/alf/types'
20export * from '#/alf/util/flatten'
21export * from '#/alf/util/platform'
22export * from '#/alf/util/themeSelector'
23export * from '#/alf/util/useGutters'
24
25export type Alf = {
26 themeName: ThemeName
27 theme: Theme
28 themes: ReturnType<typeof createThemes>
29 fonts: {
30 scale: Exclude<Device['fontScale'], undefined>
31 scaleMultiplier: number
32 family: Device['fontFamily']
33 setFontScale: (fontScale: Exclude<Device['fontScale'], undefined>) => void
34 setFontFamily: (fontFamily: Device['fontFamily']) => void
35 }
36 /**
37 * Feature flags or other gated options
38 */
39 flags: {}
40}
41
42/*
43 * Context
44 */
45export const Context = React.createContext<Alf>({
46 themeName: 'light',
47 theme: defaultTheme,
48 themes: createThemes({
49 hues: {
50 primary: BLUE_HUE,
51 negative: RED_HUE,
52 positive: GREEN_HUE,
53 },
54 }),
55 fonts: {
56 scale: getFontScale(),
57 scaleMultiplier: computeFontScaleMultiplier(getFontScale()),
58 family: getFontFamily(),
59 setFontScale: () => {},
60 setFontFamily: () => {},
61 },
62 flags: {},
63})
64Context.displayName = 'AlfContext'
65
66export function ThemeProvider({
67 children,
68 theme: themeName,
69}: React.PropsWithChildren<{theme: ThemeName}>) {
70 const [fontScale, setFontScale] = React.useState<Alf['fonts']['scale']>(() =>
71 getFontScale(),
72 )
73 const [fontScaleMultiplier, setFontScaleMultiplier] = React.useState(() =>
74 computeFontScaleMultiplier(fontScale),
75 )
76 const setFontScaleAndPersist = React.useCallback<
77 Alf['fonts']['setFontScale']
78 >(
79 fontScale => {
80 setFontScale(fontScale)
81 persistFontScale(fontScale)
82 setFontScaleMultiplier(computeFontScaleMultiplier(fontScale))
83 },
84 [setFontScale],
85 )
86 const [fontFamily, setFontFamily] = React.useState<Alf['fonts']['family']>(
87 () => getFontFamily(),
88 )
89 const setFontFamilyAndPersist = React.useCallback<
90 Alf['fonts']['setFontFamily']
91 >(
92 fontFamily => {
93 setFontFamily(fontFamily)
94 persistFontFamily(fontFamily)
95 },
96 [setFontFamily],
97 )
98 const themes = React.useMemo(() => {
99 return createThemes({
100 hues: {
101 primary: BLUE_HUE,
102 negative: RED_HUE,
103 positive: GREEN_HUE,
104 },
105 })
106 }, [])
107
108 const value = React.useMemo<Alf>(
109 () => ({
110 themes,
111 themeName: themeName,
112 theme: themes[themeName],
113 fonts: {
114 scale: fontScale,
115 scaleMultiplier: fontScaleMultiplier,
116 family: fontFamily,
117 setFontScale: setFontScaleAndPersist,
118 setFontFamily: setFontFamilyAndPersist,
119 },
120 flags: {},
121 }),
122 [
123 themeName,
124 themes,
125 fontScale,
126 setFontScaleAndPersist,
127 fontFamily,
128 setFontFamilyAndPersist,
129 fontScaleMultiplier,
130 ],
131 )
132
133 return <Context.Provider value={value}>{children}</Context.Provider>
134}
135
136export function useAlf() {
137 return React.useContext(Context)
138}
139
140export function useTheme(theme?: ThemeName) {
141 const alf = useAlf()
142 return React.useMemo(() => {
143 return theme ? alf.themes[theme] : alf.theme
144 }, [theme, alf])
145}