# Data Table

Composable TanStack Table v9 presentation with native table semantics, sorting, filtering, selection, and pagination.

- Package: `@mielui/svelte`
- Component version: `1.1.0`
- Depends on Mielui components: pagination, _internal/utils, table, input, group, button, checkbox, dropdown-menu, popover, native-select, date-picker
- Shared utilities: utils.cn, utils.createContext, utils.pressable, hugeicons-icon

## Install

~~~~sh
pnpm dlx @mielui/svelte add data-table
~~~~

## API

This reference is generated at build time from the component manifest, public `index.ts`, and documentation examples below. Changes to those source files are reflected here in the published Markdown. Standard Svelte and HTML attributes accepted by the exported prop types are supported.


### Root

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| cell | Snippet<[Cell<TableFeatures, RowData, unknown>]> \| undefined | - | No | No | Renders a cell. Defaults to the column's cell definition. |
| table | Table_Core<TableFeatures, RowData> & Table_CellSelection<TableFeatures, RowData> & Table_CellSpanning<TableFeatures, RowData> & Table_ColumnFaceting<TableFeatures, RowData> & Table_ColumnFiltering & Table_ColumnGrouping<TableFeatures, RowData> & Table_ColumnOrdering<TableFeatures, RowData> & Table_ColumnPinning<TableFeatures, RowData> & Table_ColumnResizing & Table_ColumnSizing & Table_ColumnVisibility<TableFeatures, RowData> & Table_GlobalFiltering<TableFeatures, RowData> & Table_RowExpanding<TableFeatures, RowData> & Table_RowPagination<TableFeatures, RowData> & Table_RowPinning<TableFeatures, RowData> & Table_RowSelection<TableFeatures, RowData> & Table_RowSorting<TableFeatures, RowData> | - | Yes | No | TanStack Table instance that drives the table. |
| loading | boolean \| undefined | false | No | No | Shows the loading state in place of the content. |
| caption | string \| undefined | - | No | No | Accessible caption that describes the table. |
| header | Snippet<[Header<TableFeatures, RowData, unknown>]> \| undefined | - | No | No | Renders a column header. |
| selectable | boolean \| undefined | false | No | No | Adds a selection checkbox column. |
| rowLabel | ((row: Row<TableFeatures, RowData>) => string) \| undefined | - | No | No | Returns a row's name, used in its selection checkbox's accessible name. |
| empty | Snippet<[{ loading: boolean; }]> \| undefined | - | No | No | Content shown when there are no rows. It receives the loading state. |
| variant | "default" \| "inset" \| undefined | 'default' | No | No | Both variants draw the rows in an inset table. `default` leaves the toolbar and footer outside it. `inset` puts the table and its footer in one frame, with the Toolbar above. |
| labels | DataTableLabels \| undefined | - | No | No | Overrides the built-in text and accessible names. Every key is optional and English is the fallback. |
| children | Snippet<[DataTableState<TableFeatures, RowData>]> \| undefined | - | No | No | Content rendered inside. |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Body

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| cell | Snippet<[Cell<TableFeatures, RowData, unknown>]> \| undefined | - | No | No | Renders a cell. Defaults to the column's cell definition. |
| table | Table_Core<TableFeatures, RowData> & Table_CellSelection<TableFeatures, RowData> & Table_CellSpanning<TableFeatures, RowData> & Table_ColumnFaceting<TableFeatures, RowData> & Table_ColumnFiltering & Table_ColumnGrouping<TableFeatures, RowData> & Table_ColumnOrdering<TableFeatures, RowData> & Table_ColumnPinning<TableFeatures, RowData> & Table_ColumnResizing & Table_ColumnSizing & Table_ColumnVisibility<TableFeatures, RowData> & Table_GlobalFiltering<TableFeatures, RowData> & Table_RowExpanding<TableFeatures, RowData> & Table_RowPagination<TableFeatures, RowData> & Table_RowPinning<TableFeatures, RowData> & Table_RowSelection<TableFeatures, RowData> & Table_RowSorting<TableFeatures, RowData> | - | Yes | No | TanStack Table instance that drives the table. |
| loading | boolean \| undefined | false | No | No | Shows the loading state in place of the content. |
| selectable | boolean \| undefined | false | No | No | Adds a selection checkbox column. |
| rowLabel | ((row: Row<TableFeatures, RowData>) => string) \| undefined | - | No | No | Returns a row's name, used in its selection checkbox's accessible name. |
| empty | Snippet<[{ loading: boolean; }]> \| undefined | - | No | No | Content shown when there are no rows. It receives the loading state. |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Empty

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| class | string \| undefined | - | No | No | Classes added to the element. |
| columns | number | - | Yes | No | Number of columns the empty row spans. |
| loading | boolean \| undefined | false | No | No | Shows the loading state in place of the content. |
| children | Snippet<[{ loading: boolean; }]> \| undefined | - | No | No | Content rendered inside. |



