@papernote/ui
Version:
A modern React component library with a paper notebook aesthetic - minimal, professional, and expressive
278 lines • 11.5 kB
TypeScript
import React from 'react';
import { CardViewConfig } from './DataTableCardView';
/**
* Base data item interface - all data items must have an id
*
* All data passed to DataTable must implement this interface to ensure
* proper row identification and selection handling.
*/
export interface BaseDataItem {
/** Unique identifier for the data item */
id: string | number;
}
/**
* Column configuration for DataTable
*
* Defines how each column should be displayed, including width constraints,
* custom rendering, sorting behavior, and alignment.
*/
export interface DataTableColumn<T> {
/** Property key from data item to display in this column */
key: keyof T | string;
/** Column header text */
header: string;
/** Fixed width - supports CSS values ('120px', '15%', '1fr') or numbers (120) */
width?: string | number;
/** Minimum width constraint */
minWidth?: string | number;
/** Maximum width constraint */
maxWidth?: string | number;
/** Flex-grow value for flexible width columns */
flex?: number;
/** Custom render function for cell content */
render?: (item: T, value: any) => React.ReactNode;
/** Secondary line content (smaller, muted text below primary) */
renderSecondary?: (item: T, value: any) => React.ReactNode;
/** Enable sorting for this column */
sortable?: boolean;
/** Additional CSS classes for column cells */
className?: string;
/** Text alignment in column */
align?: 'left' | 'center' | 'right';
}
/**
* Sort configuration
*
* Describes the current sort state for the table.
*/
export interface SortConfig {
/** Column key being sorted */
key: string;
/** Sort direction */
direction: 'asc' | 'desc';
/** Optional display label for sort indicator */
label?: string;
}
/**
* Row action configuration for DataTable
* Defines buttons that appear in the sticky actions column
*/
export interface DataTableAction<T> {
/** Button label text */
label: string;
/** Optional icon - can be component reference or JSX element */
icon?: React.ComponentType<any> | React.ReactNode;
/** Click handler receives the row item */
onClick: (item: T) => void;
/** Button styling variant */
variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
/** Optional conditional visibility */
show?: (item: T) => boolean;
/** Optional tooltip text */
tooltip?: string;
}
/**
* Expansion mode types
*/
export type ExpansionMode = 'edit' | 'details' | string;
/**
* Configuration for different expansion modes
*/
export interface ExpandedRowConfig<T> {
/** Edit mode - inline editing of the record */
edit?: {
render: (item: T, onSave: (updated: T) => Promise<void>, onCancel: () => void) => React.ReactNode;
triggerOnDoubleClick?: boolean;
menuLabel?: string;
menuIcon?: React.ComponentType<any>;
};
/** View details mode - read-only expanded view */
details?: {
render: (item: T) => React.ReactNode;
triggerOnExpand?: boolean;
triggerOnDoubleClick?: boolean;
menuLabel?: string;
menuIcon?: React.ComponentType<any>;
};
/** Add related modes - creating related records */
addRelated?: Array<{
key: string;
label: string;
icon?: React.ComponentType<any>;
render: (parentItem: T, onSave: (newItem: any) => Promise<void>, onCancel: () => void) => React.ReactNode;
showInMenu?: boolean;
}>;
/** Manage related modes - viewing/editing related records */
manageRelated?: Array<{
key: string;
label: string;
icon?: React.ComponentType<any>;
render: (parentItem: T, onClose: () => void) => React.ReactNode;
showInMenu?: boolean;
}>;
}
/**
* DataTable component props
*
* Feature-rich data table with sorting, filtering, selection, expansion,
* row actions, and virtual scrolling support.
*/
interface DataTableProps<T extends BaseDataItem = BaseDataItem> {
/** Array of data items to display */
data: T[];
/** Column definitions */
columns: DataTableColumn<T>[];
/** Show loading skeleton */
loading?: boolean;
/** Error message to display */
error?: string | null;
/** Message shown when data array is empty */
emptyMessage?: string;
/** Number of skeleton rows to show while loading */
loadingRows?: number;
/** Additional CSS classes */
className?: string;
/** Callback when sort changes */
onSortChange?: (sort: SortConfig | null) => void;
/** Current sort configuration */
currentSort?: SortConfig | null;
/** Built-in edit handler - adds Edit action to menu */
onEdit?: (item: T) => void | Promise<void>;
/** Built-in delete handler - adds Delete action to menu */
onDelete?: (item: T) => void | Promise<void>;
/** Optional custom row actions (in addition to edit/delete) */
actions?: DataTableAction<T>[];
/** Enable context menu (right-click) for row actions (default: true when actions exist) */
enableContextMenu?: boolean;
/** Optional click handler for rows */
onRowClick?: (item: T) => void;
/** Optional double-click handler for rows */
onRowDoubleClick?: (item: T) => void;
/** Enable row selection with checkboxes */
selectable?: boolean;
/** Controlled selected rows (set of row keys) */
selectedRows?: Set<string>;
/** Selection change callback */
onRowSelect?: (selectedRows: string[]) => void;
/** Function to extract unique key from row (defaults to row.id) */
keyExtractor?: (row: T) => string;
/** Enable row expansion (legacy - use expandedRowConfig instead) */
expandable?: boolean;
/** Controlled expanded rows (legacy - set of row keys) */
expandedRows?: Set<string>;
/** Render function for expanded row content (legacy - use expandedRowConfig instead) */
renderExpandedRow?: (row: T) => React.ReactNode;
/** NEW: Enhanced expansion configuration with multiple modes */
expandedRowConfig?: ExpandedRowConfig<T>;
/** Show the expand chevron column - hidden by default when using expandedRowConfig with double-click or menu */
showExpandChevron?: boolean;
/** Enable zebra striping - true for default, 'odd' or 'even' for specific rows */
striped?: boolean | 'odd' | 'even';
/** Custom color for striped rows (Tailwind class like 'bg-primary-50' or 'bg-accent-50') */
stripedColor?: string;
/** Row density - affects padding and text size */
density?: 'compact' | 'normal' | 'comfortable';
/** Custom class name for rows - static string or function returning class per row */
rowClassName?: string | ((item: T, index: number) => string);
/** Conditional row highlighting - returns color class (e.g., 'bg-warning-50') */
rowHighlight?: (item: T) => string | undefined;
/** ID of a single row to highlight */
highlightedRowId?: string | number;
/** Enable cell borders */
bordered?: boolean;
/** Custom border color (Tailwind class like 'border-paper-200') */
borderColor?: string;
/** Disable hover effect on rows */
disableHover?: boolean;
/** Array of column keys to hide */
hiddenColumns?: string[];
/** Custom header class name */
headerClassName?: string;
/** Custom empty state render function */
renderEmptyState?: () => React.ReactNode;
/** Enable column resizing */
resizable?: boolean;
/** Callback when column widths change */
onColumnResize?: (columnKey: string, width: number) => void;
/** Enable column reordering */
reorderable?: boolean;
/** Callback when column order changes */
onColumnReorder?: (newOrder: string[]) => void;
/** Enable virtual scrolling for large datasets */
virtualized?: boolean;
/** Container height for virtual scrolling (default: '600px') */
virtualHeight?: string;
/** Row height for virtual scrolling (default: 60) */
virtualRowHeight?: number;
/** Enable built-in pagination (renders Pagination component above table) */
paginated?: boolean;
/** Current page number (1-indexed) */
currentPage?: number;
/** Number of items per page */
pageSize?: number;
/** Total number of items (for server-side pagination) */
totalItems?: number;
/** Callback when page changes */
onPageChange?: (page: number) => void;
/** Available page size options (default: [10, 25, 50, 100]) */
pageSizeOptions?: number[];
/** Callback when page size changes */
onPageSizeChange?: (pageSize: number) => void;
/** Show page size selector (default: true when paginated) */
showPageSizeSelector?: boolean;
/** Mobile view mode: 'auto' (detect viewport), 'card' (always cards), 'table' (always table) */
mobileView?: 'auto' | 'card' | 'table';
/** Configuration for card view layout */
cardConfig?: CardViewConfig<T>;
/** Gap between cards in card view */
cardGap?: 'sm' | 'md' | 'lg';
/** Custom class name for cards */
cardClassName?: string;
}
/**
* DataTable - Feature-rich data table component
*
* Features:
* - Column sorting with visual indicators (3-state: asc → desc → none)
* - Loading states (skeleton + overlay)
* - Empty and error states
* - Row actions with sticky column
* - Row selection with checkboxes (individual + select all)
* - Row expansion with custom content
* - Click and double-click handlers
* - Sticky header and action columns
* - Fixed layout for stability
* - Custom cell rendering
* - Controlled or uncontrolled selection and expansion
* - Column width configuration (width, minWidth, maxWidth, flex)
*
* @example
* ```tsx
* const columns: DataTableColumn<User>[] = [
* { key: 'name', header: 'Name', sortable: true, width: '200px', minWidth: '150px' },
* { key: 'email', header: 'Email', sortable: true, width: '250px' },
* { key: 'role', header: 'Role', width: '120px' },
* ];
*
* const actions: DataTableAction<User>[] = [
* { label: 'Edit', icon: Edit, onClick: handleEdit },
* { label: 'Delete', icon: Trash, onClick: handleDelete, variant: 'danger' },
* ];
*
* <DataTable
* data={users}
* columns={columns}
* loading={loading}
* actions={actions}
* onSortChange={setSort}
* onRowDoubleClick={handleRowDoubleClick}
* selectable
* onRowSelect={handleSelection}
* expandable
* renderExpandedRow={(user) => <UserDetails user={user} />}
* />
* ```
*/
export default function DataTable<T extends BaseDataItem = BaseDataItem>({ data, columns, loading, error, emptyMessage, loadingRows, className, onSortChange, currentSort, onEdit, onDelete, actions, enableContextMenu, onRowClick, onRowDoubleClick, selectable, selectedRows: externalSelectedRows, onRowSelect, keyExtractor, expandable, expandedRows: externalExpandedRows, renderExpandedRow, expandedRowConfig, showExpandChevron, striped, stripedColor, density, rowClassName, rowHighlight, highlightedRowId, bordered, borderColor, disableHover, hiddenColumns, headerClassName, renderEmptyState: customRenderEmptyState, resizable, onColumnResize, reorderable, onColumnReorder, virtualized, virtualHeight, virtualRowHeight, paginated, currentPage, pageSize, totalItems, onPageChange, pageSizeOptions, onPageSizeChange, showPageSizeSelector, mobileView, cardConfig, cardGap, cardClassName, }: DataTableProps<T>): import("react/jsx-runtime").JSX.Element;
export {};
//# sourceMappingURL=DataTable.d.ts.map