0.1.2 • Published 4 years ago

@brunnerh/autocomplete v0.1.2

Weekly downloads
5
License
MIT
Repository
-
Last release
4 years ago

Autocomplete Component

An autocomplete component which can be used as a regular ES module import or as a Svelte component.

It has no dependencies, handles synchronous and asynchronous data sources, supports item templating and escapes any HTML automatically.

(Change log)

Install

npm install @brunnerh/autocomplete

Usage

In a Svelte project the component can be imported in a <script> section and then used in the HTML like any other:

<script>
	// (Named import!)
	import { AutoComplete } from '@brunnerh/autocomplete';

	const items = ['Apple', 'Orange', 'Pear'];
</script>

<AutoComplete items={() => items}/>

In any other type of project, the component can be instantiated in the script:

<div id="autocomplete-target"></div>

<script type="module">
	import { AutoComplete } from '@brunnerh/autocomplete';

	const items = ['Apple', 'Orange', 'Pear'];
	new AutoComplete({
		target: document.querySelector('#autocomplete-target'),
		props: { items: () => items },
	});
</script>

For documentation of how to interact with component instances see Client-side component API in the Svelte docs.

Properties

PropTypeDefaultDescription
idstring \| nullnullSets the id of the input element.
namestring \| nullnullSets the name of the input element.
classNamestring''Sets additional class name/names of the input element (should be space separated).
placeholderstring \| nullnullSets the placeholder of the input element.
titlestring \| nullnullSets the title of the input element.
requiredbooleanfalseSets the required attribute on the input element if true.
disabledbooleanfalseSets the disabled attribute on the input element if true.
tabindexnumber \| undefinedundefinedSets the tabindex attribute on the input element.
autoScrollbooleantrueAutomatically scrolls the component into view.Can be helpful if the component is at the bottom a scrollable area and the dropdown ends up off-screen.
autoScrollCursorbooleantrueAutomatically scrolls to the cursor position in the list.Turn off if there are performance issues.
items() => Item[]Sets the suggestions. See Items Property.
isOpenbooleanfalseGets or sets whether the suggestions dropdown is open.
keyanynullGets the last selected key. See Items Property.
valueanynullGets the last selected value. See Items Property.
resultsany[][]Gets the subset of items that match the user input, reduced to the first maxItems items.
searchstring''Gets or sets the current search term/input value.
isLoadingbooleanfalseGets whether the component is currently loading the suggestions (if items returns a promise).
cursornumber0Gets or sets the index of the currently highlighted item within the suggestions list.
cursorItemanyundefinedGets the currently highlighted item.
maxItemsnumber?undefinedSets the maximal number of items to show in suggestions list at a time.
fromStartbooleanfalseSets whether the search string has to appear at the start of the item.
caseSensitivebooleanfalseSets whether the search is case-sensitive.
minCharnumber0Sets the minimum number of characters required to trigger a search.
debouncenumber0Sets the time to wait in milliseconds before triggering a search.
blindSelectionbooleanfalseSets whether suggested items are directly selected upon pressing arrow up/down while the dropdown is closed.
lazyDropdownbooleanfalseWhether the DOM elements for the suggestions list are only created upon filtering/opening the suggestions dropdown.
searchRegEx(search: string) => RegExp \| nullnullCustom search RegEx generator.If set, fromStart and caseSensitive will not be used.
searchFunctionSearch FunctionnullCustom search function. See Search Function Property.

Items Property

The items property has to be a function returning a list of items for the auto-completion.

The return value can be a promise to load data asynchronously. Returning an existing promise if the list of suggestions can be cached is recommended. E.g.:

<script>
	// Fetch once:
	const suggestions = fetch('/api/items');
</script>
<AutoComplete items={() => suggestions}/>

The items have to be strings or of the form:

{
	key: string,
	value?: any,
}

The key will be used for the search and displayed in the suggestions dropdown by default.

The value represents a technical item value that is assigned to the value property of the component upon selection. If no value is set, the whole item will be assigned.

For strings, the string will serve as key and value.

Search Function Property

The property searchFunction can be used to provide custom search logic when a custom regular expression (searchRegEx) is not enough.

The type of the function is as follows:

(search: string) => (text: string) => {
	/** Whether the item `text` matches `search`. */
	matches: boolean,
	/**
	 * An array of start and end index tuples for parts of the text that should be highlighted as matching.
	 * Should be an empty array if nothing matches or no highlighting should be shown.
	 */
	highlights: [number, number][],
}

If set, fromStart, caseSensitive and searchRegEx will not be used.

