ouija board1
jeeboard docs core selection.md
4.1 kB
Markdown
at main


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 SelectionBoundsChange with an element ID and new bounds.
  • Properties change: a SelectionPropertiesChange with 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:

  1. Sort the elements by position along the axis.
  2. Keep the first and the last element position fixed.
  3. Compute equal gaps between the elements.
  4. 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.

API reference #

See the generated API reference for @jeeboard/core.