@jsvision/datagrid / mountCellOverlay
Function: mountCellOverlay()
mountCellOverlay(
args): () =>void
Defined in: datagrid/src/overlay.ts:116
Mount view over a cell: place it on the cell derived from a body-local cell rect (correct even when the grid is nested far from the screen origin — the host's own offset is not double-counted), focus it through the loop seam, and return a disposer that removes the view and disposes its reactive scope (so its binding effects do not leak after the overlay closes). There is no frame or border — it is a bare cell-aligned mount.
Pass either a pre-built view or a build callback. build runs inside the mount's reactive root, so an editor that creates binding effects at construction time (a typed editor's field bridges do) has those effects owned by this scope and disposed on close. A build that returns null mounts nothing (a read-only editor) and the returned disposer just tears down the empty root.
Parameters
args
host (the grid's absolute overlay group), loop (the focus seam), rect (body-local cell rect), origin (the body's absolute origin, e.g. from absoluteRect), exactly one of view (a pre-built editor) or build (a factory run inside the root, returning the editor or null), and optional clamp — pass the host-local viewport { width, height } to keep the mounted built-in responsive view within it on both axes; omit it for a cell-pinned editor. If a custom view set its own absolute layout, that size is honored even when larger than the clamp, while its origin is moved as far inside as possible. A view exposing desiredSize() opts into reactive remeasurement, viewport sizing, and re-anchoring whenever its desired geometry changes.
build?
() => View | null
clamp?
{ height: number; width: number; }
clamp.height
number
clamp.width
number
host
Group
loop
{ focusView: void; }
loop.focusView
origin
{ x: number; y: number; }
origin.x
number
origin.y
number
rect
view?
View
Returns
A dispose() that removes the view and disposes its reactive scope (idempotent-safe to call once).
() => void
Example
import { Group, Input, signal, createEventLoop, resolveCapabilities } from '@jsvision/ui';
import { column, fromRows, EditableDataGrid, mountCellOverlay, absoluteRect } 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: 20, height: 6 }, { caps });
loop.mount(root);
// Mount an editor over the focused cell (rect in body-local coords):
const editor = new Input({ value: signal('Ada') });
const dispose = mountCellOverlay({
host: grid.overlay,
loop,
rect: { x: 2, y: 1, width: 8, height: 1 },
origin: absoluteRect(grid.rows),
view: editor,
});
// ...later, when editing ends:
dispose();