Newer
Older
gnexus-ui-kit / src / vue / components / GnNavList.js
import { computed, defineComponent, h } from "vue";
import { cx, iconNode } from "../utils.js";
import { tryUseRouter, tryUseRoute, isRouteActive } from "../composables/useVueRouter.js";

export default defineComponent({
	name: "GnNavList",
	inheritAttrs: false,
	props: {
		items: { type: Array, default: () => [] },
		activeMatch: { type: String, default: "prefix" }
	},
	emits: ["select"],
	setup(props, { attrs, emit, slots }) {
		const router = tryUseRouter();
		const route = tryUseRoute();
		const hasRouter = Boolean(router && route);

		const resolveHref = to => {
			if(!to) {
				return undefined;
			}

			if(typeof to === "string") {
				return to;
			}

			if(to.path) {
				return to.path;
			}

			return undefined;
		};

		const navItems = computed(() => props.items.map(item => {
			const hasTo = Boolean(item.to);
			const resolvedHref = hasTo
				? (hasRouter ? router.resolve(item.to).href : resolveHref(item.to))
				: item.href;
			const isActive = hasTo && hasRouter
				? isRouteActive(route, item.to, props.activeMatch)
				: Boolean(item.active);

			return {
				...item,
				resolvedHref,
				isActive,
				hasTo
			};
		}));

		return () => h("ul", { ...attrs, class: cx("list list-nav", attrs.class) }, navItems.value.map(item => h("li", {
			class: cx("list-item", { "list-item-active": item.isActive })
		}, [
			h(item.resolvedHref ? "a" : "button", {
				class: "list-action",
				href: item.resolvedHref,
				type: item.resolvedHref ? undefined : "button",
				onClick: event => {
					if(item.hasTo && hasRouter) {
						event.preventDefault();
						router.push(item.to);
					}

					item.onSelect?.(item, event);
					emit("select", item);
				}
			}, [
				h("span", { class: "list-label" }, [
					iconNode(item.icon),
					slots.label?.({ item }) || item.label
				]),
				(item.meta || slots.meta) && h("span", { class: "list-meta" }, slots.meta?.({ item }) || item.meta)
			])
		])));
	}
});