import { $ , ElementSet } from '@jdl2/elementset' ; const COLLAPSED_SIZE = 64 ; const DEFAULT_SIZE = 272 ; const MIN_SIZE = Math . floor ( DEFAULT_SIZE / 2.5 ) ; const MAX_SIZE = 512 ; type NavigationCallback = ( ) => void ; type NavigationResized = ( expanded : boolean , width : number ) => void ; function getStored ( key ) { return window . localStorage . getItem ( key ) || '' ; } function setStored ( key , value ) { window . localStorage . setItem ( key , value ) ; } export class SidebarBehavior { nav : ElementSet ; navHandle : ElementSet ; body : ElementSet ; isResizing : boolean = false ; isCollapsed : boolean ; storedWidth : number ; startWidth : number ; mouseStartX : number ; onResize ? : NavigationResized ; constructor ( collapse , onResize ? ) { this . body = $ ( 'body' ) ; this . nav = $ ( '.Nav' ) ; this . navHandle = $ ( '.NavExpander' ) ; this . isCollapsed = collapse !== undefined ? collapse : 'true' === getStored ( 'jdl.navbar.collapsed' ) ; this . storedWidth = parseInt ( getStored ( 'jdl.navbar.width' ) || '0' , 10 ) || DEFAULT_SIZE ; if ( this . isCollapsed ) { this . closeNav ( ) ; } else { this . openNav ( this . storedWidth ) ; } this . onResize = onResize ; this . navHandle . on ( 'mousedown' , this . startResize ) ; this . navHandle . on ( 'mouseup' , this . toggleNav ) ; } delayRemoveClass = ( element , className , time , cb ? ) => { setTimeout ( ( ) => { element . removeClass ( className ) ; if ( cb ) { cb ( ) ; } } , time ) ; } ; releaseAnimation = ( time ) => { this . nav . addClass ( 'is-released' ) ; this . delayRemoveClass ( this . nav , 'is-released' , time ) ; } ; closeNav = ( ) => { this . nav . addClass ( 'is-collapsed' ) ; this . nav . removeClass ( 'is-expanded' ) ; this . nav . width ( COLLAPSED_SIZE ) ; if ( ! this . isCollapsed ) { setStored ( 'jdl.navbar.collapsed' , 'true' ) ; this . isCollapsed = true ; this . showMain ( ) ; if ( this . onResize ) { this . onResize ( ! this . isCollapsed , this . storedWidth ) ; } } } ; openNav = ( width ) => { this . nav . addClass ( 'is-expanded' ) ; this . nav . removeClass ( 'is-collapsed' ) ; this . nav . width ( width ) ; if ( this . isCollapsed ) { window . localStorage . removeItem ( 'jdl.navbar.collapsed' ) ; this . isCollapsed = false ; if ( this . onResize ) { this . onResize ( ! this . isCollapsed , this . storedWidth ) ; } } } ; toggleNav = ( ) => { if ( this . isResizing ) { return ; } if ( ! this . isCollapsed ) { this . closeNav ( ) ; } else { this . openNav ( this . storedWidth ) ; } this . releaseAnimation ( 300 ) ; } ; doResize = ( e ) => { const mouseMovedX = this . mouseStartX - e . clientX ; if ( ! this . body . is ( 'is-dragging' ) ) { if ( Math . abs ( mouseMovedX ) > 3 ) { this . body . addClass ( 'is-dragging' ) ; } else { return ; } } let newWidth = this . startWidth - mouseMovedX ; if ( newWidth <= MIN_SIZE ) { this . closeNav ( ) ; return ; } if ( newWidth > MAX_SIZE ) { newWidth = MAX_SIZE ; } this . openNav ( newWidth ) ; this . isResizing = true ; } ; stopResize = ( e ) => { window . removeEventListener ( 'mousemove' , this . doResize , false ) ; window . removeEventListener ( 'mouseup' , this . stopResize , false ) ; this . body . removeClass ( 'is-dragging' ) ; if ( ! this . isResizing ) { return ; } this . isResizing = false ; const mouseMovedX = this . mouseStartX - e . clientX ; let newWidth = this . startWidth - mouseMovedX ; if ( newWidth <= MIN_SIZE ) { this . closeNav ( ) ; return ; } if ( newWidth > MAX_SIZE ) { newWidth = MAX_SIZE ; } this . storedWidth = newWidth ; setStored ( 'jdl.navbar.width' , '' + this . storedWidth ) ; if ( this . onResize ) { this . onResize ( ! this . isCollapsed , this . storedWidth ) ; } } ; startResize = ( e ) => { this . startWidth = this . isCollapsed ? COLLAPSED_SIZE : this . storedWidth ; this . mouseStartX = e . clientX ; window . addEventListener ( 'mousemove' , this . doResize , false ) ; window . addEventListener ( 'mouseup' , this . stopResize , false ) ; } ; closeSheet = ( sheet , cb ? ) => { this . body . removeClass ( 'is-showing-nav-overlay' ) ; this . nav . removeClass ( 'is-showing-sheet' ) ; this . delayRemoveClass ( $ ( sheet ) , 'is-showing' , 300 , cb ) ; } ; showNavOverlay = ( ) => { this . body . addClass ( 'is-showing-nav-overlay' ) ; } ; closeSheets = ( cb ? ) => { const sheets = $ ( '.Nav-Sheet.is-showing' ) ; sheets . each ( ( sheet ) => this . closeSheet ( sheet , cb ) ) ; } ; showSheet = ( sheet , cb ? ) => { this . closeSheets ( ) ; if ( this . isCollapsed ) { this . showNavOverlay ( ) ; } $ ( sheet ) . addClass ( 'is-showing' ) ; setTimeout ( ( ) => { this . nav . addClass ( 'is-showing-sheet' ) ; } , 30 ) ; if ( cb ) { setTimeout ( cb , 300 ) ; } } ; showMain = ( cb ? ) => { this . closeSheets ( cb ) ; } ; }