fromozuzhouzzz
Deploy grok2api v3.0.11 to HF Spaces
f1dd159
Raw
History Blame Contribute Delete
3.96 kB
import * as TabsPrimitive from "@radix-ui/react-tabs";
import * as React from "react";
import { cn } from "@/shared/lib/cn";
export function Tabs({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Root>) {
return <TabsPrimitive.Root className={cn("flex flex-col", className)} {...props} />;
}
type IndicatorGeometry = { left: number; top: number; width: number; height: number };
export const TabsList = React.forwardRef<React.ElementRef<typeof TabsPrimitive.List>, React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>>(
function TabsList({ className, children, ...props }, forwardedRef) {
const listRef = React.useRef<React.ElementRef<typeof TabsPrimitive.List> | null>(null);
const [indicator, setIndicator] = React.useState<IndicatorGeometry | null>(null);
const setListRef = React.useCallback((node: React.ElementRef<typeof TabsPrimitive.List> | null) => {
listRef.current = node;
if (typeof forwardedRef === "function") forwardedRef(node);
else if (forwardedRef) (forwardedRef as React.MutableRefObject<React.ElementRef<typeof TabsPrimitive.List> | null>).current = node;
}, [forwardedRef]);
const updateIndicator = React.useCallback(() => {
const list = listRef.current;
const active = list?.querySelector<HTMLElement>('[role="tab"][data-state="active"]');
if (!list || !active) {
setIndicator(null);
return;
}
const next = { left: active.offsetLeft, top: active.offsetTop, width: active.offsetWidth, height: active.offsetHeight };
setIndicator((current) => current && current.left === next.left && current.top === next.top && current.width === next.width && current.height === next.height ? current : next);
}, []);
React.useLayoutEffect(() => {
const list = listRef.current;
if (!list) return;
updateIndicator();
const mutationObserver = new MutationObserver(updateIndicator);
mutationObserver.observe(list, { attributes: true, childList: true, subtree: true, attributeFilter: ["data-state"] });
const resizeObserver = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(updateIndicator);
resizeObserver?.observe(list);
list.querySelectorAll<HTMLElement>('[role="tab"]').forEach((tab) => resizeObserver?.observe(tab));
window.addEventListener("resize", updateIndicator);
return () => {
mutationObserver.disconnect();
resizeObserver?.disconnect();
window.removeEventListener("resize", updateIndicator);
};
}, [updateIndicator]);
return (
<TabsPrimitive.List ref={setListRef} className={cn("relative isolate inline-flex h-8 w-fit items-center gap-1 rounded-full bg-muted p-0.5", className)} {...props}>
{indicator ? (
<span
aria-hidden="true"
className="pointer-events-none absolute left-0 top-0 z-0 rounded-full bg-background shadow-sm transition-[transform,width,height] duration-200 ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:transition-none"
style={{ width: indicator.width, height: indicator.height, transform: `translate3d(${indicator.left}px, ${indicator.top}px, 0)` }}
/>
) : null}
{children}
</TabsPrimitive.List>
);
},
);
export function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
return (
<TabsPrimitive.Trigger
className={cn("relative z-10 inline-flex h-7 items-center justify-center rounded-full px-3 text-xs font-medium text-muted-foreground outline-none transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50 data-[state=active]:text-foreground", className)}
{...props}
/>
);
}
export function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {
return <TabsPrimitive.Content className={cn("min-w-0 outline-none", className)} {...props} />;
}