mirror of
https://github.com/penpot/penpot.git
synced 2025-06-03 22:41:38 +02:00
🎉 Namespace workspace data with page id.
This commit is contained in:
parent
38f675d7f9
commit
fc734328cb
13 changed files with 419 additions and 440 deletions
|
@ -112,17 +112,20 @@
|
||||||
|
|
||||||
(s/def ::attr keyword?)
|
(s/def ::attr keyword?)
|
||||||
(s/def ::val any?)
|
(s/def ::val any?)
|
||||||
(s/def ::parent-id uuid?)
|
|
||||||
(s/def ::frame-id uuid?)
|
(s/def ::frame-id uuid?)
|
||||||
|
(s/def ::loc #{:top :bottom :up :down})
|
||||||
|
|
||||||
(defmulti operation-spec-impl :type)
|
(defmulti operation-spec-impl :type)
|
||||||
|
|
||||||
(defmethod operation-spec-impl :set [_]
|
(defmethod operation-spec-impl :set [_]
|
||||||
(s/keys :req-un [::attr ::val]))
|
(s/keys :req-un [::attr ::val]))
|
||||||
|
|
||||||
(defmethod operation-spec-impl :order [_]
|
(defmethod operation-spec-impl :abs-order [_]
|
||||||
(s/keys :req-un [::id ::index]))
|
(s/keys :req-un [::id ::index]))
|
||||||
|
|
||||||
|
(defmethod operation-spec-impl :rel-order [_]
|
||||||
|
(s/keys :req-un [::id ::loc]))
|
||||||
|
|
||||||
(s/def ::operation (s/multi-spec operation-spec-impl :type))
|
(s/def ::operation (s/multi-spec operation-spec-impl :type))
|
||||||
(s/def ::operations (s/coll-of ::operation))
|
(s/def ::operations (s/coll-of ::operation))
|
||||||
|
|
||||||
|
@ -226,7 +229,7 @@
|
||||||
(dissoc shape attr)
|
(dissoc shape attr)
|
||||||
(assoc shape attr val))))
|
(assoc shape attr val))))
|
||||||
|
|
||||||
(defmethod process-operation :order
|
(defmethod process-operation :abs-order
|
||||||
[obj {:keys [id index]}]
|
[obj {:keys [id index]}]
|
||||||
(assert (vector? (:shapes obj)) ":shapes should be a vector")
|
(assert (vector? (:shapes obj)) ":shapes should be a vector")
|
||||||
(update obj :shapes (fn [items]
|
(update obj :shapes (fn [items]
|
||||||
|
@ -234,6 +237,24 @@
|
||||||
(split-at index))]
|
(split-at index))]
|
||||||
(vec (concat b [id] a))))))
|
(vec (concat b [id] a))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defmethod process-operation :rel-order
|
||||||
|
[obj {:keys [id loc] :as change}]
|
||||||
|
(assert (vector? (:shapes obj)) ":shapes should be a vector")
|
||||||
|
(let [shapes (:shapes obj)
|
||||||
|
cindex (d/index-of shapes id)
|
||||||
|
nindex (case loc
|
||||||
|
:top 0
|
||||||
|
:down (min (- (count shapes) 1) (inc cindex))
|
||||||
|
:up (max 0 (- cindex 1))
|
||||||
|
:bottom (- (count shapes) 1))]
|
||||||
|
(update obj :shapes
|
||||||
|
(fn [shapes]
|
||||||
|
(let [[fst snd] (->> (remove #(= % id) shapes)
|
||||||
|
(split-at nindex))]
|
||||||
|
(d/concat [] fst [id] snd))))))
|
||||||
|
|
||||||
|
|
||||||
(defmethod process-operation :default
|
(defmethod process-operation :default
|
||||||
[shape op]
|
[shape op]
|
||||||
(ex/raise :type :operation-not-implemented
|
(ex/raise :type :operation-not-implemented
|
||||||
|
|
|
@ -48,7 +48,7 @@ This is a potential list of persistent ops:
|
||||||
|
|
||||||
{:type :mov-obj
|
{:type :mov-obj
|
||||||
:id <uuid>
|
:id <uuid>
|
||||||
:dest <uuid>}
|
:frame-id <uuid>}
|
||||||
|
|
||||||
{:type :del-obj
|
{:type :del-obj
|
||||||
:id <uuid>}
|
:id <uuid>}
|
||||||
|
@ -61,9 +61,13 @@ This is a potential list of operations:
|
||||||
:attr <any>
|
:attr <any>
|
||||||
:val <any>}
|
:val <any>}
|
||||||
|
|
||||||
{:type :mov
|
{:type :abs-order
|
||||||
:id <uuid>
|
:id <uuid>
|
||||||
:index <int>}
|
:index <int>}
|
||||||
|
|
||||||
|
{:type :rel-order
|
||||||
|
:id <uuid>
|
||||||
|
:loc <one-of:up,down,top,bottom>}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -47,7 +47,9 @@
|
||||||
(l/derive st/state)))
|
(l/derive st/state)))
|
||||||
|
|
||||||
(def workspace-data
|
(def workspace-data
|
||||||
(-> (l/key :workspace-data)
|
(-> (l/lens (fn [state]
|
||||||
|
(let [page-id (get-in state [:workspace-page :id])]
|
||||||
|
(get-in state [:workspace-data page-id]))))
|
||||||
(l/derive st/state)))
|
(l/derive st/state)))
|
||||||
|
|
||||||
(def selected-shapes
|
(def selected-shapes
|
||||||
|
@ -68,14 +70,6 @@
|
||||||
(l/derive workspace-local)))
|
(l/derive workspace-local)))
|
||||||
|
|
||||||
;; DEPRECATED
|
;; DEPRECATED
|
||||||
(def flags
|
|
||||||
(-> (l/key :flags)
|
|
||||||
(l/derive workspace-local)))
|
|
||||||
|
|
||||||
(def selected-flags
|
|
||||||
(-> (l/key :flags)
|
|
||||||
(l/derive workspace-local)))
|
|
||||||
|
|
||||||
(def selected-zoom
|
(def selected-zoom
|
||||||
(-> (l/key :zoom)
|
(-> (l/key :zoom)
|
||||||
(l/derive workspace-local)))
|
(l/derive workspace-local)))
|
||||||
|
|
|
@ -35,26 +35,30 @@
|
||||||
(let [flags (get-in state [:workspace-local :flags])
|
(let [flags (get-in state [:workspace-local :flags])
|
||||||
selected (get-in state [:workspace-local :selected])
|
selected (get-in state [:workspace-local :selected])
|
||||||
stoper (rx/filter uws/mouse-up? stream)
|
stoper (rx/filter uws/mouse-up? stream)
|
||||||
position @uws/mouse-position]
|
zero-point? #(= % (gpt/point 0 0))
|
||||||
|
position @uws/mouse-position
|
||||||
|
deltas (atom 0)]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(->> (uws/mouse-position-deltas position)
|
(->> (uws/mouse-position-deltas position)
|
||||||
|
(rx/filter (complement zero-point?))
|
||||||
|
(rx/tap #(swap! deltas inc))
|
||||||
(rx/map #(dw/apply-displacement-in-bulk selected %))
|
(rx/map #(dw/apply-displacement-in-bulk selected %))
|
||||||
(rx/take-until stoper))
|
(rx/take-until stoper))
|
||||||
(rx/of (dw/materialize-displacement-in-bulk selected)
|
(rx/of (dw/materialize-displacement-in-bulk selected)))))))
|
||||||
::dw/page-data-update))))))
|
|
||||||
|
|
||||||
(def start-move-frame
|
(def start-move-frame
|
||||||
(ptk/reify ::start-move-selected
|
(ptk/reify ::start-move-frame
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [flags (get-in state [:workspace-local :flags])
|
(let [flags (get-in state [:workspace-local :flags])
|
||||||
selected (get-in state [:workspace-local :selected])
|
selected (get-in state [:workspace-local :selected])
|
||||||
stoper (rx/filter uws/mouse-up? stream)
|
stoper (rx/filter uws/mouse-up? stream)
|
||||||
|
zero-point? #(= % (gpt/point 0 0))
|
||||||
frame-id (first selected)
|
frame-id (first selected)
|
||||||
position @uws/mouse-position]
|
position @uws/mouse-position]
|
||||||
|
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(->> (uws/mouse-position-deltas position)
|
(->> (uws/mouse-position-deltas position)
|
||||||
|
(rx/filter (complement zero-point?))
|
||||||
(rx/map #(dw/apply-frame-displacement frame-id %))
|
(rx/map #(dw/apply-frame-displacement frame-id %))
|
||||||
(rx/take-until stoper))
|
(rx/take-until stoper))
|
||||||
(rx/of (dw/materialize-frame-displacement frame-id)))))))
|
(rx/of (dw/materialize-frame-displacement frame-id)))))))
|
||||||
|
|
|
@ -58,9 +58,8 @@
|
||||||
(scroll/scroll-to-point dom mouse-point scroll-position))))
|
(scroll/scroll-to-point dom mouse-point scroll-position))))
|
||||||
|
|
||||||
(mf/defc workspace-content
|
(mf/defc workspace-content
|
||||||
[{:keys [page file flags] :as params}]
|
[{:keys [page file layout] :as params}]
|
||||||
(let [frame (mf/use-ref nil)
|
(let [frame (mf/use-ref nil)
|
||||||
layout (mf/deref refs/workspace-layout)
|
|
||||||
left-sidebar? (not (empty? (keep layout [:layers :sitemap
|
left-sidebar? (not (empty? (keep layout [:layers :sitemap
|
||||||
:document-history])))
|
:document-history])))
|
||||||
right-sidebar? (not (empty? (keep layout [:icons :drawtools
|
right-sidebar? (not (empty? (keep layout [:icons :drawtools
|
||||||
|
@ -87,7 +86,7 @@
|
||||||
[:& vertical-rule]])
|
[:& vertical-rule]])
|
||||||
|
|
||||||
[:section.workspace-viewport {:id "workspace-viewport" :ref frame}
|
[:section.workspace-viewport {:id "workspace-viewport" :ref frame}
|
||||||
[:& viewport {:page page}]]]
|
[:& viewport {:page page :file file}]]]
|
||||||
|
|
||||||
;; Aside
|
;; Aside
|
||||||
(when left-sidebar?
|
(when left-sidebar?
|
||||||
|
@ -95,6 +94,7 @@
|
||||||
(when right-sidebar?
|
(when right-sidebar?
|
||||||
[:& right-sidebar {:page page :layout layout}])]]))
|
[:& right-sidebar {:page page :layout layout}])]]))
|
||||||
|
|
||||||
|
|
||||||
(mf/defc workspace
|
(mf/defc workspace
|
||||||
[{:keys [file-id page-id] :as props}]
|
[{:keys [file-id page-id] :as props}]
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
|
@ -109,6 +109,9 @@
|
||||||
(st/emit! (dw/initialize-ws file-id))
|
(st/emit! (dw/initialize-ws file-id))
|
||||||
#(st/emit! (dw/finalize-ws file-id)))})
|
#(st/emit! (dw/finalize-ws file-id)))})
|
||||||
|
|
||||||
|
(mf/use-effect
|
||||||
|
{:fn #(st/emit! dw/initialize-layout)})
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
{:deps (mf/deps file-id page-id)
|
{:deps (mf/deps file-id page-id)
|
||||||
:fn (fn []
|
:fn (fn []
|
||||||
|
@ -116,11 +119,15 @@
|
||||||
#(rx/cancel! sub)))})
|
#(rx/cancel! sub)))})
|
||||||
|
|
||||||
(let [file (mf/deref refs/workspace-file)
|
(let [file (mf/deref refs/workspace-file)
|
||||||
page (mf/deref refs/workspace-page)]
|
page (mf/deref refs/workspace-page)
|
||||||
|
layout (mf/deref refs/workspace-layout)]
|
||||||
[:> rdnd/provider {:backend rdnd/html5}
|
[:> rdnd/provider {:backend rdnd/html5}
|
||||||
[:& messages-widget]
|
[:& messages-widget]
|
||||||
[:& header {:page page}]
|
[:& header {:page page
|
||||||
|
:file file
|
||||||
|
:layout layout}]
|
||||||
|
|
||||||
(when page
|
(when page
|
||||||
[:& workspace-content {:file file
|
[:& workspace-content {:file file
|
||||||
:page page}])]))
|
:page page
|
||||||
|
:layout layout}])]))
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
:fill-opacity 0
|
:fill-opacity 0
|
||||||
:segments []}
|
:segments []}
|
||||||
{:type :frame
|
{:type :frame
|
||||||
:name "Canvas"}
|
:name "Artboard"}
|
||||||
{:type :curve
|
{:type :curve
|
||||||
:name "Path"
|
:name "Path"
|
||||||
:stroke-style :solid
|
:stroke-style :solid
|
||||||
|
|
|
@ -63,19 +63,15 @@
|
||||||
;; --- Header Component
|
;; --- Header Component
|
||||||
|
|
||||||
(mf/defc header
|
(mf/defc header
|
||||||
[{:keys [page] :as props}]
|
[{:keys [page file layout] :as props}]
|
||||||
(let [toggle #(st/emit! (dw/toggle-flag %))
|
(let [toggle-layout #(st/emit! (dw/toggle-layout-flag %))
|
||||||
toggle-layout #(st/emit! (dw/toggle-layout-flag %))
|
on-undo #(st/emit! (udu/undo))
|
||||||
on-undo (constantly nil)
|
on-redo #(st/emit! (udu/redo))
|
||||||
on-redo (constantly nil)
|
|
||||||
on-image #(modal/show! import-image-modal {})
|
on-image #(modal/show! import-image-modal {})
|
||||||
;;on-download #(udl/open! :download)
|
;;on-download #(udl/open! :download)
|
||||||
layout (mf/deref refs/workspace-layout)
|
|
||||||
flags (mf/deref refs/selected-flags)
|
|
||||||
file (mf/deref refs/workspace-file)
|
|
||||||
selected-drawtool (mf/deref refs/selected-drawing-tool)
|
selected-drawtool (mf/deref refs/selected-drawing-tool)
|
||||||
select-drawtool #(st/emit! :interrupt
|
select-drawtool #(st/emit! :interrupt
|
||||||
(dw/deactivate-ruler)
|
#_(dw/deactivate-ruler)
|
||||||
(dw/select-for-drawing %))]
|
(dw/select-for-drawing %))]
|
||||||
|
|
||||||
[:header#workspace-bar.workspace-bar
|
[:header#workspace-bar.workspace-bar
|
||||||
|
@ -173,13 +169,13 @@
|
||||||
i/ruler]
|
i/ruler]
|
||||||
[:li.tooltip.tooltip-bottom
|
[:li.tooltip.tooltip-bottom
|
||||||
{:alt (tr "workspace.header.grid")
|
{:alt (tr "workspace.header.grid")
|
||||||
:class (when (contains? flags :grid) "selected")
|
:class (when (contains? layout :grid) "selected")
|
||||||
:on-click (partial toggle :grid)}
|
:on-click (partial toggle-layout :grid)}
|
||||||
i/grid]
|
i/grid]
|
||||||
[:li.tooltip.tooltip-bottom
|
[:li.tooltip.tooltip-bottom
|
||||||
{:alt (tr "workspace.header.grid-snap")
|
{:alt (tr "workspace.header.grid-snap")
|
||||||
:class (when (contains? flags :grid-snap) "selected")
|
:class (when (contains? layout :grid-snap) "selected")
|
||||||
:on-click (partial toggle :grid-snap)}
|
:on-click (partial toggle-layout :grid-snap)}
|
||||||
i/grid-snap]]]
|
i/grid-snap]]]
|
||||||
;; [:li.tooltip.tooltip-bottom
|
;; [:li.tooltip.tooltip-bottom
|
||||||
;; {:alt (tr "header.align")}
|
;; {:alt (tr "header.align")}
|
||||||
|
|
|
@ -39,10 +39,10 @@
|
||||||
:ctrl+t #(st/emit! (dw/select-for-drawing :text))
|
:ctrl+t #(st/emit! (dw/select-for-drawing :text))
|
||||||
:esc #(st/emit! :interrupt dw/deselect-all)
|
:esc #(st/emit! :interrupt dw/deselect-all)
|
||||||
:delete #(st/emit! dw/delete-selected)
|
:delete #(st/emit! dw/delete-selected)
|
||||||
:ctrl+up #(st/emit! (dw/order-selected-shapes :up))
|
:ctrl+up #(st/emit! (dw/vertical-order-selected :up))
|
||||||
:ctrl+down #(st/emit! (dw/order-selected-shapes :down))
|
:ctrl+down #(st/emit! (dw/vertical-order-selected :down))
|
||||||
:ctrl+shift+up #(st/emit! (dw/order-selected-shapes :top))
|
:ctrl+shift+up #(st/emit! (dw/vertical-order-selected :top))
|
||||||
:ctrl+shift+down #(st/emit! (dw/order-selected-shapes :bottom))
|
:ctrl+shift+down #(st/emit! (dw/vertical-order-selected :bottom))
|
||||||
:shift+up #(st/emit! (dw/move-selected :up true))
|
:shift+up #(st/emit! (dw/move-selected :up true))
|
||||||
:shift+down #(st/emit! (dw/move-selected :down true))
|
:shift+down #(st/emit! (dw/move-selected :down true))
|
||||||
:shift+right #(st/emit! (dw/move-selected :right true))
|
:shift+right #(st/emit! (dw/move-selected :right true))
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
|
|
||||||
;; Initialize shortcut listener.
|
;; Initialize shortcut listener.
|
||||||
(let [event KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED
|
(let [event KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED
|
||||||
callback #(sink (keyword (.-identifier %)))
|
callback #(sink (keyword (.-identifier %)))
|
||||||
key (events/listen handler event callback)]
|
key (events/listen handler event callback)]
|
||||||
(fn []
|
(fn []
|
||||||
(events/unlistenByKey key)
|
(events/unlistenByKey key)
|
||||||
|
|
|
@ -75,7 +75,8 @@
|
||||||
[props]
|
[props]
|
||||||
(let [history (mf/deref refs/history)
|
(let [history (mf/deref refs/history)
|
||||||
section (mf/use-state :main)
|
section (mf/use-state :main)
|
||||||
close #(st/emit! (dw/toggle-flag :history))
|
;; close #(st/emit! (dw/toggle-flag :history))
|
||||||
|
close (constantly nil)
|
||||||
main? (= @section :main)
|
main? (= @section :main)
|
||||||
pinned? (= @section :pinned)
|
pinned? (= @section :pinned)
|
||||||
show-main #(st/emit! (udh/select-section :main))
|
show-main #(st/emit! (udh/select-section :main))
|
||||||
|
|
|
@ -118,14 +118,14 @@
|
||||||
(st/emit! dw/deselect-all
|
(st/emit! dw/deselect-all
|
||||||
(dw/select-shape id)))))
|
(dw/select-shape id)))))
|
||||||
|
|
||||||
on-drop
|
|
||||||
(fn [item monitor]
|
|
||||||
(st/emit! (dw/commit-shape-order-change (:obj-id item))))
|
|
||||||
|
|
||||||
on-hover
|
on-hover
|
||||||
(fn [item monitor]
|
(fn [item monitor]
|
||||||
(st/emit! (dw/shape-order-change (:obj-id item) index)))
|
(st/emit! (dw/shape-order-change (:obj-id item) index)))
|
||||||
|
|
||||||
|
on-drop
|
||||||
|
(fn [item monitor]
|
||||||
|
(st/emit! (dw/commit-shape-order-change (:obj-id item))))
|
||||||
|
|
||||||
[dprops dnd-ref] (use-sortable
|
[dprops dnd-ref] (use-sortable
|
||||||
{:type (str "layer-item" (:frame-id item))
|
{:type (str "layer-item" (:frame-id item))
|
||||||
:data {:obj-id (:id item)
|
:data {:obj-id (:id item)
|
||||||
|
|
|
@ -40,10 +40,10 @@
|
||||||
nil)])
|
nil)])
|
||||||
|
|
||||||
(mf/defc shape-options-wrapper
|
(mf/defc shape-options-wrapper
|
||||||
[{:keys [shape-id] :as props}]
|
[{:keys [shape-id page-id] :as props}]
|
||||||
(let [shape-iref (mf/use-memo
|
(let [shape-iref (mf/use-memo
|
||||||
{:deps (mf/deps shape-id)
|
{:deps (mf/deps shape-id page-id)
|
||||||
:fn #(-> (l/in [:workspace-data :objects shape-id])
|
:fn #(-> (l/in [:workspace-data page-id :objects shape-id])
|
||||||
(l/derive st/state))})
|
(l/derive st/state))})
|
||||||
shape (mf/deref shape-iref)]
|
shape (mf/deref shape-iref)]
|
||||||
[:& shape-options {:shape shape}]))
|
[:& shape-options {:shape shape}]))
|
||||||
|
@ -61,5 +61,6 @@
|
||||||
[:div.tool-window-content
|
[:div.tool-window-content
|
||||||
[:div.element-options
|
[:div.element-options
|
||||||
(if (= (count selected) 1)
|
(if (= (count selected) 1)
|
||||||
[:& shape-options-wrapper {:shape-id (first selected)}]
|
[:& shape-options-wrapper {:shape-id (first selected)
|
||||||
|
:page-id (:id page)}]
|
||||||
[:& page/options {:page page}])]]]))
|
[:& page/options {:page page}])]]]))
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
(:require
|
(:require
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[goog.events :as events]
|
[goog.events :as events]
|
||||||
|
[goog.object :as gobj]
|
||||||
[potok.core :as ptk]
|
[potok.core :as ptk]
|
||||||
|
[lentes.core :as l]
|
||||||
[rumext.alpha :as mf]
|
[rumext.alpha :as mf]
|
||||||
[uxbox.builtins.icons :as i]
|
[uxbox.builtins.icons :as i]
|
||||||
[uxbox.main.constants :as c]
|
[uxbox.main.constants :as c]
|
||||||
|
@ -141,12 +143,28 @@
|
||||||
;; --- Viewport
|
;; --- Viewport
|
||||||
|
|
||||||
(declare remote-user-cursors)
|
(declare remote-user-cursors)
|
||||||
|
(declare frames)
|
||||||
|
|
||||||
(mf/defc frame-and-shapes
|
(defn- build-workspace-data-iref
|
||||||
{:wrap [mf/wrap-memo]}
|
[page-id]
|
||||||
|
(-> (l/in [:workspace-data page-id])
|
||||||
|
(l/derive st/state)))
|
||||||
|
|
||||||
|
(mf/defrc frames-wrapper
|
||||||
|
;; {:wrap [mf/wrap-memo]}
|
||||||
[props]
|
[props]
|
||||||
(let [data (mf/deref refs/workspace-data)
|
(let [page (gobj/get props "page")
|
||||||
objects (:objects data)
|
page-id (:id page)
|
||||||
|
data-ref (mf/use-memo {:fn #(-> (l/in [:workspace-data page-id])
|
||||||
|
(l/derive st/state))
|
||||||
|
:deps (mf/deps page-id)})
|
||||||
|
data (mf/deref data-ref)]
|
||||||
|
[:& frames {:data data}]))
|
||||||
|
|
||||||
|
(mf/defc frames
|
||||||
|
{:wrap [mf/wrap-memo]}
|
||||||
|
[{:keys [data] :as props}]
|
||||||
|
(let [objects (:objects data)
|
||||||
root (get objects uuid/zero)
|
root (get objects uuid/zero)
|
||||||
shapes (->> (:shapes root)
|
shapes (->> (:shapes root)
|
||||||
(map #(get objects %)))]
|
(map #(get objects %)))]
|
||||||
|
@ -298,7 +316,7 @@
|
||||||
;; {:id "foobar"
|
;; {:id "foobar"
|
||||||
;; :on-render (perf/react-on-profile)}
|
;; :on-render (perf/react-on-profile)}
|
||||||
;; [:& frame-and-shapes]]
|
;; [:& frame-and-shapes]]
|
||||||
[:& frame-and-shapes]
|
[:& frames-wrapper {:page page}]
|
||||||
|
|
||||||
(when (seq selected)
|
(when (seq selected)
|
||||||
[:& selection-handlers {:selected selected
|
[:& selection-handlers {:selected selected
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue