or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

context-provider.mddrag-layer.mddrag-sources.mddrop-targets.mdindex.mdutilities.md
tile.json

tessl/npm-react-dnd

Drag and Drop for React applications with hooks-based API and TypeScript support

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/react-dnd@16.0.x

To install, run

npx @tessl/cli install tessl/npm-react-dnd@16.0.0

index.mddocs/

React DnD

React DnD is a comprehensive drag and drop library for React applications that provides a declarative approach to complex drag and drop interactions. Built with TypeScript, this library offers a flexible API through React hooks (useDrag, useDrop, useDragLayer) that enable developers to create sophisticated drag and drop interfaces with minimal boilerplate code.

Package Information

  • Package Name: react-dnd
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install react-dnd

Core Imports

import { DndProvider, useDrag, useDrop, useDragLayer, DndContext, useDragDropManager } from "react-dnd";

For CommonJS:

const { DndProvider, useDrag, useDrop, useDragLayer, DndContext, useDragDropManager } = require("react-dnd");

Basic Usage

import React from "react";
import { DndProvider, useDrag, useDrop } from "react-dnd";
// Note: Backend is a separate package
import { HTML5Backend } from "react-dnd-html5-backend";

// Wrap your app with DndProvider
function App() {
  return (
    <DndProvider backend={HTML5Backend}>
      <DragDropExample />
    </DndProvider>
  );
}

// Create a draggable item
function DraggableItem({ id, text }) {
  const [{ isDragging }, drag] = useDrag({
    type: "item",
    item: { id, text },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  });

  return (
    <div ref={drag} style={{ opacity: isDragging ? 0.5 : 1 }}>
      {text}
    </div>
  );
}

// Create a drop target
function DropTarget() {
  const [{ isOver }, drop] = useDrop({
    accept: "item",
    drop: (item) => console.log("Dropped:", item),
    collect: (monitor) => ({
      isOver: monitor.isOver(),
    }),
  });

  return (
    <div ref={drop} style={{ backgroundColor: isOver ? "lightblue" : "white" }}>
      Drop items here
    </div>
  );
}

Architecture

React DnD is built around several key components:

  • Context System: DndProvider and DndContext manage the drag and drop state across the component tree
  • Hook-based API: Core hooks (useDrag, useDrop, useDragLayer) provide declarative drag and drop functionality
  • Monitor System: Provides real-time information about drag and drop operations
  • Connector System: Connects React components to DOM elements for drag and drop interactions
  • Backend Integration: Pluggable backend system supporting HTML5 drag and drop, touch, and testing backends

Capabilities

Context and Provider

Core context and provider components for setting up React DnD in your application.

function DndProvider<BackendContext, BackendOptions>(
  props: DndProviderProps<BackendContext, BackendOptions>
): React.ReactElement;

type DndProviderProps<BackendContext, BackendOptions> =
  | {
      children?: React.ReactNode;
      manager: DragDropManager;
    }
  | {
      backend: BackendFactory;
      children?: React.ReactNode;
      context?: BackendContext;
      options?: BackendOptions;
      debugMode?: boolean;
    };

Context and Provider

Drag Source Hook

Hook for making components draggable with comprehensive configuration options.

function useDrag<DragObject = unknown, DropResult = unknown, CollectedProps = unknown>(
  specArg: FactoryOrInstance<DragSourceHookSpec<DragObject, DropResult, CollectedProps>>,
  deps?: unknown[]
): [CollectedProps, ConnectDragSource, ConnectDragPreview];

interface DragSourceHookSpec<DragObject, DropResult, CollectedProps> {
  type: SourceType;
  item?: DragObject | DragObjectFactory<DragObject>;
  options?: DragSourceOptions;
  previewOptions?: DragPreviewOptions;
  end?: (draggedItem: DragObject, monitor: DragSourceMonitor<DragObject, DropResult>) => void;
  canDrag?: boolean | ((monitor: DragSourceMonitor<DragObject, DropResult>) => boolean);
  isDragging?: (monitor: DragSourceMonitor<DragObject, DropResult>) => boolean;
  collect?: (monitor: DragSourceMonitor<DragObject, DropResult>) => CollectedProps;
}

Drag Sources

Drop Target Hook

Hook for making components accept dropped items with flexible handling options.

function useDrop<DragObject = unknown, DropResult = unknown, CollectedProps = unknown>(
  specArg: FactoryOrInstance<DropTargetHookSpec<DragObject, DropResult, CollectedProps>>,
  deps?: unknown[]
): [CollectedProps, ConnectDropTarget];

interface DropTargetHookSpec<DragObject, DropResult, CollectedProps> {
  accept: TargetType;
  options?: DropTargetOptions;
  drop?: (item: DragObject, monitor: DropTargetMonitor<DragObject, DropResult>) => DropResult | undefined;
  hover?: (item: DragObject, monitor: DropTargetMonitor<DragObject, DropResult>) => void;
  canDrop?: (item: DragObject, monitor: DropTargetMonitor<DragObject, DropResult>) => boolean;
  collect?: (monitor: DropTargetMonitor<DragObject, DropResult>) => CollectedProps;
}

Drop Targets

Drag Layer Hook

Hook for creating custom drag previews and accessing global drag state.

