Skip to content

Commit

Permalink
Move drag handle outside the cell (#3334)
Browse files Browse the repository at this point in the history
* Move drag handle outside the cell

* alternate approach

* revert

* Remove margin

* Fix drag handle position on frozen column

* Fix typo

* Fix colSpan

* Simplify styles

* Update src/DragHandle.tsx

Co-authored-by: Nicolas Stepien <567105+nstepien@users.noreply.github.com>

* Update src/DataGrid.tsx

Co-authored-by: Nicolas Stepien <567105+nstepien@users.noreply.github.com>

* Fix if condition

---------

Co-authored-by: Nicolas Stepien <567105+nstepien@users.noreply.github.com>
  • Loading branch information
amanmahajan7 and nstepien authored Sep 6, 2023
1 parent 6876768 commit 4af02f1
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 23 deletions.
2 changes: 0 additions & 2 deletions src/Cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ function Cell<R, SR>({
isDraggedOver,
row,
rowIdx,
dragHandle,
onClick,
onDoubleClick,
onContextMenu,
Expand Down Expand Up @@ -112,7 +111,6 @@ function Cell<R, SR>({
tabIndex: childTabIndex,
onRowChange: handleRowChange
})}
{dragHandle}
</div>
);
}
Expand Down
12 changes: 9 additions & 3 deletions src/DataGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -799,13 +799,18 @@ function DataGrid<R, SR, K extends Key>(
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 (
<DragHandle
gridRowStart={headerAndTopSummaryRowsCount + selectedPosition.rowIdx + 1}
rows={rows}
columns={columns}
selectedPosition={selectedPosition}
Expand Down Expand Up @@ -952,7 +957,6 @@ function DataGrid<R, SR, K extends Key>(
lastFrozenColumnIndex,
onRowChange: handleFormatterRowChangeLatest,
selectCell: selectCellLatest,
selectedCellDragHandle: getDragHandle(rowIdx),
selectedCellEditor: getCellEditor(rowIdx)
})
);
Expand Down Expand Up @@ -1121,6 +1125,8 @@ function DataGrid<R, SR, K extends Key>(
</RowSelectionChangeProvider>
</DataGridDefaultRenderersProvider>

{renderDragHandle()}

{/* render empty cells that span only 1 column so we can safely measure column widths, regardless of colSpan */}
{renderMeasuringCells(viewportColumns)}

Expand Down
44 changes: 33 additions & 11 deletions src/DragHandle.tsx
Original file line number Diff line number Diff line change
@@ -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<R, SR> extends Pick<DataGridProps<R, SR>, 'rows' | 'onRowsChange'> {
gridRowStart: number;
columns: readonly CalculatedColumn<R, SR>[];
selectedPosition: SelectCellState;
latestDraggedOverRowIdx: React.MutableRefObject<number | undefined>;
Expand All @@ -35,6 +44,7 @@ interface Props<R, SR> extends Pick<DataGridProps<R, SR>, 'rows' | 'onRowsChange
}

export default function DragHandle<R, SR>({
gridRowStart,
rows,
columns,
selectedPosition,
Expand All @@ -45,6 +55,9 @@ export default function DragHandle<R, SR>({
setDragging,
setDraggedOverRowIdx
}: Props<R, SR>) {
const { idx, rowIdx } = selectedPosition;
const column = columns[idx];

function handleMouseDown(event: React.MouseEvent<HTMLDivElement>) {
if (event.buttons !== 1) return;
setDragging(true);
Expand All @@ -70,7 +83,6 @@ export default function DragHandle<R, SR>({
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);
Expand All @@ -79,11 +91,10 @@ export default function DragHandle<R, SR>({

function handleDoubleClick(event: React.MouseEvent<HTMLDivElement>) {
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];
Expand All @@ -103,9 +114,20 @@ export default function DragHandle<R, SR>({
}
}

const colSpan = column.colSpan?.({ type: 'ROW', row: rows[rowIdx] }) ?? 1;
const style = getCellStyle(column, colSpan);

return (
<div
className={cellDragHandleClassname}
style={{
...style,
gridRowStart,
insetInlineStart:
style.insetInlineStart && typeof column.width === 'number'
? `calc(${style.insetInlineStart} + ${column.width}px - var(--rdg-drag-handle-size))`
: undefined
}}
className={clsx(cellDragHandleClassname, column.frozen && cellDragHandleFrozenClassname)}
onMouseDown={handleMouseDown}
onDoubleClick={handleDoubleClick}
/>
Expand Down
2 changes: 0 additions & 2 deletions src/Row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ function Row<R, SR>(
row,
viewportColumns,
selectedCellEditor,
selectedCellDragHandle,
onCellClick,
onCellDoubleClick,
onCellContextMenu,
Expand Down Expand Up @@ -78,7 +77,6 @@ function Row<R, SR>(
isCopied={copiedCellIdx === idx}
isDraggedOver={draggedOverCellIdx === idx}
isCellSelected={isCellSelected}
dragHandle={isCellSelected ? selectedCellDragHandle : undefined}
onClick={onCellClick}
onDoubleClick={onCellDoubleClick}
onContextMenu={onCellContextMenu}
Expand Down
4 changes: 1 addition & 3 deletions src/TreeDataGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,6 @@ function TreeDataGrid<R, SR, K extends Key>(
draggedOverCellIdx,
setDraggedOverRowIdx,
selectedCellEditor,
selectedCellDragHandle,
...rowProps
}: RenderRowProps<R, SR>
) {
Expand Down Expand Up @@ -402,8 +401,7 @@ function TreeDataGrid<R, SR, K extends Key>(
copiedCellIdx,
draggedOverCellIdx,
setDraggedOverRowIdx,
selectedCellEditor,
selectedCellDragHandle
selectedCellEditor
});
}

Expand Down
2 changes: 0 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ export interface CellRendererProps<TRow, TSummaryRow>
isCopied: boolean;
isDraggedOver: boolean;
isCellSelected: boolean;
dragHandle: ReactElement<React.HTMLAttributes<HTMLDivElement>> | undefined;
onClick: RenderRowProps<TRow, TSummaryRow>['onCellClick'];
onDoubleClick: RenderRowProps<TRow, TSummaryRow>['onCellDoubleClick'];
onContextMenu: RenderRowProps<TRow, TSummaryRow>['onCellContextMenu'];
Expand Down Expand Up @@ -213,7 +212,6 @@ export interface RenderRowProps<TRow, TSummaryRow = unknown>
copiedCellIdx: number | undefined;
draggedOverCellIdx: number | undefined;
selectedCellEditor: ReactElement<RenderEditCellProps<TRow>> | undefined;
selectedCellDragHandle: ReactElement<React.HTMLAttributes<HTMLDivElement>> | undefined;
onRowChange: (column: CalculatedColumn<TRow, TSummaryRow>, rowIdx: number, newRow: TRow) => void;
rowClass: Maybe<(row: TRow, rowIdx: number) => Maybe<string>>;
setDraggedOverRowIdx: ((overRowIdx: number) => void) | undefined;
Expand Down

0 comments on commit 4af02f1

Please sign in to comment.