@melt-ui/svelte
Advanced tools
Comparing version 0.48.0 to 0.49.0
@@ -20,18 +20,3 @@ /// <reference types="svelte" /> | ||
subscribe(this: void, run: import("svelte/store").Subscriber<boolean>, invalidate?: import("svelte/store").Invalidator<boolean> | undefined): import("svelte/store").Unsubscriber; | ||
}, Writable<HTMLElement | null>, { | ||
debouncedSet: (value: string) => void; | ||
debouncedUpdate: (fn: (value: string) => string) => void; | ||
set: (value: string) => void; | ||
update: (fn: (value: string) => string) => void; | ||
subscribe(this: void, run: import("svelte/store").Subscriber<{ | ||
value: string; | ||
debounced: string; | ||
}>, invalidate?: import("svelte/store").Invalidator<{ | ||
value: string; | ||
debounced: string; | ||
}> | undefined): import("svelte/store").Unsubscriber; | ||
}], (node: HTMLInputElement) => MeltActionReturn<ComboboxEvents['input']>, ([$open, $highlightedItem, $inputValue]: [boolean, HTMLElement | null, { | ||
value: string; | ||
debounced: string; | ||
}]) => { | ||
}, Writable<HTMLElement | null>, Writable<string>], (node: HTMLInputElement) => MeltActionReturn<ComboboxEvents['input']>, ([$open, $highlightedItem, $inputValue]: [boolean, HTMLElement | null, string]) => { | ||
readonly 'aria-activedescendant': string | undefined; | ||
@@ -52,33 +37,3 @@ readonly 'aria-autocomplete': "list"; | ||
subscribe(this: void, run: import("svelte/store").Subscriber<ComboboxOption<Value> | undefined>, invalidate?: import("svelte/store").Invalidator<ComboboxOption<Value> | undefined> | undefined): import("svelte/store").Unsubscriber; | ||
}, Writable<import("./types.js").ComboboxFilterFunction<Value>>, { | ||
debouncedSet: (value: string) => void; | ||
debouncedUpdate: (fn: (value: string) => string) => void; | ||
set: (value: string) => void; | ||
update: (fn: (value: string) => string) => void; | ||
subscribe(this: void, run: import("svelte/store").Subscriber<{ | ||
value: string; | ||
debounced: string; | ||
}>, invalidate?: import("svelte/store").Invalidator<{ | ||
value: string; | ||
debounced: string; | ||
}> | undefined): import("svelte/store").Unsubscriber; | ||
}, { | ||
debouncedSet: (value: boolean) => void; | ||
debouncedUpdate: (fn: (value: boolean) => boolean) => void; | ||
set: (value: boolean) => void; | ||
update: (fn: (value: boolean) => boolean) => void; | ||
subscribe(this: void, run: import("svelte/store").Subscriber<{ | ||
value: boolean; | ||
debounced: boolean; | ||
}>, invalidate?: import("svelte/store").Invalidator<{ | ||
value: boolean; | ||
debounced: boolean; | ||
}> | undefined): import("svelte/store").Unsubscriber; | ||
}], (node: HTMLElement) => MeltActionReturn<ComboboxEvents['item']>, ([$value, $filterFunction, $inputValue, $touchedInput]: [ComboboxOption<Value> | undefined, import("./types.js").ComboboxFilterFunction<Value>, { | ||
value: string; | ||
debounced: string; | ||
}, { | ||
value: boolean; | ||
debounced: boolean; | ||
}]) => (props: ComboboxItemProps<Value>) => { | ||
}], (node: HTMLElement) => MeltActionReturn<ComboboxEvents['item']>, ([$selected]: [ComboboxOption<Value> | undefined]) => (props: ComboboxItemProps<Value>) => { | ||
readonly 'data-value': string; | ||
@@ -90,4 +45,2 @@ readonly 'data-label': string | undefined; | ||
readonly 'data-selected': "" | undefined; | ||
readonly hidden: true | undefined; | ||
readonly 'data-hidden': "" | undefined; | ||
readonly id: string; | ||
@@ -120,16 +73,4 @@ readonly role: "option"; | ||
highlighted: Readable<ComboboxOption<Value> | undefined>; | ||
inputValue: { | ||
debouncedSet: (value: string) => void; | ||
debouncedUpdate: (fn: (value: string) => string) => void; | ||
set: (value: string) => void; | ||
update: (fn: (value: string) => string) => void; | ||
subscribe(this: void, run: import("svelte/store").Subscriber<{ | ||
value: string; | ||
debounced: string; | ||
}>, invalidate?: import("svelte/store").Invalidator<{ | ||
value: string; | ||
debounced: string; | ||
}> | undefined): import("svelte/store").Unsubscriber; | ||
}; | ||
isEmpty: Readable<boolean>; | ||
inputValue: Writable<string>; | ||
touchedInput: Writable<boolean>; | ||
}; | ||
@@ -150,3 +91,2 @@ helpers: { | ||
scrollAlignment: Writable<"center" | "nearest">; | ||
filterFunction: Writable<import("./types.js").ComboboxFilterFunction<Value>>; | ||
loop: Writable<boolean>; | ||
@@ -153,0 +93,0 @@ defaultSelected?: Writable<ComboboxOption<Value> | undefined> | undefined; |
import { useEscapeKeydown, usePopper } from '../../internal/actions/index.js'; | ||
import { FIRST_LAST_KEYS, addHighlight, addMeltEventListener, back, builder, createClickOutsideIgnore, createElHelpers, derivedVisible, disabledAttr, effect, executeCallbacks, forward, generateId, getElementByMeltId, getOptions, getPortalDestination, isBrowser, isElementDisabled, isHTMLElement, isHTMLInputElement, kbd, last, next, noop, omit, overridable, prev, removeHighlight, removeScroll, sleep, styleToString, toWritableStores, } from '../../internal/helpers/index.js'; | ||
import { debounceable } from '../../internal/helpers/store/index.js'; | ||
import { FIRST_LAST_KEYS, addHighlight, addMeltEventListener, back, builder, createClickOutsideIgnore, createElHelpers, derivedVisible, disabledAttr, effect, executeCallbacks, forward, generateId, getElementByMeltId, getOptions, getPortalDestination, isBrowser, isElementDisabled, isHTMLElement, isHTMLInputElement, isHidden, kbd, last, next, noop, omit, overridable, prev, removeHighlight, removeScroll, sleep, styleToString, toWritableStores, } from '../../internal/helpers/index.js'; | ||
import { dequal as deepEqual } from 'dequal'; | ||
import { onMount, tick } from 'svelte'; | ||
import { derived, get, readonly, writable } from 'svelte/store'; | ||
import { derived, get, writable } from 'svelte/store'; | ||
import { createLabel } from '../label/create.js'; | ||
@@ -23,4 +22,2 @@ // prettier-ignore | ||
portal: undefined, | ||
filterFunction: () => true, | ||
debounce: 0, | ||
}; | ||
@@ -46,3 +43,3 @@ const { name, selector } = createElHelpers('combobox'); | ||
// The current value of the input element. | ||
const inputValue = debounceable(withDefaults.defaultSelected?.label ?? '', withDefaults.debounce); | ||
const inputValue = writable(withDefaults.defaultSelected?.label ?? ''); | ||
// Either the provided open store or a store with the default open value | ||
@@ -52,6 +49,5 @@ const openWritable = withDefaults.open ?? writable(false); | ||
const open = overridable(openWritable, withDefaults?.onOpenChange); | ||
const isEmpty = writable(false); | ||
const options = toWritableStores(omit(withDefaults, 'open', 'defaultOpen', 'debounce')); | ||
const { scrollAlignment, loop, filterFunction, closeOnOutsideClick, closeOnEscape, preventScroll, portal, forceVisible, positioning, } = options; | ||
const touchedInput = debounceable(false, withDefaults.debounce); | ||
const options = toWritableStores(omit(withDefaults, 'open', 'defaultOpen')); | ||
const { scrollAlignment, loop, closeOnOutsideClick, closeOnEscape, preventScroll, portal, forceVisible, positioning, } = options; | ||
const touchedInput = writable(false); | ||
const ids = { | ||
@@ -94,2 +90,3 @@ input: generateId(), | ||
selected.set(props); | ||
inputValue.set(props.label ?? ''); | ||
const activeTrigger = getElementByMeltId(ids.input); | ||
@@ -100,21 +97,2 @@ if (activeTrigger) { | ||
} | ||
async function handleIsEmpty() { | ||
if (!isBrowser) | ||
return; | ||
await tick(); | ||
const menuElement = document.getElementById(ids.menu); | ||
if (!isHTMLElement(menuElement)) | ||
return; | ||
const options = getOptions(menuElement); | ||
const visibleOptions = options.filter((opt) => { | ||
const isHidden = opt.dataset.hidden !== undefined; | ||
return !isHidden; | ||
}); | ||
if (!visibleOptions.length) { | ||
isEmpty.set(true); | ||
} | ||
else { | ||
isEmpty.set(false); | ||
} | ||
} | ||
/** | ||
@@ -194,3 +172,3 @@ * Opens the menu, sets the active trigger, and highlights | ||
role: 'combobox', | ||
value: $inputValue.value, | ||
value: $inputValue, | ||
}; | ||
@@ -318,7 +296,9 @@ }, | ||
const value = e.target.value; | ||
inputValue.debouncedSet(value); | ||
touchedInput.debouncedSet(true); | ||
inputValue.set(value); | ||
touchedInput.set(true); | ||
tick().then(() => { | ||
const $highlightedItem = get(highlightedItem); | ||
if ($highlightedItem?.dataset.hidden) { | ||
if (!$highlightedItem || | ||
$highlightedItem?.dataset.hidden || | ||
isHidden($highlightedItem)) { | ||
// Find next visible item | ||
@@ -446,10 +426,5 @@ const menuElement = document.getElementById(ids.menu); | ||
const option = builder(name('option'), { | ||
stores: [selected, filterFunction, inputValue, touchedInput], | ||
returned: ([$value, $filterFunction, $inputValue, $touchedInput]) => (props) => { | ||
let hidden = false; | ||
if ($touchedInput.debounced && | ||
$filterFunction?.({ input: $inputValue.debounced, itemValue: props.value }) === false) { | ||
hidden = true; | ||
} | ||
const selected = deepEqual(props.value, $value); | ||
stores: [selected], | ||
returned: ([$selected]) => (props) => { | ||
const selected = deepEqual(props.value, $selected?.value); | ||
return { | ||
@@ -462,4 +437,2 @@ 'data-value': JSON.stringify(props.value), | ||
'data-selected': selected ? '' : undefined, | ||
hidden: hidden ? true : undefined, | ||
'data-hidden': hidden ? '' : undefined, | ||
id: generateId(), | ||
@@ -512,7 +485,4 @@ role: 'option', | ||
const dataLabel = selectedEl.getAttribute('data-label'); | ||
inputValue.debouncedSet(dataLabel ?? selectedEl.textContent ?? ''); | ||
inputValue.set(dataLabel ?? selectedEl.textContent ?? ''); | ||
}); | ||
effect(selected, function setInputValue($selected) { | ||
inputValue.debouncedSet($selected?.label ?? ''); | ||
}); | ||
/** | ||
@@ -540,5 +510,2 @@ * Handles moving the `data-highlighted` attribute between items when | ||
}); | ||
effect([inputValue, touchedInput], () => { | ||
handleIsEmpty(); | ||
}); | ||
return { | ||
@@ -556,3 +523,3 @@ elements: { | ||
inputValue, | ||
isEmpty: readonly(isEmpty), | ||
touchedInput, | ||
}, | ||
@@ -559,0 +526,0 @@ helpers: { |
@@ -24,12 +24,2 @@ import type { BuilderReturn } from '../../internal/types.js'; | ||
/** | ||
* Predicate function to filter the visible items. When the user types, | ||
* the filterFunction will be run on each item along with the current | ||
* input value. If the predicate returns true, the item will be displayed. | ||
* By default, the item's label will be compared to the current input value. | ||
* @param item the current item being filtered. | ||
* @param value the current input value. | ||
* @returns whether the item should be visible. | ||
*/ | ||
filterFunction?: ComboboxFilterFunction<Value>; | ||
/** | ||
* Whether or not the combobox should loop through the list when | ||
@@ -114,12 +104,3 @@ * the end or beginning is reached. | ||
forceVisible?: boolean; | ||
/** | ||
* The delay in milliseconds for the filterFunction to be called after the input value changes. | ||
*/ | ||
debounce?: number; | ||
}; | ||
type ComboboxFilterFunctionArgs<T> = { | ||
itemValue: T; | ||
input: string; | ||
}; | ||
export type ComboboxFilterFunction<T> = (args: ComboboxFilterFunctionArgs<T>) => boolean; | ||
export type ComboboxItemProps<Value> = ComboboxOption<Value> & { | ||
@@ -126,0 +107,0 @@ /** |
{ | ||
"name": "@melt-ui/svelte", | ||
"version": "0.48.0", | ||
"version": "0.49.0", | ||
"license": "MIT", | ||
@@ -5,0 +5,0 @@ "repository": "github:melt-ui/melt-ui", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
610279
14154