GridConfig.contextMenu turns the built-in right-click menu on or off, or replaces its rows with a static list or a context-aware factory.
// Right-click a cell, then choose Inspect cell to log its stored value.
Result: right-clicking Ada opens these three menu rows, with a separator after Copy value. The cell value is unchanged. Static preview; the copy shortcut is shown for Windows/Linux.
Configuration example (requires an initialized grid)
This configuration excerpt needs an initialized grid. For the result above, use a sheet with "Ada" in A1, then pass config to createGrid or call grid.setConfig(config).
A right-click on a cell shows three rows: Copy value , Inspect cell and Download CSV . When the pointer resolves no cell, Inspect cell is hidden.
On a right-click, Sheetwrite prevents the browser menu, hit-tests the pointer, and selects the resolved cell. Then it evaluates each item's visible and disabled policy.
ContextMenuItems is either a readonly ContextMenuItem[] or a factory evaluated for each ContextMenuContext.
contextMenu valueResult true (default)The default menu. falseNo bundled menu. readonly ContextMenuItem[]Static readonly rows. (context) => ContextMenuItem[]Rows built for each right-click context.
Item field Meaning idStable row id. actionA built-in action name (below). labelVisible text. shortcutShortcut hint. visible / disabledA boolean, or a predicate that receives the lean ContextMenuContext. onClick(grid, cell)Host callback. It overrides action.
The lean ContextMenuContext carries only cell, clientX, and clientY.
The built-in action names are:
Clipboard/content Rows Columns View/export cut, copy, paste, clearContentsinsertRowAbove, insertRowBelow, deleteRow, hideRow, showAllRows, autoFitRowinsertColumnLeft, insertColumnRight, deleteColumn, hideColumn, showAllColumns, autoFitColumnclearFilter, merge, unmerge, exportCsv, exportXlsx
The default menu contains copy, cut, paste, clear contents, row insert/delete/hide/show/auto-fit, column insert/delete/hide/show/auto-fit, clear column filter, merge, and unmerge actions, with separators between groups. exportCsv and exportXlsx are not in the default menu, but you can use them in a custom list. XLSX still requires @sheetwrite/xlsx/register.
For fully host-owned UI, set contextMenu: false and bind the DOM contextmenu event on the host. grid.getCellAtPoint(event.clientX, event.clientY) resolves the pointer without exposing renderer internals. The host then owns preventDefault, selection, positioning, dismissal, and calls to grid.actions. Sheetwrite does not prescribe the host's event lifecycle:
host . addEventListener ( "contextmenu" , ( event ) => {
new CustomEvent ( "sheetwrite:context-menu" , {
Temporary highlights
grid.highlightCells(ranges, color?) draws an overlay, not a document edit. Pass null to clear all temporary highlights. color overrides the theme highlight color; a range can also carry its own color.
Undo does not clear a highlight.
Choose a distinct overlay color, so users can tell it from selection and cell formatting.
Use grid.styleRange when a fill must be saved and undoable.
The Vanilla workbench offers Clear highlight in its context menu. Right-click the highlighted cell to toggle it off, or right-click another cell and choose Clear highlight . Both actions write to the host event log.
Edge cases and limits
Hidden separators are normalized.
Disabled rows cannot invoke actions.
Built-in export actions show an alert and emit one export-error event on failure.
See also
const config: GridConfig const config : GridConfig const config : GridConfig Built-in UI controls; providing an object enables the toolbar unless toolbar is false. API reference → interface GridConfig interface GridConfig interface GridConfig Toolbar / feature configuration. When config is set the built-in toolbar is shown; control flags default to true except the opt-in export flag. Example import type { GridConfig } from "@sheetwrite/core" ;
const config : GridConfig = {
toolbar: true ,
contextMenu: [{ action: "copy" }, { action: "paste" }],
keyboard ( event , grid ) {
if (event.altKey && event.key === "b" ) {
grid.actions. toggleBold ();
return true ;
}
return false ;
},
}; See also Grid.setConfig * See also ContextMenuItem API reference → const grid: Grid const grid : Grid const grid : Grid The imperative core grid this controller owns. API reference → Grid.setConfig(config: GridConfig | undefined): void Grid. setConfig (config: GridConfig | undefined ): void Grid. setConfig (config: GridConfig | undefined ): void Reconfigure built-in chrome and keyboard handling without replacing the Grid or clearing selection/history. Construction-bound GridOptions are not accepted here. API reference → const config: {
contextMenu: (context: ContextMenuContext) => ({
id: string;
action: "copy";
label: string;
shortcut: "copy";
visible?: undefined;
disabled?: undefined;
onClick?: undefined;
} | {
action: "separator";
id?: undefined;
label?: undefined;
shortcut?: undefined;
visible?: undefined;
disabled?: undefined;
onClick?: undefined;
} | {
id: string;
label: string;
visible: boolean;
disabled: ({ cell }: ContextMenuContext) => boolean;
onClick(grid: Grid, cell: CellAddress | null): void;
action?: undefined;
shortcut?: undefined;
} | {
action: "exportCsv";
... 5 more ...;
onClick?: undefined;
})[];
} const config : {
contextMenu : ( context : ContextMenuContext ) => ({
id : string ;
action : "copy" ;
label : string ;
shortcut : "copy" ;
visible ?: undefined ;
disabled ?: undefined ;
onClick ?: undefined ;
} | {
action : "separator" ;
id ?: undefined ;
label ?: undefined ;
shortcut ?: undefined ;
visible ?: undefined ;
disabled ?: undefined ;
onClick ?: undefined ;
} | {
id : string ;
label : string ;
visible : boolean ;
disabled : ({ cell } : ContextMenuContext ) => boolean ;
onClick ( grid : Grid , cell : CellAddress | null ) : void ;
action ?: undefined ;
shortcut ?: undefined ;
} | {
action : "exportCsv" ;
... 5 more ...;
onClick ?: undefined ;
})[];
} const config : {
contextMenu : ( context : ContextMenuContext ) => ({
id : string ;
action : "copy" ;
label : string ;
shortcut : "copy" ;
visible ?: undefined ;
disabled ?: undefined ;
onClick ?: undefined ;
} | {
action : "separator" ;
id ?: undefined ;
label ?: undefined ;
shortcut ?: undefined ;
visible ?: undefined ;
disabled ?: undefined ;
onClick ?: undefined ;
} | {
id : string ;
label : string ;
visible : boolean ;
disabled : ({ cell } : ContextMenuContext ) => boolean ;
onClick ( grid : Grid , cell : CellAddress | null ) : void ;
action ?: undefined ;
shortcut ?: undefined ;
} | {
action : "exportCsv" ;
... 5 more ...;
onClick ?: undefined ;
})[];
} Built-in UI controls; providing an object enables the toolbar unless toolbar is false. API reference → GridConfig.contextMenu?: boolean | ContextMenuItems | undefined interface GridConfig {
contextMenu ?: boolean | ContextMenuItems | undefined ;
} interface GridConfig {
contextMenu ?:
| boolean
| ContextMenuItems
| undefined ;
} Built-in menu, disabled menu, static rows, or a request-aware row factory. API reference → context: ContextMenuContext let context : ContextMenuContext let context : ContextMenuContext API reference → ContextMenuItem.id?: string | undefined interface ContextMenuItem {
id ?: string | undefined ;
} interface ContextMenuItem {
id ?: string | undefined ;
} Stable host identifier, exposed as data-context-menu-item. API reference → ContextMenuItem.action?: ContextMenuActionName | undefined interface ContextMenuItem {
action ?: ContextMenuActionName | undefined ;
} interface ContextMenuItem {
action ?:
| ContextMenuActionName
| undefined ;
} Built-in action to bind (or "separator"). Omit when supplying onClick. API reference → ContextMenuItem.label?: string | undefined interface ContextMenuItem {
label ?: string | undefined ;
} interface ContextMenuItem {
label ?: string | undefined ;
} Menu row text. Defaults per action. API reference → ContextMenuItem.shortcut?: KeyboardAction | KeyShortcut | undefined interface ContextMenuItem {
shortcut ?: KeyboardAction | KeyShortcut | undefined ;
} interface ContextMenuItem {
shortcut ?:
| KeyboardAction
| KeyShortcut
| undefined ;
} A bound action name or a custom key combination. An explicit combination registers onClick as a keyboard command; action names only reference the existing built-in binding. Both forms display platform-aware labels. For example, shortcut: "copy" follows the configured Copy binding, while shortcut: "Mod+Shift+K" binds this item's onClick callback. See KeyboardOptions for built-in action overrides. API reference → ContextMenuItem.visible?: boolean | ((context: ContextMenuContext) => boolean) | undefined interface ContextMenuItem {
visible ?:
| boolean
| (( context : ContextMenuContext ) => boolean )
| undefined ;
} interface ContextMenuItem {
visible ?:
| boolean
| ((
context : ContextMenuContext ,
) => boolean )
| undefined ;
} Static or request-aware visibility. Hidden separators are normalized. API reference → ContextMenuContext.cell: CellAddress | null interface ContextMenuContext {
cell : CellAddress | null ;
} interface ContextMenuContext {
cell : CellAddress | null ;
} Right-clicked cell, or null when the pointer is outside the cell body. API reference → ContextMenuItem.disabled?: boolean | ((context: ContextMenuContext) => boolean) | undefined interface ContextMenuItem {
disabled ?:
| boolean
| (( context : ContextMenuContext ) => boolean )
| undefined ;
} interface ContextMenuItem {
disabled ?:
| boolean
| ((
context : ContextMenuContext ,
) => boolean )
| undefined ;
} Static or context-aware disabled state. API reference → cell: CellAddress | null let cell : CellAddress | null let cell : CellAddress | null Right-clicked cell, or null when the pointer is outside the cell body. API reference → ContextMenuItem.onClick?: ((grid: Grid, cell: CellAddress | null) => void) | undefined interface ContextMenuItem {
onClick ?:
(( grid : Grid , cell : CellAddress | null ) => void ) | undefined ;
} interface ContextMenuItem {
onClick ?:
| ((
grid : Grid ,
cell : CellAddress | null ,
) => void )
| undefined ;
} Custom click handler; receives the grid and the right-clicked cell (null if none). API reference → grid: Grid let grid : Grid let grid : Grid The imperative core grid this controller owns. API reference → var console: Console var console : Console var console : Console Console.log(...data: any[]): void (+1 overload) Console. log ( ... data: any[]): void ( + 1 overload) Console. log ( ... data: any[]): void ( + 1 overload) The console.log() static method outputs a message to the console. MDN Reference Grid.store: Store interface Grid {
store : Store ;
} interface Grid {
store : Store ;
} Store.getCell(addr: CellAddress): ResolvedCell Store. getCell (addr: CellAddress): ResolvedCell Store. getCell (addr: CellAddress): ResolvedCell Single-cell read for interactions, API reads, and tests. NOT for the render hot path — renderers use getVisibleWindow. API reference → cell: CellAddress let cell : CellAddress let cell : CellAddress Right-clicked cell, or null when the pointer is outside the cell body. API reference → const host: HTMLElement const host : HTMLElement const host : HTMLElement HTMLElement.addEventListener<"contextmenu">(type: "contextmenu", listener: (this: HTMLElement, ev: PointerEvent) => any, options?: boolean | AddEventListenerOptions): void (+1 overload) HTMLElement. addEventListener < "contextmenu" >(type: "contextmenu" , listener: ( this : HTMLElement , ev : PointerEvent ) => any, options ?: boolean | AddEventListenerOptions): void ( + 1 overload) HTMLElement. addEventListener < "contextmenu" >(type: "contextmenu" , listener: ( this : HTMLElement , ev : PointerEvent ) => any, options ?: boolean | AddEventListenerOptions): void ( + 1 overload) The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target. MDN Reference The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target. MDN Reference event: PointerEvent let event : PointerEvent let event : PointerEvent Event.preventDefault(): void Event. preventDefault (): void Event. preventDefault (): void The preventDefault() method of the Event interface tells the user agent that if the event does not get explicitly handled, its default action should not be taken as it normally would be. MDN Reference const cell: CellAddress | null const cell : CellAddress | null const cell : CellAddress | null Right-clicked cell, or null when the pointer is outside the cell body. API reference → Grid.getCellAtPoint(clientX: number, clientY: number): CellAddress | null Grid. getCellAtPoint (clientX: number, clientY: number): CellAddress | null Grid. getCellAtPoint (clientX: number, clientY: number): CellAddress | null Resolve browser viewport coordinates to an active-sheet cell for host-owned menus and interactions. Returns null outside the cell body. API reference → MouseEvent.clientX: number interface MouseEvent {
clientX : number ;
} interface MouseEvent {
clientX : number ;
} The clientX read-only property of the MouseEvent interface provides the horizontal coordinate within the application's viewport at which the event occurred (as opposed to the coordinate within the page). MDN Reference API reference → MouseEvent.clientY: number interface MouseEvent {
clientY : number ;
} interface MouseEvent {
clientY : number ;
} The clientY read-only property of the MouseEvent interface provides the vertical coordinate within the application's viewport at which the event occurred (as opposed to the coordinate within the page). MDN Reference API reference → Grid.setSelection(sel: Selection | null): void Grid. setSelection (sel: Selection | null ): void Grid. setSelection (sel: Selection | null ): void kind: "cell" let kind : "cell" let kind : "cell" Selects one addressed cell. addr: CellAddress let addr : CellAddress let addr : CellAddress Zero-based data address of the selected cell. API reference → const cell: CellAddress const cell : CellAddress const cell : CellAddress Right-clicked cell, or null when the pointer is outside the cell body. API reference → EventTarget.dispatchEvent(event: Event): boolean EventTarget. dispatchEvent (event: Event): boolean EventTarget. dispatchEvent (event: Event): boolean The dispatchEvent() method of the EventTarget sends an Event to the object, (synchronously) invoking the affected event listeners in the appropriate order. MDN Reference var CustomEvent: new <{
cell: CellAddress | null;
x: number;
y: number;
actions: GridActions;
}>(type: string, eventInitDict?: CustomEventInit<{
cell: CellAddress | null;
x: number;
y: number;
actions: GridActions;
}> | undefined) => CustomEvent<{
cell: CellAddress | null;
x: number;
y: number;
actions: GridActions;
}> var CustomEvent : new <{
cell : CellAddress | null ;
x : number ;
y : number ;
actions : GridActions ;
}>( type : string , eventInitDict ?: CustomEventInit <{
cell : CellAddress | null ;
x : number ;
y : number ;
actions : GridActions ;
}> | undefined ) => CustomEvent <{
cell : CellAddress | null ;
x : number ;
y : number ;
actions : GridActions ;
}> var CustomEvent : new <{
cell : CellAddress | null ;
x : number ;
y : number ;
actions : GridActions ;
}>( type : string , eventInitDict ?: CustomEventInit <{
cell : CellAddress | null ;
x : number ;
y : number ;
actions : GridActions ;
}> | undefined ) => CustomEvent <{
cell : CellAddress | null ;
x : number ;
y : number ;
actions : GridActions ;
}> The CustomEvent interface represents events initialized by an application for any purpose. MDN Reference CustomEventInit<{ cell: CellAddress | null; x: number; y: number; actions: GridActions; }>.detail?: {
cell: CellAddress | null;
x: number;
y: number;
actions: GridActions;
} | undefined interface CustomEventInit <{ cell : CellAddress | null ; x : number ; y : number ; actions : GridActions ; }> { detail ?: {
cell : CellAddress | null ;
x : number ;
y : number ;
actions : GridActions ;
} | undefined } interface CustomEventInit <{ cell : CellAddress | null ; x : number ; y : number ; actions : GridActions ; }> { detail ?: {
cell : CellAddress | null ;
x : number ;
y : number ;
actions : GridActions ;
} | undefined } x: number let x : number let x : number y: number let y : number let y : number actions: GridActions let actions : GridActions let actions : GridActions Imperative action surface for binding custom toolbars/menus. API reference → Grid.actions: GridActions interface Grid {
actions : GridActions ;
} interface Grid {
actions : GridActions ;
} Imperative action surface for binding custom toolbars/menus. API reference → const sheet: string const sheet : string const sheet : string Sheet identity used by the simple data-first adapter. Defaults to sheet1. API reference → Grid.getActiveSheet(): SheetId Grid. getActiveSheet (): SheetId Grid. getActiveSheet (): SheetId Id of the currently visible sheet. API reference → Grid.highlightCells(ranges: readonly HighlightRange[] | null, color?: string): void Grid. highlightCells (ranges: readonly HighlightRange[] | null , color ?: string): void Grid. highlightCells (ranges: readonly HighlightRange[] | null , color ?: string): void Draw temporary highlights outside document history. Pass null to clear all highlights: grid.highlightCells(null). Per-range color wins over the call color. Undo does not clear highlights; use styleRange for persistent cell fills. API reference → Range.sheet: string interface Range {
sheet : string ;
} interface Range {
sheet : string ;
} Sheet identity used by the simple data-first adapter. Defaults to sheet1. API reference → Range.start: {
row: number;
col: number;
} interface Range {
start : {
row : number ;
col : number ;
};
} interface Range {
start : {
row : number ;
col : number ;
};
} Zero-based workbook column index of the first key. API reference → row: number let row : number let row : number 0-based row of the cell that holds the top-left corner. API reference → col: number let col : number let col : number 0-based column of the cell that holds the top-left corner. API reference → Range.end: {
row: number;
col: number;
} interface Range {
end : {
row : number ;
col : number ;
};
} interface Range {
end : {
row : number ;
col : number ;
};
} Exclusive workbook column index after the last key. API reference →