Skip to content

Context Menu

HTMLRevoGridElement (Extended from global)

Section titled “HTMLRevoGridElement (Extended from global)”
interface HTMLRevoGridElement {
/**
* Context menu configuration for row and body-cell targets.
*/
rowContextMenu?: ContextMenuConfig;
/**
* Context menu configuration for column-header targets.
*/
columnContextMenu?: ContextMenuConfig;
/**
* Legacy/shared context menu configuration. Used as a fallback when target-specific
* row/column configs are not provided.
*/
contextMenu?: ContextMenuConfig;
/** Kebab-case alias for framework/native custom element bindings. */
'row-context-menu'?: ContextMenuConfig;
/** Kebab-case alias for framework/native custom element bindings. */
'column-context-menu'?: ContextMenuConfig;
/** Kebab-case alias for framework/native custom element bindings. */
'context-menu'?: ContextMenuConfig
}

AdditionalData (Extended from @revolist/revogrid)

Section titled “AdditionalData (Extended from @revolist/revogrid)”
interface AdditionalData {
/**
* The context menu configuration for row and body-cell targets.
*
* @example
* ```typescript
* grid.additionalData = {
* rowContextMenu: { items: [{ name: 'Edit', action: () => console.log('Edit action') }] },
* };
* ```
*
* Prefer the direct `grid.rowContextMenu` property when the framework wrapper supports it.
*/
rowContextMenu?: ContextMenuConfig;
/**
* The context menu configuration for column-header targets.
*
* @example
* ```typescript
* grid.additionalData = {
* columnContextMenu: { items: [{ name: 'Autosize', action: () => console.log('Autosize') }] },
* };
* ```
*
* Prefer the direct `grid.columnContextMenu` property when the framework wrapper supports it.
*/
columnContextMenu?: ContextMenuConfig
}
export function getContextMenuPrimaryShortcut(
key: string,
platform = globalThis.navigator?.platform,
): string;

Locate the active Core or Pro filter runtime without forcing filter setup.

export function getContextMenuFilterPlugin(
context: ContextMenuActionContext,
): ContextMenuFilterPlugin | undefined;

Open the existing filter popup while preserving the original synchronous API.

export function openContextMenuColumnFilter(
context: ContextMenuActionContext,
column: ColumnRegular,
): boolean;

Open the existing filter popup and await its full async lifecycle.

export async function openContextMenuColumnFilterAsync(
context: ContextMenuActionContext,
column: ColumnRegular,
): Promise<boolean>;

Adds configurable context menus to RevoGrid.

The plugin supports separate rowContextMenu and columnContextMenu configurations while keeping contextMenu as a legacy fallback. Column menus receive the current column, virtual column index, and column section, so a single columnContextMenu can resolve different menu items for regular, left-pinned, right-pinned, or specific columns.

Example:

import { ContextMenuPlugin } from '@revolist/revogrid-pro'
const grid = document.createElement('revo-grid');
grid.plugins = [ContextMenuPlugin];
grid.rowContextMenu = { items: [{ name: 'Delete row' }] };
grid.columnContextMenu = {
items: [{ name: 'Autosize column' }],
resolve(context) {
if (context.target === 'column' && context.columnType === 'colPinStart') {
return { items: [{ name: 'Unpin left column' }] };
}
},
};
  • Event integration RowHeaderPlugin: Integrates with RowHeaderPlugin row menu events when present.
class ContextMenuPlugin {
/**
* Registers additive items that are resolved whenever a context menu opens.
*
* The application config and its `resolve` callback run first. Contributions
* are then appended in ascending `order`, with registration order breaking
* ties. The returned disposer is safe to call more than once.
*/
registerContribution(contribution: ContextMenuContribution): () => void;
/**
* Applies defaults to a partial context menu config.
*
* @param config - User-provided menu config.
* @param targetSelectors - Default selectors for the target-specific config.
*/
getConfig(config: Partial<ContextMenuConfig> = {}, targetSelectors: string[] = ['.rgCell']);
/**
* Resolves a rendered header target to the same semantic column context used
* by the shared context menu.
*/
resolveColumnContext(
target: HTMLElement,
event?: MouseEvent,
): ColumnContextMenuOpenContext;
/**
* Hides the context menu popup without clearing the active config.
*/
close(restoreFocus = true);
/**
* Opens the context menu for a DOM target.
*
* If `menuTarget` is provided, that target config is used directly. Otherwise
* the plugin inspects the DOM target and chooses the column menu before the row
* menu. The selected config is passed through `resolve` before rendering.
*
* @param target - Element that should anchor or identify the menu target.
* @param event - Pointer event used for positioning and resolver context.
* @param menuTarget - Optional explicit target used by row-header menu events.
*/
async open(
target: EventTarget | null,
event?: MouseEvent,
menuTarget?: ContextMenuTarget,
cell?: ContextMenuCellContext,
);
clearSubscriptions();
destroy();
}

