Make all operations on elements array immutable (#283)

* Make scene functions return array instead of mutate array

- Not all functions were changes; so the given argument was a new array to some

* Make data restoration functions immutable

- Make mutations in App component

* Make history actions immutable

* Fix an issue in change property that was causing elements to be removed

* mark elements params as readonly & remove unnecessary copying

* Make `clearSelection` return a new array

* Perform Id comparisons instead of reference comparisons in onDoubleClick

* Allow deselecting items with SHIFT key

- Refactor hit detection code

* Fix a bug in element selection and revert drag functionality

Co-authored-by: David Luzar <luzar.david@gmail.com>
This commit is contained in:
Gasim Gasimzada 2020-01-09 19:22:04 +04:00 committed by David Luzar
parent 1ea72e9134
commit 862231da4f
11 changed files with 239 additions and 157 deletions

View file

@ -2,7 +2,7 @@ import { ExcalidrawElement } from "../element/types";
import { getElementAbsoluteCoords } from "../element";
export function setSelection(
elements: ExcalidrawElement[],
elements: readonly ExcalidrawElement[],
selection: ExcalidrawElement
) {
const [
@ -25,23 +25,25 @@ export function setSelection(
selectionX2 >= elementX2 &&
selectionY2 >= elementY2;
});
return elements;
}
export function clearSelection(elements: ExcalidrawElement[]) {
elements.forEach(element => {
export function clearSelection(elements: readonly ExcalidrawElement[]) {
const newElements = [...elements];
newElements.forEach(element => {
element.isSelected = false;
});
return newElements;
}
export function deleteSelectedElements(elements: ExcalidrawElement[]) {
for (let i = elements.length - 1; i >= 0; --i) {
if (elements[i].isSelected) {
elements.splice(i, 1);
}
}
export function deleteSelectedElements(elements: readonly ExcalidrawElement[]) {
return elements.filter(el => !el.isSelected);
}
export function getSelectedIndices(elements: ExcalidrawElement[]) {
export function getSelectedIndices(elements: readonly ExcalidrawElement[]) {
const selectedIndices: number[] = [];
elements.forEach((element, index) => {
if (element.isSelected) {
@ -51,11 +53,11 @@ export function getSelectedIndices(elements: ExcalidrawElement[]) {
return selectedIndices;
}
export const someElementIsSelected = (elements: ExcalidrawElement[]) =>
export const someElementIsSelected = (elements: readonly ExcalidrawElement[]) =>
elements.some(element => element.isSelected);
export function getSelectedAttribute<T>(
elements: ExcalidrawElement[],
elements: readonly ExcalidrawElement[],
getAttribute: (element: ExcalidrawElement) => T
): T | null {
const attributes = Array.from(