UNPKG

@aotearoan/neon

Version:

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

195 lines (194 loc) 6.25 kB
import { defineComponent as B, useAttrs as L, ref as u, computed as c, onMounted as P, onUnmounted as D, watch as K } from "vue"; import { NeonSize as z } from "../../../common/enums/NeonSize.es.js"; import { NeonFunctionalColor as C } from "../../../common/enums/NeonFunctionalColor.es.js"; import E from "../../presentation/dropdown/NeonDropdown.vue.es.js"; import T from "../../presentation/icon/NeonIcon.vue.es.js"; import U from "../switch/NeonSwitch.vue.es.js"; import { NeonDropdownPlacement as s } from "../../../common/enums/NeonDropdownPlacement.es.js"; import { NeonScrollUtils as _ } from "../../../common/utils/NeonScrollUtils.es.js"; const W = B({ name: "NeonSelect", components: { NeonDropdown: E, NeonIcon: T, NeonSwitch: U }, 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: z.Medium }, /** * The color of the select. */ color: { type: String, default: C.LowContrast }, /** * Placement of the dropdown contents. */ placement: { type: String, default: s.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 = L(), y = u(null), r = u(!1), p = u(t.placement), d = u(null), a = u(-1), n = c(() => { 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 (p.value) { case s.TopLeft: case s.TopRight: case s.LeftBottom: case s.RightBottom: return !0; } return !1; }, V = () => { var l; const e = (l = y.value) == null ? void 0 : l.querySelector(".neon-select__option--highlighted"); e && _.scrollIntoView(e); }, v = (e, l) => { const o = a.value + e; o >= 0 && o <= n.value.length - 1 && (a.value = o, d.value = n.value[a.value].key, l.preventDefault(), setTimeout(V)); }, f = (e) => { k("update:modelValue", e); }, g = (e) => { if (t.multiple) { const l = [...t.modelValue], o = l.findIndex((m) => m === 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)); }, h = (e) => { if (r.value) switch (e.code) { case "ArrowUp": case "ArrowDown": { const l = S() ? -1 : 1; e.code === "ArrowUp" ? v(-1 * l, e) : v(1 * l, e); } break; case "Enter": case "Space": n.value[a.value].disabled || (g(n.value[a.value]), e.preventDefault()); break; case "Tab": !e.ctrlKey && !e.metaKey && !e.altKey && (r.value = !1); break; } }, O = c(() => t.groupedOptions || [ { group: "", options: t.options || [] } ]), b = c(() => { const { ...e } = w; return e; }), A = c(() => { 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; }), I = c(() => { if (t.modelValue) { const e = n.value.find((l) => l.key === t.modelValue); if (e) return e.icon; } return t.placeholderIcon; }), N = (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), m = t.multiple ? o.map((i) => i.key) : o[0].key; f(m); }, q = (e) => { d.value = e, a.value = n.value.findIndex((l) => l.key === e); }, x = (e) => { p.value = e; }; return P(() => { document.addEventListener("keydown", h); }), D(() => { document.removeEventListener("keydown", h); }), K( () => r.value, (e) => { e && (d.value = n.value[0].key, a.value = 0); } ), { dropdown: y, open: r, highlightedKey: d, highlightedIndex: a, flattenedOptions: n, computedLabel: A, sanitizedAttributes: b, computedOptions: O, computedIcon: I, clickOption: g, nativeSelectChange: N, changeHighlighted: q, onPlacement: x }; } }); export { W as default }; //# sourceMappingURL=NeonSelect.es.js.map