|
|
|
@ -172,6 +172,7 @@ import {
|
|
|
|
|
ResolvablePromise,
|
|
|
|
|
resolvablePromise,
|
|
|
|
|
sceneCoordsToViewportCoords,
|
|
|
|
|
setCursor,
|
|
|
|
|
setCursorForShape,
|
|
|
|
|
tupleToCoors,
|
|
|
|
|
viewportCoordsToSceneCoords,
|
|
|
|
@ -1440,16 +1441,16 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
}
|
|
|
|
|
if (event.key === KEYS.SPACE && gesture.pointers.size === 0) {
|
|
|
|
|
isHoldingSpace = true;
|
|
|
|
|
document.documentElement.style.cursor = CURSOR_TYPE.GRABBING;
|
|
|
|
|
setCursor(this.canvas, CURSOR_TYPE.GRABBING);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
private onKeyUp = withBatchedUpdates((event: KeyboardEvent) => {
|
|
|
|
|
if (event.key === KEYS.SPACE) {
|
|
|
|
|
if (this.state.elementType === "selection") {
|
|
|
|
|
resetCursor();
|
|
|
|
|
resetCursor(this.canvas);
|
|
|
|
|
} else {
|
|
|
|
|
setCursorForShape(this.state.elementType);
|
|
|
|
|
setCursorForShape(this.canvas, this.state.elementType);
|
|
|
|
|
this.setState({
|
|
|
|
|
selectedElementIds: {},
|
|
|
|
|
selectedGroupIds: {},
|
|
|
|
@ -1475,7 +1476,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
|
|
|
|
|
private selectShapeTool(elementType: AppState["elementType"]) {
|
|
|
|
|
if (!isHoldingSpace) {
|
|
|
|
|
setCursorForShape(elementType);
|
|
|
|
|
setCursorForShape(this.canvas, elementType);
|
|
|
|
|
}
|
|
|
|
|
if (isToolIcon(document.activeElement)) {
|
|
|
|
|
document.activeElement.blur();
|
|
|
|
@ -1601,7 +1602,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
editingElement: null,
|
|
|
|
|
});
|
|
|
|
|
if (this.state.elementLocked) {
|
|
|
|
|
setCursorForShape(this.state.elementType);
|
|
|
|
|
setCursorForShape(this.canvas, this.state.elementType);
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
element,
|
|
|
|
@ -1782,7 +1783,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resetCursor();
|
|
|
|
|
resetCursor(this.canvas);
|
|
|
|
|
|
|
|
|
|
const { x: sceneX, y: sceneY } = viewportCoordsToSceneCoords(
|
|
|
|
|
event,
|
|
|
|
@ -1814,7 +1815,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resetCursor();
|
|
|
|
|
resetCursor(this.canvas);
|
|
|
|
|
|
|
|
|
|
if (!event[KEYS.CTRL_OR_CMD]) {
|
|
|
|
|
this.startTextEditing({
|
|
|
|
@ -1880,9 +1881,9 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
const isOverScrollBar = isPointerOverScrollBars.isOverEither;
|
|
|
|
|
if (!this.state.draggingElement && !this.state.multiElement) {
|
|
|
|
|
if (isOverScrollBar) {
|
|
|
|
|
resetCursor();
|
|
|
|
|
resetCursor(this.canvas);
|
|
|
|
|
} else {
|
|
|
|
|
setCursorForShape(this.state.elementType);
|
|
|
|
|
setCursorForShape(this.canvas, this.state.elementType);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1933,7 +1934,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
const { points, lastCommittedPoint } = multiElement;
|
|
|
|
|
const lastPoint = points[points.length - 1];
|
|
|
|
|
|
|
|
|
|
setCursorForShape(this.state.elementType);
|
|
|
|
|
setCursorForShape(this.canvas, this.state.elementType);
|
|
|
|
|
|
|
|
|
|
if (lastPoint === lastCommittedPoint) {
|
|
|
|
|
// if we haven't yet created a temp point and we're beyond commit-zone
|
|
|
|
@ -1950,7 +1951,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
points: [...points, [scenePointerX - rx, scenePointerY - ry]],
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
document.documentElement.style.cursor = CURSOR_TYPE.POINTER;
|
|
|
|
|
setCursor(this.canvas, CURSOR_TYPE.POINTER);
|
|
|
|
|
// in this branch, we're inside the commit zone, and no uncommitted
|
|
|
|
|
// point exists. Thus do nothing (don't add/remove points).
|
|
|
|
|
}
|
|
|
|
@ -1964,13 +1965,13 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
lastCommittedPoint[1],
|
|
|
|
|
) < LINE_CONFIRM_THRESHOLD
|
|
|
|
|
) {
|
|
|
|
|
document.documentElement.style.cursor = CURSOR_TYPE.POINTER;
|
|
|
|
|
setCursor(this.canvas, CURSOR_TYPE.POINTER);
|
|
|
|
|
mutateElement(multiElement, {
|
|
|
|
|
points: points.slice(0, -1),
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
if (isPathALoop(points, this.state.zoom.value)) {
|
|
|
|
|
document.documentElement.style.cursor = CURSOR_TYPE.POINTER;
|
|
|
|
|
setCursor(this.canvas, CURSOR_TYPE.POINTER);
|
|
|
|
|
}
|
|
|
|
|
// update last uncommitted point
|
|
|
|
|
mutateElement(multiElement, {
|
|
|
|
@ -2013,8 +2014,9 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
elementWithTransformHandleType &&
|
|
|
|
|
elementWithTransformHandleType.transformHandleType
|
|
|
|
|
) {
|
|
|
|
|
document.documentElement.style.cursor = getCursorForResizingElement(
|
|
|
|
|
elementWithTransformHandleType,
|
|
|
|
|
setCursor(
|
|
|
|
|
this.canvas,
|
|
|
|
|
getCursorForResizingElement(elementWithTransformHandleType),
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -2027,9 +2029,12 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
event.pointerType,
|
|
|
|
|
);
|
|
|
|
|
if (transformHandleType) {
|
|
|
|
|
document.documentElement.style.cursor = getCursorForResizingElement({
|
|
|
|
|
transformHandleType,
|
|
|
|
|
});
|
|
|
|
|
setCursor(
|
|
|
|
|
this.canvas,
|
|
|
|
|
getCursorForResizingElement({
|
|
|
|
|
transformHandleType,
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2039,11 +2044,12 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
scenePointer.y,
|
|
|
|
|
);
|
|
|
|
|
if (this.state.elementType === "text") {
|
|
|
|
|
document.documentElement.style.cursor = isTextElement(hitElement)
|
|
|
|
|
? CURSOR_TYPE.TEXT
|
|
|
|
|
: CURSOR_TYPE.CROSSHAIR;
|
|
|
|
|
setCursor(
|
|
|
|
|
this.canvas,
|
|
|
|
|
isTextElement(hitElement) ? CURSOR_TYPE.TEXT : CURSOR_TYPE.CROSSHAIR,
|
|
|
|
|
);
|
|
|
|
|
} else if (isOverScrollBar) {
|
|
|
|
|
document.documentElement.style.cursor = CURSOR_TYPE.AUTO;
|
|
|
|
|
setCursor(this.canvas, CURSOR_TYPE.AUTO);
|
|
|
|
|
} else if (
|
|
|
|
|
hitElement ||
|
|
|
|
|
this.isHittingCommonBoundingBoxOfSelectedElements(
|
|
|
|
@ -2051,9 +2057,9 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
selectedElements,
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
document.documentElement.style.cursor = CURSOR_TYPE.MOVE;
|
|
|
|
|
setCursor(this.canvas, CURSOR_TYPE.MOVE);
|
|
|
|
|
} else {
|
|
|
|
|
document.documentElement.style.cursor = CURSOR_TYPE.AUTO;
|
|
|
|
|
setCursor(this.canvas, CURSOR_TYPE.AUTO);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -2226,7 +2232,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
let nextPastePrevented = false;
|
|
|
|
|
const isLinux = /Linux/.test(window.navigator.platform);
|
|
|
|
|
|
|
|
|
|
document.documentElement.style.cursor = CURSOR_TYPE.GRABBING;
|
|
|
|
|
setCursor(this.canvas, CURSOR_TYPE.GRABBING);
|
|
|
|
|
let { clientX: lastX, clientY: lastY } = event;
|
|
|
|
|
const onPointerMove = withBatchedUpdates((event: PointerEvent) => {
|
|
|
|
|
const deltaX = lastX - event.clientX;
|
|
|
|
@ -2278,7 +2284,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
lastPointerUp = null;
|
|
|
|
|
isPanning = false;
|
|
|
|
|
if (!isHoldingSpace) {
|
|
|
|
|
setCursorForShape(this.state.elementType);
|
|
|
|
|
setCursorForShape(this.canvas, this.state.elementType);
|
|
|
|
|
}
|
|
|
|
|
this.setState({
|
|
|
|
|
cursorButton: "up",
|
|
|
|
@ -2394,7 +2400,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
|
|
|
|
|
const onPointerUp = withBatchedUpdates(() => {
|
|
|
|
|
isDraggingScrollBar = false;
|
|
|
|
|
setCursorForShape(this.state.elementType);
|
|
|
|
|
setCursorForShape(this.canvas, this.state.elementType);
|
|
|
|
|
lastPointerUp = null;
|
|
|
|
|
this.setState({
|
|
|
|
|
cursorButton: "up",
|
|
|
|
@ -2457,9 +2463,12 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
if (pointerDownState.resize.handleType) {
|
|
|
|
|
document.documentElement.style.cursor = getCursorForResizingElement({
|
|
|
|
|
transformHandleType: pointerDownState.resize.handleType,
|
|
|
|
|
});
|
|
|
|
|
setCursor(
|
|
|
|
|
this.canvas,
|
|
|
|
|
getCursorForResizingElement({
|
|
|
|
|
transformHandleType: pointerDownState.resize.handleType,
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
pointerDownState.resize.isResizing = true;
|
|
|
|
|
pointerDownState.resize.offset = tupleToCoors(
|
|
|
|
|
getResizeOffsetXY(
|
|
|
|
@ -2624,7 +2633,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
insertAtParentCenter: !event.altKey,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
resetCursor();
|
|
|
|
|
resetCursor(this.canvas);
|
|
|
|
|
if (!this.state.elementLocked) {
|
|
|
|
|
this.setState({
|
|
|
|
|
elementType: "selection",
|
|
|
|
@ -2681,7 +2690,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
mutateElement(multiElement, {
|
|
|
|
|
lastCommittedPoint: multiElement.points[multiElement.points.length - 1],
|
|
|
|
|
});
|
|
|
|
|
document.documentElement.style.cursor = CURSOR_TYPE.POINTER;
|
|
|
|
|
setCursor(this.canvas, CURSOR_TYPE.POINTER);
|
|
|
|
|
} else {
|
|
|
|
|
const [gridX, gridY] = getGridPoint(
|
|
|
|
|
pointerDownState.origin.x,
|
|
|
|
@ -3216,7 +3225,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
}
|
|
|
|
|
this.setState({ suggestedBindings: [], startBoundElement: null });
|
|
|
|
|
if (!elementLocked && elementType !== "draw") {
|
|
|
|
|
resetCursor();
|
|
|
|
|
resetCursor(this.canvas);
|
|
|
|
|
this.setState((prevState) => ({
|
|
|
|
|
draggingElement: null,
|
|
|
|
|
elementType: "selection",
|
|
|
|
@ -3387,7 +3396,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!elementLocked && elementType !== "draw") {
|
|
|
|
|
resetCursor();
|
|
|
|
|
resetCursor(this.canvas);
|
|
|
|
|
this.setState({
|
|
|
|
|
draggingElement: null,
|
|
|
|
|
suggestedBindings: [],
|
|
|
|
|