Skip to content

Multi Range Selection

HTMLRevoGridElementEventMap (Extended from global)

Section titled “HTMLRevoGridElementEventMap (Extended from global)”
interface HTMLRevoGridElementEventMap {
/** Fires after the active or inactive multi-range selection changes. */
multirangeselectionchange: MultiRangeSelectionChangeEvent
}

HTMLRevoGridElement (Extended from @revolist/revogrid)

Section titled “HTMLRevoGridElement (Extended from @revolist/revogrid)”
interface HTMLRevoGridElement {
/**
* Multi-range selection configuration.
*/
multiRangeSelection?: MultiRangeSelectionConfig
}

AdditionalData (Extended from @revolist/revogrid)

Section titled “AdditionalData (Extended from @revolist/revogrid)”
interface AdditionalData {
/**
* Additional data property for multi-range selection configuration.
* @deprecated Use `grid.multiRangeSelection` instead.
*/
multiRangeSelection?: MultiRangeSelectionConfig
}

Event payload emitted when active or inactive multi-range selection changes.

/**
* Event payload emitted when active or inactive multi-range selection changes.
*/
export type MultiRangeSelectionChangeEvent = {
ranges: MultiRangeSelectionRange[];
inactiveRanges: MultiRangeSelectionRange[];
activeRange: MultiRangeSelectionRange | null;
activeIndex: number;
};

One selected range in a concrete RevoGrid row and column viewport.

Coordinates are local to the rowType/colType viewport stores.

/**
* One selected range in a concrete RevoGrid row and column viewport.
*
* Coordinates are local to the `rowType`/`colType` viewport stores.
*/
export type MultiRangeSelectionRange = {
rowType: DimensionRows;
colType: DimensionCols;
range: RangeArea;
};

Runtime contract used when row-header selection replaces cell selection.

interface MultiRangeRowHeaderProvider {
clearFromRowHeader(): void
}

Builds text/html/custom clipboard output for the current multi-range selection.

Ranges are first converted from viewport-local coordinates to whole-grid visual coordinates, so pinned and regular selections preserve their copied pattern when pasted into a regular viewport.

export function buildMultiRangeClipboardData(
ranges: MultiRangeSelectionRange[],
providers: PluginProviders,
options: MultiRangeClipboardOptions = {},
): MultiRangeClipboardData | null;

Custom clipboard MIME type used to preserve sparse multi-range metadata for RevoGrid-aware paste handlers while still writing standard text/html data.

MULTI_RANGE_CLIPBOARD_MIME: string;

Serialized clipboard data for a multi-range copy operation.

sparse mode preserves the relative row/column gaps between selected cells. blocks mode serializes each range as an independent table when sparse output is disabled or exceeds configured limits.

/**
* Serialized clipboard data for a multi-range copy operation.
*
* `sparse` mode preserves the relative row/column gaps between selected cells.
* `blocks` mode serializes each range as an independent table when sparse
* output is disabled or exceeds configured limits.
*/
export type MultiRangeClipboardData = {
text: string;
html: string;
mode: 'sparse' | 'blocks';
payload?: MultiRangeClipboardPayload;
};

Structured representation of a sparse multi-range copy.

The payload keeps only selected cells plus the final clipboard dimensions, allowing RevoGrid-aware consumers to distinguish intentionally empty cells from cells that were never selected.

/**
* Structured representation of a sparse multi-range copy.
*
* The payload keeps only selected cells plus the final clipboard dimensions,
* allowing RevoGrid-aware consumers to distinguish intentionally empty cells
* from cells that were never selected.
*/
export type MultiRangeClipboardPayload = {
width: number;
height: number;
cells: MultiRangeClipboardCell[];
};

Options controlling multi-range clipboard serialization.

/**
* Options controlling multi-range clipboard serialization.
*/
export type MultiRangeClipboardOptions = {
/** Maximum cells allowed in the sparse bounding box before using blocks. */
maxSparseCells?: number;
/**
* Maximum sparse bounding-box expansion over selected cell count.
*
* Defaults to no expansion limit so copied patterns are preserved until
* `maxSparseCells` is exceeded.
*/
maxSparseExpansion?: number;
/** Whether disjoint selections should keep their relative empty gaps. */
preserveSparseGaps?: boolean;
/** Converts cell values into clipboard-safe text before text/html output. */
serializeValue?: (value: unknown) => string;
};

Normalizes paste data from multi-table HTML clipboard content.

Some clipboard parsers flatten multiple HTML tables poorly. When the raw HTML contains multiple tables and the parser did not already produce structured values, this falls back to the plain text matrix that browsers place on the clipboard alongside HTML.

export function normalizeMultiTablePasteData({
raw,
dataText,
parsed,
isHTML,
}: {
raw?: string;
dataText?: string;
parsed: unknown[][];
isHTML?: boolean;
});

Builds rangeeditapply payloads that clear all selected multi-range cells.

Ranges are grouped by row viewport type because RevoGrid edit events apply to one data store at a time.

export function buildMultiRangeClearEdits(
ranges: MultiRangeSelectionRange[],
providers: PluginProviders,
value: DataFormat = '',
): BeforeRangeSaveDataDetails[] | null;

Clipboard companion for {@link MultiRangeSelectionPlugin}.

Keeps multi-range copy and paste behavior separate from selection state: it serializes all selected ranges and normalizes RevoGrid multi-table HTML paste back to the complete text payload.

  • Event integration CLIPBOARD_COPY_EVENT, CLIPBOARD_PASTE_EVENT: Listens to RevoGrid clipboard events to copy and paste multi-range selections.
  • Event integration json-clipboard: Cooperates with ClipboardJsonPlugin when JSON clipboard serialization is enabled.
class MultiRangeClipboardPlugin {
/**
* Connects this companion to the active multi-range selection source.
* Host-created instances are registered before the selection plugin exists,
* so the adapter must be replaceable after construction.
*/
setSelectedRangesAdapter(getSelectedRanges?: () => MultiRangeSelectionRange[]);
}

Coordinates cross-viewport autofill preview and commit behavior.

class MultiRangeCrossViewportAutoFillPlugin {
/**
* Updates the final selection callback supplied by `MultiRangeSelectionPlugin`.
*/
setSelectionAdapter(
setSelectedRanges: MultiRangeCrossViewportAutoFillPluginOptions['setSelectedRanges'],
);
/**
* Enables or disables cross-viewport gesture handling without removing the
* auto-installed companion plugin.
*/
setEnabled(enabled: boolean);
/**
* Starts or updates a cross-viewport session from core temporary autofill
* range events.
*/
handleBeforeTempRange(
event: CustomEvent<HTMLRevogrOverlaySelectionElementEventMap['beforesettemprange']>,
);
/**
* Intercepts core selection commit only when a cross-viewport result exists,
* then commits segmented edits instead of a single clamped range.
*/
handleSelectionChangeInit(event: Event);
/**
* Lets native mouseup reset its drag state while preventing the clamped
* same-viewport range from becoming the final selection.
*/
handleBeforeApplyRange(event: Event);
/**
* Lets the preview controller inject generated values into visible cells.
*/
handleBeforeCellRender(
event: CustomEvent<HTMLRevogrDataElementEventMap['beforecellrender']>,
);
/**
* Clears any active session after source data changes.
*/
handleAfterSource();
/**
* Releases preview state and active session data.
*/
destroy();
}

  • Auto-installed MultiRangeClipboardPlugin: Installs MultiRangeClipboardPlugin internally for multi-range copy and paste behavior.
  • Auto-installed MultiRangeCrossViewportAutoFillPlugin: Installs MultiRangeCrossViewportAutoFillPlugin internally for drag autofill across pinned and main viewports.
  • Event integration MultiRangeClipboardPlugin: Delegates multi-range clipboard serialization and paste normalization to MultiRangeClipboardPlugin.
  • Event integration MultiRangeCrossViewportAutoFillPlugin: Delegates cross-viewport autofill preview and commit handling to MultiRangeCrossViewportAutoFillPlugin.
  • Config integration additionalData.multiRangeSelection: Reads legacy multi-range selection configuration from additionalData.multiRangeSelection.
multiRangeSelectionPluginDependencies: PluginDependency[];

Enables spreadsheet-like multi-range cell selection in RevoGrid Pro.

Ctrl/Cmd+click stores the current active range and starts a new active range. Shift interactions keep extending the active core range. Additional inactive ranges are rendered by this plugin and included in multi-range copy output.

class MultiRangeSelectionPlugin {
/**
* Returns all selected ranges, including inactive ranges and the current core
* active range.
*/
getSelectedRanges(): MultiRangeSelectionRange[];
/**
* Replaces all selected ranges and applies one range as the active core
* selection.
*/
setSelectedRanges(
ranges: MultiRangeSelectionRange[],
activeIndex = ranges.length - 1,
);
/**
* Replaces selected ranges while keeping only a focus marker in the requested
* viewport. Used for plugin-owned cross-viewport selection where the source
* cell must keep focus without leaving an active expanded core range.
*/
setSelectedRangesWithFocus(
ranges: MultiRangeSelectionRange[],
focusRange: MultiRangeSelectionRange,
);
/**
* Clears inactive multi-range state and the current core selection.
*/
clearSelectedRanges();
/** Clears cell ranges before an interactive row header applies whole-row selection. */
clearFromRowHeader();
/**
* Removes plugin state, visual classes, controllers, and event listeners.
*/
destroy();
}

