Forked from p4ulcristian/gist:95aa7b28e3568a1d3e45d27807859baf
Created
December 19, 2022 14:55
-
-
Save iomonad/5c5072548ae5ba83965c53644bd395b8 to your computer and use it in GitHub Desktop.
@dnd-kit/sortable with drag overlay (clojurescript reagent)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns swordfish.sortable | |
(:require [reagent.core :as r] | |
["react" :as react] | |
["@dnd-kit/core" :refer [DndContext | |
closestCenter | |
KeyboardSensor | |
PointerSensor | |
TouchSensor | |
DragOverlay | |
useSensor | |
useSensors]] | |
["@dnd-kit/sortable" :refer [arrayMove | |
SortableContext | |
sortableKeyboardCoordinates | |
verticalListSortingStrategy | |
rectSortingStrategy | |
useSortable]] | |
["@dnd-kit/utilities" :refer [CSS]])) | |
(defn to-clj-map [hash-map] | |
(js->clj hash-map :keywordize-keys true)) | |
(defn sortable-item [props] | |
(let [{:keys [attributes | |
listeners | |
setNodeRef | |
transform | |
transition]} (to-clj-map (useSortable (clj->js {:id (:id props)})))] | |
[:div (merge {:id (str (:id props)) | |
:ref (js->clj setNodeRef) | |
:style {:transform (.toString (.-Transform CSS) (clj->js transform)) | |
:transition transition | |
:background "lightgreen" | |
:margin "10px" | |
:border "1px solid yellow" | |
:padding "5px" | |
:border-radius "10px"}} | |
attributes | |
listeners) | |
(str (:id props))])) | |
(defn drag-overlay-item [props] | |
[:div (merge {:id (str (:id props)) | |
:style {:background "lightgreen" | |
:margin "10px" | |
:border "1px solid yellow" | |
:padding "5px" | |
:border-radius "10px"}}) | |
(str (:id props))]) | |
(def dnd-context (r/adapt-react-class DndContext)) | |
(def sortable-context (r/adapt-react-class SortableContext)) | |
(def drag-overlay (r/adapt-react-class DragOverlay)) | |
(defn sortable-example [] | |
(let [[activeId, setActiveId] (react/useState nil) | |
[items, setItems] (react/useState (clj->js (mapv str (range 100)))) | |
sensors (useSensors | |
(useSensor PointerSensor) | |
(useSensor KeyboardSensor, (to-clj-map {:coordinateGetter sortableKeyboardCoordinates}))) | |
handleDragEnd (fn [event] | |
(let [{:keys [active over]} (to-clj-map event)] | |
(let [oldIndex (.indexOf items (:id active)) | |
newIndex (.indexOf items (:id over))] | |
(setItems (clj->js (arrayMove (clj->js items) oldIndex newIndex))))) | |
(setActiveId nil))] | |
[:div {:style {:width "200px"}} | |
[dnd-context {:sensors sensors | |
:collisionDetection closestCenter | |
:onDragEnd handleDragEnd | |
:onDragStart (fn [e] (setActiveId (get (js->clj (aget e "active")) "id")))} | |
[sortable-context {:items items | |
:strategy rectSortingStrategy} | |
(map (fn [id] [:f> sortable-item {:id id :key id}]) | |
items)] | |
[drag-overlay [:f> drag-overlay-item {:id (if activeId activeId nil)}]]]])) | |
(defn view [] | |
[:div {:style {:margin "100px auto"}} | |
[:h1 "Sortable example"] | |
[:f> sortable-example]]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment