浏览代码

feat: Calculate `width/height` of canvas based on container dimensions (".excalidraw" selector) & remove props width & height (#3379)

* Remove width/height from the ".excalidraw" container so it will sized automatically.
* updated all ref calculation to ".excalidraw" instead of parent since now ".excalidraw" will get resized
* Remove props width/height as its not needed anymore.
* Resize handler is also not needed anymore.
* Position absolute canvas due to #3379 (comment)

* move css to style and remove one extra rerendering

* factor out mock logic for test

* set height, width so as to avoid unnecessary updates of regression snap

* better mock

* better type checking and omit width,height from getDefaultAppState and also restore

* revert

* default to window dimensions in constructor

* update docs

* update

* update

* tweaks
vanilla_orig
Aakansha Doshi 4 年前
父节点
当前提交
c54a099010
没有帐户链接到提交者的电子邮件

+ 3
- 0
public/index.html 查看文件

@@ -147,6 +147,9 @@
147 147
         color: var(--popup-text-color);
148 148
         font-size: 1.3em;
149 149
       }
150
+      #root {
151
+        height: 100%;
152
+      }
150 153
     </style>
151 154
   </head>
152 155
 

+ 4
- 1
src/actions/types.ts 查看文件

@@ -6,7 +6,10 @@ import { AppState, ExcalidrawProps } from "../types";
6 6
 export type ActionResult =
7 7
   | {
8 8
       elements?: readonly ExcalidrawElement[] | null;
9
-      appState?: MarkOptional<AppState, "offsetTop" | "offsetLeft"> | null;
9
+      appState?: MarkOptional<
10
+        AppState,
11
+        "offsetTop" | "offsetLeft" | "width" | "height"
12
+      > | null;
10 13
       commitToHistory: boolean;
11 14
       syncHistory?: boolean;
12 15
     }

+ 1
- 3
src/appState.ts 查看文件

@@ -10,7 +10,7 @@ import { getDateTime } from "./utils";
10 10
 
11 11
 export const getDefaultAppState = (): Omit<
12 12
   AppState,
