🚧 Minor reimplementation on how workspace initialization.

This commit is contained in:
Andrey Antukh 2019-11-27 15:33:53 +01:00
parent 59bab376cd
commit 426677935e
8 changed files with 243 additions and 221 deletions

View file

@ -10,7 +10,7 @@
[beicon.core :as rx] [beicon.core :as rx]
[cuerdas.core :as str] [cuerdas.core :as str]
[potok.core :as ptk] [potok.core :as ptk]
[uxbox.main.repo :as rp] [uxbox.main.repo.core :as rp]
[uxbox.util.data :refer [index-by-id concatv]] [uxbox.util.data :refer [index-by-id concatv]]
[uxbox.util.spec :as us] [uxbox.util.spec :as us]
[uxbox.util.timers :as ts] [uxbox.util.timers :as ts]
@ -159,7 +159,7 @@
[id pages] [id pages]
(s/assert ::us/uuid id) (s/assert ::us/uuid id)
(s/assert ::us/coll pages) (s/assert ::us/coll pages)
(ptk/reify ::page-fetched (ptk/reify ::pages-fetched
IDeref IDeref
(-deref [_] (list id pages)) (-deref [_] (list id pages))
@ -175,7 +175,7 @@
(defn pages-fetched? (defn pages-fetched?
[v] [v]
(= ::page-fetched (ptk/type v))) (= ::pages-fetched (ptk/type v)))
;; --- Fetch Pages (by project id) ;; --- Fetch Pages (by project id)
@ -185,10 +185,41 @@
(reify (reify
ptk/WatchEvent ptk/WatchEvent
(watch [_ state s] (watch [_ state s]
(->> (rp/req :fetch/pages-by-project {:project id}) (->> (rp/query :pages-by-project {:project-id id})
(rx/map :payload)
(rx/map #(pages-fetched id %)))))) (rx/map #(pages-fetched id %))))))
;; --- Page Fetched
(defn page-fetched
[data]
(s/assert any? data) ;; TODO: minimal validate
(ptk/reify ::page-fetched
IDeref
(-deref [_] data)
ptk/UpdateEvent
(update [_ state]
(-> state
(unpack-page data)
(assoc-packed-page data)))))
(defn page-fetched?
[v]
(= ::page-fetched (ptk/type v)))
;; --- Fetch Pages (by project id)
(defn fetch-page
"Fetch page by id."
[id]
(s/assert ::us/uuid id)
(reify
ptk/WatchEvent
(watch [_ state s]
(->> (rp/query :page {:id id})
(rx/map page-fetched)))))
;; --- Page Created ;; --- Page Created
(declare rehash-pages) (declare rehash-pages)

View file

@ -67,36 +67,32 @@
;; --- Projects Fetched ;; --- Projects Fetched
(defrecord ProjectsFetched [projects]
ptk/UpdateEvent
(update [_ state]
(reduce assoc-project state projects))
ptk/WatchEvent
(watch [_ state stream]
(->> (rx/from-coll (map :id projects))
(rx/map udp/fetch-pages))))
(defn projects-fetched (defn projects-fetched
[projects] [projects]
{:pre [(us/valid? (s/every ::project-entity) projects)]} (s/assert (s/every ::project-entity) projects)
(ProjectsFetched. projects)) (ptk/reify ::projects-fetched
ptk/UpdateEvent
(update [_ state]
(reduce assoc-project state projects))))
;; ptk/WatchEvent
;; (watch [_ state stream]
;; (->> (rx/from-coll (map :id projects))
;; (rx/map udp/fetch-pages))))
(defn projects-fetched? (defn projects-fetched?
[v] [v]
(instance? ProjectsFetched v)) (= ::projects-fetched (ptk/type v)))
;; --- Fetch Projects ;; --- Fetch Projects
(defrecord FetchProjects [] (defn fetch-projects
[]
(ptk/reify ::fetch-projects
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
(->> (rp/query :projects) (->> (rp/query :projects)
(rx/map projects-fetched)))) (rx/map projects-fetched)))))
(defn fetch-projects
[]
(FetchProjects.))
;; --- Project Persisted ;; --- Project Persisted
@ -177,14 +173,13 @@
(defn go-to (defn go-to
[id] [id]
{:pre [(uuid? id)]} (s/assert ::us/uuid id)
(reify (ptk/reify ::go-to
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
(let [[page & rest-pages] (get-in state [:projects id :pages])] (let [page-id (get-in state [:projects id :ref-page-id])]
(when page (let [params {:project id :page page-id}]
(let [params {:project id :page page}] (rx/of (rt/nav :workspace/page params)))))))
(rx/of (rt/nav :workspace/page params))))))))
;; --- Update Opts (Filtering & Ordering) ;; --- Update Opts (Filtering & Ordering)

View file

@ -46,6 +46,15 @@
(declare initialize-alignment) (declare initialize-alignment)
(def workspace-default-data
{:initialized true
:zoom 1
:flags #{:sitemap :drawtools :layers :element-options :rules}
:selected #{}
:drawing nil
:drawing-tool nil
:tooltip nil})
(defn initialize (defn initialize
"Initialize the workspace state." "Initialize the workspace state."
[project-id page-id] [project-id page-id]
@ -54,22 +63,15 @@
(ptk/reify ::initialize (ptk/reify ::initialize
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(let [default-flags #{:sitemap :drawtools :layers :element-options :rules} (let [data (assoc workspace-default-data
initial-workspace {:project-id project-id :project-id project-id
:initialized true :page-id page-id)]
:page-id page-id
:zoom 1
:flags default-flags
:selected #{}
:drawing nil
:drawing-tool nil
:tooltip nil}]
(-> state (-> state
(update-in [:workspace page-id] (update-in [:workspace page-id]
(fn [wsp] (fn [wsp]
(if (:initialized wsp) (if (:initialized wsp)
wsp wsp
(merge wsp initial-workspace)))) (merge wsp data))))
(assoc-in [:workspace :current] page-id)))) (assoc-in [:workspace :current] page-id))))
ptk/WatchEvent ptk/WatchEvent
@ -77,17 +79,16 @@
(let [page (get-in state [:pages page-id])] (let [page (get-in state [:pages page-id])]
;; Activate loaded if page is not fetched. ;; Activate loaded if page is not fetched.
(when-not page (reset! st/loader true)) (when-not page (reset! st/loader true))
(if page
(rx/of (initialize-alignment page-id))
(rx/merge (rx/merge
;; TODO: the `fetch-pages` should fetch a limited set of attrs
(rx/of (udp/fetch-page page-id))
(rx/of (udp/fetch-pages project-id)) (rx/of (udp/fetch-pages project-id))
(->> stream (->> stream
(rx/filter udp/pages-fetched?) (rx/filter udp/page-fetched?)
(rx/take 1) (rx/take 1)
(rx/do #(reset! st/loader false)) (rx/mapcat (fn [event]
(rx/map #(initialize-alignment page-id))))))) (reset! st/loader false)
(rx/of (initialize-alignment page-id))))))))
ptk/EffectEvent ptk/EffectEvent
(effect [_ state stream] (effect [_ state stream]
;; Optimistic prefetch of projects if them are not already fetched ;; Optimistic prefetch of projects if them are not already fetched
@ -307,10 +308,13 @@
;; --- Grid Alignment ;; --- Grid Alignment
(defrecord InitializeAlignment [id] (defn initialize-alignment
[id]
(s/assert ::us/uuid id)
(ptk/reify ::initialize-alignment
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
(let [{:keys [metadata] :as page} (get-in state [:pages id]) (let [metadata (get-in state [:pages id :metadata])
params {:width c/viewport-width params {:width c/viewport-width
:height c/viewport-height :height c/viewport-height
:x-axis (:grid-x-axis metadata c/grid-x-axis) :x-axis (:grid-x-axis metadata c/grid-x-axis)
@ -318,16 +322,7 @@
(rx/concat (rx/concat
(rx/of (deactivate-flag :grid-indexed)) (rx/of (deactivate-flag :grid-indexed))
(->> (uwrk/initialize-alignment params) (->> (uwrk/initialize-alignment params)
(rx/map #(activate-flag :grid-indexed))))))) (rx/map #(activate-flag :grid-indexed))))))))
(defn initialize-alignment?
[v]
(instance? InitializeAlignment v))
(defn initialize-alignment
[id]
{:pre [(uuid? id)]}
(InitializeAlignment. id))
;; --- Duplicate Selected ;; --- Duplicate Selected

View file

@ -9,16 +9,16 @@
(:require (:require
[rumext.alpha :as mf] [rumext.alpha :as mf]
[uxbox.main.store :as st] [uxbox.main.store :as st]
[uxbox.main.ui.shapes.circle :refer [circle-shape]] ;; [uxbox.main.ui.shapes.circle :refer [circle-shape]]
[uxbox.main.ui.shapes.group :refer [group-shape]] ;; [uxbox.main.ui.shapes.group :refer [group-shape]]
[uxbox.main.ui.shapes.icon :refer [icon-shape]] ;; [uxbox.main.ui.shapes.icon :refer [icon-shape]]
[uxbox.main.ui.shapes.image :refer [image-shape]] ;; [uxbox.main.ui.shapes.image :refer [image-shape]]
[uxbox.main.ui.shapes.path :refer [path-shape]] ;; [uxbox.main.ui.shapes.path :refer [path-shape]]
[uxbox.main.ui.shapes.rect :refer [rect-shape]] ;; [uxbox.main.ui.shapes.rect :refer [rect-shape]]
[uxbox.main.ui.shapes.text :refer [text-shape]] ;; [uxbox.main.ui.shapes.text :refer [text-shape]]
[uxbox.util.dom :as dom])) [uxbox.util.dom :as dom]))
(def ^:dynamic *state* st/state) ;; (def ^:dynamic *state* st/state)
(mf/defc background (mf/defc background
[] []
@ -33,7 +33,7 @@
(defn- make-shape-element (defn- make-shape-element
[state shape] [state shape]
(mf/html #_(mf/html
(case (:type shape) (case (:type shape)
;; :text [:& text-shape {:shape shape}] ;; :text [:& text-shape {:shape shape}]
:icon [:& icon-shape {:shape shape}] :icon [:& icon-shape {:shape shape}]
@ -46,7 +46,7 @@
(mf/defc page-svg (mf/defc page-svg
[{:keys [page state] :as props}] [{:keys [page state] :as props}]
(let [{:keys [width height]} (:metadata page)] #_(let [{:keys [width height]} (:metadata page)]
[:svg {:width width [:svg {:width width
:height height :height height
:view-box (str "0 0 " width " " height) :view-box (str "0 0 " width " " height)
@ -61,7 +61,7 @@
(defn render-page (defn render-page
[id] [id]
(try #_(try
(let [state (deref st/state) (let [state (deref st/state)
page (get-in state [:pages id])] page (get-in state [:pages id])]
(when (:shapes page) (when (:shapes page)

View file

@ -5,7 +5,7 @@
;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz> ;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.group (ns uxbox.main.ui.shapes.group
(:require #_(:require
[lentes.core :as l] [lentes.core :as l]
[rumext.core :as mx] [rumext.core :as mx]
[uxbox.main.geom :as geom] [uxbox.main.geom :as geom]
@ -24,64 +24,64 @@
;; --- Helpers ;; --- Helpers
(declare group-component) ;; (declare group-component)
(defn- focus-shape ;; (defn- focus-shape
[id] ;; [id]
(-> (l/in [:shapes id]) ;; (-> (l/in [:shapes id])
(l/derive st/state))) ;; (l/derive st/state)))
(defn render-component ;; (defn render-component
[shape] ;; [shape]
(case (:type shape) ;; (case (:type shape)
:group (group-component shape) ;; :group (group-component shape)
:text (text/text-component shape) ;; :text (text/text-component shape)
:icon (icon/icon-component shape) ;; :icon (icon/icon-component shape)
:rect (rect/rect-component shape) ;; :rect (rect/rect-component shape)
:path (path/path-component shape) ;; :path (path/path-component shape)
:image (image/image-component shape) ;; :image (image/image-component shape)
:circle (circle/circle-component shape))) ;; :circle (circle/circle-component shape)))
(mx/defc component-container ;; (mx/defc component-container
{:mixins [mx/reactive mx/static]} ;; {:mixins [mx/reactive mx/static]}
[id] ;; [id]
(when-let [shape (mx/react (focus-shape id))] ;; (when-let [shape (mx/react (focus-shape id))]
(when-not (:hidden shape) ;; (when-not (:hidden shape)
(render-component shape)))) ;; (render-component shape))))
;; --- Group Component ;; ;; --- Group Component
(declare group-shape) ;; (declare group-shape)
(mx/defc group-component ;; (mx/defc group-component
{:mixins [mx/static mx/reactive]} ;; {:mixins [mx/static mx/reactive]}
[{:keys [id x y width height group] :as shape}] ;; [{:keys [id x y width height group] :as shape}]
(let [modifiers (mx/react (refs/selected-modifiers id)) ;; (let [modifiers (mx/react (refs/selected-modifiers id))
selected (mx/react refs/selected-shapes) ;; selected (mx/react refs/selected-shapes)
selected? (contains? selected id) ;; selected? (contains? selected id)
on-mouse-down #(common/on-mouse-down % shape selected) ;; on-mouse-down #(common/on-mouse-down % shape selected)
shape (assoc shape :modifiers modifiers)] ;; shape (assoc shape :modifiers modifiers)]
[:g.shape.group-shape ;; [:g.shape.group-shape
{:class (when selected? "selected") ;; {:class (when selected? "selected")
:on-mouse-down on-mouse-down} ;; :on-mouse-down on-mouse-down}
(group-shape shape component-container)])) ;; (group-shape shape component-container)]))
;; --- Group Shape ;; ;; --- Group Shape
(mx/defc group-shape ;; (mx/defc group-shape
{:mixins [mx/static mx/reactive]} ;; {:mixins [mx/static mx/reactive]}
[{:keys [id items modifiers] :as shape} factory] ;; [{:keys [id items modifiers] :as shape} factory]
(let [{:keys [resize displacement]} modifiers ;; (let [{:keys [resize displacement]} modifiers
xfmt (cond-> (gmt/matrix) ;; xfmt (cond-> (gmt/matrix)
resize (gmt/multiply resize) ;; resize (gmt/multiply resize)
displacement (gmt/multiply displacement)) ;; displacement (gmt/multiply displacement))
moving? (boolean displacement)] ;; moving? (boolean displacement)]
[:g {:id (str "shape-" id) ;; [:g {:id (str "shape-" id)
:class (classnames :move-cursor moving?) ;; :class (classnames :move-cursor moving?)
:transform (str xfmt)} ;; :transform (str xfmt)}
(for [item (reverse items)] ;; (for [item (reverse items)]
(-> (factory item) ;; (-> (factory item)
(mx/with-key (str item))))])) ;; (mx/with-key (str item))))]))

View file

@ -2,7 +2,7 @@
;; License, v. 2.0. If a copy of the MPL was not distributed with this ;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;; ;;
;; Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz> ;; Copyright (c) 2015-2019 Andrey Antukh <niwi@niwi.nz>
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com> ;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
(ns uxbox.main.ui.workspace.sidebar.sitemap (ns uxbox.main.ui.workspace.sidebar.sitemap
@ -78,7 +78,8 @@
(mf/defc pages-list (mf/defc pages-list
[{:keys [project current-page-id] :as props}] [{:keys [project current-page-id] :as props}]
(let [pages-map (mf/deref pages-map-iref) (let [pages-map (mf/deref pages-map-iref)
pages (map #(get pages-map %) (:pages project)) pages (->> (vals pages-map)
(filter #(= (:project-id %) (:id project))))
deletable? (> (count pages) 1)] deletable? (> (count pages) 1)]
[:ul.element-list [:ul.element-list
(for [[index item] (map-indexed vector pages)] (for [[index item] (map-indexed vector pages)]

View file

@ -15,7 +15,7 @@
(mf/defc background (mf/defc background
{:wrap [mf/wrap-memo]} {:wrap [mf/wrap-memo]}
[{:keys [background] :as metadata}] [{:keys [background] :as metadata}]
[:rect #_[:rect
{:x 0 :y 0 {:x 0 :y 0
:width "100%" :width "100%"
:height "100%" :height "100%"
@ -28,7 +28,7 @@
(mf/defc canvas (mf/defc canvas
{:wrap [mf/wrap-memo]} {:wrap [mf/wrap-memo]}
[{:keys [page] :as props}] [{:keys [page] :as props}]
(let [{:keys [metadata id]} page #_(let [{:keys [metadata id]} page
{:keys [width height]} metadata] {:keys [width height]} metadata]
[:div.view-canvas [:div.view-canvas
[:svg.page-layout {:width width [:svg.page-layout {:width width

View file

@ -5,7 +5,7 @@
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz> ;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.view.ui.viewer.shapes (ns uxbox.view.ui.viewer.shapes
(:require [goog.events :as events] #_(:require [goog.events :as events]
[lentes.core :as l] [lentes.core :as l]
[uxbox.builtins.icons :as i] [uxbox.builtins.icons :as i]
[uxbox.view.store :as st] [uxbox.view.store :as st]
@ -15,104 +15,104 @@
[uxbox.main.ui.shapes.rect :refer [rect-shape]] [uxbox.main.ui.shapes.rect :refer [rect-shape]]
[uxbox.main.ui.shapes.icon :refer [icon-shape]] [uxbox.main.ui.shapes.icon :refer [icon-shape]]
[uxbox.main.ui.shapes.text :refer [text-shape]] [uxbox.main.ui.shapes.text :refer [text-shape]]
[uxbox.main.ui.shapes.group :refer [group-shape]] ;; [uxbox.main.ui.shapes.group :refer [group-shape]]
[uxbox.main.ui.shapes.path :refer [path-shape]] [uxbox.main.ui.shapes.path :refer [path-shape]]
[uxbox.main.ui.shapes.circle :refer [circle-shape]] [uxbox.main.ui.shapes.circle :refer [circle-shape]]
[uxbox.main.ui.shapes.image :refer [image-shape]] [uxbox.main.ui.shapes.image :refer [image-shape]]
[rumext.core :as mx :include-macros true]) [rumext.core :as mx :include-macros true])
(:import goog.events.EventType)) #_(:import goog.events.EventType))
(def itx-flag-ref ;; (def itx-flag-ref
(-> (comp (l/key :flags) (l/lens :interactions)) ;; (-> (comp (l/key :flags) (l/lens :interactions))
(l/derive st/state))) ;; (l/derive st/state)))
(defn image-ref ;; (defn image-ref
[id] ;; [id]
(-> (l/in [:images id]) ;; (-> (l/in [:images id])
(l/derive st/state))) ;; (l/derive st/state)))
;; --- Interactions Wrapper ;; ;; --- Interactions Wrapper
(defn- interactions-wrapper-did-mount ;; (defn- interactions-wrapper-did-mount
[own] ;; [own]
(let [dom (mx/dom-node own) ;; (let [dom (mx/dom-node own)
shape (first (::mx/args own)) ;; shape (first (::mx/args own))
evnts (itx/build-events shape) ;; evnts (itx/build-events shape)
keys (reduce (fn [acc [evt callback]] ;; keys (reduce (fn [acc [evt callback]]
(conj acc (events/listen dom evt callback))) ;; (conj acc (events/listen dom evt callback)))
[] ;; []
evnts)] ;; evnts)]
(assoc own ::keys keys))) ;; (assoc own ::keys keys)))
(defn- interactions-wrapper-will-unmount ;; (defn- interactions-wrapper-will-unmount
[own] ;; [own]
(let [keys (::keys own)] ;; (let [keys (::keys own)]
(run! #(events/unlistenByKey %) keys) ;; (run! #(events/unlistenByKey %) keys)
(dissoc own ::keys))) ;; (dissoc own ::keys)))
(mx/defc interactions-wrapper ;; (mx/defc interactions-wrapper
{:did-mount interactions-wrapper-did-mount ;; {:did-mount interactions-wrapper-did-mount
:will-unmount interactions-wrapper-will-unmount ;; :will-unmount interactions-wrapper-will-unmount
:mixins [mx/reactive mx/static]} ;; :mixins [mx/reactive mx/static]}
[shape factory] ;; [shape factory]
{:pre [(map? shape)]} ;; {:pre [(map? shape)]}
(let [show-itx? (and (mx/react itx-flag-ref) ;; (let [show-itx? (and (mx/react itx-flag-ref)
(not (empty? (:interactions shape)))) ;; (not (empty? (:interactions shape))))
rect (geom/shape->rect-shape shape)] ;; rect (geom/shape->rect-shape shape)]
[:g {:id (str "itx-" (:id shape)) ;; [:g {:id (str "itx-" (:id shape))
:style {:cursor "pointer"}} ;; :style {:cursor "pointer"}}
(factory shape) ;; (factory shape)
(when show-itx? ;; (when show-itx?
[:circle {:class "interaction-bullet" ;; [:circle {:class "interaction-bullet"
:cx (:x1 rect) ;; :cx (:x1 rect)
:cy (:y1 rect) ;; :cy (:y1 rect)
:r 5}])])) ;; :r 5}])]))
;; [:rect {:class "interaction-hightlight" ;; ;; [:rect {:class "interaction-hightlight"
;; :x (:x1 rect) ;; ;; :x (:x1 rect)
;; :y (:y1 rect) ;; ;; :y (:y1 rect)
;; :width (:width rect) ;; ;; :width (:width rect)
;; :height (:height rect)}] ;; ;; :height (:height rect)}]
;; --- Image Shape Wrapper ;; ;; --- Image Shape Wrapper
;; ;; ;;
;; NOTE: This wrapper is needed for preload the referenced ;; ;; NOTE: This wrapper is needed for preload the referenced
;; image object which is need for properly show the shape. ;; ;; image object which is need for properly show the shape.
(mx/defc image-shape-wrapper ;; (mx/defc image-shape-wrapper
{:mixins [mx/static mx/reactive] ;; {:mixins [mx/static mx/reactive]
:init (fn [own] ;; :init (fn [own]
(when-let [image-id (-> own ::mx/args first :image)] ;; (when-let [image-id (-> own ::mx/args first :image)]
(st/emit! (udv/fetch-image image-id))) ;; (st/emit! (udv/fetch-image image-id)))
own)} ;; own)}
[{:keys [image] :as item}] ;; [{:keys [image] :as item}]
(when-let [image (mx/react (image-ref image))] ;; (when-let [image (mx/react (image-ref image))]
(image-shape (assoc item :image image)))) ;; (image-shape (assoc item :image image))))
;; --- Text Shape Wrapper ;; ;; --- Text Shape Wrapper
(mx/defc text-shape-wrapper ;; (mx/defc text-shape-wrapper
{:mixins [mx/static]} ;; {:mixins [mx/static]}
[item] ;; [item]
(text-shape (assoc item :user-select true))) ;; (text-shape (assoc item :user-select true)))
;; --- Shapes ;; ;; --- Shapes
(declare shape) ;; (declare shape)
(mx/defc shape* ;; (mx/defc shape*
[{:keys [type] :as item}] ;; [{:keys [type] :as item}]
(case type ;; (case type
:group (group-shape item shape) ;; ;; :group (group-shape item shape)
:image (image-shape-wrapper item) ;; :image (image-shape-wrapper item)
:text (text-shape-wrapper item) ;; :text (text-shape-wrapper item)
:icon (icon-shape item) ;; :icon (icon-shape item)
:rect (rect-shape item) ;; :rect (rect-shape item)
:path (path-shape item) ;; :path (path-shape item)
:circle (circle-shape item))) ;; :circle (circle-shape item)))
(mx/defc shape ;; (mx/defc shape
[sid] ;; [sid]
{:pre [(uuid? sid)]} ;; {:pre [(uuid? sid)]}
(let [item (get-in @st/state [:shapes sid])] ;; (let [item (get-in @st/state [:shapes sid])]
(interactions-wrapper item shape*))) ;; (interactions-wrapper item shape*)))