### Filter

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| table | Table_Core<TableFeatures, RowData> & Table_CellSelection<TableFeatures, RowData> & Table_CellSpanning<TableFeatures, RowData> & Table_ColumnFaceting<TableFeatures, RowData> & Table_ColumnFiltering & Table_ColumnGrouping<TableFeatures, RowData> & Table_ColumnOrdering<TableFeatures, RowData> & Table_ColumnPinning<TableFeatures, RowData> & Table_ColumnResizing & Table_ColumnSizing & Table_ColumnVisibility<TableFeatures, RowData> & Table_GlobalFiltering<TableFeatures, RowData> & Table_RowExpanding<TableFeatures, RowData> & Table_RowPagination<TableFeatures, RowData> & Table_RowPinning<TableFeatures, RowData> & Table_RowSelection<TableFeatures, RowData> & Table_RowSorting<TableFeatures, RowData> | - | Yes | No | TanStack Table instance that drives the table. |
| column | string | - | Yes | No | Id of the column the search field filters. |
| label | string | - | Yes | No | Accessible name of the control. |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Header

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| table | Table_Core<TableFeatures, RowData> & Table_CellSelection<TableFeatures, RowData> & Table_CellSpanning<TableFeatures, RowData> & Table_ColumnFaceting<TableFeatures, RowData> & Table_ColumnFiltering & Table_ColumnGrouping<TableFeatures, RowData> & Table_ColumnOrdering<TableFeatures, RowData> & Table_ColumnPinning<TableFeatures, RowData> & Table_ColumnResizing & Table_ColumnSizing & Table_ColumnVisibility<TableFeatures, RowData> & Table_GlobalFiltering<TableFeatures, RowData> & Table_RowExpanding<TableFeatures, RowData> & Table_RowPagination<TableFeatures, RowData> & Table_RowPinning<TableFeatures, RowData> & Table_RowSelection<TableFeatures, RowData> & Table_RowSorting<TableFeatures, RowData> | - | Yes | No | TanStack Table instance that drives the table. |
| header | Snippet<[Header<TableFeatures, RowData, unknown>]> \| undefined | - | No | No | Renders a column header. |
| selectable | boolean \| undefined | false | No | No | Adds a selection checkbox column. |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Pagination

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| table | Table_Core<TableFeatures, RowData> & Table_CellSelection<TableFeatures, RowData> & Table_CellSpanning<TableFeatures, RowData> & Table_ColumnFaceting<TableFeatures, RowData> & Table_ColumnFiltering & Table_ColumnGrouping<TableFeatures, RowData> & Table_ColumnOrdering<TableFeatures, RowData> & Table_ColumnPinning<TableFeatures, RowData> & Table_ColumnResizing & Table_ColumnSizing & Table_ColumnVisibility<TableFeatures, RowData> & Table_GlobalFiltering<TableFeatures, RowData> & Table_RowExpanding<TableFeatures, RowData> & Table_RowPagination<TableFeatures, RowData> & Table_RowPinning<TableFeatures, RowData> & Table_RowSelection<TableFeatures, RowData> & Table_RowSorting<TableFeatures, RowData> | - | Yes | No | TanStack Table instance that drives the table. |
| loading | boolean \| undefined | false | No | No | Shows the loading state in place of the content. |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Selection

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| class | string \| undefined | - | No | No | Classes added to the element. |
| checked | boolean \| undefined | false | No | No | Whether the checkbox is checked. |
| indeterminate | boolean \| undefined | false | No | No | Shows the mixed state when only some rows are selected. |
| disabled | boolean \| undefined | false | No | No | Disables the checkbox. |
| label | string | - | Yes | No | Accessible name of the control. |
| onCheckedChange | (checked: boolean) => void | - | Yes | No | Called with the new state when the checkbox changes. |



