@lensui/lens-table 0.1.87 → 0.1.89
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 +117 -35
- package/dist/index.css +27 -6
- package/dist/index.js +117 -35
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1176,6 +1176,41 @@ function getSelectionOutlineBounds({
|
|
|
1176
1176
|
bottom: Math.min(bottom + borderWidth, verticalEnd + borderWidth)
|
|
1177
1177
|
};
|
|
1178
1178
|
}
|
|
1179
|
+
function getAnimatedRowDragOffset(preview, rowIndex, rowHeight) {
|
|
1180
|
+
if (!preview || rowIndex === preview.sourceIndex) return 0;
|
|
1181
|
+
const targetOffset = preview.sourceIndex < preview.targetIndex ? rowIndex > preview.sourceIndex && rowIndex <= preview.targetIndex ? -rowHeight : 0 : rowIndex >= preview.targetIndex && rowIndex < preview.sourceIndex ? rowHeight : 0;
|
|
1182
|
+
const startOffset = preview.fromOffsets?.[rowIndex] ?? 0;
|
|
1183
|
+
const progress = Math.max(0, Math.min(1, preview.progress ?? 1));
|
|
1184
|
+
return startOffset + (targetOffset - startOffset) * progress;
|
|
1185
|
+
}
|
|
1186
|
+
function getAnimatedRowDragGapRanges(preview, rowCount, rowHeight, bodyTop, scrollTop) {
|
|
1187
|
+
if (!preview || rowCount <= 0 || rowHeight <= 0) return [];
|
|
1188
|
+
const affectedIndices = [preview.sourceIndex, preview.targetIndex];
|
|
1189
|
+
preview.fromOffsets?.forEach((offset, rowIndex) => {
|
|
1190
|
+
if (Math.abs(offset) > 0.01) affectedIndices.push(rowIndex);
|
|
1191
|
+
});
|
|
1192
|
+
const startIndex = Math.max(0, Math.min(...affectedIndices));
|
|
1193
|
+
const endIndex = Math.min(rowCount - 1, Math.max(...affectedIndices));
|
|
1194
|
+
const regionTop = bodyTop + startIndex * rowHeight - scrollTop;
|
|
1195
|
+
const regionBottom = bodyTop + (endIndex + 1) * rowHeight - scrollTop;
|
|
1196
|
+
const occupied = [];
|
|
1197
|
+
for (let rowIndex = startIndex; rowIndex <= endIndex; rowIndex += 1) {
|
|
1198
|
+
if (rowIndex === preview.sourceIndex) continue;
|
|
1199
|
+
const top = bodyTop + rowIndex * rowHeight - scrollTop + getAnimatedRowDragOffset(preview, rowIndex, rowHeight);
|
|
1200
|
+
occupied.push({ top, bottom: top + rowHeight });
|
|
1201
|
+
}
|
|
1202
|
+
occupied.sort((left, right) => left.top - right.top);
|
|
1203
|
+
const gaps = [];
|
|
1204
|
+
let cursor = regionTop;
|
|
1205
|
+
for (const interval of occupied) {
|
|
1206
|
+
const top = Math.max(regionTop, interval.top);
|
|
1207
|
+
const bottom = Math.min(regionBottom, interval.bottom);
|
|
1208
|
+
if (top > cursor + 0.01) gaps.push({ top: cursor, bottom: top });
|
|
1209
|
+
cursor = Math.max(cursor, bottom);
|
|
1210
|
+
}
|
|
1211
|
+
if (cursor < regionBottom - 0.01) gaps.push({ top: cursor, bottom: regionBottom });
|
|
1212
|
+
return gaps;
|
|
1213
|
+
}
|
|
1179
1214
|
function paintGrid(options) {
|
|
1180
1215
|
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;
|
|
1181
1216
|
const headerLeafTop = options.headerLeafTop ?? 0;
|
|
@@ -1228,13 +1263,7 @@ function paintGrid(options) {
|
|
|
1228
1263
|
};
|
|
1229
1264
|
const displayedContentRight = columns.reduce((right, _column, index) => Math.max(right, getColumnX(index) + metrics[index].width), 0);
|
|
1230
1265
|
const trailingBlankStart = displayedContentRight > 0 && displayedContentRight < width ? displayedContentRight : null;
|
|
1231
|
-
const getRowDragOffset = (rowIndex) =>
|
|
1232
|
-
if (!rowDragPreview || rowIndex === rowDragPreview.sourceIndex) return 0;
|
|
1233
|
-
if (rowDragPreview.sourceIndex < rowDragPreview.targetIndex) {
|
|
1234
|
-
return rowIndex > rowDragPreview.sourceIndex && rowIndex <= rowDragPreview.targetIndex ? -rowHeight : 0;
|
|
1235
|
-
}
|
|
1236
|
-
return rowIndex >= rowDragPreview.targetIndex && rowIndex < rowDragPreview.sourceIndex ? rowHeight : 0;
|
|
1237
|
-
};
|
|
1266
|
+
const getRowDragOffset = (rowIndex) => getAnimatedRowDragOffset(rowDragPreview, rowIndex, rowHeight);
|
|
1238
1267
|
const rowBelowDragGap = rowDragPreview ? rowDragPreview.sourceIndex <= rowDragPreview.targetIndex ? rowDragPreview.targetIndex + 1 : rowDragPreview.targetIndex : -1;
|
|
1239
1268
|
if (trailingBlankStart !== null) {
|
|
1240
1269
|
const rowStart = Math.max(0, range.rowStart);
|
|
@@ -1343,7 +1372,7 @@ function paintGrid(options) {
|
|
|
1343
1372
|
if (!verticalBorderless && !(frameBorderless && columnIndex + colSpan >= columns.length)) {
|
|
1344
1373
|
ctx.fillRect(x + cellWidth - 1, y, 1, cellHeight);
|
|
1345
1374
|
}
|
|
1346
|
-
if (rowIndex === rowBelowDragGap) ctx.fillRect(x, y, cellWidth, 1);
|
|
1375
|
+
if (!horizontalBorderless && rowIndex === rowBelowDragGap) ctx.fillRect(x, y, cellWidth, 1);
|
|
1347
1376
|
if (!horizontalBorderless && (!options.suppressLastRowBottomBorder || rowIndex !== rows.length - 1)) {
|
|
1348
1377
|
ctx.fillRect(x, y + cellHeight - 1, cellWidth, 1);
|
|
1349
1378
|
}
|
|
@@ -1477,6 +1506,26 @@ function paintGrid(options) {
|
|
|
1477
1506
|
paintBodyColumns("scroll");
|
|
1478
1507
|
paintBodyColumns("left");
|
|
1479
1508
|
paintBodyColumns("right");
|
|
1509
|
+
if (rowDragPreview && !verticalBorderless) {
|
|
1510
|
+
const gapRanges = getAnimatedRowDragGapRanges(
|
|
1511
|
+
rowDragPreview,
|
|
1512
|
+
rows.length,
|
|
1513
|
+
rowHeight,
|
|
1514
|
+
bodyTop,
|
|
1515
|
+
scrollTop
|
|
1516
|
+
);
|
|
1517
|
+
ctx.fillStyle = colors.grid;
|
|
1518
|
+
for (let columnIndex = 0; columnIndex < columns.length; columnIndex += 1) {
|
|
1519
|
+
if (frameBorderless && columnIndex === columns.length - 1) continue;
|
|
1520
|
+
const x = getColumnX(columnIndex) + metrics[columnIndex].width - 1;
|
|
1521
|
+
if (columns[columnIndex].fixed === void 0 && (x < leftFixedWidth || x >= rightFixedLeft)) continue;
|
|
1522
|
+
for (const gap of gapRanges) {
|
|
1523
|
+
const top = Math.max(bodyTop, gap.top);
|
|
1524
|
+
const bottom = Math.min(height, gap.bottom);
|
|
1525
|
+
if (bottom > top) ctx.fillRect(x, top, 1, bottom - top);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1480
1529
|
if (extendVerticalGridLines) {
|
|
1481
1530
|
const extensionTop = Math.max(bodyTop, Math.min(height, bodyTop + rows.length * rowHeight - scrollTop));
|
|
1482
1531
|
const extensionHeight = Math.max(0, height - extensionTop);
|
|
@@ -2181,6 +2230,24 @@ function TableInner({
|
|
|
2181
2230
|
const [liftedRowPreview, setLiftedRowPreview] = (0, import_react8.useState)(null);
|
|
2182
2231
|
const [columnDragPreview, setColumnDragPreview] = (0, import_react8.useState)(null);
|
|
2183
2232
|
const [columnDropTarget, setColumnDropTarget] = (0, import_react8.useState)(null);
|
|
2233
|
+
(0, import_react8.useEffect)(() => {
|
|
2234
|
+
if (!rowDragPreview || (rowDragPreview.progress ?? 1) >= 1) return;
|
|
2235
|
+
const sourceIndex = rowDragPreview.sourceIndex;
|
|
2236
|
+
const targetIndex = rowDragPreview.targetIndex;
|
|
2237
|
+
if (window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) {
|
|
2238
|
+
setRowDragPreview((current) => current?.sourceIndex === sourceIndex && current.targetIndex === targetIndex ? { ...current, progress: 1 } : current);
|
|
2239
|
+
return;
|
|
2240
|
+
}
|
|
2241
|
+
const startedAt = performance.now();
|
|
2242
|
+
let frame = 0;
|
|
2243
|
+
const animate = (now) => {
|
|
2244
|
+
const progress = Math.min(1, (now - startedAt) / 140);
|
|
2245
|
+
setRowDragPreview((current) => current?.sourceIndex === sourceIndex && current.targetIndex === targetIndex ? { ...current, progress } : current);
|
|
2246
|
+
if (progress < 1) frame = requestAnimationFrame(animate);
|
|
2247
|
+
};
|
|
2248
|
+
frame = requestAnimationFrame(animate);
|
|
2249
|
+
return () => cancelAnimationFrame(frame);
|
|
2250
|
+
}, [rowDragPreview?.sourceIndex, rowDragPreview?.targetIndex]);
|
|
2184
2251
|
(0, import_react8.useEffect)(() => {
|
|
2185
2252
|
if (!loading) hasCompletedLoadRef.current = true;
|
|
2186
2253
|
}, [loading]);
|
|
@@ -3427,9 +3494,10 @@ function TableInner({
|
|
|
3427
3494
|
const setRowDragGuide = (0, import_react8.useCallback)((y) => {
|
|
3428
3495
|
const guide = rowDragGuideRef.current;
|
|
3429
3496
|
if (!guide) return;
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3497
|
+
const visibleY = horizontalBorderless ? null : y;
|
|
3498
|
+
guide.style.display = visibleY === null ? "none" : "block";
|
|
3499
|
+
if (visibleY !== null) guide.style.transform = `translateY(${Math.round(visibleY)}px)`;
|
|
3500
|
+
}, [horizontalBorderless]);
|
|
3433
3501
|
const locateRow = (0, import_react8.useCallback)((clientY) => {
|
|
3434
3502
|
const canvas = canvasRef.current;
|
|
3435
3503
|
if (!canvas) return -1;
|
|
@@ -3476,7 +3544,15 @@ function TableInner({
|
|
|
3476
3544
|
if (drag.sourceIndex < targetIndex) targetIndex -= 1;
|
|
3477
3545
|
targetIndex = Math.max(0, Math.min(rows.length - 1, targetIndex));
|
|
3478
3546
|
drag.targetIndex = targetIndex;
|
|
3479
|
-
setRowDragPreview(
|
|
3547
|
+
setRowDragPreview((current) => current?.sourceIndex === drag.sourceIndex && current.targetIndex === targetIndex ? current : {
|
|
3548
|
+
sourceIndex: drag.sourceIndex,
|
|
3549
|
+
targetIndex,
|
|
3550
|
+
fromOffsets: Array.from(
|
|
3551
|
+
{ length: rows.length },
|
|
3552
|
+
(_, rowIndex) => getAnimatedRowDragOffset(current, rowIndex, rowHeight)
|
|
3553
|
+
),
|
|
3554
|
+
progress: 0
|
|
3555
|
+
});
|
|
3480
3556
|
setRowDragGuide(rowTop + (edge === "bottom" ? rowHeight : 0));
|
|
3481
3557
|
}, [bodyTop, hideDragTooltips, locateRow, renderHeight, rowHeight, rows.length, setRowDragGuide]);
|
|
3482
3558
|
const finishRowOrderPointerDrag = (0, import_react8.useCallback)((event, apply) => {
|
|
@@ -4415,13 +4491,7 @@ function TableInner({
|
|
|
4415
4491
|
top: Math.min(Math.max(0, clientY - root.top), Math.max(0, renderHeight - 68))
|
|
4416
4492
|
});
|
|
4417
4493
|
};
|
|
4418
|
-
const getRowDragOffset = (rowIndex) =>
|
|
4419
|
-
if (!rowDragPreview || rowIndex === rowDragPreview.sourceIndex) return 0;
|
|
4420
|
-
if (rowDragPreview.sourceIndex < rowDragPreview.targetIndex) {
|
|
4421
|
-
return rowIndex > rowDragPreview.sourceIndex && rowIndex <= rowDragPreview.targetIndex ? -rowHeight : 0;
|
|
4422
|
-
}
|
|
4423
|
-
return rowIndex >= rowDragPreview.targetIndex && rowIndex < rowDragPreview.sourceIndex ? rowHeight : 0;
|
|
4424
|
-
};
|
|
4494
|
+
const getRowDragOffset = (rowIndex) => getAnimatedRowDragOffset(rowDragPreview, rowIndex, rowHeight);
|
|
4425
4495
|
const renderAnnotationControls = (targetCells) => {
|
|
4426
4496
|
const getKey = (cell) => `${typeof cell.rowKey}:${String(cell.rowKey)}\0${cell.columnKey}`;
|
|
4427
4497
|
const hasAnnotation = targetCells.some((cell) => cellAnnotations.has(getKey(cell)));
|
|
@@ -4731,7 +4801,7 @@ function TableInner({
|
|
|
4731
4801
|
})();
|
|
4732
4802
|
const selectionOutlineStyle = (() => {
|
|
4733
4803
|
if (!selection || selectionRange) return null;
|
|
4734
|
-
if (
|
|
4804
|
+
if (liftedRowPreview?.sourceIndex === selection.rowIndex) return null;
|
|
4735
4805
|
const row = rows[selection.rowIndex];
|
|
4736
4806
|
const metric = metrics[selection.columnIndex];
|
|
4737
4807
|
const column = columns[selection.columnIndex];
|
|
@@ -5011,7 +5081,12 @@ function TableInner({
|
|
|
5011
5081
|
const draggingSelectedColumn = Boolean(
|
|
5012
5082
|
columnDragPreview && selectedColumnKeySet.has(columns[columnDragPreview.sourceIndex]?.key)
|
|
5013
5083
|
);
|
|
5014
|
-
|
|
5084
|
+
const liftedRow = liftedRowPreview ? rows[liftedRowPreview.sourceIndex] : void 0;
|
|
5085
|
+
const liftedRowKey = liftedRow && liftedRowPreview ? getRowKey(liftedRow, liftedRowPreview.sourceIndex) : void 0;
|
|
5086
|
+
const liftedRowAxisSelected = liftedRowKey !== void 0 && selectedRowKeySet.has(liftedRowKey);
|
|
5087
|
+
const liftedRowCellFocused = liftedRowKey !== void 0 && selection?.rowKey === liftedRowKey;
|
|
5088
|
+
const liftedRowStyle = liftedRow && liftedRowPreview && !liftedRowAxisSelected ? rowStyle?.(liftedRow, liftedRowPreview.sourceIndex) : void 0;
|
|
5089
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { ref: rootRef, className: `rvg-root${!hasVerticalBorders ? " is-vertical-borderless" : ""}${horizontalBorderless ? " is-horizontal-borderless" : ""}${frameBorderless ? " is-frame-borderless" : ""}${hasStripedRows ? " is-striped" : ""}${insertBusy ? " is-inserting" : ""}${deleteBusy ? " is-deleting" : ""}${draggingSelectedColumn ? " is-dragging-selected-column" : ""}${rowDragPreview ? " is-row-dragging" : ""} ${loading && !hasCompletedLoadRef.current && !hasCustomLoading ? "is-initial-loading" : ""} ${className}`, style: rootStyle, children: [
|
|
5015
5090
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { ref: scrollerRef, className: `rvg-scroller${contextMenu ? " is-context-menu-open" : ""}`, style: { bottom: scrollerBottom }, onScroll: handleScroll, onCopy: handleCopy, onContextMenu: handleContextMenu, tabIndex: 0, role: "grid", "aria-label": ariaLabel, "aria-rowcount": rows.length, "aria-colcount": columns.length, onKeyDown: handleKeyDown, children: [
|
|
5016
5091
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5017
5092
|
"canvas",
|
|
@@ -5724,24 +5799,31 @@ function TableInner({
|
|
|
5724
5799
|
]
|
|
5725
5800
|
}
|
|
5726
5801
|
),
|
|
5727
|
-
liftedRowPreview &&
|
|
5802
|
+
liftedRowPreview && liftedRow && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5728
5803
|
"div",
|
|
5729
5804
|
{
|
|
5730
5805
|
"aria-hidden": "true",
|
|
5731
|
-
className: `rvg-row-drag-preview${
|
|
5732
|
-
style: { top: liftedRowPreview.top, width: viewport.width, height: rowHeight },
|
|
5733
|
-
children: columns.map((column, columnIndex) =>
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5806
|
+
className: `rvg-row-drag-preview${liftedRowAxisSelected ? " is-selected is-axis-selected" : ""}${hasStripedRows && liftedRowPreview.sourceIndex % 2 === 1 ? " is-striped" : ""}`,
|
|
5807
|
+
style: { ...liftedRowStyle, top: liftedRowPreview.top, width: viewport.width, height: rowHeight },
|
|
5808
|
+
children: columns.map((column, columnIndex) => {
|
|
5809
|
+
const value = column.dataIndex === void 0 ? void 0 : liftedRow[column.dataIndex];
|
|
5810
|
+
const cellStyle = liftedRowAxisSelected ? void 0 : column.cellStyle?.(value, liftedRow, liftedRowPreview.sourceIndex);
|
|
5811
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5812
|
+
"div",
|
|
5813
|
+
{
|
|
5814
|
+
className: `rvg-row-drag-preview-cell${column.renderCell ? " is-custom" : ""}${liftedRowAxisSelected ? " is-axis-selected" : ""}${liftedRowCellFocused && selection?.columnKey === column.key ? " is-selected" : ""}`,
|
|
5815
|
+
style: {
|
|
5816
|
+
...cellStyle,
|
|
5817
|
+
left: getDisplayedColumnLeft(columnIndex),
|
|
5818
|
+
width: metrics[columnIndex]?.width ?? 0,
|
|
5819
|
+
justifyContent: column.align === "right" ? "flex-end" : column.align === "center" ? "center" : "flex-start",
|
|
5820
|
+
color: cellStyle?.color ?? liftedRowStyle?.color
|
|
5821
|
+
},
|
|
5822
|
+
children: column.renderCell ? column.renderCell(value, liftedRow, liftedRowPreview.sourceIndex) : getCellLabel(liftedRowPreview.sourceIndex, columnIndex)
|
|
5740
5823
|
},
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
))
|
|
5824
|
+
`row-preview:${column.key}`
|
|
5825
|
+
);
|
|
5826
|
+
})
|
|
5745
5827
|
}
|
|
5746
5828
|
),
|
|
5747
5829
|
resizeGuideX !== null && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
package/dist/index.css
CHANGED
|
@@ -230,7 +230,12 @@
|
|
|
230
230
|
font-size: var(--rvg-font-size-body);
|
|
231
231
|
transition: transform 140ms ease, opacity 100ms ease;
|
|
232
232
|
}
|
|
233
|
-
.rvg-row-
|
|
233
|
+
.rvg-root.is-row-dragging .rvg-cell-text,
|
|
234
|
+
.rvg-root.is-row-dragging .rvg-cell-render,
|
|
235
|
+
.rvg-root.is-row-dragging .rvg-selection-focus,
|
|
236
|
+
.rvg-row-drop-settling .rvg-cell-text,
|
|
237
|
+
.rvg-row-drop-settling .rvg-cell-render,
|
|
238
|
+
.rvg-row-drop-settling .rvg-selection-focus {
|
|
234
239
|
transition: none;
|
|
235
240
|
}
|
|
236
241
|
.rvg-cell-text > span,
|
|
@@ -482,7 +487,6 @@
|
|
|
482
487
|
border: 2px solid var(--rvg-color-primary);
|
|
483
488
|
box-sizing: border-box;
|
|
484
489
|
pointer-events: none;
|
|
485
|
-
transition: transform 140ms ease;
|
|
486
490
|
}
|
|
487
491
|
.rvg-selection-edge-target {
|
|
488
492
|
position: absolute;
|
|
@@ -1638,17 +1642,28 @@
|
|
|
1638
1642
|
}
|
|
1639
1643
|
.rvg-row-drag-preview {
|
|
1640
1644
|
position: absolute;
|
|
1641
|
-
z-index:
|
|
1645
|
+
z-index: 8;
|
|
1642
1646
|
left: 0;
|
|
1643
|
-
overflow:
|
|
1647
|
+
overflow: visible;
|
|
1644
1648
|
border: 1px solid #8db8f3;
|
|
1645
1649
|
background: var(--rvg-color-bg);
|
|
1646
1650
|
box-shadow: 0 5px 14px rgba(32, 75, 135, 0.2);
|
|
1647
1651
|
box-sizing: border-box;
|
|
1648
|
-
opacity:
|
|
1652
|
+
opacity: 1;
|
|
1649
1653
|
pointer-events: none;
|
|
1650
1654
|
transform: translateY(-1px);
|
|
1651
1655
|
}
|
|
1656
|
+
.rvg-root.is-horizontal-borderless .rvg-row-drag-preview {
|
|
1657
|
+
border-top: 0;
|
|
1658
|
+
border-bottom: 0;
|
|
1659
|
+
}
|
|
1660
|
+
.rvg-row-drag-preview.is-striped {
|
|
1661
|
+
background: var(--rvg-color-stripe);
|
|
1662
|
+
}
|
|
1663
|
+
.rvg-row-drag-preview *,
|
|
1664
|
+
.rvg-row-drag-preview-cell > * {
|
|
1665
|
+
pointer-events: none !important;
|
|
1666
|
+
}
|
|
1652
1667
|
.rvg-row-drag-preview-cell {
|
|
1653
1668
|
position: absolute;
|
|
1654
1669
|
top: 0;
|
|
@@ -1670,7 +1685,7 @@
|
|
|
1670
1685
|
}
|
|
1671
1686
|
.rvg-row-drag-preview.is-selected {
|
|
1672
1687
|
border-color: var(--rvg-color-primary);
|
|
1673
|
-
background: var(--rvg-color-selection-fill);
|
|
1688
|
+
background: var(--rvg-color-axis-selection-fill);
|
|
1674
1689
|
}
|
|
1675
1690
|
.rvg-row-drag-preview.is-selected .rvg-row-drag-preview-cell {
|
|
1676
1691
|
border-right-color: color-mix(in srgb, var(--rvg-color-axis-selection-text) 34%, transparent);
|
|
@@ -1686,6 +1701,12 @@
|
|
|
1686
1701
|
background: var(--rvg-color-selection-fill);
|
|
1687
1702
|
box-shadow: 0 0 0 2px var(--rvg-color-primary);
|
|
1688
1703
|
}
|
|
1704
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1705
|
+
.rvg-cell-text,
|
|
1706
|
+
.rvg-cell-render {
|
|
1707
|
+
transition: none;
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1689
1710
|
.rvg-preview-checkbox {
|
|
1690
1711
|
display: grid;
|
|
1691
1712
|
width: 14px;
|
package/dist/index.js
CHANGED
|
@@ -1146,6 +1146,41 @@ function getSelectionOutlineBounds({
|
|
|
1146
1146
|
bottom: Math.min(bottom + borderWidth, verticalEnd + borderWidth)
|
|
1147
1147
|
};
|
|
1148
1148
|
}
|
|
1149
|
+
function getAnimatedRowDragOffset(preview, rowIndex, rowHeight) {
|
|
1150
|
+
if (!preview || rowIndex === preview.sourceIndex) return 0;
|
|
1151
|
+
const targetOffset = preview.sourceIndex < preview.targetIndex ? rowIndex > preview.sourceIndex && rowIndex <= preview.targetIndex ? -rowHeight : 0 : rowIndex >= preview.targetIndex && rowIndex < preview.sourceIndex ? rowHeight : 0;
|
|
1152
|
+
const startOffset = preview.fromOffsets?.[rowIndex] ?? 0;
|
|
1153
|
+
const progress = Math.max(0, Math.min(1, preview.progress ?? 1));
|
|
1154
|
+
return startOffset + (targetOffset - startOffset) * progress;
|
|
1155
|
+
}
|
|
1156
|
+
function getAnimatedRowDragGapRanges(preview, rowCount, rowHeight, bodyTop, scrollTop) {
|
|
1157
|
+
if (!preview || rowCount <= 0 || rowHeight <= 0) return [];
|
|
1158
|
+
const affectedIndices = [preview.sourceIndex, preview.targetIndex];
|
|
1159
|
+
preview.fromOffsets?.forEach((offset, rowIndex) => {
|
|
1160
|
+
if (Math.abs(offset) > 0.01) affectedIndices.push(rowIndex);
|
|
1161
|
+
});
|
|
1162
|
+
const startIndex = Math.max(0, Math.min(...affectedIndices));
|
|
1163
|
+
const endIndex = Math.min(rowCount - 1, Math.max(...affectedIndices));
|
|
1164
|
+
const regionTop = bodyTop + startIndex * rowHeight - scrollTop;
|
|
1165
|
+
const regionBottom = bodyTop + (endIndex + 1) * rowHeight - scrollTop;
|
|
1166
|
+
const occupied = [];
|
|
1167
|
+
for (let rowIndex = startIndex; rowIndex <= endIndex; rowIndex += 1) {
|
|
1168
|
+
if (rowIndex === preview.sourceIndex) continue;
|
|
1169
|
+
const top = bodyTop + rowIndex * rowHeight - scrollTop + getAnimatedRowDragOffset(preview, rowIndex, rowHeight);
|
|
1170
|
+
occupied.push({ top, bottom: top + rowHeight });
|
|
1171
|
+
}
|
|
1172
|
+
occupied.sort((left, right) => left.top - right.top);
|
|
1173
|
+
const gaps = [];
|
|
1174
|
+
let cursor = regionTop;
|
|
1175
|
+
for (const interval of occupied) {
|
|
1176
|
+
const top = Math.max(regionTop, interval.top);
|
|
1177
|
+
const bottom = Math.min(regionBottom, interval.bottom);
|
|
1178
|
+
if (top > cursor + 0.01) gaps.push({ top: cursor, bottom: top });
|
|
1179
|
+
cursor = Math.max(cursor, bottom);
|
|
1180
|
+
}
|
|
1181
|
+
if (cursor < regionBottom - 0.01) gaps.push({ top: cursor, bottom: regionBottom });
|
|
1182
|
+
return gaps;
|
|
1183
|
+
}
|
|
1149
1184
|
function paintGrid(options) {
|
|
1150
1185
|
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;
|
|
1151
1186
|
const headerLeafTop = options.headerLeafTop ?? 0;
|
|
@@ -1198,13 +1233,7 @@ function paintGrid(options) {
|
|
|
1198
1233
|
};
|
|
1199
1234
|
const displayedContentRight = columns.reduce((right, _column, index) => Math.max(right, getColumnX(index) + metrics[index].width), 0);
|
|
1200
1235
|
const trailingBlankStart = displayedContentRight > 0 && displayedContentRight < width ? displayedContentRight : null;
|
|
1201
|
-
const getRowDragOffset = (rowIndex) =>
|
|
1202
|
-
if (!rowDragPreview || rowIndex === rowDragPreview.sourceIndex) return 0;
|
|
1203
|
-
if (rowDragPreview.sourceIndex < rowDragPreview.targetIndex) {
|
|
1204
|
-
return rowIndex > rowDragPreview.sourceIndex && rowIndex <= rowDragPreview.targetIndex ? -rowHeight : 0;
|
|
1205
|
-
}
|
|
1206
|
-
return rowIndex >= rowDragPreview.targetIndex && rowIndex < rowDragPreview.sourceIndex ? rowHeight : 0;
|
|
1207
|
-
};
|
|
1236
|
+
const getRowDragOffset = (rowIndex) => getAnimatedRowDragOffset(rowDragPreview, rowIndex, rowHeight);
|
|
1208
1237
|
const rowBelowDragGap = rowDragPreview ? rowDragPreview.sourceIndex <= rowDragPreview.targetIndex ? rowDragPreview.targetIndex + 1 : rowDragPreview.targetIndex : -1;
|
|
1209
1238
|
if (trailingBlankStart !== null) {
|
|
1210
1239
|
const rowStart = Math.max(0, range.rowStart);
|
|
@@ -1313,7 +1342,7 @@ function paintGrid(options) {
|
|
|
1313
1342
|
if (!verticalBorderless && !(frameBorderless && columnIndex + colSpan >= columns.length)) {
|
|
1314
1343
|
ctx.fillRect(x + cellWidth - 1, y, 1, cellHeight);
|
|
1315
1344
|
}
|
|
1316
|
-
if (rowIndex === rowBelowDragGap) ctx.fillRect(x, y, cellWidth, 1);
|
|
1345
|
+
if (!horizontalBorderless && rowIndex === rowBelowDragGap) ctx.fillRect(x, y, cellWidth, 1);
|
|
1317
1346
|
if (!horizontalBorderless && (!options.suppressLastRowBottomBorder || rowIndex !== rows.length - 1)) {
|
|
1318
1347
|
ctx.fillRect(x, y + cellHeight - 1, cellWidth, 1);
|
|
1319
1348
|
}
|
|
@@ -1447,6 +1476,26 @@ function paintGrid(options) {
|
|
|
1447
1476
|
paintBodyColumns("scroll");
|
|
1448
1477
|
paintBodyColumns("left");
|
|
1449
1478
|
paintBodyColumns("right");
|
|
1479
|
+
if (rowDragPreview && !verticalBorderless) {
|
|
1480
|
+
const gapRanges = getAnimatedRowDragGapRanges(
|
|
1481
|
+
rowDragPreview,
|
|
1482
|
+
rows.length,
|
|
1483
|
+
rowHeight,
|
|
1484
|
+
bodyTop,
|
|
1485
|
+
scrollTop
|
|
1486
|
+
);
|
|
1487
|
+
ctx.fillStyle = colors.grid;
|
|
1488
|
+
for (let columnIndex = 0; columnIndex < columns.length; columnIndex += 1) {
|
|
1489
|
+
if (frameBorderless && columnIndex === columns.length - 1) continue;
|
|
1490
|
+
const x = getColumnX(columnIndex) + metrics[columnIndex].width - 1;
|
|
1491
|
+
if (columns[columnIndex].fixed === void 0 && (x < leftFixedWidth || x >= rightFixedLeft)) continue;
|
|
1492
|
+
for (const gap of gapRanges) {
|
|
1493
|
+
const top = Math.max(bodyTop, gap.top);
|
|
1494
|
+
const bottom = Math.min(height, gap.bottom);
|
|
1495
|
+
if (bottom > top) ctx.fillRect(x, top, 1, bottom - top);
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1450
1499
|
if (extendVerticalGridLines) {
|
|
1451
1500
|
const extensionTop = Math.max(bodyTop, Math.min(height, bodyTop + rows.length * rowHeight - scrollTop));
|
|
1452
1501
|
const extensionHeight = Math.max(0, height - extensionTop);
|
|
@@ -2151,6 +2200,24 @@ function TableInner({
|
|
|
2151
2200
|
const [liftedRowPreview, setLiftedRowPreview] = useState6(null);
|
|
2152
2201
|
const [columnDragPreview, setColumnDragPreview] = useState6(null);
|
|
2153
2202
|
const [columnDropTarget, setColumnDropTarget] = useState6(null);
|
|
2203
|
+
useEffect3(() => {
|
|
2204
|
+
if (!rowDragPreview || (rowDragPreview.progress ?? 1) >= 1) return;
|
|
2205
|
+
const sourceIndex = rowDragPreview.sourceIndex;
|
|
2206
|
+
const targetIndex = rowDragPreview.targetIndex;
|
|
2207
|
+
if (window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) {
|
|
2208
|
+
setRowDragPreview((current) => current?.sourceIndex === sourceIndex && current.targetIndex === targetIndex ? { ...current, progress: 1 } : current);
|
|
2209
|
+
return;
|
|
2210
|
+
}
|
|
2211
|
+
const startedAt = performance.now();
|
|
2212
|
+
let frame = 0;
|
|
2213
|
+
const animate = (now) => {
|
|
2214
|
+
const progress = Math.min(1, (now - startedAt) / 140);
|
|
2215
|
+
setRowDragPreview((current) => current?.sourceIndex === sourceIndex && current.targetIndex === targetIndex ? { ...current, progress } : current);
|
|
2216
|
+
if (progress < 1) frame = requestAnimationFrame(animate);
|
|
2217
|
+
};
|
|
2218
|
+
frame = requestAnimationFrame(animate);
|
|
2219
|
+
return () => cancelAnimationFrame(frame);
|
|
2220
|
+
}, [rowDragPreview?.sourceIndex, rowDragPreview?.targetIndex]);
|
|
2154
2221
|
useEffect3(() => {
|
|
2155
2222
|
if (!loading) hasCompletedLoadRef.current = true;
|
|
2156
2223
|
}, [loading]);
|
|
@@ -3397,9 +3464,10 @@ function TableInner({
|
|
|
3397
3464
|
const setRowDragGuide = useCallback3((y) => {
|
|
3398
3465
|
const guide = rowDragGuideRef.current;
|
|
3399
3466
|
if (!guide) return;
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3467
|
+
const visibleY = horizontalBorderless ? null : y;
|
|
3468
|
+
guide.style.display = visibleY === null ? "none" : "block";
|
|
3469
|
+
if (visibleY !== null) guide.style.transform = `translateY(${Math.round(visibleY)}px)`;
|
|
3470
|
+
}, [horizontalBorderless]);
|
|
3403
3471
|
const locateRow = useCallback3((clientY) => {
|
|
3404
3472
|
const canvas = canvasRef.current;
|
|
3405
3473
|
if (!canvas) return -1;
|
|
@@ -3446,7 +3514,15 @@ function TableInner({
|
|
|
3446
3514
|
if (drag.sourceIndex < targetIndex) targetIndex -= 1;
|
|
3447
3515
|
targetIndex = Math.max(0, Math.min(rows.length - 1, targetIndex));
|
|
3448
3516
|
drag.targetIndex = targetIndex;
|
|
3449
|
-
setRowDragPreview(
|
|
3517
|
+
setRowDragPreview((current) => current?.sourceIndex === drag.sourceIndex && current.targetIndex === targetIndex ? current : {
|
|
3518
|
+
sourceIndex: drag.sourceIndex,
|
|
3519
|
+
targetIndex,
|
|
3520
|
+
fromOffsets: Array.from(
|
|
3521
|
+
{ length: rows.length },
|
|
3522
|
+
(_, rowIndex) => getAnimatedRowDragOffset(current, rowIndex, rowHeight)
|
|
3523
|
+
),
|
|
3524
|
+
progress: 0
|
|
3525
|
+
});
|
|
3450
3526
|
setRowDragGuide(rowTop + (edge === "bottom" ? rowHeight : 0));
|
|
3451
3527
|
}, [bodyTop, hideDragTooltips, locateRow, renderHeight, rowHeight, rows.length, setRowDragGuide]);
|
|
3452
3528
|
const finishRowOrderPointerDrag = useCallback3((event, apply) => {
|
|
@@ -4385,13 +4461,7 @@ function TableInner({
|
|
|
4385
4461
|
top: Math.min(Math.max(0, clientY - root.top), Math.max(0, renderHeight - 68))
|
|
4386
4462
|
});
|
|
4387
4463
|
};
|
|
4388
|
-
const getRowDragOffset = (rowIndex) =>
|
|
4389
|
-
if (!rowDragPreview || rowIndex === rowDragPreview.sourceIndex) return 0;
|
|
4390
|
-
if (rowDragPreview.sourceIndex < rowDragPreview.targetIndex) {
|
|
4391
|
-
return rowIndex > rowDragPreview.sourceIndex && rowIndex <= rowDragPreview.targetIndex ? -rowHeight : 0;
|
|
4392
|
-
}
|
|
4393
|
-
return rowIndex >= rowDragPreview.targetIndex && rowIndex < rowDragPreview.sourceIndex ? rowHeight : 0;
|
|
4394
|
-
};
|
|
4464
|
+
const getRowDragOffset = (rowIndex) => getAnimatedRowDragOffset(rowDragPreview, rowIndex, rowHeight);
|
|
4395
4465
|
const renderAnnotationControls = (targetCells) => {
|
|
4396
4466
|
const getKey = (cell) => `${typeof cell.rowKey}:${String(cell.rowKey)}\0${cell.columnKey}`;
|
|
4397
4467
|
const hasAnnotation = targetCells.some((cell) => cellAnnotations.has(getKey(cell)));
|
|
@@ -4701,7 +4771,7 @@ function TableInner({
|
|
|
4701
4771
|
})();
|
|
4702
4772
|
const selectionOutlineStyle = (() => {
|
|
4703
4773
|
if (!selection || selectionRange) return null;
|
|
4704
|
-
if (
|
|
4774
|
+
if (liftedRowPreview?.sourceIndex === selection.rowIndex) return null;
|
|
4705
4775
|
const row = rows[selection.rowIndex];
|
|
4706
4776
|
const metric = metrics[selection.columnIndex];
|
|
4707
4777
|
const column = columns[selection.columnIndex];
|
|
@@ -4981,7 +5051,12 @@ function TableInner({
|
|
|
4981
5051
|
const draggingSelectedColumn = Boolean(
|
|
4982
5052
|
columnDragPreview && selectedColumnKeySet.has(columns[columnDragPreview.sourceIndex]?.key)
|
|
4983
5053
|
);
|
|
4984
|
-
|
|
5054
|
+
const liftedRow = liftedRowPreview ? rows[liftedRowPreview.sourceIndex] : void 0;
|
|
5055
|
+
const liftedRowKey = liftedRow && liftedRowPreview ? getRowKey(liftedRow, liftedRowPreview.sourceIndex) : void 0;
|
|
5056
|
+
const liftedRowAxisSelected = liftedRowKey !== void 0 && selectedRowKeySet.has(liftedRowKey);
|
|
5057
|
+
const liftedRowCellFocused = liftedRowKey !== void 0 && selection?.rowKey === liftedRowKey;
|
|
5058
|
+
const liftedRowStyle = liftedRow && liftedRowPreview && !liftedRowAxisSelected ? rowStyle?.(liftedRow, liftedRowPreview.sourceIndex) : void 0;
|
|
5059
|
+
return /* @__PURE__ */ jsxs8("div", { ref: rootRef, className: `rvg-root${!hasVerticalBorders ? " is-vertical-borderless" : ""}${horizontalBorderless ? " is-horizontal-borderless" : ""}${frameBorderless ? " is-frame-borderless" : ""}${hasStripedRows ? " is-striped" : ""}${insertBusy ? " is-inserting" : ""}${deleteBusy ? " is-deleting" : ""}${draggingSelectedColumn ? " is-dragging-selected-column" : ""}${rowDragPreview ? " is-row-dragging" : ""} ${loading && !hasCompletedLoadRef.current && !hasCustomLoading ? "is-initial-loading" : ""} ${className}`, style: rootStyle, children: [
|
|
4985
5060
|
/* @__PURE__ */ jsxs8("div", { ref: scrollerRef, className: `rvg-scroller${contextMenu ? " is-context-menu-open" : ""}`, style: { bottom: scrollerBottom }, onScroll: handleScroll, onCopy: handleCopy, onContextMenu: handleContextMenu, tabIndex: 0, role: "grid", "aria-label": ariaLabel, "aria-rowcount": rows.length, "aria-colcount": columns.length, onKeyDown: handleKeyDown, children: [
|
|
4986
5061
|
/* @__PURE__ */ jsx8(
|
|
4987
5062
|
"canvas",
|
|
@@ -5694,24 +5769,31 @@ function TableInner({
|
|
|
5694
5769
|
]
|
|
5695
5770
|
}
|
|
5696
5771
|
),
|
|
5697
|
-
liftedRowPreview &&
|
|
5772
|
+
liftedRowPreview && liftedRow && /* @__PURE__ */ jsx8(
|
|
5698
5773
|
"div",
|
|
5699
5774
|
{
|
|
5700
5775
|
"aria-hidden": "true",
|
|
5701
|
-
className: `rvg-row-drag-preview${
|
|
5702
|
-
style: { top: liftedRowPreview.top, width: viewport.width, height: rowHeight },
|
|
5703
|
-
children: columns.map((column, columnIndex) =>
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5776
|
+
className: `rvg-row-drag-preview${liftedRowAxisSelected ? " is-selected is-axis-selected" : ""}${hasStripedRows && liftedRowPreview.sourceIndex % 2 === 1 ? " is-striped" : ""}`,
|
|
5777
|
+
style: { ...liftedRowStyle, top: liftedRowPreview.top, width: viewport.width, height: rowHeight },
|
|
5778
|
+
children: columns.map((column, columnIndex) => {
|
|
5779
|
+
const value = column.dataIndex === void 0 ? void 0 : liftedRow[column.dataIndex];
|
|
5780
|
+
const cellStyle = liftedRowAxisSelected ? void 0 : column.cellStyle?.(value, liftedRow, liftedRowPreview.sourceIndex);
|
|
5781
|
+
return /* @__PURE__ */ jsx8(
|
|
5782
|
+
"div",
|
|
5783
|
+
{
|
|
5784
|
+
className: `rvg-row-drag-preview-cell${column.renderCell ? " is-custom" : ""}${liftedRowAxisSelected ? " is-axis-selected" : ""}${liftedRowCellFocused && selection?.columnKey === column.key ? " is-selected" : ""}`,
|
|
5785
|
+
style: {
|
|
5786
|
+
...cellStyle,
|
|
5787
|
+
left: getDisplayedColumnLeft(columnIndex),
|
|
5788
|
+
width: metrics[columnIndex]?.width ?? 0,
|
|
5789
|
+
justifyContent: column.align === "right" ? "flex-end" : column.align === "center" ? "center" : "flex-start",
|
|
5790
|
+
color: cellStyle?.color ?? liftedRowStyle?.color
|
|
5791
|
+
},
|
|
5792
|
+
children: column.renderCell ? column.renderCell(value, liftedRow, liftedRowPreview.sourceIndex) : getCellLabel(liftedRowPreview.sourceIndex, columnIndex)
|
|
5710
5793
|
},
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
))
|
|
5794
|
+
`row-preview:${column.key}`
|
|
5795
|
+
);
|
|
5796
|
+
})
|
|
5715
5797
|
}
|
|
5716
5798
|
),
|
|
5717
5799
|
resizeGuideX !== null && /* @__PURE__ */ jsx8(
|