UNPKG

@dialpad/dialtone-vue

Version:

Vue component library for Dialpad's design system Dialtone

303 lines (302 loc) 9.84 kB
import n from "./combobox-loading-list.js"; import o from "./combobox-empty-list.js"; import { getUniqueString as l } from "../../common/utils/index.js"; import { n as r } from "../../_plugin-vue2_normalizer-DSLOjnn3.js"; import a from "../../common/mixins/keyboard-list-navigation.js"; import { COMBOBOX_LABEL_SIZES as d } from "./combobox-constants.js"; const h = { name: "DtCombobox", components: { ComboboxLoadingList: n, ComboboxEmptyList: o }, mixins: [ a({ indexKey: "highlightIndex", idKey: "highlightId", listElementKey: "getListElement", afterHighlightMethod: "afterHighlight", beginningOfListMethod: "beginningOfListMethod", endOfListMethod: "endOfListMethod", activeItemKey: "activeItemEl" }) ], props: { /** * String to use for the input label. */ label: { type: String, required: !0 }, /** * Determines visibility of input label. * @values true, false */ labelVisible: { type: Boolean, default: !0 }, /** * Size of the input, one of `xs`, `sm`, `md`, `lg`, `xl` * @values null, xs, sm, md, lg, xl */ size: { type: String, default: null, validator: (i) => Object.values(d).includes(i) }, /** * Description for the input */ description: { type: String, default: "" }, /** * Sets an ID on the list element of the component. Used by several aria attributes * as well as when deriving the IDs for each item. */ listId: { type: String, default() { return l(); } }, /** * A method that will be called when the selection goes past the beginning of the list. */ onBeginningOfList: { type: Function, default: null }, /** * A method that will be called when the selection goes past the end of the list. */ onEndOfList: { type: Function, default: null }, /** * Determines when to show the list element and also controls the aria-expanded attribute. * @values true, false */ showList: { type: Boolean, default: !1 }, /** * If the list is rendered outside the component, like when using popover as the list wrapper. * @values true, false */ listRenderedOutside: { type: Boolean, default: !1 }, /** * Determines when to show the skeletons and also controls aria-busy attribute. * @values true, false */ loading: { type: Boolean, default: !1 }, /** * Sets the list to an empty state, and displays the message from prop `emptyStateMessage`. * @values true, false */ emptyList: { type: Boolean, default: !1 }, /** * Message to show when the list is empty */ emptyStateMessage: { type: String, default: "" }, /** * Additional class name for the empty list element. * Can accept all of String, Object, and Array, i.e. has the * same api as Vue's built-in handling of the class attribute. */ emptyStateClass: { type: [String, Object, Array], default: "" }, /** * Programmatically click on the active list item element when a selection * comes from keyboard navigation, i.e. pressing the "Enter" key. * @values true, false */ clickOnSelect: { type: Boolean, default: !1 } }, emits: [ /** * Event fired when item selected * * @event select * @type {Number} */ "select", /** * Event fired when pressing escape * * @event escape */ "escape", /** * Event fired when the highlight changes * * @event highlight * @type {Number} */ "highlight", /** * Event fired when list is shown or hidden * * @event opened * @type {Boolean} */ "opened" ], data() { return { // If the list is rendered at the root, rather than as a child // of this component, this is the ref to that dom element. Set // by the onOpen method. outsideRenderedListRef: null }; }, computed: { inputProps() { return { label: this.label, labelVisible: this.labelVisible, size: this.size, description: this.description, role: "combobox", "aria-label": this.label, "aria-expanded": this.showList.toString(), "aria-owns": this.listId, "aria-haspopup": "listbox", "aria-activedescendant": this.activeItemId, "aria-controls": this.listId }; }, listProps() { return { role: "listbox", id: this.listId, // The list has to be positioned relatively so that the auto-scroll can // calculate the correct offset for the list items. class: "d-ps-relative", "aria-label": this.label }; }, beginningOfListMethod() { return this.onBeginningOfList || this.jumpToEnd; }, endOfListMethod() { return this.onEndOfList || this.jumpToBeginning; }, activeItemId() { if (!(!this.showList || this.highlightIndex < 0 || this.loading)) return this.highlightId; }, activeItemEl() { return this.highlightId ? this.getListElement().querySelector("#" + this.highlightId) : ""; } }, watch: { showList(i) { this.listRenderedOutside || (this.setInitialHighlightIndex(), this.$emit("opened", i)), !i && this.outsideRenderedListRef && (this.outsideRenderedListRef.removeEventListener("mousemove", this.onMouseHighlight), this.outsideRenderedListRef = null); }, loading() { this.$nextTick(() => { this.setInitialHighlightIndex(); }); }, $props: { deep: !0, immediate: !0, handler() { this.validateEmptyListProps(); } } }, created() { this.validateEmptyListProps(); }, methods: { onMouseHighlight(i) { if (this.loading) return; const t = i.target.closest("li"); t && this.highlightId !== t.id && this.setHighlightId(t.id); }, getListElement() { var i; return this.outsideRenderedListRef ?? ((i = this.$refs.listWrapper) == null ? void 0 : i.querySelector(`#${this.listId}`)); }, clearHighlightIndex() { this.showList && this.setHighlightIndex(-1); }, afterHighlight() { this.loading || this.$emit("highlight", this.highlightIndex); }, onEnterKey() { var i; this.loading || this.emptyList || this.highlightIndex >= 0 && (this.$emit("select", this.highlightIndex), this.clickOnSelect && ((i = this.activeItemEl) == null || i.click())); }, onEscapeKey() { this.$emit("escape"); }, onOpen(i, t) { var s; this.outsideRenderedListRef = t, (s = this.outsideRenderedListRef) == null || s.addEventListener("mousemove", this.onMouseHighlight), this.$emit("opened", i), i && this.setInitialHighlightIndex(); }, onKeyValidation(i, t) { !this.showList || !this.getListElement() || this[t](i); }, setInitialHighlightIndex() { this.showList && this.$nextTick(() => { this.setHighlightIndex(this.loading ? -1 : 0); }); }, validateEmptyListProps() { this.$slots.emptyListItem || this.emptyList && !this.emptyStateMessage && console.error(`Invalid props: you must pass both props emptyList and emptyStateMessage to show the empty message.`); } } }; var p = function() { var t = this, s = t._self._c; return s("div", { on: { keydown: [function(e) { return !e.type.indexOf("key") && t._k(e.keyCode, "esc", 27, e.key, ["Esc", "Escape"]) ? null : (e.stopPropagation(), t.onKeyValidation(e, "onEscapeKey")); }, function(e) { return !e.type.indexOf("key") && t._k(e.keyCode, "enter", 13, e.key, "Enter") || e.ctrlKey || e.shiftKey || e.altKey || e.metaKey ? null : t.onKeyValidation(e, "onEnterKey"); }, function(e) { return !e.type.indexOf("key") && t._k(e.keyCode, "up", 38, e.key, ["Up", "ArrowUp"]) ? null : (e.stopPropagation(), e.preventDefault(), t.onKeyValidation(e, "onUpKey")); }, function(e) { return !e.type.indexOf("key") && t._k(e.keyCode, "down", 40, e.key, ["Down", "ArrowDown"]) ? null : (e.stopPropagation(), e.preventDefault(), t.onKeyValidation(e, "onDownKey")); }, function(e) { return !e.type.indexOf("key") && t._k(e.keyCode, "home", void 0, e.key, void 0) ? null : (e.stopPropagation(), e.preventDefault(), t.onKeyValidation(e, "onHomeKey")); }, function(e) { return !e.type.indexOf("key") && t._k(e.keyCode, "end", void 0, e.key, void 0) ? null : (e.stopPropagation(), e.preventDefault(), t.onKeyValidation(e, "onEndKey")); }] } }, [s("div", { attrs: { "data-qa": "dt-combobox-input-wrapper" } }, [t._t("input", null, { inputProps: t.inputProps })], 2), t.showList ? s("div", { ref: "listWrapper", attrs: { "data-qa": "dt-combobox-list-wrapper" }, on: { mouseleave: t.clearHighlightIndex, focusout: t.clearHighlightIndex, "!mousemove": function(e) { return t.onMouseHighlight.apply(null, arguments); } } }, [t.loading && !t.listRenderedOutside ? s("combobox-loading-list", t._b({}, "combobox-loading-list", t.listProps, !1)) : t.emptyList && (t.emptyStateMessage || t.$slots.emptyListItem) && !t.listRenderedOutside ? s("combobox-empty-list", t._b({ attrs: { message: t.emptyStateMessage, "item-class": t.emptyStateClass } }, "combobox-empty-list", t.listProps, !1), [t._t("emptyListItem")], 2) : t._t("list", null, { listProps: t.listProps, opened: t.onOpen, clearHighlightIndex: t.clearHighlightIndex })], 2) : t._e()]); }, u = [], g = /* @__PURE__ */ r( h, p, u ); const I = g.exports; export { I as default }; //# sourceMappingURL=combobox.js.map