# DashboardGridHandle

Import it from `@grafloria/element`.

```ts
interface DashboardGridHandle
```

**Members**

- `sync(): void` — Rebuild the engine from the group's members + their cells, re-project pixels.
- `setSizing(mode: 'fit' | 'grow'): void`
- `getSizing(): 'fit' | 'grow'`
- `setFloat(on: boolean): void` — Engine float mode, live (the prototype's second toggle): ON — tiles stay
exactly where placed, vertical gaps are legal; OFF — gravity re-packs
upward immediately.
- `getFloat(): boolean`
- `setColumns(n: number, layout?: GridColumnLayout, opts?: { responsive?: boolean }): boolean` — Change the COLUMN COUNT live (gridstack's `column(n, layout)`), through the
engine's per-column layout cache: shrinking caches the layout it leaves,
growing back restores it. Returns true when the count actually changed.

Calling this directly PINS the count — it switches the responsive
evaluator off, so a board under an explicit count is not fought by its own
width observer. `setColumns(n, layout, { responsive: true })` is the
evaluator's own path back.
- `getColumns(): number`
- `setRtl(on: boolean): void` — RTL mirroring, live. Cells never change — only the pixels.
- `getRtl(): boolean`
- `setStatic(on: boolean): void` — Static mode, live: pointer gestures off (and handles gone) or back on.
- `getStatic(): boolean`
- `setDragHandle(v: DragHandleOption): void` — Drag-handle mode, live: `true` = the caption strip, a selector = your own handle, `{ grip: true, … }` = a painted grip, `false` = the whole card.
- `getDragHandle(): DragHandleOption`
- `focusWidget(id: string): boolean` — Move keyboard focus to a member (the roving tabindex lands on it). The
host takes DOM focus when it exists; returns false for a non-member.
- `getFocusedWidget(): string | undefined` — The member the roving tabindex currently rests on.
- `selectWidget(id: string | undefined): boolean` — SELECT a member without moving keyboard focus — what a mouse press does
(the renderer cancels the press's default, so a click never focuses the
host). `undefined` clears. False for a non-member.
- `getSelectedWidget(): string | undefined` — The selected member: the one wearing the ring and, in grip mode, the grip.
- `saveLayout(): { columns: number; cells: Map<string, CellRect> }` — The layout to PERSIST — from the engine's LARGEST cached column count, so
saving while the board is narrow still saves the wide layout the user
authored (gridstack's `save()` semantics).
- `metrics(): { columns: number; maxColumns: number; rtl: boolean; responsive: boolean; fluid: boolean; static: boolean; dragHandle: DragHandleOption; capacity: number | undefined; gap: number; padding: number; sizing: 'fit' | 'grow'; rows: number; rowHeight: number; columnUnit: number; boardHeight: number; frame: WorldRect; }` — Live board metrics (mapping inputs + derived row height / rows).
- `willItFit(w: number, h: number): boolean` — Would a w×h tile fit on the board as it is now (gridstack's `willItFit`)? Always true on an unbounded board; on a bounded fit board this is what
`addWidget()` asks before creating anything.
- `cellOf(id: string): CellRect | undefined` — The engine's cell record for a member (undefined when not a member).
- `cellRectOf(id: string): WorldRect | undefined` — World rect the member's current cells project to.
- `planRemoval(id: string): Command[]` — Commands that reconcile the survivors after removing `id` — fold into the remove batch.
- `moveTo(id: string, x: number, y: number): Promise<boolean>` — Programmatic single-step gestures — the demo asserts' deterministic hook. Same pipeline as a pointer gesture, committed as ONE BatchCommand.
- `resizeTo(id: string, w: number, h: number): Promise<boolean>`
- `beginPaletteDrag( node: NodeModel, spec: { w: number; h: number; chip?: HTMLElement }, event: PointerEvent ): void` — Palette drag-in: `node` is a DETACHED widget node (not yet in the model). A chip follows the cursor; entering the board places the node's item in
the engine (first placement skips the anti-jitter gate, as gridstack's
drag-in does) and the normal live-push loop takes over. Release inside →
`onDropIn`; release outside / Escape → aborted, nothing committed.
- `dispose(): void`
