Harlock.Table (harlock v0.8.0)

Copy Markdown View Source

Key-event helpers for the Harlock.Elements.table/1 widget.

A table has two movable things, and which one the arrows should move depends on how its rows were supplied:

  • enumerable rows — the row set is known, the visible window auto-centres on :focused_row, and moving the focus is what a user means. Use select_key/3, which yields {:select, row_id}.
  • a window function — there is no row set to walk and no index to centre on, so :offset is what moves. Use scroll_key/4, which yields {:scroll, offset}.

The runtime picks between them automatically for a focused table, delivering {:harlock_select, focus_id, row_id} or {:harlock_scroll, focus_id, offset} respectively — both messages that already existed.

Neither wraps. A table is read top-down and is often long, so jumping from the last row to the first reads as a glitch. menu wraps because its lists are short and cyclic movement is the convention there; this is a deliberate difference, not an inconsistency.

Summary

Functions

Move :offset for a window-function table.

Move :focused_row through a known list of row ids.

Types

row_id()

@type row_id() :: any()

Functions

scroll_key(event, offset, body_h, at_end?)

@spec scroll_key({:key, any(), [atom()]}, non_neg_integer(), pos_integer(), boolean()) ::
  {:scroll, non_neg_integer()} | :noop

Move :offset for a window-function table.

body_h is the number of rows the body can draw, and at_end? says whether the last fetch returned fewer rows than it was asked for.

That flag is doing real work. A window function is never asked how many rows exist — with keyset pagination the total may be genuinely unknown — so there is no maximum offset to clamp against. Without it, :down at the bottom would keep incrementing forever and scroll into empty space. A short fetch is the only available end-of-data signal, so the renderer reports it and this refuses to advance past it.

:end is :noop for the same reason: jumping to the last row requires knowing where it is.

select_key(event, ids, focused)

@spec select_key({:key, any(), [atom()]}, [row_id()], row_id()) ::
  {:select, row_id()} | :noop

Move :focused_row through a known list of row ids.

Returns :noop when the focus would not move, so the key falls through to update/2 instead of arriving as a message selecting what is already selected.