69 lines
1.8 KiB
Svelte
69 lines
1.8 KiB
Svelte
<script lang="ts">
|
|
import { Button } from '$lib/components/ui/button';
|
|
import { Palette } from 'lucide-svelte';
|
|
import { AVAILABLE_THEMES } from '$lib/utils/themes';
|
|
|
|
let {
|
|
value = 'none',
|
|
onValueChange
|
|
}: {
|
|
value?: string;
|
|
onValueChange: (theme: string) => void;
|
|
} = $props();
|
|
|
|
let showMenu = $state(false);
|
|
|
|
function toggleMenu() {
|
|
showMenu = !showMenu;
|
|
}
|
|
|
|
function handleSelect(themeName: string) {
|
|
onValueChange(themeName);
|
|
showMenu = false;
|
|
}
|
|
|
|
function handleClickOutside(event: MouseEvent) {
|
|
const target = event.target as HTMLElement;
|
|
if (!target.closest('.theme-picker-menu')) {
|
|
showMenu = false;
|
|
}
|
|
}
|
|
|
|
$effect(() => {
|
|
if (showMenu) {
|
|
document.addEventListener('click', handleClickOutside);
|
|
return () => document.removeEventListener('click', handleClickOutside);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<div class="relative theme-picker-menu">
|
|
<Button variant="outline" size="icon" onclick={toggleMenu} aria-label="Select theme pattern">
|
|
<Palette class="h-[1.2rem] w-[1.2rem]" />
|
|
</Button>
|
|
|
|
{#if showMenu}
|
|
<div
|
|
class="absolute left-0 sm:right-0 sm:left-auto mt-2 w-40 rounded-md border border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-950 shadow-lg z-50"
|
|
>
|
|
<div class="py-1">
|
|
{#each Object.entries(AVAILABLE_THEMES) as [key, theme]}
|
|
<button
|
|
type="button"
|
|
class="w-full text-left px-4 py-2 text-sm hover:bg-slate-100 dark:hover:bg-slate-900 transition-colors flex items-center justify-between"
|
|
class:font-bold={value === key}
|
|
class:bg-slate-100={value === key}
|
|
class:dark:bg-slate-900={value === key}
|
|
onclick={() => handleSelect(key)}
|
|
>
|
|
<span>{theme.name}</span>
|
|
{#if value === key}
|
|
<span class="ml-2">✓</span>
|
|
{/if}
|
|
</button>
|
|
{/each}
|
|
</div>
|
|
</div>
|
|
{/if}
|
|
</div>
|