@gechiui/components
Version:
UI components for GeChiUI.
191 lines (177 loc) • 4.29 kB
JavaScript
// @ts-nocheck
/**
* External dependencies
*/
import classnames from 'classnames';
import { flatMap, isEmpty, isFunction } from 'lodash';
/**
* GeChiUI dependencies
*/
import { DOWN } from '@gechiui/keycodes';
import { menu } from '@gechiui/icons';
/**
* Internal dependencies
*/
import Button from '../button';
import Dropdown from '../dropdown';
import { NavigableMenu } from '../navigable-container';
function mergeProps( defaultProps = {}, props = {} ) {
const mergedProps = {
...defaultProps,
...props,
};
if ( props.className && defaultProps.className ) {
mergedProps.className = classnames(
props.className,
defaultProps.className
);
}
return mergedProps;
}
function DropdownMenu( dropdownMenuProps ) {
const {
children,
className,
controls,
icon = menu,
label,
popoverProps,
toggleProps,
menuProps,
disableOpenOnArrowDown = false,
text,
noIcons,
} = dropdownMenuProps;
if ( isEmpty( controls ) && ! isFunction( children ) ) {
return null;
}
// Normalize controls to nested array of objects (sets of controls)
let controlSets;
if ( ! isEmpty( controls ) ) {
controlSets = controls;
if ( ! Array.isArray( controlSets[ 0 ] ) ) {
controlSets = [ controlSets ];
}
}
const mergedPopoverProps = mergeProps(
{
className: 'components-dropdown-menu__popover',
},
popoverProps
);
return (
<Dropdown
className={ classnames( 'components-dropdown-menu', className ) }
popoverProps={ mergedPopoverProps }
renderToggle={ ( { isOpen, onToggle } ) => {
const openOnArrowDown = ( event ) => {
if ( disableOpenOnArrowDown ) {
return;
}
if ( ! isOpen && event.keyCode === DOWN ) {
event.preventDefault();
onToggle();
}
};
const mergedToggleProps = mergeProps(
{
className: classnames(
'components-dropdown-menu__toggle',
{
'is-opened': isOpen,
}
),
},
toggleProps
);
return (
<Button
{ ...mergedToggleProps }
icon={ icon }
onClick={ ( event ) => {
onToggle( event );
if ( mergedToggleProps.onClick ) {
mergedToggleProps.onClick( event );
}
} }
onKeyDown={ ( event ) => {
openOnArrowDown( event );
if ( mergedToggleProps.onKeyDown ) {
mergedToggleProps.onKeyDown( event );
}
} }
aria-haspopup="true"
aria-expanded={ isOpen }
label={ label }
text={ text }
showTooltip={ toggleProps?.showTooltip ?? true }
>
{ mergedToggleProps.children }
</Button>
);
} }
renderContent={ ( props ) => {
const mergedMenuProps = mergeProps(
{
'aria-label': label,
className: classnames(
'components-dropdown-menu__menu',
{ 'no-icons': noIcons }
),
},
menuProps
);
return (
<NavigableMenu { ...mergedMenuProps } role="menu">
{ isFunction( children ) ? children( props ) : null }
{ flatMap( controlSets, ( controlSet, indexOfSet ) =>
controlSet.map( ( control, indexOfControl ) => (
<Button
key={ [
indexOfSet,
indexOfControl,
].join() }
onClick={ ( event ) => {
event.stopPropagation();
props.onClose();
if ( control.onClick ) {
control.onClick();
}
} }
className={ classnames(
'components-dropdown-menu__menu-item',
{
'has-separator':
indexOfSet > 0 &&
indexOfControl === 0,
'is-active': control.isActive,
'is-icon-only': ! control.title,
}
) }
icon={ control.icon }
label={ control.label }
aria-checked={
control.role === 'menuitemcheckbox' ||
control.role === 'menuitemradio'
? control.isActive
: undefined
}
role={
control.role === 'menuitemcheckbox' ||
control.role === 'menuitemradio'
? control.role
: 'menuitem'
}
disabled={ control.isDisabled }
>
{ control.title }
</Button>
) )
) }
</NavigableMenu>
);
} }
/>
);
}
export default DropdownMenu;