UNPKG

vue-search-select

Version:
614 lines (613 loc) 18.3 kB
import { openBlock as m, createElementBlock as c, normalizeClass as f, createElementVNode as p, withModifiers as a, withKeys as u, toDisplayString as x, normalizeStyle as O, Fragment as I, renderList as v, renderSlot as y, createTextVNode as g, h as S, createCommentVNode as M, withDirectives as A, vModelText as C } from "vue"; const l = { // cursor on input openOptions(e) { e.$refs.input.focus(), e.showMenu = !0, e.mousedownState = !1; }, blurInput(e) { e.mousedownState || (e.searchText = "", e.closeOptions()), e.$emit("blur"); }, closeOptions(e) { e.$refs.input.blur(), e.showMenu = !1; }, /** * up arrow key * 上の移動するときには新しいscroll位置を毎回セットする * Always scroll move, when "up arrow key" entered */ prevItem(e) { const t = e.pointer - 1, n = e.$el.offsetHeight * t; t >= 0 && (e.pointer = t), e.$refs.menu.scrollTop = n; }, /** * * down arrow key * ページsizeを計算してずれたらmove * calculate page size. If different between itemPage and currentPage move scroll */ nextItem(e) { const t = e.pointer + 1, n = e.$el.offsetHeight * t; t <= e.filteredOptions.length - 1 && (e.pointer = t); const d = e.$refs.menu.offsetHeight, r = Math.ceil((e.$refs.menu.scrollTop + e.$el.offsetHeight) / d), s = Math.ceil(n / d); r !== s && (e.$refs.menu.scrollTop = (s - 1) * e.$refs.menu.offsetHeight); }, // down enter key enterItem(e) { const t = e.filteredOptions[e.pointer], n = t.disabled; t && !n && e.selectItem(t); }, // mouse enter event on item pointerSet(e, t) { e.pointer = t; }, pointerAdjust(e) { e.pointer >= e.filteredOptions.length - 1 && (e.pointer = e.filteredOptions.length ? e.filteredOptions.length - 1 : 0); }, mousedownItem(e) { e.mousedownState = !0; } }; function E(e) { return new RegExp(e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "i"); } const b = { props: { id: { default: null }, name: { type: String, default: "" }, isError: { type: Boolean, default: !1 }, customAttr: { type: Function, default: () => "" }, isDisabled: { type: Boolean, default: !1 }, placeholder: { type: String, default: "" }, filterPredicate: { type: Function, default: (e, t) => e.match(E(t)) } } }, V = (e, t) => { const n = e.__vccOpts || e; for (const [d, r] of t) n[d] = r; return n; }, k = { name: "ModelSelect", mixins: [b], emits: ["blur", "searchchange", "update:modelValue"], props: { modelValue: { type: [String, Number, Object, Boolean] }, customAttr: { type: Function, default: () => "" }, options: { type: Array } }, data() { return { showMenu: !1, searchText: "", mousedownState: !1, // mousedown on option menu pointer: -1 }; }, watch: { value(e) { this.pointer = this.filteredOptions.findIndex((t) => t.value === this.optionValue(e)); }, filteredOptions() { this.pointerAdjust(); }, searchText() { this.$emit("searchchange", this.searchText); } }, computed: { searchTextCustomAttr() { return this.selectedOption && this.selectedOption.value ? this.customAttr(this.selectedOption) : ""; }, inputText() { if (this.searchText) return ""; { let e = this.placeholder; return this.selectedOption && (e = this.selectedOption.text), e; } }, customAttrs() { try { if (Array.isArray(this.options)) return this.options.map((e) => this.customAttr(e)); } catch { } return []; }, textClass() { return !this.selectedOption && this.placeholder ? "default" : ""; }, menuClass() { return { visible: this.showMenu, hidden: !this.showMenu }; }, menuStyle() { return { display: this.showMenu ? "block" : "none" }; }, filteredOptions() { return this.searchText ? this.options.filter((e) => { try { return this.filterPredicate(e.text, this.searchText); } catch { return !0; } }) : this.options; }, selectedOption() { return this.options.find((e) => e.value === this.optionValue(this.modelValue)); } }, methods: { deleteTextOrItem() { !this.searchText && this.modelValue && (this.selectItem({}), this.openOptions()); }, openOptions() { l.openOptions(this); }, blurInput() { l.blurInput(this); }, closeOptions() { l.closeOptions(this); }, prevItem() { l.prevItem(this); }, nextItem() { l.nextItem(this); }, enterItem() { l.enterItem(this); }, pointerSet(e) { l.pointerSet(this, e); }, pointerAdjust() { l.pointerAdjust(this); }, mousedownItem() { l.mousedownItem(this); }, selectItem(e) { this.searchText = "", this.closeOptions(), typeof this.modelValue == "object" && this.modelValue ? this.$emit("update:modelValue", e) : (this.$emit("update:modelValue", e.value), e.value !== void 0 && e.value === e.text && (this.searchText = e.value)); }, optionValue(e) { return typeof e == "object" && e !== null ? e.value : e; } } }, D = /* @__PURE__ */ p("i", { class: "dropdown icon" }, null, -1), j = ["disabled", "tabindex", "id", "name", "value"], R = ["data-vss-custom-attr"], B = ["data-vss-custom-attr", "onClick", "onMouseenter"]; function F(e, t, n, d, r, s) { return m(), c("div", { class: f(["ui fluid search selection dropdown", { "active visible": r.showMenu, error: e.isError, disabled: e.isDisabled }]), onClick: t[11] || (t[11] = (...i) => s.openOptions && s.openOptions(...i)), onFocus: t[12] || (t[12] = (...i) => s.openOptions && s.openOptions(...i)) }, [ D, p("input", { class: "search", autocomplete: "off", disabled: e.isDisabled, tabindex: e.isDisabled ? -1 : 0, id: e.id, name: e.name, value: r.searchText, onInput: t[0] || (t[0] = (i) => r.searchText = i.target.value), ref: "input", onFocus: t[1] || (t[1] = a((...i) => s.openOptions && s.openOptions(...i), ["prevent"])), onKeyup: [ t[2] || (t[2] = u((...i) => s.closeOptions && s.closeOptions(...i), ["esc"])), t[7] || (t[7] = u(a((...i) => s.enterItem && s.enterItem(...i), ["prevent"]), ["enter"])) ], onBlur: t[3] || (t[3] = (...i) => s.blurInput && s.blurInput(...i)), onKeydown: [ t[4] || (t[4] = u((...i) => s.prevItem && s.prevItem(...i), ["up"])), t[5] || (t[5] = u((...i) => s.nextItem && s.nextItem(...i), ["down"])), t[6] || (t[6] = u(a(() => { }, ["prevent"]), ["enter"])), t[8] || (t[8] = u((...i) => s.deleteTextOrItem && s.deleteTextOrItem(...i), ["delete"])) ] }, null, 40, j), p("div", { class: f(["text", s.textClass]), "data-vss-custom-attr": s.searchTextCustomAttr }, x(s.inputText), 11, R), p("div", { class: f(["menu", s.menuClass]), ref: "menu", onMousedown: t[10] || (t[10] = a(() => { }, ["prevent"])), style: O(s.menuStyle), tabindex: "-1" }, [ (m(!0), c(I, null, v(s.filteredOptions, (i, o) => (m(), c("div", { key: o, class: f(["item", { selected: i.selected || r.pointer === o, disabled: i.disabled }]), "data-vss-custom-attr": s.customAttrs[o] ? s.customAttrs[o] : "", onClick: a((h) => s.selectItem(i), ["stop"]), onMousedown: t[9] || (t[9] = (...h) => s.mousedownItem && s.mousedownItem(...h)), onMouseenter: (h) => s.pointerSet(o) }, [ y(e.$slots, "default", { option: i, idx: o }, () => [ g(x(i.text), 1) ]) ], 42, B))), 128)) ], 38) ], 34); } const T = /* @__PURE__ */ V(k, [["render", F]]), q = { name: "ModelListSelect", mixins: [b], emits: ["blur", "searchchange", "update:modelValue"], render: function() { return S(T, { id: this.id, name: this.name, options: this.options, modelValue: this.innerValue, isError: this.isError, isDisabled: this.isDisabled, placeholder: this.placeholder, filterPredicate: this.filterPredicate, onBlur: () => this.$emit("blur"), "onUpdate:modelValue": this.onInput, onSearchchange: (e) => this.$emit("searchchange", e) }); }, props: { modelValue: { type: [String, Number, Object, Boolean] }, list: { type: Array }, optionValue: { type: String }, optionText: { type: String }, customText: { type: Function }, optionDisabled: { type: String } }, computed: { options() { return this.list.map((e) => ({ value: e[this.optionValue], text: this.buildText(e), disabled: !!e[this.optionDisabled] })); }, innerValue() { return this.modelValue ? typeof this.modelValue == "object" ? this.modelValue ? { value: this.modelValue[this.optionValue], text: this.buildText(this.modelValue), disabled: !!this.modelValue[this.optionDisabled] } : { value: "", text: "", disabled: !1 } : this.modelValue : this.modelValue; } }, methods: { buildText(e) { return e[this.optionValue] !== void 0 ? this.customText ? this.customText(e) : e[this.optionText] : ""; }, onInput(e) { if (e === void 0) return this.$emit("update:modelValue", ""); if (Object.keys(e).length === 0 && e.constructor === Object) this.$emit("update:modelValue", e); else if (typeof e == "object") { const t = this.list.find((n) => n[this.optionValue] === e.value); this.$emit("update:modelValue", t); } else this.$emit("update:modelValue", e); } }, components: { ModelSelect: T } }, P = { name: "MultiSelect", mixins: [b], emits: ["blur", "searchchange", "select"], props: { customAttr: { type: Function, default: () => "" }, options: { type: Array }, selectedOptions: { type: Array }, cleanSearch: { type: Boolean, default: !0 }, hideSelectedOptions: { type: Boolean, default: !1 } }, data() { return { showMenu: !1, searchText: "", mousedownState: !1, // mousedown on option menu pointer: -1 }; }, watch: { selectedOptions() { this.pointer = -1; }, filteredOptions() { this.pointerAdjust(); }, searchText() { this.$emit("searchchange", this.searchText); } }, computed: { inputText() { return this.searchText ? "" : this.placeholder; }, textClass() { return this.placeholder ? "default" : ""; }, inputWidth() { return { width: (this.searchText.length + 1) * 8 + 20 + "px" }; }, menuClass() { return { visible: this.showMenu, hidden: !this.showMenu }; }, menuStyle() { return { display: this.showMenu ? "block" : "none" }; }, nonSelectOptions() { return this.options.filter((e) => this.selectedOptions.findIndex((t) => t.value === e.value) === -1); }, filteredOptions() { return this.searchText ? this.nonSelectOptions.filter((e) => { try { return this.cleanSearch ? this.filterPredicate(this.accentsTidy(e.text), this.searchText) : this.filterPredicate(e.text, this.searchText); } catch { return !0; } }) : this.nonSelectOptions; } }, methods: { deleteTextOrLastItem() { !this.searchText && this.selectedOptions.length > 0 && this.deleteItem(this.selectedOptions[this.selectedOptions.length - 1]); }, openOptions() { l.openOptions(this); }, blurInput() { l.blurInput(this); }, closeOptions() { l.closeOptions(this); }, prevItem() { l.prevItem(this), this.openOptions(); }, nextItem() { l.nextItem(this), this.openOptions(); }, enterItem() { l.enterItem(this); }, pointerSet(e) { l.pointerSet(this, e); }, pointerAdjust() { l.pointerAdjust(this); }, mousedownItem() { l.mousedownItem(this); }, selectItem(e) { const t = this.selectedOptions.concat(e), n = t.filter((d, r) => t.indexOf(d) === r); this.closeOptions(), this.searchText = "", this.$emit("select", n, e, "insert"); }, deleteItem(e) { const t = this.selectedOptions.filter((n) => n.value !== e.value); this.$emit("select", t, e, "delete"); }, accentsTidy(e) { let t = e.toString().toLowerCase(); return t = t.replace(new RegExp("[àáâãäå]", "g"), "a"), t = t.replace(new RegExp("æ", "g"), "ae"), t = t.replace(new RegExp("ç", "g"), "c"), t = t.replace(new RegExp("[èéêë]", "g"), "e"), t = t.replace(new RegExp("[ìíîï]", "g"), "i"), t = t.replace(new RegExp("ñ", "g"), "n"), t = t.replace(new RegExp("[òóôõö]", "g"), "o"), t = t.replace(new RegExp("œ", "g"), "oe"), t = t.replace(new RegExp("[ùúûü]", "g"), "u"), t = t.replace(new RegExp("[ýÿ]", "g"), "y"), t; } } }, L = /* @__PURE__ */ p("i", { class: "dropdown icon" }, null, -1), H = ["data-vss-custom-attr"], K = ["onClick"], N = ["disabled", "tabindex", "id", "name"], z = ["data-vss-custom-attr", "onClick", "onMouseenter"]; function U(e, t, n, d, r, s) { return m(), c("div", { class: f(["ui fluid search dropdown selection multiple", { "active visible": r.showMenu, error: e.isError, disabled: e.isDisabled }]), onClick: t[11] || (t[11] = (...i) => s.openOptions && s.openOptions(...i)), onFocus: t[12] || (t[12] = (...i) => s.openOptions && s.openOptions(...i)) }, [ L, n.hideSelectedOptions ? M("", !0) : (m(!0), c(I, { key: 0 }, v(n.selectedOptions, (i, o) => (m(), c("a", { key: o, class: "ui label transition visible", style: { display: "inline-block !important" }, "data-vss-custom-attr": n.customAttr(i) }, [ y(e.$slots, "selected", { option: i, idx: o }, () => [ g(x(i.text), 1), p("i", { class: "delete icon", onClick: (h) => s.deleteItem(i) }, null, 8, K) ]) ], 8, H))), 128)), A(p("input", { class: "search", autocomplete: "off", disabled: e.isDisabled, tabindex: e.isDisabled ? -1 : 0, id: e.id, name: e.name, "onUpdate:modelValue": t[0] || (t[0] = (i) => r.searchText = i), ref: "input", style: O(s.inputWidth), onFocus: t[1] || (t[1] = a((...i) => s.openOptions && s.openOptions(...i), ["prevent"])), onKeyup: [ t[2] || (t[2] = u((...i) => s.closeOptions && s.closeOptions(...i), ["esc"])), t[7] || (t[7] = u(a((...i) => s.enterItem && s.enterItem(...i), ["prevent"]), ["enter"])) ], onBlur: t[3] || (t[3] = (...i) => s.blurInput && s.blurInput(...i)), onKeydown: [ t[4] || (t[4] = u((...i) => s.prevItem && s.prevItem(...i), ["up"])), t[5] || (t[5] = u((...i) => s.nextItem && s.nextItem(...i), ["down"])), t[6] || (t[6] = u(a(() => { }, ["prevent"]), ["enter"])), t[8] || (t[8] = u((...i) => s.deleteTextOrLastItem && s.deleteTextOrLastItem(...i), ["delete"])) ] }, null, 44, N), [ [C, r.searchText] ]), p("div", { class: f(["text", s.textClass]) }, x(s.inputText), 3), p("div", { class: f(["menu", s.menuClass]), ref: "menu", onMousedown: t[10] || (t[10] = a(() => { }, ["prevent"])), style: O(s.menuStyle), tabindex: "-1" }, [ (m(!0), c(I, null, v(s.filteredOptions, (i, o) => (m(), c("div", { key: o, class: f(["item", { selected: i.selected || r.pointer === o, disabled: i.disabled }]), "data-vss-custom-attr": n.customAttr(i), onClick: a((h) => s.selectItem(i), ["stop"]), onMousedown: t[9] || (t[9] = (...h) => s.mousedownItem && s.mousedownItem(...h)), onMouseenter: (h) => s.pointerSet(o) }, [ y(e.$slots, "default", { option: i, idx: o }, () => [ g(x(i.text), 1) ]) ], 42, z))), 128)) ], 38) ], 34); } const w = /* @__PURE__ */ V(P, [["render", U]]), G = { name: "MultiListSelect", mixins: [b], emits: ["blur", "searchchange", "select"], render: function() { return S(w, { id: this.id, name: this.name, options: this.options, selectedOptions: this.items, isError: this.isError, isDisabled: this.isDisabled, placeholder: this.placeholder, filterPredicate: this.filterPredicate, onSelect: this.onSelect, onSearchchange: (e) => this.$emit("searchchange", e) }); }, props: { list: { type: Array }, optionValue: { type: String }, optionText: { type: String }, customText: { type: Function }, selectedItems: { type: Array }, optionDisabled: { type: String } }, computed: { options() { return this.list.map((e) => ({ value: e[this.optionValue], text: this.buildText(e), disabled: !!e[this.optionDisabled] })); }, items() { return this.selectedItems.map((e) => ({ value: e[this.optionValue], text: this.buildText(e), disabled: !!e[this.optionDisabled] })); } }, methods: { buildText(e) { return e[this.optionValue] !== void 0 ? this.customText ? this.customText(e) : e[this.optionText] : ""; }, onSelect(e, t) { if (Object.keys(t).length === 0 && t.constructor === Object) this.$emit("select", e, t); else { const n = this.list.filter((r, s) => e.find((i, o) => r[this.optionValue] === i.value)), d = this.list.find((r) => r[this.optionValue] === t.value); this.$emit("select", n, d); } } }, components: { MultiSelect: w } }; export { q as ModelListSelect, T as ModelSelect, G as MultiListSelect, w as MultiSelect };