// @flow strict
import * as React from 'react';
import type {ColorTypes} from '../../types/typography';
import classify from '../../utils/classify';
import {Button} from '../Button';
import type {IconProps} from '../Icon';
import {Icon} from '../Icon';
import type {TextProps} from '../Text';
import {
ButtonTextSmall,
SubTitleExtraSmall,
SubTitleMedium,
TEXT_COLORS,
} from '../Text';
import css from './SubMenu.module.css';
type ClassNames = $ReadOnly<{wrapper?: string}>;
export const SubMenuItemIcon = ({
className,
...props
}: IconProps): React.Node => (
);
SubMenuItemIcon.displayName = 'SubMenuItemIcon';
export const SubMenuItemText = ({
children,
className,
...props
}: TextProps): React.Node => (
{children}
);
SubMenuItemText.displayName = 'SubMenuItemText';
export type SubMenuItemActionProps = {
children?: React.Node,
color?: ColorTypes,
className?: string,
...
};
export const SubMenuItemAction = ({
children,
className,
...props
}: SubMenuItemActionProps): React.Node => (
{children}
);
SubMenuItemAction.displayName = 'SubMenuItemAction';
export type SubMenuItemProps = {
classNames?: ClassNames,
children?: React.Node,
selectedMenuKey?: string,
disabled?: boolean,
onChange?: (selectedMenuKey: string) => mixed,
menuKey: string,
...
};
export const SubMenuItem: React$AbstractComponent<
SubMenuItemProps,
HTMLElement,
> = React.forwardRef(
(
{
children,
selectedMenuKey,
disabled,
classNames,
onChange,
menuKey,
...props
}: SubMenuItemProps,
ref,
): React.Node => {
const onChangeHandler = () => {
if (!disabled) {
onChange && onChange(menuKey);
}
};
const onKeyDownHandler = (e) => {
if (e.key === 'Enter') {
onChangeHandler();
}
};
const selected = selectedMenuKey === menuKey;
const getNamedComp = (comp: string) => {
const childrenArray = React.Children.toArray(children);
if (childrenArray.length) {
const nodes: React.Node[] = [];
for (const child of childrenArray) {
if (child?.type?.displayName === comp) {
nodes.push(
React.cloneElement(child, {
selected,
disabled,
}),
);
}
}
return nodes.length > 1 ? nodes : nodes[0];
}
return null;
};
return (
{getNamedComp('SubMenuItemIcon')}
{getNamedComp('SubMenuItemText')}
{getNamedComp('SubMenuItemAction')}
);
},
);
type SubMenuGroupClassNames = $ReadOnly<{
wrapper?: string,
groupHeader?: string,
menuGroup?: string,
}>;
export type SubMenuGroupProps = {
children?: React.Node,
groupTitle?: string,
collapsible?: boolean,
disabled?: boolean,
onChange?: (value: string) => mixed,
selectedMenuKey?: string,
classNames?: SubMenuGroupClassNames,
};
export const SubMenuGroup = ({
children,
groupTitle,
collapsible = false,
disabled = false,
onChange,
selectedMenuKey,
classNames,
}: SubMenuGroupProps): React.Node => {
const [collapsed, setCollapsed] = React.useState(false);
const collapseHandler = () => {
collapsible && setCollapsed(!collapsed);
};
const onChangeHandler = (value) => {
if (onChange) {
onChange(value);
}
};
const onKeyDownHandlerHeader = (e) => {
if (e.key === 'Enter') {
collapseHandler();
}
};
const childrenWithProps = React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
const {disabled: disabledChild} = child.props;
return React.cloneElement(child, {
selectedMenuKey,
onChange: onChangeHandler,
disabled: disabledChild || disabled,
});
}
return child;
});
return (
{groupTitle}
{collapsible && (
)}
{childrenWithProps}
);
};
export type SubMenuProps = {
classNames?: ClassNames,
title: string,
children?: React.Node,
onClose?: () => mixed,
showClose?: boolean,
};
export const SubMenu: React$AbstractComponent =
React.forwardRef(
(
{classNames, children, title, onClose, showClose = false}: SubMenuProps,
ref,
): React.Node => {
const childrenWithProps = React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
return {child}
;
}
});
return (
{title}
{showClose && (
)}
{childrenWithProps}
);
},
);
SubMenu.displayName = 'SubMenu';