@ackplus/react-tanstack-data-table 1.1.19 → 1.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/hooks/use-data-table-engine.d.ts.map +1 -1
- package/dist/lib/hooks/use-data-table-engine.js +54 -15
- package/dist/lib/types/data-table.types.d.ts +2 -1
- package/dist/lib/types/data-table.types.d.ts.map +1 -1
- package/package.json +3 -4
- package/src/index.ts +0 -75
- package/src/lib/components/data-table-view.tsx +0 -386
- package/src/lib/components/droupdown/menu-dropdown.tsx +0 -103
- package/src/lib/components/filters/filter-value-input.tsx +0 -225
- package/src/lib/components/filters/index.ts +0 -126
- package/src/lib/components/headers/draggable-header.tsx +0 -326
- package/src/lib/components/headers/index.ts +0 -6
- package/src/lib/components/headers/table-header.tsx +0 -175
- package/src/lib/components/index.ts +0 -21
- package/src/lib/components/pagination/data-table-pagination.tsx +0 -111
- package/src/lib/components/pagination/index.ts +0 -5
- package/src/lib/components/rows/data-table-row.tsx +0 -218
- package/src/lib/components/rows/empty-data-row.tsx +0 -69
- package/src/lib/components/rows/index.ts +0 -7
- package/src/lib/components/rows/loading-rows.tsx +0 -164
- package/src/lib/components/toolbar/bulk-actions-toolbar.tsx +0 -125
- package/src/lib/components/toolbar/column-filter-control.tsx +0 -432
- package/src/lib/components/toolbar/column-pinning-control.tsx +0 -275
- package/src/lib/components/toolbar/column-reset-control.tsx +0 -74
- package/src/lib/components/toolbar/column-visibility-control.tsx +0 -105
- package/src/lib/components/toolbar/data-table-toolbar.tsx +0 -257
- package/src/lib/components/toolbar/index.ts +0 -17
- package/src/lib/components/toolbar/table-export-control.tsx +0 -233
- package/src/lib/components/toolbar/table-refresh-control.tsx +0 -62
- package/src/lib/components/toolbar/table-search-control.tsx +0 -155
- package/src/lib/components/toolbar/table-size-control.tsx +0 -102
- package/src/lib/contexts/data-table-context.tsx +0 -126
- package/src/lib/data-table.tsx +0 -29
- package/src/lib/features/README.md +0 -161
- package/src/lib/features/column-filter.feature.ts +0 -493
- package/src/lib/features/index.ts +0 -23
- package/src/lib/features/selection.feature.ts +0 -322
- package/src/lib/hooks/index.ts +0 -2
- package/src/lib/hooks/use-data-table-engine.ts +0 -1516
- package/src/lib/icons/add-icon.tsx +0 -23
- package/src/lib/icons/csv-icon.tsx +0 -15
- package/src/lib/icons/delete-icon.tsx +0 -30
- package/src/lib/icons/excel-icon.tsx +0 -15
- package/src/lib/icons/index.ts +0 -7
- package/src/lib/icons/unpin-icon.tsx +0 -18
- package/src/lib/icons/view-comfortable-icon.tsx +0 -45
- package/src/lib/icons/view-compact-icon.tsx +0 -55
- package/src/lib/types/column.types.ts +0 -63
- package/src/lib/types/data-table-api.ts +0 -191
- package/src/lib/types/data-table.types.ts +0 -192
- package/src/lib/types/export.types.ts +0 -223
- package/src/lib/types/index.ts +0 -24
- package/src/lib/types/slots.types.ts +0 -342
- package/src/lib/types/table.types.ts +0 -88
- package/src/lib/utils/column-helpers.ts +0 -72
- package/src/lib/utils/debounced-fetch.utils.ts +0 -131
- package/src/lib/utils/export-utils.ts +0 -712
- package/src/lib/utils/index.ts +0 -27
- package/src/lib/utils/logger.ts +0 -203
- package/src/lib/utils/slot-helpers.tsx +0 -194
- package/src/lib/utils/special-columns.utils.ts +0 -101
- package/src/lib/utils/styling-helpers.ts +0 -126
- package/src/lib/utils/table-helpers.ts +0 -106
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { Clear, Search } from '@mui/icons-material';
|
|
2
|
-
import { Box, Tooltip, IconButton, Collapse, OutlinedInput, InputAdornment, IconButtonProps, OutlinedInputProps, SxProps } from '@mui/material';
|
|
3
|
-
import React, { useCallback, useEffect, useRef, useState, ReactElement } from 'react';
|
|
4
|
-
|
|
5
|
-
import { useDataTableContext } from '../../contexts/data-table-context';
|
|
6
|
-
import { getSlotComponent, mergeSlotProps, extractSlotProps } from '../../utils/slot-helpers';
|
|
7
|
-
|
|
8
|
-
export interface TableSearchControlProps {
|
|
9
|
-
// Allow full customization of any prop
|
|
10
|
-
placeholder?: string;
|
|
11
|
-
autoFocus?: boolean;
|
|
12
|
-
searchIconProps?: IconButtonProps;
|
|
13
|
-
clearIconProps?: IconButtonProps;
|
|
14
|
-
inputProps?: OutlinedInputProps;
|
|
15
|
-
containerSx?: SxProps;
|
|
16
|
-
tooltipProps?: any;
|
|
17
|
-
[key: string]: any;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function TableSearchControl(props: TableSearchControlProps = {}): ReactElement {
|
|
21
|
-
const { table, slots, slotProps } = useDataTableContext();
|
|
22
|
-
const [searchVisible, setSearchVisible] = useState(false);
|
|
23
|
-
const searchInputRef = useRef<HTMLInputElement>(null);
|
|
24
|
-
const globalFilter = table.getState().globalFilter || '';
|
|
25
|
-
const hasSearch = globalFilter.length > 0;
|
|
26
|
-
|
|
27
|
-
// Extract slot-specific props with enhanced merging
|
|
28
|
-
const searchIconSlotProps = extractSlotProps(slotProps, 'searchIcon');
|
|
29
|
-
const clearIconSlotProps = extractSlotProps(slotProps, 'clearIcon');
|
|
30
|
-
|
|
31
|
-
const SearchIconSlot = getSlotComponent(slots, 'searchIcon', Search);
|
|
32
|
-
const ClearIconSlot = getSlotComponent(slots, 'clearIcon', Clear);
|
|
33
|
-
|
|
34
|
-
const handleChange = useCallback(
|
|
35
|
-
(e: any) => {
|
|
36
|
-
table.setGlobalFilter(e.target.value);
|
|
37
|
-
},
|
|
38
|
-
[table],
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
const handleSearchToggle = () => {
|
|
42
|
-
if (searchVisible || hasSearch) {
|
|
43
|
-
// If search is visible or has text, hide it and clear
|
|
44
|
-
setSearchVisible(false);
|
|
45
|
-
table.setGlobalFilter('');
|
|
46
|
-
} else {
|
|
47
|
-
// Show search input
|
|
48
|
-
setSearchVisible(true);
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const handleSearchClear = () => {
|
|
53
|
-
table.setGlobalFilter('');
|
|
54
|
-
if (searchInputRef.current) {
|
|
55
|
-
searchInputRef.current.focus();
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const handleSearchBlur = () => {
|
|
60
|
-
// Only auto-hide if search is empty
|
|
61
|
-
if (searchVisible && !hasSearch) {
|
|
62
|
-
setSearchVisible(false);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
if (searchVisible && searchInputRef.current) {
|
|
68
|
-
// Add a delay to ensure the Collapse animation completes
|
|
69
|
-
const timer = setTimeout(() => {
|
|
70
|
-
searchInputRef.current?.focus();
|
|
71
|
-
}, 200);
|
|
72
|
-
return () => clearTimeout(timer);
|
|
73
|
-
}
|
|
74
|
-
return undefined;
|
|
75
|
-
}, [searchVisible]);
|
|
76
|
-
|
|
77
|
-
// Merge all props for maximum flexibility
|
|
78
|
-
const mergedSearchIconProps = mergeSlotProps(
|
|
79
|
-
{
|
|
80
|
-
size: 'small',
|
|
81
|
-
onClick: handleSearchToggle,
|
|
82
|
-
color: hasSearch ? 'primary' : 'default',
|
|
83
|
-
sx: { flexShrink: 0 },
|
|
84
|
-
},
|
|
85
|
-
searchIconSlotProps,
|
|
86
|
-
props.searchIconProps || {}
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
const mergedClearIconProps = mergeSlotProps(
|
|
90
|
-
{
|
|
91
|
-
size: 'small',
|
|
92
|
-
onClick: handleSearchClear,
|
|
93
|
-
},
|
|
94
|
-
clearIconSlotProps,
|
|
95
|
-
props.clearIconProps || {}
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
const mergedInputProps = mergeSlotProps(
|
|
99
|
-
{
|
|
100
|
-
inputRef: searchInputRef,
|
|
101
|
-
size: 'small',
|
|
102
|
-
placeholder: props.placeholder || 'Search...',
|
|
103
|
-
value: globalFilter,
|
|
104
|
-
onChange: handleChange,
|
|
105
|
-
onBlur: handleSearchBlur,
|
|
106
|
-
autoFocus: props.autoFocus,
|
|
107
|
-
sx: { minWidth: 200 },
|
|
108
|
-
},
|
|
109
|
-
props.inputProps || {}
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<Box
|
|
114
|
-
sx={{
|
|
115
|
-
display: 'flex',
|
|
116
|
-
alignItems: 'center',
|
|
117
|
-
...props.containerSx,
|
|
118
|
-
}}
|
|
119
|
-
>
|
|
120
|
-
{!(searchVisible || hasSearch) && (
|
|
121
|
-
<Tooltip
|
|
122
|
-
title="Search"
|
|
123
|
-
{...props.tooltipProps}
|
|
124
|
-
>
|
|
125
|
-
<IconButton
|
|
126
|
-
{...mergedSearchIconProps}
|
|
127
|
-
>
|
|
128
|
-
<SearchIconSlot {...searchIconSlotProps} />
|
|
129
|
-
</IconButton>
|
|
130
|
-
</Tooltip>
|
|
131
|
-
)}
|
|
132
|
-
|
|
133
|
-
<Collapse
|
|
134
|
-
in={searchVisible || hasSearch}
|
|
135
|
-
orientation="horizontal"
|
|
136
|
-
timeout={200}
|
|
137
|
-
>
|
|
138
|
-
<OutlinedInput
|
|
139
|
-
{...mergedInputProps}
|
|
140
|
-
endAdornment={
|
|
141
|
-
hasSearch ? (
|
|
142
|
-
<InputAdornment position="end">
|
|
143
|
-
<IconButton
|
|
144
|
-
{...mergedClearIconProps}
|
|
145
|
-
>
|
|
146
|
-
<ClearIconSlot {...clearIconSlotProps} />
|
|
147
|
-
</IconButton>
|
|
148
|
-
</InputAdornment>
|
|
149
|
-
) : null
|
|
150
|
-
}
|
|
151
|
-
/>
|
|
152
|
-
</Collapse>
|
|
153
|
-
</Box>
|
|
154
|
-
);
|
|
155
|
-
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import React, { ReactElement } from 'react';
|
|
2
|
-
import { LineWeightOutlined } from '@mui/icons-material';
|
|
3
|
-
import { MenuItem, ListItemIcon, ListItemText, Tooltip, IconButton, IconButtonProps, SxProps } from '@mui/material';
|
|
4
|
-
|
|
5
|
-
import { MenuDropdown } from '../droupdown/menu-dropdown';
|
|
6
|
-
import { useDataTableContext } from '../../contexts/data-table-context';
|
|
7
|
-
import { ViewComfortableIcon, ViewCompactIcon } from '../../icons';
|
|
8
|
-
import { getSlotComponent, mergeSlotProps, extractSlotProps } from '../../utils/slot-helpers';
|
|
9
|
-
|
|
10
|
-
export interface TableSizeControlProps {
|
|
11
|
-
// Allow full customization of any prop
|
|
12
|
-
iconButtonProps?: IconButtonProps;
|
|
13
|
-
menuProps?: any;
|
|
14
|
-
tooltipProps?: any;
|
|
15
|
-
containerSx?: SxProps;
|
|
16
|
-
[key: string]: any;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function TableSizeControl(props: TableSizeControlProps = {}): ReactElement {
|
|
20
|
-
const { tableSize, onTableSizeChange, slotProps, slots } = useDataTableContext();
|
|
21
|
-
|
|
22
|
-
// Extract slot-specific props with enhanced merging
|
|
23
|
-
const tableSizeIconSlotProps = extractSlotProps(slotProps, 'tableSizeIcon');
|
|
24
|
-
const tableSizeSmallIconSlotProps = extractSlotProps(slotProps, 'tableSizeSmallIcon');
|
|
25
|
-
const tableSizeMediumIconSlotProps = extractSlotProps(slotProps, 'tableSizeMediumIcon');
|
|
26
|
-
|
|
27
|
-
const TableSizeIconSlot = getSlotComponent(slots, 'tableSizeIcon', LineWeightOutlined);
|
|
28
|
-
const TableSizeSmallIconSlot = getSlotComponent(slots, 'tableSizeSmallIcon', ViewCompactIcon);
|
|
29
|
-
const TableSizeMediumIconSlot = getSlotComponent(slots, 'tableSizeMediumIcon', ViewComfortableIcon);
|
|
30
|
-
|
|
31
|
-
const SIZE_OPTIONS = [
|
|
32
|
-
{
|
|
33
|
-
value: 'small' as const,
|
|
34
|
-
label: 'Compact',
|
|
35
|
-
description: 'Small padding, compact rows',
|
|
36
|
-
icon: <TableSizeSmallIconSlot {...tableSizeSmallIconSlotProps} />,
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
value: 'medium' as const,
|
|
40
|
-
label: 'Standard',
|
|
41
|
-
description: 'Default padding and spacing',
|
|
42
|
-
icon: <TableSizeMediumIconSlot {...tableSizeMediumIconSlotProps} />,
|
|
43
|
-
},
|
|
44
|
-
];
|
|
45
|
-
|
|
46
|
-
// Merge all props for maximum flexibility
|
|
47
|
-
const mergedIconButtonProps = mergeSlotProps(
|
|
48
|
-
{
|
|
49
|
-
size: 'small',
|
|
50
|
-
sx: { flexShrink: 0 },
|
|
51
|
-
},
|
|
52
|
-
tableSizeIconSlotProps,
|
|
53
|
-
props.iconButtonProps || {}
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<MenuDropdown
|
|
58
|
-
anchor={(
|
|
59
|
-
<Tooltip
|
|
60
|
-
title="Table size"
|
|
61
|
-
{...props.tooltipProps}
|
|
62
|
-
>
|
|
63
|
-
<IconButton
|
|
64
|
-
{...mergedIconButtonProps}
|
|
65
|
-
>
|
|
66
|
-
<TableSizeIconSlot {...tableSizeIconSlotProps} />
|
|
67
|
-
</IconButton>
|
|
68
|
-
</Tooltip>
|
|
69
|
-
)}
|
|
70
|
-
>
|
|
71
|
-
{SIZE_OPTIONS.map((option) => (
|
|
72
|
-
<MenuItem
|
|
73
|
-
key={option.value}
|
|
74
|
-
selected={tableSize === option.value}
|
|
75
|
-
onClick={() => onTableSizeChange(option.value)}
|
|
76
|
-
sx={{
|
|
77
|
-
minWidth: 200,
|
|
78
|
-
...props.containerSx,
|
|
79
|
-
}}
|
|
80
|
-
>
|
|
81
|
-
<ListItemIcon sx={{ minWidth: 36 }}>
|
|
82
|
-
{option.icon}
|
|
83
|
-
</ListItemIcon>
|
|
84
|
-
<ListItemText
|
|
85
|
-
primary={option.label}
|
|
86
|
-
secondary={option.description}
|
|
87
|
-
slotProps={{
|
|
88
|
-
primary: {
|
|
89
|
-
variant: 'body2',
|
|
90
|
-
fontWeight: tableSize === option.value ? 600 : 400,
|
|
91
|
-
},
|
|
92
|
-
secondary: {
|
|
93
|
-
variant: 'caption',
|
|
94
|
-
color: 'text.secondary',
|
|
95
|
-
},
|
|
96
|
-
}}
|
|
97
|
-
/>
|
|
98
|
-
</MenuItem>
|
|
99
|
-
))}
|
|
100
|
-
</MenuDropdown>
|
|
101
|
-
);
|
|
102
|
-
}
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import { Table } from '@tanstack/react-table';
|
|
2
|
-
import React, { createContext, useContext, ReactNode, useMemo, RefObject, ReactElement } from 'react';
|
|
3
|
-
|
|
4
|
-
import { ColumnFilterState, TableSize } from '../types';
|
|
5
|
-
import { SelectionState } from '../features';
|
|
6
|
-
import { DataTableApi } from '../types/data-table-api';
|
|
7
|
-
import { ExportPhase, ExportProgressPayload, ServerExportResult } from '../types/export.types';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Context value for the DataTable
|
|
12
|
-
*/
|
|
13
|
-
interface DataTableContextValue<T = any> {
|
|
14
|
-
table?: Table<T>;
|
|
15
|
-
apiRef?: RefObject<DataTableApi<T> | null>;
|
|
16
|
-
dataMode?: 'client' | 'server';
|
|
17
|
-
tableSize?: TableSize;
|
|
18
|
-
onTableSizeChange?: (size: TableSize) => void;
|
|
19
|
-
columnFilter?: ColumnFilterState;
|
|
20
|
-
onChangeColumnFilter?: (filter: ColumnFilterState) => void;
|
|
21
|
-
slots?: Record<string, any>;
|
|
22
|
-
slotProps?: Record<string, any>;
|
|
23
|
-
|
|
24
|
-
// Export state - managed by the DataTable component
|
|
25
|
-
isExporting?: boolean;
|
|
26
|
-
exportController?: AbortController | null;
|
|
27
|
-
exportPhase?: ExportPhase | null;
|
|
28
|
-
exportProgress?: ExportProgressPayload;
|
|
29
|
-
onCancelExport?: () => void;
|
|
30
|
-
|
|
31
|
-
// Export callbacks - passed from DataTable props
|
|
32
|
-
exportFilename?: string;
|
|
33
|
-
onExportProgress?: (progress: ExportProgressPayload) => void;
|
|
34
|
-
onExportComplete?: (result: { success: boolean; filename: string; totalRows: number }) => void;
|
|
35
|
-
onExportError?: (error: { message: string; code: string }) => void;
|
|
36
|
-
onServerExport?: (
|
|
37
|
-
filters?: Partial<any>,
|
|
38
|
-
selection?: SelectionState,
|
|
39
|
-
signal?: AbortSignal
|
|
40
|
-
) => Promise<ServerExportResult<any>>;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const DataTableContext = createContext<DataTableContextValue | null>(null);
|
|
44
|
-
|
|
45
|
-
interface DataTableProviderProps<T = any> extends DataTableContextValue<T> {
|
|
46
|
-
children: ReactNode;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function DataTableProvider<T = any>({
|
|
50
|
-
children,
|
|
51
|
-
table,
|
|
52
|
-
apiRef,
|
|
53
|
-
dataMode,
|
|
54
|
-
tableSize,
|
|
55
|
-
onTableSizeChange,
|
|
56
|
-
columnFilter,
|
|
57
|
-
onChangeColumnFilter,
|
|
58
|
-
slots = {},
|
|
59
|
-
slotProps = {},
|
|
60
|
-
isExporting,
|
|
61
|
-
exportController,
|
|
62
|
-
exportPhase,
|
|
63
|
-
exportProgress,
|
|
64
|
-
onCancelExport,
|
|
65
|
-
exportFilename,
|
|
66
|
-
onExportProgress,
|
|
67
|
-
onExportComplete,
|
|
68
|
-
onExportError,
|
|
69
|
-
onServerExport,
|
|
70
|
-
}: DataTableProviderProps<T>): ReactElement {
|
|
71
|
-
const value = useMemo(() => ({
|
|
72
|
-
table,
|
|
73
|
-
apiRef,
|
|
74
|
-
dataMode,
|
|
75
|
-
tableSize,
|
|
76
|
-
onTableSizeChange,
|
|
77
|
-
columnFilter,
|
|
78
|
-
onChangeColumnFilter,
|
|
79
|
-
slots,
|
|
80
|
-
slotProps,
|
|
81
|
-
isExporting,
|
|
82
|
-
exportController,
|
|
83
|
-
exportPhase,
|
|
84
|
-
exportProgress,
|
|
85
|
-
onCancelExport,
|
|
86
|
-
exportFilename,
|
|
87
|
-
onExportProgress,
|
|
88
|
-
onExportComplete,
|
|
89
|
-
onExportError,
|
|
90
|
-
onServerExport,
|
|
91
|
-
}), [
|
|
92
|
-
table,
|
|
93
|
-
apiRef,
|
|
94
|
-
dataMode,
|
|
95
|
-
tableSize,
|
|
96
|
-
onTableSizeChange,
|
|
97
|
-
columnFilter,
|
|
98
|
-
onChangeColumnFilter,
|
|
99
|
-
slots,
|
|
100
|
-
slotProps,
|
|
101
|
-
isExporting,
|
|
102
|
-
exportController,
|
|
103
|
-
exportPhase,
|
|
104
|
-
exportProgress,
|
|
105
|
-
onCancelExport,
|
|
106
|
-
exportFilename,
|
|
107
|
-
onExportProgress,
|
|
108
|
-
onExportComplete,
|
|
109
|
-
onExportError,
|
|
110
|
-
onServerExport,
|
|
111
|
-
]);
|
|
112
|
-
|
|
113
|
-
return (
|
|
114
|
-
<DataTableContext.Provider value={value}>
|
|
115
|
-
{children}
|
|
116
|
-
</DataTableContext.Provider>
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export function useDataTableContext<T = any>(): DataTableContextValue<T> {
|
|
121
|
-
const context = useContext(DataTableContext);
|
|
122
|
-
if (!context) {
|
|
123
|
-
throw new Error('useDataTableContext must be used within a DataTableProvider');
|
|
124
|
-
}
|
|
125
|
-
return context;
|
|
126
|
-
}
|
package/src/lib/data-table.tsx
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Main DataTable Component (thin wrapper)
|
|
3
|
-
*
|
|
4
|
-
* Composes useDataTableEngine + DataTableProvider + DataTableView.
|
|
5
|
-
* Preserves forwardRef API and DataTableApi surface.
|
|
6
|
-
*/
|
|
7
|
-
import React, { forwardRef, useImperativeHandle } from 'react';
|
|
8
|
-
|
|
9
|
-
import { DataTableProvider } from './contexts/data-table-context';
|
|
10
|
-
import { useDataTableEngine } from './hooks/use-data-table-engine';
|
|
11
|
-
import { DataTableView } from './components/data-table-view';
|
|
12
|
-
import type { DataTableProps } from './types/data-table.types';
|
|
13
|
-
import type { DataTableApi } from './types/data-table-api';
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export const DataTable = forwardRef(function DataTable<T extends Record<string, any>>(
|
|
17
|
-
props: DataTableProps<T>,
|
|
18
|
-
ref: React.Ref<DataTableApi<T>>,
|
|
19
|
-
) {
|
|
20
|
-
const engine = useDataTableEngine<T>(props);
|
|
21
|
-
|
|
22
|
-
useImperativeHandle(ref, () => engine.refs.apiRef.current!, []);
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<DataTableProvider {...engine.providerProps}>
|
|
26
|
-
<DataTableView<T> engine={engine} {...props} />
|
|
27
|
-
</DataTableProvider>
|
|
28
|
-
);
|
|
29
|
-
});
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
# Custom TanStack Table Features
|
|
2
|
-
|
|
3
|
-
This directory contains custom features that extend TanStack Table functionality following the official custom features pattern introduced in v8.14.0.
|
|
4
|
-
|
|
5
|
-
## Custom Column Filter Feature
|
|
6
|
-
|
|
7
|
-
The Custom Column Filter Feature adds advanced column filtering capabilities to TanStack Table, providing a more sophisticated filtering UI with AND/OR logic and multiple operators.
|
|
8
|
-
|
|
9
|
-
### Features
|
|
10
|
-
|
|
11
|
-
- **Multiple Filter Conditions**: Add multiple filter rules for different columns
|
|
12
|
-
- **Logic Operators**: Choose between AND/OR logic for combining filters
|
|
13
|
-
- **Various Operators**: Support for equals, contains, greater than, less than, empty checks, etc.
|
|
14
|
-
- **Type-Aware Filtering**: Different operators available based on column type
|
|
15
|
-
- **Integrated State Management**: Filters are managed within TanStack Table's state system
|
|
16
|
-
|
|
17
|
-
### Usage
|
|
18
|
-
|
|
19
|
-
#### 1. Import the Feature
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
import { CustomColumnFilterFeature } from '@your-package/features';
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
#### 2. Add to Table Options
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
const table = useReactTable({
|
|
29
|
-
_features: [CustomColumnFilterFeature], // Add the custom feature
|
|
30
|
-
data,
|
|
31
|
-
columns,
|
|
32
|
-
// ... other options
|
|
33
|
-
});
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
#### 3. Use the Feature Methods
|
|
37
|
-
|
|
38
|
-
The feature adds several methods to your table instance:
|
|
39
|
-
|
|
40
|
-
```typescript
|
|
41
|
-
// Add a new filter
|
|
42
|
-
table.addColumnFilter('columnId', 'contains', 'search value');
|
|
43
|
-
|
|
44
|
-
// Update an existing filter
|
|
45
|
-
table.updateColumnFilter('filterId', { value: 'new value' });
|
|
46
|
-
|
|
47
|
-
// Remove a filter
|
|
48
|
-
table.removeColumnFilter('filterId');
|
|
49
|
-
|
|
50
|
-
// Clear all filters
|
|
51
|
-
table.clearAllColumnFilters();
|
|
52
|
-
|
|
53
|
-
// Get active filters
|
|
54
|
-
const activeFilters = table.getActiveColumnFilters();
|
|
55
|
-
|
|
56
|
-
// Set filter logic (AND/OR)
|
|
57
|
-
table.setFilterLogic('OR');
|
|
58
|
-
|
|
59
|
-
// Get current filter state
|
|
60
|
-
const filterState = table.getColumnFilterState();
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
#### 4. Handle State Changes
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
const table = useReactTable({
|
|
67
|
-
_features: [CustomColumnFilterFeature],
|
|
68
|
-
// ... other options
|
|
69
|
-
onCustomColumnFilterChange: (updater) => {
|
|
70
|
-
// Handle filter state changes
|
|
71
|
-
const newState = typeof updater === 'function'
|
|
72
|
-
? updater(currentState)
|
|
73
|
-
: updater;
|
|
74
|
-
|
|
75
|
-
// Update your local state or trigger server requests
|
|
76
|
-
handleFilterChange(newState);
|
|
77
|
-
},
|
|
78
|
-
});
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Available Filter Operators
|
|
82
|
-
|
|
83
|
-
| Operator | Description | Types |
|
|
84
|
-
|----------|-------------|-------|
|
|
85
|
-
| `equals` | Exact match | All |
|
|
86
|
-
| `notEquals` | Not equal to | All |
|
|
87
|
-
| `contains` | Contains substring | Text |
|
|
88
|
-
| `notContains` | Does not contain | Text |
|
|
89
|
-
| `startsWith` | Starts with | Text |
|
|
90
|
-
| `endsWith` | Ends with | Text |
|
|
91
|
-
| `isEmpty` | Is empty/null | All |
|
|
92
|
-
| `isNotEmpty` | Is not empty/null | All |
|
|
93
|
-
| `greaterThan` | Greater than | Number, Date |
|
|
94
|
-
| `greaterThanOrEqual` | Greater than or equal | Number, Date |
|
|
95
|
-
| `lessThan` | Less than | Number, Date |
|
|
96
|
-
| `lessThanOrEqual` | Less than or equal | Number, Date |
|
|
97
|
-
| `between` | Between two values | Number, Date |
|
|
98
|
-
| `in` | In array of values | All |
|
|
99
|
-
| `notIn` | Not in array of values | All |
|
|
100
|
-
|
|
101
|
-
### Client-Side Filtering
|
|
102
|
-
|
|
103
|
-
For client-side filtering, you can use the provided utility function:
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
import { matchesCustomColumnFilters } from '@your-package/features';
|
|
107
|
-
|
|
108
|
-
const filteredRows = rows.filter(row =>
|
|
109
|
-
matchesCustomColumnFilters(row, filters, logic)
|
|
110
|
-
);
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### Server-Side Filtering
|
|
114
|
-
|
|
115
|
-
For server-side filtering, listen to filter changes and send the filter state to your backend:
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
const handleFilterChange = (filterState) => {
|
|
119
|
-
// Send to server
|
|
120
|
-
fetchData({
|
|
121
|
-
filters: filterState.filters,
|
|
122
|
-
logic: filterState.logic,
|
|
123
|
-
// ... other params
|
|
124
|
-
});
|
|
125
|
-
};
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### TypeScript Integration
|
|
129
|
-
|
|
130
|
-
The feature includes full TypeScript support with declaration merging that extends TanStack Table's types:
|
|
131
|
-
|
|
132
|
-
```typescript
|
|
133
|
-
// These types are automatically available after importing the feature
|
|
134
|
-
interface CustomColumnFilterState {
|
|
135
|
-
filters: ColumnFilterRule[];
|
|
136
|
-
logic: 'AND' | 'OR';
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
interface ColumnFilterRule {
|
|
140
|
-
id: string;
|
|
141
|
-
columnId: string;
|
|
142
|
-
operator: string;
|
|
143
|
-
value: any;
|
|
144
|
-
columnType?: string;
|
|
145
|
-
}
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Example
|
|
149
|
-
|
|
150
|
-
See `custom-column-filter-example.tsx` for a complete working example.
|
|
151
|
-
|
|
152
|
-
## Creating Additional Custom Features
|
|
153
|
-
|
|
154
|
-
To create additional custom features, follow the TanStack Table custom features pattern:
|
|
155
|
-
|
|
156
|
-
1. Define TypeScript types
|
|
157
|
-
2. Use declaration merging to extend TanStack Table types
|
|
158
|
-
3. Create the feature object with `getInitialState`, `getDefaultOptions`, and `createTable`
|
|
159
|
-
4. Add the feature to your table's `_features` array
|
|
160
|
-
|
|
161
|
-
Refer to the TanStack Table documentation for more details on creating custom features.
|