@aotearoan/neon
Version:
Neon is a lightweight design library of Vue 3 components with minimal dependencies.
202 lines (201 loc) • 6.67 kB
JavaScript
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