Files
CHOMPStation2/tgui/packages/tgui_ch/components/MenuBar.tsx
2023-06-19 19:41:48 +02:00

232 lines
4.9 KiB
TypeScript

/**
* @file
* @copyright 2022 Aleksej Komarov
* @license MIT
*/
import { classes } from 'common/react';
import { Component, createRef, InfernoNode, RefObject } from 'inferno';
import { Box } from './Box';
import { logger } from '../logging';
import { Icon } from './Icon';
type MenuProps = {
children: any;
width: string;
menuRef: RefObject<HTMLElement>;
onOutsideClick: () => void;
};
class Menu extends Component<MenuProps> {
private readonly handleClick: (event) => void;
constructor(props) {
super(props);
this.handleClick = (event) => {
if (!this.props.menuRef.current) {
logger.log(`Menu.handleClick(): No ref`);
return;
}
if (this.props.menuRef.current.contains(event.target)) {
logger.log(`Menu.handleClick(): Inside`);
} else {
logger.log(`Menu.handleClick(): Outside`);
this.props.onOutsideClick();
}
};
}
// eslint-disable-next-line react/no-deprecated
componentWillMount() {
window.addEventListener('click', this.handleClick);
}
componentWillUnmount() {
window.removeEventListener('click', this.handleClick);
}
render() {
const { width, children } = this.props;
return (
<div
className={'MenuBar__menu'}
style={{
width: width,
}}>
{children}
</div>
);
}
}
type MenuBarDropdownProps = {
open: boolean;
openWidth: string;
children: any;
disabled?: boolean;
display: any;
onMouseOver: () => void;
onClick: () => void;
onOutsideClick: () => void;
className?: string;
};
class MenuBarButton extends Component<MenuBarDropdownProps> {
private readonly menuRef: RefObject<HTMLDivElement>;
constructor(props) {
super(props);
this.menuRef = createRef();
}
render() {
const { props } = this;
const {
open,
openWidth,
children,
disabled,
display,
onMouseOver,
onClick,
onOutsideClick,
...boxProps
} = props;
const { className, ...rest } = boxProps;
return (
<div ref={this.menuRef}>
<Box
className={classes([
'MenuBar__MenuBarButton',
'MenuBar__font',
'MenuBar__hover',
className,
])}
{...rest}
onClick={disabled ? undefined : onClick}
onmouseover={onMouseOver}>
<span className="MenuBar__MenuBarButton-text">{display}</span>
</Box>
{open && (
<Menu
width={openWidth}
menuRef={this.menuRef}
onOutsideClick={onOutsideClick}>
{children}
</Menu>
)}
</div>
);
}
}
type MenuBarItemProps = {
entry: string;
children: any;
openWidth: string;
display: InfernoNode;
setOpenMenuBar: (entry: string | null) => void;
openMenuBar: string | null;
setOpenOnHover: (flag: boolean) => void;
openOnHover: boolean;
disabled?: boolean;
className?: string;
};
export const Dropdown = (props: MenuBarItemProps) => {
const {
entry,
children,
openWidth,
display,
setOpenMenuBar,
openMenuBar,
setOpenOnHover,
openOnHover,
disabled,
className,
} = props;
return (
<MenuBarButton
openWidth={openWidth}
display={display}
disabled={disabled}
open={openMenuBar === entry}
className={className}
onClick={() => {
const open = openMenuBar === entry ? null : entry;
setOpenMenuBar(open);
setOpenOnHover(!openOnHover);
}}
onOutsideClick={() => {
setOpenMenuBar(null);
setOpenOnHover(false);
}}
onMouseOver={() => {
if (openOnHover) {
setOpenMenuBar(entry);
}
}}>
{children}
</MenuBarButton>
);
};
const MenuItemToggle = (props) => {
const { value, displayText, onClick, checked } = props;
return (
<Box
className={classes([
'MenuBar__font',
'MenuBar__MenuItem',
'MenuBar__MenuItemToggle',
'MenuBar__hover',
])}
onClick={() => onClick(value)}>
<div className="MenuBar__MenuItemToggle__check">
{checked && <Icon size={1.3} name="check" />}
</div>
{displayText}
</Box>
);
};
Dropdown.MenuItemToggle = MenuItemToggle;
const MenuItem = (props) => {
const { value, displayText, onClick } = props;
return (
<Box
className={classes([
'MenuBar__font',
'MenuBar__MenuItem',
'MenuBar__hover',
])}
onClick={() => onClick(value)}>
{displayText}
</Box>
);
};
Dropdown.MenuItem = MenuItem;
const Separator = () => {
return <div className="MenuBar__Separator" />;
};
Dropdown.Separator = Separator;
type MenuBarProps = {
children: any;
};
export const MenuBar = (props: MenuBarProps) => {
const { children } = props;
return <Box className="MenuBar">{children}</Box>;
};
MenuBar.Dropdown = Dropdown;