react-glide-table 2.3.1 → 2.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/dist/compound.cjs +98 -30
- package/dist/compound.d.cts +2 -2
- package/dist/compound.d.ts +2 -2
- package/dist/compound.js +98 -30
- package/dist/core.cjs +95 -29
- package/dist/core.d.cts +2 -2
- package/dist/core.d.ts +2 -2
- package/dist/core.js +95 -29
- package/dist/index.cjs +98 -30
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +98 -30
- package/dist/{types-DdeVn-9s.d.cts → types-hf2ruVdu.d.cts} +25 -1
- package/dist/{types-DdeVn-9s.d.ts → types-hf2ruVdu.d.ts} +25 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -75,6 +75,7 @@ export function Products({ data }: { data: Product[] }) {
|
|
|
75
75
|
| `className` / column `className` / `headerClassName` | Extra class hooks |
|
|
76
76
|
| `labels` / `summary` / `toolbar` | Copy and slot nodes |
|
|
77
77
|
| `Column.render` / `ColumnDef.cell` | Cell content custom render (prefer `update` via context) |
|
|
78
|
+
| `Column.copyValue` | Clipboard: `"display"` (default) / `"value"` / `"omit"` / `(ctx) => string` |
|
|
78
79
|
| `Column.kind` / `cellRenderers` | Built-in or custom cell kinds (override / add via registry) |
|
|
79
80
|
|
|
80
81
|
Row/cell **state** is exposed as `data-*` attributes for Tailwind variants:
|
|
@@ -240,6 +241,32 @@ Cell selection ships with clipboard shortcuts. The table parses TSV and emits st
|
|
|
240
241
|
|
|
241
242
|
Subtree copy encodes relative tree depth as leading tabs in the TSV so paste can rebuild parent/child nesting via `payload.depths`. Depth is only inferred when the clipboard looks like subtree indentation (first row unindented, at least one later row indented). Otherwise leading empty cells are kept as real values (e.g. Excel/Sheets blank first column) and `depths` stay `0`.
|
|
242
243
|
|
|
244
|
+
Per-column `copyValue` controls what lands on the clipboard when a custom `render` / `kind` is present:
|
|
245
|
+
|
|
246
|
+
- (default) / `"display"` — text from the rendered cell (buttons stay empty)
|
|
247
|
+
- `"value"` — raw accessor / field value (e.g. a count behind a button)
|
|
248
|
+
- `"omit"` — drop the column from the TSV entirely (neighbors shift left; same-table paste may misalign)
|
|
249
|
+
- `(ctx) => string` — fully custom clipboard string
|
|
250
|
+
|
|
251
|
+
```tsx
|
|
252
|
+
<ProductTable.Column
|
|
253
|
+
field="partCount"
|
|
254
|
+
copyValue="value"
|
|
255
|
+
render={({ value }) => <button type="button">{value}개 보기</button>}
|
|
256
|
+
>
|
|
257
|
+
Part No
|
|
258
|
+
</ProductTable.Column>
|
|
259
|
+
|
|
260
|
+
<ProductTable.Column
|
|
261
|
+
field="actions"
|
|
262
|
+
virtual
|
|
263
|
+
copyValue="omit"
|
|
264
|
+
render={() => <button type="button">Edit</button>}
|
|
265
|
+
>
|
|
266
|
+
Actions
|
|
267
|
+
</ProductTable.Column>
|
|
268
|
+
```
|
|
269
|
+
|
|
243
270
|
```tsx
|
|
244
271
|
import type { RowsPastePayload } from "react-glide-table/compound";
|
|
245
272
|
|
package/dist/compound.cjs
CHANGED
|
@@ -2742,6 +2742,39 @@ function isEditablePasteTarget(target) {
|
|
|
2742
2742
|
// src/components/ui/table/features/cell-selection/useCellSelection.ts
|
|
2743
2743
|
var import_react7 = require("react");
|
|
2744
2744
|
|
|
2745
|
+
// src/components/ui/table/features/cell-selection/activeCellSelectionOwner.ts
|
|
2746
|
+
var activeOwner = null;
|
|
2747
|
+
var clearByOwner = /* @__PURE__ */ new Map();
|
|
2748
|
+
function createCellSelectionOwner() {
|
|
2749
|
+
return /* @__PURE__ */ Symbol("cell-selection-owner");
|
|
2750
|
+
}
|
|
2751
|
+
function registerCellSelectionOwner(owner, clearSelection) {
|
|
2752
|
+
clearByOwner.set(owner, clearSelection);
|
|
2753
|
+
return () => {
|
|
2754
|
+
clearByOwner.delete(owner);
|
|
2755
|
+
if (activeOwner === owner) {
|
|
2756
|
+
activeOwner = null;
|
|
2757
|
+
}
|
|
2758
|
+
};
|
|
2759
|
+
}
|
|
2760
|
+
function claimCellSelectionOwner(owner) {
|
|
2761
|
+
if (activeOwner === owner) return;
|
|
2762
|
+
activeOwner = owner;
|
|
2763
|
+
for (const [id, clearSelection] of clearByOwner) {
|
|
2764
|
+
if (id !== owner) {
|
|
2765
|
+
clearSelection();
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
function isActiveCellSelectionOwner(owner) {
|
|
2770
|
+
return activeOwner === owner;
|
|
2771
|
+
}
|
|
2772
|
+
function releaseCellSelectionOwner(owner) {
|
|
2773
|
+
if (activeOwner === owner) {
|
|
2774
|
+
activeOwner = null;
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
|
|
2745
2778
|
// src/components/ui/table/features/cell-selection/copyData.ts
|
|
2746
2779
|
var import_react6 = require("react");
|
|
2747
2780
|
function isReactNodeIterable(node) {
|
|
@@ -2914,19 +2947,31 @@ function extractRenderedCopyText(node, value, cellPosition, root) {
|
|
|
2914
2947
|
function formatCopyCellText(rowData, columnDef, columnId, visibleRow, fallbackIndex, sourceCell, cellPosition, options) {
|
|
2915
2948
|
const meta = columnDef.meta;
|
|
2916
2949
|
const value = sourceCell ? sourceCell.getValue() : readRowColumnValue(rowData, columnDef);
|
|
2950
|
+
const row = visibleRow ?? createCopyRenderRow(rowData, fallbackIndex);
|
|
2951
|
+
const ctx = {
|
|
2952
|
+
value,
|
|
2953
|
+
row,
|
|
2954
|
+
index: row.index,
|
|
2955
|
+
columnId,
|
|
2956
|
+
cellProps: meta?.cellProps,
|
|
2957
|
+
update: () => {
|
|
2958
|
+
}
|
|
2959
|
+
};
|
|
2960
|
+
const copyValue = meta?.copyValue;
|
|
2961
|
+
if (typeof copyValue === "function") {
|
|
2962
|
+
try {
|
|
2963
|
+
return sanitizeClipboardCell(copyValue(ctx));
|
|
2964
|
+
} catch {
|
|
2965
|
+
return formatCellValue(value);
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
if (copyValue === "value") {
|
|
2969
|
+
return formatCellValue(value);
|
|
2970
|
+
}
|
|
2917
2971
|
const cellRender = meta?.cellRender;
|
|
2918
2972
|
if (typeof cellRender === "function") {
|
|
2919
2973
|
try {
|
|
2920
|
-
const
|
|
2921
|
-
const node = cellRender({
|
|
2922
|
-
value,
|
|
2923
|
-
row,
|
|
2924
|
-
index: row.index,
|
|
2925
|
-
columnId,
|
|
2926
|
-
cellProps: meta?.cellProps,
|
|
2927
|
-
update: () => {
|
|
2928
|
-
}
|
|
2929
|
-
});
|
|
2974
|
+
const node = cellRender(ctx);
|
|
2930
2975
|
return extractRenderedCopyText(node, value, cellPosition, options?.root);
|
|
2931
2976
|
} catch {
|
|
2932
2977
|
return formatCellValue(value);
|
|
@@ -2934,16 +2979,6 @@ function formatCopyCellText(rowData, columnDef, columnId, visibleRow, fallbackIn
|
|
|
2934
2979
|
}
|
|
2935
2980
|
if (options?.registry && meta?.kind && isPrimitiveCopyValue(value)) {
|
|
2936
2981
|
try {
|
|
2937
|
-
const row = visibleRow ?? createCopyRenderRow(rowData, fallbackIndex);
|
|
2938
|
-
const ctx = {
|
|
2939
|
-
value,
|
|
2940
|
-
row,
|
|
2941
|
-
index: row.index,
|
|
2942
|
-
columnId,
|
|
2943
|
-
cellProps: meta.cellProps,
|
|
2944
|
-
update: () => {
|
|
2945
|
-
}
|
|
2946
|
-
};
|
|
2947
2982
|
const renderer = resolveCellRenderer(options.registry, meta.kind, ctx);
|
|
2948
2983
|
if (renderer) {
|
|
2949
2984
|
const node = renderer.render(ctx);
|
|
@@ -3050,11 +3085,16 @@ function serializeCopyRowsToTSV(copyRows, visibleRows, bounds, depths, options)
|
|
|
3050
3085
|
const resolvedDepths = depths && depths.length === copyRows.length ? depths : copyRows.map((row) => getRowDepth(row));
|
|
3051
3086
|
const minDepth = Math.min(...resolvedDepths);
|
|
3052
3087
|
const visibleRowByOriginal = buildVisibleRowLookup(visibleRows);
|
|
3088
|
+
const copyableColumns = columnCells.flatMap((templateCell, colOffset) => {
|
|
3089
|
+
const meta = templateCell.column.columnDef.meta;
|
|
3090
|
+
if (meta?.copyValue === "omit") return [];
|
|
3091
|
+
return [{ templateCell, colOffset }];
|
|
3092
|
+
});
|
|
3053
3093
|
return copyRows.map((rowData, index) => {
|
|
3054
3094
|
const relativeDepth = Math.max(0, (resolvedDepths[index] ?? 0) - minDepth);
|
|
3055
3095
|
const visibleRow = visibleRowByOriginal.get(rowData);
|
|
3056
3096
|
const matchingCells = visibleRow?.getVisibleCells().slice(startCol, endCol + 1);
|
|
3057
|
-
const line =
|
|
3097
|
+
const line = copyableColumns.map(({ templateCell, colOffset }) => {
|
|
3058
3098
|
const sourceCell = matchingCells?.[colOffset];
|
|
3059
3099
|
const column = sourceCell?.column ?? templateCell.column;
|
|
3060
3100
|
return formatCopyCellText(
|
|
@@ -3163,6 +3203,7 @@ function useCellSelection({
|
|
|
3163
3203
|
cellRendererRegistry,
|
|
3164
3204
|
rootRef
|
|
3165
3205
|
}) {
|
|
3206
|
+
const ownerRef = (0, import_react7.useRef)(createCellSelectionOwner());
|
|
3166
3207
|
const [dragState, setDragState] = (0, import_react7.useState)(INITIAL_DRAG_STATE);
|
|
3167
3208
|
const pendingPasteModeRef = (0, import_react7.useRef)(null);
|
|
3168
3209
|
const dragStateRef = (0, import_react7.useRef)(dragState);
|
|
@@ -3174,6 +3215,7 @@ function useCellSelection({
|
|
|
3174
3215
|
const handleCellMouseDown = (0, import_react7.useCallback)(
|
|
3175
3216
|
(rowIndex, colIndex, options) => {
|
|
3176
3217
|
if (!enabled) return;
|
|
3218
|
+
claimCellSelectionOwner(ownerRef.current);
|
|
3177
3219
|
setDragState((prev) => {
|
|
3178
3220
|
if (options?.shiftKey && prev.start) {
|
|
3179
3221
|
return {
|
|
@@ -3215,6 +3257,7 @@ function useCellSelection({
|
|
|
3215
3257
|
const handleFillHandleMouseDown = (0, import_react7.useCallback)(
|
|
3216
3258
|
(rowIndex, colIndex) => {
|
|
3217
3259
|
if (!enabled) return;
|
|
3260
|
+
claimCellSelectionOwner(ownerRef.current);
|
|
3218
3261
|
setDragState((prev) => {
|
|
3219
3262
|
const bounds = getCellSelectionBounds(prev.start, prev.end);
|
|
3220
3263
|
if (!bounds) return prev;
|
|
@@ -3234,6 +3277,7 @@ function useCellSelection({
|
|
|
3234
3277
|
if (prev.start === null && prev.end === null && !prev.isSelecting && !prev.isFillDragging) {
|
|
3235
3278
|
return;
|
|
3236
3279
|
}
|
|
3280
|
+
releaseCellSelectionOwner(ownerRef.current);
|
|
3237
3281
|
dragStateRef.current = INITIAL_DRAG_STATE;
|
|
3238
3282
|
setDragState(INITIAL_DRAG_STATE);
|
|
3239
3283
|
}, []);
|
|
@@ -3242,9 +3286,13 @@ function useCellSelection({
|
|
|
3242
3286
|
clearSelection();
|
|
3243
3287
|
}
|
|
3244
3288
|
}, [clearSelection, enabled]);
|
|
3289
|
+
(0, import_react7.useEffect)(() => {
|
|
3290
|
+
return registerCellSelectionOwner(ownerRef.current, clearSelection);
|
|
3291
|
+
}, [clearSelection]);
|
|
3245
3292
|
(0, import_react7.useEffect)(() => {
|
|
3246
3293
|
if (!enabled) return;
|
|
3247
3294
|
const handleKeyDown = (e) => {
|
|
3295
|
+
if (!isActiveCellSelectionOwner(ownerRef.current)) return;
|
|
3248
3296
|
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
|
3249
3297
|
if (isEditablePasteTarget(e.target) || isEditablePasteTarget(document.activeElement)) {
|
|
3250
3298
|
return;
|
|
@@ -3310,6 +3358,7 @@ function useCellSelection({
|
|
|
3310
3358
|
(0, import_react7.useEffect)(() => {
|
|
3311
3359
|
if (!enabled) return;
|
|
3312
3360
|
const handleKeyDown = (e) => {
|
|
3361
|
+
if (!isActiveCellSelectionOwner(ownerRef.current)) return;
|
|
3313
3362
|
if (!activeSelectionBounds) return;
|
|
3314
3363
|
if (!(e.ctrlKey || e.metaKey)) return;
|
|
3315
3364
|
if (isEditablePasteTarget(e.target) || isEditablePasteTarget(document.activeElement)) {
|
|
@@ -3346,6 +3395,7 @@ function useCellSelection({
|
|
|
3346
3395
|
const pasteHandledRef = { current: false };
|
|
3347
3396
|
const ignoreNextPasteRef = { current: false };
|
|
3348
3397
|
const handleKeyDown = (e) => {
|
|
3398
|
+
if (!isActiveCellSelectionOwner(ownerRef.current)) return;
|
|
3349
3399
|
if (!activeSelectionBounds) return;
|
|
3350
3400
|
if (!(e.ctrlKey || e.metaKey)) return;
|
|
3351
3401
|
if (e.key.toLowerCase() !== "v") return;
|
|
@@ -3366,6 +3416,7 @@ function useCellSelection({
|
|
|
3366
3416
|
const text = await navigator.clipboard.readText();
|
|
3367
3417
|
if (pasteHandledRef.current) return;
|
|
3368
3418
|
if (pendingPasteModeRef.current !== mode) return;
|
|
3419
|
+
if (!isActiveCellSelectionOwner(ownerRef.current)) return;
|
|
3369
3420
|
if (!text) return;
|
|
3370
3421
|
pasteHandledRef.current = true;
|
|
3371
3422
|
emitRowsPaste(text, mode);
|
|
@@ -3375,6 +3426,7 @@ function useCellSelection({
|
|
|
3375
3426
|
})();
|
|
3376
3427
|
};
|
|
3377
3428
|
const handlePaste = (e) => {
|
|
3429
|
+
if (!isActiveCellSelectionOwner(ownerRef.current)) return;
|
|
3378
3430
|
if (!activeSelectionBounds) return;
|
|
3379
3431
|
if (isEditablePasteTarget(e.target) || isEditablePasteTarget(document.activeElement)) {
|
|
3380
3432
|
return;
|
|
@@ -3460,6 +3512,25 @@ function useCellSelection({
|
|
|
3460
3512
|
};
|
|
3461
3513
|
}
|
|
3462
3514
|
|
|
3515
|
+
// src/components/ui/table/features/selection-dismiss/isOutsideDismissTarget.ts
|
|
3516
|
+
var OVERLAY_DISMISS_IGNORE_SELECTOR = [
|
|
3517
|
+
'[role="dialog"]',
|
|
3518
|
+
'[role="alertdialog"]',
|
|
3519
|
+
'[role="menu"]',
|
|
3520
|
+
'[role="listbox"]',
|
|
3521
|
+
'[role="tooltip"]',
|
|
3522
|
+
'[aria-modal="true"]',
|
|
3523
|
+
"[data-radix-portal]",
|
|
3524
|
+
"[data-radix-popper-content-wrapper]",
|
|
3525
|
+
"[data-floating-ui-portal]",
|
|
3526
|
+
"[data-table-ignore-outside-dismiss]"
|
|
3527
|
+
].join(",");
|
|
3528
|
+
function isOverlayDismissIgnoreTarget(target) {
|
|
3529
|
+
const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
|
|
3530
|
+
if (!element) return false;
|
|
3531
|
+
return element.closest(OVERLAY_DISMISS_IGNORE_SELECTOR) !== null;
|
|
3532
|
+
}
|
|
3533
|
+
|
|
3463
3534
|
// src/components/ui/table/features/inline-search/useInlineSearch.ts
|
|
3464
3535
|
var import_react8 = require("react");
|
|
3465
3536
|
var EMPTY_MATCH_KEYS = /* @__PURE__ */ new Set();
|
|
@@ -4084,19 +4155,14 @@ function useGlideTable(options) {
|
|
|
4084
4155
|
if (isEditablePasteTarget(event.target) || isEditablePasteTarget(document.activeElement)) {
|
|
4085
4156
|
return;
|
|
4086
4157
|
}
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
const root = rootRef.current;
|
|
4091
|
-
if (!root) return;
|
|
4092
|
-
if (event.target instanceof Node && root.contains(event.target)) return;
|
|
4158
|
+
if (isOverlayDismissIgnoreTarget(event.target) || isOverlayDismissIgnoreTarget(document.activeElement)) {
|
|
4159
|
+
return;
|
|
4160
|
+
}
|
|
4093
4161
|
clearAllSelections();
|
|
4094
4162
|
};
|
|
4095
4163
|
window.addEventListener("keydown", handleKeyDown);
|
|
4096
|
-
document.addEventListener("mousedown", handleMouseDown);
|
|
4097
4164
|
return () => {
|
|
4098
4165
|
window.removeEventListener("keydown", handleKeyDown);
|
|
4099
|
-
document.removeEventListener("mousedown", handleMouseDown);
|
|
4100
4166
|
};
|
|
4101
4167
|
}, [clearCellSelection, clearRowSelection]);
|
|
4102
4168
|
const {
|
|
@@ -4971,7 +5037,8 @@ function buildColumnDef(props, sort, onSort) {
|
|
|
4971
5037
|
cellProps,
|
|
4972
5038
|
className,
|
|
4973
5039
|
headerClassName,
|
|
4974
|
-
render
|
|
5040
|
+
render,
|
|
5041
|
+
copyValue
|
|
4975
5042
|
} = props;
|
|
4976
5043
|
return {
|
|
4977
5044
|
id: field,
|
|
@@ -5005,6 +5072,7 @@ function buildColumnDef(props, sort, onSort) {
|
|
|
5005
5072
|
kind,
|
|
5006
5073
|
cellProps,
|
|
5007
5074
|
cellRender: render,
|
|
5075
|
+
copyValue,
|
|
5008
5076
|
frozen,
|
|
5009
5077
|
reorderable,
|
|
5010
5078
|
width,
|
package/dist/compound.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ReactElement } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
export { B as BuiltinCellKind, C as CellKind, a as CellRenderContext, b as CellRenderFn, c as CellRenderer,
|
|
3
|
+
import { m as DataTableProps, s as TableColumnProps, T as TableColumnGroupProps, t as TableProps } from './types-hf2ruVdu.cjs';
|
|
4
|
+
export { B as BuiltinCellKind, C as CellKind, a as CellRenderContext, b as CellRenderFn, c as CellRenderer, d as ColumnCopyValue, g as ColumnFreezeMeta, i as ColumnFreezeSide, j as DataTableClassNames, l as DataTableLabels, n as DataTableScrollSlotProps, o as DataTableSlots, P as PasteMode, R as RowSelectionMode, p as RowsPastePayload, q as SearchResultItem } from './types-hf2ruVdu.cjs';
|
|
5
5
|
export { ColumnDef, ColumnOrderState, ColumnResizeMode, ColumnSizingState, RowSelectionState } from '@tanstack/react-table';
|
|
6
6
|
|
|
7
7
|
/**
|
package/dist/compound.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ReactElement } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
export { B as BuiltinCellKind, C as CellKind, a as CellRenderContext, b as CellRenderFn, c as CellRenderer,
|
|
3
|
+
import { m as DataTableProps, s as TableColumnProps, T as TableColumnGroupProps, t as TableProps } from './types-hf2ruVdu.js';
|
|
4
|
+
export { B as BuiltinCellKind, C as CellKind, a as CellRenderContext, b as CellRenderFn, c as CellRenderer, d as ColumnCopyValue, g as ColumnFreezeMeta, i as ColumnFreezeSide, j as DataTableClassNames, l as DataTableLabels, n as DataTableScrollSlotProps, o as DataTableSlots, P as PasteMode, R as RowSelectionMode, p as RowsPastePayload, q as SearchResultItem } from './types-hf2ruVdu.js';
|
|
5
5
|
export { ColumnDef, ColumnOrderState, ColumnResizeMode, ColumnSizingState, RowSelectionState } from '@tanstack/react-table';
|
|
6
6
|
|
|
7
7
|
/**
|
package/dist/compound.js
CHANGED
|
@@ -2730,6 +2730,39 @@ function isEditablePasteTarget(target) {
|
|
|
2730
2730
|
// src/components/ui/table/features/cell-selection/useCellSelection.ts
|
|
2731
2731
|
import { useCallback as useCallback3, useEffect as useEffect5, useRef as useRef5, useState as useState3 } from "react";
|
|
2732
2732
|
|
|
2733
|
+
// src/components/ui/table/features/cell-selection/activeCellSelectionOwner.ts
|
|
2734
|
+
var activeOwner = null;
|
|
2735
|
+
var clearByOwner = /* @__PURE__ */ new Map();
|
|
2736
|
+
function createCellSelectionOwner() {
|
|
2737
|
+
return /* @__PURE__ */ Symbol("cell-selection-owner");
|
|
2738
|
+
}
|
|
2739
|
+
function registerCellSelectionOwner(owner, clearSelection) {
|
|
2740
|
+
clearByOwner.set(owner, clearSelection);
|
|
2741
|
+
return () => {
|
|
2742
|
+
clearByOwner.delete(owner);
|
|
2743
|
+
if (activeOwner === owner) {
|
|
2744
|
+
activeOwner = null;
|
|
2745
|
+
}
|
|
2746
|
+
};
|
|
2747
|
+
}
|
|
2748
|
+
function claimCellSelectionOwner(owner) {
|
|
2749
|
+
if (activeOwner === owner) return;
|
|
2750
|
+
activeOwner = owner;
|
|
2751
|
+
for (const [id, clearSelection] of clearByOwner) {
|
|
2752
|
+
if (id !== owner) {
|
|
2753
|
+
clearSelection();
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
function isActiveCellSelectionOwner(owner) {
|
|
2758
|
+
return activeOwner === owner;
|
|
2759
|
+
}
|
|
2760
|
+
function releaseCellSelectionOwner(owner) {
|
|
2761
|
+
if (activeOwner === owner) {
|
|
2762
|
+
activeOwner = null;
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2733
2766
|
// src/components/ui/table/features/cell-selection/copyData.ts
|
|
2734
2767
|
import { isValidElement } from "react";
|
|
2735
2768
|
function isReactNodeIterable(node) {
|
|
@@ -2902,19 +2935,31 @@ function extractRenderedCopyText(node, value, cellPosition, root) {
|
|
|
2902
2935
|
function formatCopyCellText(rowData, columnDef, columnId, visibleRow, fallbackIndex, sourceCell, cellPosition, options) {
|
|
2903
2936
|
const meta = columnDef.meta;
|
|
2904
2937
|
const value = sourceCell ? sourceCell.getValue() : readRowColumnValue(rowData, columnDef);
|
|
2938
|
+
const row = visibleRow ?? createCopyRenderRow(rowData, fallbackIndex);
|
|
2939
|
+
const ctx = {
|
|
2940
|
+
value,
|
|
2941
|
+
row,
|
|
2942
|
+
index: row.index,
|
|
2943
|
+
columnId,
|
|
2944
|
+
cellProps: meta?.cellProps,
|
|
2945
|
+
update: () => {
|
|
2946
|
+
}
|
|
2947
|
+
};
|
|
2948
|
+
const copyValue = meta?.copyValue;
|
|
2949
|
+
if (typeof copyValue === "function") {
|
|
2950
|
+
try {
|
|
2951
|
+
return sanitizeClipboardCell(copyValue(ctx));
|
|
2952
|
+
} catch {
|
|
2953
|
+
return formatCellValue(value);
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
if (copyValue === "value") {
|
|
2957
|
+
return formatCellValue(value);
|
|
2958
|
+
}
|
|
2905
2959
|
const cellRender = meta?.cellRender;
|
|
2906
2960
|
if (typeof cellRender === "function") {
|
|
2907
2961
|
try {
|
|
2908
|
-
const
|
|
2909
|
-
const node = cellRender({
|
|
2910
|
-
value,
|
|
2911
|
-
row,
|
|
2912
|
-
index: row.index,
|
|
2913
|
-
columnId,
|
|
2914
|
-
cellProps: meta?.cellProps,
|
|
2915
|
-
update: () => {
|
|
2916
|
-
}
|
|
2917
|
-
});
|
|
2962
|
+
const node = cellRender(ctx);
|
|
2918
2963
|
return extractRenderedCopyText(node, value, cellPosition, options?.root);
|
|
2919
2964
|
} catch {
|
|
2920
2965
|
return formatCellValue(value);
|
|
@@ -2922,16 +2967,6 @@ function formatCopyCellText(rowData, columnDef, columnId, visibleRow, fallbackIn
|
|
|
2922
2967
|
}
|
|
2923
2968
|
if (options?.registry && meta?.kind && isPrimitiveCopyValue(value)) {
|
|
2924
2969
|
try {
|
|
2925
|
-
const row = visibleRow ?? createCopyRenderRow(rowData, fallbackIndex);
|
|
2926
|
-
const ctx = {
|
|
2927
|
-
value,
|
|
2928
|
-
row,
|
|
2929
|
-
index: row.index,
|
|
2930
|
-
columnId,
|
|
2931
|
-
cellProps: meta.cellProps,
|
|
2932
|
-
update: () => {
|
|
2933
|
-
}
|
|
2934
|
-
};
|
|
2935
2970
|
const renderer = resolveCellRenderer(options.registry, meta.kind, ctx);
|
|
2936
2971
|
if (renderer) {
|
|
2937
2972
|
const node = renderer.render(ctx);
|
|
@@ -3038,11 +3073,16 @@ function serializeCopyRowsToTSV(copyRows, visibleRows, bounds, depths, options)
|
|
|
3038
3073
|
const resolvedDepths = depths && depths.length === copyRows.length ? depths : copyRows.map((row) => getRowDepth(row));
|
|
3039
3074
|
const minDepth = Math.min(...resolvedDepths);
|
|
3040
3075
|
const visibleRowByOriginal = buildVisibleRowLookup(visibleRows);
|
|
3076
|
+
const copyableColumns = columnCells.flatMap((templateCell, colOffset) => {
|
|
3077
|
+
const meta = templateCell.column.columnDef.meta;
|
|
3078
|
+
if (meta?.copyValue === "omit") return [];
|
|
3079
|
+
return [{ templateCell, colOffset }];
|
|
3080
|
+
});
|
|
3041
3081
|
return copyRows.map((rowData, index) => {
|
|
3042
3082
|
const relativeDepth = Math.max(0, (resolvedDepths[index] ?? 0) - minDepth);
|
|
3043
3083
|
const visibleRow = visibleRowByOriginal.get(rowData);
|
|
3044
3084
|
const matchingCells = visibleRow?.getVisibleCells().slice(startCol, endCol + 1);
|
|
3045
|
-
const line =
|
|
3085
|
+
const line = copyableColumns.map(({ templateCell, colOffset }) => {
|
|
3046
3086
|
const sourceCell = matchingCells?.[colOffset];
|
|
3047
3087
|
const column = sourceCell?.column ?? templateCell.column;
|
|
3048
3088
|
return formatCopyCellText(
|
|
@@ -3151,6 +3191,7 @@ function useCellSelection({
|
|
|
3151
3191
|
cellRendererRegistry,
|
|
3152
3192
|
rootRef
|
|
3153
3193
|
}) {
|
|
3194
|
+
const ownerRef = useRef5(createCellSelectionOwner());
|
|
3154
3195
|
const [dragState, setDragState] = useState3(INITIAL_DRAG_STATE);
|
|
3155
3196
|
const pendingPasteModeRef = useRef5(null);
|
|
3156
3197
|
const dragStateRef = useRef5(dragState);
|
|
@@ -3162,6 +3203,7 @@ function useCellSelection({
|
|
|
3162
3203
|
const handleCellMouseDown = useCallback3(
|
|
3163
3204
|
(rowIndex, colIndex, options) => {
|
|
3164
3205
|
if (!enabled) return;
|
|
3206
|
+
claimCellSelectionOwner(ownerRef.current);
|
|
3165
3207
|
setDragState((prev) => {
|
|
3166
3208
|
if (options?.shiftKey && prev.start) {
|
|
3167
3209
|
return {
|
|
@@ -3203,6 +3245,7 @@ function useCellSelection({
|
|
|
3203
3245
|
const handleFillHandleMouseDown = useCallback3(
|
|
3204
3246
|
(rowIndex, colIndex) => {
|
|
3205
3247
|
if (!enabled) return;
|
|
3248
|
+
claimCellSelectionOwner(ownerRef.current);
|
|
3206
3249
|
setDragState((prev) => {
|
|
3207
3250
|
const bounds = getCellSelectionBounds(prev.start, prev.end);
|
|
3208
3251
|
if (!bounds) return prev;
|
|
@@ -3222,6 +3265,7 @@ function useCellSelection({
|
|
|
3222
3265
|
if (prev.start === null && prev.end === null && !prev.isSelecting && !prev.isFillDragging) {
|
|
3223
3266
|
return;
|
|
3224
3267
|
}
|
|
3268
|
+
releaseCellSelectionOwner(ownerRef.current);
|
|
3225
3269
|
dragStateRef.current = INITIAL_DRAG_STATE;
|
|
3226
3270
|
setDragState(INITIAL_DRAG_STATE);
|
|
3227
3271
|
}, []);
|
|
@@ -3230,9 +3274,13 @@ function useCellSelection({
|
|
|
3230
3274
|
clearSelection();
|
|
3231
3275
|
}
|
|
3232
3276
|
}, [clearSelection, enabled]);
|
|
3277
|
+
useEffect5(() => {
|
|
3278
|
+
return registerCellSelectionOwner(ownerRef.current, clearSelection);
|
|
3279
|
+
}, [clearSelection]);
|
|
3233
3280
|
useEffect5(() => {
|
|
3234
3281
|
if (!enabled) return;
|
|
3235
3282
|
const handleKeyDown = (e) => {
|
|
3283
|
+
if (!isActiveCellSelectionOwner(ownerRef.current)) return;
|
|
3236
3284
|
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
|
3237
3285
|
if (isEditablePasteTarget(e.target) || isEditablePasteTarget(document.activeElement)) {
|
|
3238
3286
|
return;
|
|
@@ -3298,6 +3346,7 @@ function useCellSelection({
|
|
|
3298
3346
|
useEffect5(() => {
|
|
3299
3347
|
if (!enabled) return;
|
|
3300
3348
|
const handleKeyDown = (e) => {
|
|
3349
|
+
if (!isActiveCellSelectionOwner(ownerRef.current)) return;
|
|
3301
3350
|
if (!activeSelectionBounds) return;
|
|
3302
3351
|
if (!(e.ctrlKey || e.metaKey)) return;
|
|
3303
3352
|
if (isEditablePasteTarget(e.target) || isEditablePasteTarget(document.activeElement)) {
|
|
@@ -3334,6 +3383,7 @@ function useCellSelection({
|
|
|
3334
3383
|
const pasteHandledRef = { current: false };
|
|
3335
3384
|
const ignoreNextPasteRef = { current: false };
|
|
3336
3385
|
const handleKeyDown = (e) => {
|
|
3386
|
+
if (!isActiveCellSelectionOwner(ownerRef.current)) return;
|
|
3337
3387
|
if (!activeSelectionBounds) return;
|
|
3338
3388
|
if (!(e.ctrlKey || e.metaKey)) return;
|
|
3339
3389
|
if (e.key.toLowerCase() !== "v") return;
|
|
@@ -3354,6 +3404,7 @@ function useCellSelection({
|
|
|
3354
3404
|
const text = await navigator.clipboard.readText();
|
|
3355
3405
|
if (pasteHandledRef.current) return;
|
|
3356
3406
|
if (pendingPasteModeRef.current !== mode) return;
|
|
3407
|
+
if (!isActiveCellSelectionOwner(ownerRef.current)) return;
|
|
3357
3408
|
if (!text) return;
|
|
3358
3409
|
pasteHandledRef.current = true;
|
|
3359
3410
|
emitRowsPaste(text, mode);
|
|
@@ -3363,6 +3414,7 @@ function useCellSelection({
|
|
|
3363
3414
|
})();
|
|
3364
3415
|
};
|
|
3365
3416
|
const handlePaste = (e) => {
|
|
3417
|
+
if (!isActiveCellSelectionOwner(ownerRef.current)) return;
|
|
3366
3418
|
if (!activeSelectionBounds) return;
|
|
3367
3419
|
if (isEditablePasteTarget(e.target) || isEditablePasteTarget(document.activeElement)) {
|
|
3368
3420
|
return;
|
|
@@ -3448,6 +3500,25 @@ function useCellSelection({
|
|
|
3448
3500
|
};
|
|
3449
3501
|
}
|
|
3450
3502
|
|
|
3503
|
+
// src/components/ui/table/features/selection-dismiss/isOutsideDismissTarget.ts
|
|
3504
|
+
var OVERLAY_DISMISS_IGNORE_SELECTOR = [
|
|
3505
|
+
'[role="dialog"]',
|
|
3506
|
+
'[role="alertdialog"]',
|
|
3507
|
+
'[role="menu"]',
|
|
3508
|
+
'[role="listbox"]',
|
|
3509
|
+
'[role="tooltip"]',
|
|
3510
|
+
'[aria-modal="true"]',
|
|
3511
|
+
"[data-radix-portal]",
|
|
3512
|
+
"[data-radix-popper-content-wrapper]",
|
|
3513
|
+
"[data-floating-ui-portal]",
|
|
3514
|
+
"[data-table-ignore-outside-dismiss]"
|
|
3515
|
+
].join(",");
|
|
3516
|
+
function isOverlayDismissIgnoreTarget(target) {
|
|
3517
|
+
const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
|
|
3518
|
+
if (!element) return false;
|
|
3519
|
+
return element.closest(OVERLAY_DISMISS_IGNORE_SELECTOR) !== null;
|
|
3520
|
+
}
|
|
3521
|
+
|
|
3451
3522
|
// src/components/ui/table/features/inline-search/useInlineSearch.ts
|
|
3452
3523
|
import {
|
|
3453
3524
|
useCallback as useCallback4,
|
|
@@ -4079,19 +4150,14 @@ function useGlideTable(options) {
|
|
|
4079
4150
|
if (isEditablePasteTarget(event.target) || isEditablePasteTarget(document.activeElement)) {
|
|
4080
4151
|
return;
|
|
4081
4152
|
}
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
const root = rootRef.current;
|
|
4086
|
-
if (!root) return;
|
|
4087
|
-
if (event.target instanceof Node && root.contains(event.target)) return;
|
|
4153
|
+
if (isOverlayDismissIgnoreTarget(event.target) || isOverlayDismissIgnoreTarget(document.activeElement)) {
|
|
4154
|
+
return;
|
|
4155
|
+
}
|
|
4088
4156
|
clearAllSelections();
|
|
4089
4157
|
};
|
|
4090
4158
|
window.addEventListener("keydown", handleKeyDown);
|
|
4091
|
-
document.addEventListener("mousedown", handleMouseDown);
|
|
4092
4159
|
return () => {
|
|
4093
4160
|
window.removeEventListener("keydown", handleKeyDown);
|
|
4094
|
-
document.removeEventListener("mousedown", handleMouseDown);
|
|
4095
4161
|
};
|
|
4096
4162
|
}, [clearCellSelection, clearRowSelection]);
|
|
4097
4163
|
const {
|
|
@@ -4966,7 +5032,8 @@ function buildColumnDef(props, sort, onSort) {
|
|
|
4966
5032
|
cellProps,
|
|
4967
5033
|
className,
|
|
4968
5034
|
headerClassName,
|
|
4969
|
-
render
|
|
5035
|
+
render,
|
|
5036
|
+
copyValue
|
|
4970
5037
|
} = props;
|
|
4971
5038
|
return {
|
|
4972
5039
|
id: field,
|
|
@@ -5000,6 +5067,7 @@ function buildColumnDef(props, sort, onSort) {
|
|
|
5000
5067
|
kind,
|
|
5001
5068
|
cellProps,
|
|
5002
5069
|
cellRender: render,
|
|
5070
|
+
copyValue,
|
|
5003
5071
|
frozen,
|
|
5004
5072
|
reorderable,
|
|
5005
5073
|
width,
|