Package-level declarations

Types

Link copied to clipboard
data class ColumnSpec<T : Any, C, E>(val key: C, val header: @Composable (E) -> Unit, val cell: @Composable context(TableCellScope) BoxScope.(T, E) -> Unit, val valueOf: (T) -> Any?, val title: @Composable () -> String? = null, val sortable: Boolean = false, val resizable: Boolean = true, val visible: Boolean = true, val width: Dp? = null, val minWidth: Dp = 10.dp, val autoWidth: Boolean = false, val autoMaxWidth: Dp? = null, val alignment: Alignment = Alignment.CenterStart, val minRowHeight: Dp? = null, val maxRowHeight: Dp? = null, val filter: TableFilterType<*>? = null, val groupHeader: @Composable BoxScope.(Any?) -> Unit? = null, val headerDecorations: Boolean = true, val headerClickToSort: Boolean = true, val editable: Boolean = false, val canStartEdit: (T, Int) -> Boolean? = null, val editCell: @Composable BoxScope.(T, E, onComplete: () -> Unit) -> Unit? = null, val footer: @Composable BoxScope.(E) -> Unit? = null)

Declarative specification of a table column.

Link copied to clipboard

Builder for a single editable ColumnSpec. Extends ReadonlyColumnBuilder with editing capabilities.

Link copied to clipboard

DSL builder for a list of editable ColumnSpec.

Link copied to clipboard
@RequiresOptIn(message = "This table library API is experimental and may change without notice. Opt in with @OptIn(ExperimentalTableApi::class).", level = RequiresOptIn.Level.ERROR)
annotation class ExperimentalTableApi

Marked the table API while it was still settling. Nothing in the library carries it as of 2.0.0 — the API is stable and needs no opt-in.

Link copied to clipboard
open class ReadonlyColumnBuilder<T : Any, C, E>

Builder for a single readonly ColumnSpec.

Link copied to clipboard

Type alias for readonly table columns (without table data)

Link copied to clipboard

DSL builder for a list of readonly ColumnSpec.

Link copied to clipboard

Scope for a row block's header band. Distinct from TableCellScope (not a supertype of it) so a Modifier.draggableHandle call here binds unambiguously to the whole-block (outer unit) engine, while the same call inside a cell binds to whatever engine that row is rendered under.

Link copied to clipboard
class RowBlockMove(val blockId: Any?, val movedKeys: List<Any>, val afterKey: Any?, val beforeKey: Any?)

The result of one completed block-drag gesture, expressed in stable row keys so it stays meaningful however the consumer's pipeline reorders or filters the source afterwards.

Link copied to clipboard
class RowBlocks<T : Any>(val blockOf: (T) -> Any?, val onCommit: (RowBlockMove) -> Unit? = null, val blockHeader: @Composable context(RowBlockHeaderScope) (blockId: Any, rows: IntRange) -> Unit? = null, val onRowReorderWithinBlock: (RowWithinBlockMove) -> Unit? = null)

Row blocks: runs of adjacent rows that render and drag as one unit, declared by identity rather than by position — the library derives block extents from the same snapshot it renders, so they cannot go stale against an asynchronously filtered list. The consumer's data stays untouched during a gesture; the move arrives as one event at drop.

Link copied to clipboard
class RowWithinBlockMove(val blockId: Any, val movedKey: Any, val afterKey: Any?, val beforeKey: Any?)

The result of one completed within-block drag gesture: a single row moved among its block-mates, expressed in stable keys. Anchors are the moved row's visible neighbours inside the same block; a null anchor means the block's edge (first/last visible row).

Link copied to clipboard

Scope available inside table body cell content.

Link copied to clipboard

Scope available for a rendered table item.

Functions

Link copied to clipboard
fun <T> MutableList<T>.applyRowBlockMove(move: RowBlockMove, keyOf: (T) -> Any, blockOf: (T) -> Any?)

Applies move to the SOURCE list — the lift from the rendered, possibly filtered view back to the consumer's source of truth.