### Summary

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| table | Table_Core<TableFeatures, RowData> & Table_CellSelection<TableFeatures, RowData> & Table_CellSpanning<TableFeatures, RowData> & Table_ColumnFaceting<TableFeatures, RowData> & Table_ColumnFiltering & Table_ColumnGrouping<TableFeatures, RowData> & Table_ColumnOrdering<TableFeatures, RowData> & Table_ColumnPinning<TableFeatures, RowData> & Table_ColumnResizing & Table_ColumnSizing & Table_ColumnVisibility<TableFeatures, RowData> & Table_GlobalFiltering<TableFeatures, RowData> & Table_RowExpanding<TableFeatures, RowData> & Table_RowPagination<TableFeatures, RowData> & Table_RowPinning<TableFeatures, RowData> & Table_RowSelection<TableFeatures, RowData> & Table_RowSorting<TableFeatures, RowData> | - | Yes | No | TanStack Table instance that drives the table. |
| children | Snippet<[DataTableState<TableFeatures, RowData>]> \| undefined | - | No | No | Content rendered inside. |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Toolbar

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### View

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| table | Table_Core<TableFeatures, RowData> & Table_CellSelection<TableFeatures, RowData> & Table_CellSpanning<TableFeatures, RowData> & Table_ColumnFaceting<TableFeatures, RowData> & Table_ColumnFiltering & Table_ColumnGrouping<TableFeatures, RowData> & Table_ColumnOrdering<TableFeatures, RowData> & Table_ColumnPinning<TableFeatures, RowData> & Table_ColumnResizing & Table_ColumnSizing & Table_ColumnVisibility<TableFeatures, RowData> & Table_GlobalFiltering<TableFeatures, RowData> & Table_RowExpanding<TableFeatures, RowData> & Table_RowPagination<TableFeatures, RowData> & Table_RowPinning<TableFeatures, RowData> & Table_RowSelection<TableFeatures, RowData> & Table_RowSorting<TableFeatures, RowData> | - | Yes | No | TanStack Table instance that drives the table. |
| loading | boolean \| undefined | false | No | No | Shows the loading state in place of the content. |
| selectable | boolean \| undefined | false | No | No | Adds a selection checkbox column. |
| caption | string \| undefined | - | No | No | Accessible caption that describes the table. |
| rowLabel | ((row: Row<TableFeatures, RowData>) => string) \| undefined | - | No | No | Returns a row's name, used in its selection checkbox's accessible name. |
| header | Snippet<[Header<TableFeatures, RowData, unknown>]> \| undefined | - | No | No | Renders a column header. |
| cell | Snippet<[Cell<TableFeatures, RowData, unknown>]> \| undefined | - | No | No | Renders a cell. Defaults to the column's cell definition. |
| empty | Snippet<[{ loading: boolean; }]> \| undefined | - | No | No | Content shown when there are no rows. It receives the loading state. |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### ColumnHeader

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| header | Header_Core<TableFeatures, RowData, unknown> & Header_ColumnResizing & Header_ColumnSizing | - | Yes | No | TanStack header to render. |
| class | string \| undefined | - | No | No | Classes added to the element. |



### Facet

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| table | Table_Core<TableFeatures, RowData> & Table_CellSelection<TableFeatures, RowData> & Table_CellSpanning<TableFeatures, RowData> & Table_ColumnFaceting<TableFeatures, RowData> & Table_ColumnFiltering & Table_ColumnGrouping<TableFeatures, RowData> & Table_ColumnOrdering<TableFeatures, RowData> & Table_ColumnPinning<TableFeatures, RowData> & Table_ColumnResizing & Table_ColumnSizing & Table_ColumnVisibility<TableFeatures, RowData> & Table_GlobalFiltering<TableFeatures, RowData> & Table_RowExpanding<TableFeatures, RowData> & Table_RowPagination<TableFeatures, RowData> & Table_RowPinning<TableFeatures, RowData> & Table_RowSelection<TableFeatures, RowData> & Table_RowSorting<TableFeatures, RowData> | - | Yes | No | TanStack Table instance that drives the table. |
| filter | { column: string; label: string; editor?: Snippet<[{ value: unknown; setValue: (value: unknown) => void; }]> \| undefined; } & ({ type: "text"; placeholder?: string \| undefined; } \| { type: "select"; options: readonly { value: string; label: string; }[]; } \| { type: "number"; min?: number \| undefined; max?: number \| undefined; step?: number \| undefined; } \| { type: "date"; }) | - | Yes | No | Filter definition this chip edits. |
| open | boolean \| undefined | false | No | Yes | Whether it is open. Bind it to control the state from outside. |
| onOpenChange | ((open: boolean) => void) \| undefined | - | No | No | Called with the new state whenever it opens or closes. |
| onRemove | (() => void) \| undefined | - | No | No | Called when the filter is removed. |
| class | string \| undefined | - | No | No | Classes added to the element. |



