TelegramPWA/src/components/ui/DropdownMenu.tsx
2021-06-12 17:20:25 +03:00

90 lines
2.0 KiB
TypeScript

import React, { FC, useState, useRef } from '../../lib/teact/teact';
import Menu from './Menu';
import './DropdownMenu.scss';
type OwnProps = {
className?: string;
trigger: FC<{ onTrigger: () => void; isOpen?: boolean }>;
positionX?: 'left' | 'right';
positionY?: 'top' | 'bottom';
footer?: string;
forceOpen?: boolean;
onOpen?: NoneToVoidFunction;
onClose?: NoneToVoidFunction;
children: any;
};
const DropdownMenu: FC<OwnProps> = ({
trigger,
className,
children,
positionX = 'left',
positionY = 'top',
footer,
forceOpen,
onOpen,
onClose,
}) => {
// eslint-disable-next-line no-null/no-null
const menuRef = useRef<HTMLDivElement>(null);
// eslint-disable-next-line no-null/no-null
const dropdownRef = useRef<HTMLDivElement>(null);
const [isOpen, setIsOpen] = useState(false);
const toggleIsOpen = () => {
setIsOpen(!isOpen);
if (isOpen) {
if (onClose) onClose();
} else if (onOpen) onOpen();
};
const handleKeyDown = (e: React.KeyboardEvent<any>) => {
const menu = menuRef.current;
if (!isOpen || e.keyCode !== 40 || !menu) {
return;
}
const focusedElement = document.activeElement;
const elementChildren = Array.from(menu.children);
if (!focusedElement || elementChildren.indexOf(focusedElement) === -1) {
(elementChildren[0] as HTMLElement).focus();
}
};
const handleClose = () => {
setIsOpen(false);
if (onClose) onClose();
};
return (
<div
ref={dropdownRef}
className={`DropdownMenu ${className || ''}`}
onKeyDown={handleKeyDown}
>
{trigger({ onTrigger: toggleIsOpen, isOpen })}
<Menu
ref={menuRef}
containerRef={dropdownRef}
isOpen={isOpen || !!forceOpen}
className={className || ''}
positionX={positionX}
positionY={positionY}
footer={footer}
autoClose
onClose={handleClose}
shouldSkipTransition={forceOpen}
>
{children}
</Menu>
</div>
);
};
export default DropdownMenu;