radh-ui
Version:
Stencil Component Starter
227 lines (226 loc) • 7.43 kB
JavaScript
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"
}]; }
}