import React, { DetailedHTMLProps, HTMLAttributes, ReactNode } from "react"; import { twMerge } from "tailwind-merge"; import Border from "./Border"; import Stack from "../layout/Stack"; import Row from "../layout/Row"; import twuiSlugify from "../utils/slugify"; export type TWUITabsObject = { title: string; value?: string; content: React.ReactNode; defaultActive?: boolean; }; export type TWUI_TOGGLE_PROPS = React.ComponentProps & { tabsContentArray: (TWUITabsObject | TWUITabsObject[] | undefined | null)[]; tabsBorderProps?: React.ComponentProps; tabsButtonsWrapperProps?: React.DetailedHTMLProps< React.HTMLAttributes, HTMLDivElement >; centered?: boolean; debounce?: number; /** * React Component to display when switching */ switchComponent?: ReactNode; setActiveValue?: React.Dispatch>; }; /** * # Tabs Component * @className twui-tabs-wrapper * @className twui-tab-buttons * @className twui-tab-button-active * @className twui-tab-buttons-wrapper */ export default function Tabs({ tabsContentArray, tabsBorderProps, tabsButtonsWrapperProps, centered, debounce = 100, switchComponent, setActiveValue: existingSetActiveValue, ...props }: TWUI_TOGGLE_PROPS) { const finalTabsContentArray = tabsContentArray .flat() .filter((ct) => Boolean(ct?.title)) as TWUITabsObject[]; const values = finalTabsContentArray.map( (obj) => obj.value || twuiSlugify(obj.title) ); const defaultActiveObj = finalTabsContentArray.find( (ctn) => ctn.defaultActive ); const [activeValue, setActiveValue] = React.useState( defaultActiveObj ? defaultActiveObj?.value || twuiSlugify(defaultActiveObj.title) : values[0] || undefined ); const targetContent = finalTabsContentArray.find( (ctn) => ctn.value == activeValue || twuiSlugify(ctn.title) == activeValue ); React.useEffect(() => { existingSetActiveValue?.(activeValue); }, [activeValue]); return (
{values.map((value, index) => { const targetObject = finalTabsContentArray.find( (ctn) => ctn.value == value || twuiSlugify(ctn.title) == value ); const isActive = value == activeValue; return ( { setActiveValue(undefined); setTimeout(() => { setActiveValue(value); }, debounce); }} key={index} > {targetObject?.title} ); })}
{activeValue ? targetContent?.content : switchComponent || null}
); }