import { Signal, TNode, Value } from '@tempots/dom'; import { ControlSize } from '../theme'; import { BulkAction, DataSource, SortDescriptor } from './data-source'; import { FilterBase } from './filter'; /** The value type of a column, used by the filter panel to determine available operators. */ export type ColumnValueType = 'text' | 'number'; /** * Props passed to a custom filter render function. * * @typeParam T - The type of data rows * @typeParam C - Column identifier type (defaults to `string`) */ export interface FilterRenderProps { dataSource: DataSource; column: C; size: Value; } /** * Filter configuration for a column. * * - `boolean` — `true` enables a text filter * - `'text'` — explicit text filter * - `'number'` — shortcut for `{ type: 'panel', valueType: 'number' }` * - `{ type: 'select', options }` — dropdown filter * - `{ type: 'tags', options }` — multi-select tag filter * - `{ type: 'panel', valueType? }` — advanced filter panel * - `{ render }` — fully custom filter UI * * @typeParam T - The type of data rows * @typeParam C - Column identifier type (defaults to `string`) */ export type ColumnFilterConfig = boolean | 'text' | 'number' | { type: 'select'; options: { value: string; label: string; }[]; } | { type: 'tags'; options: { value: string; label: string; }[]; } | { type: 'panel'; valueType?: ColumnValueType; } | { render: (props: FilterRenderProps) => TNode; } | { input: (value: Signal, size: Value) => TNode; }; /** * Column definition for a {@link DataTable}. * * @typeParam T - The type of data rows * @typeParam C - Column identifier type (defaults to `string`) */ export interface DataColumnDef { /** Unique column identifier. Used as key for value accessor, sort, and filter. */ id: C; /** Column header content. String or render function. */ header: string | (() => TNode); /** Render function for cell content. Receives a reactive row signal and the column index. */ cell: (row: Signal, index: number) => TNode; /** * Accessor function to extract the column value from a row. * If omitted, defaults to `row[id]`. */ value?: (row: T) => unknown; /** Whether this column is sortable. @default false */ sortable?: Value; /** Custom comparator for sorting this column */ comparator?: (a: unknown, b: unknown) => number; /** Filter configuration for this column. Reactive — can be toggled at runtime. */ filter?: Value>; /** Footer render function. Receives all filtered rows as a reactive signal. */ footer?: (rows: Signal) => TNode; /** Column width (e.g., '200px', '20%') */ width?: Value; /** Minimum column width */ minWidth?: Value; /** Maximum column width */ maxWidth?: Value; /** Text alignment within cells. @default 'left' */ align?: Value<'left' | 'center' | 'right'>; /** Whether this column can be hidden via the column visibility toggle. @default false */ hideable?: Value; } /** * Pagination options for {@link DataTable}. */ export interface DataTablePaginationOptions { /** Number of rows per page. @default 10 */ pageSize?: number; /** Show first/last page buttons. @default false */ showFirstLast?: boolean; /** Number of page siblings to show. @default 1 */ siblings?: number; /** Enable responsive page number display. @default false */ responsive?: boolean; } /** * Toolbar options for {@link DataTable}. */ export interface DataTableToolbarOptions { /** Show active sort indicators in toolbar. @default true */ showSort?: boolean; /** Show active filter chips in toolbar. @default true */ showFilters?: boolean; /** Show selection count in toolbar. @default true */ showSelection?: boolean; /** Bulk actions available when rows are selected */ bulkActions?: BulkAction[]; } /** * Options for row selection behavior. */ export interface SelectionOptions { /** Position of selection checkboxes. @default 'before' */ position?: 'before' | 'after'; /** Toggle row selection when clicking anywhere on the row. @default false */ selectOnRowClick?: boolean; } /** * Configuration options for the {@link DataTable} component. * * @typeParam T - The type of data rows * @typeParam C - Column identifier type (defaults to `string`) */ export interface DataTableOptions { /** Source data array (static or reactive) */ data: Value; /** Column definitions */ columns: DataColumnDef[]; /** Returns a unique string ID for each row */ rowId: (row: T) => string; /** * Enable sorting. Columns opt-in via `column.sortable`. * - `false` — sorting disabled (default) * - `true` or `'single'` — single-column sorting * - `'multi'` — multi-column sorting * @default false */ sortable?: Value; /** * Enable filtering. Columns opt-in via `column.filter`. * - `false` — filtering disabled (default) * - `true` or `'header'` — filters render inline in column header menus * - `'row'` — filters render in a dedicated row below the header * @default false */ filterable?: Value; /** * Enable row selection with checkboxes. * - `false` — selection disabled (default) * - `true` — selection enabled with default options * - `SelectionOptions` — selection enabled with custom options * @default false */ selectable?: Value; /** Enable drag-to-reorder columns. @default false */ reorderableColumns?: Value; /** Called when column order changes via drag-and-drop */ onColumnOrderChange?: (columnIds: C[]) => void; /** Pagination config. `true` uses defaults, `false`/undefined disables. */ pagination?: Value; /** Toolbar config. `true` uses defaults, `false`/undefined disables. */ toolbar?: Value; /** Size variant. @default 'md' */ size?: Value; /** Enable hover effect on rows. @default false */ hoverable?: Value; /** Make header sticky. @default false */ stickyHeader?: Value; /** Full width table. @default false */ fullWidth?: Value; /** Striped rows. @default false */ withStripedRows?: Value; /** Table border. @default true */ withTableBorder?: Value; /** Column borders. @default false */ withColumnBorders?: Value; /** Row borders. @default true */ withRowBorders?: Value; /** Called when sort state changes */ onSortChange?: (sort: SortDescriptor[]) => void; /** Called when filter state changes */ onFilterChange?: (filters: FilterBase[]) => void; /** Called when selection changes */ onSelectionChange?: (selected: Set) => void; /** Called when the group-by column changes */ onGroupByChange?: (column: C | undefined) => void; /** Called when a row is clicked */ onRowClick?: (row: T) => void; /** Skip client-side processing. @default false */ serverSide?: Value; /** Total rows for server-side pagination */ totalRows?: Value; /** Loading state */ loading?: Value; /** Column to group rows by. Renders collapsible group header rows. */ groupBy?: Value; /** Whether groups are collapsible. @default true */ groupCollapsible?: boolean; /** Show footer row. Columns opt-in via `column.footer`. @default false */ showFooter?: Value; /** Custom render function for collapsed group summaries. */ groupSummary?: (groupKey: string, rows: T[]) => TNode; /** Content to show when no rows match */ emptyContent?: TNode; /** Column visibility options. When set, a column toggle button appears. */ hiddenColumns?: Value; /** Callback to receive the internal DataSource for external integration */ onDataSource?: (ds: DataSource) => void; /** Row detail panel configuration. When set, renders expandable detail rows. */ rowDetails?: RowDetailsConfig; } /** * Configuration for row detail panels in {@link DataTable}. * * @typeParam T - The type of data rows */ export interface RowDetailsConfig { /** Render function for detail content. Called lazily on first expand. */ render: (row: Signal) => TNode; /** * Initial visibility state of detail panels. * - `'collapsed'` — panels start closed, toggle column shown (default) * - `'expanded'` — panels start open, toggle column shown * - `'always-visible'` — panels always open, no toggle column * @default 'collapsed' */ defaultState?: 'expanded' | 'collapsed' | 'always-visible'; /** Predicate controlling which rows have a detail panel. When omitted, all rows have details. */ hasDetails?: (row: Signal) => boolean; /** Callback invoked with the updated set of toggled row IDs when a panel is toggled. */ onExpandedChange?: (toggledIds: Set) => void; }