jsx import * as React from 'react' ; import { styled , useIsRTL } from '@workday/canvas-kit-react/common' ; import { css , CSSObject , jsx , keyframes } from '@emotion/core' ; import { IconButton , IconButtonProps } from '@workday/canvas-kit-react/button' ; import { space , colors , depth } from '@workday/canvas-kit-react/tokens' ; import { transformationImportIcon } from '@workday/canvas-system-icons-web' ; export type SidePanelVariant = 'standard' | 'alternate' ; export type SidePanelTransitionStates = 'collapsed' | 'collapsing' | 'expanded' | 'expanding' ; export interface SidePanelProps extends React . HTMLAttributes < HTMLDivElement > { default as ? : React . ElementType ; default collapsedWidth ? : number | string ; default expanded ? : boolean ; default expandedWidth ? : number | string ; default origin ? : 'left' | 'right' ; param boolean onExpandedChange ? : ( expanded ? : boolean ) => void ; param SidePanelTransitionStates onStateTransition ? : ( state ? : SidePanelTransitionStates ) => void ; default variant ? : SidePanelVariant ; param boolean touched : boolean ; } const createKeyframes = ( from , to ) => { const normalized = { from : typeof from === 'number' ? from + 'px' : from , to : typeof to === 'number' ? to + 'px' : to , } ; return keyframes `
    from {
      width: ${ normalized . from };
      min-width: ${ normalized . from };
      max-width: ${ normalized . from };
    } to {
      width: ${ normalized . to };
      min-width: ${ normalized . to };
      max-width: ${ normalized . to };
    }
  ` ; } ; const containerVariantStyle = { alternate : { backgroundColor : colors . frenchVanilla100 , ... depth [ 3 ] , } , standard : { backgroundColor : colors . soap100 , } , } ; const Panel = styled ( 'section' ) < Pick < SidePanelProps , 'as' > > ( { overflow : 'hidden' , position : 'relative' , boxSizing : 'border-box' , height : '100%' , } ) ; export const SidePanelContext = React . createContext ( { state : 'expanded' , origin : 'left' , } ) ; const SidePanel = ( { as = 'section' , children , collapsedWidth = 64 , expanded = true , expandedWidth = 320 , onAnimationEnd , onAnimationStart , onExpandedChange , onStateTransition , origin = 'left' , variant = 'standard' , touched , ... elemProps } ) => { const [ state , setState ] = React . useState < SidePanelTransitionStates > ( expanded ? 'expanded' : 'collapsed' ) ; React . useEffect ( ( ) => { if ( typeof onExpandedChange !== 'undefined' ) { onExpandedChange ( expanded ) ; } } , [ expanded , onExpandedChange ] ) ; React . useEffect ( ( ) => { if ( typeof onStateTransition !== 'undefined' ) { onStateTransition ( state ) ; } } , [ state , onStateTransition ] ) ; const motion = { collapse : createKeyframes ( expandedWidth , collapsedWidth ) , expand : createKeyframes ( collapsedWidth , expandedWidth ) , } ; const handleAnimationEnd = ( event ) => { if ( event . currentTarget === event . target ) { if ( event . animationName === motion . collapse . name ) { setState ( 'collapsed' ) ; } if ( event . animationName === motion . expand . name ) { setState ( 'expanded' ) ; } } if ( typeof onAnimationEnd !== 'undefined' ) { onAnimationEnd ( event ) ; } } ; const handleAnimationStart = ( event ) => { if ( event . currentTarget === event . target ) { if ( event . animationName === motion . collapse . name || event . animationName === motion . expand . name ) { setState ( expanded ? 'expanding' : 'collapsing' ) ; } } if ( typeof onAnimationStart !== 'undefined' ) { onAnimationStart ( event ) ; } } ; return ( < Panel as = { as } css = { [ { width : expanded ? expandedWidth : collapsedWidth , maxWidth : expanded ? expandedWidth : collapsedWidth , animation : touched ? `${ expanded ? motion . expand : motion . collapse } 200ms ease-out` : undefined , } , containerVariantStyle [ variant ] , ] } onAnimationEnd = { handleAnimationEnd } onAnimationStart = { handleAnimationStart } { ... elemProps } > < SidePanelContext . Provider value = { { state , origin , } } > { children } < /SidePanelContext.Provider> < /Panel>); } ; export type ToggleButtonProps = Omit < IconButtonProps , 'aria-label' > ; /**
 * A toggle button styled specifically for the side panel container.
 */ const ToggleButton = ( { variant = 'plain' , icon = transformationImportIcon , ... rest } ) => { const context = React . useContext ( SidePanelContext ) ; const useRTLOrigin = ( ) => { const isRTL = useIsRTL ( ) ; if ( isRTL ) { return context . origin === 'left' ? 'right' : 'left' ; } return context . origin ; } ; const rtlOrigin = useRTLOrigin ( ) ; const buttonStyle = css ( { position : 'absolute' , top : space . m , right : context . state === 'collapsed' ? 0 : rtlOrigin === 'left' ? space . s : undefined , left : context . state === 'collapsed' ? 0 : rtlOrigin === 'right' ? space . s : undefined , margin : context . state === 'collapsed' ? 'auto' : 0 , transform : context . state === 'collapsed' || context . state === 'collapsing' ? `scaleX(${ rtlOrigin === 'left' ? '1' : '-1' })` : `scaleX(${ rtlOrigin === 'left' ? '-1' : '1' })` , } ) ; return < IconButton type = "button" css = { buttonStyle } icon = { icon } variant = { variant } { ... rest } />; } ; SidePanel . ToggleButton = ToggleButton ; export default SidePanel ;