UNPKG

@massds/mayflower-react

Version:

React versions of Mayflower design system UI components

173 lines (169 loc) 5.16 kB
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } import React from "react"; import useEventListener from "../hooks/use-event-listener.mjs"; import useWindowWidth from "../hooks/use-window-width.mjs"; export function mainNavReducer(state, action) { const newState = _extends({}, state); switch (action.type) { case 'setButtonExpanded': { if (newState.items[action.index]) { newState.items[action.index] = _extends({}, newState.items[action.index], { buttonExpanded: action.status }); } break; } case 'setIsOpen': { if (action.status) { newState.isOpen = action.status; } break; } case 'setIsItemOpen': { if (newState.items[action.index]) { newState.items[action.index] = _extends({}, newState.items[action.index], { isOpen: action.status }); } break; } case 'hide': { newState.items = newState.items.map(() => ({ buttonExpanded: false, isOpen: false })); newState.isOpen = false; if (Object.prototype.hasOwnProperty.call(action, 'index') && newState.items[action.index]) { newState.items[action.index] = { buttonExpanded: true, isOpen: true }; } break; } case 'show': { if (Object.prototype.hasOwnProperty.call(action, 'index') && state.items[action.index]) { newState.items[action.index] = { buttonExpanded: true, isOpen: true }; } newState.isOpen = true; break; } default: return newState; } return newState; } export const initMainNavState = items => { const initialList = { isOpen: false, items: items.map(() => ({ buttonExpanded: false, isOpen: false })) }; return initialList; }; // Custom hook that sets up the Header's MainNav context. // This isn't placed in the hooks file because it uses mainNavReducer. export const useHeaderMainNav = items => { const windowWidth = useWindowWidth(); const breakpoint = 840; const _React$useReducer = React.useReducer(mainNavReducer, items, initMainNavState), state = _React$useReducer[0], dispatch = _React$useReducer[1]; const setButtonExpanded = React.useCallback(_ref => { let index = _ref.index, status = _ref.status; dispatch({ type: 'setButtonExpanded', index: index, status: status }); }, []); const setIsOpen = React.useCallback(_ref2 => { let index = _ref2.index, status = _ref2.status; dispatch({ type: 'setIsItemOpen', index: index, status: status }); }, []); // Hides all Nav Items. If you pass an object with an index key, // all nav items except the one that matches the index will be hidden. const hide = React.useCallback(function (options) { if (options === void 0) { options = {}; } const _options = options, _options$index = _options.index, index = _options$index === void 0 ? undefined : _options$index; if (windowWidth) { const body = document.querySelector('body'); const submenuClass = 'show-submenu'; body.classList.remove(submenuClass); if (windowWidth <= breakpoint) { dispatch({ type: 'hide', index: index, status: false }); } else { // @todo animate here! dispatch({ type: 'hide', index: index, status: false }); } } }, [windowWidth]); // Shows the NavItem with the passed index number. const show = React.useCallback(function (options) { if (options === void 0) { options = {}; } const _options2 = options, index = _options2.index; const body = document.querySelector('body'); const submenuClass = 'show-submenu'; body.classList.add(submenuClass); if (windowWidth <= breakpoint) { dispatch({ type: 'show', index: index }); } else { // @todo animate here! dispatch({ type: 'show', index: index }); } }, [windowWidth]); // Restrict the available functionality for NavItem components to the following. return React.useMemo(() => _extends({}, state, { setButtonExpanded: setButtonExpanded, setIsOpen: setIsOpen, hide: hide, show: show }), [state]); }; export const useHeaderNavKeydown = (element, onKeyDown) => { useEventListener('keydown', onKeyDown, element); }; export const useHeaderNavMouseEvents = (element, onMouseEnter, onMouseLeave) => { useEventListener('mouseenter', onMouseEnter, element); useEventListener('mouseleave', onMouseLeave, element); }; export const useHeaderNavButtonEffects = (element, onClick) => { useEventListener('click', onClick, element); };