CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-dnd-html5-backend

HTML5 drag and drop backend for React DnD, enabling sophisticated drag-and-drop interactions using the native HTML5 Drag and Drop API

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

drag-preview-utils.mddocs/

Drag Preview Utilities

Utilities for customizing drag preview behavior, specifically the creation of transparent images to hide the default browser drag preview and enable custom drag preview implementations.

Capabilities

Empty Image Creation

Create a transparent 1x1 pixel image for hiding the default browser drag preview, allowing for custom drag preview implementations.

/**
 * Returns a transparent 1x1 pixel image for drag preview customization
 * The image is cached and reused across calls for performance
 * @returns HTMLImageElement with transparent GIF data
 */
function getEmptyImage(): HTMLImageElement;

Usage Examples:

import { useDragPreview } from "react-dnd";
import { getEmptyImage } from "react-dnd-html5-backend";
import { useEffect } from "react";

// Hide default drag preview to show custom preview
function DragSourceWithCustomPreview() {
  const [, drag, preview] = useDrag({
    type: "ITEM",
    item: { id: "123", name: "Custom Item" },
  });

  // Hide the default browser drag preview
  useEffect(() => {
    preview(getEmptyImage(), { captureDraggingState: true });
  }, [preview]);

  return (
    <div ref={drag} style={{ cursor: "move" }}>
      Drag me (custom preview will show)
    </div>
  );
}

// Connect empty image immediately
function SimpleCustomPreview() {
  const [, drag, preview] = useDrag({
    type: "ITEM",
    item: { id: "456" },
  });

  // Connect empty image to hide default preview
  const emptyImage = getEmptyImage();
  preview(emptyImage);

  return <div ref={drag}>Drag with no default preview</div>;
}

// Use with custom drag layer for complete control
function CustomDragLayer() {
  const [, drag, preview] = useDrag({
    type: "CUSTOM_ITEM",
    item: { id: "custom" },
  });

  // Hide native preview and use custom drag layer
  useEffect(() => {
    preview(getEmptyImage(), { captureDraggingState: true });
  }, [preview]);

  return <div ref={drag}>Drag with custom layer</div>;
}

Preview Positioning Options

When using getEmptyImage() with React DnD's preview connection, you can provide positioning options:

interface DragPreviewOptions {
  /** Horizontal anchor point (0 = left edge, 0.5 = center, 1 = right edge) */
  anchorX?: number;
  /** Vertical anchor point (0 = top edge, 0.5 = center, 1 = bottom edge) */
  anchorY?: number;
  /** Manual horizontal offset in pixels (overrides anchor-based positioning) */
  offsetX?: number;
  /** Manual vertical offset in pixels (overrides anchor-based positioning) */
  offsetY?: number;
  /** Whether to capture the dragging state for the preview */
  captureDraggingState?: boolean;
}

Usage Examples:

import { useDrag } from "react-dnd";
import { getEmptyImage } from "react-dnd-html5-backend";

// Different anchor point configurations
function AnchorPointExamples() {
  const [, drag1, preview1] = useDrag({ type: "TOP_LEFT", item: {} });
  const [, drag2, preview2] = useDrag({ type: "CENTER", item: {} });
  const [, drag3, preview3] = useDrag({ type: "BOTTOM_RIGHT", item: {} });

  // Top-left anchored preview
  preview1(getEmptyImage(), { anchorX: 0, anchorY: 0 });
  
  // Center anchored preview  
  preview2(getEmptyImage(), { anchorX: 0.5, anchorY: 0.5 });
  
  // Bottom-right anchored preview
  preview3(getEmptyImage(), { anchorX: 1, anchorY: 1 });

  return (
    <div>
      <div ref={drag1}>Top-Left Anchor</div>
      <div ref={drag2}>Center Anchor</div>
      <div ref={drag3}>Bottom-Right Anchor</div>
    </div>
  );
}

// Manual offset positioning
function ManualOffsetExample() {
  const [, drag, preview] = useDrag({
    type: "MANUAL_OFFSET",
    item: { id: "manual" },
  });

  // Position preview 20px right and 10px down from cursor
  preview(getEmptyImage(), {
    offsetX: 20,
    offsetY: 10,
    captureDraggingState: true,
  });

  return <div ref={drag}>Drag with manual offset</div>;
}

// Capture dragging state for custom drag layers
function DragStateCapture() {
  const [, drag, preview] = useDrag({
    type: "STATE_CAPTURE",
    item: { id: "state" },
  });

  // Enable dragging state capture for custom drag layer integration
  preview(getEmptyImage(), {
    captureDraggingState: true,
  });

  return <div ref={drag}>Drag with state capture</div>;
}

Implementation Details

  • The getEmptyImage() function returns a cached HTMLImageElement containing a transparent 1x1 pixel GIF
  • The same image instance is reused across multiple calls for optimal performance
  • The transparent image effectively hides the browser's default drag preview
  • Most commonly used in conjunction with custom drag layers for complete visual control
  • Compatible with all positioning options supported by React DnD's preview connections

Install with Tessl CLI

npx tessl i tessl/npm-react-dnd-html5-backend

docs

backend-factory.md

drag-preview-utils.md

index.md

native-drag-sources.md

tile.json