@aotearoan/neon
Version:
Neon is a lightweight design library of Vue 3 components with minimal dependencies.
100 lines (99 loc) • 3.6 kB
JavaScript
import { defineComponent as x, ref as o, onMounted as L, nextTick as w, onUnmounted as z } from "vue";
import C from "../link/NeonLink.vue.es.js";
import I from "../dropdown-menu/NeonDropdownMenu.vue.es.js";
import { NeonFunctionalColor as B } from "../../../common/enums/NeonFunctionalColor.es.js";
import { NeonSize as F } from "../../../common/enums/NeonSize.es.js";
import O from "../../presentation/icon/NeonIcon.vue.es.js";
import { useRoute as R } from "vue-router";
const T = x({
name: "NeonMenu",
components: {
NeonDropdownMenu: I,
NeonLink: C,
NeonIcon: O
},
props: {
/**
* The menu configuration. This can have two levels, i.e. a top level horizontal menu and, if required, a dropdown
* menu containing the second level. The highlighted 'active' menu is determined by the current Vue route.
*/
menu: { type: Array, required: !0 },
/**
* The menu highlight color (excludes low-contrast and neutral).
*/
color: { type: String, default: B.Brand },
/**
* The menu size.
*/
size: { type: String, default: F.Large },
/**
* Whether to enable the priority menu which automatically calculates the available screen space and displays
* as many of the menu items as possible, moving the remaining items into the overflow menu.
*/
priorityMenuEnabled: { type: Boolean, default: !0 }
},
emits: [
/**
* Emitted when a user clicks on a menu item.
* @type {string} the key of the menu item clicked.
*/
"click"
],
setup(s, { emit: M }) {
const c = R(), m = o(null), f = o(null), r = o(null), l = o([]), y = o([]), u = o([]), p = (t) => {
const n = window.getComputedStyle(t), e = parseFloat(n.marginLeft || "0") + parseFloat(n.marginRight || "0");
return Math.ceil(t.offsetWidth + e);
}, k = (t, n) => ({
key: t,
element: n,
width: p(n)
}), b = () => {
const t = s.menu.map(
(n, e) => f.value && k(n.key, f.value[e]) || null
);
l.value = t.filter((n) => n !== null);
}, E = (t) => t && (c == null ? void 0 : c.path.indexOf(t)) >= 0, N = (t) => {
M("click", t);
}, S = (t, n, e) => {
if (e.map((i) => i.width).reduce((i, a) => i ? i + a : 0) <= t - n)
return e.map((i) => i.key);
let h = t - n, d = [];
for (let i = 0; i < e.length; i = i + 1) {
const a = e[i];
if (h < a.width) {
i === 1 && (d = d.filter((W) => W !== e[0].key));
break;
}
h = h - a.width, d.push(a.key);
}
return d;
}, v = async () => {
await w();
const t = m.value && p(m.value) || 0, n = r.value && p(r.value) || 0;
u.value = S(t, n, l.value), y.value = s.menu.filter((e) => u.value.indexOf(e.key) < 0).flatMap((e) => [
{ ...e, isGroup: e.children && e.children.length > 0 },
...(e.children || []).map((g) => ({ ...g, grouped: !0 }))
]), l.value.forEach((e) => {
e.element.hidden = u.value.indexOf(e.key) < 0;
}), r.value && (r.value.hidden = l.value.length === u.value.length);
};
return L(async () => {
s.priorityMenuEnabled && (await w(), b(), await v(), window.addEventListener("resize", v));
}), z(() => {
s.priorityMenuEnabled && window.removeEventListener("resize", v);
}), {
menuWrapper: m,
menuItem: f,
menuItems: l,
responsiveButton: r,
responsiveMenuItems: y,
visible: u,
onClick: N,
routeMatches: E
};
}
});
export {
T as default
};
//# sourceMappingURL=NeonMenu.es.js.map