Back to Dnd Kit

Plugins

apps/docs/extend/plugins.mdx

latest4.6 KB
Original Source

Overview

Plugins are a powerful way to extend the core functionality of @dnd-kit. They can be used to add new features, modify existing behavior, or react to drag and drop operations.

Built-in Plugins

Several plugins are included by default when creating a new DragDropManager:

<CardGroup cols={2}> <Card title="Accessibility" icon="universal-access" href="./plugins/accessibility" > Manages ARIA attributes and screen reader announcements for drag and drop operations. </Card> <Card title="AutoScroller" icon="arrows-up-down" href="./plugins/auto-scroller" > Automatically scrolls containers when dragging near edges. </Card> <Card title="Cursor" icon="arrow-pointer" href="./plugins/cursor" > Updates cursor styles during drag operations. </Card> <Card title="Debug" icon="bug" href="./plugins/debug" > Visualize drag shapes, droppable zones, and collisions for debugging. </Card> <Card title="Feedback" icon="eye" href="./plugins/feedback" > Manages visual feedback during dragging, including top layer promotion and drop animations. </Card> <Card title="StyleInjector" icon="palette" href="./plugins/style-injector" > Centralized style injection with CSP nonce support. </Card> </CardGroup>

Using Plugins

The plugins option accepts either an array or a function that receives the default plugins.

Extending defaults

Use the function form to add plugins to the defaults or configure existing ones, without replacing them:

ts
import {DragDropManager} from '@dnd-kit/dom';

const manager = new DragDropManager({
  plugins: (defaults) => [...defaults, MyPlugin],
});
ts
import {DragDropManager, Feedback} from '@dnd-kit/dom';

const manager = new DragDropManager({
  plugins: (defaults) => [
    ...defaults,
    Feedback.configure({ dropAnimation: null }),
  ],
});

Replacing defaults

Pass an array to fully replace the default plugins:

ts
const manager = new DragDropManager({
  plugins: [
    MyPlugin.configure({ delay: 500 }),
    AutoScroller,
  ]
});

Creating a Plugin

To create a custom plugin, extend the Plugin class:

ts
import {Plugin} from '@dnd-kit/abstract';

interface MyPluginOptions {
  delay?: number;
}

class MyPlugin extends Plugin {
  constructor(manager, options?: MyPluginOptions) {
    super(manager, options);

    this.registerEffect(() => {
      const {monitor} = this.manager;

      const cleanup = monitor.addEventListener('dragstart', (event) => {
        console.log('Drag started:', event.operation.source.id);
      });

      return cleanup;
    });
  }

  public customMethod() {
    if (this.disabled) return;
    // Custom functionality
  }
}

Plugin Lifecycle

  1. Construction: Plugin instance created with manager reference
  2. Configuration: Options applied if provided
  3. Registration: Plugin registered with manager
  4. Operation: Plugin effects are run
  5. Cleanup: Plugin destroyed when manager is destroyed

API Reference

Plugin Class

The base class for all plugins:

<ParamField path="manager" type="DragDropManager" required> Reference to the drag and drop manager instance. </ParamField> <ParamField path="options" type="PluginOptions"> Optional configuration options for the plugin. </ParamField>

Properties

  • disabled: Whether the plugin is currently disabled
  • options: Current plugin options

Methods

  • enable(): Enable the plugin
  • disable(): Disable the plugin
  • isDisabled(): Check if plugin is disabled
  • configure(options): Update plugin options
  • destroy(): Clean up plugin resources
  • registerEffect(callback): Register a reactive effect

Static Methods

  • configure(options): Create a configured plugin descriptor
ts
const configuredPlugin = MyPlugin.configure({
  delay: 500
});

const manager = new DragDropManager({
  plugins: [configuredPlugin]
});

Effects

Plugins can register effects that automatically clean up:

ts
class MyPlugin extends Plugin {
  constructor(manager) {
    super(manager);

    this.registerEffect(() => {
      const interval = setInterval(() => {
        // Do something periodically
      }, 100);

      return () => clearInterval(interval);
    });
  }
}

Best Practices

  1. Clean Up Resources: Always clean up listeners and timers in the destroy method
  2. Check Disabled State: Check this.disabled before performing operations
  3. Use Type Safety: Leverage TypeScript for better type checking
  4. Document Options: Clearly document all available options
  5. Follow Patterns: Study built-in plugins for patterns and conventions