import { Classes , IconName , IProps } from '@blueprintjs/core' ; import clsx from 'clsx' ; import _ from 'lodash' ; import * as React from 'react' ; import { CSSTransition , TransitionGroup } from 'react-transition-group' ; import View from 'components/View' ; /**
 * React State.
 */ const initialState = { direction : 'push' as 'push' | 'pop' , stack : [ ] as IView [ ] } ; type State = Readonly < typeof initialState > ; /**
 * ViewStack Component.
 */ export default class ViewStack extends React . Component < Props , State > { public state : State = initialState ; class param props constructor ( props ) { super ( props ) ; this . state = { ... initialState , stack : [ props . initialView ] , } ; } return public render ( ) { const classes = clsx ( Classes . PANEL_STACK , `${ Classes . PANEL_STACK }-${ this . state . direction }` , this . props . className ) ; return ( < TransitionGroup className = { classes } component = "div" > { this . renderCurrentView ( ) } < /TransitionGroup>); } param view public popView : PopViewAction = ( view ) => { const { stack } = this . state ; if ( stack [ 0 ] !== view || stack . length <= 1 ) { return ; } const { onPop } = this . props ; if ( ! _ . isNil ( onPop ) ) { onPop ( view ) ; } this . setState ( ( state ) => ( { direction : 'pop' , stack : state . stack . filter ( ( v ) => v !== view ) , } ) ) ; } ; return private renderCurrentView ( ) { const { stack } = this . state ; if ( stack . length === 0 ) { return ; } const [ activeView , previousView ] = stack ; return ( < CSSTransition classNames = { Classes . PANEL_STACK } key = { stack . length } timeout = { 400 } > < View previousView = { previousView } onPop = { this . popView } onPush = { this . pushView } view = { activeView } / > < /CSSTransition>); } param view private pushView = ( view ) => { const { onPush } = this . props ; if ( ! _ . isNil ( onPush ) ) { onPush ( view ) ; } this . setState ( ( state ) => ( { direction : 'push' , stack : [ view , ... state . stack ] , } ) ) ; } ; } /**
 * React Props.
 */ interface Props extends IProps { initialView : IView ; onPop ? : ( view : IView ) => void ; onPush ? : ( view : IView ) => void ; onReady ? : PopViewAction ; } /**
 * A view part of a `ViewStack`
 */ export interface IView < P = { } > { component : React . ComponentType < P & IViewProps > ; icon ? : IconName ; props ? : P ; title ? : React . ReactNode ; } /**
 * Props added to each view.
 */ export interface IViewProps { popView ( ) : void ; pushView < P > ( view ) : void ; } /**
 * View popping action.
 */ export type PopViewAction = ( view : IView ) => void ;