### Filters

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| table | Table_Core<TableFeatures, RowData> & Table_CellSelection<TableFeatures, RowData> & Table_CellSpanning<TableFeatures, RowData> & Table_ColumnFaceting<TableFeatures, RowData> & Table_ColumnFiltering & Table_ColumnGrouping<TableFeatures, RowData> & Table_ColumnOrdering<TableFeatures, RowData> & Table_ColumnPinning<TableFeatures, RowData> & Table_ColumnResizing & Table_ColumnSizing & Table_ColumnVisibility<TableFeatures, RowData> & Table_GlobalFiltering<TableFeatures, RowData> & Table_RowExpanding<TableFeatures, RowData> & Table_RowPagination<TableFeatures, RowData> & Table_RowPinning<TableFeatures, RowData> & Table_RowSelection<TableFeatures, RowData> & Table_RowSorting<TableFeatures, RowData> | - | Yes | No | TanStack Table instance that drives the table. |
| filters | readonly DataTableFilterDefinition[] | - | Yes | No | Filters offered in the Filter menu. |
| children | Snippet<[]> \| undefined | - | No | No | Content rendered inside. |
| class | string \| undefined | - | No | No | Classes added to the element. |



### Sort

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| table | Table_Core<TableFeatures, RowData> & Table_CellSelection<TableFeatures, RowData> & Table_CellSpanning<TableFeatures, RowData> & Table_ColumnFaceting<TableFeatures, RowData> & Table_ColumnFiltering & Table_ColumnGrouping<TableFeatures, RowData> & Table_ColumnOrdering<TableFeatures, RowData> & Table_ColumnPinning<TableFeatures, RowData> & Table_ColumnResizing & Table_ColumnSizing & Table_ColumnVisibility<TableFeatures, RowData> & Table_GlobalFiltering<TableFeatures, RowData> & Table_RowExpanding<TableFeatures, RowData> & Table_RowPagination<TableFeatures, RowData> & Table_RowPinning<TableFeatures, RowData> & Table_RowSelection<TableFeatures, RowData> & Table_RowSorting<TableFeatures, RowData> | - | Yes | No | TanStack Table instance that drives the table. |
| columns | readonly { id: string; label: string; }[] \| undefined | - | No | No | Columns offered in the Sort menu. |
| class | string \| undefined | - | No | No | Classes added to the element. |



### Public types

~~~~ts
import type { Cell, Header, Row, RowData, Table, TableFeatures } from '@tanstack/svelte-table';
import type { Snippet } from 'svelte';
import type { HTMLAttributes, HTMLInputAttributes, HTMLTableAttributes } from 'svelte/elements';
export type DataTableState<TFeatures extends TableFeatures, TData extends RowData> = {
    table: Table<TFeatures, TData>;
    rows: Row<TFeatures, TData>[];
    total: number;
    selected: number;
};
export type DataTableViewProps<TFeatures extends TableFeatures, TData extends RowData> = Omit<
    HTMLTableAttributes,
    'children'
