import { MDCModalDrawerFoundation , MDCDismissibleDrawerFoundation } from '@material/drawer' ; import { DrawerProps } from '.' ; import { useFoundation , FocusTrap , focusTrapFactory , triggerWindowResize } from '@rmwc/base' ; import React , { useRef , useEffect , useCallback } from 'react' ; const useDrawerFoundationFactory = ( MDCConstructor ) => function useDrawerFoundation ( props ) { const focusTrapRef = useRef < FocusTrap > ( ) ; const { foundation , ... elements } = useFoundation ( { props , elements : { rootEl : true , scrimEl : true } , foundation : ( { rootEl , emit , getProps } ) => { let previousFocusEl ; const f = new MDCConstructor ( { addClass : ( className ) => rootEl . addClass ( className ) , removeClass : ( className ) => rootEl . removeClass ( className ) , hasClass : ( className ) => rootEl . hasClass ( className ) , elementHasClass : ( element , className ) => element . classList . contains ( className ) , saveFocus : ( ) => { previousFocusEl = document . activeElement as HTMLElement ; } , restoreFocus : ( ) => { if ( rootEl . ref && rootEl . ref . contains ( document . activeElement ) && previousFocusEl ) { previousFocusEl . focus ( ) ; } } , focusActiveNavigationItem : ( ) => { const activeNavItemEl = rootEl . ref ?. querySelector ( `.mdc-list-item--activated` ) ; if ( activeNavItemEl ) { ( activeNavItemEl as HTMLElement ) . focus ( ) ; } } , notifyClose : ( ) => { } , notifyOpen : ( ) => { emit ( 'onOpen' , { } , true ) ; } , trapFocus : ( ) => { try { focusTrapRef . current ?. trapFocus ( ) ; } catch ( err ) { } } , releaseFocus : ( ) => { try { focusTrapRef . current ?. releaseFocus ( ) ; } catch ( err ) { } } } ) ; const existingClose = f . close . bind ( f ) ; const newClose = ( ) => { emit ( 'onClose' , { } ) ; setTimeout ( ( ) => { if ( ! getProps ( ) . open ) { existingClose ( ) ; } } ) ; } ; f . close = newClose ; return f ; } } ) ; const { rootEl , scrimEl } = elements ; useEffect ( ( ) => { if ( rootEl . ref ) { focusTrapRef . current = focusTrapFactory ( rootEl . ref ) ; } } , [ rootEl . ref ] ) ; useEffect ( ( ) => { props . open ? foundation . open ( ) : foundation . close ( ) ; } , [ props . open , foundation ] ) ; const handleScrimClick = useCallback ( ( ) => { ( foundation as MDCModalDrawerFoundation ) . handleScrimClick ?. ( ) ; } , [ foundation ] ) ; const handleKeyDown = useCallback ( ( evt ) => { props . onKeyDown ?. ( evt ) ; foundation . handleKeydown ( evt ) ; } , [ foundation , props . onKeyDown ] ) ; const handleTransitionEnd = useCallback ( ( evt ) => { props . onTransitionEnd ?. ( evt ) ; foundation . handleTransitionEnd ( evt ) ; triggerWindowResize ( ) ; } , [ foundation , props . onTransitionEnd ] ) ; rootEl . setProp ( 'onKeyDown' , handleKeyDown , true ) ; rootEl . setProp ( 'onTransitionEnd' , handleTransitionEnd , true ) ; scrimEl . setProp ( 'onClick' , handleScrimClick , true ) ; return { foundation , ... elements } ; } ; export const useDismissableDrawerFoundation = useDrawerFoundationFactory ( MDCDismissibleDrawerFoundation ) ; export const useModalDrawerFoundation = useDrawerFoundationFactory ( MDCModalDrawerFoundation ) ;