Supported high-level targets for the context menu.

row covers body cells and row-menu buttons. column covers column header cells, including pinned column sections.

/**
* Supported high-level targets for the context menu.
*
* `row` covers body cells and row-menu buttons. `column` covers column header
* cells, including pinned column sections.
*/
export type ContextMenuTarget = 'row' | 'column';

Shared context passed to dynamic menu resolvers and menu item actions.

/**
* Shared context passed to dynamic menu resolvers and menu item actions.
*/
export type ContextMenuOpenContextBase = {
/** The active menu target type. */
target: ContextMenuTarget;
/** Element that caused the menu to open. */
triggerElement: HTMLElement;
/** Mouse event that opened the menu, when opened from pointer interaction. */
triggerEvent?: MouseEvent;
/** Grid element that owns the plugin instance. */
revogrid: HTMLRevoGridElement;
/** Core plugin providers for data, dimensions, selection, columns, viewport, and plugins. */
providers: PluginProviders;
};

ContextMenuColumnGroup (Extended from index.ts)

Section titled “ContextMenuColumnGroup (Extended from index.ts)”
export type ContextMenuColumnGroup = Group & {
/** Grouping row depth in the header. */
depth?: number;
};

ColumnContextMenuOpenContext (Extended from index.ts)

Section titled “ColumnContextMenuOpenContext (Extended from index.ts)”

Context available when a menu opens from a column header target.

/**
* Context available when a menu opens from a column header target.
*/
export type ColumnContextMenuOpenContext = ContextMenuOpenContextBase & {
target: 'column';
/** Column model resolved from the header section and virtual column index. */
column?: ColumnRegular;
/** Column group model resolved when opening from a grouped header cell. */
columnGroup?: ContextMenuColumnGroup;
/** Physical column indexes covered by this menu target when it is a grouped header cell. */
columnIndexes?: number[];
/** Grouping row depth when opening from a grouped header cell. */
columnGroupDepth?: number;
/** Virtual column index inside the current column section. */
columnIndex?: number;
/** Column section that opened the menu: regular, left-pinned, or right-pinned. */
columnType?: DimensionCols;
};

RowContextMenuOpenContext (Extended from index.ts)

Section titled “RowContextMenuOpenContext (Extended from index.ts)”

Context available when a menu opens from a row/body target.

/**
* Context available when a menu opens from a row/body target.
*/
export type RowContextMenuOpenContext = ContextMenuOpenContextBase & {
target: 'row';
/**
* Exact body cell that opened the menu. This remains distinct from the
* current selection focus when a secondary click intentionally preserves an
* existing range.
*/
cell?: ContextMenuCellContext;
};

export type ContextMenuCellContext = Readonly<
Omit<Pick<
ColumnDataSchemaModel,
| 'prop'
| 'model'
| 'column'
| 'rowIndex'
| 'colIndex'
| 'colType'
| 'type'
| 'value'
>, 'colType'> & {
/** Data-column section or Core's dedicated row-header section. */
colType: DimensionCols | 'rowHeaders';
}
>;

Union of all target-specific open contexts.

/**
* Union of all target-specific open contexts.
*/
export type ContextMenuOpenContext = ColumnContextMenuOpenContext | RowContextMenuOpenContext;

Dynamic menu resolver.

Return undefined to keep the base config, return a partial config to override settings/items for this invocation, or return null to suppress the menu.

Example:

const columnContextMenu = {
items: defaultItems,
resolve(context) {
if (context.target === 'column' && context.columnType === 'colPinStart') {
return { items: pinnedColumnItems };
}
},
};
/**
* Dynamic menu resolver.
*
* Return `undefined` to keep the base config, return a partial config to override
* settings/items for this invocation, or return `null` to suppress the menu.
*
* @example
* ```ts
* const columnContextMenu = {
* items: defaultItems,
* resolve(context) {
* if (context.target === 'column' && context.columnType === 'colPinStart') {
* return { items: pinnedColumnItems };
* }
* },
* };
* ```
*/
export type ContextMenuConfigResolver = (
context: ContextMenuOpenContext,
) => Partial<ContextMenuConfig> | null | undefined;

Additive context-menu items owned by an independent plugin or feature.

Contributions are resolved alongside the active application config and are composed before or after it without mutating that config.

