@primer/react-brand
Version:
Primer Brand is a GitHub's design system for creating React-based marketing websites and digital experiences.
129 lines (128 loc) • 3.01 kB
JavaScript
import { useId as e } from "./useId.js";
import { useCallback as t, useRef as n, useState as r } from "react";
//#region src/hooks/useTabs.ts
var i = ({ defaultTab: i, autoActivate: a = !0, orientation: o = "horizontal", onTabActivate: s } = {}) => {
let c = e(), [l, u] = r({
activeTab: i || null,
focusedTab: null,
tabs: /* @__PURE__ */ new Set()
}), d = t((e) => {
u((t) => {
let n = e(t);
return n.activeTab && n.activeTab !== t.activeTab && t.activeTab !== null && s?.(n.activeTab, f.current.get(n.activeTab)), n;
});
}, [s]), f = n(/* @__PURE__ */ new Map()), p = t((e) => `tabs-${c}-tab-${e}`, [c]), m = t((e) => `tabs-${c}-panel-${e}`, [c]), h = t((e, t) => {
f.current.has(e) || (f.current.set(e, t), d((t) => ({
...t,
tabs: new Set([...t.tabs, e]),
activeTab: t.activeTab || e
})));
}, [d]), g = t((e) => {
f.current.get(e)?.focus();
}, []), _ = t((e) => {
d((t) => ({
...t,
activeTab: e,
focusedTab: e
}));
}, [d]), v = t((e, t) => (e + 1) % t.length, []), y = t((e, t) => (e - 1 + t.length) % t.length, []), b = t((e, t) => {
let n = [...l.tabs], r = n.indexOf(t);
switch (!0) {
case e.key === "ArrowLeft" && o === "horizontal":
case e.key === "ArrowUp" && o === "vertical": {
e.preventDefault();
let t = n[y(r, n)];
g(t), a && _(t);
break;
}
case e.key === "ArrowRight" && o === "horizontal":
case e.key === "ArrowDown" && o === "vertical": {
e.preventDefault();
let t = n[v(r, n)];
g(t), a && _(t);
break;
}
case e.key === "Home":
e.preventDefault(), g(n[0]), a && _(n[0]);
break;
case e.key === "End":
e.preventDefault(), g(n[n.length - 1]), a && _(n[n.length - 1]);
break;
case e.key === " ":
case e.key === "Enter":
e.preventDefault(), a || _(t);
break;
}
}, [
l.tabs,
o,
y,
g,
a,
_,
v
]), x = t((e) => {
_(e);
}, [_]), S = t((e) => {
d((t) => t.focusedTab === e ? t : {
...t,
focusedTab: e
});
}, [d]), C = t(({ label: e, labelledBy: t }) => ({
role: "tablist",
"aria-orientation": o,
...e && { "aria-label": e },
...t && { "aria-labelledby": t }
}), [o]), w = t((e, t) => ({
role: "tab",
id: p(e),
"aria-controls": m(e),
"aria-selected": e === l.activeTab,
tabIndex: e === l.activeTab ? 0 : -1,
onClick: () => x(e),
onKeyDown: (t) => b(t, e),
onFocus: () => S(e),
ref: (n) => {
if (n && h(e, n), t) {
if (typeof t == "function") {
t(n);
return;
}
if ("current" in t) {
t.current = n;
return;
}
}
}
}), [
l.activeTab,
p,
m,
x,
b,
S,
h
]), T = t((e) => ({
role: "tabpanel",
id: m(e),
"aria-labelledby": p(e),
hidden: e !== l.activeTab,
tabIndex: 0
}), [
l.activeTab,
m,
p
]);
return {
activeTab: l.activeTab,
focusedTab: l.focusedTab,
activateTab: _,
focusTab: g,
getTabListProps: C,
getTabProps: w,
getTabPanelProps: T
};
};
//#endregion
export { i as useTabs };
//# sourceMappingURL=useTabs.js.map