> & {
    /** TanStack Table instance that drives the table. */
    table: Table<TFeatures, TData>;
    /** Shows the loading state in place of the content. */
    loading?: boolean;
    /** Adds a selection checkbox column. */
    selectable?: boolean;
    /** Accessible caption that describes the table. */
    caption?: string;
    /** Returns a row's name, used in its selection checkbox's accessible name. */
    rowLabel?: (row: Row<TFeatures, TData>) => string;
    /** Renders a column header. */
    header?: Snippet<[Header<TFeatures, TData, unknown>]>;
    /** Renders a cell. Defaults to the column's cell definition. */
    cell?: Snippet<[Cell<TFeatures, TData, unknown>]>;
    /** Content shown when there are no rows. It receives the loading state. */
    empty?: Snippet<[{ loading: boolean }]>;
};
export type DataTableLabels = {
    /** Accessible name of the table when it has no `caption`. */
    region?: string;
    /** Text of the empty row while loading. */
    loading?: string;
    /** Text of the empty row when nothing matches. */
    empty?: string;
    /** Name of a row when `rowLabel` is not set. */
    row?: (id: string) => string;
    /** Accessible name of a row's selection checkbox, given the row's name. */
    selectRow?: (row: string) => string;
    /** Accessible name of the header checkbox that selects every row on the page. */
    selectPage?: string;
    /** Accessible name of the pagination group. */
    pages?: string;
    /** Pagination text when there are no pages. */
    noPages?: string;
    /** Pagination text for the current page. `pageCount` is undefined when the count is unknown. */
    page?: (page: number, pageCount: number | undefined) => string;
    /** Summary text for the row count, such as 12 rows. */
    rows?: (count: number) => string;
    /** Summary text for the selection, such as 3 selected. */
    selected?: (selected: number, total: number) => string;
    /** Sort button text when no column is sorted. */
    sort?: string;
    /** Accessible name of the sort button. */
    sortResults?: string;
    /** Sort button text when a column is sorted, given the column name. */
    sortedBy?: (column: string) => string;
    /** Heading of the sort menu's column list. */
    sortBy?: string;
    /** Sort menu item for ascending order. */
    ascending?: string;
    /** Sort menu item for descending order. */
    descending?: string;
    /** Tooltip on a column header whose next click sorts ascending. */
    sortAscending?: string;
    /** Tooltip on a column header whose next click sorts descending. */
    sortDescending?: string;
    /** Tooltip on a column header whose next click removes the sort, and the Sort menu item. */
    clearSorting?: string;
    /** Accessible name of the filter group. */
    filters?: string;
    /** Text of the button that adds a filter. */
    filter?: string;
    /** Heading of the add-filter menu. */
    filterBy?: string;
    /** Operator option that matches text containing the value. */
    contains?: string;
    /** Operator option that matches the exact value. */
    equals?: string;
    /** Operator option that excludes the exact value. */
    not?: string;
    /** Operator option that matches any selected option. */
    anyOf?: string;
    /** Operator option that excludes every selected option. */
    noneOf?: string;
    /** Operator option that matches a range. */
    between?: string;
    /** Number operator option for a lower bound. */
    atLeast?: string;
    /** Number operator option for an upper bound. */
    atMost?: string;
    /** Date operator option for a lower bound. */
    onOrAfter?: string;
    /** Date operator option for an upper bound. */
    onOrBefore?: string;
    /** Placeholder of a text filter's value input. */
    valuePlaceholder?: string;
    /** Placeholder of a range filter's lower bound. */
    minimum?: string;
    /** Placeholder of a range filter's upper bound. */
    maximum?: string;
    /** Label of a date range's start. */
    from?: string;
    /** Label of a date range's end. */
    through?: string;
    /** Label of a single date input. */
    date?: string;
    /** Accessible name of a filter's editor, given the filter name. */
    facet?: (filter: string) => string;
    /** Accessible name of a filter's operator select, given the filter name. */
    facetOperator?: (filter: string) => string;
    /** Accessible name of a filter's value input, given the filter name. */
    facetValue?: (filter: string) => string;
    /** Accessible name of a filter's lower bound input, given the filter name. */
    facetMinimum?: (filter: string) => string;
    /** Accessible name of a filter's upper bound input, given the filter name. */
    facetMaximum?: (filter: string) => string;
    /** Filter button summary for a text value match, such as contains draft. */
    summaryContains?: (value: string) => string;
    /** Filter button summary for an exact value, such as is draft. */
    summaryEquals?: (value: string) => string;
    /** Filter button summary for an excluded value, such as is not draft. */
    summaryNot?: (value: string) => string;
    /** Filter button summary for chosen options, such as 3 selected. */
    summarySelected?: (count: number) => string;
    /** Filter button summary for excluded options, given the option summary. */
    summaryExcluded?: (summary: string) => string;
    /** Filter button text for an open end of a range. */
    summaryAny?: string;
    /** Button in a filter's editor that removes the filter. */
    removeFilter?: string;
    /** Button that closes a filter's editor. */
    done?: string;
    /** Pagination button for the previous page. */
    previous?: string;
    /** Pagination button for the next page. */
    next?: string;
};

export type DataTableProps<TFeatures extends TableFeatures, TData extends RowData> = Omit<
    HTMLAttributes<HTMLDivElement>,
    'children'
> &
    Pick<
        DataTableViewProps<TFeatures, TData>,
        'table' | 'loading' | 'selectable' | 'caption' | 'rowLabel' | 'header' | 'cell' | 'empty'
    > & {
        /**
         * Both variants draw the rows in an inset table. `default` leaves the toolbar and footer
         * outside it. `inset` puts the table and its footer in one frame, with the Toolbar above.
         */
        variant?: 'default' | 'inset';
        /**
         * Overrides the built-in text and accessible names. Every key is optional and English is
         * the fallback.
         */
        labels?: DataTableLabels;
        /** Content rendered inside. */
        children?: Snippet<[DataTableState<TFeatures, TData>]>;
    };
export type DataTableHeaderProps<TFeatures extends TableFeatures, TData extends RowData> = Pick<
    DataTableViewProps<TFeatures, TData>,
    'table' | 'selectable' | 'header'
> &
    Omit<HTMLAttributes<HTMLTableSectionElement>, 'children'>;
export type DataTableBodyProps<TFeatures extends TableFeatures, TData extends RowData> = Pick<
    DataTableViewProps<TFeatures, TData>,
    'table' | 'selectable' | 'loading' | 'cell' | 'empty' | 'rowLabel'
> &
    Omit<HTMLAttributes<HTMLTableSectionElement>, 'children'>;
