@morpheme/autocomplete
Version:
Morpheme Autocomplete
378 lines (377 loc) • 13.7 kB
JavaScript
import { defineComponent as R, toRefs as K, ref as E, watch as L, computed as N, openBlock as a, createBlock as V, unref as t, isRef as Q, normalizeClass as c, withCtx as n, createTextVNode as g, toDisplayString as h, createCommentVNode as m, createElementVNode as y, createVNode as u, createElementBlock as d, Transition as z, Fragment as S, renderList as A, renderSlot as C, normalizeProps as I, guardReactiveProps as F, mergeProps as M } from "vue";
import { Combobox as O, ComboboxLabel as U, ComboboxInput as j, ComboboxButton as G, ComboboxOptions as H, ComboboxOption as J } from "@headlessui/vue";
import P, { Icon as D } from "@morpheme/icon";
import { useFormValue as W } from "@morpheme/forms";
import X from "@morpheme/badge";
const Y = { class: "autocomplete-body" }, Z = { class: "autocomplete-clearable" }, _ = ["disabled"], x = {
key: 0,
class: "autocomplete-empty"
}, ee = {
key: 0,
class: "autocomplete-item-selected"
}, le = {
key: 1,
class: "autocomplete-hint"
}, ye = /* @__PURE__ */ R({
__name: "VAutocomplete",
props: {
modelValue: { default: void 0 },
searchBy: { default: "text" },
displayText: { default: "text" },
placeholder: { default: "Search..." },
label: { default: "" },
items: { default: () => [] },
name: { default: "" },
rules: { default: "" },
notFoundText: {},
noDataText: { default: "No data." },
clearable: { type: Boolean, default: !1 },
errorClass: { default: "autocomplete-error" },
wrapperClass: { default: "" },
validationMode: { default: "aggressive" },
disabled: { type: Boolean },
hideError: { type: Boolean },
hint: {},
shadow: { type: Boolean },
readonly: { type: Boolean },
error: { type: Boolean },
transition: { default: "fade" }
},
emits: ["update:modelValue", "update:query", "clear"],
setup($, { emit: k }) {
const i = $, { errorMessage: o, uncontrolledValue: p, clear: B } = W(i, k), { items: T } = K(i), b = E("");
L(b, (l) => k("update:query", l));
const w = N(
() => b.value === "" ? T.value : T.value.filter(
(l) => String(l[i.searchBy]).toLowerCase().replace(/\s+/g, "").includes(b.value.toLowerCase().replace(/\s+/g, ""))
)
), e = () => {
b.value = "", B();
};
return (l, s) => (a(), V(t(O), {
modelValue: t(p),
"onUpdate:modelValue": s[1] || (s[1] = (r) => Q(p) ? p.value = r : null),
class: c(["autocomplete", [
l.wrapperClass,
{
"autocomplete--error": !!t(o) || l.error,
"autocomplete--selected": !!t(p),
"autocomplete--disabled": l.disabled,
"autocomplete--readonly": l.readonly,
"autocomplete--shadow": l.shadow
}
]]),
as: "div"
}, {
default: n(() => [
l.label ? (a(), V(t(U), {
key: 0,
class: "autocomplete-label"
}, {
default: n(() => [
g(h(l.label), 1)
]),
_: 1
})) : m("", !0),
y("div", Y, [
y("div", {
class: c(["autocomplete-field", {
"autocomplete-field--error": !!t(o) || l.error
}])
}, [
u(t(j), {
class: c(["autocomplete-input", {
"autocomplete-input--selected": !!t(p)
}]),
"display-value": (r) => r?.[l.displayText] || "",
placeholder: l.placeholder,
disabled: l.disabled,
onChange: s[0] || (s[0] = (r) => b.value = r.target.value)
}, null, 8, ["class", "display-value", "placeholder", "disabled"]),
y("div", Z, [
l.clearable && t(p) ? (a(), d("button", {
key: 0,
type: "button",
"aria-label": "Clear",
class: "autocomplete-clearable-button",
disabled: l.disabled,
onClick: e
}, [
u(t(D), {
name: "heroicons:x-mark",
class: "autocomplete-icon",
"aria-hidden": "true"
})
], 8, _)) : m("", !0),
u(t(G), { disabled: l.disabled }, {
default: n(() => [
u(t(D), {
name: "heroicons:chevron-down",
class: "autocomplete-icon",
"aria-hidden": "true"
})
]),
_: 1
}, 8, ["disabled"])
])
], 2),
u(z, { name: l.transition }, {
default: n(() => [
u(t(H), { class: "autocomplete-options" }, {
default: n(() => [
w.value.length === 0 ? (a(), d("div", x, h(l.noDataText), 1)) : m("", !0),
(a(!0), d(S, null, A(w.value, (r, v) => (a(), V(t(J), {
key: v,
as: "template",
value: r
}, {
default: n(({ selected: f, active: q }) => [
y("li", {
class: c(["autocomplete-item", {
"autocomplete-item--active": q,
"autocomplete-item--inactive": !q
}])
}, [
y("span", {
class: c(["autocomplete-item-text", {
"autocomplete-item-text--selected": f
}])
}, h(r[l.displayText]), 3),
f ? (a(), d("span", ee, [
u(t(D), {
name: "heroicons:check",
class: "autocomplete-item-selected-icon",
"aria-hidden": "true"
})
])) : m("", !0)
], 2)
]),
_: 2
}, 1032, ["value"]))), 128))
]),
_: 1
})
]),
_: 1
}, 8, ["name"])
]),
l.hint ? (a(), d("p", le, [
C(l.$slots, "hint", {}, () => [
g(h(l.hint), 1)
])
])) : m("", !0),
t(o) && !l.hideError ? (a(), d("div", {
key: 2,
class: c(l.errorClass)
}, h(t(o)), 3)) : m("", !0)
]),
_: 3
}, 8, ["modelValue", "class"]));
}
}), te = { class: "autocomplete-body" }, ae = {
key: 0,
class: "autocomplete-selection"
}, oe = { class: "autocomplete-clearable" }, se = ["disabled"], re = {
key: 0,
class: "autocomplete-empty"
}, ue = {
key: 0,
class: "autocomplete-item-selected"
}, de = {
key: 1,
class: "autocomplete-hint"
}, ie = {
key: 2,
class: "autocomplete-error"
}, be = /* @__PURE__ */ R({
__name: "Autocomplete",
props: {
modelValue: {},
items: {},
multiple: { type: Boolean },
itemText: { default: "text" },
itemValue: { default: "value" },
placeholder: { default: "Search..." },
label: {},
transition: { default: "dropdown" },
error: { type: Boolean },
disabled: { type: Boolean },
clearable: { type: Boolean },
emptyText: { default: "No results." },
searchBy: {},
displayValue: {},
selectionItemProps: {},
readonly: { type: Boolean },
shadow: { type: Boolean },
hint: {},
errorMessage: {},
hideError: { type: Boolean }
},
emits: ["update:modelValue", "clear"],
setup($, { emit: k }) {
const i = $, o = E(i.modelValue);
L(
() => i.modelValue,
(e) => {
o.value = e;
},
{ immediate: !0, deep: !0 }
), L(
o,
(e) => {
k("update:modelValue", e);
},
{ deep: !0 }
);
const p = E(""), B = N(
() => p.value === "" ? i.items : i.items.filter(
(e) => String(e[i.searchBy || i.itemText || i.itemValue]).toLowerCase().replace(/\s+/g, "").includes(p.value.toLowerCase().replace(/\s+/g, ""))
)
), T = () => {
p.value = "", o.value = void 0, k("clear");
}, b = (e) => e?.[i.itemText] || "", w = N(() => i.displayValue ?? b);
return (e, l) => (a(), V(t(O), {
modelValue: o.value,
"onUpdate:modelValue": l[1] || (l[1] = (s) => o.value = s),
as: "div",
class: c(["autocomplete autocomplete-primary", {
"autocomplete--error": e.error,
"autocomplete--selected": !!o.value,
"autocomplete--disabled": e.disabled,
"autocomplete--readonly": e.readonly,
"autocomplete--shadow": e.shadow
}]),
multiple: e.multiple
}, {
default: n(() => [
e.label ? (a(), V(t(U), {
key: 0,
class: "autocomplete-label"
}, {
default: n(() => [
g(h(e.label), 1)
]),
_: 1
})) : m("", !0),
y("div", te, [
y("div", {
class: c(["autocomplete-field", {
"autocomplete-field--error": e.error
}])
}, [
C(e.$slots, "selection", I(F({ selected: o.value, multiple: e.multiple, itemValue: e.itemValue, itemText: e.itemText, selectionItemProps: e.selectionItemProps })), () => [
e.multiple && o.value && o.value.length > 0 ? (a(), d("div", ae, [
(a(!0), d(S, null, A(o.value, (s, r) => C(e.$slots, "selection-item", I(M({ key: r }, {
item: s,
idx: r,
itemText: e.itemText,
itemValue: e.itemValue,
remove: () => o.value?.splice(r, 1)
})), () => [
u(t(X), M({
color: "primary",
dismissable: "",
onDismiss: (v) => o.value.splice(r, 1)
}, e.selectionItemProps), {
default: n(() => [
g(h(s[e.itemText]), 1)
]),
_: 2
}, 1040, ["onDismiss"])
])), 128))
])) : m("", !0)
]),
u(t(j), {
class: c(["autocomplete-input", {
"autocomplete-input--selected": !!o.value
}]),
"display-value": w.value ?? b,
placeholder: e.placeholder,
disabled: e.disabled,
onChange: l[0] || (l[0] = (s) => p.value = s.target.value)
}, null, 8, ["class", "display-value", "placeholder", "disabled"]),
y("div", oe, [
e.clearable && o.value ? (a(), d("button", {
key: 0,
type: "button",
"aria-label": "Clear",
class: "autocomplete-clearable-button",
disabled: e.disabled,
onClick: T
}, [
u(t(P), {
name: "heroicons:x-mark",
class: "autocomplete-icon",
"aria-hidden": "true"
})
], 8, se)) : m("", !0),
u(t(G), { disabled: e.disabled }, {
default: n(() => [
u(t(P), {
name: "heroicons:chevron-down",
class: "autocomplete-icon",
"aria-hidden": "true"
})
]),
_: 1
}, 8, ["disabled"])
])
], 2),
u(z, { name: e.transition }, {
default: n(() => [
u(t(H), { class: "autocomplete-options" }, {
default: n(() => [
B.value.length === 0 ? (a(), d("div", re, h(e.emptyText), 1)) : m("", !0),
(a(!0), d(S, null, A(B.value, (s, r) => (a(), V(t(J), {
key: r,
as: "template",
value: s
}, {
default: n(({ selected: v, active: f }) => [
C(e.$slots, "item", I(F({ item: s, active: f, selected: v, itemText: e.itemText, itemValue: e.itemValue })), () => [
y("li", {
class: c(["autocomplete-item", {
"autocomplete-item--active": f,
"autocomplete-item--inactive": !f
}])
}, [
y("span", {
class: c(["autocomplete-item-text", {
"autocomplete-item-text--selected": v
}])
}, h(s[e.itemText]), 3),
v ? (a(), d("span", ue, [
u(t(P), {
name: "heroicons:check",
class: "autocomplete-item-selected-icon",
"aria-hidden": "true"
})
])) : m("", !0)
], 2)
])
]),
_: 2
}, 1032, ["value"]))), 128))
]),
_: 3
})
]),
_: 3
}, 8, ["name"])
]),
e.hint ? (a(), d("div", de, [
C(e.$slots, "hint", {}, () => [
g(h(e.hint), 1)
])
])) : m("", !0),
e.error && !e.hideError ? (a(), d("div", ie, h(e.errorMessage), 1)) : m("", !0)
]),
_: 3
}, 8, ["modelValue", "multiple", "class"]));
}
});
export {
be as Autocomplete,
ye as VAutocomplete,
ye as default
};