feat: cycle through selected elements on cmd/ctrl-click
This commit is contained in:
parent
c819b653bf
commit
0e3a5b2042
@ -1862,6 +1862,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
/** if true, returns the first selected element (with highest z-index)
|
/** if true, returns the first selected element (with highest z-index)
|
||||||
of all hit elements */
|
of all hit elements */
|
||||||
preferSelected?: boolean;
|
preferSelected?: boolean;
|
||||||
|
cycleElementsUnderCursor?: boolean;
|
||||||
},
|
},
|
||||||
): NonDeleted<ExcalidrawElement> | null {
|
): NonDeleted<ExcalidrawElement> | null {
|
||||||
const allHitElements = this.getElementsAtPosition(x, y);
|
const allHitElements = this.getElementsAtPosition(x, y);
|
||||||
@ -1872,6 +1873,13 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
return allHitElements[index];
|
return allHitElements[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (opts?.cycleElementsUnderCursor) {
|
||||||
|
const selectedIdx = allHitElements.findIndex(
|
||||||
|
(element) => this.state.selectedElementIds[element.id],
|
||||||
|
);
|
||||||
|
return selectedIdx > 0
|
||||||
|
? allHitElements[selectedIdx - 1]
|
||||||
|
: allHitElements[allHitElements.length - 1];
|
||||||
}
|
}
|
||||||
const elementWithHighestZIndex =
|
const elementWithHighestZIndex =
|
||||||
allHitElements[allHitElements.length - 1];
|
allHitElements[allHitElements.length - 1];
|
||||||
@ -2746,10 +2754,13 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
|
|
||||||
// hitElement may already be set above, so check first
|
// hitElement may already be set above, so check first
|
||||||
pointerDownState.hit.element =
|
pointerDownState.hit.element =
|
||||||
pointerDownState.hit.element ??
|
(!event[KEYS.CTRL_OR_CMD] ? pointerDownState.hit.element : null) ??
|
||||||
this.getElementAtPosition(
|
this.getElementAtPosition(
|
||||||
pointerDownState.origin.x,
|
pointerDownState.origin.x,
|
||||||
pointerDownState.origin.y,
|
pointerDownState.origin.y,
|
||||||
|
{
|
||||||
|
cycleElementsUnderCursor: event[KEYS.CTRL_OR_CMD],
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// For overlapped elements one position may hit
|
// For overlapped elements one position may hit
|
||||||
|
@ -144,6 +144,52 @@ describe("inner box-selection", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("selecting with cmd/ctrl modifier", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await render(<ExcalidrawApp />);
|
||||||
|
});
|
||||||
|
it("cycling through elements under cursor", async () => {
|
||||||
|
const rect1 = API.createElement({
|
||||||
|
type: "rectangle",
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
backgroundColor: "red",
|
||||||
|
fillStyle: "solid",
|
||||||
|
});
|
||||||
|
const rect2 = API.createElement({
|
||||||
|
type: "rectangle",
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
backgroundColor: "red",
|
||||||
|
fillStyle: "solid",
|
||||||
|
});
|
||||||
|
const rect3 = API.createElement({
|
||||||
|
type: "rectangle",
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
backgroundColor: "red",
|
||||||
|
fillStyle: "solid",
|
||||||
|
});
|
||||||
|
h.elements = [rect1, rect2, rect3];
|
||||||
|
Keyboard.withModifierKeys({ ctrl: true }, () => {
|
||||||
|
mouse.clickAt(100, 100);
|
||||||
|
assertSelectedElements(rect3);
|
||||||
|
mouse.clickAt(100, 100);
|
||||||
|
assertSelectedElements(rect2);
|
||||||
|
mouse.clickAt(100, 100);
|
||||||
|
assertSelectedElements(rect1);
|
||||||
|
mouse.clickAt(100, 100);
|
||||||
|
assertSelectedElements(rect3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("selection element", () => {
|
describe("selection element", () => {
|
||||||
it("create selection element on pointer down", async () => {
|
it("create selection element on pointer down", async () => {
|
||||||
const { getByToolName, container } = await render(<ExcalidrawApp />);
|
const { getByToolName, container } = await render(<ExcalidrawApp />);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user