// retoor <retoor@molodetz.nl>
let tabsSeq = 0;
class Tabs {
constructor() {
document.querySelectorAll("[data-tabs]").forEach((root) => this.init(root));
}
init(root) {
const tabs = [...root.querySelectorAll("[data-tab]")];
const panes = [...root.querySelectorAll("[data-tab-pane]")];
if (!tabs.length) return;
const list = tabs[0].parentElement;
if (list && !list.getAttribute("role")) {
list.setAttribute("role", "tablist");
}
const base = `tabs-${tabsSeq++}`;
tabs.forEach((tab, index) => {
const name = tab.dataset.tab;
const pane = panes.find((p) => p.dataset.tabPane === name);
const tabId = tab.id || `${base}-tab-${name}`;
tab.id = tabId;
tab.setAttribute("role", "tab");
if (pane) {
const paneId = pane.id || `${base}-pane-${name}`;
pane.id = paneId;
pane.setAttribute("role", "tabpanel");
pane.setAttribute("aria-labelledby", tabId);
const focusable = pane.querySelector(
"a[href], button, input, select, textarea, [tabindex]"
);
if (!focusable && !pane.hasAttribute("tabindex")) {
pane.setAttribute("tabindex", "0");
}
tab.setAttribute("aria-controls", paneId);
}
});
const show = (name, focusTab) => {
tabs.forEach((tab) => {
const selected = tab.dataset.tab === name;
tab.classList.toggle("active", selected);
tab.setAttribute("aria-selected", selected ? "true" : "false");
tab.setAttribute("tabindex", selected ? "0" : "-1");
if (selected && focusTab) tab.focus();
});
panes.forEach((p) => {
const selected = p.dataset.tabPane === name;
p.classList.toggle("active", selected);
});
};
tabs.forEach((tab, index) => {
tab.addEventListener("click", () => {
show(tab.dataset.tab);
history.replaceState(null, "", "#" + tab.dataset.tab);
});
tab.addEventListener("keydown", (e) => {
let next = null;
if (e.key === "ArrowRight" || e.key === "ArrowDown") next = index + 1;
else if (e.key === "ArrowLeft" || e.key === "ArrowUp") next = index - 1;
else if (e.key === "Home") next = 0;
else if (e.key === "End") next = tabs.length - 1;
if (next === null) return;
e.preventDefault();
const target = tabs[(next + tabs.length) % tabs.length];
show(target.dataset.tab, true);
history.replaceState(null, "", "#" + target.dataset.tab);
});
});
const hash = (location.hash || "").slice(1);
const initial = tabs.some((t) => t.dataset.tab === hash) ? hash : tabs[0].dataset.tab;
show(initial);
}
}
window.Tabs = Tabs;
export { Tabs };