update search component
All checks were successful
delpoy / build-and-deploy (push) Successful in 52s

This commit is contained in:
bytedream 2024-12-05 23:26:30 +01:00
parent ffc4dcf8f5
commit a0cc11860f
3 changed files with 26 additions and 29 deletions

View File

@ -2,7 +2,6 @@
let { let {
id, id,
value = $bindable(), value = $bindable(),
inputValue = $bindable(),
suggestionRequired = false, suggestionRequired = false,
emptyAllowed = false, emptyAllowed = false,
searchSuggestionFunc = () => Promise.resolve([]), searchSuggestionFunc = () => Promise.resolve([]),
@ -13,8 +12,7 @@
onsubmit onsubmit
}: { }: {
id?: string; id?: string;
value?: string; value: string;
inputValue?: string;
suggestionRequired?: boolean; suggestionRequired?: boolean;
emptyAllowed?: boolean; emptyAllowed?: boolean;
searchSuggestionFunc?: (input: string) => Promise<{ name: string; value: string }[]>; searchSuggestionFunc?: (input: string) => Promise<{ name: string; value: string }[]>;
@ -25,10 +23,8 @@
onsubmit?: (event: Event & { input: string; value: string }) => void; onsubmit?: (event: Event & { input: string; value: string }) => void;
} = $props(); } = $props();
let elemValue = $state(value);
let searchSuggestions: { name: string; value: string }[] = $state([]); let searchSuggestions: { name: string; value: string }[] = $state([]);
$effect(() => {
if (!suggestionRequired) value = inputValue;
});
</script> </script>
<div class="relative"> <div class="relative">
@ -45,6 +41,7 @@
{/if} {/if}
<input <input
type="search" type="search"
autocomplete="off"
class="input input-bordered w-full" class="input input-bordered w-full"
class:input-xs={size === 'xs'} class:input-xs={size === 'xs'}
class:input-sm={size === 'sm'} class:input-sm={size === 'sm'}
@ -52,33 +49,33 @@
class:input-lg={size === 'lg'} class:input-lg={size === 'lg'}
{id} {id}
{required} {required}
bind:value={inputValue} bind:value={elemValue}
oninput={(e: Event & { currentTarget: EventTarget & HTMLInputElement }) => { oninput={async (e: Event & { currentTarget: EventTarget & HTMLInputElement }) => {
value = ''; searchSuggestions = await searchSuggestionFunc(elemValue);
searchSuggestionFunc(inputValue).then((v) => { const searchSuggestion = searchSuggestions.find((v) => v.name === elemValue);
searchSuggestions = v;
const searchSuggestion = v.find((v) => v.name === inputValue);
if (searchSuggestion !== undefined) { if (searchSuggestion !== undefined) {
inputValue = searchSuggestion.name; elemValue = searchSuggestion.name;
value = searchSuggestion.value; value = searchSuggestion.value;
searchSuggestions = []; searchSuggestions = [];
e.currentTarget.setCustomValidity(''); (e.currentTarget || e.target).setCustomValidity('');
onsubmit?.(Object.assign(e, { input: inputValue, value: value })); onsubmit?.(Object.assign(e, { input: elemValue, value: value }));
} else if (inputValue === '' && emptyAllowed) { } else if (elemValue === '' && emptyAllowed) {
onsubmit?.(Object.assign(e, { input: '', value: '' })); onsubmit?.(Object.assign(e, { input: '', value: '' }));
} else {
value = '';
} }
});
}} }}
oninvalid={(e: Event & { currentTarget: EventTarget & HTMLInputElement }) => { oninvalid={(e: Event & { currentTarget: EventTarget & HTMLInputElement }) => {
if (invalidMessage) e.currentTarget.setCustomValidity(invalidMessage); if (invalidMessage) e.currentTarget.setCustomValidity(invalidMessage);
}} }}
onfocus={() => searchSuggestionFunc(elemValue).then((v) => (searchSuggestions = v))}
pattern={suggestionRequired pattern={suggestionRequired
? `${value ? inputValue : 'a^' + (emptyAllowed ? '|$^' : '')}` ? `${value ? elemValue : 'a^' + (emptyAllowed ? '|$^' : '')}`
: null} : null}
/> />
</div> </div>
{#if inputValue && searchSuggestions.length !== 0} {#if elemValue && searchSuggestions.length !== 0}
<ul class="absolute bg-base-200 w-full z-20 menu menu-sm rounded-box"> <ul class="absolute bg-base-200 w-full z-20 menu menu-sm rounded-box">
{#each searchSuggestions as searchSuggestion} {#each searchSuggestions as searchSuggestion}
<li class="w-full text-left"> <li class="w-full text-left">
@ -86,10 +83,10 @@
class="block w-full overflow-hidden text-ellipsis whitespace-nowrap" class="block w-full overflow-hidden text-ellipsis whitespace-nowrap"
title="{searchSuggestion.name} ({searchSuggestion.value})" title="{searchSuggestion.name} ({searchSuggestion.value})"
onclick={(e) => { onclick={(e) => {
inputValue = searchSuggestion.name; elemValue = searchSuggestion.name;
value = searchSuggestion.value; value = searchSuggestion.value;
searchSuggestions = []; searchSuggestions = [];
onsubmit?.(Object.assign(e, { input: inputValue, value: value })); onsubmit?.(Object.assign(e, { input: elemValue, value: value }));
}}>{searchSuggestion.name}</button }}>{searchSuggestion.name}</button
> >
</li> </li>
@ -99,7 +96,7 @@
</div> </div>
<!-- close the search suggestions box when clicking outside --> <!-- close the search suggestions box when clicking outside -->
{#if inputValue && searchSuggestions.length !== 0} {#if elemValue && searchSuggestions.length !== 0}
<button <button
aria-label=" " aria-label=" "
class="absolute top-0 left-0 z-10 w-full h-full cursor-default" class="absolute top-0 left-0 z-10 w-full h-full cursor-default"

View File

@ -262,7 +262,7 @@
searchSuggestionFunc={usernameSuggestions} searchSuggestionFunc={usernameSuggestions}
invalidMessage="Es können nur registrierte Spieler reportet werden" invalidMessage="Es können nur registrierte Spieler reportet werden"
label="Reporteter User" label="Reporteter User"
inputValue={activeReport.reported?.username || ''} value={activeReport.reported?.username || ''}
onsubmit={(e) => onsubmit={(e) =>
(activeReport.reported = { (activeReport.reported = {
...activeReport.reported, ...activeReport.reported,

View File

@ -21,7 +21,7 @@
<ReportDraft <ReportDraft
reason={data.reason} reason={data.reason}
reporterName={data.reporter.name} reporterName={data.reporter.name}
reportedName={data.reported.name ?? undefined} reportedName={data.reported.name ?? null}
users={data.users ?? []} users={data.users ?? []}
onsubmit={() => (completed = true)} onsubmit={() => (completed = true)}
/> />