Files
shd.build/src/lib/components/BuilderPicker.svelte
T
jb 4777a3abd5
Validate and deploy production / validate (push) Canceled after 0s
Validate and deploy production / deploy (push) Canceled after 0s
Validate and deploy staging / validate (push) Successful in 44s
Validate and deploy staging / deploy (push) Successful in 1m14s
feat: refine builder skill chip flows
2026-08-06 01:00:15 -04:00

47 lines
1.9 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script lang="ts">
import ItemIcon from './ItemIcon.svelte';
let {
items,
value = $bindable(''),
label,
placeholder = 'Search…',
disabledIds = [],
onchange
}: {
items: Array<{ id: string; name: string; iconUrl?: string; category?: string; pending?: boolean }>;
value?: string;
label: string;
placeholder?: string;
disabledIds?: string[];
onchange?: (id: string) => void;
} = $props();
let open = $state(false);
let query = $state('');
const selected = $derived(items.find((item) => item.id === value));
const results = $derived(items.filter((item) => item.name.toLocaleLowerCase().includes(query.trim().toLocaleLowerCase())).slice(0, 40));
const choose = (id: string) => { value = id; onchange?.(id); open = false; query = ''; };
</script>
<div class="builder-picker">
<span>{label}</span>
<button type="button" class="builder-picker-current" aria-expanded={open} onclick={() => open = !open}>
<ItemIcon src={selected?.iconUrl} alt=""/>
<b>{selected?.name ?? 'SELECT ITEM'}</b><small>{selected?.category ?? (selected ? 'EQUIPPED' : 'UNASSIGNED')}</small><em>{open ? '×' : '+'}</em>
</button>
{#if open}
<div class="builder-picker-panel">
<input type="search" bind:value={query} {placeholder} aria-label={placeholder}/>
<div>
{#if selected}<button type="button" class="builder-picker-clear" onclick={() => choose('')}><i>×</i><span><b>CLEAR</b><small>REMOVE SELECTION</small></span><em>CLEAR</em></button>{/if}
{#each results as item}
<button type="button" class:selected={item.id === value} disabled={disabledIds.includes(item.id)} onclick={() => choose(item.id)}>
<ItemIcon src={item.iconUrl} alt=""/>
<span><b>{item.name}</b><small>{item.category ?? 'AVAILABLE'}</small></span><em>{item.id === value ? 'EQUIPPED' : disabledIds.includes(item.id) ? 'CONFLICT' : 'SELECT'}</em>
</button>
{:else}<p>NO MATCHES</p>{/each}
</div>
</div>
{/if}
</div>