UNPKG

ar-design

Version:

AR Design is a (react | nextjs) ui library.

111 lines (110 loc) 5.14 kB
"use client"; import React, { useEffect, useMemo, useRef, useState } from "react"; import "../../../assets/css/components/data-display/tabs/tabs.css"; import Skeleton from "./skeleton"; import { ARIcon } from "../../icons"; const Tabs = ({ name, tabs = [], activeTab, onChange, onClose }) => { // ref const _container = useRef(null); const _items = useRef([]); const _itemIndex = useRef(0); // states const [currentTab, setCurrentTab] = useState(0); const [scrollInfo, setScrollInfo] = useState({ isMaxLeft: true, isMaxRight: false, current: 0, maxScrollable: 0, }); // states -> Loading const [isLoading, setIsLoading] = useState(true); // methods const handleScroll = useMemo(() => { return () => { if (_container.current) { const { scrollLeft, scrollWidth, clientWidth } = _container.current; // Maksimum sağ değer: Toplam genişlik - Görünür genişlik const maxRight = scrollWidth - clientWidth; setScrollInfo({ isMaxLeft: scrollLeft <= 0, // En solda mı? isMaxRight: scrollLeft >= maxRight - 1, // En sağda mı? current: scrollLeft, // Anlık ne kadar sağda. maxScrollable: maxRight, // Gidebileceği max piksel. }); } }; }, []); const scroll = useMemo(() => { return (direction) => { const container = _container.current; if (!container) return; let nextIndex = direction === "left" ? _itemIndex.current - 1 : _itemIndex.current + 1; if (nextIndex < 0) nextIndex = 0; if (nextIndex >= _items.current.length) nextIndex = _items.current.length - 1; const targetItem = _items.current[nextIndex]; if (targetItem) { const targetLeft = targetItem.offsetLeft - container.offsetLeft; container.scrollTo({ left: targetLeft, behavior: "smooth", }); _itemIndex.current = nextIndex; } }; }, []); // useEffects useEffect(() => setCurrentTab(activeTab ?? 0), [activeTab]); useEffect(() => { const key = `${window.location.pathname}::${name}`; const stored = sessionStorage.getItem(key); setCurrentTab(stored !== null ? Number(stored) : 0); onChange?.(stored !== null ? Number(stored) : 0); setIsLoading(false); }, [name]); useEffect(() => { const timeoutId = setTimeout(() => { if (_container.current) { handleScroll(); } }, 100); window.addEventListener("resize", handleScroll); return () => { clearTimeout(timeoutId); window.removeEventListener("resize", handleScroll); }; }, []); if (isLoading) return React.createElement(Skeleton, { name: name, tabs: tabs }); return (React.createElement("div", { className: "ar-tabs" }, React.createElement("div", { className: "tabs" }, scrollInfo.current > 0 && (React.createElement("div", { className: "button left", onClick: () => scroll("left") }, React.createElement(ARIcon, { icon: "ArrowLeft", stroke: "var(--gray-700)" }))), !scrollInfo.isMaxRight && (React.createElement("div", { className: "button right", onClick: () => scroll("right") }, React.createElement(ARIcon, { icon: "ArrowRight", stroke: "var(--gray-700)" }))), React.createElement("div", { ref: _container, className: "container", onScroll: handleScroll }, tabs.length > 0 && tabs.map((tab, index) => { let className = ["item"]; if (currentTab === index) className.push("selection"); return (React.createElement("div", { key: tab.title ?? index, ref: (element) => { if (!element) return; _items.current[index] = element; }, className: className.map((c) => c).join(" "), onClick: () => { setCurrentTab(index); onChange?.(index); const key = `${window.location.pathname}::${name}`; sessionStorage.setItem(key, String(index)); } }, React.createElement("span", null, tab.title), tab.config?.canBeClosed && (React.createElement("span", { className: "close-button", onClick: (event) => { event.stopPropagation(); onClose && onClose(index); } }, "\u2716")))); }))), React.createElement("div", { className: "content" }, tabs.map((tab, index) => currentTab === index && tab.content)))); }; export default Tabs;