function useDragLayer<CollectedProps, DragObject = any>(
  collect: (monitor: DragLayerMonitor<DragObject>) => CollectedProps
): CollectedProps;

Drag Layer

Drag Drop Manager Hook

Low-level hook for accessing the DragDropManager instance directly for advanced use cases.

function useDragDropManager(): DragDropManager;

Context and Provider

Utility Components

Utility components for advanced drag and drop scenarios.

function DragPreviewImage(props: DragPreviewImageProps): React.ReactElement;

interface DragPreviewImageProps {
  connect: ConnectDragPreview;
  src: string;
}

Utilities

Types

Core Types

// Core identifiers and types (from dnd-core)
type Identifier = string | symbol;
type SourceType = string | symbol;
type TargetType = string | symbol | string[] | symbol[];

// Drag and drop managers and contexts
interface DndContextType {
  dragDropManager: DragDropManager | undefined;
}

interface DragDropManager {
  getMonitor(): DragDropMonitor;
  getBackend(): Backend;
  getRegistry(): HandlerRegistry;
  dispatch(action: any): void;
}

interface HandlerManager {
  receiveHandlerId(handlerId: Identifier | null): void;
  getHandlerId(): Identifier | null;
}

interface MonitorEventEmitter {
  subscribeToStateChange(
    fn: () => void,
    options?: { handlerIds?: Identifier[] }
  ): Unsubscribe;
}

type Unsubscribe = () => void;
type BackendFactory<BackendContext = any, BackendOptions = any> = (
  manager: DragDropManager,
  context?: BackendContext,
  options?: BackendOptions
) => Backend;

interface Backend {
  setup(): void;
  teardown(): void;
  connectDragSource(sourceId: any, node: any, options: any): () => void;
  connectDragPreview(sourceId: any, node: any, options: any): () => void;
  connectDropTarget(targetId: any, node: any, options: any): () => void;
}

interface HandlerRegistry {
  addSource(type: string, source: any): Identifier;
  addTarget(type: string, target: any): Identifier;
  removeSource(sourceId: Identifier): void;
  removeTarget(targetId: Identifier): void;
  getSource(sourceId: Identifier, includePinned?: boolean): any;
  getTarget(targetId: Identifier, includePinned?: boolean): any;
  getSourceType(sourceId: Identifier): string | null;
  getTargetType(targetId: Identifier): string | null;
  isPinned(handlerId: Identifier): boolean;
  pin(handlerId: Identifier): void;
  unpin(handlerId: Identifier): void;
}

interface DragDropMonitor extends DragSourceMonitor, DropTargetMonitor, DragLayerMonitor {
  // Additional methods specific to the combined monitor
}

// Connector functions
type ConnectDragSource = DragElementWrapper<DragSourceOptions>;
type ConnectDropTarget = DragElementWrapper<any>;
type ConnectDragPreview = DragElementWrapper<DragPreviewOptions>;
type ConnectableElement = React.RefObject<any> | React.ReactElement | Element | null;

// Utility types
type FactoryOrInstance<T> = T | (() => T);
type DragObjectFactory<T> = (monitor: DragSourceMonitor<T>) => T | null;

// Coordinate system
interface XYCoord {
  x: number;
  y: number;
}

Monitor Interfaces

interface DragSourceMonitor<DragObject = unknown, DropResult = unknown> extends HandlerManager, MonitorEventEmitter {
  canDrag(): boolean;
  isDragging(): boolean;
  getItemType(): Identifier | null;
  getItem<T = DragObject>(): T;
  getDropResult<T = DropResult>(): T | null;
  didDrop(): boolean;
  getInitialClientOffset(): XYCoord | null;
  getInitialSourceClientOffset(): XYCoord | null;
  getClientOffset(): XYCoord | null;
  getDifferenceFromInitialOffset(): XYCoord | null;
  getSourceClientOffset(): XYCoord | null;
  getTargetIds(): Identifier[];
}

interface DropTargetMonitor<DragObject = unknown, DropResult = unknown> extends HandlerManager, MonitorEventEmitter {
  canDrop(): boolean;
  isOver(options?: { shallow?: boolean }): boolean;
  getItemType(): Identifier | null;
  getItem<T = DragObject>(): T;
  getDropResult<T = DropResult>(): T | null;
  didDrop(): boolean;
  getInitialClientOffset(): XYCoord | null;
  getInitialSourceClientOffset(): XYCoord | null;
  getClientOffset(): XYCoord | null;
  getDifferenceFromInitialOffset(): XYCoord | null;
  getSourceClientOffset(): XYCoord | null;
}

interface DragLayerMonitor<DragObject = unknown> {
  isDragging(): boolean;
  getItemType(): Identifier | null;
  getItem<T = DragObject>(): T;
  getInitialClientOffset(): XYCoord | null;
  getInitialSourceClientOffset(): XYCoord | null;
  getClientOffset(): XYCoord | null;
  getDifferenceFromInitialOffset(): XYCoord | null;
  getSourceClientOffset(): XYCoord | null;
}

Option Interfaces

interface DragSourceOptions {
  dropEffect?: string;
}

interface DragPreviewOptions {
  captureDraggingState?: boolean;
  anchorX?: number;
  anchorY?: number;
  offsetX?: number;
  offsetY?: number;
}

type DropTargetOptions = any;