import type { ElementType, HTMLAttributes, ReactElement } from 'react' import React, { createContext, forwardRef, useContext } from 'react' import type { PolymorphicComponentPropsWithRef, PolymorphicRef, } from '../../typings' interface AccordionItemContext { index: number panel: string button: string prefixId: string } const AccordionItemContext = createContext( undefined ) interface Props extends HTMLAttributes { /** * ID to find this component in testing tools (e.g.: cypress, * testing-library, and jest). */ testId?: string /** * Index of the current accordion item within the accordion. */ index?: number /** * Namespace ID prefix for the current Accordion item's panel and button * to avoid ID duplication when multiple instances are on the same page. */ prefixId?: string } export type AccordionItemProps = PolymorphicComponentPropsWithRef type AccordionItemComponent = ( props: AccordionItemProps ) => ReactElement | null const AccordionItem = forwardRef< HTMLDivElement, Omit, 'ref'> >(function AccordionItem( { prefixId = '', index = 0, as: MaybeComponent, children, testId = 'fs-accordion-item', ...otherProps }: AccordionItemProps, ref: PolymorphicRef ) { const Component = MaybeComponent ?? 'div' const context = { index, prefixId, panel: `${prefixId && `${prefixId}-`}panel--${index}`, button: `${prefixId && `${prefixId}-`}button--${index}`, } return ( {children} ) }) as AccordionItemComponent export function useAccordionItem() { const context = useContext(AccordionItemContext) if (context === undefined) { throw new Error( 'Do not use AccordionItem components outside the AccordionItem context.' ) } return context } export default AccordionItem