UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

356 lines (355 loc) • 10.4 kB
/*! * All material copyright ESRI, All Rights Reserved, unless otherwise specified. * See https://github.com/Esri/calcite-components/blob/master/LICENSE.md for details. * v1.5.0-next.4 */ import { Fragment, h } from "@stencil/core"; import { debounce } from "lodash-es"; import { filter } from "../../utils/filter"; import { connectInteractive, disconnectInteractive, updateHostInteraction } from "../../utils/interactive"; import { componentLoaded, setComponentLoaded, setUpLoadableComponent } from "../../utils/loadable"; import { connectLocalized, disconnectLocalized } from "../../utils/locale"; import { connectMessages, disconnectMessages, setUpMessages, updateMessages } from "../../utils/t9n"; import { CSS, DEBOUNCE_TIMEOUT, ICONS } from "./resources"; export class Filter { constructor() { // -------------------------------------------------------------------------- // // Private Methods // // -------------------------------------------------------------------------- this.filter = debounce((value, emit = false) => this.updateFiltered(filter(this.items, value), emit), DEBOUNCE_TIMEOUT); this.inputHandler = (event) => { const target = event.target; this.value = target.value; this.filter(target.value, true); }; this.keyDownHandler = (event) => { if (event.key === "Escape") { this.clear(); event.preventDefault(); } if (event.key === "Enter") { event.preventDefault(); } }; this.clear = () => { this.value = ""; this.filter("", true); this.setFocus(); }; this.items = []; this.disabled = false; this.filteredItems = []; this.placeholder = undefined; this.scale = "m"; this.value = ""; this.messages = undefined; this.messageOverrides = undefined; this.effectiveLocale = undefined; this.defaultMessages = undefined; } watchItemsHandler() { this.filter(this.value); } onMessagesChange() { /* wired up by t9n util */ } valueHandler(value) { this.filter(value); } effectiveLocaleChange() { updateMessages(this, this.effectiveLocale); } //-------------------------------------------------------------------------- // // Lifecycle // //-------------------------------------------------------------------------- async componentWillLoad() { setUpLoadableComponent(this); this.updateFiltered(filter(this.items, this.value)); await setUpMessages(this); } connectedCallback() { connectInteractive(this); connectLocalized(this); connectMessages(this); } componentDidRender() { updateHostInteraction(this); } disconnectedCallback() { disconnectInteractive(this); disconnectLocalized(this); disconnectMessages(this); } componentDidLoad() { setComponentLoaded(this); } // -------------------------------------------------------------------------- // // Public Methods // // -------------------------------------------------------------------------- /** Sets focus on the component. */ async setFocus() { await componentLoaded(this); this.el?.focus(); } updateFiltered(filtered, emit = false) { this.filteredItems.length = 0; this.filteredItems = this.filteredItems.concat(filtered); if (emit) { this.calciteFilterChange.emit(); } } // -------------------------------------------------------------------------- // // Render Methods // // -------------------------------------------------------------------------- render() { const { disabled, scale } = this; return (h(Fragment, null, h("div", { class: CSS.container }, h("label", null, h("calcite-input", { "aria-label": this.messages.label, clearable: true, disabled: disabled, icon: ICONS.search, messageOverrides: { clear: this.messages.clear }, onCalciteInputInput: this.inputHandler, onKeyDown: this.keyDownHandler, placeholder: this.placeholder, scale: scale, type: "text", value: this.value, // eslint-disable-next-line react/jsx-sort-props ref: (el) => { this.textInput = el; } }))))); } static get is() { return "calcite-filter"; } static get encapsulation() { return "shadow"; } static get delegatesFocus() { return true; } static get originalStyleUrls() { return { "$": ["filter.scss"] }; } static get styleUrls() { return { "$": ["filter.css"] }; } static get assetsDirs() { return ["assets"]; } static get properties() { return { "items": { "type": "unknown", "mutable": false, "complexType": { "original": "object[]", "resolved": "object[]", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Defines the items to filter. The component uses the values as the starting point, and returns items\n\nthat contain the string entered in the input, using a partial match and recursive search.\n\nThis property is needed to conduct filtering." }, "defaultValue": "[]" }, "disabled": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "When `true`, interaction is prevented and the component is displayed with lower opacity." }, "attribute": "disabled", "reflect": true, "defaultValue": "false" }, "filteredItems": { "type": "unknown", "mutable": true, "complexType": { "original": "object[]", "resolved": "object[]", "references": {} }, "required": false, "optional": false, "docs": { "tags": [{ "name": "readonly", "text": undefined }], "text": "The component's resulting items after filtering." }, "defaultValue": "[]" }, "placeholder": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specifies placeholder text for the input element." }, "attribute": "placeholder", "reflect": false }, "scale": { "type": "string", "mutable": false, "complexType": { "original": "Scale", "resolved": "\"l\" | \"m\" | \"s\"", "references": { "Scale": { "location": "import", "path": "../interfaces" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specifies the size of the component." }, "attribute": "scale", "reflect": true, "defaultValue": "\"m\"" }, "value": { "type": "string", "mutable": true, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "The component's value." }, "attribute": "value", "reflect": false, "defaultValue": "\"\"" }, "messages": { "type": "unknown", "mutable": true, "complexType": { "original": "FilterMessages", "resolved": "{ label: string; clear: string; }", "references": { "FilterMessages": { "location": "import", "path": "./assets/filter/t9n" } } }, "required": false, "optional": false, "docs": { "tags": [{ "name": "internal", "text": undefined }], "text": "Made into a prop for testing purposes only" } }, "messageOverrides": { "type": "unknown", "mutable": true, "complexType": { "original": "Partial<FilterMessages>", "resolved": "{ label?: string; clear?: string; }", "references": { "Partial": { "location": "global" }, "FilterMessages": { "location": "import", "path": "./assets/filter/t9n" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "Use this property to override individual strings used by the component." } } }; } static get states() { return { "effectiveLocale": {}, "defaultMessages": {} }; } static get events() { return [{ "method": "calciteFilterChange", "name": "calciteFilterChange", "bubbles": true, "cancelable": false, "composed": true, "docs": { "tags": [], "text": "This event fires when the filter text changes." }, "complexType": { "original": "void", "resolved": "void", "references": {} } }]; } static get methods() { return { "setFocus": { "complexType": { "signature": "() => Promise<void>", "parameters": [], "references": { "Promise": { "location": "global" } }, "return": "Promise<void>" }, "docs": { "text": "Sets focus on the component.", "tags": [] } } }; } static get elementRef() { return "el"; } static get watchers() { return [{ "propName": "items", "methodName": "watchItemsHandler" }, { "propName": "messageOverrides", "methodName": "onMessagesChange" }, { "propName": "value", "methodName": "valueHandler" }, { "propName": "effectiveLocale", "methodName": "effectiveLocaleChange" }]; } }