# Presets

> Package `@umriss-ui/table`, version 0.40.0. Demo page: <https://romanhaendler.github.io/umriss-ui/table/presets/>. Every page in one line: [llms.txt](https://romanhaendler.github.io/umriss-ui/table/llms.txt); every page in full: [llms-full.txt](https://romanhaendler.github.io/umriss-ui/table/llms-full.txt).

A column written once and used in many tables: as a preset spread into a column, or as a component that brings its own presentation.

```ts
import { column } from "@umriss-ui/table";
```

Demo page: https://romanhaendler.github.io/umriss-ui/table/presets/

## Examples

### Share a column between tables

`column<P>()` makes a preset bound to a property, not to a row kind; spread it into any table whose rows have that field.

```tsx
import { Stack } from "@umriss-ui/core";
import { column, useTable } from "@umriss-ui/table";

/* The compiler checks the spread: a row without a numeric `amount` is
   refused. With more than one field, name the field too -
   `column<{ amount: number; id: string }, "amount">(…)`. */
const amount = column<{ amount: number }>({ value: "amount", label: "Amount (€)", format: { decimals: 2 }, aggregate: "sum" });

interface Invoice {
  id: string;
  amount: number;
}

interface Budget {
  costCentre: string;
  amount: number;
}

const INVOICES: Invoice[] = [
  { id: "INV-26-0318", amount: 1951.24 },
  { id: "INV-26-0309", amount: 7288 },
];

const BUDGETS: Budget[] = [
  { costCentre: "Marketing", amount: 68_000 },
  { costCentre: "IT", amount: 83_000 },
];

function Invoices() {
  const { Table, Column } = useTable(INVOICES, { rowKey: (i) => i.id });
  return (
    <Table ariaLabel="Invoices">
      <Column value="id" label="Invoice" rowHeader />
      <Column {...amount} />
    </Table>
  );
}

function Budgets() {
  const { Table, Column } = useTable(BUDGETS, { rowKey: (b) => b.costCentre });
  return (
    <Table ariaLabel="Monthly budgets">
      <Column value="costCentre" label="Cost centre" rowHeader />
      <Column {...amount} label="Monthly budget (€)" />
    </Table>
  );
}

export default function Presets() {
  return (
    <Stack gap={4}>
      <Invoices />
      <Budgets />
    </Stack>
  );
}
```

### Wrap a column in a component

A column that brings its presentation becomes a component; it takes the table as `of`, typed with a row kind, and uses its `Column`.

```tsx
import { Badge } from "@umriss-ui/core";
import { useTable } from "@umriss-ui/table";
import type { Table } from "@umriss-ui/table";

/* A wrapper generic over its rows does not compile - TypeScript does not
   resolve the overloads against an open row type - and one without `of`
   compiles but is unchecked. */

interface Incident {
  id: string;
  severity: "SEV1" | "SEV2" | "SEV3";
}

const TONE = { SEV1: "danger", SEV2: "warning", SEV3: "neutral" } as const;

const INCIDENTS: Incident[] = [
  { id: "INC-1048", severity: "SEV1" },
  { id: "INC-1047", severity: "SEV3" },
  { id: "INC-1046", severity: "SEV2" },
];

function SeverityColumn({ of }: { of: Table<Incident> }) {
  return (
    <of.Column value="severity" label="Severity">
      {(severity) => <Badge tone={TONE[severity]}>{severity}</Badge>}
    </of.Column>
  );
}

export default function Wrapper() {
  const t = useTable(INCIDENTS, { rowKey: (i) => i.id });
  const { Table, Column } = t;

  return (
    <Table ariaLabel="Incidents">
      <Column value="id" label="Incident" rowHeader />
      <SeverityColumn of={t} />
    </Table>
  );
}
```

## Keyboard

