@velox/drag-drop
Draggable + DropZone built on native drag events. Drop targets are matched by
hit-testing the pointer against each zone's live layout rect at drop time.
Install
npm install @velox/drag-dropUsage
import { Draggable, DropZone } from '@velox/drag-drop'
<Draggable data={card} type="card">
<Card />
</Draggable>
<DropZone accepts="card" onDrop={(card) => moveTo(column, card)}>
<Column />
</DropZone>Kanban board example
function KanbanBoard() {
const [columns, setColumns] = useState({
todo: [{ id: 1, title: 'Design mockup' }],
doing: [{ id: 2, title: 'Build API' }],
done: [],
})
const move = (card, toColumn) => {
setColumns(prev => {
const next = { ...prev }
for (const col of Object.keys(next)) {
next[col] = next[col].filter(c => c.id !== card.id)
}
next[toColumn] = [...next[toColumn], card]
return next
})
}
return (
<View style={{ flexDirection: 'row', gap: 16 }}>
{Object.entries(columns).map(([col, cards]) => (
<DropZone key={col} accepts="card" onDrop={(card) => move(card, col)}
style={{ flex: 1, minHeight: 200, padding: 12,
backgroundColor: '#1e2235', borderRadius: 8 }}>
<Text style={{ fontWeight: '600', marginBottom: 8 }}>{col.toUpperCase()}</Text>
{cards.map(card => (
<Draggable key={card.id} data={card} type="card">
<View style={{ padding: 10, backgroundColor: '#262b3f',
borderRadius: 6, marginBottom: 8 }}>
<Text>{card.title}</Text>
</View>
</Draggable>
))}
</DropZone>
))}
</View>
)
}useDraggable hook
For custom drag interactions that don't fit the Draggable / DropZone pattern,
use useDraggable directly from @velox/react:
import { useDraggable } from 'veloxkit'
const dragHandlers = useDraggable({
onDragStart: (x, y) => { /* pointer down + moved past threshold */ },
onDragMove: (dx, dy) => { /* called each frame while dragging */ },
onDragEnd: (x, y) => { /* pointer released */ },
})
// Attach to any View or Pressable:
<View {...dragHandlers}>
<Text>Drag me</Text>
</View>Resizable panel example
function ResizablePanel({ children }) {
const [width, setWidth] = useState(300)
const startW = useRef(300)
const dragHandlers = useDraggable({
onDragStart: () => { startW.current = width },
onDragMove: (dx) => setWidth(Math.max(120, startW.current + dx)),
})
return (
<View style={{ flexDirection: 'row' }}>
<View style={{ width }}>{children}</View>
<View {...dragHandlers}
style={{ width: 4, backgroundColor: '#3c4464', cursor: 'col-resize' }} />
</View>
)
}