mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-29 03:22:12 +00:00
tgui => tgui_ch
This commit is contained in:
231
tgui/packages/tgui_ch/components/MenuBar.tsx
Normal file
231
tgui/packages/tgui_ch/components/MenuBar.tsx
Normal file
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
* @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;
|
||||
Reference in New Issue
Block a user