@lensui/lens-table 0.1.82 → 0.1.84
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 +5 -0
- package/dist/index.cjs +122 -53
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +203 -134
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/Table.tsx
|
|
2
|
-
import { forwardRef, useImperativeHandle, Fragment as Fragment2, useCallback as
|
|
2
|
+
import { forwardRef, useImperativeHandle, Fragment as Fragment2, useCallback as useCallback3, useEffect as useEffect3, useLayoutEffect as useLayoutEffect3, useMemo as useMemo2, useRef as useRef4, useState as useState6 } from "react";
|
|
3
3
|
import { flushSync } from "react-dom";
|
|
4
4
|
|
|
5
5
|
// src/components/EmptyState.tsx
|
|
@@ -199,7 +199,7 @@ function DefaultEmptyState({ label = ZH_CN_GRID_LABELS.empty }) {
|
|
|
199
199
|
// src/components/editors/ChoiceEditor.tsx
|
|
200
200
|
import { Portal } from "@ark-ui/react/portal";
|
|
201
201
|
import { Select, createListCollection } from "@ark-ui/react/select";
|
|
202
|
-
import { useEffect, useId as useId2, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
202
|
+
import { useCallback, useEffect, useId as useId2, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
203
203
|
|
|
204
204
|
// src/icons/gridIcons.tsx
|
|
205
205
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
@@ -315,7 +315,7 @@ function getSearchableChoicePopupHorizontalLayout(anchorLeft, anchorWidth, longe
|
|
|
315
315
|
);
|
|
316
316
|
return { left, width };
|
|
317
317
|
}
|
|
318
|
-
function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownHeight, style, labels, onChange, onCommit, onCancel }) {
|
|
318
|
+
function SearchableChoiceEditor({ value, options, allowCustomValue, strictOptions, maxDropdownHeight, style, labels, onChange, onCommit, onCancel }) {
|
|
319
319
|
const editorRef = useRef(null);
|
|
320
320
|
const popupRef = useRef(null);
|
|
321
321
|
const activeOptionRef = useRef(null);
|
|
@@ -325,6 +325,7 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
|
|
|
325
325
|
const listboxId = useId2();
|
|
326
326
|
const originalValue = originalValueRef.current;
|
|
327
327
|
const [inputValue, setInputValue] = useState(value);
|
|
328
|
+
const [hasTyped, setHasTyped] = useState(false);
|
|
328
329
|
const [activeIndex, setActiveIndex] = useState(() => {
|
|
329
330
|
const selectedIndex = options.findIndex((option) => option.value === value);
|
|
330
331
|
return selectedIndex >= 0 ? selectedIndex : 0;
|
|
@@ -334,10 +335,23 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
|
|
|
334
335
|
visibility: "hidden"
|
|
335
336
|
});
|
|
336
337
|
const filteredOptions = useMemo(() => {
|
|
338
|
+
if (strictOptions) {
|
|
339
|
+
if (!hasTyped) return options;
|
|
340
|
+
if (inputValue === "") return options.filter((option) => option.value === "");
|
|
341
|
+
const strictQuery = inputValue.trim().toLocaleLowerCase();
|
|
342
|
+
if (!strictQuery) return [];
|
|
343
|
+
return options.filter((option) => option.label.toLocaleLowerCase().includes(strictQuery) || option.value.toLocaleLowerCase().includes(strictQuery));
|
|
344
|
+
}
|
|
337
345
|
const query = inputValue.trim().toLocaleLowerCase();
|
|
338
346
|
if (!query || query === originalValue.toLocaleLowerCase()) return options;
|
|
339
347
|
return options.filter((option) => option.label.toLocaleLowerCase().includes(query) || option.value.toLocaleLowerCase().includes(query));
|
|
340
|
-
}, [inputValue, options, originalValue]);
|
|
348
|
+
}, [hasTyped, inputValue, options, originalValue, strictOptions]);
|
|
349
|
+
const exactInputOption = options.find((option) => option.value === inputValue);
|
|
350
|
+
const selectedValue = exactInputOption?.value;
|
|
351
|
+
const resolveInputValue = useCallback(() => {
|
|
352
|
+
if (strictOptions) return exactInputOption?.value ?? originalValue;
|
|
353
|
+
return allowCustomValue ? inputValue || originalValue : originalValue;
|
|
354
|
+
}, [allowCustomValue, exactInputOption, inputValue, originalValue, strictOptions]);
|
|
341
355
|
useLayoutEffect(() => {
|
|
342
356
|
const positionPopup = () => {
|
|
343
357
|
const rect = editorRef.current?.getBoundingClientRect();
|
|
@@ -404,11 +418,11 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
|
|
|
404
418
|
const target = event.target;
|
|
405
419
|
if (!(target instanceof Node)) return;
|
|
406
420
|
if (editorRef.current?.contains(target) || popupRef.current?.contains(target)) return;
|
|
407
|
-
onCommit(
|
|
421
|
+
onCommit(resolveInputValue());
|
|
408
422
|
};
|
|
409
423
|
document.addEventListener("pointerdown", handleOutsidePointer, true);
|
|
410
424
|
return () => document.removeEventListener("pointerdown", handleOutsidePointer, true);
|
|
411
|
-
}, [
|
|
425
|
+
}, [onCommit, resolveInputValue]);
|
|
412
426
|
const selectOption = (option) => {
|
|
413
427
|
onChange(option.value);
|
|
414
428
|
onCommit(option.value);
|
|
@@ -430,7 +444,7 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
|
|
|
430
444
|
event.preventDefault();
|
|
431
445
|
const option = filteredOptions[activeIndex];
|
|
432
446
|
if (option) selectOption(option);
|
|
433
|
-
else if (allowCustomValue) onCommit(
|
|
447
|
+
else if (allowCustomValue || strictOptions) onCommit(resolveInputValue());
|
|
434
448
|
}
|
|
435
449
|
};
|
|
436
450
|
return /* @__PURE__ */ jsxs3("div", { ref: editorRef, className: "rvg-choice-editor rvg-searchable-choice-editor", style, children: [
|
|
@@ -444,6 +458,7 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
|
|
|
444
458
|
"aria-controls": listboxId,
|
|
445
459
|
onFocus: (event) => event.currentTarget.select(),
|
|
446
460
|
onChange: (event) => {
|
|
461
|
+
setHasTyped(true);
|
|
447
462
|
setInputValue(event.target.value);
|
|
448
463
|
onChange(event.target.value);
|
|
449
464
|
navigationSourceRef.current = "filter";
|
|
@@ -459,8 +474,8 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
|
|
|
459
474
|
ref: index === activeIndex ? activeOptionRef : void 0,
|
|
460
475
|
type: "button",
|
|
461
476
|
role: "option",
|
|
462
|
-
"aria-selected": option.value ===
|
|
463
|
-
className: `rvg-choice-item${index === activeIndex ? " is-active" : ""}${option.value ===
|
|
477
|
+
"aria-selected": option.value === selectedValue,
|
|
478
|
+
className: `rvg-choice-item${index === activeIndex ? " is-active" : ""}${option.value === selectedValue ? " is-selected" : ""}`,
|
|
464
479
|
onPointerDown: (event) => event.preventDefault(),
|
|
465
480
|
onMouseEnter: () => {
|
|
466
481
|
navigationSourceRef.current = "pointer";
|
|
@@ -469,7 +484,7 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
|
|
|
469
484
|
onClick: () => selectOption(option),
|
|
470
485
|
children: [
|
|
471
486
|
/* @__PURE__ */ jsx3("span", { children: option.label }),
|
|
472
|
-
option.value ===
|
|
487
|
+
option.value === selectedValue && /* @__PURE__ */ jsx3(ChoiceCheckIcon, {})
|
|
473
488
|
]
|
|
474
489
|
},
|
|
475
490
|
option.value
|
|
@@ -1114,6 +1129,24 @@ function ellipsizeText(context, text, maxWidth) {
|
|
|
1114
1129
|
}
|
|
1115
1130
|
return `${text.slice(0, start)}${ellipsis}`;
|
|
1116
1131
|
}
|
|
1132
|
+
function getSelectionOutlineBounds({
|
|
1133
|
+
left,
|
|
1134
|
+
right,
|
|
1135
|
+
top,
|
|
1136
|
+
bottom,
|
|
1137
|
+
horizontalStart,
|
|
1138
|
+
horizontalEnd,
|
|
1139
|
+
verticalStart,
|
|
1140
|
+
verticalEnd,
|
|
1141
|
+
borderWidth = 2
|
|
1142
|
+
}) {
|
|
1143
|
+
return {
|
|
1144
|
+
left: Math.max(left - borderWidth, horizontalStart - borderWidth),
|
|
1145
|
+
right: Math.min(right + 1, horizontalEnd + 1),
|
|
1146
|
+
top: Math.max(top - borderWidth, verticalStart - borderWidth),
|
|
1147
|
+
bottom: Math.min(bottom + borderWidth, verticalEnd + borderWidth)
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1117
1150
|
function paintGrid(options) {
|
|
1118
1151
|
const { context: ctx, width, height, pixelRatio, scrollLeft, scrollTop, rowHeight, bodyFontSize, headerActionSlotWidth, headerHeight, fixedHeader, verticalBorderless, horizontalBorderless, frameBorderless, extendVerticalGridLines, striped, columnDraggable, sortState, filterValues, hoveredHeaderAction, rows, columns, metrics, range, selection, editing, hoveredRowIndex, selectionRange, selectedRowKeys, rowSelectionMode, selectedColumnKeys, highlightEditedCells, highlightInsertedRows, insertedRowKeys, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget } = options;
|
|
1119
1152
|
const headerLeafTop = options.headerLeafTop ?? 0;
|
|
@@ -1602,51 +1635,65 @@ function paintGrid(options) {
|
|
|
1602
1635
|
const visibleRight = x + selectionWidth;
|
|
1603
1636
|
const visibleBottom = y + selectionHeight;
|
|
1604
1637
|
const selectionTop = fixedHeader ? bodyTop : 0;
|
|
1605
|
-
const selectionClipTop = selectionTop;
|
|
1606
1638
|
const hiddenAboveHeader = visibleBottom <= selectionTop;
|
|
1607
1639
|
const hiddenBelowViewport = y >= height;
|
|
1608
1640
|
const hiddenBehindLeft = !isFixed && visibleRight <= visibleLeft;
|
|
1609
1641
|
const hiddenBehindRight = !isFixed && x >= selectionAreaRight;
|
|
1610
|
-
const leftMarkerX =
|
|
1642
|
+
const leftMarkerX = leftFixedWidth - borderWidth;
|
|
1643
|
+
const rightMarkerX = selectionAreaRight - 1;
|
|
1644
|
+
const topMarkerY = selectionTop - borderWidth;
|
|
1645
|
+
const bottomMarkerY = height;
|
|
1611
1646
|
if ((hiddenAboveHeader || hiddenBelowViewport) && (hiddenBehindLeft || hiddenBehindRight)) {
|
|
1612
1647
|
const markerSize = 2;
|
|
1613
|
-
const markerX = hiddenBehindLeft ? leftMarkerX :
|
|
1614
|
-
const markerY = hiddenAboveHeader ?
|
|
1648
|
+
const markerX = hiddenBehindLeft ? leftMarkerX : rightMarkerX;
|
|
1649
|
+
const markerY = hiddenAboveHeader ? topMarkerY : bottomMarkerY;
|
|
1615
1650
|
ctx.fillStyle = colors.selection;
|
|
1616
1651
|
ctx.fillRect(markerX, markerY, markerSize, markerSize);
|
|
1617
1652
|
return;
|
|
1618
1653
|
}
|
|
1654
|
+
const outline = getSelectionOutlineBounds({
|
|
1655
|
+
left: x,
|
|
1656
|
+
right: visibleRight,
|
|
1657
|
+
top: y,
|
|
1658
|
+
bottom: visibleBottom,
|
|
1659
|
+
horizontalStart: visibleLeft,
|
|
1660
|
+
horizontalEnd: selectionAreaRight,
|
|
1661
|
+
verticalStart: selectionTop,
|
|
1662
|
+
verticalEnd: height,
|
|
1663
|
+
borderWidth
|
|
1664
|
+
});
|
|
1619
1665
|
ctx.save();
|
|
1620
1666
|
ctx.beginPath();
|
|
1621
|
-
const clipLeft =
|
|
1667
|
+
const clipLeft = Math.max(0, outline.left);
|
|
1622
1668
|
const clipRight = Math.min(width, selectionAreaRight + 1);
|
|
1623
|
-
|
|
1669
|
+
const clipTop = Math.max(0, outline.top);
|
|
1670
|
+
ctx.rect(clipLeft, clipTop, clipRight - clipLeft, height - clipTop);
|
|
1624
1671
|
ctx.clip();
|
|
1625
1672
|
ctx.fillStyle = colors.selection;
|
|
1626
1673
|
if (hiddenAboveHeader) {
|
|
1627
|
-
const markerLeft = Math.max(x - borderWidth, visibleLeft -
|
|
1628
|
-
const markerRight = Math.min(visibleRight + 1, selectionAreaRight);
|
|
1629
|
-
if (markerRight > markerLeft) ctx.fillRect(markerLeft,
|
|
1674
|
+
const markerLeft = Math.max(x - borderWidth, visibleLeft - borderWidth);
|
|
1675
|
+
const markerRight = Math.min(visibleRight + 1, selectionAreaRight + 1);
|
|
1676
|
+
if (markerRight > markerLeft) ctx.fillRect(markerLeft, topMarkerY, markerRight - markerLeft, borderWidth);
|
|
1630
1677
|
}
|
|
1631
1678
|
if (hiddenBelowViewport) {
|
|
1632
|
-
const markerLeft = Math.max(x - borderWidth, visibleLeft -
|
|
1633
|
-
const markerRight = Math.min(visibleRight + 1, selectionAreaRight);
|
|
1634
|
-
if (markerRight > markerLeft) ctx.fillRect(markerLeft,
|
|
1679
|
+
const markerLeft = Math.max(x - borderWidth, visibleLeft - borderWidth);
|
|
1680
|
+
const markerRight = Math.min(visibleRight + 1, selectionAreaRight + 1);
|
|
1681
|
+
if (markerRight > markerLeft) ctx.fillRect(markerLeft, bottomMarkerY, markerRight - markerLeft, borderWidth);
|
|
1635
1682
|
}
|
|
1636
1683
|
if (hiddenBehindLeft || hiddenBehindRight) {
|
|
1637
|
-
const markerTop = Math.max(y - borderWidth, selectionTop);
|
|
1638
|
-
const markerBottom = Math.min(y + selectionHeight +
|
|
1639
|
-
const markerX = hiddenBehindLeft ? leftMarkerX :
|
|
1684
|
+
const markerTop = Math.max(y - borderWidth, selectionTop - borderWidth);
|
|
1685
|
+
const markerBottom = Math.min(y + selectionHeight + borderWidth, height + borderWidth);
|
|
1686
|
+
const markerX = hiddenBehindLeft ? leftMarkerX : rightMarkerX;
|
|
1640
1687
|
ctx.fillRect(markerX, markerTop, borderWidth, Math.max(0, markerBottom - markerTop));
|
|
1641
1688
|
}
|
|
1642
1689
|
if (hiddenAboveHeader || hiddenBelowViewport || hiddenBehindLeft || hiddenBehindRight) {
|
|
1643
1690
|
ctx.restore();
|
|
1644
1691
|
return;
|
|
1645
1692
|
}
|
|
1646
|
-
const borderLeft =
|
|
1647
|
-
const borderRight =
|
|
1648
|
-
const borderTop =
|
|
1649
|
-
const borderBottom =
|
|
1693
|
+
const borderLeft = outline.left;
|
|
1694
|
+
const borderRight = outline.right - borderWidth;
|
|
1695
|
+
const borderTop = outline.top;
|
|
1696
|
+
const borderBottom = outline.bottom - borderWidth;
|
|
1650
1697
|
const borderOuterWidth = borderRight + borderWidth - borderLeft;
|
|
1651
1698
|
ctx.fillRect(borderLeft, borderTop, borderOuterWidth, borderWidth);
|
|
1652
1699
|
ctx.fillRect(borderLeft, borderBottom, borderOuterWidth, borderWidth);
|
|
@@ -1658,11 +1705,11 @@ function paintGrid(options) {
|
|
|
1658
1705
|
}
|
|
1659
1706
|
|
|
1660
1707
|
// src/hooks/useControllable.ts
|
|
1661
|
-
import { useCallback, useState as useState5 } from "react";
|
|
1708
|
+
import { useCallback as useCallback2, useState as useState5 } from "react";
|
|
1662
1709
|
function useControllableKeys(value, defaultValue, onChange) {
|
|
1663
1710
|
const [internal, setInternal] = useState5(defaultValue ?? []);
|
|
1664
1711
|
const keys = value === void 0 ? internal : value;
|
|
1665
|
-
const setKeys =
|
|
1712
|
+
const setKeys = useCallback2((next) => {
|
|
1666
1713
|
if (value === void 0) setInternal(next);
|
|
1667
1714
|
onChange?.(next);
|
|
1668
1715
|
}, [onChange, value]);
|
|
@@ -1671,7 +1718,7 @@ function useControllableKeys(value, defaultValue, onChange) {
|
|
|
1671
1718
|
function useControllableValue(value, defaultValue, onChange) {
|
|
1672
1719
|
const [internal, setInternal] = useState5(defaultValue ?? null);
|
|
1673
1720
|
const selected = value === void 0 ? internal : value;
|
|
1674
|
-
const setSelected =
|
|
1721
|
+
const setSelected = useCallback2((next) => {
|
|
1675
1722
|
if (value === void 0) setInternal(next);
|
|
1676
1723
|
onChange?.(next);
|
|
1677
1724
|
}, [onChange, value]);
|
|
@@ -2141,7 +2188,7 @@ function TableInner({
|
|
|
2141
2188
|
if (headerTooltipTimerRef.current !== null) clearTimeout(headerTooltipTimerRef.current);
|
|
2142
2189
|
if (cellTooltipTimerRef.current !== null) clearTimeout(cellTooltipTimerRef.current);
|
|
2143
2190
|
}, []);
|
|
2144
|
-
const measureCustomHeaderHeight =
|
|
2191
|
+
const measureCustomHeaderHeight = useCallback3(() => {
|
|
2145
2192
|
const nextHeights = Array.from({ length: headerDepth }, () => baseHeaderHeight);
|
|
2146
2193
|
customHeaderContentRefs.current.forEach((node) => {
|
|
2147
2194
|
const headerCell = node.closest(".rvg-header-title");
|
|
@@ -2192,7 +2239,7 @@ function TableInner({
|
|
|
2192
2239
|
const [hoveredHeaderAction, setHoveredHeaderAction] = useState6(null);
|
|
2193
2240
|
const [visibleHeaderTooltip, setVisibleHeaderTooltip] = useState6(null);
|
|
2194
2241
|
const [hoveredCellTooltip, setHoveredCellTooltip] = useState6(null);
|
|
2195
|
-
const hideDragTooltips =
|
|
2242
|
+
const hideDragTooltips = useCallback3(() => {
|
|
2196
2243
|
if (headerTooltipTimerRef.current !== null) {
|
|
2197
2244
|
clearTimeout(headerTooltipTimerRef.current);
|
|
2198
2245
|
headerTooltipTimerRef.current = null;
|
|
@@ -2219,10 +2266,10 @@ function TableInner({
|
|
|
2219
2266
|
const [insertedRowKeys, setInsertedRowKeys] = useState6(() => /* @__PURE__ */ new Set());
|
|
2220
2267
|
const [rowOrderKeys, setRowOrderKeys] = useState6(null);
|
|
2221
2268
|
const settledPendingInsertIdsRef = useRef4(/* @__PURE__ */ new Set());
|
|
2222
|
-
const getDataRowKey =
|
|
2269
|
+
const getDataRowKey = useCallback3((row, index) => {
|
|
2223
2270
|
return typeof rowKey === "function" ? rowKey(row, index) : rowKey ? row[rowKey] : getDefaultRowKey(row, index);
|
|
2224
2271
|
}, [rowKey]);
|
|
2225
|
-
const getSourceRowIndexByKey =
|
|
2272
|
+
const getSourceRowIndexByKey = useCallback3((key, preferredIndex) => {
|
|
2226
2273
|
const preferredRow = sourceRows[preferredIndex];
|
|
2227
2274
|
if (preferredRow && getDataRowKey(preferredRow, preferredIndex) === key) return preferredIndex;
|
|
2228
2275
|
const start = Math.max(0, preferredIndex - 8);
|
|
@@ -2293,7 +2340,7 @@ function TableInner({
|
|
|
2293
2340
|
return result * direction;
|
|
2294
2341
|
});
|
|
2295
2342
|
}, [columns, filteredRows, language, onSortChange, sortState]);
|
|
2296
|
-
const resolveSelectionTarget =
|
|
2343
|
+
const resolveSelectionTarget = useCallback3((target) => {
|
|
2297
2344
|
if (target == null) return target;
|
|
2298
2345
|
const columnIndex = columns.findIndex((column) => column.key === target.columnKey);
|
|
2299
2346
|
const rowIndex = target.rowKey !== void 0 ? rows.findIndex((row2, index) => getDataRowKey(row2, index) === target.rowKey) : target.rowIndex ?? -1;
|
|
@@ -2308,7 +2355,7 @@ function TableInner({
|
|
|
2308
2355
|
}, [columns, getDataRowKey, rows]);
|
|
2309
2356
|
const resolvedSelectedCell = useMemo2(() => resolveSelectionTarget(selectedCell), [resolveSelectionTarget, selectedCell]);
|
|
2310
2357
|
const resolvedDefaultSelectedCell = useMemo2(() => resolveSelectionTarget(defaultSelectedCell), [defaultSelectedCell, resolveSelectionTarget]);
|
|
2311
|
-
const handleSelectedCellChange =
|
|
2358
|
+
const handleSelectedCellChange = useCallback3((next) => {
|
|
2312
2359
|
if (!onSelectedCellChange) return;
|
|
2313
2360
|
if (!next) {
|
|
2314
2361
|
onSelectedCellChange(null);
|
|
@@ -2337,7 +2384,7 @@ function TableInner({
|
|
|
2337
2384
|
document.addEventListener("pointerdown", handleOutsidePointerDown);
|
|
2338
2385
|
return () => document.removeEventListener("pointerdown", handleOutsidePointerDown);
|
|
2339
2386
|
}, [selection, setSelection]);
|
|
2340
|
-
const applyRowOrder =
|
|
2387
|
+
const applyRowOrder = useCallback3((sourceIndex, targetIndex) => {
|
|
2341
2388
|
if (sourceIndex === targetIndex || sourceIndex < 0 || targetIndex < 0 || sourceIndex >= rows.length || targetIndex >= rows.length) return;
|
|
2342
2389
|
const nextEntries = rows.map((row, index) => ({ row, key: getDataRowKey(row, index) }));
|
|
2343
2390
|
const [entry] = nextEntries.splice(sourceIndex, 1);
|
|
@@ -2346,7 +2393,7 @@ function TableInner({
|
|
|
2346
2393
|
setRowOrderKeys(nextEntries.map(({ key }) => key));
|
|
2347
2394
|
onRowsReorder?.(nextRows, { sourceIndex, targetIndex });
|
|
2348
2395
|
}, [getDataRowKey, onRowsReorder, rows]);
|
|
2349
|
-
const applyColumnOrder =
|
|
2396
|
+
const applyColumnOrder = useCallback3((sourceIndex, targetIndex, detail) => {
|
|
2350
2397
|
const nextColumns = reorderColumns(sourceColumns, detail);
|
|
2351
2398
|
setSourceColumns(nextColumns);
|
|
2352
2399
|
onColumnsReorder?.(nextColumns, { sourceIndex, targetIndex, ...detail });
|
|
@@ -2419,7 +2466,7 @@ function TableInner({
|
|
|
2419
2466
|
}
|
|
2420
2467
|
return lefts;
|
|
2421
2468
|
}, [columns, fixedWidth, metrics]);
|
|
2422
|
-
const getScrollableColumnLeft =
|
|
2469
|
+
const getScrollableColumnLeft = useCallback3((columnIndex) => scrollableColumnLefts[columnIndex] ?? fixedWidth, [fixedWidth, scrollableColumnLefts]);
|
|
2423
2470
|
const hasRowSelectionColumn = useMemo2(() => columns.some((column) => column.rowSelection), [columns]);
|
|
2424
2471
|
const rowSelectionMode = typeof rowSelection === "object" ? rowSelection.mode ?? "multiple" : "multiple";
|
|
2425
2472
|
const summarySignature = useMemo2(() => getSummarySignature(columns), [columns]);
|
|
@@ -2472,7 +2519,7 @@ function TableInner({
|
|
|
2472
2519
|
const rowScrollTop = fixedHeader ? currentScroll2.top : Math.max(0, currentScroll2.top - bodyTop);
|
|
2473
2520
|
return getViewportRange(currentScroll2.left, rowScrollTop, viewport.width, bodyViewportHeight, rows.length, rowHeight, metrics, virtualOverscan);
|
|
2474
2521
|
}, [bodyTop, bodyViewportHeight, columns.length, fixedHeader, isVirtualized, metrics, rowHeight, rows.length, scrollPosition, viewport.width, virtualOverscan]);
|
|
2475
|
-
const getRowKey =
|
|
2522
|
+
const getRowKey = useCallback3((row, index) => {
|
|
2476
2523
|
const key = getDataRowKey(row, index);
|
|
2477
2524
|
rowByKeyRef.current.set(key, row);
|
|
2478
2525
|
rowIndexByKeyRef.current.set(key, index);
|
|
@@ -2541,7 +2588,7 @@ function TableInner({
|
|
|
2541
2588
|
const selectedRowKeySet = useMemo2(() => new Set(rowKeys), [rowKeys]);
|
|
2542
2589
|
const selectedColumnKeySet = useMemo2(() => new Set(columnKeys), [columnKeys]);
|
|
2543
2590
|
const insertedRowKeySet = useMemo2(() => insertedRowKeys, [insertedRowKeys]);
|
|
2544
|
-
const measureHeaderTitleWidth =
|
|
2591
|
+
const measureHeaderTitleWidth = useCallback3((columnIndex) => {
|
|
2545
2592
|
const title = columns[columnIndex]?.title ?? "";
|
|
2546
2593
|
const context = canvasRef.current?.getContext("2d");
|
|
2547
2594
|
if (!context) return Array.from(title).reduce((width3, character) => width3 + (/^[\x00-\x7F]$/.test(character) ? 7 : 13), 0);
|
|
@@ -2551,7 +2598,7 @@ function TableInner({
|
|
|
2551
2598
|
context.restore();
|
|
2552
2599
|
return width2;
|
|
2553
2600
|
}, [columns]);
|
|
2554
|
-
const getCellLabel =
|
|
2601
|
+
const getCellLabel = useCallback3((rowIndex, columnIndex) => {
|
|
2555
2602
|
const row = rows[rowIndex];
|
|
2556
2603
|
const column = columns[columnIndex];
|
|
2557
2604
|
if (!row || !column || column.rowSelection || column.rowDragHandle) return "";
|
|
@@ -2562,8 +2609,8 @@ function TableInner({
|
|
|
2562
2609
|
return "Render error";
|
|
2563
2610
|
}
|
|
2564
2611
|
}, [columns, rows]);
|
|
2565
|
-
const getCellSpan =
|
|
2566
|
-
const getCellDisplayWidth =
|
|
2612
|
+
const getCellSpan = useCallback3((rowIndex, columnIndex) => cellSpanLookup.covered.get(getCellCoordKey2(rowIndex, columnIndex)), [cellSpanLookup]);
|
|
2613
|
+
const getCellDisplayWidth = useCallback3((columnIndex, colSpan = 1) => {
|
|
2567
2614
|
let width2 = 0;
|
|
2568
2615
|
for (let index = columnIndex; index < Math.min(columns.length, columnIndex + colSpan); index += 1) {
|
|
2569
2616
|
width2 += metrics[index]?.width ?? 0;
|
|
@@ -2578,7 +2625,7 @@ function TableInner({
|
|
|
2578
2625
|
if (nextRowIndex === selection.rowIndex && nextColumnIndex === selection.columnIndex) return;
|
|
2579
2626
|
setSelection({ ...selection, rowIndex: nextRowIndex, columnIndex: nextColumnIndex });
|
|
2580
2627
|
}, [columns, getRowKey, rows, selection, setSelection]);
|
|
2581
|
-
const draw =
|
|
2628
|
+
const draw = useCallback3(() => {
|
|
2582
2629
|
frameRef.current = null;
|
|
2583
2630
|
const canvas = canvasRef.current;
|
|
2584
2631
|
if (!canvas || viewport.width <= 0) return;
|
|
@@ -2624,15 +2671,15 @@ function TableInner({
|
|
|
2624
2671
|
const range = isVirtualized ? getViewportRange(scroll.left, rowScrollTop, viewport.width, bodyViewportHeight, rows.length, rowHeight, metrics, virtualOverscan) : { rowStart: 0, rowEnd: rows.length, columnStart: 0, columnEnd: columns.length };
|
|
2625
2672
|
paintGrid({ context, width: viewport.width, height: renderHeight, pixelRatio: ratio, scrollLeft: scroll.left, scrollTop: scroll.top, rowHeight, bodyFontSize, headerActionSlotWidth, headerHeight, headerLeafTop, headerLeafHeight, bodyTop, suppressLastRowBottomBorder: bottomSummaryHeight > 0, suppressFrameBottomBorder: bottomSummaryHeight > 0, fixedHeader, verticalBorderless: !hasVerticalBorders, horizontalBorderless, frameBorderless, extendVerticalGridLines: !autoHeight, striped: hasStripedRows, columnDraggable, sortState, filterValues, hoveredHeaderAction: hoveredHeaderActionRef.current, rows, rowStyle, columns, metrics, range, selection, editing, hoveredRowIndex: hoveredRowIndexRef.current, selectionRange, selectedRowKeys: selectedRowKeySet, rowSelectionMode, selectedColumnKeys: selectedColumnKeySet, cellSpans: cellSpanLookup.covered, maxRowSpan: cellSpanLookup.maxRowSpan, highlightEditedCells: highlightsEditedCells, highlightInsertedRows: highlightsInsertedRows, insertedRowKeys: insertedRowKeySet, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget, resolveColor: (color) => resolveCanvasColor(themeStyles, color), colors: themeColors });
|
|
2626
2673
|
}, [autoHeight, bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, columnDragPreview, columnDraggable, columnDropTarget, columns, editedCellHighlightColor, editedCellKeys, editing, renderHeight, filterValues, fixedHeader, frameBorderless, getRowKey, hasStripedRows, hasVerticalBorders, headerActionSlotWidth, headerDepth, headerHeight, headerLeafHeight, headerLeafTop, horizontalBorderless, highlightsEditedCells, highlightsInsertedRows, insertedRowHighlightColor, insertedRowKeySet, isVirtualized, metrics, rowDragPreview, rowHeight, rowSelectionMode, rowStyle, rows, selectedColumnKeySet, selectedRowKeySet, selection, selectionRange, sortState, stripedColor, viewport.width, virtualOverscan]);
|
|
2627
|
-
const scheduleDraw =
|
|
2674
|
+
const scheduleDraw = useCallback3(() => {
|
|
2628
2675
|
if (frameRef.current === null) frameRef.current = requestAnimationFrame(draw);
|
|
2629
2676
|
}, [draw]);
|
|
2630
|
-
const drawImmediately =
|
|
2677
|
+
const drawImmediately = useCallback3(() => {
|
|
2631
2678
|
if (frameRef.current !== null) cancelAnimationFrame(frameRef.current);
|
|
2632
2679
|
frameRef.current = null;
|
|
2633
2680
|
draw();
|
|
2634
2681
|
}, [draw]);
|
|
2635
|
-
const getSelectionHorizontalVisibility =
|
|
2682
|
+
const getSelectionHorizontalVisibility = useCallback3((scrollLeft) => {
|
|
2636
2683
|
if (!selection || selectionRange) return "visible";
|
|
2637
2684
|
const column = columns[selection.columnIndex];
|
|
2638
2685
|
if (!column || column.fixed !== void 0) return "visible";
|
|
@@ -2643,7 +2690,7 @@ function TableInner({
|
|
|
2643
2690
|
if (left >= viewport.width - rightFixedWidth) return "hidden-right";
|
|
2644
2691
|
return "visible";
|
|
2645
2692
|
}, [columns, fixedWidth, getCellDisplayWidth, getCellSpan, getScrollableColumnLeft, rightFixedWidth, selection, selectionRange, viewport.width]);
|
|
2646
|
-
const getSelectionEdgeIndicator =
|
|
2693
|
+
const getSelectionEdgeIndicator = useCallback3((scrollLeft, scrollTop) => {
|
|
2647
2694
|
if (!selection || selectionRange) return null;
|
|
2648
2695
|
const row = rows[selection.rowIndex];
|
|
2649
2696
|
const metric = metrics[selection.columnIndex];
|
|
@@ -2666,14 +2713,17 @@ function TableInner({
|
|
|
2666
2713
|
const cornerLength = 10;
|
|
2667
2714
|
const hitSlop = 6;
|
|
2668
2715
|
const targetSize = borderWidth + hitSlop * 2;
|
|
2669
|
-
const
|
|
2670
|
-
const
|
|
2671
|
-
const
|
|
2716
|
+
const leftBoundary = horizontalStart - borderWidth;
|
|
2717
|
+
const rightBoundary = horizontalEnd - 1;
|
|
2718
|
+
const topBoundary = verticalStart - borderWidth;
|
|
2719
|
+
const bottomBoundary = renderHeight;
|
|
2720
|
+
const markerX = hiddenLeft ? leftBoundary : rightBoundary;
|
|
2721
|
+
const markerY = hiddenTop ? topBoundary : bottomBoundary;
|
|
2672
2722
|
if (hiddenLeft || hiddenRight) {
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
const topClip = Math.max(0, verticalStart -
|
|
2676
|
-
const bottomClip = Math.max(0, rawBottom
|
|
2723
|
+
const markerTop = Math.max(rawTop - borderWidth, topBoundary);
|
|
2724
|
+
const markerBottom = Math.min(rawBottom + borderWidth, renderHeight + borderWidth);
|
|
2725
|
+
const topClip = Math.max(0, verticalStart - rawTop);
|
|
2726
|
+
const bottomClip = Math.max(0, rawBottom - renderHeight);
|
|
2677
2727
|
if (topClip > 0 || bottomClip > 0) {
|
|
2678
2728
|
const foldAtTop = topClip > 0;
|
|
2679
2729
|
const fold = Math.min(cornerLength, foldAtTop ? topClip : bottomClip);
|
|
@@ -2682,7 +2732,7 @@ function TableInner({
|
|
|
2682
2732
|
const cornerHeight = Math.max(cornerLength, markerBottom - markerTop);
|
|
2683
2733
|
const cornerOnLeft = hiddenLeft;
|
|
2684
2734
|
const shapeLeft = cornerOnLeft ? markerX : markerX + borderWidth - cornerWidth;
|
|
2685
|
-
const shapeTop = foldAtTop ?
|
|
2735
|
+
const shapeTop = foldAtTop ? topBoundary : renderHeight + borderWidth - cornerHeight;
|
|
2686
2736
|
return {
|
|
2687
2737
|
side: `${foldAtTop ? "top" : "bottom"}-${cornerOnLeft ? "left" : "right"}`,
|
|
2688
2738
|
orientation: "corner",
|
|
@@ -2709,19 +2759,19 @@ function TableInner({
|
|
|
2709
2759
|
}
|
|
2710
2760
|
};
|
|
2711
2761
|
}
|
|
2712
|
-
const horizontalMarkerEnd = horizontalEnd
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
const leftClip = Math.max(0, horizontalStart -
|
|
2716
|
-
const rightClip = Math.max(0, rawRight
|
|
2762
|
+
const horizontalMarkerEnd = horizontalEnd + 1;
|
|
2763
|
+
const markerLeft = Math.max(rawLeft - borderWidth, leftBoundary);
|
|
2764
|
+
const markerRight = Math.min(rawRight + 1, horizontalMarkerEnd);
|
|
2765
|
+
const leftClip = Math.max(0, horizontalStart - rawLeft);
|
|
2766
|
+
const rightClip = Math.max(0, rawRight - horizontalEnd);
|
|
2717
2767
|
if (leftClip > 0 || rightClip > 0) {
|
|
2718
2768
|
const foldAtLeft = leftClip > 0;
|
|
2719
2769
|
const fold = Math.min(cornerLength, foldAtLeft ? leftClip : rightClip);
|
|
2720
2770
|
if (fold > borderWidth) {
|
|
2721
2771
|
const cornerWidth = Math.max(cornerLength, markerRight - markerLeft);
|
|
2722
2772
|
const cornerHeight = fold;
|
|
2723
|
-
const shapeLeft = foldAtLeft ?
|
|
2724
|
-
const shapeTop = hiddenTop ?
|
|
2773
|
+
const shapeLeft = foldAtLeft ? leftBoundary : horizontalMarkerEnd - cornerWidth;
|
|
2774
|
+
const shapeTop = hiddenTop ? topBoundary : renderHeight + borderWidth - cornerHeight;
|
|
2725
2775
|
return {
|
|
2726
2776
|
side: `${hiddenTop ? "top" : "bottom"}-${foldAtLeft ? "left" : "right"}`,
|
|
2727
2777
|
orientation: "corner",
|
|
@@ -2747,8 +2797,8 @@ function TableInner({
|
|
|
2747
2797
|
height: targetSize
|
|
2748
2798
|
}
|
|
2749
2799
|
};
|
|
2750
|
-
}, [bodyTop, columns, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, getScrollableColumnLeft,
|
|
2751
|
-
const syncSelectionEdgeTarget =
|
|
2800
|
+
}, [bodyTop, columns, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, getScrollableColumnLeft, leftFixedOffsets, metrics, renderHeight, rightFixedOffsets, rightFixedWidth, rowHeight, rows, selection, selectionRange, viewport.width]);
|
|
2801
|
+
const syncSelectionEdgeTarget = useCallback3((scrollLeft, scrollTop) => {
|
|
2752
2802
|
const target = selectionEdgeTargetRef.current;
|
|
2753
2803
|
if (!target) return;
|
|
2754
2804
|
const indicator = getSelectionEdgeIndicator(scrollLeft, scrollTop);
|
|
@@ -2870,7 +2920,7 @@ function TableInner({
|
|
|
2870
2920
|
scroller.addEventListener("scroll", lockScroll);
|
|
2871
2921
|
return () => scroller.removeEventListener("scroll", lockScroll);
|
|
2872
2922
|
}, [insertBusy]);
|
|
2873
|
-
const showCustomScrollbar =
|
|
2923
|
+
const showCustomScrollbar = useCallback3((axis, persist = false) => {
|
|
2874
2924
|
const showVertical = axis === "vertical" || axis === "both";
|
|
2875
2925
|
const showHorizontal = axis === "horizontal" || axis === "both";
|
|
2876
2926
|
if (showVertical) {
|
|
@@ -2894,15 +2944,15 @@ function TableInner({
|
|
|
2894
2944
|
}
|
|
2895
2945
|
}
|
|
2896
2946
|
}, []);
|
|
2897
|
-
const keepCustomScrollbarVisible =
|
|
2947
|
+
const keepCustomScrollbarVisible = useCallback3((axis) => {
|
|
2898
2948
|
showCustomScrollbar(axis, true);
|
|
2899
2949
|
}, [showCustomScrollbar]);
|
|
2900
|
-
const releaseCustomScrollbarVisible =
|
|
2950
|
+
const releaseCustomScrollbarVisible = useCallback3((axis) => {
|
|
2901
2951
|
if (axis === "vertical" && verticalScrollbarDragRef.current) return;
|
|
2902
2952
|
if (axis === "horizontal" && horizontalScrollbarDragRef.current) return;
|
|
2903
2953
|
showCustomScrollbar(axis);
|
|
2904
2954
|
}, [showCustomScrollbar]);
|
|
2905
|
-
const updateCustomScrollbars =
|
|
2955
|
+
const updateCustomScrollbars = useCallback3(() => {
|
|
2906
2956
|
const scroller = scrollerRef.current;
|
|
2907
2957
|
const verticalTrack = verticalScrollbarRef.current;
|
|
2908
2958
|
const verticalThumb = verticalScrollbarThumbRef.current;
|
|
@@ -2955,7 +3005,7 @@ function TableInner({
|
|
|
2955
3005
|
useLayoutEffect3(() => {
|
|
2956
3006
|
updateCustomScrollbars();
|
|
2957
3007
|
}, [contentHeight, contentWidth, updateCustomScrollbars, viewport.height, viewport.width]);
|
|
2958
|
-
const handleVerticalScrollbarPointerDown =
|
|
3008
|
+
const handleVerticalScrollbarPointerDown = useCallback3((event) => {
|
|
2959
3009
|
const scroller = scrollerRef.current;
|
|
2960
3010
|
const track = verticalScrollbarRef.current;
|
|
2961
3011
|
const thumb = verticalScrollbarThumbRef.current;
|
|
@@ -2992,7 +3042,7 @@ function TableInner({
|
|
|
2992
3042
|
maxScrollTop
|
|
2993
3043
|
};
|
|
2994
3044
|
}, [showCustomScrollbar, updateCustomScrollbars]);
|
|
2995
|
-
const handleVerticalScrollbarPointerMove =
|
|
3045
|
+
const handleVerticalScrollbarPointerMove = useCallback3((event) => {
|
|
2996
3046
|
const drag = verticalScrollbarDragRef.current;
|
|
2997
3047
|
const scroller = scrollerRef.current;
|
|
2998
3048
|
if (!drag || !scroller || drag.pointerId !== event.pointerId) return;
|
|
@@ -3002,14 +3052,14 @@ function TableInner({
|
|
|
3002
3052
|
scroller.scrollTop = nextThumbTop / maxThumbTop * drag.maxScrollTop;
|
|
3003
3053
|
updateCustomScrollbars();
|
|
3004
3054
|
}, [updateCustomScrollbars]);
|
|
3005
|
-
const handleVerticalScrollbarPointerUp =
|
|
3055
|
+
const handleVerticalScrollbarPointerUp = useCallback3((event) => {
|
|
3006
3056
|
const drag = verticalScrollbarDragRef.current;
|
|
3007
3057
|
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
3008
3058
|
if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);
|
|
3009
3059
|
verticalScrollbarDragRef.current = null;
|
|
3010
3060
|
showCustomScrollbar("vertical");
|
|
3011
3061
|
}, [showCustomScrollbar]);
|
|
3012
|
-
const handleHorizontalScrollbarPointerDown =
|
|
3062
|
+
const handleHorizontalScrollbarPointerDown = useCallback3((event) => {
|
|
3013
3063
|
const scroller = scrollerRef.current;
|
|
3014
3064
|
const track = horizontalScrollbarRef.current;
|
|
3015
3065
|
const thumb = horizontalScrollbarThumbRef.current;
|
|
@@ -3052,7 +3102,7 @@ function TableInner({
|
|
|
3052
3102
|
maxScrollLeft
|
|
3053
3103
|
};
|
|
3054
3104
|
}, [drawImmediately, getSelectionHorizontalVisibility, showCustomScrollbar, syncSelectionEdgeTarget, updateCustomScrollbars]);
|
|
3055
|
-
const handleHorizontalScrollbarPointerMove =
|
|
3105
|
+
const handleHorizontalScrollbarPointerMove = useCallback3((event) => {
|
|
3056
3106
|
const drag = horizontalScrollbarDragRef.current;
|
|
3057
3107
|
const scroller = scrollerRef.current;
|
|
3058
3108
|
if (!drag || !scroller || drag.pointerId !== event.pointerId) return;
|
|
@@ -3068,7 +3118,7 @@ function TableInner({
|
|
|
3068
3118
|
if (visibilityChanged) drawImmediately();
|
|
3069
3119
|
updateCustomScrollbars();
|
|
3070
3120
|
}, [drawImmediately, getSelectionHorizontalVisibility, syncSelectionEdgeTarget, updateCustomScrollbars]);
|
|
3071
|
-
const handleHorizontalScrollbarPointerUp =
|
|
3121
|
+
const handleHorizontalScrollbarPointerUp = useCallback3((event) => {
|
|
3072
3122
|
const drag = horizontalScrollbarDragRef.current;
|
|
3073
3123
|
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
3074
3124
|
if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);
|
|
@@ -3082,7 +3132,7 @@ function TableInner({
|
|
|
3082
3132
|
clip.style.transform = "";
|
|
3083
3133
|
});
|
|
3084
3134
|
}, [scrollPosition.top]);
|
|
3085
|
-
const handleScroll =
|
|
3135
|
+
const handleScroll = useCallback3(() => {
|
|
3086
3136
|
const element = scrollerRef.current;
|
|
3087
3137
|
if (!element) return;
|
|
3088
3138
|
const previousScroll = scrollRef.current;
|
|
@@ -3117,11 +3167,20 @@ function TableInner({
|
|
|
3117
3167
|
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= renderHeight) {
|
|
3118
3168
|
focus.style.display = "none";
|
|
3119
3169
|
} else {
|
|
3120
|
-
const
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3170
|
+
const bounds = getSelectionOutlineBounds({
|
|
3171
|
+
left: rawLeft,
|
|
3172
|
+
right: rawRight,
|
|
3173
|
+
top: rawTop,
|
|
3174
|
+
bottom: rawBottom,
|
|
3175
|
+
horizontalStart,
|
|
3176
|
+
horizontalEnd,
|
|
3177
|
+
verticalStart,
|
|
3178
|
+
verticalEnd: renderHeight
|
|
3179
|
+
});
|
|
3180
|
+
const left = Math.round(bounds.left);
|
|
3181
|
+
const right = Math.round(bounds.right);
|
|
3182
|
+
const top = Math.round(bounds.top);
|
|
3183
|
+
const bottom = Math.round(bounds.bottom);
|
|
3125
3184
|
focus.style.display = "block";
|
|
3126
3185
|
focus.style.left = `${left}px`;
|
|
3127
3186
|
focus.style.top = `${top}px`;
|
|
@@ -3150,7 +3209,7 @@ function TableInner({
|
|
|
3150
3209
|
setHoveredCellTooltip(null);
|
|
3151
3210
|
scheduleDraw();
|
|
3152
3211
|
}, [bodyTop, columns, renderHeight, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, getScrollableColumnLeft, metrics, rightFixedOffsets, rightFixedWidth, rowHeight, rows, scheduleDraw, selection, selectionRange, showCustomScrollbar, syncSelectionEdgeTarget, updateCustomScrollbars, viewport.width]);
|
|
3153
|
-
const locateColumn =
|
|
3212
|
+
const locateColumn = useCallback3((clientX) => {
|
|
3154
3213
|
const canvas = canvasRef.current;
|
|
3155
3214
|
if (!canvas) return -1;
|
|
3156
3215
|
const rect = canvas.getBoundingClientRect();
|
|
@@ -3178,7 +3237,7 @@ function TableInner({
|
|
|
3178
3237
|
}
|
|
3179
3238
|
return columnIndex;
|
|
3180
3239
|
}, [columns, fixedWidth, getScrollableColumnLeft, leftFixedOffsets, metrics, rightFixedOffsets, rightFixedWidth, viewport.width]);
|
|
3181
|
-
const getDisplayedColumnLeft =
|
|
3240
|
+
const getDisplayedColumnLeft = useCallback3((columnIndex) => {
|
|
3182
3241
|
const metric = metrics[columnIndex];
|
|
3183
3242
|
if (columns[columnIndex].fixed === "left") return leftFixedOffsets.get(columnIndex) ?? 0;
|
|
3184
3243
|
if (columns[columnIndex].fixed === "right") return viewport.width - (rightFixedOffsets.get(columnIndex) ?? 0) - metric.width;
|
|
@@ -3188,7 +3247,7 @@ function TableInner({
|
|
|
3188
3247
|
const displayedContentRight = columns.reduce((right, _column, columnIndex) => Math.max(right, getDisplayedColumnLeft(columnIndex) + metrics[columnIndex].width), 0);
|
|
3189
3248
|
return displayedContentRight > 0 && displayedContentRight < viewport.width ? Math.round(displayedContentRight) - 1 : null;
|
|
3190
3249
|
}, [columns, getDisplayedColumnLeft, metrics, scrollPosition.left, viewport.width]);
|
|
3191
|
-
const getHeaderLevelAtY =
|
|
3250
|
+
const getHeaderLevelAtY = useCallback3((localY, headerY) => {
|
|
3192
3251
|
const y = localY - headerY;
|
|
3193
3252
|
for (let level = 0; level < headerRowHeights.length; level += 1) {
|
|
3194
3253
|
const top = headerRowOffsets[level] ?? 0;
|
|
@@ -3196,11 +3255,11 @@ function TableInner({
|
|
|
3196
3255
|
}
|
|
3197
3256
|
return headerDepth - 1;
|
|
3198
3257
|
}, [headerDepth, headerRowHeights, headerRowOffsets]);
|
|
3199
|
-
const resizeColumn =
|
|
3258
|
+
const resizeColumn = useCallback3((columnKey, width2) => {
|
|
3200
3259
|
setResizedColumnWidths((current) => current[columnKey] === width2 ? current : { ...current, [columnKey]: width2 });
|
|
3201
3260
|
onColumnResize?.(columnKey, width2);
|
|
3202
3261
|
}, [onColumnResize]);
|
|
3203
|
-
const locateHeaderAction =
|
|
3262
|
+
const locateHeaderAction = useCallback3((clientX, clientY, columnIndex) => {
|
|
3204
3263
|
if (columnIndex < 0 || !canvasRef.current) return null;
|
|
3205
3264
|
const column = columns[columnIndex];
|
|
3206
3265
|
if (column.rowSelection || column.rowDragHandle || column.rowNumber) return null;
|
|
@@ -3220,7 +3279,7 @@ function TableInner({
|
|
|
3220
3279
|
if (visibleActions.filter && localX >= right - headerActionSlotWidth && localX < right) return "filter";
|
|
3221
3280
|
return null;
|
|
3222
3281
|
}, [columnDraggable, columns, fixedHeader, getDisplayedColumnLeft, headerActionSize, headerActionSlotWidth, headerLeafHeight, headerLeafTop, measureHeaderTitleWidth, metrics]);
|
|
3223
|
-
const isHeaderTitleTruncated =
|
|
3282
|
+
const isHeaderTitleTruncated = useCallback3((columnIndex) => {
|
|
3224
3283
|
const canvas = canvasRef.current;
|
|
3225
3284
|
if (columnIndex < 0 || !canvas) return false;
|
|
3226
3285
|
const column = columns[columnIndex];
|
|
@@ -3230,7 +3289,7 @@ function TableInner({
|
|
|
3230
3289
|
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
|
|
3231
3290
|
return getHeaderTitleRequiredWidth(column, titleWidth) > Math.max(0, metric.width - actionWidth);
|
|
3232
3291
|
}, [columnDraggable, columns, headerActionSlotWidth, measureHeaderTitleWidth, metrics]);
|
|
3233
|
-
const locateHeaderDragHandle =
|
|
3292
|
+
const locateHeaderDragHandle = useCallback3((clientX, clientY, columnIndex) => {
|
|
3234
3293
|
if (!columnDraggable || columnIndex < 0 || !canvasRef.current) return false;
|
|
3235
3294
|
const column = columns[columnIndex];
|
|
3236
3295
|
if (column.rowSelection || column.rowDragHandle || column.rowNumber) return false;
|
|
@@ -3244,14 +3303,14 @@ function TableInner({
|
|
|
3244
3303
|
const columnRight = getDisplayedColumnLeft(columnIndex) + metrics[columnIndex].width;
|
|
3245
3304
|
return localX >= columnRight - headerActionSlotWidth && localX < columnRight - 2;
|
|
3246
3305
|
}, [columnDraggable, columns, fixedHeader, getDisplayedColumnLeft, headerActionSize, headerActionSlotWidth, headerLeafHeight, headerLeafTop, measureHeaderTitleWidth, metrics]);
|
|
3247
|
-
const getHeaderCellLeft =
|
|
3306
|
+
const getHeaderCellLeft = useCallback3((cell) => {
|
|
3248
3307
|
const startMetric = metrics[cell.startIndex];
|
|
3249
3308
|
const fixedSide = columns[cell.startIndex]?.fixed;
|
|
3250
3309
|
if (!startMetric) return 0;
|
|
3251
3310
|
return fixedSide === "left" ? leftFixedOffsets.get(cell.startIndex) ?? 0 : fixedSide === "right" ? viewport.width - (rightFixedOffsets.get(cell.startIndex) ?? 0) - startMetric.width : getScrollableColumnLeft(cell.startIndex) - scrollRef.current.left;
|
|
3252
3311
|
}, [columns, getScrollableColumnLeft, leftFixedOffsets, metrics, rightFixedOffsets, viewport.width]);
|
|
3253
|
-
const getHeaderCellWidth =
|
|
3254
|
-
const getHeaderCellEdgeFromMetrics =
|
|
3312
|
+
const getHeaderCellWidth = useCallback3((cell) => cell.leaf ? metrics[cell.startIndex]?.width ?? 0 : getCellDisplayWidth(cell.startIndex, cell.endIndex - cell.startIndex + 1), [getCellDisplayWidth, metrics]);
|
|
3313
|
+
const getHeaderCellEdgeFromMetrics = useCallback3((startIndex, endIndex, edge, nextMetrics) => {
|
|
3255
3314
|
const fixedSide = columns[startIndex]?.fixed;
|
|
3256
3315
|
const width2 = nextMetrics.slice(startIndex, endIndex + 1).reduce((total, metric) => total + metric.width, 0);
|
|
3257
3316
|
let left;
|
|
@@ -3275,7 +3334,7 @@ function TableInner({
|
|
|
3275
3334
|
}
|
|
3276
3335
|
return left + (edge === "right" ? width2 : 0);
|
|
3277
3336
|
}, [columns, fixedWidth, viewport.width]);
|
|
3278
|
-
const locateHeaderResizeHit =
|
|
3337
|
+
const locateHeaderResizeHit = useCallback3((clientX, clientY) => {
|
|
3279
3338
|
if (!columnResizable || !canvasRef.current) return null;
|
|
3280
3339
|
const rect = canvasRef.current.getBoundingClientRect();
|
|
3281
3340
|
const localX = clientX - rect.left;
|
|
@@ -3302,15 +3361,15 @@ function TableInner({
|
|
|
3302
3361
|
}
|
|
3303
3362
|
return closest;
|
|
3304
3363
|
}, [columnResizable, columns, fixedHeader, getHeaderCellLeft, getHeaderCellWidth, getHeaderLevelAtY, headerCells, headerHeight]);
|
|
3305
|
-
const locateHeaderResizeCell =
|
|
3306
|
-
const locateHeaderCellDragHandle =
|
|
3364
|
+
const locateHeaderResizeCell = useCallback3((clientX, clientY) => locateHeaderResizeHit(clientX, clientY)?.cell ?? null, [locateHeaderResizeHit]);
|
|
3365
|
+
const locateHeaderCellDragHandle = useCallback3((clientX, clientY, cell) => {
|
|
3307
3366
|
if (!columnDraggable || !canvasRef.current) return false;
|
|
3308
3367
|
if (cell.leaf) return locateHeaderDragHandle(clientX, clientY, cell.startIndex);
|
|
3309
3368
|
const localX = clientX - canvasRef.current.getBoundingClientRect().left;
|
|
3310
3369
|
const right = getHeaderCellLeft(cell) + getHeaderCellWidth(cell);
|
|
3311
3370
|
return localX >= right - headerActionSlotWidth && localX < right - 2;
|
|
3312
3371
|
}, [columnDraggable, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, locateHeaderDragHandle]);
|
|
3313
|
-
const locateHeaderCell =
|
|
3372
|
+
const locateHeaderCell = useCallback3((clientX, clientY) => {
|
|
3314
3373
|
const canvas = canvasRef.current;
|
|
3315
3374
|
if (!canvas) return null;
|
|
3316
3375
|
const rect = canvas.getBoundingClientRect();
|
|
@@ -3327,7 +3386,7 @@ function TableInner({
|
|
|
3327
3386
|
}
|
|
3328
3387
|
return null;
|
|
3329
3388
|
}, [fixedHeader, getHeaderCellLeft, getHeaderCellWidth, getHeaderLevelAtY, headerCells, headerHeight]);
|
|
3330
|
-
const setDragGuide =
|
|
3389
|
+
const setDragGuide = useCallback3((x, top = 0) => {
|
|
3331
3390
|
const guide = dragGuideRef.current;
|
|
3332
3391
|
if (!guide) return;
|
|
3333
3392
|
guide.style.display = x === null ? "none" : "block";
|
|
@@ -3336,20 +3395,20 @@ function TableInner({
|
|
|
3336
3395
|
guide.style.transform = `translateX(${Math.round(x)}px)`;
|
|
3337
3396
|
}
|
|
3338
3397
|
}, []);
|
|
3339
|
-
const setRowDragGuide =
|
|
3398
|
+
const setRowDragGuide = useCallback3((y) => {
|
|
3340
3399
|
const guide = rowDragGuideRef.current;
|
|
3341
3400
|
if (!guide) return;
|
|
3342
3401
|
guide.style.display = y === null ? "none" : "block";
|
|
3343
3402
|
if (y !== null) guide.style.transform = `translateY(${Math.round(y)}px)`;
|
|
3344
3403
|
}, []);
|
|
3345
|
-
const locateRow =
|
|
3404
|
+
const locateRow = useCallback3((clientY) => {
|
|
3346
3405
|
const canvas = canvasRef.current;
|
|
3347
3406
|
if (!canvas) return -1;
|
|
3348
3407
|
const localY = clientY - canvas.getBoundingClientRect().top;
|
|
3349
3408
|
const rowIndex = Math.floor((localY - bodyTop + scrollRef.current.top) / rowHeight);
|
|
3350
3409
|
return rowIndex >= 0 && rowIndex < rows.length ? rowIndex : -1;
|
|
3351
3410
|
}, [bodyTop, rowHeight, rows.length]);
|
|
3352
|
-
const handleRowOrderPointerDown =
|
|
3411
|
+
const handleRowOrderPointerDown = useCallback3((event) => {
|
|
3353
3412
|
if (!rowDraggable || event.button !== 0 || rowOrderDragRef.current) return;
|
|
3354
3413
|
const columnIndex = locateColumn(event.clientX);
|
|
3355
3414
|
const sourceIndex = locateRow(event.clientY);
|
|
@@ -3363,7 +3422,7 @@ function TableInner({
|
|
|
3363
3422
|
targetIndex: sourceIndex
|
|
3364
3423
|
};
|
|
3365
3424
|
}, [columns, locateColumn, locateRow, rowDraggable]);
|
|
3366
|
-
const handleRowOrderPointerMove =
|
|
3425
|
+
const handleRowOrderPointerMove = useCallback3((event) => {
|
|
3367
3426
|
const drag = rowOrderDragRef.current;
|
|
3368
3427
|
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
3369
3428
|
if (!drag.active) {
|
|
@@ -3391,7 +3450,7 @@ function TableInner({
|
|
|
3391
3450
|
setRowDragPreview(null);
|
|
3392
3451
|
setRowDragGuide(rowTop + (edge === "bottom" ? rowHeight : 0));
|
|
3393
3452
|
}, [bodyTop, hideDragTooltips, locateRow, renderHeight, rowHeight, rows.length, setRowDragGuide]);
|
|
3394
|
-
const finishRowOrderPointerDrag =
|
|
3453
|
+
const finishRowOrderPointerDrag = useCallback3((event, apply) => {
|
|
3395
3454
|
const drag = rowOrderDragRef.current;
|
|
3396
3455
|
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
3397
3456
|
if (event.currentTarget.hasPointerCapture?.(event.pointerId)) event.currentTarget.releasePointerCapture?.(event.pointerId);
|
|
@@ -3409,7 +3468,7 @@ function TableInner({
|
|
|
3409
3468
|
});
|
|
3410
3469
|
}
|
|
3411
3470
|
}, [applyRowOrder, setRowDragGuide]);
|
|
3412
|
-
const locateCell =
|
|
3471
|
+
const locateCell = useCallback3((clientX, clientY) => {
|
|
3413
3472
|
const canvas = canvasRef.current;
|
|
3414
3473
|
if (!canvas) return null;
|
|
3415
3474
|
const rect = canvas.getBoundingClientRect();
|
|
@@ -3429,7 +3488,7 @@ function TableInner({
|
|
|
3429
3488
|
columnKey: columns[targetColumnIndex].key
|
|
3430
3489
|
};
|
|
3431
3490
|
}, [bodyTop, columns, fixedHeader, getCellSpan, getRowKey, locateColumn, rowHeight, rows]);
|
|
3432
|
-
const beginRangeDrag =
|
|
3491
|
+
const beginRangeDrag = useCallback3((event) => {
|
|
3433
3492
|
if (!rangeSelection) return;
|
|
3434
3493
|
if (event.button !== 0 || editing || event.target !== event.currentTarget) return;
|
|
3435
3494
|
const cell = locateCell(event.clientX, event.clientY);
|
|
@@ -3438,7 +3497,7 @@ function TableInner({
|
|
|
3438
3497
|
setSelectionRange(null);
|
|
3439
3498
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
3440
3499
|
}, [columns, editing, locateCell, rangeSelection]);
|
|
3441
|
-
const updateRangeDrag =
|
|
3500
|
+
const updateRangeDrag = useCallback3((event) => {
|
|
3442
3501
|
const drag = rangeDragRef.current;
|
|
3443
3502
|
if (!drag) return;
|
|
3444
3503
|
const focus = locateCell(event.clientX, event.clientY);
|
|
@@ -3448,7 +3507,7 @@ function TableInner({
|
|
|
3448
3507
|
event.preventDefault();
|
|
3449
3508
|
setSelectionRange((current) => current?.focus.rowIndex === focus.rowIndex && current.focus.columnIndex === focus.columnIndex ? current : { anchor: drag.anchor, focus });
|
|
3450
3509
|
}, [columns, locateCell]);
|
|
3451
|
-
const endRangeDrag =
|
|
3510
|
+
const endRangeDrag = useCallback3((event) => {
|
|
3452
3511
|
const drag = rangeDragRef.current;
|
|
3453
3512
|
if (!drag) return;
|
|
3454
3513
|
rangeDragRef.current = null;
|
|
@@ -3458,7 +3517,7 @@ function TableInner({
|
|
|
3458
3517
|
setSelection(drag.anchor);
|
|
3459
3518
|
scrollerRef.current?.focus({ preventScroll: true });
|
|
3460
3519
|
}, [setSelection]);
|
|
3461
|
-
const selectRow =
|
|
3520
|
+
const selectRow = useCallback3((rowIndex, event, forceToggle = false) => {
|
|
3462
3521
|
if (!rowSelection) return;
|
|
3463
3522
|
clickedCellRef.current = null;
|
|
3464
3523
|
setSelectionRange(null);
|
|
@@ -3478,7 +3537,7 @@ function TableInner({
|
|
|
3478
3537
|
rowAnchorRef.current = rowIndex;
|
|
3479
3538
|
setRowKeys(next);
|
|
3480
3539
|
}, [getRowKey, rowKeys, rowSelection, rows, selectedRowKeySet, setRowKeys, setSelection]);
|
|
3481
|
-
const selectColumn =
|
|
3540
|
+
const selectColumn = useCallback3((columnIndex, event) => {
|
|
3482
3541
|
if (!columnSelection || columnIndex < 0) return;
|
|
3483
3542
|
clickedCellRef.current = null;
|
|
3484
3543
|
setSelectionRange(null);
|
|
@@ -3498,7 +3557,7 @@ function TableInner({
|
|
|
3498
3557
|
columnAnchorRef.current = columnIndex;
|
|
3499
3558
|
setColumnKeys(next);
|
|
3500
3559
|
}, [columnKeys, columnSelection, columns, selectedColumnKeySet, setColumnKeys, setSelection]);
|
|
3501
|
-
const toggleColumnFromMenu =
|
|
3560
|
+
const toggleColumnFromMenu = useCallback3((columnIndex) => {
|
|
3502
3561
|
if (!columnSelection || columnIndex < 0) return;
|
|
3503
3562
|
clickedCellRef.current = null;
|
|
3504
3563
|
setSelectionRange(null);
|
|
@@ -3510,7 +3569,7 @@ function TableInner({
|
|
|
3510
3569
|
columnAnchorRef.current = columnIndex;
|
|
3511
3570
|
setColumnKeys(next);
|
|
3512
3571
|
}, [columnKeys, columnSelection, columns, selectedColumnKeySet, setColumnKeys, setSelection]);
|
|
3513
|
-
const revealCell =
|
|
3572
|
+
const revealCell = useCallback3((cell) => {
|
|
3514
3573
|
const scroller = scrollerRef.current;
|
|
3515
3574
|
const metric = metrics[cell.columnIndex];
|
|
3516
3575
|
const column = columns[cell.columnIndex];
|
|
@@ -3540,13 +3599,13 @@ function TableInner({
|
|
|
3540
3599
|
scrollRef.current = { left: scroller.scrollLeft, top: scroller.scrollTop };
|
|
3541
3600
|
scheduleDraw();
|
|
3542
3601
|
}, [bodyTop, columns, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getScrollableColumnLeft, metrics, rightFixedWidth, rowHeight, scheduleDraw, viewport.width]);
|
|
3543
|
-
const isCellEditable =
|
|
3602
|
+
const isCellEditable = useCallback3((cell) => {
|
|
3544
3603
|
const column = columns[cell.columnIndex];
|
|
3545
3604
|
const row = rows[cell.rowIndex];
|
|
3546
3605
|
if (!column || !row || column.dataIndex === void 0 || column.rowNumber || column.rowSelection || column.rowDragHandle) return false;
|
|
3547
3606
|
return typeof column.editable === "function" ? column.editable(row[column.dataIndex], row, cell.rowIndex) : column.editable === true;
|
|
3548
3607
|
}, [columns, rows]);
|
|
3549
|
-
const beginEdit =
|
|
3608
|
+
const beginEdit = useCallback3((cell) => {
|
|
3550
3609
|
const column = columns[cell.columnIndex];
|
|
3551
3610
|
if (!isCellEditable(cell) || column.dataIndex === void 0) return;
|
|
3552
3611
|
const value = rows[cell.rowIndex]?.[column.dataIndex];
|
|
@@ -3616,7 +3675,7 @@ function TableInner({
|
|
|
3616
3675
|
return next;
|
|
3617
3676
|
});
|
|
3618
3677
|
};
|
|
3619
|
-
const commitEdit =
|
|
3678
|
+
const commitEdit = useCallback3((nextDraft, close = true) => {
|
|
3620
3679
|
if (!editing) return;
|
|
3621
3680
|
if (!isCellEditable(editing)) {
|
|
3622
3681
|
setEditing(null);
|
|
@@ -3648,6 +3707,7 @@ function TableInner({
|
|
|
3648
3707
|
options: column.editor.options,
|
|
3649
3708
|
searchable: column.editor.searchable,
|
|
3650
3709
|
allowCustomValue: column.editor.allowCustomValue,
|
|
3710
|
+
strictOptions: column.editor.strictOptions,
|
|
3651
3711
|
maxDropdownHeight: column.editor.maxDropdownHeight,
|
|
3652
3712
|
style: editorStyle,
|
|
3653
3713
|
labels,
|
|
@@ -3720,7 +3780,7 @@ function TableInner({
|
|
|
3720
3780
|
}
|
|
3721
3781
|
);
|
|
3722
3782
|
};
|
|
3723
|
-
const handleKeyDown =
|
|
3783
|
+
const handleKeyDown = useCallback3((event) => {
|
|
3724
3784
|
if (editing || !selection) return;
|
|
3725
3785
|
if (event.key === "Enter") {
|
|
3726
3786
|
event.preventDefault();
|
|
@@ -3793,7 +3853,7 @@ function TableInner({
|
|
|
3793
3853
|
clipPath: `inset(${Math.max(0, visibleTop - cellTop)}px ${Math.max(0, cellLeft + cellWidth - visibleRight)}px ${Math.max(0, cellTop + cellHeight - visibleBottom)}px ${Math.max(0, visibleLeft - cellLeft)}px)`
|
|
3794
3854
|
};
|
|
3795
3855
|
}, [bodyTop, columns, editing, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getScrollableColumnLeft, leftFixedOffsets, metrics, renderHeight, rightFixedOffsets, rightFixedWidth, rowHeight, rows, rowStyle, viewport.width]);
|
|
3796
|
-
const handleColumnPointerDown =
|
|
3856
|
+
const handleColumnPointerDown = useCallback3((event) => {
|
|
3797
3857
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
3798
3858
|
const localY = event.clientY - rect.top;
|
|
3799
3859
|
const headerY = fixedHeader ? 0 : -scrollRef.current.top;
|
|
@@ -3837,7 +3897,7 @@ function TableInner({
|
|
|
3837
3897
|
return;
|
|
3838
3898
|
}
|
|
3839
3899
|
}, [fixedHeader, getHeaderCellLeft, getHeaderCellWidth, headerHeight, headerRowOffsets, locateHeaderResizeHit, metrics]);
|
|
3840
|
-
const handleColumnPointerMove =
|
|
3900
|
+
const handleColumnPointerMove = useCallback3((event) => {
|
|
3841
3901
|
const drag = columnDragRef.current;
|
|
3842
3902
|
if (!drag) return;
|
|
3843
3903
|
const column = columns[drag.columnIndex];
|
|
@@ -3873,7 +3933,7 @@ function TableInner({
|
|
|
3873
3933
|
resizeColumn(column.key, width2);
|
|
3874
3934
|
setGuideFromWidths([width2]);
|
|
3875
3935
|
}, [columnDraggable, columns, getHeaderCellEdgeFromMetrics, resizeColumn, viewport.width]);
|
|
3876
|
-
const handleColumnPointerUp =
|
|
3936
|
+
const handleColumnPointerUp = useCallback3((event) => {
|
|
3877
3937
|
const drag = columnDragRef.current;
|
|
3878
3938
|
if (!drag) return;
|
|
3879
3939
|
if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);
|
|
@@ -3883,7 +3943,7 @@ function TableInner({
|
|
|
3883
3943
|
document.documentElement.classList.remove("rvg-is-dragging");
|
|
3884
3944
|
event.currentTarget.style.cursor = "default";
|
|
3885
3945
|
}, []);
|
|
3886
|
-
const clearColumnOrderPointerDrag =
|
|
3946
|
+
const clearColumnOrderPointerDrag = useCallback3((canvas) => {
|
|
3887
3947
|
if (columnOrderLongPressTimerRef.current) {
|
|
3888
3948
|
clearTimeout(columnOrderLongPressTimerRef.current);
|
|
3889
3949
|
columnOrderLongPressTimerRef.current = null;
|
|
@@ -3896,7 +3956,7 @@ function TableInner({
|
|
|
3896
3956
|
document.documentElement.classList.remove("rvg-is-dragging");
|
|
3897
3957
|
canvas.style.cursor = "default";
|
|
3898
3958
|
}, [setDragGuide]);
|
|
3899
|
-
const updateColumnDragPreview =
|
|
3959
|
+
const updateColumnDragPreview = useCallback3((sourceCell, clientX, canvas) => {
|
|
3900
3960
|
const rootRect = rootRef.current?.getBoundingClientRect() ?? canvas.getBoundingClientRect();
|
|
3901
3961
|
const sourceWidth = metrics[sourceCell.startIndex]?.width ?? 100;
|
|
3902
3962
|
const previewWidth = sourceWidth;
|
|
@@ -3908,7 +3968,7 @@ function TableInner({
|
|
|
3908
3968
|
sourceLeft: getDisplayedColumnLeft(sourceCell.startIndex)
|
|
3909
3969
|
});
|
|
3910
3970
|
}, [getDisplayedColumnLeft, metrics, viewport.width]);
|
|
3911
|
-
const activateColumnOrderPointerDrag =
|
|
3971
|
+
const activateColumnOrderPointerDrag = useCallback3((canvas, clientX) => {
|
|
3912
3972
|
const drag = columnOrderDragRef.current;
|
|
3913
3973
|
if (!drag || drag.active) return;
|
|
3914
3974
|
if (columnOrderLongPressTimerRef.current) {
|
|
@@ -3922,7 +3982,7 @@ function TableInner({
|
|
|
3922
3982
|
canvas.style.cursor = "move";
|
|
3923
3983
|
updateColumnDragPreview(drag.sourceCell, clientX, canvas);
|
|
3924
3984
|
}, [hideDragTooltips, updateColumnDragPreview]);
|
|
3925
|
-
const handleColumnOrderPointerDown =
|
|
3985
|
+
const handleColumnOrderPointerDown = useCallback3((event) => {
|
|
3926
3986
|
if (!columnDraggable || event.button !== 0 || columnDragRef.current) return;
|
|
3927
3987
|
const sourceCell = locateHeaderCell(event.clientX, event.clientY);
|
|
3928
3988
|
if (!sourceCell || locateHeaderResizeCell(event.clientX, event.clientY)) return;
|
|
@@ -3946,7 +4006,7 @@ function TableInner({
|
|
|
3946
4006
|
activateColumnOrderPointerDrag(canvas, drag.startX);
|
|
3947
4007
|
}, 320);
|
|
3948
4008
|
}, [activateColumnOrderPointerDrag, columnDraggable, columns, locateHeaderAction, locateHeaderCell, locateHeaderResizeCell]);
|
|
3949
|
-
const handleColumnOrderPointerMove =
|
|
4009
|
+
const handleColumnOrderPointerMove = useCallback3((event) => {
|
|
3950
4010
|
const drag = columnOrderDragRef.current;
|
|
3951
4011
|
if (!drag || drag.pointerId !== event.pointerId || columnDragRef.current) return;
|
|
3952
4012
|
if (!drag.active) {
|
|
@@ -4017,7 +4077,7 @@ function TableInner({
|
|
|
4017
4077
|
columnEdge
|
|
4018
4078
|
};
|
|
4019
4079
|
}, [activateColumnOrderPointerDrag, columns, getHeaderCellLeft, getHeaderCellWidth, headerCells, headerRowOffsets, locateColumn, locateHeaderCell, setDragGuide, updateColumnDragPreview]);
|
|
4020
|
-
const finishColumnOrderPointerDrag =
|
|
4080
|
+
const finishColumnOrderPointerDrag = useCallback3((event, apply) => {
|
|
4021
4081
|
const drag = columnOrderDragRef.current;
|
|
4022
4082
|
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
4023
4083
|
if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);
|
|
@@ -4041,7 +4101,7 @@ function TableInner({
|
|
|
4041
4101
|
suppressClickRef.current = false;
|
|
4042
4102
|
}, 0);
|
|
4043
4103
|
}, [applyColumnOrder, clearColumnOrderPointerDrag, utilityColumnCount]);
|
|
4044
|
-
const queueSortStateChange =
|
|
4104
|
+
const queueSortStateChange = useCallback3((next) => {
|
|
4045
4105
|
setSortState(next);
|
|
4046
4106
|
}, []);
|
|
4047
4107
|
const renderHeaderIcons = (columnIndex, left) => {
|
|
@@ -4076,7 +4136,7 @@ function TableInner({
|
|
|
4076
4136
|
}
|
|
4077
4137
|
return icons;
|
|
4078
4138
|
};
|
|
4079
|
-
const createHeaderTooltip =
|
|
4139
|
+
const createHeaderTooltip = useCallback3((action, columnIndex, cell) => {
|
|
4080
4140
|
const column = cell?.column ?? columns[columnIndex];
|
|
4081
4141
|
if (!column) return null;
|
|
4082
4142
|
const cellLeft = cell ? getHeaderCellLeft(cell) : getDisplayedColumnLeft(columnIndex);
|
|
@@ -4145,7 +4205,7 @@ function TableInner({
|
|
|
4145
4205
|
placement
|
|
4146
4206
|
};
|
|
4147
4207
|
}, [baseHeaderHeight, columnDraggable, columns, filterValues, fixedHeader, getDisplayedColumnLeft, getHeaderCellLeft, getHeaderCellWidth, headerActionSize, headerActionSlotWidth, headerDepth, headerLeafHeight, headerLeafTop, headerRowHeights, headerRowOffsets, labels, measureHeaderTitleWidth, metrics, scrollPosition.top, sortState, viewport.width]);
|
|
4148
|
-
const isPointerOnHeaderTitle =
|
|
4208
|
+
const isPointerOnHeaderTitle = useCallback3((clientX, clientY, cell) => {
|
|
4149
4209
|
const canvas = canvasRef.current;
|
|
4150
4210
|
if (!canvas) return false;
|
|
4151
4211
|
const rect = canvas.getBoundingClientRect();
|
|
@@ -4166,7 +4226,7 @@ function TableInner({
|
|
|
4166
4226
|
const textTop = rowTop + 8;
|
|
4167
4227
|
return localX >= textLeft - 4 && localX <= textLeft + textWidth + 4 && localY >= textTop - 2 && localY <= textTop + 18;
|
|
4168
4228
|
}, [columnDraggable, fixedHeader, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, headerRowOffsets]);
|
|
4169
|
-
const locateCustomHeaderTooltip =
|
|
4229
|
+
const locateCustomHeaderTooltip = useCallback3((clientX, clientY, columnIndex) => {
|
|
4170
4230
|
const root = rootRef.current;
|
|
4171
4231
|
const canvas = canvasRef.current;
|
|
4172
4232
|
if (!root || !canvas || columnIndex < 0) return null;
|
|
@@ -4657,11 +4717,20 @@ function TableInner({
|
|
|
4657
4717
|
const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
|
|
4658
4718
|
const verticalStart = fixedHeader ? bodyTop : 0;
|
|
4659
4719
|
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom + dragOffset <= verticalStart || rawTop + dragOffset >= renderHeight) return null;
|
|
4660
|
-
const
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4720
|
+
const bounds = getSelectionOutlineBounds({
|
|
4721
|
+
left: rawLeft,
|
|
4722
|
+
right: rawRight,
|
|
4723
|
+
top: rawTop,
|
|
4724
|
+
bottom: rawBottom,
|
|
4725
|
+
horizontalStart,
|
|
4726
|
+
horizontalEnd,
|
|
4727
|
+
verticalStart,
|
|
4728
|
+
verticalEnd: renderHeight
|
|
4729
|
+
});
|
|
4730
|
+
const left = Math.round(bounds.left);
|
|
4731
|
+
const right = Math.round(bounds.right);
|
|
4732
|
+
const top = Math.round(bounds.top);
|
|
4733
|
+
const bottom = Math.round(bounds.bottom);
|
|
4665
4734
|
return {
|
|
4666
4735
|
left,
|
|
4667
4736
|
top,
|