mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Moved selection in element, refactor common
This commit is contained in:
parent
e7a0a7e0b7
commit
dfd48c221c
19 changed files with 67 additions and 110 deletions
|
@ -4,6 +4,8 @@ import {
|
||||||
type LocalPoint,
|
type LocalPoint,
|
||||||
} from "@excalidraw/math";
|
} from "@excalidraw/math";
|
||||||
|
|
||||||
|
import type { NullableGridSize } from "@excalidraw/excalidraw/types";
|
||||||
|
|
||||||
export const getSizeFromPoints = (
|
export const getSizeFromPoints = (
|
||||||
points: readonly (GlobalPoint | LocalPoint)[],
|
points: readonly (GlobalPoint | LocalPoint)[],
|
||||||
) => {
|
) => {
|
||||||
|
@ -61,3 +63,18 @@ export const rescalePoints = <Point extends GlobalPoint | LocalPoint>(
|
||||||
|
|
||||||
return nextPoints;
|
return nextPoints;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: Rounding this point causes some shake when free drawing
|
||||||
|
export const getGridPoint = (
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
gridSize: NullableGridSize,
|
||||||
|
): [number, number] => {
|
||||||
|
if (gridSize) {
|
||||||
|
return [
|
||||||
|
Math.round(x / gridSize) * gridSize,
|
||||||
|
Math.round(y / gridSize) * gridSize,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [x, y];
|
||||||
|
};
|
||||||
|
|
|
@ -1206,59 +1206,3 @@ export const escapeDoubleQuotes = (str: string) => {
|
||||||
|
|
||||||
export const castArray = <T>(value: T | T[]): T[] =>
|
export const castArray = <T>(value: T | T[]): T[] =>
|
||||||
Array.isArray(value) ? value : [value];
|
Array.isArray(value) ? value : [value];
|
||||||
|
|
||||||
// TODO_SEP: perhaps could be refactored away
|
|
||||||
|
|
||||||
// TODO: Rounding this point causes some shake when free drawing
|
|
||||||
export const getGridPoint = (
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
gridSize: NullableGridSize,
|
|
||||||
): [number, number] => {
|
|
||||||
if (gridSize) {
|
|
||||||
return [
|
|
||||||
Math.round(x / gridSize) * gridSize,
|
|
||||||
Math.round(y / gridSize) * gridSize,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return [x, y];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const elementsAreInSameGroup = (
|
|
||||||
elements: readonly ExcalidrawElement[],
|
|
||||||
) => {
|
|
||||||
const allGroups = elements.flatMap((element) => element.groupIds);
|
|
||||||
const groupCount = new Map<string, number>();
|
|
||||||
let maxGroup = 0;
|
|
||||||
|
|
||||||
for (const group of allGroups) {
|
|
||||||
groupCount.set(group, (groupCount.get(group) ?? 0) + 1);
|
|
||||||
if (groupCount.get(group)! > maxGroup) {
|
|
||||||
maxGroup = groupCount.get(group)!;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return maxGroup === elements.length;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const isInGroup = (element: NonDeletedExcalidrawElement) => {
|
|
||||||
return element.groupIds.length > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getNewGroupIdsForDuplication = (
|
|
||||||
groupIds: ExcalidrawElement["groupIds"],
|
|
||||||
editingGroupId: AppState["editingGroupId"],
|
|
||||||
mapper: (groupId: GroupId) => GroupId,
|
|
||||||
) => {
|
|
||||||
const copy = [...groupIds];
|
|
||||||
const positionOfEditingGroupId = editingGroupId
|
|
||||||
? groupIds.indexOf(editingGroupId)
|
|
||||||
: -1;
|
|
||||||
const endIndex =
|
|
||||||
positionOfEditingGroupId > -1 ? positionOfEditingGroupId : groupIds.length;
|
|
||||||
for (let index = 0; index < endIndex; index++) {
|
|
||||||
copy[index] = mapper(copy[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return copy;
|
|
||||||
};
|
|
||||||
|
|
|
@ -12,7 +12,9 @@ import type {
|
||||||
OrderedExcalidrawElement,
|
OrderedExcalidrawElement,
|
||||||
} from "@excalidraw/element/types";
|
} from "@excalidraw/element/types";
|
||||||
|
|
||||||
import { InvalidFractionalIndexError } from "../../excalidraw/errors";
|
export class InvalidFractionalIndexError extends Error {
|
||||||
|
public code = "ELEMENT_HAS_INVALID_INDEX" as const;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Envisioned relation between array order and fractional indices:
|
* Envisioned relation between array order and fractional indices:
|
||||||
|
|
|
@ -5,11 +5,6 @@ import {
|
||||||
elementsOverlappingBBox,
|
elementsOverlappingBBox,
|
||||||
} from "@excalidraw/utils";
|
} from "@excalidraw/utils";
|
||||||
|
|
||||||
import {
|
|
||||||
getElementsWithinSelection,
|
|
||||||
getSelectedElements,
|
|
||||||
} from "@excalidraw/excalidraw/scene";
|
|
||||||
|
|
||||||
import { getElementAbsoluteCoords, isTextElement } from "@excalidraw/element";
|
import { getElementAbsoluteCoords, isTextElement } from "@excalidraw/element";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
@ -31,6 +26,7 @@ import type {
|
||||||
|
|
||||||
import type { ReadonlySetLike } from "@excalidraw/common/utility-types";
|
import type { ReadonlySetLike } from "@excalidraw/common/utility-types";
|
||||||
|
|
||||||
|
import { getElementsWithinSelection, getSelectedElements } from "./selection";
|
||||||
import { getElementsInGroup, selectGroupsFromGivenElements } from "./groups";
|
import { getElementsInGroup, selectGroupsFromGivenElements } from "./groups";
|
||||||
|
|
||||||
import { getElementLineSegments, getCommonBounds } from "./bounds";
|
import { getElementLineSegments, getCommonBounds } from "./bounds";
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
import { getBoundTextElement } from "@excalidraw/element/textElement";
|
import { getBoundTextElement } from "@excalidraw/element/textElement";
|
||||||
|
|
||||||
import { getSelectedElements } from "@excalidraw/excalidraw/scene";
|
|
||||||
import { makeNextSelectedElementIds } from "@excalidraw/excalidraw/scene/selection";
|
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
GroupId,
|
GroupId,
|
||||||
ExcalidrawElement,
|
ExcalidrawElement,
|
||||||
|
@ -19,6 +16,8 @@ import type {
|
||||||
} from "@excalidraw/excalidraw/types";
|
} from "@excalidraw/excalidraw/types";
|
||||||
import type { Mutable } from "@excalidraw/common/utility-types";
|
import type { Mutable } from "@excalidraw/common/utility-types";
|
||||||
|
|
||||||
|
import { makeNextSelectedElementIds, getSelectedElements } from "./selection";
|
||||||
|
|
||||||
export const selectGroup = (
|
export const selectGroup = (
|
||||||
groupId: GroupId,
|
groupId: GroupId,
|
||||||
appState: InteractiveCanvasAppState,
|
appState: InteractiveCanvasAppState,
|
||||||
|
|
|
@ -11,7 +11,6 @@ import {
|
||||||
import {
|
import {
|
||||||
MIN_FONT_SIZE,
|
MIN_FONT_SIZE,
|
||||||
SHIFT_LOCKING_ANGLE,
|
SHIFT_LOCKING_ANGLE,
|
||||||
isInGroup,
|
|
||||||
rescalePoints,
|
rescalePoints,
|
||||||
getFontString,
|
getFontString,
|
||||||
} from "@excalidraw/common";
|
} from "@excalidraw/common";
|
||||||
|
@ -59,6 +58,8 @@ import {
|
||||||
isTextElement,
|
isTextElement,
|
||||||
} from "./typeChecks";
|
} from "./typeChecks";
|
||||||
|
|
||||||
|
import { isInGroup } from "./groups";
|
||||||
|
|
||||||
import type { BoundingBox } from "./bounds";
|
import type { BoundingBox } from "./bounds";
|
||||||
import type {
|
import type {
|
||||||
MaybeTransformHandleType,
|
MaybeTransformHandleType,
|
||||||
|
|
|
@ -1,17 +1,3 @@
|
||||||
import {
|
|
||||||
getElementAbsoluteCoords,
|
|
||||||
getElementBounds,
|
|
||||||
} from "@excalidraw/element/bounds";
|
|
||||||
import { isElementInViewport } from "@excalidraw/element/sizeHelpers";
|
|
||||||
import {
|
|
||||||
isBoundToContainer,
|
|
||||||
isFrameLikeElement,
|
|
||||||
} from "@excalidraw/element/typeChecks";
|
|
||||||
import {
|
|
||||||
elementOverlapsWithFrame,
|
|
||||||
getContainingFrame,
|
|
||||||
getFrameChildren,
|
|
||||||
} from "@excalidraw/element/frame";
|
|
||||||
import { isShallowEqual } from "@excalidraw/common";
|
import { isShallowEqual } from "@excalidraw/common";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
@ -21,7 +7,19 @@ import type {
|
||||||
NonDeletedExcalidrawElement,
|
NonDeletedExcalidrawElement,
|
||||||
} from "@excalidraw/element/types";
|
} from "@excalidraw/element/types";
|
||||||
|
|
||||||
import type { AppState, InteractiveCanvasAppState } from "../types";
|
import type {
|
||||||
|
AppState,
|
||||||
|
InteractiveCanvasAppState,
|
||||||
|
} from "@excalidraw/excalidraw/types";
|
||||||
|
|
||||||
|
import { getElementAbsoluteCoords, getElementBounds } from "./bounds";
|
||||||
|
import { isElementInViewport } from "./sizeHelpers";
|
||||||
|
import { isBoundToContainer, isFrameLikeElement } from "./typeChecks";
|
||||||
|
import {
|
||||||
|
elementOverlapsWithFrame,
|
||||||
|
getContainingFrame,
|
||||||
|
getFrameChildren,
|
||||||
|
} from "./frame";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frames and their containing elements are not to be selected at the same time.
|
* Frames and their containing elements are not to be selected at the same time.
|
|
@ -1,7 +1,7 @@
|
||||||
import { getSelectedElements } from "@excalidraw/excalidraw/scene";
|
|
||||||
|
|
||||||
import type { UIAppState } from "@excalidraw/excalidraw/types";
|
import type { UIAppState } from "@excalidraw/excalidraw/types";
|
||||||
|
|
||||||
|
import { getSelectedElements } from "./selection";
|
||||||
|
|
||||||
import type { NonDeletedExcalidrawElement } from "./types";
|
import type { NonDeletedExcalidrawElement } from "./types";
|
||||||
|
|
||||||
export const showSelectedShapeActions = (
|
export const showSelectedShapeActions = (
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { makeNextSelectedElementIds } from "./selection";
|
import { makeNextSelectedElementIds } from "../src/selection";
|
||||||
|
|
||||||
describe("makeNextSelectedElementIds", () => {
|
describe("makeNextSelectedElementIds", () => {
|
||||||
const _makeNextSelectedElementIds = (
|
const _makeNextSelectedElementIds = (
|
|
@ -39,6 +39,11 @@ import {
|
||||||
getElementsInGroup,
|
getElementsInGroup,
|
||||||
} from "@excalidraw/element/groups";
|
} from "@excalidraw/element/groups";
|
||||||
|
|
||||||
|
import {
|
||||||
|
excludeElementsInFramesFromSelection,
|
||||||
|
getSelectedElements,
|
||||||
|
} from "@excalidraw/element/selection";
|
||||||
|
|
||||||
import type { ExcalidrawElement } from "@excalidraw/element/types";
|
import type { ExcalidrawElement } from "@excalidraw/element/types";
|
||||||
|
|
||||||
import { ToolButton } from "../components/ToolButton";
|
import { ToolButton } from "../components/ToolButton";
|
||||||
|
@ -46,10 +51,6 @@ import { DuplicateIcon } from "../components/icons";
|
||||||
|
|
||||||
import { t } from "../i18n";
|
import { t } from "../i18n";
|
||||||
import { isSomeElementSelected } from "../scene";
|
import { isSomeElementSelected } from "../scene";
|
||||||
import {
|
|
||||||
excludeElementsInFramesFromSelection,
|
|
||||||
getSelectedElements,
|
|
||||||
} from "../scene/selection";
|
|
||||||
import { CaptureUpdateAction } from "../store";
|
import { CaptureUpdateAction } from "../store";
|
||||||
|
|
||||||
import { register } from "./register";
|
import { register } from "./register";
|
||||||
|
|
|
@ -289,6 +289,11 @@ import {
|
||||||
syncMovedIndices,
|
syncMovedIndices,
|
||||||
} from "@excalidraw/element/fractionalIndex";
|
} from "@excalidraw/element/fractionalIndex";
|
||||||
|
|
||||||
|
import {
|
||||||
|
excludeElementsInFramesFromSelection,
|
||||||
|
makeNextSelectedElementIds,
|
||||||
|
} from "@excalidraw/element/selection";
|
||||||
|
|
||||||
import type { LocalPoint, Radians } from "@excalidraw/math";
|
import type { LocalPoint, Radians } from "@excalidraw/math";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
@ -420,10 +425,6 @@ import {
|
||||||
|
|
||||||
import { Fonts } from "../fonts";
|
import { Fonts } from "../fonts";
|
||||||
import { getLineHeight } from "../fonts/FontMetadata";
|
import { getLineHeight } from "../fonts/FontMetadata";
|
||||||
import {
|
|
||||||
excludeElementsInFramesFromSelection,
|
|
||||||
makeNextSelectedElementIds,
|
|
||||||
} from "../scene/selection";
|
|
||||||
import { editorJotaiStore } from "../editor-jotai";
|
import { editorJotaiStore } from "../editor-jotai";
|
||||||
import { ImageSceneDataError } from "../errors";
|
import { ImageSceneDataError } from "../errors";
|
||||||
import {
|
import {
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { isInGroup } from "@excalidraw/common";
|
|
||||||
|
|
||||||
import { degreesToRadians, radiansToDegrees } from "@excalidraw/math";
|
import { degreesToRadians, radiansToDegrees } from "@excalidraw/math";
|
||||||
|
|
||||||
import { mutateElement } from "@excalidraw/element/mutateElement";
|
import { mutateElement } from "@excalidraw/element/mutateElement";
|
||||||
|
@ -7,6 +5,8 @@ import { mutateElement } from "@excalidraw/element/mutateElement";
|
||||||
import { getBoundTextElement } from "@excalidraw/element/textElement";
|
import { getBoundTextElement } from "@excalidraw/element/textElement";
|
||||||
import { isArrowElement } from "@excalidraw/element/typeChecks";
|
import { isArrowElement } from "@excalidraw/element/typeChecks";
|
||||||
|
|
||||||
|
import { isInGroup } from "@excalidraw/element/groups";
|
||||||
|
|
||||||
import type { Degrees } from "@excalidraw/math";
|
import type { Degrees } from "@excalidraw/math";
|
||||||
|
|
||||||
import type { ExcalidrawElement } from "@excalidraw/element/types";
|
import type { ExcalidrawElement } from "@excalidraw/element/types";
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { isInGroup } from "@excalidraw/common";
|
|
||||||
|
|
||||||
import { isTextElement, redrawTextBoundingBox } from "@excalidraw/element";
|
import { isTextElement, redrawTextBoundingBox } from "@excalidraw/element";
|
||||||
import { mutateElement } from "@excalidraw/element/mutateElement";
|
import { mutateElement } from "@excalidraw/element/mutateElement";
|
||||||
import { getBoundTextElement } from "@excalidraw/element/textElement";
|
import { getBoundTextElement } from "@excalidraw/element/textElement";
|
||||||
import { hasBoundTextElement } from "@excalidraw/element/typeChecks";
|
import { hasBoundTextElement } from "@excalidraw/element/typeChecks";
|
||||||
|
|
||||||
|
import { isInGroup } from "@excalidraw/element/groups";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ExcalidrawElement,
|
ExcalidrawElement,
|
||||||
ExcalidrawTextElement,
|
ExcalidrawTextElement,
|
||||||
|
|
|
@ -5,7 +5,9 @@ import { vi } from "vitest";
|
||||||
|
|
||||||
import { getCommonBounds, isTextElement } from "@excalidraw/element";
|
import { getCommonBounds, isTextElement } from "@excalidraw/element";
|
||||||
|
|
||||||
import { setDateTimeForTests, isInGroup, reseed } from "@excalidraw/common";
|
import { setDateTimeForTests, reseed } from "@excalidraw/common";
|
||||||
|
|
||||||
|
import { isInGroup } from "@excalidraw/element/groups";
|
||||||
|
|
||||||
import type { Degrees } from "@excalidraw/math";
|
import type { Degrees } from "@excalidraw/math";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { isInGroup } from "@excalidraw/common";
|
|
||||||
import { pointFrom, pointRotateRads } from "@excalidraw/math";
|
import { pointFrom, pointRotateRads } from "@excalidraw/math";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -16,6 +15,7 @@ import {
|
||||||
import {
|
import {
|
||||||
getSelectedGroupIds,
|
getSelectedGroupIds,
|
||||||
getElementsInGroup,
|
getElementsInGroup,
|
||||||
|
isInGroup,
|
||||||
} from "@excalidraw/element/groups";
|
} from "@excalidraw/element/groups";
|
||||||
|
|
||||||
import type { Radians } from "@excalidraw/math";
|
import type { Radians } from "@excalidraw/math";
|
||||||
|
|
|
@ -33,10 +33,6 @@ export class ImageSceneDataError extends Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InvalidFractionalIndexError extends Error {
|
|
||||||
public code = "ELEMENT_HAS_INVALID_INDEX" as const;
|
|
||||||
}
|
|
||||||
|
|
||||||
type WorkerErrorCodes = "WORKER_URL_NOT_DEFINED" | "WORKER_IN_THE_MAIN_CHUNK";
|
type WorkerErrorCodes = "WORKER_URL_NOT_DEFINED" | "WORKER_IN_THE_MAIN_CHUNK";
|
||||||
|
|
||||||
export class WorkerUrlNotDefinedError extends Error {
|
export class WorkerUrlNotDefinedError extends Error {
|
||||||
|
|
|
@ -17,6 +17,8 @@ import {
|
||||||
validateFractionalIndices,
|
validateFractionalIndices,
|
||||||
} from "@excalidraw/element/fractionalIndex";
|
} from "@excalidraw/element/fractionalIndex";
|
||||||
|
|
||||||
|
import { getSelectedElements } from "@excalidraw/element/selection";
|
||||||
|
|
||||||
import type { LinearElementEditor } from "@excalidraw/element/linearElementEditor";
|
import type { LinearElementEditor } from "@excalidraw/element/linearElementEditor";
|
||||||
import type {
|
import type {
|
||||||
ExcalidrawElement,
|
ExcalidrawElement,
|
||||||
|
@ -32,8 +34,6 @@ import type {
|
||||||
|
|
||||||
import type { Assert, SameType } from "@excalidraw/common/utility-types";
|
import type { Assert, SameType } from "@excalidraw/common/utility-types";
|
||||||
|
|
||||||
import { getSelectedElements } from "./selection";
|
|
||||||
|
|
||||||
import type { AppState } from "../types";
|
import type { AppState } from "../types";
|
||||||
|
|
||||||
type ElementIdKey = InstanceType<typeof LinearElementEditor>["elementId"];
|
type ElementIdKey = InstanceType<typeof LinearElementEditor>["elementId"];
|
||||||
|
|
|
@ -4,7 +4,7 @@ export {
|
||||||
getCommonAttributeOfSelectedElements,
|
getCommonAttributeOfSelectedElements,
|
||||||
getSelectedElements,
|
getSelectedElements,
|
||||||
getTargetElements,
|
getTargetElements,
|
||||||
} from "./selection";
|
} from "@excalidraw/element/selection";
|
||||||
export { calculateScrollCenter } from "./scroll";
|
export { calculateScrollCenter } from "./scroll";
|
||||||
export {
|
export {
|
||||||
hasBackground,
|
hasBackground,
|
||||||
|
|
|
@ -20,6 +20,11 @@ import {
|
||||||
|
|
||||||
import { getMaximumGroups } from "@excalidraw/element/groups";
|
import { getMaximumGroups } from "@excalidraw/element/groups";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getSelectedElements,
|
||||||
|
getVisibleAndNonSelectedElements,
|
||||||
|
} from "@excalidraw/element/selection";
|
||||||
|
|
||||||
import type { InclusiveRange } from "@excalidraw/math";
|
import type { InclusiveRange } from "@excalidraw/math";
|
||||||
|
|
||||||
import type { Bounds } from "@excalidraw/element/bounds";
|
import type { Bounds } from "@excalidraw/element/bounds";
|
||||||
|
@ -30,11 +35,6 @@ import type {
|
||||||
NonDeletedExcalidrawElement,
|
NonDeletedExcalidrawElement,
|
||||||
} from "@excalidraw/element/types";
|
} from "@excalidraw/element/types";
|
||||||
|
|
||||||
import {
|
|
||||||
getSelectedElements,
|
|
||||||
getVisibleAndNonSelectedElements,
|
|
||||||
} from "./scene/selection";
|
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
AppClassProperties,
|
AppClassProperties,
|
||||||
AppState,
|
AppState,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue