import React from "react" import Layouts from "@layouts" export default class Layout extends React.PureComponent { state = { layoutType: "default", renderError: null, } events = { "layout.forceUpdate": () => { this.forceUpdate() }, "layout.animations.fadeOut": () => { if (app.cores.settings.get("reduceAnimations")) { console.warn( "Skipping fadeIn animation due to `reduceAnimations` setting", ) return false } const transitionLayer = document.getElementById("transitionLayer") if (!transitionLayer) { console.warn( "transitionLayer not found, no animation will be played", ) return false } transitionLayer.classList.add("fade-opacity-leave") }, "layout.animations.fadeIn": () => { if (app.cores.settings.get("reduceAnimations")) { console.warn( "Skipping fadeOut animation due to `reduceAnimations` setting", ) return false } const transitionLayer = document.getElementById("transitionLayer") if (!transitionLayer) { console.warn( "transitionLayer not found, no animation will be played", ) return false } transitionLayer.classList.remove("fade-opacity-leave") }, } componentDidMount() { // register events Object.keys(this.events).forEach((event) => { window.app.eventBus.on(event, this.events[event]) }) if (app.isMobile) { this.layoutInterface.toggleMobileStyle(true) } if (app.cores.settings.get("reduceAnimations")) { this.layoutInterface.toggleRootContainerClassname( "reduce-animations", true, ) } this.layoutInterface.toggleCenteredContent(true) } componentWillUnmount() { // unregister events Object.keys(this.events).forEach((event) => { window.app.eventBus.off(event, this.events[event]) }) } componentDidCatch(info, stack) { this.setState({ renderError: { info, stack } }) } layoutInterface = (window.app.layout = { set: (layout) => { if (typeof Layouts[layout] !== "function") { return console.error("Layout not found") } console.log(`Setting layout to [${layout}]`) return this.setState({ layoutType: layout, }) }, toggleTotalWindowHeight: (to) => { return this.layoutInterface.toggleRootContainerClassname( "total-window-height", to, ) }, toggleCenteredContent: (to) => { return this.layoutInterface.toggleRootContainerClassname( "centered-content", to, ) }, toggleRootScaleEffect: (to) => { return this.layoutInterface.toggleRootContainerClassname( "root-scale-effect", to, ) }, toggleMobileStyle: (to) => { return this.layoutInterface.toggleRootContainerClassname( "mobile", to, ) }, toggleReducedAnimations: (to) => { return this.layoutInterface.toggleRootContainerClassname( "reduce-animations", to, ) }, toggleTopBarSpacer: (to) => { return this.layoutInterface.toggleRootContainerClassname( "top-bar-spacer", to, ) }, toggleDisableTopLayoutPadding: (to) => { return this.layoutInterface.toggleRootContainerClassname( "disable-top-layout-padding", to, ) }, togglePagePanelSpacer: (to) => { return this.layoutInterface.toggleRootContainerClassname( "page-panel-spacer", to, ) }, toggleCompactMode: (to) => { return this.layoutInterface.toggleRootContainerClassname( "compact-mode", to, ) }, toggleRootContainerClassname: (classname, to) => { const root = document.documentElement if (!root) { console.error("root not found") return false } to = typeof to === "boolean" ? to : !root.classList.contains(classname) if (root.classList.contains(classname) === to) { // ignore return false } if (to === true) { root.classList.add(classname) } else { root.classList.remove(classname) } }, rootContainerHasClassname: (classname) => { const root = document.documentElement if (!root) { console.error("root not found") return false } return root.classList.contains(classname) }, scrollTo: (to) => { const content_layout = document.getElementById("content_layout") if (!content_layout) { console.error("content_layout not found") return false } content_layout.scrollTo({ ...to, behavior: "smooth", }) }, }) render() { let layoutType = this.state.layoutType const layoutComponentProps = { ...this.props.bindProps, ...this.state, } if (this.state.renderError) { if (this.props.staticRenders?.RenderError) { return React.createElement( this.props.staticRenders?.RenderError, { error: this.state.renderError }, ) } return JSON.stringify(this.state.renderError) } const Layout = Layouts[layoutType] if (!Layout) { return app.eventBus.emit( "runtime.crash", new Error(`Layout type [${layoutType}] not found`), ) } return {this.props.children} } }