react-live-data-table 1.0.19 → 1.1.2
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/package.json +1 -1
- package/src/ReactDataTable.jsx +293 -66
package/package.json
CHANGED
package/src/ReactDataTable.jsx
CHANGED
@@ -21,6 +21,10 @@ function ReactDataTable({
|
|
21
21
|
rowStyle = {},
|
22
22
|
rowClassName = "",
|
23
23
|
columnReorder = false,
|
24
|
+
subTableColumns = null, // Array of column definitions for subtable
|
25
|
+
expandedRows = {},
|
26
|
+
onRowExpand = null,
|
27
|
+
subTableWidth = "100%",
|
24
28
|
}) {
|
25
29
|
const tableContainerRef = React.useRef(null);
|
26
30
|
const [data, setData] = React.useState({ pages: [], meta: { totalPages: 1 } });
|
@@ -33,17 +37,103 @@ function ReactDataTable({
|
|
33
37
|
const [startX, setStartX] = useState(null);
|
34
38
|
const [initialWidth, setInitialWidth] = useState(null);
|
35
39
|
const [tableWidth, setTableWidth] = useState(0);
|
36
|
-
|
40
|
+
|
37
41
|
// Column reordering state - only used when columnReorder is true
|
38
42
|
const [orderedColumns, setOrderedColumns] = useState(columns);
|
39
43
|
const [draggedColumn, setDraggedColumn] = useState(null);
|
40
44
|
const [dragOverColumn, setDragOverColumn] = useState(null);
|
41
|
-
|
42
|
-
// Ref to store column widths to ensure persistence during data loading
|
43
|
-
const persistedColumnWidthsRef = React.useRef([]);
|
44
45
|
|
46
|
+
const persistedColumnWidthsRef = React.useRef([]);
|
45
47
|
const flatData = data.pages.flatMap(page => page.data);
|
46
48
|
|
49
|
+
// Helper function to check if a row has subtable data
|
50
|
+
const hasSubTableData = useCallback((row) => {
|
51
|
+
if (!subTableColumns) return false;
|
52
|
+
|
53
|
+
return subTableColumns.some(col => {
|
54
|
+
const value = row[col.accessorKey || col.id];
|
55
|
+
// Check for arrays with content OR non-empty strings
|
56
|
+
return (Array.isArray(value) && value.length > 0) ||
|
57
|
+
(typeof value === 'string' && value.trim() !== '' && value !== '--');
|
58
|
+
});
|
59
|
+
}, [subTableColumns]);
|
60
|
+
|
61
|
+
// Helper function to get subtable rows from main row data
|
62
|
+
const getSubTableRows = useCallback((row) => {
|
63
|
+
if (!subTableColumns || !hasSubTableData(row)) return [];
|
64
|
+
|
65
|
+
// Find the maximum length among all array columns, default to 1 for strings
|
66
|
+
let maxLength = 1; // At least 1 row for string values
|
67
|
+
subTableColumns.forEach(col => {
|
68
|
+
const value = row[col.accessorKey || col.id];
|
69
|
+
if (Array.isArray(value)) {
|
70
|
+
maxLength = Math.max(maxLength, value.length);
|
71
|
+
}
|
72
|
+
});
|
73
|
+
|
74
|
+
// Create rows for subtable
|
75
|
+
const subRows = [];
|
76
|
+
for (let i = 0; i < maxLength; i++) {
|
77
|
+
const subRow = { id: `${row.id}-sub-${i}` };
|
78
|
+
|
79
|
+
subTableColumns.forEach(col => {
|
80
|
+
const value = row[col.accessorKey || col.id];
|
81
|
+
if (Array.isArray(value)) {
|
82
|
+
// For arrays, use the value at index i, or undefined if out of bounds
|
83
|
+
subRow[col.accessorKey || col.id] = i < value.length ? value[i] : undefined;
|
84
|
+
} else {
|
85
|
+
// For strings/non-arrays, use the value only in the first row
|
86
|
+
subRow[col.accessorKey || col.id] = i === 0 ? value : undefined;
|
87
|
+
}
|
88
|
+
});
|
89
|
+
|
90
|
+
subRows.push(subRow);
|
91
|
+
}
|
92
|
+
|
93
|
+
return subRows;
|
94
|
+
}, [subTableColumns, hasSubTableData]);
|
95
|
+
|
96
|
+
const calculateDynamicHeight = useCallback(() => {
|
97
|
+
const expandedCount = Object.values(expandedRows || {}).filter(Boolean).length;
|
98
|
+
|
99
|
+
if (expandedCount === 0) {
|
100
|
+
return height;
|
101
|
+
}
|
102
|
+
|
103
|
+
// Calculate subtable height based on actual data
|
104
|
+
let totalSubTableHeight = 0;
|
105
|
+
Object.keys(expandedRows || {}).forEach(rowId => {
|
106
|
+
if (expandedRows[rowId]) {
|
107
|
+
const row = flatData.find(r => r.id === rowId);
|
108
|
+
if (row) {
|
109
|
+
const subRows = getSubTableRows(row);
|
110
|
+
const headerHeight = 36;
|
111
|
+
const rowsHeight = subRows.length * 32; // Assuming 32px per subtable row
|
112
|
+
totalSubTableHeight += headerHeight + rowsHeight + 20; // +20 for padding
|
113
|
+
}
|
114
|
+
}
|
115
|
+
});
|
116
|
+
|
117
|
+
const baseHeight = typeof height === 'string' ? parseInt(height) : height;
|
118
|
+
return `${Math.max(baseHeight, baseHeight + totalSubTableHeight)}px`;
|
119
|
+
}, [height, expandedRows, flatData, getSubTableRows]);
|
120
|
+
|
121
|
+
const dynamicHeight = calculateDynamicHeight();
|
122
|
+
|
123
|
+
const handleRowExpand = useCallback((rowId) => {
|
124
|
+
const currentExpandedRows = expandedRows || {};
|
125
|
+
const isCurrentlyExpanded = currentExpandedRows[rowId];
|
126
|
+
|
127
|
+
if (isCurrentlyExpanded) {
|
128
|
+
const newExpandedRows = { ...currentExpandedRows };
|
129
|
+
delete newExpandedRows[rowId];
|
130
|
+
onRowExpand?.(newExpandedRows, rowId);
|
131
|
+
} else {
|
132
|
+
const newExpandedRows = { [rowId]: true };
|
133
|
+
onRowExpand?.(newExpandedRows, rowId);
|
134
|
+
}
|
135
|
+
}, [expandedRows, onRowExpand]);
|
136
|
+
|
47
137
|
const checkboxColumn = {
|
48
138
|
id: 'select',
|
49
139
|
size: 50,
|
@@ -113,9 +203,59 @@ function ReactDataTable({
|
|
113
203
|
}
|
114
204
|
};
|
115
205
|
|
116
|
-
|
206
|
+
// Expand/collapse column for sub-tables - keep it similar to checkbox column
|
207
|
+
const expandColumn = {
|
208
|
+
id: 'expand',
|
209
|
+
size: 50,
|
210
|
+
minWidth: 50,
|
211
|
+
resizable: false,
|
212
|
+
reorderable: false,
|
213
|
+
textAlign: "center",
|
214
|
+
header: () => (
|
215
|
+
<div className="flex items-center justify-center h-[40px]">
|
216
|
+
<span className="text-xs text-gray-600">Expand</span>
|
217
|
+
</div>
|
218
|
+
),
|
219
|
+
cell: ({ row }) => {
|
220
|
+
const isExpanded = (expandedRows || {})[row.id];
|
221
|
+
const hasSubData = hasSubTableData(row);
|
222
|
+
|
223
|
+
if (!hasSubData) {
|
224
|
+
return <div className="flex items-center justify-center h-[40px]"></div>;
|
225
|
+
}
|
226
|
+
|
227
|
+
return (
|
228
|
+
<div className="flex items-center justify-center h-[40px]" onClick={(e) => e.stopPropagation()}>
|
229
|
+
<button
|
230
|
+
onClick={(e) => {
|
231
|
+
e.stopPropagation();
|
232
|
+
handleRowExpand(row.id);
|
233
|
+
}}
|
234
|
+
className="w-6 h-6 flex items-center justify-center rounded hover:bg-gray-200 transition-colors"
|
235
|
+
>
|
236
|
+
<svg
|
237
|
+
className={`w-4 h-4 transition-transform ${isExpanded ? 'rotate-90' : ''}`}
|
238
|
+
fill="none"
|
239
|
+
stroke="currentColor"
|
240
|
+
viewBox="0 0 24 24"
|
241
|
+
>
|
242
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
243
|
+
</svg>
|
244
|
+
</button>
|
245
|
+
</div>
|
246
|
+
);
|
247
|
+
}
|
248
|
+
};
|
249
|
+
|
250
|
+
const hasAnySubTableData = subTableColumns && flatData.some(row => hasSubTableData(row));
|
251
|
+
|
252
|
+
const enhancedColumns = (() => {
|
253
|
+
let cols = [];
|
254
|
+
if (showCheckbox) cols.push(checkboxColumn);
|
255
|
+
if (hasAnySubTableData) cols.push(expandColumn);
|
256
|
+
return [...cols, ...orderedColumns];
|
257
|
+
})();
|
117
258
|
|
118
|
-
// Update ordered columns when columns prop changes
|
119
259
|
useEffect(() => {
|
120
260
|
setOrderedColumns(columns);
|
121
261
|
}, [columns]);
|
@@ -127,10 +267,9 @@ function ReactDataTable({
|
|
127
267
|
}
|
128
268
|
}, [selected]);
|
129
269
|
|
130
|
-
// Initialize column widths array only once when component mounts or columns change
|
131
270
|
useEffect(() => {
|
132
|
-
const allColumns =
|
133
|
-
|
271
|
+
const allColumns = enhancedColumns;
|
272
|
+
|
134
273
|
// If we have persisted widths and the number of columns matches, use those
|
135
274
|
if (persistedColumnWidthsRef.current.length === allColumns.length) {
|
136
275
|
setColumnWidths([...persistedColumnWidthsRef.current]);
|
@@ -143,7 +282,7 @@ function ReactDataTable({
|
|
143
282
|
// Store in our ref for persistence
|
144
283
|
persistedColumnWidthsRef.current = [...initialWidths];
|
145
284
|
}
|
146
|
-
}, [
|
285
|
+
}, [showCheckbox, hasAnySubTableData]);
|
147
286
|
|
148
287
|
useEffect(() => {
|
149
288
|
setData({ pages: [], meta: { totalPages: 1 } });
|
@@ -186,7 +325,7 @@ function ReactDataTable({
|
|
186
325
|
|
187
326
|
const handleDrop = (e, dropIndex) => {
|
188
327
|
e.preventDefault();
|
189
|
-
|
328
|
+
|
190
329
|
if (!columnReorder || draggedColumn === null || draggedColumn === dropIndex) {
|
191
330
|
setDraggedColumn(null);
|
192
331
|
setDragOverColumn(null);
|
@@ -201,12 +340,20 @@ function ReactDataTable({
|
|
201
340
|
|
202
341
|
const newColumns = [...enhancedColumns];
|
203
342
|
const draggedColumnData = newColumns[draggedColumn];
|
204
|
-
|
343
|
+
|
205
344
|
newColumns.splice(draggedColumn, 1);
|
206
345
|
const adjustedDropIndex = draggedColumn < dropIndex ? dropIndex - 1 : dropIndex;
|
207
346
|
newColumns.splice(adjustedDropIndex, 0, draggedColumnData);
|
208
347
|
|
209
|
-
|
348
|
+
// FIXED: Updated logic to handle different column types
|
349
|
+
let updatedOrderedColumns;
|
350
|
+
if (showCheckbox && hasAnySubTableData) {
|
351
|
+
updatedOrderedColumns = newColumns.slice(2); // Remove both checkbox and expand columns
|
352
|
+
} else if (showCheckbox || hasAnySubTableData) {
|
353
|
+
updatedOrderedColumns = newColumns.slice(1); // Remove one column (checkbox or expand)
|
354
|
+
} else {
|
355
|
+
updatedOrderedColumns = newColumns;
|
356
|
+
}
|
210
357
|
setOrderedColumns(updatedOrderedColumns);
|
211
358
|
|
212
359
|
// Reorder column widths
|
@@ -217,8 +364,6 @@ function ReactDataTable({
|
|
217
364
|
setColumnWidths(newColumnWidths);
|
218
365
|
persistedColumnWidthsRef.current = newColumnWidths;
|
219
366
|
|
220
|
-
// onColumnReorder?.(updatedOrderedColumns);
|
221
|
-
|
222
367
|
setDraggedColumn(null);
|
223
368
|
setDragOverColumn(null);
|
224
369
|
};
|
@@ -229,17 +374,12 @@ function ReactDataTable({
|
|
229
374
|
const delta = e.clientX - startX;
|
230
375
|
const newWidth = Math.max(enhancedColumns[resizingIndex]?.minWidth || 80, initialWidth + delta);
|
231
376
|
|
232
|
-
// Create a new array of column widths with the updated width
|
233
377
|
const newColumnWidths = [...columnWidths];
|
234
378
|
newColumnWidths[resizingIndex] = newWidth;
|
235
379
|
|
236
|
-
// Update the column widths state
|
237
380
|
setColumnWidths(newColumnWidths);
|
238
|
-
|
239
|
-
// Update our persisted ref to maintain widths during pagination
|
240
381
|
persistedColumnWidthsRef.current = newColumnWidths;
|
241
382
|
|
242
|
-
// Recalculate table width based on the new column widths
|
243
383
|
const newTableWidth = newColumnWidths.reduce((sum, width) => sum + width, 0);
|
244
384
|
setTableWidth(newTableWidth);
|
245
385
|
}, [resizingIndex, startX, initialWidth, enhancedColumns, columnWidths]);
|
@@ -250,7 +390,6 @@ function ReactDataTable({
|
|
250
390
|
setInitialWidth(null);
|
251
391
|
}, []);
|
252
392
|
|
253
|
-
// Add resize event listeners
|
254
393
|
useEffect(() => {
|
255
394
|
if (resizingIndex !== null) {
|
256
395
|
document.addEventListener('mousemove', handleMouseMove);
|
@@ -299,7 +438,6 @@ function ReactDataTable({
|
|
299
438
|
limit: defaultLimit
|
300
439
|
});
|
301
440
|
|
302
|
-
// Update the data but maintain our column widths
|
303
441
|
setData(prev => ({
|
304
442
|
pages: [...prev.pages, nextData],
|
305
443
|
meta: nextData.meta
|
@@ -423,7 +561,7 @@ function ReactDataTable({
|
|
423
561
|
|
424
562
|
{
|
425
563
|
flatData.length === 0 && !loading ? (
|
426
|
-
<div className="flex items-center justify-center" style={{ height }}>
|
564
|
+
<div className="flex items-center justify-center" style={{ height: dynamicHeight }}>
|
427
565
|
<div className="text-gray-500">
|
428
566
|
{emptyText || 'No data available'}
|
429
567
|
</div>
|
@@ -433,13 +571,18 @@ function ReactDataTable({
|
|
433
571
|
<div
|
434
572
|
ref={tableContainerRef}
|
435
573
|
className="overflow-auto w-full"
|
436
|
-
style={{
|
574
|
+
style={{
|
575
|
+
maxHeight: dynamicHeight,
|
576
|
+
height: dynamicHeight
|
577
|
+
}}
|
437
578
|
onScroll={(e) => handleScroll(e.currentTarget)}
|
438
579
|
>
|
439
580
|
<table
|
440
581
|
className="w-full border-collapse"
|
441
582
|
style={{
|
442
583
|
tableLayout: 'fixed',
|
584
|
+
width: `${tableWidth}px`, // FIXED: Use calculated table width for scrolling
|
585
|
+
minWidth: '100%'
|
443
586
|
}}
|
444
587
|
>
|
445
588
|
<thead
|
@@ -455,16 +598,14 @@ function ReactDataTable({
|
|
455
598
|
return (
|
456
599
|
<th
|
457
600
|
key={column.accessorKey || column.id}
|
458
|
-
className={`text-left font-normal h-[40px] border-b border-t border-solid border-[#e4e3e2] relative select-none ${
|
459
|
-
|
460
|
-
|
461
|
-
isDropTarget ? 'bg-blue-400' : ''
|
462
|
-
}`}
|
601
|
+
className={`text-left font-normal h-[40px] border-b border-t border-solid border-[#e4e3e2] relative select-none ${columnIndex < enhancedColumns.length - 1 ? 'border-r' : ''
|
602
|
+
} ${isReorderable ? 'cursor-move' : ''} ${isDropTarget ? 'bg-blue-400' : ''
|
603
|
+
}`}
|
463
604
|
style={{
|
464
605
|
width: `${width}px`,
|
465
606
|
minWidth: `${width}px`,
|
466
607
|
maxWidth: `${width}px`,
|
467
|
-
textAlign: column.textAlign,
|
608
|
+
textAlign: column.textAlign || "left",
|
468
609
|
}}
|
469
610
|
draggable={isReorderable}
|
470
611
|
onDragStart={(e) => handleDragStart(e, columnIndex)}
|
@@ -480,9 +621,8 @@ function ReactDataTable({
|
|
480
621
|
{/* Resize handle - Only show if column is resizable */}
|
481
622
|
{column.resizable !== false && (
|
482
623
|
<div
|
483
|
-
className={`absolute top-0 right-0 h-full w-4 flex items-center justify-center group ${
|
484
|
-
|
485
|
-
} transition-colors duration-200`}
|
624
|
+
className={`absolute top-0 right-0 h-full w-4 flex items-center justify-center group ${resizingIndex === columnIndex ? 'bg-blue-100' : 'hover:bg-blue-100'
|
625
|
+
} transition-colors duration-200`}
|
486
626
|
onMouseDown={(e) => handleResizeStart(e, columnIndex)}
|
487
627
|
style={{
|
488
628
|
touchAction: 'none',
|
@@ -501,41 +641,128 @@ function ReactDataTable({
|
|
501
641
|
{flatData.length > 0 ? (
|
502
642
|
flatData.map((row, rowIndex) => {
|
503
643
|
const isLastRow = rowIndex === flatData.length - 1;
|
644
|
+
const isExpanded = (expandedRows || {})[row.id];
|
645
|
+
const subRows = getSubTableRows(row);
|
646
|
+
|
504
647
|
return (
|
505
|
-
<
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
648
|
+
<React.Fragment key={row.id}>
|
649
|
+
<tr
|
650
|
+
className={`react-live-data-table-row-${rowIndex} border-t ${isLastRow ? 'border-b' : ''} border-gray-200 hover:bg-[#dee1f2] ${selectedRows[row.id] ? 'bg-[#dee1f2]' : ''} ${rowClassName} cursor-pointer`}
|
651
|
+
style={{
|
652
|
+
height: `${rowHeights}px`,
|
653
|
+
...rowStyle,
|
654
|
+
...(typeof rowStyle === 'function' ? rowStyle(row, rowIndex) : {})
|
655
|
+
}}
|
656
|
+
onClick={() => handleRowClick(row, rowIndex, flatData)}
|
657
|
+
>
|
658
|
+
{enhancedColumns.map((column, columnIndex) => {
|
659
|
+
const width = columnWidths[columnIndex] || column.size || column.minWidth || 150;
|
660
|
+
|
661
|
+
return (
|
662
|
+
<td
|
663
|
+
key={column.accessorKey || column.id}
|
664
|
+
className={`text-left font-normal ${columnIndex < enhancedColumns.length - 1 ? 'border-r' : ''
|
665
|
+
} ${column?.cellProps?.className || ''}`}
|
666
|
+
style={{
|
667
|
+
width: `${width}px`,
|
668
|
+
minWidth: `${width}px`,
|
669
|
+
maxWidth: `${width}px`,
|
670
|
+
textAlign: column.textAlign || "left",
|
671
|
+
...column?.cellProps?.style,
|
672
|
+
overflow: 'hidden',
|
673
|
+
textOverflow: 'ellipsis',
|
674
|
+
whiteSpace: 'nowrap'
|
675
|
+
}}
|
676
|
+
>
|
677
|
+
{typeof column.cell === 'function' ? column.cell({ row }) : null}
|
678
|
+
</td>
|
679
|
+
);
|
680
|
+
})}
|
681
|
+
</tr>
|
682
|
+
{/* Subtable row */}
|
683
|
+
{isExpanded && subRows.length > 0 && (
|
684
|
+
<tr className="bg-gray-50 border-b border-gray-200">
|
685
|
+
<td colSpan={enhancedColumns.length} className="p-0">
|
686
|
+
<div className="bg-white border border-gray-200" style={{ width: subTableWidth, maxWidth: '100%' }}>
|
687
|
+
<div
|
688
|
+
className="sub-table-container"
|
689
|
+
style={{
|
690
|
+
maxHeight: "300px",
|
691
|
+
width: '100%',
|
692
|
+
overflow: 'auto',
|
693
|
+
scrollbarWidth: 'thin',
|
694
|
+
scrollbarColor: '#cbd5e0 #f7fafc',
|
695
|
+
}}
|
696
|
+
>
|
697
|
+
<style>
|
698
|
+
{`
|
699
|
+
.sub-table-container::-webkit-scrollbar {
|
700
|
+
width: 6px;
|
701
|
+
height: 6px;
|
702
|
+
}
|
703
|
+
.sub-table-container::-webkit-scrollbar-track {
|
704
|
+
background: #f7fafc;
|
705
|
+
border-radius: 3px;
|
706
|
+
}
|
707
|
+
.sub-table-container::-webkit-scrollbar-thumb {
|
708
|
+
background: #cbd5e0;
|
709
|
+
border-radius: 3px;
|
710
|
+
}
|
711
|
+
.sub-table-container::-webkit-scrollbar-thumb:hover {
|
712
|
+
background: #a0aec0;
|
713
|
+
}
|
714
|
+
`}
|
715
|
+
</style>
|
716
|
+
<table className="w-full" style={{ tableLayout: 'fixed' }}>
|
717
|
+
<thead className="bg-gray-100 sticky top-0 z-10">
|
718
|
+
<tr>
|
719
|
+
{subTableColumns.map((col, colIndex) => {
|
720
|
+
return (
|
721
|
+
<th
|
722
|
+
key={col.id || col.accessorKey || colIndex}
|
723
|
+
className={`px-4 py-2 text-left text-sm font-medium text-black border-b border-gray-200 ${colIndex < subTableColumns.length - 1 ? 'border-r border-gray-200' : ''
|
724
|
+
}`}
|
725
|
+
style={{
|
726
|
+
width: col.size ? `${col.size}px` : "auto",
|
727
|
+
minWidth: col.minWidth ? `${col.minWidth}px` : "80px",
|
728
|
+
}}
|
729
|
+
>
|
730
|
+
{typeof col.header === 'function' ? col.header() : (col.header || col.name)}
|
731
|
+
</th>
|
732
|
+
|
733
|
+
);
|
734
|
+
})}
|
735
|
+
</tr>
|
736
|
+
</thead>
|
737
|
+
<tbody>
|
738
|
+
{subRows.map((subRow, subRowIndex) => (
|
739
|
+
<tr key={subRow.id} className="border-b border-gray-100 hover:bg-gray-50">
|
740
|
+
{subTableColumns.map((col, colIndex) => {
|
741
|
+
return (
|
742
|
+
<td
|
743
|
+
key={col.id || col.accessorKey || colIndex}
|
744
|
+
className={`px-4 py-2 text-sm text-gray-900 ${colIndex < subTableColumns.length - 1 ? 'border-r border-gray-200' : ''
|
745
|
+
}`}
|
746
|
+
style={{
|
747
|
+
width: col.size ? `${col.size}px` : "auto",
|
748
|
+
minWidth: col.minWidth ? `${col.minWidth}px` : "80px",
|
749
|
+
}}
|
750
|
+
>
|
751
|
+
{col.cell ? col.cell({ row: subRow }) : subRow[col.accessorKey || col.id]}
|
752
|
+
</td>
|
753
|
+
|
754
|
+
);
|
755
|
+
})}
|
756
|
+
</tr>
|
757
|
+
))}
|
758
|
+
</tbody>
|
759
|
+
</table>
|
760
|
+
</div>
|
761
|
+
</div>
|
535
762
|
</td>
|
536
|
-
|
537
|
-
|
538
|
-
</
|
763
|
+
</tr>
|
764
|
+
)}
|
765
|
+
</React.Fragment>
|
539
766
|
);
|
540
767
|
})
|
541
768
|
) : (
|