feat: Enter and Exit line editor via context menu (#5719)
* feat: Enter and exit line editor via context menu * Add tests * fix * review fixes * fix
This commit is contained in:
parent
b477c2ad6b
commit
6c1246ef77
49
src/actions/actionLinearEditor.ts
Normal file
49
src/actions/actionLinearEditor.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { getNonDeletedElements } from "../element";
|
||||
import { LinearElementEditor } from "../element/linearElementEditor";
|
||||
import { isLinearElement } from "../element/typeChecks";
|
||||
import { ExcalidrawLinearElement } from "../element/types";
|
||||
import { getSelectedElements } from "../scene";
|
||||
import { register } from "./register";
|
||||
|
||||
export const actionToggleLinearEditor = register({
|
||||
name: "toggleLinearEditor",
|
||||
trackEvent: {
|
||||
category: "element",
|
||||
},
|
||||
contextItemPredicate: (elements, appState) => {
|
||||
const selectedElements = getSelectedElements(elements, appState);
|
||||
if (selectedElements.length === 1 && isLinearElement(selectedElements[0])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
perform(elements, appState, _, app) {
|
||||
const selectedElement = getSelectedElements(
|
||||
getNonDeletedElements(elements),
|
||||
appState,
|
||||
true,
|
||||
)[0] as ExcalidrawLinearElement;
|
||||
|
||||
const editingLinearElement =
|
||||
appState.editingLinearElement?.elementId === selectedElement.id
|
||||
? null
|
||||
: new LinearElementEditor(selectedElement, app.scene);
|
||||
return {
|
||||
appState: {
|
||||
...appState,
|
||||
editingLinearElement,
|
||||
},
|
||||
commitToHistory: false,
|
||||
};
|
||||
},
|
||||
contextItemLabel: (elements, appState) => {
|
||||
const selectedElement = getSelectedElements(
|
||||
getNonDeletedElements(elements),
|
||||
appState,
|
||||
true,
|
||||
)[0] as ExcalidrawLinearElement;
|
||||
return appState.editingLinearElement?.elementId === selectedElement.id
|
||||
? "labels.lineEditor.exit"
|
||||
: "labels.lineEditor.edit";
|
||||
},
|
||||
});
|
@ -85,3 +85,4 @@ export { actionToggleStats } from "./actionToggleStats";
|
||||
export { actionUnbindText, actionBindText } from "./actionBoundText";
|
||||
export { actionLink } from "../element/Hyperlink";
|
||||
export { actionToggleLock } from "./actionToggleLock";
|
||||
export { actionToggleLinearEditor } from "./actionLinearEditor";
|
||||
|
@ -111,7 +111,8 @@ export type ActionName =
|
||||
| "hyperlink"
|
||||
| "eraser"
|
||||
| "bindText"
|
||||
| "toggleLock";
|
||||
| "toggleLock"
|
||||
| "toggleLinearEditor";
|
||||
|
||||
export type PanelComponentProps = {
|
||||
elements: readonly ExcalidrawElement[];
|
||||
|
@ -34,6 +34,7 @@ import {
|
||||
actionUngroup,
|
||||
actionLink,
|
||||
actionToggleLock,
|
||||
actionToggleLinearEditor,
|
||||
} from "../actions";
|
||||
import { createRedoAction, createUndoAction } from "../actions/actionHistory";
|
||||
import { ActionManager } from "../actions/manager";
|
||||
@ -5876,6 +5877,12 @@ class App extends React.Component<AppProps, AppState> {
|
||||
this.actionManager.getAppState(),
|
||||
);
|
||||
|
||||
const mayBeAllowToggleLineEditing =
|
||||
actionToggleLinearEditor.contextItemPredicate(
|
||||
this.actionManager.getElementsIncludingDeleted(),
|
||||
this.actionManager.getAppState(),
|
||||
);
|
||||
|
||||
const separator = "separator";
|
||||
|
||||
const elements = this.scene.getNonDeletedElements();
|
||||
@ -6017,6 +6024,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
maybeFlipHorizontal && actionFlipHorizontal,
|
||||
maybeFlipVertical && actionFlipVertical,
|
||||
(maybeFlipHorizontal || maybeFlipVertical) && separator,
|
||||
mayBeAllowToggleLineEditing && actionToggleLinearEditor,
|
||||
actionLink.contextItemPredicate(elements, this.state) && actionLink,
|
||||
actionDuplicateSelection,
|
||||
actionToggleLock,
|
||||
|
@ -114,6 +114,11 @@
|
||||
"create": "Create link",
|
||||
"label": "Link"
|
||||
},
|
||||
"lineEditor": {
|
||||
"edit": "Edit line",
|
||||
"exit": "Exit line editor"
|
||||
},
|
||||
|
||||
"elementLock": {
|
||||
"lock": "Lock",
|
||||
"unlock": "Unlock",
|
||||
|
@ -5,11 +5,12 @@ import { centerPoint } from "../math";
|
||||
import { reseed } from "../random";
|
||||
import * as Renderer from "../renderer/renderScene";
|
||||
import { Keyboard, Pointer } from "./helpers/ui";
|
||||
import { screen, render, fireEvent } from "./test-utils";
|
||||
import { screen, render, fireEvent, GlobalTestState } from "./test-utils";
|
||||
import { API } from "../tests/helpers/api";
|
||||
import { Point } from "../types";
|
||||
import { KEYS } from "../keys";
|
||||
import { LinearElementEditor } from "../element/linearElementEditor";
|
||||
import { queryByText } from "@testing-library/react";
|
||||
|
||||
const renderScene = jest.spyOn(Renderer, "renderScene");
|
||||
|
||||
@ -150,6 +151,42 @@ describe(" Test Linear Elements", () => {
|
||||
`);
|
||||
});
|
||||
|
||||
it("should allow entering and exiting line editor via context menu", () => {
|
||||
createTwoPointerLinearElement("line");
|
||||
fireEvent.contextMenu(GlobalTestState.canvas, {
|
||||
button: 2,
|
||||
clientX: midpoint[0],
|
||||
clientY: midpoint[1],
|
||||
});
|
||||
// Enter line editor
|
||||
let contextMenu = document.querySelector(".context-menu");
|
||||
fireEvent.contextMenu(GlobalTestState.canvas, {
|
||||
button: 2,
|
||||
clientX: midpoint[0],
|
||||
clientY: midpoint[1],
|
||||
});
|
||||
fireEvent.click(queryByText(contextMenu as HTMLElement, "Edit line")!);
|
||||
|
||||
expect(h.state.editingLinearElement?.elementId).toEqual(h.elements[0].id);
|
||||
|
||||
// Exiting line editor
|
||||
fireEvent.contextMenu(GlobalTestState.canvas, {
|
||||
button: 2,
|
||||
clientX: midpoint[0],
|
||||
clientY: midpoint[1],
|
||||
});
|
||||
contextMenu = document.querySelector(".context-menu");
|
||||
fireEvent.contextMenu(GlobalTestState.canvas, {
|
||||
button: 2,
|
||||
clientX: midpoint[0],
|
||||
clientY: midpoint[1],
|
||||
});
|
||||
fireEvent.click(
|
||||
queryByText(contextMenu as HTMLElement, "Exit line editor")!,
|
||||
);
|
||||
expect(h.state.editingLinearElement?.elementId).toBeUndefined();
|
||||
});
|
||||
|
||||
describe("Inside editor", () => {
|
||||
it("should allow dragging line from midpoint in 2 pointer lines", async () => {
|
||||
createTwoPointerLinearElement("line");
|
||||
|
Loading…
x
Reference in New Issue
Block a user