adds icon picker

This commit is contained in:
Christian Beutel
2024-03-14 17:02:58 +01:00
parent eeac6cadc1
commit aba9c85e99
4 changed files with 1501 additions and 8 deletions

View File

@@ -0,0 +1,93 @@
<script context="module" lang="ts">
export type ComboboxItem = {
text: string;
value: any;
icon: string;
};
</script>
<script lang="ts">
import { createEventDispatcher, tick } from "svelte";
import TextField from "./text_field.svelte";
export let name: string = "";
export let icon: string = "";
export let label: string = "";
export let value: string = "";
export let items: ComboboxItem[] = [];
export let placeholder: string = "";
export let extraClasses: string = "";
const dispatch = createEventDispatcher();
let searching: boolean = false;
$: dropDownOpen = value.length > 0 && items.length > 0 && searching;
async function onSearchType() {
await tick();
const dropdownMenu = document.querySelector(".menu");
if (dropdownMenu) {
let dropdownHTML = dropdownMenu.innerHTML;
for (const li of dropdownMenu.children) {
const textNode = li.getElementsByTagName("p")[0];
const text = textNode.innerText.replace(
new RegExp(value, "gi"),
(match) => `<strong>${match}</strong>`,
);
textNode.innerHTML = text;
}
}
update(value);
}
function update(q: string) {
dispatch("update", q);
}
function handleItemClick(item: ComboboxItem) {
value = item.value;
dispatch("click", item);
}
</script>
<div class="relative {extraClasses}">
<TextField
type="search"
{name}
autocomplete="off"
{icon}
{label}
{placeholder}
bind:value
on:change
on:input={onSearchType}
on:focusin={() => (searching = true)}
on:focusout={() => (searching = false)}
></TextField>
{#if dropDownOpen}
<ul
class="menu absolute bg-menu-background border border-input-border rounded-xl shadow-md w-full max-h-64 overflow-x-hidden overflow-y-scroll"
class:none={!dropDownOpen}
style="z-index: 1001"
>
{#each items as item}
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<li
class="menu-item flex items-center px-4 py-3 cursor-pointer hover:bg-menu-item-background-hover focus:bg-menu-item-background-focus transition-colors"
tabindex="0"
on:mousedown|stopPropagation={() => handleItemClick(item)}
on:keydown|stopPropagation={() => handleItemClick(item)}
>
<i class="fa fa-{item.icon} mr-6"></i>
<p class="text-ellipsis">{item.text}</p>
</li>
{/each}
</ul>
{/if}
</div>

View File

@@ -72,9 +72,9 @@
type="search"
name="q"
autocomplete="off"
extraClasses="{large
? 'px-12 py-4 text-xl min-w-80 w-[33vw] max-w-[532px] rounded-xl'
: 'px-10'}"
extraClasses={large
? "px-12 py-4 text-xl min-w-80 w-[33vw] max-w-[532px] rounded-xl"
: "px-10"}
{placeholder}
bind:value
on:input={onSearchType}

View File

@@ -3,9 +3,11 @@
import { createEventDispatcher } from "svelte";
import { waypoint } from "$lib/stores/waypoint_store";
import { icons } from "$lib/util/icon_util";
import { createForm } from "$lib/vendor/svelte-form-lib/index";
import { util } from "$lib/vendor/svelte-form-lib/util";
import { _ } from "svelte-i18n";
import Combobox from "../base/combobox.svelte";
import Modal from "../base/modal.svelte";
import TextField from "../base/text_field.svelte";
import Textarea from "../base/textarea.svelte";
@@ -23,6 +25,13 @@
},
});
$: form.set(util.cloneDeep($waypoint));
$: filteredIcons =
($form.icon?.length ?? 0) > 2
? icons
.filter((i) => i.includes($form.icon ?? ""))
.map((i) => ({ text: i, value: i, icon: i }))
: [];
</script>
<Modal
@@ -40,7 +49,7 @@
on:submit={handleSubmit}
>
<div class="flex gap-4">
<div class="basis-full">
<div class="basis-2/3">
<TextField
name="name"
label={$_("name")}
@@ -50,14 +59,14 @@
></TextField>
</div>
<TextField
<Combobox
name="icon"
label={$_("icon")}
bind:value={$form.icon}
icon={$form.icon}
error={$errors.icon}
items={filteredIcons}
label={$_("icon")}
on:change={handleChange}
></TextField>
></Combobox>
</div>
<Textarea

File diff suppressed because it is too large Load Diff