@affino/selection-core
v1.1.1
Published
Headless selection core for Affino UI primitives
Maintainers
Readme
@affino/selection-core
Headless selection primitives for Affino UI: linear selection (1D ranges) and grid selection (2D cells/areas).
Need Vue bindings or a listbox state machine? Use @affino/selection-vue on top of
@affino/listbox-core.
Features
- Normalized 1D ranges (
start,end) with anchor/focus semantics - Grid/cell selection snapshots with range + area normalization
- Immutable merge/toggle/extend helpers
- Deterministic
resolveLinearSelectionUpdate()snapshots for stores/renderers - Deterministic
resolveSelectionUpdate()snapshots for grid renderers/controllers - Zero DOM dependencies so adapters stay thin
Non-goals
- No DOM manipulation
- No event handling
- No rendering concerns
- No framework bindings
Mental model
- A selection is expressed as ranges + anchor + focus.
- Operations consume intent and emit new
HeadlessSelectionStatesnapshots. - Framework adapters translate user input into those operations.
Usage
import {
selectLinearIndex,
extendLinearSelectionToIndex,
toggleLinearIndex,
} from "@affino/selection-core"
let state = selectLinearIndex({ index: 2 })
state = extendLinearSelectionToIndex({ state, index: 6 })
state = toggleLinearIndex({ state, index: 4 })Package boundaries
@affino/selection-core: canonical package for 1D linear selection and 2D grid selection.@affino/selection-vue: Vue bindings and stores on top of the headless primitives.@affino/grid-selection-core: legacy package name kept only for transition strategy outside this package.
Migration guide
Preferred imports
Import both linear and grid helpers from @affino/selection-core.
import { selectSingleCell } from "@affino/selection-core"
import { selectLinearIndex } from "@affino/selection-core"Replace ad-hoc range mutation with intent operations
Prefer operation helpers over manual ranges editing:
- single click ->
selectLinearIndex - shift extend ->
extendLinearSelectionToIndex - cmd/ctrl toggle ->
toggleLinearIndex - clear action ->
clearLinearSelection
Use resolveLinearSelectionUpdate only when hydrating external snapshots.
Guardrails
- Treat returned states as immutable snapshots and replace the full value in stores.
- Do not rely on invalid inputs being auto-corrected; pass finite integer indexes.
resolveLinearSelectionUpdatethrows ifactiveRangeIndexis out of bounds.- Use one canonical source of truth for selection state in the adapter.
See /demo-vue for integration patterns.
