Clean-up: Remove anti-pattern from the Select component

Instead of updating the state through an effect, factor out the `searchValue` state variable into the parent component, and only derive the filtered options from it
This commit is contained in:
estib 2024-09-05 15:25:29 +02:00
parent a3800459c3
commit 057df19c9d
2 changed files with 11 additions and 32 deletions

View File

@ -1,42 +1,27 @@
<script lang="ts">
import { type SelectItem } from './Select.svelte';
import Icon from '@gitbutler/ui/Icon.svelte';
interface Props {
searchValue: string;
placeholder?: string;
items: SelectItem[];
onSort?: (items: SelectItem[]) => void;
}
const { placeholder = 'Search…', items, onSort }: Props = $props();
let value = $state('');
let filteredItems = $state(items);
let { placeholder = 'Search…', searchValue = $bindable() }: Props = $props();
let inputEl: HTMLInputElement;
function handleFilter() {
filteredItems = items.filter((item) => item.label.toLowerCase().includes(value.toLowerCase()));
}
function resetFilter() {
value = '';
handleFilter();
searchValue = '';
inputEl.focus();
}
function handleInput(event: Event) {
value = (event.target as HTMLInputElement).value;
handleFilter();
searchValue = (event.target as HTMLInputElement).value;
}
$effect(() => {
onSort?.(filteredItems);
});
</script>
<div class="container">
{#if !value}
{#if !searchValue}
<i class="icon search-icon">
<Icon name="search" />
</i>
@ -51,7 +36,7 @@
class="text-13 search-input"
type="text"
{placeholder}
bind:value
bind:value={searchValue}
oninput={handleInput}
autocorrect="off"
autocomplete="off"

View File

@ -50,15 +50,14 @@
let selectWrapperEl: HTMLElement;
let highlightedIndex: number | undefined = $state(undefined);
let filteredOptions = $state(options);
let searchValue = $state('');
let filteredOptions = $derived(
options.filter((item) => item.label.toLowerCase().includes(searchValue.toLowerCase()))
);
let maxHeightState = $state(maxHeight);
let listOpen = $state(false);
let inputBoundingRect = $state<DOMRect>();
$effect(() => {
filteredOptions = options;
});
const maxBottomPadding = 20;
function setMaxHeight() {
@ -187,12 +186,7 @@
>
<ScrollableContainer initiallyVisible>
{#if searchable && options.length > 5}
<SearchItem
items={options}
onSort={(filtered) => {
filteredOptions = filtered;
}}
/>
<SearchItem bind:searchValue />
{/if}
<OptionsGroup>
{#if filteredOptions.length === 0}