Link copied to clipboard
fun <T> MutableList<T>.applyRowReorderWithinBlock(move: RowWithinBlockMove, keyOf: (T) -> Any, blockOf: (T) -> Any?)

Lifts a RowWithinBlockMove to the SOURCE list: relocates the single moved row among its block-mates, using RowWithinBlockMove.afterKey as the primary anchor and beforeKey as the fallback. Block members hidden by the current filter keep their relative order; the moved row lands immediately adjacent to the resolved visible anchor. The list is left untouched when the moved row is gone, its block id no longer matches, or neither anchor resolves.

Link copied to clipboard
context(scope: RowBlockHeaderScope)
fun Modifier.draggableHandle(enabled: Boolean = true, interactionSource: MutableInteractionSource? = null, onDragStarted: (startedPosition: Offset) -> Unit = {}, onDragStopped: () -> Unit = {}, dragGestureDetector: DragGestureDetector = DragGestureDetector.Press): Modifier

Makes this modifier the drag handle for the whole block, from its header band. The node must be a descendant of the block's ReorderableItem.

context(cellScope: TableCellScope)
fun Modifier.draggableHandle(enabled: Boolean = true, interactionSource: MutableInteractionSource? = null, onDragStarted: (startedPosition: Offset) -> Unit = {}, onDragStopped: () -> Unit = {}, dragGestureDetector: DragGestureDetector = DragGestureDetector.Press): Modifier

Makes this modifier act as a drag handle for the current table item from cell content.

Link copied to clipboard
fun <T : Any, C, E> EditableTable(itemsCount: Int, itemAt: (Int) -> T?, state: TableState<C>, columns: ImmutableList<ColumnSpec<T, C, E>>, tableData: E, modifier: Modifier = Modifier, placeholderRow: @Composable () -> Unit? = null, rowKey: (item: T?, index: Int) -> Any = DefaultRowKey, rowKeyAt: (index: Int) -> Any? = null, onRowClick: (T) -> Unit? = null, onRowLongClick: (T) -> Unit? = null, onRowMove: (fromIndex: Int, toIndex: Int) -> Unit? = null, rowBlocks: RowBlocks<T>? = null, contextMenu: @Composable (item: T, pos: Offset, dismiss: () -> Unit) -> Unit? = null, customization: TableCustomization<T, C> = DefaultTableCustomization(), colors: TableColors = TableDefaults.colors(), strings: StringProvider = DefaultStrings, verticalState: LazyListState = rememberLazyListState(), horizontalState: ScrollState = rememberScrollState(), icons: TableHeaderIcons = TableHeaderDefaults.icons(), shape: Shape = RoundedCornerShape(4.dp), border: BorderStroke? = null, rowEmbedded: @Composable (rowIndex: Int, item: T) -> Unit? = null, embedded: Boolean = false, onRowEditStart: (item: T, rowIndex: Int) -> Unit? = null, onRowEditComplete: (rowIndex: Int) -> Boolean? = null, onEditCancel: (rowIndex: Int) -> Unit? = null)

Composable editable data table that renders a header and a virtualized list of rows.

Link copied to clipboard
fun <T : Any, C, E> editableTableColumns(build: EditableTableColumnsBuilder<T, C, E>.() -> Unit): ImmutableList<ColumnSpec<T, C, E>>

DSL entry to declare editable table columns.

Link copied to clipboard
fun <T> List<T>.filteredWholeRowBlocks(blockOf: (T) -> Any?, predicate: (T) -> Boolean): List<T>

Filters at block granularity: a block survives in full when ANY member matches, so the rendered blocks never show partially. The plain row-level filter stays first-class — hidden members simply travel with their block on a drag — this helper exists for consumers who want match-whole-block semantics instead.

Link copied to clipboard
context(cellScope: TableCellScope)
fun Modifier.longPressDraggableHandle(enabled: Boolean = true, interactionSource: MutableInteractionSource? = null, onDragStarted: (startedPosition: Offset) -> Unit = {}, onDragStopped: () -> Unit = {}): Modifier

