@reactorui/datagrid 1.0.19 → 1.0.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/README.md +273 -551
- package/dist/components/DataGrid/DataGrid.d.ts +1 -1
- package/dist/components/DataGrid/DataGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/DataGrid.js +80 -47
- package/dist/components/Filter/FilterControls.d.ts +6 -2
- package/dist/components/Filter/FilterControls.d.ts.map +1 -1
- package/dist/components/Filter/FilterControls.js +114 -62
- package/dist/components/Table/TableHeader.d.ts +2 -1
- package/dist/components/Table/TableHeader.d.ts.map +1 -1
- package/dist/components/Table/TableHeader.js +4 -2
- package/dist/hooks/useDataGrid.d.ts +16 -18
- package/dist/hooks/useDataGrid.d.ts.map +1 -1
- package/dist/hooks/useDataGrid.js +139 -299
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/types/index.d.ts +76 -38
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/utils/index.d.ts +14 -5
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +166 -156
- package/package.json +1 -1
|
@@ -1,354 +1,194 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const [searchTerm, setSearchTerm] = useState('');
|
|
1
|
+
// File: src/hooks/useDataGrid.ts
|
|
2
|
+
import { useState, useCallback, useMemo } from 'react';
|
|
3
|
+
import { compareValues, sortData } from '../utils';
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// Hook Implementation
|
|
6
|
+
// ============================================================================
|
|
7
|
+
export const useDataGrid = ({ data, pageSize: initialPageSize = 10, totalRecords: externalTotalRecords, currentPage: externalCurrentPage, loading: externalLoading = false, onPageChange, onPageSizeChange, onSortChange, onSearchChange, onApplyFilter, onRemoveFilter, onClearFilters, onFilterChange, }) => {
|
|
8
|
+
// ===== Internal State =====
|
|
9
|
+
const [searchTerm, setSearchTermState] = useState('');
|
|
11
10
|
const [activeFilters, setActiveFilters] = useState([]);
|
|
12
11
|
const [sortConfig, setSortConfig] = useState({ column: '', direction: 'asc' });
|
|
13
12
|
const [selectedRows, setSelectedRows] = useState(new Set());
|
|
14
|
-
|
|
15
|
-
const [
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
//
|
|
20
|
-
const sourceData = staticData || serverData;
|
|
21
|
-
// Generate stable unique IDs for rows - always generate, never use existing fields
|
|
13
|
+
const [internalPage, setInternalPage] = useState(1);
|
|
14
|
+
const [currentPageSize, setCurrentPageSizeState] = useState(initialPageSize);
|
|
15
|
+
// Determine if we're in controlled mode (server-side) or uncontrolled (client-side)
|
|
16
|
+
const isControlled = externalTotalRecords !== undefined;
|
|
17
|
+
const currentPage = externalCurrentPage ?? internalPage;
|
|
18
|
+
// ===== Row ID Generation =====
|
|
22
19
|
const rowIdMap = useMemo(() => {
|
|
23
20
|
const map = new Map();
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
const
|
|
27
|
-
.
|
|
28
|
-
.
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
data.forEach((row, index) => {
|
|
22
|
+
// Use existing id if available, otherwise generate stable ID
|
|
23
|
+
const id = row.id !== undefined
|
|
24
|
+
? String(row.id)
|
|
25
|
+
: `row-${index}-${JSON.stringify(row)
|
|
26
|
+
.slice(0, 30)
|
|
27
|
+
.replace(/[^a-zA-Z0-9]/g, '')}`;
|
|
28
|
+
map.set(row, id);
|
|
31
29
|
});
|
|
32
30
|
return map;
|
|
33
|
-
}, [
|
|
34
|
-
// Helper function to get row ID - always uses generated IDs
|
|
31
|
+
}, [data]);
|
|
35
32
|
const getRowId = useCallback((row) => {
|
|
36
33
|
return rowIdMap.get(row) || `fallback-${Math.random().toString(36).substr(2, 9)}`;
|
|
37
34
|
}, [rowIdMap]);
|
|
38
|
-
//
|
|
39
|
-
const handleLoadingChange = useCallback((newLoading, context) => {
|
|
40
|
-
setLoading(newLoading);
|
|
41
|
-
onLoadingStateChange?.(newLoading, context);
|
|
42
|
-
}, [onLoadingStateChange]);
|
|
43
|
-
// Internal error handler
|
|
44
|
-
const handleError = useCallback((err, context) => {
|
|
45
|
-
const errorMessage = err.message || 'An unknown error occurred';
|
|
46
|
-
setError(errorMessage);
|
|
47
|
-
onDataError?.(err, context);
|
|
48
|
-
}, [onDataError]);
|
|
49
|
-
// Process data (search, filter, sort) - sorting is ALWAYS client-side
|
|
35
|
+
// ===== Data Processing (Client-side only) =====
|
|
50
36
|
const processedData = useMemo(() => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
//
|
|
57
|
-
if (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
37
|
+
if (isControlled) {
|
|
38
|
+
// In controlled mode, parent handles filtering - just sort
|
|
39
|
+
return sortConfig.column ? sortData(data, sortConfig.column, sortConfig.direction) : data;
|
|
40
|
+
}
|
|
41
|
+
let result = [...data];
|
|
42
|
+
// Search
|
|
43
|
+
if (searchTerm) {
|
|
44
|
+
const term = searchTerm.toLowerCase();
|
|
45
|
+
result = result.filter((row) => Object.values(row).some((value) => value?.toString().toLowerCase().includes(term)));
|
|
46
|
+
}
|
|
47
|
+
// Filters
|
|
48
|
+
activeFilters.forEach((filter) => {
|
|
49
|
+
result = result.filter((row) => {
|
|
50
|
+
const value = row[filter.column];
|
|
51
|
+
return compareValues(value, filter.value, filter.operator, filter.dataType);
|
|
63
52
|
});
|
|
64
|
-
}
|
|
65
|
-
//
|
|
53
|
+
});
|
|
54
|
+
// Sort
|
|
66
55
|
if (sortConfig.column) {
|
|
67
|
-
|
|
56
|
+
result = sortData(result, sortConfig.column, sortConfig.direction);
|
|
68
57
|
}
|
|
69
|
-
return
|
|
70
|
-
}, [
|
|
71
|
-
//
|
|
58
|
+
return result;
|
|
59
|
+
}, [data, searchTerm, activeFilters, sortConfig, isControlled]);
|
|
60
|
+
// ===== Pagination =====
|
|
72
61
|
const paginatedData = useMemo(() => {
|
|
73
|
-
if (
|
|
74
|
-
return
|
|
62
|
+
if (isControlled)
|
|
63
|
+
return data; // Parent handles pagination
|
|
75
64
|
const start = (currentPage - 1) * currentPageSize;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}, [processedData, currentPage, currentPageSize, staticData, sourceData]);
|
|
79
|
-
// Memoize selectedData with proper dependencies and stable ID handling
|
|
80
|
-
const selectedData = useMemo(() => {
|
|
81
|
-
return sourceData.filter((row) => {
|
|
82
|
-
const rowId = getRowId(row);
|
|
83
|
-
return selectedRows.has(rowId);
|
|
84
|
-
});
|
|
85
|
-
}, [sourceData, selectedRows, getRowId]);
|
|
86
|
-
// Pagination info
|
|
65
|
+
return processedData.slice(start, start + currentPageSize);
|
|
66
|
+
}, [processedData, currentPage, currentPageSize, isControlled, data]);
|
|
87
67
|
const paginationInfo = useMemo(() => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const end = displayedCount;
|
|
93
|
-
return {
|
|
94
|
-
currentPage,
|
|
95
|
-
totalPages: 1, // Not meaningful with continuation tokens
|
|
96
|
-
pageSize: currentPageSize,
|
|
97
|
-
totalRecords: lastServerResponse.Count,
|
|
98
|
-
start,
|
|
99
|
-
end,
|
|
100
|
-
hasNext: lastServerResponse.HasMore,
|
|
101
|
-
hasPrevious: tokenHistory.length > 0,
|
|
102
|
-
continuationToken: lastServerResponse.ContinuationToken,
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
// Client-side pagination info
|
|
106
|
-
const totalPages = Math.ceil(processedData.length / currentPageSize);
|
|
107
|
-
const start = processedData.length === 0 ? 0 : (currentPage - 1) * currentPageSize + 1;
|
|
108
|
-
const end = Math.min(currentPage * currentPageSize, processedData.length);
|
|
68
|
+
const total = isControlled ? (externalTotalRecords ?? 0) : processedData.length;
|
|
69
|
+
const totalPages = Math.ceil(total / currentPageSize);
|
|
70
|
+
const start = total === 0 ? 0 : (currentPage - 1) * currentPageSize + 1;
|
|
71
|
+
const end = Math.min(currentPage * currentPageSize, total);
|
|
109
72
|
return {
|
|
110
73
|
currentPage,
|
|
111
74
|
totalPages,
|
|
112
75
|
pageSize: currentPageSize,
|
|
113
|
-
totalRecords:
|
|
76
|
+
totalRecords: total,
|
|
114
77
|
start,
|
|
115
78
|
end,
|
|
116
79
|
hasNext: currentPage < totalPages,
|
|
117
80
|
hasPrevious: currentPage > 1,
|
|
118
81
|
};
|
|
119
|
-
}, [
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return;
|
|
132
|
-
handleLoadingChange(true, 'data-load');
|
|
133
|
-
setError(null);
|
|
134
|
-
try {
|
|
135
|
-
let requestToken = continuationToken;
|
|
136
|
-
// Handle navigation
|
|
137
|
-
if (resetPagination) {
|
|
138
|
-
requestToken = undefined;
|
|
139
|
-
setContinuationToken(undefined);
|
|
140
|
-
setTokenHistory([]);
|
|
141
|
-
setCurrentPage(1);
|
|
142
|
-
}
|
|
143
|
-
else if (navigationDirection === 'previous' && tokenHistory.length > 0) {
|
|
144
|
-
// Go back to previous token
|
|
145
|
-
const newHistory = [...tokenHistory];
|
|
146
|
-
requestToken = newHistory.pop();
|
|
147
|
-
setTokenHistory(newHistory);
|
|
148
|
-
setContinuationToken(requestToken);
|
|
149
|
-
}
|
|
150
|
-
const request = {
|
|
151
|
-
page: currentPage,
|
|
152
|
-
pageSize: serverPageSize,
|
|
153
|
-
search: searchTerm,
|
|
154
|
-
filters: activeFilters,
|
|
155
|
-
continuationToken: requestToken,
|
|
156
|
-
};
|
|
157
|
-
const response = await createApiRequest(endpoint, request, httpConfig);
|
|
158
|
-
// Handle response
|
|
159
|
-
setServerData(response.Items);
|
|
160
|
-
setLastServerResponse(response);
|
|
161
|
-
// Update token for next navigation
|
|
162
|
-
if (navigationDirection === 'next' && continuationToken) {
|
|
163
|
-
// Save current token to history
|
|
164
|
-
setTokenHistory((prev) => [...prev, continuationToken]);
|
|
165
|
-
}
|
|
166
|
-
if (response.ContinuationToken) {
|
|
167
|
-
setContinuationToken(response.ContinuationToken);
|
|
168
|
-
}
|
|
169
|
-
onDataLoad?.(response);
|
|
170
|
-
}
|
|
171
|
-
catch (err) {
|
|
172
|
-
handleError(err instanceof Error ? err : new Error('Failed to load data'), 'data-load');
|
|
173
|
-
}
|
|
174
|
-
finally {
|
|
175
|
-
handleLoadingChange(false, 'data-load');
|
|
176
|
-
}
|
|
177
|
-
}, [
|
|
178
|
-
endpoint,
|
|
179
|
-
staticData,
|
|
180
|
-
currentPage,
|
|
181
|
-
serverPageSize,
|
|
182
|
-
searchTerm,
|
|
183
|
-
sortConfig,
|
|
184
|
-
activeFilters,
|
|
185
|
-
continuationToken,
|
|
186
|
-
tokenHistory,
|
|
187
|
-
httpConfig,
|
|
188
|
-
onDataLoad,
|
|
189
|
-
handleLoadingChange,
|
|
190
|
-
handleError,
|
|
191
|
-
]);
|
|
192
|
-
// Load data on mount and when dependencies change (no sorting here - that's client-side)
|
|
193
|
-
useEffect(() => {
|
|
194
|
-
if (!staticData) {
|
|
195
|
-
loadServerData(true); // Reset pagination on mount
|
|
196
|
-
}
|
|
197
|
-
}, [staticData, searchTerm, activeFilters]); // Note: sortConfig removed - sorting is client-side only
|
|
198
|
-
// Actions
|
|
82
|
+
}, [processedData.length, currentPage, currentPageSize, isControlled, externalTotalRecords]);
|
|
83
|
+
// ===== Selection =====
|
|
84
|
+
const selectedData = useMemo(() => {
|
|
85
|
+
return data.filter((row) => selectedRows.has(getRowId(row)));
|
|
86
|
+
}, [data, selectedRows, getRowId]);
|
|
87
|
+
// ===== Actions =====
|
|
88
|
+
const setSearchTerm = useCallback((term) => {
|
|
89
|
+
setSearchTermState(term);
|
|
90
|
+
if (!isControlled)
|
|
91
|
+
setInternalPage(1);
|
|
92
|
+
onSearchChange?.(term);
|
|
93
|
+
}, [isControlled, onSearchChange]);
|
|
199
94
|
const setSort = useCallback((column) => {
|
|
200
|
-
const
|
|
95
|
+
const newConfig = {
|
|
201
96
|
column,
|
|
202
97
|
direction: sortConfig.column === column && sortConfig.direction === 'asc' ? 'desc' : 'asc',
|
|
203
98
|
};
|
|
204
|
-
setSortConfig(
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
else {
|
|
221
|
-
// Server-side with continuation tokens doesn't support arbitrary page jumps
|
|
222
|
-
console.warn('Direct page navigation not supported with continuation tokens. Use navigateNext/navigatePrevious instead.');
|
|
223
|
-
}
|
|
224
|
-
}, [staticData, paginationInfo, onPageChange]);
|
|
99
|
+
setSortConfig(newConfig);
|
|
100
|
+
if (!isControlled)
|
|
101
|
+
setInternalPage(1);
|
|
102
|
+
onSortChange?.(newConfig);
|
|
103
|
+
}, [sortConfig, isControlled, onSortChange]);
|
|
104
|
+
const setCurrentPage = useCallback((page) => {
|
|
105
|
+
if (!isControlled)
|
|
106
|
+
setInternalPage(page);
|
|
107
|
+
onPageChange?.(page, { ...paginationInfo, currentPage: page });
|
|
108
|
+
}, [isControlled, paginationInfo, onPageChange]);
|
|
109
|
+
const setCurrentPageSize = useCallback((size) => {
|
|
110
|
+
setCurrentPageSizeState(size);
|
|
111
|
+
if (!isControlled)
|
|
112
|
+
setInternalPage(1);
|
|
113
|
+
onPageSizeChange?.(size);
|
|
114
|
+
}, [isControlled, onPageSizeChange]);
|
|
225
115
|
const navigateNext = useCallback(() => {
|
|
226
|
-
if (
|
|
227
|
-
|
|
228
|
-
if (!staticData) {
|
|
229
|
-
// Server-side navigation
|
|
230
|
-
loadServerData(false, 'next');
|
|
231
|
-
}
|
|
232
|
-
else {
|
|
233
|
-
// Client-side navigation
|
|
234
|
-
setPage(currentPage + 1);
|
|
116
|
+
if (paginationInfo.hasNext) {
|
|
117
|
+
setCurrentPage(currentPage + 1);
|
|
235
118
|
}
|
|
236
|
-
}, [paginationInfo.hasNext,
|
|
119
|
+
}, [paginationInfo.hasNext, currentPage, setCurrentPage]);
|
|
237
120
|
const navigatePrevious = useCallback(() => {
|
|
238
|
-
if (
|
|
239
|
-
|
|
240
|
-
if (!staticData) {
|
|
241
|
-
// Server-side navigation
|
|
242
|
-
loadServerData(false, 'previous');
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
// Client-side navigation
|
|
246
|
-
setPage(currentPage - 1);
|
|
247
|
-
}
|
|
248
|
-
}, [paginationInfo.hasPrevious, staticData, loadServerData, setPage, currentPage]);
|
|
249
|
-
const setPageSize = useCallback((newPageSize) => {
|
|
250
|
-
setCurrentPageSize(newPageSize);
|
|
251
|
-
setCurrentPage(1);
|
|
252
|
-
const newPaginationInfo = {
|
|
253
|
-
...paginationInfo,
|
|
254
|
-
pageSize: newPageSize,
|
|
255
|
-
currentPage: 1,
|
|
256
|
-
totalPages: staticData ? Math.ceil(processedData.length / newPageSize) : 1,
|
|
257
|
-
};
|
|
258
|
-
onPageSizeChange?.(newPageSize, newPaginationInfo);
|
|
259
|
-
// Reset pagination for server-side
|
|
260
|
-
if (!staticData) {
|
|
261
|
-
setContinuationToken(undefined);
|
|
262
|
-
setTokenHistory([]);
|
|
263
|
-
loadServerData(true);
|
|
264
|
-
}
|
|
265
|
-
}, [paginationInfo, staticData, processedData.length, onPageSizeChange, loadServerData]);
|
|
266
|
-
const updateSearchTerm = useCallback((term) => {
|
|
267
|
-
setSearchTerm(term);
|
|
268
|
-
onSearchChange?.(term);
|
|
269
|
-
// Reset pagination when search changes
|
|
270
|
-
setCurrentPage(1);
|
|
271
|
-
if (!staticData) {
|
|
272
|
-
setContinuationToken(undefined);
|
|
273
|
-
setTokenHistory([]);
|
|
121
|
+
if (paginationInfo.hasPrevious) {
|
|
122
|
+
setCurrentPage(currentPage - 1);
|
|
274
123
|
}
|
|
275
|
-
}, [
|
|
124
|
+
}, [paginationInfo.hasPrevious, currentPage, setCurrentPage]);
|
|
125
|
+
// ===== Filter Actions (Enhanced) =====
|
|
276
126
|
const addFilter = useCallback((filter) => {
|
|
277
127
|
const label = `${filter.column} ${filter.operator} "${filter.value}"`;
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
];
|
|
128
|
+
const fullFilter = { ...filter, label };
|
|
129
|
+
// Replace existing filter on same column or add new
|
|
130
|
+
const newFilters = [...activeFilters.filter((f) => f.column !== filter.column), fullFilter];
|
|
282
131
|
setActiveFilters(newFilters);
|
|
132
|
+
if (!isControlled)
|
|
133
|
+
setInternalPage(1);
|
|
134
|
+
// Fire callbacks
|
|
135
|
+
onApplyFilter?.(fullFilter, newFilters);
|
|
283
136
|
onFilterChange?.(newFilters);
|
|
284
|
-
|
|
285
|
-
setCurrentPage(1);
|
|
286
|
-
if (!staticData) {
|
|
287
|
-
setContinuationToken(undefined);
|
|
288
|
-
setTokenHistory([]);
|
|
289
|
-
}
|
|
290
|
-
}, [activeFilters, onFilterChange, staticData]);
|
|
137
|
+
}, [activeFilters, isControlled, onApplyFilter, onFilterChange]);
|
|
291
138
|
const removeFilter = useCallback((index) => {
|
|
139
|
+
const removed = activeFilters[index];
|
|
292
140
|
const newFilters = activeFilters.filter((_, i) => i !== index);
|
|
293
141
|
setActiveFilters(newFilters);
|
|
142
|
+
if (!isControlled)
|
|
143
|
+
setInternalPage(1);
|
|
144
|
+
// Fire callbacks
|
|
145
|
+
if (removed)
|
|
146
|
+
onRemoveFilter?.(removed, newFilters);
|
|
294
147
|
onFilterChange?.(newFilters);
|
|
295
|
-
|
|
296
|
-
setCurrentPage(1);
|
|
297
|
-
if (!staticData) {
|
|
298
|
-
setContinuationToken(undefined);
|
|
299
|
-
setTokenHistory([]);
|
|
300
|
-
}
|
|
301
|
-
}, [activeFilters, onFilterChange, staticData]);
|
|
148
|
+
}, [activeFilters, isControlled, onRemoveFilter, onFilterChange]);
|
|
302
149
|
const clearFilters = useCallback(() => {
|
|
303
150
|
setActiveFilters([]);
|
|
151
|
+
if (!isControlled)
|
|
152
|
+
setInternalPage(1);
|
|
153
|
+
// Fire callbacks
|
|
154
|
+
onClearFilters?.();
|
|
304
155
|
onFilterChange?.([]);
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (!staticData) {
|
|
308
|
-
setContinuationToken(undefined);
|
|
309
|
-
setTokenHistory([]);
|
|
310
|
-
}
|
|
311
|
-
}, [onFilterChange, staticData]);
|
|
156
|
+
}, [isControlled, onClearFilters, onFilterChange]);
|
|
157
|
+
// ===== Selection Actions =====
|
|
312
158
|
const selectRow = useCallback((rowId, selected) => {
|
|
313
159
|
setSelectedRows((prev) => {
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
else {
|
|
319
|
-
newSet.delete(rowId);
|
|
320
|
-
}
|
|
321
|
-
return newSet;
|
|
160
|
+
const next = new Set(prev);
|
|
161
|
+
selected ? next.add(rowId) : next.delete(rowId);
|
|
162
|
+
return next;
|
|
322
163
|
});
|
|
323
164
|
}, []);
|
|
324
165
|
const selectAll = useCallback((selected) => {
|
|
325
166
|
if (selected) {
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
setSelectedRows(new Set(allIds));
|
|
167
|
+
const ids = paginatedData.map(getRowId);
|
|
168
|
+
setSelectedRows(new Set(ids));
|
|
329
169
|
}
|
|
330
170
|
else {
|
|
331
171
|
setSelectedRows(new Set());
|
|
332
172
|
}
|
|
333
|
-
}, [
|
|
173
|
+
}, [paginatedData, getRowId]);
|
|
174
|
+
const clearSelection = useCallback(() => {
|
|
175
|
+
setSelectedRows(new Set());
|
|
176
|
+
}, []);
|
|
177
|
+
// ===== Refresh (just resets internal state) =====
|
|
334
178
|
const refresh = useCallback(() => {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
loadServerData(true);
|
|
343
|
-
}
|
|
344
|
-
}, [staticData, loadServerData]);
|
|
179
|
+
setSearchTermState('');
|
|
180
|
+
setActiveFilters([]);
|
|
181
|
+
setSortConfig({ column: '', direction: 'asc' });
|
|
182
|
+
setInternalPage(1);
|
|
183
|
+
setSelectedRows(new Set());
|
|
184
|
+
}, []);
|
|
185
|
+
// ===== Return Value =====
|
|
345
186
|
return {
|
|
346
187
|
// Data
|
|
347
|
-
data
|
|
188
|
+
data,
|
|
348
189
|
processedData,
|
|
349
|
-
paginatedData
|
|
350
|
-
loading,
|
|
351
|
-
error,
|
|
190
|
+
paginatedData,
|
|
191
|
+
loading: externalLoading,
|
|
352
192
|
// State
|
|
353
193
|
searchTerm,
|
|
354
194
|
activeFilters,
|
|
@@ -356,14 +196,11 @@ export const useDataGrid = ({ data: staticData, endpoint, httpConfig, pageSize =
|
|
|
356
196
|
selectedRows,
|
|
357
197
|
currentPage,
|
|
358
198
|
currentPageSize,
|
|
359
|
-
totalRecords: paginationInfo.totalRecords,
|
|
360
|
-
hasMore: paginationInfo.hasNext,
|
|
361
|
-
continuationToken: paginationInfo.continuationToken,
|
|
362
199
|
// Actions
|
|
363
|
-
setSearchTerm
|
|
200
|
+
setSearchTerm,
|
|
364
201
|
setSort,
|
|
365
|
-
setCurrentPage
|
|
366
|
-
setCurrentPageSize
|
|
202
|
+
setCurrentPage,
|
|
203
|
+
setCurrentPageSize,
|
|
367
204
|
navigateNext,
|
|
368
205
|
navigatePrevious,
|
|
369
206
|
addFilter,
|
|
@@ -371,11 +208,14 @@ export const useDataGrid = ({ data: staticData, endpoint, httpConfig, pageSize =
|
|
|
371
208
|
clearFilters,
|
|
372
209
|
selectRow,
|
|
373
210
|
selectAll,
|
|
211
|
+
clearSelection,
|
|
374
212
|
refresh,
|
|
375
213
|
// Computed
|
|
376
214
|
paginationInfo,
|
|
377
215
|
selectedData,
|
|
378
216
|
hasSelection: selectedRows.size > 0,
|
|
379
|
-
getRowId,
|
|
217
|
+
getRowId,
|
|
218
|
+
// Mode
|
|
219
|
+
isControlled,
|
|
380
220
|
};
|
|
381
221
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { DataGrid } from './components/DataGrid';
|
|
2
2
|
export { useDataGrid } from './hooks';
|
|
3
|
-
export type { BaseRowData, Column, DataGridProps, ActiveFilter, SortConfig, PaginationInfo,
|
|
3
|
+
export type { BaseRowData, Column, DataGridProps, ActiveFilter, SortConfig, PaginationInfo, LoadingState, DataGridRequest, DataGridResponse, OnPageChangeCallback, OnPageSizeChangeCallback, OnSortChangeCallback, OnFilterChangeCallback, OnSearchChangeCallback, OnTableRowClickCallback, OnTableRowDoubleClickCallback, OnRowSelectCallback, OnSelectionChangeCallback, OnTableRowHoverCallback, OnCellClickCallback, OnTableRefreshCallback, OnBulkDeleteCallback, OnApplyFilterCallback, OnRemoveFilterCallback, OnClearFiltersCallback, } from './types';
|
|
4
4
|
export { getTheme, themes } from './themes';
|
|
5
5
|
export type { Theme } from './themes';
|
|
6
|
-
export { formatters, compareValues
|
|
6
|
+
export { formatters, compareValues } from './utils';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGtC,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGtC,YAAY,EAEV,WAAW,EACX,MAAM,EACN,aAAa,EACb,YAAY,EACZ,UAAU,EACV,cAAc,EACd,YAAY,EAGZ,eAAe,EACf,gBAAgB,EAGhB,oBAAoB,EACpB,wBAAwB,EACxB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,6BAA6B,EAC7B,mBAAmB,EACnB,yBAAyB,EACzB,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EAGpB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAGtC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED