import * as React from "react" ; import { BlankMaskRenderer , ChildrenRenderer , MayersRenderer , NavbarRenderer , SidepanelRenderer , ViewsRenderer } from "./SceneRenderer/Items" ; import { PureComponent , SyntheticEvent , ReactNode , RefObject } from "react" ; import { Props as MayerProps } from "./Mayer" ; import Sidepanel from "./Sidepanel" ; import { AnimationType , NavbarMenu , SidepanelConfig } from "./Airr" ; import { ViewsConfigItem } from "./Scene" ; export type NavbarProp = 1 | true | - 1 | 0 | false ; export type ViewsArray = ViewsConfigItem < any > [ ] ; export interface CoreSceneProps { /**
     * The name of the scene. Must be unique among others views in parent scene. Will be used as identification string
     */ name : string ; /**
     * Name of the active view
     */ activeViewName ? : string ; /**
     * Boolean telling if GUI should be disabled meaning no user actions, events are allowed.
     * GUI is disabled via absolute positioned, not visible div that has the biggest z-Index
     */ GUIDisabled ? : boolean ; /**
     * React element to be placed in GUI disabling div
     */ GUIDisableCover ? : ReactNode ; /**
     * Type of animation to perform when switching views
     */ animation ? : AnimationType ; /**
     * Time of views changing animation in miliseconds
     */ animationTime ? : number ; /**
     * Specify if navbar is present (1,true) or not (0,false). Or maybe hidden (-1)
     */ navbar ? : NavbarProp ; /**
     * Height of the navbar in pixels
     */ navbarHeight ? : number ; /**
     * Navbar menu is placed on the right most side. Might contain "toggleSidepanel" button or any custom buttons list.
     */ navbarMenu ? : NavbarMenu ; /**
     * Extra, space separated, navbar's class list
     */ navbarClass ? : string ; /**
     * Boolean specifing if navbar renders BackButton. Placed by default on the left side of navbar.
     */ backButton ? : boolean ; /**
     * Do you need to still show backButton even if scene is rendering first view from stack?
     */ backButtonOnFirstView ? : boolean ; /**
     * Function that will handle back button click events
     */ handleBackButton ? : ( e : SyntheticEvent < HTMLElement > ) => void ; /**
     * Function that will handle back button clicks events on when first view in stack is active
     */ handleBackBehaviourOnFirstView ? : ( ) => void ; /**
     * Is this view active in parent scene. Readonly.
     */ active ? : boolean ; /**
     * Sidepanels declaration. Must contain two properties: `type` and `props`
     **/ sidepanel ? : SidepanelConfig < any > ; /**
     * This function will be called when sidepanel changes it's visibility.
     * It's argument will be isShown bool.
     */ sidepanelVisibilityCallback ? ( isShown ) : void ; /**
     * Array of `views`. Every view object declaration must contain two properties: `type` and `props`.
     */ views ? : ViewsArray ; /**
     * Array of `mayers` objects that will be render into this Scene. Must contain special Mayer class properties.
     * To check the possible values of properties go to Mayer declaration.
     */ mayers ? : MayerProps [ ] ; /**
     * Title that will be use in parent Scene navbar title section
     */ title ? : ReactNode ; /**
     * Extra, space separated classes names to use upon first div element.
     */ className ? : string ; /**
     * Children prop
     */ children ? : ReactNode ; /**
     * Inner, private prop for manipulating navbar title. Do not set manually.
     */ mockTitleName ? : string ; key ? : string ; ref ? : React . LegacyRef < PureComponent > ; } export interface Props extends CoreSceneProps { /**
     * React component's ref object
     */ refCOMPSidepanel : RefObject < Sidepanel > ; /**
     * React ref to dom object
     */ refDOM : RefObject < HTMLDivElement > ; /**
     * React ref to dom object
     */ refDOMNavbar : RefObject < HTMLDivElement > ; /**
     * Object of React refs components specified under string keys
     */ refsCOMPViews : { [ name ] : RefObject < PureComponent > ; } ; /**
     * React component's ref object
     */ refDOMContainer : RefObject < HTMLDivElement > ; /**
     * Inner, private prop with containers height information
     */ containersHeight : number ; } export const sceneDefaultProps = { name : "" , activeViewName : null , GUIDisabled : false , GUIDisableCover : null , animation : "slide" , animationTime : 300 , navbar : false , navbarHeight : 48 , navbarMenu : null , navbarClass : "" , backButton : false , backButtonOnFirstView : false , handleBackButton : null , handleBackBehaviourOnFirstView : null , active : false , sidepanel : null , views : [ ] , mayers : [ ] , title : "" , className : "" , sidepanelVisibilityCallback : null , children : null , mockTitleName : null } ; export default class SceneRenderer extends PureComponent < Props > { static defaultProps : Props = { ... sceneDefaultProps , refCOMPSidepanel : null , refDOM : null , refDOMNavbar : null , refsCOMPViews : null , refDOMContainer : null , mockTitleName : "" , containersHeight : null } ; /**
     * Mayers Components refferencies
     */ mayersCompsRefs = { } ; param { string } viewName returns { Number } getViewIndex ( viewName ) { return this . props . views . findIndex ( ( config ) : boolean => config . props . name === viewName ) ; } param { object } e returns { void } handleBackButton = ( e ) : void => { const backBtn = e . currentTarget ; backBtn . classList . add ( "clicked" ) ; setTimeout ( ( ) : void => { backBtn . classList . remove ( "clicked" ) ; } , 300 ) ; if ( this . getViewIndex ( this . props . activeViewName ) === 0 && this . props . handleBackBehaviourOnFirstView ) { return this . props . handleBackBehaviourOnFirstView ( ) ; } if ( this . props . handleBackButton ) { this . props . handleBackButton ( e ) ; } else { console . warn ( "[] Back button handler was not specified." ) ; } } ; param { object } e returns { void } handleMenuButtonToggleSidepanel = ( e ) : void => { if ( this . props . refCOMPSidepanel && this . props . refCOMPSidepanel . current ) { this . props . refCOMPSidepanel . current . isShown ( ) ? this . props . refCOMPSidepanel . current . hide ( ) : this . props . refCOMPSidepanel . current . show ( ) ; } } ; checkValidActiveView = ( ) : boolean => { const isAnyViewActive = this . props . views . some ( ( view ) : boolean => view . props . name === this . props . activeViewName ) ; if ( ! isAnyViewActive ) { console . warn ( "[] No view was set as active" + ( this . props . name && " in Scene named `" + this . props . name + "`" ) + "." ) ; } return Boolean ( isAnyViewActive ) ; } ; render ( ) { let className = "airr-view airr-scene" ; this . props . active && ( className += " active" ) ; this . props . className && ( className += " " + this . props . className ) ; this . checkValidActiveView ( ) ; const activeViewIndex = this . getViewIndex ( this . props . activeViewName ) ; let mockViewTitle ; if ( this . props . mockTitleName ) { const mockViewIndex = this . getViewIndex ( this . props . mockTitleName ) ; if ( mockViewIndex >= 0 ) { const mockView = this . props . views [ mockViewIndex ] ; if ( mockView . props . title ) { mockViewTitle = mockView . props . title ; } } } return ( < div className = { className } ref = { this . props . refDOM } > < div className = "airr-content-wrap" > < NavbarRenderer navbar = { this . props . navbar } activeViewIndex = { activeViewIndex } backButtonOnFirstView = { this . props . backButtonOnFirstView } backButton = { this . props . backButton } handleBackButton = { this . handleBackButton } navbarMenu = { this . props . navbarMenu } hasSidepanel = { Boolean ( this . props . sidepanel ) } handleMenuButtonToggleSidepanel = { this . handleMenuButtonToggleSidepanel } navbarClass = { this . props . navbarClass } mockViewTitle = { mockViewTitle } activeViewTitle = { this . props . views [ activeViewIndex ] && this . props . views [ activeViewIndex ] . props . title } refDOMNavbar = { this . props . refDOMNavbar } navbarHeight = { this . props . navbarHeight } / > < ViewsRenderer className = { this . props . animation ? this . props . animation + "-animation" : "" } refsCOMPViews = { this . props . refsCOMPViews } activeViewName = { this . props . activeViewName } views = { this . props . views } refDOMContainer = { this . props . refDOMContainer } containersHeight = { this . props . containersHeight } / > < /div> < ChildrenRenderer { ... this . props } > { this . props . children } < /ChildrenRenderer> { this . props . sidepanel && ( < SidepanelRenderer type = { this . props . sidepanel . type } refCOMPSidepanel = { this . props . refCOMPSidepanel } visibilityCallback = { this . props . sidepanelVisibilityCallback } sceneHasMayers = { Boolean ( this . props . mayers . length ) } props = { this . props . sidepanel . props } / > ) } < MayersRenderer mayers = { this . props . mayers } /> < BlankMaskRenderer GUIDisabled = { this . props . GUIDisabled } GUIDisableCover = { this . props . GUIDisableCover } / > < /div>); } }