Page MenuHomec4science

useMenu.js
No OneTemporary

File Metadata

Created
Fri, Jan 10, 21:56

useMenu.js

import _extends from "@babel/runtime/helpers/esm/extends";
import * as React from 'react';
import { unstable_useForkRef as useForkRef } from '@mui/utils';
import { defaultListboxReducer, useListbox, ActionTypes } from '../ListboxUnstyled';
function stateReducer(state, action) {
if (action.type === ActionTypes.blur || action.type === ActionTypes.optionHover || action.type === ActionTypes.setValue) {
return state;
}
const newState = defaultListboxReducer(state, action);
if (action.type !== ActionTypes.setHighlight && newState.highlightedValue === null && action.props.options.length > 0) {
return _extends({}, newState, {
highlightedValue: action.props.options[0]
});
}
return newState;
}
export default function useMenu(parameters = {}) {
const {
listboxRef: listboxRefProp,
open = false,
onClose,
listboxId
} = parameters;
const [menuItems, setMenuItems] = React.useState({});
const listboxRef = React.useRef(null);
const handleRef = useForkRef(listboxRef, listboxRefProp);
const registerItem = React.useCallback((id, metadata) => {
setMenuItems(previousState => {
const newState = _extends({}, previousState);
newState[id] = metadata;
return newState;
});
}, []);
const unregisterItem = React.useCallback(id => {
setMenuItems(previousState => {
const newState = _extends({}, previousState);
delete newState[id];
return newState;
});
}, []);
const {
getOptionState,
getOptionProps,
getRootProps,
highlightedOption,
setHighlightedValue: setListboxHighlight
} = useListbox({
options: Object.keys(menuItems),
optionStringifier: id => {
var _menuItems$id$ref$cur;
return menuItems[id].label || ((_menuItems$id$ref$cur = menuItems[id].ref.current) == null ? void 0 : _menuItems$id$ref$cur.innerText);
},
isOptionDisabled: id => {
var _menuItems$id;
return (menuItems == null ? void 0 : (_menuItems$id = menuItems[id]) == null ? void 0 : _menuItems$id.disabled) || false;
},
listboxRef: handleRef,
focusManagement: 'DOM',
id: listboxId,
stateReducer,
disabledItemsFocusable: true
});
const highlightFirstItem = React.useCallback(() => {
if (Object.keys(menuItems).length > 0) {
setListboxHighlight(menuItems[Object.keys(menuItems)[0]].id);
}
}, [menuItems, setListboxHighlight]);
const highlightLastItem = React.useCallback(() => {
if (Object.keys(menuItems).length > 0) {
setListboxHighlight(menuItems[Object.keys(menuItems)[Object.keys(menuItems).length - 1]].id);
}
}, [menuItems, setListboxHighlight]);
React.useEffect(() => {
if (!open) {
highlightFirstItem();
}
}, [open, highlightFirstItem]);
const createHandleKeyDown = otherHandlers => e => {
var _otherHandlers$onKeyD;
(_otherHandlers$onKeyD = otherHandlers.onKeyDown) == null ? void 0 : _otherHandlers$onKeyD.call(otherHandlers, e);
if (e.defaultPrevented) {
return;
}
if (e.key === 'Escape' && open) {
onClose == null ? void 0 : onClose();
}
};
const createHandleBlur = otherHandlers => e => {
var _otherHandlers$onBlur, _listboxRef$current;
(_otherHandlers$onBlur = otherHandlers.onBlur) == null ? void 0 : _otherHandlers$onBlur.call(otherHandlers, e);
if (!((_listboxRef$current = listboxRef.current) != null && _listboxRef$current.contains(e.relatedTarget))) {
onClose == null ? void 0 : onClose();
}
};
React.useEffect(() => {
var _listboxRef$current2;
// set focus to the highlighted item (but prevent stealing focus from other elements on the page)
if ((_listboxRef$current2 = listboxRef.current) != null && _listboxRef$current2.contains(document.activeElement) && highlightedOption !== null) {
var _menuItems$highlighte, _menuItems$highlighte2;
menuItems == null ? void 0 : (_menuItems$highlighte = menuItems[highlightedOption]) == null ? void 0 : (_menuItems$highlighte2 = _menuItems$highlighte.ref.current) == null ? void 0 : _menuItems$highlighte2.focus();
}
}, [highlightedOption, menuItems]);
const getListboxProps = (otherHandlers = {}) => {
const rootProps = getRootProps(_extends({}, otherHandlers, {
onBlur: createHandleBlur(otherHandlers),
onKeyDown: createHandleKeyDown(otherHandlers)
}));
return _extends({}, otherHandlers, rootProps, {
role: 'menu'
});
};
const getItemState = id => {
const {
disabled,
highlighted
} = getOptionState(id);
return {
disabled,
highlighted
};
};
React.useDebugValue({
menuItems,
highlightedOption
});
return {
registerItem,
unregisterItem,
menuItems,
getListboxProps,
getItemState,
getItemProps: getOptionProps,
highlightedOption,
highlightFirstItem,
highlightLastItem
};
}

Event Timeline