/**
* Additive context-menu items owned by an independent plugin or feature.
*
* Contributions are resolved alongside the active application config and are
* composed before or after it without mutating that config.
*/
export type ContextMenuContribution = {
/** Identifier unique within one `ContextMenuPlugin` instance. */
readonly id: string;
/** Ascending contribution order. Registration order breaks ties. */
readonly order?: number;
/**
* Places the contribution before or after the resolved application items.
* Defaults to `append` for backward compatibility.
*/
readonly placement?: 'prepend' | 'append';
/**
* Optional application-item filter for contexts owned by this contribution.
* Return `false` to suppress a base item without mutating its source config.
*/
readonly filterBaseItem?: (
item: ContextMenuItem,
context: ContextMenuOpenContext,
) => boolean;
/** Optional policy applied to the complete menu after all contributions compose. */
readonly filterItem?: (
item: ContextMenuItem,
context: ContextMenuOpenContext,
) => boolean;
/**
* Accessible popup name used when the application config does not provide
* one. A later, more specific contribution overrides an earlier label.
*/
readonly ariaLabel?: string | ((context: ContextMenuOpenContext) => string | undefined);
/** Resolves items for the current row or column menu invocation. */
readonly resolve: (context: ContextMenuOpenContext) => ContextMenuItem[];
};

Context passed as the fifth argument to ContextMenuItem.action.

/**
* Context passed as the fifth argument to `ContextMenuItem.action`.
*/
export type ContextMenuActionContext = {
/** Grid element that owns the plugin instance. */
revogrid: HTMLRevoGridElement,
/** Core plugin providers for data, dimensions, selection, columns, viewport, and plugins. */
providers: PluginProviders,
/** Context captured when this menu was opened. */
menu?: ContextMenuOpenContext,
};

export type ContextMenuItemStateResolver = (
item: ContextMenuItem,
focused?: Cell | null,
range?: RangeArea | null,
) => boolean;

export type ContextMenuChildrenResolver = (
focused?: Cell | null,
range?: RangeArea | null,
context?: ContextMenuActionContext,
) => ContextMenuItem[];

Single menu item definition.

/**
* Single menu item definition.
*/
export type ContextMenuItem = {
/** Stable identifier used by consumers and renderers. */
id?: string;
/**
* Item semantics. `separator` items ignore action, icon, checked, and
* children. `heading` items are non-interactive menu context. Omitted kind
* renders a standard menu item.
*/
kind?: 'item' | 'checkbox' | 'radio' | 'separator' | 'heading';
/** Text or dynamic text rendered inside the item. */
name: string | ((focused?: Cell | null, range?: RangeArea | null) => string);
/** Secondary text rendered below a heading label. */
subtitle?: string;
/** Accessible label when visible text is insufficient. */
ariaLabel?: string;
/** Keyboard shortcut hint rendered at the trailing edge. */
shortcut?: string;
/** Inline SVG rendered inside the trailing shortcut keycap. */
shortcutIcon?: string;
/** Native tooltip text, useful for explaining a disabled action. */
title?: string;
/** CSS class added to the `<li>` item. */
class?: string;
/** Icon rendered before the item name. Accepts CSS classes or inline SVG markup. */
icon?: string;
/** Apply the shared destructive-action presentation. */
danger?: boolean;
/** CSS class added to the `<li>` item, optionally calculated from selection state. */
rowClass?: string | ((item: ContextMenuItem, focused?: Cell | null, range?: RangeArea | null) => string);
/** Hide the item statically or from current selection state. */
hidden?: boolean | ContextMenuItemStateResolver;
/** Disable the item statically or from current selection state while keeping it visible. */
disabled?: boolean | ContextMenuItemStateResolver;
/** Checked state for checkbox and radio items. */
checked?: boolean | ContextMenuItemStateResolver;
/** Logical group for radio items. */
radioGroup?: string;
/** Nested submenu items or a resolver evaluated for the current menu context. */
children?: ContextMenuItem[] | ContextMenuChildrenResolver;
/** Called when the item is selected. */
action?: (event: MouseEvent, focused?: Cell | null, range?: RangeArea | null, close?: () => void, context?: ContextMenuActionContext) => void;
/** Keep the popup open after this item action runs. */
keepOpen?: boolean;
/** Custom item renderer. */
template?: (h: HyperFunc<VNode>, item: ContextMenuItem, focused?: Cell | null, range?: RangeArea | null, close?: () => void) => any;
};

Context menu configuration.

Use rowContextMenu for row/body targets and columnContextMenu for header targets. resolve can refine either menu at open time for column sections, individual columns, or any other target-specific condition.

