mirror of
https://github.com/penpot/penpot.git
synced 2025-05-25 19:06:12 +02:00
🚧 Add ad-hoc d&d implementation.
React-Dnd is a very nice library but adds a lot of overhead. Causes a lot of latency when a number of elements grows.
This commit is contained in:
parent
274a85186e
commit
7db2db96e1
10 changed files with 272 additions and 70 deletions
|
@ -1018,3 +1018,21 @@ input[type=range]:focus::-ms-fill-upper {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[draggable] {
|
||||||
|
-moz-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
/* Required to make elements draggable in old WebKit */
|
||||||
|
-khtml-user-drag: element;
|
||||||
|
-webkit-user-drag: element;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dnd-over-top {
|
||||||
|
border-top: 1px solid white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dnd-over-bot {
|
||||||
|
border-bottom: 1px solid white !important;
|
||||||
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
grid-template-rows: 12rem 25% 1fr;
|
grid-template-rows: 12rem 25% 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding-top: 40px;
|
padding-top: 40px;
|
||||||
|
@ -136,10 +136,9 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
border-top: 1px solid transparent;
|
||||||
|
border-bottom: 1px solid transparent;
|
||||||
|
|
||||||
&.dragging-TODO {
|
|
||||||
background-color: #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.open {
|
&.open {
|
||||||
|
|
||||||
|
|
|
@ -1407,20 +1407,27 @@
|
||||||
|
|
||||||
;; --- Change Shape Order (D&D Ordering)
|
;; --- Change Shape Order (D&D Ordering)
|
||||||
|
|
||||||
(defn shape-order-change
|
;; TODO: pending UNDO
|
||||||
[id index]
|
|
||||||
|
(defn relocate-shape
|
||||||
|
[id ref-id index]
|
||||||
(us/verify ::us/uuid id)
|
(us/verify ::us/uuid id)
|
||||||
|
(us/verify ::us/uuid ref-id)
|
||||||
(us/verify number? index)
|
(us/verify number? index)
|
||||||
(ptk/reify ::change-shape-order
|
|
||||||
ptk/UpdateEvent
|
(ptk/reify ::reloacate-shape
|
||||||
(update [_ state]
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
(let [page-id (::page-id state)
|
(let [page-id (::page-id state)
|
||||||
obj (get-in state [:workspace-data page-id :objects id])
|
selected (get-in state [:workspace-local :selected])
|
||||||
frm (get-in state [:workspace-data page-id :objects (:frame-id obj)])
|
objects (get-in state [:workspace-data page-id :objects])
|
||||||
shp (remove #(= % id) (:shapes frm))
|
parent-id (helpers/get-parent ref-id objects)]
|
||||||
[b a] (split-at index shp)
|
(rx/of (commit-changes [{:type :mov-objects
|
||||||
shp (d/concat [] b [id] a)]
|
:parent-id parent-id
|
||||||
(assoc-in state [:workspace-data page-id :objects (:id frm) :shapes] shp)))))
|
:index index
|
||||||
|
:shapes (vec selected)}]
|
||||||
|
[]
|
||||||
|
{:commit-local? true}))))))
|
||||||
|
|
||||||
(defn commit-shape-order-change
|
(defn commit-shape-order-change
|
||||||
[id]
|
[id]
|
||||||
|
@ -2359,7 +2366,8 @@
|
||||||
(fn [state] (assoc-in state [:workspace-local :selected] #{id})))))
|
(fn [state] (assoc-in state [:workspace-local :selected] #{id})))))
|
||||||
rx/empty))))))
|
rx/empty))))))
|
||||||
|
|
||||||
(defn remove-group []
|
(defn remove-group
|
||||||
|
[]
|
||||||
(ptk/reify ::remove-group
|
(ptk/reify ::remove-group
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[goog.events :as events]
|
[goog.events :as events]
|
||||||
[rumext.alpha :as mf]
|
[rumext.alpha :as mf]
|
||||||
|
[uxbox.util.transit :as t]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
[uxbox.util.webapi :as wapi]
|
[uxbox.util.webapi :as wapi]
|
||||||
["mousetrap" :as mousetrap])
|
["mousetrap" :as mousetrap])
|
||||||
|
@ -65,3 +66,139 @@
|
||||||
|
|
||||||
[toggle @state]))
|
[toggle @state]))
|
||||||
|
|
||||||
|
;; (defn- extract-type
|
||||||
|
;; [dt]
|
||||||
|
;; (let [types (unchecked-get dt "types")
|
||||||
|
;; total (alength types)]
|
||||||
|
;; (loop [i 0]
|
||||||
|
;; (if (= i total)
|
||||||
|
;; nil
|
||||||
|
;; (if-let [match (re-find #"dnd/(.+)" (aget types i))]
|
||||||
|
;; (second match)
|
||||||
|
;; (recur (inc i)))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn invisible-image
|
||||||
|
[]
|
||||||
|
(let [img (js/Image.)
|
||||||
|
imd "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="]
|
||||||
|
(set! (.-src img) imd)
|
||||||
|
img))
|
||||||
|
|
||||||
|
(defn use-sortable
|
||||||
|
[& {:keys [type data on-drop on-drag] :as opts}]
|
||||||
|
(let [ref (mf/use-ref)
|
||||||
|
state (mf/use-state {})
|
||||||
|
|
||||||
|
on-drag-start
|
||||||
|
(fn [event]
|
||||||
|
;; (dom/prevent-default event)
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(let [dtrans (unchecked-get event "dataTransfer")]
|
||||||
|
(.setDragImage dtrans (invisible-image) 0 0)
|
||||||
|
(set! (.-effectAllowed dtrans) "move")
|
||||||
|
(.setData dtrans "application/json" (t/encode data))
|
||||||
|
;; (.setData dtrans (str "dnd/" type) "")
|
||||||
|
(when (fn? on-drag)
|
||||||
|
(on-drag data))
|
||||||
|
(swap! state (fn [state]
|
||||||
|
(if (:dragging? state)
|
||||||
|
state
|
||||||
|
(assoc state :dragging? true))))))
|
||||||
|
|
||||||
|
on-drag-over
|
||||||
|
(fn [event]
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(dom/prevent-default event)
|
||||||
|
|
||||||
|
(let [target (dom/get-target event)
|
||||||
|
dtrans (unchecked-get event "dataTransfer")
|
||||||
|
ypos (unchecked-get event "offsetY")
|
||||||
|
height (unchecked-get target "clientHeight")
|
||||||
|
thold (/ height 2)
|
||||||
|
side (if (> ypos thold) :bot :top)]
|
||||||
|
|
||||||
|
(set! (.-dropEffect dtrans) "move")
|
||||||
|
(set! (.-effectAllowed dtrans) "move")
|
||||||
|
|
||||||
|
(swap! state update :over (fn [state]
|
||||||
|
(if (not= state side)
|
||||||
|
side
|
||||||
|
state)))))
|
||||||
|
|
||||||
|
;; on-drag-enter
|
||||||
|
;; (fn [event]
|
||||||
|
;; (dom/prevent-default event)
|
||||||
|
;; (dom/stop-propagation event)
|
||||||
|
;; (let [dtrans (unchecked-get event "dataTransfer")
|
||||||
|
;; ty (extract-type dt)]
|
||||||
|
;; (when (= ty type)
|
||||||
|
;; #_(js/console.log "on-drag-enter" (:name data) ty type)
|
||||||
|
;; #_(swap! state (fn [state]
|
||||||
|
;; (if (:over? state)
|
||||||
|
;; state
|
||||||
|
;; (assoc state :over? true)))))))
|
||||||
|
|
||||||
|
on-drag-leave
|
||||||
|
(fn [event]
|
||||||
|
(let [target (.-currentTarget event)
|
||||||
|
related (.-relatedTarget event)]
|
||||||
|
(when-not (.contains target related)
|
||||||
|
;; (js/console.log "on-drag-leave" (:name data))
|
||||||
|
(swap! state (fn [state]
|
||||||
|
(if (:over state)
|
||||||
|
(dissoc state :over)
|
||||||
|
state))))))
|
||||||
|
|
||||||
|
on-drop'
|
||||||
|
(fn [event]
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(let [target (dom/get-target event)
|
||||||
|
dtrans (unchecked-get event "dataTransfer")
|
||||||
|
dtdata (.getData dtrans "application/json")
|
||||||
|
|
||||||
|
ypos (unchecked-get event "offsetY")
|
||||||
|
height (unchecked-get target "clientHeight")
|
||||||
|
thold (/ height 2)
|
||||||
|
side (if (> ypos thold) :bot :top)]
|
||||||
|
|
||||||
|
;; TODO: seems unnecessary
|
||||||
|
(swap! state (fn [state]
|
||||||
|
(cond-> state
|
||||||
|
(:dragging? state) (dissoc :dragging?)
|
||||||
|
(:over state) (dissoc :over))))
|
||||||
|
|
||||||
|
(when (fn? on-drop)
|
||||||
|
(on-drop side (t/decode dtdata)))))
|
||||||
|
|
||||||
|
on-drag-end
|
||||||
|
(fn [event]
|
||||||
|
(swap! state (fn [state]
|
||||||
|
(cond-> state
|
||||||
|
(:dragging? state) (dissoc :dragging?)
|
||||||
|
(:over state) (dissoc :over)))))
|
||||||
|
|
||||||
|
on-mount
|
||||||
|
(fn []
|
||||||
|
(let [dom (mf/ref-val ref)]
|
||||||
|
(.setAttribute dom "draggable" true)
|
||||||
|
(.setAttribute dom "data-type" type)
|
||||||
|
|
||||||
|
(.addEventListener dom "dragstart" on-drag-start false)
|
||||||
|
;; (.addEventListener dom "dragenter" on-drag-enter false)
|
||||||
|
(.addEventListener dom "dragover" on-drag-over false)
|
||||||
|
(.addEventListener dom "dragleave" on-drag-leave true)
|
||||||
|
(.addEventListener dom "drop" on-drop' false)
|
||||||
|
(.addEventListener dom "dragend" on-drag-end false)
|
||||||
|
#(do
|
||||||
|
(.removeEventListener dom "dragstart" on-drag-start)
|
||||||
|
;; (.removeEventListener dom "dragenter" on-drag-enter)
|
||||||
|
(.removeEventListener dom "dragover" on-drag-over)
|
||||||
|
(.removeEventListener dom "dragleave" on-drag-leave)
|
||||||
|
(.removeEventListener dom "drop" on-drop')
|
||||||
|
(.removeEventListener dom "dragend" on-drag-end))))]
|
||||||
|
|
||||||
|
(mf/use-effect
|
||||||
|
(mf/deps type data on-drop)
|
||||||
|
on-mount)
|
||||||
|
[(deref state) ref]))
|
||||||
|
|
|
@ -102,7 +102,7 @@
|
||||||
[:& frame-shape {:shape (geom/transform-shape shape)
|
[:& frame-shape {:shape (geom/transform-shape shape)
|
||||||
:childs childs}]])))))
|
:childs childs}]])))))
|
||||||
|
|
||||||
(defn frame-shape
|
(defn frame-shape
|
||||||
[shape-wrapper]
|
[shape-wrapper]
|
||||||
(mf/fnc frame-shape
|
(mf/fnc frame-shape
|
||||||
[{:keys [shape childs] :as props}]
|
[{:keys [shape childs] :as props}]
|
||||||
|
|
|
@ -118,7 +118,7 @@
|
||||||
page (mf/deref refs/workspace-page)
|
page (mf/deref refs/workspace-page)
|
||||||
project (mf/deref refs/workspace-project)
|
project (mf/deref refs/workspace-project)
|
||||||
layout (mf/deref refs/workspace-layout)]
|
layout (mf/deref refs/workspace-layout)]
|
||||||
[:> rdnd/provider {:backend rdnd/html5}
|
[:*
|
||||||
[:& header {:page page
|
[:& header {:page page
|
||||||
:file file
|
:file file
|
||||||
:project project
|
:project project
|
||||||
|
|
|
@ -17,10 +17,12 @@
|
||||||
[uxbox.main.data.workspace :as dw]
|
[uxbox.main.data.workspace :as dw]
|
||||||
[uxbox.main.refs :as refs]
|
[uxbox.main.refs :as refs]
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.store :as st]
|
||||||
|
[uxbox.main.ui.hooks :as hooks]
|
||||||
[uxbox.main.ui.keyboard :as kbd]
|
[uxbox.main.ui.keyboard :as kbd]
|
||||||
[uxbox.main.ui.shapes.icon :as icon]
|
[uxbox.main.ui.shapes.icon :as icon]
|
||||||
[uxbox.main.ui.workspace.sortable :refer [use-sortable]]
|
[uxbox.main.ui.workspace.sortable :refer [use-sortable]]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
|
[uxbox.util.perf :as perf]
|
||||||
[uxbox.util.uuid :as uuid]
|
[uxbox.util.uuid :as uuid]
|
||||||
[uxbox.util.i18n :as i18n :refer [t]]))
|
[uxbox.util.i18n :as i18n :refer [t]]))
|
||||||
|
|
||||||
|
@ -78,21 +80,33 @@
|
||||||
{:on-double-click on-click}
|
{:on-double-click on-click}
|
||||||
(:name shape "")])))
|
(:name shape "")])))
|
||||||
|
|
||||||
|
(defn- layer-item-memo-equals?
|
||||||
|
[nprops oprops]
|
||||||
|
(let [n-item (unchecked-get nprops "item")
|
||||||
|
o-item (unchecked-get oprops "item")
|
||||||
|
n-selc (unchecked-get nprops "selected")
|
||||||
|
o-selc (unchecked-get oprops "selected")
|
||||||
|
n-indx (unchecked-get nprops "index")
|
||||||
|
o-indx (unchecked-get oprops "index")]
|
||||||
|
;; (js/console.log "FOR" (:name n-item)
|
||||||
|
;; "NEW SEL" n-selc
|
||||||
|
;; "OLD SEL" o-selc)6
|
||||||
|
(and (identical? n-item o-item)
|
||||||
|
(identical? n-indx o-indx)
|
||||||
|
(identical? n-selc o-selc))))
|
||||||
|
|
||||||
(def strip-attrs
|
(declare layer-item)
|
||||||
#(select-keys % [:id :frame :name :type :hidden :blocked]))
|
|
||||||
|
|
||||||
(mf/defc layer-item
|
(mf/defc layer-item
|
||||||
{:wrap [mf/memo]}
|
{::mf/wrap [#(mf/memo' % layer-item-memo-equals?)]}
|
||||||
[{:keys [index item selected objects] :as props}]
|
[{:keys [index item selected objects] :as props}]
|
||||||
(let [selected? (contains? selected (:id item))
|
(let [selected? (contains? selected (:id item))
|
||||||
local (mf/use-state {:collapsed false})
|
collapsed? (mf/use-state false)
|
||||||
collapsed? (:collapsed @local)
|
|
||||||
|
|
||||||
toggle-collapse
|
toggle-collapse
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(swap! local update :collapsed not))
|
(swap! collapsed? not))
|
||||||
|
|
||||||
toggle-blocking
|
toggle-blocking
|
||||||
(fn [event]
|
(fn [event]
|
||||||
|
@ -135,26 +149,35 @@
|
||||||
(st/emit! (dw/show-shape-context-menu {:position pos
|
(st/emit! (dw/show-shape-context-menu {:position pos
|
||||||
:shape item}))))
|
:shape item}))))
|
||||||
|
|
||||||
on-hover
|
on-drag
|
||||||
(fn [item monitor]
|
(fn [{:keys [id]}]
|
||||||
(st/emit! (dw/shape-order-change (:obj-id item) index)))
|
(when (not (contains? selected id))
|
||||||
|
(st/emit! dw/deselect-all
|
||||||
|
(dw/select-shape id))))
|
||||||
|
|
||||||
on-drop
|
on-drop
|
||||||
(fn [item monitor]
|
(fn [side {:keys [id name] :as data}]
|
||||||
(st/emit! (dw/commit-shape-order-change (:obj-id item))))
|
(let [index (if (= :top side) (inc index) index)]
|
||||||
|
;; (println "droping" name "on" side "of" (:name item) "/" index)
|
||||||
|
(st/emit! (dw/relocate-shape id (:id item) index))))
|
||||||
|
|
||||||
[dprops dnd-ref] (use-sortable
|
[dprops dref] (hooks/use-sortable
|
||||||
{:type (str "layer-item" (:frame-id item))
|
:type (str (:frame-id item))
|
||||||
:data {:obj-id (:id item)
|
:on-drop on-drop
|
||||||
:page-id (:page item)
|
:on-drag on-drag
|
||||||
:index index}
|
:data {:id (:id item)
|
||||||
:on-hover on-hover
|
:index index
|
||||||
:on-drop on-drop})]
|
:name (:name item)})
|
||||||
[:li {:ref dnd-ref
|
]
|
||||||
:on-context-menu on-context-menu
|
;; (prn "layer-item" (:name item) index)
|
||||||
|
[:li {:on-context-menu on-context-menu
|
||||||
|
:ref dref
|
||||||
|
:data-index index
|
||||||
:class (dom/classnames
|
:class (dom/classnames
|
||||||
|
:dnd-over-top (= (:over dprops) :top)
|
||||||
|
:dnd-over-bot (= (:over dprops) :bot)
|
||||||
:selected selected?
|
:selected selected?
|
||||||
:dragging-TODO (:dragging? dprops))}
|
)}
|
||||||
[:div.element-list-body {:class (dom/classnames :selected selected?
|
[:div.element-list-body {:class (dom/classnames :selected selected?
|
||||||
:icon-layer (= (:type item) :icon))
|
:icon-layer (= (:type item) :icon))
|
||||||
:on-click select-shape
|
:on-click select-shape
|
||||||
|
@ -173,13 +196,13 @@
|
||||||
(when (:shapes item)
|
(when (:shapes item)
|
||||||
[:span.toggle-content
|
[:span.toggle-content
|
||||||
{:on-click toggle-collapse
|
{:on-click toggle-collapse
|
||||||
:class (when-not collapsed? "inverse")}
|
:class (when-not @collapsed? "inverse")}
|
||||||
i/arrow-slide])]
|
i/arrow-slide])]
|
||||||
(when (and (:shapes item) (not collapsed?))
|
(when (and (:shapes item) (not @collapsed?))
|
||||||
[:ul.element-children
|
[:ul.element-children
|
||||||
(for [[index id] (reverse (d/enumerate (:shapes item)))]
|
(for [[index id] (reverse (d/enumerate (:shapes item)))]
|
||||||
(when-let [item (get objects id)]
|
(when-let [item (get objects id)]
|
||||||
[:& layer-item
|
[:& uxbox.main.ui.workspace.sidebar.layers/layer-item
|
||||||
{:item item
|
{:item item
|
||||||
:selected selected
|
:selected selected
|
||||||
:index index
|
:index index
|
||||||
|
@ -193,15 +216,16 @@
|
||||||
data (mf/deref refs/workspace-data)
|
data (mf/deref refs/workspace-data)
|
||||||
objects (:objects data)
|
objects (:objects data)
|
||||||
root (get objects uuid/zero)]
|
root (get objects uuid/zero)]
|
||||||
|
|
||||||
|
;; [:& perf/profiler {:label "layers-tree" :enabled false}
|
||||||
[:ul.element-list
|
[:ul.element-list
|
||||||
(for [[index id] (reverse (d/enumerate (:shapes root)))]
|
(for [[index id] (reverse (d/enumerate (:shapes root)))]
|
||||||
(let [item (get objects id)]
|
[:& layer-item
|
||||||
[:& layer-item
|
{:item (get objects id)
|
||||||
{:item item
|
:selected selected
|
||||||
:selected selected
|
:index index
|
||||||
:index index
|
:objects objects
|
||||||
:objects objects
|
:key id}])]))
|
||||||
:key (:id item)}]))]))
|
|
||||||
|
|
||||||
;; --- Layers Toolbox
|
;; --- Layers Toolbox
|
||||||
|
|
||||||
|
|
|
@ -60,15 +60,17 @@
|
||||||
:index index}))
|
:index index}))
|
||||||
|
|
||||||
navigate-fn #(st/emit! (dw/go-to-page (:id page)))
|
navigate-fn #(st/emit! (dw/go-to-page (:id page)))
|
||||||
[dprops ref] (use-sortable {:type "page-item"
|
;; [dprops ref] (use-sortable {:type "page-item"
|
||||||
:data {:id (:id page)
|
;; :data {:id (:id page)
|
||||||
:index index}
|
;; :index index}
|
||||||
:on-hover on-hover
|
;; :on-hover on-hover
|
||||||
:on-drop on-drop})]
|
;; :on-drop on-drop})
|
||||||
[:li {:ref ref :class (classnames :selected selected?)}
|
]
|
||||||
|
[:li {:class (classnames :selected selected?)}
|
||||||
[:div.element-list-body {:class (classnames
|
[:div.element-list-body {:class (classnames
|
||||||
:selected selected?
|
:selected selected?
|
||||||
:dragging (:dragging? dprops))
|
;; :dragging (:dragging? dprops)
|
||||||
|
)
|
||||||
:on-click navigate-fn
|
:on-click navigate-fn
|
||||||
:on-double-click on-double-click}
|
:on-double-click on-double-click}
|
||||||
[:div.page-icon i/file-html]
|
[:div.page-icon i/file-html]
|
||||||
|
|
|
@ -21,18 +21,35 @@
|
||||||
on-drop (constantly nil)}
|
on-drop (constantly nil)}
|
||||||
:as options}]
|
:as options}]
|
||||||
(let [ref (mf/use-ref nil)
|
(let [ref (mf/use-ref nil)
|
||||||
[_, drop] (rdnd/useDrop
|
|
||||||
|
on-hover
|
||||||
|
(fn [item monitor]
|
||||||
|
(when (mf/ref-val ref)
|
||||||
|
(on-hover (unchecked-get item "data") monitor)))
|
||||||
|
|
||||||
|
on-drop
|
||||||
|
(fn [item monitor]
|
||||||
|
(when (mf/ref-val ref)
|
||||||
|
(on-drop (unchecked-get item "data") monitor)))
|
||||||
|
|
||||||
|
on-drop-collect
|
||||||
|
(fn [monitor]
|
||||||
|
#js {:is-over (.isOver ^js monitor)
|
||||||
|
:can-drop (.canDrop ^js monitor)})
|
||||||
|
|
||||||
|
on-drag-collect
|
||||||
|
(fn [monitor]
|
||||||
|
#js {:dragging? (.isDragging monitor)})
|
||||||
|
|
||||||
|
[props1, drop] (rdnd/useDrop
|
||||||
#js {:accept type
|
#js {:accept type
|
||||||
:hover (fn [item monitor]
|
:collect on-drop-collect
|
||||||
(when (mf/ref-val ref)
|
:hover on-hover
|
||||||
(on-hover (unchecked-get item "data") monitor)))
|
:drop on-drop})
|
||||||
:drop (fn [item monitor]
|
[props2, drag] (rdnd/useDrag
|
||||||
(when (mf/ref-val ref)
|
|
||||||
(on-drop (unchecked-get item "data") monitor)))})
|
|
||||||
[props, drag] (rdnd/useDrag
|
|
||||||
#js {:item #js {:type type :data data}
|
#js {:item #js {:type type :data data}
|
||||||
:collect (fn [^js/ReactDnd.Monitor monitor]
|
:collect on-drag-collect})
|
||||||
#js {:dragging? (.isDragging monitor)})})]
|
props (js/Object.assign props1 props2)]
|
||||||
[(mfu/obj->map props)
|
[(mfu/obj->map props)
|
||||||
(drag (drop ref))]))
|
(drag (drop ref))]))
|
||||||
|
|
||||||
|
|
|
@ -295,10 +295,7 @@
|
||||||
:on-drag-over on-drag-over
|
:on-drag-over on-drag-over
|
||||||
:on-drop on-drop}
|
:on-drop on-drop}
|
||||||
[:g.zoom {:transform (str "scale(" zoom ", " zoom ")")}
|
[:g.zoom {:transform (str "scale(" zoom ", " zoom ")")}
|
||||||
;; [:> js/React.Profiler
|
;; [:& perf/profiler {:label "viewport-frames"}
|
||||||
;; {:id "foobar"
|
|
||||||
;; :on-render (perf/react-on-profile)}
|
|
||||||
;; [:& frame-and-shapes]]
|
|
||||||
[:& frames-wrapper {:page page}]
|
[:& frames-wrapper {:page page}]
|
||||||
|
|
||||||
(when (seq selected)
|
(when (seq selected)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue