Skip to content

Sticky Cells

ColumnRegular (Extended from @revolist/revogrid)

Section titled “ColumnRegular (Extended from @revolist/revogrid)”
interface ColumnRegular {
/**
* Defines whether a cell participates in StickyCellsPlugin row discovery.
*
* Use this for sticky behavior and keep `cellProperties` focused on cell
* styling, attributes, and event props.
*/
stickyCell?: StickyCellPredicate
}

AdditionalData (Extended from @revolist/revogrid)

Section titled “AdditionalData (Extended from @revolist/revogrid)”
interface AdditionalData {
/**
* Sticky cells plugin configuration.
*
* ```ts
* grid.additionalData = {
* stickyCells: { maxRows: 2 },
* };
* ```
*/
stickyCells?: StickyCellsConfig
}
interface StickyCellsConfig {
/**
* Maximum amount of active sticky rows appended to `pinnedTopSource`.
*
* The nearest sticky row is appended last, so it renders closest to the
* scrollable body after any user-defined pinned top rows.
*
* @default 1
*/
maxRows?: number;
/**
* Makes plugin-managed sticky pinned rows readonly.
*
* This only affects the cloned rows rendered in `rowPinStart`; original source
* rows and user-provided pinned top rows keep their normal readonly behavior.
*
* @default true
*/
readonlyPinnedRows?: boolean
}

export type StickyCellPredicate = boolean | ((params: CellTemplateProp) => boolean);

The StickyCellsPlugin keeps marked rows visible by appending the active sticky rows to RevoGrid’s pinned top row source.

Sticky cells are configured through a column stickyCell predicate. If any visible cell in a row resolves stickyCell to true, that row can become an active sticky row. The row is cloned into rowPinStart once it starts crossing above the visible row viewport.

Key Features:

  • Uses a dedicated column stickyCell predicate; no separate sticky row data source is required.
  • Supports one or more active sticky rows pinned at the top of the scrolling row viewport.
  • Activates only after the bottom edge of the source row crosses above the visible viewport.
  • Preserves user-defined pinnedTopSource rows and removes only plugin-managed sticky rows.
  • Reuses normal pinned row rendering, including cellTemplate and beforecellrender integrations.

Behavior:

  • The last stickyCells.maxRows sticky rows at or above the scroll position stay active.
  • User pinned top rows render first; plugin-managed sticky rows are appended after them.
import { StickyCellsPlugin } from '@revolist/revogrid-pro';
const stickyCell = ({ model }) => model.isCheckpoint === true;
const grid = document.createElement('revo-grid');
grid.plugins = [StickyCellsPlugin];
grid.columns = [
{
name: 'Account',
prop: 'account',
stickyCell,
},
{
name: 'Status',
prop: 'status',
stickyCell,
},
];
class StickyCellsPlugin {}

export function resolveActiveStickyRows(
rowIndex: number,
context: ActiveStickyRowsContext,
): number[];

export function resolveBottomStableTreeRows(
rowIndex: number,
rowCount: number,
context: ActiveStickyRowsContext,
): number[];

export function findIndexedStickyRowsAtOrBefore(
indexedStickyRows: number[],
rowIndex: number,
maxRows: number,
): number[];

export function filterVisibleBottomRows(
rowIndexes: number[],
providers: PluginProviders,
isAtBottom: () => boolean = () => isScrolledToBottom(providers),
): number[];

export function filterVisibleRows(
rowIndexes: number[],
providers: PluginProviders,
): number[];

export function isScrolledToBottom(providers: PluginProviders): boolean;

export function isSameRowIndexes(a: number[], b: number[]): boolean;

interface ActiveStickyRowsContext {
maxRows: number;
providers: PluginProviders;
revogrid: HTMLRevoGridElement;
indexedStickyRows: number[];
includeTreeRow?: boolean;
isAtBottom(): boolean;
resolveStickyColumns(rowIndex: number): boolean
}

export function normalizeStickyCellsConfig(
config: StickyCellsConfig | undefined,
): Required<StickyCellsConfig>;

STICKY_GRID_CLASS: string;

STICKY_ACTIVE_CLASS: string;

STICKY_PIN_ANIMATING_CLASS: string;

STICKY_PIN_ANIMATION_MS: 180;

STICKY_INDEX_SLICE_MS: 4;

STICKY_INDEX_SLICE_ROWS: 2500;

DEFAULT_MAX_STICKY_ROWS: 1;

class StickyRowsIndexer {
reset();
cancel();
schedule(rowIndex: number, callback: () => void);
indexSlice():;
add(rowIndex: number);
}

export function createPinnedStickyRow(
rowStore: RowStore,
rowIndex: number,
): StickyPinnedRow | null;

export function stripPluginPinnedRows(source: DataType[]): DataType[];

export function isPluginPinnedRow(row: DataType): row is StickyPinnedRow;

export function isSamePinnedTopSource(current: DataType[], next: DataType[]): boolean;

StickyPinnedRow (Extended from sticky-cells.pinned.ts)

Section titled “StickyPinnedRow (Extended from sticky-cells.pinned.ts)”
export type StickyPinnedRow = DataType & {
[STICKY_PINNED_ROW_SOURCE_INDEX]?: number;
};

export function isStickyCell(model: CellTemplateProp): boolean;

export type StickyRowCache = Map<DimensionCols, Set<number>>;

class StickyCellResolver {
clear();
resolveStickyColumns(rowIndex: number): StickyRowCache | null;
rememberStickyCell(rowIndex: number, colType: DimensionCols, columnIndex: number);
}

Captures the main vertical scroll state before Sticky Cells mutates rowPinStart.

The returned callback must run after the pinned source update. It restores the user’s visual scroll anchor once RevoGrid has had a chance to lay out the new pinned top height.

export function captureVerticalScrollAnchor(
revogrid: HTMLRevoGridElement,
options: ScrollAnchorOptions =;

export function resolveStickyCellPredicate(
stickyCell: StickyCellPredicate | undefined,
model: CellTemplateProp,
): boolean;