react-glide-table 2.3.0 → 2.3.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/compound.cjs +129 -83
- package/dist/compound.js +129 -83
- package/dist/core.cjs +132 -86
- package/dist/core.d.cts +1 -0
- package/dist/core.d.ts +1 -0
- package/dist/core.js +132 -86
- package/dist/index.cjs +132 -86
- package/dist/index.js +132 -86
- package/package.json +1 -1
package/dist/compound.cjs
CHANGED
|
@@ -2658,6 +2658,87 @@ function formatDefaultCellValue(value) {
|
|
|
2658
2658
|
return String(value);
|
|
2659
2659
|
}
|
|
2660
2660
|
|
|
2661
|
+
// src/components/ui/table/features/cell-selection/pasteData.ts
|
|
2662
|
+
function countLeadingEmptyCells(cells) {
|
|
2663
|
+
let depth = 0;
|
|
2664
|
+
while (depth < cells.length && cells[depth] === "") {
|
|
2665
|
+
depth += 1;
|
|
2666
|
+
}
|
|
2667
|
+
return depth;
|
|
2668
|
+
}
|
|
2669
|
+
function looksLikeSubtreeIndentation(leadingEmptyCounts) {
|
|
2670
|
+
if (leadingEmptyCounts.length === 0) return false;
|
|
2671
|
+
const firstDepth = leadingEmptyCounts[0] ?? 0;
|
|
2672
|
+
if (firstDepth !== 0) return false;
|
|
2673
|
+
return leadingEmptyCounts.some((depth) => depth > 0);
|
|
2674
|
+
}
|
|
2675
|
+
function parseClipboardTSVWithDepths(text) {
|
|
2676
|
+
if (!text) return { values: [], depths: [] };
|
|
2677
|
+
const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
2678
|
+
const withoutTrailing = normalized.replace(/\n+$/, "");
|
|
2679
|
+
if (!withoutTrailing) return { values: [], depths: [] };
|
|
2680
|
+
const rows = withoutTrailing.split("\n").map((line) => line.split(" "));
|
|
2681
|
+
const leadingEmptyCounts = rows.map(countLeadingEmptyCells);
|
|
2682
|
+
const treatAsDepth = looksLikeSubtreeIndentation(leadingEmptyCounts);
|
|
2683
|
+
const values = [];
|
|
2684
|
+
const depths = [];
|
|
2685
|
+
for (let index = 0; index < rows.length; index += 1) {
|
|
2686
|
+
const cells = rows[index] ?? [];
|
|
2687
|
+
const depth = leadingEmptyCounts[index] ?? 0;
|
|
2688
|
+
if (treatAsDepth) {
|
|
2689
|
+
values.push(cells.slice(depth));
|
|
2690
|
+
depths.push(depth);
|
|
2691
|
+
} else {
|
|
2692
|
+
values.push(cells);
|
|
2693
|
+
depths.push(0);
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
return { values, depths };
|
|
2697
|
+
}
|
|
2698
|
+
function resolvePasteColumnIds(rows, startCol, width) {
|
|
2699
|
+
if (width <= 0) return [];
|
|
2700
|
+
const cells = rows[0]?.getVisibleCells() ?? [];
|
|
2701
|
+
const columnIds = [];
|
|
2702
|
+
for (let offset = 0; offset < width; offset += 1) {
|
|
2703
|
+
const cell = cells[startCol + offset];
|
|
2704
|
+
if (!cell) break;
|
|
2705
|
+
columnIds.push(cell.column.id);
|
|
2706
|
+
}
|
|
2707
|
+
return columnIds;
|
|
2708
|
+
}
|
|
2709
|
+
function buildRowsPastePayload(rows, startRow, startCol, text, mode, endRow = startRow) {
|
|
2710
|
+
const { values, depths } = parseClipboardTSVWithDepths(text);
|
|
2711
|
+
if (values.length === 0) return null;
|
|
2712
|
+
const width = Math.max(...values.map((row) => row.length), 0);
|
|
2713
|
+
if (width === 0) return null;
|
|
2714
|
+
const columnIds = resolvePasteColumnIds(rows, startCol, width);
|
|
2715
|
+
if (columnIds.length === 0) return null;
|
|
2716
|
+
const rowIds = [];
|
|
2717
|
+
for (let offset = 0; offset < values.length; offset += 1) {
|
|
2718
|
+
const row = rows[startRow + offset];
|
|
2719
|
+
if (!row) break;
|
|
2720
|
+
rowIds.push(row.id);
|
|
2721
|
+
}
|
|
2722
|
+
const anchorRow = rows[endRow] ?? rows[startRow];
|
|
2723
|
+
return {
|
|
2724
|
+
mode,
|
|
2725
|
+
startRow,
|
|
2726
|
+
startCol,
|
|
2727
|
+
endRow,
|
|
2728
|
+
rowIds,
|
|
2729
|
+
anchorRowId: anchorRow?.id ?? "",
|
|
2730
|
+
columnIds,
|
|
2731
|
+
values,
|
|
2732
|
+
depths
|
|
2733
|
+
};
|
|
2734
|
+
}
|
|
2735
|
+
function isEditablePasteTarget(target) {
|
|
2736
|
+
if (!(target instanceof HTMLElement)) return false;
|
|
2737
|
+
const tag = target.tagName;
|
|
2738
|
+
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
|
|
2739
|
+
return Boolean(target.isContentEditable);
|
|
2740
|
+
}
|
|
2741
|
+
|
|
2661
2742
|
// src/components/ui/table/features/cell-selection/useCellSelection.ts
|
|
2662
2743
|
var import_react7 = require("react");
|
|
2663
2744
|
|
|
@@ -3067,87 +3148,6 @@ function hasFillExtension(sourceBounds, fillBounds) {
|
|
|
3067
3148
|
return fillBounds.startRow < sourceBounds.startRow || fillBounds.endRow > sourceBounds.endRow || fillBounds.startCol < sourceBounds.startCol || fillBounds.endCol > sourceBounds.endCol;
|
|
3068
3149
|
}
|
|
3069
3150
|
|
|
3070
|
-
// src/components/ui/table/features/cell-selection/pasteData.ts
|
|
3071
|
-
function countLeadingEmptyCells(cells) {
|
|
3072
|
-
let depth = 0;
|
|
3073
|
-
while (depth < cells.length && cells[depth] === "") {
|
|
3074
|
-
depth += 1;
|
|
3075
|
-
}
|
|
3076
|
-
return depth;
|
|
3077
|
-
}
|
|
3078
|
-
function looksLikeSubtreeIndentation(leadingEmptyCounts) {
|
|
3079
|
-
if (leadingEmptyCounts.length === 0) return false;
|
|
3080
|
-
const firstDepth = leadingEmptyCounts[0] ?? 0;
|
|
3081
|
-
if (firstDepth !== 0) return false;
|
|
3082
|
-
return leadingEmptyCounts.some((depth) => depth > 0);
|
|
3083
|
-
}
|
|
3084
|
-
function parseClipboardTSVWithDepths(text) {
|
|
3085
|
-
if (!text) return { values: [], depths: [] };
|
|
3086
|
-
const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
3087
|
-
const withoutTrailing = normalized.replace(/\n+$/, "");
|
|
3088
|
-
if (!withoutTrailing) return { values: [], depths: [] };
|
|
3089
|
-
const rows = withoutTrailing.split("\n").map((line) => line.split(" "));
|
|
3090
|
-
const leadingEmptyCounts = rows.map(countLeadingEmptyCells);
|
|
3091
|
-
const treatAsDepth = looksLikeSubtreeIndentation(leadingEmptyCounts);
|
|
3092
|
-
const values = [];
|
|
3093
|
-
const depths = [];
|
|
3094
|
-
for (let index = 0; index < rows.length; index += 1) {
|
|
3095
|
-
const cells = rows[index] ?? [];
|
|
3096
|
-
const depth = leadingEmptyCounts[index] ?? 0;
|
|
3097
|
-
if (treatAsDepth) {
|
|
3098
|
-
values.push(cells.slice(depth));
|
|
3099
|
-
depths.push(depth);
|
|
3100
|
-
} else {
|
|
3101
|
-
values.push(cells);
|
|
3102
|
-
depths.push(0);
|
|
3103
|
-
}
|
|
3104
|
-
}
|
|
3105
|
-
return { values, depths };
|
|
3106
|
-
}
|
|
3107
|
-
function resolvePasteColumnIds(rows, startCol, width) {
|
|
3108
|
-
if (width <= 0) return [];
|
|
3109
|
-
const cells = rows[0]?.getVisibleCells() ?? [];
|
|
3110
|
-
const columnIds = [];
|
|
3111
|
-
for (let offset = 0; offset < width; offset += 1) {
|
|
3112
|
-
const cell = cells[startCol + offset];
|
|
3113
|
-
if (!cell) break;
|
|
3114
|
-
columnIds.push(cell.column.id);
|
|
3115
|
-
}
|
|
3116
|
-
return columnIds;
|
|
3117
|
-
}
|
|
3118
|
-
function buildRowsPastePayload(rows, startRow, startCol, text, mode, endRow = startRow) {
|
|
3119
|
-
const { values, depths } = parseClipboardTSVWithDepths(text);
|
|
3120
|
-
if (values.length === 0) return null;
|
|
3121
|
-
const width = Math.max(...values.map((row) => row.length), 0);
|
|
3122
|
-
if (width === 0) return null;
|
|
3123
|
-
const columnIds = resolvePasteColumnIds(rows, startCol, width);
|
|
3124
|
-
if (columnIds.length === 0) return null;
|
|
3125
|
-
const rowIds = [];
|
|
3126
|
-
for (let offset = 0; offset < values.length; offset += 1) {
|
|
3127
|
-
const row = rows[startRow + offset];
|
|
3128
|
-
if (!row) break;
|
|
3129
|
-
rowIds.push(row.id);
|
|
3130
|
-
}
|
|
3131
|
-
const anchorRow = rows[endRow] ?? rows[startRow];
|
|
3132
|
-
return {
|
|
3133
|
-
mode,
|
|
3134
|
-
startRow,
|
|
3135
|
-
startCol,
|
|
3136
|
-
endRow,
|
|
3137
|
-
rowIds,
|
|
3138
|
-
anchorRowId: anchorRow?.id ?? "",
|
|
3139
|
-
columnIds,
|
|
3140
|
-
values,
|
|
3141
|
-
depths
|
|
3142
|
-
};
|
|
3143
|
-
}
|
|
3144
|
-
function isEditablePasteTarget(target) {
|
|
3145
|
-
if (!(target instanceof HTMLElement)) return false;
|
|
3146
|
-
const tag = target.tagName;
|
|
3147
|
-
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
|
|
3148
|
-
return Boolean(target.isContentEditable);
|
|
3149
|
-
}
|
|
3150
|
-
|
|
3151
3151
|
// src/components/ui/table/features/cell-selection/useCellSelection.ts
|
|
3152
3152
|
function useCellSelection({
|
|
3153
3153
|
data,
|
|
@@ -3229,11 +3229,19 @@ function useCellSelection({
|
|
|
3229
3229
|
},
|
|
3230
3230
|
[enabled]
|
|
3231
3231
|
);
|
|
3232
|
+
const clearSelection = (0, import_react7.useCallback)(() => {
|
|
3233
|
+
const prev = dragStateRef.current;
|
|
3234
|
+
if (prev.start === null && prev.end === null && !prev.isSelecting && !prev.isFillDragging) {
|
|
3235
|
+
return;
|
|
3236
|
+
}
|
|
3237
|
+
dragStateRef.current = INITIAL_DRAG_STATE;
|
|
3238
|
+
setDragState(INITIAL_DRAG_STATE);
|
|
3239
|
+
}, []);
|
|
3232
3240
|
(0, import_react7.useEffect)(() => {
|
|
3233
3241
|
if (!enabled) {
|
|
3234
|
-
|
|
3242
|
+
clearSelection();
|
|
3235
3243
|
}
|
|
3236
|
-
}, [enabled]);
|
|
3244
|
+
}, [clearSelection, enabled]);
|
|
3237
3245
|
(0, import_react7.useEffect)(() => {
|
|
3238
3246
|
if (!enabled) return;
|
|
3239
3247
|
const handleKeyDown = (e) => {
|
|
@@ -3447,6 +3455,7 @@ function useCellSelection({
|
|
|
3447
3455
|
handleCellMouseDown,
|
|
3448
3456
|
handleCellMouseEnter,
|
|
3449
3457
|
handleFillHandleMouseDown,
|
|
3458
|
+
clearSelection,
|
|
3450
3459
|
copySelection
|
|
3451
3460
|
};
|
|
3452
3461
|
}
|
|
@@ -4038,6 +4047,7 @@ function useGlideTable(options) {
|
|
|
4038
4047
|
handleCellMouseDown,
|
|
4039
4048
|
handleCellMouseEnter,
|
|
4040
4049
|
handleFillHandleMouseDown,
|
|
4050
|
+
clearSelection: clearCellSelection,
|
|
4041
4051
|
copySelection
|
|
4042
4052
|
} = useCellSelection({
|
|
4043
4053
|
data: tableData,
|
|
@@ -4053,6 +4063,42 @@ function useGlideTable(options) {
|
|
|
4053
4063
|
cellRendererRegistry,
|
|
4054
4064
|
rootRef
|
|
4055
4065
|
});
|
|
4066
|
+
const clearRowSelection = (0, import_react9.useCallback)(() => {
|
|
4067
|
+
if (rowSelectionMode === "none") return;
|
|
4068
|
+
const hasSelection = Object.values(rowSelection).some(Boolean);
|
|
4069
|
+
if (!hasSelection) return;
|
|
4070
|
+
if (onRowSelectionChange) {
|
|
4071
|
+
onRowSelectionChange(() => ({}));
|
|
4072
|
+
return;
|
|
4073
|
+
}
|
|
4074
|
+
setInternalRowSelection({});
|
|
4075
|
+
}, [onRowSelectionChange, rowSelection, rowSelectionMode]);
|
|
4076
|
+
(0, import_react9.useEffect)(() => {
|
|
4077
|
+
const clearAllSelections = () => {
|
|
4078
|
+
clearCellSelection();
|
|
4079
|
+
clearRowSelection();
|
|
4080
|
+
};
|
|
4081
|
+
const handleKeyDown = (event) => {
|
|
4082
|
+
if (event.key !== "Escape") return;
|
|
4083
|
+
if (event.defaultPrevented) return;
|
|
4084
|
+
if (isEditablePasteTarget(event.target) || isEditablePasteTarget(document.activeElement)) {
|
|
4085
|
+
return;
|
|
4086
|
+
}
|
|
4087
|
+
clearAllSelections();
|
|
4088
|
+
};
|
|
4089
|
+
const handleMouseDown = (event) => {
|
|
4090
|
+
const root = rootRef.current;
|
|
4091
|
+
if (!root) return;
|
|
4092
|
+
if (event.target instanceof Node && root.contains(event.target)) return;
|
|
4093
|
+
clearAllSelections();
|
|
4094
|
+
};
|
|
4095
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4096
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
4097
|
+
return () => {
|
|
4098
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
4099
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
|
4100
|
+
};
|
|
4101
|
+
}, [clearCellSelection, clearRowSelection]);
|
|
4056
4102
|
const {
|
|
4057
4103
|
editingCell,
|
|
4058
4104
|
draftValue,
|
package/dist/compound.js
CHANGED
|
@@ -2646,6 +2646,87 @@ function formatDefaultCellValue(value) {
|
|
|
2646
2646
|
return String(value);
|
|
2647
2647
|
}
|
|
2648
2648
|
|
|
2649
|
+
// src/components/ui/table/features/cell-selection/pasteData.ts
|
|
2650
|
+
function countLeadingEmptyCells(cells) {
|
|
2651
|
+
let depth = 0;
|
|
2652
|
+
while (depth < cells.length && cells[depth] === "") {
|
|
2653
|
+
depth += 1;
|
|
2654
|
+
}
|
|
2655
|
+
return depth;
|
|
2656
|
+
}
|
|
2657
|
+
function looksLikeSubtreeIndentation(leadingEmptyCounts) {
|
|
2658
|
+
if (leadingEmptyCounts.length === 0) return false;
|
|
2659
|
+
const firstDepth = leadingEmptyCounts[0] ?? 0;
|
|
2660
|
+
if (firstDepth !== 0) return false;
|
|
2661
|
+
return leadingEmptyCounts.some((depth) => depth > 0);
|
|
2662
|
+
}
|
|
2663
|
+
function parseClipboardTSVWithDepths(text) {
|
|
2664
|
+
if (!text) return { values: [], depths: [] };
|
|
2665
|
+
const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
2666
|
+
const withoutTrailing = normalized.replace(/\n+$/, "");
|
|
2667
|
+
if (!withoutTrailing) return { values: [], depths: [] };
|
|
2668
|
+
const rows = withoutTrailing.split("\n").map((line) => line.split(" "));
|
|
2669
|
+
const leadingEmptyCounts = rows.map(countLeadingEmptyCells);
|
|
2670
|
+
const treatAsDepth = looksLikeSubtreeIndentation(leadingEmptyCounts);
|
|
2671
|
+
const values = [];
|
|
2672
|
+
const depths = [];
|
|
2673
|
+
for (let index = 0; index < rows.length; index += 1) {
|
|
2674
|
+
const cells = rows[index] ?? [];
|
|
2675
|
+
const depth = leadingEmptyCounts[index] ?? 0;
|
|
2676
|
+
if (treatAsDepth) {
|
|
2677
|
+
values.push(cells.slice(depth));
|
|
2678
|
+
depths.push(depth);
|
|
2679
|
+
} else {
|
|
2680
|
+
values.push(cells);
|
|
2681
|
+
depths.push(0);
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2684
|
+
return { values, depths };
|
|
2685
|
+
}
|
|
2686
|
+
function resolvePasteColumnIds(rows, startCol, width) {
|
|
2687
|
+
if (width <= 0) return [];
|
|
2688
|
+
const cells = rows[0]?.getVisibleCells() ?? [];
|
|
2689
|
+
const columnIds = [];
|
|
2690
|
+
for (let offset = 0; offset < width; offset += 1) {
|
|
2691
|
+
const cell = cells[startCol + offset];
|
|
2692
|
+
if (!cell) break;
|
|
2693
|
+
columnIds.push(cell.column.id);
|
|
2694
|
+
}
|
|
2695
|
+
return columnIds;
|
|
2696
|
+
}
|
|
2697
|
+
function buildRowsPastePayload(rows, startRow, startCol, text, mode, endRow = startRow) {
|
|
2698
|
+
const { values, depths } = parseClipboardTSVWithDepths(text);
|
|
2699
|
+
if (values.length === 0) return null;
|
|
2700
|
+
const width = Math.max(...values.map((row) => row.length), 0);
|
|
2701
|
+
if (width === 0) return null;
|
|
2702
|
+
const columnIds = resolvePasteColumnIds(rows, startCol, width);
|
|
2703
|
+
if (columnIds.length === 0) return null;
|
|
2704
|
+
const rowIds = [];
|
|
2705
|
+
for (let offset = 0; offset < values.length; offset += 1) {
|
|
2706
|
+
const row = rows[startRow + offset];
|
|
2707
|
+
if (!row) break;
|
|
2708
|
+
rowIds.push(row.id);
|
|
2709
|
+
}
|
|
2710
|
+
const anchorRow = rows[endRow] ?? rows[startRow];
|
|
2711
|
+
return {
|
|
2712
|
+
mode,
|
|
2713
|
+
startRow,
|
|
2714
|
+
startCol,
|
|
2715
|
+
endRow,
|
|
2716
|
+
rowIds,
|
|
2717
|
+
anchorRowId: anchorRow?.id ?? "",
|
|
2718
|
+
columnIds,
|
|
2719
|
+
values,
|
|
2720
|
+
depths
|
|
2721
|
+
};
|
|
2722
|
+
}
|
|
2723
|
+
function isEditablePasteTarget(target) {
|
|
2724
|
+
if (!(target instanceof HTMLElement)) return false;
|
|
2725
|
+
const tag = target.tagName;
|
|
2726
|
+
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
|
|
2727
|
+
return Boolean(target.isContentEditable);
|
|
2728
|
+
}
|
|
2729
|
+
|
|
2649
2730
|
// src/components/ui/table/features/cell-selection/useCellSelection.ts
|
|
2650
2731
|
import { useCallback as useCallback3, useEffect as useEffect5, useRef as useRef5, useState as useState3 } from "react";
|
|
2651
2732
|
|
|
@@ -3055,87 +3136,6 @@ function hasFillExtension(sourceBounds, fillBounds) {
|
|
|
3055
3136
|
return fillBounds.startRow < sourceBounds.startRow || fillBounds.endRow > sourceBounds.endRow || fillBounds.startCol < sourceBounds.startCol || fillBounds.endCol > sourceBounds.endCol;
|
|
3056
3137
|
}
|
|
3057
3138
|
|
|
3058
|
-
// src/components/ui/table/features/cell-selection/pasteData.ts
|
|
3059
|
-
function countLeadingEmptyCells(cells) {
|
|
3060
|
-
let depth = 0;
|
|
3061
|
-
while (depth < cells.length && cells[depth] === "") {
|
|
3062
|
-
depth += 1;
|
|
3063
|
-
}
|
|
3064
|
-
return depth;
|
|
3065
|
-
}
|
|
3066
|
-
function looksLikeSubtreeIndentation(leadingEmptyCounts) {
|
|
3067
|
-
if (leadingEmptyCounts.length === 0) return false;
|
|
3068
|
-
const firstDepth = leadingEmptyCounts[0] ?? 0;
|
|
3069
|
-
if (firstDepth !== 0) return false;
|
|
3070
|
-
return leadingEmptyCounts.some((depth) => depth > 0);
|
|
3071
|
-
}
|
|
3072
|
-
function parseClipboardTSVWithDepths(text) {
|
|
3073
|
-
if (!text) return { values: [], depths: [] };
|
|
3074
|
-
const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
3075
|
-
const withoutTrailing = normalized.replace(/\n+$/, "");
|
|
3076
|
-
if (!withoutTrailing) return { values: [], depths: [] };
|
|
3077
|
-
const rows = withoutTrailing.split("\n").map((line) => line.split(" "));
|
|
3078
|
-
const leadingEmptyCounts = rows.map(countLeadingEmptyCells);
|
|
3079
|
-
const treatAsDepth = looksLikeSubtreeIndentation(leadingEmptyCounts);
|
|
3080
|
-
const values = [];
|
|
3081
|
-
const depths = [];
|
|
3082
|
-
for (let index = 0; index < rows.length; index += 1) {
|
|
3083
|
-
const cells = rows[index] ?? [];
|
|
3084
|
-
const depth = leadingEmptyCounts[index] ?? 0;
|
|
3085
|
-
if (treatAsDepth) {
|
|
3086
|
-
values.push(cells.slice(depth));
|
|
3087
|
-
depths.push(depth);
|
|
3088
|
-
} else {
|
|
3089
|
-
values.push(cells);
|
|
3090
|
-
depths.push(0);
|
|
3091
|
-
}
|
|
3092
|
-
}
|
|
3093
|
-
return { values, depths };
|
|
3094
|
-
}
|
|
3095
|
-
function resolvePasteColumnIds(rows, startCol, width) {
|
|
3096
|
-
if (width <= 0) return [];
|
|
3097
|
-
const cells = rows[0]?.getVisibleCells() ?? [];
|
|
3098
|
-
const columnIds = [];
|
|
3099
|
-
for (let offset = 0; offset < width; offset += 1) {
|
|
3100
|
-
const cell = cells[startCol + offset];
|
|
3101
|
-
if (!cell) break;
|
|
3102
|
-
columnIds.push(cell.column.id);
|
|
3103
|
-
}
|
|
3104
|
-
return columnIds;
|
|
3105
|
-
}
|
|
3106
|
-
function buildRowsPastePayload(rows, startRow, startCol, text, mode, endRow = startRow) {
|
|
3107
|
-
const { values, depths } = parseClipboardTSVWithDepths(text);
|
|
3108
|
-
if (values.length === 0) return null;
|
|
3109
|
-
const width = Math.max(...values.map((row) => row.length), 0);
|
|
3110
|
-
if (width === 0) return null;
|
|
3111
|
-
const columnIds = resolvePasteColumnIds(rows, startCol, width);
|
|
3112
|
-
if (columnIds.length === 0) return null;
|
|
3113
|
-
const rowIds = [];
|
|
3114
|
-
for (let offset = 0; offset < values.length; offset += 1) {
|
|
3115
|
-
const row = rows[startRow + offset];
|
|
3116
|
-
if (!row) break;
|
|
3117
|
-
rowIds.push(row.id);
|
|
3118
|
-
}
|
|
3119
|
-
const anchorRow = rows[endRow] ?? rows[startRow];
|
|
3120
|
-
return {
|
|
3121
|
-
mode,
|
|
3122
|
-
startRow,
|
|
3123
|
-
startCol,
|
|
3124
|
-
endRow,
|
|
3125
|
-
rowIds,
|
|
3126
|
-
anchorRowId: anchorRow?.id ?? "",
|
|
3127
|
-
columnIds,
|
|
3128
|
-
values,
|
|
3129
|
-
depths
|
|
3130
|
-
};
|
|
3131
|
-
}
|
|
3132
|
-
function isEditablePasteTarget(target) {
|
|
3133
|
-
if (!(target instanceof HTMLElement)) return false;
|
|
3134
|
-
const tag = target.tagName;
|
|
3135
|
-
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
|
|
3136
|
-
return Boolean(target.isContentEditable);
|
|
3137
|
-
}
|
|
3138
|
-
|
|
3139
3139
|
// src/components/ui/table/features/cell-selection/useCellSelection.ts
|
|
3140
3140
|
function useCellSelection({
|
|
3141
3141
|
data,
|
|
@@ -3217,11 +3217,19 @@ function useCellSelection({
|
|
|
3217
3217
|
},
|
|
3218
3218
|
[enabled]
|
|
3219
3219
|
);
|
|
3220
|
+
const clearSelection = useCallback3(() => {
|
|
3221
|
+
const prev = dragStateRef.current;
|
|
3222
|
+
if (prev.start === null && prev.end === null && !prev.isSelecting && !prev.isFillDragging) {
|
|
3223
|
+
return;
|
|
3224
|
+
}
|
|
3225
|
+
dragStateRef.current = INITIAL_DRAG_STATE;
|
|
3226
|
+
setDragState(INITIAL_DRAG_STATE);
|
|
3227
|
+
}, []);
|
|
3220
3228
|
useEffect5(() => {
|
|
3221
3229
|
if (!enabled) {
|
|
3222
|
-
|
|
3230
|
+
clearSelection();
|
|
3223
3231
|
}
|
|
3224
|
-
}, [enabled]);
|
|
3232
|
+
}, [clearSelection, enabled]);
|
|
3225
3233
|
useEffect5(() => {
|
|
3226
3234
|
if (!enabled) return;
|
|
3227
3235
|
const handleKeyDown = (e) => {
|
|
@@ -3435,6 +3443,7 @@ function useCellSelection({
|
|
|
3435
3443
|
handleCellMouseDown,
|
|
3436
3444
|
handleCellMouseEnter,
|
|
3437
3445
|
handleFillHandleMouseDown,
|
|
3446
|
+
clearSelection,
|
|
3438
3447
|
copySelection
|
|
3439
3448
|
};
|
|
3440
3449
|
}
|
|
@@ -4033,6 +4042,7 @@ function useGlideTable(options) {
|
|
|
4033
4042
|
handleCellMouseDown,
|
|
4034
4043
|
handleCellMouseEnter,
|
|
4035
4044
|
handleFillHandleMouseDown,
|
|
4045
|
+
clearSelection: clearCellSelection,
|
|
4036
4046
|
copySelection
|
|
4037
4047
|
} = useCellSelection({
|
|
4038
4048
|
data: tableData,
|
|
@@ -4048,6 +4058,42 @@ function useGlideTable(options) {
|
|
|
4048
4058
|
cellRendererRegistry,
|
|
4049
4059
|
rootRef
|
|
4050
4060
|
});
|
|
4061
|
+
const clearRowSelection = useCallback5(() => {
|
|
4062
|
+
if (rowSelectionMode === "none") return;
|
|
4063
|
+
const hasSelection = Object.values(rowSelection).some(Boolean);
|
|
4064
|
+
if (!hasSelection) return;
|
|
4065
|
+
if (onRowSelectionChange) {
|
|
4066
|
+
onRowSelectionChange(() => ({}));
|
|
4067
|
+
return;
|
|
4068
|
+
}
|
|
4069
|
+
setInternalRowSelection({});
|
|
4070
|
+
}, [onRowSelectionChange, rowSelection, rowSelectionMode]);
|
|
4071
|
+
useEffect7(() => {
|
|
4072
|
+
const clearAllSelections = () => {
|
|
4073
|
+
clearCellSelection();
|
|
4074
|
+
clearRowSelection();
|
|
4075
|
+
};
|
|
4076
|
+
const handleKeyDown = (event) => {
|
|
4077
|
+
if (event.key !== "Escape") return;
|
|
4078
|
+
if (event.defaultPrevented) return;
|
|
4079
|
+
if (isEditablePasteTarget(event.target) || isEditablePasteTarget(document.activeElement)) {
|
|
4080
|
+
return;
|
|
4081
|
+
}
|
|
4082
|
+
clearAllSelections();
|
|
4083
|
+
};
|
|
4084
|
+
const handleMouseDown = (event) => {
|
|
4085
|
+
const root = rootRef.current;
|
|
4086
|
+
if (!root) return;
|
|
4087
|
+
if (event.target instanceof Node && root.contains(event.target)) return;
|
|
4088
|
+
clearAllSelections();
|
|
4089
|
+
};
|
|
4090
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4091
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
4092
|
+
return () => {
|
|
4093
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
4094
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
|
4095
|
+
};
|
|
4096
|
+
}, [clearCellSelection, clearRowSelection]);
|
|
4051
4097
|
const {
|
|
4052
4098
|
editingCell,
|
|
4053
4099
|
draftValue,
|