mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-11-24 23:19:12 +03:00
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:
parent
a3800459c3
commit
057df19c9d
@ -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"
|
||||
|
@ -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}
|
||||
|
Loading…
Reference in New Issue
Block a user