import styled from "@emotion/styled"; import { Button, IconButton, Menu, MenuItem, Modal } from "@mui/material"; import { ChevronRight, EllipsisVertical, FileDown, FileUp, Plus, Trash2, } from "lucide-react"; import { useRef, useState } from "react"; import DeleteWorkbookDialog from "./DeleteWorkbookDialog"; import UploadFileDialog from "./UploadFileDialog"; import { getModelsMetadata, getSelectedUuid } from "./storage"; export function DesktopMenu(props: { newModel: () => void; setModel: (key: string) => void; onDownload: () => void; onModelUpload: (blob: ArrayBuffer, fileName: string) => Promise; onDelete: () => void; }) { const [isFileMenuOpen, setFileMenuOpen] = useState(false); const anchorElement = useRef( null as unknown as HTMLButtonElement, ); return ( <> setFileMenuOpen(!isFileMenuOpen)} ref={anchorElement} disableRipple isOpen={isFileMenuOpen} > File {}} anchorElement={anchorElement} /> ); } export function MobileMenu(props: { newModel: () => void; setModel: (key: string) => void; onDownload: () => void; onModelUpload: (blob: ArrayBuffer, fileName: string) => Promise; onDelete: () => void; }) { const [isMobileMenuOpen, setMobileMenuOpen] = useState(false); const [isFileMenuOpen, setFileMenuOpen] = useState(false); const anchorElement = useRef( null as unknown as HTMLButtonElement, ); const [fileMenuAnchorEl, setFileMenuAnchorEl] = useState( null, ); return ( <> setMobileMenuOpen(true)} ref={anchorElement} disableRipple > setMobileMenuOpen(false)} anchorEl={anchorElement.current} > { setFileMenuOpen(true); setFileMenuAnchorEl(event.currentTarget); }} disableRipple > File { window.open("https://docs.ironcalc.com", "_blank"); setMobileMenuOpen(false); }} disableRipple > Help ); } export function FileMenu(props: { newModel: () => void; setModel: (key: string) => void; onDownload: () => void; onModelUpload: (blob: ArrayBuffer, fileName: string) => Promise; onDelete: () => void; isFileMenuOpen: boolean; setFileMenuOpen: (open: boolean) => void; setMobileMenuOpen: (open: boolean) => void; anchorElement: React.RefObject; }) { const [isImportMenuOpen, setImportMenuOpen] = useState(false); const models = getModelsMetadata(); const selectedUuid = getSelectedUuid(); const [isDeleteDialogOpen, setDeleteDialogOpen] = useState(false); return ( <> props.setFileMenuOpen(false)} anchorEl={props.anchorElement.current} anchorOrigin={{ vertical: "bottom", horizontal: "left", }} transformOrigin={{ vertical: "top", horizontal: "left", }} // To prevent closing parent menu when interacting with submenu onMouseLeave={() => { if (!isImportMenuOpen && !isDeleteDialogOpen) { props.setFileMenuOpen(false); } }} > { props.newModel(); props.setFileMenuOpen(false); props.setMobileMenuOpen(false); }} disableRipple > New { setImportMenuOpen(true); props.setFileMenuOpen(false); props.setMobileMenuOpen(false); }} disableRipple > Import { props.onDownload(); props.setMobileMenuOpen(false); }} disableRipple > Download (.xlsx) { setDeleteDialogOpen(true); props.setFileMenuOpen(false); props.setMobileMenuOpen(false); }} disableRipple > Delete workbook { setImportMenuOpen(false); }} aria-labelledby="modal-modal-title" aria-describedby="modal-modal-description" > { setImportMenuOpen(false); }} onModelUpload={props.onModelUpload} /> setDeleteDialogOpen(false)} aria-labelledby="delete-dialog-title" aria-describedby="delete-dialog-description" > setDeleteDialogOpen(false)} onConfirm={props.onDelete} workbookName={selectedUuid ? models[selectedUuid]?.name || "" : ""} /> ); } const StyledIcon = styled.div` display: flex; align-items: center; svg { width: 16px; height: 100%; color: #757575; padding-right: 10px; } `; const MenuButton = styled(IconButton)` height: 32px; width: 32px; padding: 8px; border-radius: 4px; svg { stroke-width: 2px; stroke: #757575; width: 16px; height: 16px; } &:hover { background-color: #f2f2f2; } &:active { background-color: #e0e0e0; } `; const FileBarButton = styled(Button)<{ isOpen: boolean }>` display: flex; flex-direction: row; align-items: center; font-size: 12px; height: 32px; width: auto; padding: 4px 8px; font-weight: 400; min-width: 0px; text-transform: capitalize; color: #333333; background-color: ${({ isOpen }) => (isOpen ? "#f2f2f2" : "none")}; &:hover { background-color: #f2f2f2; } &:active { background-color: #e0e0e0; } `; const StyledFileDown = styled(FileDown)` width: 16px; height: 16px; color: #333333; padding-right: 10px; `; const MenuDivider = styled("div")` width: 100%; margin: auto; margin-top: 4px; margin-bottom: 4px; border-top: 1px solid #eeeeee; `; const MenuItemText = styled.div` color: #000; font-size: 12px; flex-grow: 1; `; const MenuItemWrapper = styled(MenuItem)` display: flex; justify-content: flex-start; font-size: 14px; width: calc(100% - 8px); min-width: 172px; margin: 0px 4px; border-radius: 4px; padding: 8px; height: 32px; min-height: 32px; svg { width: 16px; height: 16px; } `; const StyledMenu = styled(Menu)` .MuiPaper-root { border-radius: 8px; padding: 4px 0px; }, .MuiList-root { padding: 0; }, `;