feat: support props.locked for setActiveTool (#7153)

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
This commit is contained in:
David Luzar 2023-10-20 13:16:23 +02:00 committed by GitHub
parent e7cc2337ea
commit 3697618266
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 5 deletions

View File

@ -3249,7 +3249,7 @@ class App extends React.Component<AppProps, AppState> {
}); });
setActiveTool = ( setActiveTool = (
tool: tool: (
| ( | (
| { type: Exclude<ToolType, "image"> } | { type: Exclude<ToolType, "image"> }
| { | {
@ -3257,7 +3257,8 @@ class App extends React.Component<AppProps, AppState> {
insertOnCanvasDirectly?: boolean; insertOnCanvasDirectly?: boolean;
} }
) )
| { type: "custom"; customType: string }, | { type: "custom"; customType: string }
) & { locked?: boolean },
) => { ) => {
const nextActiveTool = updateActiveTool(this.state, tool); const nextActiveTool = updateActiveTool(this.state, tool);
if (nextActiveTool.type === "hand") { if (nextActiveTool.type === "hand") {
@ -4714,7 +4715,7 @@ class App extends React.Component<AppProps, AppState> {
pointerDownState, pointerDownState,
); );
} else if (this.state.activeTool.type === "custom") { } else if (this.state.activeTool.type === "custom") {
setCursor(this.interactiveCanvas, CURSOR_TYPE.AUTO); setCursorForShape(this.interactiveCanvas, this.state);
} else if (this.state.activeTool.type === "frame") { } else if (this.state.activeTool.type === "frame") {
this.createFrameElementOnPointerDown(pointerDownState); this.createFrameElementOnPointerDown(pointerDownState);
} else if (this.state.activeTool.type === "laser") { } else if (this.state.activeTool.type === "laser") {

View File

@ -99,5 +99,7 @@ export const setCursorForShape = (
interactiveCanvas.style.cursor = `url(${url}), auto`; interactiveCanvas.style.cursor = `url(${url}), auto`;
} else if (!["image", "custom"].includes(appState.activeTool.type)) { } else if (!["image", "custom"].includes(appState.activeTool.type)) {
interactiveCanvas.style.cursor = CURSOR_TYPE.CROSSHAIR; interactiveCanvas.style.cursor = CURSOR_TYPE.CROSSHAIR;
} else {
interactiveCanvas.style.cursor = CURSOR_TYPE.AUTO;
} }
}; };

55
src/tests/tool.test.tsx Normal file
View File

@ -0,0 +1,55 @@
import { Excalidraw } from "../packages/excalidraw/index";
import { ExcalidrawImperativeAPI } from "../types";
import { resolvablePromise } from "../utils";
import { render } from "./test-utils";
import { Pointer } from "./helpers/ui";
describe("setActiveTool()", () => {
const h = window.h;
let excalidrawAPI: ExcalidrawImperativeAPI;
const mouse = new Pointer("mouse");
beforeEach(async () => {
const excalidrawAPIPromise = resolvablePromise<ExcalidrawImperativeAPI>();
await render(
<Excalidraw ref={(api) => excalidrawAPIPromise.resolve(api as any)} />,
);
excalidrawAPI = await excalidrawAPIPromise;
});
it("should expose setActiveTool on package API", () => {
expect(excalidrawAPI.setActiveTool).toBeDefined();
expect(excalidrawAPI.setActiveTool).toBe(h.app.setActiveTool);
});
it("should set the active tool type", async () => {
expect(h.state.activeTool.type).toBe("selection");
excalidrawAPI.setActiveTool({ type: "rectangle" });
expect(h.state.activeTool.type).toBe("rectangle");
mouse.down(10, 10);
mouse.up(20, 20);
expect(h.state.activeTool.type).toBe("selection");
});
it("should support tool locking", async () => {
expect(h.state.activeTool.type).toBe("selection");
excalidrawAPI.setActiveTool({ type: "rectangle", locked: true });
expect(h.state.activeTool.type).toBe("rectangle");
mouse.down(10, 10);
mouse.up(20, 20);
expect(h.state.activeTool.type).toBe("rectangle");
});
it("should set custom tool", async () => {
expect(h.state.activeTool.type).toBe("selection");
excalidrawAPI.setActiveTool({ type: "custom", customType: "comment" });
expect(h.state.activeTool.type).toBe("custom");
expect(h.state.activeTool.customType).toBe("comment");
});
});

View File

@ -363,18 +363,21 @@ export const distance = (x: number, y: number) => Math.abs(x - y);
export const updateActiveTool = ( export const updateActiveTool = (
appState: Pick<AppState, "activeTool">, appState: Pick<AppState, "activeTool">,
data: ( data: ((
| { | {
type: ToolType; type: ToolType;
} }
| { type: "custom"; customType: string } | { type: "custom"; customType: string }
) & { lastActiveToolBeforeEraser?: ActiveTool | null }, ) & { locked?: boolean }) & {
lastActiveToolBeforeEraser?: ActiveTool | null;
},
): AppState["activeTool"] => { ): AppState["activeTool"] => {
if (data.type === "custom") { if (data.type === "custom") {
return { return {
...appState.activeTool, ...appState.activeTool,
type: "custom", type: "custom",
customType: data.customType, customType: data.customType,
locked: data.locked ?? appState.activeTool.locked,
}; };
} }
@ -386,6 +389,7 @@ export const updateActiveTool = (
: data.lastActiveToolBeforeEraser, : data.lastActiveToolBeforeEraser,
type: data.type, type: data.type,
customType: null, customType: null,
locked: data.locked ?? appState.activeTool.locked,
}; };
}; };