The keys of [First table](https://romanhaendler.github.io/umriss-ui/table/first-table/#keyboard-first-table) apply here.

## Props on this page

From `TableProps` — the full table stands on [First table](https://romanhaendler.github.io/umriss-ui/table/first-table/#type-TableProps).

| Prop | Type | Default | Description |
|---|---|---|---|
| [`children`](https://romanhaendler.github.io/umriss-ui/table/first-table/#TableProps-children) | `ReactNode` | — | Columns, `RowDetail`, `RowActions` and the unbound parts. |

#### Accessibility

| Prop | Type | Default | Description |
|---|---|---|---|
| [`ariaLabel`](https://romanhaendler.github.io/umriss-ui/table/first-table/#TableProps-ariaLabel) | `string` | — | Accessible name of the table (not of the outer frame). |

From `TableOptions` — the full table stands on [First table](https://romanhaendler.github.io/umriss-ui/table/first-table/#type-TableOptions).

| Prop | Type | Default | Description |
|---|---|---|---|
| [`rowKey`](https://romanhaendler.github.io/umriss-ui/table/first-table/#TableOptions-rowKey) *required* | `(row: Z) => string` | — | A stable key per row – the basis of selection and expansion. |

From `FieldColumn` — the full table stands on [Column](https://romanhaendler.github.io/umriss-ui/table/column/#type-FieldColumn).

| Prop | Type | Default | Description |
|---|---|---|---|
| [`value`](https://romanhaendler.github.io/umriss-ui/table/column/#FieldColumn-value) *required* | `K` | — | A field of the row. Supplies the column's `id` at the same time. |
| [`id`](https://romanhaendler.github.io/umriss-ui/table/column/#FieldColumn-id) | `string` | — | An id of one's own instead of the field name – for two columns over the same field. |
| [`format`](https://romanhaendler.github.io/umriss-ui/table/column/#FieldColumn-format) | [`FormatFor`](https://romanhaendler.github.io/umriss-ui/table/column/#type-FormatFor)`<Z[K]>` | — | A standard presentation by name: `"percent"`, `"count"` or `{ decimals }` for numbers, `"date"`, `"time"` or `"dateTime"` for points in time. Alignment, sorting, export and footer stay with the value. |
| [`filter`](https://romanhaendler.github.io/umriss-ui/table/column/#FieldColumn-filter) | [`FilterFor`](https://romanhaendler.github.io/umriss-ui/table/column/#type-FilterFor)`<Z[K]>` | — | A filter in the column header: `"list"` offers the values that occur, `"range"` two bounds (numbers or points in time), a filter from `columnFilter` asks whatever it asks itself. Its condition stands in the table toolbar. |
| [`group`](https://romanhaendler.github.io/umriss-ui/table/column/#FieldColumn-group) | [`GroupFor`](https://romanhaendler.github.io/umriss-ui/table/column/#type-GroupFor)`<Z[K]>` | — | Groups points in time by `"day"`, `"week"`, `"month"` or `"year"`. |
| [`edit`](https://romanhaendler.github.io/umriss-ui/table/column/#FieldColumn-edit) | [`EditFor`](https://romanhaendler.github.io/umriss-ui/table/column/#type-EditFor)`<Z[K], Z>` | — | Edits the column's cells in place in grid mode: Enter, F2 or typing starts it, Enter or Tab commits, Escape cancels. The table applies nothing - the edit is reported through the table's `onCellEdit`. From `EditOptions`. |
| [`editOptions`](https://romanhaendler.github.io/umriss-ui/table/column/#FieldColumn-editOptions) | `readonly `[`Present`](https://romanhaendler.github.io/umriss-ui/table/column/#type-Present)`<Z[K]>[]` | the values that occur | What `edit="select"` offers. From `EditOptions`. |
| [`validate`](https://romanhaendler.github.io/umriss-ui/table/column/#FieldColumn-validate) | `(value: Z[K] \| null, row: Z) => string \| null \| undefined` | — | Checks a draft before it is reported: a message keeps the editor open and stands beneath the field, as in a `FormField`; nothing lets it through. From `EditOptions`. |
| [`children`](https://romanhaendler.github.io/umriss-ui/table/column/#FieldColumn-children) | [`Presentation`](https://romanhaendler.github.io/umriss-ui/table/column/#type-Presentation)`<Z[K], Z>` | — | How the value appears: `(value, row)`. Never called for an absent value. Required where the value has no text form. |

From `ColumnBase` — the full table stands on [Column](https://romanhaendler.github.io/umriss-ui/table/column/#type-ColumnBase).

| Prop | Type | Default | Description |
|---|---|---|---|
| [`label`](https://romanhaendler.github.io/umriss-ui/table/column/#ColumnBase-label) *required* | `string` | — | Names the column in its header, in the column menu and in the header row of the export. |
| [`rowHeader`](https://romanhaendler.github.io/umriss-ui/table/column/#ColumnBase-rowHeader) | `boolean` | — | This column names the row: row header cells, never hideable, the column `stickyRowHeader` pins, and the name by which the row's selection, expander and actions are read out. At most one per table. |
| [`numeric`](https://romanhaendler.github.io/umriss-ui/table/column/#ColumnBase-numeric) | `boolean` | decided by the first value present | Right-aligned with tabular figures. |
| [`width`](https://romanhaendler.github.io/umriss-ui/table/column/#ColumnBase-width) | `number` | the browser's | Initial width in pixels. |
| [`resizable`](https://romanhaendler.github.io/umriss-ui/table/column/#ColumnBase-resizable) | `boolean` | — | Shows the drag grip on the header cell. |
| [`pin`](https://romanhaendler.github.io/umriss-ui/table/column/#ColumnBase-pin) | [`Pin`](https://romanhaendler.github.io/umriss-ui/table/column/#type-Pin)<br>`"start" \| "end"` | — | Keeps the column in view while the table scrolls sideways: in a block before every other column, or after them. The user can change it in the column menu; the view carries the change. Pinned blocks take at most half of the width the table shows: on a narrower one the end block, then the start block scrolls with the rest, and sticks again when there is room. |
| [`sortable`](https://romanhaendler.github.io/umriss-ui/table/column/#ColumnBase-sortable) | `boolean` | `true` when the value is text, a number, a point in time or a boolean | Whether the column can be sorted by. |
| [`searchable`](https://romanhaendler.github.io/umriss-ui/table/column/#ColumnBase-searchable) | `boolean` | `true` for text, `false` otherwise | Takes part in the search. |
| [`groupable`](https://romanhaendler.github.io/umriss-ui/table/column/#ColumnBase-groupable) | `boolean` | `true` when its value is text, a number, a point in time or a boolean, or it has a `groupValue` | Can the table be grouped by this column? |

From `ValuePaths` — the full table stands on [Column](https://romanhaendler.github.io/umriss-ui/table/column/#type-ValuePaths).

| Prop | Type | Default | Description |
|---|---|---|---|
| [`sortValue`](https://romanhaendler.github.io/umriss-ui/table/column/#ValuePaths-sortValue) | `(value: `[`Present`](https://romanhaendler.github.io/umriss-ui/table/column/#type-Present)`<W>) => string \| number \| `[`Absent`](https://romanhaendler.github.io/umriss-ui/table/column/#type-Absent) | — | What is sorted by, when not by the value itself. |
| [`exportValue`](https://romanhaendler.github.io/umriss-ui/table/column/#ValuePaths-exportValue) | `(value: `[`Present`](https://romanhaendler.github.io/umriss-ui/table/column/#type-Present)`<W>) => string \| number \| `[`Absent`](https://romanhaendler.github.io/umriss-ui/table/column/#type-Absent) | — | What stands in the export, when not the value itself. |
| [`groupValue`](https://romanhaendler.github.io/umriss-ui/table/column/#ValuePaths-groupValue) | `(value: `[`Present`](https://romanhaendler.github.io/umriss-ui/table/column/#type-Present)`<W>) => string \| number \| boolean \| Date \| `[`Absent`](https://romanhaendler.github.io/umriss-ui/table/column/#type-Absent) | — | What is grouped by, when not the value itself - a group header of a number, say. Rows whose group value is absent form a group of their own. |

From `AggregateOptions` — the full table stands on [Aggregate](https://romanhaendler.github.io/umriss-ui/table/aggregate/#type-AggregateOptions).

| Prop | Type | Default | Description |
|---|---|---|---|
| [`aggregate`](https://romanhaendler.github.io/umriss-ui/table/aggregate/#AggregateOptions-aggregate) | [`AggregateFor`](https://romanhaendler.github.io/umriss-ui/table/aggregate/#type-AggregateFor)`<W, Z>` | — | What the column's values come to: in the footer over the filtered set, in a group's header over its rows. `"sum"`, `"avg"` for numbers; `"min"`, `"max"` for numbers and points in time; `"range"` for points in time; `"count"`, `"distinct"` for every value with a text form - or a function of one's own. Always from the values, never from other aggregates; absent values count towards nothing. |
| [`share`](https://romanhaendler.github.io/umriss-ui/table/aggregate/#AggregateOptions-share) | `boolean` | — | The share bar in a group's header – the group's share of the filtered set's sum. It stands under the first column with a sum, one per header; `false` passes it on to the next. |
