Files
sui/components/ToggleGroup.svelte
2025-04-13 07:56:23 -07:00

72 lines
1.7 KiB
Svelte

<script lang="ts">
import Label from './Label.svelte';
import ToggleSelect from './ToggleSelect.svelte';
import { validate, validateInput } from '@repo/validate';
let {
items,
selected = $bindable([]),
name,
label,
required,
missingMessage
}: {
items: string[];
selected?: string[];
name?: string;
label: string;
required?: boolean;
missingMessage?: string;
} = $props();
let inputElement: HTMLInputElement | undefined = $state<HTMLInputElement>();
let valid: boolean = $state(true);
const makeSelectedHandler = (name: string) => {
return (toggled: boolean) => {
if (!inputElement) return;
if (toggled) selected = [...selected, name];
else selected = selected.filter((item) => item !== name);
inputElement.value = JSON.stringify(selected);
validateInput(inputElement); // trigger validation on hidden input
};
};
</script>
<div>
{#if label && name}
<Label for={name}>{label}</Label>
{/if}
<div class="flex flex-wrap gap-3">
{#if name}
<input
type="hidden"
{name}
required={required ? true : false}
use:validate={{ required, baseval: '[]' }}
bind:this={inputElement}
onvalidate={(e) => {
valid = e.detail.valid;
}}
/>
{/if}
{#each items as item}
<ToggleSelect name={name ? undefined : `toggl_${item}`} ontoggle={makeSelectedHandler(item)}>
<span class="capitalize">{item}</span>
</ToggleSelect>
{/each}
</div>
{#if name}
<div class={['mt-2 opacity-0 transition-opacity', !valid && 'opacity-100']}>
<Label for={name} error>
{missingMessage !== undefined && missingMessage !== ''
? missingMessage
: 'Field is required'}
</Label>
</div>
{/if}
</div>