Files
tatort/src/lib/components/ui/Select.svelte
2025-04-11 11:31:10 +02:00

127 lines
3.0 KiB
Svelte

<style>
img {
width: 'auto';
height: 90%;
flex-shrink: 0;
}
</style>
<script>
import { clickOutside } from '$lib/helpers/clickOutside.js';
import Check from '$lib/icons/Check.svelte';
import Selector from '$lib/icons/Selector.svelte';
import Button from './Button.svelte';
export let title = 'Bitte wählen';
export let options = [];
export let onChange = null;
export let selected = -1;
export let disabled = false;
let classNames = '';
export { classNames as class };
let showOptions = false;
const selectOnChange = (index) => {
setTimeout(() => {
hideShowOptions();
}, 0);
if (typeof onChange == 'function') onChange(index);
};
const toggleShowOptions = () => {
showOptions = !showOptions;
};
const hideShowOptions = () => {
showOptions = false;
};
$: selected = selected ?? -1;
$: selectedItem =
selected >= 0
? options[selected]
: {
title,
img: null
};
</script>
<div class={classNames}>
<div use:clickOutside on:click_outside={hideShowOptions} class="relative mt-1">
<Button
on:click={toggleShowOptions}
{disabled}
type="button"
variant="white"
fullWidth
align="left"
class="relative cursor-default justify-start py-2 pl-3 pr-10 text-left"
>
<span class="flex h-6 items-center">
{#if selectedItem.img}
<img src={selectedItem.img} alt={selectedItem.alt} />
{/if}
<span class="ml-3 block truncate">
{selectedItem.title}
</span>
</span>
<span class="pointer-events-none absolute inset-y-0 right-0 ml-3 flex items-center pr-2">
<Selector />
</span>
</Button>
<div
class:hidden={!showOptions}
class="absolute z-10 mt-1 w-full rounded-md bg-white shadow-lg"
>
<ul
tabindex="-1"
role="listbox"
aria-labelledby="listbox-label"
class="max-h-48 overflow-auto rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"
>
<!--
Select option, manage highlight styles based on mouseenter/mouseleave and keyboard navigation.
Highlighted: "text-white bg-indigo-600", Not Highlighted: "text-gray-900"
-->
{#each options as option, index}
<li
on:click={() => {
selectOnChange(index);
}}
id="listbox-item-0"
role="option"
class="group relative cursor-default select-none py-2 pl-3 pr-9 text-gray-900 hover:bg-blue-500 hover:text-white"
>
<div class="flex h-6 items-center">
{#if option.img}
<img src={option.img} alt={option.alt} />
{/if}
<!-- Selected: "font-bold", Not Selected: "font-normal" -->
<span
class:font-bold={selected === index}
class:font-normal={!selected === index}
class:ml-3={option.img}
class="block truncate"
>
{option.title}
</span>
</div>
{#if selected === index}
<span
class="absolute inset-y-0 right-0 flex items-center pr-4 text-blue-500 group-hover:text-white"
>
<Check />
</span>
{/if}
</li>
{/each}
</ul>
</div>
</div>
</div>