Converts the public boolean/object config into the internal normalized form.

export function normalizeMultiRangeSelectionConfig(
config?: MultiRangeSelectionConfig,
): NormalizedMultiRangeSelectionConfig;

Compares normalized configs so observable config updates can skip no-op work.

export function isSameMultiRangeSelectionConfig(
previous: NormalizedMultiRangeSelectionConfig,
next: NormalizedMultiRangeSelectionConfig,
);

Object form of the multi-range selection configuration.

/**
* Object form of the multi-range selection configuration.
*/
export type MultiRangeSelectionOptions = {
/**
* Enables autofill gestures across pinned/main viewport boundaries.
*
* The integration fills only visible viewport-scoped target segments and
* represents the final result as multi-range selection.
*/
crossViewportAutofill?: boolean;
};

Public grid property shape for enabling multi-range selection options.

true enables the plugin with default optional integrations.

/**
* Public grid property shape for enabling multi-range selection options.
*
* `true` enables the plugin with default optional integrations.
*/
export type MultiRangeSelectionConfig = boolean | MultiRangeSelectionOptions;

Internal normalized configuration used by the plugin runtime.

/**
* Internal normalized configuration used by the plugin runtime.
*/
export type NormalizedMultiRangeSelectionConfig = {
crossViewportAutofill: boolean;
};

Returns a range with x/y as the minimum bounds and x1/y1 as the maximum bounds.

export function normalizeRange(range: RangeArea): RangeArea;

Creates a shallow clone of a normalized or raw range object.

export function cloneRange(range: RangeArea): RangeArea;

Normalizes the coordinate bounds of a viewport-scoped selection.

export function normalizeSelectionRange(
selection: MultiRangeSelectionRange,
): MultiRangeSelectionRange;

Creates a clone of a viewport-scoped selection range.

export function cloneSelectionRange(
selection: MultiRangeSelectionRange,
): MultiRangeSelectionRange;

Builds a stable identity key for a normalized viewport-scoped range.

export function rangeKey(selection: MultiRangeSelectionRange);

Normalizes ranges and removes duplicate viewport/range entries.

export function dedupeRanges(
ranges: MultiRangeSelectionRange[],
): MultiRangeSelectionRange[];

Returns ranges in deterministic viewport and row-major order.

export function sortRanges(
ranges: MultiRangeSelectionRange[],
): MultiRangeSelectionRange[];

Checks whether a viewport-local cell coordinate is inside a range.

export function isCellInRange(cell: Cell, range: RangeArea);

Finds the first range that contains the given viewport-scoped cell.

export function findRangeForCell(
cell: MultiRangeSelectionCell,
ranges: MultiRangeSelectionRange[],
);

Counts cells covered by a range after normalizing its bounds.

export function rangeCellCount(range: RangeArea);

Checks whether a range contains exactly one cell.

export function isSingleCellRange(range: RangeArea);

Computes the bounding box that contains all provided range coordinates.

export function getRangeBounds(ranges: MultiRangeSelectionRange[]): RangeArea | null;

Groups ranges by their row and column viewport type pair.

export function groupRangesByDimension(ranges: MultiRangeSelectionRange[]);

Builds the class map required to render inactive range body and edge styles for a concrete cell.

export function getInactiveRangeCellClasses(
cell: MultiRangeSelectionCell,
selection: MultiRangeSelectionRange,
);

Resolves the next focus cell inside a range for Tab or Enter traversal.

export function moveCellWithinRange(
range: RangeArea,
focus: Cell,
key: string,
backwards = false,
): Cell | null;

Grid host class added while multi-range selection is active.

MULTI_RANGE_SELECTION_GRID_CLASS: string;

Cell class applied to inactive selected ranges.

MULTI_RANGE_SELECTION_CELL_CLASS: string;

Cell attribute applied to inactive selected ranges for styling hooks.

MULTI_RANGE_SELECTION_ATTR: string;

Edge class applied to the top side of an inactive range.

MULTI_RANGE_SELECTION_EDGE_TOP_CLASS: string;

Edge class applied to the right side of an inactive range.

MULTI_RANGE_SELECTION_EDGE_RIGHT_CLASS: string;

