mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-09-18 06:50:31 +02:00
add Preferences default menu item
This commit is contained in:
@@ -37,6 +37,7 @@ export const AppMainMenu: React.FC<{
|
||||
)}
|
||||
<MainMenu.DefaultItems.CommandPalette className="highlighted" />
|
||||
<MainMenu.DefaultItems.SearchMenu />
|
||||
<MainMenu.DefaultItems.Preferences />
|
||||
<MainMenu.DefaultItems.Help />
|
||||
<MainMenu.DefaultItems.ClearCanvas />
|
||||
<MainMenu.Separator />
|
||||
|
@@ -54,7 +54,8 @@ export type ShortcutName =
|
||||
| "saveScene"
|
||||
| "imageExport"
|
||||
| "commandPalette"
|
||||
| "searchMenu";
|
||||
| "searchMenu"
|
||||
| "toolLock";
|
||||
|
||||
const shortcutMap: Record<ShortcutName, string[]> = {
|
||||
toggleTheme: [getShortcutKey("Shift+Alt+D")],
|
||||
@@ -116,6 +117,7 @@ const shortcutMap: Record<ShortcutName, string[]> = {
|
||||
toggleShortcuts: [getShortcutKey("?")],
|
||||
searchMenu: [getShortcutKey("CtrlOrCmd+F")],
|
||||
wrapSelectionInFrame: [],
|
||||
toolLock: [getShortcutKey("Q")],
|
||||
};
|
||||
|
||||
export const getShortcutFromShortcutName = (name: ShortcutName, idx = 0) => {
|
||||
|
@@ -451,10 +451,10 @@ export const ShapesSwitcher = ({
|
||||
<DropdownMenu.Item
|
||||
onSelect={() => app.onMagicframeToolSelect()}
|
||||
icon={MagicIcon}
|
||||
badge={<DropdownMenu.Item.Badge>AI</DropdownMenu.Item.Badge>}
|
||||
data-testid="toolbar-magicframe"
|
||||
>
|
||||
{t("toolBar.magicframe")}
|
||||
<DropdownMenu.Item.Badge>AI</DropdownMenu.Item.Badge>
|
||||
</DropdownMenu.Item>
|
||||
</>
|
||||
)}
|
||||
|
@@ -25,10 +25,6 @@ import { PropertiesPopover } from "../PropertiesPopover";
|
||||
import { QuickSearch } from "../QuickSearch";
|
||||
import { ScrollableList } from "../ScrollableList";
|
||||
import DropdownMenuGroup from "../dropdownMenu/DropdownMenuGroup";
|
||||
import DropdownMenuItem, {
|
||||
DropDownMenuItemBadgeType,
|
||||
DropDownMenuItemBadge,
|
||||
} from "../dropdownMenu/DropdownMenuItem";
|
||||
import {
|
||||
FontFamilyCodeIcon,
|
||||
FontFamilyHeadingIcon,
|
||||
@@ -36,8 +32,15 @@ import {
|
||||
FreedrawIcon,
|
||||
} from "../icons";
|
||||
|
||||
import { Ellipsify } from "../Ellipsify";
|
||||
|
||||
import { fontPickerKeyHandler } from "./keyboardNavHandlers";
|
||||
|
||||
import {
|
||||
FontPickerListItem,
|
||||
FontPickerListItemBadgeType,
|
||||
} from "./FontPickerListItem";
|
||||
|
||||
import type { JSX } from "react";
|
||||
|
||||
export interface FontDescriptor {
|
||||
@@ -46,7 +49,7 @@ export interface FontDescriptor {
|
||||
text: string;
|
||||
deprecated?: true;
|
||||
badge?: {
|
||||
type: ValueOf<typeof DropDownMenuItemBadgeType>;
|
||||
type: ValueOf<typeof FontPickerListItemBadgeType>;
|
||||
placeholder: string;
|
||||
};
|
||||
}
|
||||
@@ -112,7 +115,7 @@ export const FontPickerList = React.memo(
|
||||
Object.assign(fontDescriptor, {
|
||||
deprecated: metadata.deprecated,
|
||||
badge: {
|
||||
type: DropDownMenuItemBadgeType.RED,
|
||||
type: FontPickerListItemBadgeType.RED,
|
||||
placeholder: t("fontList.badge.old"),
|
||||
},
|
||||
});
|
||||
@@ -227,7 +230,7 @@ export const FontPickerList = React.memo(
|
||||
);
|
||||
|
||||
const renderFont = (font: FontDescriptor, index: number) => (
|
||||
<DropdownMenuItem
|
||||
<FontPickerListItem
|
||||
key={font.value}
|
||||
icon={font.icon}
|
||||
value={font.value}
|
||||
@@ -239,8 +242,8 @@ export const FontPickerList = React.memo(
|
||||
selected={font.value === selectedFontFamily}
|
||||
// allow to tab between search and selected font
|
||||
tabIndex={font.value === selectedFontFamily ? 0 : -1}
|
||||
onClick={(e) => {
|
||||
onSelect(Number(e.currentTarget.value));
|
||||
onSelect={() => {
|
||||
onSelect(font.value);
|
||||
}}
|
||||
onMouseMove={() => {
|
||||
if (hoveredFont?.value !== font.value) {
|
||||
@@ -248,13 +251,13 @@ export const FontPickerList = React.memo(
|
||||
}
|
||||
}}
|
||||
>
|
||||
{font.text}
|
||||
<Ellipsify>{font.text}</Ellipsify>
|
||||
{font.badge && (
|
||||
<DropDownMenuItemBadge type={font.badge.type}>
|
||||
<FontPickerListItem.Badge type={font.badge.type}>
|
||||
{font.badge.placeholder}
|
||||
</DropDownMenuItemBadge>
|
||||
</FontPickerListItem.Badge>
|
||||
)}
|
||||
</DropdownMenuItem>
|
||||
</FontPickerListItem>
|
||||
);
|
||||
|
||||
const groups = [];
|
||||
|
151
packages/excalidraw/components/FontPicker/FontPickerListItem.tsx
Normal file
151
packages/excalidraw/components/FontPicker/FontPickerListItem.tsx
Normal file
@@ -0,0 +1,151 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
|
||||
import { THEME } from "@excalidraw/common";
|
||||
|
||||
import type { ValueOf } from "@excalidraw/common/utility-types";
|
||||
|
||||
import { Button } from "../Button";
|
||||
|
||||
import { useExcalidrawAppState } from "../App";
|
||||
|
||||
import { useDevice } from "../App";
|
||||
|
||||
import { getDropdownMenuItemClassName } from "../dropdownMenu/common";
|
||||
|
||||
import type { JSX } from "react";
|
||||
|
||||
const MenuItemContent = ({
|
||||
textStyle,
|
||||
icon,
|
||||
shortcut,
|
||||
children,
|
||||
}: {
|
||||
icon?: React.ReactNode;
|
||||
shortcut?: string;
|
||||
textStyle?: React.CSSProperties;
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
const device = useDevice();
|
||||
return (
|
||||
<>
|
||||
{icon && <div className="dropdown-menu-item__icon">{icon}</div>}
|
||||
<div style={textStyle} className="dropdown-menu-item__text">
|
||||
{children}
|
||||
</div>
|
||||
{shortcut && !device.editor.isMobile && (
|
||||
<div className="dropdown-menu-item__shortcut">{shortcut}</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const FontPickerListItem = ({
|
||||
icon,
|
||||
value,
|
||||
order,
|
||||
children,
|
||||
shortcut,
|
||||
className,
|
||||
hovered,
|
||||
selected,
|
||||
textStyle,
|
||||
onSelect,
|
||||
onClick,
|
||||
...rest
|
||||
}: {
|
||||
icon?: JSX.Element;
|
||||
value?: string | number | undefined;
|
||||
order?: number;
|
||||
onSelect: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
||||
children: React.ReactNode;
|
||||
shortcut?: string;
|
||||
hovered?: boolean;
|
||||
selected?: boolean;
|
||||
textStyle?: React.CSSProperties;
|
||||
className?: string;
|
||||
} & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onSelect">) => {
|
||||
const ref = useRef<HTMLButtonElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (hovered) {
|
||||
if (order === 0) {
|
||||
// scroll into the first item differently, so it's visible what is above (i.e. group title)
|
||||
ref.current?.scrollIntoView({ block: "end" });
|
||||
} else {
|
||||
ref.current?.scrollIntoView({ block: "nearest" });
|
||||
}
|
||||
}
|
||||
}, [hovered, order]);
|
||||
|
||||
return (
|
||||
<div className="radix-menu-item">
|
||||
<Button
|
||||
{...rest}
|
||||
ref={ref}
|
||||
onSelect={onSelect}
|
||||
className={getDropdownMenuItemClassName(className, selected, hovered)}
|
||||
title={rest.title ?? rest["aria-label"]}
|
||||
>
|
||||
<MenuItemContent textStyle={textStyle} icon={icon} shortcut={shortcut}>
|
||||
{children}
|
||||
</MenuItemContent>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
FontPickerListItem.displayName = "FontPickerListItem";
|
||||
|
||||
export const FontPickerListItemBadgeType = {
|
||||
GREEN: "green",
|
||||
RED: "red",
|
||||
BLUE: "blue",
|
||||
} as const;
|
||||
|
||||
export const FontPickerListItemBadge = ({
|
||||
type = FontPickerListItemBadgeType.BLUE,
|
||||
children,
|
||||
}: {
|
||||
type?: ValueOf<typeof FontPickerListItemBadgeType>;
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
const { theme } = useExcalidrawAppState();
|
||||
const style = {
|
||||
display: "inline-flex",
|
||||
marginLeft: "auto",
|
||||
padding: "2px 4px",
|
||||
borderRadius: 6,
|
||||
fontSize: 9,
|
||||
fontFamily: "Cascadia, monospace",
|
||||
border: theme === THEME.LIGHT ? "1.5px solid white" : "none",
|
||||
};
|
||||
|
||||
switch (type) {
|
||||
case FontPickerListItemBadgeType.GREEN:
|
||||
Object.assign(style, {
|
||||
backgroundColor: "var(--background-color-badge)",
|
||||
color: "var(--color-badge)",
|
||||
});
|
||||
break;
|
||||
case FontPickerListItemBadgeType.RED:
|
||||
Object.assign(style, {
|
||||
backgroundColor: "pink",
|
||||
color: "darkred",
|
||||
});
|
||||
break;
|
||||
case FontPickerListItemBadgeType.BLUE:
|
||||
default:
|
||||
Object.assign(style, {
|
||||
background: "var(--color-promo)",
|
||||
color: "var(--color-surface-lowest)",
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="DropDownMenuItemBadge" style={style}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
FontPickerListItemBadge.displayName = "DropdownMenuItemBadge";
|
||||
|
||||
FontPickerListItem.Badge = FontPickerListItemBadge;
|
@@ -238,7 +238,10 @@ export const HelpDialog = ({ onClose }: { onClose?: () => void }) => {
|
||||
shortcuts={[getShortcutKey("Enter"), getShortcutKey("Escape")]}
|
||||
isOr={true}
|
||||
/>
|
||||
<Shortcut label={t("toolBar.lock")} shortcuts={[KEYS.Q]} />
|
||||
<Shortcut
|
||||
label={t("toolBar.lock")}
|
||||
shortcuts={[getShortcutFromShortcutName("toolLock")]}
|
||||
/>
|
||||
<Shortcut
|
||||
label={t("helpDialog.preventBinding")}
|
||||
shortcuts={[getShortcutKey("CtrlOrCmd")]}
|
||||
|
@@ -26,9 +26,9 @@ export const TTDDialogTrigger = ({
|
||||
setAppState({ openDialog: { name: "ttd", tab: "text-to-diagram" } });
|
||||
}}
|
||||
icon={icon ?? brainIcon}
|
||||
badge={<DropdownMenu.Item.Badge>AI</DropdownMenu.Item.Badge>}
|
||||
>
|
||||
{children ?? t("labels.textToDiagram")}
|
||||
<DropdownMenu.Item.Badge>AI</DropdownMenu.Item.Badge>
|
||||
</DropdownMenu.Item>
|
||||
</TTDDialogTriggerTunnel.In>
|
||||
);
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
.dropdown-menu {
|
||||
max-width: 16rem;
|
||||
margin-top: 0.25rem;
|
||||
|
||||
&__submenu-trigger {
|
||||
&[aria-expanded="true"] {
|
||||
@@ -60,6 +61,7 @@
|
||||
|
||||
.dropdown-menu-item-base {
|
||||
display: flex;
|
||||
padding: 0 0.625rem;
|
||||
column-gap: 0.625rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-on-surface);
|
||||
@@ -125,7 +127,7 @@
|
||||
border: 1px solid transparent;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
border-radius: var(--border-radius-sm);
|
||||
border-radius: var(--border-radius-md);
|
||||
flex: 1 0 auto;
|
||||
|
||||
@media screen and (min-width: 1921px) {
|
||||
|
@@ -1,5 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||
|
||||
import DropdownMenuContent from "./DropdownMenuContent";
|
||||
import DropdownMenuGroup from "./DropdownMenuGroup";
|
||||
import DropdownMenuItem from "./DropdownMenuItem";
|
||||
@@ -14,8 +16,6 @@ import {
|
||||
|
||||
import "./DropdownMenu.scss";
|
||||
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||
|
||||
const DropdownMenu = ({
|
||||
children,
|
||||
open,
|
||||
|
@@ -3,6 +3,8 @@ import React, { useEffect, useRef } from "react";
|
||||
|
||||
import { EVENT, KEYS } from "@excalidraw/common";
|
||||
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||
|
||||
import { useOutsideClick } from "../../hooks/useOutsideClick";
|
||||
import { useStable } from "../../hooks/useStable";
|
||||
import { useDevice } from "../App";
|
||||
@@ -11,8 +13,6 @@ import Stack from "../Stack";
|
||||
|
||||
import { DropdownMenuContentPropsContext } from "./common";
|
||||
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||
|
||||
const MenuContent = ({
|
||||
children,
|
||||
onClickOutside,
|
||||
@@ -89,7 +89,7 @@ const MenuContent = ({
|
||||
) : (
|
||||
<Island
|
||||
className="dropdown-menu-container"
|
||||
padding={1}
|
||||
padding={2}
|
||||
style={{ zIndex: 2 }}
|
||||
>
|
||||
{children}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import React, { useRef } from "react";
|
||||
|
||||
import { THEME } from "@excalidraw/common";
|
||||
|
||||
@@ -22,53 +22,41 @@ import type { JSX } from "react";
|
||||
const DropdownMenuItem = ({
|
||||
icon,
|
||||
value,
|
||||
badge,
|
||||
order,
|
||||
children,
|
||||
shortcut,
|
||||
className,
|
||||
hovered,
|
||||
selected,
|
||||
textStyle,
|
||||
onSelect,
|
||||
onClick,
|
||||
...rest
|
||||
}: {
|
||||
icon?: JSX.Element;
|
||||
badge?: React.ReactNode;
|
||||
value?: string | number | undefined;
|
||||
order?: number;
|
||||
onSelect?: (event: Event) => void;
|
||||
children: React.ReactNode;
|
||||
shortcut?: string;
|
||||
hovered?: boolean;
|
||||
|
||||
selected?: boolean;
|
||||
textStyle?: React.CSSProperties;
|
||||
|
||||
className?: string;
|
||||
} & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onSelect">) => {
|
||||
const handleClick = useHandleDropdownMenuItemClick(onClick, onSelect);
|
||||
const ref = useRef<HTMLButtonElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (hovered) {
|
||||
if (order === 0) {
|
||||
// scroll into the first item differently, so it's visible what is above (i.e. group title)
|
||||
ref.current?.scrollIntoView({ block: "end" });
|
||||
} else {
|
||||
ref.current?.scrollIntoView({ block: "nearest" });
|
||||
}
|
||||
}
|
||||
}, [hovered, order]);
|
||||
|
||||
return (
|
||||
<DropdownMenuPrimitive.Item className="radix-menu-item">
|
||||
<Button
|
||||
{...rest}
|
||||
ref={ref}
|
||||
// onClick={handleClick}
|
||||
onSelect={handleClick}
|
||||
className={getDropdownMenuItemClassName(className, selected, hovered)}
|
||||
className={getDropdownMenuItemClassName(className)}
|
||||
title={rest.title ?? rest["aria-label"]}
|
||||
>
|
||||
<MenuItemContent textStyle={textStyle} icon={icon} shortcut={shortcut}>
|
||||
<MenuItemContent icon={icon} shortcut={shortcut} badge={badge}>
|
||||
{children}
|
||||
</MenuItemContent>
|
||||
</Button>
|
||||
|
@@ -2,25 +2,24 @@ import { useDevice } from "../App";
|
||||
|
||||
import { Ellipsify } from "../Ellipsify";
|
||||
|
||||
import type { JSX } from "react";
|
||||
|
||||
const MenuItemContent = ({
|
||||
textStyle,
|
||||
icon,
|
||||
badge,
|
||||
shortcut,
|
||||
children,
|
||||
}: {
|
||||
icon?: JSX.Element;
|
||||
icon?: React.ReactNode;
|
||||
shortcut?: string;
|
||||
textStyle?: React.CSSProperties;
|
||||
children: React.ReactNode;
|
||||
badge?: React.ReactNode;
|
||||
}) => {
|
||||
const device = useDevice();
|
||||
return (
|
||||
<>
|
||||
{icon && <div className="dropdown-menu-item__icon">{icon}</div>}
|
||||
<div style={textStyle} className="dropdown-menu-item__text">
|
||||
<div className="dropdown-menu-item__text">
|
||||
<Ellipsify>{children}</Ellipsify>
|
||||
{badge}
|
||||
</div>
|
||||
{shortcut && !device.editor.isMobile && (
|
||||
<div className="dropdown-menu-item__shortcut">{shortcut}</div>
|
||||
|
@@ -8,8 +8,6 @@ import {
|
||||
useHandleDropdownMenuItemClick,
|
||||
} from "./common";
|
||||
|
||||
import type { JSX } from "react";
|
||||
|
||||
const DropdownMenuSubItem = ({
|
||||
icon,
|
||||
onSelect,
|
||||
@@ -18,7 +16,7 @@ const DropdownMenuSubItem = ({
|
||||
className,
|
||||
...rest
|
||||
}: {
|
||||
icon?: JSX.Element;
|
||||
icon?: React.ReactNode;
|
||||
onSelect: (event: Event) => void;
|
||||
children: React.ReactNode;
|
||||
shortcut?: string;
|
||||
@@ -30,8 +28,7 @@ const DropdownMenuSubItem = ({
|
||||
<DropdownMenuPrimitive.Item className="radix-menu-item">
|
||||
<Button
|
||||
{...rest}
|
||||
onClick={handleClick}
|
||||
onSelect={() => {}}
|
||||
onSelect={handleClick}
|
||||
type="button"
|
||||
className={getDropdownMenuItemClassName(className)}
|
||||
title={rest.title ?? rest["aria-label"]}
|
||||
|
@@ -1,8 +1,9 @@
|
||||
import clsx from "clsx";
|
||||
|
||||
import { useDevice } from "../App";
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||
|
||||
import { useDevice } from "../App";
|
||||
|
||||
const MenuTrigger = ({
|
||||
className = "",
|
||||
children,
|
||||
|
@@ -2278,3 +2278,21 @@ export const elementLinkIcon = createIcon(
|
||||
</g>,
|
||||
tablerIconProps,
|
||||
);
|
||||
|
||||
export const settingsIcon = createIcon(
|
||||
<g strokeWidth={1.25}>
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M14 6m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
|
||||
<path d="M4 6l8 0" />
|
||||
<path d="M16 6l4 0" />
|
||||
<path d="M8 12m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
|
||||
<path d="M4 12l2 0" />
|
||||
<path d="M10 12l10 0" />
|
||||
<path d="M17 18m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
|
||||
<path d="M4 18l11 0" />
|
||||
<path d="M19 18l1 0" />
|
||||
</g>,
|
||||
tablerIconProps,
|
||||
);
|
||||
|
||||
export const emptyIcon = <div style={{ width: "1rem", height: "1rem" }} />;
|
||||
|
@@ -9,8 +9,11 @@ import {
|
||||
actionLoadScene,
|
||||
actionSaveToActiveFile,
|
||||
actionShortcuts,
|
||||
actionToggleGridMode,
|
||||
actionToggleObjectsSnapMode,
|
||||
actionToggleSearchMenu,
|
||||
actionToggleTheme,
|
||||
actionToggleZenMode,
|
||||
} from "../../actions";
|
||||
import { getShortcutFromShortcutName } from "../../actions/shortcuts";
|
||||
import { trackEvent } from "../../analytics";
|
||||
@@ -23,13 +26,23 @@ import {
|
||||
useExcalidrawActionManager,
|
||||
useExcalidrawElements,
|
||||
useAppProps,
|
||||
useApp,
|
||||
} from "../App";
|
||||
import { openConfirmModal } from "../OverwriteConfirm/OverwriteConfirmState";
|
||||
import Trans from "../Trans";
|
||||
import DropdownMenuItem from "../dropdownMenu/DropdownMenuItem";
|
||||
import DropdownMenuItemContentRadio from "../dropdownMenu/DropdownMenuItemContentRadio";
|
||||
import DropdownMenuItemLink from "../dropdownMenu/DropdownMenuItemLink";
|
||||
import { GithubIcon, DiscordIcon, XBrandIcon } from "../icons";
|
||||
import DropdownMenuSub from "../dropdownMenu/DropdownMenuSub";
|
||||
import { actionToggleViewMode } from "../../actions/actionToggleViewMode";
|
||||
import {
|
||||
GithubIcon,
|
||||
DiscordIcon,
|
||||
XBrandIcon,
|
||||
settingsIcon,
|
||||
checkIcon,
|
||||
emptyIcon,
|
||||
} from "../icons";
|
||||
import {
|
||||
boltIcon,
|
||||
DeviceDesktopIcon,
|
||||
@@ -396,3 +409,73 @@ export const LiveCollaborationTrigger = ({
|
||||
};
|
||||
|
||||
LiveCollaborationTrigger.displayName = "LiveCollaborationTrigger";
|
||||
|
||||
export const Preferences = ({ children }: { children?: React.ReactNode }) => {
|
||||
const { t } = useI18n();
|
||||
const actionManager = useExcalidrawActionManager();
|
||||
const appState = useUIAppState();
|
||||
const app = useApp();
|
||||
|
||||
return (
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSub.Trigger icon={settingsIcon}>
|
||||
{t("labels.preferences")}
|
||||
</DropdownMenuSub.Trigger>
|
||||
<DropdownMenuSub.Content className="excalidraw-main-menu-preferences-submenu">
|
||||
<DropdownMenuSub.Item
|
||||
icon={appState.activeTool.locked ? checkIcon : emptyIcon}
|
||||
shortcut={getShortcutFromShortcutName("toolLock")}
|
||||
onSelect={(event) => {
|
||||
app.toggleLock();
|
||||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
{t("labels.preferences_toolLock")}
|
||||
</DropdownMenuSub.Item>
|
||||
<DropdownMenuSub.Item
|
||||
icon={appState.objectsSnapModeEnabled ? checkIcon : emptyIcon}
|
||||
shortcut={getShortcutFromShortcutName("objectsSnapMode")}
|
||||
onSelect={(event) => {
|
||||
actionManager.executeAction(actionToggleObjectsSnapMode);
|
||||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
{t("buttons.objectsSnapMode")}
|
||||
</DropdownMenuSub.Item>
|
||||
<DropdownMenuSub.Item
|
||||
icon={appState.gridModeEnabled ? checkIcon : emptyIcon}
|
||||
shortcut={getShortcutFromShortcutName("gridMode")}
|
||||
onSelect={(event) => {
|
||||
actionManager.executeAction(actionToggleGridMode);
|
||||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
{t("labels.toggleGrid")}
|
||||
</DropdownMenuSub.Item>
|
||||
<DropdownMenuSub.Item
|
||||
icon={appState.zenModeEnabled ? checkIcon : emptyIcon}
|
||||
shortcut={getShortcutFromShortcutName("zenMode")}
|
||||
onSelect={(event) => {
|
||||
actionManager.executeAction(actionToggleZenMode);
|
||||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
{t("buttons.zenMode")}
|
||||
</DropdownMenuSub.Item>
|
||||
<DropdownMenuSub.Item
|
||||
icon={appState.viewModeEnabled ? checkIcon : emptyIcon}
|
||||
shortcut={getShortcutFromShortcutName("viewMode")}
|
||||
onSelect={(event) => {
|
||||
actionManager.executeAction(actionToggleViewMode);
|
||||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
{t("labels.viewMode")}
|
||||
</DropdownMenuSub.Item>
|
||||
{children}
|
||||
</DropdownMenuSub.Content>
|
||||
</DropdownMenuSub>
|
||||
);
|
||||
};
|
||||
|
||||
Preferences.displayName = "Preferences";
|
||||
|
@@ -171,7 +171,9 @@
|
||||
"linkToElement": "Link to object",
|
||||
"wrapSelectionInFrame": "Wrap selection in frame",
|
||||
"tab": "Tab",
|
||||
"shapeSwitch": "Switch shape"
|
||||
"shapeSwitch": "Switch shape",
|
||||
"preferences": "Preferences",
|
||||
"preferences_toolLock": "Tool lock"
|
||||
},
|
||||
"elementLink": {
|
||||
"title": "Link to object",
|
||||
|
Reference in New Issue
Block a user