title: "@jeeboard/core: selection helpers" description: Covers selection bounds, marquee selection, alignment, distribution, grouping, and locking helpers. #
Selection #
The @jeeboard/core package provides pure functions for selection operations.
These functions compute changes. They never mutate elements directly.
Apply the returned changes inside a transaction on the editor core.
Key concepts #
- Selection union: the smallest rectangle that contains all selected elements.
- Marquee: the rectangle that the user drags to select elements.
- Bounds change: a
SelectionBoundsChangewith an element ID and new bounds. - Properties change: a
SelectionPropertiesChangewith an element ID and new properties.
Selection bounds #
selectionBounds(elements) returns the union of the element bounds.
It returns null for an empty array.
Negative width and height values are normalized first.
import { selectionBounds } from "@jeeboard/core";
const union = selectionBounds(elements);
Marquee selection #
selectElementsInBounds(elements, marquee, mode?) returns the IDs of matching elements.
The SelectionBoundsMode type has two values:
"intersects"(default) selects elements that overlap the marquee."contains"selects elements fully inside the marquee.
import { selectElementsInBounds } from "@jeeboard/core";
const ids = selectElementsInBounds(
elements,
{ x: 0, y: 0, width: 180, height: 80 },
"contains"
);
Alignment #
alignElements(elements, alignment) returns one bounds change per element.
Each element moves against the selection union.
The element sizes do not change.
The SelectionAlignment type has six values:
"left","center-x", and"right"for horizontal alignment."top","center-y", and"bottom"for vertical alignment.
import { alignElements } from "@jeeboard/core";
const changes = alignElements(elements, "top");
core.transact("align selection top", (tx) => {
for (const change of changes) {
tx.update(change.id, { bounds: change.bounds });
}
});
An empty selection returns an empty array.
Distribution #
distributeElements(elements, axis) equalizes the gaps between elements.
The SelectionDistributionAxis type is "x" or "y".
The function follows these rules:
- Sort the elements by position along the axis.
- Keep the first and the last element position fixed.
- Compute equal gaps between the elements.
- Return one bounds change per element in the input order.
import { distributeElements } from "@jeeboard/core";
const changes = distributeElements(elements, "x");
NOTE: Fewer than three elements cannot be distributed. The function returns their normalized bounds unchanged.
Locking #
A locked element has properties.locked === true.
A host application should block edits of locked elements.
isElementLocked(element)returns the lock state.setElementsLocked(elements, locked)returns one properties change per element.
import { isElementLocked, setElementsLocked } from "@jeeboard/core";
const changes = setElementsLocked(elements, true);
core.transact("lock selection", (tx) => {
for (const change of changes) {
tx.update(change.id, { properties: change.properties });
}
});
The changes preserve all other properties of each element.
Grouping #
A grouped element has a shared properties.groupId string.
A host application can use the group ID to move groups together.
groupElements(elements, groupId)sets the same group ID on all elements.ungroupElements(elements)removes the group ID from all elements.
import { groupElements, ungroupElements } from "@jeeboard/core";
const changes = groupElements(elements, "group-1");
Both functions preserve all other properties of each element.
Related pages #
- Data model and runtime covers transactions and the editor core.
- Navigation and transforms covers rotation and resize math.
API reference #
See the generated API reference for @jeeboard/core.