Bluesky app fork with some witchin' additions 馃挮
at 5ee667f307bc459ba53cdaabdad00a0ea1ee6846 133 lines 3.2 kB view raw
1import React from 'react' 2import {type Theme, type ThemeName} from '@bsky.app/alf' 3 4import { 5 computeFontScaleMultiplier, 6 getFontFamily, 7 getFontScale, 8 setFontFamily as persistFontFamily, 9 setFontScale as persistFontScale, 10} from '#/alf/fonts' 11import {themes} from '#/alf/themes' 12import {type Device} from '#/storage' 13 14export { 15 type TextStyleProp, 16 type Theme, 17 utils, 18 type ViewStyleProp, 19} from '@bsky.app/alf' 20export {atoms} from '#/alf/atoms' 21export * from '#/alf/breakpoints' 22export * from '#/alf/fonts' 23export * as tokens from '#/alf/tokens' 24export * from '#/alf/util/flatten' 25export * from '#/alf/util/platform' 26export * from '#/alf/util/themeSelector' 27export * from '#/alf/util/useGutters' 28 29export type Alf = { 30 themeName: ThemeName 31 theme: Theme 32 themes: typeof themes 33 fonts: { 34 scale: Exclude<Device['fontScale'], undefined> 35 scaleMultiplier: number 36 family: Device['fontFamily'] 37 setFontScale: (fontScale: Exclude<Device['fontScale'], undefined>) => void 38 setFontFamily: (fontFamily: Device['fontFamily']) => void 39 } 40 /** 41 * Feature flags or other gated options 42 */ 43 flags: {} 44} 45 46/* 47 * Context 48 */ 49export const Context = React.createContext<Alf>({ 50 themeName: 'light', 51 theme: themes.light, 52 themes, 53 fonts: { 54 scale: getFontScale(), 55 scaleMultiplier: computeFontScaleMultiplier(getFontScale()), 56 family: getFontFamily(), 57 setFontScale: () => {}, 58 setFontFamily: () => {}, 59 }, 60 flags: {}, 61}) 62Context.displayName = 'AlfContext' 63 64export function ThemeProvider({ 65 children, 66 theme: themeName, 67}: React.PropsWithChildren<{theme: ThemeName}>) { 68 const [fontScale, setFontScale] = React.useState<Alf['fonts']['scale']>(() => 69 getFontScale(), 70 ) 71 const [fontScaleMultiplier, setFontScaleMultiplier] = React.useState(() => 72 computeFontScaleMultiplier(fontScale), 73 ) 74 const setFontScaleAndPersist = React.useCallback< 75 Alf['fonts']['setFontScale'] 76 >( 77 fs => { 78 setFontScale(fs) 79 persistFontScale(fs) 80 setFontScaleMultiplier(computeFontScaleMultiplier(fs)) 81 }, 82 [setFontScale], 83 ) 84 const [fontFamily, setFontFamily] = React.useState<Alf['fonts']['family']>( 85 () => getFontFamily(), 86 ) 87 const setFontFamilyAndPersist = React.useCallback< 88 Alf['fonts']['setFontFamily'] 89 >( 90 ff => { 91 setFontFamily(ff) 92 persistFontFamily(ff) 93 }, 94 [setFontFamily], 95 ) 96 97 const value = React.useMemo<Alf>( 98 () => ({ 99 themes, 100 themeName: themeName, 101 theme: themes[themeName], 102 fonts: { 103 scale: fontScale, 104 scaleMultiplier: fontScaleMultiplier, 105 family: fontFamily, 106 setFontScale: setFontScaleAndPersist, 107 setFontFamily: setFontFamilyAndPersist, 108 }, 109 flags: {}, 110 }), 111 [ 112 themeName, 113 fontScale, 114 setFontScaleAndPersist, 115 fontFamily, 116 setFontFamilyAndPersist, 117 fontScaleMultiplier, 118 ], 119 ) 120 121 return <Context.Provider value={value}>{children}</Context.Provider> 122} 123 124export function useAlf() { 125 return React.useContext(Context) 126} 127 128export function useTheme(theme?: ThemeName) { 129 const alf = useAlf() 130 return React.useMemo(() => { 131 return theme ? alf.themes[theme] : alf.theme 132 }, [theme, alf]) 133}