Newer
Older
gnexus-ui-kit / src / vue / utils.js
@Eugene Sukhodolskiy Eugene Sukhodolskiy 18 hours ago 1 KB Harden Vue adapter accessibility behavior
import { h } from "vue";

export const variants = new Set([
	"primary",
	"secondary",
	"accent",
	"success",
	"warning",
	"danger",
	"error",
	"info"
]);

export function cx(...items) {
	return items
		.flatMap(item => {
			if(!item) {
				return [];
			}

			if(Array.isArray(item)) {
				return item;
			}

			if(typeof item === "object") {
				return Object.entries(item)
					.filter(([, enabled]) => enabled)
					.map(([name]) => name);
			}

			return [item];
		})
		.filter(Boolean)
		.join(" ");
}

export function normalizeVariant(value, fallback = "primary") {
	return variants.has(value) ? value : fallback;
}

export function iconNode(icon, extraClass = "") {
	if(!icon) {
		return null;
	}

	const iconClass = icon.includes("ph ") || icon.startsWith("ph-")
		? icon
		: `ph ${icon}`;

	return h("i", {
		class: cx(iconClass, extraClass),
		"aria-hidden": "true"
	});
}

export function slotOrText(slots, name, text) {
	return slots[name] ? slots[name]() : text;
}

export function eventValue(event) {
	const target = event.target;

	if(target.type === "checkbox") {
		return target.checked;
	}

	return target.value;
}

export const focusableSelector = [
	"a[href]",
	"button:not([disabled])",
	"input:not([disabled])",
	"select:not([disabled])",
	"textarea:not([disabled])",
	"[tabindex]:not([tabindex='-1'])"
].join(",");

export function trapFocus(event, root) {
	if(event.key !== "Tab" || !root) {
		return;
	}

	const focusable = [...root.querySelectorAll(focusableSelector)]
		.filter(node => !node.hasAttribute("disabled") && node.offsetParent !== null);

	if(!focusable.length) {
		event.preventDefault();
		root.focus();
		return;
	}

	const first = focusable[0];
	const last = focusable[focusable.length - 1];

	if(event.shiftKey && document.activeElement === first) {
		event.preventDefault();
		last.focus();
	} else if(!event.shiftKey && document.activeElement === last) {
		event.preventDefault();
		first.focus();
	}
}