/**
* Context menu configuration.
*
* Use `rowContextMenu` for row/body targets and `columnContextMenu` for header
* targets. `resolve` can refine either menu at open time for column sections,
* individual columns, or any other target-specific condition.
*/
export type ContextMenuConfig = {
/** Items rendered in the popup. */
items: ContextMenuItem[];
/** Accessible name for the root menu. */
ariaLabel?: string;
/** Open the menu on the native `contextmenu` event. Defaults to `true`. */
rightClick?: boolean;
/** Open the menu on left click. Defaults to `false`. */
leftClick?: boolean;
/** CSS selectors that can trigger this menu. */
targetSelectors?: string[];
/** Position the popup relative to the target element instead of pointer coordinates. */
anchorToTarget?: boolean;
/**
* Resolves a menu override for the current target before the menu opens.
* Return `null` to suppress the menu for that target, `undefined` to use the base config,
* or a partial config to override items/settings for this invocation.
*/
resolve?: ContextMenuConfigResolver;
};

Keeps each open submenu stable while the pointer crosses its sibling rows. It does no continuous pointer tracking: decisions happen only on item entry.

class ContextMenuPointerIntent {
enter(
item: HTMLElement,
event: Pick<MouseEvent, 'clientX' | 'clientY'>,
activate: () => void,
): void;
enterSubmenu(item: HTMLElement): void;
reset(): void;
}

Opens a context-menu element in the browser top layer when available. Browsers without the Popover API retain the existing display-based popup.

export function showContextMenuPopup(element: PopupElement): ContextMenuPopupMode;

Hides a popup opened by showContextMenuPopup; safe to call repeatedly.

export function hideContextMenuPopup(
element: PopupElement,
mode?: ContextMenuPopupMode,
): void;

Resolves menu coordinates in the coordinate space of the supplied boundary. The caller converts the result to grid-local coordinates for the fallback.

export function calculateContextMenuPosition({
anchorRect,
menuRect,
boundary,
anchorToTarget,
pointer,
inset = 0,
}: ContextMenuPositionOptions): { top: number; left: number };

export type ContextMenuPopupMode = 'popover' | 'fallback';

export type ContextMenuBoundary = Pick<
DOMRect,
'top' | 'right' | 'bottom' | 'left' | 'width' | 'height'
>;

export type ContextMenuPositionOptions = {
anchorRect: Pick<DOMRect, 'top' | 'right' | 'bottom' | 'left' | 'width' | 'height'>;
menuRect: Pick<DOMRect, 'width' | 'height'>;
boundary: ContextMenuBoundary;
anchorToTarget: boolean;
pointer?: Pick<MouseEvent, 'clientX' | 'clientY'>;
inset?: number;
};

Resolves Core’s full-width synthetic group renderer to a semantic cell-like context. Group rows are intentionally not focusable and therefore do not emit the normal beforecellfocus payload used by ordinary body cells.

export function resolveGroupingRowCellContext(
target: HTMLElement,
providers: PluginProviders,
): ContextMenuCellContext | undefined;

Resolves a rendered row-header cell when Core does not emit the ordinary beforecellfocus payload. Row headers share the row data store but live in their own column viewport, so their context must be reconstructed from the rendered virtual row index.

export function resolveRowHeaderCellContext(
target: HTMLElement,
providers: PluginProviders,
): ContextMenuCellContext | undefined;

Whether a target belongs to Core’s dedicated row-header viewport.

export function isRowHeaderCellTarget(target: HTMLElement): boolean;

Core body targets that have row context-menu semantics.

DEFAULT_ROW_CONTEXT_MENU_TARGET_SELECTORS: string[];

export function resetContextMenuPointerIntent(element?: HTMLElement): void;

export function resetContextMenuInteractionState(element?: HTMLElement): void;

export function renderMenuItemIcon(icon?: string);

Resolves dynamic children and removes hidden, empty, leading, trailing, and consecutive separators without mutating application-owned menu items.

export function normalizeContextMenuItems(
items: ContextMenuItem[],
focused?: Cell | null,
range?: RangeArea | null,
context?: ContextMenuActionContext,
): ContextMenuItem[];

export function calculateContextSubmenuPosition(input: {
itemRect: Pick<DOMRect, 'top' | 'right' | 'left'>;
menuRect: Pick<DOMRect, 'width' | 'height'>;
viewportWidth: number;
viewportHeight: number;
inset?: number;
});

export function handleContextMenuKeyDown(event: KeyboardEvent, close: () => void): void;

Extra VNode renderer registered by ContextMenuPlugin.

It reads the plugin instance state (config, activeContext, selection, and close handler) and renders the current popup items. Menu item actions receive the latest activeContext, which lets column menu actions know the exact pinned section and column that opened the menu.

export function contextPopUp(this: {
contextMenu?: HTMLElement | undefined;
providers: PluginProviders;
revogrid: HTMLRevoGridElement;
config?: ContextMenuConfig;
activeContext?: ContextMenuOpenContext;
close: () => void;
});

Registered extra VNode name for the context-menu popup.

The plugin uses this value to replace any previous popup renderer when the plugin is re-created, preventing duplicate popup nodes.

POP_EL: string;