Skip to content

@jsvision/datagrid / installGridNavigation

Function: installGridNavigation()

installGridNavigation(loop, grids): () => void

Defined in: datagrid/src/navigation.ts:149

Register the Tab/Shift+Tab command handlers for one or more grids and return an uninstaller.

On the command, the focused grid (the first whose body holds focus) advances by one cell. At the grid's edge ('exit') focus moves to the next/previous widget via the loop's own traversal, preserving global Tab; when no passed grid is focused, the command also falls back to that traversal. On a 'moved' result the body is re-focused explicitly — a Tab-commit may have closed the editor overlay and left no focused leaf on the grid, and the loop does not auto-recover — so the grid never goes dead. A single pair of handlers inspects every passed grid, so two grids (e.g. master-detail) never both advance.

Parameters

loop

EventLoop

The event loop the grid's app is mounted in.

grids

NavGrid | readonly NavGrid[]

One grid, or a list of grids sharing the same loop.

Returns

A function that unregisters both handlers (idempotent).

() => void

Example

ts
import { createEventLoop, resolveCapabilities, signal, Group } from '@jsvision/ui';
import { column, fromRows, EditableDataGrid, gridKeymap, installGridNavigation } from '@jsvision/datagrid';

interface Row { id: number; name: string }
const rows = signal<Row[]>([{ id: 1, name: 'Ada' }]);
const columns = [column({ id: 'name', title: 'Name', value: (r: Row) => r.name })];
const grid = new EditableDataGrid<Row>({ columns, source: fromRows(rows, { rowKey: (r) => r.id }) });
const root = new Group();
root.add(grid);

const caps = resolveCapabilities().profile;
const loop = createEventLoop({ width: 80, height: 24 }, { caps, keymap: gridKeymap });
loop.mount(root);
loop.focusView(grid.rows);
const uninstall = installGridNavigation(loop, grid);
// …later: uninstall();