@massds/mayflower-react
Version:
React versions of Mayflower design system UI components
190 lines (165 loc) • 5.24 kB
JavaScript
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, 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);
};