UNPKG

@aotearoan/neon

Version:

Neon is a lightweight design library of Vue 3 components with minimal dependencies.

202 lines (201 loc) 6.67 kB
import { defineComponent as B, useAttrs as D, ref as d, computed as u, onMounted as L, onUnmounted as K, watch as z } from "vue"; import { NeonSize as C } from "../../../model/common/size/NeonSize.es.js"; import { NeonFunctionalColor as E } from "../../../model/common/color/NeonFunctionalColor.es.js"; import T from "../../presentation/dropdown/NeonDropdown.vue.es.js"; import U from "../../presentation/icon/NeonIcon.vue.es.js"; import _ from "../switch/NeonSwitch.vue.es.js"; import { NeonDropdownPlacement as c } from "../../../model/presentation/dropdown/NeonDropdownPlacement.es.js"; import { NeonScrollUtils as M } from "../../../utils/common/dom/NeonScrollUtils.es.js"; import { NeonDropdownStyle as R } from "../../../model/presentation/dropdown/NeonDropdownStyle.es.js"; const Z = B({ name: "NeonSelect", components: { NeonDropdown: T, NeonIcon: U, NeonSwitch: _ }, props: { /** * Id for the dropdown button */ id: { type: String }, /** * Placeholder to display as button label when there is no option selected. */ placeholder: { type: String, required: !0 }, /** * Display the placeholder as the first option in the select, this is useful as an alternative to a label. */ placeholderAsOption: { type: Boolean, default: !1 }, /** * Optional placeholder icon. */ placeholderIcon: { type: String, required: !1 }, /** * A list of options to render in the select. */ options: { type: Array, required: !1 }, /** * A list of grouped options to render in the select. */ groupedOptions: { type: Array, required: !1 }, /** * Either a single string, indicating the key of the selected option or an array of selected keys in the case * multiple = true. */ modelValue: { type: [String, Array], required: !0 }, /** * Allow multi-select. */ multiple: { type: Boolean, default: !1 }, /** * Placeholder when multiple values are selected. */ multiselectPlaceholder: { type: String, required: !1 }, /** * Disable the select */ disabled: { type: Boolean, default: !1 }, /** * The size of the dropdown - Small, Medium or Large. */ size: { type: String, default: C.Medium }, /** * The color of the select. */ color: { type: String, default: E.Primary }, /** * The button style of the select. */ buttonStyle: { type: String, default: R.Input }, /** * Placement of the dropdown contents. */ placement: { type: String, default: c.BottomLeft } }, emits: [ /** * emitted when the user changes the selection. * @type {string | string[]} either the selected option's key (single select) or an array of the selected keys * (multi-select). */ "update:modelValue" ], setup(t, { emit: k }) { const w = D(), p = d(null), r = d(!1), g = d(t.placement), s = d(null), a = d(-1), n = u(() => { var e; return t.options ? t.options : t.groupedOptions ? (e = t.groupedOptions) == null ? void 0 : e.flatMap((l) => l.options) : []; }), S = () => { if (!t.groupedOptions) switch (g.value) { case c.TopLeft: case c.TopRight: case c.LeftBottom: case c.RightBottom: return !0; } return !1; }, V = () => { var l, o; const e = (o = (l = p.value) == null ? void 0 : l.dropdownContent) == null ? void 0 : o.querySelector( ".neon-select__option--highlighted" ); e && (e.focus(), M.scrollIntoView(e)); }, m = (e, l) => { const o = a.value + e; o >= 0 && o <= n.value.length - 1 && (a.value = o, s.value = n.value[a.value].key, l == null || l.preventDefault(), setTimeout(V)); }, f = (e) => { k("update:modelValue", e); }, h = (e) => { if (t.multiple) { const l = [...t.modelValue], o = l.findIndex((y) => y === e.key); o >= 0 ? l.splice(o, 1) : l.push(e.key), f(l); } else t.modelValue !== e.key && (r.value = !1, f(e.key)); }, v = (e) => { if (r.value) switch (e.code) { case "ArrowUp": case "ArrowDown": { const l = S() ? -1 : 1; e.code === "ArrowUp" ? m(-1 * l, e) : m(1 * l, e); } break; case "Enter": case "Space": n.value[a.value].disabled || (h(n.value[a.value]), e.preventDefault()); break; case "Tab": !e.ctrlKey && !e.metaKey && !e.altKey && (r.value = !1); break; } }, b = u(() => t.groupedOptions || [ { group: "", options: t.options || [] } ]), I = u(() => { const { ...e } = w; return e; }), O = u(() => { if (t.multiple && t.modelValue.length > 0) { if (t.multiselectPlaceholder) return t.multiselectPlaceholder; if (t.modelValue.length > 1) return `${t.modelValue.length} items selected`; { const e = n.value.find((l) => l.key === t.modelValue[0]); return (e == null ? void 0 : e.label) || ""; } } else if (t.modelValue) { const e = n.value.find((l) => l.key === t.modelValue); if (e) return e.label; } return t.placeholder; }), A = u(() => !t.modelValue || t.modelValue.length === 0), N = u(() => { if (t.modelValue) { const e = n.value.find((l) => l.key === t.modelValue); if (e) return e.icon; } return t.placeholderIcon; }), P = (e) => { const l = Array.from(e.target.options).filter((i) => i.selected).map((i) => i.value), o = n.value.filter((i) => l.indexOf(i.key) >= 0), y = t.multiple ? o.map((i) => i.key) : o[0].key; f(y); }, q = (e) => { s.value = e, a.value = n.value.findIndex((l) => l.key === e); }, x = (e) => { g.value = e; }; return L(() => { document.addEventListener("keydown", v); }), K(() => { document.removeEventListener("keydown", v); }), z( () => r.value, (e) => { e && (s.value = n.value[0].key, a.value = 0, m(a.value)); } ), { dropdown: p, open: r, highlightedKey: s, highlightedIndex: a, flattenedOptions: n, computedLabel: O, sanitizedAttributes: I, computedOptions: b, computedIcon: N, labelIsPlaceholder: A, clickOption: h, nativeSelectChange: P, changeHighlighted: q, onPlacement: x }; } }); export { Z as default }; //# sourceMappingURL=NeonSelect.es.js.map