Edge class applied to the bottom side of an inactive range.

MULTI_RANGE_SELECTION_EDGE_BOTTOM_CLASS: string;

Edge class applied to the left side of an inactive range.

MULTI_RANGE_SELECTION_EDGE_LEFT_CLASS: string;

Dependencies supplied by the owning multi-range selection plugin.

/**
* Dependencies supplied by the owning multi-range selection plugin.
*/
export type MultiRangeClipboardPluginOptions = {
/** Returns the current selected ranges when a copy event is handled. */
getSelectedRanges?: () => MultiRangeSelectionRange[];
};

One copied cell inside the sparse multi-range clipboard payload.

row and col are zero-based offsets inside the normalized clipboard bounding box, not viewport-local grid coordinates.

/**
* One copied cell inside the sparse multi-range clipboard payload.
*
* `row` and `col` are zero-based offsets inside the normalized clipboard
* bounding box, not viewport-local grid coordinates.
*/
export type MultiRangeClipboardCell = {
row: number;
col: number;
value: unknown;
};

Builds the final visible target segment for a source/target drag pair.

export function buildCrossViewportAutoFillTarget(
source: MultiRangeSelectionRange,
target: MultiRangeSelectionRange,
providers: Pick<PluginProviders, 'viewport'>,
visibleIndexes?: CrossViewportAutoFillVisibleIndexes,
): CrossViewportAutoFillTarget | null;

Splits a cross-viewport drag into visible viewport-scoped target ranges.

V1 supports one changed axis only. Diagonal changes that alter both row and column viewport types return no targets so core autofill can remain clamped.

export function buildCrossViewportAutoFillTargets(
source: MultiRangeSelectionRange,
target: MultiRangeSelectionRange,
providers: Pick<PluginProviders, 'viewport'>,
visibleIndexes?: CrossViewportAutoFillVisibleIndexes,
): CrossViewportAutoFillTarget[];

Computes edit data for visible cross-viewport autofill targets.

Strategies receive a synthetic continuous range so existing autofill algorithms can continue sequences across visible segments, while mapping back never includes hidden scroll-gap rows or columns.

export function computeCrossViewportAutoFillData({
source,
targets,
providers,
strategies,
}: CrossViewportAutoFillComputeOptions): CrossViewportAutoFillResult | null;

Converts a focused cell address into a single-cell selection range.

export function cellToSelection(cell: Cell & {
rowType: DimensionRows;
colType: DimensionCols;
}): MultiRangeSelectionRange;

Axis that crosses viewport types during one autofill gesture.

/**
* Axis that crosses viewport types during one autofill gesture.
*/
export type CrossViewportAutoFillMode = 'row' | 'column';

CrossViewportAutoFillTarget (Extended from cross-viewport-autofill.compute.ts)

Section titled “CrossViewportAutoFillTarget (Extended from cross-viewport-autofill.compute.ts)”

One visible target segment for a cross-viewport autofill gesture.

/**
* One visible target segment for a cross-viewport autofill gesture.
*/
export type CrossViewportAutoFillTarget = MultiRangeSelectionRange & {
direction: AutoFillDirection;
};

Test or integration override for visible row/column indexes by viewport type.

/**
* Test or integration override for visible row/column indexes by viewport type.
*/
export type CrossViewportAutoFillVisibleIndexes = Partial<Record<
DimensionRows | DimensionCols,
{ start: number; end: number }
>>;

Inputs required to compute autofill data across viewport boundaries.

/**
* Inputs required to compute autofill data across viewport boundaries.
*/
export type CrossViewportAutoFillComputeOptions = {
source: MultiRangeSelectionRange;
targets: CrossViewportAutoFillTarget[];
providers: PluginProviders;
strategies: AutoFillStrategy[];
};

One editable data segment generated for a visible target range.

/**
* One editable data segment generated for a visible target range.
*/
export type CrossViewportAutoFillSegment = {
selection: MultiRangeSelectionRange;
data: DataLookup;
models: Partial<DataLookup>;
};

Full computed cross-viewport autofill result.

/**
* Full computed cross-viewport autofill result.
*/
export type CrossViewportAutoFillResult = {
source: MultiRangeSelectionRange;
targets: CrossViewportAutoFillTarget[];
segments: CrossViewportAutoFillSegment[];
};

Checks whether the original event path started from a core autofill handle.

export function isAutofillHandleEvent(event: MouseEvent);

Resolves the visible RevoGrid cell at viewport coordinates.

export function resolveRenderedCellAt(
revogrid: HTMLRevoGridElement,
clientX: number,
clientY: number,
): MultiRangeSelectionRange | null;

