UNPKG

@dialpad/dialtone

Version:

Dialpad's Dialtone design system monorepo

456 lines (455 loc) 13.6 kB
import { validationMessageValidator as e } from "../../common/validators/index.js"; import { extractNonListeners as t, extractVueListeners as n, hasSlotContent as r, returnFirstEl as i } from "../../common/utils/index.js"; import { t as a } from "../../_plugin-vue_export-helper-BTgDAbhb.js"; import o from "../validation-messages/validation-messages.js"; import s from "../chip/chip.js"; import { POPOVER_APPEND_TO_VALUES as c } from "../popover/popover-constants.js"; import l from "../input/input.js"; import u from "../combobox-with-popover/combobox-with-popover.js"; import { CHIP_SIZES as d, CHIP_TOP_POSITION as f, MULTI_SELECT_SIZES as p } from "./combobox-multi-select-constants.js"; import { Fragment as m, createBlock as h, createElementBlock as g, createElementVNode as _, createSlots as v, createTextVNode as y, createVNode as b, mergeProps as x, normalizeClass as S, openBlock as C, renderList as w, renderSlot as T, resolveComponent as E, toDisplayString as D, toHandlers as O, withCtx as k, withKeys as A, withModifiers as j } from "vue"; //#region components/combobox_multi_select/combobox_multi_select.vue var M = { compatConfig: { MODE: 3 }, name: "DtComboboxMultiSelect", components: { DtComboboxWithPopover: u, DtInput: l, DtChip: s, DtValidationMessages: o }, inheritAttrs: !1, props: { label: { type: String, required: !0 }, labelVisible: { type: Boolean, default: !0 }, description: { type: String, default: "" }, placeholder: { type: String, default: "Select one or start typing" }, inputMessages: { type: Array, default: () => [], validator: (t) => e(t) }, showInputMessages: { type: Boolean, default: !0 }, loading: { type: Boolean, default: !1 }, loadingMessage: { type: String, default: "loading..." }, showList: { type: Boolean, default: null }, listMaxHeight: { type: String, default: "300px" }, selectedItems: { type: Array, default: function() { return []; } }, maxSelected: { type: Number, default: 0 }, maxSelectedMessage: { type: Array, default: function() { return []; } }, hasSuggestionList: { type: Boolean, default: !0 }, size: { type: String, default: "md", validator: (e) => Object.values(p).includes(e) }, appendTo: { type: [HTMLElement, String], default: "body", validator: (e) => c.includes(e) || e instanceof HTMLElement }, transition: { type: String, default: "fade" }, collapseOnFocusOut: { type: Boolean, default: !1 }, listMaxWidth: { type: String, default: "" }, reservedRightSpace: { type: Number, default: 64 }, chipMaxWidth: { type: String, default: "" }, inputClass: { type: [ String, Object, Array ], default: "" }, inputWrapperClass: { type: [ String, Object, Array ], default: "" }, disabled: { type: Boolean, default: !1 }, dialogClass: { type: [ String, Object, Array ], default: "" } }, emits: [ "input", "select", "remove", "max-selected", "keydown", "chip-keydown", "escape", "enter", "combobox-highlight" ], data() { return { value: "", popoverOffset: [0, 4], showValidationMessages: !1, resizeWindowObserver: null, initialInputHeight: null, CHIP_SIZES: d, hasSlotContent: r, inputFocused: !1, hideInputText: !1 }; }, computed: { inputPlaceHolder() { return this.selectedItems?.length > 0 ? "" : this.placeholder; }, chipListeners() { return { keydown: (e) => { this.disabled || (this.onChipKeyDown(e), this.$emit("chip-keydown", e)); } }; }, inputListeners() { return { ...n(this.$attrs), onInput: (e) => { this.$emit("input", e), this.hasSuggestionList && this.showComboboxList(); }, onKeydown: (e) => { if (this.disabled) return; this.onInputKeyDown(e), this.$emit("keydown", e); let t = e.key?.toLowerCase(); t === "escape" ? this.$emit("escape", e) : t === "enter" && this.$emit("enter", e); }, onClick: () => { this.hasSuggestionList && this.showComboboxList(); } }; }, chipWrapperClass() { return { [`d-recipe-combobox-multi-select__chip-wrapper-${this.size}--collapsed`]: !this.inputFocused && this.collapseOnFocusOut }; } }, watch: { selectedItems: { deep: !0, handler: async function() { await this.initSelectedItems(); } }, chipMaxWidth: { async handler() { await this.initSelectedItems(); } }, async label() { await this.$nextTick(), this.setChipsTopPosition(); }, async description() { await this.$nextTick(), this.setChipsTopPosition(); }, size: { async handler() { await this.$nextTick(); let e = this.getInput(); this.revertInputPadding(e), this.initialInputHeight = e.getBoundingClientRect().height, this.setInputPadding(), this.setChipsTopPosition(); } } }, async mounted() { this.setInitialInputHeight(), this.resizeWindowObserver = new ResizeObserver(async () => { this.setChipsTopPosition(), this.setInputPadding(); }), this.resizeWindowObserver.observe(document.body), await this.initSelectedItems(); }, beforeUnmount() { this.resizeWindowObserver?.unobserve(document.body); }, methods: { extractNonListeners: t, comboboxHighlight(e) { this.$emit("combobox-highlight", e); }, async initSelectedItems() { await this.$nextTick(), this.setInputPadding(), this.setChipsTopPosition(), this.setInputMinWidth(), this.checkMaxSelected(); }, onChipRemove(e) { this.$emit("remove", e), this.$refs.input?.focus(); }, onComboboxSelect(e) { this.loading || (this.value = "", this.$emit("select", e)); }, showComboboxList() { this.showList ?? this.$refs.comboboxWithPopover?.showComboboxList(); }, closeComboboxList() { this.showList ?? this.$refs.comboboxWithPopover?.closeComboboxList(); }, getChips() { if (!this.selectedItems.length || !this.$refs.chips) return null; let e = /* @__PURE__ */ new Set(); return this.selectedItems.map((t) => this.$refs.chips.find((n, r) => e.has(r) ? !1 : i(n.$el)?.querySelector(".d-chip__label")?.textContent?.trim() === t ? (e.add(r), !0) : !1)).filter(Boolean).map((e) => i(e.$el)); }, getChipButtons() { let e = this.getChips(); return e && e.map((e) => i(e).querySelector("button")); }, getLastChipButton() { let e = this.getChipButtons(); return e && e[e.length - 1]; }, getLastChip() { let e = this.getChips(); return e && e[e.length - 1]; }, getFirstChip() { let e = this.getChips(); return e && e[0]; }, getInput() { return this.$refs.input?.$refs.input; }, onChipKeyDown(e) { let t = e.code?.toLowerCase(); t === "arrowleft" ? this.navigateBetweenChips(e.target, !0) : t === "arrowright" && (e.target.id === this.getLastChipButton().id ? this.moveFromChipToInput() : this.navigateBetweenChips(e.target, !1)); }, onInputKeyDown(e) { let t = e.key?.toLowerCase(); if (this.selectedItems.length > 0 && e.target.selectionStart === 0) { if (e.target.selectionEnd !== e.target.selectionStart) return; (t === "backspace" || t === "arrowleft") && this.moveFromInputToChip(); } }, moveFromInputToChip() { this.getLastChipButton().focus(), this.$refs.input?.blur(), this.closeComboboxList(); }, moveFromChipToInput() { this.getLastChipButton().blur(), this.$refs.input?.focus(), this.showComboboxList(); }, navigateBetweenChips(e, t) { let n = this.getChipButtons().indexOf(e), r = t ? n - 1 : n + 1; r < 0 || r >= this.$refs.chips?.length || (this.getChipButtons()[n].blur(), this.getChipButtons()[r].focus(), this.closeComboboxList()); }, setChipsTopPosition() { let e = this.getInput(); if (!e) return; let t = this.$refs.inputSlotWrapper, n = e.getBoundingClientRect().top - t.getBoundingClientRect().top, r = this.$refs.chipsWrapper; r.style.top = n - f[this.size] + "px"; }, setInputPadding() { let e = this.getLastChip(), t = this.getInput(), n = this.$refs.chipsWrapper; if (!t || (this.revertInputPadding(t), this.popoverOffset = [0, 4], !e) || this.collapseOnFocusOut && !this.inputFocused) return; let r = e.offsetLeft + this.getFullWidth(e), i = t.getBoundingClientRect().width - r; i > this.reservedRightSpace ? t.style.paddingLeft = r + "px" : t.style.paddingLeft = "4px"; let a = n.getBoundingClientRect().height - 4, o = e.getBoundingClientRect().height - 4, s = i > this.reservedRightSpace ? e.offsetTop + 2 : a + o - 9; t.style.paddingTop = `${s}px`; }, revertInputPadding(e) { e.style.paddingLeft = "", e.style.paddingTop = "", e.style.paddingBottom = ""; }, getFullWidth(e) { let t = window.getComputedStyle(e); return e.offsetWidth + parseInt(t.marginLeft) + parseInt(t.marginRight); }, setInputMinWidth() { let e = this.getFirstChip(), t = this.getInput(); t && (e ? t.style.minWidth = this.getFullWidth(e) + 4 + "px" : t.style.minWidth = ""); }, checkMaxSelected() { this.maxSelected !== 0 && (this.selectedItems.length > this.maxSelected ? (this.showValidationMessages = !0, this.$emit("max-selected")) : this.showValidationMessages = !1); }, setInitialInputHeight() { let e = this.getInput(); e && (this.initialInputHeight = e.getBoundingClientRect().height); }, async handleInputFocusIn() { this.inputFocused = !0, this.collapseOnFocusOut && (this.hideInputText = !1, await this.$nextTick(), this.setInputPadding()); }, async handleInputFocusOut() { if (this.inputFocused = !1, this.collapseOnFocusOut) { this.hideInputText = !0; let e = this.getInput(); if (!e || !e.style.paddingTop) return; this.revertInputPadding(e); } } } }, N = { ref: "header" }, P = { key: 1, class: "d-recipe-combobox-multi-select__list--loading" }, F = { ref: "footer" }; function I(e, t, n, r, i, a) { let o = E("dt-chip"), s = E("dt-input"), c = E("dt-validation-messages"), l = E("dt-combobox-with-popover"); return C(), h(l, x({ ref: "comboboxWithPopover", label: n.label, "show-list": n.showList, "max-height": n.listMaxHeight, "max-width": n.listMaxWidth, "popover-offset": i.popoverOffset, "has-suggestion-list": n.hasSuggestionList, "content-width": "anchor", "append-to": n.appendTo, "dialog-class": n.dialogClass, transition: n.transition }, a.extractNonListeners(e.$attrs), { onSelect: a.onComboboxSelect, onHighlight: a.comboboxHighlight }), v({ input: k(({ onInput: e }) => [_("span", { ref: "inputSlotWrapper", class: "d-recipe-combobox-multi-select__input-wrapper", onFocusin: t[1] || (t[1] = (...e) => a.handleInputFocusIn && a.handleInputFocusIn(...e)), onFocusout: t[2] || (t[2] = (...e) => a.handleInputFocusOut && a.handleInputFocusOut(...e)) }, [ _("span", { ref: "chipsWrapper", class: S(["d-recipe-combobox-multi-select__chip-wrapper", a.chipWrapperClass]) }, [(C(!0), g(m, null, w(n.selectedItems, (e, t) => (C(), h(o, x({ ref_for: !0, ref: "chips", key: `${t}-${e}`, "label-class": ["d-chip__label"], class: ["d-recipe-combobox-multi-select__chip", { "d-recipe-combobox-multi-select__chip--truncate": !!n.chipMaxWidth }], style: { maxWidth: n.chipMaxWidth }, size: i.CHIP_SIZES[n.size], disabled: n.disabled }, O(a.chipListeners), { onKeydown: A((t) => a.onChipRemove(e), ["backspace"]), onClose: (t) => a.onChipRemove(e) }), { default: k(() => [y(D(e), 1)]), _: 2 }, 1040, [ "class", "style", "size", "disabled", "onKeydown", "onClose" ]))), 128))], 2), b(s, x({ ref: "input", modelValue: i.value, "onUpdate:modelValue": t[0] || (t[0] = (e) => i.value = e), class: "d-recipe-combobox-multi-select__input", "input-class": [n.inputClass, { "d-recipe-combobox-multi-select__input--hidden": i.hideInputText }], "input-wrapper-class": n.inputWrapperClass, disabled: n.disabled, "aria-label": n.label, label: n.labelVisible ? n.label : "", description: n.description, placeholder: a.inputPlaceHolder, "show-messages": n.showInputMessages, messages: n.inputMessages, size: n.size }, a.inputListeners, { onInput: e }), null, 16, [ "modelValue", "input-class", "input-wrapper-class", "disabled", "aria-label", "label", "description", "placeholder", "show-messages", "messages", "size", "onInput" ]), b(c, { "validation-messages": n.maxSelectedMessage, "show-messages": i.showValidationMessages }, null, 8, ["validation-messages", "show-messages"]) ], 544)]), list: k(() => [_("div", { ref: "list", class: "d-recipe-combobox-multi-select__list", onMousedown: t[3] || (t[3] = j(() => {}, ["prevent"])) }, [n.loading ? (C(), g("div", P, D(n.loadingMessage), 1)) : T(e.$slots, "list", { key: 0 })], 544)]), _: 2 }, [i.hasSlotContent(e.$slots.header) ? { name: "header", fn: k(() => [_("div", N, [T(e.$slots, "header")], 512)]), key: "0" } : void 0, i.hasSlotContent(e.$slots.footer) ? { name: "footer", fn: k(() => [_("div", F, [T(e.$slots, "footer")], 512)]), key: "1" } : void 0]), 1040, [ "label", "show-list", "max-height", "max-width", "popover-offset", "has-suggestion-list", "append-to", "dialog-class", "transition", "onSelect", "onHighlight" ]); } var L = /* @__PURE__ */ a(M, [["render", I]]); //#endregion export { L as default }; //# sourceMappingURL=combobox-multi-select.js.map