UNPKG

@amaui/ui-react

Version:
265 lines (263 loc) 11.8 kB
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;