Import these from @grafloria/engine.
Classes
GridPackEngine
tsclass GridPackEngine
Properties
| Name | Type | Default | Description |
|---|---|---|---|
float | boolean | ||
maxRows? | number | Row bound (see GridPackOptions.maxRows). Undefined = unbounded. Changed through {@link setBound}. | |
capacity? | number | Row capacity (see GridPackOptions.capacity). Undefined = unbounded. |
Methods
get columns(): number— Live column count. Change it only through {@link setColumns}.constructor(items: GridPackItem[] = [], options: GridPackOptions = {})getItems(): readonly GridPackItem[]getItem(id: string): GridPackItem | undefinedrows(): number— Content height in rows: max(y+h) over all items (0 when empty).hasOverlaps(): boolean— True when any two items overlap — the invariant every op must preserve.add(item: GridPackItem): GridPackItem | null— Add an item. An explicit legal position is honoured verbatim. When the position collides — or the item asks forautoPosition— the tile AUTO-POSITIONS: a row-major scan for the first hole it fits, which is gridstack'sautoPositionand NOT the same thing as gravity (gravity climbs one column; a hole at (3,0) under an occupied column is only reachable by the scan — the spec's first red proved it).remove(id: string): voidbeginGesture(): void— Begin a drag/resize gesture: fresh displaced-tile memory, and a full snapshot socancelGesture(Escape) can restore every tile (gridstacksaveInitial/restoreInitial).endGesture(): void— End a gesture: memory does NOT outlive it (E2, and the S4 swap lock).cancelGesture(): void— Escape: restore every tile to its gesture-start cell AND size, bring back the tiles removed during the gesture, drop the ones added, and restore the bound. Surviving tiles keep their object identity (a binder holds them).setBound(rows: number): boolean— Change the row bound — a container asking for rows on behalf of a child (tile first, step 1). Refused below the current content. Inside a gesture the change rides in the snapshot, so Escape gives the rows back.moveCheck(id: string, x: number, y: number, options: MoveCheckOptions = {}): GridPackResult— Try to putidat cell (x,y). Applies the full pipeline on acceptance: swap (three shapes) | push-down (+skip below locked) → settle (teleport memory + gravity). Refuses: out-of-gesture no-ops, cells intersecting a locked tile (E4b), and collisions under the anti-jitter coverage gate.{ gate: false }(see {@link MoveCheckOptions}) is first-placement mode: gate and swaps are skipped, push-down still applies, E4b still refuses.resizeCheck(id: string, w: number, h: number, options: ResizeCheckOptions = {}): GridPackResult— Resizeidto w×h cells. Growth is CLAMPED so the tile never covers a locked tile (E4b applied to size); displaced neighbours push + settle, and return when the size shrinks back (E1/S2).placeBeside(id: string, neighbourId: string, side: BesideSide, row?: number): PlaceBesideResult— PutidNEXT TOneighbourIdonside, atrow(the pointer's row, clamped to the neighbour's rows; the neighbour's own row by default) — the one sideways primitive the tile-first drag model needs (step 1).
With room on that side the mover simply takes the cell. At the board's edge the neighbour SHIFTS over by the mover's span and the mover takes the edge — the fluid demo's side panel sits at the right edge and "after it" was nowhere. With no room even shifted (a full-width neighbour), the mover takes the cell and the neighbour goes DOWN under it, the way any tile gives way. Top always pushes; bottom always places.
The mover steps off the board while the neighbour shifts: its own cell must not be what refuses the shift (a chart as wide as the panel, lab L94). Locked tiles refuse as everywhere; a bound rollback names itself.
setColumns(next: number, layout: GridColumnLayout = 'moveScale'): boolean— Change the board's COLUMN COUNT — gridstack'scolumn(n, layout), and the whole of responsive behaviour in one operation.
Three things happen, in this order:
- THE LAYOUT WE ARE LEAVING IS CACHED under its own column count. This is the load-bearing step: without it, 12 → 1 → 12 would have to re-derive twelve columns from a one-column stack and every tile would come back full width.
- GROWING RESTORES FROM THE CACHE, per item. Items the cache knows come back at exactly the cells they had the last time the board was this wide; items it does not know (added while narrow) fall through to the scale rules below. Shrinking never restores — a narrower layout is always derived from where the board is NOW, which is what makes a gradual squeeze look natural.
- THE REMAINDER IS SCALED by
layout(see {@link GridColumnLayout}),columns === 1forcing a single stack, and everything is re-placed in reading order so the result cannot overlap.
Returns true when the count actually changed.
saveLayout(): { columns: number; items: GridPackItem[] }— The layout to PERSIST — gridstack'ssave(), which serialises from the LARGEST cached column count rather than the live one. Saving while the board is narrow (a phone) therefore saves the DESKTOP layout: the cells a user authored at full width are the document, and the narrow arrangement is a projection of it.
h is never cached because it does not depend on the column count, so it
always comes from the live item; items the widest cache does not know
(added while narrow) contribute their live cells, which are legal at any
count at least as wide.
cachedColumns(): number[]— The column counts the cache currently holds a layout for (ascending).getLayouts(): GridLayoutCache— The cache as plain data — hand it to a rebuilt engine via {@link setLayouts}.setLayouts(cache: GridLayoutCache): void— Adopt a cache exported by {@link getLayouts}. The kit calls this after rebuilding its engine from the model (sync()), which would otherwise throw the wider layouts away on every undo, add or refresh.
Interfaces
CachedCell
One item's cached geometry at a column count. h is column-independent.
tsinterface CachedCell
Properties
| Name | Type | Default | Description |
|---|---|---|---|
x | number | ||
y | number | ||
w | number |
GridPackItem
One tile, in integer grid cells.
tsinterface GridPackItem
Properties
| Name | Type | Default | Description |
|---|---|---|---|
id | string | ||
x | number | ||
y | number | ||
w | number | ||
h | number | ||
locked? | boolean | Pinned: never pushed, never packed, refuses the mover outright (E4b). | |
solid? | boolean | SOLID (tile first, step 3): a container. Never pushed by a PASSING tile and never packed — a widget carried over it slides aside, so the board under the hand holds still and the container's zones stay reachable — but moved by INTENT: a mover that asks pushSolid (a moved section, a dock, a refused adoption), placeBeside, or a direct move of its own. | |
minW? | number | Per-item SIZE LIMITS in cells (gridstack's minW/maxW/minH/maxH). A resize clamps to them, and a column change scales a width only within them. They never move a tile: a push or a swap is not a resize. | |
maxW? | number | ||
minH? | number | ||
maxH? | number | ||
autoPosition? | boolean | Ask add() to IGNORE x/y and scan row-major for the first free hole — gridstack's autoPosition (addWidget without coordinates). Distinct from gravity, which climbs one column: a hole at (3,0) under an occupied column is only reachable by the scan. Seeding/load honours explicit cells; palette-style adds pass this flag. |
GridPackOptions
tsinterface GridPackOptions
Properties
| Name | Type | Default | Description |
|---|---|---|---|
columns? | number | Column count of the board. Default 12. | |
float? | boolean | Float mode (gridstack float: true): tiles stay where placed and gaps are legal; gravity does not pack. Default false (gravity). | |
maxRows? | number | Row bound for a board whose DESIGN is a fixed strip (the nested KPI section: one row, always). Any op whose settled result would exceed it — a height resize, a width resize whose push spills a sibling down, a move displacing someone out of bounds — ROLLS BACK wholesale and reports changed: false; add() returns null when nothing can fit. | |
capacity? | number | Row CAPACITY of a board whose frame can hold only so many rows — the dashboard kit's bounded fit mode (a fit board never changes size; past its row floor it refuses rather than overflows). |
GridPackResult
Result of a move/resize attempt.
tsinterface GridPackResult
Properties
| Name | Type | Default | Description |
|---|---|---|---|
changed | boolean | Whether the board accepted (and applied) the change. | |
refusedBy? | GridPackRefusal | Present on every refusal, absent on an accepted change. |
MoveCheckOptions
Options for {@link GridPackEngine.moveCheck}.
tsinterface MoveCheckOptions
Properties
| Name | Type | Default | Description |
|---|---|---|---|
gate? | boolean | The >50% anti-jitter coverage gate AND the swap heuristics it feeds. gate: false is the FIRST-PLACEMENT mode (a palette drag-in entering the board, or a dragged-out tile re-entering — gridstack's dragInNode behaviour): the cell is taken unconditionally — locked tiles still refuse (E4b), but any unlocked occupant is pushed down regardless of coverage, and no swap shape fires (an entering tile … | |
pushSolid? | boolean | Push SOLID tiles in the way as if they were plain — the mover means it (a moved section, a dock, a refused adoption). Default false. |
PlaceBesideResult
Also has every member of GridPackResult, listed on its own entry.
Result of {@link GridPackEngine.placeBeside}.
tsinterface PlaceBesideResult extends GridPackResult
Properties
| Name | Type | Default | Description |
|---|---|---|---|
how? | 'placed' | 'shifted' | 'pushed' | placed: the cell beside the neighbour was free (or only unlocked tiles were in it, pushed down); shifted: no room on that side of the board, the neighbour moved over by the mover's span and the mover took the edge; pushed: no room even shifted — the mover took the cell and the neighbour went down under it, the way any tile gives way. |
ResizeCheckOptions
Options for {@link GridPackEngine.resizeCheck}.
tsinterface ResizeCheckOptions
Properties
| Name | Type | Default | Description |
|---|---|---|---|
pushSolid? | boolean | Grow INTO solid tiles, pushing them, instead of clamping at them — a dock taking its band means it. Default false. |
Types
BesideSide
Also has every member of String, listed on its own entry.
The side of a neighbour a tile is placed against.
tstype BesideSide = 'left' | 'right' | 'top' | 'bottom';
GridColumnLayout
Also has every member of String, listed on its own entry.
How a COLUMN-COUNT change re-lays the board out — gridstack's
ColumnOptions, recorded from its documented semantics:
'moveScale' (default) — scale both x and w by newColumns/oldColumns, so the board keeps its proportions at any width; 'move' — scale x only; widths survive verbatim (clamped to fit); 'scale' — scale w only; x survives verbatim (clamped to fit); 'none' — keep x and w exactly; clamp only what no longer fits.
Whatever the mode, columns === 1 forces a SINGLE STACK (every tile x=0,
w=1) — the phone layout — and every mode re-places the result in reading
order afterwards, so the outcome can never overlap.
tstype GridColumnLayout = 'moveScale' | 'move' | 'scale' | 'none';
GridLayoutCache
The PER-COLUMN LAYOUT CACHE, as plain data: column count → item id → cell. Exported/imported so a host that rebuilds its engine (the kit's sync())
carries the wider layouts across the rebuild instead of losing them.
tstype GridLayoutCache = Record<number, Record<string, CachedCell>>;
GridPackRefusal
Also has every member of String, listed on its own entry.
Why a change was refused (tile first, step 1). A binder used to read
changed:false as "refused" when it also means "already there", and asked
the tile where it was instead; now every refusal names itself.
tstype GridPackRefusal = 'locked' | 'solid' | 'bound' | 'gate' | 'noop' | 'missing';
Was this page helpful?