diff --git a/src/Cell.tsx b/src/Cell.tsx index 82b0ee7bd2..d0a26f28bd 100644 --- a/src/Cell.tsx +++ b/src/Cell.tsx @@ -33,7 +33,6 @@ function Cell({ isDraggedOver, row, rowIdx, - dragHandle, onClick, onDoubleClick, onContextMenu, @@ -112,7 +111,6 @@ function Cell({ tabIndex: childTabIndex, onRowChange: handleRowChange })} - {dragHandle} ); } diff --git a/src/DataGrid.tsx b/src/DataGrid.tsx index 70cc37ce31..1d7b31b609 100644 --- a/src/DataGrid.tsx +++ b/src/DataGrid.tsx @@ -799,13 +799,18 @@ function DataGrid( return isDraggedOver ? selectedPosition.idx : undefined; } - function getDragHandle(rowIdx: number) { - if (selectedPosition.rowIdx !== rowIdx || selectedPosition.mode === 'EDIT' || onFill == null) { + function renderDragHandle() { + if ( + onFill == null || + selectedPosition.mode === 'EDIT' || + !isCellWithinViewportBounds(selectedPosition) + ) { return; } return ( ( lastFrozenColumnIndex, onRowChange: handleFormatterRowChangeLatest, selectCell: selectCellLatest, - selectedCellDragHandle: getDragHandle(rowIdx), selectedCellEditor: getCellEditor(rowIdx) }) ); @@ -1121,6 +1125,8 @@ function DataGrid( + {renderDragHandle()} + {/* render empty cells that span only 1 column so we can safely measure column widths, regardless of colSpan */} {renderMeasuringCells(viewportColumns)} diff --git a/src/DragHandle.tsx b/src/DragHandle.tsx index 2258aaf654..05d575bb4c 100644 --- a/src/DragHandle.tsx +++ b/src/DragHandle.tsx @@ -1,30 +1,39 @@ import { css } from '@linaria/core'; +import clsx from 'clsx'; +import { getCellStyle } from './utils'; import type { CalculatedColumn, FillEvent, Position } from './types'; import type { DataGridProps, SelectCellState } from './DataGrid'; const cellDragHandle = css` @layer rdg.DragHandle { + --rdg-drag-handle-size: 8px; + z-index: 0; cursor: move; - position: absolute; - inset-inline-end: 0; - inset-block-end: 0; - inline-size: 8px; - block-size: 8px; + inline-size: var(--rdg-drag-handle-size); + block-size: var(--rdg-drag-handle-size); background-color: var(--rdg-selection-color); + place-self: end; &:hover { - inline-size: 16px; - block-size: 16px; + --rdg-drag-handle-size: 16px; border: 2px solid var(--rdg-selection-color); background-color: var(--rdg-background-color); } } `; +const cellDragHandleFrozenClassname = css` + @layer rdg.DragHandle { + z-index: 1; + position: sticky; + } +`; + const cellDragHandleClassname = `rdg-cell-drag-handle ${cellDragHandle}`; interface Props extends Pick, 'rows' | 'onRowsChange'> { + gridRowStart: number; columns: readonly CalculatedColumn[]; selectedPosition: SelectCellState; latestDraggedOverRowIdx: React.MutableRefObject; @@ -35,6 +44,7 @@ interface Props extends Pick, 'rows' | 'onRowsChange } export default function DragHandle({ + gridRowStart, rows, columns, selectedPosition, @@ -45,6 +55,9 @@ export default function DragHandle({ setDragging, setDraggedOverRowIdx }: Props) { + const { idx, rowIdx } = selectedPosition; + const column = columns[idx]; + function handleMouseDown(event: React.MouseEvent) { if (event.buttons !== 1) return; setDragging(true); @@ -70,7 +83,6 @@ export default function DragHandle({ const overRowIdx = latestDraggedOverRowIdx.current; if (overRowIdx === undefined) return; - const { rowIdx } = selectedPosition; const startRowIndex = rowIdx < overRowIdx ? rowIdx + 1 : overRowIdx; const endRowIndex = rowIdx < overRowIdx ? overRowIdx + 1 : rowIdx; updateRows(startRowIndex, endRowIndex); @@ -79,11 +91,10 @@ export default function DragHandle({ function handleDoubleClick(event: React.MouseEvent) { event.stopPropagation(); - updateRows(selectedPosition.rowIdx + 1, rows.length); + updateRows(rowIdx + 1, rows.length); } function updateRows(startRowIdx: number, endRowIdx: number) { - const { idx, rowIdx } = selectedPosition; const column = columns[idx]; const sourceRow = rows[rowIdx]; const updatedRows = [...rows]; @@ -103,9 +114,20 @@ export default function DragHandle({ } } + const colSpan = column.colSpan?.({ type: 'ROW', row: rows[rowIdx] }) ?? 1; + const style = getCellStyle(column, colSpan); + return (
diff --git a/src/Row.tsx b/src/Row.tsx index 7e4affbe9c..aab22bda6b 100644 --- a/src/Row.tsx +++ b/src/Row.tsx @@ -21,7 +21,6 @@ function Row( row, viewportColumns, selectedCellEditor, - selectedCellDragHandle, onCellClick, onCellDoubleClick, onCellContextMenu, @@ -78,7 +77,6 @@ function Row( isCopied={copiedCellIdx === idx} isDraggedOver={draggedOverCellIdx === idx} isCellSelected={isCellSelected} - dragHandle={isCellSelected ? selectedCellDragHandle : undefined} onClick={onCellClick} onDoubleClick={onCellDoubleClick} onContextMenu={onCellContextMenu} diff --git a/src/TreeDataGrid.tsx b/src/TreeDataGrid.tsx index 7f8f151c27..8ee7675d8f 100644 --- a/src/TreeDataGrid.tsx +++ b/src/TreeDataGrid.tsx @@ -363,7 +363,6 @@ function TreeDataGrid( draggedOverCellIdx, setDraggedOverRowIdx, selectedCellEditor, - selectedCellDragHandle, ...rowProps }: RenderRowProps ) { @@ -402,8 +401,7 @@ function TreeDataGrid( copiedCellIdx, draggedOverCellIdx, setDraggedOverRowIdx, - selectedCellEditor, - selectedCellDragHandle + selectedCellEditor }); } diff --git a/src/types.ts b/src/types.ts index 14b7656c2b..2bb18ffa11 100644 --- a/src/types.ts +++ b/src/types.ts @@ -148,7 +148,6 @@ export interface CellRendererProps isCopied: boolean; isDraggedOver: boolean; isCellSelected: boolean; - dragHandle: ReactElement> | undefined; onClick: RenderRowProps['onCellClick']; onDoubleClick: RenderRowProps['onCellDoubleClick']; onContextMenu: RenderRowProps['onCellContextMenu']; @@ -213,7 +212,6 @@ export interface RenderRowProps copiedCellIdx: number | undefined; draggedOverCellIdx: number | undefined; selectedCellEditor: ReactElement> | undefined; - selectedCellDragHandle: ReactElement> | undefined; onRowChange: (column: CalculatedColumn, rowIdx: number, newRow: TRow) => void; rowClass: Maybe<(row: TRow, rowIdx: number) => Maybe>; setDraggedOverRowIdx: ((overRowIdx: number) => void) | undefined;