From fbb8273df8626a31c4aad210646e9e62d80c3154 Mon Sep 17 00:00:00 2001 From: kcvikander Date: Mon, 8 Apr 2024 12:32:55 -0500 Subject: [PATCH 1/4] adds prop to guide where the drag image anchors to --- packages/core/src/data-editor/data-editor.tsx | 40 +++++----- .../stories/data-editor.stories.tsx | 16 ++++ .../internal/data-grid-dnd/data-grid-dnd.tsx | 1 + .../data-grid-search/data-grid-search.tsx | 1 + .../core/src/internal/data-grid/data-grid.tsx | 77 +++++++++++-------- .../scrolling-data-grid.tsx | 29 +++---- 6 files changed, 98 insertions(+), 66 deletions(-) diff --git a/packages/core/src/data-editor/data-editor.tsx b/packages/core/src/data-editor/data-editor.tsx index 7a3c89d86..7f3a7f611 100644 --- a/packages/core/src/data-editor/data-editor.tsx +++ b/packages/core/src/data-editor/data-editor.tsx @@ -182,16 +182,16 @@ function shiftSelection(input: GridSelection, offset: number): GridSelection { input.current === undefined ? undefined : { - cell: [input.current.cell[0] + offset, input.current.cell[1]], - range: { - ...input.current.range, - x: input.current.range.x + offset, - }, - rangeStack: input.current.rangeStack.map(r => ({ - ...r, - x: r.x + offset, - })), - }, + cell: [input.current.cell[0] + offset, input.current.cell[1]], + range: { + ...input.current.range, + x: input.current.range.x + offset, + }, + rangeStack: input.current.rangeStack.map(r => ({ + ...r, + x: r.x + offset, + })), + }, rows: input.rows, columns: input.columns.offset(offset), }; @@ -845,6 +845,7 @@ const DataEditorImpl: React.ForwardRefRenderFunction ({ - ...x, - location: [x.location[0] - rowMarkerOffset, x.location[1]] as const, - })); + ...x, + location: [x.location[0] - rowMarkerOffset, x.location[1]] as const, + })); const r = onCellsEdited?.(mangledItems); if (r !== true) { @@ -1187,7 +1188,7 @@ const DataEditorImpl: React.ForwardRefRenderFunction 1 + gridSelection.current.range.width * gridSelection.current.range.height > 1 ? gridSelection.current.range : undefined; @@ -2469,11 +2470,11 @@ const DataEditorImpl: React.ForwardRefRenderFunction { + args.setData("text", "testing"); + }} + dragImageAnchor={'clickevent'} + getCellContent={getData} + columns={columns} + rows={1000} + /> + ); +} + export function DynamicAddRemoveColumns({ columnCount }: { columnCount: number }) { // trying to be 500x500 const cols: GridColumn[] = [ diff --git a/packages/core/src/internal/data-grid-dnd/data-grid-dnd.tsx b/packages/core/src/internal/data-grid-dnd/data-grid-dnd.tsx index f91c16da6..a54d61842 100644 --- a/packages/core/src/internal/data-grid-dnd/data-grid-dnd.tsx +++ b/packages/core/src/internal/data-grid-dnd/data-grid-dnd.tsx @@ -398,6 +398,7 @@ const DataGridDnd: React.FunctionComponent = p => { imageWindowLoader={p.imageWindowLoader} resizeColumn={resizeCol} isDraggable={p.isDraggable} + dragImageAnchor={p.dragImageAnchor} isFilling={p.isFilling} isFocused={p.isFocused} onCanvasBlur={p.onCanvasBlur} diff --git a/packages/core/src/internal/data-grid-search/data-grid-search.tsx b/packages/core/src/internal/data-grid-search/data-grid-search.tsx index d507d6a43..974ba2232 100644 --- a/packages/core/src/internal/data-grid-search/data-grid-search.tsx +++ b/packages/core/src/internal/data-grid-search/data-grid-search.tsx @@ -524,6 +524,7 @@ const DataGridSearch: React.FunctionComponent = p => { gridRef={p.gridRef} headerIcons={p.headerIcons} isDraggable={p.isDraggable} + dragImageAnchor={p.dragImageAnchor} onCanvasBlur={p.onCanvasBlur} onCanvasFocused={p.onCanvasFocused} onCellFocused={p.onCellFocused} diff --git a/packages/core/src/internal/data-grid/data-grid.tsx b/packages/core/src/internal/data-grid/data-grid.tsx index 52338a786..5c2204e4f 100644 --- a/packages/core/src/internal/data-grid/data-grid.tsx +++ b/packages/core/src/internal/data-grid/data-grid.tsx @@ -189,6 +189,13 @@ export interface DataGridProps { * @group Drag and Drop */ readonly isDraggable: boolean | "cell" | "header" | undefined; + + /** + * Determines, when dragging, where the cursor is anchored to the drag image. + * @defaultValue 'center' + * @group Drag and Drop + */ + readonly dragImageAnchor: 'center' | 'click' | 'click-x' | 'click-y' | undefined; /** * If `isDraggable` is set, the grid becomes HTML draggable, and `onDragStart` will be called when dragging starts. * You can use this to build a UI where the user can drag the Grid around. @@ -230,11 +237,11 @@ export interface DataGridProps { readonly drawFocusRing: boolean; readonly dragAndDropState: - | { - src: number; - dest: number; - } - | undefined; + | { + src: number; + dest: number; + } + | undefined; /** * Experimental features @@ -242,21 +249,21 @@ export interface DataGridProps { * @experimental */ readonly experimental: - | { - readonly disableAccessibilityTree?: boolean; - readonly disableMinimumCellWidth?: boolean; - readonly paddingRight?: number; - readonly paddingBottom?: number; - readonly enableFirefoxRescaling?: boolean; - readonly enableSafariRescaling?: boolean; - readonly kineticScrollPerfHack?: boolean; - readonly isSubGrid?: boolean; - readonly strict?: boolean; - readonly scrollbarWidthOverride?: number; - readonly hyperWrapping?: boolean; - readonly renderStrategy?: "single-buffer" | "double-buffer" | "direct"; - } - | undefined; + | { + readonly disableAccessibilityTree?: boolean; + readonly disableMinimumCellWidth?: boolean; + readonly paddingRight?: number; + readonly paddingBottom?: number; + readonly enableFirefoxRescaling?: boolean; + readonly enableSafariRescaling?: boolean; + readonly kineticScrollPerfHack?: boolean; + readonly isSubGrid?: boolean; + readonly strict?: boolean; + readonly scrollbarWidthOverride?: number; + readonly hyperWrapping?: boolean; + readonly renderStrategy?: "single-buffer" | "double-buffer" | "direct"; + } + | undefined; /** * Additional header icons for use by `GridColumn`. @@ -390,6 +397,7 @@ const DataGrid: React.ForwardRefRenderFunction = (p, experimental, getCellRenderer, resizeIndicator = "full", + dragImageAnchor = "center" } = p; const translateX = p.translateX ?? 0; const translateY = p.translateY ?? 0; @@ -932,14 +940,14 @@ const DataGrid: React.ForwardRefRenderFunction = (p, const cursor = isDragging ? "grabbing" : canDrag || isResizing - ? "col-resize" - : overFill || isFilling - ? "crosshair" - : cursorOverride !== undefined - ? cursorOverride - : headerHovered || clickableInnerCellHovered || editableBoolHovered || groupHeaderHovered - ? "pointer" - : "default"; + ? "col-resize" + : overFill || isFilling + ? "crosshair" + : cursorOverride !== undefined + ? cursorOverride + : headerHovered || clickableInnerCellHovered || editableBoolHovered || groupHeaderHovered + ? "pointer" + : "default"; const style = React.useMemo( () => ({ // width, @@ -983,9 +991,9 @@ const DataGrid: React.ForwardRefRenderFunction = (p, clientY: number ): | { - area: "menu" | "indicator"; - bounds: Rectangle; - } + area: "menu" | "indicator"; + bounds: Rectangle; + } | undefined => { const header = mappedColumns[col]; @@ -1566,10 +1574,13 @@ const DataGrid: React.ForwardRefRenderFunction = (p, document.body.append(offscreen); + const dragAnchorX = ['click', 'click-x'].includes(dragImageAnchor) ? event.clientX - boundsForDragTarget.x : boundsForDragTarget.width / 2 + const dragAnchorY = ['click', 'click-y'].includes(dragImageAnchor) ? event.clientY - boundsForDragTarget.y : boundsForDragTarget.height / 2 + event.dataTransfer.setDragImage( offscreen, - boundsForDragTarget.width / 2, - boundsForDragTarget.height / 2 + dragAnchorX, + dragAnchorY ); window.setTimeout(() => { diff --git a/packages/core/src/internal/scrolling-data-grid/scrolling-data-grid.tsx b/packages/core/src/internal/scrolling-data-grid/scrolling-data-grid.tsx index 1013c7ea9..2fb5eac25 100644 --- a/packages/core/src/internal/scrolling-data-grid/scrolling-data-grid.tsx +++ b/packages/core/src/internal/scrolling-data-grid/scrolling-data-grid.tsx @@ -8,15 +8,15 @@ type Props = Omit; export interface ScrollingDataGridProps extends Props { readonly className: string | undefined; readonly onVisibleRegionChanged: - | (( - range: Rectangle, - clientWidth: number, - clientHeight: number, - rightElWidth: number, - tx: number, - ty: number - ) => void) - | undefined; + | (( + range: Rectangle, + clientWidth: number, + clientHeight: number, + rightElWidth: number, + tx: number, + ty: number + ) => void) + | undefined; readonly scrollRef: React.MutableRefObject | undefined; /** @@ -54,11 +54,11 @@ export interface ScrollingDataGridProps extends Props { * @group Advanced */ readonly rightElementProps: - | { - readonly sticky?: boolean; - readonly fill?: boolean; - } - | undefined; + | { + readonly sticky?: boolean; + readonly fill?: boolean; + } + | undefined; /** * The right element is a DOM node which can be inserted at the end of the horizontal scroll region. This can be * used to create a right handle panel, make a big add button, or display messages. @@ -312,6 +312,7 @@ const GridScroller: React.FunctionComponent = p => { gridRef={p.gridRef} headerIcons={p.headerIcons} isDraggable={p.isDraggable} + dragImageAnchor={p.dragImageAnchor} onCanvasBlur={p.onCanvasBlur} onCanvasFocused={p.onCanvasFocused} onCellFocused={p.onCellFocused} From d744b0eef5be639d6f520b9ab530306966b77bbb Mon Sep 17 00:00:00 2001 From: kcvikander Date: Mon, 8 Apr 2024 12:57:09 -0500 Subject: [PATCH 2/4] fix story test --- packages/core/src/data-editor/stories/data-editor.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/data-editor/stories/data-editor.stories.tsx b/packages/core/src/data-editor/stories/data-editor.stories.tsx index 7d4d604d4..f2620aed1 100644 --- a/packages/core/src/data-editor/stories/data-editor.stories.tsx +++ b/packages/core/src/data-editor/stories/data-editor.stories.tsx @@ -359,7 +359,7 @@ export function DraggableWithEventAnchor() { onDragStart={args => { args.setData("text", "testing"); }} - dragImageAnchor={'clickevent'} + dragImageAnchor={'click'} getCellContent={getData} columns={columns} rows={1000} From 03c103072fc97e6ca73bbbabc2071bcd0d436315 Mon Sep 17 00:00:00 2001 From: kcvikander Date: Mon, 8 Apr 2024 13:33:34 -0500 Subject: [PATCH 3/4] fix bad spacing --- packages/core/src/data-editor/data-editor.tsx | 24 +++---- .../core/src/internal/data-grid/data-grid.tsx | 62 +++++++++---------- .../scrolling-data-grid.tsx | 28 ++++----- 3 files changed, 57 insertions(+), 57 deletions(-) diff --git a/packages/core/src/data-editor/data-editor.tsx b/packages/core/src/data-editor/data-editor.tsx index 7f3a7f611..abb977c87 100644 --- a/packages/core/src/data-editor/data-editor.tsx +++ b/packages/core/src/data-editor/data-editor.tsx @@ -182,15 +182,15 @@ function shiftSelection(input: GridSelection, offset: number): GridSelection { input.current === undefined ? undefined : { - cell: [input.current.cell[0] + offset, input.current.cell[1]], - range: { - ...input.current.range, - x: input.current.range.x + offset, - }, - rangeStack: input.current.rangeStack.map(r => ({ - ...r, - x: r.x + offset, - })), + cell: [input.current.cell[0] + offset, input.current.cell[1]], + range: { + ...input.current.range, + x: input.current.range.x + offset, + }, + rangeStack: input.current.rangeStack.map(r => ({ + ...r, + x: r.x + offset, + })), }, rows: input.rows, columns: input.columns.offset(offset), @@ -1169,9 +1169,9 @@ const DataEditorImpl: React.ForwardRefRenderFunction ({ - ...x, - location: [x.location[0] - rowMarkerOffset, x.location[1]] as const, - })); + ...x, + location: [x.location[0] - rowMarkerOffset, x.location[1]] as const, + })); const r = onCellsEdited?.(mangledItems); if (r !== true) { diff --git a/packages/core/src/internal/data-grid/data-grid.tsx b/packages/core/src/internal/data-grid/data-grid.tsx index 5c2204e4f..c829ece5e 100644 --- a/packages/core/src/internal/data-grid/data-grid.tsx +++ b/packages/core/src/internal/data-grid/data-grid.tsx @@ -237,11 +237,11 @@ export interface DataGridProps { readonly drawFocusRing: boolean; readonly dragAndDropState: - | { - src: number; - dest: number; - } - | undefined; + | { + src: number; + dest: number; + } + | undefined; /** * Experimental features @@ -249,21 +249,21 @@ export interface DataGridProps { * @experimental */ readonly experimental: - | { - readonly disableAccessibilityTree?: boolean; - readonly disableMinimumCellWidth?: boolean; - readonly paddingRight?: number; - readonly paddingBottom?: number; - readonly enableFirefoxRescaling?: boolean; - readonly enableSafariRescaling?: boolean; - readonly kineticScrollPerfHack?: boolean; - readonly isSubGrid?: boolean; - readonly strict?: boolean; - readonly scrollbarWidthOverride?: number; - readonly hyperWrapping?: boolean; - readonly renderStrategy?: "single-buffer" | "double-buffer" | "direct"; - } - | undefined; + | { + readonly disableAccessibilityTree?: boolean; + readonly disableMinimumCellWidth?: boolean; + readonly paddingRight?: number; + readonly paddingBottom?: number; + readonly enableFirefoxRescaling?: boolean; + readonly enableSafariRescaling?: boolean; + readonly kineticScrollPerfHack?: boolean; + readonly isSubGrid?: boolean; + readonly strict?: boolean; + readonly scrollbarWidthOverride?: number; + readonly hyperWrapping?: boolean; + readonly renderStrategy?: "single-buffer" | "double-buffer" | "direct"; + } + | undefined; /** * Additional header icons for use by `GridColumn`. @@ -940,14 +940,14 @@ const DataGrid: React.ForwardRefRenderFunction = (p, const cursor = isDragging ? "grabbing" : canDrag || isResizing - ? "col-resize" - : overFill || isFilling - ? "crosshair" - : cursorOverride !== undefined - ? cursorOverride - : headerHovered || clickableInnerCellHovered || editableBoolHovered || groupHeaderHovered - ? "pointer" - : "default"; + ? "col-resize" + : overFill || isFilling + ? "crosshair" + : cursorOverride !== undefined + ? cursorOverride + : headerHovered || clickableInnerCellHovered || editableBoolHovered || groupHeaderHovered + ? "pointer" + : "default"; const style = React.useMemo( () => ({ // width, @@ -991,9 +991,9 @@ const DataGrid: React.ForwardRefRenderFunction = (p, clientY: number ): | { - area: "menu" | "indicator"; - bounds: Rectangle; - } + area: "menu" | "indicator"; + bounds: Rectangle; + } | undefined => { const header = mappedColumns[col]; diff --git a/packages/core/src/internal/scrolling-data-grid/scrolling-data-grid.tsx b/packages/core/src/internal/scrolling-data-grid/scrolling-data-grid.tsx index 2fb5eac25..f3fabb0d9 100644 --- a/packages/core/src/internal/scrolling-data-grid/scrolling-data-grid.tsx +++ b/packages/core/src/internal/scrolling-data-grid/scrolling-data-grid.tsx @@ -8,15 +8,15 @@ type Props = Omit; export interface ScrollingDataGridProps extends Props { readonly className: string | undefined; readonly onVisibleRegionChanged: - | (( - range: Rectangle, - clientWidth: number, - clientHeight: number, - rightElWidth: number, - tx: number, - ty: number - ) => void) - | undefined; + | (( + range: Rectangle, + clientWidth: number, + clientHeight: number, + rightElWidth: number, + tx: number, + ty: number + ) => void) + | undefined; readonly scrollRef: React.MutableRefObject | undefined; /** @@ -54,11 +54,11 @@ export interface ScrollingDataGridProps extends Props { * @group Advanced */ readonly rightElementProps: - | { - readonly sticky?: boolean; - readonly fill?: boolean; - } - | undefined; + | { + readonly sticky?: boolean; + readonly fill?: boolean; + } + | undefined; /** * The right element is a DOM node which can be inserted at the end of the horizontal scroll region. This can be * used to create a right handle panel, make a big add button, or display messages. From 195d658f4e90512cd62a2099a9240c34a1ea350f Mon Sep 17 00:00:00 2001 From: kcvikander Date: Mon, 8 Apr 2024 13:39:44 -0500 Subject: [PATCH 4/4] cleanup --- packages/core/src/data-editor/data-editor.tsx | 14 ++++---- .../core/src/internal/data-grid/data-grid.tsx | 32 +++++++++---------- .../scrolling-data-grid.tsx | 20 ++++++------ 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/packages/core/src/data-editor/data-editor.tsx b/packages/core/src/data-editor/data-editor.tsx index abb977c87..9d0ccdab6 100644 --- a/packages/core/src/data-editor/data-editor.tsx +++ b/packages/core/src/data-editor/data-editor.tsx @@ -191,7 +191,7 @@ function shiftSelection(input: GridSelection, offset: number): GridSelection { ...r, x: r.x + offset, })), - }, + }, rows: input.rows, columns: input.columns.offset(offset), }; @@ -1188,7 +1188,7 @@ const DataEditorImpl: React.ForwardRefRenderFunction 1 + gridSelection.current.range.width * gridSelection.current.range.height > 1 ? gridSelection.current.range : undefined; @@ -2470,11 +2470,11 @@ const DataEditorImpl: React.ForwardRefRenderFunction void) + range: Rectangle, + clientWidth: number, + clientHeight: number, + rightElWidth: number, + tx: number, + ty: number + ) => void) | undefined; readonly scrollRef: React.MutableRefObject | undefined; @@ -55,9 +55,9 @@ export interface ScrollingDataGridProps extends Props { */ readonly rightElementProps: | { - readonly sticky?: boolean; - readonly fill?: boolean; - } + readonly sticky?: boolean; + readonly fill?: boolean; + } | undefined; /** * The right element is a DOM node which can be inserted at the end of the horizontal scroll region. This can be