Makes this modifier act as a long-press drag handle for the current table item from cell content.

Link copied to clipboard
fun <T> List<T>.sortedWithinRowBlocks(blockOf: (T) -> Any?, comparator: Comparator<in T>): List<T>

Sorts rows within each block while keeping every block whole — a plain sortedBy fragments blocks into duplicate bands. Each unit — a block or a standalone row — takes its position from its minimal member under comparator, so the list still reads as sorted at unit granularity. The sort is stable both within a block and between units: ties keep their existing order, and re-applying the same sort changes nothing.

Link copied to clipboard
fun <T : Any, C> Table(itemsCount: Int, itemAt: (Int) -> T?, state: TableState<C>, columns: ImmutableList<ColumnSpec<T, C, Unit>>, modifier: Modifier = Modifier, placeholderRow: @Composable () -> Unit? = null, rowKey: (item: T?, index: Int) -> Any = DefaultRowKey, rowKeyAt: (index: Int) -> Any? = null, onRowClick: (T) -> Unit? = null, onRowLongClick: (T) -> Unit? = null, onRowMove: (fromIndex: Int, toIndex: Int) -> Unit? = null, rowBlocks: RowBlocks<T>? = null, contextMenu: @Composable (item: T, pos: Offset, dismiss: () -> Unit) -> Unit? = null, customization: TableCustomization<T, C> = DefaultTableCustomization(), colors: TableColors = TableDefaults.colors(), strings: StringProvider = DefaultStrings, verticalState: LazyListState = rememberLazyListState(), horizontalState: ScrollState = rememberScrollState(), icons: TableHeaderIcons = TableHeaderDefaults.icons(), shape: Shape = RoundedCornerShape(4.dp), border: BorderStroke? = null, rowEmbedded: @Composable (rowIndex: Int, item: T) -> Unit? = null, embedded: Boolean = false)

Composable read-only data table that renders a header and a virtualized list of rows.

fun <T : Any, C, E> Table(itemsCount: Int, itemAt: (Int) -> T?, state: TableState<C>, columns: ImmutableList<ColumnSpec<T, C, E>>, tableData: E, modifier: Modifier = Modifier, placeholderRow: @Composable () -> Unit? = null, rowKey: (item: T?, index: Int) -> Any = DefaultRowKey, rowKeyAt: (index: Int) -> Any? = null, onRowClick: (T) -> Unit? = null, onRowLongClick: (T) -> Unit? = null, onRowMove: (fromIndex: Int, toIndex: Int) -> Unit? = null, rowBlocks: RowBlocks<T>? = null, contextMenu: @Composable (item: T, pos: Offset, dismiss: () -> Unit) -> Unit? = null, customization: TableCustomization<T, C> = DefaultTableCustomization(), colors: TableColors = TableDefaults.colors(), strings: StringProvider = DefaultStrings, verticalState: LazyListState = rememberLazyListState(), horizontalState: ScrollState = rememberScrollState(), icons: TableHeaderIcons = TableHeaderDefaults.icons(), shape: Shape = RoundedCornerShape(4.dp), border: BorderStroke? = null, rowEmbedded: @Composable (rowIndex: Int, item: T) -> Unit? = null, embedded: Boolean = false)

Composable data table with custom table data state.

Link copied to clipboard
fun <T : Any, C, E> TableActiveFilters(columns: ImmutableList<ColumnSpec<T, C, E>>, state: TableState<C>, modifier: Modifier = Modifier, strings: StringProvider = DefaultStrings, includeClearAllChip: Boolean = true)

Renders a compact header row with chips describing currently active filters. Provides quick clear actions for individual columns or all at once.

Link copied to clipboard
fun <T : Any, C, E> tableColumns(build: ReadonlyTableColumnsBuilder<T, C, E>.() -> Unit): ImmutableList<ColumnSpec<T, C, E>>

DSL entry to declare readonly table columns with custom table data type.