Compare commits
4 Commits
38aa0df4e2
...
7f68bbd192
Author | SHA1 | Date |
---|---|---|
dependabot[bot] | 7f68bbd192 | |
Marcel Mraz | 6e5aeb112d | |
Marcel Mraz | 4d83d1c91e | |
dependabot[bot] | c6fa1aff46 |
|
@ -2720,21 +2720,21 @@ binary-extensions@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||
|
||||
body-parser@1.20.0:
|
||||
version "1.20.0"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5"
|
||||
integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==
|
||||
body-parser@1.20.2:
|
||||
version "1.20.2"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
|
||||
integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
content-type "~1.0.4"
|
||||
content-type "~1.0.5"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
on-finished "2.4.1"
|
||||
qs "6.10.3"
|
||||
raw-body "2.5.1"
|
||||
qs "6.11.0"
|
||||
raw-body "2.5.2"
|
||||
type-is "~1.6.18"
|
||||
unpipe "1.0.0"
|
||||
|
||||
|
@ -3179,6 +3179,11 @@ content-type@~1.0.4:
|
|||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
|
||||
|
||||
content-type@~1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
|
||||
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
|
||||
|
||||
convert-source-map@^1.7.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
|
||||
|
@ -3191,10 +3196,10 @@ cookie-signature@1.0.6:
|
|||
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
||||
integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
|
||||
|
||||
cookie@0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
|
||||
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
|
||||
cookie@0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
|
||||
integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
|
||||
|
||||
copy-text-to-clipboard@^3.0.1:
|
||||
version "3.0.1"
|
||||
|
@ -3869,16 +3874,16 @@ execa@^5.0.0:
|
|||
strip-final-newline "^2.0.0"
|
||||
|
||||
express@^4.17.3:
|
||||
version "4.18.1"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf"
|
||||
integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==
|
||||
version "4.19.2"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465"
|
||||
integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==
|
||||
dependencies:
|
||||
accepts "~1.3.8"
|
||||
array-flatten "1.1.1"
|
||||
body-parser "1.20.0"
|
||||
body-parser "1.20.2"
|
||||
content-disposition "0.5.4"
|
||||
content-type "~1.0.4"
|
||||
cookie "0.5.0"
|
||||
cookie "0.6.0"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
|
@ -3894,7 +3899,7 @@ express@^4.17.3:
|
|||
parseurl "~1.3.3"
|
||||
path-to-regexp "0.1.7"
|
||||
proxy-addr "~2.0.7"
|
||||
qs "6.10.3"
|
||||
qs "6.11.0"
|
||||
range-parser "~1.2.1"
|
||||
safe-buffer "5.2.1"
|
||||
send "0.18.0"
|
||||
|
@ -6094,10 +6099,10 @@ pure-color@^1.2.0:
|
|||
resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e"
|
||||
integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA==
|
||||
|
||||
qs@6.10.3:
|
||||
version "6.10.3"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e"
|
||||
integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==
|
||||
qs@6.11.0:
|
||||
version "6.11.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
|
||||
integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
|
||||
dependencies:
|
||||
side-channel "^1.0.4"
|
||||
|
||||
|
@ -6130,10 +6135,10 @@ range-parser@^1.2.1, range-parser@~1.2.1:
|
|||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
|
||||
|
||||
raw-body@2.5.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
|
||||
integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
|
||||
raw-body@2.5.2:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a"
|
||||
integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
http-errors "2.0.0"
|
||||
|
|
|
@ -4166,6 +4166,11 @@ class App extends React.Component<AppProps, AppState> {
|
|||
originSnapOffset: null,
|
||||
activeEmbeddable: null,
|
||||
} as const;
|
||||
|
||||
if (nextActiveTool.type === "freedraw") {
|
||||
this.store.shouldCaptureIncrement();
|
||||
}
|
||||
|
||||
if (nextActiveTool.type !== "selection") {
|
||||
return {
|
||||
...prevState,
|
||||
|
|
|
@ -22,7 +22,7 @@ export const getObservedAppState = (appState: AppState): ObservedAppState => {
|
|||
selectedLinearElementId: appState.selectedLinearElement?.elementId || null,
|
||||
};
|
||||
|
||||
Object.defineProperty(observedAppState, hiddenObservedAppStateProp, {
|
||||
Reflect.defineProperty(observedAppState, hiddenObservedAppStateProp, {
|
||||
value: true,
|
||||
enumerable: false,
|
||||
});
|
||||
|
@ -33,7 +33,7 @@ export const getObservedAppState = (appState: AppState): ObservedAppState => {
|
|||
const isObservedAppState = (
|
||||
appState: AppState | ObservedAppState,
|
||||
): appState is ObservedAppState =>
|
||||
Object.hasOwn(appState, hiddenObservedAppStateProp);
|
||||
!!Reflect.get(appState, hiddenObservedAppStateProp);
|
||||
|
||||
export type StoreActionType = "capture" | "update" | "none";
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6570,12 +6570,27 @@ History {
|
|||
"delta": Delta {
|
||||
"deleted": {
|
||||
"selectedElementIds": {},
|
||||
"selectedLinearElementId": null,
|
||||
},
|
||||
"inserted": {
|
||||
"selectedElementIds": {
|
||||
"id6": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"elementsChange": ElementsChange {
|
||||
"added": Map {},
|
||||
"removed": Map {},
|
||||
"updated": Map {},
|
||||
},
|
||||
},
|
||||
HistoryEntry {
|
||||
"appStateChange": AppStateChange {
|
||||
"delta": Delta {
|
||||
"deleted": {
|
||||
"selectedLinearElementId": null,
|
||||
},
|
||||
"inserted": {
|
||||
"selectedLinearElementId": "id6",
|
||||
},
|
||||
},
|
||||
|
|
|
@ -15,7 +15,11 @@ import { createUndoAction, createRedoAction } from "../actions/actionHistory";
|
|||
import { EXPORT_DATA_TYPES, MIME_TYPES } from "../constants";
|
||||
import { AppState, ExcalidrawImperativeAPI } from "../types";
|
||||
import { arrayToMap, resolvablePromise } from "../utils";
|
||||
import { COLOR_PALETTE } from "../colors";
|
||||
import {
|
||||
COLOR_PALETTE,
|
||||
DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX,
|
||||
DEFAULT_ELEMENT_STROKE_COLOR_INDEX,
|
||||
} from "../colors";
|
||||
import { KEYS } from "../keys";
|
||||
import { newElementWith } from "../element/mutateElement";
|
||||
import {
|
||||
|
@ -67,10 +71,11 @@ const checkpoint = (name: string) => {
|
|||
const renderStaticScene = vi.spyOn(StaticScene, "renderStaticScene");
|
||||
|
||||
const transparent = COLOR_PALETTE.transparent;
|
||||
const red = COLOR_PALETTE.red[1];
|
||||
const blue = COLOR_PALETTE.blue[1];
|
||||
const yellow = COLOR_PALETTE.yellow[1];
|
||||
const violet = COLOR_PALETTE.violet[1];
|
||||
const black = COLOR_PALETTE.black;
|
||||
const red = COLOR_PALETTE.red[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX];
|
||||
const blue = COLOR_PALETTE.blue[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX];
|
||||
const yellow = COLOR_PALETTE.yellow[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX];
|
||||
const violet = COLOR_PALETTE.violet[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX];
|
||||
|
||||
describe("history", () => {
|
||||
beforeEach(() => {
|
||||
|
@ -973,6 +978,69 @@ describe("history", () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it("should create entry when selecting freedraw", async () => {
|
||||
await render(<Excalidraw handleKeyboardGlobally={true} />);
|
||||
|
||||
UI.clickTool("rectangle");
|
||||
mouse.down(-10, -10);
|
||||
mouse.up(10, 10);
|
||||
|
||||
UI.clickTool("freedraw");
|
||||
mouse.down(40, -20);
|
||||
mouse.up(50, 10);
|
||||
|
||||
const rectangle = h.elements[0];
|
||||
const freedraw1 = h.elements[1];
|
||||
|
||||
expect(API.getUndoStack().length).toBe(3);
|
||||
expect(API.getRedoStack().length).toBe(0);
|
||||
expect(API.getSelectedElements().length).toBe(0);
|
||||
expect(h.elements).toEqual([
|
||||
expect.objectContaining({ id: rectangle.id }),
|
||||
expect.objectContaining({ id: freedraw1.id, strokeColor: black }),
|
||||
]);
|
||||
|
||||
Keyboard.undo();
|
||||
expect(API.getUndoStack().length).toBe(2);
|
||||
expect(API.getRedoStack().length).toBe(1);
|
||||
expect(API.getSelectedElements().length).toBe(0);
|
||||
expect(h.elements).toEqual([
|
||||
expect.objectContaining({ id: rectangle.id }),
|
||||
expect.objectContaining({
|
||||
id: freedraw1.id,
|
||||
strokeColor: black,
|
||||
isDeleted: true,
|
||||
}),
|
||||
]);
|
||||
|
||||
togglePopover("Stroke");
|
||||
UI.clickOnTestId("color-red");
|
||||
mouse.down(40, -20);
|
||||
mouse.up(50, 10);
|
||||
|
||||
const freedraw2 = h.elements[2];
|
||||
|
||||
expect(API.getUndoStack().length).toBe(3);
|
||||
expect(API.getRedoStack().length).toBe(0);
|
||||
expect(h.elements).toEqual([
|
||||
expect.objectContaining({ id: rectangle.id }),
|
||||
expect.objectContaining({
|
||||
id: freedraw1.id,
|
||||
strokeColor: black,
|
||||
isDeleted: true,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: freedraw2.id,
|
||||
strokeColor: COLOR_PALETTE.red[DEFAULT_ELEMENT_STROKE_COLOR_INDEX],
|
||||
}),
|
||||
]);
|
||||
|
||||
// ensure we don't end up with duplicated entries
|
||||
UI.clickTool("freedraw");
|
||||
expect(API.getUndoStack().length).toBe(3);
|
||||
expect(API.getRedoStack().length).toBe(0);
|
||||
});
|
||||
|
||||
it("should support duplication of groups, appstate group selection and editing group", async () => {
|
||||
await render(<Excalidraw handleKeyboardGlobally={true} />);
|
||||
const rect1 = API.createElement({
|
||||
|
|
Loading…
Reference in New Issue