* feat: new Menu Component API * allow valid children types * introduce menu group to group items * Add lang footer * use display name * displayName * define types inside * fix default menu * add json export to menu * fix * simplify expression * put open menu into own compo to optimize perf So that we don't rerun `useOutsideClickHook` (and rebind event listeners all the time) * naming tweaks * rename MenuComponents->MenuDefaultItems and export default items from Menu.Items * import Menu.scss in Menu.tsx * move menu scss to excal app * Don't filter children inside menu group * move E+ out of socials * support style prop for MenuItem and MenuGroup * Support header in menu group and add Excalidraw links header for default items in social section * rename header to title * fix padding for lang * render menu in mobile * review fixes * tweaks * Export collaborators and show in mobile menu * revert .env * lint :p * again lint * show correct actions in view mode for mobile * Whitelist Collaborators Comp * mobile styling * padding * don't show nerds when menu open in mobile * lint :( * hide shortcuts * refactor userlist to support mobile and keep a wrapper comp for excal app * use only UserList * render only on mobile for default items * remove unused hooks * Show collab button in menu when onCollabButtonClick present and hide export when UIOptions.canvasActions.export is false * fix tests * lint * inject userlist inside menu on mobile * revert userlist * move menu socials to default menu * fix collab * use meny in library * Make Menu generic and create hamburgemenu for public excal menu and use menu in library as well * use appState.openMenu for mobile * fix tests * styling fixes and support style and class name in menu content * fix test * rename MenuDefaultItems->DefaultItems * move footer css to its own comp * rename HamburgerMenu -> MainMenu * rename menu -> dropdownMenu and update classes, onClick->onToggle * close main menu when dialog closes * by bye filtering * update docs * fix lint * update example, docs for useDevice and footer in mobile, rename menu ->DropDownMenu everywhere * spec * remove isMenuOpenAtom and set openMenu as canvas for main menu, render decreases in specs :) * [temp] remove cyclic depenedency to fix build * hack- update appstate to sync lang change * Add more specs * wip: rewrite MainMenu footer * fix margin * fix snaps * not needed as lang list no more imported * simplify custom footer rendering * Add DropdownMenuItemLink and DropdownMenuItemCustom and update API, docs * fix `MainMenu.ItemCustom` * naming * use onSelect and base class for custom items * fix lint * fix snap * use custom item for lang * update docs * fix * properly use `MainMenu.ItemCustom` for `LanguageList` * add margin top to custom items * flex Co-authored-by: dwelle <luzar.david@gmail.com>
128 lines
3.8 KiB
TypeScript
128 lines
3.8 KiB
TypeScript
import React from "react";
|
|
import { NonDeletedExcalidrawElement } from "../element/types";
|
|
import { t } from "../i18n";
|
|
|
|
import { AppState, ExportOpts, BinaryFiles } from "../types";
|
|
import { Dialog } from "./Dialog";
|
|
import { exportToFileIcon, LinkIcon } from "./icons";
|
|
import { ToolButton } from "./ToolButton";
|
|
import { actionSaveFileToDisk } from "../actions/actionExport";
|
|
import { Card } from "./Card";
|
|
|
|
import "./ExportDialog.scss";
|
|
import { nativeFileSystemSupported } from "../data/filesystem";
|
|
import { trackEvent } from "../analytics";
|
|
import { ActionManager } from "../actions/manager";
|
|
import { getFrame } from "../utils";
|
|
|
|
export type ExportCB = (
|
|
elements: readonly NonDeletedExcalidrawElement[],
|
|
scale?: number,
|
|
) => void;
|
|
|
|
const JSONExportModal = ({
|
|
elements,
|
|
appState,
|
|
files,
|
|
actionManager,
|
|
exportOpts,
|
|
canvas,
|
|
}: {
|
|
appState: AppState;
|
|
files: BinaryFiles;
|
|
elements: readonly NonDeletedExcalidrawElement[];
|
|
actionManager: ActionManager;
|
|
onCloseRequest: () => void;
|
|
exportOpts: ExportOpts;
|
|
canvas: HTMLCanvasElement | null;
|
|
}) => {
|
|
const { onExportToBackend } = exportOpts;
|
|
return (
|
|
<div className="ExportDialog ExportDialog--json">
|
|
<div className="ExportDialog-cards">
|
|
{exportOpts.saveFileToDisk && (
|
|
<Card color="lime">
|
|
<div className="Card-icon">{exportToFileIcon}</div>
|
|
<h2>{t("exportDialog.disk_title")}</h2>
|
|
<div className="Card-details">
|
|
{t("exportDialog.disk_details")}
|
|
{!nativeFileSystemSupported &&
|
|
actionManager.renderAction("changeProjectName")}
|
|
</div>
|
|
<ToolButton
|
|
className="Card-button"
|
|
type="button"
|
|
title={t("exportDialog.disk_button")}
|
|
aria-label={t("exportDialog.disk_button")}
|
|
showAriaLabel={true}
|
|
onClick={() => {
|
|
actionManager.executeAction(actionSaveFileToDisk, "ui");
|
|
}}
|
|
/>
|
|
</Card>
|
|
)}
|
|
{onExportToBackend && (
|
|
<Card color="pink">
|
|
<div className="Card-icon">{LinkIcon}</div>
|
|
<h2>{t("exportDialog.link_title")}</h2>
|
|
<div className="Card-details">{t("exportDialog.link_details")}</div>
|
|
<ToolButton
|
|
className="Card-button"
|
|
type="button"
|
|
title={t("exportDialog.link_button")}
|
|
aria-label={t("exportDialog.link_button")}
|
|
showAriaLabel={true}
|
|
onClick={() => {
|
|
onExportToBackend(elements, appState, files, canvas);
|
|
trackEvent("export", "link", `ui (${getFrame()})`);
|
|
}}
|
|
/>
|
|
</Card>
|
|
)}
|
|
{exportOpts.renderCustomUI &&
|
|
exportOpts.renderCustomUI(elements, appState, files, canvas)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const JSONExportDialog = ({
|
|
elements,
|
|
appState,
|
|
files,
|
|
actionManager,
|
|
exportOpts,
|
|
canvas,
|
|
setAppState,
|
|
}: {
|
|
elements: readonly NonDeletedExcalidrawElement[];
|
|
appState: AppState;
|
|
files: BinaryFiles;
|
|
actionManager: ActionManager;
|
|
exportOpts: ExportOpts;
|
|
canvas: HTMLCanvasElement | null;
|
|
setAppState: React.Component<any, AppState>["setState"];
|
|
}) => {
|
|
const handleClose = React.useCallback(() => {
|
|
setAppState({ openDialog: null });
|
|
}, [setAppState]);
|
|
|
|
return (
|
|
<>
|
|
{appState.openDialog === "jsonExport" && (
|
|
<Dialog onCloseRequest={handleClose} title={t("buttons.export")}>
|
|
<JSONExportModal
|
|
elements={elements}
|
|
appState={appState}
|
|
files={files}
|
|
actionManager={actionManager}
|
|
onCloseRequest={handleClose}
|
|
exportOpts={exportOpts}
|
|
canvas={canvas}
|
|
/>
|
|
</Dialog>
|
|
)}
|
|
</>
|
|
);
|
|
};
|