fix: stale appState of MainMenu defaultItems rendered from Actions (#6074)
This commit is contained in:
parent
9803a85381
commit
40d53d9231
@ -26,7 +26,7 @@ export const actionUnbindText = register({
|
|||||||
name: "unbindText",
|
name: "unbindText",
|
||||||
contextItemLabel: "labels.unbindText",
|
contextItemLabel: "labels.unbindText",
|
||||||
trackEvent: { category: "element" },
|
trackEvent: { category: "element" },
|
||||||
contextItemPredicate: (elements, appState) => {
|
predicate: (elements, appState) => {
|
||||||
const selectedElements = getSelectedElements(elements, appState);
|
const selectedElements = getSelectedElements(elements, appState);
|
||||||
return selectedElements.some((element) => hasBoundTextElement(element));
|
return selectedElements.some((element) => hasBoundTextElement(element));
|
||||||
},
|
},
|
||||||
@ -76,7 +76,7 @@ export const actionBindText = register({
|
|||||||
name: "bindText",
|
name: "bindText",
|
||||||
contextItemLabel: "labels.bindText",
|
contextItemLabel: "labels.bindText",
|
||||||
trackEvent: { category: "element" },
|
trackEvent: { category: "element" },
|
||||||
contextItemPredicate: (elements, appState) => {
|
predicate: (elements, appState) => {
|
||||||
const selectedElements = getSelectedElements(elements, appState);
|
const selectedElements = getSelectedElements(elements, appState);
|
||||||
|
|
||||||
if (selectedElements.length === 2) {
|
if (selectedElements.length === 2) {
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
import { ColorPicker } from "../components/ColorPicker";
|
import { ColorPicker } from "../components/ColorPicker";
|
||||||
import {
|
import { eraser, ZoomInIcon, ZoomOutIcon } from "../components/icons";
|
||||||
eraser,
|
|
||||||
MoonIcon,
|
|
||||||
SunIcon,
|
|
||||||
ZoomInIcon,
|
|
||||||
ZoomOutIcon,
|
|
||||||
} from "../components/icons";
|
|
||||||
import { ToolButton } from "../components/ToolButton";
|
import { ToolButton } from "../components/ToolButton";
|
||||||
import { MIN_ZOOM, THEME, ZOOM_STEP } from "../constants";
|
import { MIN_ZOOM, THEME, ZOOM_STEP } from "../constants";
|
||||||
import { getCommonBounds, getNonDeletedElements } from "../element";
|
import { getCommonBounds, getNonDeletedElements } from "../element";
|
||||||
@ -21,14 +15,17 @@ import { register } from "./register";
|
|||||||
import { Tooltip } from "../components/Tooltip";
|
import { Tooltip } from "../components/Tooltip";
|
||||||
import { newElementWith } from "../element/mutateElement";
|
import { newElementWith } from "../element/mutateElement";
|
||||||
import { getDefaultAppState, isEraserActive } from "../appState";
|
import { getDefaultAppState, isEraserActive } from "../appState";
|
||||||
import ClearCanvas from "../components/ClearCanvas";
|
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import DropdownMenuItem from "../components/dropdownMenu/DropdownMenuItem";
|
|
||||||
import { getShortcutFromShortcutName } from "./shortcuts";
|
|
||||||
|
|
||||||
export const actionChangeViewBackgroundColor = register({
|
export const actionChangeViewBackgroundColor = register({
|
||||||
name: "changeViewBackgroundColor",
|
name: "changeViewBackgroundColor",
|
||||||
trackEvent: false,
|
trackEvent: false,
|
||||||
|
predicate: (elements, appState, props, app) => {
|
||||||
|
return (
|
||||||
|
!!app.props.UIOptions.canvasActions.changeViewBackgroundColor &&
|
||||||
|
!appState.viewModeEnabled
|
||||||
|
);
|
||||||
|
},
|
||||||
perform: (_, appState, value) => {
|
perform: (_, appState, value) => {
|
||||||
return {
|
return {
|
||||||
appState: { ...appState, ...value },
|
appState: { ...appState, ...value },
|
||||||
@ -36,6 +33,7 @@ export const actionChangeViewBackgroundColor = register({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
PanelComponent: ({ elements, appState, updateData }) => {
|
PanelComponent: ({ elements, appState, updateData }) => {
|
||||||
|
// FIXME move me to src/components/mainMenu/DefaultItems.tsx
|
||||||
return (
|
return (
|
||||||
<div style={{ position: "relative" }}>
|
<div style={{ position: "relative" }}>
|
||||||
<ColorPicker
|
<ColorPicker
|
||||||
@ -59,6 +57,12 @@ export const actionChangeViewBackgroundColor = register({
|
|||||||
export const actionClearCanvas = register({
|
export const actionClearCanvas = register({
|
||||||
name: "clearCanvas",
|
name: "clearCanvas",
|
||||||
trackEvent: { category: "canvas" },
|
trackEvent: { category: "canvas" },
|
||||||
|
predicate: (elements, appState, props, app) => {
|
||||||
|
return (
|
||||||
|
!!app.props.UIOptions.canvasActions.clearCanvas &&
|
||||||
|
!appState.viewModeEnabled
|
||||||
|
);
|
||||||
|
},
|
||||||
perform: (elements, appState, _, app) => {
|
perform: (elements, appState, _, app) => {
|
||||||
app.imageCache.clear();
|
app.imageCache.clear();
|
||||||
return {
|
return {
|
||||||
@ -84,8 +88,6 @@ export const actionClearCanvas = register({
|
|||||||
commitToHistory: true,
|
commitToHistory: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
PanelComponent: ({ updateData }) => <ClearCanvas onConfirm={updateData} />,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const actionZoomIn = register({
|
export const actionZoomIn = register({
|
||||||
@ -298,26 +300,10 @@ export const actionToggleTheme = register({
|
|||||||
commitToHistory: false,
|
commitToHistory: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
PanelComponent: ({ appState, updateData }) => (
|
|
||||||
<DropdownMenuItem
|
|
||||||
onSelect={() => {
|
|
||||||
updateData(appState.theme === THEME.LIGHT ? THEME.DARK : THEME.LIGHT);
|
|
||||||
}}
|
|
||||||
icon={appState.theme === "dark" ? SunIcon : MoonIcon}
|
|
||||||
dataTestId="toggle-dark-mode"
|
|
||||||
shortcut={getShortcutFromShortcutName("toggleTheme")}
|
|
||||||
ariaLabel={
|
|
||||||
appState.theme === "dark"
|
|
||||||
? t("buttons.lightMode")
|
|
||||||
: t("buttons.darkMode")
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{appState.theme === "dark"
|
|
||||||
? t("buttons.lightMode")
|
|
||||||
: t("buttons.darkMode")}
|
|
||||||
</DropdownMenuItem>
|
|
||||||
),
|
|
||||||
keyTest: (event) => event.altKey && event.shiftKey && event.code === CODES.D,
|
keyTest: (event) => event.altKey && event.shiftKey && event.code === CODES.D,
|
||||||
|
predicate: (elements, appState, props, app) => {
|
||||||
|
return !!app.props.UIOptions.canvasActions.toggleTheme;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const actionErase = register({
|
export const actionErase = register({
|
||||||
|
@ -24,7 +24,7 @@ export const actionCopy = register({
|
|||||||
commitToHistory: false,
|
commitToHistory: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
contextItemPredicate: (elements, appState, appProps, app) => {
|
predicate: (elements, appState, appProps, app) => {
|
||||||
return app.device.isMobile && !!navigator.clipboard;
|
return app.device.isMobile && !!navigator.clipboard;
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.copy",
|
contextItemLabel: "labels.copy",
|
||||||
@ -41,7 +41,7 @@ export const actionPaste = register({
|
|||||||
commitToHistory: false,
|
commitToHistory: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
contextItemPredicate: (elements, appState, appProps, app) => {
|
predicate: (elements, appState, appProps, app) => {
|
||||||
return app.device.isMobile && !!navigator.clipboard;
|
return app.device.isMobile && !!navigator.clipboard;
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.paste",
|
contextItemLabel: "labels.paste",
|
||||||
@ -56,7 +56,7 @@ export const actionCut = register({
|
|||||||
actionCopy.perform(elements, appState, data, app);
|
actionCopy.perform(elements, appState, data, app);
|
||||||
return actionDeleteSelected.perform(elements, appState);
|
return actionDeleteSelected.perform(elements, appState);
|
||||||
},
|
},
|
||||||
contextItemPredicate: (elements, appState, appProps, app) => {
|
predicate: (elements, appState, appProps, app) => {
|
||||||
return app.device.isMobile && !!navigator.clipboard;
|
return app.device.isMobile && !!navigator.clipboard;
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.cut",
|
contextItemLabel: "labels.cut",
|
||||||
@ -101,7 +101,7 @@ export const actionCopyAsSvg = register({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
contextItemPredicate: (elements) => {
|
predicate: (elements) => {
|
||||||
return probablySupportsClipboardWriteText && elements.length > 0;
|
return probablySupportsClipboardWriteText && elements.length > 0;
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.copyAsSvg",
|
contextItemLabel: "labels.copyAsSvg",
|
||||||
@ -158,7 +158,7 @@ export const actionCopyAsPng = register({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
contextItemPredicate: (elements) => {
|
predicate: (elements) => {
|
||||||
return probablySupportsClipboardBlob && elements.length > 0;
|
return probablySupportsClipboardBlob && elements.length > 0;
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.copyAsPng",
|
contextItemLabel: "labels.copyAsPng",
|
||||||
@ -188,7 +188,7 @@ export const copyText = register({
|
|||||||
commitToHistory: false,
|
commitToHistory: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
contextItemPredicate: (elements, appState) => {
|
predicate: (elements, appState) => {
|
||||||
return (
|
return (
|
||||||
probablySupportsClipboardWriteText &&
|
probablySupportsClipboardWriteText &&
|
||||||
getSelectedElements(elements, appState, true).some(isTextElement)
|
getSelectedElements(elements, appState, true).some(isTextElement)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { LoadIcon, questionCircle, saveAs } from "../components/icons";
|
import { questionCircle, saveAs } from "../components/icons";
|
||||||
import { ProjectName } from "../components/ProjectName";
|
import { ProjectName } from "../components/ProjectName";
|
||||||
import { ToolButton } from "../components/ToolButton";
|
import { ToolButton } from "../components/ToolButton";
|
||||||
import "../components/ToolIcon.scss";
|
|
||||||
import { Tooltip } from "../components/Tooltip";
|
import { Tooltip } from "../components/Tooltip";
|
||||||
import { DarkModeToggle } from "../components/DarkModeToggle";
|
import { DarkModeToggle } from "../components/DarkModeToggle";
|
||||||
import { loadFromJSON, saveAsJSON } from "../data";
|
import { loadFromJSON, saveAsJSON } from "../data";
|
||||||
@ -15,12 +14,11 @@ import { getExportSize } from "../scene/export";
|
|||||||
import { DEFAULT_EXPORT_PADDING, EXPORT_SCALES, THEME } from "../constants";
|
import { DEFAULT_EXPORT_PADDING, EXPORT_SCALES, THEME } from "../constants";
|
||||||
import { getSelectedElements, isSomeElementSelected } from "../scene";
|
import { getSelectedElements, isSomeElementSelected } from "../scene";
|
||||||
import { getNonDeletedElements } from "../element";
|
import { getNonDeletedElements } from "../element";
|
||||||
import { ActiveFile } from "../components/ActiveFile";
|
|
||||||
import { isImageFileHandle } from "../data/blob";
|
import { isImageFileHandle } from "../data/blob";
|
||||||
import { nativeFileSystemSupported } from "../data/filesystem";
|
import { nativeFileSystemSupported } from "../data/filesystem";
|
||||||
import { Theme } from "../element/types";
|
import { Theme } from "../element/types";
|
||||||
import DropdownMenuItem from "../components/dropdownMenu/DropdownMenuItem";
|
|
||||||
import { getShortcutFromShortcutName } from "./shortcuts";
|
import "../components/ToolIcon.scss";
|
||||||
|
|
||||||
export const actionChangeProjectName = register({
|
export const actionChangeProjectName = register({
|
||||||
name: "changeProjectName",
|
name: "changeProjectName",
|
||||||
@ -133,6 +131,13 @@ export const actionChangeExportEmbedScene = register({
|
|||||||
export const actionSaveToActiveFile = register({
|
export const actionSaveToActiveFile = register({
|
||||||
name: "saveToActiveFile",
|
name: "saveToActiveFile",
|
||||||
trackEvent: { category: "export" },
|
trackEvent: { category: "export" },
|
||||||
|
predicate: (elements, appState, props, app) => {
|
||||||
|
return (
|
||||||
|
!!app.props.UIOptions.canvasActions.saveToActiveFile &&
|
||||||
|
!!appState.fileHandle &&
|
||||||
|
!appState.viewModeEnabled
|
||||||
|
);
|
||||||
|
},
|
||||||
perform: async (elements, appState, value, app) => {
|
perform: async (elements, appState, value, app) => {
|
||||||
const fileHandleExists = !!appState.fileHandle;
|
const fileHandleExists = !!appState.fileHandle;
|
||||||
|
|
||||||
@ -169,12 +174,6 @@ export const actionSaveToActiveFile = register({
|
|||||||
},
|
},
|
||||||
keyTest: (event) =>
|
keyTest: (event) =>
|
||||||
event.key === KEYS.S && event[KEYS.CTRL_OR_CMD] && !event.shiftKey,
|
event.key === KEYS.S && event[KEYS.CTRL_OR_CMD] && !event.shiftKey,
|
||||||
PanelComponent: ({ updateData, appState }) => (
|
|
||||||
<ActiveFile
|
|
||||||
onSave={() => updateData(null)}
|
|
||||||
fileName={appState.fileHandle?.name}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const actionSaveFileToDisk = register({
|
export const actionSaveFileToDisk = register({
|
||||||
@ -220,6 +219,11 @@ export const actionSaveFileToDisk = register({
|
|||||||
export const actionLoadScene = register({
|
export const actionLoadScene = register({
|
||||||
name: "loadScene",
|
name: "loadScene",
|
||||||
trackEvent: { category: "export" },
|
trackEvent: { category: "export" },
|
||||||
|
predicate: (elements, appState, props, app) => {
|
||||||
|
return (
|
||||||
|
!!app.props.UIOptions.canvasActions.loadScene && !appState.viewModeEnabled
|
||||||
|
);
|
||||||
|
},
|
||||||
perform: async (elements, appState, _, app) => {
|
perform: async (elements, appState, _, app) => {
|
||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
@ -247,19 +251,6 @@ export const actionLoadScene = register({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.key === KEYS.O,
|
keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.key === KEYS.O,
|
||||||
PanelComponent: ({ updateData }) => {
|
|
||||||
return (
|
|
||||||
<DropdownMenuItem
|
|
||||||
icon={LoadIcon}
|
|
||||||
onSelect={updateData}
|
|
||||||
dataTestId="load-button"
|
|
||||||
shortcut={getShortcutFromShortcutName("loadScene")}
|
|
||||||
ariaLabel={t("buttons.load")}
|
|
||||||
>
|
|
||||||
{t("buttons.load")}
|
|
||||||
</DropdownMenuItem>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const actionExportWithDarkMode = register({
|
export const actionExportWithDarkMode = register({
|
||||||
|
@ -50,7 +50,7 @@ export const actionFlipHorizontal = register({
|
|||||||
},
|
},
|
||||||
keyTest: (event) => event.shiftKey && event.code === "KeyH",
|
keyTest: (event) => event.shiftKey && event.code === "KeyH",
|
||||||
contextItemLabel: "labels.flipHorizontal",
|
contextItemLabel: "labels.flipHorizontal",
|
||||||
contextItemPredicate: (elements, appState) =>
|
predicate: (elements, appState) =>
|
||||||
enableActionFlipHorizontal(elements, appState),
|
enableActionFlipHorizontal(elements, appState),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ export const actionFlipVertical = register({
|
|||||||
keyTest: (event) =>
|
keyTest: (event) =>
|
||||||
event.shiftKey && event.code === "KeyV" && !event[KEYS.CTRL_OR_CMD],
|
event.shiftKey && event.code === "KeyV" && !event[KEYS.CTRL_OR_CMD],
|
||||||
contextItemLabel: "labels.flipVertical",
|
contextItemLabel: "labels.flipVertical",
|
||||||
contextItemPredicate: (elements, appState) =>
|
predicate: (elements, appState) =>
|
||||||
enableActionFlipVertical(elements, appState),
|
enableActionFlipVertical(elements, appState),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -129,8 +129,7 @@ export const actionGroup = register({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.group",
|
contextItemLabel: "labels.group",
|
||||||
contextItemPredicate: (elements, appState) =>
|
predicate: (elements, appState) => enableActionGroup(elements, appState),
|
||||||
enableActionGroup(elements, appState),
|
|
||||||
keyTest: (event) =>
|
keyTest: (event) =>
|
||||||
!event.shiftKey && event[KEYS.CTRL_OR_CMD] && event.key === KEYS.G,
|
!event.shiftKey && event[KEYS.CTRL_OR_CMD] && event.key === KEYS.G,
|
||||||
PanelComponent: ({ elements, appState, updateData }) => (
|
PanelComponent: ({ elements, appState, updateData }) => (
|
||||||
@ -193,8 +192,7 @@ export const actionUngroup = register({
|
|||||||
event[KEYS.CTRL_OR_CMD] &&
|
event[KEYS.CTRL_OR_CMD] &&
|
||||||
event.key === KEYS.G.toUpperCase(),
|
event.key === KEYS.G.toUpperCase(),
|
||||||
contextItemLabel: "labels.ungroup",
|
contextItemLabel: "labels.ungroup",
|
||||||
contextItemPredicate: (elements, appState) =>
|
predicate: (elements, appState) => getSelectedGroupIds(appState).length > 0,
|
||||||
getSelectedGroupIds(appState).length > 0,
|
|
||||||
|
|
||||||
PanelComponent: ({ elements, appState, updateData }) => (
|
PanelComponent: ({ elements, appState, updateData }) => (
|
||||||
<ToolButton
|
<ToolButton
|
||||||
|
@ -10,7 +10,7 @@ export const actionToggleLinearEditor = register({
|
|||||||
trackEvent: {
|
trackEvent: {
|
||||||
category: "element",
|
category: "element",
|
||||||
},
|
},
|
||||||
contextItemPredicate: (elements, appState) => {
|
predicate: (elements, appState) => {
|
||||||
const selectedElements = getSelectedElements(elements, appState);
|
const selectedElements = getSelectedElements(elements, appState);
|
||||||
if (selectedElements.length === 1 && isLinearElement(selectedElements[0])) {
|
if (selectedElements.length === 1 && isLinearElement(selectedElements[0])) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import { HamburgerMenuIcon, HelpIcon, palette } from "../components/icons";
|
import { HamburgerMenuIcon, palette } from "../components/icons";
|
||||||
import { ToolButton } from "../components/ToolButton";
|
import { ToolButton } from "../components/ToolButton";
|
||||||
import { t } from "../i18n";
|
import { t } from "../i18n";
|
||||||
import { showSelectedShapeActions, getNonDeletedElements } from "../element";
|
import { showSelectedShapeActions, getNonDeletedElements } from "../element";
|
||||||
import { register } from "./register";
|
import { register } from "./register";
|
||||||
import { allowFullScreen, exitFullScreen, isFullScreen } from "../utils";
|
import { allowFullScreen, exitFullScreen, isFullScreen } from "../utils";
|
||||||
import { KEYS } from "../keys";
|
import { KEYS } from "../keys";
|
||||||
import { HelpButton } from "../components/HelpButton";
|
|
||||||
import DropdownMenuItem from "../components/dropdownMenu/DropdownMenuItem";
|
|
||||||
|
|
||||||
export const actionToggleCanvasMenu = register({
|
export const actionToggleCanvasMenu = register({
|
||||||
name: "toggleCanvasMenu",
|
name: "toggleCanvasMenu",
|
||||||
@ -88,19 +86,5 @@ export const actionShortcuts = register({
|
|||||||
commitToHistory: false,
|
commitToHistory: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
PanelComponent: ({ updateData, isInHamburgerMenu }) =>
|
|
||||||
isInHamburgerMenu ? (
|
|
||||||
<DropdownMenuItem
|
|
||||||
dataTestId="help-menu-item"
|
|
||||||
icon={HelpIcon}
|
|
||||||
onSelect={updateData}
|
|
||||||
shortcut="?"
|
|
||||||
ariaLabel={t("helpDialog.title")}
|
|
||||||
>
|
|
||||||
{t("helpDialog.title")}
|
|
||||||
</DropdownMenuItem>
|
|
||||||
) : (
|
|
||||||
<HelpButton title={t("helpDialog.title")} onClick={updateData} />
|
|
||||||
),
|
|
||||||
keyTest: (event) => event.key === KEYS.QUESTION_MARK,
|
keyTest: (event) => event.key === KEYS.QUESTION_MARK,
|
||||||
});
|
});
|
||||||
|
@ -20,7 +20,7 @@ export const actionToggleGridMode = register({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
checked: (appState: AppState) => appState.gridSize !== null,
|
checked: (appState: AppState) => appState.gridSize !== null,
|
||||||
contextItemPredicate: (element, appState, props) => {
|
predicate: (element, appState, props) => {
|
||||||
return typeof props.gridModeEnabled === "undefined";
|
return typeof props.gridModeEnabled === "undefined";
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.showGrid",
|
contextItemLabel: "labels.showGrid",
|
||||||
|
@ -18,7 +18,7 @@ export const actionToggleViewMode = register({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
checked: (appState) => appState.viewModeEnabled,
|
checked: (appState) => appState.viewModeEnabled,
|
||||||
contextItemPredicate: (elements, appState, appProps) => {
|
predicate: (elements, appState, appProps) => {
|
||||||
return typeof appProps.viewModeEnabled === "undefined";
|
return typeof appProps.viewModeEnabled === "undefined";
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.viewMode",
|
contextItemLabel: "labels.viewMode",
|
||||||
|
@ -18,7 +18,7 @@ export const actionToggleZenMode = register({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
checked: (appState) => appState.zenModeEnabled,
|
checked: (appState) => appState.zenModeEnabled,
|
||||||
contextItemPredicate: (elements, appState, appProps) => {
|
predicate: (elements, appState, appProps) => {
|
||||||
return typeof appProps.zenModeEnabled === "undefined";
|
return typeof appProps.zenModeEnabled === "undefined";
|
||||||
},
|
},
|
||||||
contextItemLabel: "buttons.zenMode",
|
contextItemLabel: "buttons.zenMode",
|
||||||
|
@ -131,11 +131,7 @@ export class ActionManager {
|
|||||||
/**
|
/**
|
||||||
* @param data additional data sent to the PanelComponent
|
* @param data additional data sent to the PanelComponent
|
||||||
*/
|
*/
|
||||||
renderAction = (
|
renderAction = (name: ActionName, data?: PanelComponentProps["data"]) => {
|
||||||
name: ActionName,
|
|
||||||
data?: PanelComponentProps["data"],
|
|
||||||
isInHamburgerMenu = false,
|
|
||||||
) => {
|
|
||||||
const canvasActions = this.app.props.UIOptions.canvasActions;
|
const canvasActions = this.app.props.UIOptions.canvasActions;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -170,11 +166,20 @@ export class ActionManager {
|
|||||||
updateData={updateData}
|
updateData={updateData}
|
||||||
appProps={this.app.props}
|
appProps={this.app.props}
|
||||||
data={data}
|
data={data}
|
||||||
isInHamburgerMenu={isInHamburgerMenu}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
isActionEnabled = (action: Action) => {
|
||||||
|
const elements = this.getElementsIncludingDeleted();
|
||||||
|
const appState = this.getAppState();
|
||||||
|
|
||||||
|
return (
|
||||||
|
!action.predicate ||
|
||||||
|
action.predicate(elements, appState, this.app.props, this.app)
|
||||||
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -124,9 +124,7 @@ export type PanelComponentProps = {
|
|||||||
|
|
||||||
export interface Action {
|
export interface Action {
|
||||||
name: ActionName;
|
name: ActionName;
|
||||||
PanelComponent?: React.FC<
|
PanelComponent?: React.FC<PanelComponentProps>;
|
||||||
PanelComponentProps & { isInHamburgerMenu: boolean }
|
|
||||||
>;
|
|
||||||
perform: ActionFn;
|
perform: ActionFn;
|
||||||
keyPriority?: number;
|
keyPriority?: number;
|
||||||
keyTest?: (
|
keyTest?: (
|
||||||
@ -140,7 +138,7 @@ export interface Action {
|
|||||||
elements: readonly ExcalidrawElement[],
|
elements: readonly ExcalidrawElement[],
|
||||||
appState: Readonly<AppState>,
|
appState: Readonly<AppState>,
|
||||||
) => string);
|
) => string);
|
||||||
contextItemPredicate?: (
|
predicate?: (
|
||||||
elements: readonly ExcalidrawElement[],
|
elements: readonly ExcalidrawElement[],
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
appProps: ExcalidrawProps,
|
appProps: ExcalidrawProps,
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
// TODO barnabasmolnar/editor-redesign
|
|
||||||
// this icon is not great
|
|
||||||
import { getShortcutFromShortcutName } from "../actions/shortcuts";
|
|
||||||
import { save } from "../components/icons";
|
|
||||||
import { t } from "../i18n";
|
|
||||||
|
|
||||||
import "./ActiveFile.scss";
|
|
||||||
import DropdownMenuItem from "./dropdownMenu/DropdownMenuItem";
|
|
||||||
|
|
||||||
type ActiveFileProps = {
|
|
||||||
fileName?: string;
|
|
||||||
onSave: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ActiveFile = ({ fileName, onSave }: ActiveFileProps) => (
|
|
||||||
<DropdownMenuItem
|
|
||||||
shortcut={getShortcutFromShortcutName("saveScene")}
|
|
||||||
dataTestId="save-button"
|
|
||||||
onSelect={onSave}
|
|
||||||
icon={save}
|
|
||||||
ariaLabel={`${t("buttons.save")}`}
|
|
||||||
>{`${t("buttons.save")}`}</DropdownMenuItem>
|
|
||||||
);
|
|
@ -312,9 +312,9 @@ const ExcalidrawSetAppStateContext = React.createContext<
|
|||||||
>(() => {});
|
>(() => {});
|
||||||
ExcalidrawSetAppStateContext.displayName = "ExcalidrawSetAppStateContext";
|
ExcalidrawSetAppStateContext.displayName = "ExcalidrawSetAppStateContext";
|
||||||
|
|
||||||
const ExcalidrawActionManagerContext = React.createContext<
|
const ExcalidrawActionManagerContext = React.createContext<ActionManager>(
|
||||||
ActionManager | { renderAction: ActionManager["renderAction"] }
|
null!,
|
||||||
>({ renderAction: () => null });
|
);
|
||||||
ExcalidrawActionManagerContext.displayName = "ExcalidrawActionManagerContext";
|
ExcalidrawActionManagerContext.displayName = "ExcalidrawActionManagerContext";
|
||||||
|
|
||||||
export const useExcalidrawElements = () =>
|
export const useExcalidrawElements = () =>
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
import { useState } from "react";
|
|
||||||
import { t } from "../i18n";
|
|
||||||
import { TrashIcon } from "./icons";
|
|
||||||
|
|
||||||
import ConfirmDialog from "./ConfirmDialog";
|
|
||||||
import DropdownMenuItem from "./dropdownMenu/DropdownMenuItem";
|
|
||||||
|
|
||||||
const ClearCanvas = ({ onConfirm }: { onConfirm: () => void }) => {
|
|
||||||
const [showDialog, setShowDialog] = useState(false);
|
|
||||||
const toggleDialog = () => {
|
|
||||||
setShowDialog(!showDialog);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<DropdownMenuItem
|
|
||||||
icon={TrashIcon}
|
|
||||||
onSelect={toggleDialog}
|
|
||||||
dataTestId="clear-canvas-button"
|
|
||||||
ariaLabel={t("buttons.clearReset")}
|
|
||||||
>
|
|
||||||
{t("buttons.clearReset")}
|
|
||||||
</DropdownMenuItem>
|
|
||||||
|
|
||||||
{showDialog && (
|
|
||||||
<ConfirmDialog
|
|
||||||
onConfirm={() => {
|
|
||||||
onConfirm();
|
|
||||||
toggleDialog();
|
|
||||||
}}
|
|
||||||
onCancel={toggleDialog}
|
|
||||||
title={t("clearCanvasDialog.title")}
|
|
||||||
>
|
|
||||||
<p className="clear-canvas__content"> {t("alerts.clearReset")}</p>
|
|
||||||
</ConfirmDialog>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ClearCanvas;
|
|
@ -2,48 +2,30 @@ import { t } from "../i18n";
|
|||||||
import { UsersIcon } from "./icons";
|
import { UsersIcon } from "./icons";
|
||||||
|
|
||||||
import "./CollabButton.scss";
|
import "./CollabButton.scss";
|
||||||
import DropdownMenuItem from "./dropdownMenu/DropdownMenuItem";
|
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
const CollabButton = ({
|
const CollabButton = ({
|
||||||
isCollaborating,
|
isCollaborating,
|
||||||
collaboratorCount,
|
collaboratorCount,
|
||||||
onClick,
|
onClick,
|
||||||
isInHamburgerMenu = true,
|
|
||||||
}: {
|
}: {
|
||||||
isCollaborating: boolean;
|
isCollaborating: boolean;
|
||||||
collaboratorCount: number;
|
collaboratorCount: number;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
isInHamburgerMenu?: boolean;
|
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<button
|
||||||
{isInHamburgerMenu ? (
|
className={clsx("collab-button", { active: isCollaborating })}
|
||||||
<DropdownMenuItem
|
type="button"
|
||||||
dataTestId="collab-button"
|
onClick={onClick}
|
||||||
icon={UsersIcon}
|
style={{ position: "relative" }}
|
||||||
onSelect={onClick}
|
title={t("labels.liveCollaboration")}
|
||||||
ariaLabel={t("labels.liveCollaboration")}
|
>
|
||||||
>
|
{UsersIcon}
|
||||||
{t("labels.liveCollaboration")}
|
{collaboratorCount > 0 && (
|
||||||
</DropdownMenuItem>
|
<div className="CollabButton-collaborators">{collaboratorCount}</div>
|
||||||
) : (
|
|
||||||
<button
|
|
||||||
className={clsx("collab-button", { active: isCollaborating })}
|
|
||||||
type="button"
|
|
||||||
onClick={onClick}
|
|
||||||
style={{ position: "relative" }}
|
|
||||||
title={t("labels.liveCollaboration")}
|
|
||||||
>
|
|
||||||
{UsersIcon}
|
|
||||||
{collaboratorCount > 0 && (
|
|
||||||
<div className="CollabButton-collaborators">
|
|
||||||
{collaboratorCount}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
)}
|
)}
|
||||||
</>
|
</button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ export const ContextMenu = React.memo(
|
|||||||
if (
|
if (
|
||||||
item &&
|
item &&
|
||||||
(item === CONTEXT_MENU_SEPARATOR ||
|
(item === CONTEXT_MENU_SEPARATOR ||
|
||||||
!item.contextItemPredicate ||
|
!item.predicate ||
|
||||||
item.contextItemPredicate(
|
item.predicate(
|
||||||
elements,
|
elements,
|
||||||
appState,
|
appState,
|
||||||
actionManager.app.props,
|
actionManager.app.props,
|
||||||
|
@ -183,7 +183,9 @@ const LayerUI = ({
|
|||||||
<MainMenu>
|
<MainMenu>
|
||||||
<MainMenu.DefaultItems.LoadScene />
|
<MainMenu.DefaultItems.LoadScene />
|
||||||
<MainMenu.DefaultItems.SaveToActiveFile />
|
<MainMenu.DefaultItems.SaveToActiveFile />
|
||||||
|
{/* FIXME we should to test for this inside the item itself */}
|
||||||
{UIOptions.canvasActions.export && <MainMenu.DefaultItems.Export />}
|
{UIOptions.canvasActions.export && <MainMenu.DefaultItems.Export />}
|
||||||
|
{/* FIXME we should to test for this inside the item itself */}
|
||||||
{UIOptions.canvasActions.saveAsImage && (
|
{UIOptions.canvasActions.saveAsImage && (
|
||||||
<MainMenu.DefaultItems.SaveAsImage />
|
<MainMenu.DefaultItems.SaveAsImage />
|
||||||
)}
|
)}
|
||||||
@ -350,7 +352,6 @@ const LayerUI = ({
|
|||||||
<UserList collaborators={appState.collaborators} />
|
<UserList collaborators={appState.collaborators} />
|
||||||
{onCollabButtonClick && (
|
{onCollabButtonClick && (
|
||||||
<CollabButton
|
<CollabButton
|
||||||
isInHamburgerMenu={false}
|
|
||||||
isCollaborating={isCollaborating}
|
isCollaborating={isCollaborating}
|
||||||
collaboratorCount={appState.collaborators.size}
|
collaboratorCount={appState.collaborators.size}
|
||||||
onClick={onCollabButtonClick}
|
onClick={onCollabButtonClick}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
import { actionShortcuts } from "../../actions";
|
||||||
import { ActionManager } from "../../actions/manager";
|
import { ActionManager } from "../../actions/manager";
|
||||||
import { t } from "../../i18n";
|
import { t } from "../../i18n";
|
||||||
import { AppState, UIChildrenComponents } from "../../types";
|
import { AppState, UIChildrenComponents } from "../../types";
|
||||||
@ -9,6 +10,7 @@ import {
|
|||||||
ZoomActions,
|
ZoomActions,
|
||||||
} from "../Actions";
|
} from "../Actions";
|
||||||
import { useDevice } from "../App";
|
import { useDevice } from "../App";
|
||||||
|
import { HelpButton } from "../HelpButton";
|
||||||
import { WelcomeScreenHelpArrow } from "../icons";
|
import { WelcomeScreenHelpArrow } from "../icons";
|
||||||
import { Section } from "../Section";
|
import { Section } from "../Section";
|
||||||
import Stack from "../Stack";
|
import Stack from "../Stack";
|
||||||
@ -86,7 +88,10 @@ const Footer = ({
|
|||||||
</div>
|
</div>
|
||||||
</WelcomeScreenDecor>
|
</WelcomeScreenDecor>
|
||||||
|
|
||||||
{actionManager.renderAction("toggleShortcuts")}
|
<HelpButton
|
||||||
|
title={t("helpDialog.title")}
|
||||||
|
onClick={() => actionManager.executeAction(actionShortcuts)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ExitZenModeAction
|
<ExitZenModeAction
|
||||||
|
@ -6,34 +6,81 @@ import {
|
|||||||
useExcalidrawSetAppState,
|
useExcalidrawSetAppState,
|
||||||
useExcalidrawActionManager,
|
useExcalidrawActionManager,
|
||||||
} from "../App";
|
} from "../App";
|
||||||
import { ExportIcon, ExportImageIcon, UsersIcon } from "../icons";
|
import {
|
||||||
|
ExportIcon,
|
||||||
|
ExportImageIcon,
|
||||||
|
HelpIcon,
|
||||||
|
LoadIcon,
|
||||||
|
MoonIcon,
|
||||||
|
save,
|
||||||
|
SunIcon,
|
||||||
|
TrashIcon,
|
||||||
|
UsersIcon,
|
||||||
|
} from "../icons";
|
||||||
import { GithubIcon, DiscordIcon, TwitterIcon } from "../icons";
|
import { GithubIcon, DiscordIcon, TwitterIcon } from "../icons";
|
||||||
import DropdownMenuItem from "../dropdownMenu/DropdownMenuItem";
|
import DropdownMenuItem from "../dropdownMenu/DropdownMenuItem";
|
||||||
import DropdownMenuItemLink from "../dropdownMenu/DropdownMenuItemLink";
|
import DropdownMenuItemLink from "../dropdownMenu/DropdownMenuItemLink";
|
||||||
|
import {
|
||||||
|
actionClearCanvas,
|
||||||
|
actionLoadScene,
|
||||||
|
actionSaveToActiveFile,
|
||||||
|
actionShortcuts,
|
||||||
|
actionToggleTheme,
|
||||||
|
} from "../../actions";
|
||||||
|
|
||||||
|
import "./DefaultItems.scss";
|
||||||
|
import { useState } from "react";
|
||||||
|
import ConfirmDialog from "../ConfirmDialog";
|
||||||
|
|
||||||
export const LoadScene = () => {
|
export const LoadScene = () => {
|
||||||
|
// FIXME Hack until we tie "t" to lang state
|
||||||
|
// eslint-disable-next-line
|
||||||
const appState = useExcalidrawAppState();
|
const appState = useExcalidrawAppState();
|
||||||
const actionManager = useExcalidrawActionManager();
|
const actionManager = useExcalidrawActionManager();
|
||||||
if (appState.viewModeEnabled) {
|
|
||||||
|
if (!actionManager.isActionEnabled(actionLoadScene)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return actionManager.renderAction("loadScene");
|
|
||||||
|
return (
|
||||||
|
<DropdownMenuItem
|
||||||
|
icon={LoadIcon}
|
||||||
|
onSelect={() => actionManager.executeAction(actionLoadScene)}
|
||||||
|
dataTestId="load-button"
|
||||||
|
shortcut={getShortcutFromShortcutName("loadScene")}
|
||||||
|
ariaLabel={t("buttons.load")}
|
||||||
|
>
|
||||||
|
{t("buttons.load")}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
LoadScene.displayName = "LoadScene";
|
LoadScene.displayName = "LoadScene";
|
||||||
|
|
||||||
export const SaveToActiveFile = () => {
|
export const SaveToActiveFile = () => {
|
||||||
|
// FIXME Hack until we tie "t" to lang state
|
||||||
|
// eslint-disable-next-line
|
||||||
const appState = useExcalidrawAppState();
|
const appState = useExcalidrawAppState();
|
||||||
const actionManager = useExcalidrawActionManager();
|
const actionManager = useExcalidrawActionManager();
|
||||||
if (!appState.fileHandle) {
|
|
||||||
|
if (!actionManager.isActionEnabled(actionSaveToActiveFile)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return actionManager.renderAction("saveToActiveFile");
|
|
||||||
|
return (
|
||||||
|
<DropdownMenuItem
|
||||||
|
shortcut={getShortcutFromShortcutName("saveScene")}
|
||||||
|
dataTestId="save-button"
|
||||||
|
onSelect={() => actionManager.executeAction(actionSaveToActiveFile)}
|
||||||
|
icon={save}
|
||||||
|
ariaLabel={`${t("buttons.save")}`}
|
||||||
|
>{`${t("buttons.save")}`}</DropdownMenuItem>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
SaveToActiveFile.displayName = "SaveToActiveFile";
|
SaveToActiveFile.displayName = "SaveToActiveFile";
|
||||||
|
|
||||||
export const SaveAsImage = () => {
|
export const SaveAsImage = () => {
|
||||||
const setAppState = useExcalidrawSetAppState();
|
const setAppState = useExcalidrawSetAppState();
|
||||||
// Hack until we tie "t" to lang state
|
// FIXME Hack until we tie "t" to lang state
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const appState = useExcalidrawAppState();
|
const appState = useExcalidrawAppState();
|
||||||
return (
|
return (
|
||||||
@ -51,32 +98,96 @@ export const SaveAsImage = () => {
|
|||||||
SaveAsImage.displayName = "SaveAsImage";
|
SaveAsImage.displayName = "SaveAsImage";
|
||||||
|
|
||||||
export const Help = () => {
|
export const Help = () => {
|
||||||
// Hack until we tie "t" to lang state
|
// FIXME Hack until we tie "t" to lang state
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const appState = useExcalidrawAppState();
|
const appState = useExcalidrawAppState();
|
||||||
|
|
||||||
const actionManager = useExcalidrawActionManager();
|
const actionManager = useExcalidrawActionManager();
|
||||||
return actionManager.renderAction("toggleShortcuts", undefined, true);
|
|
||||||
|
return (
|
||||||
|
<DropdownMenuItem
|
||||||
|
dataTestId="help-menu-item"
|
||||||
|
icon={HelpIcon}
|
||||||
|
onSelect={() => actionManager.executeAction(actionShortcuts)}
|
||||||
|
shortcut="?"
|
||||||
|
ariaLabel={t("helpDialog.title")}
|
||||||
|
>
|
||||||
|
{t("helpDialog.title")}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
Help.displayName = "Help";
|
Help.displayName = "Help";
|
||||||
|
|
||||||
export const ClearCanvas = () => {
|
export const ClearCanvas = () => {
|
||||||
|
// FIXME Hack until we tie "t" to lang state
|
||||||
|
// eslint-disable-next-line
|
||||||
const appState = useExcalidrawAppState();
|
const appState = useExcalidrawAppState();
|
||||||
const actionManager = useExcalidrawActionManager();
|
const actionManager = useExcalidrawActionManager();
|
||||||
|
|
||||||
if (appState.viewModeEnabled) {
|
const [showDialog, setShowDialog] = useState(false);
|
||||||
|
const toggleDialog = () => setShowDialog(!showDialog);
|
||||||
|
|
||||||
|
if (!actionManager.isActionEnabled(actionClearCanvas)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return actionManager.renderAction("clearCanvas");
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<DropdownMenuItem
|
||||||
|
icon={TrashIcon}
|
||||||
|
onSelect={toggleDialog}
|
||||||
|
dataTestId="clear-canvas-button"
|
||||||
|
ariaLabel={t("buttons.clearReset")}
|
||||||
|
>
|
||||||
|
{t("buttons.clearReset")}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
|
||||||
|
{/* FIXME this should live outside MainMenu so it stays open
|
||||||
|
if menu is closed */}
|
||||||
|
{showDialog && (
|
||||||
|
<ConfirmDialog
|
||||||
|
onConfirm={() => {
|
||||||
|
actionManager.executeAction(actionClearCanvas);
|
||||||
|
toggleDialog();
|
||||||
|
}}
|
||||||
|
onCancel={toggleDialog}
|
||||||
|
title={t("clearCanvasDialog.title")}
|
||||||
|
>
|
||||||
|
<p className="clear-canvas__content"> {t("alerts.clearReset")}</p>
|
||||||
|
</ConfirmDialog>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
ClearCanvas.displayName = "ClearCanvas";
|
ClearCanvas.displayName = "ClearCanvas";
|
||||||
|
|
||||||
export const ToggleTheme = () => {
|
export const ToggleTheme = () => {
|
||||||
// Hack until we tie "t" to lang state
|
|
||||||
// eslint-disable-next-line
|
|
||||||
const appState = useExcalidrawAppState();
|
const appState = useExcalidrawAppState();
|
||||||
const actionManager = useExcalidrawActionManager();
|
const actionManager = useExcalidrawActionManager();
|
||||||
return actionManager.renderAction("toggleTheme");
|
|
||||||
|
if (!actionManager.isActionEnabled(actionToggleTheme)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownMenuItem
|
||||||
|
onSelect={() => {
|
||||||
|
return actionManager.executeAction(actionToggleTheme);
|
||||||
|
}}
|
||||||
|
icon={appState.theme === "dark" ? SunIcon : MoonIcon}
|
||||||
|
dataTestId="toggle-dark-mode"
|
||||||
|
shortcut={getShortcutFromShortcutName("toggleTheme")}
|
||||||
|
ariaLabel={
|
||||||
|
appState.theme === "dark"
|
||||||
|
? t("buttons.lightMode")
|
||||||
|
: t("buttons.darkMode")
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{appState.theme === "dark"
|
||||||
|
? t("buttons.lightMode")
|
||||||
|
: t("buttons.darkMode")}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
ToggleTheme.displayName = "ToggleTheme";
|
ToggleTheme.displayName = "ToggleTheme";
|
||||||
|
|
||||||
@ -101,7 +212,7 @@ export const ChangeCanvasBackground = () => {
|
|||||||
ChangeCanvasBackground.displayName = "ChangeCanvasBackground";
|
ChangeCanvasBackground.displayName = "ChangeCanvasBackground";
|
||||||
|
|
||||||
export const Export = () => {
|
export const Export = () => {
|
||||||
// Hack until we tie "t" to lang state
|
// FIXME Hack until we tie "t" to lang state
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const appState = useExcalidrawAppState();
|
const appState = useExcalidrawAppState();
|
||||||
const setAppState = useExcalidrawSetAppState();
|
const setAppState = useExcalidrawSetAppState();
|
||||||
@ -154,7 +265,7 @@ export const LiveCollaboration = ({
|
|||||||
onSelect: () => void;
|
onSelect: () => void;
|
||||||
isCollaborating: boolean;
|
isCollaborating: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
// Hack until we tie "t" to lang state
|
// FIXME Hack until we tie "t" to lang state
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const appState = useExcalidrawAppState();
|
const appState = useExcalidrawAppState();
|
||||||
return (
|
return (
|
||||||
|
@ -267,7 +267,7 @@ export const actionLink = register({
|
|||||||
keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.key === KEYS.K,
|
keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.key === KEYS.K,
|
||||||
contextItemLabel: (elements, appState) =>
|
contextItemLabel: (elements, appState) =>
|
||||||
getContextMenuLabel(elements, appState),
|
getContextMenuLabel(elements, appState),
|
||||||
contextItemPredicate: (elements, appState) => {
|
predicate: (elements, appState) => {
|
||||||
const selectedElements = getSelectedElements(elements, appState);
|
const selectedElements = getSelectedElements(elements, appState);
|
||||||
return selectedElements.length === 1;
|
return selectedElements.length === 1;
|
||||||
},
|
},
|
||||||
|
@ -13,30 +13,30 @@ Object {
|
|||||||
"items": Array [
|
"items": Array [
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.cut",
|
"contextItemLabel": "labels.cut",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "cut",
|
"name": "cut",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copy",
|
"contextItemLabel": "labels.copy",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": undefined,
|
"keyTest": undefined,
|
||||||
"name": "copy",
|
"name": "copy",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.paste",
|
"contextItemLabel": "labels.paste",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": undefined,
|
"keyTest": undefined,
|
||||||
"name": "paste",
|
"name": "paste",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -44,28 +44,28 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyAsPng",
|
"contextItemLabel": "labels.copyAsPng",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "copyAsPng",
|
"name": "copyAsPng",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyAsSvg",
|
"contextItemLabel": "labels.copyAsSvg",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "copyAsSvg",
|
"name": "copyAsSvg",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyText",
|
"contextItemLabel": "labels.copyText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "copyText",
|
"name": "copyText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -93,28 +93,28 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": "labels.group",
|
"contextItemLabel": "labels.group",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "group",
|
"name": "group",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.unbindText",
|
"contextItemLabel": "labels.unbindText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "unbindText",
|
"name": "unbindText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.bindText",
|
"contextItemLabel": "labels.bindText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "bindText",
|
"name": "bindText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -122,10 +122,10 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": "labels.ungroup",
|
"contextItemLabel": "labels.ungroup",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "ungroup",
|
"name": "ungroup",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -185,20 +185,20 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.flipHorizontal",
|
"contextItemLabel": "labels.flipHorizontal",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "flipHorizontal",
|
"name": "flipHorizontal",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.flipVertical",
|
"contextItemLabel": "labels.flipVertical",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "flipVertical",
|
"name": "flipVertical",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -206,9 +206,9 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": [Function],
|
"contextItemLabel": [Function],
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "toggleLinearEditor",
|
"name": "toggleLinearEditor",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -216,10 +216,10 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": [Function],
|
"contextItemLabel": [Function],
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "hyperlink",
|
"name": "hyperlink",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"action": "click",
|
"action": "click",
|
||||||
"category": "hyperlink",
|
"category": "hyperlink",
|
||||||
@ -4401,30 +4401,30 @@ Object {
|
|||||||
"items": Array [
|
"items": Array [
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.cut",
|
"contextItemLabel": "labels.cut",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "cut",
|
"name": "cut",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copy",
|
"contextItemLabel": "labels.copy",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": undefined,
|
"keyTest": undefined,
|
||||||
"name": "copy",
|
"name": "copy",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.paste",
|
"contextItemLabel": "labels.paste",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": undefined,
|
"keyTest": undefined,
|
||||||
"name": "paste",
|
"name": "paste",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -4432,28 +4432,28 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyAsPng",
|
"contextItemLabel": "labels.copyAsPng",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "copyAsPng",
|
"name": "copyAsPng",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyAsSvg",
|
"contextItemLabel": "labels.copyAsSvg",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "copyAsSvg",
|
"name": "copyAsSvg",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyText",
|
"contextItemLabel": "labels.copyText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "copyText",
|
"name": "copyText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -4481,28 +4481,28 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": "labels.group",
|
"contextItemLabel": "labels.group",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "group",
|
"name": "group",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.unbindText",
|
"contextItemLabel": "labels.unbindText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "unbindText",
|
"name": "unbindText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.bindText",
|
"contextItemLabel": "labels.bindText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "bindText",
|
"name": "bindText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -4510,10 +4510,10 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": "labels.ungroup",
|
"contextItemLabel": "labels.ungroup",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "ungroup",
|
"name": "ungroup",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -4573,20 +4573,20 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.flipHorizontal",
|
"contextItemLabel": "labels.flipHorizontal",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "flipHorizontal",
|
"name": "flipHorizontal",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.flipVertical",
|
"contextItemLabel": "labels.flipVertical",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "flipVertical",
|
"name": "flipVertical",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -4594,9 +4594,9 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": [Function],
|
"contextItemLabel": [Function],
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "toggleLinearEditor",
|
"name": "toggleLinearEditor",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -4604,10 +4604,10 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": [Function],
|
"contextItemLabel": [Function],
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "hyperlink",
|
"name": "hyperlink",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"action": "click",
|
"action": "click",
|
||||||
"category": "hyperlink",
|
"category": "hyperlink",
|
||||||
@ -4942,30 +4942,30 @@ Object {
|
|||||||
"items": Array [
|
"items": Array [
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.cut",
|
"contextItemLabel": "labels.cut",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "cut",
|
"name": "cut",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copy",
|
"contextItemLabel": "labels.copy",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": undefined,
|
"keyTest": undefined,
|
||||||
"name": "copy",
|
"name": "copy",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.paste",
|
"contextItemLabel": "labels.paste",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": undefined,
|
"keyTest": undefined,
|
||||||
"name": "paste",
|
"name": "paste",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -4973,28 +4973,28 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyAsPng",
|
"contextItemLabel": "labels.copyAsPng",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "copyAsPng",
|
"name": "copyAsPng",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyAsSvg",
|
"contextItemLabel": "labels.copyAsSvg",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "copyAsSvg",
|
"name": "copyAsSvg",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyText",
|
"contextItemLabel": "labels.copyText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "copyText",
|
"name": "copyText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -5022,28 +5022,28 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": "labels.group",
|
"contextItemLabel": "labels.group",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "group",
|
"name": "group",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.unbindText",
|
"contextItemLabel": "labels.unbindText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "unbindText",
|
"name": "unbindText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.bindText",
|
"contextItemLabel": "labels.bindText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "bindText",
|
"name": "bindText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -5051,10 +5051,10 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": "labels.ungroup",
|
"contextItemLabel": "labels.ungroup",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "ungroup",
|
"name": "ungroup",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -5114,20 +5114,20 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.flipHorizontal",
|
"contextItemLabel": "labels.flipHorizontal",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "flipHorizontal",
|
"name": "flipHorizontal",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.flipVertical",
|
"contextItemLabel": "labels.flipVertical",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "flipVertical",
|
"name": "flipVertical",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -5135,9 +5135,9 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": [Function],
|
"contextItemLabel": [Function],
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "toggleLinearEditor",
|
"name": "toggleLinearEditor",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -5145,10 +5145,10 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": [Function],
|
"contextItemLabel": [Function],
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "hyperlink",
|
"name": "hyperlink",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"action": "click",
|
"action": "click",
|
||||||
"category": "hyperlink",
|
"category": "hyperlink",
|
||||||
@ -5568,10 +5568,10 @@ Object {
|
|||||||
"items": Array [
|
"items": Array [
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.paste",
|
"contextItemLabel": "labels.paste",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": undefined,
|
"keyTest": undefined,
|
||||||
"name": "paste",
|
"name": "paste",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -5579,28 +5579,28 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyAsPng",
|
"contextItemLabel": "labels.copyAsPng",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "copyAsPng",
|
"name": "copyAsPng",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyAsSvg",
|
"contextItemLabel": "labels.copyAsSvg",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "copyAsSvg",
|
"name": "copyAsSvg",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyText",
|
"contextItemLabel": "labels.copyText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "copyText",
|
"name": "copyText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -5619,10 +5619,10 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"checked": [Function],
|
"checked": [Function],
|
||||||
"contextItemLabel": "labels.showGrid",
|
"contextItemLabel": "labels.showGrid",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "gridMode",
|
"name": "gridMode",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "canvas",
|
"category": "canvas",
|
||||||
"predicate": [Function],
|
"predicate": [Function],
|
||||||
@ -5632,10 +5632,10 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"checked": [Function],
|
"checked": [Function],
|
||||||
"contextItemLabel": "buttons.zenMode",
|
"contextItemLabel": "buttons.zenMode",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "zenMode",
|
"name": "zenMode",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "canvas",
|
"category": "canvas",
|
||||||
"predicate": [Function],
|
"predicate": [Function],
|
||||||
@ -5645,10 +5645,10 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"checked": [Function],
|
"checked": [Function],
|
||||||
"contextItemLabel": "labels.viewMode",
|
"contextItemLabel": "labels.viewMode",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "viewMode",
|
"name": "viewMode",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "canvas",
|
"category": "canvas",
|
||||||
"predicate": [Function],
|
"predicate": [Function],
|
||||||
@ -5782,30 +5782,30 @@ Object {
|
|||||||
"items": Array [
|
"items": Array [
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.cut",
|
"contextItemLabel": "labels.cut",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "cut",
|
"name": "cut",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copy",
|
"contextItemLabel": "labels.copy",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": undefined,
|
"keyTest": undefined,
|
||||||
"name": "copy",
|
"name": "copy",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.paste",
|
"contextItemLabel": "labels.paste",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": undefined,
|
"keyTest": undefined,
|
||||||
"name": "paste",
|
"name": "paste",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -5813,28 +5813,28 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyAsPng",
|
"contextItemLabel": "labels.copyAsPng",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "copyAsPng",
|
"name": "copyAsPng",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyAsSvg",
|
"contextItemLabel": "labels.copyAsSvg",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "copyAsSvg",
|
"name": "copyAsSvg",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyText",
|
"contextItemLabel": "labels.copyText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "copyText",
|
"name": "copyText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -5862,28 +5862,28 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": "labels.group",
|
"contextItemLabel": "labels.group",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "group",
|
"name": "group",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.unbindText",
|
"contextItemLabel": "labels.unbindText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "unbindText",
|
"name": "unbindText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.bindText",
|
"contextItemLabel": "labels.bindText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "bindText",
|
"name": "bindText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -5891,10 +5891,10 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": "labels.ungroup",
|
"contextItemLabel": "labels.ungroup",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "ungroup",
|
"name": "ungroup",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -5954,20 +5954,20 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.flipHorizontal",
|
"contextItemLabel": "labels.flipHorizontal",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "flipHorizontal",
|
"name": "flipHorizontal",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.flipVertical",
|
"contextItemLabel": "labels.flipVertical",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "flipVertical",
|
"name": "flipVertical",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -5975,9 +5975,9 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": [Function],
|
"contextItemLabel": [Function],
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "toggleLinearEditor",
|
"name": "toggleLinearEditor",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -5985,10 +5985,10 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": [Function],
|
"contextItemLabel": [Function],
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "hyperlink",
|
"name": "hyperlink",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"action": "click",
|
"action": "click",
|
||||||
"category": "hyperlink",
|
"category": "hyperlink",
|
||||||
@ -6119,30 +6119,30 @@ Object {
|
|||||||
"items": Array [
|
"items": Array [
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.cut",
|
"contextItemLabel": "labels.cut",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "cut",
|
"name": "cut",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copy",
|
"contextItemLabel": "labels.copy",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": undefined,
|
"keyTest": undefined,
|
||||||
"name": "copy",
|
"name": "copy",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.paste",
|
"contextItemLabel": "labels.paste",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": undefined,
|
"keyTest": undefined,
|
||||||
"name": "paste",
|
"name": "paste",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -6150,28 +6150,28 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyAsPng",
|
"contextItemLabel": "labels.copyAsPng",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "copyAsPng",
|
"name": "copyAsPng",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyAsSvg",
|
"contextItemLabel": "labels.copyAsSvg",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "copyAsSvg",
|
"name": "copyAsSvg",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.copyText",
|
"contextItemLabel": "labels.copyText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "copyText",
|
"name": "copyText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -6199,28 +6199,28 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": "labels.group",
|
"contextItemLabel": "labels.group",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "group",
|
"name": "group",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.unbindText",
|
"contextItemLabel": "labels.unbindText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "unbindText",
|
"name": "unbindText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.bindText",
|
"contextItemLabel": "labels.bindText",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "bindText",
|
"name": "bindText",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -6228,10 +6228,10 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": "labels.ungroup",
|
"contextItemLabel": "labels.ungroup",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "ungroup",
|
"name": "ungroup",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -6291,20 +6291,20 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.flipHorizontal",
|
"contextItemLabel": "labels.flipHorizontal",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "flipHorizontal",
|
"name": "flipHorizontal",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": "labels.flipVertical",
|
"contextItemLabel": "labels.flipVertical",
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "flipVertical",
|
"name": "flipVertical",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -6312,9 +6312,9 @@ Object {
|
|||||||
"separator",
|
"separator",
|
||||||
Object {
|
Object {
|
||||||
"contextItemLabel": [Function],
|
"contextItemLabel": [Function],
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"name": "toggleLinearEditor",
|
"name": "toggleLinearEditor",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"category": "element",
|
"category": "element",
|
||||||
},
|
},
|
||||||
@ -6322,10 +6322,10 @@ Object {
|
|||||||
Object {
|
Object {
|
||||||
"PanelComponent": [Function],
|
"PanelComponent": [Function],
|
||||||
"contextItemLabel": [Function],
|
"contextItemLabel": [Function],
|
||||||
"contextItemPredicate": [Function],
|
|
||||||
"keyTest": [Function],
|
"keyTest": [Function],
|
||||||
"name": "hyperlink",
|
"name": "hyperlink",
|
||||||
"perform": [Function],
|
"perform": [Function],
|
||||||
|
"predicate": [Function],
|
||||||
"trackEvent": Object {
|
"trackEvent": Object {
|
||||||
"action": "click",
|
"action": "click",
|
||||||
"category": "hyperlink",
|
"category": "hyperlink",
|
||||||
|
@ -1,5 +1,114 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`<Excalidraw/> <MainMenu/> should render main menu with host menu items if passed from host 1`] = `
|
||||||
|
<div
|
||||||
|
class="dropdown-menu"
|
||||||
|
data-testid="dropdown-menu"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="Island dropdown-menu-container"
|
||||||
|
style="--padding: 2; z-index: 1;"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="dropdown-menu-item dropdown-menu-item-base"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="dropdown-menu-item__icon"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="dropdown-menu-item__text"
|
||||||
|
>
|
||||||
|
Click me
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<a
|
||||||
|
class="dropdown-menu-item dropdown-menu-item-base"
|
||||||
|
href="blog.excalidaw.com"
|
||||||
|
rel="noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="dropdown-menu-item__icon"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="dropdown-menu-item__text"
|
||||||
|
>
|
||||||
|
Excalidraw blog
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<div
|
||||||
|
class="dropdown-menu-item-base dropdown-menu-item-custom"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
style="height: 2rem;"
|
||||||
|
>
|
||||||
|
|
||||||
|
custom menu item
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
aria-label="Help"
|
||||||
|
class="dropdown-menu-item dropdown-menu-item-base"
|
||||||
|
data-testid="help-menu-item"
|
||||||
|
title="Help"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="dropdown-menu-item__icon"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class=""
|
||||||
|
fill="none"
|
||||||
|
focusable="false"
|
||||||
|
role="img"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
stroke-width="1.5"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M0 0h24v24H0z"
|
||||||
|
fill="none"
|
||||||
|
stroke="none"
|
||||||
|
/>
|
||||||
|
<circle
|
||||||
|
cx="12"
|
||||||
|
cy="12"
|
||||||
|
r="9"
|
||||||
|
/>
|
||||||
|
<line
|
||||||
|
x1="12"
|
||||||
|
x2="12"
|
||||||
|
y1="17"
|
||||||
|
y2="17.01"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M12 13.5a1.5 1.5 0 0 1 1 -1.5a2.6 2.6 0 1 0 -3 -4"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="dropdown-menu-item__text"
|
||||||
|
>
|
||||||
|
Help
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="dropdown-menu-item__shortcut"
|
||||||
|
>
|
||||||
|
?
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`<Excalidraw/> Test UIOptions prop Test canvasActions should render menu with default items when "UIOPtions" is "undefined" 1`] = `
|
exports[`<Excalidraw/> Test UIOptions prop Test canvasActions should render menu with default items when "UIOPtions" is "undefined" 1`] = `
|
||||||
<div
|
<div
|
||||||
class="dropdown-menu"
|
class="dropdown-menu"
|
||||||
@ -454,112 +563,3 @@ exports[`<Excalidraw/> Test UIOptions prop Test canvasActions should render menu
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<Excalidraw/> should render main menu with host menu items if passed from host 1`] = `
|
|
||||||
<div
|
|
||||||
class="dropdown-menu"
|
|
||||||
data-testid="dropdown-menu"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="Island dropdown-menu-container"
|
|
||||||
style="--padding: 2; z-index: 1;"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="dropdown-menu-item dropdown-menu-item-base"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="dropdown-menu-item__icon"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="dropdown-menu-item__text"
|
|
||||||
>
|
|
||||||
Click me
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<a
|
|
||||||
class="dropdown-menu-item dropdown-menu-item-base"
|
|
||||||
href="blog.excalidaw.com"
|
|
||||||
rel="noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="dropdown-menu-item__icon"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="dropdown-menu-item__text"
|
|
||||||
>
|
|
||||||
Excalidraw blog
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<div
|
|
||||||
class="dropdown-menu-item-base dropdown-menu-item-custom"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
style="height: 2rem;"
|
|
||||||
>
|
|
||||||
|
|
||||||
custom menu item
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
aria-label="Help"
|
|
||||||
class="dropdown-menu-item dropdown-menu-item-base"
|
|
||||||
data-testid="help-menu-item"
|
|
||||||
title="Help"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="dropdown-menu-item__icon"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
class=""
|
|
||||||
fill="none"
|
|
||||||
focusable="false"
|
|
||||||
role="img"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<g
|
|
||||||
stroke-width="1.5"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M0 0h24v24H0z"
|
|
||||||
fill="none"
|
|
||||||
stroke="none"
|
|
||||||
/>
|
|
||||||
<circle
|
|
||||||
cx="12"
|
|
||||||
cy="12"
|
|
||||||
r="9"
|
|
||||||
/>
|
|
||||||
<line
|
|
||||||
x1="12"
|
|
||||||
x2="12"
|
|
||||||
y1="17"
|
|
||||||
y2="17.01"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M12 13.5a1.5 1.5 0 0 1 1 -1.5a2.6 2.6 0 1 0 -3 -4"
|
|
||||||
/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="dropdown-menu-item__text"
|
|
||||||
>
|
|
||||||
Help
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="dropdown-menu-item__shortcut"
|
|
||||||
>
|
|
||||||
?
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
@ -3,6 +3,7 @@ import { Excalidraw, Footer, MainMenu } from "../../packages/excalidraw/index";
|
|||||||
import { queryByText, queryByTestId } from "@testing-library/react";
|
import { queryByText, queryByTestId } from "@testing-library/react";
|
||||||
import { GRID_SIZE, THEME } from "../../constants";
|
import { GRID_SIZE, THEME } from "../../constants";
|
||||||
import { t } from "../../i18n";
|
import { t } from "../../i18n";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
|
||||||
const { h } = window;
|
const { h } = window;
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ describe("<Excalidraw/>", () => {
|
|||||||
toggleMenu(document.querySelector(".excalidraw")!);
|
toggleMenu(document.querySelector(".excalidraw")!);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Test zenModeEnabled prop", () => {
|
describe("Test zenModeEnabled prop", () => {
|
||||||
it('should show exit zen mode button when zen mode is set and zen mode option in context menu when zenModeEnabled is "undefined"', async () => {
|
it('should show exit zen mode button when zen mode is set and zen mode option in context menu when zenModeEnabled is "undefined"', async () => {
|
||||||
const { container } = await render(<Excalidraw />);
|
const { container } = await render(<Excalidraw />);
|
||||||
@ -121,34 +123,6 @@ describe("<Excalidraw/>", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render main menu with host menu items if passed from host", async () => {
|
|
||||||
const { container } = await render(
|
|
||||||
<Excalidraw UIOptions={undefined}>
|
|
||||||
<MainMenu>
|
|
||||||
<MainMenu.Item onSelect={() => window.alert("Clicked")}>
|
|
||||||
Click me
|
|
||||||
</MainMenu.Item>
|
|
||||||
<MainMenu.ItemLink href="blog.excalidaw.com">
|
|
||||||
Excalidraw blog
|
|
||||||
</MainMenu.ItemLink>
|
|
||||||
<MainMenu.ItemCustom>
|
|
||||||
<button
|
|
||||||
style={{ height: "2rem" }}
|
|
||||||
onClick={() => window.alert("custom menu item")}
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
custom menu item
|
|
||||||
</button>
|
|
||||||
</MainMenu.ItemCustom>
|
|
||||||
<MainMenu.DefaultItems.Help />
|
|
||||||
</MainMenu>
|
|
||||||
</Excalidraw>,
|
|
||||||
);
|
|
||||||
//open menu
|
|
||||||
toggleMenu(container);
|
|
||||||
expect(queryByTestId(container, "dropdown-menu")).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Test UIOptions prop", () => {
|
describe("Test UIOptions prop", () => {
|
||||||
describe("Test canvasActions", () => {
|
describe("Test canvasActions", () => {
|
||||||
it('should render menu with default items when "UIOPtions" is "undefined"', async () => {
|
it('should render menu with default items when "UIOPtions" is "undefined"', async () => {
|
||||||
@ -306,7 +280,7 @@ describe("<Excalidraw/>", () => {
|
|||||||
//open menu
|
//open menu
|
||||||
toggleMenu(container);
|
toggleMenu(container);
|
||||||
const darkModeToggle = queryByTestId(container, "toggle-dark-mode");
|
const darkModeToggle = queryByTestId(container, "toggle-dark-mode");
|
||||||
expect(darkModeToggle).toBeFalsy();
|
expect(darkModeToggle).toBe(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -336,6 +310,7 @@ describe("<Excalidraw/>", () => {
|
|||||||
expect(textInput?.nodeName).toBe("SPAN");
|
expect(textInput?.nodeName).toBe("SPAN");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Test autoFocus prop", () => {
|
describe("Test autoFocus prop", () => {
|
||||||
it("should not focus when autoFocus is false", async () => {
|
it("should not focus when autoFocus is false", async () => {
|
||||||
const { container } = await render(<Excalidraw />);
|
const { container } = await render(<Excalidraw />);
|
||||||
@ -353,4 +328,64 @@ describe("<Excalidraw/>", () => {
|
|||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("<MainMenu/>", () => {
|
||||||
|
it("should render main menu with host menu items if passed from host", async () => {
|
||||||
|
const { container } = await render(
|
||||||
|
<Excalidraw>
|
||||||
|
<MainMenu>
|
||||||
|
<MainMenu.Item onSelect={() => window.alert("Clicked")}>
|
||||||
|
Click me
|
||||||
|
</MainMenu.Item>
|
||||||
|
<MainMenu.ItemLink href="blog.excalidaw.com">
|
||||||
|
Excalidraw blog
|
||||||
|
</MainMenu.ItemLink>
|
||||||
|
<MainMenu.ItemCustom>
|
||||||
|
<button
|
||||||
|
style={{ height: "2rem" }}
|
||||||
|
onClick={() => window.alert("custom menu item")}
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
custom menu item
|
||||||
|
</button>
|
||||||
|
</MainMenu.ItemCustom>
|
||||||
|
<MainMenu.DefaultItems.Help />
|
||||||
|
</MainMenu>
|
||||||
|
</Excalidraw>,
|
||||||
|
);
|
||||||
|
//open menu
|
||||||
|
toggleMenu(container);
|
||||||
|
expect(queryByTestId(container, "dropdown-menu")).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should update themeToggle text even if MainMenu memoized", async () => {
|
||||||
|
const CustomExcalidraw = () => {
|
||||||
|
const customMenu = useMemo(() => {
|
||||||
|
return (
|
||||||
|
<MainMenu>
|
||||||
|
<MainMenu.DefaultItems.ToggleTheme />
|
||||||
|
</MainMenu>
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return <Excalidraw>{customMenu}</Excalidraw>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { container } = await render(<CustomExcalidraw />);
|
||||||
|
//open menu
|
||||||
|
toggleMenu(container);
|
||||||
|
|
||||||
|
expect(h.state.theme).toBe(THEME.LIGHT);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
queryByTestId(container, "toggle-dark-mode")?.textContent,
|
||||||
|
).toContain(t("buttons.darkMode"));
|
||||||
|
|
||||||
|
fireEvent.click(queryByTestId(container, "toggle-dark-mode")!);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
queryByTestId(container, "toggle-dark-mode")?.textContent,
|
||||||
|
).toContain(t("buttons.lightMode"));
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user