UNPKG

@ebay/ebayui-core

Version:

Collection of core eBay components; considered to be the building blocks for all composite structures, pages & apps.

302 lines (301 loc) 11.4 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const makeup_active_descendant_1 = require("makeup-active-descendant"); const makeup_floating_label_1 = __importDefault(require("makeup-floating-label")); const makeup_expander_1 = __importDefault(require("makeup-expander")); const dropdown_1 = require("../../common/dropdown"); const element_scroll_1 = require("../../common/element-scroll"); const eventUtils = __importStar(require("../../common/event-utils")); const build_safe_regex_1 = __importDefault(require("../../common/build-safe-regex")); class Combobox { focus() { this.getEl("combobox").focus(); } handleFocus() { this._emitComboboxEvent("focus"); } isExpanded() { return this.expander && this.expander.expanded; } isCollapsed() { return this.expander && !this.expander.expanded; } expand() { if (this.isCollapsed()) { this.expander.expanded = true; } } collapse() { if (this.isExpanded()) { this.expander.expanded = false; } } handleButtonClick(originalEvent) { this.buttonClicked = true; this.emit("button-click", { originalEvent }); } handleActiveDescendantChange(ev) { if (this.listSelection === "automatic") { const selected = this._getVisibleOptions()[ev.detail.toIndex]; // Set textbox value to selected, don't update state since it messes up active descendant // Check if selected is set, since it could be undefined in case of a race condition this.getEl("combobox").value = selected === null || selected === void 0 ? void 0 : selected.text; } } setSelectedView() { const current = this._getVisibleOptions().indexOf(this._getSelectedOption()); this.activeDescendant.index = current; const selectedEl = this.getEls("options")[current]; if (selectedEl) { (0, element_scroll_1.scroll)(selectedEl); } } handleExpand() { this.setSelectedView(); this.dropdownUtil.show(); this.emit("expand"); } handleCollapse() { this.activeDescendant.reset(); this.dropdownUtil.hide(); this.emit("collapse"); } handleComboboxClick(e) { if (e.target === document.activeElement) { this.expand(); } } handleComboboxKeyDown(originalEvent) { eventUtils.handleUpDownArrowsKeydown(originalEvent, () => { originalEvent.preventDefault(); this.expand(); }); eventUtils.handleEnterKeydown(originalEvent, () => { if (this.isExpanded()) { const selectedIndex = this.activeDescendant.index; if (selectedIndex !== -1) { this._setSelectedText(this._getVisibleOptions()[selectedIndex].text); } if (this.input.expanded !== true) { this.collapse(); } } }); eventUtils.handleEscapeKeydown(originalEvent, () => { this.collapse(); }); this.emit("keydown", originalEvent); } handleComboboxKeyUp(originalEvent) { eventUtils.handleTextInput(originalEvent, () => { this.state.currentValue = this.getEl("combobox").value; this.once("update", () => { // If we have an expander after the update // that could mean that new content was made visible. // We force the expander open just in case. this.expand(); }); this._emitComboboxEvent("input-change"); }); } handleComboboxBlur() { const wasClickedOption = this.optionClicked; if (wasClickedOption) { this.focus(); } if (!wasClickedOption && !this.buttonClicked && this.input.expanded !== true) { this.collapse(); } this.buttonClicked = false; const combobox = this.getEl("combobox"); if (this.listSelection === "automatic" && combobox.value !== this.state.currentValue) { this.state.currentValue = combobox.value; } if (this.lastValue !== this.state.currentValue) { this.lastValue = this.state.currentValue; this._emitComboboxEvent("change"); } } handleSelectOption(text) { this._setSelectedText(text); this.emit("option-click", text); } handleFloatingLabelInit() { this._emitComboboxEvent("floating-label-init"); } onInput(input) { this.autocomplete = input.autocomplete === "list" ? "list" : "none"; this.listSelection = input.listSelection === "manual" ? "manual" : "automatic"; this.lastValue = input.value; this.state = { currentValue: this.lastValue, }; if (this.expander) { this.expandedChange = input.expanded !== this.expanded; if (this.expandedChange) { this.expander.expanded = input.expanded; } } this.expanded = input.expanded; } onMount() { this._setupMakeup(); } onUpdate() { this._setupMakeup(); } onRender() { if (typeof window !== "undefined") { this._cleanupMakeup(); } } onDestroy() { this._cleanupMakeup(); } _setupFloatingLabel() { // TODO: makeup-floating-label should be updated so that we can remove the event listeners. // It probably makes more sense to just move this functionality into Marko though. if (this._floatingLabel) { this._floatingLabel.refresh(); this.handleFloatingLabelInit(); } else if (document.readyState === "complete") { if (this.el) { this._floatingLabel = new makeup_floating_label_1.default(this.el); this.handleFloatingLabelInit(); } } else { this.subscribeTo(window).once("load", () => { this._setupFloatingLabel(); }); } } _setupMakeup() { var _a, _b, _c; if (this._hasVisibleOptions()) { if (!this.activeDescendant) { this.activeDescendant = (0, makeup_active_descendant_1.createLinear)(this.el, this.getEl("combobox"), this.getEl("listbox"), '[role="option"]', { activeDescendantClassName: "combobox__option--active", autoInit: -1, autoReset: -1, axis: "y", autoScroll: true, }); } if (!this.expander) { this.expander = new makeup_expander_1.default(this.el, { autoCollapse: !this.expanded, expandOnFocus: true, collapseOnFocusOut: !this.expanded && !this.input.button, contentSelector: '[role="listbox"]', hostSelector: '[role="combobox"]', expandedClass: "combobox--expanded", simulateSpacebarClick: true, }); } if (this.expandedChange) { this.expander.expanded = this.expanded; this.expandedChange = false; } } this.dropdownUtil = new dropdown_1.DropdownUtil((_c = (_b = (_a = this.input).dropdownElement) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : this.getEl("combobox"), this.getEl("listbox"), { strategy: this.input.strategy, flip: this.input.flip, }); if (this.isExpanded()) { this.dropdownUtil.show(); } if (this.input.floatingLabel) { this._setupFloatingLabel(); } } _cleanupMakeup() { if (this.activeDescendant) { this.activeDescendant.reset(); this.activeDescendant.destroy(); this.activeDescendant = null; } if (this.expander) { this.expander.destroy(); this.expander = null; } if (this._floatingLabel) { this._floatingLabel.destroy(); this._floatingLabel = null; } } _setSelectedText(text) { if (this.state.currentValue !== text) { const input = this.getEl("combobox"); this.state.currentValue = input.value = text; // Move cursor to the end of the input. input.selectionStart = input.selectionEnd = text.length; input.focus(); this._emitComboboxEvent("select"); } } _getSelectedOption() { var _a; return [...((_a = this.input.option) !== null && _a !== void 0 ? _a : [])].find((option) => option.text === this.state.currentValue); } _getVisibleOptions() { var _a, _b, _c; if (this.autocomplete === "none") { return [...((_a = this.input.option) !== null && _a !== void 0 ? _a : [])]; } const currentValueReg = (0, build_safe_regex_1.default)((_b = this.state.currentValue) === null || _b === void 0 ? void 0 : _b.toString()); return [...((_c = this.input.option) !== null && _c !== void 0 ? _c : [])].filter((option) => currentValueReg.test(option.text || "") || option.sticky); } _hasVisibleOptions() { return !this.input.disabled && this._getVisibleOptions().length > 0; } _emitComboboxEvent(eventName) { this.emit(`${eventName}`, { currentInputValue: this.state.currentValue, selectedOption: this._getSelectedOption(), option: this.input.option, }); } } module.exports = Combobox;