@underverse-ui/underverse 1.0.95 → 1.0.96
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api-reference.json +1 -1
- package/dist/index.cjs +119 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +119 -52
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -6608,6 +6608,32 @@ var variantStyles5 = {
|
|
|
6608
6608
|
inactiveTab: "text-muted-foreground hover:text-foreground"
|
|
6609
6609
|
}
|
|
6610
6610
|
};
|
|
6611
|
+
function getTabsBaseId(tabs) {
|
|
6612
|
+
const key = tabs.map((t) => t.value).join("-");
|
|
6613
|
+
return `tabs-${key || "default"}`;
|
|
6614
|
+
}
|
|
6615
|
+
function getTabTriggerId(baseId, index) {
|
|
6616
|
+
return `${baseId}-tab-${index}`;
|
|
6617
|
+
}
|
|
6618
|
+
function getTabPanelId(baseId, index) {
|
|
6619
|
+
return `${baseId}-panel-${index}`;
|
|
6620
|
+
}
|
|
6621
|
+
function getTabHref(tab, panelId) {
|
|
6622
|
+
return tab.href ?? `#${panelId}`;
|
|
6623
|
+
}
|
|
6624
|
+
function resolveTabValueFromHash(hash, tabs, baseId) {
|
|
6625
|
+
const normalizedHash = hash.replace(/^#/, "");
|
|
6626
|
+
if (!normalizedHash) return null;
|
|
6627
|
+
const matchIndex = tabs.findIndex((tab, index) => {
|
|
6628
|
+
const tabId = getTabTriggerId(baseId, index);
|
|
6629
|
+
const panelId = getTabPanelId(baseId, index);
|
|
6630
|
+
return normalizedHash === tabId || normalizedHash === panelId;
|
|
6631
|
+
});
|
|
6632
|
+
return matchIndex >= 0 ? tabs[matchIndex]?.value ?? null : null;
|
|
6633
|
+
}
|
|
6634
|
+
function shouldHandleTabClickLocally(event, target) {
|
|
6635
|
+
return !(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || target === "_blank");
|
|
6636
|
+
}
|
|
6611
6637
|
var Tabs = ({
|
|
6612
6638
|
tabs,
|
|
6613
6639
|
defaultValue,
|
|
@@ -6625,14 +6651,33 @@ var Tabs = ({
|
|
|
6625
6651
|
const [active, setActive] = React22.useState(defaultValue || tabs[0]?.value);
|
|
6626
6652
|
const [underlineStyle, setUnderlineStyle] = React22.useState({});
|
|
6627
6653
|
const tabRefs = React22.useRef([]);
|
|
6628
|
-
const baseId = React22.useMemo(() =>
|
|
6629
|
-
const key = tabs.map((t) => t.value).join("-");
|
|
6630
|
-
return `tabs-${key || "default"}`;
|
|
6631
|
-
}, [tabs]);
|
|
6654
|
+
const baseId = React22.useMemo(() => getTabsBaseId(tabs), [tabs]);
|
|
6632
6655
|
const handleTabChange = (value) => {
|
|
6633
6656
|
setActive(value);
|
|
6634
6657
|
onTabChange?.(value);
|
|
6635
6658
|
};
|
|
6659
|
+
const handleTabKeyDown = (event) => {
|
|
6660
|
+
const count = tabs.length;
|
|
6661
|
+
const idx = tabs.findIndex((t) => t.value === active);
|
|
6662
|
+
let next = idx;
|
|
6663
|
+
if (orientation === "horizontal") {
|
|
6664
|
+
if (event.key === "ArrowRight") next = (idx + 1) % count;
|
|
6665
|
+
if (event.key === "ArrowLeft") next = (idx - 1 + count) % count;
|
|
6666
|
+
} else {
|
|
6667
|
+
if (event.key === "ArrowDown") next = (idx + 1) % count;
|
|
6668
|
+
if (event.key === "ArrowUp") next = (idx - 1 + count) % count;
|
|
6669
|
+
}
|
|
6670
|
+
if (event.key === "Home") next = 0;
|
|
6671
|
+
if (event.key === "End") next = count - 1;
|
|
6672
|
+
if (next !== idx) {
|
|
6673
|
+
event.preventDefault();
|
|
6674
|
+
const nextTab = tabs[next];
|
|
6675
|
+
if (!nextTab?.disabled) {
|
|
6676
|
+
handleTabChange(nextTab.value);
|
|
6677
|
+
}
|
|
6678
|
+
tabRefs.current[next]?.focus();
|
|
6679
|
+
}
|
|
6680
|
+
};
|
|
6636
6681
|
React22.useEffect(() => {
|
|
6637
6682
|
if (variant === "underline" && orientation === "horizontal") {
|
|
6638
6683
|
const activeIndex2 = tabs.findIndex((tab) => tab.value === active);
|
|
@@ -6646,6 +6691,18 @@ var Tabs = ({
|
|
|
6646
6691
|
}
|
|
6647
6692
|
}
|
|
6648
6693
|
}, [active, variant, orientation, tabs]);
|
|
6694
|
+
React22.useEffect(() => {
|
|
6695
|
+
if (typeof window === "undefined") return;
|
|
6696
|
+
const syncFromHash = () => {
|
|
6697
|
+
const nextValue = resolveTabValueFromHash(window.location.hash, tabs, baseId);
|
|
6698
|
+
if (nextValue) {
|
|
6699
|
+
setActive(nextValue);
|
|
6700
|
+
}
|
|
6701
|
+
};
|
|
6702
|
+
syncFromHash();
|
|
6703
|
+
window.addEventListener("hashchange", syncFromHash);
|
|
6704
|
+
return () => window.removeEventListener("hashchange", syncFromHash);
|
|
6705
|
+
}, [baseId, tabs]);
|
|
6649
6706
|
const containerClasses = cn(
|
|
6650
6707
|
"relative",
|
|
6651
6708
|
orientation === "horizontal" ? "w-full flex space-x-1 overflow-x-auto" : "flex flex-col space-y-1 shrink-0",
|
|
@@ -6668,59 +6725,69 @@ var Tabs = ({
|
|
|
6668
6725
|
tabs.map((tab, index) => {
|
|
6669
6726
|
const isActive = active === tab.value;
|
|
6670
6727
|
const Icon = tab.icon;
|
|
6671
|
-
const tabId2 =
|
|
6672
|
-
const panelId2 =
|
|
6728
|
+
const tabId2 = getTabTriggerId(baseId, index);
|
|
6729
|
+
const panelId2 = getTabPanelId(baseId, index);
|
|
6730
|
+
const tabHref = getTabHref(tab, panelId2);
|
|
6731
|
+
const sharedClassName = cn(
|
|
6732
|
+
"font-medium transition-all duration-200 cursor-pointer flex items-center gap-2",
|
|
6733
|
+
"focus:outline-none focus-visible:outline-none",
|
|
6734
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
6735
|
+
sizeStyles6[size].tab,
|
|
6736
|
+
variantStyles5[variant].tab,
|
|
6737
|
+
isActive ? variantStyles5[variant].activeTab : variantStyles5[variant].inactiveTab,
|
|
6738
|
+
orientation === "vertical" && "justify-start w-full",
|
|
6739
|
+
stretch && orientation === "horizontal" && "flex-1 justify-center",
|
|
6740
|
+
tab.href && tab.disabled && "pointer-events-none cursor-not-allowed opacity-50"
|
|
6741
|
+
);
|
|
6742
|
+
const sharedStyle = {
|
|
6743
|
+
boxShadow: "none",
|
|
6744
|
+
transform: "none",
|
|
6745
|
+
outline: "none",
|
|
6746
|
+
border: "none"
|
|
6747
|
+
};
|
|
6748
|
+
const sharedProps = {
|
|
6749
|
+
ref: (el) => {
|
|
6750
|
+
tabRefs.current[index] = el;
|
|
6751
|
+
},
|
|
6752
|
+
id: tabId2,
|
|
6753
|
+
role: "tab",
|
|
6754
|
+
"aria-selected": isActive,
|
|
6755
|
+
"aria-controls": panelId2,
|
|
6756
|
+
tabIndex: isActive ? 0 : -1,
|
|
6757
|
+
className: sharedClassName,
|
|
6758
|
+
style: sharedStyle,
|
|
6759
|
+
onKeyDown: handleTabKeyDown
|
|
6760
|
+
};
|
|
6761
|
+
if (!tab.disabled) {
|
|
6762
|
+
return /* @__PURE__ */ jsxs20(
|
|
6763
|
+
"a",
|
|
6764
|
+
{
|
|
6765
|
+
...sharedProps,
|
|
6766
|
+
href: tabHref,
|
|
6767
|
+
target: tab.target,
|
|
6768
|
+
rel: tab.rel,
|
|
6769
|
+
onClick: (event) => {
|
|
6770
|
+
if (shouldHandleTabClickLocally(event, tab.target)) {
|
|
6771
|
+
event.preventDefault();
|
|
6772
|
+
handleTabChange(tab.value);
|
|
6773
|
+
}
|
|
6774
|
+
},
|
|
6775
|
+
className: cn(sharedClassName, "no-underline"),
|
|
6776
|
+
children: [
|
|
6777
|
+
Icon && /* @__PURE__ */ jsx27(Icon, { className: "h-4 w-4" }),
|
|
6778
|
+
tab.label
|
|
6779
|
+
]
|
|
6780
|
+
},
|
|
6781
|
+
tab.value
|
|
6782
|
+
);
|
|
6783
|
+
}
|
|
6673
6784
|
return /* @__PURE__ */ jsxs20(
|
|
6674
6785
|
"button",
|
|
6675
6786
|
{
|
|
6676
|
-
|
|
6677
|
-
tabRefs.current[index] = el;
|
|
6678
|
-
},
|
|
6787
|
+
...sharedProps,
|
|
6679
6788
|
onClick: () => !tab.disabled && handleTabChange(tab.value),
|
|
6680
6789
|
disabled: tab.disabled,
|
|
6681
|
-
|
|
6682
|
-
boxShadow: "none",
|
|
6683
|
-
transform: "none",
|
|
6684
|
-
outline: "none",
|
|
6685
|
-
border: "none"
|
|
6686
|
-
},
|
|
6687
|
-
className: cn(
|
|
6688
|
-
"font-medium transition-all duration-200 cursor-pointer flex items-center gap-2",
|
|
6689
|
-
"focus:outline-none focus-visible:outline-none",
|
|
6690
|
-
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
6691
|
-
"border-0 bg-transparent outline-none",
|
|
6692
|
-
// Reset button default styles
|
|
6693
|
-
sizeStyles6[size].tab,
|
|
6694
|
-
variantStyles5[variant].tab,
|
|
6695
|
-
isActive ? variantStyles5[variant].activeTab : variantStyles5[variant].inactiveTab,
|
|
6696
|
-
orientation === "vertical" && "justify-start w-full",
|
|
6697
|
-
stretch && orientation === "horizontal" && "flex-1 justify-center"
|
|
6698
|
-
),
|
|
6699
|
-
role: "tab",
|
|
6700
|
-
id: tabId2,
|
|
6701
|
-
"aria-selected": isActive,
|
|
6702
|
-
"aria-controls": panelId2,
|
|
6703
|
-
tabIndex: isActive ? 0 : -1,
|
|
6704
|
-
onKeyDown: (e) => {
|
|
6705
|
-
const count = tabs.length;
|
|
6706
|
-
const idx = tabs.findIndex((t) => t.value === active);
|
|
6707
|
-
let next = idx;
|
|
6708
|
-
if (orientation === "horizontal") {
|
|
6709
|
-
if (e.key === "ArrowRight") next = (idx + 1) % count;
|
|
6710
|
-
if (e.key === "ArrowLeft") next = (idx - 1 + count) % count;
|
|
6711
|
-
} else {
|
|
6712
|
-
if (e.key === "ArrowDown") next = (idx + 1) % count;
|
|
6713
|
-
if (e.key === "ArrowUp") next = (idx - 1 + count) % count;
|
|
6714
|
-
}
|
|
6715
|
-
if (e.key === "Home") next = 0;
|
|
6716
|
-
if (e.key === "End") next = count - 1;
|
|
6717
|
-
if (next !== idx) {
|
|
6718
|
-
e.preventDefault();
|
|
6719
|
-
const nextVal = tabs[next].value;
|
|
6720
|
-
handleTabChange(nextVal);
|
|
6721
|
-
tabRefs.current[next]?.focus();
|
|
6722
|
-
}
|
|
6723
|
-
},
|
|
6790
|
+
className: cn(sharedClassName, "border-0 bg-transparent outline-none"),
|
|
6724
6791
|
children: [
|
|
6725
6792
|
Icon && /* @__PURE__ */ jsx27(Icon, { className: "h-4 w-4" }),
|
|
6726
6793
|
tab.label
|