import { type HandlerEvent, attr, godown, htmlSlot, styles } from "@godown/element"; import svgCaretDown from "../../internal/icons/caret-down.js"; import { type TemplateResult, css, html, nothing } from "lit"; import { property, query } from "lit/decorators.js"; import Input from "../input/component.js"; import { hidePopover, showPopover } from "../../internal/popover.js"; import { memoize } from "../../internal/utils.js"; const supportsPositionArea = memoize(() => CSS.supports("position-area:top")); function updateSelected(element: HTMLElement | null, operation: 0 | 1) { if (element) { const name = "selected"; if (operation) { element.setAttribute(name, ""); } else { element.removeAttribute(name); } } } const protoName = "select"; /** * {@linkcode Select} is similar to ` ` : "", html` `, this._renderSuffix(), ]}
${htmlSlot()}
`; } protected _renderSuffix(): TemplateResult<1> { return html` ${htmlSlot("suffix", svgCaretDown())} `; } protected firstUpdated(): void { this.events.add(this._slot, "click", (e: HandlerEvent) => { const { target } = e; if (target.tagName !== "OPTION") { return; } e.preventDefault(); const { label, value } = target; const operation = this.select(value, label); if (!this.multiple) { updateSelected(this.lastChecked, 0); this.hideOptions(); } updateSelected(target, operation); this.lastChecked = target; }); } protected _connectedInit(): void { this.default = this.value ??= ""; this.defaultText = this.text ??= ""; this.events.add(this, "focus", this.showOptions); } reset(): void { this.value = this.default; this.text = this.defaultText; } select(value: string, label: string): 0 | 1 { label ||= value; let operation: 0 | 1 = 0; const i = this.values.findIndex((s) => s.value === value); if (i > -1) { this.values.splice(i, 1); } else { this.values.push({ value, label }); operation = 1; } this.checkValues(); this.value = this.values.map((s) => s.value).join(","); this.text = this.values.map((s) => s.label).join(", "); this.dispatchCustomEvent("select", this.value); return operation; } checkValues(): void { if (!this.multiple && this.values.length > 1) { this.values.splice(0, this.values.length - 1); this.requestUpdate(); } } showOptions(): void { if (this.optionsVisible) { return; } showPopover(this._popover); const listener = (e) => { if (!this.contains(e.target)) { this.hideOptions(); this.events.remove(document, "click", listener); } }; this.events.add(document, "click", listener); this.optionsVisible = true; } hideOptions(): void { if (!this.optionsVisible) { return; } hidePopover(this._popover); this.optionsVisible = false; } focus(options?: FocusOptions): void { super.focus(); this._input.focus(options); this.showOptions(); } blur(): void { super.blur(); this._input.blur(); hidePopover(this._popover); } } export default Select; export { Select };