Data grid / foldkit-data-grid

Column state

The grid owns where its columns stand and how wide they are: a ColumnLayout plus the widths of the columns resized. A column's spec says how it starts and what it allows: width, minWidth, maxWidth, resizable and hideable.

ts
const State = Grid.columnState

const resized = State.resize(State.initial(), 'price', 90)
State.widthOf(resized)('price') // 90
State.move(resized, 'price', 'start', 0) // pinned first
const saved = JSON.stringify(State.hide(resized, 'sku'))

const { state, dropped } = State.restore(JSON.parse(saved))
// state is what was saved; dropped lists ids these columns no longer define
  • Each operation returns the state it was given when it changes nothing: a resize to the width a column has, hiding a hidden column, a move to where a column stands. A resize is clamped to the column's limits; a column that is not resizable or hideable refuses.
  • The last column shown stays shown, so the grid always has a cell to focus.
  • move(state, column, region, index) is a reorder within a region, or a pin or an unpin across them; index counts the region with the column taken out.
  • dropAt(state, column, delta) is where a column dragged delta pixels toward its region's end lands, as the index move takes: past the middle of each shown neighbour it crossed. The grid's ColumnDragStarted, ColumnDragged and ColumnDragEnded hold the drag as the column and its delta, and work the drop out when it is let go, from the widths and order as they are then.
  • A column's menu gathers these for the pointer and the keyboard: Grid.menuItems(state, column) lists pinning the column to each other region, hiding it, and showing each hidden column, each only when it changes something. MenuOpened, MenuMoved, MenuChosen and MenuClosed hold which menu is open and its active item; a chosen item is read from the menu as it stands then and sent as the column Message it stands for, so hiding from the menu ends an edit on the column, takes its header's focus and closes its menu, as ColumnHidden always does.
  • restore(saved) reads a saved state leniently: an id the columns no longer define, or one named twice, is dropped and listed in dropped; a column the save predates takes its declared place; a width is clamped. Input that is not a saved state is the initial state. The Model's own Schema, by contrast, decodes only these columns' ids, so a stored Model naming a removed column fails to decode: restore a saved layout with restore, not by decoding it as the Model.
  • widthOf(state) is the width each column is drawn at. Call it once per state: it indexes the widths.

A projection built from a hand-written layout is lenient too: a column the layout omits joins the center, an unknown id is dropped, and an id named twice keeps its first place.

Limits

  • Not built: a drag across regions to pin a column (the view's column menu pins), a Shift-click row range, more than one cell range, and a fill handle.
  • Every row is one height.