@illusionalsagacity/rescript-dnd-kit
v0.2.0
Published
ReScript bindings for [@dnd-kit/react](https://dndkit.com/) v0.2.x.
Downloads
206
Readme
rescript-dnd-kit
ReScript bindings for @dnd-kit/react v0.2.x.
Installation
npm install @illusionalsagacity/rescript-dnd-kit @dnd-kit/react @dnd-kit/helpersAdd to your rescript.json:
{
"dependencies": ["@illusionalsagacity/rescript-dnd-kit", "@rescript/react"]
}Usage
All bindings are in the top-level DndKit module.
Sortable List
module SortableItem = {
@react.component
let make = (~id: string, ~index: int) => {
let {ref, isDragSource} = DndKit.useSortable({
id: String(id),
index,
})
<div
ref={ReactDOM.Ref.callbackDomRef(el => {ref(el); None})}
style={{opacity: isDragSource ? "0.3" : "1"}}>
{React.string(id)}
</div>
}
}
@react.component
let make = () => {
let (items, setItems) = React.useState(() => ["Apple", "Banana", "Cherry"])
let onDragOver = (event, _manager) => {
setItems(prev => DndKit.move(prev, event))
}
<DndKit.DragDropProvider
sensors={[DndKit.pointerSensor, DndKit.keyboardSensor]}
onDragOver>
{items
->Array.mapWithIndex((item, index) =>
<SortableItem key={item} id={item} index />
)
->React.array}
</DndKit.DragDropProvider>
}Draggable + Droppable
module DraggableCard = {
@react.component
let make = (~id: string) => {
let {ref, isDragSource} = DndKit.useDraggable({id: String(id)})
<div
ref={ReactDOM.Ref.callbackDomRef(el => {ref(el); None})}
style={{opacity: isDragSource ? "0.3" : "1", cursor: "grab"}}>
{React.string(id)}
</div>
}
}
module DropZone = {
@react.component
let make = (~id: string, ~children: React.element) => {
let {ref, isDropTarget} = DndKit.useDroppable({id: String(id)})
<div
ref={ReactDOM.Ref.callbackDomRef(el => {ref(el); None})}
style={{background: isDropTarget ? "#e8f5e9" : "#f5f5f5"}}>
children
</div>
}
}Event Handling
Events carry an operation with source/target accessible via getters:
let onDragEnd = (event: DndKit.dragEndEvent, _manager) => {
if !event.canceled {
let sourceId =
event.operation
->DndKit.operationSource
->Nullable.toOption
->Option.map(DndKit.draggableId)
let targetId =
event.operation
->DndKit.operationTarget
->Nullable.toOption
->Option.map(DndKit.droppableId)
switch (sourceId, targetId) {
| (Some(String(from)), Some(String(to_))) => handleDrop(from, to_)
| _ => ()
}
}
}DragOverlay
Render a preview of the dragged item:
<DndKit.DragOverlay>
{switch activeItem {
| Some(item) => <ItemPreview item />
| None => React.null
}}
</DndKit.DragOverlay>Monitoring Events
DndKit.useDragDropMonitor({
onDragStart: ?Some((event, _manager) => Console.log("started")),
onDragEnd: ?Some((event, _manager) => Console.log("ended")),
})Current Drag State
let {source, target} = DndKit.useDragOperation()
let isDragging = source->Nullable.toOption->Option.isSomeAvailable Bindings
Sensors
| Binding | Source |
|---|---|
| DndKit.pointerSensor | @dnd-kit/react |
| DndKit.keyboardSensor | @dnd-kit/react |
Collision Detectors
| Binding | Source |
|---|---|
| DndKit.defaultCollisionDetection | @dnd-kit/collision |
| DndKit.closestCenter | @dnd-kit/collision |
| DndKit.closestCorners | @dnd-kit/collision |
| DndKit.pointerIntersection | @dnd-kit/collision |
| DndKit.shapeIntersection | @dnd-kit/collision |
| DndKit.directionBiased | @dnd-kit/collision |
| DndKit.pointerDistance | @dnd-kit/collision |
Modifiers
| Binding | Source |
|---|---|
| DndKit.restrictToVerticalAxis | @dnd-kit/abstract/modifiers |
| DndKit.restrictToHorizontalAxis | @dnd-kit/abstract/modifiers |
| DndKit.restrictToWindow | @dnd-kit/dom/modifiers |
| DndKit.restrictToElement | @dnd-kit/dom/modifiers |
Helpers
| Binding | Source |
|---|---|
| DndKit.move | @dnd-kit/helpers |
| DndKit.swap | @dnd-kit/helpers |
| DndKit.arrayMove | @dnd-kit/helpers |
| DndKit.arraySwap | @dnd-kit/helpers |
Examples
See the example/ directory for working demos:
- SortableDemo — Vertical list reordering with
useSortable,DndKit.move, modifiers,DragOverlay, and event monitoring - KanbanDemo — Multi-column board with
useDraggable/useDroppablefor moving cards between columns
Run the examples:
cd example
yarn install
yarn run res:build
yarn run dev