import { UUID } from "../components/ItemContext" ; export interface InjectedPanelAttributes { role : string | undefined ; 'aria-hidden' : boolean | undefined ; 'aria-labelledby' : string ; id : string ; hidden : boolean | undefined ; } export interface InjectedHeadingAttributes { role : string ; } export interface InjectedButtonAttributes { id : string ; 'aria-controls' : string ; 'aria-expanded' : boolean ; 'aria-disabled' : boolean ; role : string ; tabIndex : number ; } export default class AccordionStore { public readonly expanded : UUID [ ] ; public readonly allowMultipleExpanded : boolean ; public readonly allowZeroExpanded : boolean ; constructor ( { expanded = [ ] , allowMultipleExpanded = false , allowZeroExpanded = false , } ) { this . expanded = expanded ; this . allowMultipleExpanded = allowMultipleExpanded ; this . allowZeroExpanded = allowZeroExpanded ; } public readonly toggleExpanded = ( uuid ) : AccordionStore => { if ( this . isItemDisabled ( uuid ) ) { return this ; } const isExpanded = this . isItemExpanded ( uuid ) ; if ( ! isExpanded ) { return this . augment ( { expanded : this . allowMultipleExpanded ? [ ... this . expanded , uuid ] : [ uuid ] , } ) ; } else { return this . augment ( { expanded : this . expanded . filter ( ( expandedUuid ) : boolean => expandedUuid !== uuid ) , } ) ; } } ; public readonly isItemDisabled = ( uuid ) : boolean => { const isExpanded = this . isItemExpanded ( uuid ) ; const isOnlyOneExpanded = this . expanded . length === 1 ; return Boolean ( isExpanded && ! this . allowZeroExpanded && isOnlyOneExpanded ) ; } ; public readonly isItemExpanded = ( uuid ) : boolean => { return this . expanded . indexOf ( uuid ) !== - 1 ; } ; public readonly getPanelAttributes = ( uuid , dangerouslySetExpanded ? ) : InjectedPanelAttributes => { const expanded = dangerouslySetExpanded ? dangerouslySetExpanded : this . isItemExpanded ( uuid ) ; return { role : this . allowMultipleExpanded ? undefined : 'region' , 'aria-hidden' : this . allowMultipleExpanded ? ! expanded : undefined , 'aria-labelledby' : this . getButtonId ( uuid ) , id : this . getPanelId ( uuid ) , hidden : expanded ? undefined : true , } ; } ; public readonly getHeadingAttributes = ( ) : InjectedHeadingAttributes => { return { role : 'heading' , } ; } ; public readonly getButtonAttributes = ( uuid , dangerouslySetExpanded ? ) : InjectedButtonAttributes => { const expanded = dangerouslySetExpanded ? dangerouslySetExpanded : this . isItemExpanded ( uuid ) ; const disabled = this . isItemDisabled ( uuid ) ; return { id : this . getButtonId ( uuid ) , 'aria-disabled' : disabled , 'aria-expanded' : expanded , 'aria-controls' : this . getPanelId ( uuid ) , role : 'button' , tabIndex : 0 , } ; } ; private readonly getPanelId = ( uuid ) : string => `accordion__panel-${ uuid }` ; private readonly getButtonId = ( uuid ) : string => `accordion__heading-${ uuid }` ; private readonly augment = ( args ) : AccordionStore => { return new AccordionStore ( { expanded : this . expanded , allowMultipleExpanded : this . allowMultipleExpanded , allowZeroExpanded : this . allowZeroExpanded , ... args , } ) ; } ; }