UNPKG

radh-ui

Version:

Stencil Component Starter

227 lines (226 loc) 7.43 kB
import { Component, Element, Event, Method, Prop, State, Watch, h } from '@stencil/core'; export class RadhAutocomplete { constructor() { this.results = []; this.search = ''; this.isLoading = false; this.arrowCounter = 0; this.activedescendant = ''; } itemsChanged(val) { if (val) { this.innerItems = JSON.parse(val); this.isLoading = false; } } onChange(ev) { this.search = ev.target ? ev.target.value : null; if (this.isAsync) { this.isLoading = true; } else { this.filterResults(); this.isOpen = true; } } componentWillLoad() { this.innerItems = JSON.parse(this.items); this.closeOptions(); } componentDidLoad() { document.addEventListener("click", this.handleClickOutside); } componentDidUnload() { document.removeEventListener("click", this.handleClickOutside); } filterResults() { this.results = this.innerItems.filter(item => { return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1; }); } setResult(result) { this.search = result; this.isOpen = false; this.valueSelected.emit(this.search); } async closeOptions() { this.isOpen = false; this.arrowCounter = -1; } onArrow(ev) { if (this.isOpen) { if (ev.which === 38) { //UP if (this.arrowCounter > 0) { this.arrowCounter = this.arrowCounter - 1; this.setActiveDescendent(); } } else if (ev.which === 40) { //DOWN if (this.arrowCounter < this.results.length) { this.arrowCounter = this.arrowCounter + 1; this.setActiveDescendent(); } } } } onKeyPress(ev) { if (ev.which === 13) { //ENTER this.search = this.results[this.arrowCounter]; this.setResult(this.search); this.isOpen = false; this.arrowCounter = -1; } } handleClickOutside() { var radhAutocomplete = document.querySelector('radh-autocomplete'); radhAutocomplete.componentOnReady().then(() => { radhAutocomplete.closeOptions(); }); } isSelected(index) { return index === this.arrowCounter; } setActiveDescendent() { this.activedescendant = this.getId(this.arrowCounter); } getId(index) { return `result-option-${index}`; } render() { if (this.items) { return (h("div", { class: "autocomplete", role: "combobox", "aria-expanded": this.isOpen ? 'true' : 'false' }, h("label", { htmlFor: this.labelBy, "aria-label": this.labelBy }, this.label), h("input", { type: "text", id: this.labelBy, onInput: (ev) => this.onChange(ev), onKeyPress: (ev) => this.onKeyPress(ev), onKeyDown: (ev) => this.onArrow(ev), "aria-multiline": "false", role: "searchbox", "aria-autocomplete": "list", "aria-controls": "autocomplete-results", "aria-activedescendant": this.activedescendant, "aria-labelledby": this.labelBy, value: this.search, title: 'Elige la fruta', autocomplete: "off" }), this.isOpen ? h("ul", { id: "autocomplete-results", class: "autocomplete-results", role: "listbox" }, this.isLoading ? h("li", { class: "loading" }, "Loading results") : h("span", null, this.results.map((result, index) => h("li", { key: index, onClick: () => this.setResult(result), role: "option", id: this.getId(index), "aria-selected": this.isSelected(index), class: 'autocomplete-result' + (this.isSelected(index) ? ' is-active' : '') }, result)))) : h("span", null))); } } static get is() { return "radh-autocomplete"; } static get originalStyleUrls() { return { "$": ["radh-autocomplete.css"] }; } static get styleUrls() { return { "$": ["radh-autocomplete.css"] }; } static get properties() { return { "items": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "items", "reflect": false }, "isAsync": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "is-async", "reflect": false }, "labelBy": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "label-by", "reflect": false }, "label": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "label", "reflect": false } }; } static get states() { return { "innerItems": {}, "isOpen": {}, "results": {}, "search": {}, "isLoading": {}, "arrowCounter": {}, "activedescendant": {} }; } static get events() { return [{ "method": "valueSelected", "name": "valueSelected", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "" }, "complexType": { "original": "any", "resolved": "any", "references": {} } }]; } static get methods() { return { "closeOptions": { "complexType": { "signature": "() => Promise<void>", "parameters": [], "references": { "Promise": { "location": "global" } }, "return": "Promise<void>" }, "docs": { "text": "", "tags": [] } } }; } static get elementRef() { return "el"; } static get watchers() { return [{ "propName": "items", "methodName": "itemsChanged" }]; } }