select single element on cmd-click (#2087)
This commit is contained in:
parent
b8f8bc2e32
commit
4c2d34ffd7
@ -157,6 +157,7 @@ import {
|
|||||||
isElementInGroup,
|
isElementInGroup,
|
||||||
getSelectedGroupIdForElement,
|
getSelectedGroupIdForElement,
|
||||||
getElementsInGroup,
|
getElementsInGroup,
|
||||||
|
editGroupForSelectedElement,
|
||||||
} from "../groups";
|
} from "../groups";
|
||||||
import { Library } from "../data/library";
|
import { Library } from "../data/library";
|
||||||
import Scene from "../scene/Scene";
|
import Scene from "../scene/Scene";
|
||||||
@ -939,10 +940,9 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
private onTapEnd = (event: TouchEvent) => {
|
private onTapEnd = (event: TouchEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (event.touches.length > 0) {
|
if (event.touches.length > 0) {
|
||||||
const { previousSelectedElementIds } = this.state;
|
|
||||||
this.setState({
|
this.setState({
|
||||||
previousSelectedElementIds: {},
|
previousSelectedElementIds: {},
|
||||||
selectedElementIds: previousSelectedElementIds,
|
selectedElementIds: this.state.previousSelectedElementIds,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1617,10 +1617,9 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
|
|
||||||
private onGestureEnd = withBatchedUpdates((event: GestureEvent) => {
|
private onGestureEnd = withBatchedUpdates((event: GestureEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const { previousSelectedElementIds } = this.state;
|
|
||||||
this.setState({
|
this.setState({
|
||||||
previousSelectedElementIds: {},
|
previousSelectedElementIds: {},
|
||||||
selectedElementIds: previousSelectedElementIds,
|
selectedElementIds: this.state.previousSelectedElementIds,
|
||||||
});
|
});
|
||||||
gesture.initialScale = null;
|
gesture.initialScale = null;
|
||||||
});
|
});
|
||||||
@ -1904,11 +1903,13 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
|
|
||||||
resetCursor();
|
resetCursor();
|
||||||
|
|
||||||
|
if (!event[KEYS.CTRL_OR_CMD]) {
|
||||||
this.startTextEditing({
|
this.startTextEditing({
|
||||||
sceneX,
|
sceneX,
|
||||||
sceneY,
|
sceneY,
|
||||||
insertAtParentCenter: !event.altKey,
|
insertAtParentCenter: !event.altKey,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private handleCanvasPointerMove = (
|
private handleCanvasPointerMove = (
|
||||||
@ -2485,7 +2486,9 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns whether the pointer event has been completely handled
|
/**
|
||||||
|
* @returns whether the pointer event has been completely handled
|
||||||
|
*/
|
||||||
private handleSelectionOnPointerDown = (
|
private handleSelectionOnPointerDown = (
|
||||||
event: React.PointerEvent<HTMLCanvasElement>,
|
event: React.PointerEvent<HTMLCanvasElement>,
|
||||||
pointerDownState: PointerDownState,
|
pointerDownState: PointerDownState,
|
||||||
@ -2587,6 +2590,16 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
|
|
||||||
// If we click on something
|
// If we click on something
|
||||||
if (hitElement != null) {
|
if (hitElement != null) {
|
||||||
|
// on CMD/CTRL, drill down to hit element regardless of groups etc.
|
||||||
|
if (event[KEYS.CTRL_OR_CMD]) {
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...editGroupForSelectedElement(prevState, hitElement),
|
||||||
|
previousSelectedElementIds: this.state.selectedElementIds,
|
||||||
|
}));
|
||||||
|
// mark as not completely handled so as to allow dragging etc.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// deselect if item is selected
|
// deselect if item is selected
|
||||||
// if shift is not clicked, this will always return true
|
// if shift is not clicked, this will always return true
|
||||||
// otherwise, it will trigger selection based on current
|
// otherwise, it will trigger selection based on current
|
||||||
@ -2619,7 +2632,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
...prevState,
|
...prevState,
|
||||||
selectedElementIds: {
|
selectedElementIds: {
|
||||||
...prevState.selectedElementIds,
|
...prevState.selectedElementIds,
|
||||||
[hitElement!.id]: true,
|
[hitElement.id]: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
this.scene.getElements(),
|
this.scene.getElements(),
|
||||||
@ -2630,9 +2643,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { selectedElementIds } = this.state;
|
|
||||||
this.setState({
|
this.setState({
|
||||||
previousSelectedElementIds: selectedElementIds,
|
previousSelectedElementIds: this.state.selectedElementIds,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3530,10 +3542,9 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
? prevState.editingGroupId
|
? prevState.editingGroupId
|
||||||
: null,
|
: null,
|
||||||
}));
|
}));
|
||||||
const { selectedElementIds } = this.state;
|
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedElementIds: {},
|
selectedElementIds: {},
|
||||||
previousSelectedElementIds: selectedElementIds,
|
previousSelectedElementIds: this.state.selectedElementIds,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +86,20 @@ export function selectGroupsForSelectedElements(
|
|||||||
return nextAppState;
|
return nextAppState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const editGroupForSelectedElement = (
|
||||||
|
appState: AppState,
|
||||||
|
element: NonDeleted<ExcalidrawElement>,
|
||||||
|
): AppState => {
|
||||||
|
return {
|
||||||
|
...appState,
|
||||||
|
editingGroupId: element.groupIds.length ? element.groupIds[0] : null,
|
||||||
|
selectedGroupIds: {},
|
||||||
|
selectedElementIds: {
|
||||||
|
[element.id]: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export function isElementInGroup(element: ExcalidrawElement, groupId: string) {
|
export function isElementInGroup(element: ExcalidrawElement, groupId: string) {
|
||||||
return element.groupIds.includes(groupId);
|
return element.groupIds.includes(groupId);
|
||||||
}
|
}
|
||||||
|
@ -878,6 +878,757 @@ exports[`given element A and group of elements B and given both are selected whe
|
|||||||
|
|
||||||
exports[`given element A and group of elements B and given both are selected when user shift-clicks on B, on pointer up only element A should be selected: [end of test] number of renders 1`] = `22`;
|
exports[`given element A and group of elements B and given both are selected when user shift-clicks on B, on pointer up only element A should be selected: [end of test] number of renders 1`] = `22`;
|
||||||
|
|
||||||
|
exports[`regression tests Cmd/Ctrl-click exclusively select element under pointer: [end of test] appState 1`] = `
|
||||||
|
Object {
|
||||||
|
"appearance": "light",
|
||||||
|
"collaborators": Map {},
|
||||||
|
"currentItemBackgroundColor": "transparent",
|
||||||
|
"currentItemFillStyle": "hachure",
|
||||||
|
"currentItemFontFamily": 1,
|
||||||
|
"currentItemFontSize": 20,
|
||||||
|
"currentItemLinearStrokeSharpness": "round",
|
||||||
|
"currentItemOpacity": 100,
|
||||||
|
"currentItemRoughness": 1,
|
||||||
|
"currentItemStrokeColor": "#000000",
|
||||||
|
"currentItemStrokeSharpness": "sharp",
|
||||||
|
"currentItemStrokeStyle": "solid",
|
||||||
|
"currentItemStrokeWidth": 1,
|
||||||
|
"currentItemTextAlign": "left",
|
||||||
|
"cursorButton": "up",
|
||||||
|
"cursorX": 0,
|
||||||
|
"cursorY": 0,
|
||||||
|
"draggingElement": null,
|
||||||
|
"editingElement": null,
|
||||||
|
"editingGroupId": "id10",
|
||||||
|
"editingLinearElement": null,
|
||||||
|
"elementLocked": false,
|
||||||
|
"elementType": "selection",
|
||||||
|
"errorMessage": null,
|
||||||
|
"exportBackground": true,
|
||||||
|
"gridSize": null,
|
||||||
|
"height": 768,
|
||||||
|
"isBindingEnabled": true,
|
||||||
|
"isCollaborating": false,
|
||||||
|
"isLibraryOpen": false,
|
||||||
|
"isLoading": false,
|
||||||
|
"isResizing": false,
|
||||||
|
"isRotating": false,
|
||||||
|
"lastPointerDownWith": "mouse",
|
||||||
|
"multiElement": null,
|
||||||
|
"name": "Untitled-201933152653",
|
||||||
|
"offsetLeft": 0,
|
||||||
|
"offsetTop": 0,
|
||||||
|
"openMenu": null,
|
||||||
|
"previousSelectedElementIds": Object {},
|
||||||
|
"resizingElement": null,
|
||||||
|
"scrollX": 0,
|
||||||
|
"scrollY": 0,
|
||||||
|
"scrolledOutside": false,
|
||||||
|
"selectedElementIds": Object {
|
||||||
|
"id12": true,
|
||||||
|
"id7": true,
|
||||||
|
},
|
||||||
|
"selectedGroupIds": Object {},
|
||||||
|
"selectionElement": null,
|
||||||
|
"shouldAddWatermark": false,
|
||||||
|
"shouldCacheIgnoreZoom": false,
|
||||||
|
"showShortcutsDialog": false,
|
||||||
|
"startBoundElement": null,
|
||||||
|
"suggestedBindings": Array [],
|
||||||
|
"username": "",
|
||||||
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"width": 1024,
|
||||||
|
"zenModeEnabled": false,
|
||||||
|
"zoom": 1,
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`regression tests Cmd/Ctrl-click exclusively select element under pointer: [end of test] element 0 1`] = `
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
"id10",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id0",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 337897,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 4,
|
||||||
|
"versionNonce": 493213705,
|
||||||
|
"width": 10,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`regression tests Cmd/Ctrl-click exclusively select element under pointer: [end of test] element 1 1`] = `
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
"id10",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id1",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 449462985,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 4,
|
||||||
|
"versionNonce": 915032327,
|
||||||
|
"width": 10,
|
||||||
|
"x": 30,
|
||||||
|
"y": 30,
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`regression tests Cmd/Ctrl-click exclusively select element under pointer: [end of test] element 2 1`] = `
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id10",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id7",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 400692809,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 3,
|
||||||
|
"versionNonce": 81784553,
|
||||||
|
"width": 10,
|
||||||
|
"x": 60,
|
||||||
|
"y": 60,
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`regression tests Cmd/Ctrl-click exclusively select element under pointer: [end of test] history 1`] = `
|
||||||
|
Object {
|
||||||
|
"recording": false,
|
||||||
|
"redoStack": Array [],
|
||||||
|
"stateHistory": Array [
|
||||||
|
Object {
|
||||||
|
"appState": Object {
|
||||||
|
"editingGroupId": null,
|
||||||
|
"editingLinearElement": null,
|
||||||
|
"name": "Untitled-201933152653",
|
||||||
|
"selectedElementIds": Object {
|
||||||
|
"id0": true,
|
||||||
|
},
|
||||||
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
},
|
||||||
|
"elements": Array [
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id0",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 337897,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 2,
|
||||||
|
"versionNonce": 1278240551,
|
||||||
|
"width": 10,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"appState": Object {
|
||||||
|
"editingGroupId": null,
|
||||||
|
"editingLinearElement": null,
|
||||||
|
"name": "Untitled-201933152653",
|
||||||
|
"selectedElementIds": Object {
|
||||||
|
"id1": true,
|
||||||
|
},
|
||||||
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
},
|
||||||
|
"elements": Array [
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id0",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 337897,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 2,
|
||||||
|
"versionNonce": 1278240551,
|
||||||
|
"width": 10,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id1",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 449462985,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 2,
|
||||||
|
"versionNonce": 453191,
|
||||||
|
"width": 10,
|
||||||
|
"x": 30,
|
||||||
|
"y": 30,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"appState": Object {
|
||||||
|
"editingGroupId": null,
|
||||||
|
"editingLinearElement": null,
|
||||||
|
"name": "Untitled-201933152653",
|
||||||
|
"selectedElementIds": Object {
|
||||||
|
"id0": true,
|
||||||
|
"id1": true,
|
||||||
|
"id2": true,
|
||||||
|
"id3": true,
|
||||||
|
},
|
||||||
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
},
|
||||||
|
"elements": Array [
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id0",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 337897,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 3,
|
||||||
|
"versionNonce": 1150084233,
|
||||||
|
"width": 10,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id1",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 449462985,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 3,
|
||||||
|
"versionNonce": 1116226695,
|
||||||
|
"width": 10,
|
||||||
|
"x": 30,
|
||||||
|
"y": 30,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"appState": Object {
|
||||||
|
"editingGroupId": "id4",
|
||||||
|
"editingLinearElement": null,
|
||||||
|
"name": "Untitled-201933152653",
|
||||||
|
"selectedElementIds": Object {
|
||||||
|
"id0": true,
|
||||||
|
"id5": true,
|
||||||
|
},
|
||||||
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
},
|
||||||
|
"elements": Array [
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id0",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 337897,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 3,
|
||||||
|
"versionNonce": 1150084233,
|
||||||
|
"width": 10,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id1",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 449462985,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 3,
|
||||||
|
"versionNonce": 1116226695,
|
||||||
|
"width": 10,
|
||||||
|
"x": 30,
|
||||||
|
"y": 30,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"appState": Object {
|
||||||
|
"editingGroupId": null,
|
||||||
|
"editingLinearElement": null,
|
||||||
|
"name": "Untitled-201933152653",
|
||||||
|
"selectedElementIds": Object {
|
||||||
|
"id7": true,
|
||||||
|
},
|
||||||
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
},
|
||||||
|
"elements": Array [
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id0",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 337897,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 3,
|
||||||
|
"versionNonce": 1150084233,
|
||||||
|
"width": 10,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id1",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 449462985,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 3,
|
||||||
|
"versionNonce": 1116226695,
|
||||||
|
"width": 10,
|
||||||
|
"x": 30,
|
||||||
|
"y": 30,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id7",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 400692809,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 2,
|
||||||
|
"versionNonce": 1604849351,
|
||||||
|
"width": 10,
|
||||||
|
"x": 60,
|
||||||
|
"y": 60,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"appState": Object {
|
||||||
|
"editingGroupId": null,
|
||||||
|
"editingLinearElement": null,
|
||||||
|
"name": "Untitled-201933152653",
|
||||||
|
"selectedElementIds": Object {
|
||||||
|
"id0": true,
|
||||||
|
"id1": true,
|
||||||
|
"id7": true,
|
||||||
|
"id8": true,
|
||||||
|
"id9": true,
|
||||||
|
},
|
||||||
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
},
|
||||||
|
"elements": Array [
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
"id10",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id0",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 337897,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 4,
|
||||||
|
"versionNonce": 493213705,
|
||||||
|
"width": 10,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
"id10",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id1",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 449462985,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 4,
|
||||||
|
"versionNonce": 915032327,
|
||||||
|
"width": 10,
|
||||||
|
"x": 30,
|
||||||
|
"y": 30,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id10",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id7",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 400692809,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 3,
|
||||||
|
"versionNonce": 81784553,
|
||||||
|
"width": 10,
|
||||||
|
"x": 60,
|
||||||
|
"y": 60,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"appState": Object {
|
||||||
|
"editingGroupId": "id4",
|
||||||
|
"editingLinearElement": null,
|
||||||
|
"name": "Untitled-201933152653",
|
||||||
|
"selectedElementIds": Object {
|
||||||
|
"id0": true,
|
||||||
|
"id11": true,
|
||||||
|
},
|
||||||
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
},
|
||||||
|
"elements": Array [
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
"id10",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id0",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 337897,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 4,
|
||||||
|
"versionNonce": 493213705,
|
||||||
|
"width": 10,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
"id10",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id1",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 449462985,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 4,
|
||||||
|
"versionNonce": 915032327,
|
||||||
|
"width": 10,
|
||||||
|
"x": 30,
|
||||||
|
"y": 30,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id10",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id7",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 400692809,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 3,
|
||||||
|
"versionNonce": 81784553,
|
||||||
|
"width": 10,
|
||||||
|
"x": 60,
|
||||||
|
"y": 60,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"appState": Object {
|
||||||
|
"editingGroupId": "id10",
|
||||||
|
"editingLinearElement": null,
|
||||||
|
"name": "Untitled-201933152653",
|
||||||
|
"selectedElementIds": Object {
|
||||||
|
"id12": true,
|
||||||
|
"id7": true,
|
||||||
|
},
|
||||||
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
},
|
||||||
|
"elements": Array [
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
"id10",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id0",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 337897,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 4,
|
||||||
|
"versionNonce": 493213705,
|
||||||
|
"width": 10,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id4",
|
||||||
|
"id10",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id1",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 449462985,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 4,
|
||||||
|
"versionNonce": 915032327,
|
||||||
|
"width": 10,
|
||||||
|
"x": 30,
|
||||||
|
"y": 30,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElementIds": null,
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"groupIds": Array [
|
||||||
|
"id10",
|
||||||
|
],
|
||||||
|
"height": 10,
|
||||||
|
"id": "id7",
|
||||||
|
"isDeleted": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 400692809,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 3,
|
||||||
|
"versionNonce": 81784553,
|
||||||
|
"width": 10,
|
||||||
|
"x": 60,
|
||||||
|
"y": 60,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`regression tests Cmd/Ctrl-click exclusively select element under pointer: [end of test] number of elements 1`] = `3`;
|
||||||
|
|
||||||
|
exports[`regression tests Cmd/Ctrl-click exclusively select element under pointer: [end of test] number of renders 1`] = `41`;
|
||||||
|
|
||||||
exports[`regression tests Drags selected element when hitting only bounding box and keeps element selected: [end of test] appState 1`] = `
|
exports[`regression tests Drags selected element when hitting only bounding box and keeps element selected: [end of test] appState 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"appearance": "light",
|
"appearance": "light",
|
||||||
|
@ -50,6 +50,20 @@ const group = (elements: ExcalidrawElement[]) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const assertSelectedElements = (...elements: ExcalidrawElement[]) => {
|
||||||
|
expect(
|
||||||
|
getSelectedElements().map((element) => {
|
||||||
|
return element.id;
|
||||||
|
}),
|
||||||
|
).toEqual(expect.arrayContaining(elements.map((element) => element.id)));
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearSelection = () => {
|
||||||
|
// @ts-ignore
|
||||||
|
h.app.clearSelection(null);
|
||||||
|
expect(getSelectedElements().length).toBe(0);
|
||||||
|
};
|
||||||
|
|
||||||
let altKey = false;
|
let altKey = false;
|
||||||
let shiftKey = false;
|
let shiftKey = false;
|
||||||
let ctrlKey = false;
|
let ctrlKey = false;
|
||||||
@ -191,8 +205,7 @@ class Pointer {
|
|||||||
/** if multiple elements supplied, they're shift-selected */
|
/** if multiple elements supplied, they're shift-selected */
|
||||||
elements: ExcalidrawElement | ExcalidrawElement[],
|
elements: ExcalidrawElement | ExcalidrawElement[],
|
||||||
) {
|
) {
|
||||||
// @ts-ignore
|
clearSelection();
|
||||||
h.app.clearSelection(null);
|
|
||||||
withModifierKeys({ shift: true }, () => {
|
withModifierKeys({ shift: true }, () => {
|
||||||
elements = Array.isArray(elements) ? elements : [elements];
|
elements = Array.isArray(elements) ? elements : [elements];
|
||||||
elements.forEach((element) => {
|
elements.forEach((element) => {
|
||||||
@ -1649,6 +1662,40 @@ describe("regression tests", () => {
|
|||||||
expect(h.state.selectedGroupIds).toEqual(selectedGroupIds_prev);
|
expect(h.state.selectedGroupIds).toEqual(selectedGroupIds_prev);
|
||||||
expect(getSelectedElements()).toEqual(selectedElements_prev);
|
expect(getSelectedElements()).toEqual(selectedElements_prev);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Cmd/Ctrl-click exclusively select element under pointer", () => {
|
||||||
|
const rect1 = createElement("rectangle", { x: 0 });
|
||||||
|
const rect2 = createElement("rectangle", { x: 30 });
|
||||||
|
|
||||||
|
group([rect1, rect2]);
|
||||||
|
assertSelectedElements(rect1, rect2);
|
||||||
|
|
||||||
|
withModifierKeys({ ctrl: true }, () => {
|
||||||
|
mouse.clickOn(rect1);
|
||||||
|
});
|
||||||
|
assertSelectedElements(rect1);
|
||||||
|
|
||||||
|
clearSelection();
|
||||||
|
withModifierKeys({ ctrl: true }, () => {
|
||||||
|
mouse.clickOn(rect1);
|
||||||
|
});
|
||||||
|
assertSelectedElements(rect1);
|
||||||
|
|
||||||
|
const rect3 = createElement("rectangle", { x: 60 });
|
||||||
|
group([rect1, rect3]);
|
||||||
|
assertSelectedElements(rect1, rect2, rect3);
|
||||||
|
|
||||||
|
withModifierKeys({ ctrl: true }, () => {
|
||||||
|
mouse.clickOn(rect1);
|
||||||
|
});
|
||||||
|
assertSelectedElements(rect1);
|
||||||
|
|
||||||
|
clearSelection();
|
||||||
|
withModifierKeys({ ctrl: true }, () => {
|
||||||
|
mouse.clickOn(rect3);
|
||||||
|
});
|
||||||
|
assertSelectedElements(rect3);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(
|
it(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user