fix group selection (#2092)
This commit is contained in:
parent
546e13571d
commit
b8f8bc2e32
@ -3384,33 +3384,15 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
if (isSelectedViaGroup(this.state, hitElement)) {
|
||||
/*
|
||||
We want to select the group(s) the hit element is in not the particular element.
|
||||
That means we have to deselect elements that are not part of the groups of the
|
||||
hit element, while keeping the elements that are.
|
||||
*/
|
||||
const idsOfSelectedElementsThatAreInGroups = hitElement.groupIds
|
||||
.flatMap((groupId) =>
|
||||
getElementsInGroup(this.scene.getElements(), groupId),
|
||||
)
|
||||
.map((element) => ({ [element.id]: true }))
|
||||
.reduce((prevId, acc) => ({ ...prevId, ...acc }), {});
|
||||
|
||||
this.setState((_prevState) => ({
|
||||
selectedGroupIds: {
|
||||
...hitElement.groupIds
|
||||
.map((gId) => ({ [gId]: true }))
|
||||
.reduce((prevId, acc) => ({ ...prevId, ...acc }), {}),
|
||||
this.setState((prevState) => ({
|
||||
...selectGroupsForSelectedElements(
|
||||
{
|
||||
...prevState,
|
||||
selectedElementIds: { [hitElement.id]: true },
|
||||
},
|
||||
selectedElementIds: { ...idsOfSelectedElementsThatAreInGroups },
|
||||
}));
|
||||
} else {
|
||||
this.setState((_prevState) => ({
|
||||
selectedGroupIds: {},
|
||||
selectedElementIds: { [hitElement!.id]: true },
|
||||
}));
|
||||
}
|
||||
this.scene.getElements(),
|
||||
),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,33 @@ const clickTool = (toolName: ToolName) => {
|
||||
fireEvent.click(getByToolName(toolName));
|
||||
};
|
||||
|
||||
const createElement = (
|
||||
type: ToolName,
|
||||
{
|
||||
x = 0,
|
||||
y = x,
|
||||
size = 10,
|
||||
}: {
|
||||
x?: number;
|
||||
y?: number;
|
||||
size?: number;
|
||||
},
|
||||
) => {
|
||||
clickTool(type);
|
||||
mouse.reset();
|
||||
mouse.down(x, y);
|
||||
mouse.reset();
|
||||
mouse.up(x + size, y + size);
|
||||
return h.elements[h.elements.length - 1];
|
||||
};
|
||||
|
||||
const group = (elements: ExcalidrawElement[]) => {
|
||||
mouse.select(elements);
|
||||
withModifierKeys({ ctrl: true }, () => {
|
||||
keyPress("g");
|
||||
});
|
||||
};
|
||||
|
||||
let altKey = false;
|
||||
let shiftKey = false;
|
||||
let ctrlKey = false;
|
||||
@ -159,6 +186,28 @@ class Pointer {
|
||||
this.move(dx, dy);
|
||||
fireEvent.doubleClick(canvas, this.getEvent());
|
||||
}
|
||||
|
||||
select(
|
||||
/** if multiple elements supplied, they're shift-selected */
|
||||
elements: ExcalidrawElement | ExcalidrawElement[],
|
||||
) {
|
||||
// @ts-ignore
|
||||
h.app.clearSelection(null);
|
||||
withModifierKeys({ shift: true }, () => {
|
||||
elements = Array.isArray(elements) ? elements : [elements];
|
||||
elements.forEach((element) => {
|
||||
mouse.reset();
|
||||
mouse.click(element.x, element.y);
|
||||
});
|
||||
});
|
||||
mouse.reset();
|
||||
}
|
||||
|
||||
clickOn(element: ExcalidrawElement) {
|
||||
mouse.reset();
|
||||
mouse.click(element.x, element.y);
|
||||
mouse.reset();
|
||||
}
|
||||
}
|
||||
|
||||
const mouse = new Pointer("mouse");
|
||||
@ -1579,6 +1628,27 @@ describe("regression tests", () => {
|
||||
});
|
||||
expect(getSelectedElements().length).toBe(0);
|
||||
});
|
||||
|
||||
it("single-clicking on a subgroup of a selected group should not alter selection", () => {
|
||||
const rect1 = createElement("rectangle", { x: 10 });
|
||||
const rect2 = createElement("rectangle", { x: 50 });
|
||||
group([rect1, rect2]);
|
||||
|
||||
const rect3 = createElement("rectangle", { x: 10, y: 50 });
|
||||
const rect4 = createElement("rectangle", { x: 50, y: 50 });
|
||||
group([rect3, rect4]);
|
||||
|
||||
withModifierKeys({ ctrl: true }, () => {
|
||||
keyPress("a");
|
||||
keyPress("g");
|
||||
});
|
||||
|
||||
const selectedGroupIds_prev = h.state.selectedGroupIds;
|
||||
const selectedElements_prev = getSelectedElements();
|
||||
mouse.clickOn(rect3);
|
||||
expect(h.state.selectedGroupIds).toEqual(selectedGroupIds_prev);
|
||||
expect(getSelectedElements()).toEqual(selectedElements_prev);
|
||||
});
|
||||
});
|
||||
|
||||
it(
|
||||
@ -1586,52 +1656,26 @@ it(
|
||||
"when user clicks on B, on pointer up " +
|
||||
"only elements from B should be selected",
|
||||
() => {
|
||||
clickTool("rectangle");
|
||||
mouse.down();
|
||||
mouse.up(100, 100);
|
||||
const rect1 = createElement("rectangle", { y: 0 });
|
||||
const rect2 = createElement("rectangle", { y: 30 });
|
||||
const rect3 = createElement("rectangle", { y: 60 });
|
||||
|
||||
clickTool("rectangle");
|
||||
mouse.down(10, 10);
|
||||
mouse.up(100, 100);
|
||||
|
||||
clickTool("rectangle");
|
||||
mouse.down(10, 10);
|
||||
mouse.up(100, 100);
|
||||
|
||||
// Select first rectangle while keeping third one selected.
|
||||
// Third rectangle is selected because it was the last element
|
||||
// to be created.
|
||||
mouse.reset();
|
||||
withModifierKeys({ shift: true }, () => {
|
||||
mouse.click();
|
||||
});
|
||||
|
||||
// Create group with first and third rectangle
|
||||
withModifierKeys({ ctrl: true }, () => {
|
||||
keyPress("g");
|
||||
});
|
||||
group([rect1, rect3]);
|
||||
|
||||
expect(getSelectedElements().length).toBe(2);
|
||||
const selectedGroupIds = Object.keys(h.state.selectedGroupIds);
|
||||
expect(selectedGroupIds.length).toBe(1);
|
||||
expect(Object.keys(h.state.selectedGroupIds).length).toBe(1);
|
||||
|
||||
// Select second rectangle without deselecting group
|
||||
withModifierKeys({ shift: true }, () => {
|
||||
mouse.click(110, 110);
|
||||
mouse.clickOn(rect2);
|
||||
});
|
||||
expect(getSelectedElements().length).toBe(3);
|
||||
|
||||
// pointer down on first rectangle that is
|
||||
// part of the group
|
||||
mouse.reset();
|
||||
mouse.down();
|
||||
expect(getSelectedElements().length).toBe(3);
|
||||
|
||||
// should only deselect on pointer up
|
||||
mouse.up();
|
||||
// clicking on first rectangle that is part of the group should select
|
||||
// that group (exclusively)
|
||||
mouse.clickOn(rect1);
|
||||
expect(getSelectedElements().length).toBe(2);
|
||||
const newSelectedGroupIds = Object.keys(h.state.selectedGroupIds);
|
||||
expect(newSelectedGroupIds.length).toBe(1);
|
||||
expect(Object.keys(h.state.selectedGroupIds).length).toBe(1);
|
||||
},
|
||||
);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user