Sensors are used to detect different input methods in order to initiate drag operations, respond to movement and end or cancel the operation.
Built-in sensors
The @dnd-kit/dom
package provides a set of built-in sensors that can be used to detect user input in the browser.
Usage
Sensors can be applied globally or to individual draggable elements.
The Pointer sensor and Keyboard sensor are enabled by default.
Global sensors
Sensors can be applied globally by passing them to the DragDropManager instance.
For example, if you wanted to only enable the Pointer sensor:
import {DragDropManager} from '@dnd-kit/dom';
import {PointerSensor} from '@dnd-kit/dom/sensors';
function App() {
const manager = new DragDropManager({
sensors: [PointerSensor],
});
}
Local sensors
Sensors can also be applied to individual draggable elements by passing them to the modifiers option.
For example, if you wanted to only enable the KeyboardSensor for this specific draggable element, while using the PointerSensor
globally for all other draggable elements:
import {Draggable} from '@dnd-kit/dom';
import {PointerSensor, KeyboardSensor} from '@dnd-kit/dom/sensors';
function App() {
const manager = new DragDropManager({
sensors: [PointerSensor],
});
const draggable = new Draggable({
id: 'draggable',
sensors: [KeyboardSensor],
}, manager);
}
Local sensors take precedence over global sensors.
Custom sensors
You can also create custom sensors to detect input from other input sources, or extend the built-in sensors to add additional functionality on top of them.
To do so, you can create a new sensor by extending the Sensor
class and implementing the required methods.
import {Sensor} from '@dnd-kit/abstract';
import {effect} from '@dnd-kit/state';
class CustomPointerSensor extends Sensor {
constructor(manager) {
super(manager);
document.addEventListener('pointermove', this.handlePointerMove);
document.addEventListener('pointerup', this.handlePointerUp);
this.destroy = () => {
document.removeEventListener('pointermove', this.handlePointerMove);
document.removeEventListener('pointerup', this.handlePointerUp);
};
}
public bind(source) {
const unbind = effect(() => {
const target = source.handle ?? source.element;
const listener = (event) => {
this.handlePointerDown(event, source);
};
if (target) {
target.addEventListener('pointerdown', listener);
return () => {
target.removeEventListener('pointerdown', listener);
};
}
});
return unbind;
}
handlePointerDown = (event, source) => {
const coordinates = {x: event.clientX, y: event.clientY};
manager.actions.setDragSource(source.id);
manager.actions.start({coordinates, event});
}
handlePointerMove = (event) => {
if (!manager.dragOperation.status.initialized) return;
const coordinates = {x: event.clientX, y: event.clientY};
this.manager.actions.move({to: coordinates});
}
handlePointerUp = (event) => {
if (!manager.dragOperation.status.initialized) return;
this.manager.actions.stop();
}
}