@lensui/lens-table 0.1.81 → 0.1.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +101 -71
- package/dist/index.d.cts +0 -5
- package/dist/index.d.ts +0 -5
- package/dist/index.js +101 -71
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1144,6 +1144,24 @@ function ellipsizeText(context, text, maxWidth) {
|
|
|
1144
1144
|
}
|
|
1145
1145
|
return `${text.slice(0, start)}${ellipsis}`;
|
|
1146
1146
|
}
|
|
1147
|
+
function getSelectionOutlineBounds({
|
|
1148
|
+
left,
|
|
1149
|
+
right,
|
|
1150
|
+
top,
|
|
1151
|
+
bottom,
|
|
1152
|
+
horizontalStart,
|
|
1153
|
+
horizontalEnd,
|
|
1154
|
+
verticalStart,
|
|
1155
|
+
verticalEnd,
|
|
1156
|
+
borderWidth = 2
|
|
1157
|
+
}) {
|
|
1158
|
+
return {
|
|
1159
|
+
left: Math.max(left - borderWidth, horizontalStart - borderWidth),
|
|
1160
|
+
right: Math.min(right + 1, horizontalEnd + 1),
|
|
1161
|
+
top: Math.max(top - borderWidth, verticalStart - borderWidth),
|
|
1162
|
+
bottom: Math.min(bottom + borderWidth, verticalEnd + borderWidth)
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1147
1165
|
function paintGrid(options) {
|
|
1148
1166
|
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;
|
|
1149
1167
|
const headerLeafTop = options.headerLeafTop ?? 0;
|
|
@@ -1632,51 +1650,65 @@ function paintGrid(options) {
|
|
|
1632
1650
|
const visibleRight = x + selectionWidth;
|
|
1633
1651
|
const visibleBottom = y + selectionHeight;
|
|
1634
1652
|
const selectionTop = fixedHeader ? bodyTop : 0;
|
|
1635
|
-
const selectionClipTop = selectionTop;
|
|
1636
1653
|
const hiddenAboveHeader = visibleBottom <= selectionTop;
|
|
1637
1654
|
const hiddenBelowViewport = y >= height;
|
|
1638
1655
|
const hiddenBehindLeft = !isFixed && visibleRight <= visibleLeft;
|
|
1639
1656
|
const hiddenBehindRight = !isFixed && x >= selectionAreaRight;
|
|
1640
|
-
const leftMarkerX =
|
|
1657
|
+
const leftMarkerX = leftFixedWidth - borderWidth;
|
|
1658
|
+
const rightMarkerX = selectionAreaRight - 1;
|
|
1659
|
+
const topMarkerY = selectionTop - borderWidth;
|
|
1660
|
+
const bottomMarkerY = height;
|
|
1641
1661
|
if ((hiddenAboveHeader || hiddenBelowViewport) && (hiddenBehindLeft || hiddenBehindRight)) {
|
|
1642
1662
|
const markerSize = 2;
|
|
1643
|
-
const markerX = hiddenBehindLeft ? leftMarkerX :
|
|
1644
|
-
const markerY = hiddenAboveHeader ?
|
|
1663
|
+
const markerX = hiddenBehindLeft ? leftMarkerX : rightMarkerX;
|
|
1664
|
+
const markerY = hiddenAboveHeader ? topMarkerY : bottomMarkerY;
|
|
1645
1665
|
ctx.fillStyle = colors.selection;
|
|
1646
1666
|
ctx.fillRect(markerX, markerY, markerSize, markerSize);
|
|
1647
1667
|
return;
|
|
1648
1668
|
}
|
|
1669
|
+
const outline = getSelectionOutlineBounds({
|
|
1670
|
+
left: x,
|
|
1671
|
+
right: visibleRight,
|
|
1672
|
+
top: y,
|
|
1673
|
+
bottom: visibleBottom,
|
|
1674
|
+
horizontalStart: visibleLeft,
|
|
1675
|
+
horizontalEnd: selectionAreaRight,
|
|
1676
|
+
verticalStart: selectionTop,
|
|
1677
|
+
verticalEnd: height,
|
|
1678
|
+
borderWidth
|
|
1679
|
+
});
|
|
1649
1680
|
ctx.save();
|
|
1650
1681
|
ctx.beginPath();
|
|
1651
|
-
const clipLeft =
|
|
1682
|
+
const clipLeft = Math.max(0, outline.left);
|
|
1652
1683
|
const clipRight = Math.min(width, selectionAreaRight + 1);
|
|
1653
|
-
|
|
1684
|
+
const clipTop = Math.max(0, outline.top);
|
|
1685
|
+
ctx.rect(clipLeft, clipTop, clipRight - clipLeft, height - clipTop);
|
|
1654
1686
|
ctx.clip();
|
|
1655
1687
|
ctx.fillStyle = colors.selection;
|
|
1656
1688
|
if (hiddenAboveHeader) {
|
|
1657
|
-
const markerLeft = Math.max(x - borderWidth, visibleLeft -
|
|
1658
|
-
const markerRight = Math.min(visibleRight + 1, selectionAreaRight);
|
|
1659
|
-
if (markerRight > markerLeft) ctx.fillRect(markerLeft,
|
|
1689
|
+
const markerLeft = Math.max(x - borderWidth, visibleLeft - borderWidth);
|
|
1690
|
+
const markerRight = Math.min(visibleRight + 1, selectionAreaRight + 1);
|
|
1691
|
+
if (markerRight > markerLeft) ctx.fillRect(markerLeft, topMarkerY, markerRight - markerLeft, borderWidth);
|
|
1660
1692
|
}
|
|
1661
1693
|
if (hiddenBelowViewport) {
|
|
1662
|
-
const markerLeft = Math.max(x - borderWidth, visibleLeft -
|
|
1663
|
-
const markerRight = Math.min(visibleRight + 1, selectionAreaRight);
|
|
1664
|
-
if (markerRight > markerLeft) ctx.fillRect(markerLeft,
|
|
1694
|
+
const markerLeft = Math.max(x - borderWidth, visibleLeft - borderWidth);
|
|
1695
|
+
const markerRight = Math.min(visibleRight + 1, selectionAreaRight + 1);
|
|
1696
|
+
if (markerRight > markerLeft) ctx.fillRect(markerLeft, bottomMarkerY, markerRight - markerLeft, borderWidth);
|
|
1665
1697
|
}
|
|
1666
1698
|
if (hiddenBehindLeft || hiddenBehindRight) {
|
|
1667
|
-
const markerTop = Math.max(y - borderWidth, selectionTop);
|
|
1668
|
-
const markerBottom = Math.min(y + selectionHeight +
|
|
1669
|
-
const markerX = hiddenBehindLeft ? leftMarkerX :
|
|
1699
|
+
const markerTop = Math.max(y - borderWidth, selectionTop - borderWidth);
|
|
1700
|
+
const markerBottom = Math.min(y + selectionHeight + borderWidth, height + borderWidth);
|
|
1701
|
+
const markerX = hiddenBehindLeft ? leftMarkerX : rightMarkerX;
|
|
1670
1702
|
ctx.fillRect(markerX, markerTop, borderWidth, Math.max(0, markerBottom - markerTop));
|
|
1671
1703
|
}
|
|
1672
1704
|
if (hiddenAboveHeader || hiddenBelowViewport || hiddenBehindLeft || hiddenBehindRight) {
|
|
1673
1705
|
ctx.restore();
|
|
1674
1706
|
return;
|
|
1675
1707
|
}
|
|
1676
|
-
const borderLeft =
|
|
1677
|
-
const borderRight =
|
|
1678
|
-
const borderTop =
|
|
1679
|
-
const borderBottom =
|
|
1708
|
+
const borderLeft = outline.left;
|
|
1709
|
+
const borderRight = outline.right - borderWidth;
|
|
1710
|
+
const borderTop = outline.top;
|
|
1711
|
+
const borderBottom = outline.bottom - borderWidth;
|
|
1680
1712
|
const borderOuterWidth = borderRight + borderWidth - borderLeft;
|
|
1681
1713
|
ctx.fillRect(borderLeft, borderTop, borderOuterWidth, borderWidth);
|
|
1682
1714
|
ctx.fillRect(borderLeft, borderBottom, borderOuterWidth, borderWidth);
|
|
@@ -1929,9 +1961,6 @@ function TableInner({
|
|
|
1929
1961
|
defaultSelectedCell,
|
|
1930
1962
|
onSelectedCellChange,
|
|
1931
1963
|
rangeSelection = false,
|
|
1932
|
-
selectedRange,
|
|
1933
|
-
defaultSelectedRange,
|
|
1934
|
-
onSelectedRangeChange,
|
|
1935
1964
|
rowSelection,
|
|
1936
1965
|
selectedRowKeys,
|
|
1937
1966
|
defaultSelectedRowKeys,
|
|
@@ -2341,20 +2370,6 @@ function TableInner({
|
|
|
2341
2370
|
}, [columns, getDataRowKey, rows]);
|
|
2342
2371
|
const resolvedSelectedCell = (0, import_react8.useMemo)(() => resolveSelectionTarget(selectedCell), [resolveSelectionTarget, selectedCell]);
|
|
2343
2372
|
const resolvedDefaultSelectedCell = (0, import_react8.useMemo)(() => resolveSelectionTarget(defaultSelectedCell), [defaultSelectedCell, resolveSelectionTarget]);
|
|
2344
|
-
const resolveSelectionRangeTarget = (0, import_react8.useCallback)((target) => {
|
|
2345
|
-
if (target == null) return target;
|
|
2346
|
-
const anchor = resolveSelectionTarget(target.anchor);
|
|
2347
|
-
const focus = resolveSelectionTarget(target.focus);
|
|
2348
|
-
return anchor && focus ? { anchor, focus } : null;
|
|
2349
|
-
}, [resolveSelectionTarget]);
|
|
2350
|
-
const resolvedSelectedRange = (0, import_react8.useMemo)(
|
|
2351
|
-
() => resolveSelectionRangeTarget(selectedRange),
|
|
2352
|
-
[resolveSelectionRangeTarget, selectedRange]
|
|
2353
|
-
);
|
|
2354
|
-
const resolvedDefaultSelectedRange = (0, import_react8.useMemo)(
|
|
2355
|
-
() => resolveSelectionRangeTarget(defaultSelectedRange),
|
|
2356
|
-
[defaultSelectedRange, resolveSelectionRangeTarget]
|
|
2357
|
-
);
|
|
2358
2373
|
const handleSelectedCellChange = (0, import_react8.useCallback)((next) => {
|
|
2359
2374
|
if (!onSelectedCellChange) return;
|
|
2360
2375
|
if (!next) {
|
|
@@ -2367,11 +2382,7 @@ function TableInner({
|
|
|
2367
2382
|
onSelectedCellChange({ ...next, value });
|
|
2368
2383
|
}, [columns, onSelectedCellChange, rows]);
|
|
2369
2384
|
const [selection, setSelection] = useControllableValue(resolvedSelectedCell, resolvedDefaultSelectedCell, handleSelectedCellChange);
|
|
2370
|
-
const [selectionRange, setSelectionRange] =
|
|
2371
|
-
resolvedSelectedRange,
|
|
2372
|
-
resolvedDefaultSelectedRange,
|
|
2373
|
-
onSelectedRangeChange
|
|
2374
|
-
);
|
|
2385
|
+
const [selectionRange, setSelectionRange] = (0, import_react8.useState)(null);
|
|
2375
2386
|
const rangeDragRef = (0, import_react8.useRef)(null);
|
|
2376
2387
|
(0, import_react8.useEffect)(() => {
|
|
2377
2388
|
if (!selection) return void 0;
|
|
@@ -2717,14 +2728,17 @@ function TableInner({
|
|
|
2717
2728
|
const cornerLength = 10;
|
|
2718
2729
|
const hitSlop = 6;
|
|
2719
2730
|
const targetSize = borderWidth + hitSlop * 2;
|
|
2720
|
-
const
|
|
2721
|
-
const
|
|
2722
|
-
const
|
|
2731
|
+
const leftBoundary = horizontalStart - borderWidth;
|
|
2732
|
+
const rightBoundary = horizontalEnd - 1;
|
|
2733
|
+
const topBoundary = verticalStart - borderWidth;
|
|
2734
|
+
const bottomBoundary = renderHeight;
|
|
2735
|
+
const markerX = hiddenLeft ? leftBoundary : rightBoundary;
|
|
2736
|
+
const markerY = hiddenTop ? topBoundary : bottomBoundary;
|
|
2723
2737
|
if (hiddenLeft || hiddenRight) {
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
const topClip = Math.max(0, verticalStart -
|
|
2727
|
-
const bottomClip = Math.max(0, rawBottom
|
|
2738
|
+
const markerTop = Math.max(rawTop - borderWidth, topBoundary);
|
|
2739
|
+
const markerBottom = Math.min(rawBottom + borderWidth, renderHeight + borderWidth);
|
|
2740
|
+
const topClip = Math.max(0, verticalStart - rawTop);
|
|
2741
|
+
const bottomClip = Math.max(0, rawBottom - renderHeight);
|
|
2728
2742
|
if (topClip > 0 || bottomClip > 0) {
|
|
2729
2743
|
const foldAtTop = topClip > 0;
|
|
2730
2744
|
const fold = Math.min(cornerLength, foldAtTop ? topClip : bottomClip);
|
|
@@ -2733,7 +2747,7 @@ function TableInner({
|
|
|
2733
2747
|
const cornerHeight = Math.max(cornerLength, markerBottom - markerTop);
|
|
2734
2748
|
const cornerOnLeft = hiddenLeft;
|
|
2735
2749
|
const shapeLeft = cornerOnLeft ? markerX : markerX + borderWidth - cornerWidth;
|
|
2736
|
-
const shapeTop = foldAtTop ?
|
|
2750
|
+
const shapeTop = foldAtTop ? topBoundary : renderHeight + borderWidth - cornerHeight;
|
|
2737
2751
|
return {
|
|
2738
2752
|
side: `${foldAtTop ? "top" : "bottom"}-${cornerOnLeft ? "left" : "right"}`,
|
|
2739
2753
|
orientation: "corner",
|
|
@@ -2760,19 +2774,19 @@ function TableInner({
|
|
|
2760
2774
|
}
|
|
2761
2775
|
};
|
|
2762
2776
|
}
|
|
2763
|
-
const horizontalMarkerEnd = horizontalEnd
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
const leftClip = Math.max(0, horizontalStart -
|
|
2767
|
-
const rightClip = Math.max(0, rawRight
|
|
2777
|
+
const horizontalMarkerEnd = horizontalEnd + 1;
|
|
2778
|
+
const markerLeft = Math.max(rawLeft - borderWidth, leftBoundary);
|
|
2779
|
+
const markerRight = Math.min(rawRight + 1, horizontalMarkerEnd);
|
|
2780
|
+
const leftClip = Math.max(0, horizontalStart - rawLeft);
|
|
2781
|
+
const rightClip = Math.max(0, rawRight - horizontalEnd);
|
|
2768
2782
|
if (leftClip > 0 || rightClip > 0) {
|
|
2769
2783
|
const foldAtLeft = leftClip > 0;
|
|
2770
2784
|
const fold = Math.min(cornerLength, foldAtLeft ? leftClip : rightClip);
|
|
2771
2785
|
if (fold > borderWidth) {
|
|
2772
2786
|
const cornerWidth = Math.max(cornerLength, markerRight - markerLeft);
|
|
2773
2787
|
const cornerHeight = fold;
|
|
2774
|
-
const shapeLeft = foldAtLeft ?
|
|
2775
|
-
const shapeTop = hiddenTop ?
|
|
2788
|
+
const shapeLeft = foldAtLeft ? leftBoundary : horizontalMarkerEnd - cornerWidth;
|
|
2789
|
+
const shapeTop = hiddenTop ? topBoundary : renderHeight + borderWidth - cornerHeight;
|
|
2776
2790
|
return {
|
|
2777
2791
|
side: `${hiddenTop ? "top" : "bottom"}-${foldAtLeft ? "left" : "right"}`,
|
|
2778
2792
|
orientation: "corner",
|
|
@@ -2798,7 +2812,7 @@ function TableInner({
|
|
|
2798
2812
|
height: targetSize
|
|
2799
2813
|
}
|
|
2800
2814
|
};
|
|
2801
|
-
}, [bodyTop, columns, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, getScrollableColumnLeft,
|
|
2815
|
+
}, [bodyTop, columns, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, getScrollableColumnLeft, leftFixedOffsets, metrics, renderHeight, rightFixedOffsets, rightFixedWidth, rowHeight, rows, selection, selectionRange, viewport.width]);
|
|
2802
2816
|
const syncSelectionEdgeTarget = (0, import_react8.useCallback)((scrollLeft, scrollTop) => {
|
|
2803
2817
|
const target = selectionEdgeTargetRef.current;
|
|
2804
2818
|
if (!target) return;
|
|
@@ -3168,11 +3182,20 @@ function TableInner({
|
|
|
3168
3182
|
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= renderHeight) {
|
|
3169
3183
|
focus.style.display = "none";
|
|
3170
3184
|
} else {
|
|
3171
|
-
const
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3185
|
+
const bounds = getSelectionOutlineBounds({
|
|
3186
|
+
left: rawLeft,
|
|
3187
|
+
right: rawRight,
|
|
3188
|
+
top: rawTop,
|
|
3189
|
+
bottom: rawBottom,
|
|
3190
|
+
horizontalStart,
|
|
3191
|
+
horizontalEnd,
|
|
3192
|
+
verticalStart,
|
|
3193
|
+
verticalEnd: renderHeight
|
|
3194
|
+
});
|
|
3195
|
+
const left = Math.round(bounds.left);
|
|
3196
|
+
const right = Math.round(bounds.right);
|
|
3197
|
+
const top = Math.round(bounds.top);
|
|
3198
|
+
const bottom = Math.round(bounds.bottom);
|
|
3176
3199
|
focus.style.display = "block";
|
|
3177
3200
|
focus.style.left = `${left}px`;
|
|
3178
3201
|
focus.style.top = `${top}px`;
|
|
@@ -3497,10 +3520,8 @@ function TableInner({
|
|
|
3497
3520
|
if (focus.rowIndex === drag.anchor.rowIndex && focus.columnIndex === drag.anchor.columnIndex) return;
|
|
3498
3521
|
drag.moved = true;
|
|
3499
3522
|
event.preventDefault();
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
setSelectionRange({ anchor: drag.anchor, focus });
|
|
3503
|
-
}, [columns, locateCell, selectionRange, setSelectionRange]);
|
|
3523
|
+
setSelectionRange((current) => current?.focus.rowIndex === focus.rowIndex && current.focus.columnIndex === focus.columnIndex ? current : { anchor: drag.anchor, focus });
|
|
3524
|
+
}, [columns, locateCell]);
|
|
3504
3525
|
const endRangeDrag = (0, import_react8.useCallback)((event) => {
|
|
3505
3526
|
const drag = rangeDragRef.current;
|
|
3506
3527
|
if (!drag) return;
|
|
@@ -4710,11 +4731,20 @@ function TableInner({
|
|
|
4710
4731
|
const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
|
|
4711
4732
|
const verticalStart = fixedHeader ? bodyTop : 0;
|
|
4712
4733
|
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom + dragOffset <= verticalStart || rawTop + dragOffset >= renderHeight) return null;
|
|
4713
|
-
const
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4734
|
+
const bounds = getSelectionOutlineBounds({
|
|
4735
|
+
left: rawLeft,
|
|
4736
|
+
right: rawRight,
|
|
4737
|
+
top: rawTop,
|
|
4738
|
+
bottom: rawBottom,
|
|
4739
|
+
horizontalStart,
|
|
4740
|
+
horizontalEnd,
|
|
4741
|
+
verticalStart,
|
|
4742
|
+
verticalEnd: renderHeight
|
|
4743
|
+
});
|
|
4744
|
+
const left = Math.round(bounds.left);
|
|
4745
|
+
const right = Math.round(bounds.right);
|
|
4746
|
+
const top = Math.round(bounds.top);
|
|
4747
|
+
const bottom = Math.round(bounds.bottom);
|
|
4718
4748
|
return {
|
|
4719
4749
|
left,
|
|
4720
4750
|
top,
|
package/dist/index.d.cts
CHANGED
|
@@ -415,11 +415,6 @@ interface TableProps<Row extends object> {
|
|
|
415
415
|
onSelectedCellChange?: (selection: SelectedCellChange | null) => void;
|
|
416
416
|
/** Enable spreadsheet-style mouse drag selection across multiple body cells. Defaults to false. */
|
|
417
417
|
rangeSelection?: boolean;
|
|
418
|
-
/** Controlled rectangular cell selection. */
|
|
419
|
-
selectedRange?: GridSelectionRangeTarget | null;
|
|
420
|
-
/** Initial rectangular cell selection for uncontrolled usage. */
|
|
421
|
-
defaultSelectedRange?: GridSelectionRangeTarget | null;
|
|
422
|
-
onSelectedRangeChange?: (range: GridSelectionRange | null) => void;
|
|
423
418
|
rowSelection?: boolean | RowSelectionConfig;
|
|
424
419
|
selectedRowKeys?: GridKey[];
|
|
425
420
|
defaultSelectedRowKeys?: GridKey[];
|
package/dist/index.d.ts
CHANGED
|
@@ -415,11 +415,6 @@ interface TableProps<Row extends object> {
|
|
|
415
415
|
onSelectedCellChange?: (selection: SelectedCellChange | null) => void;
|
|
416
416
|
/** Enable spreadsheet-style mouse drag selection across multiple body cells. Defaults to false. */
|
|
417
417
|
rangeSelection?: boolean;
|
|
418
|
-
/** Controlled rectangular cell selection. */
|
|
419
|
-
selectedRange?: GridSelectionRangeTarget | null;
|
|
420
|
-
/** Initial rectangular cell selection for uncontrolled usage. */
|
|
421
|
-
defaultSelectedRange?: GridSelectionRangeTarget | null;
|
|
422
|
-
onSelectedRangeChange?: (range: GridSelectionRange | null) => void;
|
|
423
418
|
rowSelection?: boolean | RowSelectionConfig;
|
|
424
419
|
selectedRowKeys?: GridKey[];
|
|
425
420
|
defaultSelectedRowKeys?: GridKey[];
|
package/dist/index.js
CHANGED
|
@@ -1114,6 +1114,24 @@ function ellipsizeText(context, text, maxWidth) {
|
|
|
1114
1114
|
}
|
|
1115
1115
|
return `${text.slice(0, start)}${ellipsis}`;
|
|
1116
1116
|
}
|
|
1117
|
+
function getSelectionOutlineBounds({
|
|
1118
|
+
left,
|
|
1119
|
+
right,
|
|
1120
|
+
top,
|
|
1121
|
+
bottom,
|
|
1122
|
+
horizontalStart,
|
|
1123
|
+
horizontalEnd,
|
|
1124
|
+
verticalStart,
|
|
1125
|
+
verticalEnd,
|
|
1126
|
+
borderWidth = 2
|
|
1127
|
+
}) {
|
|
1128
|
+
return {
|
|
1129
|
+
left: Math.max(left - borderWidth, horizontalStart - borderWidth),
|
|
1130
|
+
right: Math.min(right + 1, horizontalEnd + 1),
|
|
1131
|
+
top: Math.max(top - borderWidth, verticalStart - borderWidth),
|
|
1132
|
+
bottom: Math.min(bottom + borderWidth, verticalEnd + borderWidth)
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1117
1135
|
function paintGrid(options) {
|
|
1118
1136
|
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
1137
|
const headerLeafTop = options.headerLeafTop ?? 0;
|
|
@@ -1602,51 +1620,65 @@ function paintGrid(options) {
|
|
|
1602
1620
|
const visibleRight = x + selectionWidth;
|
|
1603
1621
|
const visibleBottom = y + selectionHeight;
|
|
1604
1622
|
const selectionTop = fixedHeader ? bodyTop : 0;
|
|
1605
|
-
const selectionClipTop = selectionTop;
|
|
1606
1623
|
const hiddenAboveHeader = visibleBottom <= selectionTop;
|
|
1607
1624
|
const hiddenBelowViewport = y >= height;
|
|
1608
1625
|
const hiddenBehindLeft = !isFixed && visibleRight <= visibleLeft;
|
|
1609
1626
|
const hiddenBehindRight = !isFixed && x >= selectionAreaRight;
|
|
1610
|
-
const leftMarkerX =
|
|
1627
|
+
const leftMarkerX = leftFixedWidth - borderWidth;
|
|
1628
|
+
const rightMarkerX = selectionAreaRight - 1;
|
|
1629
|
+
const topMarkerY = selectionTop - borderWidth;
|
|
1630
|
+
const bottomMarkerY = height;
|
|
1611
1631
|
if ((hiddenAboveHeader || hiddenBelowViewport) && (hiddenBehindLeft || hiddenBehindRight)) {
|
|
1612
1632
|
const markerSize = 2;
|
|
1613
|
-
const markerX = hiddenBehindLeft ? leftMarkerX :
|
|
1614
|
-
const markerY = hiddenAboveHeader ?
|
|
1633
|
+
const markerX = hiddenBehindLeft ? leftMarkerX : rightMarkerX;
|
|
1634
|
+
const markerY = hiddenAboveHeader ? topMarkerY : bottomMarkerY;
|
|
1615
1635
|
ctx.fillStyle = colors.selection;
|
|
1616
1636
|
ctx.fillRect(markerX, markerY, markerSize, markerSize);
|
|
1617
1637
|
return;
|
|
1618
1638
|
}
|
|
1639
|
+
const outline = getSelectionOutlineBounds({
|
|
1640
|
+
left: x,
|
|
1641
|
+
right: visibleRight,
|
|
1642
|
+
top: y,
|
|
1643
|
+
bottom: visibleBottom,
|
|
1644
|
+
horizontalStart: visibleLeft,
|
|
1645
|
+
horizontalEnd: selectionAreaRight,
|
|
1646
|
+
verticalStart: selectionTop,
|
|
1647
|
+
verticalEnd: height,
|
|
1648
|
+
borderWidth
|
|
1649
|
+
});
|
|
1619
1650
|
ctx.save();
|
|
1620
1651
|
ctx.beginPath();
|
|
1621
|
-
const clipLeft =
|
|
1652
|
+
const clipLeft = Math.max(0, outline.left);
|
|
1622
1653
|
const clipRight = Math.min(width, selectionAreaRight + 1);
|
|
1623
|
-
|
|
1654
|
+
const clipTop = Math.max(0, outline.top);
|
|
1655
|
+
ctx.rect(clipLeft, clipTop, clipRight - clipLeft, height - clipTop);
|
|
1624
1656
|
ctx.clip();
|
|
1625
1657
|
ctx.fillStyle = colors.selection;
|
|
1626
1658
|
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,
|
|
1659
|
+
const markerLeft = Math.max(x - borderWidth, visibleLeft - borderWidth);
|
|
1660
|
+
const markerRight = Math.min(visibleRight + 1, selectionAreaRight + 1);
|
|
1661
|
+
if (markerRight > markerLeft) ctx.fillRect(markerLeft, topMarkerY, markerRight - markerLeft, borderWidth);
|
|
1630
1662
|
}
|
|
1631
1663
|
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,
|
|
1664
|
+
const markerLeft = Math.max(x - borderWidth, visibleLeft - borderWidth);
|
|
1665
|
+
const markerRight = Math.min(visibleRight + 1, selectionAreaRight + 1);
|
|
1666
|
+
if (markerRight > markerLeft) ctx.fillRect(markerLeft, bottomMarkerY, markerRight - markerLeft, borderWidth);
|
|
1635
1667
|
}
|
|
1636
1668
|
if (hiddenBehindLeft || hiddenBehindRight) {
|
|
1637
|
-
const markerTop = Math.max(y - borderWidth, selectionTop);
|
|
1638
|
-
const markerBottom = Math.min(y + selectionHeight +
|
|
1639
|
-
const markerX = hiddenBehindLeft ? leftMarkerX :
|
|
1669
|
+
const markerTop = Math.max(y - borderWidth, selectionTop - borderWidth);
|
|
1670
|
+
const markerBottom = Math.min(y + selectionHeight + borderWidth, height + borderWidth);
|
|
1671
|
+
const markerX = hiddenBehindLeft ? leftMarkerX : rightMarkerX;
|
|
1640
1672
|
ctx.fillRect(markerX, markerTop, borderWidth, Math.max(0, markerBottom - markerTop));
|
|
1641
1673
|
}
|
|
1642
1674
|
if (hiddenAboveHeader || hiddenBelowViewport || hiddenBehindLeft || hiddenBehindRight) {
|
|
1643
1675
|
ctx.restore();
|
|
1644
1676
|
return;
|
|
1645
1677
|
}
|
|
1646
|
-
const borderLeft =
|
|
1647
|
-
const borderRight =
|
|
1648
|
-
const borderTop =
|
|
1649
|
-
const borderBottom =
|
|
1678
|
+
const borderLeft = outline.left;
|
|
1679
|
+
const borderRight = outline.right - borderWidth;
|
|
1680
|
+
const borderTop = outline.top;
|
|
1681
|
+
const borderBottom = outline.bottom - borderWidth;
|
|
1650
1682
|
const borderOuterWidth = borderRight + borderWidth - borderLeft;
|
|
1651
1683
|
ctx.fillRect(borderLeft, borderTop, borderOuterWidth, borderWidth);
|
|
1652
1684
|
ctx.fillRect(borderLeft, borderBottom, borderOuterWidth, borderWidth);
|
|
@@ -1899,9 +1931,6 @@ function TableInner({
|
|
|
1899
1931
|
defaultSelectedCell,
|
|
1900
1932
|
onSelectedCellChange,
|
|
1901
1933
|
rangeSelection = false,
|
|
1902
|
-
selectedRange,
|
|
1903
|
-
defaultSelectedRange,
|
|
1904
|
-
onSelectedRangeChange,
|
|
1905
1934
|
rowSelection,
|
|
1906
1935
|
selectedRowKeys,
|
|
1907
1936
|
defaultSelectedRowKeys,
|
|
@@ -2311,20 +2340,6 @@ function TableInner({
|
|
|
2311
2340
|
}, [columns, getDataRowKey, rows]);
|
|
2312
2341
|
const resolvedSelectedCell = useMemo2(() => resolveSelectionTarget(selectedCell), [resolveSelectionTarget, selectedCell]);
|
|
2313
2342
|
const resolvedDefaultSelectedCell = useMemo2(() => resolveSelectionTarget(defaultSelectedCell), [defaultSelectedCell, resolveSelectionTarget]);
|
|
2314
|
-
const resolveSelectionRangeTarget = useCallback2((target) => {
|
|
2315
|
-
if (target == null) return target;
|
|
2316
|
-
const anchor = resolveSelectionTarget(target.anchor);
|
|
2317
|
-
const focus = resolveSelectionTarget(target.focus);
|
|
2318
|
-
return anchor && focus ? { anchor, focus } : null;
|
|
2319
|
-
}, [resolveSelectionTarget]);
|
|
2320
|
-
const resolvedSelectedRange = useMemo2(
|
|
2321
|
-
() => resolveSelectionRangeTarget(selectedRange),
|
|
2322
|
-
[resolveSelectionRangeTarget, selectedRange]
|
|
2323
|
-
);
|
|
2324
|
-
const resolvedDefaultSelectedRange = useMemo2(
|
|
2325
|
-
() => resolveSelectionRangeTarget(defaultSelectedRange),
|
|
2326
|
-
[defaultSelectedRange, resolveSelectionRangeTarget]
|
|
2327
|
-
);
|
|
2328
2343
|
const handleSelectedCellChange = useCallback2((next) => {
|
|
2329
2344
|
if (!onSelectedCellChange) return;
|
|
2330
2345
|
if (!next) {
|
|
@@ -2337,11 +2352,7 @@ function TableInner({
|
|
|
2337
2352
|
onSelectedCellChange({ ...next, value });
|
|
2338
2353
|
}, [columns, onSelectedCellChange, rows]);
|
|
2339
2354
|
const [selection, setSelection] = useControllableValue(resolvedSelectedCell, resolvedDefaultSelectedCell, handleSelectedCellChange);
|
|
2340
|
-
const [selectionRange, setSelectionRange] =
|
|
2341
|
-
resolvedSelectedRange,
|
|
2342
|
-
resolvedDefaultSelectedRange,
|
|
2343
|
-
onSelectedRangeChange
|
|
2344
|
-
);
|
|
2355
|
+
const [selectionRange, setSelectionRange] = useState6(null);
|
|
2345
2356
|
const rangeDragRef = useRef4(null);
|
|
2346
2357
|
useEffect3(() => {
|
|
2347
2358
|
if (!selection) return void 0;
|
|
@@ -2687,14 +2698,17 @@ function TableInner({
|
|
|
2687
2698
|
const cornerLength = 10;
|
|
2688
2699
|
const hitSlop = 6;
|
|
2689
2700
|
const targetSize = borderWidth + hitSlop * 2;
|
|
2690
|
-
const
|
|
2691
|
-
const
|
|
2692
|
-
const
|
|
2701
|
+
const leftBoundary = horizontalStart - borderWidth;
|
|
2702
|
+
const rightBoundary = horizontalEnd - 1;
|
|
2703
|
+
const topBoundary = verticalStart - borderWidth;
|
|
2704
|
+
const bottomBoundary = renderHeight;
|
|
2705
|
+
const markerX = hiddenLeft ? leftBoundary : rightBoundary;
|
|
2706
|
+
const markerY = hiddenTop ? topBoundary : bottomBoundary;
|
|
2693
2707
|
if (hiddenLeft || hiddenRight) {
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
const topClip = Math.max(0, verticalStart -
|
|
2697
|
-
const bottomClip = Math.max(0, rawBottom
|
|
2708
|
+
const markerTop = Math.max(rawTop - borderWidth, topBoundary);
|
|
2709
|
+
const markerBottom = Math.min(rawBottom + borderWidth, renderHeight + borderWidth);
|
|
2710
|
+
const topClip = Math.max(0, verticalStart - rawTop);
|
|
2711
|
+
const bottomClip = Math.max(0, rawBottom - renderHeight);
|
|
2698
2712
|
if (topClip > 0 || bottomClip > 0) {
|
|
2699
2713
|
const foldAtTop = topClip > 0;
|
|
2700
2714
|
const fold = Math.min(cornerLength, foldAtTop ? topClip : bottomClip);
|
|
@@ -2703,7 +2717,7 @@ function TableInner({
|
|
|
2703
2717
|
const cornerHeight = Math.max(cornerLength, markerBottom - markerTop);
|
|
2704
2718
|
const cornerOnLeft = hiddenLeft;
|
|
2705
2719
|
const shapeLeft = cornerOnLeft ? markerX : markerX + borderWidth - cornerWidth;
|
|
2706
|
-
const shapeTop = foldAtTop ?
|
|
2720
|
+
const shapeTop = foldAtTop ? topBoundary : renderHeight + borderWidth - cornerHeight;
|
|
2707
2721
|
return {
|
|
2708
2722
|
side: `${foldAtTop ? "top" : "bottom"}-${cornerOnLeft ? "left" : "right"}`,
|
|
2709
2723
|
orientation: "corner",
|
|
@@ -2730,19 +2744,19 @@ function TableInner({
|
|
|
2730
2744
|
}
|
|
2731
2745
|
};
|
|
2732
2746
|
}
|
|
2733
|
-
const horizontalMarkerEnd = horizontalEnd
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
const leftClip = Math.max(0, horizontalStart -
|
|
2737
|
-
const rightClip = Math.max(0, rawRight
|
|
2747
|
+
const horizontalMarkerEnd = horizontalEnd + 1;
|
|
2748
|
+
const markerLeft = Math.max(rawLeft - borderWidth, leftBoundary);
|
|
2749
|
+
const markerRight = Math.min(rawRight + 1, horizontalMarkerEnd);
|
|
2750
|
+
const leftClip = Math.max(0, horizontalStart - rawLeft);
|
|
2751
|
+
const rightClip = Math.max(0, rawRight - horizontalEnd);
|
|
2738
2752
|
if (leftClip > 0 || rightClip > 0) {
|
|
2739
2753
|
const foldAtLeft = leftClip > 0;
|
|
2740
2754
|
const fold = Math.min(cornerLength, foldAtLeft ? leftClip : rightClip);
|
|
2741
2755
|
if (fold > borderWidth) {
|
|
2742
2756
|
const cornerWidth = Math.max(cornerLength, markerRight - markerLeft);
|
|
2743
2757
|
const cornerHeight = fold;
|
|
2744
|
-
const shapeLeft = foldAtLeft ?
|
|
2745
|
-
const shapeTop = hiddenTop ?
|
|
2758
|
+
const shapeLeft = foldAtLeft ? leftBoundary : horizontalMarkerEnd - cornerWidth;
|
|
2759
|
+
const shapeTop = hiddenTop ? topBoundary : renderHeight + borderWidth - cornerHeight;
|
|
2746
2760
|
return {
|
|
2747
2761
|
side: `${hiddenTop ? "top" : "bottom"}-${foldAtLeft ? "left" : "right"}`,
|
|
2748
2762
|
orientation: "corner",
|
|
@@ -2768,7 +2782,7 @@ function TableInner({
|
|
|
2768
2782
|
height: targetSize
|
|
2769
2783
|
}
|
|
2770
2784
|
};
|
|
2771
|
-
}, [bodyTop, columns, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, getScrollableColumnLeft,
|
|
2785
|
+
}, [bodyTop, columns, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, getScrollableColumnLeft, leftFixedOffsets, metrics, renderHeight, rightFixedOffsets, rightFixedWidth, rowHeight, rows, selection, selectionRange, viewport.width]);
|
|
2772
2786
|
const syncSelectionEdgeTarget = useCallback2((scrollLeft, scrollTop) => {
|
|
2773
2787
|
const target = selectionEdgeTargetRef.current;
|
|
2774
2788
|
if (!target) return;
|
|
@@ -3138,11 +3152,20 @@ function TableInner({
|
|
|
3138
3152
|
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= renderHeight) {
|
|
3139
3153
|
focus.style.display = "none";
|
|
3140
3154
|
} else {
|
|
3141
|
-
const
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3155
|
+
const bounds = getSelectionOutlineBounds({
|
|
3156
|
+
left: rawLeft,
|
|
3157
|
+
right: rawRight,
|
|
3158
|
+
top: rawTop,
|
|
3159
|
+
bottom: rawBottom,
|
|
3160
|
+
horizontalStart,
|
|
3161
|
+
horizontalEnd,
|
|
3162
|
+
verticalStart,
|
|
3163
|
+
verticalEnd: renderHeight
|
|
3164
|
+
});
|
|
3165
|
+
const left = Math.round(bounds.left);
|
|
3166
|
+
const right = Math.round(bounds.right);
|
|
3167
|
+
const top = Math.round(bounds.top);
|
|
3168
|
+
const bottom = Math.round(bounds.bottom);
|
|
3146
3169
|
focus.style.display = "block";
|
|
3147
3170
|
focus.style.left = `${left}px`;
|
|
3148
3171
|
focus.style.top = `${top}px`;
|
|
@@ -3467,10 +3490,8 @@ function TableInner({
|
|
|
3467
3490
|
if (focus.rowIndex === drag.anchor.rowIndex && focus.columnIndex === drag.anchor.columnIndex) return;
|
|
3468
3491
|
drag.moved = true;
|
|
3469
3492
|
event.preventDefault();
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
setSelectionRange({ anchor: drag.anchor, focus });
|
|
3473
|
-
}, [columns, locateCell, selectionRange, setSelectionRange]);
|
|
3493
|
+
setSelectionRange((current) => current?.focus.rowIndex === focus.rowIndex && current.focus.columnIndex === focus.columnIndex ? current : { anchor: drag.anchor, focus });
|
|
3494
|
+
}, [columns, locateCell]);
|
|
3474
3495
|
const endRangeDrag = useCallback2((event) => {
|
|
3475
3496
|
const drag = rangeDragRef.current;
|
|
3476
3497
|
if (!drag) return;
|
|
@@ -4680,11 +4701,20 @@ function TableInner({
|
|
|
4680
4701
|
const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
|
|
4681
4702
|
const verticalStart = fixedHeader ? bodyTop : 0;
|
|
4682
4703
|
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom + dragOffset <= verticalStart || rawTop + dragOffset >= renderHeight) return null;
|
|
4683
|
-
const
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4704
|
+
const bounds = getSelectionOutlineBounds({
|
|
4705
|
+
left: rawLeft,
|
|
4706
|
+
right: rawRight,
|
|
4707
|
+
top: rawTop,
|
|
4708
|
+
bottom: rawBottom,
|
|
4709
|
+
horizontalStart,
|
|
4710
|
+
horizontalEnd,
|
|
4711
|
+
verticalStart,
|
|
4712
|
+
verticalEnd: renderHeight
|
|
4713
|
+
});
|
|
4714
|
+
const left = Math.round(bounds.left);
|
|
4715
|
+
const right = Math.round(bounds.right);
|
|
4716
|
+
const top = Math.round(bounds.top);
|
|
4717
|
+
const bottom = Math.round(bounds.bottom);
|
|
4688
4718
|
return {
|
|
4689
4719
|
left,
|
|
4690
4720
|
top,
|