export type DataTableToolbarProps = HTMLAttributes<HTMLDivElement>;
export type DataTablePaginationProps<TFeatures extends TableFeatures, TData extends RowData> = Omit<
    HTMLAttributes<HTMLElement>,
    'children'
> & {
    /** TanStack Table instance that drives the table. */
    table: Table<TFeatures, TData>;
    /** Shows the loading state in place of the content. */
    loading?: boolean;
};
export type DataTableSummaryProps<TFeatures extends TableFeatures, TData extends RowData> = Omit<
    HTMLAttributes<HTMLParagraphElement>,
    'children'
> & {
    /** TanStack Table instance that drives the table. */
    table: Table<TFeatures, TData>;
    /** Content rendered inside. */
    children?: Snippet<[DataTableState<TFeatures, TData>]>;
};
export type DataTableFilterProps<TFeatures extends TableFeatures, TData extends RowData> = Omit<
    HTMLInputAttributes,
    'value' | 'type' | 'oninput' | 'checked' | 'files'
> & {
    /** TanStack Table instance that drives the table. */
    table: Table<TFeatures, TData>;
    /** Id of the column the search field filters. */
    column: string;
    /** Accessible name of the control. */
    label: string;
};
export type DataTableEmptyProps = {
    /** Classes added to the element. */
    class?: string;
    /** Number of columns the empty row spans. */
    columns: number;
    /** Shows the loading state in place of the content. */
    loading?: boolean;
    /** Content rendered inside. */
    children?: Snippet<[{ loading: boolean }]>;
};
export type DataTableSelectionProps = {
    /** Classes added to the element. */
    class?: string;
    /** Whether the checkbox is checked. */
    checked?: boolean;
    /** Shows the mixed state when only some rows are selected. */
    indeterminate?: boolean;
    /** Disables the checkbox. */
    disabled?: boolean;
    /** Accessible name of the control. */
    label: string;
    /** Called with the new state when the checkbox changes. */
    onCheckedChange: (checked: boolean) => void;
};
export { default as Root } from './data-table.svelte';
export { default as Body } from './data-table-body.svelte';
export { default as Empty } from './data-table-empty.svelte';
export { default as Filter } from './data-table-filter.svelte';
export { default as Header } from './data-table-header.svelte';
export { default as Pagination } from './data-table-pagination.svelte';
export { default as Selection } from './data-table-selection.svelte';
export { default as Summary } from './data-table-summary.svelte';
export { default as Toolbar } from './data-table-toolbar.svelte';
export { default as View } from './data-table-view.svelte';

export type DataTableFilterClause =
    | {
          type: 'text';
          operator: 'contains' | 'equals' | 'not';
          value: string;
      }
    | {
          type: 'select';
          operator: 'in' | 'notIn';
          value: string[];
      }
    | {
          type: 'number';
          operator: 'equals' | 'lt' | 'lte' | 'gt' | 'gte';
          value: number;
      }
    | {
          type: 'number';
          operator: 'between';
          value: [number | undefined, number | undefined];
      }
    | {
          type: 'date';
          operator: 'equals' | 'lt' | 'lte' | 'gt' | 'gte';
          value: string;
      }
    | {
          type: 'date';
          operator: 'between';
          value: [string | undefined, string | undefined];
      };
export type DataTableFilterDefinition = {
    column: string;
    label: string;
    editor?: Snippet<
        [
            {
                value: unknown;
                setValue: (value: unknown) => void;
            }
        ]
    >;
} & (
    | {
          type: 'text';
          placeholder?: string;
      }
    | {
          type: 'select';
          options: readonly {
              value: string;
              label: string;
          }[];
      }
    | {
          type: 'number';
          min?: number;
          max?: number;
          step?: number;
      }
    | { type: 'date' }
);
export type DataTableFiltersProps<TFeatures extends TableFeatures, TData extends RowData> = {
    /** TanStack Table instance that drives the table. */
    table: Table<TFeatures, TData>;
    /** Filters offered in the Filter menu. */
    filters: readonly DataTableFilterDefinition[];
    /** Content rendered inside. */
    children?: Snippet;
    /** Classes added to the element. */
    class?: string;
};
export type DataTableFacetProps<TFeatures extends TableFeatures, TData extends RowData> = {
    /** TanStack Table instance that drives the table. */
    table: Table<TFeatures, TData>;
    /** Filter definition this chip edits. */
    filter: DataTableFilterDefinition;
    /** Whether it is open. Bind it to control the state from outside. */
    open?: boolean;
    /** Called with the new state whenever it opens or closes. */
    onOpenChange?: (open: boolean) => void;
    /** Called when the filter is removed. */
    onRemove?: () => void;
    /** Classes added to the element. */
    class?: string;
};
export type DataTableSortProps<TFeatures extends TableFeatures, TData extends RowData> = {
    /** TanStack Table instance that drives the table. */
    table: Table<TFeatures, TData>;
    /** Columns offered in the Sort menu. */
    columns?: readonly {
        id: string;
        label: string;
    }[];
    /** Classes added to the element. */
    class?: string;
};
export type DataTableColumnHeaderProps<TFeatures extends TableFeatures, TData extends RowData> = {
    /** TanStack header to render. */
    header: Header<TFeatures, TData, unknown>;
    /** Classes added to the element. */
    class?: string;
};
export { default as ColumnHeader } from './data-table-column-header.svelte';
export { default as Facet } from './data-table-facet.svelte';
export { default as Filters } from './data-table-filters.svelte';
export { default as Sort } from './data-table-sort.svelte';
export { dataTableFilter } from './filter';
~~~~

