mirror of
https://github.com/excalidraw/excalidraw
synced 2025-07-25 13:58:22 +08:00

* 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>
72 lines
1.8 KiB
TypeScript
72 lines
1.8 KiB
TypeScript
import { ExcalidrawElement } from "../element/types";
|
|
import { getElementAbsoluteCoords } from "../element";
|
|
|
|
export function setSelection(
|
|
elements: readonly ExcalidrawElement[],
|
|
selection: ExcalidrawElement
|
|
) {
|
|
const [
|
|
selectionX1,
|
|
selectionY1,
|
|
selectionX2,
|
|
selectionY2
|
|
] = getElementAbsoluteCoords(selection);
|
|
elements.forEach(element => {
|
|
const [
|
|
elementX1,
|
|
elementY1,
|
|
elementX2,
|
|
elementY2
|
|
] = getElementAbsoluteCoords(element);
|
|
element.isSelected =
|
|
element.type !== "selection" &&
|
|
selectionX1 <= elementX1 &&
|
|
selectionY1 <= elementY1 &&
|
|
selectionX2 >= elementX2 &&
|
|
selectionY2 >= elementY2;
|
|
});
|
|
|
|
return elements;
|
|
}
|
|
|
|
export function clearSelection(elements: readonly ExcalidrawElement[]) {
|
|
const newElements = [...elements];
|
|
|
|
newElements.forEach(element => {
|
|
element.isSelected = false;
|
|
});
|
|
|
|
return newElements;
|
|
}
|
|
|
|
export function deleteSelectedElements(elements: readonly ExcalidrawElement[]) {
|
|
return elements.filter(el => !el.isSelected);
|
|
}
|
|
|
|
export function getSelectedIndices(elements: readonly ExcalidrawElement[]) {
|
|
const selectedIndices: number[] = [];
|
|
elements.forEach((element, index) => {
|
|
if (element.isSelected) {
|
|
selectedIndices.push(index);
|
|
}
|
|
});
|
|
return selectedIndices;
|
|
}
|
|
|
|
export const someElementIsSelected = (elements: readonly ExcalidrawElement[]) =>
|
|
elements.some(element => element.isSelected);
|
|
|
|
export function getSelectedAttribute<T>(
|
|
elements: readonly ExcalidrawElement[],
|
|
getAttribute: (element: ExcalidrawElement) => T
|
|
): T | null {
|
|
const attributes = Array.from(
|
|
new Set(
|
|
elements
|
|
.filter(element => element.isSelected)
|
|
.map(element => getAttribute(element))
|
|
)
|
|
);
|
|
return attributes.length === 1 ? attributes[0] : null;
|
|
}
|