"use client" import getEnv from "@/lib/env-entry" import { cn } from "@/lib/utils" import { useTranslations } from "next-intl" import React, { createRef, useEffect, useRef, useState } from "react" export default function Switch({ allTag, nowTag, tagCountMap, onTagChange, }: { allTag: string[] nowTag: string tagCountMap: Record onTagChange: (tag: string) => void }) { const scrollRef = useRef(null) const tagRefs = useRef(allTag.map(() => createRef())) const t = useTranslations("ServerListClient") const [indicator, setIndicator] = useState<{ x: number; w: number }>({ x: 0, w: 0 }) // 处理初始标签加载 useEffect(() => { const savedTag = sessionStorage.getItem("selectedTag") if (savedTag && allTag.includes(savedTag)) { onTagChange(savedTag) } }, [allTag, onTagChange]) // 处理鼠标滚轮横向滚动 useEffect(() => { const container = scrollRef.current if (!container) return const isOverflowing = container.scrollWidth > container.clientWidth if (!isOverflowing) return const onWheel = (e: WheelEvent) => { e.preventDefault() container.scrollLeft += e.deltaY } container.addEventListener("wheel", onWheel, { passive: false }) return () => { container.removeEventListener("wheel", onWheel) } }, []) // 更新指示器位置 useEffect(() => { const currentTagElement = tagRefs.current[allTag.indexOf(nowTag)]?.current if (currentTagElement) { const parentPadding = 1 setIndicator({ x: allTag.indexOf(nowTag) !== 0 ? currentTagElement.offsetLeft - parentPadding : currentTagElement.offsetLeft, w: currentTagElement.offsetWidth, }) } }, [nowTag, allTag]) // 处理选中标签的自动滚动 useEffect(() => { const currentTagElement = tagRefs.current[allTag.indexOf(nowTag)]?.current const container = scrollRef.current if (currentTagElement && container) { const containerRect = container.getBoundingClientRect() const tagRect = currentTagElement.getBoundingClientRect() // 计算需要滚动的位置,使选中的标签居中显示 const scrollLeft = currentTagElement.offsetLeft - (containerRect.width - tagRect.width) / 2 // 使用平滑滚动效果 container.scrollTo({ left: Math.max(0, scrollLeft), // 确保不会出现负值 behavior: 'smooth' }) } }, [nowTag, allTag]) return (
{indicator.w > 0 && (
)} {allTag.map((tag, index) => (
{ onTagChange(tag) sessionStorage.setItem("selectedTag", tag) }} className={cn( "relative cursor-pointer rounded-3xl px-2.5 py-[8px] text-[13px] font-[600]", "transition-all duration-500 ease-in-out text-stone-400 dark:text-stone-500", { "text-stone-950 dark:text-stone-50": nowTag === tag, }, )} >
{tag === "defaultTag" ? t("defaultTag") : tag}{" "} {getEnv("NEXT_PUBLIC_ShowTagCount") === "true" && tag !== "defaultTag" && (
{tagCountMap[tag]}
)}
))}
) }