UNPKG

flowbite-react

Version:

Official React components built for Flowbite and Tailwind CSS

1 lines 10 kB
{"version":3,"file":"Tabs.mjs","sources":["../../../../src/components/Tabs/Tabs.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentProps, ForwardedRef, KeyboardEvent, PropsWithChildren, ReactElement } from \"react\";\nimport { Children, forwardRef, useEffect, useId, useImperativeHandle, useMemo, useRef, useState } from \"react\";\nimport { twMerge } from \"tailwind-merge\";\nimport { mergeDeep } from \"../../helpers/merge-deep\";\nimport { getTheme } from \"../../theme-store\";\nimport type { DeepPartial } from \"../../types\";\nimport type { FlowbiteBoolean } from \"../Flowbite\";\nimport type { TabItemProps } from \"./TabItem\";\nimport { TabItem } from \"./TabItem\";\n\nexport interface FlowbiteTabsTheme {\n base: string;\n tablist: {\n base: string;\n styles: TabStyles;\n tabitem: {\n base: string;\n styles: TabStyleItem<TabStyles>;\n icon: string;\n };\n };\n tabitemcontainer: {\n base: string;\n styles: TabStyles;\n };\n tabpanel: string;\n}\n\nexport interface TabStyles {\n default: string;\n fullWidth: string;\n pills: string;\n underline: string;\n}\n\nexport interface TabStyleItemProps {\n base: string;\n active: FlowbiteBoolean;\n}\n\nexport type TabStyleItem<Type> = {\n [K in keyof Type]: TabStyleItemProps;\n};\n\nexport type TabItemStatus = \"active\" | \"notActive\";\n\ninterface TabEventProps {\n target: number;\n}\n\ninterface TabKeyboardEventProps extends TabEventProps {\n event: KeyboardEvent<HTMLButtonElement>;\n}\n\nexport interface TabsProps extends Omit<ComponentProps<\"div\">, \"ref\" | \"style\"> {\n onActiveTabChange?: (activeTab: number) => void;\n style?: keyof TabStyles;\n theme?: DeepPartial<FlowbiteTabsTheme>;\n}\n\nexport interface TabsRef {\n setActiveTab: (activeTab: number) => void;\n}\n\nconst TabsComponent = forwardRef<TabsRef, TabsProps>(\n (\n { children, className, onActiveTabChange, style = \"default\", theme: customTheme = {}, ...props },\n ref: ForwardedRef<TabsRef>,\n ) => {\n const theme = mergeDeep(getTheme().tabs, customTheme);\n\n const id = useId();\n const tabs = useMemo(\n () =>\n Children.map(\n Children.toArray(children) as ReactElement<PropsWithChildren<TabItemProps>>[],\n ({ props }) => props,\n ),\n [children],\n );\n const tabRefs = useRef<HTMLButtonElement[]>([]);\n const [activeTab, setActiveTab] = useState(\n Math.max(\n 0,\n tabs.findIndex((tab) => tab.active),\n ),\n );\n const [focusedTab, setFocusedTab] = useState(-1);\n\n const setActiveTabWithCallback = (activeTab: number) => {\n setActiveTab(activeTab);\n if (onActiveTabChange) onActiveTabChange(activeTab);\n };\n\n const handleClick = ({ target }: TabEventProps): void => {\n setActiveTabWithCallback(target);\n setFocusedTab(target);\n };\n\n const handleKeyboard = ({ event, target }: TabKeyboardEventProps): void => {\n if (event.key === \"ArrowLeft\") {\n setFocusedTab(Math.max(0, focusedTab - 1));\n }\n\n if (event.key === \"ArrowRight\") {\n setFocusedTab(Math.min(tabs.length - 1, focusedTab + 1));\n }\n\n if (event.key === \"Enter\") {\n setActiveTabWithCallback(target);\n setFocusedTab(target);\n }\n };\n\n const tabItemStyle = theme.tablist.tabitem.styles[style];\n const tabItemContainerStyle = theme.tabitemcontainer.styles[style];\n\n useEffect(() => {\n tabRefs.current[focusedTab]?.focus();\n }, [focusedTab]);\n\n useImperativeHandle(ref, () => ({\n setActiveTab: setActiveTabWithCallback,\n }));\n\n return (\n <div className={twMerge(theme.base, className)}>\n <div\n aria-label=\"Tabs\"\n role=\"tablist\"\n className={twMerge(theme.tablist.base, theme.tablist.styles[style], className)}\n {...props}\n >\n {tabs.map((tab, index) => (\n <button\n key={index}\n type=\"button\"\n aria-controls={`${id}-tabpanel-${index}`}\n aria-selected={index === activeTab}\n className={twMerge(\n theme.tablist.tabitem.base,\n tabItemStyle.base,\n index === activeTab && tabItemStyle.active.on,\n index !== activeTab && !tab.disabled && tabItemStyle.active.off,\n )}\n disabled={tab.disabled}\n id={`${id}-tab-${index}`}\n onClick={() => handleClick({ target: index })}\n onKeyDown={(event) => handleKeyboard({ event, target: index })}\n ref={(element) => (tabRefs.current[index] = element as HTMLButtonElement)}\n role=\"tab\"\n tabIndex={index === focusedTab ? 0 : -1}\n style={{ zIndex: index === focusedTab ? 2 : 1 }}\n >\n {tab.icon && <tab.icon className={theme.tablist.tabitem.icon} />}\n {tab.title}\n </button>\n ))}\n </div>\n <div className={twMerge(theme.tabitemcontainer.base, tabItemContainerStyle)}>\n {tabs.map((tab, index) => (\n <div\n key={index}\n aria-labelledby={`${id}-tab-${index}`}\n className={theme.tabpanel}\n hidden={index !== activeTab}\n id={`${id}-tabpanel-${index}`}\n role=\"tabpanel\"\n tabIndex={0}\n >\n {tab.children}\n </div>\n ))}\n </div>\n </div>\n );\n },\n);\n\nTabsComponent.displayName = \"Tabs\";\n\nexport const Tabs = Object.assign(TabsComponent, {\n Item: TabItem,\n});\n"],"names":[],"mappings":"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"}