Package Exports
- @neodrag/react
- @neodrag/react/package.json
Readme
@neodrag/react
One draggable to rule em all
A lightweight React hook to make your elements draggable.
Features
- 🤏 Small in size - ~5KB, plugin architecture enables tree-shaking
- 🧩 Plugin-based - Mix and match only what you need
- ⚡ Performance - Event delegation, pointer capture, optimized for modern browsers
- 🎯 React Native - Built for React hooks with
useDraggable
- 🔄 Reactive -
useCompartment
for reactive plugin updates
Installing
npm install @neodrag/react@next
Usage
Basic usage
import { useRef } from 'react';
import { useDraggable } from '@neodrag/react';
function App() {
const draggableRef = useRef<HTMLDivElement>(null);
useDraggable(draggableRef);
return <div ref={draggableRef}>Hello</div>;
}
With plugins
import { useRef } from 'react';
import { useDraggable, axis, grid } from '@neodrag/react';
function App() {
const draggableRef = useRef<HTMLDivElement>(null);
useDraggable(draggableRef, [axis('x'), grid([10, 10])]);
return <div ref={draggableRef}>Hello</div>;
}
Defining plugins elsewhere with TypeScript
import { useRef } from 'react';
import { useDraggable, axis, bounds, BoundsFrom, type Plugin } from '@neodrag/react';
function App() {
const draggableRef = useRef<HTMLDivElement>(null);
const plugins: Plugin[] = [axis('y'), bounds(BoundsFrom.parent())];
useDraggable(draggableRef, plugins);
return <div ref={draggableRef}>Hello</div>;
}
Getting drag state
import { useRef, useEffect } from 'react';
import { useDraggable } from '@neodrag/react';
function App() {
const draggableRef = useRef<HTMLDivElement>(null);
const dragState = useDraggable(draggableRef);
useEffect(() => {
console.log('Position:', dragState.offset);
console.log('Is dragging:', dragState.isDragging);
}, [dragState]);
return <div ref={draggableRef}>Hello</div>;
}
Reactive plugins with useCompartment
import { useRef, useState } from 'react';
import { useDraggable, axis, useCompartment } from '@neodrag/react';
function App() {
const elementRef = useRef<HTMLDivElement>(null);
const [currentAxis, setCurrentAxis] = useState<'x' | 'y'>('x');
const axisCompartment = useCompartment(() => axis(currentAxis), [currentAxis]);
useDraggable(elementRef, () => [axisCompartment]);
return (
<div>
<div ref={elementRef}>Current axis: {currentAxis}</div>
<button onClick={() => setCurrentAxis(currentAxis === 'x' ? 'y' : 'x')}>Switch Axis</button>
</div>
);
}
Credits
Inspired by react-draggable, but with a modern plugin architecture and optimized for performance.
License
MIT License © Puru Vijay