feat: extend line snapping to creation
This commit is contained in:
parent
5403fa8a0d
commit
07640dd756
@ -107,6 +107,7 @@ export * from "./ShapeCache";
|
|||||||
export * from "./shapes";
|
export * from "./shapes";
|
||||||
export * from "./showSelectedShapeActions";
|
export * from "./showSelectedShapeActions";
|
||||||
export * from "./sizeHelpers";
|
export * from "./sizeHelpers";
|
||||||
|
export * from "./snapping";
|
||||||
export * from "./sortElements";
|
export * from "./sortElements";
|
||||||
export * from "./store";
|
export * from "./store";
|
||||||
export * from "./textElement";
|
export * from "./textElement";
|
||||||
|
@ -20,6 +20,11 @@ import {
|
|||||||
tupleToCoors,
|
tupleToCoors,
|
||||||
} from "@excalidraw/common";
|
} from "@excalidraw/common";
|
||||||
|
|
||||||
|
import {
|
||||||
|
type SnapLine,
|
||||||
|
snapLinearElementPoint,
|
||||||
|
} from "@excalidraw/element/snapping";
|
||||||
|
|
||||||
import type { Store } from "@excalidraw/element";
|
import type { Store } from "@excalidraw/element";
|
||||||
|
|
||||||
import type { Radians } from "@excalidraw/math";
|
import type { Radians } from "@excalidraw/math";
|
||||||
@ -33,11 +38,6 @@ import type {
|
|||||||
Zoom,
|
Zoom,
|
||||||
} from "@excalidraw/excalidraw/types";
|
} from "@excalidraw/excalidraw/types";
|
||||||
|
|
||||||
import {
|
|
||||||
SnapLine,
|
|
||||||
snapLinearElementPoint,
|
|
||||||
} from "@excalidraw/excalidraw/snapping";
|
|
||||||
|
|
||||||
import type { Mutable } from "@excalidraw/common/utility-types";
|
import type { Mutable } from "@excalidraw/common/utility-types";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -388,6 +388,7 @@ export class LinearElementEditor {
|
|||||||
app,
|
app,
|
||||||
event,
|
event,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
|
{ includeSelfPoints: true }, // Include element's own points for snapping when editing
|
||||||
);
|
);
|
||||||
|
|
||||||
_snapLines = snapLines;
|
_snapLines = snapLines;
|
||||||
@ -1045,10 +1046,12 @@ export class LinearElementEditor {
|
|||||||
return {
|
return {
|
||||||
...appState.editingLinearElement,
|
...appState.editingLinearElement,
|
||||||
lastUncommittedPoint: null,
|
lastUncommittedPoint: null,
|
||||||
|
snapLines: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let newPoint: LocalPoint;
|
let newPoint: LocalPoint;
|
||||||
|
let snapLines: SnapLine[] = [];
|
||||||
|
|
||||||
if (shouldRotateWithDiscreteAngle(event) && points.length >= 2) {
|
if (shouldRotateWithDiscreteAngle(event) && points.length >= 2) {
|
||||||
const lastCommittedPoint = points[points.length - 2];
|
const lastCommittedPoint = points[points.length - 2];
|
||||||
@ -1066,11 +1069,32 @@ export class LinearElementEditor {
|
|||||||
height + lastCommittedPoint[1],
|
height + lastCommittedPoint[1],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
const originalPointerX =
|
||||||
|
scenePointerX - appState.editingLinearElement.pointerOffset.x;
|
||||||
|
const originalPointerY =
|
||||||
|
scenePointerY - appState.editingLinearElement.pointerOffset.y;
|
||||||
|
|
||||||
|
const { snapOffset, snapLines: snappingLines } = snapLinearElementPoint(
|
||||||
|
app.scene.getNonDeletedElements(),
|
||||||
|
element,
|
||||||
|
points.length - 1,
|
||||||
|
{ x: originalPointerX, y: originalPointerY },
|
||||||
|
app,
|
||||||
|
event,
|
||||||
|
elementsMap,
|
||||||
|
{ includeSelfPoints: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
snapLines = snappingLines;
|
||||||
|
|
||||||
|
const snappedPointerX = originalPointerX + snapOffset.x;
|
||||||
|
const snappedPointerY = originalPointerY + snapOffset.y;
|
||||||
|
|
||||||
newPoint = LinearElementEditor.createPointAt(
|
newPoint = LinearElementEditor.createPointAt(
|
||||||
element,
|
element,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
scenePointerX - appState.editingLinearElement.pointerOffset.x,
|
snappedPointerX,
|
||||||
scenePointerY - appState.editingLinearElement.pointerOffset.y,
|
snappedPointerY,
|
||||||
event[KEYS.CTRL_OR_CMD] || isElbowArrow(element)
|
event[KEYS.CTRL_OR_CMD] || isElbowArrow(element)
|
||||||
? null
|
? null
|
||||||
: app.getEffectiveGridSize(),
|
: app.getEffectiveGridSize(),
|
||||||
@ -1096,6 +1120,7 @@ export class LinearElementEditor {
|
|||||||
return {
|
return {
|
||||||
...appState.editingLinearElement,
|
...appState.editingLinearElement,
|
||||||
lastUncommittedPoint: element.points[element.points.length - 1],
|
lastUncommittedPoint: element.points[element.points.length - 1],
|
||||||
|
snapLines,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
isCloseTo,
|
||||||
pointFrom,
|
pointFrom,
|
||||||
pointRotateRads,
|
pointRotateRads,
|
||||||
rangeInclusive,
|
rangeInclusive,
|
||||||
@ -13,7 +14,11 @@ import {
|
|||||||
getDraggedElementsBounds,
|
getDraggedElementsBounds,
|
||||||
getElementAbsoluteCoords,
|
getElementAbsoluteCoords,
|
||||||
} from "@excalidraw/element";
|
} from "@excalidraw/element";
|
||||||
import { isBoundToContainer, isFrameLikeElement, isElbowArrow } from "@excalidraw/element";
|
import {
|
||||||
|
isBoundToContainer,
|
||||||
|
isFrameLikeElement,
|
||||||
|
isElbowArrow,
|
||||||
|
} from "@excalidraw/element";
|
||||||
|
|
||||||
import { getMaximumGroups } from "@excalidraw/element";
|
import { getMaximumGroups } from "@excalidraw/element";
|
||||||
|
|
||||||
@ -37,7 +42,7 @@ import type {
|
|||||||
AppClassProperties,
|
AppClassProperties,
|
||||||
AppState,
|
AppState,
|
||||||
KeyboardModifiersObject,
|
KeyboardModifiersObject,
|
||||||
} from "./types";
|
} from "@excalidraw/excalidraw/types";
|
||||||
|
|
||||||
const SNAP_DISTANCE = 8;
|
const SNAP_DISTANCE = 8;
|
||||||
|
|
||||||
@ -200,12 +205,8 @@ export const getLinearElementPoints = (
|
|||||||
): GlobalPoint[] => {
|
): GlobalPoint[] => {
|
||||||
const { dragOffset, excludePointIndex } = options;
|
const { dragOffset, excludePointIndex } = options;
|
||||||
|
|
||||||
// Only process linear elements and freedraw
|
// Only process linear elements
|
||||||
if (
|
if (element.type !== "line" && element.type !== "arrow") {
|
||||||
element.type !== "line" &&
|
|
||||||
element.type !== "arrow" &&
|
|
||||||
element.type !== "freedraw"
|
|
||||||
) {
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,11 +293,13 @@ export const getElementsCorners = (
|
|||||||
const halfHeight = (y2 - y1) / 2;
|
const halfHeight = (y2 - y1) / 2;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(element.type === "line" || element.type === "arrow" || element.type === "freedraw") &&
|
(element.type === "line" || element.type === "arrow") &&
|
||||||
!boundingBoxCorners
|
!boundingBoxCorners
|
||||||
) {
|
) {
|
||||||
// For linear elements, use actual points instead of bounding box
|
// For linear elements, use actual points instead of bounding box
|
||||||
const linearPoints = getLinearElementPoints(element, elementsMap, { dragOffset });
|
const linearPoints = getLinearElementPoints(element, elementsMap, {
|
||||||
|
dragOffset,
|
||||||
|
});
|
||||||
result = linearPoints;
|
result = linearPoints;
|
||||||
} else if (
|
} else if (
|
||||||
(element.type === "diamond" || element.type === "ellipse") &&
|
(element.type === "diamond" || element.type === "ellipse") &&
|
||||||
@ -710,7 +713,12 @@ export const getReferenceSnapPointsForLinearElementPoint = (
|
|||||||
editingPointIndex: number,
|
editingPointIndex: number,
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
elementsMap: ElementsMap,
|
elementsMap: ElementsMap,
|
||||||
|
options: {
|
||||||
|
includeSelfPoints?: boolean;
|
||||||
|
} = {},
|
||||||
) => {
|
) => {
|
||||||
|
const { includeSelfPoints = false } = options;
|
||||||
|
|
||||||
// Get all reference elements (excluding the one being edited)
|
// Get all reference elements (excluding the one being edited)
|
||||||
const referenceElements = getReferenceElements(
|
const referenceElements = getReferenceElements(
|
||||||
elements,
|
elements,
|
||||||
@ -719,11 +727,13 @@ export const getReferenceSnapPointsForLinearElementPoint = (
|
|||||||
elementsMap,
|
elementsMap,
|
||||||
);
|
);
|
||||||
|
|
||||||
let allSnapPoints: GlobalPoint[] = [];
|
const allSnapPoints: GlobalPoint[] = [];
|
||||||
|
|
||||||
// Add snap points from all reference elements
|
// Add snap points from all reference elements
|
||||||
const referenceGroups = getMaximumGroups(referenceElements, elementsMap)
|
const referenceGroups = getMaximumGroups(
|
||||||
.filter(
|
referenceElements,
|
||||||
|
elementsMap,
|
||||||
|
).filter(
|
||||||
(elementsGroup) =>
|
(elementsGroup) =>
|
||||||
!(elementsGroup.length === 1 && isBoundToContainer(elementsGroup[0])),
|
!(elementsGroup.length === 1 && isBoundToContainer(elementsGroup[0])),
|
||||||
);
|
);
|
||||||
@ -732,8 +742,13 @@ export const getReferenceSnapPointsForLinearElementPoint = (
|
|||||||
allSnapPoints.push(...getElementsCorners(elementGroup, elementsMap));
|
allSnapPoints.push(...getElementsCorners(elementGroup, elementsMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: We do not include other points from the same linear element
|
// Include other points from the same linear element when creating new points or in editing mode
|
||||||
// as reference points when dragging a point, per user feedback
|
if (includeSelfPoints) {
|
||||||
|
const elementPoints = getLinearElementPoints(editingElement, elementsMap, {
|
||||||
|
excludePointIndex: editingPointIndex >= 0 ? editingPointIndex : undefined,
|
||||||
|
});
|
||||||
|
allSnapPoints.push(...elementPoints);
|
||||||
|
}
|
||||||
|
|
||||||
return allSnapPoints;
|
return allSnapPoints;
|
||||||
};
|
};
|
||||||
@ -746,9 +761,14 @@ export const snapLinearElementPoint = (
|
|||||||
app: AppClassProperties,
|
app: AppClassProperties,
|
||||||
event: KeyboardModifiersObject,
|
event: KeyboardModifiersObject,
|
||||||
elementsMap: ElementsMap,
|
elementsMap: ElementsMap,
|
||||||
|
options: {
|
||||||
|
includeSelfPoints?: boolean;
|
||||||
|
} = {},
|
||||||
) => {
|
) => {
|
||||||
if (!isSnappingEnabled({ app, event, selectedElements: [editingElement] }) ||
|
if (
|
||||||
isElbowArrow(editingElement)) {
|
!isSnappingEnabled({ app, event, selectedElements: [editingElement] }) ||
|
||||||
|
isElbowArrow(editingElement)
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
snapOffset: { x: 0, y: 0 },
|
snapOffset: { x: 0, y: 0 },
|
||||||
snapLines: [],
|
snapLines: [],
|
||||||
@ -771,10 +791,14 @@ export const snapLinearElementPoint = (
|
|||||||
editingPointIndex,
|
editingPointIndex,
|
||||||
app.state,
|
app.state,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
|
options,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create a snap point for the current point position
|
// Create a snap point for the current point position
|
||||||
const currentPointGlobal = pointFrom<GlobalPoint>(pointPosition.x, pointPosition.y);
|
const currentPointGlobal = pointFrom<GlobalPoint>(
|
||||||
|
pointPosition.x,
|
||||||
|
pointPosition.y,
|
||||||
|
);
|
||||||
|
|
||||||
// Find nearest snaps
|
// Find nearest snaps
|
||||||
for (const referencePoint of referenceSnapPoints) {
|
for (const referencePoint of referenceSnapPoints) {
|
||||||
@ -822,7 +846,7 @@ export const snapLinearElementPoint = (
|
|||||||
// Recalculate snap lines with the snapped position
|
// Recalculate snap lines with the snapped position
|
||||||
const snappedPosition = pointFrom<GlobalPoint>(
|
const snappedPosition = pointFrom<GlobalPoint>(
|
||||||
pointPosition.x + snapOffset.x,
|
pointPosition.x + snapOffset.x,
|
||||||
pointPosition.y + snapOffset.y
|
pointPosition.y + snapOffset.y,
|
||||||
);
|
);
|
||||||
|
|
||||||
const snappedSnapsX: Snaps = [];
|
const snappedSnapsX: Snaps = [];
|
||||||
@ -834,7 +858,7 @@ export const snapLinearElementPoint = (
|
|||||||
const offsetY = referencePoint[1] - snappedPosition[1];
|
const offsetY = referencePoint[1] - snappedPosition[1];
|
||||||
|
|
||||||
// Only include points that we're actually snapping to
|
// Only include points that we're actually snapping to
|
||||||
if (Math.abs(offsetX) < 0.01) { // essentially zero after snapping
|
if (isCloseTo(offsetX, 0, 0.01)) {
|
||||||
snappedSnapsX.push({
|
snappedSnapsX.push({
|
||||||
type: "point",
|
type: "point",
|
||||||
points: [snappedPosition, referencePoint],
|
points: [snappedPosition, referencePoint],
|
||||||
@ -842,7 +866,7 @@ export const snapLinearElementPoint = (
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.abs(offsetY) < 0.01) { // essentially zero after snapping
|
if (isCloseTo(offsetY, 0, 0.01)) {
|
||||||
snappedSnapsY.push({
|
snappedSnapsY.push({
|
||||||
type: "point",
|
type: "point",
|
||||||
points: [snappedPosition, referencePoint],
|
points: [snappedPosition, referencePoint],
|
@ -292,6 +292,20 @@ import { Scene } from "@excalidraw/element";
|
|||||||
|
|
||||||
import { Store, CaptureUpdateAction } from "@excalidraw/element";
|
import { Store, CaptureUpdateAction } from "@excalidraw/element";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getSnapLinesAtPointer,
|
||||||
|
snapDraggedElements,
|
||||||
|
isActiveToolNonLinearSnappable,
|
||||||
|
snapNewElement,
|
||||||
|
snapResizingElements,
|
||||||
|
isSnappingEnabled,
|
||||||
|
getVisibleGaps,
|
||||||
|
getReferenceSnapPoints,
|
||||||
|
SnapCache,
|
||||||
|
isGridModeEnabled,
|
||||||
|
snapLinearElementPoint,
|
||||||
|
} from "@excalidraw/element";
|
||||||
|
|
||||||
import type { ElementUpdate } from "@excalidraw/element";
|
import type { ElementUpdate } from "@excalidraw/element";
|
||||||
|
|
||||||
import type { LocalPoint, Radians } from "@excalidraw/math";
|
import type { LocalPoint, Radians } from "@excalidraw/math";
|
||||||
@ -424,18 +438,6 @@ import {
|
|||||||
import { Fonts } from "../fonts";
|
import { Fonts } from "../fonts";
|
||||||
import { editorJotaiStore, type WritableAtom } from "../editor-jotai";
|
import { editorJotaiStore, type WritableAtom } from "../editor-jotai";
|
||||||
import { ImageSceneDataError } from "../errors";
|
import { ImageSceneDataError } from "../errors";
|
||||||
import {
|
|
||||||
getSnapLinesAtPointer,
|
|
||||||
snapDraggedElements,
|
|
||||||
isActiveToolNonLinearSnappable,
|
|
||||||
snapNewElement,
|
|
||||||
snapResizingElements,
|
|
||||||
isSnappingEnabled,
|
|
||||||
getVisibleGaps,
|
|
||||||
getReferenceSnapPoints,
|
|
||||||
SnapCache,
|
|
||||||
isGridModeEnabled,
|
|
||||||
} from "../snapping";
|
|
||||||
import { convertToExcalidrawElements } from "../data/transform";
|
import { convertToExcalidrawElements } from "../data/transform";
|
||||||
import { Renderer } from "../scene/Renderer";
|
import { Renderer } from "../scene/Renderer";
|
||||||
import {
|
import {
|
||||||
@ -5874,9 +5876,13 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
const scenePointer = viewportCoordsToSceneCoords(event, this.state);
|
const scenePointer = viewportCoordsToSceneCoords(event, this.state);
|
||||||
const { x: scenePointerX, y: scenePointerY } = scenePointer;
|
const { x: scenePointerX, y: scenePointerY } = scenePointer;
|
||||||
|
|
||||||
|
// snap origin of the new element that's to be created
|
||||||
if (
|
if (
|
||||||
!this.state.newElement &&
|
!this.state.newElement &&
|
||||||
isActiveToolNonLinearSnappable(this.state.activeTool.type)
|
(isActiveToolNonLinearSnappable(this.state.activeTool.type) ||
|
||||||
|
((this.state.activeTool.type === "line" ||
|
||||||
|
this.state.activeTool.type === "arrow") &&
|
||||||
|
this.state.currentItemArrowType !== ARROW_TYPE.elbow))
|
||||||
) {
|
) {
|
||||||
const { originOffset, snapLines } = getSnapLinesAtPointer(
|
const { originOffset, snapLines } = getSnapLinesAtPointer(
|
||||||
this.scene.getNonDeletedElements(),
|
this.scene.getNonDeletedElements(),
|
||||||
@ -6047,12 +6053,32 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
gridX,
|
gridX,
|
||||||
gridY,
|
gridY,
|
||||||
));
|
));
|
||||||
|
} else if (!isElbowArrow(multiElement)) {
|
||||||
|
const { snapOffset, snapLines } = snapLinearElementPoint(
|
||||||
|
this.scene.getNonDeletedElements(),
|
||||||
|
multiElement,
|
||||||
|
points.length - 1,
|
||||||
|
{ x: gridX, y: gridY },
|
||||||
|
this,
|
||||||
|
event,
|
||||||
|
this.scene.getNonDeletedElementsMap(),
|
||||||
|
{ includeSelfPoints: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
const snappedGridX = gridX + snapOffset.x;
|
||||||
|
const snappedGridY = gridY + snapOffset.y;
|
||||||
|
|
||||||
|
dxFromLastCommitted = snappedGridX - rx - lastCommittedX;
|
||||||
|
dyFromLastCommitted = snappedGridY - ry - lastCommittedY;
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
snapLines,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPathALoop(points, this.state.zoom.value)) {
|
if (isPathALoop(points, this.state.zoom.value)) {
|
||||||
setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER);
|
setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update last uncommitted point
|
// update last uncommitted point
|
||||||
this.scene.mutateElement(
|
this.scene.mutateElement(
|
||||||
multiElement,
|
multiElement,
|
||||||
@ -8778,6 +8804,26 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
let dx = gridX - newElement.x;
|
let dx = gridX - newElement.x;
|
||||||
let dy = gridY - newElement.y;
|
let dy = gridY - newElement.y;
|
||||||
|
|
||||||
|
// snap a two-point line/arrow as well
|
||||||
|
if (!isElbowArrow(newElement)) {
|
||||||
|
const { snapOffset, snapLines } = snapLinearElementPoint(
|
||||||
|
this.scene.getNonDeletedElements(),
|
||||||
|
newElement,
|
||||||
|
points.length - 1,
|
||||||
|
{ x: gridX, y: gridY },
|
||||||
|
this,
|
||||||
|
event,
|
||||||
|
this.scene.getNonDeletedElementsMap(),
|
||||||
|
{ includeSelfPoints: true },
|
||||||
|
);
|
||||||
|
const snappedGridX = gridX + snapOffset.x;
|
||||||
|
const snappedGridY = gridY + snapOffset.y;
|
||||||
|
dx = snappedGridX - newElement.x;
|
||||||
|
dy = snappedGridY - newElement.y;
|
||||||
|
|
||||||
|
this.setState({ snapLines });
|
||||||
|
}
|
||||||
|
|
||||||
if (shouldRotateWithDiscreteAngle(event) && points.length === 2) {
|
if (shouldRotateWithDiscreteAngle(event) && points.length === 2) {
|
||||||
({ width: dx, height: dy } = getLockedLinearCursorAlignSize(
|
({ width: dx, height: dy } = getLockedLinearCursorAlignSize(
|
||||||
newElement.x,
|
newElement.x,
|
||||||
|
@ -10,11 +10,10 @@ import {
|
|||||||
|
|
||||||
import { getShortcutKey } from "@excalidraw/common";
|
import { getShortcutKey } from "@excalidraw/common";
|
||||||
|
|
||||||
import { isNodeInFlowchart } from "@excalidraw/element";
|
import { isNodeInFlowchart, isGridModeEnabled } from "@excalidraw/element";
|
||||||
|
|
||||||
import { t } from "../i18n";
|
import { t } from "../i18n";
|
||||||
import { isEraserActive } from "../appState";
|
import { isEraserActive } from "../appState";
|
||||||
import { isGridModeEnabled } from "../snapping";
|
|
||||||
|
|
||||||
import "./HintViewer.scss";
|
import "./HintViewer.scss";
|
||||||
|
|
||||||
|
@ -12,10 +12,11 @@ import { frameAndChildrenSelectedTogether } from "@excalidraw/element";
|
|||||||
|
|
||||||
import { elementsAreInSameGroup } from "@excalidraw/element";
|
import { elementsAreInSameGroup } from "@excalidraw/element";
|
||||||
|
|
||||||
|
import { isGridModeEnabled } from "@excalidraw/element";
|
||||||
|
|
||||||
import type { NonDeletedExcalidrawElement } from "@excalidraw/element/types";
|
import type { NonDeletedExcalidrawElement } from "@excalidraw/element/types";
|
||||||
|
|
||||||
import { t } from "../../i18n";
|
import { t } from "../../i18n";
|
||||||
import { isGridModeEnabled } from "../../snapping";
|
|
||||||
import { useExcalidrawAppState, useExcalidrawSetAppState } from "../App";
|
import { useExcalidrawAppState, useExcalidrawSetAppState } from "../App";
|
||||||
import { Island } from "../Island";
|
import { Island } from "../Island";
|
||||||
import { CloseIcon } from "../icons";
|
import { CloseIcon } from "../icons";
|
||||||
|
@ -2,7 +2,8 @@ import { pointFrom, type GlobalPoint, type LocalPoint } from "@excalidraw/math";
|
|||||||
|
|
||||||
import { THEME } from "@excalidraw/common";
|
import { THEME } from "@excalidraw/common";
|
||||||
|
|
||||||
import type { PointSnapLine, PointerSnapLine } from "../snapping";
|
import type { PointSnapLine, PointerSnapLine } from "@excalidraw/element";
|
||||||
|
|
||||||
import type { InteractiveCanvasAppState } from "../types";
|
import type { InteractiveCanvasAppState } from "../types";
|
||||||
|
|
||||||
const SNAP_COLOR_LIGHT = "#ff6b6b";
|
const SNAP_COLOR_LIGHT = "#ff6b6b";
|
||||||
|
@ -11,6 +11,8 @@ import type { LinearElementEditor } from "@excalidraw/element";
|
|||||||
|
|
||||||
import type { MaybeTransformHandleType } from "@excalidraw/element";
|
import type { MaybeTransformHandleType } from "@excalidraw/element";
|
||||||
|
|
||||||
|
import type { SnapLine } from "@excalidraw/element";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
PointerType,
|
PointerType,
|
||||||
ExcalidrawLinearElement,
|
ExcalidrawLinearElement,
|
||||||
@ -56,7 +58,6 @@ import type App from "./components/App";
|
|||||||
import type Library from "./data/library";
|
import type Library from "./data/library";
|
||||||
import type { FileSystemHandle } from "./data/filesystem";
|
import type { FileSystemHandle } from "./data/filesystem";
|
||||||
import type { ContextMenuItems } from "./components/ContextMenu";
|
import type { ContextMenuItems } from "./components/ContextMenu";
|
||||||
import type { SnapLine } from "./snapping";
|
|
||||||
import type { ImportedDataState } from "./data/types";
|
import type { ImportedDataState } from "./data/types";
|
||||||
|
|
||||||
import type { Language } from "./i18n";
|
import type { Language } from "./i18n";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user