import { AccordionProps } from '@mui/material' ; import React , { MutableRefObject } from 'react' ; type ManagedProps = 'onChange' | 'expanded' ; export interface SpotlightHandle { spotlight ( ) : void ; } export type SpotlightAccordionProps < P extends OptionalChildren < AccordionProps > > = Omit < P , ManagedProps > ; type OptionalChildren < T extends React . PropsWithChildren < unknown > > = Omit < T , 'children' > & { children ? : T [ 'children' ] ; } ; param BaseAccordion export function withSpotlight < P extends OptionalChildren < AccordionProps > > ( BaseAccordion ) { return React . forwardRef ( ( props , ref ) => { const [ expanded , setExpanded ] = React . useState ( false ) ; const innerRef = React . useRef < HTMLElement > ( ) ; React . useImperativeHandle ( ref , ( ) => { return { spotlight : ( ) => { setExpanded ( true ) ; innerRef . current ?. scrollIntoView ( { behavior : 'smooth' } ) ; } , } ; } ) ; return ( < BaseAccordion expanded = { expanded } onChange = { ( _ , newExpanded ) => setExpanded ( newExpanded ) } { ... ( props as P ) } > { props . children } < /BaseAccordion>); } ) ; } export interface SpotlightRef { ref : React . RefCallback < SpotlightHandle > ; spotlight : ( ) => void ; } /**
 * Allows a spotlight to be called even when the component is not mounted. The spotlight will be
 * deferred until the component is mounted.
 */ export function createSpotlightRef ( ) { const ref = { current : null , } ; const spotlightDefer = { current : false , } ; const doSpotlight = ( ) => { if ( ref . current ) { ref . current . spotlight ( ) ; } else { spotlightDefer . current = true ; } } ; const refCb = ( newRef ) => { if ( spotlightDefer . current ) { newRef ?. spotlight ( ) ; spotlightDefer . current = false ; } ref . current = newRef ; } ; return { ref : refCb , spotlight : doSpotlight } ; } export function useSpotlightRef ( ) { return React . useRef ( createSpotlightRef ( ) ) ; }