Skip to content

New: Add rectangle selection - #115

Merged
AlexIchenskiy merged 3 commits into
mainfrom
new/add-rectangle-selection
Sep 8, 2026
Merged

New: Add rectangle selection#115
AlexIchenskiy merged 3 commits into
mainfrom
new/add-rectangle-selection

Conversation

@AlexIchenskiy

Copy link
Copy Markdown
Collaborator

This PR introduces rectangle node selection.

The selection logic lives in core as neutral primitives, the visual ships as an opt-in
module (@memgraph/orb/interactions), so core stays renderer-agnostic.

Core got some new public methods for position transform and neutral BACKGROUND_DRAG_* events via interaction.backgroundDrag. Panning and node dragging are unchanged. A modifier-held drag on the empty background is intercepted to emit these events instead of panning.

A new interaction module adds a RectangleSelection helper that listens to the background-drag events, draws its own overlay, and applies the selection through those primitives.

Verified on canvas + WebGL; some WebGL improvements, tests and a docs demo included. Map view, lasso select, touch and WebGL label dimming are left for later.

@AlexIchenskiy AlexIchenskiy self-assigned this Sep 4, 2026

@tonilastre tonilastre left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great! I've tested it and works fine.

Btw maybe I misconfigured but is it possible to:

  • Do rectangle select -> selects N nodes
  • Click SHIFT and select new (N+1) node

Currently, it unselects the rectangle ones.

Comment on lines +175 to +179
import { RectangleArea } from '@memgraph/orb';

const area = new RectangleArea({ x, y, width, height });
const nodes = orb.data.getNodesInArea(area); // nodes whose center is inside
orb.interaction.selectNodesByIds(nodes.map((n) => n.getId()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@@ -1,2 +1,2 @@
/*! For license information please see orb.min.js.LICENSE.txt */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw do we need orb.min.js in here? Can we pull it from <script src="https://unpkg.com/@memgraph/orb/dist/browser/orb.min.js"></script>

It won't have the current version, but the latest deployed one (which also makes sense because docs are deployed on main)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is that locally you couldn' see how it works then :/

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to keep as-is, so the demos always match the source which makes the DX better. The only downside is having this binary in git, but since it does not go into build, I'd say it's fine. Let me know if we want to remove it

Comment thread src/interactions/shared.ts Outdated

export type IRectangleSelectionMode = 'replace' | 'add';

export type IRectangleSelectionEdgeMode = 'none' | 'endpointsInside';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we even need these? You as a user can simply filter out or add edges once you get a selection?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! Dropped the edge selection interfaces

Comment thread src/utils/graph.utils.ts
Comment on lines +66 to +104
export const selectNodes = <N extends INodeBase, E extends IEdgeBase>(
nodes: INode<N, E>[],
options?: ISelectionOptions,
): { changedCount: number } => {
for (let i = 0; i < nodes.length; i++) {
selectNode(nodes[i], options);
}
return { changedCount: nodes.length };
};

export const unselectNodes = <N extends INodeBase, E extends IEdgeBase>(
nodes: INode<N, E>[],
options?: ISelectionOptions,
): { changedCount: number } => {
for (let i = 0; i < nodes.length; i++) {
unselectNode(nodes[i], options);
}
return { changedCount: nodes.length };
};

export const selectEdges = <N extends INodeBase, E extends IEdgeBase>(
edges: IEdge<N, E>[],
options?: ISelectionOptions,
): { changedCount: number } => {
for (let i = 0; i < edges.length; i++) {
selectEdge(edges[i], options);
}
return { changedCount: edges.length };
};

export const unselectEdges = <N extends INodeBase, E extends IEdgeBase>(
edges: IEdge<N, E>[],
options?: ISelectionOptions,
): { changedCount: number } => {
for (let i = 0; i < edges.length; i++) {
unselectEdge(edges[i], options);
}
return { changedCount: edges.length };
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changed counts might not give correct value for "changed" - they return the total number of edges and nodes, not necessarily if it was changed

@AlexIchenskiy
AlexIchenskiy merged commit 2fde65d into main Sep 8, 2026
3 checks passed
@AlexIchenskiy
AlexIchenskiy deleted the new/add-rectangle-selection branch September 8, 2026 10:25
github-actions Bot pushed a commit that referenced this pull request Sep 8, 2026
# [1.1.0](v1.0.2...v1.1.0) (2026-09-08)

### New

* Add rectangle selection (#115) ([2fde65d](2fde65d)), closes [#115](#115)
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 1.1.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants