Compare commits

...

6 Commits

Author SHA1 Message Date
Ashley A Abel aeab55d7ee
Merge 9d98084b8e into 6e5aeb112d 2024-04-28 12:23:14 +02:00
Marcel Mraz 6e5aeb112d
feat: record freedraw tool selection to history (#7949) 2024-04-25 17:24:05 +00:00
Marcel Mraz 4d83d1c91e
fix: use Reflect API instead of Object.hasOwn (#7958) 2024-04-25 15:36:26 +02:00
Ashley A Abel 9d98084b8e
Update contributing.mdx
Fixed wording contributing docs
2023-08-15 10:52:13 -05:00
Ashley A Abel 73172053d8
Update contributing.mdx 2023-07-25 20:11:53 -05:00
Ashley A Abel 5d62fb43c9
Update integration.mdx 2023-07-25 19:46:05 -05:00
7 changed files with 1037 additions and 548 deletions

View File

@ -1,5 +1,11 @@
# Integration # Integration
See [here](https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor) for VSCode intergration
See [here](https://www.npmjs.com/package/@excalidraw/excalidraw) for npm package
[Use Directly in Browser](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/integration#browser)
## Module bundler ## Module bundler
If you are using a module bundler (for instance, Webpack), you can import it as an ES6 module as shown below If you are using a module bundler (for instance, Webpack), you can import it as an ES6 module as shown below
@ -157,6 +163,8 @@ Since Vite removes env variables by default, you can update the vite config to e
## Browser ## Browser
Excalidraw can be rendered directly in your browser.
To use it in a browser directly: To use it in a browser directly:
For development use :point_down: For development use :point_down:

View File

@ -26,11 +26,11 @@ In case you want to pick up something from the roadmap, comment on that issue an
### Option 2 - CodeSandbox ### Option 2 - CodeSandbox
1. Go to https://codesandbox.io/p/github/excalidraw/excalidraw 1. Go to https://codesandbox.io/p/github/excalidraw/excalidraw
1. Connect your GitHub account 1. Connect your GitHub account (Sign in on the top left corner)
1. Go to Git tab on left side 1. Tap on `Create Branch` in the top right corner
1. Tap on `Fork Sandbox` 1. Click on the page icon on the left-hand side to access files
1. Write your code 1. Write code
1. Commit and PR automatically 1. Commit and PR automatically by clicking on the Pull request symbol on the left-hand side
## Pull Request Guidelines ## Pull Request Guidelines

View File

@ -4166,6 +4166,11 @@ class App extends React.Component<AppProps, AppState> {
originSnapOffset: null, originSnapOffset: null,
activeEmbeddable: null, activeEmbeddable: null,
} as const; } as const;
if (nextActiveTool.type === "freedraw") {
this.store.shouldCaptureIncrement();
}
if (nextActiveTool.type !== "selection") { if (nextActiveTool.type !== "selection") {
return { return {
...prevState, ...prevState,

View File

@ -22,7 +22,7 @@ export const getObservedAppState = (appState: AppState): ObservedAppState => {
selectedLinearElementId: appState.selectedLinearElement?.elementId || null, selectedLinearElementId: appState.selectedLinearElement?.elementId || null,
}; };
Object.defineProperty(observedAppState, hiddenObservedAppStateProp, { Reflect.defineProperty(observedAppState, hiddenObservedAppStateProp, {
value: true, value: true,
enumerable: false, enumerable: false,
}); });
@ -33,7 +33,7 @@ export const getObservedAppState = (appState: AppState): ObservedAppState => {
const isObservedAppState = ( const isObservedAppState = (
appState: AppState | ObservedAppState, appState: AppState | ObservedAppState,
): appState is ObservedAppState => ): appState is ObservedAppState =>
Object.hasOwn(appState, hiddenObservedAppStateProp); !!Reflect.get(appState, hiddenObservedAppStateProp);
export type StoreActionType = "capture" | "update" | "none"; export type StoreActionType = "capture" | "update" | "none";

File diff suppressed because it is too large Load Diff

View File

@ -6570,12 +6570,27 @@ History {
"delta": Delta { "delta": Delta {
"deleted": { "deleted": {
"selectedElementIds": {}, "selectedElementIds": {},
"selectedLinearElementId": null,
}, },
"inserted": { "inserted": {
"selectedElementIds": { "selectedElementIds": {
"id6": true, "id6": true,
}, },
},
},
},
"elementsChange": ElementsChange {
"added": Map {},
"removed": Map {},
"updated": Map {},
},
},
HistoryEntry {
"appStateChange": AppStateChange {
"delta": Delta {
"deleted": {
"selectedLinearElementId": null,
},
"inserted": {
"selectedLinearElementId": "id6", "selectedLinearElementId": "id6",
}, },
}, },

View File

@ -15,7 +15,11 @@ import { createUndoAction, createRedoAction } from "../actions/actionHistory";
import { EXPORT_DATA_TYPES, MIME_TYPES } from "../constants"; import { EXPORT_DATA_TYPES, MIME_TYPES } from "../constants";
import { AppState, ExcalidrawImperativeAPI } from "../types"; import { AppState, ExcalidrawImperativeAPI } from "../types";
import { arrayToMap, resolvablePromise } from "../utils"; 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 { KEYS } from "../keys";
import { newElementWith } from "../element/mutateElement"; import { newElementWith } from "../element/mutateElement";
import { import {
@ -67,10 +71,11 @@ const checkpoint = (name: string) => {
const renderStaticScene = vi.spyOn(StaticScene, "renderStaticScene"); const renderStaticScene = vi.spyOn(StaticScene, "renderStaticScene");
const transparent = COLOR_PALETTE.transparent; const transparent = COLOR_PALETTE.transparent;
const red = COLOR_PALETTE.red[1]; const black = COLOR_PALETTE.black;
const blue = COLOR_PALETTE.blue[1]; const red = COLOR_PALETTE.red[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX];
const yellow = COLOR_PALETTE.yellow[1]; const blue = COLOR_PALETTE.blue[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX];
const violet = COLOR_PALETTE.violet[1]; const yellow = COLOR_PALETTE.yellow[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX];
const violet = COLOR_PALETTE.violet[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX];
describe("history", () => { describe("history", () => {
beforeEach(() => { 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 () => { it("should support duplication of groups, appstate group selection and editing group", async () => {
await render(<Excalidraw handleKeyboardGlobally={true} />); await render(<Excalidraw handleKeyboardGlobally={true} />);
const rect1 = API.createElement({ const rect1 = API.createElement({