Table
Display flat records, then add selection, sorting or editing while your application owns the data and state.
- Category
- Data and hierarchy
- Import
@neural-ui/core/table- Selector
neu-table
import { NeuTableComponent } from '@neural-ui/core/table';Display data
Customer | Amount (โฌ) | Region |
|---|---|---|
| Atlas | 240 | EU |
| Birch | 180 | US |
| Cedar | 420 | EU |
Configurator
Preview
| Atlas | 240 | EU |
| Birch | 180 | US |
| Cedar | 420 | EU |
Your configuration code
This snippet updates when you change options. The Code tab includes the complete component, data and templates.
Structured data, callbacks and templates are shown in the examples and API.
Code adds advanced options when they differ from the default. Current configuration data and values appear in the template state.
<neu-table
[data]="records()"
[columns]="columns()"
[rowKey]="rowKey"
[appearance]='{
"density": "normal",
"borders": "rows",
"striped": false,
"stickyHeader": false,
"responsive": "contained-scroll"
}'
[selectionOptions]='{
"mode": "none"
}'
[sortOptions]='{
"mode": "single",
"removable": true,
"defaultDirection": "asc",
"resetPageOnChange": true
}'
[filterOptions]='{
"surfaces": [],
"globalFields": [],
"predicates": {},
"debounceMs": 0,
"commit": "immediate"
}'
[paginationOptions]='{
"enabled": true,
"pageSizeOptions": [
3,
6,
10
],
"position": "bottom",
"report": "range",
"showPageJump": false
}'
[columnOptions]='{
"reorderable": false,
"resizable": false,
"hideable": false,
"pinnable": false
}'
[editingOptions]='{
"mode": "none",
"activation": "click",
"commitOnBlur": false
}'
[expansionOptions]='{
"enabled": false,
"toggleOnRowClick": false
}'
[interactionOptions]='{
"navigation": "native",
"wrapFocus": false,
"announceChanges": true
}'
[query]="query()"
(queryChange)="query.set($event)"
[selection]="selection()"
(selectionChange)="selection.set($event.next)"
[layout]="layout()"
(layoutChange)="layout.set($event.next)"
[editState]="editState()"
(editStateChange)="editState.set($event.next)"
(editCommit)="save($event)"
[expandedKeys]="expanded()"
(expandedKeysChange)="expanded.set($event.next)"
>
<!-- Include the editor and detail templates from the complete example. -->
</neu-table>These values match the current preview. Complete handlers, Core imports and templates are in Source.
import { signal } from '@angular/core';
export const records = signal([
{
"id": 101,
"customer": "Atlas",
"amount": 240,
"region": "EU"
},
{
"id": 102,
"customer": "Birch",
"amount": 180,
"region": "US"
},
{
"id": 103,
"customer": "Cedar",
"amount": 420,
"region": "EU"
},
{
"id": 104,
"customer": "Delta",
"amount": 95,
"region": "US"
},
{
"id": 105,
"customer": "Elm",
"amount": 310,
"region": "EU"
},
{
"id": 106,
"customer": "Fern",
"amount": 160,
"region": "US"
}
]);
export const columns = signal([
{
"id": "customer",
"field": "customer",
"header": "Customer",
"minWidth": "14rem",
"sort": {
"field": "customer"
}
},
{
"id": "amount",
"field": "amount",
"header": "Amount (โฌ)",
"minWidth": "10rem",
"sort": {
"field": "amount"
}
},
{
"id": "region",
"field": "region",
"header": "Region",
"minWidth": "10rem",
"sort": {
"field": "region"
}
}
]);
export const rowKey = () => { /* Handler in the complete example. */ };
export const query = signal({
"page": 0,
"pageSize": 3,
"search": "",
"sort": [],
"filters": null
});
export const selection = signal({
"kind": "keys",
"keys": []
});
export const layout = signal({
"order": [],
"hidden": [],
"widths": {},
"pinnedStart": [],
"pinnedEnd": []
});
export const editState = signal({
"kind": "none"
});
export const expanded = signal([]);These inputs require a model or function, not a checkbox. Edit the same-named field in the Source component and bind it in the template; data already used by this preview appears in the state above.
data ยท readonly T[]In Source: define data with this type and use [data]="data" (or data() for a signal).
grouping ยท NeuTableGroupingState<F> | nullIn Source: define grouping with this type and use [grouping]="grouping" (or grouping() for a signal).
groupingOptions ยท NeuTableGroupingOptions<T, F>In Source: define groupingOptions with this type and use [groupingOptions]="groupingOptions" (or groupingOptions() for a signal).
labels ยท NeuTableLabelsIn Source: define labels with this type and use [labels]="labels" (or labels() for a signal).
metadata ยท NeuTableMetadataIn Source: define metadata with this type and use [metadata]="metadata" (or metadata() for a signal).
rowKey ยท NeuRowKey<T, K>In Source: define rowKey with this type and use [rowKey]="rowKey" (or rowKey() for a signal).
rowOptions ยท NeuTableRowOptions<T, K>In Source: define rowOptions with this type and use [rowOptions]="rowOptions" (or rowOptions() for a signal).
rowTrackBy ยท NeuRowTrackBy<T> | undefinedIn Source: define rowTrackBy with this type and use [rowTrackBy]="rowTrackBy" (or rowTrackBy() for a signal).
virtualizationOptions ยท NeuTableVirtualizationOptionsIn Source: define virtualizationOptions with this type and use [virtualizationOptions]="virtualizationOptions" (or virtualizationOptions() for a signal).
Feature examples
Selection
Customer | Amount (โฌ) | Region | |
|---|---|---|---|
| Atlas | 240 | EU | |
| Birch | 180 | US | |
| Cedar | 420 | EU |
Selected ids: โ
Accessibility and keyboard
Key | Action |
|---|---|
| Tab / Shift+Tab | Move between enabled controls and interactive template content. |
| Enter / Space | Activate the focused native control, such as sorting or expansion. |
| Enter / Escape | In the example editor, commit or cancel the draft. |
API
Inputs
Configure the component with [property]="value". Your application supplies these values; the component does not replace the state you pass in.
Name | Type | Default | Template binding | Description |
|---|---|---|---|---|
appearance | NeuTableAppearance | {
density: 'normal',
borders: 'rows',
striped: false,
stickyHeader: false,
responsive: 'contained-scroll',
} | [appearance] | |
columnOptions | NeuTableColumnOptions | {} | [columnOptions] | |
columns | readonly NeuTableColumn<T, F>[] | [] | [columns] | |
data | readonly T[] | [] | [data] | |
dataMode | NeuTableDataMode | 'client' | [dataMode] | |
editingOptions | NeuTableEditingOptions<T, K, F> | { mode: 'none' } | [editingOptions] | |
editState | NeuTableEditState<K> | {
kind: 'none',
} | [editState] | |
expandedKeys | readonly K[] | [] | [expandedKeys] | |
expansionOptions | NeuTableExpansionOptions<T> | {
enabled: false,
toggleOnRowClick: false,
} | [expansionOptions] | |
filterOptions | NeuTableFilterOptions<T, F> | {
surfaces: [],
globalFields: [],
predicates: {},
debounceMs: 0,
commit: 'immediate',
} | [filterOptions] | |
grouping | NeuTableGroupingState<F> | null | null | [grouping] | |
groupingOptions | NeuTableGroupingOptions<T, F> | {
mode: 'subheader',
scope: 'loaded',
} | [groupingOptions] | |
interactionOptions | NeuTableInteractionOptions | {
navigation: 'native',
wrapFocus: false,
announceChanges: false,
} | [interactionOptions] | |
labels | NeuTableLabels | {
ariaLabel: 'Data table',
empty: 'No data',
loading: 'Loading',
error: 'Unable to load data',
retry: 'Retry',
selection: 'Selection',
pagination: 'Pagination',
} | [labels] | |
layout | NeuTableLayoutState | {
order: [],
hidden: [],
widths: {},
pinnedStart: [],
pinnedEnd: [],
} | [layout] | |
metadata | NeuTableMetadata | {
totalItems: null,
loading: false,
error: null,
queryRevision: 0,
appliedRequestId: null,
} | [metadata] | |
paginationOptions | NeuTablePaginationOptions | {
enabled: false,
pageSizeOptions: [],
position: 'bottom',
report: 'none',
showPageJump: false,
} | [paginationOptions] | |
query | NeuTableQuery<F> | {
page: 0,
pageSize: 25,
search: '',
sort: [],
filters: null,
} | [query] | |
rowKey | NeuRowKey<T, K> | Required | [rowKey] | |
rowOptions | NeuTableRowOptions<T, K> | {
reorderable: false,
} | [rowOptions] | |
rowTrackBy | NeuRowTrackBy<T> | undefined | No default | [rowTrackBy] | |
selection | NeuTableSelection<K, F> | {
kind: 'keys',
keys: [],
} | [selection] | |
selectionOptions | NeuTableSelectionOptions<T> | { mode: 'none' } | [selectionOptions] | |
sortOptions | NeuTableSortOptions | {
mode: 'single',
removable: true,
defaultDirection: 'asc',
resetPageOnChange: true,
} | [sortOptions] | |
virtualizationOptions | NeuTableVirtualizationOptions | { enabled: false } | [virtualizationOptions] |
Outputs
Listen to an event with (event)="handler($event)". The table explains the data your handler receives and how to use it.
Name | Payload | Template binding | Description |
|---|---|---|---|
dataRequest | NeuTableDataRequest<F> | (dataRequest)="onDataRequest($event)" | |
editCancel | NeuTableEditCancel<T, K> | (editCancel)="onEditCancel($event)" | |
editCommit | NeuTableEditCommit<T, K, F> | (editCommit)="onEditCommit($event)" | |
editStateChange | NeuTableEditChange<K> | (editStateChange)="onEditStateChange($event)" | |
expandedKeysChange | NeuTableExpandedKeysChange<K> | (expandedKeysChange)="onExpandedKeysChange($event)" | |
exportRequest | NeuTableExportRequest<F> | (exportRequest)="onExportRequest($event)" | |
featureError | NeuTableFeatureError | (featureError)="onFeatureError($event)" | |
groupingChange | NeuTableGroupingChange<F> | (groupingChange)="onGroupingChange($event)" | |
layoutChange | NeuTableLayoutChange | (layoutChange)="onLayoutChange($event)" | |
queryChange | NeuTableQuery<F> | (queryChange)="onQueryChange($event)" | |
rangeChange | NeuTableRangeChange | (rangeChange)="onRangeChange($event)" | |
rowAction | NeuTableRowAction<T, K> | (rowAction)="onRowAction($event)" | |
rowReorder | NeuTableRowMove<K> | (rowReorder)="onRowReorder($event)" | |
selectionChange | NeuTableSelectionChange<T, K, F> | (selectionChange)="onSelectionChange($event)" |
Templates
ng-content projects content into the component. TemplateRef inputs receive a template; ng-template directives identify templates with a typed context. A directive shared by an entrypoint is not necessarily a slot of this component.
Name | Mechanism | Contract |
|---|---|---|
NeuTableCaptionDirective | Public template directive (entrypoint) | ng-template[neuTableCaption]Context used: template.d.ts context.d.ts |
NeuTableCellDirective | Public template directive (entrypoint) | ng-template[neuTableCell]Context used: template.d.ts context.d.ts |
NeuTableEditorDirective | Public template directive (entrypoint) | ng-template[neuTableEditor]Context used: template.d.ts context.d.ts |
NeuTableEmptyDirective | Public template directive (entrypoint) | ng-template[neuTableEmpty]Context used: template.d.ts context.d.ts |
NeuTableErrorDirective | Public template directive (entrypoint) | ng-template[neuTableError]Context used: template.d.ts context.d.ts |
NeuTableFilterDirective | Public template directive (entrypoint) | ng-template[neuTableFilter]Context used: template.d.ts context.d.ts |
NeuTableFooterDirective | Public template directive (entrypoint) | ng-template[neuTableFooter]Context used: template.d.ts context.d.ts |
NeuTableGroupFooterDirective | Public template directive (entrypoint) | ng-template[neuTableGroupFooter]Context used: template.d.ts context.d.ts |
NeuTableGroupHeaderDirective | Public template directive (entrypoint) | ng-template[neuTableGroupHeader]Context used: template.d.ts context.d.ts |
NeuTableHeaderDirective | Public template directive (entrypoint) | ng-template[neuTableHeader]Context used: template.d.ts context.d.ts |
NeuTableLoadingDirective | Public template directive (entrypoint) | ng-template[neuTableLoading]Context used: template.d.ts context.d.ts |
NeuTablePaginatorDirective | Public template directive (entrypoint) | ng-template[neuTablePaginator]Context used: template.d.ts context.d.ts |
NeuTableRowDetailDirective | Public template directive (entrypoint) | ng-template[neuTableRowDetail]Context used: template.d.ts context.d.ts |
NeuTableSummaryDirective | Public template directive (entrypoint) | ng-template[neuTableSummary]Context used: template.d.ts context.d.ts |
NeuTableToolbarDirective | Public template directive (entrypoint) | ng-template[neuTableToolbar]Context used: template.d.ts context.d.ts |
Each example demonstrates a different template. Switch between Demo and Code to inspect its implementation, imports and state.
Table caption
NeuTableCaptionDirective
Customer | Amount (โฌ) | Region |
|---|---|---|
| Atlas | 240 | EU |
| Birch | 180 | US |
| Cedar | 420 | EU |
Table actions
NeuTableToolbarDirective
Customer | Amount (โฌ) | Region |
|---|---|---|
| Atlas | 240 | EU |
| Birch | 180 | US |
| Cedar | 420 | EU |
Result summary
NeuTableSummaryDirective
Customer | Amount (โฌ) | Region |
|---|---|---|
| Atlas | 240 | EU |
| Birch | 180 | US |
| Cedar | 420 | EU |
Displayed orders: 3 ยท Total amount: 840 โฌ | ||
Column header
NeuTableHeaderDirective
Customer Business account | Amount (โฌ) | Region |
|---|---|---|
| Atlas | 240 | EU |
| Birch | 180 | US |
| Cedar | 420 | EU |
Cell content
NeuTableCellDirective
Customer | Amount (โฌ) | Region |
|---|---|---|
| AtlasOrder #101 | 240 | EU |
| BirchOrder #102 | 180 | US |
| CedarOrder #103 | 420 | EU |
Column footer
NeuTableFooterDirective
Customer | Amount (โฌ) | Region |
|---|---|---|
| Atlas | 240 | EU |
| Birch | 180 | US |
| Cedar | 420 | EU |
| Total: 840 โฌ |
Custom filter
NeuTableFilterDirective
Customer | Amount (โฌ) | Region |
|---|---|---|
| Atlas | 240 | EU |
| Birch | 180 | US |
| Cedar | 420 | EU |
Custom editor
NeuTableEditorDirective
Use the rowโs pencil to edit its customer. Save changes or cancel using that rowโs actions.
Customer | Amount (โฌ) | Region | Edit |
|---|---|---|---|
| Atlas | 240 | EU | |
| Birch | 180 | US | |
| Cedar | 420 | EU |
Row detail
NeuTableRowDetailDirective
| Expansion | Customer | Amount (โฌ) | Region | ||||
|---|---|---|---|---|---|---|---|
| Atlas | 240 | EU | |||||
Order detail #101
| |||||||
| Birch | 180 | US | |||||
| Cedar | 420 | EU | |||||
Group header
NeuTableGroupHeaderDirective
Expand a region to see its orders.
Customer | Amount (โฌ) | Region |
|---|---|---|
Group summary
NeuTableGroupFooterDirective
Expand a region to see its orders and summary.
Customer | Amount (โฌ) | Region |
|---|---|---|
Empty state
NeuTableEmptyDirective
Customer | Amount (โฌ) | Region |
|---|---|---|
No orders yet New orders will appear here. | ||
Loading state
NeuTableLoadingDirective
Customer | Amount (โฌ) | Region |
|---|---|---|
Loading ordersโฆ Retrieving your results. | ||
Error state and retry
NeuTableErrorDirective
Customer | Amount (โฌ) | Region |
|---|---|---|
Orders could not be loaded. | ||
Custom pagination
NeuTablePaginatorDirective
Customer | Amount (โฌ) | Region |
|---|---|---|
| Atlas | 240 | EU |
| Birch | 180 | US |
| Cedar | 420 | EU |
Public methods
Name | Contract |
|---|---|
export | export(request: NeuTableExportRequest<F>): Promise<NeuTableExportOutcome>;Create an export from the requested scope. Inspect the outcome; a delegated export requires application handling. The Export example shows the complete call and result. example.ts |
focusCell | focusCell(target: {
readonly key: K;
readonly columnId: string;
}): boolean;Move focus to a rendered cell by stable row key and column id. The boolean result reports whether focus could be placed. example.ts |
retryData | retryData(): void;Request another attempt for the current remote query. Handle dataRequest in the application; this method does not fetch data itself. example.ts |
scrollTo | scrollTo(target: {
readonly index?: number;
readonly key?: K;
}): Promise<void>;Scroll to a row by index or key. Await completion when a subsequent action depends on the row being visible. example.ts |
Public Types
Open a type to inspect its definition and interface fields.
import type { NeuFilterConstraint } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuFilterConstraint<F extends string> {
readonly field: F;
readonly kind: 'condition';
readonly rule: 'equals' | 'notEquals' | 'contains' | 'notContains' | 'startsWith' | 'endsWith' | 'lessThan' | 'lessThanOrEqual' | 'greaterThan' | 'greaterThanOrEqual' | 'between' | 'in' | 'notIn' | 'isNull' | 'isNotNull' | 'isEmpty' | 'isNotEmpty';
readonly value: unknown;
}import type { NeuFilterConstraint } from '@neural-ui/core/table';
import type { NeuFilterGroup } from '@neural-ui/core/table';
import type { NeuFilterExpression } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuFilterExpression<F extends string> = NeuFilterConstraint<F> | NeuFilterGroup<F>;import type { NeuFilterExpression } from '@neural-ui/core/table';
import type { NeuFilterOperator } from '@neural-ui/core/table';
import type { NeuFilterGroup } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuFilterGroup<F extends string> {
readonly children: readonly NeuFilterExpression<F>[];
readonly kind: 'group';
readonly operator: NeuFilterOperator;
}import type { NeuFilterOperator } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuFilterOperator = 'and' | 'or';import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuRowKey } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuRowKey<T, K extends NeuTableKey> = (row: T) => K;import type { NeuRowTrackBy } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuRowTrackBy<T> = (index: number, row: T) => unknown;import type { NeuSortDirection } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuSortDirection = 'asc' | 'desc';import type { NeuSortDirection } from '@neural-ui/core/table';
import type { NeuSortEntry } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuSortEntry<F extends string> {
readonly direction: NeuSortDirection;
readonly field: F;
}import type { NeuTableAppearance } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableAppearance {
readonly borders: 'none' | 'rows' | 'cells';
readonly density: 'compact' | 'normal' | 'relaxed';
readonly responsive: 'contained-scroll' | 'stacked';
readonly stickyHeader: boolean;
readonly striped: boolean;
}import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableRowContext } from '@neural-ui/core/table';
import type { NeuTableCellContext } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableCellContext<T, K extends NeuTableKey> extends NeuTableRowContext<T, K> {
readonly columnId: string;
readonly value: unknown;
}import type { NeuTableEditColumn } from '@neural-ui/core/table';
import type { NeuTableFilterColumn } from '@neural-ui/core/table';
import type { NeuTableSortColumn } from '@neural-ui/core/table';
import type { NeuTableValueAccessor } from '@neural-ui/core/table';
import type { NeuTableColumn } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableColumn<T, F extends string> {
readonly align?: 'start' | 'center' | 'end';
readonly edit?: NeuTableEditColumn<T, F>;
readonly field?: F;
readonly filter?: NeuTableFilterColumn<T, F>;
readonly header: string;
readonly id: string;
readonly maxWidth?: string;
readonly minWidth?: string;
readonly sort?: NeuTableSortColumn<T, F>;
readonly value?: NeuTableValueAccessor<T>;
readonly width?: string;
}import type { NeuTableColumnOptions } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableColumnOptions {
readonly hideable?: boolean;
readonly pinnable?: boolean;
readonly reorderable?: boolean;
readonly resizable?: boolean;
}import type { NeuTableDataMode } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableDataMode = 'client' | 'remote';import type { NeuTableDataRequestReason } from '@neural-ui/core/table';
import type { NeuTableQuery } from '@neural-ui/core/table';
import type { NeuTableRange } from '@neural-ui/core/table';
import type { NeuTableDataRequest } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableDataRequest<F extends string> {
readonly query: NeuTableQuery<F>;
readonly queryRevision: number;
readonly range?: NeuTableRange;
readonly reason: NeuTableDataRequestReason;
readonly requestId: number;
}import type { NeuTableDataRequestReason } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableDataRequestReason = 'initial' | 'query' | 'viewport' | 'retry';import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableRowContext } from '@neural-ui/core/table';
import type { NeuTableDetailContext } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableDetailContext<T, K extends NeuTableKey> extends NeuTableRowContext<T, K> {
}import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableEditCancel } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableEditCancel<T, K extends NeuTableKey> {
readonly key: K;
readonly reason: 'escape' | 'consumer' | 'data-change';
readonly row: T;
}import type { NeuTableEditState } from '@neural-ui/core/table';
import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableEditChange } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableEditChange<K extends NeuTableKey> {
readonly next: NeuTableEditState<K>;
readonly source: 'pointer' | 'keyboard' | 'programmatic' | 'commit' | 'cancel';
}import type { NeuTableValueAccessor } from '@neural-ui/core/table';
import type { NeuTableEditColumn } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableEditColumn<T, F extends string> {
readonly field: F;
readonly read?: NeuTableValueAccessor<T>;
readonly write?: (row: T, value: unknown) => T;
}import type { NeuTableEditValueChange } from '@neural-ui/core/table';
import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableEditCommit } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableEditCommit<T, K extends NeuTableKey, F extends string> {
readonly changes: readonly NeuTableEditValueChange<F>[];
readonly key: K;
readonly row: T;
}import type { NeuTableEditError } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableEditError {
readonly code: string;
readonly columnId?: string;
readonly message: string;
}import type { NeuTableEditValidation } from '@neural-ui/core/table';
import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableEditingOptions } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableEditingOptions<T, K extends NeuTableKey, F extends string> = {
readonly mode: 'none';
} | {
readonly mode: 'cell' | 'row';
readonly activation: 'click' | 'double-click' | 'enter' | 'f2';
readonly validate?: NeuTableEditValidation<T, K, F>;
readonly commitOnBlur: boolean;
};import type { NeuTableCellContext } from '@neural-ui/core/table';
import type { NeuTableEditError } from '@neural-ui/core/table';
import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableEditorContext } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableEditorContext<T, K extends NeuTableKey, F extends string> extends NeuTableCellContext<T, K> {
readonly cancel: () => void;
readonly commit: () => void;
readonly errors: Signal<readonly NeuTableEditError[]>;
readonly setValue: (value: unknown) => void;
readonly valueSignal: Signal<unknown>;
}import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableEditState } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableEditState<K extends NeuTableKey> = {
readonly kind: 'none';
} | {
readonly kind: 'cell';
readonly key: K;
readonly columnId: string;
} | {
readonly kind: 'row';
readonly key: K;
};import type { NeuTableEditCommit } from '@neural-ui/core/table';
import type { NeuTableEditError } from '@neural-ui/core/table';
import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableEditValidation } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableEditValidation<T, K extends NeuTableKey, F extends string> = (event: NeuTableEditCommit<T, K, F>) => readonly NeuTableEditError[] | Promise<readonly NeuTableEditError[]>;import type { NeuTableEditValueChange } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableEditValueChange<F extends string> {
readonly columnId: string;
readonly field?: F;
readonly previous: unknown;
readonly value: unknown;
}import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableExpandedKeysChange } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableExpandedKeysChange<K extends NeuTableKey> {
readonly expanded: boolean;
readonly key: K;
readonly next: readonly K[];
readonly source: 'toggle' | 'keyboard' | 'programmatic';
}import type { NeuTableExpansionOptions } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableExpansionOptions<T> {
readonly enabled: boolean;
readonly isExpandable?: (row: T) => boolean;
readonly toggleOnRowClick: boolean;
}import type { NeuTableExportFormat } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableExportFormat = 'csv' | 'json' | 'xlsx';import type { NeuTableExportResult } from '@neural-ui/core/table';
import type { NeuTableExportOutcome } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableExportOutcome = {
readonly kind: 'generated';
readonly result: NeuTableExportResult;
} | {
readonly kind: 'delegated';
};import type { NeuTableExportFormat } from '@neural-ui/core/table';
import type { NeuTableExportScope } from '@neural-ui/core/table';
import type { NeuTableQuery } from '@neural-ui/core/table';
import type { NeuTableExportRequest } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableExportRequest<F extends string> {
readonly fileName: string;
readonly format: NeuTableExportFormat;
readonly query: NeuTableQuery<F>;
readonly scope: NeuTableExportScope;
}import type { NeuTableExportResult } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableExportResult {
readonly bytes: Uint8Array;
readonly fileName: string;
readonly mediaType: string;
}import type { NeuTableExportScope } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableExportScope = 'page' | 'loaded' | 'filtered' | 'selected' | 'all';import type { NeuTableFeatureError } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableFeatureError {
readonly cause: unknown;
readonly feature: 'filters' | 'editing' | 'virtualization' | 'export';
readonly recoverable: boolean;
}import type { NeuFilterConstraint } from '@neural-ui/core/table';
import type { NeuTableValueAccessor } from '@neural-ui/core/table';
import type { NeuTableFilterColumn } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableFilterColumn<T, F extends string> {
readonly defaultRule: NeuFilterConstraint<F>['rule'];
readonly field: F;
readonly rules: readonly NeuFilterConstraint<F>['rule'][];
readonly value?: NeuTableValueAccessor<T>;
}import type { NeuFilterConstraint } from '@neural-ui/core/table';
import type { NeuTableHeaderContext } from '@neural-ui/core/table';
import type { NeuTableFilterContext } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableFilterContext<T, F extends string> extends NeuTableHeaderContext<T, F> {
readonly apply: (value: unknown, rule?: NeuFilterConstraint<F>['rule']) => void;
readonly clear: () => void;
readonly rule: NeuFilterConstraint<F>['rule'];
readonly value: unknown;
}import type { NeuTableFilterPredicate } from '@neural-ui/core/table';
import type { NeuTableFilterSurface } from '@neural-ui/core/table';
import type { NeuTableFilterOptions } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableFilterOptions<T, F extends string> {
readonly commit: 'immediate' | 'explicit';
readonly debounceMs: number;
readonly equals?: (left: unknown, right: unknown) => boolean;
readonly globalFields: readonly F[];
readonly predicates: Readonly<Record<string, NeuTableFilterPredicate<T, F>>>;
readonly surfaces: readonly NeuTableFilterSurface[];
}import type { NeuTableFilterPredicateContext } from '@neural-ui/core/table';
import type { NeuTableFilterPredicate } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableFilterPredicate<T, F extends string> = (context: NeuTableFilterPredicateContext<T, F>) => boolean;import type { NeuTableFilterPredicateContext } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableFilterPredicateContext<T, F extends string> {
readonly candidate: unknown;
readonly field: F;
readonly filterValue: unknown;
readonly row: T;
}import type { NeuTableFilterSurface } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableFilterSurface = 'row' | 'menu' | 'builder';import type { NeuTableGroupContext } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableGroupContext<T> {
readonly expanded: boolean;
readonly id: string;
readonly level: number;
readonly rows: readonly T[];
readonly value: unknown;
}import type { NeuTableGroupingState } from '@neural-ui/core/table';
import type { NeuTableGroupingChange } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableGroupingChange<F extends string> {
readonly next: NeuTableGroupingState<F>;
readonly source: 'toggle' | 'programmatic';
}import type { NeuTableGroupingOptions } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableGroupingOptions<T, F extends string> {
readonly aggregate?: (rows: readonly T[], field: F) => unknown;
readonly mode: 'subheader' | 'rowspan';
readonly scope: 'loaded';
readonly value?: (row: T, field: F) => unknown;
}import type { NeuTableGroupingState } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableGroupingState<F extends string> {
readonly by: readonly F[];
readonly expandedGroupIds: readonly string[];
}import type { NeuSortEntry } from '@neural-ui/core/table';
import type { NeuTableColumn } from '@neural-ui/core/table';
import type { NeuTableHeaderContext } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableHeaderContext<T, F extends string> {
readonly column: NeuTableColumn<T, F>;
readonly sort: readonly NeuSortEntry<F>[];
}import type { NeuTableInteractionOptions } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableInteractionOptions {
readonly announceChanges: boolean;
readonly navigation: 'native' | 'rows' | 'cells';
readonly wrapFocus: boolean;
}import type { NeuTableKey } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableKey = string | number;import type { NeuTableMessage } from '@neural-ui/core/table';
import type { NeuTableLabels } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableLabels {
readonly ariaLabel: string;
readonly empty: string;
readonly error: string;
readonly loading: string;
readonly messages?: Partial<Record<NeuTableMessage, string>>;
readonly pagination: string;
readonly retry: string;
readonly selection: string;
}import type { NeuTableLayoutState } from '@neural-ui/core/table';
import type { NeuTableLayoutChange } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableLayoutChange {
readonly next: NeuTableLayoutState;
readonly source: 'resize' | 'reorder' | 'visibility' | 'pin';
}import type { NeuTableLayoutState } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableLayoutState {
readonly hidden: readonly string[];
readonly order: readonly string[];
readonly pinnedEnd: readonly string[];
readonly pinnedStart: readonly string[];
readonly widths: Readonly<Record<string, string>>;
}import type { NeuFilterConstraint } from '@neural-ui/core/table';
import type { NeuTableMessage } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableMessage = 'stateAnnouncement' | 'firstPage' | 'previousPage' | 'nextPage' | 'lastPage' | 'page' | 'of' | 'goToPage' | 'rowsPerPage' | 'searchTable' | 'search' | 'clearSearch' | 'clear' | 'advancedFilters' | 'hiddenColumns' | 'showColumn' | 'expansion' | 'selectAll' | 'filterColumn' | 'filter' | 'moveLeft' | 'moveRight' | 'pinColumn' | 'pin' | 'hideColumn' | 'hide' | 'resizeColumn' | 'rule' | 'value' | 'applyColumnFilter' | 'clearColumnFilter' | 'cancelFilter' | 'filterRule' | 'filterValue' | 'apply' | 'collapseRow' | 'expandRow' | 'selectRow' | 'sortAction' | 'ascending' | 'descending' | 'none' | 'field' | 'join' | 'and' | 'or' | 'applyAdvancedFilter' | 'cancelAdvancedFilter' | 'edit' | 'save' | 'cancel' | 'validating' | NeuFilterConstraint<string>['rule'];import type { NeuTableRange } from '@neural-ui/core/table';
import type { NeuTableMetadata } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableMetadata {
readonly appliedRequestId: number | null;
readonly dataRange?: NeuTableRange;
readonly error: unknown | null;
readonly loading: boolean;
readonly queryRevision: number;
readonly totalItems: number | null;
}import type { NeuTablePaginationOptions } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTablePaginationOptions {
readonly enabled: boolean;
readonly pageSizeOptions: readonly number[];
readonly position: 'top' | 'bottom' | 'both';
readonly report: 'none' | 'summary' | 'range';
readonly showPageJump: boolean;
}import type { NeuTablePaginatorContext } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTablePaginatorContext {
readonly canFirst: boolean;
readonly canLast: boolean;
readonly canNext: boolean;
readonly canPrevious: boolean;
readonly changePage: (page: number) => void;
readonly changePageSize: (pageSize: number) => void;
readonly humanPage: number;
readonly page: number;
readonly pageCount: number | null;
readonly pageSize: number;
readonly pageSizeOptions: readonly number[];
readonly rangeEnd: number;
readonly rangeStart: number;
readonly total: number | null;
}import type { NeuFilterExpression } from '@neural-ui/core/table';
import type { NeuSortEntry } from '@neural-ui/core/table';
import type { NeuTableQuery } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableQuery<F extends string> {
readonly filters: NeuFilterExpression<F> | null;
readonly page: number;
readonly pageSize: number;
readonly search: string;
readonly sort: readonly NeuSortEntry<F>[];
}import type { NeuTableRange } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableRange {
readonly end: number;
readonly start: number;
}import type { NeuTableRange } from '@neural-ui/core/table';
import type { NeuTableRangeChange } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableRangeChange {
readonly reason: 'scroll' | 'resize' | 'programmatic' | 'query';
readonly render: NeuTableRange;
readonly visible: NeuTableRange;
}import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableRowAction } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableRowAction<T, K extends NeuTableKey> {
readonly action: 'activate' | 'double-activate' | 'context-menu';
readonly index: number;
readonly key: K;
readonly row: T;
}import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableRowContext } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableRowContext<T, K extends NeuTableKey> {
readonly $implicit: T;
readonly disabled: boolean;
readonly expanded: boolean;
readonly index: number;
readonly key: K;
readonly row: T;
readonly selected: boolean;
}import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableRowMove } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableRowMove<K extends NeuTableKey> {
readonly beforeKey: K | null;
readonly fromIndex: number;
readonly key: K;
readonly toIndex: number;
}import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableRowOptions } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableRowOptions<T, K extends NeuTableKey> {
readonly className?: (row: T) => string | readonly string[] | null;
readonly isDisabled?: (row: T) => boolean;
readonly pin?: (row: T, key: K) => 'start' | 'end' | null;
readonly reorderable: boolean;
}import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableSelectionScope } from '@neural-ui/core/table';
import type { NeuTableSelection } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableSelection<K extends NeuTableKey, F extends string> = {
readonly kind: 'keys';
readonly keys: readonly K[];
} | {
readonly kind: 'all-matching';
readonly scope: NeuTableSelectionScope<F>;
readonly excludedKeys: readonly K[];
};import type { NeuTableKey } from '@neural-ui/core/table';
import type { NeuTableSelection } from '@neural-ui/core/table';
import type { NeuTableSelectionChange } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableSelectionChange<T, K extends NeuTableKey, F extends string> {
readonly addedKeys: readonly K[];
readonly loadedRows: readonly T[];
readonly next: NeuTableSelection<K, F>;
readonly removedKeys: readonly K[];
readonly source: 'row' | 'radio' | 'checkbox' | 'keyboard' | 'toggle-all';
}import type { NeuTableSelectionOptions } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableSelectionOptions<T> = {
readonly mode: 'none';
} | {
readonly mode: 'single';
readonly indicator: 'none' | 'radio';
readonly selectOnRowClick: boolean;
readonly allowClear: boolean;
readonly isRowDisabled?: (row: T) => boolean;
} | {
readonly mode: 'multiple';
readonly indicator: 'none' | 'checkbox';
readonly selectOnRowClick: boolean;
readonly modifier: 'replace' | 'platform' | 'toggle';
readonly range: boolean;
readonly toggleAllScope: 'rendered' | 'page' | 'loaded' | 'all-matching';
readonly isRowDisabled?: (row: T) => boolean;
};import type { NeuFilterExpression } from '@neural-ui/core/table';
import type { NeuTableSelectionScope } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableSelectionScope<F extends string> {
readonly filters: NeuFilterExpression<F> | null;
readonly globalFields: readonly F[];
readonly search: string;
}import type { NeuTableValueAccessor } from '@neural-ui/core/table';
import type { NeuTableSortColumn } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableSortColumn<T, F extends string> {
readonly compare?: (left: T, right: T) => number;
readonly field: F;
readonly value?: NeuTableValueAccessor<T>;
}import type { NeuSortDirection } from '@neural-ui/core/table';
import type { NeuTableSortOptions } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableSortOptions {
readonly defaultDirection: NeuSortDirection;
readonly mode: 'single' | 'multiple';
readonly removable: boolean;
readonly resetPageOnChange: boolean;
}import type { NeuTableStateTemplateContext } from '@neural-ui/core/table';
// Public declaration (reference only)
export interface NeuTableStateTemplateContext {
readonly error: unknown | null;
readonly loading: boolean;
readonly retry: () => void;
}import type { NeuTableValueAccessor } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableValueAccessor<T> = (row: T) => unknown;import type { NeuTableVirtualizationOptions } from '@neural-ui/core/table';
// Public declaration (reference only)
export type NeuTableVirtualizationOptions = {
readonly enabled: false;
} | {
readonly enabled: true;
readonly itemSize: number;
readonly overscan: number;
readonly requestStep?: number;
};Appearance and tokens
Specific tokens
Token | Purpose | State / variant | Default / source | Fallback |
|---|---|---|---|---|
--neu-table-cell-block | Vertical cell padding at normal density. | density="normal" | 0.625remRoot declaration | No token alias |
--neu-table-cell-block-compact | Vertical cell padding at compact density. | density="compact" | 0.375remRoot declaration | No token alias |
--neu-table-cell-block-relaxed | Vertical cell padding at relaxed density. | density="relaxed" | 0.875remRoot declaration | No token alias |
--neu-table-cell-inline | Horizontal cell padding. | Table cells | var(--neu-space-3)Root declaration | --neu-space-3 |
--neu-table-group-background | Background of group heading rows. | Group heading | color-mix(in srgb, currentColor 4%, transparent)Root declaration | No token alias |
--neu-table-header-height | Header cell height; wrapped content can require more room. | Column heading | 44pxRoot declaration | No token alias |
--neu-table-max-height | Maximum non-virtual viewport height; taller data scrolls inside it. | Non-virtual viewport | 480pxRoot declaration | No token alias |
--neu-table-selected-background | Selected-row background, taking precedence over stripes. | Selected row | color-mix(in srgb, currentColor 9%, transparent)Root declaration | No token alias |
--neu-table-space-sm | Spacing in table controls and action groups. | Controls and actions | var(--neu-space-2)Root declaration | --neu-space-2 |
--neu-table-space-xs | Small gaps between adjacent table controls. | Controls and actions | var(--neu-space-1)Root declaration | --neu-space-1 |
--neu-table-state-block | Vertical padding of empty, loading and error content. | Empty / loading / error | var(--neu-space-6)Root declaration | --neu-space-6 |
--neu-table-sticky-offset | Top offset of the header when stickyHeader is enabled. | stickyHeader | 0pxRoot declaration | No token alias |
--neu-table-stripe-background | Alternating-row background when striped is enabled. | striped | color-mix(in srgb, currentColor 4%, transparent)Root declaration | No token alias |
--neu-table-virtual-block-size | Height of the virtualized scroll viewport. | Virtualization | 24remRoot declaration | No token alias |
Shared tokens used
Override these on a local wrapper to affect this example. An override on :root affects other components that use the same token.
Token | Purpose here | Other impact | Default / fallback |
|---|---|---|---|
--neu-border | Normal control and cell borders | Shared by other Core consumers; scope the override. | rgba(15, 23, 42, 0.08) |
--neu-border-hover | Control borders on hover | Shared by other Core consumers; scope the override. | rgba(15, 23, 42, 0.16) |
--neu-focus-color | Visible keyboard-focus outline | Shared by other Core consumers; scope the override. | var(--neu-primary) |
--neu-primary | Brand color for active controls and emphasis | Shared by other Core consumers; scope the override. | #007aff |
--neu-primary-soft | Subtle selected or active surface | Shared by other Core consumers; scope the override. | var(--neu-primary-50) |
--neu-surface | Main field, header or control surface | Shared by other Core consumers; scope the override. | #ffffff |
--neu-surface-2 | Secondary surfaces and alternating rows | Shared by other Core consumers; scope the override. | #f1f5f9 |
--neu-text | Main text and inherited icon color | Shared by other Core consumers; scope the override. | #0f172a |