Coves frontend - a photon fork
1<script lang="ts">
2 import { locale } from '$lib/app/i18n'
3 import { type Snippet, getContext, onDestroy } from 'svelte'
4 import type { IconSource } from 'svelte-hero-icons/dist'
5 import type { HTMLOptionAttributes } from 'svelte/elements'
6
7 interface Props extends Omit<HTMLOptionAttributes, 'prefix'> {
8 children: Snippet
9 icon?: IconSource
10 }
11 let { children, icon, ...rest }: Props = $props()
12
13 let optionElement = $state<HTMLOptionElement>()
14 let option = $derived({
15 value: optionElement?.value ?? '',
16 label: optionElement?.innerText ?? '',
17 icon: icon,
18 disabled: optionElement?.disabled,
19 isLabel: optionElement?.getAttribute('data-label') == 'true',
20 })
21
22 interface SelectContext {
23 options: {
24 value: string
25 label: string
26 icon?: IconSource
27 disabled?: boolean
28 isLabel?: boolean
29 }[]
30 }
31
32 const context = getContext<SelectContext>('select')
33
34 $effect(() => {
35 if ($locale || !context.options.find((v) => v == option)) {
36 const index = context.options.findIndex((i) => i.value == option.value)
37
38 if (index != -1) {
39 context.options.splice(index, 1, option)
40 } else {
41 context.options.push(option)
42 }
43 }
44 })
45
46 onDestroy(() => {
47 const index = context.options.findIndex((i) => i.value == option.value)
48 if (index != -1) {
49 context.options.splice(index, 1)
50 }
51 })
52</script>
53
54{#key $locale}
55 <option {...rest} bind:this={optionElement}>
56 {@render children()}
57 </option>
58{/key}