react-glide-table 1.0.2 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,15 +1,39 @@
1
- // src/components/ui/table/components/DataTable/DataTable.tsx
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 { useVirtualizer } from "@tanstack/react-virtual";
8
- import { useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo2, useRef as useRef4, useState as useState3 } from "react";
9
-
10
- // src/components/ui/table/components/DataTable/DataTableRow.tsx
11
- import { flexRender } from "@tanstack/react-table";
12
- import { useEffect as useEffect2, useRef as useRef2 } from "react";
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
39
  var CELL_ALIGN_CLASS = {
@@ -23,23 +47,8 @@ var CELL_SELECTION_FILL_CLASS = "cell-selection-fill";
23
47
  var DATA_TABLE_ROW_HEIGHT = 44;
24
48
  var DATA_TABLE_VIRTUAL_OVERSCAN = 8;
25
49
 
26
- // src/components/ui/table/DataTableContext.tsx
27
- import { createContext, use } from "react";
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
- }
50
+ // src/components/ui/table/features/cell-edit/useCellEdit.ts
51
+ import { useCallback, useEffect, useRef, useState } from "react";
43
52
 
44
53
  // src/components/ui/table/features/cell-edit/cellEdit.ts
45
54
  function getColumnAccessorKey(columnDef) {
@@ -87,6 +96,87 @@ function applyCellEdit(data, rows, rowIndex, colIndex, raw) {
87
96
  return newData;
88
97
  }
89
98
 
99
+ // src/components/ui/table/features/cell-edit/useCellEdit.ts
100
+ function useCellEdit({
101
+ data,
102
+ rows,
103
+ onDataChange,
104
+ onCellChange
105
+ }) {
106
+ const [editingCell, setEditingCell] = useState(null);
107
+ const [draftValue, setDraftValue] = useState("");
108
+ const draftValueRef = useRef(draftValue);
109
+ const editingCellRef = useRef(editingCell);
110
+ useEffect(() => {
111
+ draftValueRef.current = draftValue;
112
+ }, [draftValue]);
113
+ useEffect(() => {
114
+ editingCellRef.current = editingCell;
115
+ }, [editingCell]);
116
+ const cancelEdit = useCallback(() => {
117
+ setEditingCell(null);
118
+ setDraftValue("");
119
+ }, []);
120
+ const commitEdit = useCallback(
121
+ (raw) => {
122
+ const current = editingCellRef.current;
123
+ if (!current) return true;
124
+ if (!onCellChange && !onDataChange) {
125
+ cancelEdit();
126
+ return true;
127
+ }
128
+ const row = rows[current.rowIndex];
129
+ const cell = row?.getVisibleCells()[current.colIndex];
130
+ if (!row || !cell) {
131
+ cancelEdit();
132
+ return true;
133
+ }
134
+ const value = raw ?? draftValueRef.current;
135
+ if (!isColumnEditable(cell.column.columnDef)) {
136
+ cancelEdit();
137
+ return true;
138
+ }
139
+ const parsed = parseCellEditValue(value, getColumnEditType(cell.column.columnDef));
140
+ if (!parsed.ok) return false;
141
+ if (onCellChange) {
142
+ onCellChange(row.id, cell.column.id, parsed.value);
143
+ cancelEdit();
144
+ return true;
145
+ }
146
+ const next = applyCellEdit(data, rows, current.rowIndex, current.colIndex, value);
147
+ if (!next) return false;
148
+ onDataChange?.(next);
149
+ cancelEdit();
150
+ return true;
151
+ },
152
+ [cancelEdit, data, onCellChange, onDataChange, rows]
153
+ );
154
+ const startEdit = useCallback(
155
+ (rowIndex, colIndex) => {
156
+ const cell = rows[rowIndex]?.getVisibleCells()[colIndex];
157
+ if (!cell || !isColumnEditable(cell.column.columnDef)) return;
158
+ const current = editingCellRef.current;
159
+ if (current && (current.rowIndex !== rowIndex || current.colIndex !== colIndex) && !commitEdit()) {
160
+ return;
161
+ }
162
+ setEditingCell({ rowIndex, colIndex });
163
+ setDraftValue(getCellEditDraftValue(cell.getValue()));
164
+ },
165
+ [commitEdit, rows]
166
+ );
167
+ return {
168
+ editingCell,
169
+ draftValue,
170
+ setDraftValue,
171
+ startEdit,
172
+ commitEdit,
173
+ cancelEdit
174
+ };
175
+ }
176
+
177
+ // src/components/ui/table/features/cell-selection/useCellSelection.ts
178
+ import { useCallback as useCallback2, useEffect as useEffect2, useState as useState2 } from "react";
179
+
90
180
  // src/components/ui/table/features/cell-selection/cellSelection.ts
91
181
  var INITIAL_DRAG_STATE = {
92
182
  isSelecting: false,
@@ -110,7 +200,10 @@ function getRowIndexInMergedCell(clientY, cellElement, rowIndex, rowSpan) {
110
200
  const rect = cellElement.getBoundingClientRect();
111
201
  const relativeY = clientY - rect.top;
112
202
  const rowHeight = rect.height / rowSpan;
113
- const offset = Math.min(Math.max(Math.floor(relativeY / rowHeight), 0), rowSpan - 1);
203
+ const offset = Math.min(
204
+ Math.max(Math.floor(relativeY / rowHeight), 0),
205
+ rowSpan - 1
206
+ );
114
207
  return rowIndex + offset;
115
208
  }
116
209
  function isCellInSelection(rowIndex, colIndex, bounds, rowSpan = 1) {
@@ -126,31 +219,348 @@ function getActiveSelectionBounds(dragState, selectionBounds) {
126
219
  }
127
220
  var SELECTION_EDGE_WIDTH_PX = 2;
128
221
  var SELECTION_EDGE_COLOR = "var(--color-brand-primary)";
129
- function getCellSelectionEdgeStyle(rowIndex, colIndex, bounds, rowSpan = 1) {
130
- if (!isCellInSelection(rowIndex, colIndex, bounds, rowSpan) || !bounds) return void 0;
222
+ var CELL_SELECTION_EDGES_CLASS = "cell-selection-edges";
223
+ function getMergedCellStepEdges(rowIndex, colIndex, bounds, rowSpan, isVisuallySelectedAt) {
224
+ const cellEndRow = rowIndex + rowSpan - 1;
225
+ const span = cellEndRow - rowIndex + 1;
226
+ if (span <= 1) return [];
227
+ const edges = [];
228
+ const isNeighborSelected = (row, neighborCol) => {
229
+ if (isVisuallySelectedAt) {
230
+ return isVisuallySelectedAt(row, neighborCol);
231
+ }
232
+ return row >= bounds.startRow && row <= bounds.endRow && neighborCol >= bounds.startCol && neighborCol <= bounds.endCol;
233
+ };
234
+ const pushUnselectedRuns = (side, neighborCol, fromRow, toRowExclusive) => {
235
+ let runStart = null;
236
+ for (let row = fromRow; row < toRowExclusive; row++) {
237
+ if (!isNeighborSelected(row, neighborCol)) {
238
+ if (runStart === null) runStart = row;
239
+ continue;
240
+ }
241
+ if (runStart !== null) {
242
+ edges.push({
243
+ side,
244
+ offsetRatio: (runStart - rowIndex) / span,
245
+ heightRatio: (row - runStart) / span
246
+ });
247
+ runStart = null;
248
+ }
249
+ }
250
+ if (runStart !== null) {
251
+ edges.push({
252
+ side,
253
+ offsetRatio: (runStart - rowIndex) / span,
254
+ heightRatio: (toRowExclusive - runStart) / span
255
+ });
256
+ }
257
+ };
258
+ const collectSide = (side, neighborCol) => {
259
+ if (bounds.startRow > rowIndex) {
260
+ pushUnselectedRuns(
261
+ side,
262
+ neighborCol,
263
+ rowIndex,
264
+ Math.min(bounds.startRow, cellEndRow + 1)
265
+ );
266
+ }
267
+ if (bounds.endRow < cellEndRow) {
268
+ pushUnselectedRuns(
269
+ side,
270
+ neighborCol,
271
+ Math.max(bounds.endRow + 1, rowIndex),
272
+ cellEndRow + 1
273
+ );
274
+ }
275
+ };
276
+ if (colIndex < bounds.endCol) {
277
+ collectSide("right", colIndex + 1);
278
+ }
279
+ if (colIndex > bounds.startCol) {
280
+ collectSide("left", colIndex - 1);
281
+ }
282
+ return edges;
283
+ }
284
+ function buildPartialVerticalGradient(edge) {
285
+ const startPct = edge.offsetRatio * 100;
286
+ const endPct = (edge.offsetRatio + edge.heightRatio) * 100;
287
+ const overlapPx = SELECTION_EDGE_WIDTH_PX + 1;
288
+ const isTopProtrusion = edge.offsetRatio === 0 && edge.heightRatio < 1;
289
+ const isBottomProtrusion = edge.offsetRatio > 0;
290
+ const startStop = isBottomProtrusion ? `calc(${startPct}% - ${overlapPx}px)` : `${startPct}%`;
291
+ const endStop = isTopProtrusion ? `calc(${endPct}% + ${overlapPx}px)` : `${endPct}%`;
292
+ const xPos = edge.side === "left" ? "0" : "100%";
293
+ const layers = [
294
+ {
295
+ image: `linear-gradient(to bottom, transparent 0%, transparent ${startStop}, ${SELECTION_EDGE_COLOR} ${startStop}, ${SELECTION_EDGE_COLOR} ${endStop}, transparent ${endStop}, transparent 100%)`,
296
+ size: `${SELECTION_EDGE_WIDTH_PX}px 100%`,
297
+ position: `${xPos} 0`
298
+ }
299
+ ];
300
+ if (isTopProtrusion || isBottomProtrusion) {
301
+ const capTop = isTopProtrusion ? `calc(${endPct}% - ${SELECTION_EDGE_WIDTH_PX}px)` : `calc(${startPct}% - ${SELECTION_EDGE_WIDTH_PX}px)`;
302
+ layers.push({
303
+ image: `linear-gradient(${SELECTION_EDGE_COLOR}, ${SELECTION_EDGE_COLOR})`,
304
+ size: `${SELECTION_EDGE_WIDTH_PX}px ${SELECTION_EDGE_WIDTH_PX}px`,
305
+ position: `${xPos} ${capTop}`
306
+ });
307
+ }
308
+ return layers;
309
+ }
310
+ function getCellSelectionEdgeStyle(rowIndex, colIndex, bounds, rowSpan = 1, isVisuallySelectedAt) {
311
+ if (!isCellInSelection(rowIndex, colIndex, bounds, rowSpan) || !bounds)
312
+ return void 0;
131
313
  const cellEndRow = rowIndex + rowSpan - 1;
132
314
  const isTopEdge = bounds.startRow >= rowIndex && bounds.startRow <= cellEndRow;
133
315
  const isBottomEdge = bounds.endRow >= rowIndex && bounds.endRow <= cellEndRow;
134
316
  const isLeftEdge = colIndex === bounds.startCol;
135
317
  const isRightEdge = colIndex === bounds.endCol;
318
+ const selectionContinuesBelow = cellEndRow < bounds.endRow;
136
319
  const shadows = [];
137
320
  if (isTopEdge) {
138
- shadows.push(`inset 0 ${SELECTION_EDGE_WIDTH_PX}px 0 0 ${SELECTION_EDGE_COLOR}`);
321
+ shadows.push(
322
+ `inset 0 ${SELECTION_EDGE_WIDTH_PX}px 0 0 ${SELECTION_EDGE_COLOR}`
323
+ );
139
324
  }
140
325
  if (isBottomEdge) {
141
- shadows.push(`inset 0 -${SELECTION_EDGE_WIDTH_PX}px 0 0 ${SELECTION_EDGE_COLOR}`);
326
+ shadows.push(
327
+ `inset 0 -${SELECTION_EDGE_WIDTH_PX}px 0 0 ${SELECTION_EDGE_COLOR}`
328
+ );
142
329
  }
143
330
  if (isLeftEdge) {
144
- shadows.push(`inset ${SELECTION_EDGE_WIDTH_PX}px 0 0 0 ${SELECTION_EDGE_COLOR}`);
331
+ shadows.push(
332
+ `inset ${SELECTION_EDGE_WIDTH_PX}px 0 0 0 ${SELECTION_EDGE_COLOR}`
333
+ );
145
334
  }
146
335
  if (isRightEdge) {
147
- shadows.push(`inset -${SELECTION_EDGE_WIDTH_PX}px 0 0 0 ${SELECTION_EDGE_COLOR}`);
336
+ shadows.push(
337
+ `inset -${SELECTION_EDGE_WIDTH_PX}px 0 0 0 ${SELECTION_EDGE_COLOR}`
338
+ );
339
+ }
340
+ const stepEdges = getMergedCellStepEdges(
341
+ rowIndex,
342
+ colIndex,
343
+ bounds,
344
+ rowSpan,
345
+ isVisuallySelectedAt
346
+ );
347
+ const gradients = [];
348
+ const sizes = [];
349
+ const positions = [];
350
+ for (const edge of stepEdges) {
351
+ for (const partial of buildPartialVerticalGradient(edge)) {
352
+ gradients.push(partial.image);
353
+ sizes.push(partial.size);
354
+ positions.push(partial.position);
355
+ }
356
+ }
357
+ if (shadows.length === 0 && gradients.length === 0 && !selectionContinuesBelow) {
358
+ return void 0;
359
+ }
360
+ const style = {};
361
+ if (shadows.length > 0) {
362
+ style["--selection-edge-shadows"] = shadows.join(", ");
363
+ }
364
+ if (gradients.length > 0) {
365
+ style["--selection-edge-gradients"] = gradients.join(", ");
366
+ style["--selection-edge-sizes"] = sizes.join(", ");
367
+ style["--selection-edge-positions"] = positions.join(", ");
368
+ }
369
+ if (selectionContinuesBelow) {
370
+ style.borderBottomColor = "var(--color-brand-surface)";
371
+ }
372
+ return style;
373
+ }
374
+ function hasCellSelectionEdges(style) {
375
+ return Boolean(
376
+ style?.["--selection-edge-shadows"] || style?.["--selection-edge-gradients"]
377
+ );
378
+ }
379
+
380
+ // src/components/ui/table/features/cell-selection/fillData.ts
381
+ function getColumnAccessorKey2(columnDef) {
382
+ if ("accessorKey" in columnDef && columnDef.accessorKey) {
383
+ return String(columnDef.accessorKey);
384
+ }
385
+ return columnDef.id;
386
+ }
387
+ function collectFillTargets(rows, sourceBounds, fillBounds) {
388
+ const targets = [];
389
+ const sourceHeight = sourceBounds.endRow - sourceBounds.startRow + 1;
390
+ const sourceWidth = sourceBounds.endCol - sourceBounds.startCol + 1;
391
+ for (let rowIndex = fillBounds.startRow; rowIndex <= fillBounds.endRow; rowIndex += 1) {
392
+ for (let colIndex = fillBounds.startCol; colIndex <= fillBounds.endCol; colIndex += 1) {
393
+ if (isCellInSelection(rowIndex, colIndex, sourceBounds)) continue;
394
+ const offsetRow = rowIndex - sourceBounds.startRow;
395
+ const offsetCol = colIndex - sourceBounds.startCol;
396
+ const sourceRowIndex = sourceBounds.startRow + (offsetRow % sourceHeight + sourceHeight) % sourceHeight;
397
+ const sourceColIndex = sourceBounds.startCol + (offsetCol % sourceWidth + sourceWidth) % sourceWidth;
398
+ const targetRow = rows[rowIndex];
399
+ const targetCell = targetRow?.getVisibleCells()[colIndex];
400
+ const sourceCell = rows[sourceRowIndex]?.getVisibleCells()[sourceColIndex];
401
+ if (!targetRow || !targetCell || !sourceCell) continue;
402
+ const accessorKey = getColumnAccessorKey2(
403
+ targetCell.column.columnDef
404
+ );
405
+ if (!accessorKey) continue;
406
+ targets.push({
407
+ rowIndex,
408
+ accessorKey,
409
+ columnId: targetCell.column.id,
410
+ value: sourceCell.getValue(),
411
+ rowId: targetRow.id
412
+ });
413
+ }
414
+ }
415
+ return targets;
416
+ }
417
+ function collectFillChanges(rows, sourceBounds, fillBounds) {
418
+ return collectFillTargets(rows, sourceBounds, fillBounds).map(
419
+ ({ rowId, columnId, value }) => ({ rowId, columnId, value })
420
+ );
421
+ }
422
+ function applyFillData(data, rows, sourceBounds, fillBounds) {
423
+ const newData = data.map((row) => ({ ...row }));
424
+ const targets = collectFillTargets(rows, sourceBounds, fillBounds);
425
+ for (const target of targets) {
426
+ if (!newData[target.rowIndex]) continue;
427
+ newData[target.rowIndex][target.accessorKey] = target.value;
148
428
  }
149
- return shadows.length > 0 ? { boxShadow: shadows.join(", ") } : void 0;
429
+ return newData;
430
+ }
431
+ function hasFillExtension(sourceBounds, fillBounds) {
432
+ if (!sourceBounds) return false;
433
+ return fillBounds.startRow < sourceBounds.startRow || fillBounds.endRow > sourceBounds.endRow || fillBounds.startCol < sourceBounds.startCol || fillBounds.endCol > sourceBounds.endCol;
434
+ }
435
+
436
+ // src/components/ui/table/features/cell-selection/useCellSelection.ts
437
+ function useCellSelection({
438
+ data,
439
+ rows,
440
+ enabled = true,
441
+ onDataChange,
442
+ onBatchChange
443
+ }) {
444
+ const [dragState, setDragState] = useState2(INITIAL_DRAG_STATE);
445
+ const cellSelectionBounds = getCellSelectionBounds(dragState.start, dragState.end);
446
+ const activeSelectionBounds = enabled ? getActiveSelectionBounds(dragState, cellSelectionBounds) : null;
447
+ const handleCellMouseDown = useCallback2(
448
+ (rowIndex, colIndex) => {
449
+ if (!enabled) return;
450
+ setDragState({
451
+ isSelecting: true,
452
+ isFillDragging: false,
453
+ start: { row: rowIndex, col: colIndex },
454
+ end: { row: rowIndex, col: colIndex },
455
+ fillAnchor: null,
456
+ fillEnd: null
457
+ });
458
+ },
459
+ [enabled]
460
+ );
461
+ const handleCellMouseEnter = useCallback2(
462
+ (rowIndex, colIndex) => {
463
+ if (!enabled) return;
464
+ setDragState((prev) => {
465
+ if (prev.isSelecting) {
466
+ return { ...prev, end: { row: rowIndex, col: colIndex } };
467
+ }
468
+ if (prev.isFillDragging) {
469
+ return { ...prev, fillEnd: { row: rowIndex, col: colIndex } };
470
+ }
471
+ return prev;
472
+ });
473
+ },
474
+ [enabled]
475
+ );
476
+ const handleFillHandleMouseDown = useCallback2(
477
+ (rowIndex, colIndex) => {
478
+ if (!enabled) return;
479
+ setDragState((prev) => {
480
+ const bounds = getCellSelectionBounds(prev.start, prev.end);
481
+ if (!bounds) return prev;
482
+ return {
483
+ ...prev,
484
+ isSelecting: false,
485
+ isFillDragging: true,
486
+ fillAnchor: { row: bounds.startRow, col: bounds.startCol },
487
+ fillEnd: { row: rowIndex, col: colIndex }
488
+ };
489
+ });
490
+ },
491
+ [enabled]
492
+ );
493
+ useEffect2(() => {
494
+ if (!enabled) {
495
+ setDragState(INITIAL_DRAG_STATE);
496
+ }
497
+ }, [enabled]);
498
+ useEffect2(() => {
499
+ if (!enabled) return;
500
+ const handleKeyDown = (e) => {
501
+ if ((e.ctrlKey || e.metaKey) && e.key === "c" && activeSelectionBounds) {
502
+ const { startRow, endRow, startCol, endCol } = activeSelectionBounds;
503
+ const selectedData = rows.slice(startRow, endRow + 1).map((row) => {
504
+ const cells = row.getVisibleCells();
505
+ return cells.slice(startCol, endCol + 1).map((cell) => cell.getValue()).join(" ");
506
+ }).join("\n");
507
+ navigator.clipboard.writeText(selectedData);
508
+ }
509
+ };
510
+ window.addEventListener("keydown", handleKeyDown);
511
+ return () => window.removeEventListener("keydown", handleKeyDown);
512
+ }, [activeSelectionBounds, enabled, rows]);
513
+ useEffect2(() => {
514
+ if (!enabled) return;
515
+ const handleMouseUp = () => {
516
+ setDragState((prev) => {
517
+ if (prev.isFillDragging && prev.fillAnchor && prev.fillEnd) {
518
+ const sourceBounds = getCellSelectionBounds(prev.start, prev.end);
519
+ const newBounds = getCellSelectionBounds(prev.fillAnchor, prev.fillEnd);
520
+ if (newBounds) {
521
+ if (hasFillExtension(sourceBounds, newBounds) && sourceBounds) {
522
+ if (onBatchChange) {
523
+ const changes = collectFillChanges(rows, sourceBounds, newBounds);
524
+ if (changes.length > 0) {
525
+ onBatchChange(changes);
526
+ }
527
+ } else if (onDataChange) {
528
+ onDataChange(applyFillData(data, rows, sourceBounds, newBounds));
529
+ }
530
+ }
531
+ return {
532
+ isSelecting: false,
533
+ isFillDragging: false,
534
+ start: { row: newBounds.startRow, col: newBounds.startCol },
535
+ end: { row: newBounds.endRow, col: newBounds.endCol },
536
+ fillAnchor: null,
537
+ fillEnd: null
538
+ };
539
+ }
540
+ }
541
+ if (prev.isSelecting) {
542
+ return { ...prev, isSelecting: false };
543
+ }
544
+ if (prev.isFillDragging) {
545
+ return { ...prev, isFillDragging: false, fillAnchor: null, fillEnd: null };
546
+ }
547
+ return prev;
548
+ });
549
+ };
550
+ window.addEventListener("mouseup", handleMouseUp);
551
+ return () => window.removeEventListener("mouseup", handleMouseUp);
552
+ }, [data, enabled, onBatchChange, onDataChange, rows]);
553
+ return {
554
+ dragState: enabled ? dragState : INITIAL_DRAG_STATE,
555
+ activeSelectionBounds,
556
+ handleCellMouseDown,
557
+ handleCellMouseEnter,
558
+ handleFillHandleMouseDown
559
+ };
150
560
  }
151
561
 
152
562
  // src/components/ui/table/features/row-expand/row-expand.ts
153
- import { useEffect, useMemo, useRef } from "react";
563
+ import { useEffect as useEffect3, useMemo, useRef as useRef2 } from "react";
154
564
  function getFieldValue(row, key) {
155
565
  return row[key];
156
566
  }
@@ -171,20 +581,21 @@ function toggleExpandedRowId(rowId, previous) {
171
581
  var useConvertTreeData = ({
172
582
  data,
173
583
  enabled = true,
174
- toggleField = "materialCode",
175
- childField = "assemblyCode",
176
- flattenField = "assemblyMaterials",
584
+ toggleField = DEFAULT_TREE_ID_FIELD,
585
+ childField = DEFAULT_TREE_PARENT_ID_FIELD,
586
+ flattenField = DEFAULT_TREE_CHILDREN_FIELD,
587
+ qtyField = DEFAULT_TREE_QTY_FIELD,
177
588
  preventExpand = false,
178
589
  startIndex = 1,
179
590
  expandedRows,
180
591
  onExpandedRowsChange
181
592
  }) => {
182
- const onExpandedRowsChangeRef = useRef(onExpandedRowsChange);
183
- const hasInitializedRef = useRef(false);
184
- useEffect(() => {
593
+ const onExpandedRowsChangeRef = useRef2(onExpandedRowsChange);
594
+ const hasInitializedRef = useRef2(false);
595
+ useEffect3(() => {
185
596
  onExpandedRowsChangeRef.current = onExpandedRowsChange;
186
597
  }, [onExpandedRowsChange]);
187
- useEffect(() => {
598
+ useEffect3(() => {
188
599
  if (!data || data.length === 0) {
189
600
  hasInitializedRef.current = false;
190
601
  return;
@@ -294,14 +705,23 @@ var useConvertTreeData = ({
294
705
  const parentItem = flattenedData.find(
295
706
  (parent) => getFieldValue(parent, toggleField) === getFieldValue(item, childField)
296
707
  );
297
- const parentAmount = parentItem ? Number(getFieldValue(parentItem, "amount") ?? 1) : 1;
708
+ const parentAmount = parentItem ? Number(getFieldValue(parentItem, qtyField) ?? 1) : 1;
298
709
  item.parentCount = parentAmount || 1;
299
710
  } else {
300
711
  item.parentCount = 1;
301
712
  }
302
713
  });
303
714
  return flattenedData;
304
- }, [enabled, processedData, startIndex, toggleField, childField, preventExpand, expandedRows]);
715
+ }, [
716
+ enabled,
717
+ processedData,
718
+ startIndex,
719
+ toggleField,
720
+ childField,
721
+ qtyField,
722
+ preventExpand,
723
+ expandedRows
724
+ ]);
305
725
  const sortedData = useMemo(() => {
306
726
  if (!enabled) {
307
727
  return data ?? [];
@@ -322,185 +742,599 @@ var useConvertTreeData = ({
322
742
  return sortedData;
323
743
  };
324
744
 
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
- );
745
+ // src/components/ui/table/features/row-selection/rowSelection.ts
746
+ function resolveRowSelection(mode, controlledSelection, internalSelection) {
747
+ if (mode === "none") return {};
748
+ return controlledSelection ?? internalSelection;
344
749
  }
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
- );
750
+ function normalizeSingleSelection(next) {
751
+ const selectedIds = Object.keys(next).filter((id) => next[id]);
752
+ if (selectedIds.length <= 1) return next;
753
+ return { [selectedIds[selectedIds.length - 1]]: true };
362
754
  }
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
- );
755
+ function applySelectionUpdater(mode, updater, previous) {
756
+ const next = typeof updater === "function" ? updater(previous) : updater;
757
+ return mode === "single" ? normalizeSingleSelection(next) : next;
380
758
  }
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
- );
759
+
760
+ // src/components/ui/table/features/row-span/rowSpan.ts
761
+ function getRowFieldValue(row, key) {
762
+ return row[key];
398
763
  }
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
- ]
764
+ function computeRowSpans(data, rowSpanKey) {
765
+ if (data.length === 0) return [];
766
+ const result = [];
767
+ for (let index = 0; index < data.length; index++) {
768
+ const currentValue = getRowFieldValue(data[index], rowSpanKey);
769
+ const previousValue = index > 0 ? getRowFieldValue(data[index - 1], rowSpanKey) : void 0;
770
+ if (index > 0 && currentValue === previousValue) {
771
+ result.push({ rowSpan: 0, isFirstInGroup: false });
772
+ continue;
417
773
  }
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
- ]
774
+ let span = 1;
775
+ for (let nextIndex = index + 1; nextIndex < data.length; nextIndex++) {
776
+ if (getRowFieldValue(data[nextIndex], rowSpanKey) === currentValue) {
777
+ span++;
778
+ } else {
779
+ break;
780
+ }
438
781
  }
439
- );
782
+ result.push({ rowSpan: span, isFirstInGroup: true });
783
+ }
784
+ return result;
440
785
  }
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
- ]
786
+ function resolveRowSpanAt(rowSpans, rowIndex) {
787
+ if (!rowSpans?.[rowIndex]) {
788
+ return { startRow: rowIndex, rowSpan: 1 };
789
+ }
790
+ const current = rowSpans[rowIndex];
791
+ if (current.rowSpan > 0) {
792
+ return { startRow: rowIndex, rowSpan: current.rowSpan };
793
+ }
794
+ for (let row = rowIndex - 1; row >= 0; row--) {
795
+ const info = rowSpans[row];
796
+ if (info && info.rowSpan > 0) {
797
+ return { startRow: row, rowSpan: info.rowSpan };
461
798
  }
462
- );
799
+ }
800
+ return { startRow: rowIndex, rowSpan: 1 };
463
801
  }
464
-
465
- // src/lib/cn.ts
466
- function cn(...inputs) {
467
- return inputs.filter(Boolean).join(" ");
802
+ function buildColumnRowSpanMap(data, columnKeys) {
803
+ const map = /* @__PURE__ */ new Map();
804
+ for (const { columnId, rowSpanKey } of columnKeys) {
805
+ map.set(columnId, computeRowSpans(data, rowSpanKey));
806
+ }
807
+ return map;
808
+ }
809
+ function collectRowSpanColumns(columns) {
810
+ const result = [];
811
+ const visit = (defs) => {
812
+ for (const columnDef of defs) {
813
+ if ("columns" in columnDef && columnDef.columns?.length) {
814
+ visit(columnDef.columns);
815
+ continue;
816
+ }
817
+ const columnId = columnDef.id ?? ("accessorKey" in columnDef && columnDef.accessorKey ? String(columnDef.accessorKey) : void 0);
818
+ if (!columnId || !columnDef.meta?.rowSpan) continue;
819
+ result.push({
820
+ columnId,
821
+ rowSpanKey: columnDef.meta.rowSpanKey ?? columnId
822
+ });
823
+ }
824
+ };
825
+ visit(columns);
826
+ return result;
468
827
  }
469
828
 
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
829
+ // src/core/useGlideTable.ts
830
+ function useGlideTable(options) {
831
+ const {
832
+ data,
833
+ columns,
834
+ rowSelectionMode = "none",
835
+ rowSelection: controlledRowSelection,
836
+ onRowSelectionChange,
837
+ selectionLabel,
838
+ emptyText,
839
+ loadingText,
840
+ labels: labelsProp,
841
+ enableRowSpan = false,
842
+ getRowId,
843
+ onRowClick,
844
+ getRowClassName,
845
+ getRowCanSelect,
846
+ selectOnRowClick = true,
847
+ enableCellSelection = true,
848
+ onDataChange,
849
+ onCellChange,
850
+ onBatchChange,
851
+ preserveRowSelection = false,
852
+ toggleField,
853
+ childField,
854
+ flattenField,
855
+ qtyField,
856
+ expandedRows: controlledExpandedRows,
857
+ onExpandedRowsChange,
858
+ preventExpand = false,
859
+ enableVirtualization = true,
860
+ estimateRowHeight = DATA_TABLE_ROW_HEIGHT,
861
+ virtualOverscan = DATA_TABLE_VIRTUAL_OVERSCAN
862
+ } = options;
863
+ const labels = useMemo2(() => {
864
+ const resolved = resolveDataTableLabels(labelsProp);
865
+ return {
866
+ ...resolved,
867
+ empty: labelsProp?.empty ?? emptyText ?? resolved.empty,
868
+ loading: labelsProp?.loading ?? loadingText ?? resolved.loading,
869
+ selection: labelsProp?.selection ?? selectionLabel ?? resolved.selection
870
+ };
871
+ }, [labelsProp, emptyText, loadingText, selectionLabel]);
872
+ const enableExpand = Boolean(toggleField);
873
+ const [internalRowSelection, setInternalRowSelection] = useState3({});
874
+ const [internalExpandedRows, setInternalExpandedRows] = useState3(
875
+ () => /* @__PURE__ */ new Set()
476
876
  );
477
- if (matchedIndex >= 0) return matchedIndex;
478
- const noColumnIndex = cells.findIndex(
479
- (cell) => cell.column.id === "no" || cell.column.id === "treeNo"
877
+ const [hoveredRowIndex, setHoveredRowIndex] = useState3(null);
878
+ const [hoveredGroupKey, setHoveredGroupKey] = useState3(null);
879
+ const scrollRef = useRef3(null);
880
+ const shouldVirtualize = enableVirtualization && !enableRowSpan;
881
+ useEffect4(() => {
882
+ if (enableVirtualization && enableRowSpan) {
883
+ console.warn(
884
+ "[useGlideTable] enableRowSpan is on; virtualization is disabled to preserve cell merges."
885
+ );
886
+ }
887
+ }, [enableVirtualization, enableRowSpan]);
888
+ const rowSelection = resolveRowSelection(
889
+ rowSelectionMode,
890
+ controlledRowSelection,
891
+ internalRowSelection
480
892
  );
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,
893
+ const expandedRows = controlledExpandedRows ?? internalExpandedRows;
894
+ const handleExpandedRowsChange = useCallback3(
895
+ (next) => {
896
+ if (onExpandedRowsChange) {
897
+ onExpandedRowsChange(next);
898
+ return;
899
+ }
900
+ setInternalExpandedRows(next);
901
+ },
902
+ [onExpandedRowsChange]
903
+ );
904
+ const tableData = useConvertTreeData({
905
+ data,
906
+ enabled: enableExpand,
907
+ toggleField,
908
+ childField,
909
+ flattenField,
910
+ qtyField,
911
+ expandedRows,
912
+ onExpandedRowsChange: enableExpand ? handleExpandedRowsChange : void 0,
913
+ preventExpand
914
+ });
915
+ const table = useReactTable({
916
+ data: tableData,
917
+ columns,
918
+ state: {
919
+ rowSelection: rowSelectionMode === "none" ? {} : rowSelection
920
+ },
921
+ enableRowSelection: rowSelectionMode === "none" ? false : getRowCanSelect ? (row) => getRowCanSelect(row.original, row.index) : true,
922
+ enableMultiRowSelection: rowSelectionMode === "multi",
923
+ onRowSelectionChange: (updater) => {
924
+ if (onRowSelectionChange) {
925
+ onRowSelectionChange(
926
+ (previous) => applySelectionUpdater(rowSelectionMode, updater, previous)
927
+ );
928
+ return;
929
+ }
930
+ setInternalRowSelection(
931
+ (previous) => applySelectionUpdater(rowSelectionMode, updater, previous)
932
+ );
933
+ },
934
+ getCoreRowModel: getCoreRowModel(),
935
+ getRowId: getRowId ? (originalRow, index) => getRowId(originalRow, index) : (_originalRow, index) => String(index)
936
+ });
937
+ const rowSpanColumnKeys = useMemo2(() => {
938
+ if (!enableRowSpan) return [];
939
+ return collectRowSpanColumns(columns);
940
+ }, [enableRowSpan, columns]);
941
+ const primaryRowSpanKey = rowSpanColumnKeys[0]?.rowSpanKey;
942
+ const columnRowSpanMap = useMemo2(
943
+ () => buildColumnRowSpanMap(tableData, rowSpanColumnKeys),
944
+ [tableData, rowSpanColumnKeys]
945
+ );
946
+ const selectedRows = table.getSelectedRowModel().rows;
947
+ const selectedCount = selectedRows.length;
948
+ const rows = table.getRowModel().rows;
949
+ const columnCount = table.getAllLeafColumns().length || 1;
950
+ const rowVirtualizer = useVirtualizer({
951
+ count: shouldVirtualize ? rows.length : 0,
952
+ getScrollElement: () => scrollRef.current,
953
+ estimateSize: () => estimateRowHeight,
954
+ overscan: virtualOverscan
955
+ });
956
+ const virtualRows = rowVirtualizer.getVirtualItems();
957
+ const totalSize = rowVirtualizer.getTotalSize();
958
+ const paddingTop = virtualRows.length > 0 ? virtualRows[0]?.start ?? 0 : 0;
959
+ const paddingBottom = virtualRows.length > 0 ? totalSize - (virtualRows[virtualRows.length - 1]?.end ?? 0) : 0;
960
+ const selectedGroupKeys = useMemo2(() => {
961
+ if (!enableRowSpan || !primaryRowSpanKey) return /* @__PURE__ */ new Set();
962
+ const keys = /* @__PURE__ */ new Set();
963
+ for (const selectedRow of selectedRows) {
964
+ const value = selectedRow.original[primaryRowSpanKey];
965
+ if (value !== null && value !== void 0) keys.add(String(value));
966
+ }
967
+ return keys;
968
+ }, [enableRowSpan, primaryRowSpanKey, selectedRows]);
969
+ const {
970
+ dragState,
971
+ activeSelectionBounds,
972
+ handleCellMouseDown,
973
+ handleCellMouseEnter,
974
+ handleFillHandleMouseDown
975
+ } = useCellSelection({
976
+ data: tableData,
977
+ rows,
978
+ enabled: enableCellSelection,
979
+ onDataChange,
980
+ onBatchChange
981
+ });
982
+ const {
983
+ editingCell,
984
+ draftValue,
985
+ setDraftValue,
986
+ startEdit,
987
+ commitEdit,
988
+ cancelEdit
989
+ } = useCellEdit({ data: tableData, rows, onDataChange, onCellChange });
990
+ const handleCellMouseDownWithCommit = useCallback3(
991
+ (rowIndex, colIndex) => {
992
+ const isSameEditingCell = editingCell?.rowIndex === rowIndex && editingCell?.colIndex === colIndex;
993
+ if (editingCell && !isSameEditingCell && !commitEdit()) {
994
+ return;
995
+ }
996
+ handleCellMouseDown(rowIndex, colIndex);
997
+ },
998
+ [commitEdit, editingCell, handleCellMouseDown]
999
+ );
1000
+ const clearHover = useCallback3(() => {
1001
+ setHoveredRowIndex(null);
1002
+ setHoveredGroupKey(null);
1003
+ }, []);
1004
+ const handleRowHover = useCallback3(
1005
+ (rowIndex, rowData) => {
1006
+ setHoveredRowIndex(rowIndex);
1007
+ if (!primaryRowSpanKey) {
1008
+ setHoveredGroupKey(null);
1009
+ return;
1010
+ }
1011
+ const groupValue = rowData[primaryRowSpanKey];
1012
+ setHoveredGroupKey(
1013
+ groupValue === null || groupValue === void 0 ? null : String(groupValue)
1014
+ );
1015
+ },
1016
+ [primaryRowSpanKey]
1017
+ );
1018
+ const handleToggleSelect = useCallback3(
1019
+ (row) => {
1020
+ if (!row.getCanSelect()) return;
1021
+ if (preserveRowSelection && row.getIsSelected()) {
1022
+ return;
1023
+ }
1024
+ row.toggleSelected();
1025
+ },
1026
+ [preserveRowSelection]
1027
+ );
1028
+ const handleToggleExpand = useCallback3(
1029
+ (rowKey) => {
1030
+ if (preventExpand) return;
1031
+ handleExpandedRowsChange(toggleExpandedRowId(rowKey, expandedRows));
1032
+ },
1033
+ [preventExpand, handleExpandedRowsChange, expandedRows]
1034
+ );
1035
+ const rowContextValue = useMemo2(() => {
1036
+ return {
1037
+ rowSpan: {
1038
+ enableRowSpan,
1039
+ primaryRowSpanKey,
1040
+ columnRowSpanMap,
1041
+ hoveredRowIndex,
1042
+ hoveredGroupKey,
1043
+ selectedGroupKeys,
1044
+ onRowHover: handleRowHover
1045
+ },
1046
+ selection: {
1047
+ rowSelectionMode,
1048
+ selectOnRowClick,
1049
+ onRowClick,
1050
+ getRowClassName
1051
+ },
1052
+ cellSelection: {
1053
+ enableCellSelection,
1054
+ activeSelectionBounds,
1055
+ dragState,
1056
+ onCellMouseDown: handleCellMouseDownWithCommit,
1057
+ onCellMouseEnter: handleCellMouseEnter,
1058
+ onFillHandleMouseDown: handleFillHandleMouseDown
1059
+ },
1060
+ cellEdit: {
1061
+ editingCell,
1062
+ draftValue,
1063
+ onDraftValueChange: setDraftValue,
1064
+ onStartEdit: startEdit,
1065
+ onCommitEdit: commitEdit,
1066
+ onCancelEdit: cancelEdit
1067
+ },
1068
+ expand: {
1069
+ enableExpand,
1070
+ toggleField,
1071
+ expandedRows,
1072
+ preventExpand,
1073
+ onToggleExpand: handleToggleExpand,
1074
+ expandRowLabel: labels.expandRow,
1075
+ collapseRowLabel: labels.collapseRow
1076
+ }
1077
+ };
1078
+ }, [
1079
+ enableRowSpan,
1080
+ primaryRowSpanKey,
1081
+ columnRowSpanMap,
1082
+ hoveredRowIndex,
1083
+ hoveredGroupKey,
1084
+ selectedGroupKeys,
1085
+ handleRowHover,
1086
+ rowSelectionMode,
1087
+ selectOnRowClick,
1088
+ onRowClick,
1089
+ getRowClassName,
1090
+ enableCellSelection,
1091
+ activeSelectionBounds,
1092
+ dragState,
1093
+ handleCellMouseDownWithCommit,
1094
+ handleCellMouseEnter,
1095
+ handleFillHandleMouseDown,
1096
+ editingCell,
1097
+ draftValue,
1098
+ setDraftValue,
1099
+ startEdit,
1100
+ commitEdit,
1101
+ cancelEdit,
1102
+ enableExpand,
1103
+ toggleField,
1104
+ expandedRows,
1105
+ preventExpand,
1106
+ handleToggleExpand,
1107
+ labels.expandRow,
1108
+ labels.collapseRow
1109
+ ]);
1110
+ return {
1111
+ table,
1112
+ tableData,
1113
+ rows,
1114
+ columnCount,
1115
+ selectedCount,
1116
+ labels,
1117
+ emptyText: labels.empty,
1118
+ loadingText: labels.loading,
1119
+ selectionLabel: labels.selection,
1120
+ enableCellSelection,
1121
+ shouldVirtualize,
1122
+ scrollRef,
1123
+ rowVirtualizer,
1124
+ virtualRows,
1125
+ paddingTop,
1126
+ paddingBottom,
1127
+ rowContextValue,
1128
+ handleToggleSelect,
1129
+ clearHover
1130
+ };
1131
+ }
1132
+
1133
+ // src/components/ui/table/components/DataTable/DataTable.tsx
1134
+ import { flexRender as flexRender2 } from "@tanstack/react-table";
1135
+
1136
+ // src/components/ui/table/components/DataTable/DataTableRow.tsx
1137
+ import { flexRender } from "@tanstack/react-table";
1138
+ import { useEffect as useEffect5, useRef as useRef4 } from "react";
1139
+
1140
+ // src/components/ui/table/DataTableContext.tsx
1141
+ import { createContext, use } from "react";
1142
+ import { jsx } from "react/jsx-runtime";
1143
+ var DataTableContext = createContext(null);
1144
+ function useDataTableRowContext() {
1145
+ const context = use(DataTableContext);
1146
+ if (!context) {
1147
+ throw new Error("useDataTableRowContext must be used within a DataTableContextProvider");
1148
+ }
1149
+ return context;
1150
+ }
1151
+ function DataTableContextProvider({
1152
+ value,
1153
+ children
1154
+ }) {
1155
+ return /* @__PURE__ */ jsx(DataTableContext, { value, children });
1156
+ }
1157
+
1158
+ // src/components/ui/table/components/icons.tsx
1159
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
1160
+ function ChevronDown({ className, "aria-hidden": ariaHidden = true }) {
1161
+ return /* @__PURE__ */ jsx2(
1162
+ "svg",
1163
+ {
1164
+ className,
1165
+ "aria-hidden": ariaHidden,
1166
+ width: "16",
1167
+ height: "16",
1168
+ viewBox: "0 0 24 24",
1169
+ fill: "none",
1170
+ stroke: "currentColor",
1171
+ strokeWidth: "2",
1172
+ strokeLinecap: "round",
1173
+ strokeLinejoin: "round",
1174
+ children: /* @__PURE__ */ jsx2("path", { d: "m6 9 6 6 6-6" })
1175
+ }
1176
+ );
1177
+ }
1178
+ function ChevronUp({ className, "aria-hidden": ariaHidden = true }) {
1179
+ return /* @__PURE__ */ jsx2(
1180
+ "svg",
1181
+ {
1182
+ className,
1183
+ "aria-hidden": ariaHidden,
1184
+ width: "16",
1185
+ height: "16",
1186
+ viewBox: "0 0 24 24",
1187
+ fill: "none",
1188
+ stroke: "currentColor",
1189
+ strokeWidth: "2",
1190
+ strokeLinecap: "round",
1191
+ strokeLinejoin: "round",
1192
+ children: /* @__PURE__ */ jsx2("path", { d: "m18 15-6-6-6 6" })
1193
+ }
1194
+ );
1195
+ }
1196
+ function ChevronLeft({ className, "aria-hidden": ariaHidden = true }) {
1197
+ return /* @__PURE__ */ jsx2(
1198
+ "svg",
1199
+ {
1200
+ className,
1201
+ "aria-hidden": ariaHidden,
1202
+ width: "16",
1203
+ height: "16",
1204
+ viewBox: "0 0 24 24",
1205
+ fill: "none",
1206
+ stroke: "currentColor",
1207
+ strokeWidth: "2",
1208
+ strokeLinecap: "round",
1209
+ strokeLinejoin: "round",
1210
+ children: /* @__PURE__ */ jsx2("path", { d: "m15 18-6-6 6-6" })
1211
+ }
1212
+ );
1213
+ }
1214
+ function ChevronRight({ className, "aria-hidden": ariaHidden = true }) {
1215
+ return /* @__PURE__ */ jsx2(
1216
+ "svg",
1217
+ {
1218
+ className,
1219
+ "aria-hidden": ariaHidden,
1220
+ width: "16",
1221
+ height: "16",
1222
+ viewBox: "0 0 24 24",
1223
+ fill: "none",
1224
+ stroke: "currentColor",
1225
+ strokeWidth: "2",
1226
+ strokeLinecap: "round",
1227
+ strokeLinejoin: "round",
1228
+ children: /* @__PURE__ */ jsx2("path", { d: "m9 18 6-6-6-6" })
1229
+ }
1230
+ );
1231
+ }
1232
+ function ArrowUp({ className, "aria-hidden": ariaHidden = true }) {
1233
+ return /* @__PURE__ */ jsxs(
1234
+ "svg",
1235
+ {
1236
+ className,
1237
+ "aria-hidden": ariaHidden,
1238
+ width: "14",
1239
+ height: "14",
1240
+ viewBox: "0 0 24 24",
1241
+ fill: "none",
1242
+ stroke: "currentColor",
1243
+ strokeWidth: "2",
1244
+ strokeLinecap: "round",
1245
+ strokeLinejoin: "round",
1246
+ children: [
1247
+ /* @__PURE__ */ jsx2("path", { d: "m18 15-6-6-6 6" }),
1248
+ /* @__PURE__ */ jsx2("path", { d: "M12 21V9" })
1249
+ ]
1250
+ }
1251
+ );
1252
+ }
1253
+ function ArrowDown({ className, "aria-hidden": ariaHidden = true }) {
1254
+ return /* @__PURE__ */ jsxs(
1255
+ "svg",
1256
+ {
1257
+ className,
1258
+ "aria-hidden": ariaHidden,
1259
+ width: "14",
1260
+ height: "14",
1261
+ viewBox: "0 0 24 24",
1262
+ fill: "none",
1263
+ stroke: "currentColor",
1264
+ strokeWidth: "2",
1265
+ strokeLinecap: "round",
1266
+ strokeLinejoin: "round",
1267
+ children: [
1268
+ /* @__PURE__ */ jsx2("path", { d: "m6 9 6 6 6-6" }),
1269
+ /* @__PURE__ */ jsx2("path", { d: "M12 3v12" })
1270
+ ]
1271
+ }
1272
+ );
1273
+ }
1274
+ function ArrowUpDown({ className, "aria-hidden": ariaHidden = true }) {
1275
+ return /* @__PURE__ */ jsxs(
1276
+ "svg",
1277
+ {
1278
+ className,
1279
+ "aria-hidden": ariaHidden,
1280
+ width: "14",
1281
+ height: "14",
1282
+ viewBox: "0 0 24 24",
1283
+ fill: "none",
1284
+ stroke: "currentColor",
1285
+ strokeWidth: "2",
1286
+ strokeLinecap: "round",
1287
+ strokeLinejoin: "round",
1288
+ children: [
1289
+ /* @__PURE__ */ jsx2("path", { d: "m21 16-4 4-4-4" }),
1290
+ /* @__PURE__ */ jsx2("path", { d: "M17 20V4" }),
1291
+ /* @__PURE__ */ jsx2("path", { d: "m3 8 4-4 4 4" }),
1292
+ /* @__PURE__ */ jsx2("path", { d: "M7 4v16" })
1293
+ ]
1294
+ }
1295
+ );
1296
+ }
1297
+
1298
+ // src/lib/cn.ts
1299
+ function cn(...inputs) {
1300
+ return inputs.filter(Boolean).join(" ");
1301
+ }
1302
+
1303
+ // src/components/ui/table/components/DataTable/DataTableRow.tsx
1304
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1305
+ function resolveExpandCellIndex(cells, toggleField) {
1306
+ if (!toggleField) return 0;
1307
+ const matchedIndex = cells.findIndex(
1308
+ (cell) => cell.column.id === toggleField
1309
+ );
1310
+ if (matchedIndex >= 0) return matchedIndex;
1311
+ const noColumnIndex = cells.findIndex(
1312
+ (cell) => cell.column.id === "no" || cell.column.id === "treeNo"
1313
+ );
1314
+ if (noColumnIndex >= 0 && noColumnIndex + 1 < cells.length) {
1315
+ return noColumnIndex + 1;
1316
+ }
1317
+ return 0;
1318
+ }
1319
+ function DataTableRow({
1320
+ row,
1321
+ onToggleSelect,
1322
+ virtualIndex,
1323
+ measureElement
1324
+ }) {
1325
+ const { rowSpan, selection, cellSelection, cellEdit, expand } = useDataTableRowContext();
1326
+ const {
1327
+ enableRowSpan,
1328
+ primaryRowSpanKey,
1329
+ columnRowSpanMap,
1330
+ hoveredRowIndex,
1331
+ hoveredGroupKey,
499
1332
  selectedGroupKeys,
500
1333
  onRowHover
501
1334
  } = rowSpan;
502
1335
  const { rowSelectionMode, selectOnRowClick, onRowClick, getRowClassName } = selection;
503
1336
  const {
1337
+ enableCellSelection,
504
1338
  activeSelectionBounds,
505
1339
  dragState,
506
1340
  onCellMouseDown,
@@ -520,7 +1354,9 @@ function DataTableRow({
520
1354
  toggleField,
521
1355
  expandedRows,
522
1356
  preventExpand,
523
- onToggleExpand
1357
+ onToggleExpand,
1358
+ expandRowLabel,
1359
+ collapseRowLabel
524
1360
  } = expand;
525
1361
  const rowIndex = row.index;
526
1362
  const rowData = row.original;
@@ -530,14 +1366,31 @@ function DataTableRow({
530
1366
  const isGroupHovered = enableRowSpan && hoveredGroupKey !== null && rowGroupKey === hoveredGroupKey;
531
1367
  const isGroupSelected = enableRowSpan && rowGroupKey !== null && selectedGroupKeys.has(rowGroupKey);
532
1368
  const visibleCells = row.getVisibleCells();
1369
+ const columnIdsByIndex = visibleCells.map((cell) => cell.column.id);
1370
+ const isVisuallySelectedAt = activeSelectionBounds ? (targetRow, targetCol) => {
1371
+ if (targetCol < activeSelectionBounds.startCol || targetCol > activeSelectionBounds.endCol) {
1372
+ return false;
1373
+ }
1374
+ const columnId = columnIdsByIndex[targetCol];
1375
+ const { startRow, rowSpan: span } = resolveRowSpanAt(
1376
+ columnId ? columnRowSpanMap.get(columnId) : void 0,
1377
+ targetRow
1378
+ );
1379
+ return isCellInSelection(
1380
+ startRow,
1381
+ targetCol,
1382
+ activeSelectionBounds,
1383
+ span
1384
+ );
1385
+ } : void 0;
533
1386
  const expandCellIndex = enableExpand ? resolveExpandCellIndex(visibleCells, toggleField) : -1;
534
1387
  const canExpand = enableExpand && !preventExpand && canExpandRow(rowData);
535
1388
  const expandKey = toggleField && rowData[toggleField] !== null && rowData[toggleField] !== void 0 ? String(rowData[toggleField]) : null;
536
1389
  const isExpanded = expandKey !== null && Boolean(expandedRows?.has(expandKey));
537
1390
  const rowLevel = typeof rowData.level === "number" ? rowData.level : 0;
538
- const editInputRef = useRef2(null);
1391
+ const editInputRef = useRef4(null);
539
1392
  const isRowEditing = editingCell?.rowIndex === rowIndex;
540
- useEffect2(() => {
1393
+ useEffect5(() => {
541
1394
  if (!isRowEditing) return;
542
1395
  editInputRef.current?.focus();
543
1396
  editInputRef.current?.select();
@@ -583,6 +1436,11 @@ function DataTableRow({
583
1436
  const showCellHover = isRowSpanColumn ? isGroupHovered : isRowHovered;
584
1437
  const showCellSelected = isRowSpanColumn ? isGroupSelected : isRowSelected;
585
1438
  const cellRowSpan = rowSpanInfo?.rowSpan ?? 1;
1439
+ const isMerged = cellRowSpan > 1;
1440
+ const showMergedRightEdge = isMerged && (cellIndex === visibleCells.length - 1 || resolveRowSpanAt(
1441
+ columnRowSpanMap.get(columnIdsByIndex[cellIndex + 1]),
1442
+ rowIndex
1443
+ ).rowSpan <= 1);
586
1444
  const isCellDragSelected = isCellInSelection(
587
1445
  rowIndex,
588
1446
  cellIndex,
@@ -590,6 +1448,13 @@ function DataTableRow({
590
1448
  cellRowSpan
591
1449
  );
592
1450
  const isBottomRightCell = !isEditing && activeSelectionBounds && !dragState.isSelecting && activeSelectionBounds.endRow >= rowIndex && activeSelectionBounds.endRow <= rowIndex + cellRowSpan - 1 && cellIndex === activeSelectionBounds.endCol;
1451
+ const selectionEdgeStyle = getCellSelectionEdgeStyle(
1452
+ rowIndex,
1453
+ cellIndex,
1454
+ activeSelectionBounds,
1455
+ cellRowSpan,
1456
+ isVisuallySelectedAt
1457
+ );
593
1458
  const resolveCellRowIndex = (clientY, element) => getRowIndexInMergedCell(clientY, element, rowIndex, cellRowSpan);
594
1459
  return /* @__PURE__ */ jsxs2(
595
1460
  "td",
@@ -600,17 +1465,22 @@ function DataTableRow({
600
1465
  event.stopPropagation();
601
1466
  return;
602
1467
  }
1468
+ if (!enableCellSelection) return;
603
1469
  event.preventDefault();
604
1470
  onCellMouseDown(
605
1471
  resolveCellRowIndex(event.clientY, event.currentTarget),
606
1472
  cellIndex
607
1473
  );
608
1474
  },
609
- onMouseEnter: (event) => onCellMouseEnter(
610
- resolveCellRowIndex(event.clientY, event.currentTarget),
611
- cellIndex
612
- ),
1475
+ onMouseEnter: (event) => {
1476
+ if (!enableCellSelection) return;
1477
+ onCellMouseEnter(
1478
+ resolveCellRowIndex(event.clientY, event.currentTarget),
1479
+ cellIndex
1480
+ );
1481
+ },
613
1482
  onMouseMove: (event) => {
1483
+ if (!enableCellSelection) return;
614
1484
  if (!dragState.isSelecting && !dragState.isFillDragging) return;
615
1485
  onCellMouseEnter(
616
1486
  resolveCellRowIndex(event.clientY, event.currentTarget),
@@ -623,19 +1493,17 @@ function DataTableRow({
623
1493
  event.stopPropagation();
624
1494
  onStartEdit(rowIndex, cellIndex);
625
1495
  },
626
- style: getCellSelectionEdgeStyle(
627
- rowIndex,
628
- cellIndex,
629
- activeSelectionBounds,
630
- cellRowSpan
631
- ),
1496
+ style: selectionEdgeStyle,
632
1497
  className: cn(
633
1498
  "data-table-cell",
634
1499
  CELL_ALIGN_CLASS[align],
635
1500
  cellClassName,
1501
+ isMerged && cellIndex > 0 && "is-merged",
1502
+ showMergedRightEdge && "is-merged-edge-right",
636
1503
  enableRowSpan && showCellSelected && "is-group-selected",
637
1504
  enableRowSpan && showCellHover && !showCellSelected && "is-group-hovered",
638
1505
  isCellDragSelected && CELL_SELECTION_FILL_CLASS,
1506
+ hasCellSelectionEdges(selectionEdgeStyle) && CELL_SELECTION_EDGES_CLASS,
639
1507
  editable && "is-editable"
640
1508
  ),
641
1509
  children: [
@@ -672,7 +1540,7 @@ function DataTableRow({
672
1540
  "button",
673
1541
  {
674
1542
  type: "button",
675
- "aria-label": isExpanded ? "\uD589 \uC811\uAE30" : "\uD589 \uD3BC\uCE58\uAE30",
1543
+ "aria-label": isExpanded ? collapseRowLabel : expandRowLabel,
676
1544
  className: "expand-toggle-button",
677
1545
  onClick: (event) => {
678
1546
  event.stopPropagation();
@@ -706,14 +1574,6 @@ function DataTableRow({
706
1574
 
707
1575
  // src/components/ui/table/components/DataTable/DataTableToolbar.tsx
708
1576
  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
1577
  function DataTableToolbar({
718
1578
  filteredCount,
719
1579
  totalCount,
@@ -727,8 +1587,8 @@ function DataTableToolbar({
727
1587
  const hasCount = displayFiltered !== void 0 || totalCount !== void 0;
728
1588
  const hasLeftContent = hasCount || Boolean(summary);
729
1589
  const hasToolbar = Boolean(toolbar);
730
- const selectionContent = selectionLabel ? selectionLabel(selectedCount) : /* @__PURE__ */ jsx4(DefaultSelectionLabel, { selectedCount });
731
- const hasSelectionContent = selectionContent !== null && selectionContent !== false;
1590
+ const selectionContent = selectionLabel?.(selectedCount) ?? null;
1591
+ const hasSelectionContent = selectionContent !== null && selectionContent !== false && selectionContent !== void 0 && typeof selectionContent !== "boolean";
732
1592
  if (!hasLeftContent && !hasToolbar && !hasSelectionContent) return null;
733
1593
  return /* @__PURE__ */ jsxs3("div", { className: cn("DataTableToolbarJSX", className), children: [
734
1594
  /* @__PURE__ */ jsxs3("div", { className: "toolbar-left", children: [
@@ -742,610 +1602,151 @@ function DataTableToolbar({
742
1602
  summary
743
1603
  ] }),
744
1604
  /* @__PURE__ */ jsxs3("div", { className: "toolbar-right", children: [
745
- selectionContent,
1605
+ hasSelectionContent && (typeof selectionContent === "string" || typeof selectionContent === "number" ? /* @__PURE__ */ jsx4("span", { className: "toolbar-selection", children: selectionContent }) : selectionContent),
746
1606
  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 } };
876
- }
877
- return prev;
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
- };
891
- });
892
- }, []);
893
- useEffect4(() => {
894
- const handleKeyDown = (e) => {
895
- if ((e.ctrlKey || e.metaKey) && e.key === "c" && activeSelectionBounds) {
896
- const { startRow, endRow, startCol, endCol } = activeSelectionBounds;
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);
902
- }
903
- };
904
- window.addEventListener("keydown", handleKeyDown);
905
- return () => window.removeEventListener("keydown", handleKeyDown);
906
- }, [activeSelectionBounds, rows]);
907
- useEffect4(() => {
908
- const handleMouseUp = () => {
909
- setDragState((prev) => {
910
- if (prev.isFillDragging && prev.fillAnchor && prev.fillEnd) {
911
- const sourceBounds = getCellSelectionBounds(prev.start, prev.end);
912
- const newBounds = getCellSelectionBounds(prev.fillAnchor, prev.fillEnd);
913
- if (newBounds) {
914
- if (hasFillExtension(sourceBounds, newBounds) && sourceBounds && onDataChange) {
915
- onDataChange(applyFillData(data, rows, sourceBounds, newBounds));
916
- }
917
- return {
918
- isSelecting: false,
919
- isFillDragging: false,
920
- start: { row: newBounds.startRow, col: newBounds.startCol },
921
- end: { row: newBounds.endRow, col: newBounds.endCol },
922
- fillAnchor: null,
923
- fillEnd: null
924
- };
925
- }
926
- }
927
- if (prev.isSelecting) {
928
- return { ...prev, isSelecting: false };
929
- }
930
- if (prev.isFillDragging) {
931
- return { ...prev, isFillDragging: false, fillAnchor: null, fillEnd: null };
932
- }
933
- return prev;
934
- });
935
- };
936
- window.addEventListener("mouseup", handleMouseUp);
937
- return () => window.removeEventListener("mouseup", handleMouseUp);
938
- }, [data, onDataChange, rows]);
939
- return {
940
- dragState,
941
- activeSelectionBounds,
942
- handleCellMouseDown,
943
- handleCellMouseEnter,
944
- handleFillHandleMouseDown
945
- };
946
- }
947
-
948
- // src/components/ui/table/features/row-selection/rowSelection.ts
949
- function resolveRowSelection(mode, controlledSelection, internalSelection) {
950
- if (mode === "none") return {};
951
- return controlledSelection ?? internalSelection;
952
- }
953
- function normalizeSingleSelection(next) {
954
- const selectedIds = Object.keys(next).filter((id) => next[id]);
955
- if (selectedIds.length <= 1) return next;
956
- return { [selectedIds[selectedIds.length - 1]]: true };
957
- }
958
- function applySelectionUpdater(mode, updater, previous) {
959
- const next = typeof updater === "function" ? updater(previous) : updater;
960
- return mode === "single" ? normalizeSingleSelection(next) : next;
961
- }
962
-
963
- // src/components/ui/table/features/row-span/rowSpan.ts
964
- function getRowFieldValue(row, key) {
965
- return row[key];
966
- }
967
- function computeRowSpans(data, rowSpanKey) {
968
- if (data.length === 0) return [];
969
- const result = [];
970
- for (let index = 0; index < data.length; index++) {
971
- const currentValue = getRowFieldValue(data[index], rowSpanKey);
972
- const previousValue = index > 0 ? getRowFieldValue(data[index - 1], rowSpanKey) : void 0;
973
- if (index > 0 && currentValue === previousValue) {
974
- result.push({ rowSpan: 0, isFirstInGroup: false });
975
- continue;
976
- }
977
- let span = 1;
978
- for (let nextIndex = index + 1; nextIndex < data.length; nextIndex++) {
979
- if (getRowFieldValue(data[nextIndex], rowSpanKey) === currentValue) {
980
- span++;
981
- } else {
982
- break;
983
- }
984
- }
985
- result.push({ rowSpan: span, isFirstInGroup: true });
986
- }
987
- return result;
988
- }
989
- function buildColumnRowSpanMap(data, columnKeys) {
990
- const map = /* @__PURE__ */ new Map();
991
- for (const { columnId, rowSpanKey } of columnKeys) {
992
- map.set(columnId, computeRowSpans(data, rowSpanKey));
993
- }
994
- return map;
995
- }
996
- function collectRowSpanColumns(columns) {
997
- const result = [];
998
- const visit = (defs) => {
999
- for (const columnDef of defs) {
1000
- if ("columns" in columnDef && columnDef.columns?.length) {
1001
- visit(columnDef.columns);
1002
- continue;
1003
- }
1004
- const columnId = columnDef.id ?? ("accessorKey" in columnDef && columnDef.accessorKey ? String(columnDef.accessorKey) : void 0);
1005
- if (!columnId || !columnDef.meta?.rowSpan) continue;
1006
- result.push({
1007
- columnId,
1008
- rowSpanKey: columnDef.meta.rowSpanKey ?? columnId
1009
- });
1010
- }
1011
- };
1012
- visit(columns);
1013
- return result;
1607
+ ] })
1608
+ ] });
1014
1609
  }
1015
1610
 
1016
1611
  // src/components/ui/table/components/DataTable/DataTable.tsx
1017
1612
  import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1613
+ function DefaultPending({
1614
+ loadingText,
1615
+ className
1616
+ }) {
1617
+ return /* @__PURE__ */ jsx5("div", { className: cn("DataTableJSX", "DataTableJSX--pending", className), children: /* @__PURE__ */ jsx5("span", { className: "data-table-loading-text", children: loadingText }) });
1618
+ }
1619
+ function DefaultEmpty({
1620
+ emptyText,
1621
+ columnCount
1622
+ }) {
1623
+ return /* @__PURE__ */ jsx5("tr", { children: /* @__PURE__ */ jsx5("td", { colSpan: columnCount, className: "data-table-empty-cell", children: emptyText }) });
1624
+ }
1018
1625
  function DataTable({
1019
- data,
1020
- columns,
1021
- rowSelectionMode = "none",
1022
- rowSelection: controlledRowSelection,
1023
- onRowSelectionChange,
1024
- totalCount,
1025
- filteredCount,
1626
+ isPending = false,
1026
1627
  summary,
1027
1628
  toolbar,
1028
- selectionLabel,
1029
- isPending = false,
1030
- emptyText = "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
1031
- enableRowSpan = false,
1032
- getRowId,
1033
- onRowClick,
1034
- getRowClassName,
1035
- getRowCanSelect,
1036
- selectOnRowClick = true,
1037
- onDataChange,
1629
+ filteredCount,
1630
+ totalCount,
1038
1631
  className,
1039
- preserveRowSelection = false,
1040
- toggleField,
1041
- childField,
1042
- flattenField,
1043
- expandedRows: controlledExpandedRows,
1044
- onExpandedRowsChange,
1045
- preventExpand = false,
1046
- enableVirtualization = true,
1047
- estimateRowHeight = DATA_TABLE_ROW_HEIGHT,
1048
- virtualOverscan = DATA_TABLE_VIRTUAL_OVERSCAN
1632
+ slots,
1633
+ ...glideOptions
1049
1634
  }) {
1050
- const enableExpand = Boolean(toggleField);
1051
- const [internalRowSelection, setInternalRowSelection] = useState3({});
1052
- const [internalExpandedRows, setInternalExpandedRows] = useState3(() => /* @__PURE__ */ new Set());
1053
- const [hoveredRowIndex, setHoveredRowIndex] = useState3(null);
1054
- const [hoveredGroupKey, setHoveredGroupKey] = useState3(null);
1055
- const scrollRef = useRef4(null);
1056
- const shouldVirtualize = enableVirtualization && !enableRowSpan;
1057
- useEffect5(() => {
1058
- if (enableVirtualization && enableRowSpan) {
1059
- console.warn(
1060
- "[DataTable] enableRowSpan\uC774 \uCF1C\uC838 \uC788\uC73C\uBA74 \uC140 \uBCD1\uD569 \uC720\uC9C0\uB97C \uC704\uD574 \uAC00\uC0C1\uD654\uB97C \uBE44\uD65C\uC131\uD654\uD569\uB2C8\uB2E4."
1061
- );
1062
- }
1063
- }, [enableVirtualization, enableRowSpan]);
1064
- const rowSelection = resolveRowSelection(
1065
- rowSelectionMode,
1066
- controlledRowSelection,
1067
- internalRowSelection
1068
- );
1069
- const expandedRows = controlledExpandedRows ?? internalExpandedRows;
1070
- const handleExpandedRowsChange = useCallback3(
1071
- (next) => {
1072
- if (onExpandedRowsChange) {
1073
- onExpandedRowsChange(next);
1074
- return;
1075
- }
1076
- setInternalExpandedRows(next);
1077
- },
1078
- [onExpandedRowsChange]
1079
- );
1080
- const tableData = useConvertTreeData({
1081
- data,
1082
- enabled: enableExpand,
1083
- toggleField,
1084
- childField,
1085
- flattenField,
1086
- expandedRows,
1087
- onExpandedRowsChange: enableExpand ? handleExpandedRowsChange : void 0,
1088
- preventExpand
1089
- });
1090
- const table = useReactTable({
1091
- data: tableData,
1092
- columns,
1093
- state: {
1094
- rowSelection: rowSelectionMode === "none" ? {} : rowSelection
1095
- },
1096
- enableRowSelection: rowSelectionMode === "none" ? false : getRowCanSelect ? (row) => getRowCanSelect(row.original, row.index) : true,
1097
- enableMultiRowSelection: rowSelectionMode === "multi",
1098
- onRowSelectionChange: (updater) => {
1099
- if (onRowSelectionChange) {
1100
- onRowSelectionChange(
1101
- (previous) => applySelectionUpdater(rowSelectionMode, updater, previous)
1102
- );
1103
- return;
1104
- }
1105
- setInternalRowSelection(
1106
- (previous) => applySelectionUpdater(rowSelectionMode, updater, previous)
1107
- );
1108
- },
1109
- getCoreRowModel: getCoreRowModel(),
1110
- getRowId: getRowId ? (originalRow, index) => getRowId(originalRow, index) : (_originalRow, index) => String(index)
1111
- });
1112
- const rowSpanColumnKeys = useMemo2(() => {
1113
- if (!enableRowSpan) return [];
1114
- return collectRowSpanColumns(columns);
1115
- }, [enableRowSpan, columns]);
1116
- const primaryRowSpanKey = rowSpanColumnKeys[0]?.rowSpanKey;
1117
- const columnRowSpanMap = useMemo2(
1118
- () => buildColumnRowSpanMap(tableData, rowSpanColumnKeys),
1119
- [tableData, rowSpanColumnKeys]
1120
- );
1121
- const selectedRows = table.getSelectedRowModel().rows;
1122
- const selectedCount = selectedRows.length;
1123
- const rows = table.getRowModel().rows;
1124
- const columnCount = table.getAllLeafColumns().length || 1;
1125
- const rowVirtualizer = useVirtualizer({
1126
- count: shouldVirtualize ? rows.length : 0,
1127
- getScrollElement: () => scrollRef.current,
1128
- estimateSize: () => estimateRowHeight,
1129
- overscan: virtualOverscan
1130
- });
1131
- const virtualRows = rowVirtualizer.getVirtualItems();
1132
- const totalSize = rowVirtualizer.getTotalSize();
1133
- const paddingTop = virtualRows.length > 0 ? virtualRows[0]?.start ?? 0 : 0;
1134
- const paddingBottom = virtualRows.length > 0 ? totalSize - (virtualRows[virtualRows.length - 1]?.end ?? 0) : 0;
1135
- const selectedGroupKeys = useMemo2(() => {
1136
- if (!enableRowSpan || !primaryRowSpanKey) return /* @__PURE__ */ new Set();
1137
- const keys = /* @__PURE__ */ new Set();
1138
- for (const selectedRow of selectedRows) {
1139
- const value = selectedRow.original[primaryRowSpanKey];
1140
- if (value !== null && value !== void 0) keys.add(String(value));
1141
- }
1142
- return keys;
1143
- }, [enableRowSpan, primaryRowSpanKey, selectedRows]);
1144
1635
  const {
1145
- dragState,
1146
- activeSelectionBounds,
1147
- handleCellMouseDown,
1148
- handleCellMouseEnter,
1149
- handleFillHandleMouseDown
1150
- } = useCellSelection({ data: tableData, rows, onDataChange });
1151
- const { editingCell, draftValue, setDraftValue, startEdit, commitEdit, cancelEdit } = useCellEdit(
1152
- { data: tableData, rows, onDataChange }
1153
- );
1154
- const handleCellMouseDownWithCommit = useCallback3(
1155
- (rowIndex, colIndex) => {
1156
- const isSameEditingCell = editingCell?.rowIndex === rowIndex && editingCell?.colIndex === colIndex;
1157
- if (editingCell && !isSameEditingCell && !commitEdit()) {
1158
- return;
1159
- }
1160
- handleCellMouseDown(rowIndex, colIndex);
1161
- },
1162
- [commitEdit, editingCell, handleCellMouseDown]
1163
- );
1164
- const clearHover = () => {
1165
- setHoveredRowIndex(null);
1166
- setHoveredGroupKey(null);
1167
- };
1168
- const handleRowHover = useCallback3(
1169
- (rowIndex, rowData) => {
1170
- setHoveredRowIndex(rowIndex);
1171
- if (!primaryRowSpanKey) {
1172
- setHoveredGroupKey(null);
1173
- return;
1174
- }
1175
- const groupValue = rowData[primaryRowSpanKey];
1176
- setHoveredGroupKey(
1177
- groupValue === null || groupValue === void 0 ? null : String(groupValue)
1178
- );
1179
- },
1180
- [primaryRowSpanKey]
1181
- );
1182
- const handleToggleSelect = useCallback3(
1183
- (row) => {
1184
- if (!row.getCanSelect()) return;
1185
- if (preserveRowSelection && row.getIsSelected()) {
1186
- return;
1187
- }
1188
- row.toggleSelected();
1189
- },
1190
- [preserveRowSelection]
1191
- );
1192
- const handleToggleExpand = useCallback3(
1193
- (rowKey) => {
1194
- if (preventExpand) return;
1195
- handleExpandedRowsChange(toggleExpandedRowId(rowKey, expandedRows));
1196
- },
1197
- [preventExpand, handleExpandedRowsChange, expandedRows]
1198
- );
1199
- const rowContextValue = useMemo2(() => {
1200
- return {
1201
- rowSpan: {
1202
- enableRowSpan,
1203
- primaryRowSpanKey,
1204
- columnRowSpanMap,
1205
- hoveredRowIndex,
1206
- hoveredGroupKey,
1207
- selectedGroupKeys,
1208
- onRowHover: handleRowHover
1209
- },
1210
- selection: {
1211
- rowSelectionMode,
1212
- selectOnRowClick,
1213
- onRowClick,
1214
- getRowClassName
1215
- },
1216
- cellSelection: {
1217
- activeSelectionBounds,
1218
- dragState,
1219
- onCellMouseDown: handleCellMouseDownWithCommit,
1220
- onCellMouseEnter: handleCellMouseEnter,
1221
- onFillHandleMouseDown: handleFillHandleMouseDown
1222
- },
1223
- cellEdit: {
1224
- editingCell,
1225
- draftValue,
1226
- onDraftValueChange: setDraftValue,
1227
- onStartEdit: startEdit,
1228
- onCommitEdit: commitEdit,
1229
- onCancelEdit: cancelEdit
1230
- },
1231
- expand: {
1232
- enableExpand,
1233
- toggleField,
1234
- expandedRows,
1235
- preventExpand,
1236
- onToggleExpand: handleToggleExpand
1237
- }
1238
- };
1239
- }, [
1240
- enableRowSpan,
1241
- primaryRowSpanKey,
1242
- columnRowSpanMap,
1243
- hoveredRowIndex,
1244
- hoveredGroupKey,
1245
- selectedGroupKeys,
1246
- handleRowHover,
1247
- rowSelectionMode,
1248
- selectOnRowClick,
1249
- onRowClick,
1250
- getRowClassName,
1251
- activeSelectionBounds,
1252
- dragState,
1253
- handleCellMouseDownWithCommit,
1254
- handleCellMouseEnter,
1255
- handleFillHandleMouseDown,
1256
- editingCell,
1257
- draftValue,
1258
- setDraftValue,
1259
- startEdit,
1260
- commitEdit,
1261
- cancelEdit,
1262
- enableExpand,
1263
- toggleField,
1264
- expandedRows,
1265
- preventExpand,
1266
- handleToggleExpand
1267
- ]);
1636
+ table,
1637
+ tableData,
1638
+ rows,
1639
+ columnCount,
1640
+ selectedCount,
1641
+ emptyText,
1642
+ loadingText,
1643
+ selectionLabel,
1644
+ enableCellSelection,
1645
+ shouldVirtualize,
1646
+ scrollRef,
1647
+ rowVirtualizer,
1648
+ virtualRows,
1649
+ paddingTop,
1650
+ paddingBottom,
1651
+ rowContextValue,
1652
+ handleToggleSelect,
1653
+ clearHover
1654
+ } = useGlideTable(glideOptions);
1655
+ const ToolbarSlot = slots?.Toolbar ?? DataTableToolbar;
1656
+ const RowSlot = slots?.Row ?? DataTableRow;
1657
+ const PendingSlot = slots?.Pending ?? DefaultPending;
1658
+ const EmptySlot = slots?.Empty ?? DefaultEmpty;
1268
1659
  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..." }) });
1660
+ return /* @__PURE__ */ jsx5(PendingSlot, { loadingText, className });
1270
1661
  }
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,
1662
+ return /* @__PURE__ */ jsxs4(
1663
+ "div",
1664
+ {
1665
+ className: cn(
1666
+ "DataTableJSX",
1667
+ !enableCellSelection && "DataTableJSX--no-cell-selection",
1668
+ className
1669
+ ),
1670
+ children: [
1671
+ /* @__PURE__ */ jsx5(
1672
+ ToolbarSlot,
1673
+ {
1674
+ filteredCount: filteredCount ?? tableData.length,
1675
+ totalCount,
1676
+ summary,
1677
+ selectedCount,
1678
+ selectionLabel,
1679
+ toolbar
1680
+ }
1681
+ ),
1682
+ /* @__PURE__ */ jsx5("div", { ref: scrollRef, className: "data-table-scroll", children: /* @__PURE__ */ jsxs4(
1683
+ "table",
1684
+ {
1685
+ className: "data-table",
1686
+ onDragStart: enableCellSelection ? (event) => event.preventDefault() : void 0,
1687
+ children: [
1688
+ /* @__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) => {
1689
+ const align = header.column.columnDef.meta?.align ?? "center";
1690
+ const headerClassName = header.column.columnDef.meta?.headerClassName;
1691
+ return /* @__PURE__ */ jsx5(
1692
+ "th",
1693
+ {
1694
+ style: { width: header.getSize() !== 150 ? header.getSize() : void 0 },
1695
+ className: cn(
1696
+ "data-table-head-cell",
1697
+ CELL_ALIGN_CLASS[align],
1698
+ headerClassName
1699
+ ),
1700
+ children: header.isPlaceholder ? null : flexRender2(header.column.columnDef.header, header.getContext())
1701
+ },
1702
+ header.id
1703
+ );
1704
+ }) }, headerGroup.id)) }),
1705
+ /* @__PURE__ */ jsx5(DataTableContextProvider, { value: rowContextValue, children: /* @__PURE__ */ jsx5("tbody", { onMouseLeave: clearHover, className: "data-table-body", children: rows.length === 0 ? /* @__PURE__ */ jsx5(EmptySlot, { emptyText, columnCount }) : shouldVirtualize ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1706
+ paddingTop > 0 && /* @__PURE__ */ jsx5("tr", { "aria-hidden": true, className: "data-table-virtual-spacer", children: /* @__PURE__ */ jsx5(
1707
+ "td",
1708
+ {
1709
+ colSpan: columnCount,
1710
+ style: { height: paddingTop },
1711
+ className: "data-table-virtual-spacer-cell"
1712
+ }
1713
+ ) }),
1714
+ virtualRows.map((virtualRow) => {
1715
+ const row = rows[virtualRow.index];
1716
+ if (!row) return null;
1717
+ return /* @__PURE__ */ jsx5(
1718
+ RowSlot,
1719
+ {
1720
+ row,
1721
+ virtualIndex: virtualRow.index,
1722
+ measureElement: rowVirtualizer.measureElement,
1723
+ onToggleSelect: () => handleToggleSelect(row)
1724
+ },
1725
+ row.id
1726
+ );
1727
+ }),
1728
+ paddingBottom > 0 && /* @__PURE__ */ jsx5("tr", { "aria-hidden": true, className: "data-table-virtual-spacer", children: /* @__PURE__ */ jsx5(
1729
+ "td",
1730
+ {
1731
+ colSpan: columnCount,
1732
+ style: { height: paddingBottom },
1733
+ className: "data-table-virtual-spacer-cell"
1734
+ }
1735
+ ) })
1736
+ ] }) : rows.map((row) => /* @__PURE__ */ jsx5(
1737
+ RowSlot,
1320
1738
  {
1321
1739
  row,
1322
- virtualIndex: virtualRow.index,
1323
- measureElement: rowVirtualizer.measureElement,
1324
1740
  onToggleSelect: () => handleToggleSelect(row)
1325
1741
  },
1326
1742
  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
- ] });
1743
+ )) }) })
1744
+ ]
1745
+ }
1746
+ ) })
1747
+ ]
1748
+ }
1749
+ );
1349
1750
  }
1350
1751
 
1351
1752
  // src/components/ui/table/components/Table/Table.tsx
@@ -1544,7 +1945,7 @@ function TablePagination({
1544
1945
  className: "pagination-button",
1545
1946
  disabled: !canGoPrev,
1546
1947
  onClick: () => onChange(safePage - 1),
1547
- "aria-label": "\uC774\uC804 \uD398\uC774\uC9C0",
1948
+ "aria-label": "Previous page",
1548
1949
  children: /* @__PURE__ */ jsx7(ChevronLeft, { className: "pagination-button-icon" })
1549
1950
  }
1550
1951
  ),
@@ -1560,7 +1961,7 @@ function TablePagination({
1560
1961
  className: "pagination-button",
1561
1962
  disabled: !canGoNext,
1562
1963
  onClick: () => onChange(safePage + 1),
1563
- "aria-label": "\uB2E4\uC74C \uD398\uC774\uC9C0",
1964
+ "aria-label": "Next page",
1564
1965
  children: /* @__PURE__ */ jsx7(ChevronRight, { className: "pagination-button-icon" })
1565
1966
  }
1566
1967
  )
@@ -1609,7 +2010,7 @@ function TableRoot({
1609
2010
  return paginateTableData(sortedData, page, pageSize);
1610
2011
  }, [data, sort, paginationProps, page, pageSize]);
1611
2012
  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.");
2013
+ console.warn("[Table] Declare at least one Table.Column inside Table.Header.");
1613
2014
  }
1614
2015
  return /* @__PURE__ */ jsxs7("div", { className: "TableJSX", children: [
1615
2016
  /* @__PURE__ */ jsx8(
@@ -1660,7 +2061,36 @@ var Table = Object.assign(TableRoot, {
1660
2061
  Pagination: TablePagination
1661
2062
  });
1662
2063
  export {
2064
+ CELL_SELECTION_EDGES_CLASS,
2065
+ DEFAULT_DATA_TABLE_LABELS,
2066
+ DEFAULT_TREE_CHILDREN_FIELD,
2067
+ DEFAULT_TREE_ID_FIELD,
2068
+ DEFAULT_TREE_PARENT_ID_FIELD,
2069
+ DEFAULT_TREE_QTY_FIELD,
1663
2070
  DataTable,
1664
2071
  Table,
1665
- createTable
2072
+ applyCellEdit,
2073
+ applyFillData,
2074
+ applySelectionUpdater,
2075
+ buildColumnRowSpanMap,
2076
+ canExpandRow,
2077
+ collectFillChanges,
2078
+ collectRowSpanColumns,
2079
+ createTable,
2080
+ getCellEditDraftValue,
2081
+ getCellSelectionEdgeStyle,
2082
+ getColumnEditType,
2083
+ getRowIndexInMergedCell,
2084
+ hasCellSelectionEdges,
2085
+ isCellInSelection,
2086
+ isColumnEditable,
2087
+ parseCellEditValue,
2088
+ resolveDataTableLabels,
2089
+ resolveRowSelection,
2090
+ resolveRowSpanAt,
2091
+ toggleExpandedRowId,
2092
+ useCellEdit,
2093
+ useCellSelection,
2094
+ useConvertTreeData,
2095
+ useGlideTable
1666
2096
  };