13
-  "offsetTop" | "offsetLeft"
13
+  "offsetTop" | "offsetLeft" | "width" | "height"
14 14
 > => {
15 15
   return {
16 16
     theme: "light",
@@ -43,7 +43,6 @@ export const getDefaultAppState = (): Omit<
43 43
     exportWithDarkMode: false,
44 44
     fileHandle: null,
45 45
     gridSize: null,
46
-    height: window.innerHeight,
47 46
     isBindingEnabled: true,
48 47
     isLibraryOpen: false,
49 48
     isLoading: false,
@@ -70,7 +69,6 @@ export const getDefaultAppState = (): Omit<
70 69
     suggestedBindings: [],
71 70
     toastMessage: null,
72 71
     viewBackgroundColor: oc.white,
73
-    width: window.innerWidth,
74 72
     zenModeEnabled: false,
75 73
     zoom: { value: 1 as NormalizedZoomValue, translation: { x: 0, y: 0 } },
76 74
     viewModeEnabled: false,

+ 53
- 45
src/components/App.tsx 查看文件

@@ -293,19 +293,12 @@ class App extends React.Component<ExcalidrawProps, AppState> {
293 293
   actionManager: ActionManager;
294 294
   private excalidrawContainerRef = React.createRef<HTMLDivElement>();
295 295
 
296
-  public static defaultProps: Partial<ExcalidrawProps> = {
297
-    width: window.innerWidth,
298
-    height: window.innerHeight,
299
-  };
300 296
   private scene: Scene;
301 297
   private resizeObserver: ResizeObserver | undefined;
302 298
   constructor(props: ExcalidrawProps) {
303 299
     super(props);
304 300
     const defaultAppState = getDefaultAppState();
305
-
306 301
     const {
307
-      width = window.innerWidth,
308
-      height = window.innerHeight,
309 302
       excalidrawRef,
310 303
       viewModeEnabled = false,
311 304
       zenModeEnabled = false,
@@ -317,13 +310,13 @@ class App extends React.Component<ExcalidrawProps, AppState> {
317 310
       ...defaultAppState,
318 311
       theme,
319 312
       isLoading: true,
320
-      width,
321
-      height,
322 313
       ...this.getCanvasOffsets(),
323 314
       viewModeEnabled,
324 315
       zenModeEnabled,
325 316
       gridSize: gridModeEnabled ? GRID_SIZE : null,
326 317
       name,
318
+      width: window.innerWidth,
319
+      height: window.innerHeight,
327 320
     };
328 321
     if (excalidrawRef) {
329 322
       const readyPromise =
@@ -447,10 +440,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
447 440
           "excalidraw--view-mode": viewModeEnabled,
448 441
         })}
449 442
         ref={this.excalidrawContainerRef}
450
-        style={{
451
-          width: canvasDOMWidth,
452
-          height: canvasDOMHeight,
453
-        }}
454 443
       >
455 444
         <LayerUI
456 445
           canvas={this.canvas}
@@ -561,7 +550,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
561 550
         if (typeof this.props.name !== "undefined") {
562 551
           name = this.props.name;
563 552
         }
564
-
565 553
         this.setState(
566 554
           (state) => {
567 555
             // using Object.assign instead of spread to fool TS 4.2.2+ into
@@ -570,10 +558,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
570 558
             return Object.assign(actionResult.appState || {}, {
571 559
               editingElement:
572 560
                 editingElement || actionResult.appState?.editingElement || null,
573
-              width: state.width,
574
-              height: state.height,
575
-              offsetTop: state.offsetTop,
576
-              offsetLeft: state.offsetLeft,
577 561
               viewModeEnabled,
578 562
               zenModeEnabled,
579 563
               gridSize,
@@ -706,7 +690,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
706 690
     if (!this.state.isLoading) {
707 691
       this.setState({ isLoading: true });
708 692
     }
709
-
710 693
     let initialData = null;
711 694
     try {
712 695
       initialData = (await this.props.initialData) || null;
@@ -715,7 +698,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
715 698
     }
716 699
 
717 700
     const scene = restore(initialData, null);
718
-
719 701
     scene.appState = {
720 702
       ...scene.appState,
721 703
       isLoading: false,
@@ -787,14 +769,11 @@ class App extends React.Component<ExcalidrawProps, AppState> {
787 769
     this.scene.addCallback(this.onSceneUpdated);
788 770
     this.addEventListeners();
789 771
 
790
-    if (
791
-      "ResizeObserver" in window &&
792
-      this.excalidrawContainerRef?.current?.parentElement
793
-    ) {
794
-      this.resizeObserver = new ResizeObserver(() => this.setCanvasOffsets());
795
-      this.resizeObserver?.observe(
796
-        this.excalidrawContainerRef.current.parentElement,
797
-      );
772
+    if ("ResizeObserver" in window && this.excalidrawContainerRef?.current) {
773
+      this.resizeObserver = new ResizeObserver(() => {
774
+        this.updateDOMRect();
775
+      });
776
+      this.resizeObserver?.observe(this.excalidrawContainerRef.current);
798 777
     }
799 778
     const searchParams = new URLSearchParams(window.location.search.slice(1));
800 779
 
@@ -802,9 +781,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
802 781
       // Obtain a file that was shared via the Web Share Target API.
803 782
       this.restoreFileFromShare();
804 783
     } else {
805
-      this.setState(this.getCanvasOffsets(), () => {
806
-        this.initializeScene();
807
-      });
784
+      this.updateDOMRect(this.initializeScene);
808 785
     }
809 786
   }
810 787
 
@@ -906,17 +883,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
906 883
       this.updateLanguage();
907 884
     }
908 885
 
909
-    if (
910
-      prevProps.width !== this.props.width ||
911
-      prevProps.height !== this.props.height
912
-    ) {
913
-      this.setState({
914
-        width: this.props.width ?? window.innerWidth,
915
-        height: this.props.height ?? window.innerHeight,
916
-        ...this.getCanvasOffsets(),
917
-      });
918
-    }
919
-
920 886
     if (prevProps.viewModeEnabled !== this.props.viewModeEnabled) {
921 887
       this.setState(
922 888
         { viewModeEnabled: !!this.props.viewModeEnabled },
@@ -4093,14 +4059,56 @@ class App extends React.Component<ExcalidrawProps, AppState> {
4093 4059
     }
4094 4060
   }, 300);
4095 4061
 
4062
+  private updateDOMRect = (cb?: () => void) => {
4063
+    if (this.excalidrawContainerRef?.current) {
4064
+      const excalidrawContainer = this.excalidrawContainerRef.current;
4065
+      const {
4066
+        width,
4067
+        height,
4068
+        left: offsetLeft,
4069
+        top: offsetTop,
4070
+      } = excalidrawContainer.getBoundingClientRect();
4071
+      const {
4072
+        width: currentWidth,
4073
+        height: currentHeight,
4074
+        offsetTop: currentOffsetTop,
4075
+        offsetLeft: currentOffsetLeft,
4076
+      } = this.state;
4077
+
4078
+      if (
4079
+        width === currentWidth &&
4080
+        height === currentHeight &&
4081
+        offsetLeft === currentOffsetLeft &&
4082
+        offsetTop === currentOffsetTop
4083
+      ) {
4084
+        if (cb) {
4085
+          cb();
4086
+        }
4087
+        return;
4088
+      }
4089
+
4090
+      this.setState(
4091
+        {
4092
+          width,
4093
+          height,
4094
+          offsetLeft,
4095
+          offsetTop,
4096
+        },
4097
+        () => {
4098
+          cb && cb();
4099
+        },
4100
+      );
4101
+    }
4102
+  };
4103
+
4096 4104
   public setCanvasOffsets = () => {
4097 4105
     this.setState({ ...this.getCanvasOffsets() });
4098 4106
   };
4099 4107
 
4100 4108
   private getCanvasOffsets(): Pick<AppState, "offsetTop" | "offsetLeft"> {
4101
-    if (this.excalidrawContainerRef?.current?.parentElement) {
4102
-      const parentElement = this.excalidrawContainerRef.current.parentElement;
4103
-      const { left, top } = parentElement.getBoundingClientRect();
4109
+    if (this.excalidrawContainerRef?.current) {
4110
+      const excalidrawContainer = this.excalidrawContainerRef.current;
4111
+      const { left, top } = excalidrawContainer.getBoundingClientRect();
4104 4112
       return {
4105 4113
         offsetLeft: left,
4106 4114
         offsetTop: top,

+ 6
- 0
src/css/styles.scss 查看文件

@@ -16,6 +16,8 @@
16 16
   bottom: 0;
17 17
   left: 0;
18 18
   right: 0;
19
+  height: 100%;
20
+  width: 100%;
19 21
 
20 22
   // serves 2 purposes:
21 23
   // 1. prevent selecting text outside the component when double-clicking or
@@ -45,6 +47,10 @@
45 47
     image-rendering: -moz-crisp-edges; // FF
46 48
 
47 49
     z-index: var(--zIndex-canvas);
50
+
51
+    // Remove canvas from document flow to avoid resizeObserver feedback loop
52
+    // (see https://github.com/excalidraw/excalidraw/pull/3379)
53
+    position: absolute;
48 54
   }
49 55
 
50 56
   &.theme--dark {

+ 1
- 3
src/data/restore.ts 查看文件

@@ -144,7 +144,7 @@ export const restoreElements = (
144 144
 export const restoreAppState = (
145 145
   appState: ImportedDataState["appState"],
146 146
   localAppState: Partial<AppState> | null,
147
-): AppState => {
147
+): DataState["appState"] => {
148 148
   appState = appState || {};
149 149
 
150 150
   const defaultAppState = getDefaultAppState();
@@ -166,8 +166,6 @@ export const restoreAppState = (
166 166
 
167 167
   return {
168 168
     ...nextAppState,
169
-    offsetLeft: appState.offsetLeft || 0,
170
-    offsetTop: appState.offsetTop || 0,
171 169
     // Migrates from previous version where appState.zoom was a number
172 170
     zoom:
173 171
       typeof appState.zoom === "number"

+ 1
- 1
src/data/types.ts 查看文件

@@ -6,7 +6,7 @@ export interface DataState {
6 6
   version?: string;
7 7
   source?: string;
8 8
   elements: readonly ExcalidrawElement[];
9
-  appState: MarkOptional<AppState, "offsetTop" | "offsetLeft">;
9
+  appState: Omit<AppState, "offsetTop" | "offsetLeft" | "width" | "height">;
10 10
 }
11 11
 
12 12
 export interface ImportedDataState {

+ 0
- 23
src/excalidraw-app/index.tsx 查看文件

@@ -3,7 +3,6 @@ import React, {
3 3
   useCallback,
4 4
   useContext,
5 5
   useEffect,
6
-  useLayoutEffect,
7 6
   useRef,
8 7
   useState,
9 8
 } from "react";
@@ -163,30 +162,10 @@ const initializeScene = async (opts: {
163 162
 };
164 163
 
165 164
 const ExcalidrawWrapper = () => {
166
-  // dimensions
167
-  // ---------------------------------------------------------------------------
168
-
169
-  const [dimensions, setDimensions] = useState({
170
-    width: window.innerWidth,
171
-    height: window.innerHeight,
172
-  });
173 165
   const [errorMessage, setErrorMessage] = useState("");
174 166
   const currentLangCode = languageDetector.detect() || defaultLang.code;
175 167
   const [langCode, setLangCode] = useState(currentLangCode);
176 168
 
177
-  useLayoutEffect(() => {
178
-    const onResize = () => {
179
-      setDimensions({
180
-        width: window.innerWidth,
181
-        height: window.innerHeight,
182
-      });
183
-    };
184
-
185
-    window.addEventListener("resize", onResize);
186
-
187
-    return () => window.removeEventListener("resize", onResize);
188
-  }, []);
189
-
190 169
   // initial state
191 170
   // ---------------------------------------------------------------------------
192 171
 
@@ -337,8 +316,6 @@ const ExcalidrawWrapper = () => {
337 316
       <Excalidraw
338 317
         ref={excalidrawRefCallback}
339 318
         onChange={onChange}
340
-        width={dimensions.width}
341
-        height={dimensions.height}
342 319
         initialData={initialStatePromiseRef.current.promise}
343 320
         onCollabButtonClick={collabAPI?.onCollabButtonClick}
344 321
         isCollaborating={collabAPI?.isCollaborating()}

+ 2
- 0
src/index-node.ts 查看文件

@@ -63,6 +63,8 @@ const canvas = exportToCanvas(
63 63
     ...getDefaultAppState(),
64 64
     offsetTop: 0,
65 65
     offsetLeft: 0,
66
+    width: 0,
67
+    height: 0,
66 68
   },
67 69
   {
68 70
     exportBackground: true,

+ 3
- 0
src/packages/excalidraw/CHANGELOG.md 查看文件

@@ -18,6 +18,9 @@ Please add the latest change on the top under the correct section.
18 18
 
19 19
 ### Features
20 20
 
21
+- Calculate `width/height` of canvas based on excalidraw component (".excalidraw" selector) & also resize and update offsets whenever the dimensions of excalidraw component gets updated [#3379](https://github.com/excalidraw/excalidraw/pull/3379). You also don't need to add a resize handler anymore for excalidraw as its handled now in excalidraw itself.
22
+  #### BREAKING CHANGE
23
+  - `width/height` props have been removed. Instead now it takes `100%` of `width` and `height` of the container so you need to make sure the container in which you are rendering Excalidraw has non zero dimensions (It should have non zero width and height so Excalidraw can match the dimensions of containing block)
21 24
 - Calculate offsets when excalidraw container resizes using resize observer api [#3374](https://github.com/excalidraw/excalidraw/pull/3374).
22 25
 - Export types for the package so now it can be used with typescript [#3337](https://github.com/excalidraw/excalidraw/pull/3337). The types are available at `@excalidraw/excalirdraw/types`.
23 26
 - Add `renderCustomStats` prop to render extra stats on host, and expose `setToastMessage` API via refs which can be used to show toast with custom message [#3360](https://github.com/excalidraw/excalidraw/pull/3360).

+ 4
- 58
src/packages/excalidraw/README_NEXT.md 查看文件

@@ -45,32 +45,11 @@ import "./styles.scss";
45 45
 
46 46
 export default function App() {
47 47
   const excalidrawRef = useRef(null);
48
-  const excalidrawWrapperRef = useRef(null);
49
-  const [dimensions, setDimensions] = useState({
50
-    width: undefined,
51
-    height: undefined,
52
-  });
53 48
 
54 49
   const [viewModeEnabled, setViewModeEnabled] = useState(false);
55 50
   const [zenModeEnabled, setZenModeEnabled] = useState(false);
56 51
   const [gridModeEnabled, setGridModeEnabled] = useState(false);
57 52
 
58
-  useEffect(() => {
59
-    setDimensions({
60
-      width: excalidrawWrapperRef.current.getBoundingClientRect().width,
61
-      height: excalidrawWrapperRef.current.getBoundingClientRect().height,
62
-    });
63
-    const onResize = () => {
64
-      setDimensions({
65
-        width: excalidrawWrapperRef.current.getBoundingClientRect().width,
66
-        height: excalidrawWrapperRef.current.getBoundingClientRect().height,
67
-      });
68
-    };
69
-
70
-    window.addEventListener("resize", onResize);
71
-
72
-    return () => window.removeEventListener("resize", onResize);
73
-  }, [excalidrawWrapperRef]);
74 53
 
75 54
   const updateScene = () => {
76 55
     const sceneData = {
@@ -144,13 +123,11 @@ export default function App() {
144 123
           Grid mode
145 124
         </label>
146 125
       </div>
147
-      <div className="excalidraw-wrapper" ref={excalidrawWrapperRef}>
126
+      <div className="excalidraw-wrapper">
148 127
         <Excalidraw
149 128
           ref={excalidrawRef}
150
-          width={dimensions.width}
151
-          height={dimensions.height}
152 129
           initialData={InitialData}
153
-          onChange={(elements, state) =>
130
+          onChange={(elements, state) => {
154 131
             console.log("Elements :", elements, "State : ", state)
155 132
           }
156 133
           onPointerUpdate={(payload) => console.log(payload)}
@@ -246,33 +223,11 @@ import InitialData from "./initialData";
246 223
 
247 224
 const App = () => {
248 225
   const excalidrawRef = React.useRef(null);
249
-  const excalidrawWrapperRef = React.useRef(null);
250
-  const [dimensions, setDimensions] = React.useState({
251
-    width: undefined,
252
-    height: undefined,
253
-  });
254 226
 
255 227
   const [viewModeEnabled, setViewModeEnabled] = React.useState(false);
256 228
   const [zenModeEnabled, setZenModeEnabled] = React.useState(false);
257 229
   const [gridModeEnabled, setGridModeEnabled] = React.useState(false);
258 230
 
259
-  React.useEffect(() => {
260
-    setDimensions({
261
-      width: excalidrawWrapperRef.current.getBoundingClientRect().width,
262
-      height: excalidrawWrapperRef.current.getBoundingClientRect().height,
263
-    });
264
-    const onResize = () => {
265
-      setDimensions({
266
-        width: excalidrawWrapperRef.current.getBoundingClientRect().width,
267
-        height: excalidrawWrapperRef.current.getBoundingClientRect().height,
268
-      });
269
-    };
270
-
271
-    window.addEventListener("resize", onResize);
272
-
273
-    return () => window.removeEventListener("resize", onResize);
274
-  }, [excalidrawWrapperRef]);
275
-
276 231
   const updateScene = () => {
277 232
     const sceneData = {
278 233
       elements: [
@@ -365,9 +320,6 @@ const App = () => {
365 320
         ref: excalidrawWrapperRef,
366 321
       },
367 322
       React.createElement(Excalidraw.default, {
368
-        ref: excalidrawRef,
369
-        width: dimensions.width,
370
-        height: dimensions.height,
371 323
         initialData: InitialData,
372 324
         onChange: (elements, state) =>
373 325
           console.log("Elements :", elements, "State : ", state),
@@ -396,8 +348,6 @@ To view the full example visit :point_down:
396 348
 
397 349
 | Name | Type | Default | Description |
398 350
 | --- | --- | --- | --- |
399
-| [`width`](#width) | Number | `window.innerWidth` | The width of Excalidraw component |
400
-| [`height`](#height) | Number | `window.innerHeight` | The height of Excalidraw component |
401 351
 | [`onChange`](#onChange) | Function |  | This callback is triggered whenever the component updates due to any change. This callback will receive the excalidraw elements and the current app state. |
402 352
 | [`initialData`](#initialData) | <pre>{elements?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>, appState?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37">AppState<a> } </pre> | null | The initial data with which app loads. |
403 353
 | [`ref`](#ref) | [`createRef`](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) or [`callbackRef`](https://reactjs.org/docs/refs-and-the-dom.html#callback-refs) or <pre>{ current: { readyPromise: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/utils.ts#L317">resolvablePromise</a> } }</pre> |  | Ref to be passed to Excalidraw |
@@ -415,13 +365,9 @@ To view the full example visit :point_down:
415 365
 | [`theme`](#theme) | `light` or `dark` |  | The theme of the Excalidraw component |
416 366
 | [`name`](#name) | string |  | Name of the drawing |
417 367
 
418
-#### `width`
419
-
420
-This props defines the `width` of the Excalidraw component. Defaults to `window.innerWidth` if not passed.
421
-
422
-#### `height`
368
+### Dimensions of Excalidraw
423 369
 
424
-This props defines the `height` of the Excalidraw component. Defaults to `window.innerHeight` if not passed.
370
+Excalidraw takes `100%` of `width` and `height` of the containing block so you need to make sure the container in which you are rendering Excalidraw has non zero dimensions (It should have non zero width and height so Excalidraw can match the dimensions of the containing block). This is to make sure you don't have to worry about updating the offsets of dimensions when resizing Excalidraw.
425 371
 
426 372
 #### `onChange`
427 373
 

+ 0
- 4
src/packages/excalidraw/index.tsx 查看文件

@@ -13,8 +13,6 @@ import { defaultLang } from "../../i18n";
13 13
 
14 14
 const Excalidraw = (props: ExcalidrawProps) => {
15 15
   const {
16
-    width,
17
-    height,
18 16
     onChange,
19 17
     initialData,
20 18
     excalidrawRef,
@@ -55,8 +53,6 @@ const Excalidraw = (props: ExcalidrawProps) => {
55 53
     <InitializeApp langCode={langCode}>
56 54
       <IsMobileProvider>
57 55
         <App
58
-          width={width}
59
-          height={height}
60 56
           onChange={onChange}
61 57
           initialData={initialData}
62 58
           excalidrawRef={excalidrawRef}

+ 1
- 1
src/packages/utils.ts 查看文件

@@ -33,7 +33,7 @@ export const exportToCanvas = ({
33 33
   } = restoredAppState;
34 34
   return _exportToCanvas(
35 35
     getNonDeletedElements(restoredElements),
36
-    { ...restoredAppState, offsetTop: 0, offsetLeft: 0 },
36
+    { ...restoredAppState, offsetTop: 0, offsetLeft: 0, width: 0, height: 0 },
37 37
     { exportBackground, viewBackgroundColor, shouldAddWatermark },
38 38
     (width: number, height: number) => {
39 39
       const canvas = document.createElement("canvas");

+ 67
- 67
src/tests/__snapshots__/regressionTests.test.tsx.snap 查看文件

@@ -459,7 +459,7 @@ Object {
459 459
 
460 460
 exports[`given element A and group of elements B and given both are selected when user clicks on B, on pointer up only elements from B should be selected: [end of test] number of elements 1`] = `3`;
461 461
 
462
-exports[`given element A and group of elements B and given both are selected when user clicks on B, on pointer up only elements from B should be selected: [end of test] number of renders 1`] = `26`;
462
+exports[`given element A and group of elements B and given both are selected when user clicks on B, on pointer up only elements from B should be selected: [end of test] number of renders 1`] = `27`;
463 463
 
464 464
 exports[`given element A and group of elements B and given both are selected when user shift-clicks on B, on pointer up only element A should be selected: [end of test] appState 1`] = `
465 465
 Object {
@@ -926,7 +926,7 @@ Object {
926 926
 
927 927
 exports[`given element A and group of elements B and given both are selected when user shift-clicks on B, on pointer up only element A should be selected: [end of test] number of elements 1`] = `3`;
928 928
 
929
-exports[`given element A and group of elements B and given both are selected when user shift-clicks on B, on pointer up only element A should be selected: [end of test] number of renders 1`] = `22`;
929
+exports[`given element A and group of elements B and given both are selected when user shift-clicks on B, on pointer up only element A should be selected: [end of test] number of renders 1`] = `23`;
930 930
 
931 931
 exports[`regression tests Cmd/Ctrl-click exclusively select element under pointer: [end of test] appState 1`] = `
932 932
 Object {
@@ -1702,7 +1702,7 @@ Object {
1702 1702
 
1703 1703
 exports[`regression tests Cmd/Ctrl-click exclusively select element under pointer: [end of test] number of elements 1`] = `3`;
1704 1704
 
1705
-exports[`regression tests Cmd/Ctrl-click exclusively select element under pointer: [end of test] number of renders 1`] = `41`;
1705
+exports[`regression tests Cmd/Ctrl-click exclusively select element under pointer: [end of test] number of renders 1`] = `42`;
1706 1706
 
1707 1707
 exports[`regression tests Drags selected element when hitting only bounding box and keeps element selected: [end of test] appState 1`] = `
1708 1708
 Object {
@@ -1906,7 +1906,7 @@ Object {
1906 1906
 
1907 1907
 exports[`regression tests Drags selected element when hitting only bounding box and keeps element selected: [end of test] number of elements 1`] = `1`;
1908 1908
 
1909
-exports[`regression tests Drags selected element when hitting only bounding box and keeps element selected: [end of test] number of renders 1`] = `10`;
1909
+exports[`regression tests Drags selected element when hitting only bounding box and keeps element selected: [end of test] number of renders 1`] = `11`;
1910 1910
 
1911 1911
 exports[`regression tests adjusts z order when grouping: [end of test] appState 1`] = `
1912 1912
 Object {
@@ -2364,7 +2364,7 @@ Object {
2364 2364
 
2365 2365
 exports[`regression tests adjusts z order when grouping: [end of test] number of elements 1`] = `3`;
2366 2366
 
2367
-exports[`regression tests adjusts z order when grouping: [end of test] number of renders 1`] = `20`;
2367
+exports[`regression tests adjusts z order when grouping: [end of test] number of renders 1`] = `21`;
2368 2368
 
2369 2369
 exports[`regression tests alt-drag duplicates an element: [end of test] appState 1`] = `
2370 2370
 Object {
@@ -2617,7 +2617,7 @@ Object {
2617 2617
 
2618 2618
 exports[`regression tests alt-drag duplicates an element: [end of test] number of elements 1`] = `2`;
2619 2619
 
2620
-exports[`regression tests alt-drag duplicates an element: [end of test] number of renders 1`] = `10`;
2620
+exports[`regression tests alt-drag duplicates an element: [end of test] number of renders 1`] = `11`;
2621 2621
 
2622 2622
 exports[`regression tests arrow keys: [end of test] appState 1`] = `
2623 2623
 Object {
@@ -2781,7 +2781,7 @@ Object {
2781 2781
 
2782 2782
 exports[`regression tests arrow keys: [end of test] number of elements 1`] = `1`;
2783 2783
 
2784
-exports[`regression tests arrow keys: [end of test] number of renders 1`] = `19`;
2784
+exports[`regression tests arrow keys: [end of test] number of renders 1`] = `20`;
2785 2785
 
2786 2786
 exports[`regression tests can drag element that covers another element, while another elem is selected: [end of test] appState 1`] = `
2787 2787
 Object {
@@ -3258,7 +3258,7 @@ Object {
3258 3258
 
3259 3259
 exports[`regression tests can drag element that covers another element, while another elem is selected: [end of test] number of elements 1`] = `3`;
3260 3260
 
3261
-exports[`regression tests can drag element that covers another element, while another elem is selected: [end of test] number of renders 1`] = `18`;
3261
+exports[`regression tests can drag element that covers another element, while another elem is selected: [end of test] number of renders 1`] = `19`;
3262 3262
 
3263 3263
 exports[`regression tests change the properties of a shape: [end of test] appState 1`] = `
3264 3264
 Object {
@@ -3494,7 +3494,7 @@ Object {
3494 3494
 
3495 3495
 exports[`regression tests change the properties of a shape: [end of test] number of elements 1`] = `1`;
3496 3496
 
3497
-exports[`regression tests change the properties of a shape: [end of test] number of renders 1`] = `11`;
3497
+exports[`regression tests change the properties of a shape: [end of test] number of renders 1`] = `12`;
3498 3498
 
3499 3499
 exports[`regression tests click on an element and drag it: [dragged] appState 1`] = `
3500 3500
 Object {
@@ -3698,7 +3698,7 @@ Object {
3698 3698
 
3699 3699
 exports[`regression tests click on an element and drag it: [dragged] number of elements 1`] = `1`;
3700 3700
 
3701
-exports[`regression tests click on an element and drag it: [dragged] number of renders 1`] = `10`;
3701
+exports[`regression tests click on an element and drag it: [dragged] number of renders 1`] = `11`;
3702 3702
 
3703 3703
 exports[`regression tests click on an element and drag it: [end of test] appState 1`] = `
3704 3704
 Object {
@@ -3942,7 +3942,7 @@ Object {
3942 3942
 
3943 3943
 exports[`regression tests click on an element and drag it: [end of test] number of elements 1`] = `1`;
3944 3944
 
3945
-exports[`regression tests click on an element and drag it: [end of test] number of renders 1`] = `13`;
3945
+exports[`regression tests click on an element and drag it: [end of test] number of renders 1`] = `14`;
3946 3946
 
3947 3947
 exports[`regression tests click to select a shape: [end of test] appState 1`] = `
3948 3948
 Object {
@@ -4194,7 +4194,7 @@ Object {
4194 4194
 
4195 4195
 exports[`regression tests click to select a shape: [end of test] number of elements 1`] = `2`;
4196 4196
 
4197
-exports[`regression tests click to select a shape: [end of test] number of renders 1`] = `13`;
4197
+exports[`regression tests click to select a shape: [end of test] number of renders 1`] = `14`;
4198 4198
 
4199 4199
 exports[`regression tests click-drag to select a group: [end of test] appState 1`] = `
4200 4200
 Object {
@@ -4555,7 +4555,7 @@ Object {
4555 4555
 
4556 4556
 exports[`regression tests click-drag to select a group: [end of test] number of elements 1`] = `3`;
4557 4557
 
4558
-exports[`regression tests click-drag to select a group: [end of test] number of renders 1`] = `19`;
4558
+exports[`regression tests click-drag to select a group: [end of test] number of renders 1`] = `20`;
4559 4559
 
4560 4560
 exports[`regression tests deselects group of selected elements on pointer down when pointer doesn't hit any element: [end of test] appState 1`] = `
4561 4561
 Object {
@@ -4850,7 +4850,7 @@ Object {
4850 4850
 
4851 4851
 exports[`regression tests deselects group of selected elements on pointer down when pointer doesn't hit any element: [end of test] number of elements 1`] = `2`;
4852 4852
 
4853
-exports[`regression tests deselects group of selected elements on pointer down when pointer doesn't hit any element: [end of test] number of renders 1`] = `14`;
4853
+exports[`regression tests deselects group of selected elements on pointer down when pointer doesn't hit any element: [end of test] number of renders 1`] = `15`;
4854 4854
 
4855 4855
 exports[`regression tests deselects group of selected elements on pointer up when pointer hits common bounding box without hitting any element: [end of test] appState 1`] = `
4856 4856
 Object {
@@ -5157,7 +5157,7 @@ Object {
5157 5157
 
5158 5158
 exports[`regression tests deselects group of selected elements on pointer up when pointer hits common bounding box without hitting any element: [end of test] number of elements 1`] = `2`;
5159 5159
 
5160
-exports[`regression tests deselects group of selected elements on pointer up when pointer hits common bounding box without hitting any element: [end of test] number of renders 1`] = `15`;
5160
+exports[`regression tests deselects group of selected elements on pointer up when pointer hits common bounding box without hitting any element: [end of test] number of renders 1`] = `16`;
5161 5161
 
5162 5162
 exports[`regression tests deselects selected element on pointer down when pointer doesn't hit any element: [end of test] appState 1`] = `
5163 5163
 Object {
@@ -5365,7 +5365,7 @@ Object {
5365 5365
 
5366 5366
 exports[`regression tests deselects selected element on pointer down when pointer doesn't hit any element: [end of test] number of elements 1`] = `1`;
5367 5367
 
5368
-exports[`regression tests deselects selected element on pointer down when pointer doesn't hit any element: [end of test] number of renders 1`] = `8`;
5368
+exports[`regression tests deselects selected element on pointer down when pointer doesn't hit any element: [end of test] number of renders 1`] = `9`;
5369 5369
 
5370 5370
 exports[`regression tests deselects selected element, on pointer up, when click hits element bounding box but doesn't hit the element: [end of test] appState 1`] = `
5371 5371
 Object {
@@ -5551,7 +5551,7 @@ Object {
5551 5551
 
5552 5552
 exports[`regression tests deselects selected element, on pointer up, when click hits element bounding box but doesn't hit the element: [end of test] number of elements 1`] = `1`;
5553 5553
 
5554
-exports[`regression tests deselects selected element, on pointer up, when click hits element bounding box but doesn't hit the element: [end of test] number of renders 1`] = `9`;
5554
+exports[`regression tests deselects selected element, on pointer up, when click hits element bounding box but doesn't hit the element: [end of test] number of renders 1`] = `10`;
5555 5555
 
5556 5556
 exports[`regression tests double click to edit a group: [end of test] appState 1`] = `
5557 5557
 Object {
@@ -6004,7 +6004,7 @@ Object {
6004 6004
 
6005 6005
 exports[`regression tests double click to edit a group: [end of test] number of elements 1`] = `3`;
6006 6006
 
6007
-exports[`regression tests double click to edit a group: [end of test] number of renders 1`] = `18`;
6007
+exports[`regression tests double click to edit a group: [end of test] number of renders 1`] = `19`;
6008 6008
 
6009 6009
 exports[`regression tests drags selected elements from point inside common bounding box that doesn't hit any element and keeps elements selected after dragging: [end of test] appState 1`] = `
6010 6010
 Object {
@@ -6322,7 +6322,7 @@ Object {
6322 6322
 
6323 6323
 exports[`regression tests drags selected elements from point inside common bounding box that doesn't hit any element and keeps elements selected after dragging: [end of test] number of elements 1`] = `2`;
6324 6324
 
6325
-exports[`regression tests drags selected elements from point inside common bounding box that doesn't hit any element and keeps elements selected after dragging: [end of test] number of renders 1`] = `16`;
6325
+exports[`regression tests drags selected elements from point inside common bounding box that doesn't hit any element and keeps elements selected after dragging: [end of test] number of renders 1`] = `17`;
6326 6326
 
6327 6327
 exports[`regression tests draw every type of shape: [end of test] appState 1`] = `
6328 6328
 Object {
@@ -8356,7 +8356,7 @@ Object {
8356 8356
 
8357 8357
 exports[`regression tests draw every type of shape: [end of test] number of elements 1`] = `8`;
8358 8358
 
8359
-exports[`regression tests draw every type of shape: [end of test] number of renders 1`] = `51`;
8359
+exports[`regression tests draw every type of shape: [end of test] number of renders 1`] = `52`;
8360 8360
 
8361 8361
 exports[`regression tests given a group of selected elements with an element that is not selected inside the group common bounding box when element that is not selected is clicked should switch selection to not selected element on pointer up: [end of test] appState 1`] = `
8362 8362
 Object {
@@ -8718,7 +8718,7 @@ Object {
8718 8718
 
8719 8719
 exports[`regression tests given a group of selected elements with an element that is not selected inside the group common bounding box when element that is not selected is clicked should switch selection to not selected element on pointer up: [end of test] number of elements 1`] = `3`;
8720 8720
 
8721
-exports[`regression tests given a group of selected elements with an element that is not selected inside the group common bounding box when element that is not selected is clicked should switch selection to not selected element on pointer up: [end of test] number of renders 1`] = `19`;
8721
+exports[`regression tests given a group of selected elements with an element that is not selected inside the group common bounding box when element that is not selected is clicked should switch selection to not selected element on pointer up: [end of test] number of renders 1`] = `20`;
8722 8722
 
8723 8723
 exports[`regression tests given a selected element A and a not selected element B with higher z-index than A and given B partialy overlaps A when there's a shift-click on the overlapped section B is added to the selection: [end of test] appState 1`] = `
8724 8724
 Object {
@@ -8973,7 +8973,7 @@ Object {
8973 8973
 
8974 8974
 exports[`regression tests given a selected element A and a not selected element B with higher z-index than A and given B partialy overlaps A when there's a shift-click on the overlapped section B is added to the selection: [end of test] number of elements 1`] = `2`;
8975 8975
 
8976
-exports[`regression tests given a selected element A and a not selected element B with higher z-index than A and given B partialy overlaps A when there's a shift-click on the overlapped section B is added to the selection: [end of test] number of renders 1`] = `17`;
8976
+exports[`regression tests given a selected element A and a not selected element B with higher z-index than A and given B partialy overlaps A when there's a shift-click on the overlapped section B is added to the selection: [end of test] number of renders 1`] = `18`;
8977 8977
 
8978 8978
 exports[`regression tests given selected element A with lower z-index than unselected element B and given B is partially over A when clicking intersection between A and B B should be selected on pointer up: [end of test] appState 1`] = `
8979 8979
 Object {
@@ -9226,7 +9226,7 @@ Object {
9226 9226
 
9227 9227
 exports[`regression tests given selected element A with lower z-index than unselected element B and given B is partially over A when clicking intersection between A and B B should be selected on pointer up: [end of test] number of elements 1`] = `2`;
9228 9228
 
9229
-exports[`regression tests given selected element A with lower z-index than unselected element B and given B is partially over A when clicking intersection between A and B B should be selected on pointer up: [end of test] number of renders 1`] = `17`;
9229
+exports[`regression tests given selected element A with lower z-index than unselected element B and given B is partially over A when clicking intersection between A and B B should be selected on pointer up: [end of test] number of renders 1`] = `18`;
9230 9230
 
9231 9231
 exports[`regression tests given selected element A with lower z-index than unselected element B and given B is partially over A when dragging on intersection between A and B A should be dragged and keep being selected: [end of test] appState 1`] = `
9232 9232
 Object {
@@ -9541,7 +9541,7 @@ Object {
9541 9541
 
9542 9542
 exports[`regression tests given selected element A with lower z-index than unselected element B and given B is partially over A when dragging on intersection between A and B A should be dragged and keep being selected: [end of test] number of elements 1`] = `2`;
9543 9543
 
9544
-exports[`regression tests given selected element A with lower z-index than unselected element B and given B is partially over A when dragging on intersection between A and B A should be dragged and keep being selected: [end of test] number of renders 1`] = `18`;
9544
+exports[`regression tests given selected element A with lower z-index than unselected element B and given B is partially over A when dragging on intersection between A and B A should be dragged and keep being selected: [end of test] number of renders 1`] = `19`;
9545 9545
 
9546 9546
 exports[`regression tests key 2 selects rectangle tool: [end of test] appState 1`] = `
9547 9547
 Object {
@@ -9705,7 +9705,7 @@ Object {
9705 9705
 
9706 9706
 exports[`regression tests key 2 selects rectangle tool: [end of test] number of elements 1`] = `1`;
9707 9707
 
9708
-exports[`regression tests key 2 selects rectangle tool: [end of test] number of renders 1`] = `7`;
9708
+exports[`regression tests key 2 selects rectangle tool: [end of test] number of renders 1`] = `8`;
9709 9709
 
9710 9710
 exports[`regression tests key 3 selects diamond tool: [end of test] appState 1`] = `
9711 9711
 Object {
@@ -9869,7 +9869,7 @@ Object {
9869 9869
 
9870 9870
 exports[`regression tests key 3 selects diamond tool: [end of test] number of elements 1`] = `1`;
9871 9871
 
9872
-exports[`regression tests key 3 selects diamond tool: [end of test] number of renders 1`] = `7`;
9872
+exports[`regression tests key 3 selects diamond tool: [end of test] number of renders 1`] = `8`;
9873 9873
 
9874 9874
 exports[`regression tests key 4 selects ellipse tool: [end of test] appState 1`] = `
9875 9875
 Object {
@@ -10033,7 +10033,7 @@ Object {
10033 10033
 
10034 10034
 exports[`regression tests key 4 selects ellipse tool: [end of test] number of elements 1`] = `1`;
10035 10035
 
10036
-exports[`regression tests key 4 selects ellipse tool: [end of test] number of renders 1`] = `7`;
10036
+exports[`regression tests key 4 selects ellipse tool: [end of test] number of renders 1`] = `8`;
10037 10037
 
10038 10038
 exports[`regression tests key 5 selects arrow tool: [end of test] appState 1`] = `
10039 10039
 Object {
@@ -10227,7 +10227,7 @@ Object {
10227 10227
 
10228 10228
 exports[`regression tests key 5 selects arrow tool: [end of test] number of elements 1`] = `1`;
10229 10229
 
10230
-exports[`regression tests key 5 selects arrow tool: [end of test] number of renders 1`] = `8`;
10230
+exports[`regression tests key 5 selects arrow tool: [end of test] number of renders 1`] = `9`;
10231 10231
 
10232 10232
 exports[`regression tests key 6 selects line tool: [end of test] appState 1`] = `
10233 10233
 Object {
@@ -10421,7 +10421,7 @@ Object {
10421 10421
 
10422 10422
 exports[`regression tests key 6 selects line tool: [end of test] number of elements 1`] = `1`;
10423 10423
 
10424
-exports[`regression tests key 6 selects line tool: [end of test] number of renders 1`] = `7`;
10424
+exports[`regression tests key 6 selects line tool: [end of test] number of renders 1`] = `8`;
10425 10425
 
10426 10426
 exports[`regression tests key 7 selects draw tool: [end of test] appState 1`] = `
10427 10427
 Object {
@@ -10615,7 +10615,7 @@ Object {
10615 10615
 
10616 10616
 exports[`regression tests key 7 selects draw tool: [end of test] number of elements 1`] = `1`;
10617 10617
 
10618
-exports[`regression tests key 7 selects draw tool: [end of test] number of renders 1`] = `7`;
10618
+exports[`regression tests key 7 selects draw tool: [end of test] number of renders 1`] = `8`;
10619 10619
 
10620 10620
 exports[`regression tests key a selects arrow tool: [end of test] appState 1`] = `
10621 10621
 Object {
@@ -10809,7 +10809,7 @@ Object {
10809 10809
 
10810 10810
 exports[`regression tests key a selects arrow tool: [end of test] number of elements 1`] = `1`;
10811 10811
 
10812
-exports[`regression tests key a selects arrow tool: [end of test] number of renders 1`] = `8`;
10812
+exports[`regression tests key a selects arrow tool: [end of test] number of renders 1`] = `9`;
10813 10813
 
10814 10814
 exports[`regression tests key d selects diamond tool: [end of test] appState 1`] = `
10815 10815
 Object {
@@ -10973,7 +10973,7 @@ Object {
10973 10973
 
10974 10974
 exports[`regression tests key d selects diamond tool: [end of test] number of elements 1`] = `1`;
10975 10975
 
10976
-exports[`regression tests key d selects diamond tool: [end of test] number of renders 1`] = `7`;
10976
+exports[`regression tests key d selects diamond tool: [end of test] number of renders 1`] = `8`;
10977 10977
 
10978 10978
 exports[`regression tests key e selects ellipse tool: [end of test] appState 1`] = `
10979 10979
 Object {
@@ -11137,7 +11137,7 @@ Object {
11137 11137
 
11138 11138
 exports[`regression tests key e selects ellipse tool: [end of test] number of elements 1`] = `1`;
11139 11139
 
11140
-exports[`regression tests key e selects ellipse tool: [end of test] number of renders 1`] = `7`;
11140
+exports[`regression tests key e selects ellipse tool: [end of test] number of renders 1`] = `8`;
11141 11141
 
11142 11142
 exports[`regression tests key l selects line tool: [end of test] appState 1`] = `
11143 11143
 Object {
@@ -11331,7 +11331,7 @@ Object {
11331 11331
 
11332 11332
 exports[`regression tests key l selects line tool: [end of test] number of elements 1`] = `1`;
11333 11333
 
11334
-exports[`regression tests key l selects line tool: [end of test] number of renders 1`] = `7`;
11334
+exports[`regression tests key l selects line tool: [end of test] number of renders 1`] = `8`;
11335 11335
 
11336 11336
 exports[`regression tests key r selects rectangle tool: [end of test] appState 1`] = `
11337 11337
 Object {
@@ -11495,7 +11495,7 @@ Object {
11495 11495
 
11496 11496
 exports[`regression tests key r selects rectangle tool: [end of test] number of elements 1`] = `1`;
11497 11497
 
11498
-exports[`regression tests key r selects rectangle tool: [end of test] number of renders 1`] = `7`;
11498
+exports[`regression tests key r selects rectangle tool: [end of test] number of renders 1`] = `8`;
11499 11499
 
11500 11500
 exports[`regression tests key x selects draw tool: [end of test] appState 1`] = `
11501 11501
 Object {
@@ -11689,7 +11689,7 @@ Object {
11689 11689
 
11690 11690
 exports[`regression tests key x selects draw tool: [end of test] number of elements 1`] = `1`;
11691 11691
 
11692
-exports[`regression tests key x selects draw tool: [end of test] number of renders 1`] = `7`;
11692
+exports[`regression tests key x selects draw tool: [end of test] number of renders 1`] = `8`;
11693 11693
 
11694 11694
 exports[`regression tests make a group and duplicate it: [end of test] appState 1`] = `
11695 11695
 Object {
@@ -12405,7 +12405,7 @@ Object {
12405 12405
 
12406 12406
 exports[`regression tests make a group and duplicate it: [end of test] number of elements 1`] = `6`;
12407 12407
 
12408
-exports[`regression tests make a group and duplicate it: [end of test] number of renders 1`] = `22`;
12408
+exports[`regression tests make a group and duplicate it: [end of test] number of renders 1`] = `23`;
12409 12409
 
12410 12410
 exports[`regression tests noop interaction after undo shouldn't create history entry: [end of test] appState 1`] = `
12411 12411
 Object {
@@ -12658,7 +12658,7 @@ Object {
12658 12658
 
12659 12659
 exports[`regression tests noop interaction after undo shouldn't create history entry: [end of test] number of elements 1`] = `2`;
12660 12660
 
12661
-exports[`regression tests noop interaction after undo shouldn't create history entry: [end of test] number of renders 1`] = `19`;
12661
+exports[`regression tests noop interaction after undo shouldn't create history entry: [end of test] number of renders 1`] = `20`;
12662 12662
 
12663 12663
 exports[`regression tests pinch-to-zoom works: [end of test] appState 1`] = `
12664 12664
 Object {
@@ -12760,7 +12760,7 @@ Object {
12760 12760
 
12761 12761
 exports[`regression tests pinch-to-zoom works: [end of test] number of elements 1`] = `0`;
12762 12762
 
12763
-exports[`regression tests pinch-to-zoom works: [end of test] number of renders 1`] = `9`;
12763
+exports[`regression tests pinch-to-zoom works: [end of test] number of renders 1`] = `10`;
12764 12764
 
12765 12765
 exports[`regression tests rerenders UI on language change: [end of test] appState 1`] = `
12766 12766
 Object {
@@ -12860,7 +12860,7 @@ Object {
12860 12860
 
12861 12861
 exports[`regression tests rerenders UI on language change: [end of test] number of elements 1`] = `0`;
12862 12862
 
12863
-exports[`regression tests rerenders UI on language change: [end of test] number of renders 1`] = `8`;
12863
+exports[`regression tests rerenders UI on language change: [end of test] number of renders 1`] = `9`;
12864 12864
 
12865 12865
 exports[`regression tests selecting 'Add to library' in context menu adds element to library: [end of test] appState 1`] = `
12866 12866
 Object {
@@ -13024,7 +13024,7 @@ Object {
13024 13024
 
13025 13025
 exports[`regression tests selecting 'Add to library' in context menu adds element to library: [end of test] number of elements 1`] = `1`;
13026 13026
 
13027
-exports[`regression tests selecting 'Add to library' in context menu adds element to library: [end of test] number of renders 1`] = `7`;
13027
+exports[`regression tests selecting 'Add to library' in context menu adds element to library: [end of test] number of renders 1`] = `8`;
13028 13028
 
13029 13029
 exports[`regression tests selecting 'Bring forward' in context menu brings element forward: [end of test] appState 1`] = `
13030 13030
 Object {
@@ -13332,7 +13332,7 @@ Object {
13332 13332
 
13333 13333
 exports[`regression tests selecting 'Bring forward' in context menu brings element forward: [end of test] number of elements 1`] = `2`;
13334 13334
 
13335
-exports[`regression tests selecting 'Bring forward' in context menu brings element forward: [end of test] number of renders 1`] = `13`;
13335
+exports[`regression tests selecting 'Bring forward' in context menu brings element forward: [end of test] number of renders 1`] = `14`;
13336 13336
 
13337 13337
 exports[`regression tests selecting 'Bring to front' in context menu brings element to front: [end of test] appState 1`] = `
13338 13338
 Object {
@@ -13640,7 +13640,7 @@ Object {
13640 13640
 
13641 13641
 exports[`regression tests selecting 'Bring to front' in context menu brings element to front: [end of test] number of elements 1`] = `2`;
13642 13642
 
13643
-exports[`regression tests selecting 'Bring to front' in context menu brings element to front: [end of test] number of renders 1`] = `13`;
13643
+exports[`regression tests selecting 'Bring to front' in context menu brings element to front: [end of test] number of renders 1`] = `14`;
13644 13644
 
13645 13645
 exports[`regression tests selecting 'Copy styles' in context menu copies styles: [end of test] appState 1`] = `
13646 13646
 Object {
@@ -13804,7 +13804,7 @@ Object {
13804 13804
 
13805 13805
 exports[`regression tests selecting 'Copy styles' in context menu copies styles: [end of test] number of elements 1`] = `1`;
13806 13806
 
13807
-exports[`regression tests selecting 'Copy styles' in context menu copies styles: [end of test] number of renders 1`] = `8`;
13807
+exports[`regression tests selecting 'Copy styles' in context menu copies styles: [end of test] number of renders 1`] = `9`;
13808 13808
 
13809 13809
 exports[`regression tests selecting 'Delete' in context menu deletes element: [end of test] appState 1`] = `
13810 13810
 Object {
@@ -14000,7 +14000,7 @@ Object {
14000 14000
 
14001 14001
 exports[`regression tests selecting 'Delete' in context menu deletes element: [end of test] number of elements 1`] = `1`;
14002 14002
 
14003
-exports[`regression tests selecting 'Delete' in context menu deletes element: [end of test] number of renders 1`] = `8`;
14003
+exports[`regression tests selecting 'Delete' in context menu deletes element: [end of test] number of renders 1`] = `9`;
14004 14004
 
14005 14005
 exports[`regression tests selecting 'Duplicate' in context menu duplicates element: [end of test] appState 1`] = `
14006 14006
 Object {
@@ -14249,7 +14249,7 @@ Object {
14249 14249
 
14250 14250
 exports[`regression tests selecting 'Duplicate' in context menu duplicates element: [end of test] number of elements 1`] = `2`;
14251 14251
 
14252
-exports[`regression tests selecting 'Duplicate' in context menu duplicates element: [end of test] number of renders 1`] = `8`;
14252
+exports[`regression tests selecting 'Duplicate' in context menu duplicates element: [end of test] number of renders 1`] = `9`;
14253 14253
 
14254 14254
 exports[`regression tests selecting 'Group selection' in context menu groups selected elements: [end of test] appState 1`] = `
14255 14255
 Object {
@@ -14573,7 +14573,7 @@ Object {
14573 14573
 
14574 14574
 exports[`regression tests selecting 'Group selection' in context menu groups selected elements: [end of test] number of elements 1`] = `2`;
14575 14575
 
14576
-exports[`regression tests selecting 'Group selection' in context menu groups selected elements: [end of test] number of renders 1`] = `14`;
14576
+exports[`regression tests selecting 'Group selection' in context menu groups selected elements: [end of test] number of renders 1`] = `15`;
14577 14577
 
14578 14578
 exports[`regression tests selecting 'Paste styles' in context menu pastes styles: [end of test] appState 1`] = `
14579 14579
 Object {
@@ -15294,7 +15294,7 @@ Object {
15294 15294
 
15295 15295
 exports[`regression tests selecting 'Paste styles' in context menu pastes styles: [end of test] number of elements 1`] = `2`;
15296 15296
 
15297
-exports[`regression tests selecting 'Paste styles' in context menu pastes styles: [end of test] number of renders 1`] = `23`;
15297
+exports[`regression tests selecting 'Paste styles' in context menu pastes styles: [end of test] number of renders 1`] = `24`;
15298 15298
 
15299 15299
 exports[`regression tests selecting 'Send backward' in context menu sends element backward: [end of test] appState 1`] = `
15300 15300
 Object {
@@ -15602,7 +15602,7 @@ Object {
15602 15602
 
15603 15603
 exports[`regression tests selecting 'Send backward' in context menu sends element backward: [end of test] number of elements 1`] = `2`;
15604 15604
 
15605
-exports[`regression tests selecting 'Send backward' in context menu sends element backward: [end of test] number of renders 1`] = `12`;
15605
+exports[`regression tests selecting 'Send backward' in context menu sends element backward: [end of test] number of renders 1`] = `13`;
15606 15606
 
15607 15607
 exports[`regression tests selecting 'Send to back' in context menu sends element to back: [end of test] appState 1`] = `
15608 15608
 Object {
@@ -15910,7 +15910,7 @@ Object {
15910 15910
 
15911 15911
 exports[`regression tests selecting 'Send to back' in context menu sends element to back: [end of test] number of elements 1`] = `2`;
15912 15912
 
15913
-exports[`regression tests selecting 'Send to back' in context menu sends element to back: [end of test] number of renders 1`] = `12`;
15913
+exports[`regression tests selecting 'Send to back' in context menu sends element to back: [end of test] number of renders 1`] = `13`;
15914 15914
 
15915 15915
 exports[`regression tests selecting 'Ungroup selection' in context menu ungroups selected group: [end of test] appState 1`] = `
15916 15916
 Object {
@@ -16289,7 +16289,7 @@ Object {
16289 16289
 
16290 16290
 exports[`regression tests selecting 'Ungroup selection' in context menu ungroups selected group: [end of test] number of elements 1`] = `2`;
16291 16291
 
16292
-exports[`regression tests selecting 'Ungroup selection' in context menu ungroups selected group: [end of test] number of renders 1`] = `15`;
16292
+exports[`regression tests selecting 'Ungroup selection' in context menu ungroups selected group: [end of test] number of renders 1`] = `16`;
16293 16293
 
16294 16294
 exports[`regression tests shift click on selected element should deselect it on pointer up: [end of test] appState 1`] = `
16295 16295
 Object {
@@ -16456,7 +16456,7 @@ Object {
16456 16456
 
16457 16457
 exports[`regression tests shift click on selected element should deselect it on pointer up: [end of test] number of elements 1`] = `1`;
16458 16458
 
16459
-exports[`regression tests shift click on selected element should deselect it on pointer up: [end of test] number of renders 1`] = `9`;
16459
+exports[`regression tests shift click on selected element should deselect it on pointer up: [end of test] number of renders 1`] = `10`;
16460 16460
 
16461 16461
 exports[`regression tests shift-click to multiselect, then drag: [end of test] appState 1`] = `
16462 16462
 Object {
@@ -16777,7 +16777,7 @@ Object {
16777 16777
 
16778 16778
 exports[`regression tests shift-click to multiselect, then drag: [end of test] number of elements 1`] = `2`;
16779 16779
 
16780
-exports[`regression tests shift-click to multiselect, then drag: [end of test] number of renders 1`] = `18`;
16780
+exports[`regression tests shift-click to multiselect, then drag: [end of test] number of renders 1`] = `19`;
16781 16781
 
16782 16782
 exports[`regression tests should show fill icons when element has non transparent background: [end of test] appState 1`] = `
16783 16783
 Object {
@@ -16980,7 +16980,7 @@ Object {
16980 16980
 
16981 16981
 exports[`regression tests should show fill icons when element has non transparent background: [end of test] number of elements 1`] = `1`;
16982 16982
 
16983
-exports[`regression tests should show fill icons when element has non transparent background: [end of test] number of renders 1`] = `11`;
16983
+exports[`regression tests should show fill icons when element has non transparent background: [end of test] number of renders 1`] = `12`;
16984 16984
 
16985 16985
 exports[`regression tests shows 'Group selection' in context menu for multiple selected elements: [end of test] appState 1`] = `
16986 16986
 Object {
@@ -17235,7 +17235,7 @@ Object {
17235 17235
 
17236 17236
 exports[`regression tests shows 'Group selection' in context menu for multiple selected elements: [end of test] number of elements 1`] = `2`;
17237 17237
 
17238
-exports[`regression tests shows 'Group selection' in context menu for multiple selected elements: [end of test] number of renders 1`] = `15`;
17238
+exports[`regression tests shows 'Group selection' in context menu for multiple selected elements: [end of test] number of renders 1`] = `16`;
17239 17239
 
17240 17240
 exports[`regression tests shows 'Ungroup selection' in context menu for group inside selected elements: [end of test] appState 1`] = `
17241 17241
 Object {
@@ -17562,7 +17562,7 @@ Object {
17562 17562
 
17563 17563
 exports[`regression tests shows 'Ungroup selection' in context menu for group inside selected elements: [end of test] number of elements 1`] = `2`;
17564 17564
 
17565
-exports[`regression tests shows 'Ungroup selection' in context menu for group inside selected elements: [end of test] number of renders 1`] = `16`;
17565
+exports[`regression tests shows 'Ungroup selection' in context menu for group inside selected elements: [end of test] number of renders 1`] = `17`;
17566 17566
 
17567 17567
 exports[`regression tests shows context menu for canvas: [end of test] appState 1`] = `
17568 17568
 Object {
@@ -17662,7 +17662,7 @@ Object {
17662 17662
 
17663 17663
 exports[`regression tests shows context menu for canvas: [end of test] number of elements 1`] = `0`;
17664 17664
 
17665
-exports[`regression tests shows context menu for canvas: [end of test] number of renders 1`] = `3`;
17665
+exports[`regression tests shows context menu for canvas: [end of test] number of renders 1`] = `4`;
17666 17666
 
17667 17667
 exports[`regression tests shows context menu for element: [end of test] appState 1`] = `
17668 17668
 Object {
@@ -17826,7 +17826,7 @@ Object {
17826 17826
 
17827 17827
 exports[`regression tests shows context menu for element: [end of test] number of elements 1`] = `1`;
17828 17828
 
17829
-exports[`regression tests shows context menu for element: [end of test] number of renders 1`] = `7`;
17829
+exports[`regression tests shows context menu for element: [end of test] number of renders 1`] = `8`;
17830 17830
 
17831 17831
 exports[`regression tests single-clicking on a subgroup of a selected group should not alter selection: [end of test] appState 1`] = `
17832 17832
 Object {
@@ -18647,7 +18647,7 @@ Object {
18647 18647
 
18648 18648
 exports[`regression tests single-clicking on a subgroup of a selected group should not alter selection: [end of test] number of elements 1`] = `4`;
18649 18649
 
18650
-exports[`regression tests single-clicking on a subgroup of a selected group should not alter selection: [end of test] number of renders 1`] = `37`;
18650
+exports[`regression tests single-clicking on a subgroup of a selected group should not alter selection: [end of test] number of renders 1`] = `38`;
18651 18651
 
18652 18652
 exports[`regression tests spacebar + drag scrolls the canvas: [end of test] appState 1`] = `
18653 18653
 Object {
@@ -18747,7 +18747,7 @@ Object {
18747 18747
 
18748 18748
 exports[`regression tests spacebar + drag scrolls the canvas: [end of test] number of elements 1`] = `0`;
18749 18749
 
18750
-exports[`regression tests spacebar + drag scrolls the canvas: [end of test] number of renders 1`] = `6`;
18750
+exports[`regression tests spacebar + drag scrolls the canvas: [end of test] number of renders 1`] = `7`;
18751 18751
 
18752 18752
 exports[`regression tests supports nested groups: [end of test] appState 1`] = `
18753 18753
 Object {
@@ -19479,7 +19479,7 @@ Object {
19479 19479
 
19480 19480
 exports[`regression tests supports nested groups: [end of test] number of elements 1`] = `3`;
19481 19481
 
19482
-exports[`regression tests supports nested groups: [end of test] number of renders 1`] = `30`;
19482
+exports[`regression tests supports nested groups: [end of test] number of renders 1`] = `31`;
19483 19483
 
19484 19484
 exports[`regression tests switches from group of selected elements to another element on pointer down: [end of test] appState 1`] = `
19485 19485
 Object {
@@ -19884,7 +19884,7 @@ Object {
19884 19884
 
19885 19885
 exports[`regression tests switches from group of selected elements to another element on pointer down: [end of test] number of elements 1`] = `3`;
19886 19886
 
19887
-exports[`regression tests switches from group of selected elements to another element on pointer down: [end of test] number of renders 1`] = `18`;
19887
+exports[`regression tests switches from group of selected elements to another element on pointer down: [end of test] number of renders 1`] = `19`;
19888 19888
 
19889 19889
 exports[`regression tests switches selected element on pointer down: [end of test] appState 1`] = `
19890 19890
 Object {
@@ -20179,7 +20179,7 @@ Object {
20179 20179
 
20180 20180
 exports[`regression tests switches selected element on pointer down: [end of test] number of elements 1`] = `2`;
20181 20181
 
20182
-exports[`regression tests switches selected element on pointer down: [end of test] number of renders 1`] = `12`;
20182
+exports[`regression tests switches selected element on pointer down: [end of test] number of renders 1`] = `13`;
20183 20183
 
20184 20184
 exports[`regression tests two-finger scroll works: [end of test] appState 1`] = `
20185 20185
 Object {
@@ -20281,7 +20281,7 @@ Object {
20281 20281
 
20282 20282
 exports[`regression tests two-finger scroll works: [end of test] number of elements 1`] = `0`;
20283 20283
 
20284
-exports[`regression tests two-finger scroll works: [end of test] number of renders 1`] = `11`;
20284
+exports[`regression tests two-finger scroll works: [end of test] number of renders 1`] = `12`;
20285 20285
 
20286 20286
 exports[`regression tests undo/redo drawing an element: [end of test] appState 1`] = `
20287 20287
 Object {
@@ -20779,7 +20779,7 @@ Object {
20779 20779
 
20780 20780
 exports[`regression tests undo/redo drawing an element: [end of test] number of elements 1`] = `3`;
20781 20781
 
20782
-exports[`regression tests undo/redo drawing an element: [end of test] number of renders 1`] = `28`;
20782
+exports[`regression tests undo/redo drawing an element: [end of test] number of renders 1`] = `29`;
20783 20783
 
20784 20784
 exports[`regression tests updates fontSize & fontFamily appState: [end of test] appState 1`] = `
20785 20785
 Object {
@@ -20879,7 +20879,7 @@ Object {
20879 20879
 
20880 20880
 exports[`regression tests updates fontSize & fontFamily appState: [end of test] number of elements 1`] = `0`;
20881 20881
 
20882
-exports[`regression tests updates fontSize & fontFamily appState: [end of test] number of renders 1`] = `5`;
20882
+exports[`regression tests updates fontSize & fontFamily appState: [end of test] number of renders 1`] = `6`;
20883 20883
 
20884 20884
 exports[`regression tests zoom hotkeys: [end of test] appState 1`] = `
20885 20885
 Object {
@@ -20979,4 +20979,4 @@ Object {
20979 20979
 
20980 20980
 exports[`regression tests zoom hotkeys: [end of test] number of elements 1`] = `0`;
20981 20981
 
20982
-exports[`regression tests zoom hotkeys: [end of test] number of renders 1`] = `5`;
20982
+exports[`regression tests zoom hotkeys: [end of test] number of renders 1`] = `6`;

+ 10
- 10
src/tests/__snapshots__/selection.test.tsx.snap 查看文件

@@ -36,8 +36,8 @@ Object {
36 36
   "version": 3,
37 37
   "versionNonce": 449462985,
38 38
   "width": 30,
39
-  "x": 30,
40
-  "y": 20,
39
+  "x": 10,
40
+  "y": 10,
41 41
 }
42 42
 `;
43 43
 
@@ -77,8 +77,8 @@ Object {
77 77
   "version": 3,
78 78
   "versionNonce": 449462985,
79 79
   "width": 30,
80
-  "x": 30,
81
-  "y": 20,
80
+  "x": 10,
81
+  "y": 10,
82 82
 }
83 83
 `;
84 84
 
@@ -103,8 +103,8 @@ Object {
103 103
   "version": 2,
104 104
   "versionNonce": 1278240551,
105 105
   "width": 30,
106
-  "x": 30,
107
-  "y": 20,
106
+  "x": 10,
107
+  "y": 10,
108 108
 }
109 109
 `;
110 110
 
@@ -129,8 +129,8 @@ Object {
129 129
   "version": 2,
130 130
   "versionNonce": 1278240551,
131 131
   "width": 30,
132
-  "x": 30,
133
-  "y": 20,
132
+  "x": 10,
133
+  "y": 10,
134 134
 }
135 135
 `;
136 136
 
@@ -155,7 +155,7 @@ Object {
155 155
   "version": 2,
156 156
   "versionNonce": 1278240551,
157 157
   "width": 30,
158
-  "x": 30,
159
-  "y": 20,
158
+  "x": 10,
159
+  "y": 10,
160 160
 }
161 161
 `;

+ 18
- 6
src/tests/dragCreate.test.tsx 查看文件

@@ -3,7 +3,12 @@ import ReactDOM from "react-dom";
3 3
 import ExcalidrawApp from "../excalidraw-app";
4 4
 import * as Renderer from "../renderer/renderScene";
5 5
 import { KEYS } from "../keys";
6
-import { render, fireEvent } from "./test-utils";
6
+import {
7
+  render,
8
+  fireEvent,
9
+  mockBoundingClientRect,
10
+  restoreOriginalGetBoundingClientRect,
11
+} from "./test-utils";
7 12
 import { ExcalidrawLinearElement } from "../element/types";
8 13
 import { reseed } from "../random";
9 14
 
@@ -37,7 +42,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
37 42
     // finish (position does not matter)
38 43
     fireEvent.pointerUp(canvas);
39 44
 
40
-    expect(renderScene).toHaveBeenCalledTimes(7);
45
+    expect(renderScene).toHaveBeenCalledTimes(8);
41 46
     expect(h.state.selectionElement).toBeNull();
42 47
 
43 48
     expect(h.elements.length).toEqual(1);
@@ -68,7 +73,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
68 73
     // finish (position does not matter)
69 74
     fireEvent.pointerUp(canvas);
70 75
 
71
-    expect(renderScene).toHaveBeenCalledTimes(7);
76
+    expect(renderScene).toHaveBeenCalledTimes(8);
72 77
     expect(h.state.selectionElement).toBeNull();
73 78
 
74 79
     expect(h.elements.length).toEqual(1);
@@ -99,7 +104,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
99 104
     // finish (position does not matter)
100 105
     fireEvent.pointerUp(canvas);
101 106
 
102
-    expect(renderScene).toHaveBeenCalledTimes(7);
107
+    expect(renderScene).toHaveBeenCalledTimes(8);
103 108
     expect(h.state.selectionElement).toBeNull();
104 109
 
105 110
     expect(h.elements.length).toEqual(1);
@@ -130,7 +135,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
130 135
     // finish (position does not matter)
131 136
     fireEvent.pointerUp(canvas);
132 137
 
133
-    expect(renderScene).toHaveBeenCalledTimes(7);
138
+    expect(renderScene).toHaveBeenCalledTimes(8);
134 139
     expect(h.state.selectionElement).toBeNull();
135 140
 
136 141
     expect(h.elements.length).toEqual(1);
@@ -165,7 +170,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
165 170
     // finish (position does not matter)
166 171
     fireEvent.pointerUp(canvas);
167 172
 
168
-    expect(renderScene).toHaveBeenCalledTimes(7);
173
+    expect(renderScene).toHaveBeenCalledTimes(8);
169 174
     expect(h.state.selectionElement).toBeNull();
170 175
 
171 176
     expect(h.elements.length).toEqual(1);
@@ -184,6 +189,13 @@ describe("add element to the scene when pointer dragging long enough", () => {
184 189
 });
185 190
 
186 191
 describe("do not add element to the scene if size is too small", () => {
192
+  beforeAll(() => {
193
+    mockBoundingClientRect();
194
+  });
195
+  afterAll(() => {
196
+    restoreOriginalGetBoundingClientRect();
197
+  });
198
+
187 199
   it("rectangle", async () => {
188 200
     const { getByToolName, container } = await render(<ExcalidrawApp />);
189 201
     // select tool

+ 2
- 2
src/tests/move.test.tsx 查看文件

@@ -38,7 +38,7 @@ describe("move element", () => {
38 38
       fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
39 39
       fireEvent.pointerUp(canvas);
40 40
 
41
-      expect(renderScene).toHaveBeenCalledTimes(7);
41
+      expect(renderScene).toHaveBeenCalledTimes(8);
42 42
       expect(h.state.selectionElement).toBeNull();
43 43
       expect(h.elements.length).toEqual(1);
44 44
       expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
@@ -120,7 +120,7 @@ describe("duplicate element on move when ALT is clicked", () => {
120 120
       fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
121 121
       fireEvent.pointerUp(canvas);
122 122
 
123
-      expect(renderScene).toHaveBeenCalledTimes(7);
123
+      expect(renderScene).toHaveBeenCalledTimes(8);
124 124
       expect(h.state.selectionElement).toBeNull();
125 125
       expect(h.elements.length).toEqual(1);
126 126
       expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();

+ 16
- 3
src/tests/multiPointCreate.test.tsx 查看文件

@@ -1,6 +1,11 @@
1 1
 import React from "react";
2 2
 import ReactDOM from "react-dom";
3
-import { render, fireEvent } from "./test-utils";
3
+import {
4
+  render,
5
+  fireEvent,
6
+  mockBoundingClientRect,
7
+  restoreOriginalGetBoundingClientRect,
8
+} from "./test-utils";
4 9
 import ExcalidrawApp from "../excalidraw-app";
5 10
 import * as Renderer from "../renderer/renderScene";
6 11
 import { KEYS } from "../keys";
@@ -20,6 +25,14 @@ beforeEach(() => {
20 25
 const { h } = window;
21 26
 
22 27
 describe("remove shape in non linear elements", () => {
28
+  beforeAll(() => {
29
+    mockBoundingClientRect();
30
+  });
31
+
32
+  afterAll(() => {
33
+    restoreOriginalGetBoundingClientRect();
34
+  });
35
+
23 36
   it("rectangle", async () => {
24 37
     const { getByToolName, container } = await render(<ExcalidrawApp />);
25 38
     // select tool
@@ -88,7 +101,7 @@ describe("multi point mode in linear elements", () => {
88 101
     fireEvent.pointerUp(canvas);
89 102
     fireEvent.keyDown(document, { key: KEYS.ENTER });
90 103
 
91
-    expect(renderScene).toHaveBeenCalledTimes(13);
104
+    expect(renderScene).toHaveBeenCalledTimes(14);
92 105
     expect(h.elements.length).toEqual(1);
93 106
 
94 107
     const element = h.elements[0] as ExcalidrawLinearElement;
@@ -129,7 +142,7 @@ describe("multi point mode in linear elements", () => {
129 142
     fireEvent.pointerUp(canvas);
130 143
     fireEvent.keyDown(document, { key: KEYS.ENTER });
131 144
 
132
-    expect(renderScene).toHaveBeenCalledTimes(13);
145
+    expect(renderScene).toHaveBeenCalledTimes(14);
133 146
     expect(h.elements.length).toEqual(1);
134 147
 
135 148
     const element = h.elements[0] as ExcalidrawLinearElement;

+ 0
- 4
src/tests/packages/__snapshots__/utils.test.ts.snap 查看文件

@@ -32,7 +32,6 @@ Object {
32 32
   "exportWithDarkMode": false,
33 33
   "fileHandle": null,
34 34
   "gridSize": null,
35
-  "height": 768,
36 35
   "isBindingEnabled": true,
37 36
   "isLibraryOpen": false,
38 37
   "isLoading": false,
@@ -42,8 +41,6 @@ Object {
42 41
   "metadata": undefined,
43 42
   "multiElement": null,
44 43
   "name": "name",
45
-  "offsetLeft": 0,
46
-  "offsetTop": 0,
47 44
   "openMenu": null,
48 45
   "pasteDialog": Object {
49 46
     "data": null,
@@ -67,7 +64,6 @@ Object {
67 64
   "toastMessage": null,
68 65
   "viewBackgroundColor": "#ffffff",
69 66
   "viewModeEnabled": false,
70
-  "width": 1024,
71 67
   "zenModeEnabled": false,
72 68
   "zoom": Object {
73 69
     "translation": Object {

+ 1
- 0
src/tests/regressionTests.test.tsx 查看文件

@@ -76,6 +76,7 @@ beforeEach(async () => {
76 76
   finger2.reset();
77 77
 
78 78
   await render(<ExcalidrawApp />);
79
+  h.setState({ height: 768, width: 1024 });
79 80
 });
80 81
 
81 82
 afterEach(() => {

+ 14
- 24
src/tests/scroll.test.tsx 查看文件

@@ -1,5 +1,10 @@
1 1
 import React from "react";
2
-import { render, waitFor } from "./test-utils";
2
+import {
3
+  mockBoundingClientRect,
4
+  render,
5
+  restoreOriginalGetBoundingClientRect,
6
+  waitFor,
7
+} from "./test-utils";
3 8
 import Excalidraw from "../packages/excalidraw/index";
4 9
 import { API } from "./helpers/api";
5 10
 
@@ -7,34 +12,19 @@ const { h } = window;
7 12
 
8 13
 describe("appState", () => {
9 14
   it("scroll-to-content on init works with non-zero offsets", async () => {
10
-    const WIDTH = 600;
11
-    const HEIGHT = 700;
12
-    const OFFSET_LEFT = 200;
13
-    const OFFSET_TOP = 100;
15
+    const WIDTH = 200;
16
+    const HEIGHT = 100;
17
+    const OFFSET_LEFT = 20;
18
+    const OFFSET_TOP = 10;
14 19
 
15 20
     const ELEM_WIDTH = 100;
16 21
     const ELEM_HEIGHT = 60;
17 22
 
18
-    const originalGetBoundingClientRect =
19
-      global.window.HTMLDivElement.prototype.getBoundingClientRect;
20
-    // override getBoundingClientRect as by default it will always return all values as 0 even if customized in html
21
-    global.window.HTMLDivElement.prototype.getBoundingClientRect = () => ({
22
-      top: OFFSET_TOP,
23
-      left: OFFSET_LEFT,
24
-      bottom: 10,
25
-      right: 10,
26
-      width: 100,
27
-      x: 10,
28
-      y: 20,
29
-      height: 100,
30
-      toJSON: () => {},
31
-    });
23
+    mockBoundingClientRect();
32 24
 
33 25
     await render(
34 26
       <div>
35 27
         <Excalidraw
36
-          width={WIDTH}
37
-          height={HEIGHT}
38 28
           initialData={{
39 29
             elements: [
40 30
               API.createElement({
@@ -50,8 +40,8 @@ describe("appState", () => {
50 40
       </div>,
51 41
     );
52 42
     await waitFor(() => {
53
-      expect(h.state.width).toBe(WIDTH);
54
-      expect(h.state.height).toBe(HEIGHT);
43
+      expect(h.state.width).toBe(200);
44
+      expect(h.state.height).toBe(100);
55 45
       expect(h.state.offsetLeft).toBe(OFFSET_LEFT);
56 46
       expect(h.state.offsetTop).toBe(OFFSET_TOP);
57 47
 
@@ -59,6 +49,6 @@ describe("appState", () => {
59 49
       expect(h.state.scrollX).toBe(WIDTH / 2 - ELEM_WIDTH / 2);
60 50
       expect(h.state.scrollY).toBe(HEIGHT / 2 - ELEM_HEIGHT / 2);
61 51
     });
62
-    global.window.HTMLDivElement.prototype.getBoundingClientRect = originalGetBoundingClientRect;
52
+    restoreOriginalGetBoundingClientRect();
63 53
   });
64 54
 });

+ 14
- 1
src/tests/selection.test.tsx 查看文件

@@ -1,6 +1,11 @@
1 1
 import React from "react";
2 2
 import ReactDOM from "react-dom";
3
-import { render, fireEvent } from "./test-utils";
3
+import {
4
+  render,
5
+  fireEvent,
6
+  mockBoundingClientRect,
7
+  restoreOriginalGetBoundingClientRect,
8
+} from "./test-utils";
4 9
 import ExcalidrawApp from "../excalidraw-app";
5 10
 import * as Renderer from "../renderer/renderScene";
6 11
 import { KEYS } from "../keys";
@@ -77,6 +82,14 @@ describe("selection element", () => {
77 82
 });
78 83
 
79 84
 describe("select single element on the scene", () => {
85
+  beforeAll(() => {
86
+    mockBoundingClientRect();
87
+  });
88
+
89
+  afterAll(() => {
90
+    restoreOriginalGetBoundingClientRect();
91
+  });
92
+
80 93
   it("rectangle", async () => {
81 94
     const { getByToolName, container } = await render(<ExcalidrawApp />);
82 95
     const canvas = container.querySelector("canvas")!;

+ 22
- 0
src/tests/test-utils.ts 查看文件

@@ -102,3 +102,25 @@ const initLocalStorage = (data: ImportedDataState) => {
102 102
 export const updateSceneData = (data: SceneData) => {
103 103
   (window.collab as any).excalidrawAPI.updateScene(data);
104 104
 };
105
+
106
+const originalGetBoundingClientRect =
107
+  global.window.HTMLDivElement.prototype.getBoundingClientRect;
108
+
109
+export const mockBoundingClientRect = () => {
110
+  // override getBoundingClientRect as by default it will always return all values as 0 even if customized in html
111
+  global.window.HTMLDivElement.prototype.getBoundingClientRect = () => ({
112
+    top: 10,
113
+    left: 20,
114
+    bottom: 10,
115
+    right: 10,
116
+    width: 200,
117
+    x: 10,
118
+    y: 20,
119
+    height: 100,
120
+    toJSON: () => {},
121
+  });
122
+};
123
+
124
+export const restoreOriginalGetBoundingClientRect = () => {
125
+  global.window.HTMLDivElement.prototype.getBoundingClientRect = originalGetBoundingClientRect;
126
+};

+ 0
- 2
src/types.ts 查看文件

@@ -159,8 +159,6 @@ export type ExcalidrawAPIRefValue =
159 159
     };
160 160
 
161 161
 export interface ExcalidrawProps {
162
-  width?: number;
163
-  height?: number;
164 162
   onChange?: (
165 163
     elements: readonly ExcalidrawElement[],
166 164
     appState: AppState,

正在加载...
取消
保存