hooks.layout.ts Maven / Gradle / Ivy
import {
defaultSidebarLayoutProps, ExpandEnable, ExpandState, LayoutContext, LayoutProps,
PartialLayoutProps
} from 'contexts/LayoutContext';
import merge from 'deepmerge';
import useKeyboardShortcut from 'hooks/shortcut';
import { useContext, useEffect, useRef } from 'react';
import Types from 'types/types';
import { prune } from 'utils/prune';
import { useMediaQuery, useTheme } from '@mui/material';
import { useLocalTypeState } from './state';
export const useLayoutContext = () => useContext(LayoutContext)
export const useBannerState = (withBanner?: boolean, shortcut?: KeyboardEvent['code']): [LayoutProps['bannerState'], LayoutProps['setBannerState']] => {
if (!withBanner)
return ['none', defaultSidebarLayoutProps.setBannerState]
else {
// @ts-ignore
const bannerTrigger = useMediaQuery(theme => theme?.breakpoints?.up('md'));
const { name, bannerProps: {enabled} } = useLayoutContext()
const location = `${name}.banner`
const defaultBannerState = () => withBanner ? enabled.expanded && "expanded" || enabled.collapsed && "collapsed" || "none" : "none"
const {value: bannerState, setValue: setBannerState} = useLocalTypeState(location, defaultBannerState())
if (shortcut){
useKeyboardShortcut(
(e) => { setBannerState("none") },
{code: shortcut, ctrlKey: true, altKey: true}
)
useKeyboardShortcut(
(e) => { setBannerState(state => nextBannerState(state, enabled)) },
{code: shortcut, ctrlKey: true}
)
}
const initialRender = useRef(false)
useEffect(() => {
if (initialRender.current){
if (withBanner) {
if (bannerTrigger)
setBannerState("expanded")
else
setBannerState("collapsed")
}
}
initialRender.current = true
}, [bannerTrigger])
return [bannerState, setBannerState]
}
}
export function nextBannerState(state: ExpandState, enabled: ExpandEnable): ExpandState {
switch (state) {
case enabled.none && "expanded": return "none"
case enabled.collapsed && "expanded": return "collapsed"
case enabled.expanded && "collapsed": return "expanded"
case enabled.none && "collapsed": return "none"
case enabled.expanded && "none": return "expanded"
case enabled.collapsed && "none": return "collapsed"
default: return state
}
}
export const useLayoutConfig = (layoutProps: PartialLayoutProps, reset?: boolean) => {
const ctx = useLayoutContext()
const theme = useTheme()
if (reset) {
const defaultBannerConfig: PartialLayoutProps = {
bannerProps: {
// @ts-ignore
height: theme.components?.banner?.height
},
}
return joinAll([defaultSidebarLayoutProps, defaultBannerConfig, layoutProps])
} else {
return joinAll([ctx, layoutProps])
}
}
function joinAll(configs: PartialLayoutProps[]): LayoutProps {
return Types.as(
merge.all(
configs.map((config, index) => index == 0 ? config : prune(config, {undefined: true}))
)
)
}