UNPKG

@scania/tegel

Version:
1,206 lines (1,205 loc) 56.1 kB
import { Host, h, } from "@stencil/core"; import findNextFocusableElement from "../../utils/findNextFocusableElement"; import findPreviousFocusableElement from "../../utils/findPreviousFocusableElement"; import appendHiddenInput from "../../utils/appendHiddenInput"; import { convertToString, convertArrayToStrings } from "../../utils/convertToString"; import generateUniqueId from "../../utils/generateUniqueId"; function hasValueChanged(newValue, currentValue) { if (newValue.length !== currentValue.length) return true; return newValue.some((val) => !currentValue.includes(val)); } function getTypedQuery(rawValue, displayValue) { if (rawValue.length <= displayValue.length + 1) { return rawValue; } if (rawValue.startsWith(displayValue)) { return rawValue.slice(displayValue.length); } if (rawValue.endsWith(displayValue)) { return rawValue.slice(0, rawValue.length - displayValue.length); } return rawValue; } /** * @slot <default> - <b>Unnamed slot.</b> For dropdown option elements. */ export class TdsDropdown { constructor() { /** Sets the Dropdown in a disabled state */ this.disabled = false; /** Mode variant of the component, based on current mode. */ this.modeVariant = null; /** The direction the Dropdown should open, auto if not specified. */ this.openDirection = 'auto'; /** The size of the Dropdown. */ this.size = 'lg'; this.animation = 'slide'; /** Sets the Dropdown in an error state */ this.error = false; /** Enables multiselect in the Dropdown. */ this.multiselect = false; /** Enables filtration in the Dropdown. */ this.filter = false; /** Normalizes input text for fuzzier search */ this.normalizeText = true; /** Text that is displayed if filter is used and there are no options that matches the search. * Setting it to an empty string disables message from showing up. */ this.noResultText = 'No result'; /** Value of the dropdown. For multiselect, provide array of strings/numbers. For single select, provide a string/number. */ this.value = null; this.open = false; this.internalValue = ''; this.filterResult = null; this.filterFocus = false; this.internalDefaultValue = ''; this.selectedOptions = []; this.filterQuery = ''; this.hasFocus = false; this.uuid = generateUniqueId(); this.setDefaultOption = () => { if (this.internalDefaultValue) { /** Convert the internal default value to an array if it's not already */ const defaultValues = this.multiselect ? this.internalDefaultValue.split(',') : [this.internalDefaultValue]; this.updateDropdownStateInternal(defaultValues); } }; this.getChildren = () => { const tdsDropdownOptions = Array.from(this.host.children).filter((element) => element.tagName === 'TDS-DROPDOWN-OPTION'); if (tdsDropdownOptions.length === 0) { console.warn('TDS DROPDOWN: No options found. Disregard if loading data asynchronously.'); } return tdsDropdownOptions; }; this.getSelectedChildren = () => { if (this.selectedOptions.length === 0) return []; return this.selectedOptions .map((stringValue) => { var _a; const matchingElement = (_a = this.getChildren()) === null || _a === void 0 ? void 0 : _a.find((element) => convertToString(element.value) === convertToString(stringValue)); return matchingElement; }) .filter(Boolean); }; this.getSelectedChildrenLabels = () => { var _a; return (_a = this.getSelectedChildren()) === null || _a === void 0 ? void 0 : _a.map((element) => { var _a; return (_a = element.textContent) === null || _a === void 0 ? void 0 : _a.trim(); }); }; this.getValue = () => { const labels = this.getSelectedChildrenLabels(); if (!labels) { return ''; } return labels === null || labels === void 0 ? void 0 : labels.join(', '); }; this.setValueAttribute = () => { if (this.selectedOptions.length === 0) { this.host.removeAttribute('value'); } else { this.host.setAttribute('value', this.selectedOptions.join(',')); } }; this.getOpenDirection = () => { var _a, _b, _c, _d, _e; if (this.openDirection === 'auto' || !this.openDirection) { const dropdownMenuHeight = (_b = (_a = this.dropdownList) === null || _a === void 0 ? void 0 : _a.offsetHeight) !== null && _b !== void 0 ? _b : 0; const distanceToBottom = (_e = (_d = (_c = this.host).getBoundingClientRect) === null || _d === void 0 ? void 0 : _d.call(_c).top) !== null && _e !== void 0 ? _e : 0; const viewportHeight = window.innerHeight; if (distanceToBottom + dropdownMenuHeight + 57 > viewportHeight) { return 'up'; } return 'down'; } return this.openDirection; }; this.handleToggleOpen = () => { var _a; if (!this.disabled) { this.open = !this.open; if (this.open) { if (this.filter) { this.focusInputElement(); } else { const button = (_a = this.host.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('button'); if (button) { button.focus(); } } } } }; this.focusInputElement = () => { if (this.inputElement) this.inputElement.focus(); }; this.handleFilter = (event) => { const input = event.currentTarget; if (this.multiselect && this.filterQuery.length === 0 && this.selectedOptions.length > 0 && this.inputElement) { const displayValue = this.getValue(); const rawValue = input.value; const typed = getTypedQuery(rawValue, displayValue); if (typed !== rawValue) { this.inputElement.value = typed; } } this.tdsInput.emit(event); const query = this.inputElement ? this.inputElement.value.toLowerCase() : input.value.toLowerCase(); this.filterQuery = query; /** Check if the query is empty, and if so, show all options */ const children = this.getChildren(); if (query === '') { children.forEach((element) => { element.removeAttribute('hidden'); return element; }); this.filterResult = null; /** Hide the options that do not match the query */ } else { this.filterResult = children.filter((element) => { var _a; if (!this.normalizeString((_a = element === null || element === void 0 ? void 0 : element.textContent) !== null && _a !== void 0 ? _a : '') .toLowerCase() .includes(this.normalizeString(query).toLowerCase())) { element.setAttribute('hidden', ''); } else { element.removeAttribute('hidden'); } return !element.hasAttribute('hidden'); }).length; } }; this.handleFilterReset = () => { if (this.multiselect) { /** Multiselect + filter: two-step clear */ if (this.filterQuery.length > 0) { const clearedValue = this.filterQuery; this.filterQuery = ''; this.resetFilterVisibility(); if (this.inputElement) { this.inputElement.value = this.getValue(); this.inputElement.focus(); } this.tdsClear.emit({ clearedValue }); } else if (this.selectedOptions.length > 0) { const clearedValue = this.selectedOptions.join(','); this.updateDropdownStateFromUser([]); if (this.inputElement) { this.inputElement.value = ''; this.inputElement.focus(); } this.tdsClear.emit({ clearedValue }); } } else { /** Single select + filter: clear everything immediately */ const clearedParts = []; if (this.filterQuery.length > 0) { clearedParts.push(this.filterQuery); this.filterQuery = ''; this.resetFilterVisibility(); } if (this.selectedOptions.length > 0) { clearedParts.push(this.selectedOptions.join(',')); this.updateDropdownStateFromUser([]); } if (this.inputElement) { this.inputElement.value = ''; this.inputElement.focus(); } if (clearedParts.length > 0) { this.tdsClear.emit({ clearedValue: clearedParts.join(',') }); } } }; this.resetFilterVisibility = () => { this.filterQuery = ''; const children = this.getChildren(); children.forEach((element) => { element.removeAttribute('hidden'); }); this.filterResult = null; }; this.handleMultiselectClear = () => { const clearedValue = this.selectedOptions.join(','); this.updateDropdownStateFromUser([]); this.tdsClear.emit({ clearedValue }); }; this.handleFocus = () => { this.open = true; this.filterFocus = true; if (this.multiselect && this.filter) { /** For multiselect+filter, show selected labels on focus. * Clearing happens on click via handleInputClick. */ if (this.inputElement) { this.inputElement.value = this.getValue(); } } else if (this.inputElement) { this.inputElement.value = ''; } if (this.filter) { this.resetFilterVisibility(); } }; this.handleBlur = () => { this.filterFocus = false; this.filterQuery = ''; if (this.inputElement) { this.inputElement.value = this.getValue(); } /** Reset filter to show all options for next open */ if (this.filter) { this.resetFilterVisibility(); } }; this.handleInputClick = () => { if (this.multiselect && this.filter) { this.filterQuery = ''; if (this.inputElement) { this.inputElement.value = ''; } this.resetFilterVisibility(); } }; this.resetInput = () => { const inputEl = this.host.querySelector('input'); if (inputEl) { this.reset(); } }; } handleValueChange(newValue) { /** Normalize to array */ const normalizedValue = this.normalizeValue(newValue); /** Only update if actually changed */ if (hasValueChanged(normalizedValue, this.selectedOptions)) { this.updateDropdownStateFromUser(normalizedValue); } } normalizeValue(value) { if (value === null || value === undefined || value === '') return []; /** For single select, ensure we handle both string and array inputs */ if (!this.multiselect) { /** If array is passed to single select, take first value */ if (Array.isArray(value)) { return [convertToString(value[0])]; } return [convertToString(value)]; } /** For multiselect */ if (Array.isArray(value)) { return convertArrayToStrings(value); } /** Handle comma-separated string for multiselect */ return value .toString() .split(',') .filter((v) => v !== ''); } updateDropdownStateInternal(values) { this.updateDropdownState(values, false); } updateDropdownStateFromUser(values) { this.updateDropdownState(values, true); } updateDropdownState(values, emitChange = true) { /** Validate the values first */ const validValues = this.validateValues(values); /** Update internal state */ this.selectedOptions = [...validValues]; /** Update the value prop */ this.value = this.multiselect ? this.selectedOptions : this.selectedOptions[0] || null; /** Update internal value for display */ this.internalValue = this.getValue(); /** Update DOM */ this.updateOptionElements(); /** Update display value */ this.updateDisplayValue(); /** Emit change event only if value has changed by user */ if (emitChange) this.emitChange(); /** Update value attribute */ this.setValueAttribute(); } validateValues(values) { /** Make sure we have children before validation */ const children = this.getChildren(); if (!children || children.length === 0) { console.warn('No dropdown options found'); return values; /** Return original values if no children yet */ } return values.filter((val) => { const isValid = children.some((element) => convertToString(element.value) === convertToString(val)); if (!isValid) { console.warn(`Option with value "${val}" does not exist`); } return isValid; }); } updateOptionElements() { var _a; (_a = this.getChildren()) === null || _a === void 0 ? void 0 : _a.forEach((element) => { /** Convert element.value to string for comparison */ element.setSelected(this.selectedOptions.includes(convertToString(element.value))); }); } updateDisplayValue() { this.internalValue = this.getSelectedChildrenLabels().join(', '); if (this.filter && this.inputElement) { this.inputElement.value = this.internalValue; } } emitChange() { const value = this.multiselect ? this.selectedOptions.join(',') : this.selectedOptions[0] || null; this.tdsChange.emit({ name: this.name, value: value !== null && value !== void 0 ? value : null, }); } /** Method for setting the selected value of the Dropdown. * * Single selection example: * * <code> * dropdown.setValue('option-1', 'Option 1'); * </code> * * Multiselect example: * * <code> * dropdown.setValue(['option-1', 'option-2']); * </code> */ // @ts-expect-error for label: the label is optional here ONLY to not break the API. Should be removed for 2.0. // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars async setValue(value, label) { let normalizedValue; if (Array.isArray(value)) { normalizedValue = convertArrayToStrings(value); } else { normalizedValue = [convertToString(value)]; } this.updateDropdownStateFromUser(normalizedValue); return this.getSelectedChildren().map((element) => { var _a; return ({ value: element.value, label: (_a = element.textContent) === null || _a === void 0 ? void 0 : _a.trim(), }); }); } async reset() { this.updateDropdownStateFromUser([]); } async removeValue(oldValue) { const newValues = this.selectedOptions.filter((v) => v !== oldValue); this.updateDropdownStateFromUser(newValues); } /** Method that forces focus on the input element. */ async focusElement() { var _a; if (this.filter) { /** For filter mode, focus the input element */ this.focusInputElement(); } else { /** For non-filter mode, focus the button element */ const button = (_a = this.host.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('button'); if (button) { button.focus(); } } /** Always trigger the focus event to open the dropdown */ this.handleFocus(); } /** Method for closing the Dropdown. */ async close() { this.open = false; } /** Method to force update the dropdown display value. * Use this method when you programmatically change the text content of dropdown options * to ensure the selected value display updates immediately. */ async updateDisplay() { this.updateDisplayValue(); } onAnyClick(event) { if (this.open) { /** Source: https://lamplightdev.com/blog/2021/04/10/how-to-detect-clicks-outside-of-a-web-component/ */ const isClickOutside = !event.composedPath().includes(this.host); if (isClickOutside) { /** Emit clear event if there's a filter query when clicking outside */ if (this.filter && this.filterQuery) { this.tdsClear.emit({ clearedValue: this.filterQuery }); } this.open = false; } } } onFocusIn(event) { /** Check if the focus is within this dropdown component */ if (this.host.contains(event.target)) { if (!this.hasFocus) { this.hasFocus = true; this.tdsFocus.emit(event); } } } onFocusOut(event) { /** Only emit blur if focus is actually leaving the entire dropdown component */ const relatedTarget = event.relatedTarget; /** If relatedTarget is null (focus going to body/window) or outside the component, emit blur */ if (this.hasFocus && (!relatedTarget || !this.host.contains(relatedTarget))) { this.hasFocus = false; this.handleBlur(); this.tdsBlur.emit(event); } } async onKeyDown(event) { var _a, _b; /** Get the active element */ const { activeElement } = document; if (!activeElement) { return; } const children = this.getChildren(); if (event.key === 'ArrowDown') { /** Get the index of the current focus index, if there is no nextElementSibling return the index for the first child in our Dropdown. */ const startingIndex = activeElement.nextElementSibling ? children.findIndex((element) => element === activeElement.nextElementSibling) : 0; if (children.length > 0) { const elementIndex = findNextFocusableElement(children, startingIndex); const target = typeof elementIndex === 'number' ? children[elementIndex] : children[0]; target === null || target === void 0 ? void 0 : target.focus(); } } else if (event.key === 'ArrowUp') { /** Get the index of the current focus index, if there is no previousElementSibling return the index for the first last in our Dropdown. */ const startingIndex = activeElement.nextElementSibling ? this.getChildren().findIndex((element) => element === activeElement.previousElementSibling) : 0; if (children.length > 0) { const elementIndex = findPreviousFocusableElement(children, startingIndex); const target = typeof elementIndex === 'number' ? children[elementIndex] : children[children.length - 1]; target === null || target === void 0 ? void 0 : target.focus(); } } else if (event.key === 'Escape') { this.open = false; /** Return focus to input/button when Escape key is used */ if (this.filter) { (_a = this.inputElement) === null || _a === void 0 ? void 0 : _a.focus(); } else { const button = (_b = this.host.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('button'); button === null || button === void 0 ? void 0 : button.focus(); } } } /** If the Dropdown gets closed, this sets the value of the dropdown to the current selection labels or null if no selection is made. */ handleOpenState() { if (this.filter) { if (!this.open) { this.filterQuery = ''; this.resetFilterVisibility(); if (this.inputElement) { this.inputElement.value = this.selectedOptions.length ? this.getValue() : ''; } } } this.updateDropdownListInertState(); } handleDefaultValueChange(newValue) { if (newValue !== undefined && newValue !== null) { this.internalDefaultValue = convertToString(newValue); this.setDefaultOption(); } } componentWillLoad() { /** First handle the value prop if it exists */ if (this.value !== null && this.value !== undefined) { const normalizedValue = this.normalizeValue(this.value); this.updateDropdownStateInternal(normalizedValue); return; /** Exit early if we handled the value prop */ } /** Only use defaultValue if no value prop was provided */ if (this.defaultValue !== null && this.defaultValue !== undefined) { const defaultValueStr = convertToString(this.defaultValue); const initialValue = this.multiselect ? defaultValueStr.split(',').map(convertToString) : [defaultValueStr]; this.updateDropdownStateInternal(initialValue); } } /** Method to handle slot changes */ handleSlotChange() { this.setDefaultOption(); } /** Method to check if we should normalize text */ normalizeString(text) { return this.normalizeText ? text.normalize('NFD').replace(/\p{Diacritic}/gu, '') : text; } /** * @internal */ async appendValue(value) { /** Clear filter query when an option is selected */ if (this.filter && this.filterQuery.length > 0) { this.filterQuery = ''; /** Reset filter to show all options */ this.resetFilterVisibility(); } if (this.multiselect) { this.updateDropdownStateFromUser([...this.selectedOptions, value]); } else { this.updateDropdownStateFromUser([value]); } /** After selection, show all selected labels in the input */ if (this.filter && this.multiselect && this.inputElement) { this.inputElement.value = this.getValue(); } } componentDidRender() { const form = this.host.closest('form'); if (form) { form.addEventListener('reset', this.resetInput); } /** Initialize inert state after rendering */ this.updateDropdownListInertState(); } disconnectedCallback() { const form = this.host.closest('form'); if (form) { form.removeEventListener('reset', this.resetInput); } } updateDropdownListInertState() { if (this.dropdownList) { if (this.open) { this.dropdownList.removeAttribute('inert'); } else { this.dropdownList.setAttribute('inert', ''); } } } render() { var _a, _b, _c, _d; appendHiddenInput(this.host, this.name, this.selectedOptions.join(','), this.disabled); /** Generate unique IDs for associating labels and helpers with the input/button */ const baseId = this.name || this.uuid; const inputId = `dropdown-input-${baseId}`; const labelId = this.label ? `dropdown-label-${baseId}` : undefined; const helperId = this.helper ? `dropdown-helper-${baseId}` : undefined; const hasSelection = this.selectedOptions.length > 0; const hasTyped = this.filterQuery.length > 0; const isFloated = this.filterFocus || hasSelection || hasTyped; const isFloatedButton = this.open || hasSelection; const showPlaceholderInside = this.filterFocus && !hasTyped && !hasSelection; const showPlaceholderButton = this.labelPosition !== 'inside' || isFloatedButton; const fallbackAriaLabel = this.label ? undefined : 'Dropdown'; const ariaLabel = (_a = this.tdsAriaLabel) !== null && _a !== void 0 ? _a : fallbackAriaLabel; let derivedPlaceholder = (_b = this.placeholder) !== null && _b !== void 0 ? _b : ''; if (this.labelPosition === 'inside') { derivedPlaceholder = showPlaceholderInside ? (_c = this.placeholder) !== null && _c !== void 0 ? _c : '' : ''; } let buttonText = ''; if (this.selectedOptions.length > 0) { buttonText = this.getValue(); } else if (showPlaceholderButton) { buttonText = (_d = this.placeholder) !== null && _d !== void 0 ? _d : ''; } return (h(Host, { key: 'e7c3ade8e5b56a41f78016c44fb75efcaaf666c1', class: { [`tds-mode-variant-${this.modeVariant}`]: Boolean(this.modeVariant), } }, this.label && this.labelPosition === 'outside' && (h("div", { key: '26dd2d4137fea024b4b436fca739cfecaea13491', id: labelId, class: `label-outside ${this.disabled ? 'disabled' : ''}` }, this.label)), h("div", { key: 'ce88e29fa87c4c9e54ea68bef9bde26b6300bae9', class: { 'dropdown-select': true, [this.size]: true, 'disabled': this.disabled, } }, this.filter ? (h("div", { class: { filter: true, focus: this.filterFocus, disabled: this.disabled, error: this.error, } }, h("div", { class: "value-wrapper" }, this.label && this.labelPosition === 'inside' && (h("label", { id: labelId, htmlFor: inputId, class: { 'label-inside': true, [this.size]: true, 'floated': isFloated, } }, this.label)), h("input", { "aria-label": ariaLabel, "aria-labelledby": labelId, "aria-describedby": helperId, "aria-disabled": this.disabled, ref: (inputEl) => { this.inputElement = inputEl; if (this.inputElement && !this.filterFocus) { this.inputElement.value = this.getValue(); } }, class: { placeholder: this.labelPosition === 'inside', }, id: inputId, type: "text", placeholder: derivedPlaceholder, disabled: this.disabled, onInput: (event) => this.handleFilter(event), onFocus: () => this.handleFocus(), onClick: () => this.handleInputClick(), onKeyDown: (event) => { if (event.key === 'Escape') { this.open = false; } } })), h("tds-icon", { tabIndex: 0, role: "button", "aria-label": this.filterQuery.length > 0 ? 'Clear filter' : 'Clear selection', svgTitle: this.filterQuery.length > 0 ? 'Clear filter' : 'Clear selection', onClick: this.handleFilterReset, onKeyDown: (event) => { if (event.key === 'Enter') { this.handleFilterReset(); } }, class: { 'clear-icon': true, 'hide': !(this.filterQuery.length > 0 || this.selectedOptions.length > 0), }, name: "cross", size: "16px" }), h("tds-icon", { tdsAriaHidden: true, role: "button", "aria-label": "Open/Close dropdown", svgTitle: "Open/Close dropdown", onClick: this.handleToggleOpen, onKeyDown: (event) => { if (event.key === 'Enter') { this.handleToggleOpen(); } }, class: `menu-icon ${this.open ? 'open' : 'closed'}`, name: "chevron_down", size: "16px" }))) : (h("button", { "aria-label": this.tdsAriaLabel, "aria-labelledby": labelId, "aria-describedby": helperId, "aria-disabled": this.disabled, onClick: () => this.handleToggleOpen(), onKeyDown: (event) => { if (event.key === 'Escape') { this.open = false; } }, class: ` ${this.selectedOptions.length ? 'value' : 'placeholder'} ${this.open ? 'open' : 'closed'} ${this.error ? 'error' : ''} `, disabled: this.disabled }, h("div", { class: `value-wrapper ${this.size}` }, this.label && this.labelPosition === 'inside' && (h("div", { id: labelId, class: { 'label-inside': true, [this.size]: true, 'floated': isFloatedButton, } }, this.label)), h("div", { "aria-label": this.tdsAriaLabel ? `Selected options for ${this.tdsAriaLabel}` : undefined, class: `placeholder ${this.size}` }, buttonText)), h("tds-icon", { tabIndex: 0, role: "button", "aria-label": "Clear selection", svgTitle: "Clear selection", onClick: (event) => { event.stopPropagation(); this.handleMultiselectClear(); }, onKeyDown: (event) => { if (event.key === 'Enter' || event.key === ' ') { event.stopPropagation(); event.preventDefault(); this.handleMultiselectClear(); } }, class: { 'clear-icon': true, 'hide': !(this.multiselect && this.selectedOptions.length > 0), }, name: "cross", size: "16px" }), h("tds-icon", { "aria-label": "Open/Close dropdown", svgTitle: "Open/Close dropdown", class: `menu-icon ${this.open ? 'open' : 'closed'}`, name: "chevron_down", size: "16px" })))), h("div", { key: '0d76e422a2f0887595f60d57e03ec3980d4b9774', role: "listbox", "aria-label": this.tdsAriaLabel, inert: !this.open, "aria-orientation": "vertical", "aria-multiselectable": this.multiselect, ref: (element) => { if (element) this.dropdownList = element; }, class: { 'dropdown-list': true, [this.size]: true, [this.getOpenDirection()]: true, 'label-outside': !!(this.label && this.labelPosition === 'outside'), 'open': this.open, 'closed': !this.open, [`animation-enter-${this.animation}`]: this.animation !== 'none' && this.open, [`animation-exit-${this.animation}`]: this.animation !== 'none' && !this.open, } }, h("slot", { key: 'f971e4e9e24fe8d9092066d72bb05b76547f05a7', onSlotchange: () => this.handleSlotChange() }), this.filterResult === 0 && this.noResultText !== '' && (h("div", { key: '0d8f90a543bf7b8dc3b3185d27f05d0517b4e0e6', class: `no-result ${this.size}` }, this.noResultText))), this.helper && (h("div", { key: '4f17cfead0616b262e91e0e5b82cf59ce1309d73', id: helperId, class: { helper: true, error: this.error, disabled: this.disabled, } }, this.error && h("tds-icon", { key: '032599d86280e2a204c22fb97409f097841259b5', name: "error", size: "16px" }), this.helper)))); } static get is() { return "tds-dropdown"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["dropdown.scss"] }; } static get styleUrls() { return { "$": ["dropdown.css"] }; } static get properties() { return { "name": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Name for the Dropdowns input element." }, "getter": false, "setter": false, "reflect": false, "attribute": "name" }, "disabled": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Sets the Dropdown in a disabled state" }, "getter": false, "setter": false, "reflect": false, "attribute": "disabled", "defaultValue": "false" }, "helper": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Helper text for the Dropdown." }, "getter": false, "setter": false, "reflect": false, "attribute": "helper" }, "label": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Label text for the Dropdown." }, "getter": false, "setter": false, "reflect": false, "attribute": "label" }, "labelPosition": { "type": "string", "mutable": false, "complexType": { "original": "'inside' | 'outside'", "resolved": "\"inside\" | \"outside\" | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Label text position" }, "getter": false, "setter": false, "reflect": false, "attribute": "label-position" }, "modeVariant": { "type": "string", "mutable": false, "complexType": { "original": "'primary' | 'secondary' | null", "resolved": "\"primary\" | \"secondary\" | null", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Mode variant of the component, based on current mode." }, "getter": false, "setter": false, "reflect": false, "attribute": "mode-variant", "defaultValue": "null" }, "openDirection": { "type": "string", "mutable": false, "complexType": { "original": "'up' | 'down' | 'auto'", "resolved": "\"auto\" | \"down\" | \"up\"", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "The direction the Dropdown should open, auto if not specified." }, "getter": false, "setter": false, "reflect": false, "attribute": "open-direction", "defaultValue": "'auto'" }, "placeholder": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Placeholder text for the Dropdown." }, "getter": false, "setter": false, "reflect": false, "attribute": "placeholder" }, "size": { "type": "string", "mutable": false, "complexType": { "original": "'xs' | 'sm' | 'md' | 'lg'", "resolved": "\"lg\" | \"md\" | \"sm\" | \"xs\"", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "The size of the Dropdown." }, "getter": false, "setter": false, "reflect": false, "attribute": "size", "defaultValue": "'lg'" }, "animation": { "type": "string", "mutable": false, "complexType": { "original": "'none' | 'slide'", "resolved": "\"none\" | \"slide\"", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "getter": false, "setter": false, "reflect": false, "attribute": "animation", "defaultValue": "'slide'" }, "error": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Sets the Dropdown in an error state" }, "getter": false, "setter": false, "reflect": false, "attribute": "error", "defaultValue": "false" }, "multiselect": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Enables multiselect in the Dropdown." }, "getter": false, "setter": false, "reflect": false, "attribute": "multiselect", "defaultValue": "false" }, "filter": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Enables filtration in the Dropdown." }, "getter": false, "setter": false, "reflect": false, "attribute": "filter", "defaultValue": "false" }, "normalizeText": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Normalizes input text for fuzzier search" }, "getter": false, "setter": false, "reflect": false, "attribute": "normalize-text", "defaultValue": "true" }, "noResultText": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Text that is displayed if filter is used and there are no options that matches the search.\nSetting it to an empty string disables message from showing up." }, "getter": false, "setter": false, "reflect": false, "attribute": "no-result-text", "defaultValue": "'No result'" }, "defaultValue": { "type": "any", "mutable": false, "complexType": { "original": "string | number", "resolved": "number | string | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Default value selected in the Dropdown." }, "getter": false, "setter": false, "reflect": false, "attribute": "default-value" }, "value": { "type": "any", "mutable": true, "complexType": { "original": "string | number | (string | number)[] | null", "resolved": "(string | number)[] | null | number | string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Value of the dropdown. For multiselect, provide array of strings/numbers. For single select, provide a string/number." }, "getter": false, "setter": false, "reflect": false, "attribute": "value", "defaultValue": "null" }, "tdsAriaLabel": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Defines aria-label attribute for input" }, "getter": false, "setter": false, "reflect": false, "attribute": "tds-aria-label" } }; } static get states() { return { "open": {}, "internalValue": {}, "filterResult": {}, "filterFocus": {}, "internalDefaultValue": {}, "selectedOptions": {}, "filterQuery": {} }; } static get events() { return [{ "method": "tdsChange", "name": "tdsChange", "bubbles": true, "cancelable": false, "composed": true, "docs": { "tags": [], "text": "Change event for the Dropdown." }, "complexType": { "original": "{\n name: string | undefined;\n value: string | null;\n }", "resolved": "{ name: string | undefined; value: string | null; }", "references": {} } }, { "method": "tdsFocus", "name": "tdsFocus", "bubbles": true, "cancelable": false, "composed": true, "docs": { "tags": [], "text": "Focus event for the Dropdown." }, "complexType": { "original": "FocusEvent", "resolved": "FocusEvent", "references": { "FocusEvent": { "location": "global", "id": "global::FocusEvent" } } } }, { "method": "tdsBlur", "name": "tdsBlur", "bubbles": true, "cancelable": false, "composed": true, "docs": { "tags": [], "text": "Blur event for the Dropdown." }, "complexType": { "original": "FocusEvent", "resolved": "FocusEvent", "references": { "FocusEvent": { "location": "global", "id": "global::FocusEvent" } } } }, { "method": "tdsInput", "name": "tdsInput", "bubbles": true, "cancelable": false, "composed": true, "docs": { "tags": [], "text": "Input event for the Dropdown." }, "complexType": { "original": "InputEvent", "resolved": "InputEvent", "references": { "InputEvent": { "location": "global", "id": "global::InputEvent" } } } }, { "method": "tdsClear", "name": "tdsClear", "bubbles": true, "cancelable": false, "composed": true, "docs": { "tags": [], "text": "Clear event for the Dropdown." }, "complexType": { "original": "{ clearedValue: string }", "resolved": "{ clearedValue: string; }", "references": {} } }]; } static get methods() { return { "setValue": { "complexType": { "signature": "(value: string | number | string[] | number[], label?: string) => Promise<{ value: string | number | undefined; label: string | undefined; }[]>", "parameters": [{ "name": "value", "type": "string | number | string[] | number[]", "docs": "" }, { "name": "label", "type": "string | undefined", "docs": "" }], "references": { "Promise": { "location": "global", "id": "global::Promise" },