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)