@aotearoan/neon
Version:
Neon is a lightweight design library of Vue 3 components with minimal dependencies.
182 lines (181 loc) • 6.65 kB
JavaScript
import { defineComponent as O, useAttrs as T, ref as l, watch as b, onMounted as _, onUnmounted as z, computed as f } from "vue";
import { NeonSize as K } from "../../../model/common/size/NeonSize.es.js";
import { NeonFunctionalColor as P } from "../../../model/common/color/NeonFunctionalColor.es.js";
import U from "../../presentation/dropdown/NeonDropdown.vue.es.js";
import q from "../../presentation/icon/NeonIcon.vue.es.js";
import F from "../input/NeonInput.vue.es.js";
import M from "../chip/NeonChip.vue.es.js";
import { NeonDropdownPlacement as u } from "../../../model/presentation/dropdown/NeonDropdownPlacement.es.js";
import { NeonScrollUtils as R } from "../../../utils/common/dom/NeonScrollUtils.es.js";
import { NeonInputMode as H } from "../../../model/user-input/input/NeonInputMode.es.js";
const te = O({
name: "NeonSearch",
components: {
NeonChip: M,
NeonDropdown: U,
NeonIcon: q,
NeonInput: F
},
props: {
/**
* The selected model value(s). In the case of single select this should be set to a single NeonSearchOption or null.
* In the case of multiple selection (multiple=true) pass an Array of selected NeonSearchOptions or an empty array
* if nothing is selected.
*/
modelValue: { type: [Object, Array] },
/**
* Placeholder to display in search input when there is no search string entered.
*/
placeholder: { type: String, required: !0 },
/**
* The list of search results.
*/
options: { type: Array, required: !0 },
/**
* Allow multi-select.
*/
multiple: { type: Boolean, default: !1 },
/**
* Disable the search
*/
disabled: { type: Boolean, default: !1 },
/**
* The size of the dropdown - Small, Medium or Large.
*/
size: { type: String, default: K.Medium },
/**
* The color of the search.
*/
color: { type: String, default: P.Primary },
/**
* The HTML autocomplete mode as specified <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete#values">here</a>.
* NOTE: No enum is provided in Neon as some values can be used in combination, please refer to the full list of values in the preceding link.
*/
autocomplete: { type: String, default: "on" },
/**
* The HTML input mode as specified <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode">here</a>.
* This can be used to simplify populating the filter field, e.g. providing the user's country from their address.
*/
inputmode: { type: String, default: H.Text },
/**
* Placement of the dropdown contents.
*/
placement: { type: String, default: u.BottomLeft }
},
emits: [
/**
* @type {NeonSearchOption | NeonSearchOption[] | null} either the selected option (single select) or an array of
* the selected options (multi-select). In the case nothing is selected in single select mode <null> is returned &
* for multiple selection an empty array is returned.
*/
"update:modelValue",
/**
* emitted when the user types in filter box.
* @type {string} the current filter criteria. This can be used by the application to filter the displayed options.
*/
"filter-changed"
],
setup(t, { emit: y }) {
var S;
const I = T(), h = l(null), p = l(null), d = l(t.placement), i = l(!1), c = l(null), a = l(-1), r = l(!t.multiple && ((S = t.modelValue) == null ? void 0 : S.label) || "");
b(
() => i.value,
(e) => {
e && t.options.length > 0 && (c.value = t.options[0].key, a.value = 0);
}
), b(
() => t.modelValue,
(e) => {
t.multiple || (r.value = (e == null ? void 0 : e.label) || "");
}
);
const N = () => {
switch (d.value) {
case u.TopLeft:
case u.TopRight:
case u.LeftBottom:
case u.RightBottom:
return !0;
}
return !1;
}, A = () => {
var n, o;
const e = (o = (n = h.value) == null ? void 0 : n.dropdownContent) == null ? void 0 : o.querySelector(
".neon-search__option--highlighted"
);
e && (e.focus(), R.scrollIntoView(e));
}, g = (e, n) => {
const o = a.value + e;
o >= 0 && o <= t.options.length - 1 && (a.value = o, c.value = t.options[a.value].key, n.preventDefault(), setTimeout(A));
}, s = (e) => {
y("update:modelValue", e);
}, v = (e) => {
!t.multiple && t.modelValue && s(null), r.value = e, y("filter-changed", e);
}, w = (e) => {
if (t.multiple) {
const n = t.modelValue.map((m) => m), o = n.findIndex((m) => m.key === e.key);
o >= 0 ? n.splice(o, 1) : n.push(e), s(n);
} else
s(e);
v(t.multiple ? "" : e.label.toString());
}, k = (e) => {
var n;
if (i.value)
switch (e.code) {
case "ArrowUp":
case "ArrowDown":
{
const o = N() ? -1 : 1;
e.code === "ArrowUp" ? g(-1 * o, e) : g(1 * o, e);
}
break;
case "Enter":
case "Space":
e.target.classList.contains("neon-search__input") || (w(t.options[a.value]), e.preventDefault());
break;
case "Tab":
document.activeElement !== ((n = p.value) == null ? void 0 : n.neonInput) && !e.ctrlKey && !e.metaKey && !e.altKey && (i.value = !1);
break;
}
}, V = (e) => {
d.value = e;
};
_(() => {
document.addEventListener("keydown", k);
}), z(() => {
document.removeEventListener("keydown", k);
});
const x = f(() => {
const { onFilterChanged: e, ...n } = I;
return n;
}), B = (e) => {
c.value = e, a.value = t.options.findIndex((n) => n.key === e);
}, C = () => i.value = !0, D = (e) => s(t.modelValue.filter((n) => n.key !== e.key)), L = f(() => t.multiple ? t.options : t.options.filter((e) => e.label !== r.value)), E = f(
() => {
var e;
return t.multiple && Array.isArray(t.modelValue) ? t.modelValue[0] && t.modelValue[0].key : ((e = t.modelValue) == null ? void 0 : e.key) || null;
}
);
return {
dropdown: h,
searchInput: p,
open: i,
highlightedKey: c,
filter: r,
sanitizedAttributes: x,
computedOptions: L,
dropdownPlacement: d,
onPlacement: V,
onFilterChange: v,
clickOption: w,
changeHighlighted: B,
showOptions: C,
removeSelected: D,
activeDescendant: E
};
}
});
export {
te as default
};
//# sourceMappingURL=NeonSearch.es.js.map