|
12 | 12 | primaryColor = $bindable(), |
13 | 13 | accentColor = $bindable(), |
14 | 14 | }: { |
15 | | - currentTheme: string | null | undefined; |
| 15 | + currentTheme: string | null | undefined; |
16 | 16 | primaryColor: string | null | undefined; |
17 | 17 | accentColor: string | null | undefined; |
18 | 18 | } = $props(); |
19 | 19 |
|
20 | 20 | let saving = $state(false); |
21 | 21 | const hexColorRegex = /^#([0-9a-f]{6})$/i; |
22 | 22 |
|
23 | | - const currentThemeData = $derived(currentTheme ? getTheme(currentTheme) ?? null : null); |
| 23 | + const currentThemeData = $derived(currentTheme ? (getTheme(currentTheme) ?? null) : null); |
24 | 24 | const primarySwatch = $derived( |
25 | 25 | primaryColor && hexColorRegex.test(primaryColor) |
26 | 26 | ? primaryColor.toLowerCase() |
27 | | - : currentThemeData?.colors.primary ?? getComputedThemeColor('--primary') ?? '#0f172a' |
| 27 | + : (currentThemeData?.colors.primary ?? getComputedThemeColor('--primary') ?? '#0f172a') |
28 | 28 | ); |
29 | 29 | const accentSwatch = $derived( |
30 | 30 | accentColor && hexColorRegex.test(accentColor) |
31 | 31 | ? accentColor.toLowerCase() |
32 | | - : currentThemeData?.colors.accent ?? getComputedThemeColor('--accent') ?? '#0f172a' |
| 32 | + : (currentThemeData?.colors.accent ?? getComputedThemeColor('--accent') ?? '#0f172a') |
33 | 33 | ); |
34 | 34 |
|
35 | 35 | function normalizeHex(color: string | null | undefined): string | null { |
|
40 | 40 |
|
41 | 41 | function getComputedThemeColor(variable: '--primary' | '--accent'): string | null { |
42 | 42 | if (typeof document === 'undefined') return null; |
43 | | - const style = getComputedStyle(document.documentElement).getPropertyValue(variable).trim().toLowerCase(); |
| 43 | + const style = getComputedStyle(document.documentElement) |
| 44 | + .getPropertyValue(variable) |
| 45 | + .trim() |
| 46 | + .toLowerCase(); |
44 | 47 | return /^#([0-9a-f]{6})$/.test(style) ? style : null; |
45 | 48 | } |
46 | 49 |
|
47 | | - async function saveTheme(themeId: string | null, nextPrimaryColor: string | null, nextAccentColor: string | null) { |
| 50 | + async function saveTheme( |
| 51 | + themeId: string | null, |
| 52 | + nextPrimaryColor: string | null, |
| 53 | + nextAccentColor: string | null |
| 54 | + ) { |
48 | 55 | if (!session.current?.user.id) return; |
49 | 56 |
|
50 | | - const theme = themeId ? getTheme(themeId) ?? null : null; |
| 57 | + const theme = themeId ? (getTheme(themeId) ?? null) : null; |
51 | 58 | const previousTheme = currentTheme; |
52 | 59 | const previousPrimaryColor = normalizeHex(primaryColor); |
53 | 60 | const previousAccentColor = normalizeHex(accentColor); |
|
82 | 89 | currentTheme = previousTheme; |
83 | 90 | primaryColor = previousPrimaryColor; |
84 | 91 | accentColor = previousAccentColor; |
85 | | - const previousThemeData = previousTheme ? getTheme(previousTheme) ?? null : null; |
| 92 | + const previousThemeData = previousTheme ? (getTheme(previousTheme) ?? null) : null; |
86 | 93 | applyTheme(previousThemeData, { |
87 | 94 | primaryColor: previousPrimaryColor, |
88 | 95 | accentColor: previousAccentColor, |
|
118 | 125 | void saveTheme(currentTheme ?? null, normalizeHex(primaryColor), null); |
119 | 126 | } |
120 | 127 | } |
121 | | -
|
122 | 128 | </script> |
123 | 129 |
|
124 | 130 | <div class="flex flex-col gap-4"> |
|
167 | 173 | <div class="mt-2 flex gap-1"> |
168 | 174 | <div |
169 | 175 | class="h-8 w-8 rounded border" |
170 | | - style="background-color: {theme.colors.background}; border-color: {theme.colors.border};" |
| 176 | + style="background-color: {theme.colors.background}; border-color: {theme.colors |
| 177 | + .border};" |
171 | 178 | ></div> |
172 | 179 | <div |
173 | 180 | class="h-8 w-8 rounded border" |
|
187 | 194 | </div> |
188 | 195 |
|
189 | 196 | {#if currentThemeData || currentTheme === null} |
190 | | - <div class="space-y-3 rounded-lg border border-border p-3"> |
| 197 | + <div class="border-border space-y-3 rounded-lg border p-3"> |
191 | 198 | <p class="text-muted-foreground text-sm">Customize this theme's key accents.</p> |
192 | 199 |
|
193 | 200 | <div class="grid grid-cols-1 gap-3 sm:grid-cols-2"> |
194 | 201 | <div class="flex flex-col gap-2"> |
195 | | - <label class="text-sm font-medium">Primary</label> |
| 202 | + <label for="theme-primary-color" class="text-sm font-medium">Primary</label> |
196 | 203 | <div class="flex items-center gap-2"> |
197 | 204 | <input |
| 205 | + id="theme-primary-color" |
198 | 206 | type="color" |
199 | 207 | value={primarySwatch} |
200 | 208 | onchange={handlePrimaryColorChange} |
|
214 | 222 | </div> |
215 | 223 | </div> |
216 | 224 | <div class="flex flex-col gap-2"> |
217 | | - <label class="text-sm font-medium">Accent</label> |
| 225 | + <label for="theme-accent-color" class="text-sm font-medium">Accent</label> |
218 | 226 | <div class="flex items-center gap-2"> |
219 | 227 | <input |
| 228 | + id="theme-accent-color" |
220 | 229 | type="color" |
221 | 230 | value={accentSwatch} |
222 | 231 | onchange={handleAccentColorChange} |
|
0 commit comments