license import { MDCFoundation } from '@material/base/foundation' ; import { MDCDrawerAdapter } from '../adapter' ; import { cssClasses , strings } from '../constants' ; export class MDCDismissibleDrawerFoundation extends MDCFoundation < MDCDrawerAdapter > { static override get strings ( ) { return strings ; } static override get cssClasses ( ) { return cssClasses ; } static override get defaultAdapter ( ) : MDCDrawerAdapter { return { addClass : ( ) => undefined , removeClass : ( ) => undefined , hasClass : ( ) => false , elementHasClass : ( ) => false , notifyClose : ( ) => undefined , notifyOpen : ( ) => undefined , saveFocus : ( ) => undefined , restoreFocus : ( ) => undefined , focusActiveNavigationItem : ( ) => undefined , trapFocus : ( ) => undefined , releaseFocus : ( ) => undefined , } ; } private animationFrame = 0 ; private animationTimer = 0 ; constructor ( adapter ? ) { super ( { ... MDCDismissibleDrawerFoundation . defaultAdapter , ... adapter } ) ; } override destroy ( ) { if ( this . animationFrame ) { cancelAnimationFrame ( this . animationFrame ) ; } if ( this . animationTimer ) { clearTimeout ( this . animationTimer ) ; } } /**
     * Opens the drawer from the closed state.
     */ open ( ) { if ( this . isOpen ( ) || this . isOpening ( ) || this . isClosing ( ) ) { return ; } this . adapter . addClass ( cssClasses . OPEN ) ; this . adapter . addClass ( cssClasses . ANIMATE ) ; this . runNextAnimationFrame ( ( ) => { this . adapter . addClass ( cssClasses . OPENING ) ; } ) ; this . adapter . saveFocus ( ) ; } /**
     * Closes the drawer from the open state.
     */ close ( ) { if ( ! this . isOpen ( ) || this . isOpening ( ) || this . isClosing ( ) ) { return ; } this . adapter . addClass ( cssClasses . CLOSING ) ; } return isOpen ( ) { return this . adapter . hasClass ( cssClasses . OPEN ) ; } return isOpening ( ) { return this . adapter . hasClass ( cssClasses . OPENING ) || this . adapter . hasClass ( cssClasses . ANIMATE ) ; } return isClosing ( ) { return this . adapter . hasClass ( cssClasses . CLOSING ) ; } /**
     * Keydown handler to close drawer when key is escape.
     */ handleKeydown ( evt ) { const { keyCode , key } = evt ; const isEscape = key === 'Escape' || keyCode === 27 ; if ( isEscape ) { this . close ( ) ; } } /**
     * Handles the `transitionend` event when the drawer finishes opening/closing.
     */ handleTransitionEnd ( evt ) { const { OPENING , CLOSING , OPEN , ANIMATE , ROOT } = cssClasses ; const isRootElement = this . isElement ( evt . target ) && this . adapter . elementHasClass ( evt . target , ROOT ) ; if ( ! isRootElement ) { return ; } if ( this . isClosing ( ) ) { this . adapter . removeClass ( OPEN ) ; this . closed ( ) ; this . adapter . restoreFocus ( ) ; this . adapter . notifyClose ( ) ; } else { this . adapter . focusActiveNavigationItem ( ) ; this . opened ( ) ; this . adapter . notifyOpen ( ) ; } this . adapter . removeClass ( ANIMATE ) ; this . adapter . removeClass ( OPENING ) ; this . adapter . removeClass ( CLOSING ) ; } /**
     * Extension point for when drawer finishes open animation.
     */ protected opened ( ) { } /**
     * Extension point for when drawer finishes close animation.
     */ protected closed ( ) { } /**
     * Runs the given logic on the next animation frame, using setTimeout to factor in Firefox reflow behavior.
     */ private runNextAnimationFrame ( callback ) { cancelAnimationFrame ( this . animationFrame ) ; this . animationFrame = requestAnimationFrame ( ( ) => { this . animationFrame = 0 ; clearTimeout ( this . animationTimer ) ; this . animationTimer = setTimeout ( callback , 0 ) ; } ) ; } private isElement ( element ) { return Boolean ( ( element as Element ) . classList ) ; } } export default MDCDismissibleDrawerFoundation ;