@arcturus3/react-drag-drop
v1.0.1
Published
Simple, flexible components and hooks for drag and drop in React.
Downloads
10
Maintainers
Readme
React Drag and Drop
Simple, flexible components and hooks for drag and drop in React.
Installation
npm i @arcturus3/react-drag-drop
Examples
This library provides both components and hooks for drag and drop. The components encapsulate some common functionality and may be useful in simple cases or in addition to the hooks. If you need more control over drag and drop it should be fairly simple to implement this functionality yourself using the hooks. Following are two similar examples using each.
Components
import React from 'react';
import {Drag, Drop, DragView} from '@arcturus3/react-drag-drop';
export const Components = () => <>
<DragView onDrop={() => alert('dropped')} />
<Drag previewChildren>drag</Drag>
<br />
<Drop>drop</Drop>
</>;
Hooks
import React from 'react';
import {useDrag, useDrop, useDragDrop} from '@arcturus3/react-drag-drop';
export const Hooks = () => {
const dragRef = useDrag();
const dropRef = useDrop();
const state = useDragDrop({
onDrop: () => alert('dropped')
});
const dragStyle = {
display: 'inline-block',
transform: state.dragging
? `translate(
${state.displacement!.x}px,
${state.displacement!.y}px
)`
: undefined
};
return <>
<span ref={dragRef} style={dragStyle}>drag</span>
<br />
<span ref={dropRef}>drop</span>
</>;
};
Alternatives
React DnD
I think React DnD is based on some good ideas, but I wasn't a fan of its API, and the default HTML5 "backend" for mouse drag and drop comes with some of the limitations of native HTML5 drag and drop. I experienced performance issues with the only third party backend I could find. On the other hand, you may want to use React DnD if you need to support drag and drop with external types like files, links, and selected text.
React UseGesture
React UseGesture does not support drag and drop, but you may want to use it if you only need to support dragging elements and not interacting with drop elements. You could also use it for animating dragging while using this library to handle the drag and drop state.
Documentation
<Drag />
import {Drag} from '@arcturus3/react-drag-drop';
A component that wraps its children with a drag element and prevents browser touch actions from interfering with dragging. Use with <DragView />
to display a drag preview and set the cursor style when hovering. It accepts the following props in addition to children.
previewChildren?: boolean
(default:false
): Whether to use children as the drag preview for<DragView />
. Setting totrue
modifiespayload
such that the value passed to thepayload
prop is stored inpayload.data
and the children are stored inpayload.preview
for use by<DragView />
.payload?: any
(default:undefined
): SeeDragConfig
.disabled?: boolean
(default:false
): SeeDragConfig
.deps?: DependencyList
(default:[]
): SeeDragConfig
.
<Drop />
import {Drop} from '@arcturus3/react-drag-drop';
A component that wraps its children with a drop element. It accepts the following props in addition to children.
payload?: any
(default:undefined
): SeeDropConfig
.disabled?: boolean
(default:false
): SeeDropConfig
.deps?: DependencyList
(default:[]
): SeeDropConfig
.
<DragView />
import {DragView} from '@arcturus3/react-drag-drop';
A component that displays a preview of the element being dragged based on its payload and disables text selection while dragging. It's recommended to render this at the top of the component hierarchy so that it is always mounted. It accepts the following props.
preview?: (payload: any) => ReactNode
(default: usespayload.preview
if defined, which is set automatically ifpreviewChildren={true}
on<Drag />
components): Takes a drag payload and returns the preview to render. The preview could be calculated from the payload data or stored directly in the payload.hoverCursor?: string
(default:''
): Thecursor
style to use while hovering over a<Drag />
component before dragging starts.dragCursor?: string
(default:''
): Thecursor
style to use while dragging.onDragStart?: Handler
: SeeDragDropConfig
.onDragMove?: Handler
: SeeDragDropConfig
.onDragEnd?: Handler
: SeeDragDropConfig
.onHoverStart?: Handler
: SeeDragDropConfig
.onHoverEnd?: Handler
: SeeDragDropConfig
.onDrop?: Handler
: SeeDragDropConfig
.onAny?: Handler
: SeeDragDropConfig
.deps?: DependencyList
(default:[]
): SeeDragDropConfig
.
useDrag<T extends HTMLElement>(config)
import {useDrag} from '@arcturus3/react-drag-drop';
Make a drag element.
config: DragConfig
(default:{}
): Configuration for the drag element. Note that ifconfig
may change when the component using this hook rerenders,config.deps
should be specified. Additionally, updates toconfig
will only be reflected inDragDropState
once the next drag and drop event occurs.return: RefCallback<T>
: A ref to assign to the element that should be draggable.
useDrop<T extends HTMLElement>(config)
import {useDrop} from '@arcturus3/react-drag-drop';
Make a drop element.
config: DropConfig
(default:{}
): Configuration for the drop element. Note that ifconfig
may change when the component using this hook rerenders,config.deps
should be specified. Additionally, updates toconfig
will only be reflected inDragDropState
once the next drag and drop event occurs.return: RefCallback<T>
: A ref to assign to the element that should accept drag elements.
useDragDrop(config)
import {useDragDrop} from '@arcturus3/react-drag-drop';
Get the drag and drop state and handle events.
config: DragDropConfig
(default:{}
): Configuration for state and event handlers.return: DragDropState
: The drag and drop state, updated according toconfig.stateProps
andrequestAnimationFrame
.
DragConfig
Configuration object for drag elements with the following properties.
payload?: any
(default:undefined
): Data describing the drag element.disabled?: boolean
(default:false
): Whether to allow dragging the element. If set tofalse
while dragging the element, this only takes effect once dragging ends normally.deps?: DependencyList
(default:[]
): Array containing the values of any variables that other properties ofDragConfig
depend upon. Used in the same manner as theuseEffect
dependency list.
DropConfig
Configuration object for drop elements with the following properties.
payload?: any
(default:undefined
): Data describing the drop element.disabled?: boolean
(default:false
): Whether to allow dropping and hovering on the element.deps?: DependencyList
(default:[]
): Array containing the values of any variables that other properties ofDropConfig
depend upon. Used in the same manner as theuseEffect
dependency list.
DragDropConfig
Configuration object for state and event handlers with the following properties.
onDragStart?: Handler
: Pointer activates on a drag element.onDragMove?: Handler
: Pointer moves after dragging has started.onDragEnd?: Handler
: Pointer deactivates after dragging has started.onHoverStart?: Handler
: Dragging is in progress and pointer moves over a drop element.onHoverEnd?: Handler
: Dragging is in progress and pointer moves off a drop element.onDrop?: Handler
: Dragging is in progress and pointer deactivates over a drop element.onAny?: Handler
: Called on any of the other events inDragDropConfig
.stateProps?: (keyof DragDropState)[]
(default: array of allDragDropState
properties): Changes to theDragDropState
returned byuseDragDrop
will only cause a component to rerender if one of the properties in this array changes. If set, the array should contain all properties ofDragDropState
that are used in the component, and serves as a performance optimization by ignoring those that aren't.deps?: DependencyList
(default:[]
): Array containing the values of any variables that other properties ofDragDropConfig
depend upon. Used in the same manner as theuseEffect
dependency list.
Handler: (state, prevState) => void
Drag and drop event handler passed to DragDropConfig
.
state: DragDropState
: The drag and drop state after this event occurs. Note that foronDragEnd
andonDrop
in particular, this will be the initial state where nothing is being dragged, andprevState
may be more useful.prevState: DragDropState
: The drag and drop state before this event occurred.
DragDropState
Object containing the following properties.
dragging: boolean
: Whether an element is being dragged.hovering: boolean
: Whether the pointer is hovering a droppable element while dragging.dragPayload: any
: Payload of the item being dragged orundefined
if not dragging.dropPayload: any
: Payload of the item being hovered orundefined
if not dragginginitialPointerPosition: Point | null
:pointerPosition
when dragging started ornull
if not dragging.pointerPosition: Point | null
: Position of the pointer relative to the viewport ornull
if not dragging. Addwindow.scrollX
andwindow.scrollY
to get the position relative to the document.initialElementPosition: Point | null
:elementPosition
when dragging started ornull
if not dragging.elementPosition: Point | null
:initialElementPosition
plusdisplacement
ornull
if not dragging.displacement: Point | null
: Displacement betweeninitialPointerPosition
andpointerPosition
ornull
if not dragging.
Point
Object containing the following properties.
x: number
: Horizontal coordinate of a position relative to the viewport.y: number
: Vertical coordinate of a position relative to the viewport.