Events

The following events are emitted by the component, event data/forwarded event can be found in the detail property:

TypeDescription
filteredFired after the suggestion list has been filtered.
item-selectedFired upon item selection, either by pressing Enter or clicking on one.The event data is the selected item.
focusForwarded from input.
blurForwarded from input.
inputForwarded from input.
keydownForwarded from input.
clickForwarded from input.

Slots

The following slots can be used in Svelte projects:

NameInjected PropsDescription
loadingThe loading indicator that is displayed while items are loading asynchronously.Default: Loading data...
templateresultA custom template for rendering the items. See Template

template

By default, items show the item key with matching parts of the text highlighted. This slot can be used to customize this output.

The injected result prop has the following type:

{
	/** The index of the item in the filtered results list (0-based). */
	index: number,

	/** The key of the item. Either the `key` property or the item itself, if it a string. */
	key: string,

	/** The value of the item. Either the `value` property or the whole item. */
	value: any,

	/** An HTML string that contains highlighted parts in spans with the class `ac-match`. */
	label: string,
}

Example:

<AutoComplete items={() => data} let:result>
	<!-- Renders item with index prefix and value in parentheses on a second line. -->
	<div slot="template">
		{result.index + 1}: {@html result.label}
		<br/>
		<span style="font-size: smaller; opacity: 0.7">({result.value})</span>
	</div>
</AutoComplete>

Styling

The component comes with a default style and defines various CSS custom properties to make theming easier.

It can also be styled via the classes of the various parts.

Structure

.autocomplete
	input.autocomplete-input
	.autocomplete-results-dropdown
		.autocomplete-loading
		ul.autocomplete-results-list
			li.autocomplete-result[.ac-highlighted]
				span[.ac-match]
  • ac-highlighted is applied to the item highlighted via arrow/up or mouse hover.
  • ac-match is applied to the parts of the item text that match the search.
    • E.g.: Search: ap, item text: Apple => <span class="ac-match">Ap</span>ple

CSS Custom Properties

TargetNameDefault Value
.autocomplete-input--ac-input-colorblack
.autocomplete-input--ac-input-backgroundwhite
.autocomplete-input--ac-input-border1px solid hsl(0, 0%, 60%)
.autocomplete-input--ac-input-border-radius0
.autocomplete-input--ac-input-padding3px
.autocomplete-input--ac-input-margin0
.autocomplete-input--ac-input-font-sizesmall
.autocomplete-input--ac-input-font-weightnormal
.autocomplete-results-dropdown--ac-dropdown-colorFallback: --ac-input-color
.autocomplete-results-dropdown--ac-dropdown-backgroundFallback: --ac-input-background
.autocomplete-results-dropdown--ac-dropdown-box-shadow0px 2px 5px hsla(0, 0%, 0%, 0.7)
.autocomplete-results-dropdown--ac-dropdown-margin:0
.autocomplete-results-dropdown--ac-dropdown-padding:0
.autocomplete-results-dropdown--ac-dropdown-border-radius0
.autocomplete-loading--ac-loading-colorinherit
.autocomplete-loading--ac-loading-backgroundnone
.autocomplete-loading--ac-loading-padding0
.autocomplete-loading--ac-loading-margin5px
.autocomplete-result--ac-result-colorinherit
.autocomplete-result--ac-result-backgroundnone
.autocomplete-result--ac-result-bordernone
.autocomplete-result--ac-result-margin0
.autocomplete-result--ac-result-padding0.2em 0.5em
.autocomplete-result--ac-result-border-radius0
.autocomplete-result.ac-highlighted--ac-result-highlighted-colorinherit + Fallback: --ac-result-color
.autocomplete-result.ac-highlighted--ac-result-highlighted-background#dbdbdb + Fallback: --ac-result-background
.autocomplete-result.ac-highlighted--ac-result-highlighted-borderFallback: --ac-result-border
.autocomplete-result.ac-highlighted--ac-result-highlighted-marginFallback: --ac-result-margin
.autocomplete-result.ac-highlighted--ac-result-highlighted-paddingFallback: --ac-result-padding
.autocomplete-result.ac-highlighted--ac-result-highlighted-border-radiusFallback: --ac-result-border-radius
.autocomplete-result .ac-match--ac-result-match-colorinherit
.autocomplete-result .ac-match--ac-result-match-backgroundnone
.autocomplete-result .ac-match--ac-result-match-border-radius0
.autocomplete-result .ac-match--ac-result-match-font-weightbold
.autocomplete-result .ac-match--ac-result-match-font-styleinherit

Attribution