import { h } from "vue";
import VmkIcon from "./components/Icon.js";
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;
}
const SIZE_MAP = {
xxs: "btn-xxs",
xs: "btn-xs",
sm: "btn-sm",
md: "btn-md",
lg: "btn-lg"
};
export function normalizeSize(value, fallback = "btn-md") {
return SIZE_MAP[value] || fallback;
}
export const inputVariants = new Set(["error", "success", "warning"]);
export function normalizeInputState(value, fallback = "") {
return inputVariants.has(value) ? value : fallback;
}
export function eventValue(event) {
const target = event.target;
if (target.type === "checkbox") {
return target.checked;
}
return target.value;
}
/**
* Keep keyboard focus inside a modal/drawer container when Tab is pressed.
*/
export function trapFocus(event, container) {
if (!container || event.key !== "Tab") return;
const focusable = Array.from(
container.querySelectorAll(
'a[href], button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
)
).filter(el => el.offsetParent !== null);
if (focusable.length === 0) {
event.preventDefault();
return;
}
const first = focusable[0];
const last = focusable[focusable.length - 1];
const active = document.activeElement;
if (event.shiftKey) {
if (active === first || !container.contains(active)) {
event.preventDefault();
last.focus();
}
} else {
if (active === last || !container.contains(active)) {
event.preventDefault();
first.focus();
}
}
}
const PHOSPHOR_TO_VMK = {
spinner: "essentials/loading",
loader: "essentials/loading",
loading: "essentials/loading",
"arrow-right": "arrows/arrow/right",
"arrow-left": "arrows/arrow/left",
"arrow-up": "arrows/arrow/up",
"arrow-down": "arrows/arrow/down",
"chevron-right": "arrows/chevron/right",
"chevron-left": "arrows/chevron/left",
"chevron-up": "arrows/chevron/up",
"chevron-down": "arrows/chevron/down",
plus: "essentials/plus",
minus: "essentials/minus",
x: "essentials/close-cross",
close: "essentials/close-cross",
check: "essentials/check",
user: "essentials/user",
trash: "essentials/trash",
information: "essentials/information/circle",
info: "essentials/information/circle",
alert: "essentials/alert-sign",
warning: "essentials/alert-sign",
danger: "essentials/alert/circle",
error: "essentials/alert/circle",
success: "essentials/check/circle"
};
const PHOSPHOR_PREFIX_RE = /^ph[-\s]/;
export function iconNode(icon, extraClass = "") {
if (!icon) {
return null;
}
let name = icon.trim();
// Accept legacy Phosphor prefixes (ph-plus, ph bold ph-spinner, etc).
if (PHOSPHOR_PREFIX_RE.test(name)) {
name = name.slice(3).trim();
}
// If the name already looks like a VMK key, use it directly.
if (!name.includes("/")) {
name = PHOSPHOR_TO_VMK[name] || `essentials/${name}`;
}
return h(VmkIcon, {
name,
class: extraClass
});
}