this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 248 lines 5.8 kB view raw
1import {createContext, useCallback, useContext, useMemo, useState} from 'react' 2import {createTheme, type Theme, type ThemeName} from '@bsky.app/alf' 3import chroma from 'chroma-js' 4 5import {useThemePrefs} from '#/state/shell/color-mode' 6import { 7 computeFontScaleMultiplier, 8 getFontFamily, 9 getFontScale, 10 setFontFamily as persistFontFamily, 11 setFontScale as persistFontScale, 12} from '#/alf/fonts' 13import { 14 blackskyscheme, 15 blueskyscheme, 16 catppuccinscheme, 17 deerscheme, 18 evergardenscheme, 19 kittyscheme, 20 type Palette, 21 reddwarfscheme, 22 themes, 23 witchskyscheme, 24 zeppelinscheme, 25} from '#/alf/themes' 26import {type Device} from '#/storage' 27 28export { 29 type TextStyleProp, 30 type Theme, 31 utils, 32 type ViewStyleProp, 33} from '@bsky.app/alf' 34export {atoms} from '#/alf/atoms' 35export * from '#/alf/breakpoints' 36export * from '#/alf/fonts' 37export * as tokens from '#/alf/tokens' 38export * from '#/alf/util/flatten' 39export * from '#/alf/util/platform' 40export * from '#/alf/util/themeSelector' 41export * from '#/alf/util/useGutters' 42 43export type Alf = { 44 themeName: ThemeName 45 theme: Theme 46 themes: typeof themes 47 fonts: { 48 scale: Exclude<Device['fontScale'], undefined> 49 scaleMultiplier: number 50 family: Device['fontFamily'] 51 setFontScale: (fontScale: Exclude<Device['fontScale'], undefined>) => void 52 setFontFamily: (fontFamily: Device['fontFamily']) => void 53 } 54 /** 55 * Feature flags or other gated options 56 */ 57 flags: {} 58} 59 60/* 61 * Context 62 */ 63export const Context = createContext<Alf>({ 64 themeName: 'light', 65 theme: themes.light, 66 themes, 67 fonts: { 68 scale: getFontScale(), 69 scaleMultiplier: computeFontScaleMultiplier(getFontScale()), 70 family: getFontFamily(), 71 setFontScale: () => {}, 72 setFontFamily: () => {}, 73 }, 74 flags: {}, 75}) 76Context.displayName = 'AlfContext' 77 78export type SchemeType = typeof themes 79 80export function changeHue(colorStr: string, hueShift: number) { 81 if (!hueShift || hueShift === 0) return colorStr 82 83 const color = chroma(colorStr).oklch() 84 85 const newHue = (color[2] + hueShift + 360) % 360 86 87 return chroma.oklch(color[0], color[1], newHue).hex() 88} 89 90export function shiftPalette(palette: Palette, hueShift: number): Palette { 91 const newPalette = {...palette} 92 const keys = Object.keys(newPalette) as Array<keyof Palette> 93 94 keys.forEach(key => { 95 if ( 96 key.startsWith('positive_') || 97 key.startsWith('negative_') || 98 key === 'like' || 99 key === 'pink' || 100 key === 'yellow' 101 ) { 102 return 103 } 104 newPalette[key] = changeHue(newPalette[key], hueShift) 105 }) 106 107 return newPalette 108} 109 110export function hueShifter(scheme: SchemeType, hueShift: number): SchemeType { 111 if (!hueShift || hueShift === 0) { 112 return scheme 113 } 114 115 const lightPalette = shiftPalette(scheme.lightPalette, hueShift) 116 const darkPalette = shiftPalette(scheme.darkPalette, hueShift) 117 const dimPalette = shiftPalette(scheme.dimPalette, hueShift) 118 119 const light = createTheme({ 120 scheme: 'light', 121 name: 'light', 122 palette: lightPalette, 123 }) 124 125 const dark = createTheme({ 126 scheme: 'dark', 127 name: 'dark', 128 palette: darkPalette, 129 options: { 130 shadowOpacity: 0.4, 131 }, 132 }) 133 134 const dim = createTheme({ 135 scheme: 'dark', 136 name: 'dim', 137 palette: dimPalette, 138 options: { 139 shadowOpacity: 0.4, 140 }, 141 }) 142 143 return { 144 lightPalette, 145 darkPalette, 146 dimPalette, 147 light, 148 dark, 149 dim, 150 } 151} 152 153export function selectScheme(colorScheme: string | undefined): SchemeType { 154 switch (colorScheme) { 155 case 'witchsky': 156 return witchskyscheme 157 case 'bluesky': 158 return blueskyscheme 159 case 'blacksky': 160 return blackskyscheme 161 case 'deer': 162 return deerscheme 163 case 'zeppelin': 164 return zeppelinscheme 165 case 'kitty': 166 return kittyscheme 167 case 'reddwarf': 168 return reddwarfscheme 169 case 'catppuccin': 170 return catppuccinscheme 171 case 'evergarden': 172 return evergardenscheme 173 default: 174 return themes 175 } 176} 177 178export function ThemeProvider({ 179 children, 180 theme: themeName, 181}: React.PropsWithChildren<{theme: ThemeName}>) { 182 const {colorScheme, hue} = useThemePrefs() 183 const currentScheme = selectScheme(colorScheme) 184 const [fontScale, setFontScale] = useState<Alf['fonts']['scale']>(() => 185 getFontScale(), 186 ) 187 const [fontScaleMultiplier, setFontScaleMultiplier] = useState(() => 188 computeFontScaleMultiplier(fontScale), 189 ) 190 const setFontScaleAndPersist = useCallback<Alf['fonts']['setFontScale']>( 191 fs => { 192 setFontScale(fs) 193 persistFontScale(fs) 194 setFontScaleMultiplier(computeFontScaleMultiplier(fs)) 195 }, 196 [setFontScale], 197 ) 198 const [fontFamily, setFontFamily] = useState<Alf['fonts']['family']>(() => 199 getFontFamily(), 200 ) 201 const setFontFamilyAndPersist = useCallback<Alf['fonts']['setFontFamily']>( 202 ff => { 203 setFontFamily(ff) 204 persistFontFamily(ff) 205 }, 206 [setFontFamily], 207 ) 208 209 const value = useMemo<Alf>(() => { 210 const shiftedThemes = hueShifter(currentScheme, hue) 211 212 return { 213 themes: shiftedThemes, 214 themeName: themeName, 215 theme: shiftedThemes[themeName], 216 fonts: { 217 scale: fontScale, 218 scaleMultiplier: fontScaleMultiplier, 219 family: fontFamily, 220 setFontScale: setFontScaleAndPersist, 221 setFontFamily: setFontFamilyAndPersist, 222 }, 223 flags: {}, 224 } 225 }, [ 226 currentScheme, 227 hue, 228 themeName, 229 fontScale, 230 fontScaleMultiplier, 231 fontFamily, 232 setFontScaleAndPersist, 233 setFontFamilyAndPersist, 234 ]) 235 236 return <Context.Provider value={value}>{children}</Context.Provider> 237} 238 239export function useAlf() { 240 return useContext(Context) 241} 242 243export function useTheme(theme?: ThemeName) { 244 const alf = useAlf() 245 return useMemo(() => { 246 return theme ? alf.themes[theme] : alf.theme 247 }, [theme, alf]) 248}