Reads visible row/column indexes from clipped rendered cells.

export function getRenderedVisibleIndexes(
revogrid: HTMLRevoGridElement,
): CrossViewportAutoFillVisibleIndexes;

Renders and refreshes cross-viewport autofill preview cells.

class CrossViewportAutoFillPreviewController {
/**
* Injects preview value and styling into a rendered target cell.
*/
renderCell(
event: CustomEvent<HTMLRevogrDataElementEventMap['beforecellrender']>,
result: CrossViewportAutoFillResult | null,
showPreviewValues = true,
renderRanges: MultiRangeSelectionRange[] | boolean = false,
dashedRange = false,
autofillRange = false,
);
/**
* Replaces the active preview result and schedules refresh for changed cells.
*/
setResult(
result: CrossViewportAutoFillResult | null,
renderRanges: MultiRangeSelectionRange[] | boolean = false,
);
/**
* Cancels pending refresh work and clears tracked preview cells.
*/
destroy();
}

Builds the source-viewport part of a diagonal cross-viewport autofill target.

export function buildSourceViewportOrthogonalTarget({
source,
target,
rowChanged,
colChanged,
visibleIndexes,
direction,
}: {
source: MultiRangeSelectionRange;
target: MultiRangeSelectionRange;
rowChanged: boolean;
colChanged: boolean;
visibleIndexes?: CrossViewportAutoFillVisibleIndexes;
direction: CrossViewportAutoFillTarget['direction'];
}): CrossViewportAutoFillTarget | null;

Builds final selected ranges while folding source-viewport fill extensions into the visual source range.

export function getFinalSelectionRanges(
result: CrossViewportAutoFillResult,
): MultiRangeSelectionRange[];

Builds the visual temporary ranges. Value previews still come only from generated edit segments; these ranges define ghost styling and edges.

export function getPreviewRenderRanges(
result: CrossViewportAutoFillResult,
): MultiRangeSelectionRange[];

MultiRangeCrossViewportAutoFillPluginOptions

Section titled “MultiRangeCrossViewportAutoFillPluginOptions”

Options supplied by MultiRangeSelectionPlugin.

/**
* Options supplied by `MultiRangeSelectionPlugin`.
*/
export type MultiRangeCrossViewportAutoFillPluginOptions = {
/** Applies source and target segments as the final multi-range selection. */
setSelectedRanges?: (
ranges: MultiRangeSelectionRange[],
activeIndex?: number,
options?: { focusRange?: MultiRangeSelectionRange },
) => void;
/** Enables cross-viewport gesture handling. */
enabled?: boolean;
};

Handles multi-range keyboard behavior before core selection navigation.

export function handleMultiRangeSelectionKeyDown(
event: MultiRangeSelectionKeyDownEvent,
context: MultiRangeSelectionKeyboardContext,
);

export type MultiRangeSelectionKeyboardContext = {
providers: PluginProviders;
getActiveRange(): MultiRangeSelectionRange | null;
getSelectedRanges(): MultiRangeSelectionRange[];
clearInactiveRanges(): void;
emitRangeEditApply(detail: BeforeRangeSaveDataDetails): void;
emitChange(): void;
};

export function createCellSchema({
rowIndex,
colIndex,
rowType,
colType,
rowSource,
model,
column,
}: {
rowIndex: number;
colIndex: number;
rowType: DimensionRows;
colType: DimensionCols;
rowSource: DataType[];
model: DataType;
column: ColumnRegular;
}): ColumnDataSchemaModel;

export function isReadOnlyColumn(
column: ColumnRegular,
schema: ColumnDataSchemaModel,
);

A cell address with explicit row and column viewport ownership.

/**
* A cell address with explicit row and column viewport ownership.
*/
export type MultiRangeSelectionCell = {
row: number;
col: number;
rowType: DimensionRows;
colType: DimensionCols;
};

export function getColumnTypeOffset(
type: DimensionCols,
providers: PluginProviders,
);

export function getRowTypeOffset(
type: DimensionRows,
providers: PluginProviders,
);

export function resolveRowViewportCoordinate(
providers: PluginProviders,
sourceType: DimensionRows,
sourceIndex: number,
offset: number,
);

export function resolveColumnViewportCoordinate(
providers: PluginProviders,
sourceType: DimensionCols,
sourceIndex: number,
offset: number,
);

export function getStoreSource<T>(
store: StoreLike,
);

export function getStoreItems<T>(
store: StoreLike,
source: T[],
);

export type ViewportCoordinate<T extends string> = {
type: T;
index: number;
};