Skip to main content

packGrid

Bin-packing utility that places items into a 2D grid respecting each item's column and row span. Items are placed left-to-right, top-to-bottom into the first available slot that fits — the same algorithm used by mobile home screens.

Import

import { packGrid } from 'react-native-drax';

Usage

const result = packGrid(items.length, 4, (index) => ({
colSpan: items[index].colSpan,
rowSpan: items[index].rowSpan,
}));

// result.positions[i] = { row: number, col: number }
// result.totalRows = number of rows needed

Signature

packGrid(
count: number,
numColumns: number,
getSpan: (index: number) => GridItemSpan,
): GridPackResult

Parameters

ParameterTypeDescription
countnumberNumber of items to pack
numColumnsnumberNumber of columns in the grid
getSpan(index: number) => GridItemSpanReturns span for item at index

Return Value: GridPackResult

interface GridPackResult {
/** Grid position (row, col) for each item, in input order */
positions: { row: number; col: number }[];
/** Total number of rows in the packed grid */
totalRows: number;
}

Converting to Pixel Positions

const cellSize = 80;
const gap = 8;

const pixelPositions = result.positions.map((pos, i) => ({
x: pos.col * (cellSize + gap),
y: pos.row * (cellSize + gap),
width: items[i].colSpan * cellSize + (items[i].colSpan - 1) * gap,
height: items[i].rowSpan * cellSize + (items[i].rowSpan - 1) * gap,
}));

const totalHeight = result.totalRows * (cellSize + gap) - gap;

Example

A 4-column grid with mixed items:

Input order: [2×2, 1×1, 1×1, 1×1, 1×1, 2×1]

Packed layout:
┌───────┐ ┌───┐ ┌───┐
│ 2×2 │ │1×1│ │1×1│
│ │ ├───┤ ├───┤
│ │ │1×1│ │1×1│
└───────┘ └───┘ └───┘
┌───────────────┐
│ 2×1 │
└───────────────┘