@amaui/ui-react
Version:
UI for React
265 lines (263 loc) • 11.8 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
const _excluded = ["tonal", "color", "colorSelected", "size", "menu", "menuId", "menuOpen", "openMenu", "openMenuDefault", "openList", "openListDefault", "menuItem", "list", "preselected", "selected", "inset", "end", "indicator", "include", "footer", "menuCloseOnClick", "listCloseOnClick", "disabled", "onClick", "onFocus", "onBlur", "onMouseEnter", "onMouseLeave", "ExpandIcon", "ListTransitionComponent", "ListProps", "ListTransitionComponentProps", "ExpandProps", "MenuProps"];
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
import React from 'react';
import { is, isEnvironment } from '@amaui/utils';
import { classNames, style as styleMethod, useAmauiTheme } from '@amaui/style-react';
import IconMaterialExpandMore from '@amaui/icons-material-rounded-react/IconMaterialExpandMoreW100';
import IconMaterialArrowRight from '@amaui/icons-material-rounded-react/IconMaterialArrowRightW100';
import ListItemElement from '../ListItem';
import ListElement from '../List';
import IconButtonElement from '../IconButton';
import MenuElement from '../Menu';
import ExpandElement from '../Expand';
import FadeElement from '../Fade';
import { iconFontSize, staticClassName } from '../utils';
const useStyle = styleMethod(theme => ({
icon: {
transition: theme.methods.transitions.make('transform')
},
icon_open: {
transform: 'rotate(-180deg)'
}
}), {
name: 'amaui-ListItem'
});
const ListItemDelays = {
Transition: {
enter: 70
}
};
const MenuItem = /*#__PURE__*/React.forwardRef((props_, ref) => {
const theme = useAmauiTheme();
const props = React.useMemo(() => _objectSpread(_objectSpread(_objectSpread({}, theme?.ui?.elements?.all?.props?.default), theme?.ui?.elements?.amauiMenuItem?.props?.default), props_), [props_]);
const ListItem = React.useMemo(() => theme?.elements?.ListItem || ListItemElement, [theme]);
const List = React.useMemo(() => theme?.elements?.List || ListElement, [theme]);
const IconButton = React.useMemo(() => theme?.elements?.IconButton || IconButtonElement, [theme]);
const Menu = React.useMemo(() => theme?.elements?.Menu || MenuElement, [theme]);
const Expand = React.useMemo(() => theme?.elements?.Expand || ExpandElement, [theme]);
const Fade = React.useMemo(() => theme?.elements?.Fade || FadeElement, [theme]);
const {
tonal = true,
color = 'default',
colorSelected = props.color,
size = 'regular',
menu,
menuId,
menuOpen,
openMenu: openMenu_,
openMenuDefault,
openList: openList_,
openListDefault,
menuItem,
list: list_,
preselected,
selected,
inset,
end: end_,
indicator = true,
include,
footer,
menuCloseOnClick,
listCloseOnClick,
disabled,
onClick: onClick_,
onFocus: onFocus_,
onBlur: onBlur_,
onMouseEnter: onMouseEnter_,
onMouseLeave: onMouseLeave_,
ExpandIcon = IconMaterialExpandMore,
ListTransitionComponent = Fade,
ListProps,
ListTransitionComponentProps: ListTransitionComponentProps_,
ExpandProps,
MenuProps = {
autoSelect: true
}
} = props,
other = _objectWithoutProperties(props, _excluded);
const {
classes
} = useStyle();
const [openMenu, setOpenMenu] = React.useState(openMenuDefault !== undefined ? openMenuDefault : openMenu_);
const [openList, setOpenList] = React.useState(openListDefault !== undefined ? openListDefault : openList_);
const [hover, setHover] = React.useState(false);
const [focus, setFocus] = React.useState(false);
const refs = {
root: React.useRef(undefined),
props: React.useRef(undefined),
openMenu: React.useRef(undefined),
openList: React.useRef(undefined),
focus: React.useRef(undefined),
ids: {
primary: React.useId(),
secondary: React.useId()
}
};
refs.props.current = props;
refs.openMenu.current = openMenu;
refs.openList.current = openList;
refs.focus.current = focus;
const ListTransitionComponentProps = _objectSpread({
add: true,
delay: {
enter: ListItemDelays.Transition.enter
}
}, ListTransitionComponentProps_);
const list = list_ && React.Children.toArray(list_).map((item, index) => /*#__PURE__*/React.cloneElement(item, _objectSpread({
key: index,
onClick: event => {
if (item.props.listCloseOnClick) onCloseList();
if (is('function', item.props.onClick)) item.props.onClick(event);
}
}, item?.props)));
const onClick = React.useCallback(event => {
if (!refs.props.current.disabled) {
if (refs.props.current.list) setOpenList(!refs.openList.current);
}
if (is('function', onClick_)) onClick_(event);
}, [onClick_]);
let end = end_;
if (menu) end = end_ || /*#__PURE__*/React.createElement(IconMaterialArrowRight, null);
if (list) end = end_ || indicator && /*#__PURE__*/React.createElement(IconButton, {
size: 24,
fontSize: iconFontSize,
onClick: onClick,
className: classNames([staticClassName('ListItem', theme) && ['amaui-ListItem-icon-button'], classes.iconButton])
}, /*#__PURE__*/React.createElement(ExpandIcon, {
className: classNames([classes.icon, openList && classes.icon_open])
}));
React.useEffect(() => {
const onKeyDown = event => {
if (!refs.props.current.disabled) {
if (menu) {
if (refs.openMenu.current && (theme.direction === 'ltr' && event.key === 'ArrowLeft' || theme.direction === 'rtl' && event.key === 'ArrowRight')) setOpenMenu(false);
if (!refs.openMenu.current && (theme.direction === 'ltr' && event.key === 'ArrowRight' || theme.direction === 'rtl' && event.key === 'ArrowLeft')) setOpenMenu(true);
} else if (list) {
if (refs.openList.current && (event.key === 'ArrowUp' || theme.direction === 'ltr' && event.key === 'ArrowLeft' || theme.direction === 'rtl' && event.key === 'ArrowRight')) setOpenMenu(false);
if (!refs.openList.current && (event.key === 'ArrowDown' || theme.direction === 'ltr' && event.key === 'ArrowRight' || theme.direction === 'rtl' && event.key === 'ArrowLeft')) setOpenMenu(true);
if (event.key === 'Enter' && refs.focus.current) onClick();
} else {
if (event.key === 'Enter' && !refs.props.current.button && refs.focus.current) {
if (is('function', refs.props.current.onClick)) refs.props.current.onClick(event);
}
}
}
};
const rootDocument = isEnvironment('browser') ? refs.root.current?.ownerDocument || window.document : undefined;
rootDocument.addEventListener('keydown', onKeyDown);
return () => {
rootDocument.removeEventListener('keydown', onKeyDown);
};
}, []);
React.useEffect(() => {
if (openMenu_ !== openMenu) setOpenMenu(openMenu_);
}, [openMenu_]);
React.useEffect(() => {
if (openList_ !== openList) setOpenList(openList_);
}, [openList_]);
React.useEffect(() => {
if (menuOpen && preselected) refs.root.current.focus();
}, [preselected, menuOpen]);
React.useEffect(() => {
if (menu) setOpenMenu(hover || preselected || selected);
}, [hover]);
React.useEffect(() => {
if (menu) setOpenMenu(hover || focus || preselected || selected);
}, [focus]);
const onMouseEnter = React.useCallback(event => {
if (!disabled) setHover(true);
if (is('function', onMouseEnter_)) onMouseEnter_(event);
}, []);
const onMouseLeave = React.useCallback(event => {
if (!disabled) {
setHover(false);
setFocus(false);
}
if (is('function', onMouseLeave_)) onMouseLeave_(event);
}, []);
const onFocus = React.useCallback(event => {
if (event.target === event.currentTarget && !disabled) setFocus(true);
if (is('function', onFocus_)) onFocus_(event);
}, []);
const onBlur = React.useCallback(event => {
if (event.target === event.currentTarget && !disabled) setFocus(false);
if (is('function', onBlur_)) onBlur_(event);
}, []);
const onCloseList = React.useCallback(() => {
if (!disabled) {
setOpenList(false);
setHover(false);
setFocus(false);
// if (is('function', onClose_)) onClose_();
}
}, []);
const onCloseMenu = React.useCallback(() => {
if (!disabled) {
setOpenMenu(false);
setHover(false);
setFocus(false);
// if (is('function', onClose_)) onClose_();
}
}, []);
ListTransitionComponentProps.in = !!openList;
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ListItem, _extends({
ref: item => {
if (ref) {
if (is('function', ref)) ref(item);else if (ref?.current) ref.current = item;
}
refs.root.current = item;
},
tonal: tonal,
color: color,
colorSelected: colorSelected,
size: size,
inset: inset,
selected: selected,
preselected: preselected,
end: end,
disabled: disabled,
onClick: onClick,
onFocus: onFocus,
onBlur: onBlur,
onMouseEnter: onMouseEnter,
onMouseLeave: onMouseLeave,
"aria-haspopup": !!menu,
"aria-expanded": openMenu,
menuItem: true,
className: classNames([staticClassName('MenuItem', theme) && ['amaui-MenuItem-root', `amaui-MenuItem-size-${size}`], classes.root]),
InteractionProps: {
focus
},
RootProps: {
className: classNames([staticClassName('ListItem', theme) && [menu && `amaui-ListItem-menu`, list && `amaui-ListItem-list`, menuItem && `amaui-ListItem-menu-item`, menuOpen && `amaui-ListItem-menu-open`, openMenu && `amaui-ListItem-open-menu`, openList && `amaui-ListItem-open-list`, menuItem && [inset && `amaui-ListItem-menu-item-inset`]]])
},
footer: /*#__PURE__*/React.createElement(React.Fragment, null, footer, /*#__PURE__*/React.createElement(Expand, _extends({
in: openList,
parent: refs.root.current
}, ExpandProps), /*#__PURE__*/React.createElement(ListTransitionComponent, ListTransitionComponentProps, /*#__PURE__*/React.createElement(List, _extends({
indent: 5
}, ListProps, {
className: classNames([staticClassName('ListItem', theme) && ['amaui-ListItem-list'], ListProps?.className, classes.list])
}), list))), menu && /*#__PURE__*/React.createElement(Menu, _extends({
open: !!openMenu,
include: include,
onClose: onCloseMenu,
closeOnClickAway: false,
anchorElement: refs.root.current,
menuItems: menu,
transformOrigin: "left top",
transformOriginSwitch: "right top",
transformOriginRtl: "left top",
transformOriginRtlSwitch: "right top",
position: "right",
alignment: "start",
onMouseEnter: onMouseEnter
}, MenuProps)))
}, other)));
});
MenuItem.displayName = 'amaui-MenuItem';
export default MenuItem;