@lensui/lens-table 0.1.77 → 0.1.79

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 CHANGED
@@ -332,6 +332,19 @@ function LoadingSpinnerIcon() {
332
332
 
333
333
  // src/components/editors/ChoiceEditor.tsx
334
334
  var import_jsx_runtime3 = require("react/jsx-runtime");
335
+ var SEARCHABLE_CHOICE_POPUP_MAX_WIDTH = 360;
336
+ var SEARCHABLE_CHOICE_POPUP_HORIZONTAL_PADDING = 44;
337
+ var SEARCHABLE_CHOICE_POPUP_VIEWPORT_GAP = 8;
338
+ function getSearchableChoicePopupHorizontalLayout(anchorLeft, anchorWidth, longestLabelWidth, viewportWidth) {
339
+ const availableWidth = Math.max(0, viewportWidth - SEARCHABLE_CHOICE_POPUP_VIEWPORT_GAP * 2);
340
+ const desiredWidth = Math.max(anchorWidth, longestLabelWidth + SEARCHABLE_CHOICE_POPUP_HORIZONTAL_PADDING);
341
+ const width = Math.min(desiredWidth, SEARCHABLE_CHOICE_POPUP_MAX_WIDTH, availableWidth);
342
+ const left = Math.max(
343
+ SEARCHABLE_CHOICE_POPUP_VIEWPORT_GAP,
344
+ Math.min(anchorLeft, viewportWidth - SEARCHABLE_CHOICE_POPUP_VIEWPORT_GAP - width)
345
+ );
346
+ return { left, width };
347
+ }
335
348
  function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownHeight, style, labels, onChange, onCommit, onCancel }) {
336
349
  const editorRef = (0, import_react2.useRef)(null);
337
350
  const popupRef = (0, import_react2.useRef)(null);
@@ -359,14 +372,24 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
359
372
  const positionPopup = () => {
360
373
  const rect = editorRef.current?.getBoundingClientRect();
361
374
  if (!rect) return;
375
+ const longestLabelWidth = Math.max(
376
+ 0,
377
+ ...Array.from(popupRef.current?.querySelectorAll(".rvg-choice-item > span") ?? []).map((label) => label.scrollWidth)
378
+ );
379
+ const horizontal = getSearchableChoicePopupHorizontalLayout(
380
+ rect.left,
381
+ rect.width,
382
+ longestLabelWidth,
383
+ window.innerWidth
384
+ );
362
385
  const availableBelow = window.innerHeight - rect.bottom - 8;
363
386
  const availableAbove = rect.top - 8;
364
387
  if (availableBelow < 120 && availableAbove > availableBelow) {
365
388
  setPopupStyle({
366
389
  position: "fixed",
367
390
  bottom: window.innerHeight - rect.top + 4,
368
- left: rect.left,
369
- width: rect.width,
391
+ left: horizontal.left,
392
+ width: horizontal.width,
370
393
  maxHeight: Math.min(maxDropdownHeight, availableAbove),
371
394
  visibility: popupReadyRef.current ? "visible" : "hidden"
372
395
  });
@@ -375,8 +398,8 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
375
398
  setPopupStyle({
376
399
  position: "fixed",
377
400
  top: rect.bottom + 4,
378
- left: rect.left,
379
- width: rect.width,
401
+ left: horizontal.left,
402
+ width: horizontal.width,
380
403
  maxHeight: Math.min(maxDropdownHeight, Math.max(80, availableBelow)),
381
404
  visibility: popupReadyRef.current ? "visible" : "hidden"
382
405
  });
@@ -884,7 +907,11 @@ function TextEditor({ value, type, min, max, integer = false, style, labels, onC
884
907
  if (type === "number" && integer && next !== "" && !/^-?\d+$/.test(next)) return;
885
908
  onChange(next);
886
909
  },
887
- onBlur: commitValue,
910
+ onBlur: (event) => {
911
+ const nextTarget = event.relatedTarget;
912
+ if (nextTarget instanceof Element && nextTarget.closest("[data-rvg-preserve-edit]")) return;
913
+ commitValue();
914
+ },
888
915
  onKeyDown: handleKeyDown
889
916
  }
890
917
  ),
@@ -968,25 +995,6 @@ function TextAreaEditor({ value, title, maxLength, style, labels, onChange, onCo
968
995
  ] });
969
996
  }
970
997
 
971
- // src/icons/domIcons.ts
972
- function createRowDragHandleSvg() {
973
- const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
974
- svg.setAttribute("viewBox", "0 0 16 16");
975
- for (const [cx, cy] of [[5, 4], [11, 4], [5, 8], [11, 8], [5, 12], [11, 12]]) {
976
- const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
977
- circle.setAttribute("cx", String(cx));
978
- circle.setAttribute("cy", String(cy));
979
- circle.setAttribute("r", "1");
980
- svg.appendChild(circle);
981
- }
982
- return svg;
983
- }
984
-
985
- // src/Table.tsx
986
- var import_adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
987
- var import_set_custom_native_drag_preview = require("@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview");
988
- var import_closest_edge = require("@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge");
989
-
990
998
  // src/core/format.ts
991
999
  function getDisplayLabel(column, row, rowIndex) {
992
1000
  const value = column.dataIndex === void 0 ? void 0 : row[column.dataIndex];
@@ -1298,7 +1306,7 @@ function paintGrid(options) {
1298
1306
  ctx.fillStyle = isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill;
1299
1307
  ctx.fillRect(x, y, cellWidth, cellHeight);
1300
1308
  }
1301
- ctx.fillStyle = selectedRowKeys.has(rowKey) ? getAxisSelectionFill(rowIndex, column.key) : colors.grid;
1309
+ ctx.fillStyle = selectedRowKeys.has(rowKey) ? getAxisSelectionFill(rowIndex, column.key) : isRangeCell ? colors.selectionFill : colors.grid;
1302
1310
  if (!verticalBorderless && !(frameBorderless && columnIndex + colSpan >= columns.length)) {
1303
1311
  ctx.fillRect(x + cellWidth - 1, y, 1, cellHeight);
1304
1312
  }
@@ -2068,6 +2076,7 @@ function TableInner({
2068
2076
  const columnDragRef = (0, import_react8.useRef)(null);
2069
2077
  const columnOrderDragRef = (0, import_react8.useRef)(null);
2070
2078
  const columnOrderLongPressTimerRef = (0, import_react8.useRef)(null);
2079
+ const rowOrderDragRef = (0, import_react8.useRef)(null);
2071
2080
  const dragGuideRef = (0, import_react8.useRef)(null);
2072
2081
  const rowDragGuideRef = (0, import_react8.useRef)(null);
2073
2082
  const selectionFocusRef = (0, import_react8.useRef)(null);
@@ -2122,6 +2131,7 @@ function TableInner({
2122
2131
  const [editing, setEditing] = (0, import_react8.useState)(null);
2123
2132
  const [draft, setDraft] = (0, import_react8.useState)("");
2124
2133
  const [rowDragPreview, setRowDragPreview] = (0, import_react8.useState)(null);
2134
+ const [liftedRowPreview, setLiftedRowPreview] = (0, import_react8.useState)(null);
2125
2135
  const [columnDragPreview, setColumnDragPreview] = (0, import_react8.useState)(null);
2126
2136
  const [columnDropTarget, setColumnDropTarget] = (0, import_react8.useState)(null);
2127
2137
  (0, import_react8.useEffect)(() => {
@@ -3368,131 +3378,66 @@ function TableInner({
3368
3378
  const rowIndex = Math.floor((localY - bodyTop + scrollRef.current.top) / rowHeight);
3369
3379
  return rowIndex >= 0 && rowIndex < rows.length ? rowIndex : -1;
3370
3380
  }, [bodyTop, rowHeight, rows.length]);
3371
- (0, import_react8.useEffect)(() => {
3372
- const canvas = canvasRef.current;
3373
- if (!canvas || !rowDraggable) return;
3374
- const cleanupDrag = (0, import_adapter.draggable)({
3375
- element: canvas,
3376
- canDrag: ({ input }) => {
3377
- const columnIndex = locateColumn(input.clientX);
3378
- return columnIndex >= 0 && Boolean(columns[columnIndex].rowDragHandle) && locateRow(input.clientY) >= 0;
3379
- },
3380
- getInitialData: ({ input }) => ({ type: "table-row", sourceIndex: locateRow(input.clientY) }),
3381
- onGenerateDragPreview: ({ nativeSetDragImage, source, location }) => {
3382
- const sourceIndex = Number(source.data.sourceIndex);
3383
- const canvasRect = canvas.getBoundingClientRect();
3384
- const input = location.current.input;
3385
- const previewOffset = {
3386
- x: Math.max(0, Math.min(canvasRect.width, input.clientX - canvasRect.left)) + 2,
3387
- y: Math.max(0, Math.min(rowHeight, input.clientY - canvasRect.top - bodyTop - sourceIndex * rowHeight + scrollRef.current.top)) + 2
3388
- };
3389
- (0, import_set_custom_native_drag_preview.setCustomNativeDragPreview)({
3390
- nativeSetDragImage,
3391
- getOffset: () => previewOffset,
3392
- render: ({ container }) => {
3393
- const frame = document.createElement("div");
3394
- frame.className = "rvg-row-drag-preview-frame";
3395
- frame.style.width = `${canvasRect.width + 4}px`;
3396
- frame.style.height = `${rowHeight + 4}px`;
3397
- const preview = document.createElement("div");
3398
- preview.className = "rvg-row-drag-preview";
3399
- preview.style.width = `${canvasRect.width}px`;
3400
- preview.style.height = `${rowHeight}px`;
3401
- const row = rows[sourceIndex];
3402
- const rowKey2 = getRowKey(row, sourceIndex);
3403
- columns.forEach((column, columnIndex) => {
3404
- const left = getDisplayedColumnLeft(columnIndex);
3405
- const columnWidth = metrics[columnIndex].width;
3406
- if (left + columnWidth <= 0 || left >= canvasRect.width) return;
3407
- const cell = document.createElement("div");
3408
- cell.className = "rvg-row-drag-preview-cell";
3409
- cell.style.left = `${left}px`;
3410
- cell.style.width = `${columnWidth}px`;
3411
- cell.style.justifyContent = column.align === "right" ? "flex-end" : column.align === "center" ? "center" : "flex-start";
3412
- if (column.rowDragHandle && !column.rowSelection) {
3413
- cell.appendChild(createRowDragHandleSvg());
3414
- } else if (column.rowSelection) {
3415
- if (column.rowSelectionIndicator !== "none") {
3416
- const checkbox = document.createElement("span");
3417
- checkbox.className = selectedRowKeySet.has(rowKey2) ? "rvg-preview-checkbox is-checked" : "rvg-preview-checkbox";
3418
- checkbox.textContent = selectedRowKeySet.has(rowKey2) ? "\u2713" : "";
3419
- cell.appendChild(checkbox);
3420
- }
3421
- } else {
3422
- cell.textContent = getCellLabel(sourceIndex, columnIndex);
3423
- }
3424
- if (selection?.rowKey === rowKey2 && selection.columnKey === column.key) cell.classList.add("is-selected");
3425
- preview.appendChild(cell);
3426
- });
3427
- frame.appendChild(preview);
3428
- container.appendChild(frame);
3429
- return () => frame.remove();
3430
- }
3431
- });
3432
- },
3433
- onDragStart: ({ source }) => {
3434
- const sourceIndex = Number(source.data.sourceIndex);
3435
- suppressClickRef.current = true;
3436
- hideDragTooltips();
3437
- document.documentElement.classList.add("rvg-is-dragging");
3438
- canvas.style.cursor = "move";
3439
- setRowDragPreview({ sourceIndex, targetIndex: sourceIndex });
3440
- },
3441
- onDrag: ({ source, location }) => {
3442
- const target = location.current.dropTargets[0]?.data;
3443
- const sourceIndex = Number(source.data.sourceIndex);
3444
- const rawTargetIndex = Number(target?.targetIndex);
3445
- if (!Number.isInteger(rawTargetIndex)) {
3446
- setRowDragPreview(null);
3447
- setRowDragGuide(null);
3448
- return;
3449
- }
3450
- const edge = target?.rowEdge;
3451
- let targetIndex = rawTargetIndex + (edge === "bottom" ? 1 : 0);
3452
- if (sourceIndex < targetIndex) targetIndex -= 1;
3453
- targetIndex = Math.max(0, Math.min(rows.length - 1, targetIndex));
3454
- setRowDragPreview((current) => current?.sourceIndex === sourceIndex && current.targetIndex === targetIndex ? current : { sourceIndex, targetIndex });
3455
- setRowDragGuide(bodyTop + rawTargetIndex * rowHeight - scrollRef.current.top + (edge === "bottom" ? rowHeight : 0));
3456
- },
3457
- onDrop: ({ source, location }) => {
3458
- const target = location.current.dropTargets[0]?.data;
3459
- const sourceIndex = Number(source.data.sourceIndex);
3460
- const rawTargetIndex = Number(target?.targetIndex);
3461
- let targetIndex = rawTargetIndex + (target?.rowEdge === "bottom" ? 1 : 0);
3462
- if (sourceIndex < targetIndex) targetIndex -= 1;
3463
- targetIndex = Math.max(0, Math.min(rows.length - 1, targetIndex));
3464
- scrollerRef.current?.classList.add("rvg-row-drop-settling");
3465
- setRowDragPreview(null);
3466
- setRowDragGuide(null);
3467
- document.documentElement.classList.remove("rvg-is-dragging");
3468
- canvas.style.cursor = "default";
3469
- if (Number.isInteger(rawTargetIndex) && sourceIndex !== targetIndex) applyRowOrder(sourceIndex, targetIndex);
3470
- requestAnimationFrame(() => {
3471
- requestAnimationFrame(() => scrollerRef.current?.classList.remove("rvg-row-drop-settling"));
3472
- });
3473
- window.setTimeout(() => {
3474
- suppressClickRef.current = false;
3475
- }, 0);
3476
- }
3477
- });
3478
- const cleanupDrop = (0, import_adapter.dropTargetForElements)({
3479
- element: canvas,
3480
- canDrop: ({ source }) => source.data.type === "table-row",
3481
- getDropEffect: () => "move",
3482
- getData: ({ input, element }) => {
3483
- const targetIndex = locateRow(input.clientY);
3484
- if (targetIndex < 0) return { targetIndex: -1 };
3485
- const rowTop = bodyTop + targetIndex * rowHeight - scrollRef.current.top;
3486
- const rowEdge = input.clientY - canvas.getBoundingClientRect().top < rowTop + rowHeight / 2 ? "top" : "bottom";
3487
- return (0, import_closest_edge.attachClosestEdge)({ targetIndex, rowEdge }, { element, input, allowedEdges: ["top", "bottom"] });
3488
- }
3489
- });
3490
- return () => {
3491
- document.documentElement.classList.remove("rvg-is-dragging");
3492
- cleanupDrag();
3493
- cleanupDrop();
3381
+ const handleRowOrderPointerDown = (0, import_react8.useCallback)((event) => {
3382
+ if (!rowDraggable || event.button !== 0 || rowOrderDragRef.current) return;
3383
+ const columnIndex = locateColumn(event.clientX);
3384
+ const sourceIndex = locateRow(event.clientY);
3385
+ if (columnIndex < 0 || sourceIndex < 0 || !columns[columnIndex].rowDragHandle) return;
3386
+ event.currentTarget.setPointerCapture?.(event.pointerId);
3387
+ rowOrderDragRef.current = {
3388
+ pointerId: event.pointerId,
3389
+ startY: event.clientY,
3390
+ active: false,
3391
+ sourceIndex,
3392
+ targetIndex: sourceIndex
3494
3393
  };
3495
- }, [applyRowOrder, bodyTop, columns, getCellLabel, getDisplayedColumnLeft, getRowKey, hideDragTooltips, locateColumn, locateRow, metrics, rowDraggable, rowHeight, rows, selectedRowKeySet, selection, setRowDragGuide]);
3394
+ }, [columns, locateColumn, locateRow, rowDraggable]);
3395
+ const handleRowOrderPointerMove = (0, import_react8.useCallback)((event) => {
3396
+ const drag = rowOrderDragRef.current;
3397
+ if (!drag || drag.pointerId !== event.pointerId) return;
3398
+ if (!drag.active) {
3399
+ if (Math.abs(event.clientY - drag.startY) < 4) return;
3400
+ drag.active = true;
3401
+ suppressClickRef.current = true;
3402
+ hideDragTooltips();
3403
+ document.documentElement.classList.add("rvg-is-dragging");
3404
+ event.currentTarget.style.cursor = "move";
3405
+ }
3406
+ event.preventDefault();
3407
+ const canvasTop = event.currentTarget.getBoundingClientRect().top;
3408
+ setLiftedRowPreview({
3409
+ sourceIndex: drag.sourceIndex,
3410
+ top: Math.max(bodyTop, Math.min(renderHeight - rowHeight, event.clientY - canvasTop - rowHeight / 2))
3411
+ });
3412
+ const rawTargetIndex = locateRow(event.clientY);
3413
+ if (rawTargetIndex < 0) return;
3414
+ const rowTop = bodyTop + rawTargetIndex * rowHeight - scrollRef.current.top;
3415
+ const edge = event.clientY - canvasTop < rowTop + rowHeight / 2 ? "top" : "bottom";
3416
+ let targetIndex = rawTargetIndex + (edge === "bottom" ? 1 : 0);
3417
+ if (drag.sourceIndex < targetIndex) targetIndex -= 1;
3418
+ targetIndex = Math.max(0, Math.min(rows.length - 1, targetIndex));
3419
+ drag.targetIndex = targetIndex;
3420
+ setRowDragPreview(null);
3421
+ setRowDragGuide(rowTop + (edge === "bottom" ? rowHeight : 0));
3422
+ }, [bodyTop, hideDragTooltips, locateRow, renderHeight, rowHeight, rows.length, setRowDragGuide]);
3423
+ const finishRowOrderPointerDrag = (0, import_react8.useCallback)((event, apply) => {
3424
+ const drag = rowOrderDragRef.current;
3425
+ if (!drag || drag.pointerId !== event.pointerId) return;
3426
+ if (event.currentTarget.hasPointerCapture?.(event.pointerId)) event.currentTarget.releasePointerCapture?.(event.pointerId);
3427
+ rowOrderDragRef.current = null;
3428
+ setRowDragPreview(null);
3429
+ setLiftedRowPreview(null);
3430
+ setRowDragGuide(null);
3431
+ document.documentElement.classList.remove("rvg-is-dragging");
3432
+ event.currentTarget.style.cursor = "default";
3433
+ if (apply && drag.active && drag.sourceIndex !== drag.targetIndex) {
3434
+ scrollerRef.current?.classList.add("rvg-row-drop-settling");
3435
+ applyRowOrder(drag.sourceIndex, drag.targetIndex);
3436
+ requestAnimationFrame(() => {
3437
+ requestAnimationFrame(() => scrollerRef.current?.classList.remove("rvg-row-drop-settling"));
3438
+ });
3439
+ }
3440
+ }, [applyRowOrder, setRowDragGuide]);
3496
3441
  const locateCell = (0, import_react8.useCallback)((clientX, clientY) => {
3497
3442
  const canvas = canvasRef.current;
3498
3443
  if (!canvas) return null;
@@ -5085,7 +5030,7 @@ function TableInner({
5085
5030
  }
5086
5031
  }
5087
5032
  }
5088
- const cursor = inHeader && locateHeaderResizeCell(event.clientX, event.clientY) ? "col-resize" : hoveredAction ? "pointer" : hoveredDragHandle ? "move" : columnIndex >= 0 && columns[columnIndex].rowSelection ? "pointer" : !inHeader && rowDraggable && columnIndex >= 0 && columns[columnIndex].rowDragHandle ? "move" : "default";
5033
+ const cursor = inHeader && locateHeaderResizeCell(event.clientX, event.clientY) ? "col-resize" : hoveredAction ? "pointer" : hoveredDragHandle ? "move" : !inHeader && rowDraggable && columnIndex >= 0 && columns[columnIndex].rowDragHandle ? "move" : columnIndex >= 0 && columns[columnIndex].rowSelection ? "pointer" : "default";
5089
5034
  if (event.currentTarget.style.cursor !== cursor) event.currentTarget.style.cursor = cursor;
5090
5035
  },
5091
5036
  onMouseLeave: (event) => {
@@ -5104,6 +5049,7 @@ function TableInner({
5104
5049
  }
5105
5050
  },
5106
5051
  onPointerDown: (event) => {
5052
+ handleRowOrderPointerDown(event);
5107
5053
  handleColumnPointerDown(event);
5108
5054
  if (columnDragRef.current) return;
5109
5055
  const headerDragCell = columnDraggable ? locateHeaderCell(event.clientX, event.clientY) : null;
@@ -5116,16 +5062,19 @@ function TableInner({
5116
5062
  beginRangeDrag(event);
5117
5063
  },
5118
5064
  onPointerMove: (event) => {
5065
+ handleRowOrderPointerMove(event);
5119
5066
  handleColumnPointerMove(event);
5120
5067
  handleColumnOrderPointerMove(event);
5121
5068
  updateRangeDrag(event);
5122
5069
  },
5123
5070
  onPointerUp: (event) => {
5071
+ finishRowOrderPointerDrag(event, true);
5124
5072
  handleColumnPointerUp(event);
5125
5073
  finishColumnOrderPointerDrag(event, true);
5126
5074
  endRangeDrag(event);
5127
5075
  },
5128
5076
  onPointerCancel: (event) => {
5077
+ finishRowOrderPointerDrag(event, false);
5129
5078
  handleColumnPointerUp(event);
5130
5079
  finishColumnOrderPointerDrag(event, false);
5131
5080
  endRangeDrag(event);
@@ -5689,6 +5638,26 @@ function TableInner({
5689
5638
  ]
5690
5639
  }
5691
5640
  ),
5641
+ liftedRowPreview && rows[liftedRowPreview.sourceIndex] && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5642
+ "div",
5643
+ {
5644
+ "aria-hidden": "true",
5645
+ className: `rvg-row-drag-preview${selectedRowKeySet.has(getRowKey(rows[liftedRowPreview.sourceIndex], liftedRowPreview.sourceIndex)) ? " is-selected" : ""}`,
5646
+ style: { top: liftedRowPreview.top, width: viewport.width, height: rowHeight },
5647
+ children: columns.map((column, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5648
+ "div",
5649
+ {
5650
+ className: "rvg-row-drag-preview-cell",
5651
+ style: {
5652
+ left: getDisplayedColumnLeft(columnIndex),
5653
+ width: metrics[columnIndex]?.width ?? 0
5654
+ },
5655
+ children: getCellLabel(liftedRowPreview.sourceIndex, columnIndex)
5656
+ },
5657
+ `row-preview:${column.key}`
5658
+ ))
5659
+ }
5660
+ ),
5692
5661
  resizeGuideX !== null && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5693
5662
  "div",
5694
5663
  {
package/dist/index.css CHANGED
@@ -1638,13 +1638,16 @@
1638
1638
  }
1639
1639
  .rvg-row-drag-preview {
1640
1640
  position: absolute;
1641
- top: 2px;
1642
- left: 2px;
1643
- overflow: visible;
1644
- border: 1px solid #a9c8f5;
1645
- background: #fff;
1646
- box-shadow: 0 2px 6px rgba(5, 5, 5, 0.08);
1641
+ z-index: 6;
1642
+ left: 0;
1643
+ overflow: hidden;
1644
+ border: 1px solid #8db8f3;
1645
+ background: var(--rvg-color-bg);
1646
+ box-shadow: 0 5px 14px rgba(32, 75, 135, 0.2);
1647
1647
  box-sizing: border-box;
1648
+ opacity: 0.94;
1649
+ pointer-events: none;
1650
+ transform: translateY(-1px);
1648
1651
  }
1649
1652
  .rvg-row-drag-preview-cell {
1650
1653
  position: absolute;
@@ -1665,6 +1668,14 @@
1665
1668
  text-overflow: ellipsis;
1666
1669
  box-sizing: border-box;
1667
1670
  }
1671
+ .rvg-row-drag-preview.is-selected {
1672
+ border-color: var(--rvg-color-primary);
1673
+ background: var(--rvg-color-selection-fill);
1674
+ }
1675
+ .rvg-row-drag-preview.is-selected .rvg-row-drag-preview-cell {
1676
+ border-right-color: color-mix(in srgb, var(--rvg-color-axis-selection-text) 34%, transparent);
1677
+ color: var(--rvg-color-axis-selection-text);
1678
+ }
1668
1679
  .rvg-row-drag-preview-cell svg {
1669
1680
  width: 16px;
1670
1681
  height: 16px;
@@ -2704,10 +2715,17 @@
2704
2715
  }
2705
2716
  .rvg-searchable-choice-content .rvg-choice-item {
2706
2717
  width: 100%;
2718
+ min-width: 0;
2707
2719
  border: 0;
2708
2720
  background: transparent;
2709
2721
  text-align: left;
2710
2722
  }
2723
+ .rvg-searchable-choice-content .rvg-choice-item > span {
2724
+ min-width: 0;
2725
+ overflow: hidden;
2726
+ white-space: nowrap;
2727
+ text-overflow: ellipsis;
2728
+ }
2711
2729
  .rvg-searchable-choice-content .rvg-choice-item:is(:hover, .is-active) {
2712
2730
  background: var(--rvg-color-hover);
2713
2731
  }
package/dist/index.js CHANGED
@@ -302,6 +302,19 @@ function LoadingSpinnerIcon() {
302
302
 
303
303
  // src/components/editors/ChoiceEditor.tsx
304
304
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
305
+ var SEARCHABLE_CHOICE_POPUP_MAX_WIDTH = 360;
306
+ var SEARCHABLE_CHOICE_POPUP_HORIZONTAL_PADDING = 44;
307
+ var SEARCHABLE_CHOICE_POPUP_VIEWPORT_GAP = 8;
308
+ function getSearchableChoicePopupHorizontalLayout(anchorLeft, anchorWidth, longestLabelWidth, viewportWidth) {
309
+ const availableWidth = Math.max(0, viewportWidth - SEARCHABLE_CHOICE_POPUP_VIEWPORT_GAP * 2);
310
+ const desiredWidth = Math.max(anchorWidth, longestLabelWidth + SEARCHABLE_CHOICE_POPUP_HORIZONTAL_PADDING);
311
+ const width = Math.min(desiredWidth, SEARCHABLE_CHOICE_POPUP_MAX_WIDTH, availableWidth);
312
+ const left = Math.max(
313
+ SEARCHABLE_CHOICE_POPUP_VIEWPORT_GAP,
314
+ Math.min(anchorLeft, viewportWidth - SEARCHABLE_CHOICE_POPUP_VIEWPORT_GAP - width)
315
+ );
316
+ return { left, width };
317
+ }
305
318
  function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownHeight, style, labels, onChange, onCommit, onCancel }) {
306
319
  const editorRef = useRef(null);
307
320
  const popupRef = useRef(null);
@@ -329,14 +342,24 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
329
342
  const positionPopup = () => {
330
343
  const rect = editorRef.current?.getBoundingClientRect();
331
344
  if (!rect) return;
345
+ const longestLabelWidth = Math.max(
346
+ 0,
347
+ ...Array.from(popupRef.current?.querySelectorAll(".rvg-choice-item > span") ?? []).map((label) => label.scrollWidth)
348
+ );
349
+ const horizontal = getSearchableChoicePopupHorizontalLayout(
350
+ rect.left,
351
+ rect.width,
352
+ longestLabelWidth,
353
+ window.innerWidth
354
+ );
332
355
  const availableBelow = window.innerHeight - rect.bottom - 8;
333
356
  const availableAbove = rect.top - 8;
334
357
  if (availableBelow < 120 && availableAbove > availableBelow) {
335
358
  setPopupStyle({
336
359
  position: "fixed",
337
360
  bottom: window.innerHeight - rect.top + 4,
338
- left: rect.left,
339
- width: rect.width,
361
+ left: horizontal.left,
362
+ width: horizontal.width,
340
363
  maxHeight: Math.min(maxDropdownHeight, availableAbove),
341
364
  visibility: popupReadyRef.current ? "visible" : "hidden"
342
365
  });
@@ -345,8 +368,8 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
345
368
  setPopupStyle({
346
369
  position: "fixed",
347
370
  top: rect.bottom + 4,
348
- left: rect.left,
349
- width: rect.width,
371
+ left: horizontal.left,
372
+ width: horizontal.width,
350
373
  maxHeight: Math.min(maxDropdownHeight, Math.max(80, availableBelow)),
351
374
  visibility: popupReadyRef.current ? "visible" : "hidden"
352
375
  });
@@ -854,7 +877,11 @@ function TextEditor({ value, type, min, max, integer = false, style, labels, onC
854
877
  if (type === "number" && integer && next !== "" && !/^-?\d+$/.test(next)) return;
855
878
  onChange(next);
856
879
  },
857
- onBlur: commitValue,
880
+ onBlur: (event) => {
881
+ const nextTarget = event.relatedTarget;
882
+ if (nextTarget instanceof Element && nextTarget.closest("[data-rvg-preserve-edit]")) return;
883
+ commitValue();
884
+ },
858
885
  onKeyDown: handleKeyDown
859
886
  }
860
887
  ),
@@ -938,25 +965,6 @@ function TextAreaEditor({ value, title, maxLength, style, labels, onChange, onCo
938
965
  ] });
939
966
  }
940
967
 
941
- // src/icons/domIcons.ts
942
- function createRowDragHandleSvg() {
943
- const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
944
- svg.setAttribute("viewBox", "0 0 16 16");
945
- for (const [cx, cy] of [[5, 4], [11, 4], [5, 8], [11, 8], [5, 12], [11, 12]]) {
946
- const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
947
- circle.setAttribute("cx", String(cx));
948
- circle.setAttribute("cy", String(cy));
949
- circle.setAttribute("r", "1");
950
- svg.appendChild(circle);
951
- }
952
- return svg;
953
- }
954
-
955
- // src/Table.tsx
956
- import { draggable, dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
957
- import { setCustomNativeDragPreview } from "@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview";
958
- import { attachClosestEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
959
-
960
968
  // src/core/format.ts
961
969
  function getDisplayLabel(column, row, rowIndex) {
962
970
  const value = column.dataIndex === void 0 ? void 0 : row[column.dataIndex];
@@ -1268,7 +1276,7 @@ function paintGrid(options) {
1268
1276
  ctx.fillStyle = isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill;
1269
1277
  ctx.fillRect(x, y, cellWidth, cellHeight);
1270
1278
  }
1271
- ctx.fillStyle = selectedRowKeys.has(rowKey) ? getAxisSelectionFill(rowIndex, column.key) : colors.grid;
1279
+ ctx.fillStyle = selectedRowKeys.has(rowKey) ? getAxisSelectionFill(rowIndex, column.key) : isRangeCell ? colors.selectionFill : colors.grid;
1272
1280
  if (!verticalBorderless && !(frameBorderless && columnIndex + colSpan >= columns.length)) {
1273
1281
  ctx.fillRect(x + cellWidth - 1, y, 1, cellHeight);
1274
1282
  }
@@ -2038,6 +2046,7 @@ function TableInner({
2038
2046
  const columnDragRef = useRef4(null);
2039
2047
  const columnOrderDragRef = useRef4(null);
2040
2048
  const columnOrderLongPressTimerRef = useRef4(null);
2049
+ const rowOrderDragRef = useRef4(null);
2041
2050
  const dragGuideRef = useRef4(null);
2042
2051
  const rowDragGuideRef = useRef4(null);
2043
2052
  const selectionFocusRef = useRef4(null);
@@ -2092,6 +2101,7 @@ function TableInner({
2092
2101
  const [editing, setEditing] = useState6(null);
2093
2102
  const [draft, setDraft] = useState6("");
2094
2103
  const [rowDragPreview, setRowDragPreview] = useState6(null);
2104
+ const [liftedRowPreview, setLiftedRowPreview] = useState6(null);
2095
2105
  const [columnDragPreview, setColumnDragPreview] = useState6(null);
2096
2106
  const [columnDropTarget, setColumnDropTarget] = useState6(null);
2097
2107
  useEffect3(() => {
@@ -3338,131 +3348,66 @@ function TableInner({
3338
3348
  const rowIndex = Math.floor((localY - bodyTop + scrollRef.current.top) / rowHeight);
3339
3349
  return rowIndex >= 0 && rowIndex < rows.length ? rowIndex : -1;
3340
3350
  }, [bodyTop, rowHeight, rows.length]);
3341
- useEffect3(() => {
3342
- const canvas = canvasRef.current;
3343
- if (!canvas || !rowDraggable) return;
3344
- const cleanupDrag = draggable({
3345
- element: canvas,
3346
- canDrag: ({ input }) => {
3347
- const columnIndex = locateColumn(input.clientX);
3348
- return columnIndex >= 0 && Boolean(columns[columnIndex].rowDragHandle) && locateRow(input.clientY) >= 0;
3349
- },
3350
- getInitialData: ({ input }) => ({ type: "table-row", sourceIndex: locateRow(input.clientY) }),
3351
- onGenerateDragPreview: ({ nativeSetDragImage, source, location }) => {
3352
- const sourceIndex = Number(source.data.sourceIndex);
3353
- const canvasRect = canvas.getBoundingClientRect();
3354
- const input = location.current.input;
3355
- const previewOffset = {
3356
- x: Math.max(0, Math.min(canvasRect.width, input.clientX - canvasRect.left)) + 2,
3357
- y: Math.max(0, Math.min(rowHeight, input.clientY - canvasRect.top - bodyTop - sourceIndex * rowHeight + scrollRef.current.top)) + 2
3358
- };
3359
- setCustomNativeDragPreview({
3360
- nativeSetDragImage,
3361
- getOffset: () => previewOffset,
3362
- render: ({ container }) => {
3363
- const frame = document.createElement("div");
3364
- frame.className = "rvg-row-drag-preview-frame";
3365
- frame.style.width = `${canvasRect.width + 4}px`;
3366
- frame.style.height = `${rowHeight + 4}px`;
3367
- const preview = document.createElement("div");
3368
- preview.className = "rvg-row-drag-preview";
3369
- preview.style.width = `${canvasRect.width}px`;
3370
- preview.style.height = `${rowHeight}px`;
3371
- const row = rows[sourceIndex];
3372
- const rowKey2 = getRowKey(row, sourceIndex);
3373
- columns.forEach((column, columnIndex) => {
3374
- const left = getDisplayedColumnLeft(columnIndex);
3375
- const columnWidth = metrics[columnIndex].width;
3376
- if (left + columnWidth <= 0 || left >= canvasRect.width) return;
3377
- const cell = document.createElement("div");
3378
- cell.className = "rvg-row-drag-preview-cell";
3379
- cell.style.left = `${left}px`;
3380
- cell.style.width = `${columnWidth}px`;
3381
- cell.style.justifyContent = column.align === "right" ? "flex-end" : column.align === "center" ? "center" : "flex-start";
3382
- if (column.rowDragHandle && !column.rowSelection) {
3383
- cell.appendChild(createRowDragHandleSvg());
3384
- } else if (column.rowSelection) {
3385
- if (column.rowSelectionIndicator !== "none") {
3386
- const checkbox = document.createElement("span");
3387
- checkbox.className = selectedRowKeySet.has(rowKey2) ? "rvg-preview-checkbox is-checked" : "rvg-preview-checkbox";
3388
- checkbox.textContent = selectedRowKeySet.has(rowKey2) ? "\u2713" : "";
3389
- cell.appendChild(checkbox);
3390
- }
3391
- } else {
3392
- cell.textContent = getCellLabel(sourceIndex, columnIndex);
3393
- }
3394
- if (selection?.rowKey === rowKey2 && selection.columnKey === column.key) cell.classList.add("is-selected");
3395
- preview.appendChild(cell);
3396
- });
3397
- frame.appendChild(preview);
3398
- container.appendChild(frame);
3399
- return () => frame.remove();
3400
- }
3401
- });
3402
- },
3403
- onDragStart: ({ source }) => {
3404
- const sourceIndex = Number(source.data.sourceIndex);
3405
- suppressClickRef.current = true;
3406
- hideDragTooltips();
3407
- document.documentElement.classList.add("rvg-is-dragging");
3408
- canvas.style.cursor = "move";
3409
- setRowDragPreview({ sourceIndex, targetIndex: sourceIndex });
3410
- },
3411
- onDrag: ({ source, location }) => {
3412
- const target = location.current.dropTargets[0]?.data;
3413
- const sourceIndex = Number(source.data.sourceIndex);
3414
- const rawTargetIndex = Number(target?.targetIndex);
3415
- if (!Number.isInteger(rawTargetIndex)) {
3416
- setRowDragPreview(null);
3417
- setRowDragGuide(null);
3418
- return;
3419
- }
3420
- const edge = target?.rowEdge;
3421
- let targetIndex = rawTargetIndex + (edge === "bottom" ? 1 : 0);
3422
- if (sourceIndex < targetIndex) targetIndex -= 1;
3423
- targetIndex = Math.max(0, Math.min(rows.length - 1, targetIndex));
3424
- setRowDragPreview((current) => current?.sourceIndex === sourceIndex && current.targetIndex === targetIndex ? current : { sourceIndex, targetIndex });
3425
- setRowDragGuide(bodyTop + rawTargetIndex * rowHeight - scrollRef.current.top + (edge === "bottom" ? rowHeight : 0));
3426
- },
3427
- onDrop: ({ source, location }) => {
3428
- const target = location.current.dropTargets[0]?.data;
3429
- const sourceIndex = Number(source.data.sourceIndex);
3430
- const rawTargetIndex = Number(target?.targetIndex);
3431
- let targetIndex = rawTargetIndex + (target?.rowEdge === "bottom" ? 1 : 0);
3432
- if (sourceIndex < targetIndex) targetIndex -= 1;
3433
- targetIndex = Math.max(0, Math.min(rows.length - 1, targetIndex));
3434
- scrollerRef.current?.classList.add("rvg-row-drop-settling");
3435
- setRowDragPreview(null);
3436
- setRowDragGuide(null);
3437
- document.documentElement.classList.remove("rvg-is-dragging");
3438
- canvas.style.cursor = "default";
3439
- if (Number.isInteger(rawTargetIndex) && sourceIndex !== targetIndex) applyRowOrder(sourceIndex, targetIndex);
3440
- requestAnimationFrame(() => {
3441
- requestAnimationFrame(() => scrollerRef.current?.classList.remove("rvg-row-drop-settling"));
3442
- });
3443
- window.setTimeout(() => {
3444
- suppressClickRef.current = false;
3445
- }, 0);
3446
- }
3447
- });
3448
- const cleanupDrop = dropTargetForElements({
3449
- element: canvas,
3450
- canDrop: ({ source }) => source.data.type === "table-row",
3451
- getDropEffect: () => "move",
3452
- getData: ({ input, element }) => {
3453
- const targetIndex = locateRow(input.clientY);
3454
- if (targetIndex < 0) return { targetIndex: -1 };
3455
- const rowTop = bodyTop + targetIndex * rowHeight - scrollRef.current.top;
3456
- const rowEdge = input.clientY - canvas.getBoundingClientRect().top < rowTop + rowHeight / 2 ? "top" : "bottom";
3457
- return attachClosestEdge({ targetIndex, rowEdge }, { element, input, allowedEdges: ["top", "bottom"] });
3458
- }
3459
- });
3460
- return () => {
3461
- document.documentElement.classList.remove("rvg-is-dragging");
3462
- cleanupDrag();
3463
- cleanupDrop();
3351
+ const handleRowOrderPointerDown = useCallback2((event) => {
3352
+ if (!rowDraggable || event.button !== 0 || rowOrderDragRef.current) return;
3353
+ const columnIndex = locateColumn(event.clientX);
3354
+ const sourceIndex = locateRow(event.clientY);
3355
+ if (columnIndex < 0 || sourceIndex < 0 || !columns[columnIndex].rowDragHandle) return;
3356
+ event.currentTarget.setPointerCapture?.(event.pointerId);
3357
+ rowOrderDragRef.current = {
3358
+ pointerId: event.pointerId,
3359
+ startY: event.clientY,
3360
+ active: false,
3361
+ sourceIndex,
3362
+ targetIndex: sourceIndex
3464
3363
  };
3465
- }, [applyRowOrder, bodyTop, columns, getCellLabel, getDisplayedColumnLeft, getRowKey, hideDragTooltips, locateColumn, locateRow, metrics, rowDraggable, rowHeight, rows, selectedRowKeySet, selection, setRowDragGuide]);
3364
+ }, [columns, locateColumn, locateRow, rowDraggable]);
3365
+ const handleRowOrderPointerMove = useCallback2((event) => {
3366
+ const drag = rowOrderDragRef.current;
3367
+ if (!drag || drag.pointerId !== event.pointerId) return;
3368
+ if (!drag.active) {
3369
+ if (Math.abs(event.clientY - drag.startY) < 4) return;
3370
+ drag.active = true;
3371
+ suppressClickRef.current = true;
3372
+ hideDragTooltips();
3373
+ document.documentElement.classList.add("rvg-is-dragging");
3374
+ event.currentTarget.style.cursor = "move";
3375
+ }
3376
+ event.preventDefault();
3377
+ const canvasTop = event.currentTarget.getBoundingClientRect().top;
3378
+ setLiftedRowPreview({
3379
+ sourceIndex: drag.sourceIndex,
3380
+ top: Math.max(bodyTop, Math.min(renderHeight - rowHeight, event.clientY - canvasTop - rowHeight / 2))
3381
+ });
3382
+ const rawTargetIndex = locateRow(event.clientY);
3383
+ if (rawTargetIndex < 0) return;
3384
+ const rowTop = bodyTop + rawTargetIndex * rowHeight - scrollRef.current.top;
3385
+ const edge = event.clientY - canvasTop < rowTop + rowHeight / 2 ? "top" : "bottom";
3386
+ let targetIndex = rawTargetIndex + (edge === "bottom" ? 1 : 0);
3387
+ if (drag.sourceIndex < targetIndex) targetIndex -= 1;
3388
+ targetIndex = Math.max(0, Math.min(rows.length - 1, targetIndex));
3389
+ drag.targetIndex = targetIndex;
3390
+ setRowDragPreview(null);
3391
+ setRowDragGuide(rowTop + (edge === "bottom" ? rowHeight : 0));
3392
+ }, [bodyTop, hideDragTooltips, locateRow, renderHeight, rowHeight, rows.length, setRowDragGuide]);
3393
+ const finishRowOrderPointerDrag = useCallback2((event, apply) => {
3394
+ const drag = rowOrderDragRef.current;
3395
+ if (!drag || drag.pointerId !== event.pointerId) return;
3396
+ if (event.currentTarget.hasPointerCapture?.(event.pointerId)) event.currentTarget.releasePointerCapture?.(event.pointerId);
3397
+ rowOrderDragRef.current = null;
3398
+ setRowDragPreview(null);
3399
+ setLiftedRowPreview(null);
3400
+ setRowDragGuide(null);
3401
+ document.documentElement.classList.remove("rvg-is-dragging");
3402
+ event.currentTarget.style.cursor = "default";
3403
+ if (apply && drag.active && drag.sourceIndex !== drag.targetIndex) {
3404
+ scrollerRef.current?.classList.add("rvg-row-drop-settling");
3405
+ applyRowOrder(drag.sourceIndex, drag.targetIndex);
3406
+ requestAnimationFrame(() => {
3407
+ requestAnimationFrame(() => scrollerRef.current?.classList.remove("rvg-row-drop-settling"));
3408
+ });
3409
+ }
3410
+ }, [applyRowOrder, setRowDragGuide]);
3466
3411
  const locateCell = useCallback2((clientX, clientY) => {
3467
3412
  const canvas = canvasRef.current;
3468
3413
  if (!canvas) return null;
@@ -5055,7 +5000,7 @@ function TableInner({
5055
5000
  }
5056
5001
  }
5057
5002
  }
5058
- const cursor = inHeader && locateHeaderResizeCell(event.clientX, event.clientY) ? "col-resize" : hoveredAction ? "pointer" : hoveredDragHandle ? "move" : columnIndex >= 0 && columns[columnIndex].rowSelection ? "pointer" : !inHeader && rowDraggable && columnIndex >= 0 && columns[columnIndex].rowDragHandle ? "move" : "default";
5003
+ const cursor = inHeader && locateHeaderResizeCell(event.clientX, event.clientY) ? "col-resize" : hoveredAction ? "pointer" : hoveredDragHandle ? "move" : !inHeader && rowDraggable && columnIndex >= 0 && columns[columnIndex].rowDragHandle ? "move" : columnIndex >= 0 && columns[columnIndex].rowSelection ? "pointer" : "default";
5059
5004
  if (event.currentTarget.style.cursor !== cursor) event.currentTarget.style.cursor = cursor;
5060
5005
  },
5061
5006
  onMouseLeave: (event) => {
@@ -5074,6 +5019,7 @@ function TableInner({
5074
5019
  }
5075
5020
  },
5076
5021
  onPointerDown: (event) => {
5022
+ handleRowOrderPointerDown(event);
5077
5023
  handleColumnPointerDown(event);
5078
5024
  if (columnDragRef.current) return;
5079
5025
  const headerDragCell = columnDraggable ? locateHeaderCell(event.clientX, event.clientY) : null;
@@ -5086,16 +5032,19 @@ function TableInner({
5086
5032
  beginRangeDrag(event);
5087
5033
  },
5088
5034
  onPointerMove: (event) => {
5035
+ handleRowOrderPointerMove(event);
5089
5036
  handleColumnPointerMove(event);
5090
5037
  handleColumnOrderPointerMove(event);
5091
5038
  updateRangeDrag(event);
5092
5039
  },
5093
5040
  onPointerUp: (event) => {
5041
+ finishRowOrderPointerDrag(event, true);
5094
5042
  handleColumnPointerUp(event);
5095
5043
  finishColumnOrderPointerDrag(event, true);
5096
5044
  endRangeDrag(event);
5097
5045
  },
5098
5046
  onPointerCancel: (event) => {
5047
+ finishRowOrderPointerDrag(event, false);
5099
5048
  handleColumnPointerUp(event);
5100
5049
  finishColumnOrderPointerDrag(event, false);
5101
5050
  endRangeDrag(event);
@@ -5659,6 +5608,26 @@ function TableInner({
5659
5608
  ]
5660
5609
  }
5661
5610
  ),
5611
+ liftedRowPreview && rows[liftedRowPreview.sourceIndex] && /* @__PURE__ */ jsx8(
5612
+ "div",
5613
+ {
5614
+ "aria-hidden": "true",
5615
+ className: `rvg-row-drag-preview${selectedRowKeySet.has(getRowKey(rows[liftedRowPreview.sourceIndex], liftedRowPreview.sourceIndex)) ? " is-selected" : ""}`,
5616
+ style: { top: liftedRowPreview.top, width: viewport.width, height: rowHeight },
5617
+ children: columns.map((column, columnIndex) => /* @__PURE__ */ jsx8(
5618
+ "div",
5619
+ {
5620
+ className: "rvg-row-drag-preview-cell",
5621
+ style: {
5622
+ left: getDisplayedColumnLeft(columnIndex),
5623
+ width: metrics[columnIndex]?.width ?? 0
5624
+ },
5625
+ children: getCellLabel(liftedRowPreview.sourceIndex, columnIndex)
5626
+ },
5627
+ `row-preview:${column.key}`
5628
+ ))
5629
+ }
5630
+ ),
5662
5631
  resizeGuideX !== null && /* @__PURE__ */ jsx8(
5663
5632
  "div",
5664
5633
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensui/lens-table",
3
- "version": "0.1.77",
3
+ "version": "0.1.79",
4
4
  "description": "A lightweight, canvas-rendered React table component for LensUI.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",