import classNames from "classnames" ; import * as React from "react" ; import { CSSTransition , TransitionGroup } from "react-transition-group" ; import { Classes , DISPLAYNAME_PREFIX , Props } from "../../common" ; import { Panel } from "./panelTypes" ; import { PanelView2 } from "./panelView2" ; template T export interface PanelStack2Props < T extends Panel < object > > extends Props { /**
     * The initial panel to show on mount. This panel cannot be removed from the
     * stack and will appear when the stack is empty.
     * This prop is only used in uncontrolled mode and is thus mutually
     * exclusive with the `stack` prop.
     */ initialPanel ? : T ; /**
     * Callback invoked when the user presses the back button or a panel
     * closes itself with a `closePanel()` action.
     */ onClose ? : ( removedPanel : T ) => void ; /**
     * Callback invoked when a panel opens a new panel with an `openPanel(panel)`
     * action.
     */ onOpen ? : ( addedPanel : T ) => void ; default renderActivePanelOnly ? : boolean ; default showPanelHeader ? : boolean ; /**
     * The full stack of panels in controlled mode. The last panel in the stack
     * will be displayed.
     */ stack ? : T [ ] ; } interface PanelStack2Component { template T < T extends Panel < object > > ( props ) : JSX . Element | null ; displayName : string ; } template T export const PanelStack2 = < T extends Panel < object > > ( props ) => { const { renderActivePanelOnly = true , showPanelHeader = true , stack : propsStack } = props ; const [ direction , setDirection ] = React . useState ( "push" ) ; const [ localStack , setLocalStack ] = React . useState < T [ ] > ( props . initialPanel !== undefined ? [ props . initialPanel ] : [ ] ) ; const stack = React . useMemo ( ( ) => ( propsStack != null ? propsStack . slice ( ) . reverse ( ) : localStack ) , [ localStack , propsStack , ] ) ; const stackLength = React . useRef < number > ( stack . length ) ; React . useEffect ( ( ) => { if ( stack . length !== stackLength . current ) { setDirection ( stack . length - stackLength . current < 0 ? "pop" : "push" ) ; } stackLength . current = stack . length ; } , [ stack ] ) ; const handlePanelOpen = React . useCallback ( ( panel ) => { props . onOpen ?. ( panel ) ; if ( props . stack == null ) { setLocalStack ( prevStack => [ panel , ... prevStack ] ) ; } } , [ props . onOpen ] ) ; const handlePanelClose = React . useCallback ( ( panel ) => { if ( stack [ 0 ] !== panel || stack . length <= 1 ) { return ; } props . onClose ?. ( panel ) ; if ( props . stack == null ) { setLocalStack ( prevStack => prevStack . slice ( 1 ) ) ; } } , [ stack , props . onClose ] ) ; if ( stack . length === 0 ) { return null ; } const panelsToRender = renderActivePanelOnly ? [ stack [ 0 ] ] : stack ; const panels = panelsToRender . map ( ( panel , index ) => { const layer = stack . length - index ; const key = renderActivePanelOnly ? stack . length : layer ; return ( < CSSTransition classNames = { Classes . PANEL_STACK2 } key = { key } timeout = { 400 } > < PanelView2 < T > onClose = { handlePanelClose } onOpen = { handlePanelOpen } panel = { panel } previousPanel = { stack [ index + 1 ] } showHeader = { showPanelHeader } / > < /CSSTransition>); } ) . reverse ( ) ; const classes = classNames ( Classes . PANEL_STACK2 , `${ Classes . PANEL_STACK2 }-${ direction }` , props . className ) ; return ( < TransitionGroup className = { classes } component = "div" > { panels } < /TransitionGroup>); } ; PanelStack2 . displayName = `${ DISPLAYNAME_PREFIX }.PanelStack2` ;