2025-10-20 14:39:53 +00:00
|
|
|
<script lang="ts">
|
|
|
|
|
import {createSearch} from "@welshman/app"
|
|
|
|
|
import Icon from "@lib/components/Icon.svelte"
|
2026-09-04 15:36:19 +00:00
|
|
|
import Spinner from "@lib/components/Spinner.svelte"
|
2025-10-20 14:39:53 +00:00
|
|
|
import Magnifier from "@assets/icons/magnifier.svg?dataurl"
|
2026-09-04 15:36:19 +00:00
|
|
|
import type {IconOption} from "@app/icons"
|
2025-10-20 14:39:53 +00:00
|
|
|
|
|
|
|
|
type Props = {
|
|
|
|
|
onSelect: (iconUrl: string) => void
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const {onSelect}: Props = $props()
|
|
|
|
|
|
2026-09-04 15:36:19 +00:00
|
|
|
let icons: IconOption[] = $state([])
|
2025-10-20 14:39:53 +00:00
|
|
|
let searchTerm = $state("")
|
|
|
|
|
|
2026-09-04 15:36:19 +00:00
|
|
|
const loading = import("@app/icons").then(module => {
|
|
|
|
|
icons = module.icons
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const iconSearch = $derived(
|
|
|
|
|
createSearch(icons, {
|
|
|
|
|
getValue: (icon: IconOption) => icon.name,
|
|
|
|
|
fuseOptions: {
|
|
|
|
|
keys: ["name", "searchText"],
|
|
|
|
|
threshold: 0.4,
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
|
2025-10-20 14:39:53 +00:00
|
|
|
const filteredIcons = $derived(searchTerm ? iconSearch.searchOptions(searchTerm) : icons)
|
|
|
|
|
</script>
|
|
|
|
|
|
2026-06-24 20:56:53 +00:00
|
|
|
<label class="input flex w-full items-center gap-2">
|
2026-01-29 19:11:08 +00:00
|
|
|
<Icon icon={Magnifier} />
|
|
|
|
|
<input bind:value={searchTerm} class="grow" type="text" placeholder="Search icons..." />
|
|
|
|
|
</label>
|
|
|
|
|
<div class="mt-2 max-h-80 overflow-y-auto">
|
2026-09-04 15:36:19 +00:00
|
|
|
{#await loading}
|
|
|
|
|
<Spinner class="p-2">Loading icons…</Spinner>
|
|
|
|
|
{:then}
|
|
|
|
|
<div class="grid grid-cols-8 gap-2 p-2">
|
|
|
|
|
{#each filteredIcons as icon (icon.name)}
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
title={icon.name}
|
|
|
|
|
class="flex aspect-square items-center justify-center rounded-2xl transition-colors hover:bg-primary hover:text-primary-content"
|
|
|
|
|
onclick={() => onSelect(icon.url)}>
|
|
|
|
|
<Icon icon={icon.url} class="h-6 w-6" />
|
|
|
|
|
</button>
|
|
|
|
|
{/each}
|
|
|
|
|
</div>
|
|
|
|
|
{/await}
|
2025-10-20 14:39:53 +00:00
|
|
|
</div>
|