## Examples

### Controlled

~~~~svelte
<script lang="ts">
    import { numberShuffle } from '@mielui/svelte/actions/number-shuffle';
    import { Button } from '@mielui/svelte/components/button';
    import * as DataTable from '@mielui/svelte/components/data-table';
    import { createTable, createTableState, type SortingState } from '@tanstack/svelte-table';
    import { columns, features, members } from './data';

    const [sorting, setSorting] = createTableState<SortingState>([
        {
            id: 'name',
            desc: false
        }
    ]);

    let data = $state(members.slice(0, 3));

    const table = createTable({
        features,
        columns,
        get data() {
            return data;
        },
        getRowId: (member) => member.id,
        state: {
            get sorting() {
                return sorting();
            }
        },
        onSortingChange: setSorting
    });
</script>

<DataTable.Root {table} class="w-full">
    {#snippet children({ total })}
        <DataTable.Toolbar>
            <p class="text-sm font-medium">
                <span use:numberShuffle={{ value: total }}>{total}</span>
                team members
            </p>
            <Button
                variant="secondary"
                size="sm"
                onclick={() => {
                    data = members;
                }}
            >
                Show all members
            </Button>
        </DataTable.Toolbar>
        <DataTable.View
            {table}
            selectable
            caption="Team members"
            rowLabel={(row) => row.original.name}
        />
        <DataTable.Summary {table}>
            {#snippet children({ selected })}
                {selected}
                selected
            {/snippet}
        </DataTable.Summary>
    {/snippet}
</DataTable.Root>
~~~~

### Empty

~~~~svelte
<script lang="ts">
    import { Button } from '@mielui/svelte/components/button';
    import * as DataTable from '@mielui/svelte/components/data-table';
    import { createTable } from '@tanstack/svelte-table';
    import { columns, features, members } from './data';

    let loading = $state(false);

    const table = createTable({
        features,
        columns,
        data: members,
        getRowId: (member) => member.id,
        initialState: {
            columnFilters: [
                {
                    id: 'name',
                    value: 'No matching member'
                }
            ]
        }
    });
</script>

<div class="flex w-full flex-col gap-4">
    <Button
        variant="secondary"
        size="sm"
        class="self-start"
        onclick={() => {
            loading = !loading;
        }}
    >
        {loading ? 'Show empty state' : 'Show loading state'}
    </Button>
    <DataTable.Root {table} {loading} caption="Filtered members" class="w-full">
        {#snippet empty({ loading })}
            <div class="flex flex-col items-center gap-3">
                <p>{loading ? 'Loading members…' : 'No members match this filter.'}</p>
                {#if !loading}
                    <Button
                        size="sm"
                        variant="secondary"
                        onclick={() => {
                            table.resetColumnFilters(true);
                        }}
                    >
                        Clear filter
                    </Button>
                {/if}
            </div>
        {/snippet}
    </DataTable.Root>
</div>
~~~~

### Inset

~~~~svelte
<script lang="ts">
    import { Badge } from '@mielui/svelte/components/badge';
    import * as DataTable from '@mielui/svelte/components/data-table';
    import { createTable, FlexRender } from '@tanstack/svelte-table';
    import { columns, features, filters, members } from './data';

    const table = createTable({
        features,
        columns,
        data: members,
        getRowId: (member) => member.id,
        initialState: {
            columnVisibility: {
                joined: false
            },
            pagination: {
                pageIndex: 0,
                pageSize: 5
            }
        }
    });
</script>

<DataTable.Root {table} variant="inset" class="w-full">
    {#snippet children()}
        <DataTable.Toolbar>
            <DataTable.Filters {table} {filters} class="min-w-0 flex-1">
                <DataTable.Filter
                    {table}
                    column="name"
                    label="Filter members by name"
                    placeholder="Filter members…"
                    class="min-w-0 flex-1"
                />
            </DataTable.Filters>
            <DataTable.Sort {table} class="ms-auto" />
        </DataTable.Toolbar>
        <DataTable.View
            {table}
            selectable
            caption="Workspace members"
            rowLabel={(row) => row.original.name}
        >
            {#snippet cell(cell)}
                {#if cell.column.id === 'role'}
                    <Badge variant="secondary">{String(cell.getValue())}</Badge>
                {:else if cell.column.id === 'projects'}
                    <span class="tabular-nums">{String(cell.getValue())}</span>
                {:else}
                    <FlexRender {cell} />
                {/if}
            {/snippet}
        </DataTable.View>
        <div data-ui="data-table-footer" class="flex flex-wrap items-center justify-between gap-3">
            <DataTable.Summary {table} />
            <DataTable.Pagination {table} />
        </div>
    {/snippet}
</DataTable.Root>
~~~~

### data.ts

The examples import this module as `./data`. It sits beside them in the same folder.

~~~~ts
import {
    type DataTableFilterDefinition,
    dataTableFilter
} from '@mielui/svelte/components/data-table';
import {
    type ColumnDef,
    columnFilteringFeature,
    columnVisibilityFeature,
    createFilteredRowModel,
    createPaginatedRowModel,
    createSortedRowModel,
    filterFns,
    rowPaginationFeature,
    rowSelectionFeature,
    rowSortingFeature,
    sortFns,
    tableFeatures
} from '@tanstack/svelte-table';

export type Member = {
    id: string;
    name: string;
    email: string;
    role: string;
    projects: number;
    joined: string;
};
export const features = tableFeatures({
    columnFilteringFeature,
    columnVisibilityFeature,
    rowPaginationFeature,
    rowSelectionFeature,
    rowSortingFeature,
    filteredRowModel: createFilteredRowModel(),
    sortedRowModel: createSortedRowModel(),
    paginatedRowModel: createPaginatedRowModel(),
    filterFns,
    sortFns
});
export const columns: ColumnDef<typeof features, Member>[] = [
    { accessorKey: 'name', header: 'Name', filterFn: 'includesString' },
    { accessorKey: 'email', header: 'Email', filterFn: dataTableFilter },
    { accessorKey: 'role', header: 'Role', filterFn: dataTableFilter },
    { accessorKey: 'projects', header: 'Projects', filterFn: dataTableFilter },
    { accessorKey: 'joined', header: 'Joined', filterFn: dataTableFilter }
];
export const members: Member[] = [
    {
        id: 'm-01',
        joined: '2026-01-15',
        name: 'Maya Chen',
        email: 'maya@acme.test',
        role: 'Owner',
        projects: 12
    },
    {
        id: 'm-02',
        joined: '2026-02-15',
        name: 'Theo Martin',
        email: 'theo@acme.test',
        role: 'Editor',
        projects: 8
    },
    {
        id: 'm-03',
        joined: '2026-03-15',
        name: 'Amira Diallo',
        email: 'amira@acme.test',
        role: 'Editor',
        projects: 6
    },
    {
        id: 'm-04',
        joined: '2026-04-15',
        name: 'Noah Kim',
        email: 'noah@acme.test',
        role: 'Viewer',
        projects: 3
    },
    {
        id: 'm-05',
        joined: '2026-05-15',
        name: 'Luca Rossi',
        email: 'luca@acme.test',
        role: 'Editor',
        projects: 7
    },
    {
        id: 'm-06',
        joined: '2026-06-15',
        name: 'Sofia Costa',
        email: 'sofia@acme.test',
        role: 'Viewer',
        projects: 2
    },
    {
        id: 'm-07',
        joined: '2026-07-15',
        name: 'Eva Novak',
        email: 'eva@acme.test',
        role: 'Editor',
        projects: 9
    },
    {
        id: 'm-08',
        joined: '2026-08-15',
        name: 'Oscar Anders',
        email: 'oscar@acme.test',
        role: 'Viewer',
        projects: 4
    }
];

export const filters: DataTableFilterDefinition[] = [
    {
        column: 'role',
        label: 'Role',
        type: 'select',
        options: [
            { value: 'Owner', label: 'Owner' },
            { value: 'Editor', label: 'Editor' },
            { value: 'Viewer', label: 'Viewer' }
        ]
    },
    { column: 'projects', label: 'Projects', type: 'number', min: 0, step: 1 },
    { column: 'joined', label: 'Joined', type: 'date' },
    { column: 'email', label: 'Email', type: 'text', placeholder: 'company.test' }
];
~~~~

For the rendered reference, visit [/docs/components/data-table](/docs/components/data-table).
