import { getTabWrapperStyles, getTabListStyles, getTabStyles, getTabPanelStyles, splitClassNameProp, } from '@pluralsight/headless-styles' import { useAriaTabList, useAriaTab, useAriaTabPanel, type UseTabListOptions, type UseTabOptions, type UseTabPanelOptions, } from '@pluralsight/react-aria' import { forwardRef, type ButtonHTMLAttributes, type HTMLAttributes, type ForwardedRef, type MouseEvent, useTransition, useRef, useEffect, } from 'react' import { CircularProgress, Show, useTabs } from '../index.ts' // export type TabsWrapperProps = HTMLAttributes function TabsWrapperEl( props: TabsWrapperProps, ref: ForwardedRef, ) { const pandoStyles = getTabWrapperStyles({ classNames: splitClassNameProp(props.className), }) return
} // export interface TabsListProps extends HTMLAttributes, Pick {} function TabsListEl(props: TabsListProps, ref: ForwardedRef) { const { labelledBy, ...nativeProps } = props const pandoStyles = getTabListStyles({ classNames: splitClassNameProp(nativeProps.className), }) const { activeTab, onTabClick, tabsRefList } = useTabs() const ariaProps = useAriaTabList({ activeTabValue: activeTab, labelledBy, setFocus: onTabClick, tabsRefList, }) return
} // export interface TabProps extends Omit, 'value'>, UseTabOptions { value: string } function TabEl(props: TabProps, ref: ForwardedRef) { const { controls, ...nativeProps } = props const pandoStyles = getTabStyles({ classNames: splitClassNameProp(nativeProps.className), }) const tabRef = useRef(null) const [isPending, startTransition] = useTransition() const { activeTab, onTabClick, setTabsRefList } = useTabs() const ariaProps = useAriaTab({ controls, selected: activeTab === nativeProps.value, }) function handleClick(e: MouseEvent) { const target = e.target as HTMLButtonElement if (target.disabled) return startTransition(() => onTabClick(target.value)) if (nativeProps.onClick) nativeProps.onClick(e) } useEffect(() => { if (tabRef.current && !nativeProps.disabled) { setTabsRefList((prev) => { return { ...prev, [nativeProps.value]: tabRef.current } }) } }, [tabRef, setTabsRefList, nativeProps.value, nativeProps.disabled]) return ( ) } // export interface TabsPanelProps extends HTMLAttributes, UseTabPanelOptions {} function TabsPanelEl(props: TabsPanelProps, ref: ForwardedRef) { const { labelledBy, ...nativeProps } = props const pandoStyles = getTabPanelStyles({ classNames: splitClassNameProp(nativeProps.className), }) const { activeTab } = useTabs() const ariaProps = useAriaTabPanel({ labelledBy, hidden: nativeProps.hidden ?? activeTab !== labelledBy, }) return (
) } // exports /** * Displays the wrapper for a set of tabs. * @see https://design.pluralsight.com/docs/reference/components/tabs */ export const TabsWrapper = forwardRef( TabsWrapperEl, ) /** * Displays a list of tabs. * @see https://design.pluralsight.com/docs/reference/components/tabs */ export const TabsList = forwardRef(TabsListEl) /** * Displays a single tab. * @see https://design.pluralsight.com/docs/reference/components/tabs */ export const Tab = forwardRef(TabEl) /** * Displays a single tab panel. * @see https://design.pluralsight.com/docs/reference/components/tabs */ export const TabsPanel = forwardRef(TabsPanelEl)