1
0
Fork 0
freesewing/sites/shared/context/mobile-menubar-context.mjs

134 lines
4.3 KiB
JavaScript
Raw Normal View History

import React, { useState, useContext, useEffect, useCallback } from 'react'
2023-06-29 17:29:13 +00:00
/**
* A context for holding elements from various places that should be presented
* cohesively in mobile, e.g. sidebar menus and toolbars
*
* There are two ways of presenting menus on the menubar:
* 1) Menus: These are larger interfaces that should be placed in a modal on mobile
* They will be presented as buttons on the menubar which will open a modal when clicked
* example: workbench nav menu
* 2) Actions: These are smaller and will be presented directly on the menubar
* example: zoom buttons
*/
export const MobileMenubarContext = React.createContext(null)
2023-06-29 17:29:13 +00:00
/**
* A provider for the {@link MobileMenubarContext}
* */
export const MobileMenubarContextProvider = ({ children }) => {
const [menus, setMenus] = useState({})
const [actions, setActions] = useState({})
2023-06-29 17:29:13 +00:00
/**
* Add a menu to the menubar
* @type Function
* @param {String} key - the key for this menu in the menus object
* @param {Object} menuProps - the properties of this menu
* @param {React.Component} menuProps.Icon - the icon for the menu button
* @param {ReactElement} menuProps.menuContent - the content of the menu to be displayed in a modal
* @param {Number} menuProps.order - the sort order of this menu
* */
const addMenu = useCallback(
(key, menuProps) => {
setMenus((oldMenus) => ({ ...oldMenus, [key]: menuProps }))
},
[setMenus]
)
2023-06-29 17:29:13 +00:00
/**
* Remove a menu from the menubar
* @type Function
* @param {String} key - the key that was used to add the menu to the menubar
*/
const removeMenu = useCallback(
(key) => {
setMenus((oldMenus) => {
const newMenus = { ...oldMenus }
delete newMenus[key]
return newMenus
})
},
[setMenus]
)
2023-06-29 17:29:13 +00:00
/**
* Add an action to the menubar
* @param {String} key - the key for this action in the actions object
* @param {Object} actionProps - the properties of this action
* @param {ReactElement} actionProps.actionContent - the content of the action to be displayed in a modal
* @param {Number} actionProps.order - the sort order of this action
*/
const addAction = useCallback(
2023-06-29 17:29:13 +00:00
(key, actionProps) => {
setActions((oldActions) => ({
...oldActions,
2023-06-29 17:29:13 +00:00
[key]: actionProps,
}))
},
[setActions]
)
2023-06-29 17:29:13 +00:00
/**
* Remove an action from the menubar
* @type Function
* @param {String} key - the key that was used to add the action to the menubar
*/
const removeAction = useCallback(
(key) => {
setActions((oldActions) => {
const newActions = { ...oldActions }
delete newActions[key]
return newActions
})
},
[setActions]
)
const value = {
menus,
addMenu,
removeMenu,
actions,
addAction,
removeAction,
}
return <MobileMenubarContext.Provider value={value}>{children}</MobileMenubarContext.Provider>
}
2023-06-29 17:29:13 +00:00
/**
* A hook to add content as a menu in the mobile menubar and handle remove on unmount
* @param {String} key - the key for this menu in the menus object
* @param {Object} menuProps - the properties of this menu
* @param {React.Component} menuProps.Icon - the icon for the menu button
* @param {ReactElement} menuProps.menuContent - the content of the menu to be displayed in a modal
* @param {Number} menuProps.order - the sort order of this menu
* */
export const useMobileMenu = (key, menuProps) => {
const { addMenu, removeMenu } = useContext(MobileMenubarContext)
useEffect(() => {
addMenu(key, menuProps)
return () => removeMenu(key)
}, [menuProps, key, addMenu, removeMenu])
}
2023-06-29 17:29:13 +00:00
/**
* A hook to add content as an action to the mobile menubar and handle removal on unmount
* @param @param {String} key - the key for this action in the actions object
* @param {Object} actionProps - the properties of this action
* @param {ReactElement} actionProps.actionContent - the content of the action to be displayed in a modal
* @param {Number} actionProps.order - the sort order of this action
*/
export const useMobileAction = (key, content) => {
const { addAction, removeAction } = useContext(MobileMenubarContext)
useEffect(() => {
addAction(key, content)
return () => removeAction(key)
2023-06-29 16:41:11 +00:00
}, [...Object.values(content), key, addAction, removeAction])
}