From 4d297de91dc152d5aa5b9cab75d3e9e6dfb1021f Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Wed, 26 Apr 2023 11:50:56 -0500 Subject: [PATCH] Initial checkin --- src/qqq/components/buttons/MenuButton.tsx | 144 ++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 src/qqq/components/buttons/MenuButton.tsx diff --git a/src/qqq/components/buttons/MenuButton.tsx b/src/qqq/components/buttons/MenuButton.tsx new file mode 100644 index 0000000..869f2f6 --- /dev/null +++ b/src/qqq/components/buttons/MenuButton.tsx @@ -0,0 +1,144 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2023. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {ClickAwayListener, Grow, MenuList, Paper, Popper} from "@mui/material"; +import Button from "@mui/material/Button/Button"; +import Icon from "@mui/material/Icon"; +import MenuItem from "@mui/material/MenuItem"; +import React, {useEffect, useRef, useState} from "react"; + + +interface Props +{ + label: string; + iconName?: string + options: string[]; + disabled?: boolean; + callback: (selectedIndex: number) => void; +} + +MenuButton.defaultProps = +{ + disabled: false +}; + +function MenuButton({label, iconName, options, disabled, callback}: Props) +{ + const [open, setOpen] = useState(false); + const anchorRef = useRef(null); + + const handleToggle = () => + { + setOpen((prevOpen) => !prevOpen); + }; + + const handleClose = (event: Event | React.SyntheticEvent) => + { + if (anchorRef.current && anchorRef.current.contains(event.target as HTMLElement)) + { + return; + } + + setOpen(false); + }; + + function handleListKeyDown(event: React.KeyboardEvent) + { + if (event.key === "Tab") + { + event.preventDefault(); + setOpen(false); + } + else if (event.key === "Escape") + { + setOpen(false); + } + } + + // return focus to the button when we transitioned from !open -> open + const prevOpen = useRef(open); + useEffect(() => + { + if (prevOpen.current === true && open === false) + { + anchorRef.current!.focus(); + } + + prevOpen.current = open; + }, [open]); + + + const menuItemClicked = (e: React.MouseEvent, newIndex: number) => + { + callback(newIndex); + handleClose(e); + } + + const menuItems: JSX.Element[] = [] + options.map((option, index) => + { + menuItems.push( menuItemClicked(e, index)}> + {option} + ); + }) + + return ( +
+ + + {({TransitionProps, placement}) => ( + + + + + {menuItems} + + + + + )} + +
+ ); +} + +export default MenuButton; +