react-glide-table 1.0.1 → 1.1.0
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 +62 -497
- package/dist/index.cjs +736 -1229
- package/dist/index.d.cts +337 -68
- package/dist/index.d.ts +337 -68
- package/dist/index.js +699 -1211
- package/package.json +14 -8
- package/dist/style.css +0 -404
package/dist/index.js
CHANGED
|
@@ -1,45 +1,46 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/core/labels.ts
|
|
2
|
+
var DEFAULT_DATA_TABLE_LABELS = {
|
|
3
|
+
empty: "No data",
|
|
4
|
+
loading: "Loading...",
|
|
5
|
+
selection: (selectedCount) => selectedCount > 0 ? `\u2713 ${selectedCount} selected` : null,
|
|
6
|
+
expandRow: "Expand row",
|
|
7
|
+
collapseRow: "Collapse row"
|
|
8
|
+
};
|
|
9
|
+
function resolveDataTableLabels(partial) {
|
|
10
|
+
return {
|
|
11
|
+
...DEFAULT_DATA_TABLE_LABELS,
|
|
12
|
+
...partial
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/core/treeDefaults.ts
|
|
17
|
+
var DEFAULT_TREE_ID_FIELD = "id";
|
|
18
|
+
var DEFAULT_TREE_PARENT_ID_FIELD = "parentId";
|
|
19
|
+
var DEFAULT_TREE_CHILDREN_FIELD = "children";
|
|
20
|
+
var DEFAULT_TREE_QTY_FIELD = "qty";
|
|
21
|
+
|
|
22
|
+
// src/core/useGlideTable.ts
|
|
2
23
|
import {
|
|
3
|
-
flexRender as flexRender2,
|
|
4
24
|
getCoreRowModel,
|
|
5
25
|
useReactTable
|
|
6
26
|
} from "@tanstack/react-table";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
27
|
+
import {
|
|
28
|
+
useVirtualizer
|
|
29
|
+
} from "@tanstack/react-virtual";
|
|
30
|
+
import {
|
|
31
|
+
useCallback as useCallback3,
|
|
32
|
+
useEffect as useEffect4,
|
|
33
|
+
useMemo as useMemo2,
|
|
34
|
+
useRef as useRef3,
|
|
35
|
+
useState as useState3
|
|
36
|
+
} from "react";
|
|
13
37
|
|
|
14
38
|
// src/components/ui/table/constants.ts
|
|
15
|
-
var CELL_ALIGN_CLASS = {
|
|
16
|
-
left: "cell-align-left",
|
|
17
|
-
center: "cell-align-center",
|
|
18
|
-
right: "cell-align-right"
|
|
19
|
-
};
|
|
20
|
-
var ROW_HOVER_CLASS = "row-hoverable";
|
|
21
|
-
var ROW_HOVERED_BG_CLASS = "row-hovered";
|
|
22
|
-
var CELL_SELECTION_FILL_CLASS = "cell-selection-fill";
|
|
23
39
|
var DATA_TABLE_ROW_HEIGHT = 44;
|
|
24
40
|
var DATA_TABLE_VIRTUAL_OVERSCAN = 8;
|
|
25
41
|
|
|
26
|
-
// src/components/ui/table/
|
|
27
|
-
import {
|
|
28
|
-
import { jsx } from "react/jsx-runtime";
|
|
29
|
-
var DataTableContext = createContext(null);
|
|
30
|
-
function useDataTableRowContext() {
|
|
31
|
-
const context = use(DataTableContext);
|
|
32
|
-
if (!context) {
|
|
33
|
-
throw new Error("useDataTableRowContext must be used within a DataTableContextProvider");
|
|
34
|
-
}
|
|
35
|
-
return context;
|
|
36
|
-
}
|
|
37
|
-
function DataTableContextProvider({
|
|
38
|
-
value,
|
|
39
|
-
children
|
|
40
|
-
}) {
|
|
41
|
-
return /* @__PURE__ */ jsx(DataTableContext, { value, children });
|
|
42
|
-
}
|
|
42
|
+
// src/components/ui/table/features/cell-edit/useCellEdit.ts
|
|
43
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
43
44
|
|
|
44
45
|
// src/components/ui/table/features/cell-edit/cellEdit.ts
|
|
45
46
|
function getColumnAccessorKey(columnDef) {
|
|
@@ -87,6 +88,87 @@ function applyCellEdit(data, rows, rowIndex, colIndex, raw) {
|
|
|
87
88
|
return newData;
|
|
88
89
|
}
|
|
89
90
|
|
|
91
|
+
// src/components/ui/table/features/cell-edit/useCellEdit.ts
|
|
92
|
+
function useCellEdit({
|
|
93
|
+
data,
|
|
94
|
+
rows,
|
|
95
|
+
onDataChange,
|
|
96
|
+
onCellChange
|
|
97
|
+
}) {
|
|
98
|
+
const [editingCell, setEditingCell] = useState(null);
|
|
99
|
+
const [draftValue, setDraftValue] = useState("");
|
|
100
|
+
const draftValueRef = useRef(draftValue);
|
|
101
|
+
const editingCellRef = useRef(editingCell);
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
draftValueRef.current = draftValue;
|
|
104
|
+
}, [draftValue]);
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
editingCellRef.current = editingCell;
|
|
107
|
+
}, [editingCell]);
|
|
108
|
+
const cancelEdit = useCallback(() => {
|
|
109
|
+
setEditingCell(null);
|
|
110
|
+
setDraftValue("");
|
|
111
|
+
}, []);
|
|
112
|
+
const commitEdit = useCallback(
|
|
113
|
+
(raw) => {
|
|
114
|
+
const current = editingCellRef.current;
|
|
115
|
+
if (!current) return true;
|
|
116
|
+
if (!onCellChange && !onDataChange) {
|
|
117
|
+
cancelEdit();
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
const row = rows[current.rowIndex];
|
|
121
|
+
const cell = row?.getVisibleCells()[current.colIndex];
|
|
122
|
+
if (!row || !cell) {
|
|
123
|
+
cancelEdit();
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
const value = raw ?? draftValueRef.current;
|
|
127
|
+
if (!isColumnEditable(cell.column.columnDef)) {
|
|
128
|
+
cancelEdit();
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
const parsed = parseCellEditValue(value, getColumnEditType(cell.column.columnDef));
|
|
132
|
+
if (!parsed.ok) return false;
|
|
133
|
+
if (onCellChange) {
|
|
134
|
+
onCellChange(row.id, cell.column.id, parsed.value);
|
|
135
|
+
cancelEdit();
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
const next = applyCellEdit(data, rows, current.rowIndex, current.colIndex, value);
|
|
139
|
+
if (!next) return false;
|
|
140
|
+
onDataChange?.(next);
|
|
141
|
+
cancelEdit();
|
|
142
|
+
return true;
|
|
143
|
+
},
|
|
144
|
+
[cancelEdit, data, onCellChange, onDataChange, rows]
|
|
145
|
+
);
|
|
146
|
+
const startEdit = useCallback(
|
|
147
|
+
(rowIndex, colIndex) => {
|
|
148
|
+
const cell = rows[rowIndex]?.getVisibleCells()[colIndex];
|
|
149
|
+
if (!cell || !isColumnEditable(cell.column.columnDef)) return;
|
|
150
|
+
const current = editingCellRef.current;
|
|
151
|
+
if (current && (current.rowIndex !== rowIndex || current.colIndex !== colIndex) && !commitEdit()) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
setEditingCell({ rowIndex, colIndex });
|
|
155
|
+
setDraftValue(getCellEditDraftValue(cell.getValue()));
|
|
156
|
+
},
|
|
157
|
+
[commitEdit, rows]
|
|
158
|
+
);
|
|
159
|
+
return {
|
|
160
|
+
editingCell,
|
|
161
|
+
draftValue,
|
|
162
|
+
setDraftValue,
|
|
163
|
+
startEdit,
|
|
164
|
+
commitEdit,
|
|
165
|
+
cancelEdit
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// src/components/ui/table/features/cell-selection/useCellSelection.ts
|
|
170
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useState as useState2 } from "react";
|
|
171
|
+
|
|
90
172
|
// src/components/ui/table/features/cell-selection/cellSelection.ts
|
|
91
173
|
var INITIAL_DRAG_STATE = {
|
|
92
174
|
isSelecting: false,
|
|
@@ -110,7 +192,10 @@ function getRowIndexInMergedCell(clientY, cellElement, rowIndex, rowSpan) {
|
|
|
110
192
|
const rect = cellElement.getBoundingClientRect();
|
|
111
193
|
const relativeY = clientY - rect.top;
|
|
112
194
|
const rowHeight = rect.height / rowSpan;
|
|
113
|
-
const offset = Math.min(
|
|
195
|
+
const offset = Math.min(
|
|
196
|
+
Math.max(Math.floor(relativeY / rowHeight), 0),
|
|
197
|
+
rowSpan - 1
|
|
198
|
+
);
|
|
114
199
|
return rowIndex + offset;
|
|
115
200
|
}
|
|
116
201
|
function isCellInSelection(rowIndex, colIndex, bounds, rowSpan = 1) {
|
|
@@ -126,31 +211,348 @@ function getActiveSelectionBounds(dragState, selectionBounds) {
|
|
|
126
211
|
}
|
|
127
212
|
var SELECTION_EDGE_WIDTH_PX = 2;
|
|
128
213
|
var SELECTION_EDGE_COLOR = "var(--color-brand-primary)";
|
|
129
|
-
|
|
130
|
-
|
|
214
|
+
var CELL_SELECTION_EDGES_CLASS = "cell-selection-edges";
|
|
215
|
+
function getMergedCellStepEdges(rowIndex, colIndex, bounds, rowSpan, isVisuallySelectedAt) {
|
|
216
|
+
const cellEndRow = rowIndex + rowSpan - 1;
|
|
217
|
+
const span = cellEndRow - rowIndex + 1;
|
|
218
|
+
if (span <= 1) return [];
|
|
219
|
+
const edges = [];
|
|
220
|
+
const isNeighborSelected = (row, neighborCol) => {
|
|
221
|
+
if (isVisuallySelectedAt) {
|
|
222
|
+
return isVisuallySelectedAt(row, neighborCol);
|
|
223
|
+
}
|
|
224
|
+
return row >= bounds.startRow && row <= bounds.endRow && neighborCol >= bounds.startCol && neighborCol <= bounds.endCol;
|
|
225
|
+
};
|
|
226
|
+
const pushUnselectedRuns = (side, neighborCol, fromRow, toRowExclusive) => {
|
|
227
|
+
let runStart = null;
|
|
228
|
+
for (let row = fromRow; row < toRowExclusive; row++) {
|
|
229
|
+
if (!isNeighborSelected(row, neighborCol)) {
|
|
230
|
+
if (runStart === null) runStart = row;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (runStart !== null) {
|
|
234
|
+
edges.push({
|
|
235
|
+
side,
|
|
236
|
+
offsetRatio: (runStart - rowIndex) / span,
|
|
237
|
+
heightRatio: (row - runStart) / span
|
|
238
|
+
});
|
|
239
|
+
runStart = null;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (runStart !== null) {
|
|
243
|
+
edges.push({
|
|
244
|
+
side,
|
|
245
|
+
offsetRatio: (runStart - rowIndex) / span,
|
|
246
|
+
heightRatio: (toRowExclusive - runStart) / span
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
const collectSide = (side, neighborCol) => {
|
|
251
|
+
if (bounds.startRow > rowIndex) {
|
|
252
|
+
pushUnselectedRuns(
|
|
253
|
+
side,
|
|
254
|
+
neighborCol,
|
|
255
|
+
rowIndex,
|
|
256
|
+
Math.min(bounds.startRow, cellEndRow + 1)
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
if (bounds.endRow < cellEndRow) {
|
|
260
|
+
pushUnselectedRuns(
|
|
261
|
+
side,
|
|
262
|
+
neighborCol,
|
|
263
|
+
Math.max(bounds.endRow + 1, rowIndex),
|
|
264
|
+
cellEndRow + 1
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
if (colIndex < bounds.endCol) {
|
|
269
|
+
collectSide("right", colIndex + 1);
|
|
270
|
+
}
|
|
271
|
+
if (colIndex > bounds.startCol) {
|
|
272
|
+
collectSide("left", colIndex - 1);
|
|
273
|
+
}
|
|
274
|
+
return edges;
|
|
275
|
+
}
|
|
276
|
+
function buildPartialVerticalGradient(edge) {
|
|
277
|
+
const startPct = edge.offsetRatio * 100;
|
|
278
|
+
const endPct = (edge.offsetRatio + edge.heightRatio) * 100;
|
|
279
|
+
const overlapPx = SELECTION_EDGE_WIDTH_PX + 1;
|
|
280
|
+
const isTopProtrusion = edge.offsetRatio === 0 && edge.heightRatio < 1;
|
|
281
|
+
const isBottomProtrusion = edge.offsetRatio > 0;
|
|
282
|
+
const startStop = isBottomProtrusion ? `calc(${startPct}% - ${overlapPx}px)` : `${startPct}%`;
|
|
283
|
+
const endStop = isTopProtrusion ? `calc(${endPct}% + ${overlapPx}px)` : `${endPct}%`;
|
|
284
|
+
const xPos = edge.side === "left" ? "0" : "100%";
|
|
285
|
+
const layers = [
|
|
286
|
+
{
|
|
287
|
+
image: `linear-gradient(to bottom, transparent 0%, transparent ${startStop}, ${SELECTION_EDGE_COLOR} ${startStop}, ${SELECTION_EDGE_COLOR} ${endStop}, transparent ${endStop}, transparent 100%)`,
|
|
288
|
+
size: `${SELECTION_EDGE_WIDTH_PX}px 100%`,
|
|
289
|
+
position: `${xPos} 0`
|
|
290
|
+
}
|
|
291
|
+
];
|
|
292
|
+
if (isTopProtrusion || isBottomProtrusion) {
|
|
293
|
+
const capTop = isTopProtrusion ? `calc(${endPct}% - ${SELECTION_EDGE_WIDTH_PX}px)` : `calc(${startPct}% - ${SELECTION_EDGE_WIDTH_PX}px)`;
|
|
294
|
+
layers.push({
|
|
295
|
+
image: `linear-gradient(${SELECTION_EDGE_COLOR}, ${SELECTION_EDGE_COLOR})`,
|
|
296
|
+
size: `${SELECTION_EDGE_WIDTH_PX}px ${SELECTION_EDGE_WIDTH_PX}px`,
|
|
297
|
+
position: `${xPos} ${capTop}`
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
return layers;
|
|
301
|
+
}
|
|
302
|
+
function getCellSelectionEdgeStyle(rowIndex, colIndex, bounds, rowSpan = 1, isVisuallySelectedAt) {
|
|
303
|
+
if (!isCellInSelection(rowIndex, colIndex, bounds, rowSpan) || !bounds)
|
|
304
|
+
return void 0;
|
|
131
305
|
const cellEndRow = rowIndex + rowSpan - 1;
|
|
132
306
|
const isTopEdge = bounds.startRow >= rowIndex && bounds.startRow <= cellEndRow;
|
|
133
307
|
const isBottomEdge = bounds.endRow >= rowIndex && bounds.endRow <= cellEndRow;
|
|
134
308
|
const isLeftEdge = colIndex === bounds.startCol;
|
|
135
309
|
const isRightEdge = colIndex === bounds.endCol;
|
|
310
|
+
const selectionContinuesBelow = cellEndRow < bounds.endRow;
|
|
136
311
|
const shadows = [];
|
|
137
312
|
if (isTopEdge) {
|
|
138
|
-
shadows.push(
|
|
313
|
+
shadows.push(
|
|
314
|
+
`inset 0 ${SELECTION_EDGE_WIDTH_PX}px 0 0 ${SELECTION_EDGE_COLOR}`
|
|
315
|
+
);
|
|
139
316
|
}
|
|
140
317
|
if (isBottomEdge) {
|
|
141
|
-
shadows.push(
|
|
318
|
+
shadows.push(
|
|
319
|
+
`inset 0 -${SELECTION_EDGE_WIDTH_PX}px 0 0 ${SELECTION_EDGE_COLOR}`
|
|
320
|
+
);
|
|
142
321
|
}
|
|
143
322
|
if (isLeftEdge) {
|
|
144
|
-
shadows.push(
|
|
323
|
+
shadows.push(
|
|
324
|
+
`inset ${SELECTION_EDGE_WIDTH_PX}px 0 0 0 ${SELECTION_EDGE_COLOR}`
|
|
325
|
+
);
|
|
145
326
|
}
|
|
146
327
|
if (isRightEdge) {
|
|
147
|
-
shadows.push(
|
|
328
|
+
shadows.push(
|
|
329
|
+
`inset -${SELECTION_EDGE_WIDTH_PX}px 0 0 0 ${SELECTION_EDGE_COLOR}`
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
const stepEdges = getMergedCellStepEdges(
|
|
333
|
+
rowIndex,
|
|
334
|
+
colIndex,
|
|
335
|
+
bounds,
|
|
336
|
+
rowSpan,
|
|
337
|
+
isVisuallySelectedAt
|
|
338
|
+
);
|
|
339
|
+
const gradients = [];
|
|
340
|
+
const sizes = [];
|
|
341
|
+
const positions = [];
|
|
342
|
+
for (const edge of stepEdges) {
|
|
343
|
+
for (const partial of buildPartialVerticalGradient(edge)) {
|
|
344
|
+
gradients.push(partial.image);
|
|
345
|
+
sizes.push(partial.size);
|
|
346
|
+
positions.push(partial.position);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
if (shadows.length === 0 && gradients.length === 0 && !selectionContinuesBelow) {
|
|
350
|
+
return void 0;
|
|
351
|
+
}
|
|
352
|
+
const style = {};
|
|
353
|
+
if (shadows.length > 0) {
|
|
354
|
+
style["--selection-edge-shadows"] = shadows.join(", ");
|
|
355
|
+
}
|
|
356
|
+
if (gradients.length > 0) {
|
|
357
|
+
style["--selection-edge-gradients"] = gradients.join(", ");
|
|
358
|
+
style["--selection-edge-sizes"] = sizes.join(", ");
|
|
359
|
+
style["--selection-edge-positions"] = positions.join(", ");
|
|
360
|
+
}
|
|
361
|
+
if (selectionContinuesBelow) {
|
|
362
|
+
style.borderBottomColor = "var(--color-brand-surface)";
|
|
363
|
+
}
|
|
364
|
+
return style;
|
|
365
|
+
}
|
|
366
|
+
function hasCellSelectionEdges(style) {
|
|
367
|
+
return Boolean(
|
|
368
|
+
style?.["--selection-edge-shadows"] || style?.["--selection-edge-gradients"]
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// src/components/ui/table/features/cell-selection/fillData.ts
|
|
373
|
+
function getColumnAccessorKey2(columnDef) {
|
|
374
|
+
if ("accessorKey" in columnDef && columnDef.accessorKey) {
|
|
375
|
+
return String(columnDef.accessorKey);
|
|
376
|
+
}
|
|
377
|
+
return columnDef.id;
|
|
378
|
+
}
|
|
379
|
+
function collectFillTargets(rows, sourceBounds, fillBounds) {
|
|
380
|
+
const targets = [];
|
|
381
|
+
const sourceHeight = sourceBounds.endRow - sourceBounds.startRow + 1;
|
|
382
|
+
const sourceWidth = sourceBounds.endCol - sourceBounds.startCol + 1;
|
|
383
|
+
for (let rowIndex = fillBounds.startRow; rowIndex <= fillBounds.endRow; rowIndex += 1) {
|
|
384
|
+
for (let colIndex = fillBounds.startCol; colIndex <= fillBounds.endCol; colIndex += 1) {
|
|
385
|
+
if (isCellInSelection(rowIndex, colIndex, sourceBounds)) continue;
|
|
386
|
+
const offsetRow = rowIndex - sourceBounds.startRow;
|
|
387
|
+
const offsetCol = colIndex - sourceBounds.startCol;
|
|
388
|
+
const sourceRowIndex = sourceBounds.startRow + (offsetRow % sourceHeight + sourceHeight) % sourceHeight;
|
|
389
|
+
const sourceColIndex = sourceBounds.startCol + (offsetCol % sourceWidth + sourceWidth) % sourceWidth;
|
|
390
|
+
const targetRow = rows[rowIndex];
|
|
391
|
+
const targetCell = targetRow?.getVisibleCells()[colIndex];
|
|
392
|
+
const sourceCell = rows[sourceRowIndex]?.getVisibleCells()[sourceColIndex];
|
|
393
|
+
if (!targetRow || !targetCell || !sourceCell) continue;
|
|
394
|
+
const accessorKey = getColumnAccessorKey2(
|
|
395
|
+
targetCell.column.columnDef
|
|
396
|
+
);
|
|
397
|
+
if (!accessorKey) continue;
|
|
398
|
+
targets.push({
|
|
399
|
+
rowIndex,
|
|
400
|
+
accessorKey,
|
|
401
|
+
columnId: targetCell.column.id,
|
|
402
|
+
value: sourceCell.getValue(),
|
|
403
|
+
rowId: targetRow.id
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return targets;
|
|
408
|
+
}
|
|
409
|
+
function collectFillChanges(rows, sourceBounds, fillBounds) {
|
|
410
|
+
return collectFillTargets(rows, sourceBounds, fillBounds).map(
|
|
411
|
+
({ rowId, columnId, value }) => ({ rowId, columnId, value })
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
function applyFillData(data, rows, sourceBounds, fillBounds) {
|
|
415
|
+
const newData = data.map((row) => ({ ...row }));
|
|
416
|
+
const targets = collectFillTargets(rows, sourceBounds, fillBounds);
|
|
417
|
+
for (const target of targets) {
|
|
418
|
+
if (!newData[target.rowIndex]) continue;
|
|
419
|
+
newData[target.rowIndex][target.accessorKey] = target.value;
|
|
148
420
|
}
|
|
149
|
-
return
|
|
421
|
+
return newData;
|
|
422
|
+
}
|
|
423
|
+
function hasFillExtension(sourceBounds, fillBounds) {
|
|
424
|
+
if (!sourceBounds) return false;
|
|
425
|
+
return fillBounds.startRow < sourceBounds.startRow || fillBounds.endRow > sourceBounds.endRow || fillBounds.startCol < sourceBounds.startCol || fillBounds.endCol > sourceBounds.endCol;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// src/components/ui/table/features/cell-selection/useCellSelection.ts
|
|
429
|
+
function useCellSelection({
|
|
430
|
+
data,
|
|
431
|
+
rows,
|
|
432
|
+
enabled = true,
|
|
433
|
+
onDataChange,
|
|
434
|
+
onBatchChange
|
|
435
|
+
}) {
|
|
436
|
+
const [dragState, setDragState] = useState2(INITIAL_DRAG_STATE);
|
|
437
|
+
const cellSelectionBounds = getCellSelectionBounds(dragState.start, dragState.end);
|
|
438
|
+
const activeSelectionBounds = enabled ? getActiveSelectionBounds(dragState, cellSelectionBounds) : null;
|
|
439
|
+
const handleCellMouseDown = useCallback2(
|
|
440
|
+
(rowIndex, colIndex) => {
|
|
441
|
+
if (!enabled) return;
|
|
442
|
+
setDragState({
|
|
443
|
+
isSelecting: true,
|
|
444
|
+
isFillDragging: false,
|
|
445
|
+
start: { row: rowIndex, col: colIndex },
|
|
446
|
+
end: { row: rowIndex, col: colIndex },
|
|
447
|
+
fillAnchor: null,
|
|
448
|
+
fillEnd: null
|
|
449
|
+
});
|
|
450
|
+
},
|
|
451
|
+
[enabled]
|
|
452
|
+
);
|
|
453
|
+
const handleCellMouseEnter = useCallback2(
|
|
454
|
+
(rowIndex, colIndex) => {
|
|
455
|
+
if (!enabled) return;
|
|
456
|
+
setDragState((prev) => {
|
|
457
|
+
if (prev.isSelecting) {
|
|
458
|
+
return { ...prev, end: { row: rowIndex, col: colIndex } };
|
|
459
|
+
}
|
|
460
|
+
if (prev.isFillDragging) {
|
|
461
|
+
return { ...prev, fillEnd: { row: rowIndex, col: colIndex } };
|
|
462
|
+
}
|
|
463
|
+
return prev;
|
|
464
|
+
});
|
|
465
|
+
},
|
|
466
|
+
[enabled]
|
|
467
|
+
);
|
|
468
|
+
const handleFillHandleMouseDown = useCallback2(
|
|
469
|
+
(rowIndex, colIndex) => {
|
|
470
|
+
if (!enabled) return;
|
|
471
|
+
setDragState((prev) => {
|
|
472
|
+
const bounds = getCellSelectionBounds(prev.start, prev.end);
|
|
473
|
+
if (!bounds) return prev;
|
|
474
|
+
return {
|
|
475
|
+
...prev,
|
|
476
|
+
isSelecting: false,
|
|
477
|
+
isFillDragging: true,
|
|
478
|
+
fillAnchor: { row: bounds.startRow, col: bounds.startCol },
|
|
479
|
+
fillEnd: { row: rowIndex, col: colIndex }
|
|
480
|
+
};
|
|
481
|
+
});
|
|
482
|
+
},
|
|
483
|
+
[enabled]
|
|
484
|
+
);
|
|
485
|
+
useEffect2(() => {
|
|
486
|
+
if (!enabled) {
|
|
487
|
+
setDragState(INITIAL_DRAG_STATE);
|
|
488
|
+
}
|
|
489
|
+
}, [enabled]);
|
|
490
|
+
useEffect2(() => {
|
|
491
|
+
if (!enabled) return;
|
|
492
|
+
const handleKeyDown = (e) => {
|
|
493
|
+
if ((e.ctrlKey || e.metaKey) && e.key === "c" && activeSelectionBounds) {
|
|
494
|
+
const { startRow, endRow, startCol, endCol } = activeSelectionBounds;
|
|
495
|
+
const selectedData = rows.slice(startRow, endRow + 1).map((row) => {
|
|
496
|
+
const cells = row.getVisibleCells();
|
|
497
|
+
return cells.slice(startCol, endCol + 1).map((cell) => cell.getValue()).join(" ");
|
|
498
|
+
}).join("\n");
|
|
499
|
+
navigator.clipboard.writeText(selectedData);
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
503
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
504
|
+
}, [activeSelectionBounds, enabled, rows]);
|
|
505
|
+
useEffect2(() => {
|
|
506
|
+
if (!enabled) return;
|
|
507
|
+
const handleMouseUp = () => {
|
|
508
|
+
setDragState((prev) => {
|
|
509
|
+
if (prev.isFillDragging && prev.fillAnchor && prev.fillEnd) {
|
|
510
|
+
const sourceBounds = getCellSelectionBounds(prev.start, prev.end);
|
|
511
|
+
const newBounds = getCellSelectionBounds(prev.fillAnchor, prev.fillEnd);
|
|
512
|
+
if (newBounds) {
|
|
513
|
+
if (hasFillExtension(sourceBounds, newBounds) && sourceBounds) {
|
|
514
|
+
if (onBatchChange) {
|
|
515
|
+
const changes = collectFillChanges(rows, sourceBounds, newBounds);
|
|
516
|
+
if (changes.length > 0) {
|
|
517
|
+
onBatchChange(changes);
|
|
518
|
+
}
|
|
519
|
+
} else if (onDataChange) {
|
|
520
|
+
onDataChange(applyFillData(data, rows, sourceBounds, newBounds));
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return {
|
|
524
|
+
isSelecting: false,
|
|
525
|
+
isFillDragging: false,
|
|
526
|
+
start: { row: newBounds.startRow, col: newBounds.startCol },
|
|
527
|
+
end: { row: newBounds.endRow, col: newBounds.endCol },
|
|
528
|
+
fillAnchor: null,
|
|
529
|
+
fillEnd: null
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
if (prev.isSelecting) {
|
|
534
|
+
return { ...prev, isSelecting: false };
|
|
535
|
+
}
|
|
536
|
+
if (prev.isFillDragging) {
|
|
537
|
+
return { ...prev, isFillDragging: false, fillAnchor: null, fillEnd: null };
|
|
538
|
+
}
|
|
539
|
+
return prev;
|
|
540
|
+
});
|
|
541
|
+
};
|
|
542
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
543
|
+
return () => window.removeEventListener("mouseup", handleMouseUp);
|
|
544
|
+
}, [data, enabled, onBatchChange, onDataChange, rows]);
|
|
545
|
+
return {
|
|
546
|
+
dragState: enabled ? dragState : INITIAL_DRAG_STATE,
|
|
547
|
+
activeSelectionBounds,
|
|
548
|
+
handleCellMouseDown,
|
|
549
|
+
handleCellMouseEnter,
|
|
550
|
+
handleFillHandleMouseDown
|
|
551
|
+
};
|
|
150
552
|
}
|
|
151
553
|
|
|
152
554
|
// src/components/ui/table/features/row-expand/row-expand.ts
|
|
153
|
-
import { useEffect, useMemo, useRef } from "react";
|
|
555
|
+
import { useEffect as useEffect3, useMemo, useRef as useRef2 } from "react";
|
|
154
556
|
function getFieldValue(row, key) {
|
|
155
557
|
return row[key];
|
|
156
558
|
}
|
|
@@ -171,20 +573,21 @@ function toggleExpandedRowId(rowId, previous) {
|
|
|
171
573
|
var useConvertTreeData = ({
|
|
172
574
|
data,
|
|
173
575
|
enabled = true,
|
|
174
|
-
toggleField =
|
|
175
|
-
childField =
|
|
176
|
-
flattenField =
|
|
576
|
+
toggleField = DEFAULT_TREE_ID_FIELD,
|
|
577
|
+
childField = DEFAULT_TREE_PARENT_ID_FIELD,
|
|
578
|
+
flattenField = DEFAULT_TREE_CHILDREN_FIELD,
|
|
579
|
+
qtyField = DEFAULT_TREE_QTY_FIELD,
|
|
177
580
|
preventExpand = false,
|
|
178
581
|
startIndex = 1,
|
|
179
582
|
expandedRows,
|
|
180
583
|
onExpandedRowsChange
|
|
181
584
|
}) => {
|
|
182
|
-
const onExpandedRowsChangeRef =
|
|
183
|
-
const hasInitializedRef =
|
|
184
|
-
|
|
585
|
+
const onExpandedRowsChangeRef = useRef2(onExpandedRowsChange);
|
|
586
|
+
const hasInitializedRef = useRef2(false);
|
|
587
|
+
useEffect3(() => {
|
|
185
588
|
onExpandedRowsChangeRef.current = onExpandedRowsChange;
|
|
186
589
|
}, [onExpandedRowsChange]);
|
|
187
|
-
|
|
590
|
+
useEffect3(() => {
|
|
188
591
|
if (!data || data.length === 0) {
|
|
189
592
|
hasInitializedRef.current = false;
|
|
190
593
|
return;
|
|
@@ -215,735 +618,121 @@ var useConvertTreeData = ({
|
|
|
215
618
|
});
|
|
216
619
|
flattenItems(children);
|
|
217
620
|
} else {
|
|
218
|
-
flattenedData.push(newItem);
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
};
|
|
222
|
-
flattenItems(data);
|
|
223
|
-
const dataWithLevels = flattenedData.map((item) => ({
|
|
224
|
-
...item,
|
|
225
|
-
level: 0,
|
|
226
|
-
children: [],
|
|
227
|
-
processed: false
|
|
228
|
-
}));
|
|
229
|
-
const itemMap = /* @__PURE__ */ new Map();
|
|
230
|
-
dataWithLevels.forEach((item) => {
|
|
231
|
-
const key = getFieldValue(item, toggleField);
|
|
232
|
-
if (typeof key !== "string" || !key) return;
|
|
233
|
-
if (!itemMap.has(key)) {
|
|
234
|
-
itemMap.set(key, []);
|
|
235
|
-
}
|
|
236
|
-
itemMap.get(key)?.push(item);
|
|
237
|
-
});
|
|
238
|
-
const rootItems = [];
|
|
239
|
-
dataWithLevels.forEach((item) => {
|
|
240
|
-
if (!getFieldValue(item, childField)) {
|
|
241
|
-
rootItems.push(item);
|
|
242
|
-
item.processed = true;
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
dataWithLevels.forEach((item) => {
|
|
246
|
-
const parentKey = getFieldValue(item, childField);
|
|
247
|
-
if (!parentKey || item.processed) return;
|
|
248
|
-
const parentItems = dataWithLevels.filter(
|
|
249
|
-
(parent) => getFieldValue(parent, toggleField) === parentKey && !getFieldValue(parent, childField)
|
|
250
|
-
);
|
|
251
|
-
if (parentItems.length > 0) {
|
|
252
|
-
const parent = parentItems[0];
|
|
253
|
-
item.level = parent.level + 1;
|
|
254
|
-
parent.children.push(item);
|
|
255
|
-
item.processed = true;
|
|
256
|
-
} else {
|
|
257
|
-
const otherParents = itemMap.get(String(parentKey)) || [];
|
|
258
|
-
if (otherParents.length > 0) {
|
|
259
|
-
const parent = otherParents[0];
|
|
260
|
-
item.level = parent.level + 1;
|
|
261
|
-
parent.children.push(item);
|
|
262
|
-
item.processed = true;
|
|
263
|
-
} else {
|
|
264
|
-
rootItems.push(item);
|
|
265
|
-
item.processed = true;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
return rootItems;
|
|
270
|
-
}, [enabled, data, toggleField, childField, flattenField]);
|
|
271
|
-
const flattenTree = useMemo(() => {
|
|
272
|
-
if (!enabled) return [];
|
|
273
|
-
const flatten = (nodes, result = [], level = 0) => {
|
|
274
|
-
nodes.forEach((node, index) => {
|
|
275
|
-
const currentIndex = level === 0 ? `${index + startIndex}` : `${level}-${index + 1}`;
|
|
276
|
-
const toggleValue = getFieldValue(node, toggleField);
|
|
277
|
-
const uniqueId = `${index}-${String(toggleValue ?? "")}`;
|
|
278
|
-
result.push({
|
|
279
|
-
...node,
|
|
280
|
-
treeNo: currentIndex,
|
|
281
|
-
uniqueId,
|
|
282
|
-
processed: true
|
|
283
|
-
});
|
|
284
|
-
const shouldExpandChildren = node.children.length > 0 && (preventExpand || typeof toggleValue === "string" && expandedRows?.has(toggleValue));
|
|
285
|
-
if (shouldExpandChildren) {
|
|
286
|
-
flatten(node.children, result, index + startIndex);
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
return result;
|
|
290
|
-
};
|
|
291
|
-
const flattenedData = flatten(processedData, [], 0);
|
|
292
|
-
flattenedData.forEach((item) => {
|
|
293
|
-
if (getFieldValue(item, childField)) {
|
|
294
|
-
const parentItem = flattenedData.find(
|
|
295
|
-
(parent) => getFieldValue(parent, toggleField) === getFieldValue(item, childField)
|
|
296
|
-
);
|
|
297
|
-
const parentAmount = parentItem ? Number(getFieldValue(parentItem, "amount") ?? 1) : 1;
|
|
298
|
-
item.parentCount = parentAmount || 1;
|
|
299
|
-
} else {
|
|
300
|
-
item.parentCount = 1;
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
return flattenedData;
|
|
304
|
-
}, [enabled, processedData, startIndex, toggleField, childField, preventExpand, expandedRows]);
|
|
305
|
-
const sortedData = useMemo(() => {
|
|
306
|
-
if (!enabled) {
|
|
307
|
-
return data ?? [];
|
|
308
|
-
}
|
|
309
|
-
return [...flattenTree].sort((a, b) => {
|
|
310
|
-
const aParts = String(a.treeNo ?? "").split("-").map(Number);
|
|
311
|
-
const bParts = String(b.treeNo ?? "").split("-").map(Number);
|
|
312
|
-
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
313
|
-
const aVal = aParts[i] || 0;
|
|
314
|
-
const bVal = bParts[i] || 0;
|
|
315
|
-
if (aVal !== bVal) {
|
|
316
|
-
return aVal - bVal;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
return 0;
|
|
320
|
-
});
|
|
321
|
-
}, [enabled, data, flattenTree]);
|
|
322
|
-
return sortedData;
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
// src/components/ui/table/components/icons.tsx
|
|
326
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
327
|
-
function ChevronDown({ className, "aria-hidden": ariaHidden = true }) {
|
|
328
|
-
return /* @__PURE__ */ jsx2(
|
|
329
|
-
"svg",
|
|
330
|
-
{
|
|
331
|
-
className,
|
|
332
|
-
"aria-hidden": ariaHidden,
|
|
333
|
-
width: "16",
|
|
334
|
-
height: "16",
|
|
335
|
-
viewBox: "0 0 24 24",
|
|
336
|
-
fill: "none",
|
|
337
|
-
stroke: "currentColor",
|
|
338
|
-
strokeWidth: "2",
|
|
339
|
-
strokeLinecap: "round",
|
|
340
|
-
strokeLinejoin: "round",
|
|
341
|
-
children: /* @__PURE__ */ jsx2("path", { d: "m6 9 6 6 6-6" })
|
|
342
|
-
}
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
function ChevronUp({ className, "aria-hidden": ariaHidden = true }) {
|
|
346
|
-
return /* @__PURE__ */ jsx2(
|
|
347
|
-
"svg",
|
|
348
|
-
{
|
|
349
|
-
className,
|
|
350
|
-
"aria-hidden": ariaHidden,
|
|
351
|
-
width: "16",
|
|
352
|
-
height: "16",
|
|
353
|
-
viewBox: "0 0 24 24",
|
|
354
|
-
fill: "none",
|
|
355
|
-
stroke: "currentColor",
|
|
356
|
-
strokeWidth: "2",
|
|
357
|
-
strokeLinecap: "round",
|
|
358
|
-
strokeLinejoin: "round",
|
|
359
|
-
children: /* @__PURE__ */ jsx2("path", { d: "m18 15-6-6-6 6" })
|
|
360
|
-
}
|
|
361
|
-
);
|
|
362
|
-
}
|
|
363
|
-
function ChevronLeft({ className, "aria-hidden": ariaHidden = true }) {
|
|
364
|
-
return /* @__PURE__ */ jsx2(
|
|
365
|
-
"svg",
|
|
366
|
-
{
|
|
367
|
-
className,
|
|
368
|
-
"aria-hidden": ariaHidden,
|
|
369
|
-
width: "16",
|
|
370
|
-
height: "16",
|
|
371
|
-
viewBox: "0 0 24 24",
|
|
372
|
-
fill: "none",
|
|
373
|
-
stroke: "currentColor",
|
|
374
|
-
strokeWidth: "2",
|
|
375
|
-
strokeLinecap: "round",
|
|
376
|
-
strokeLinejoin: "round",
|
|
377
|
-
children: /* @__PURE__ */ jsx2("path", { d: "m15 18-6-6 6-6" })
|
|
378
|
-
}
|
|
379
|
-
);
|
|
380
|
-
}
|
|
381
|
-
function ChevronRight({ className, "aria-hidden": ariaHidden = true }) {
|
|
382
|
-
return /* @__PURE__ */ jsx2(
|
|
383
|
-
"svg",
|
|
384
|
-
{
|
|
385
|
-
className,
|
|
386
|
-
"aria-hidden": ariaHidden,
|
|
387
|
-
width: "16",
|
|
388
|
-
height: "16",
|
|
389
|
-
viewBox: "0 0 24 24",
|
|
390
|
-
fill: "none",
|
|
391
|
-
stroke: "currentColor",
|
|
392
|
-
strokeWidth: "2",
|
|
393
|
-
strokeLinecap: "round",
|
|
394
|
-
strokeLinejoin: "round",
|
|
395
|
-
children: /* @__PURE__ */ jsx2("path", { d: "m9 18 6-6-6-6" })
|
|
396
|
-
}
|
|
397
|
-
);
|
|
398
|
-
}
|
|
399
|
-
function ArrowUp({ className, "aria-hidden": ariaHidden = true }) {
|
|
400
|
-
return /* @__PURE__ */ jsxs(
|
|
401
|
-
"svg",
|
|
402
|
-
{
|
|
403
|
-
className,
|
|
404
|
-
"aria-hidden": ariaHidden,
|
|
405
|
-
width: "14",
|
|
406
|
-
height: "14",
|
|
407
|
-
viewBox: "0 0 24 24",
|
|
408
|
-
fill: "none",
|
|
409
|
-
stroke: "currentColor",
|
|
410
|
-
strokeWidth: "2",
|
|
411
|
-
strokeLinecap: "round",
|
|
412
|
-
strokeLinejoin: "round",
|
|
413
|
-
children: [
|
|
414
|
-
/* @__PURE__ */ jsx2("path", { d: "m18 15-6-6-6 6" }),
|
|
415
|
-
/* @__PURE__ */ jsx2("path", { d: "M12 21V9" })
|
|
416
|
-
]
|
|
417
|
-
}
|
|
418
|
-
);
|
|
419
|
-
}
|
|
420
|
-
function ArrowDown({ className, "aria-hidden": ariaHidden = true }) {
|
|
421
|
-
return /* @__PURE__ */ jsxs(
|
|
422
|
-
"svg",
|
|
423
|
-
{
|
|
424
|
-
className,
|
|
425
|
-
"aria-hidden": ariaHidden,
|
|
426
|
-
width: "14",
|
|
427
|
-
height: "14",
|
|
428
|
-
viewBox: "0 0 24 24",
|
|
429
|
-
fill: "none",
|
|
430
|
-
stroke: "currentColor",
|
|
431
|
-
strokeWidth: "2",
|
|
432
|
-
strokeLinecap: "round",
|
|
433
|
-
strokeLinejoin: "round",
|
|
434
|
-
children: [
|
|
435
|
-
/* @__PURE__ */ jsx2("path", { d: "m6 9 6 6 6-6" }),
|
|
436
|
-
/* @__PURE__ */ jsx2("path", { d: "M12 3v12" })
|
|
437
|
-
]
|
|
438
|
-
}
|
|
439
|
-
);
|
|
440
|
-
}
|
|
441
|
-
function ArrowUpDown({ className, "aria-hidden": ariaHidden = true }) {
|
|
442
|
-
return /* @__PURE__ */ jsxs(
|
|
443
|
-
"svg",
|
|
444
|
-
{
|
|
445
|
-
className,
|
|
446
|
-
"aria-hidden": ariaHidden,
|
|
447
|
-
width: "14",
|
|
448
|
-
height: "14",
|
|
449
|
-
viewBox: "0 0 24 24",
|
|
450
|
-
fill: "none",
|
|
451
|
-
stroke: "currentColor",
|
|
452
|
-
strokeWidth: "2",
|
|
453
|
-
strokeLinecap: "round",
|
|
454
|
-
strokeLinejoin: "round",
|
|
455
|
-
children: [
|
|
456
|
-
/* @__PURE__ */ jsx2("path", { d: "m21 16-4 4-4-4" }),
|
|
457
|
-
/* @__PURE__ */ jsx2("path", { d: "M17 20V4" }),
|
|
458
|
-
/* @__PURE__ */ jsx2("path", { d: "m3 8 4-4 4 4" }),
|
|
459
|
-
/* @__PURE__ */ jsx2("path", { d: "M7 4v16" })
|
|
460
|
-
]
|
|
461
|
-
}
|
|
462
|
-
);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// src/lib/cn.ts
|
|
466
|
-
function cn(...inputs) {
|
|
467
|
-
return inputs.filter(Boolean).join(" ");
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// src/components/ui/table/components/DataTable/DataTableRow.tsx
|
|
471
|
-
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
472
|
-
function resolveExpandCellIndex(cells, toggleField) {
|
|
473
|
-
if (!toggleField) return 0;
|
|
474
|
-
const matchedIndex = cells.findIndex(
|
|
475
|
-
(cell) => cell.column.id === toggleField
|
|
476
|
-
);
|
|
477
|
-
if (matchedIndex >= 0) return matchedIndex;
|
|
478
|
-
const noColumnIndex = cells.findIndex(
|
|
479
|
-
(cell) => cell.column.id === "no" || cell.column.id === "treeNo"
|
|
480
|
-
);
|
|
481
|
-
if (noColumnIndex >= 0 && noColumnIndex + 1 < cells.length) {
|
|
482
|
-
return noColumnIndex + 1;
|
|
483
|
-
}
|
|
484
|
-
return 0;
|
|
485
|
-
}
|
|
486
|
-
function DataTableRow({
|
|
487
|
-
row,
|
|
488
|
-
onToggleSelect,
|
|
489
|
-
virtualIndex,
|
|
490
|
-
measureElement
|
|
491
|
-
}) {
|
|
492
|
-
const { rowSpan, selection, cellSelection, cellEdit, expand } = useDataTableRowContext();
|
|
493
|
-
const {
|
|
494
|
-
enableRowSpan,
|
|
495
|
-
primaryRowSpanKey,
|
|
496
|
-
columnRowSpanMap,
|
|
497
|
-
hoveredRowIndex,
|
|
498
|
-
hoveredGroupKey,
|
|
499
|
-
selectedGroupKeys,
|
|
500
|
-
onRowHover
|
|
501
|
-
} = rowSpan;
|
|
502
|
-
const { rowSelectionMode, selectOnRowClick, onRowClick, getRowClassName } = selection;
|
|
503
|
-
const {
|
|
504
|
-
activeSelectionBounds,
|
|
505
|
-
dragState,
|
|
506
|
-
onCellMouseDown,
|
|
507
|
-
onCellMouseEnter,
|
|
508
|
-
onFillHandleMouseDown
|
|
509
|
-
} = cellSelection;
|
|
510
|
-
const {
|
|
511
|
-
editingCell,
|
|
512
|
-
draftValue,
|
|
513
|
-
onDraftValueChange,
|
|
514
|
-
onStartEdit,
|
|
515
|
-
onCommitEdit,
|
|
516
|
-
onCancelEdit
|
|
517
|
-
} = cellEdit;
|
|
518
|
-
const {
|
|
519
|
-
enableExpand,
|
|
520
|
-
toggleField,
|
|
521
|
-
expandedRows,
|
|
522
|
-
preventExpand,
|
|
523
|
-
onToggleExpand
|
|
524
|
-
} = expand;
|
|
525
|
-
const rowIndex = row.index;
|
|
526
|
-
const rowData = row.original;
|
|
527
|
-
const isRowHovered = hoveredRowIndex === rowIndex;
|
|
528
|
-
const isRowSelected = row.getIsSelected();
|
|
529
|
-
const rowGroupKey = primaryRowSpanKey !== void 0 && rowData[primaryRowSpanKey] !== null && rowData[primaryRowSpanKey] !== void 0 ? String(rowData[primaryRowSpanKey]) : null;
|
|
530
|
-
const isGroupHovered = enableRowSpan && hoveredGroupKey !== null && rowGroupKey === hoveredGroupKey;
|
|
531
|
-
const isGroupSelected = enableRowSpan && rowGroupKey !== null && selectedGroupKeys.has(rowGroupKey);
|
|
532
|
-
const visibleCells = row.getVisibleCells();
|
|
533
|
-
const expandCellIndex = enableExpand ? resolveExpandCellIndex(visibleCells, toggleField) : -1;
|
|
534
|
-
const canExpand = enableExpand && !preventExpand && canExpandRow(rowData);
|
|
535
|
-
const expandKey = toggleField && rowData[toggleField] !== null && rowData[toggleField] !== void 0 ? String(rowData[toggleField]) : null;
|
|
536
|
-
const isExpanded = expandKey !== null && Boolean(expandedRows?.has(expandKey));
|
|
537
|
-
const rowLevel = typeof rowData.level === "number" ? rowData.level : 0;
|
|
538
|
-
const editInputRef = useRef2(null);
|
|
539
|
-
const isRowEditing = editingCell?.rowIndex === rowIndex;
|
|
540
|
-
useEffect2(() => {
|
|
541
|
-
if (!isRowEditing) return;
|
|
542
|
-
editInputRef.current?.focus();
|
|
543
|
-
editInputRef.current?.select();
|
|
544
|
-
}, [isRowEditing, editingCell?.colIndex]);
|
|
545
|
-
return /* @__PURE__ */ jsx3(
|
|
546
|
-
"tr",
|
|
547
|
-
{
|
|
548
|
-
ref: measureElement,
|
|
549
|
-
"data-index": virtualIndex,
|
|
550
|
-
className: cn(
|
|
551
|
-
"DataTableRowJSX",
|
|
552
|
-
!enableRowSpan && ROW_HOVER_CLASS,
|
|
553
|
-
enableRowSpan && isRowHovered && !isRowSelected && ROW_HOVERED_BG_CLASS,
|
|
554
|
-
isRowSelected && "is-selected",
|
|
555
|
-
enableExpand && canExpand && "is-expandable",
|
|
556
|
-
getRowClassName?.(rowData, rowIndex)
|
|
557
|
-
),
|
|
558
|
-
onMouseEnter: () => onRowHover(rowIndex, rowData),
|
|
559
|
-
onClick: () => {
|
|
560
|
-
if (isRowEditing) return;
|
|
561
|
-
onRowClick?.(rowData, rowIndex);
|
|
562
|
-
if (rowSelectionMode !== "none" && selectOnRowClick) {
|
|
563
|
-
onToggleSelect();
|
|
564
|
-
}
|
|
565
|
-
},
|
|
566
|
-
children: visibleCells.map((cell, cellIndex) => {
|
|
567
|
-
const columnId = cell.column.id;
|
|
568
|
-
const meta = cell.column.columnDef.meta;
|
|
569
|
-
const align = meta?.align ?? "center";
|
|
570
|
-
const cellClassName = meta?.className;
|
|
571
|
-
const isRowSpanColumn = Boolean(enableRowSpan && meta?.rowSpan);
|
|
572
|
-
const isExpandCell = cellIndex === expandCellIndex;
|
|
573
|
-
const editable = isColumnEditable(cell.column.columnDef);
|
|
574
|
-
const editType = getColumnEditType(cell.column.columnDef);
|
|
575
|
-
let rowSpanInfo;
|
|
576
|
-
if (isRowSpanColumn) {
|
|
577
|
-
rowSpanInfo = columnRowSpanMap.get(columnId)?.[rowIndex];
|
|
578
|
-
if (rowSpanInfo && rowSpanInfo.rowSpan === 0) {
|
|
579
|
-
return null;
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
const isEditing = editingCell?.rowIndex === rowIndex && editingCell?.colIndex === cellIndex;
|
|
583
|
-
const showCellHover = isRowSpanColumn ? isGroupHovered : isRowHovered;
|
|
584
|
-
const showCellSelected = isRowSpanColumn ? isGroupSelected : isRowSelected;
|
|
585
|
-
const cellRowSpan = rowSpanInfo?.rowSpan ?? 1;
|
|
586
|
-
const isCellDragSelected = isCellInSelection(
|
|
587
|
-
rowIndex,
|
|
588
|
-
cellIndex,
|
|
589
|
-
activeSelectionBounds,
|
|
590
|
-
cellRowSpan
|
|
591
|
-
);
|
|
592
|
-
const isBottomRightCell = !isEditing && activeSelectionBounds && !dragState.isSelecting && activeSelectionBounds.endRow >= rowIndex && activeSelectionBounds.endRow <= rowIndex + cellRowSpan - 1 && cellIndex === activeSelectionBounds.endCol;
|
|
593
|
-
const resolveCellRowIndex = (clientY, element) => getRowIndexInMergedCell(clientY, element, rowIndex, cellRowSpan);
|
|
594
|
-
return /* @__PURE__ */ jsxs2(
|
|
595
|
-
"td",
|
|
596
|
-
{
|
|
597
|
-
rowSpan: rowSpanInfo && rowSpanInfo.rowSpan > 1 ? rowSpanInfo.rowSpan : void 0,
|
|
598
|
-
onMouseDown: (event) => {
|
|
599
|
-
if (isEditing) {
|
|
600
|
-
event.stopPropagation();
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
event.preventDefault();
|
|
604
|
-
onCellMouseDown(
|
|
605
|
-
resolveCellRowIndex(event.clientY, event.currentTarget),
|
|
606
|
-
cellIndex
|
|
607
|
-
);
|
|
608
|
-
},
|
|
609
|
-
onMouseEnter: (event) => onCellMouseEnter(
|
|
610
|
-
resolveCellRowIndex(event.clientY, event.currentTarget),
|
|
611
|
-
cellIndex
|
|
612
|
-
),
|
|
613
|
-
onMouseMove: (event) => {
|
|
614
|
-
if (!dragState.isSelecting && !dragState.isFillDragging) return;
|
|
615
|
-
onCellMouseEnter(
|
|
616
|
-
resolveCellRowIndex(event.clientY, event.currentTarget),
|
|
617
|
-
cellIndex
|
|
618
|
-
);
|
|
619
|
-
},
|
|
620
|
-
onDoubleClick: (event) => {
|
|
621
|
-
if (!editable) return;
|
|
622
|
-
event.preventDefault();
|
|
623
|
-
event.stopPropagation();
|
|
624
|
-
onStartEdit(rowIndex, cellIndex);
|
|
625
|
-
},
|
|
626
|
-
style: getCellSelectionEdgeStyle(
|
|
627
|
-
rowIndex,
|
|
628
|
-
cellIndex,
|
|
629
|
-
activeSelectionBounds,
|
|
630
|
-
cellRowSpan
|
|
631
|
-
),
|
|
632
|
-
className: cn(
|
|
633
|
-
"data-table-cell",
|
|
634
|
-
CELL_ALIGN_CLASS[align],
|
|
635
|
-
cellClassName,
|
|
636
|
-
enableRowSpan && showCellSelected && "is-group-selected",
|
|
637
|
-
enableRowSpan && showCellHover && !showCellSelected && "is-group-hovered",
|
|
638
|
-
isCellDragSelected && CELL_SELECTION_FILL_CLASS,
|
|
639
|
-
editable && "is-editable"
|
|
640
|
-
),
|
|
641
|
-
children: [
|
|
642
|
-
isEditing ? /* @__PURE__ */ jsx3(
|
|
643
|
-
"input",
|
|
644
|
-
{
|
|
645
|
-
ref: editInputRef,
|
|
646
|
-
type: editType === "number" ? "number" : "text",
|
|
647
|
-
defaultValue: draftValue,
|
|
648
|
-
className: cn("cell-edit-input", CELL_ALIGN_CLASS[align]),
|
|
649
|
-
onChange: (event) => onDraftValueChange(event.target.value),
|
|
650
|
-
onMouseDown: (event) => event.stopPropagation(),
|
|
651
|
-
onClick: (event) => event.stopPropagation(),
|
|
652
|
-
onKeyDown: (event) => {
|
|
653
|
-
if (event.key === "Enter") {
|
|
654
|
-
event.preventDefault();
|
|
655
|
-
onCommitEdit(event.currentTarget.value);
|
|
656
|
-
}
|
|
657
|
-
if (event.key === "Escape") {
|
|
658
|
-
event.preventDefault();
|
|
659
|
-
onCancelEdit();
|
|
660
|
-
}
|
|
661
|
-
},
|
|
662
|
-
onBlur: (event) => {
|
|
663
|
-
onCommitEdit(event.currentTarget.value);
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
) : isExpandCell && enableExpand ? /* @__PURE__ */ jsxs2("div", { className: "expand-cell", children: [
|
|
667
|
-
/* @__PURE__ */ jsxs2("div", { className: "expand-cell-content", children: [
|
|
668
|
-
rowLevel > 0 && /* @__PURE__ */ jsx3("span", { className: "expand-cell-indent", children: "\xB7" }),
|
|
669
|
-
/* @__PURE__ */ jsx3("div", { className: "expand-cell-value", children: flexRender(cell.column.columnDef.cell, cell.getContext()) })
|
|
670
|
-
] }),
|
|
671
|
-
canExpand && expandKey && /* @__PURE__ */ jsx3(
|
|
672
|
-
"button",
|
|
673
|
-
{
|
|
674
|
-
type: "button",
|
|
675
|
-
"aria-label": isExpanded ? "\uD589 \uC811\uAE30" : "\uD589 \uD3BC\uCE58\uAE30",
|
|
676
|
-
className: "expand-toggle-button",
|
|
677
|
-
onClick: (event) => {
|
|
678
|
-
event.stopPropagation();
|
|
679
|
-
onToggleExpand?.(expandKey);
|
|
680
|
-
},
|
|
681
|
-
onMouseDown: (event) => event.stopPropagation(),
|
|
682
|
-
children: isExpanded ? /* @__PURE__ */ jsx3(ChevronUp, { className: "expand-toggle-icon" }) : /* @__PURE__ */ jsx3(ChevronDown, { className: "expand-toggle-icon" })
|
|
683
|
-
}
|
|
684
|
-
)
|
|
685
|
-
] }) : flexRender(cell.column.columnDef.cell, cell.getContext()),
|
|
686
|
-
isBottomRightCell && /* @__PURE__ */ jsx3(
|
|
687
|
-
"div",
|
|
688
|
-
{
|
|
689
|
-
role: "presentation",
|
|
690
|
-
className: "fill-handle",
|
|
691
|
-
onMouseDown: (event) => {
|
|
692
|
-
event.stopPropagation();
|
|
693
|
-
event.preventDefault();
|
|
694
|
-
onFillHandleMouseDown(rowIndex, cellIndex);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
)
|
|
698
|
-
]
|
|
699
|
-
},
|
|
700
|
-
cell.id
|
|
701
|
-
);
|
|
702
|
-
})
|
|
703
|
-
}
|
|
704
|
-
);
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
// src/components/ui/table/components/DataTable/DataTableToolbar.tsx
|
|
708
|
-
import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
709
|
-
function DefaultSelectionLabel({ selectedCount }) {
|
|
710
|
-
if (selectedCount <= 0) return null;
|
|
711
|
-
return /* @__PURE__ */ jsxs3("span", { className: "toolbar-selection", children: [
|
|
712
|
-
"\u2713 ",
|
|
713
|
-
selectedCount,
|
|
714
|
-
"\uAC1C \uC120\uD0DD\uB428"
|
|
715
|
-
] });
|
|
716
|
-
}
|
|
717
|
-
function DataTableToolbar({
|
|
718
|
-
filteredCount,
|
|
719
|
-
totalCount,
|
|
720
|
-
summary,
|
|
721
|
-
selectedCount,
|
|
722
|
-
selectionLabel,
|
|
723
|
-
toolbar,
|
|
724
|
-
className
|
|
725
|
-
}) {
|
|
726
|
-
const displayFiltered = filteredCount ?? totalCount;
|
|
727
|
-
const hasCount = displayFiltered !== void 0 || totalCount !== void 0;
|
|
728
|
-
const hasLeftContent = hasCount || Boolean(summary);
|
|
729
|
-
const hasToolbar = Boolean(toolbar);
|
|
730
|
-
const selectionContent = selectionLabel ? selectionLabel(selectedCount) : /* @__PURE__ */ jsx4(DefaultSelectionLabel, { selectedCount });
|
|
731
|
-
const hasSelectionContent = selectionContent !== null && selectionContent !== false;
|
|
732
|
-
if (!hasLeftContent && !hasToolbar && !hasSelectionContent) return null;
|
|
733
|
-
return /* @__PURE__ */ jsxs3("div", { className: cn("DataTableToolbarJSX", className), children: [
|
|
734
|
-
/* @__PURE__ */ jsxs3("div", { className: "toolbar-left", children: [
|
|
735
|
-
hasCount && /* @__PURE__ */ jsx4("span", { className: "toolbar-count", children: displayFiltered !== void 0 && totalCount !== void 0 ? /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
736
|
-
/* @__PURE__ */ jsx4("span", { className: "toolbar-count-primary", children: displayFiltered }),
|
|
737
|
-
/* @__PURE__ */ jsxs3("span", { className: "toolbar-count-placeholder", children: [
|
|
738
|
-
" / ",
|
|
739
|
-
totalCount
|
|
740
|
-
] })
|
|
741
|
-
] }) : /* @__PURE__ */ jsx4("span", { className: "toolbar-count-primary", children: displayFiltered ?? totalCount }) }),
|
|
742
|
-
summary
|
|
743
|
-
] }),
|
|
744
|
-
/* @__PURE__ */ jsxs3("div", { className: "toolbar-right", children: [
|
|
745
|
-
selectionContent,
|
|
746
|
-
hasToolbar && /* @__PURE__ */ jsx4("div", { className: "toolbar-actions", children: toolbar })
|
|
747
|
-
] })
|
|
748
|
-
] });
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
// src/components/ui/table/features/cell-edit/useCellEdit.ts
|
|
752
|
-
import { useCallback, useEffect as useEffect3, useRef as useRef3, useState } from "react";
|
|
753
|
-
function useCellEdit({
|
|
754
|
-
data,
|
|
755
|
-
rows,
|
|
756
|
-
onDataChange
|
|
757
|
-
}) {
|
|
758
|
-
const [editingCell, setEditingCell] = useState(null);
|
|
759
|
-
const [draftValue, setDraftValue] = useState("");
|
|
760
|
-
const draftValueRef = useRef3(draftValue);
|
|
761
|
-
const editingCellRef = useRef3(editingCell);
|
|
762
|
-
useEffect3(() => {
|
|
763
|
-
draftValueRef.current = draftValue;
|
|
764
|
-
}, [draftValue]);
|
|
765
|
-
useEffect3(() => {
|
|
766
|
-
editingCellRef.current = editingCell;
|
|
767
|
-
}, [editingCell]);
|
|
768
|
-
const cancelEdit = useCallback(() => {
|
|
769
|
-
setEditingCell(null);
|
|
770
|
-
setDraftValue("");
|
|
771
|
-
}, []);
|
|
772
|
-
const commitEdit = useCallback(
|
|
773
|
-
(raw) => {
|
|
774
|
-
const current = editingCellRef.current;
|
|
775
|
-
if (!current) return true;
|
|
776
|
-
if (!onDataChange) {
|
|
777
|
-
cancelEdit();
|
|
778
|
-
return true;
|
|
779
|
-
}
|
|
780
|
-
const value = raw ?? draftValueRef.current;
|
|
781
|
-
const next = applyCellEdit(data, rows, current.rowIndex, current.colIndex, value);
|
|
782
|
-
if (!next) return false;
|
|
783
|
-
onDataChange(next);
|
|
784
|
-
cancelEdit();
|
|
785
|
-
return true;
|
|
786
|
-
},
|
|
787
|
-
[cancelEdit, data, onDataChange, rows]
|
|
788
|
-
);
|
|
789
|
-
const startEdit = useCallback(
|
|
790
|
-
(rowIndex, colIndex) => {
|
|
791
|
-
const cell = rows[rowIndex]?.getVisibleCells()[colIndex];
|
|
792
|
-
if (!cell || !isColumnEditable(cell.column.columnDef)) return;
|
|
793
|
-
const current = editingCellRef.current;
|
|
794
|
-
if (current && (current.rowIndex !== rowIndex || current.colIndex !== colIndex) && !commitEdit()) {
|
|
795
|
-
return;
|
|
796
|
-
}
|
|
797
|
-
setEditingCell({ rowIndex, colIndex });
|
|
798
|
-
setDraftValue(getCellEditDraftValue(cell.getValue()));
|
|
799
|
-
},
|
|
800
|
-
[commitEdit, rows]
|
|
801
|
-
);
|
|
802
|
-
return {
|
|
803
|
-
editingCell,
|
|
804
|
-
draftValue,
|
|
805
|
-
setDraftValue,
|
|
806
|
-
startEdit,
|
|
807
|
-
commitEdit,
|
|
808
|
-
cancelEdit
|
|
809
|
-
};
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
// src/components/ui/table/features/cell-selection/useCellSelection.ts
|
|
813
|
-
import { useCallback as useCallback2, useEffect as useEffect4, useState as useState2 } from "react";
|
|
814
|
-
|
|
815
|
-
// src/components/ui/table/features/cell-selection/fillData.ts
|
|
816
|
-
function getColumnAccessorKey2(columnDef) {
|
|
817
|
-
if ("accessorKey" in columnDef && columnDef.accessorKey) {
|
|
818
|
-
return String(columnDef.accessorKey);
|
|
819
|
-
}
|
|
820
|
-
return columnDef.id;
|
|
821
|
-
}
|
|
822
|
-
function applyFillData(data, rows, sourceBounds, fillBounds) {
|
|
823
|
-
const newData = data.map((row) => ({ ...row }));
|
|
824
|
-
const sourceHeight = sourceBounds.endRow - sourceBounds.startRow + 1;
|
|
825
|
-
const sourceWidth = sourceBounds.endCol - sourceBounds.startCol + 1;
|
|
826
|
-
for (let rowIndex = fillBounds.startRow; rowIndex <= fillBounds.endRow; rowIndex += 1) {
|
|
827
|
-
for (let colIndex = fillBounds.startCol; colIndex <= fillBounds.endCol; colIndex += 1) {
|
|
828
|
-
if (isCellInSelection(rowIndex, colIndex, sourceBounds)) continue;
|
|
829
|
-
const offsetRow = rowIndex - sourceBounds.startRow;
|
|
830
|
-
const offsetCol = colIndex - sourceBounds.startCol;
|
|
831
|
-
const sourceRowIndex = sourceBounds.startRow + (offsetRow % sourceHeight + sourceHeight) % sourceHeight;
|
|
832
|
-
const sourceColIndex = sourceBounds.startCol + (offsetCol % sourceWidth + sourceWidth) % sourceWidth;
|
|
833
|
-
const targetCell = rows[rowIndex]?.getVisibleCells()[colIndex];
|
|
834
|
-
const sourceCell = rows[sourceRowIndex]?.getVisibleCells()[sourceColIndex];
|
|
835
|
-
if (!targetCell || !sourceCell) continue;
|
|
836
|
-
const accessorKey = getColumnAccessorKey2(
|
|
837
|
-
targetCell.column.columnDef
|
|
838
|
-
);
|
|
839
|
-
if (!accessorKey) continue;
|
|
840
|
-
newData[rowIndex][accessorKey] = sourceCell.getValue();
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
return newData;
|
|
844
|
-
}
|
|
845
|
-
function hasFillExtension(sourceBounds, fillBounds) {
|
|
846
|
-
if (!sourceBounds) return false;
|
|
847
|
-
return fillBounds.startRow < sourceBounds.startRow || fillBounds.endRow > sourceBounds.endRow || fillBounds.startCol < sourceBounds.startCol || fillBounds.endCol > sourceBounds.endCol;
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
// src/components/ui/table/features/cell-selection/useCellSelection.ts
|
|
851
|
-
function useCellSelection({
|
|
852
|
-
data,
|
|
853
|
-
rows,
|
|
854
|
-
onDataChange
|
|
855
|
-
}) {
|
|
856
|
-
const [dragState, setDragState] = useState2(INITIAL_DRAG_STATE);
|
|
857
|
-
const cellSelectionBounds = getCellSelectionBounds(dragState.start, dragState.end);
|
|
858
|
-
const activeSelectionBounds = getActiveSelectionBounds(dragState, cellSelectionBounds);
|
|
859
|
-
const handleCellMouseDown = useCallback2((rowIndex, colIndex) => {
|
|
860
|
-
setDragState({
|
|
861
|
-
isSelecting: true,
|
|
862
|
-
isFillDragging: false,
|
|
863
|
-
start: { row: rowIndex, col: colIndex },
|
|
864
|
-
end: { row: rowIndex, col: colIndex },
|
|
865
|
-
fillAnchor: null,
|
|
866
|
-
fillEnd: null
|
|
867
|
-
});
|
|
868
|
-
}, []);
|
|
869
|
-
const handleCellMouseEnter = useCallback2((rowIndex, colIndex) => {
|
|
870
|
-
setDragState((prev) => {
|
|
871
|
-
if (prev.isSelecting) {
|
|
872
|
-
return { ...prev, end: { row: rowIndex, col: colIndex } };
|
|
873
|
-
}
|
|
874
|
-
if (prev.isFillDragging) {
|
|
875
|
-
return { ...prev, fillEnd: { row: rowIndex, col: colIndex } };
|
|
621
|
+
flattenedData.push(newItem);
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
};
|
|
625
|
+
flattenItems(data);
|
|
626
|
+
const dataWithLevels = flattenedData.map((item) => ({
|
|
627
|
+
...item,
|
|
628
|
+
level: 0,
|
|
629
|
+
children: [],
|
|
630
|
+
processed: false
|
|
631
|
+
}));
|
|
632
|
+
const itemMap = /* @__PURE__ */ new Map();
|
|
633
|
+
dataWithLevels.forEach((item) => {
|
|
634
|
+
const key = getFieldValue(item, toggleField);
|
|
635
|
+
if (typeof key !== "string" || !key) return;
|
|
636
|
+
if (!itemMap.has(key)) {
|
|
637
|
+
itemMap.set(key, []);
|
|
876
638
|
}
|
|
877
|
-
|
|
878
|
-
});
|
|
879
|
-
}, []);
|
|
880
|
-
const handleFillHandleMouseDown = useCallback2((rowIndex, colIndex) => {
|
|
881
|
-
setDragState((prev) => {
|
|
882
|
-
const bounds = getCellSelectionBounds(prev.start, prev.end);
|
|
883
|
-
if (!bounds) return prev;
|
|
884
|
-
return {
|
|
885
|
-
...prev,
|
|
886
|
-
isSelecting: false,
|
|
887
|
-
isFillDragging: true,
|
|
888
|
-
fillAnchor: { row: bounds.startRow, col: bounds.startCol },
|
|
889
|
-
fillEnd: { row: rowIndex, col: colIndex }
|
|
890
|
-
};
|
|
639
|
+
itemMap.get(key)?.push(item);
|
|
891
640
|
});
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
const selectedData = rows.slice(startRow, endRow + 1).map((row) => {
|
|
898
|
-
const cells = row.getVisibleCells();
|
|
899
|
-
return cells.slice(startCol, endCol + 1).map((cell) => cell.getValue()).join(" ");
|
|
900
|
-
}).join("\n");
|
|
901
|
-
navigator.clipboard.writeText(selectedData);
|
|
641
|
+
const rootItems = [];
|
|
642
|
+
dataWithLevels.forEach((item) => {
|
|
643
|
+
if (!getFieldValue(item, childField)) {
|
|
644
|
+
rootItems.push(item);
|
|
645
|
+
item.processed = true;
|
|
902
646
|
}
|
|
903
|
-
};
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
if (prev.isSelecting) {
|
|
928
|
-
return { ...prev, isSelecting: false };
|
|
647
|
+
});
|
|
648
|
+
dataWithLevels.forEach((item) => {
|
|
649
|
+
const parentKey = getFieldValue(item, childField);
|
|
650
|
+
if (!parentKey || item.processed) return;
|
|
651
|
+
const parentItems = dataWithLevels.filter(
|
|
652
|
+
(parent) => getFieldValue(parent, toggleField) === parentKey && !getFieldValue(parent, childField)
|
|
653
|
+
);
|
|
654
|
+
if (parentItems.length > 0) {
|
|
655
|
+
const parent = parentItems[0];
|
|
656
|
+
item.level = parent.level + 1;
|
|
657
|
+
parent.children.push(item);
|
|
658
|
+
item.processed = true;
|
|
659
|
+
} else {
|
|
660
|
+
const otherParents = itemMap.get(String(parentKey)) || [];
|
|
661
|
+
if (otherParents.length > 0) {
|
|
662
|
+
const parent = otherParents[0];
|
|
663
|
+
item.level = parent.level + 1;
|
|
664
|
+
parent.children.push(item);
|
|
665
|
+
item.processed = true;
|
|
666
|
+
} else {
|
|
667
|
+
rootItems.push(item);
|
|
668
|
+
item.processed = true;
|
|
929
669
|
}
|
|
930
|
-
|
|
931
|
-
|
|
670
|
+
}
|
|
671
|
+
});
|
|
672
|
+
return rootItems;
|
|
673
|
+
}, [enabled, data, toggleField, childField, flattenField]);
|
|
674
|
+
const flattenTree = useMemo(() => {
|
|
675
|
+
if (!enabled) return [];
|
|
676
|
+
const flatten = (nodes, result = [], level = 0) => {
|
|
677
|
+
nodes.forEach((node, index) => {
|
|
678
|
+
const currentIndex = level === 0 ? `${index + startIndex}` : `${level}-${index + 1}`;
|
|
679
|
+
const toggleValue = getFieldValue(node, toggleField);
|
|
680
|
+
const uniqueId = `${index}-${String(toggleValue ?? "")}`;
|
|
681
|
+
result.push({
|
|
682
|
+
...node,
|
|
683
|
+
treeNo: currentIndex,
|
|
684
|
+
uniqueId,
|
|
685
|
+
processed: true
|
|
686
|
+
});
|
|
687
|
+
const shouldExpandChildren = node.children.length > 0 && (preventExpand || typeof toggleValue === "string" && expandedRows?.has(toggleValue));
|
|
688
|
+
if (shouldExpandChildren) {
|
|
689
|
+
flatten(node.children, result, index + startIndex);
|
|
932
690
|
}
|
|
933
|
-
return prev;
|
|
934
691
|
});
|
|
692
|
+
return result;
|
|
935
693
|
};
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
}
|
|
694
|
+
const flattenedData = flatten(processedData, [], 0);
|
|
695
|
+
flattenedData.forEach((item) => {
|
|
696
|
+
if (getFieldValue(item, childField)) {
|
|
697
|
+
const parentItem = flattenedData.find(
|
|
698
|
+
(parent) => getFieldValue(parent, toggleField) === getFieldValue(item, childField)
|
|
699
|
+
);
|
|
700
|
+
const parentAmount = parentItem ? Number(getFieldValue(parentItem, qtyField) ?? 1) : 1;
|
|
701
|
+
item.parentCount = parentAmount || 1;
|
|
702
|
+
} else {
|
|
703
|
+
item.parentCount = 1;
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
return flattenedData;
|
|
707
|
+
}, [
|
|
708
|
+
enabled,
|
|
709
|
+
processedData,
|
|
710
|
+
startIndex,
|
|
711
|
+
toggleField,
|
|
712
|
+
childField,
|
|
713
|
+
qtyField,
|
|
714
|
+
preventExpand,
|
|
715
|
+
expandedRows
|
|
716
|
+
]);
|
|
717
|
+
const sortedData = useMemo(() => {
|
|
718
|
+
if (!enabled) {
|
|
719
|
+
return data ?? [];
|
|
720
|
+
}
|
|
721
|
+
return [...flattenTree].sort((a, b) => {
|
|
722
|
+
const aParts = String(a.treeNo ?? "").split("-").map(Number);
|
|
723
|
+
const bParts = String(b.treeNo ?? "").split("-").map(Number);
|
|
724
|
+
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
725
|
+
const aVal = aParts[i] || 0;
|
|
726
|
+
const bVal = bParts[i] || 0;
|
|
727
|
+
if (aVal !== bVal) {
|
|
728
|
+
return aVal - bVal;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
return 0;
|
|
732
|
+
});
|
|
733
|
+
}, [enabled, data, flattenTree]);
|
|
734
|
+
return sortedData;
|
|
735
|
+
};
|
|
947
736
|
|
|
948
737
|
// src/components/ui/table/features/row-selection/rowSelection.ts
|
|
949
738
|
function resolveRowSelection(mode, controlledSelection, internalSelection) {
|
|
@@ -986,6 +775,22 @@ function computeRowSpans(data, rowSpanKey) {
|
|
|
986
775
|
}
|
|
987
776
|
return result;
|
|
988
777
|
}
|
|
778
|
+
function resolveRowSpanAt(rowSpans, rowIndex) {
|
|
779
|
+
if (!rowSpans?.[rowIndex]) {
|
|
780
|
+
return { startRow: rowIndex, rowSpan: 1 };
|
|
781
|
+
}
|
|
782
|
+
const current = rowSpans[rowIndex];
|
|
783
|
+
if (current.rowSpan > 0) {
|
|
784
|
+
return { startRow: rowIndex, rowSpan: current.rowSpan };
|
|
785
|
+
}
|
|
786
|
+
for (let row = rowIndex - 1; row >= 0; row--) {
|
|
787
|
+
const info = rowSpans[row];
|
|
788
|
+
if (info && info.rowSpan > 0) {
|
|
789
|
+
return { startRow: row, rowSpan: info.rowSpan };
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
return { startRow: rowIndex, rowSpan: 1 };
|
|
793
|
+
}
|
|
989
794
|
function buildColumnRowSpanMap(data, columnKeys) {
|
|
990
795
|
const map = /* @__PURE__ */ new Map();
|
|
991
796
|
for (const { columnId, rowSpanKey } of columnKeys) {
|
|
@@ -1013,51 +818,62 @@ function collectRowSpanColumns(columns) {
|
|
|
1013
818
|
return result;
|
|
1014
819
|
}
|
|
1015
820
|
|
|
1016
|
-
// src/
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
}
|
|
821
|
+
// src/core/useGlideTable.ts
|
|
822
|
+
function useGlideTable(options) {
|
|
823
|
+
const {
|
|
824
|
+
data,
|
|
825
|
+
columns,
|
|
826
|
+
rowSelectionMode = "none",
|
|
827
|
+
rowSelection: controlledRowSelection,
|
|
828
|
+
onRowSelectionChange,
|
|
829
|
+
selectionLabel,
|
|
830
|
+
emptyText,
|
|
831
|
+
loadingText,
|
|
832
|
+
labels: labelsProp,
|
|
833
|
+
enableRowSpan = false,
|
|
834
|
+
getRowId,
|
|
835
|
+
onRowClick,
|
|
836
|
+
getRowClassName,
|
|
837
|
+
getRowCanSelect,
|
|
838
|
+
selectOnRowClick = true,
|
|
839
|
+
enableCellSelection = true,
|
|
840
|
+
onDataChange,
|
|
841
|
+
onCellChange,
|
|
842
|
+
onBatchChange,
|
|
843
|
+
preserveRowSelection = false,
|
|
844
|
+
toggleField,
|
|
845
|
+
childField,
|
|
846
|
+
flattenField,
|
|
847
|
+
qtyField,
|
|
848
|
+
expandedRows: controlledExpandedRows,
|
|
849
|
+
onExpandedRowsChange,
|
|
850
|
+
preventExpand = false,
|
|
851
|
+
enableVirtualization = true,
|
|
852
|
+
estimateRowHeight = DATA_TABLE_ROW_HEIGHT,
|
|
853
|
+
virtualOverscan = DATA_TABLE_VIRTUAL_OVERSCAN
|
|
854
|
+
} = options;
|
|
855
|
+
const labels = useMemo2(() => {
|
|
856
|
+
const resolved = resolveDataTableLabels(labelsProp);
|
|
857
|
+
return {
|
|
858
|
+
...resolved,
|
|
859
|
+
empty: labelsProp?.empty ?? emptyText ?? resolved.empty,
|
|
860
|
+
loading: labelsProp?.loading ?? loadingText ?? resolved.loading,
|
|
861
|
+
selection: labelsProp?.selection ?? selectionLabel ?? resolved.selection
|
|
862
|
+
};
|
|
863
|
+
}, [labelsProp, emptyText, loadingText, selectionLabel]);
|
|
1050
864
|
const enableExpand = Boolean(toggleField);
|
|
1051
865
|
const [internalRowSelection, setInternalRowSelection] = useState3({});
|
|
1052
|
-
const [internalExpandedRows, setInternalExpandedRows] = useState3(
|
|
866
|
+
const [internalExpandedRows, setInternalExpandedRows] = useState3(
|
|
867
|
+
() => /* @__PURE__ */ new Set()
|
|
868
|
+
);
|
|
1053
869
|
const [hoveredRowIndex, setHoveredRowIndex] = useState3(null);
|
|
1054
870
|
const [hoveredGroupKey, setHoveredGroupKey] = useState3(null);
|
|
1055
|
-
const scrollRef =
|
|
871
|
+
const scrollRef = useRef3(null);
|
|
1056
872
|
const shouldVirtualize = enableVirtualization && !enableRowSpan;
|
|
1057
|
-
|
|
873
|
+
useEffect4(() => {
|
|
1058
874
|
if (enableVirtualization && enableRowSpan) {
|
|
1059
875
|
console.warn(
|
|
1060
|
-
"[
|
|
876
|
+
"[useGlideTable] enableRowSpan is on; virtualization is disabled to preserve cell merges."
|
|
1061
877
|
);
|
|
1062
878
|
}
|
|
1063
879
|
}, [enableVirtualization, enableRowSpan]);
|
|
@@ -1083,6 +899,7 @@ function DataTable({
|
|
|
1083
899
|
toggleField,
|
|
1084
900
|
childField,
|
|
1085
901
|
flattenField,
|
|
902
|
+
qtyField,
|
|
1086
903
|
expandedRows,
|
|
1087
904
|
onExpandedRowsChange: enableExpand ? handleExpandedRowsChange : void 0,
|
|
1088
905
|
preventExpand
|
|
@@ -1147,10 +964,21 @@ function DataTable({
|
|
|
1147
964
|
handleCellMouseDown,
|
|
1148
965
|
handleCellMouseEnter,
|
|
1149
966
|
handleFillHandleMouseDown
|
|
1150
|
-
} = useCellSelection({
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
967
|
+
} = useCellSelection({
|
|
968
|
+
data: tableData,
|
|
969
|
+
rows,
|
|
970
|
+
enabled: enableCellSelection,
|
|
971
|
+
onDataChange,
|
|
972
|
+
onBatchChange
|
|
973
|
+
});
|
|
974
|
+
const {
|
|
975
|
+
editingCell,
|
|
976
|
+
draftValue,
|
|
977
|
+
setDraftValue,
|
|
978
|
+
startEdit,
|
|
979
|
+
commitEdit,
|
|
980
|
+
cancelEdit
|
|
981
|
+
} = useCellEdit({ data: tableData, rows, onDataChange, onCellChange });
|
|
1154
982
|
const handleCellMouseDownWithCommit = useCallback3(
|
|
1155
983
|
(rowIndex, colIndex) => {
|
|
1156
984
|
const isSameEditingCell = editingCell?.rowIndex === rowIndex && editingCell?.colIndex === colIndex;
|
|
@@ -1161,10 +989,10 @@ function DataTable({
|
|
|
1161
989
|
},
|
|
1162
990
|
[commitEdit, editingCell, handleCellMouseDown]
|
|
1163
991
|
);
|
|
1164
|
-
const clearHover = () => {
|
|
992
|
+
const clearHover = useCallback3(() => {
|
|
1165
993
|
setHoveredRowIndex(null);
|
|
1166
994
|
setHoveredGroupKey(null);
|
|
1167
|
-
};
|
|
995
|
+
}, []);
|
|
1168
996
|
const handleRowHover = useCallback3(
|
|
1169
997
|
(rowIndex, rowData) => {
|
|
1170
998
|
setHoveredRowIndex(rowIndex);
|
|
@@ -1214,6 +1042,7 @@ function DataTable({
|
|
|
1214
1042
|
getRowClassName
|
|
1215
1043
|
},
|
|
1216
1044
|
cellSelection: {
|
|
1045
|
+
enableCellSelection,
|
|
1217
1046
|
activeSelectionBounds,
|
|
1218
1047
|
dragState,
|
|
1219
1048
|
onCellMouseDown: handleCellMouseDownWithCommit,
|
|
@@ -1233,7 +1062,9 @@ function DataTable({
|
|
|
1233
1062
|
toggleField,
|
|
1234
1063
|
expandedRows,
|
|
1235
1064
|
preventExpand,
|
|
1236
|
-
onToggleExpand: handleToggleExpand
|
|
1065
|
+
onToggleExpand: handleToggleExpand,
|
|
1066
|
+
expandRowLabel: labels.expandRow,
|
|
1067
|
+
collapseRowLabel: labels.collapseRow
|
|
1237
1068
|
}
|
|
1238
1069
|
};
|
|
1239
1070
|
}, [
|
|
@@ -1248,6 +1079,7 @@ function DataTable({
|
|
|
1248
1079
|
selectOnRowClick,
|
|
1249
1080
|
onRowClick,
|
|
1250
1081
|
getRowClassName,
|
|
1082
|
+
enableCellSelection,
|
|
1251
1083
|
activeSelectionBounds,
|
|
1252
1084
|
dragState,
|
|
1253
1085
|
handleCellMouseDownWithCommit,
|
|
@@ -1263,404 +1095,60 @@ function DataTable({
|
|
|
1263
1095
|
toggleField,
|
|
1264
1096
|
expandedRows,
|
|
1265
1097
|
preventExpand,
|
|
1266
|
-
handleToggleExpand
|
|
1098
|
+
handleToggleExpand,
|
|
1099
|
+
labels.expandRow,
|
|
1100
|
+
labels.collapseRow
|
|
1267
1101
|
]);
|
|
1268
|
-
if (isPending) {
|
|
1269
|
-
return /* @__PURE__ */ jsx5("div", { className: cn("DataTableJSX", "DataTableJSX--pending", className), children: /* @__PURE__ */ jsx5("span", { className: "data-table-loading-text", children: "\uB85C\uB529 \uC911..." }) });
|
|
1270
|
-
}
|
|
1271
|
-
return /* @__PURE__ */ jsxs4("div", { className: cn("DataTableJSX", className), children: [
|
|
1272
|
-
/* @__PURE__ */ jsx5(
|
|
1273
|
-
DataTableToolbar,
|
|
1274
|
-
{
|
|
1275
|
-
filteredCount: filteredCount ?? tableData.length,
|
|
1276
|
-
totalCount,
|
|
1277
|
-
summary,
|
|
1278
|
-
selectedCount,
|
|
1279
|
-
selectionLabel,
|
|
1280
|
-
toolbar
|
|
1281
|
-
}
|
|
1282
|
-
),
|
|
1283
|
-
/* @__PURE__ */ jsx5("div", { ref: scrollRef, className: "data-table-scroll", children: /* @__PURE__ */ jsxs4(
|
|
1284
|
-
"table",
|
|
1285
|
-
{
|
|
1286
|
-
className: "data-table",
|
|
1287
|
-
onDragStart: (event) => event.preventDefault(),
|
|
1288
|
-
children: [
|
|
1289
|
-
/* @__PURE__ */ jsx5("thead", { className: "data-table-head", children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx5("tr", { className: "data-table-head-row", children: headerGroup.headers.map((header) => {
|
|
1290
|
-
const align = header.column.columnDef.meta?.align ?? "center";
|
|
1291
|
-
const headerClassName = header.column.columnDef.meta?.headerClassName;
|
|
1292
|
-
return /* @__PURE__ */ jsx5(
|
|
1293
|
-
"th",
|
|
1294
|
-
{
|
|
1295
|
-
style: { width: header.getSize() !== 150 ? header.getSize() : void 0 },
|
|
1296
|
-
className: cn(
|
|
1297
|
-
"data-table-head-cell",
|
|
1298
|
-
CELL_ALIGN_CLASS[align],
|
|
1299
|
-
headerClassName
|
|
1300
|
-
),
|
|
1301
|
-
children: header.isPlaceholder ? null : flexRender2(header.column.columnDef.header, header.getContext())
|
|
1302
|
-
},
|
|
1303
|
-
header.id
|
|
1304
|
-
);
|
|
1305
|
-
}) }, headerGroup.id)) }),
|
|
1306
|
-
/* @__PURE__ */ jsx5(DataTableContextProvider, { value: rowContextValue, children: /* @__PURE__ */ jsx5("tbody", { onMouseLeave: clearHover, className: "data-table-body", children: rows.length === 0 ? /* @__PURE__ */ jsx5("tr", { children: /* @__PURE__ */ jsx5("td", { colSpan: columnCount, className: "data-table-empty-cell", children: emptyText }) }) : shouldVirtualize ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1307
|
-
paddingTop > 0 && /* @__PURE__ */ jsx5("tr", { "aria-hidden": true, className: "data-table-virtual-spacer", children: /* @__PURE__ */ jsx5(
|
|
1308
|
-
"td",
|
|
1309
|
-
{
|
|
1310
|
-
colSpan: columnCount,
|
|
1311
|
-
style: { height: paddingTop },
|
|
1312
|
-
className: "data-table-virtual-spacer-cell"
|
|
1313
|
-
}
|
|
1314
|
-
) }),
|
|
1315
|
-
virtualRows.map((virtualRow) => {
|
|
1316
|
-
const row = rows[virtualRow.index];
|
|
1317
|
-
if (!row) return null;
|
|
1318
|
-
return /* @__PURE__ */ jsx5(
|
|
1319
|
-
DataTableRow,
|
|
1320
|
-
{
|
|
1321
|
-
row,
|
|
1322
|
-
virtualIndex: virtualRow.index,
|
|
1323
|
-
measureElement: rowVirtualizer.measureElement,
|
|
1324
|
-
onToggleSelect: () => handleToggleSelect(row)
|
|
1325
|
-
},
|
|
1326
|
-
row.id
|
|
1327
|
-
);
|
|
1328
|
-
}),
|
|
1329
|
-
paddingBottom > 0 && /* @__PURE__ */ jsx5("tr", { "aria-hidden": true, className: "data-table-virtual-spacer", children: /* @__PURE__ */ jsx5(
|
|
1330
|
-
"td",
|
|
1331
|
-
{
|
|
1332
|
-
colSpan: columnCount,
|
|
1333
|
-
style: { height: paddingBottom },
|
|
1334
|
-
className: "data-table-virtual-spacer-cell"
|
|
1335
|
-
}
|
|
1336
|
-
) })
|
|
1337
|
-
] }) : rows.map((row) => /* @__PURE__ */ jsx5(
|
|
1338
|
-
DataTableRow,
|
|
1339
|
-
{
|
|
1340
|
-
row,
|
|
1341
|
-
onToggleSelect: () => handleToggleSelect(row)
|
|
1342
|
-
},
|
|
1343
|
-
row.id
|
|
1344
|
-
)) }) })
|
|
1345
|
-
]
|
|
1346
|
-
}
|
|
1347
|
-
) })
|
|
1348
|
-
] });
|
|
1349
|
-
}
|
|
1350
|
-
|
|
1351
|
-
// src/components/ui/table/components/Table/Table.tsx
|
|
1352
|
-
import { useCallback as useCallback4, useMemo as useMemo3, useState as useState4 } from "react";
|
|
1353
|
-
|
|
1354
|
-
// src/components/ui/table/components/Table/buildColumnDef.tsx
|
|
1355
|
-
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1356
|
-
function SortableHeader({
|
|
1357
|
-
label,
|
|
1358
|
-
field,
|
|
1359
|
-
sort,
|
|
1360
|
-
onSort
|
|
1361
|
-
}) {
|
|
1362
|
-
const isActive = sort?.field === field;
|
|
1363
|
-
const Icon = isActive ? sort.direction === "asc" ? ArrowUp : ArrowDown : ArrowUpDown;
|
|
1364
|
-
return /* @__PURE__ */ jsxs5(
|
|
1365
|
-
"button",
|
|
1366
|
-
{
|
|
1367
|
-
type: "button",
|
|
1368
|
-
className: cn("SortableHeaderJSX", isActive ? "is-active" : "is-inactive"),
|
|
1369
|
-
onClick: () => onSort(field),
|
|
1370
|
-
children: [
|
|
1371
|
-
/* @__PURE__ */ jsx6("span", { children: label }),
|
|
1372
|
-
/* @__PURE__ */ jsx6(Icon, { className: "sortable-header-icon" })
|
|
1373
|
-
]
|
|
1374
|
-
}
|
|
1375
|
-
);
|
|
1376
|
-
}
|
|
1377
|
-
function buildColumnDef(props, sort, onSort) {
|
|
1378
|
-
const {
|
|
1379
|
-
field,
|
|
1380
|
-
virtual = false,
|
|
1381
|
-
children,
|
|
1382
|
-
sortable = false,
|
|
1383
|
-
width,
|
|
1384
|
-
align,
|
|
1385
|
-
rowSpan,
|
|
1386
|
-
rowSpanKey,
|
|
1387
|
-
editable,
|
|
1388
|
-
editType,
|
|
1389
|
-
className,
|
|
1390
|
-
headerClassName,
|
|
1391
|
-
render
|
|
1392
|
-
} = props;
|
|
1393
1102
|
return {
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
editable,
|
|
1414
|
-
editType,
|
|
1415
|
-
className,
|
|
1416
|
-
headerClassName
|
|
1417
|
-
}
|
|
1418
|
-
};
|
|
1419
|
-
}
|
|
1420
|
-
|
|
1421
|
-
// src/components/ui/table/components/Table/parseTableChildren.ts
|
|
1422
|
-
import { Children } from "react";
|
|
1423
|
-
|
|
1424
|
-
// src/components/ui/table/components/Table/tableChildTypes.ts
|
|
1425
|
-
import { isValidElement } from "react";
|
|
1426
|
-
var TABLE_HEADER_DISPLAY_NAME = "Table.Header";
|
|
1427
|
-
var TABLE_BODY_DISPLAY_NAME = "Table.Body";
|
|
1428
|
-
var TABLE_COLUMN_DISPLAY_NAME = "Table.Column";
|
|
1429
|
-
var TABLE_PAGINATION_DISPLAY_NAME = "Table.Pagination";
|
|
1430
|
-
function getComponentDisplayName(type) {
|
|
1431
|
-
if (typeof type === "function" || typeof type === "object" && type !== null) {
|
|
1432
|
-
return type.displayName;
|
|
1433
|
-
}
|
|
1434
|
-
return void 0;
|
|
1435
|
-
}
|
|
1436
|
-
function isTableHeaderElement(child) {
|
|
1437
|
-
return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
|
|
1438
|
-
}
|
|
1439
|
-
function isTableBodyElement(child) {
|
|
1440
|
-
return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
|
|
1441
|
-
}
|
|
1442
|
-
function isTableColumnElement(child) {
|
|
1443
|
-
return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
|
|
1444
|
-
}
|
|
1445
|
-
function isTablePaginationElement(child) {
|
|
1446
|
-
return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
|
|
1447
|
-
}
|
|
1448
|
-
|
|
1449
|
-
// src/components/ui/table/components/Table/parseTableChildren.ts
|
|
1450
|
-
function parseTableChildren(children) {
|
|
1451
|
-
const slots = {
|
|
1452
|
-
header: null,
|
|
1453
|
-
body: null,
|
|
1454
|
-
pagination: null
|
|
1103
|
+
table,
|
|
1104
|
+
tableData,
|
|
1105
|
+
rows,
|
|
1106
|
+
columnCount,
|
|
1107
|
+
selectedCount,
|
|
1108
|
+
labels,
|
|
1109
|
+
emptyText: labels.empty,
|
|
1110
|
+
loadingText: labels.loading,
|
|
1111
|
+
selectionLabel: labels.selection,
|
|
1112
|
+
enableCellSelection,
|
|
1113
|
+
shouldVirtualize,
|
|
1114
|
+
scrollRef,
|
|
1115
|
+
rowVirtualizer,
|
|
1116
|
+
virtualRows,
|
|
1117
|
+
paddingTop,
|
|
1118
|
+
paddingBottom,
|
|
1119
|
+
rowContextValue,
|
|
1120
|
+
handleToggleSelect,
|
|
1121
|
+
clearHover
|
|
1455
1122
|
};
|
|
1456
|
-
for (const child of Children.toArray(children)) {
|
|
1457
|
-
if (isTableHeaderElement(child)) {
|
|
1458
|
-
slots.header = child;
|
|
1459
|
-
continue;
|
|
1460
|
-
}
|
|
1461
|
-
if (isTableBodyElement(child)) {
|
|
1462
|
-
slots.body = child;
|
|
1463
|
-
continue;
|
|
1464
|
-
}
|
|
1465
|
-
if (isTablePaginationElement(child)) {
|
|
1466
|
-
slots.pagination = child;
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
|
-
return slots;
|
|
1470
|
-
}
|
|
1471
|
-
function extractColumnElements(header) {
|
|
1472
|
-
if (!header) return [];
|
|
1473
|
-
const { children } = header.props;
|
|
1474
|
-
return Children.toArray(children).filter(isTableColumnElement);
|
|
1475
|
-
}
|
|
1476
|
-
|
|
1477
|
-
// src/components/ui/table/components/Table/TableBody.tsx
|
|
1478
|
-
function TableBody() {
|
|
1479
|
-
return null;
|
|
1480
|
-
}
|
|
1481
|
-
TableBody.displayName = TABLE_BODY_DISPLAY_NAME;
|
|
1482
|
-
|
|
1483
|
-
// src/components/ui/table/components/Table/TableColumn.tsx
|
|
1484
|
-
function TableColumn(props) {
|
|
1485
|
-
void props;
|
|
1486
|
-
return null;
|
|
1487
|
-
}
|
|
1488
|
-
TableColumn.displayName = TABLE_COLUMN_DISPLAY_NAME;
|
|
1489
|
-
|
|
1490
|
-
// src/components/ui/table/components/Table/tableDataPipeline.ts
|
|
1491
|
-
function sortTableData(data, sort) {
|
|
1492
|
-
if (!sort) return data;
|
|
1493
|
-
const { field, direction } = sort;
|
|
1494
|
-
const multiplier = direction === "asc" ? 1 : -1;
|
|
1495
|
-
return [...data].sort((left, right) => {
|
|
1496
|
-
const leftValue = left[field];
|
|
1497
|
-
const rightValue = right[field];
|
|
1498
|
-
if ((leftValue === null || leftValue === void 0) && (rightValue === null || rightValue === void 0)) {
|
|
1499
|
-
return 0;
|
|
1500
|
-
}
|
|
1501
|
-
if (leftValue === null || leftValue === void 0) return 1;
|
|
1502
|
-
if (rightValue === null || rightValue === void 0) return -1;
|
|
1503
|
-
if (typeof leftValue === "number" && typeof rightValue === "number") {
|
|
1504
|
-
return (leftValue - rightValue) * multiplier;
|
|
1505
|
-
}
|
|
1506
|
-
return String(leftValue).localeCompare(String(rightValue), "ko") * multiplier;
|
|
1507
|
-
});
|
|
1508
|
-
}
|
|
1509
|
-
function paginateTableData(data, page, pageSize) {
|
|
1510
|
-
const safePage = Math.max(1, page);
|
|
1511
|
-
const start = (safePage - 1) * pageSize;
|
|
1512
|
-
return data.slice(start, start + pageSize);
|
|
1513
|
-
}
|
|
1514
|
-
function getTotalPages(totalCount, pageSize) {
|
|
1515
|
-
if (pageSize <= 0) return 1;
|
|
1516
|
-
return Math.max(1, Math.ceil(totalCount / pageSize));
|
|
1517
|
-
}
|
|
1518
|
-
|
|
1519
|
-
// src/components/ui/table/components/Table/TableHeader.tsx
|
|
1520
|
-
function TableHeader(props) {
|
|
1521
|
-
void props;
|
|
1522
|
-
return null;
|
|
1523
|
-
}
|
|
1524
|
-
TableHeader.displayName = TABLE_HEADER_DISPLAY_NAME;
|
|
1525
|
-
|
|
1526
|
-
// src/components/ui/table/components/Table/TablePagination.tsx
|
|
1527
|
-
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1528
|
-
function TablePagination({
|
|
1529
|
-
page,
|
|
1530
|
-
pageSize = 10,
|
|
1531
|
-
totalCount = 0,
|
|
1532
|
-
onChange,
|
|
1533
|
-
className
|
|
1534
|
-
}) {
|
|
1535
|
-
const totalPages = getTotalPages(totalCount, pageSize);
|
|
1536
|
-
const safePage = Math.min(Math.max(1, page), totalPages);
|
|
1537
|
-
const canGoPrev = safePage > 1;
|
|
1538
|
-
const canGoNext = safePage < totalPages;
|
|
1539
|
-
return /* @__PURE__ */ jsxs6("div", { className: cn("TablePaginationJSX", className), children: [
|
|
1540
|
-
/* @__PURE__ */ jsx7(
|
|
1541
|
-
"button",
|
|
1542
|
-
{
|
|
1543
|
-
type: "button",
|
|
1544
|
-
className: "pagination-button",
|
|
1545
|
-
disabled: !canGoPrev,
|
|
1546
|
-
onClick: () => onChange(safePage - 1),
|
|
1547
|
-
"aria-label": "\uC774\uC804 \uD398\uC774\uC9C0",
|
|
1548
|
-
children: /* @__PURE__ */ jsx7(ChevronLeft, { className: "pagination-button-icon" })
|
|
1549
|
-
}
|
|
1550
|
-
),
|
|
1551
|
-
/* @__PURE__ */ jsxs6("span", { className: "pagination-label", children: [
|
|
1552
|
-
safePage,
|
|
1553
|
-
" / ",
|
|
1554
|
-
totalPages
|
|
1555
|
-
] }),
|
|
1556
|
-
/* @__PURE__ */ jsx7(
|
|
1557
|
-
"button",
|
|
1558
|
-
{
|
|
1559
|
-
type: "button",
|
|
1560
|
-
className: "pagination-button",
|
|
1561
|
-
disabled: !canGoNext,
|
|
1562
|
-
onClick: () => onChange(safePage + 1),
|
|
1563
|
-
"aria-label": "\uB2E4\uC74C \uD398\uC774\uC9C0",
|
|
1564
|
-
children: /* @__PURE__ */ jsx7(ChevronRight, { className: "pagination-button-icon" })
|
|
1565
|
-
}
|
|
1566
|
-
)
|
|
1567
|
-
] });
|
|
1568
|
-
}
|
|
1569
|
-
TablePagination.displayName = TABLE_PAGINATION_DISPLAY_NAME;
|
|
1570
|
-
|
|
1571
|
-
// src/components/ui/table/components/Table/Table.tsx
|
|
1572
|
-
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1573
|
-
function TableRoot({
|
|
1574
|
-
data,
|
|
1575
|
-
children,
|
|
1576
|
-
className,
|
|
1577
|
-
totalCount,
|
|
1578
|
-
filteredCount,
|
|
1579
|
-
...dataTableProps
|
|
1580
|
-
}) {
|
|
1581
|
-
const { header, pagination: paginationElement } = useMemo3(
|
|
1582
|
-
() => parseTableChildren(children),
|
|
1583
|
-
[children]
|
|
1584
|
-
);
|
|
1585
|
-
const [sort, setSort] = useState4(null);
|
|
1586
|
-
const handleSort = useCallback4((field) => {
|
|
1587
|
-
setSort((previous) => {
|
|
1588
|
-
if (previous?.field !== field) {
|
|
1589
|
-
return { field, direction: "asc" };
|
|
1590
|
-
}
|
|
1591
|
-
if (previous.direction === "asc") {
|
|
1592
|
-
return { field, direction: "desc" };
|
|
1593
|
-
}
|
|
1594
|
-
return null;
|
|
1595
|
-
});
|
|
1596
|
-
}, []);
|
|
1597
|
-
const columns = useMemo3(() => {
|
|
1598
|
-
return extractColumnElements(header).map(
|
|
1599
|
-
(columnElement) => buildColumnDef(columnElement.props, sort, handleSort)
|
|
1600
|
-
);
|
|
1601
|
-
}, [header, sort, handleSort]);
|
|
1602
|
-
const paginationProps = paginationElement?.props;
|
|
1603
|
-
const pageSize = paginationProps?.pageSize ?? 10;
|
|
1604
|
-
const page = paginationProps?.page ?? 1;
|
|
1605
|
-
const resolvedTotalCount = paginationProps?.totalCount ?? totalCount ?? data.length;
|
|
1606
|
-
const tableData = useMemo3(() => {
|
|
1607
|
-
const sortedData = sortTableData(data, sort);
|
|
1608
|
-
if (!paginationProps) return sortedData;
|
|
1609
|
-
return paginateTableData(sortedData, page, pageSize);
|
|
1610
|
-
}, [data, sort, paginationProps, page, pageSize]);
|
|
1611
|
-
if (columns.length === 0) {
|
|
1612
|
-
console.warn("[Table] Table.Header \uC548\uC5D0 Table.Column\uC744 \uD558\uB098 \uC774\uC0C1 \uC120\uC5B8\uD574 \uC8FC\uC138\uC694.");
|
|
1613
|
-
}
|
|
1614
|
-
return /* @__PURE__ */ jsxs7("div", { className: "TableJSX", children: [
|
|
1615
|
-
/* @__PURE__ */ jsx8(
|
|
1616
|
-
DataTable,
|
|
1617
|
-
{
|
|
1618
|
-
...dataTableProps,
|
|
1619
|
-
data: tableData,
|
|
1620
|
-
columns,
|
|
1621
|
-
totalCount: paginationProps ? resolvedTotalCount : totalCount,
|
|
1622
|
-
filteredCount: filteredCount ?? data.length,
|
|
1623
|
-
className: cn(className, paginationProps && "DataTableJSX--with-pagination")
|
|
1624
|
-
}
|
|
1625
|
-
),
|
|
1626
|
-
paginationProps && /* @__PURE__ */ jsx8(
|
|
1627
|
-
TablePagination,
|
|
1628
|
-
{
|
|
1629
|
-
page,
|
|
1630
|
-
pageSize,
|
|
1631
|
-
totalCount: resolvedTotalCount,
|
|
1632
|
-
onChange: paginationProps.onChange,
|
|
1633
|
-
className: paginationProps.className
|
|
1634
|
-
}
|
|
1635
|
-
)
|
|
1636
|
-
] });
|
|
1637
|
-
}
|
|
1638
|
-
function createTable() {
|
|
1639
|
-
function Column(props) {
|
|
1640
|
-
void props;
|
|
1641
|
-
return null;
|
|
1642
|
-
}
|
|
1643
|
-
Column.displayName = TABLE_COLUMN_DISPLAY_NAME;
|
|
1644
|
-
return Object.assign(
|
|
1645
|
-
function BoundTable(props) {
|
|
1646
|
-
return /* @__PURE__ */ jsx8(TableRoot, { ...props });
|
|
1647
|
-
},
|
|
1648
|
-
{
|
|
1649
|
-
Header: TableHeader,
|
|
1650
|
-
Column,
|
|
1651
|
-
Body: TableBody,
|
|
1652
|
-
Pagination: TablePagination
|
|
1653
|
-
}
|
|
1654
|
-
);
|
|
1655
1123
|
}
|
|
1656
|
-
var Table = Object.assign(TableRoot, {
|
|
1657
|
-
Header: TableHeader,
|
|
1658
|
-
Column: TableColumn,
|
|
1659
|
-
Body: TableBody,
|
|
1660
|
-
Pagination: TablePagination
|
|
1661
|
-
});
|
|
1662
1124
|
export {
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1125
|
+
CELL_SELECTION_EDGES_CLASS,
|
|
1126
|
+
DEFAULT_DATA_TABLE_LABELS,
|
|
1127
|
+
DEFAULT_TREE_CHILDREN_FIELD,
|
|
1128
|
+
DEFAULT_TREE_ID_FIELD,
|
|
1129
|
+
DEFAULT_TREE_PARENT_ID_FIELD,
|
|
1130
|
+
DEFAULT_TREE_QTY_FIELD,
|
|
1131
|
+
applyCellEdit,
|
|
1132
|
+
applyFillData,
|
|
1133
|
+
applySelectionUpdater,
|
|
1134
|
+
buildColumnRowSpanMap,
|
|
1135
|
+
canExpandRow,
|
|
1136
|
+
collectFillChanges,
|
|
1137
|
+
collectRowSpanColumns,
|
|
1138
|
+
getCellEditDraftValue,
|
|
1139
|
+
getCellSelectionEdgeStyle,
|
|
1140
|
+
getColumnEditType,
|
|
1141
|
+
getRowIndexInMergedCell,
|
|
1142
|
+
hasCellSelectionEdges,
|
|
1143
|
+
isCellInSelection,
|
|
1144
|
+
isColumnEditable,
|
|
1145
|
+
parseCellEditValue,
|
|
1146
|
+
resolveDataTableLabels,
|
|
1147
|
+
resolveRowSelection,
|
|
1148
|
+
resolveRowSpanAt,
|
|
1149
|
+
toggleExpandedRowId,
|
|
1150
|
+
useCellEdit,
|
|
1151
|
+
useCellSelection,
|
|
1152
|
+
useConvertTreeData,
|
|
1153
|
+
useGlideTable
|
|
1666
1154
|
};
|