import React from 'react' import type { DisplayOnType } from '.' import { BREAKPOINT_DESKTOP, DISPLAY_ON_DESKTOP, DISPLAY_ON_PHONE } from '.' import type { COLLAPSE_ABOVE, COLLAPSE_BELOW } from '../more-menu' import type { IconProps } from '@planview/pv-icons' export type ResizeContextType = { initialized: boolean breakpoint: string showLabels: boolean showSeparators: boolean shouldDisplay: (displayOn: DisplayOnType) => boolean } const ResizeContext = React.createContext({ initialized: false, breakpoint: BREAKPOINT_DESKTOP, showLabels: true, showSeparators: true, shouldDisplay: () => true, }) export default ResizeContext type WrappingParentContextType = { wrappedInToolbarParent: boolean } export const WrappingParentContext = React.createContext({ wrappedInToolbarParent: false, }) type GenericContextType = { displayOn: DisplayOnType showMoreMenuItem: boolean } export const GenericContext = React.createContext({ displayOn: DISPLAY_ON_DESKTOP, showMoreMenuItem: false, }) type MainNavigationContextType = { wrappedInNavigation: boolean } export const MainNavigationContext = React.createContext({ wrappedInNavigation: false, }) export const useMainNavigationContext = () => React.useContext(MainNavigationContext) export type UserMenuConfig = { trigger: React.JSX.Element children: React.ReactNode } type UserMenuContextType = { add: (config: UserMenuConfig) => void remove: () => void } export const UserMenuContext = React.createContext({ add: () => {}, remove: () => {}, }) export const useUserMenu = () => React.useContext(UserMenuContext) export type MoreMenuChildType = React.ReactElement type ChildEntry = { child: MoreMenuChildType id: string displayOn: DisplayOnType } type CustomMoreMenuState = { children: MoreMenuChildType[] icon?: React.ReactElement collapse: typeof COLLAPSE_ABOVE | typeof COLLAPSE_BELOW } type MoreMenuContextType = { inMoreMenuSection: boolean dispatch: (value: ActionType) => void registeredItems: ChildEntry[] customMoreMenu: CustomMoreMenuState | null } export const MoreMenuContext = React.createContext({ inMoreMenuSection: false, dispatch: () => {}, registeredItems: [], customMoreMenu: null, }) type SectionState = { registeredItems: ChildEntry[] dropdownOpen: boolean customMoreMenu: CustomMoreMenuState | null } const InitialState: SectionState = { registeredItems: [], dropdownOpen: false, customMoreMenu: null, } type RegisterAction = { type: 'REGISTER_CHILD' id: string child: MoreMenuChildType displayOn: DisplayOnType } type RegisterMoreMenuAction = { type: 'REGISTER_MORE_MENU_CONTENT' children: MoreMenuChildType[] collapse: typeof COLLAPSE_ABOVE | typeof COLLAPSE_BELOW icon?: React.ReactElement } type UnRegisterMoreMenuAction = { type: 'UNREGISTER_MORE_MENU_CONTENT' } type UpdateAction = { type: 'UPDATE_CHILD' id: string child: MoreMenuChildType displayOn: DisplayOnType } type UnRegisterAction = { type: 'UNREGISTER_CHILD' id: string } type ClearAction = { type: 'CLEAR' } export type ActionType = | RegisterAction | ClearAction | UnRegisterAction | UpdateAction | RegisterMoreMenuAction | UnRegisterMoreMenuAction type ProviderProps = { children: React.ReactNode } const reducer = (state: SectionState, action: ActionType): SectionState => { switch (action.type) { case 'REGISTER_CHILD': { const found = state.registeredItems.find( (c: ChildEntry) => c.id === action.id ) if (found) { console.warn('child already registered', action.id) return state } const items = [...state.registeredItems] items.push({ id: action.id, child: action.child, displayOn: action.displayOn, }) return { ...state, registeredItems: items, } } case 'UPDATE_CHILD': return { ...state, registeredItems: state.registeredItems.map((c) => c.id === action.id ? { ...c, child: action.child, displayOn: action.displayOn, } : c ), } case 'UNREGISTER_CHILD': { const newState = { ...state, registeredItems: state.registeredItems.filter( (c) => c.id !== action.id ), } return newState } case 'CLEAR': return InitialState case 'REGISTER_MORE_MENU_CONTENT': return { ...state, customMoreMenu: action, } case 'UNREGISTER_MORE_MENU_CONTENT': return { ...state, customMoreMenu: null, } default: return state } } export const MoreMenuProvider = ({ children }: ProviderProps) => { const [state, dispatch] = React.useReducer(reducer, InitialState) React.useEffect(() => () => dispatch({ type: 'CLEAR' }), []) const context = React.useMemo( () => ({ inMoreMenuSection: true, dispatch, customMoreMenu: state.customMoreMenu, registeredItems: state.registeredItems.filter( (c) => c.displayOn !== DISPLAY_ON_PHONE ), }), [state, dispatch] ) return ( {children} ) }