@lensui/lens-table 0.1.77 → 0.1.78

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
  });
@@ -968,25 +991,6 @@ function TextAreaEditor({ value, title, maxLength, style, labels, onChange, onCo
968
991
  ] });
969
992
  }
970
993
 
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
994
  // src/core/format.ts
991
995
  function getDisplayLabel(column, row, rowIndex) {
992
996
  const value = column.dataIndex === void 0 ? void 0 : row[column.dataIndex];
@@ -2068,6 +2072,7 @@ function TableInner({
2068
2072
  const columnDragRef = (0, import_react8.useRef)(null);
2069
2073
  const columnOrderDragRef = (0, import_react8.useRef)(null);
2070
2074
  const columnOrderLongPressTimerRef = (0, import_react8.useRef)(null);
2075
+ const rowOrderDragRef = (0, import_react8.useRef)(null);
2071
2076
  const dragGuideRef = (0, import_react8.useRef)(null);
2072
2077
  const rowDragGuideRef = (0, import_react8.useRef)(null);
2073
2078
  const selectionFocusRef = (0, import_react8.useRef)(null);
@@ -3368,131 +3373,61 @@ function TableInner({
3368
3373
  const rowIndex = Math.floor((localY - bodyTop + scrollRef.current.top) / rowHeight);
3369
3374
  return rowIndex >= 0 && rowIndex < rows.length ? rowIndex : -1;
3370
3375
  }, [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();
3376
+ const handleRowOrderPointerDown = (0, import_react8.useCallback)((event) => {
3377
+ if (!rowDraggable || event.button !== 0 || rowOrderDragRef.current) return;
3378
+ const columnIndex = locateColumn(event.clientX);
3379
+ const sourceIndex = locateRow(event.clientY);
3380
+ if (columnIndex < 0 || sourceIndex < 0 || !columns[columnIndex].rowDragHandle) return;
3381
+ event.currentTarget.setPointerCapture?.(event.pointerId);
3382
+ rowOrderDragRef.current = {
3383
+ pointerId: event.pointerId,
3384
+ startY: event.clientY,
3385
+ active: false,
3386
+ sourceIndex,
3387
+ targetIndex: sourceIndex
3494
3388
  };
3495
- }, [applyRowOrder, bodyTop, columns, getCellLabel, getDisplayedColumnLeft, getRowKey, hideDragTooltips, locateColumn, locateRow, metrics, rowDraggable, rowHeight, rows, selectedRowKeySet, selection, setRowDragGuide]);
3389
+ }, [columns, locateColumn, locateRow, rowDraggable]);
3390
+ const handleRowOrderPointerMove = (0, import_react8.useCallback)((event) => {
3391
+ const drag = rowOrderDragRef.current;
3392
+ if (!drag || drag.pointerId !== event.pointerId) return;
3393
+ if (!drag.active) {
3394
+ if (Math.abs(event.clientY - drag.startY) < 4) return;
3395
+ drag.active = true;
3396
+ suppressClickRef.current = true;
3397
+ hideDragTooltips();
3398
+ document.documentElement.classList.add("rvg-is-dragging");
3399
+ event.currentTarget.style.cursor = "move";
3400
+ }
3401
+ event.preventDefault();
3402
+ const rawTargetIndex = locateRow(event.clientY);
3403
+ if (rawTargetIndex < 0) return;
3404
+ const canvasTop = event.currentTarget.getBoundingClientRect().top;
3405
+ const rowTop = bodyTop + rawTargetIndex * rowHeight - scrollRef.current.top;
3406
+ const edge = event.clientY - canvasTop < rowTop + rowHeight / 2 ? "top" : "bottom";
3407
+ let targetIndex = rawTargetIndex + (edge === "bottom" ? 1 : 0);
3408
+ if (drag.sourceIndex < targetIndex) targetIndex -= 1;
3409
+ targetIndex = Math.max(0, Math.min(rows.length - 1, targetIndex));
3410
+ drag.targetIndex = targetIndex;
3411
+ setRowDragPreview((current) => current?.sourceIndex === drag.sourceIndex && current.targetIndex === targetIndex ? current : { sourceIndex: drag.sourceIndex, targetIndex });
3412
+ setRowDragGuide(rowTop + (edge === "bottom" ? rowHeight : 0));
3413
+ }, [bodyTop, hideDragTooltips, locateRow, rowHeight, rows.length, setRowDragGuide]);
3414
+ const finishRowOrderPointerDrag = (0, import_react8.useCallback)((event, apply) => {
3415
+ const drag = rowOrderDragRef.current;
3416
+ if (!drag || drag.pointerId !== event.pointerId) return;
3417
+ if (event.currentTarget.hasPointerCapture?.(event.pointerId)) event.currentTarget.releasePointerCapture?.(event.pointerId);
3418
+ rowOrderDragRef.current = null;
3419
+ setRowDragPreview(null);
3420
+ setRowDragGuide(null);
3421
+ document.documentElement.classList.remove("rvg-is-dragging");
3422
+ event.currentTarget.style.cursor = "default";
3423
+ if (apply && drag.active && drag.sourceIndex !== drag.targetIndex) {
3424
+ scrollerRef.current?.classList.add("rvg-row-drop-settling");
3425
+ applyRowOrder(drag.sourceIndex, drag.targetIndex);
3426
+ requestAnimationFrame(() => {
3427
+ requestAnimationFrame(() => scrollerRef.current?.classList.remove("rvg-row-drop-settling"));
3428
+ });
3429
+ }
3430
+ }, [applyRowOrder, setRowDragGuide]);
3496
3431
  const locateCell = (0, import_react8.useCallback)((clientX, clientY) => {
3497
3432
  const canvas = canvasRef.current;
3498
3433
  if (!canvas) return null;
@@ -5085,7 +5020,7 @@ function TableInner({
5085
5020
  }
5086
5021
  }
5087
5022
  }
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";
5023
+ 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
5024
  if (event.currentTarget.style.cursor !== cursor) event.currentTarget.style.cursor = cursor;
5090
5025
  },
5091
5026
  onMouseLeave: (event) => {
@@ -5104,6 +5039,7 @@ function TableInner({
5104
5039
  }
5105
5040
  },
5106
5041
  onPointerDown: (event) => {
5042
+ handleRowOrderPointerDown(event);
5107
5043
  handleColumnPointerDown(event);
5108
5044
  if (columnDragRef.current) return;
5109
5045
  const headerDragCell = columnDraggable ? locateHeaderCell(event.clientX, event.clientY) : null;
@@ -5116,16 +5052,19 @@ function TableInner({
5116
5052
  beginRangeDrag(event);
5117
5053
  },
5118
5054
  onPointerMove: (event) => {
5055
+ handleRowOrderPointerMove(event);
5119
5056
  handleColumnPointerMove(event);
5120
5057
  handleColumnOrderPointerMove(event);
5121
5058
  updateRangeDrag(event);
5122
5059
  },
5123
5060
  onPointerUp: (event) => {
5061
+ finishRowOrderPointerDrag(event, true);
5124
5062
  handleColumnPointerUp(event);
5125
5063
  finishColumnOrderPointerDrag(event, true);
5126
5064
  endRangeDrag(event);
5127
5065
  },
5128
5066
  onPointerCancel: (event) => {
5067
+ finishRowOrderPointerDrag(event, false);
5129
5068
  handleColumnPointerUp(event);
5130
5069
  finishColumnOrderPointerDrag(event, false);
5131
5070
  endRangeDrag(event);
package/dist/index.css CHANGED
@@ -2704,10 +2704,17 @@
2704
2704
  }
2705
2705
  .rvg-searchable-choice-content .rvg-choice-item {
2706
2706
  width: 100%;
2707
+ min-width: 0;
2707
2708
  border: 0;
2708
2709
  background: transparent;
2709
2710
  text-align: left;
2710
2711
  }
2712
+ .rvg-searchable-choice-content .rvg-choice-item > span {
2713
+ min-width: 0;
2714
+ overflow: hidden;
2715
+ white-space: nowrap;
2716
+ text-overflow: ellipsis;
2717
+ }
2711
2718
  .rvg-searchable-choice-content .rvg-choice-item:is(:hover, .is-active) {
2712
2719
  background: var(--rvg-color-hover);
2713
2720
  }
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
  });
@@ -938,25 +961,6 @@ function TextAreaEditor({ value, title, maxLength, style, labels, onChange, onCo
938
961
  ] });
939
962
  }
940
963
 
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
964
  // src/core/format.ts
961
965
  function getDisplayLabel(column, row, rowIndex) {
962
966
  const value = column.dataIndex === void 0 ? void 0 : row[column.dataIndex];
@@ -2038,6 +2042,7 @@ function TableInner({
2038
2042
  const columnDragRef = useRef4(null);
2039
2043
  const columnOrderDragRef = useRef4(null);
2040
2044
  const columnOrderLongPressTimerRef = useRef4(null);
2045
+ const rowOrderDragRef = useRef4(null);
2041
2046
  const dragGuideRef = useRef4(null);
2042
2047
  const rowDragGuideRef = useRef4(null);
2043
2048
  const selectionFocusRef = useRef4(null);
@@ -3338,131 +3343,61 @@ function TableInner({
3338
3343
  const rowIndex = Math.floor((localY - bodyTop + scrollRef.current.top) / rowHeight);
3339
3344
  return rowIndex >= 0 && rowIndex < rows.length ? rowIndex : -1;
3340
3345
  }, [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();
3346
+ const handleRowOrderPointerDown = useCallback2((event) => {
3347
+ if (!rowDraggable || event.button !== 0 || rowOrderDragRef.current) return;
3348
+ const columnIndex = locateColumn(event.clientX);
3349
+ const sourceIndex = locateRow(event.clientY);
3350
+ if (columnIndex < 0 || sourceIndex < 0 || !columns[columnIndex].rowDragHandle) return;
3351
+ event.currentTarget.setPointerCapture?.(event.pointerId);
3352
+ rowOrderDragRef.current = {
3353
+ pointerId: event.pointerId,
3354
+ startY: event.clientY,
3355
+ active: false,
3356
+ sourceIndex,
3357
+ targetIndex: sourceIndex
3464
3358
  };
3465
- }, [applyRowOrder, bodyTop, columns, getCellLabel, getDisplayedColumnLeft, getRowKey, hideDragTooltips, locateColumn, locateRow, metrics, rowDraggable, rowHeight, rows, selectedRowKeySet, selection, setRowDragGuide]);
3359
+ }, [columns, locateColumn, locateRow, rowDraggable]);
3360
+ const handleRowOrderPointerMove = useCallback2((event) => {
3361
+ const drag = rowOrderDragRef.current;
3362
+ if (!drag || drag.pointerId !== event.pointerId) return;
3363
+ if (!drag.active) {
3364
+ if (Math.abs(event.clientY - drag.startY) < 4) return;
3365
+ drag.active = true;
3366
+ suppressClickRef.current = true;
3367
+ hideDragTooltips();
3368
+ document.documentElement.classList.add("rvg-is-dragging");
3369
+ event.currentTarget.style.cursor = "move";
3370
+ }
3371
+ event.preventDefault();
3372
+ const rawTargetIndex = locateRow(event.clientY);
3373
+ if (rawTargetIndex < 0) return;
3374
+ const canvasTop = event.currentTarget.getBoundingClientRect().top;
3375
+ const rowTop = bodyTop + rawTargetIndex * rowHeight - scrollRef.current.top;
3376
+ const edge = event.clientY - canvasTop < rowTop + rowHeight / 2 ? "top" : "bottom";
3377
+ let targetIndex = rawTargetIndex + (edge === "bottom" ? 1 : 0);
3378
+ if (drag.sourceIndex < targetIndex) targetIndex -= 1;
3379
+ targetIndex = Math.max(0, Math.min(rows.length - 1, targetIndex));
3380
+ drag.targetIndex = targetIndex;
3381
+ setRowDragPreview((current) => current?.sourceIndex === drag.sourceIndex && current.targetIndex === targetIndex ? current : { sourceIndex: drag.sourceIndex, targetIndex });
3382
+ setRowDragGuide(rowTop + (edge === "bottom" ? rowHeight : 0));
3383
+ }, [bodyTop, hideDragTooltips, locateRow, rowHeight, rows.length, setRowDragGuide]);
3384
+ const finishRowOrderPointerDrag = useCallback2((event, apply) => {
3385
+ const drag = rowOrderDragRef.current;
3386
+ if (!drag || drag.pointerId !== event.pointerId) return;
3387
+ if (event.currentTarget.hasPointerCapture?.(event.pointerId)) event.currentTarget.releasePointerCapture?.(event.pointerId);
3388
+ rowOrderDragRef.current = null;
3389
+ setRowDragPreview(null);
3390
+ setRowDragGuide(null);
3391
+ document.documentElement.classList.remove("rvg-is-dragging");
3392
+ event.currentTarget.style.cursor = "default";
3393
+ if (apply && drag.active && drag.sourceIndex !== drag.targetIndex) {
3394
+ scrollerRef.current?.classList.add("rvg-row-drop-settling");
3395
+ applyRowOrder(drag.sourceIndex, drag.targetIndex);
3396
+ requestAnimationFrame(() => {
3397
+ requestAnimationFrame(() => scrollerRef.current?.classList.remove("rvg-row-drop-settling"));
3398
+ });
3399
+ }
3400
+ }, [applyRowOrder, setRowDragGuide]);
3466
3401
  const locateCell = useCallback2((clientX, clientY) => {
3467
3402
  const canvas = canvasRef.current;
3468
3403
  if (!canvas) return null;
@@ -5055,7 +4990,7 @@ function TableInner({
5055
4990
  }
5056
4991
  }
5057
4992
  }
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";
4993
+ 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
4994
  if (event.currentTarget.style.cursor !== cursor) event.currentTarget.style.cursor = cursor;
5060
4995
  },
5061
4996
  onMouseLeave: (event) => {
@@ -5074,6 +5009,7 @@ function TableInner({
5074
5009
  }
5075
5010
  },
5076
5011
  onPointerDown: (event) => {
5012
+ handleRowOrderPointerDown(event);
5077
5013
  handleColumnPointerDown(event);
5078
5014
  if (columnDragRef.current) return;
5079
5015
  const headerDragCell = columnDraggable ? locateHeaderCell(event.clientX, event.clientY) : null;
@@ -5086,16 +5022,19 @@ function TableInner({
5086
5022
  beginRangeDrag(event);
5087
5023
  },
5088
5024
  onPointerMove: (event) => {
5025
+ handleRowOrderPointerMove(event);
5089
5026
  handleColumnPointerMove(event);
5090
5027
  handleColumnOrderPointerMove(event);
5091
5028
  updateRangeDrag(event);
5092
5029
  },
5093
5030
  onPointerUp: (event) => {
5031
+ finishRowOrderPointerDrag(event, true);
5094
5032
  handleColumnPointerUp(event);
5095
5033
  finishColumnOrderPointerDrag(event, true);
5096
5034
  endRangeDrag(event);
5097
5035
  },
5098
5036
  onPointerCancel: (event) => {
5037
+ finishRowOrderPointerDrag(event, false);
5099
5038
  handleColumnPointerUp(event);
5100
5039
  finishColumnOrderPointerDrag(event, false);
5101
5040
  endRangeDrag(event);
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.78",
4
4
  "description": "A lightweight, canvas-rendered React table component for LensUI.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",