UNPKG

@gits-id/multi-select

Version:

Vue Multi Select Component

461 lines (460 loc) 14.4 kB
import { defineComponent as he, toRefs as Se, ref as p, computed as j, onBeforeUpdate as ke, openBlock as i, createElementBlock as u, Fragment as D, unref as e, normalizeClass as c, toDisplayString as m, createCommentVNode as v, createElementVNode as r, mergeProps as T, renderList as ae, renderSlot as y, createVNode as f, withCtx as h, createTextVNode as E, withKeys as B, withModifiers as V, createBlock as se, toHandlers as Ce, Transition as be, nextTick as we } from "vue"; import R from "@gits-id/badge"; import xe from "@gits-id/tooltip"; import { useDebounceFn as Be, onClickOutside as Ve } from "@vueuse/core"; import { ErrorMessage as Me } from "vee-validate"; import I from "@gits-id/icon"; import { useFormValue as $e } from "@gits-id/forms"; const ze = ["for"], Ae = { class: "v-multi-select-panel" }, De = { class: "v-multi-select-badges" }, Te = ["id", "placeholder", "name", "readonly", "disabled", "onKeydown"], Ee = { class: "v-multi-select-action" }, Ie = /* @__PURE__ */ r("span", null, "Clear", -1), Ne = { key: 0, class: "v-multi-select-item-check" }, Oe = /* @__PURE__ */ r("div", { class: "border-b h-1" }, null, -1), Fe = ["onClick", "onMouseover"], Pe = { class: "v-multi-select-item-text" }, Ke = { key: 1, class: "v-multi-select-hint" }, Le = { inheritAttrs: !1 }, Je = /* @__PURE__ */ he({ ...Le, __name: "VMultiSelect", props: { modelValue: { type: Array, default: () => [] }, items: { type: Array, default: () => [] }, itemText: { type: String, default: "text" }, itemValue: { type: String, default: "value" }, searchBy: { type: [String, Function], default: "text" }, maxBadge: { type: Number, default: 0 }, placeholder: { type: String, default: "Search..." }, delay: { type: Number, default: 500 }, id: { type: String, default: "" }, name: { type: String, default: "" }, inputProps: { type: Object, default: () => ({}) }, selectAll: { type: Boolean, default: !1 }, loading: { type: Boolean, default: !1 }, error: { type: Boolean, default: !1 }, errorMessages: { type: Array, default: () => [] }, wrapperClass: { type: String, default: "" }, inputClass: { type: String, default: "" }, badgeColor: { type: String, default: "primary" }, badgeClass: { type: String, default: "" }, badgeProps: { type: Object, default: () => ({}) }, dropdownClass: { type: String, default: "" }, itemClass: { type: String, default: "" }, checkWrapperClass: { type: String, default: "" }, checkIconClass: { type: String, default: "" }, noDataClass: { type: String, default: "" }, loadingClass: { type: String, default: "" }, label: { type: String, default: "" }, labelClass: { type: String, default: "mb-2 block" }, rules: { type: String, default: "" }, errorClass: { type: String, default: "text-error-600 mt-1 text-sm" }, transition: { type: String, default: "fade" }, iconSize: { type: String, default: "sm" }, readonly: { type: Boolean, default: !1 }, disabled: { type: Boolean, default: !1 }, validationMode: { type: String, default: "aggressive" }, fieldOptions: { type: Object, default: () => ({}) }, hideError: { type: Boolean, default: !1 }, hint: { type: String, default: "" } }, emits: [ "click:outside", "update:modelValue", "search", "selected", "clear" ], setup(l, { emit: S }) { const N = l, { maxBadge: k, items: M, placeholder: ne, id: H, delay: oe, name: O, inputProps: ie, itemText: C, itemValue: F, searchBy: $, selectAll: re, loading: ue, disabled: U, readonly: W } = Se(N), q = p(null), d = p(!1), b = p(""), n = p(-1), P = p([]), K = p(null), { errorMessage: z, uncontrolledValue: o } = $e(N, S, N.fieldOptions), ce = (t, a) => String(t?.[a])?.toLowerCase()?.includes(b.value.toLowerCase()), de = (t) => b.value ? [ typeof $.value == "string" ? $.value : "", C.value, F.value ].filter(Boolean).some((a) => typeof $.value == "function" ? $.value(t, b.value) : ce(t, a)) : !0, L = j(() => M.value.filter(de)), ve = j( () => k.value > 0 ? o.value.slice(0, k.value) : o.value ), fe = (t, a) => { t && (P.value[a] = t); }; ke(() => { P.value = []; }); const G = (t) => { const a = A(t); a > -1 ? o.value.splice(a, 1) : o.value.push(t), S("selected", o); }, A = (t) => o.value?.findIndex( (a) => a[F.value] === t?.[F.value] ), me = (t) => A(t) > -1, J = (t, a) => t.selected || me(t), Q = () => { o.value = [], n.value = -1, S("clear"); }, X = (t) => { const a = A(t); a > -1 && o.value.splice(a, 1); }, Y = Be((t) => { d.value = !0, b.value = t.target.value, n.value = 0, S("search", b); }, oe.value), w = j( () => o.value.length === M.value.length ), Z = () => { w.value ? Q() : M.value.forEach((t) => { A(t) < 0 && o.value.push(t); }); }, _ = () => { !W.value && !U.value && (d.value = !0); }; Ve(q, () => { S("click:outside"), d.value = !1; }); const ye = () => { const t = L.value[n.value]; t && G(t); }, ee = () => { d.value || (d.value = !0), n.value === null ? n.value = 0 : n.value < M.value.length - 1 && n.value++, le(); }, te = () => { d.value || (d.value = !0), n.value === null ? n.value = 0 : n.value === 0 ? n.value = -1 : n.value--, le(); }, ge = (t) => { t.shiftKey ? te() : ee(); }, pe = () => { d.value = !1; }, le = () => { we(() => { const t = n.value, s = P.value[t]?.offsetTop - (K.value.offsetHeight - 100); K.value?.scrollTo({ top: s, behavior: "smooth" }); }); }; return (t, a) => (i(), u(D, null, [ l.label ? (i(), u("label", { key: 0, for: e(H) || e(O), class: c(["v-multi-select-label", l.labelClass]) }, m(l.label), 11, ze)) : v("", !0), r("div", T({ ref_key: "target", ref: q, class: ["v-multi-select", { "v-multi-select--error": l.error || l.errorMessages.length > 0 || !!e(z) }] }, t.$attrs), [ r("div", null, [ r("div", Ae, [ r("div", { class: c(["v-multi-select-input", [ { "v-multi-select-normal": l.error || !!e(z) }, l.wrapperClass ]]), onClick: _ }, [ r("div", De, [ e(o).length ? (i(!0), u(D, { key: 0 }, ae(e(ve), (s, g) => y(t.$slots, "selection", { key: s.value, index: g, item: s, value: s[e(C)], onRemove: () => X(s) }, () => [ f(e(R), T({ color: l.badgeColor, dismissable: "", class: ["truncate", l.badgeClass], onDismiss: (x) => X(s) }, l.badgeProps), { default: h(() => [ E(m(s[e(C)]), 1) ]), _: 2 }, 1040, ["color", "class", "onDismiss"]) ])), 128)) : v("", !0), e(k) > 0 && e(o).length > e(k) ? y(t.$slots, "max-selection", { key: 1 }, () => [ f(e(R), { small: "" }, { default: h(() => [ E(m(e(o).length - e(k)) + " more", 1) ]), _: 1 }) ]) : v("", !0), r("input", T({ id: e(H), type: "text", class: ["v-multi-select-input-control", l.inputClass], autofill: "false", autocomplete: "off", placeholder: e(ne), name: e(O) }, e(ie), { readonly: e(W), disabled: e(U), onInput: a[0] || (a[0] = (...s) => e(Y) && e(Y)(...s)), onFocus: _, onKeydown: [ B(V(ye, ["prevent"]), ["enter"]), B(V(ee, ["prevent"]), ["down"]), B(V(te, ["prevent"]), ["up"]), B(V(ge, ["prevent"]), ["tab"]), B(V(pe, ["prevent"]), ["esc"]) ] }), null, 16, Te) ]), r("div", Ee, [ e(o).length > 1 ? (i(), se(e(xe), { key: 0 }, { activator: h(({ on: s }) => [ f(e(R), T({ circle: "", class: "!p-1 !bg-transparent", onClick: Q }, Ce(s)), { default: h(() => [ f(e(I), { name: "ri:close-line", size: l.iconSize, class: "v-multi-select-icon", "aria-hidden": "true" }, null, 8, ["size"]) ]), _: 2 }, 1040) ]), default: h(() => [ Ie ]), _: 1 })) : v("", !0), f(e(I), { name: "heroicons:chevron-down", size: l.iconSize, class: "v-multi-select-icon", "aria-hidden": "true" }, null, 8, ["size"]) ]) ], 2), f(be, { name: l.transition }, { default: h(() => [ d.value ? (i(), u("div", { key: 0, ref_key: "dropdown", ref: K, class: c(["v-multi-select-dropdown", l.dropdownClass]) }, [ e(ue) ? (i(), u("div", { key: 0, class: c(["v-multi-select-dropdown-loading", l.loadingClass]) }, " Loading... ", 2)) : e(L).length ? (i(), u(D, { key: 1 }, [ e(re) ? y(t.$slots, "select-all", { key: 0, onClick: Z, isSelected: e(w) }, () => [ r("div", { class: "v-multi-select-item", onClick: Z }, [ r("div", { class: c([ e(w) ? "font-medium" : "font-normal", "block truncate" ]) }, m(e(w) ? "Deselect All" : "Select All"), 3), e(w) ? (i(), u("div", Ne, [ f(e(I), { name: "heroicons:check", class: "w-5 h-5", "aria-hidden": "true" }) ])) : v("", !0) ]), Oe ]) : v("", !0), y(t.$slots, "prepend.item"), (i(!0), u(D, null, ae(e(L), (s, g) => (i(), u("div", { key: s.value, ref_for: !0, ref: (x) => fe(x, g), onClick: (x) => G(s), onMouseover: (x) => n.value = g, onMouseout: a[1] || (a[1] = (x) => n.value = -1), class: c(["v-multi-select-item group", [ l.itemClass, { "v-multi-select-item--focused": n.value === g, "v-multi-select-item--active": J(s) } ]]) }, [ r("div", { class: c(["v-multi-select-item-check", l.checkWrapperClass]) }, [ f(e(I), { name: "heroicons:check", size: l.iconSize, class: c(["v-multi-select-check-icon", l.checkIconClass]), "aria-hidden": "true" }, null, 8, ["size", "class"]) ], 2), r("div", Pe, [ y(t.$slots, "item.label", { index: g, item: s, value: s[e(C)], isSelected: J(s) }, () => [ E(m(s[e(C)]), 1) ]) ]) ], 42, Fe))), 128)), y(t.$slots, "append.item") ], 64)) : (i(), u("div", { key: 2, class: c(["pl-6 pr-4 py-2 text-gray-600", l.noDataClass]) }, " No Data ", 2)) ], 2)) : v("", !0) ]), _: 3 }, 8, ["name"]) ]) ]) ], 16), l.hint ? (i(), u("p", Ke, [ y(t.$slots, "hint", {}, () => [ E(m(l.hint), 1) ]) ])) : v("", !0), l.errorMessages.length && !l.hideError ? (i(), se(e(Me), { key: 2, class: "text-error-500 text-sm", name: e(O) }, null, 8, ["name"])) : e(z) ? (i(), u("div", { key: 3, class: c(l.errorClass) }, m(e(z)), 3)) : v("", !0) ], 64)); } }); export { Je as VMultiSelect, Je as default };