mirror of
https://github.com/penpot/penpot.git
synced 2025-03-25 06:01:46 -05:00
✨ Allow swap over multiple components
This commit is contained in:
parent
93fbb0655f
commit
39ed665b93
10 changed files with 390 additions and 423 deletions
|
@ -539,6 +539,11 @@
|
|||
""
|
||||
(join-path (butlast split)))))
|
||||
|
||||
(defn last-path
|
||||
"Returns the last item of the path."
|
||||
[path]
|
||||
(last (split-path path)))
|
||||
|
||||
(defn compact-name
|
||||
"Append the first item of the path and the name."
|
||||
[path name]
|
||||
|
|
|
@ -324,7 +324,8 @@
|
|||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (->> (wsh/lookup-selected state)
|
||||
(cph/clean-loops objects))
|
||||
(cph/clean-loops objects)
|
||||
(remove #(ctn/has-any-copy-parent? objects (get objects %)))) ;; We don't want to change the structure of component copies
|
||||
components-v2 (features/active-feature? state :components-v2)]
|
||||
(rx/of (add-component2 selected components-v2))))))
|
||||
|
||||
|
@ -337,7 +338,8 @@
|
|||
(let [components-v2 (features/active-feature? state :components-v2)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
selected (->> (wsh/lookup-selected state)
|
||||
(cph/clean-loops objects))
|
||||
(cph/clean-loops objects)
|
||||
(remove #(ctn/has-any-copy-parent? objects (get objects %)))) ;; We don't want to change the structure of component copies
|
||||
added-components (map
|
||||
#(add-component2 [%] components-v2)
|
||||
selected)
|
||||
|
@ -483,6 +485,20 @@
|
|||
|
||||
(rx/of (dch/commit-changes (assoc changes :file-id library-id)))))))
|
||||
|
||||
|
||||
(defn restore-components
|
||||
"Restore multiple deleted component definded by a map with the component id as key and the component library as value"
|
||||
[components-data]
|
||||
(dm/assert! (map? components-data))
|
||||
(ptk/reify ::restore-components
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [undo-id (js/Symbol)]
|
||||
(rx/concat
|
||||
(rx/of (dwu/start-undo-transaction undo-id))
|
||||
(rx/map #(restore-component (val %) (key %)) (rx/from components-data))
|
||||
(rx/of (dwu/commit-undo-transaction undo-id)))))))
|
||||
|
||||
(defn instantiate-component
|
||||
"Create a new shape in the current page, from the component with the given id
|
||||
in the given file library. Then selects the newly created instance."
|
||||
|
@ -534,6 +550,19 @@
|
|||
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
(defn detach-components
|
||||
"Remove all references to components in the shapes with the given ids"
|
||||
[ids]
|
||||
(dm/assert! (seq ids))
|
||||
(ptk/reify ::detach-components
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [undo-id (js/Symbol)]
|
||||
(rx/concat
|
||||
(rx/of (dwu/start-undo-transaction undo-id))
|
||||
(rx/map #(detach-component %) (rx/from ids))
|
||||
(rx/of (dwu/commit-undo-transaction undo-id)))))))
|
||||
|
||||
(def detach-selected-components
|
||||
(ptk/reify ::detach-selected-components
|
||||
ptk/WatchEvent
|
||||
|
@ -621,6 +650,20 @@
|
|||
file))
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
(defn reset-components
|
||||
"Cancels all modifications in the shapes with the given ids"
|
||||
[ids]
|
||||
(dm/assert! (seq ids))
|
||||
(ptk/reify ::reset-components
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [undo-id (js/Symbol)]
|
||||
(rx/concat
|
||||
(rx/of (dwu/start-undo-transaction undo-id))
|
||||
(rx/map #(reset-component %) (rx/from ids))
|
||||
(rx/of (dwu/commit-undo-transaction undo-id)))))))
|
||||
|
||||
|
||||
(defn update-component
|
||||
"Modify the component linked to the shape with the given id, in the
|
||||
current page, so that all attributes of its shapes are equal to the
|
||||
|
@ -734,17 +777,6 @@
|
|||
root-id (:main-instance-id component)]
|
||||
(rx/of (dwt/update-thumbnail file-id page-id root-id))))))
|
||||
|
||||
(defn update-component-in-bulk
|
||||
[shapes file-id]
|
||||
(ptk/reify ::update-component-in-bulk
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [undo-id (js/Symbol)]
|
||||
(rx/concat
|
||||
(rx/of (dwu/start-undo-transaction undo-id))
|
||||
(rx/map #(update-component-sync (:id %) file-id (uuid/next)) (rx/from shapes))
|
||||
(rx/of (dwu/commit-undo-transaction undo-id)))))))
|
||||
|
||||
(defn- find-shape-index
|
||||
[objects id shape-id]
|
||||
(let [object (get objects id)]
|
||||
|
@ -757,7 +789,7 @@
|
|||
second)
|
||||
0)))))
|
||||
|
||||
(defn component-swap
|
||||
(defn- component-swap
|
||||
"Swaps a component with another one"
|
||||
[shape file-id id-new-component]
|
||||
(dm/assert! (uuid? id-new-component))
|
||||
|
@ -782,18 +814,29 @@
|
|||
position
|
||||
page
|
||||
libraries)
|
||||
changes (pcb/change-parent changes (:parent-id shape) [new-shape] index {:component-swap true})
|
||||
undo-id (js/Symbol)]
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(dch/commit-changes changes)
|
||||
changes (pcb/change-parent changes (:parent-id shape) [new-shape] index {:component-swap true})]
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(ptk/data-event :layout/update [(:id new-shape)])
|
||||
(dws/select-shapes (d/ordered-set (:id new-shape)))
|
||||
(dwsh/delete-shapes nil (d/ordered-set (:id shape)) {:component-swap true})
|
||||
(dwu/commit-undo-transaction undo-id)
|
||||
(dwsp/open-specialized-panel :component-swap [(assoc new-shape :parent-id (:parent-id shape))]))))))
|
||||
(dws/select-shape (:id new-shape) true)
|
||||
(dwsh/delete-shapes nil (d/ordered-set (:id shape)) {:component-swap true}))))))
|
||||
|
||||
|
||||
|
||||
(defn component-multi-swap
|
||||
"Swaps several components with another one"
|
||||
[shapes file-id id-new-component]
|
||||
(dm/assert! (seq shapes))
|
||||
(dm/assert! (uuid? id-new-component))
|
||||
(dm/assert! (uuid? file-id))
|
||||
(ptk/reify ::component-multi-swap
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [undo-id (js/Symbol)]
|
||||
(rx/concat
|
||||
(rx/of (dwu/start-undo-transaction undo-id))
|
||||
(rx/map #(component-swap % file-id id-new-component) (rx/from shapes))
|
||||
(rx/of (dwu/commit-undo-transaction undo-id))
|
||||
(rx/of (dwsp/open-specialized-panel :component-swap)))))))
|
||||
|
||||
|
||||
(def valid-asset-types
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
(ns app.main.data.workspace.specialized-panel
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[beicon.core :as rx]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
|
@ -18,14 +20,25 @@
|
|||
(dissoc state :specialized-panel))))
|
||||
|
||||
(defn open-specialized-panel
|
||||
[type shapes]
|
||||
(ptk/reify ::open-specialized-panel
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc state :specialized-panel {:type type :shapes shapes}))
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ stream]
|
||||
(->> stream
|
||||
(rx/filter interrupt?)
|
||||
(rx/take 1)
|
||||
(rx/map (constantly clear-specialized-panel))))))
|
||||
([type]
|
||||
(ptk/reify ::open-specialized-panel-1
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected-ids (wsh/lookup-selected state)
|
||||
selected-shapes (map (d/getf objects) selected-ids)]
|
||||
|
||||
(rx/of (open-specialized-panel type selected-shapes))))))
|
||||
|
||||
([type shapes]
|
||||
(ptk/reify ::open-specialized-panel-2
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc state :specialized-panel {:type type :shapes shapes}))
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ stream]
|
||||
(->> stream
|
||||
(rx/filter interrupt?)
|
||||
(rx/take 1)
|
||||
(rx/map (constantly clear-specialized-panel)))))))
|
||||
|
|
|
@ -12,9 +12,8 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.types.page :as ctp]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.events :as ev]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.shortcuts :as scd]
|
||||
|
@ -25,7 +24,6 @@
|
|||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.shortcuts :as sc]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
|
@ -33,6 +31,7 @@
|
|||
[app.main.ui.components.shape-icon-refactor :as sic]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :refer [tr] :as i18n]
|
||||
[app.util.timers :as timers]
|
||||
|
@ -440,180 +439,40 @@
|
|||
(mf/defc context-menu-component
|
||||
[{:keys [shapes]}]
|
||||
(let [single? (= (count shapes) 1)
|
||||
shapes (filter ctk/instance-head? shapes)
|
||||
components-v2 (features/use-feature :components-v2)
|
||||
|
||||
has-component? (some true? (map #(ctk/instance-head? %) shapes))
|
||||
is-component? (and single? (-> shapes first :component-id some?))
|
||||
in-copy-not-root? (some true? (map #(ctk/in-component-copy-not-head? %) shapes))
|
||||
|
||||
objects (deref refs/workspace-page-objects)
|
||||
touched? (and single? (cph/component-touched? objects (:id (first shapes))))
|
||||
can-update-main? (or (not components-v2) touched?)
|
||||
|
||||
|
||||
|
||||
first-shape (first shapes)
|
||||
{:keys [id component-id component-file]} first-shape
|
||||
main-instance? (ctk/main-instance? first-shape)
|
||||
component-shapes (filter #(ctk/instance-head? %) shapes)
|
||||
|
||||
touched-components (filter #(cph/component-touched? objects (:id %)) component-shapes)
|
||||
can-update-main-of-any? (or (not components-v2) (not-empty touched-components))
|
||||
|
||||
|
||||
current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
local-component? (= component-file current-file-id)
|
||||
remote-components (filter #(not= (:component-file %) current-file-id)
|
||||
component-shapes)
|
||||
|
||||
workspace-data (deref refs/workspace-data)
|
||||
workspace-libraries (deref refs/workspace-libraries)
|
||||
component (if local-component?
|
||||
(ctkl/get-component workspace-data component-id)
|
||||
(ctf/get-component workspace-libraries component-file component-id))
|
||||
is-dangling? (nil? component)
|
||||
lacks-annotation? (nil? (:annotation component))
|
||||
lib-exists? (and (not local-component?)
|
||||
(some? (get workspace-libraries component-file)))
|
||||
|
||||
in-main? (some true? (map #(ctk/main-instance? %) shapes))
|
||||
components-menu-entries (cmm/generate-components-menu-entries shapes components-v2)
|
||||
do-add-component #(st/emit! (dwl/add-component))
|
||||
do-add-multiple-components #(st/emit! (dwl/add-multiple-components))
|
||||
do-detach-component #(st/emit! (dwl/detach-component id))
|
||||
do-detach-component-in-bulk #(st/emit! dwl/detach-selected-components)
|
||||
do-reset-component #(st/emit! (dwl/reset-component id))
|
||||
do-reset-component-in-bulk (fn []
|
||||
(let [undo-id (js/Symbol)]
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(apply st/emit!
|
||||
(map #(dwl/reset-component (:id %)) touched-components))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id))))
|
||||
do-show-component #(st/emit! (dw/go-to-component component-id))
|
||||
do-show-in-assets #(st/emit! (if components-v2
|
||||
(dw/show-component-in-assets component-id)
|
||||
(dw/go-to-component component-id)))
|
||||
create-annotation #(when components-v2
|
||||
(st/emit! (dw/set-annotations-id-for-create (:id first-shape))))
|
||||
|
||||
do-navigate-component-file #(st/emit! (dwl/nav-to-component-file component-file))
|
||||
do-update-component #(st/emit! (dwl/update-component-sync id component-file))
|
||||
do-update-component-in-bulk #(st/emit! (dwl/update-component-in-bulk touched-components component-file))
|
||||
do-restore-component #(st/emit! (dwl/restore-component component-file component-id)
|
||||
(dw/go-to-main-instance nil component-id))
|
||||
|
||||
do-update-remote-component
|
||||
#(st/emit! (modal/show
|
||||
{:type :confirm
|
||||
:message ""
|
||||
:title (tr "modals.update-remote-component.message")
|
||||
:hint (tr "modals.update-remote-component.hint")
|
||||
:cancel-label (tr "modals.update-remote-component.cancel")
|
||||
:accept-label (tr "modals.update-remote-component.accept")
|
||||
:accept-style :primary
|
||||
:on-accept do-update-component}))
|
||||
|
||||
do-update-in-bulk (fn []
|
||||
(if (empty? remote-components)
|
||||
(do-update-component-in-bulk)
|
||||
#(st/emit! (modal/show
|
||||
{:type :confirm
|
||||
:message ""
|
||||
:title (tr "modals.update-remote-component-in-bulk.message")
|
||||
:hint (tr "modals.update-remote-component-in-bulk.hint")
|
||||
:items remote-components
|
||||
:cancel-label (tr "modals.update-remote-component.cancel")
|
||||
:accept-label (tr "modals.update-remote-component.accept")
|
||||
:accept-style :primary
|
||||
:on-accept do-update-component-in-bulk}))))]
|
||||
do-add-multiple-components #(st/emit! (dwl/add-multiple-components))]
|
||||
[:*
|
||||
[:*
|
||||
(when (or (not in-copy-not-root?) (and has-component? (not single?)))
|
||||
[:& menu-separator])
|
||||
(when-not in-copy-not-root?
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.create-component")
|
||||
:shortcut (sc/get-tooltip :create-component)
|
||||
:on-click do-add-component}])
|
||||
(when-not (or single? in-copy-not-root?)
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.create-multiple-components")
|
||||
:on-click do-add-multiple-components}])
|
||||
(when (and has-component? (not single?))
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.detach-instances-in-bulk")
|
||||
:shortcut (sc/get-tooltip :detach-component)
|
||||
:on-click do-detach-component-in-bulk}])
|
||||
(when (and has-component? can-update-main-of-any? (not single?))
|
||||
[:* [:& menu-entry {:title (tr "workspace.shape.menu.update-components-in-bulk")
|
||||
:on-click do-update-in-bulk}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.reset-overrides")
|
||||
:on-click do-reset-component-in-bulk}]]
|
||||
)]
|
||||
|
||||
(when is-component?
|
||||
;; WARNING: this menu is the same as the context menu at the sidebar.
|
||||
;; If you change it, you must change equally the file
|
||||
;; app/main/ui/workspace/sidebar/options/menus/component.cljs
|
||||
(when-not in-main?
|
||||
[:*
|
||||
[:& menu-separator]
|
||||
(if main-instance?
|
||||
[:*
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.show-in-assets")
|
||||
:on-click do-show-in-assets}]
|
||||
(when (and components-v2 local-component? lacks-annotation?)
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.create-annotation")
|
||||
:on-click create-annotation}])]
|
||||
(if local-component?
|
||||
(if is-dangling?
|
||||
[:*
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.detach-instance")
|
||||
:shortcut (sc/get-tooltip :detach-component)
|
||||
:on-click do-detach-component}]
|
||||
(when can-update-main?
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.reset-overrides")
|
||||
:on-click do-reset-component}])
|
||||
(when components-v2
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.restore-main")
|
||||
:on-click do-restore-component}])]
|
||||
[:*
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.detach-instance")
|
||||
:shortcut (sc/get-tooltip :detach-component)
|
||||
:on-click do-detach-component}]
|
||||
(when can-update-main?
|
||||
[:*
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.reset-overrides")
|
||||
:on-click do-reset-component}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.update-main")
|
||||
:on-click do-update-component}]])
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.show-main")
|
||||
:on-click do-show-component}]])
|
||||
(if is-dangling?
|
||||
[:*
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.detach-instance")
|
||||
:shortcut (sc/get-tooltip :detach-component)
|
||||
:on-click do-detach-component}]
|
||||
(when can-update-main?
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.reset-overrides")
|
||||
:on-click do-reset-component}])
|
||||
(when (and components-v2 lib-exists?)
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.restore-main")
|
||||
:on-click do-restore-component}])]
|
||||
[:*
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.detach-instance")
|
||||
:shortcut (sc/get-tooltip :detach-component)
|
||||
:on-click do-detach-component}]
|
||||
(when can-update-main?
|
||||
[:*
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.reset-overrides")
|
||||
:on-click do-reset-component}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.update-main")
|
||||
:on-click do-update-remote-component}]])
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.go-main")
|
||||
:on-click do-navigate-component-file}]])))])
|
||||
[:& menu-separator]]))
|
||||
(if single?
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.create-component")
|
||||
:shortcut (sc/get-tooltip :create-component)
|
||||
:on-click do-add-component}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.create-multiple-components")
|
||||
:on-click do-add-multiple-components}])])
|
||||
|
||||
(when (seq components-menu-entries)
|
||||
[:*
|
||||
[:& menu-separator]
|
||||
(for [entry components-menu-entries :when (not (nil? entry))]
|
||||
[:& menu-entry {:key (uuid/next)
|
||||
:title (tr (:msg entry))
|
||||
:shortcut (when (contains? entry :shortcut) (sc/get-tooltip (:shortcut entry)))
|
||||
:on-click (:action entry)}])])]))
|
||||
|
||||
(mf/defc context-menu-delete
|
||||
[]
|
||||
(let [do-delete #(st/emit! (dw/delete-selected))]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.delete")
|
||||
[:*
|
||||
[:& menu-separator]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.delete")
|
||||
:shortcut (sc/get-tooltip :delete)
|
||||
:on-click do-delete}]))
|
||||
:on-click do-delete}]]))
|
||||
|
||||
(mf/defc shape-context-menu
|
||||
{::mf/wrap [mf/memo]}
|
||||
|
|
|
@ -11,8 +11,11 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.thumbnails :as dwt]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.refs :as refs]
|
||||
|
@ -25,6 +28,7 @@
|
|||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.dom.dnd :as dnd]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.strings :refer [matches-search]]
|
||||
[app.util.timers :as ts]
|
||||
[cljs.spec.alpha :as s]
|
||||
|
@ -290,3 +294,131 @@
|
|||
:class (dom/classnames (css :thumbnail) true)}]
|
||||
[:& component-svg {:root-shape root-shape
|
||||
:objects (:objects container)}])))
|
||||
|
||||
|
||||
(defn generate-components-menu-entries
|
||||
[shapes components-v2]
|
||||
(let [multi (> (count shapes) 1)
|
||||
copies (filter ctk/in-component-copy? shapes)
|
||||
|
||||
current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
objects (deref refs/workspace-page-objects)
|
||||
workspace-data (deref refs/workspace-data)
|
||||
workspace-libraries (deref refs/workspace-libraries)
|
||||
current-file {:id current-file-id :data workspace-data}
|
||||
|
||||
find-component #(ctf/resolve-component % current-file workspace-libraries)
|
||||
|
||||
local-or-exists (fn [shape]
|
||||
(let [library-id (:component-file shape)]
|
||||
(or (= library-id current-file-id)
|
||||
(some? (get workspace-libraries library-id)))))
|
||||
|
||||
restorable-copies (->> copies
|
||||
(filter #(nil? (find-component %)))
|
||||
(filter #(local-or-exists %)))
|
||||
|
||||
|
||||
touched-components (filter #(cph/component-touched? objects (:id %)) copies)
|
||||
|
||||
can-reset-overrides? (or (not components-v2) (seq touched-components))
|
||||
|
||||
|
||||
;; For when it's only one shape
|
||||
shape (first shapes)
|
||||
id (:id shape)
|
||||
main-instance? (if components-v2 (ctk/main-instance? shape) true)
|
||||
|
||||
component-id (:component-id shape)
|
||||
library-id (:component-file shape)
|
||||
|
||||
local-component? (= library-id current-file-id)
|
||||
component (find-component shape)
|
||||
lacks-annotation? (nil? (:annotation shape))
|
||||
is-dangling? (nil? component)
|
||||
|
||||
can-update-main? (or (not components-v2)
|
||||
(and
|
||||
(not main-instance?)
|
||||
(cph/component-touched? objects (:id shape))))
|
||||
|
||||
do-detach-component
|
||||
#(st/emit! (dwl/detach-components (map :id copies)))
|
||||
|
||||
do-reset-component
|
||||
#(st/emit! (dwl/reset-components (map :id touched-components)))
|
||||
|
||||
do-restore-component
|
||||
#(let [;; Extract a map of component-id -> component-file in order to avoid duplicates
|
||||
comps-to-restore (reduce (fn [id-file-map {:keys [component-id component-file]}]
|
||||
(assoc id-file-map component-id component-file))
|
||||
{}
|
||||
restorable-copies)]
|
||||
|
||||
(st/emit! (dwl/restore-components comps-to-restore)
|
||||
(when (= 1 (count comps-to-restore))
|
||||
(dw/go-to-main-instance (val (first comps-to-restore)) (key (first comps-to-restore))))))
|
||||
|
||||
do-update-component-sync
|
||||
#(st/emit! (dwl/update-component-sync id library-id))
|
||||
|
||||
do-update-remote-component
|
||||
(fn []
|
||||
(st/emit! (modal/show
|
||||
{:type :confirm
|
||||
:message ""
|
||||
:title (tr "modals.update-remote-component.message")
|
||||
:hint (tr "modals.update-remote-component.hint")
|
||||
:cancel-label (tr "modals.update-remote-component.cancel")
|
||||
:accept-label (tr "modals.update-remote-component.accept")
|
||||
:accept-style :primary
|
||||
:on-accept do-update-component-sync})))
|
||||
|
||||
do-update-component
|
||||
#(if local-component?
|
||||
(do-update-component-sync)
|
||||
(do-update-remote-component))
|
||||
|
||||
do-show-local-component
|
||||
#(st/emit! (dw/go-to-component component-id))
|
||||
|
||||
do-show-in-assets
|
||||
#(st/emit! (if components-v2
|
||||
(dw/show-component-in-assets component-id)
|
||||
(dw/go-to-component component-id)))
|
||||
do-create-annotation
|
||||
#(st/emit! (dw/set-annotations-id-for-create id))
|
||||
|
||||
do-navigate-component-file
|
||||
#(st/emit! (dwl/nav-to-component-file library-id))
|
||||
|
||||
do-show-component
|
||||
#(if local-component?
|
||||
(do-show-local-component)
|
||||
(do-navigate-component-file))
|
||||
|
||||
menu-entries [(when (and (not multi) main-instance?)
|
||||
{:msg "workspace.shape.menu.show-in-assets"
|
||||
:action do-show-in-assets})
|
||||
(when (and (not multi) main-instance? local-component? lacks-annotation? components-v2)
|
||||
{:msg "workspace.shape.menu.create-annotation"
|
||||
:action do-create-annotation})
|
||||
(when (seq copies)
|
||||
{:msg (if (> (count copies) 1)
|
||||
"workspace.shape.menu.detach-instances-in-bulk"
|
||||
"workspace.shape.menu.detach-instance")
|
||||
:action do-detach-component
|
||||
:shortcut :detach-component})
|
||||
(when can-reset-overrides?
|
||||
{:msg "workspace.shape.menu.reset-overrides"
|
||||
:action do-reset-component})
|
||||
(when (and (seq restorable-copies) components-v2)
|
||||
{:msg "workspace.shape.menu.restore-main"
|
||||
:action do-restore-component})
|
||||
(when (and (not multi) (not main-instance?) (not is-dangling?))
|
||||
{:msg "workspace.shape.menu.show-main"
|
||||
:action do-show-component})
|
||||
(when (and (not multi) can-update-main? (not is-dangling?))
|
||||
{:msg "workspace.shape.menu.update-main"
|
||||
:action do-update-component})]]
|
||||
(filter (complement nil?) menu-entries)))
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [panel]}]
|
||||
(when (= (:type panel) :component-swap)
|
||||
[:& component-menu {:shape (first (:shapes panel)) :swap-opened? true}]))
|
||||
[:& component-menu {:shapes (:shapes panel) :swap-opened? true}]))
|
||||
|
||||
|
||||
(mf/defc options-content
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
(:require
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.modal :as modal]
|
||||
|
@ -30,13 +29,10 @@
|
|||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def component-attrs [:component-id :component-file :shape-ref :main-instance :annotation])
|
||||
|
||||
|
||||
(mf/defc component-annotation
|
||||
[{:keys [id values shape component] :as props}]
|
||||
(let [main-instance? (:main-instance values)
|
||||
component-id (:component-id values)
|
||||
[{:keys [id shape component] :as props}]
|
||||
(let [main-instance? (:main-instance shape)
|
||||
component-id (:component-id shape)
|
||||
annotation (:annotation component)
|
||||
editing? (mf/use-state false)
|
||||
invalid-text? (mf/use-state (or (nil? annotation)(str/empty? annotation)))
|
||||
|
@ -150,7 +146,8 @@
|
|||
|
||||
(mf/defc component-swap
|
||||
[{:keys [shapes] :as props}]
|
||||
(let [shape (first shapes)
|
||||
(let [single? (= 1 (count shapes))
|
||||
shape (first shapes)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
workspace-file (deref refs/workspace-file)
|
||||
|
@ -158,10 +155,35 @@
|
|||
workspace-libraries (deref refs/workspace-libraries)
|
||||
objects (deref refs/workspace-page-objects)
|
||||
libraries (assoc workspace-libraries current-file-id (assoc workspace-file :data workspace-data))
|
||||
every-same-file? (every? #(= (:component-file shape) (:component-file %)) shapes)
|
||||
current-comp-id (when (every? #(= (:component-id shape) (:component-id %)) shapes)
|
||||
(:component-id shape))
|
||||
|
||||
file-id (if every-same-file?
|
||||
(:component-file shape)
|
||||
current-file-id)
|
||||
paths (->> shapes
|
||||
(map :name)
|
||||
(map cph/split-path)
|
||||
(map butlast))
|
||||
|
||||
find-common-path (fn common-path [path n]
|
||||
(let [current (nth (first paths) n nil)]
|
||||
(if (or (nil? current)
|
||||
(not (every? #(= current (nth % n nil)) paths)))
|
||||
path
|
||||
(common-path (conj path current) (inc n)))))
|
||||
|
||||
path (if single?
|
||||
(cph/butlast-path (:name shape))
|
||||
(cph/join-path (if (not every-same-file?)
|
||||
""
|
||||
(find-common-path [] 0))))
|
||||
|
||||
filters* (mf/use-state
|
||||
{:term ""
|
||||
:file-id (:component-file shape)
|
||||
:path (cph/butlast-path (:name shape))})
|
||||
:file-id file-id
|
||||
:path path})
|
||||
filters (deref filters*)
|
||||
|
||||
components (-> (get-in libraries [(:file-id filters) :data :components])
|
||||
|
@ -171,11 +193,21 @@
|
|||
components
|
||||
(filter #(str/includes? (str/lower (:name %)) (str/lower (:term filters))) components))
|
||||
|
||||
groups (->> (map :path components)
|
||||
(filter #(= (cph/butlast-path (:path %)) (:path filters)))
|
||||
(remove str/empty?)
|
||||
distinct
|
||||
(map #(hash-map :name %)))
|
||||
get-subgroups (fn [path]
|
||||
(let [split-path (cph/split-path path)]
|
||||
(reduce (fn [acc dir]
|
||||
(conj acc (str (last acc) " / " dir)))
|
||||
[(first split-path)] (rest split-path))))
|
||||
|
||||
groups (->> components
|
||||
(map :path)
|
||||
(map get-subgroups)
|
||||
(apply concat)
|
||||
(remove str/empty?)
|
||||
(remove nil?)
|
||||
distinct
|
||||
(filter #(= (cph/butlast-path %) (:path filters)))
|
||||
sort)
|
||||
|
||||
components (filter #(= (:path %) (:path filters)) components)
|
||||
|
||||
|
@ -191,7 +223,13 @@
|
|||
ids)]
|
||||
(get-comps-ids (get objects (:parent-id shape)) ids))))
|
||||
|
||||
parent-components (set (get-comps-ids (get objects (:parent-id shape)) []))
|
||||
parent-components (->> shapes
|
||||
(map :parent-id)
|
||||
(map #(get objects %))
|
||||
(map #(get-comps-ids % []))
|
||||
(apply concat)
|
||||
set)
|
||||
|
||||
|
||||
on-library-change
|
||||
(mf/use-fn
|
||||
|
@ -279,63 +317,67 @@
|
|||
:key (:id item)
|
||||
:on-click #(when-not loop?
|
||||
(st/emit!
|
||||
(dwl/component-swap shape (:file-id filters) (:id item))))}
|
||||
(dwl/component-multi-swap shapes (:file-id filters) (:id item))))}
|
||||
[:& cmm/component-item-thumbnail {:file-id (:file-id item)
|
||||
:root-shape root-shape
|
||||
:component item
|
||||
:container container}]
|
||||
[:span.component-name
|
||||
{:class (stl/css-case :selected (= (:id item) (:component-id shape)))}
|
||||
{:class (stl/css-case :selected (= (:id item) current-comp-id))}
|
||||
(:name item)]])
|
||||
[:div.component-group {:key (uuid/next) :on-click #(on-enter-group (:name item))}
|
||||
[:span (:name item)]
|
||||
[:div.component-group {:key (uuid/next) :on-click #(on-enter-group item)}
|
||||
[:span (cph/last-path item)]
|
||||
[:span i/arrow-slide]]))]]]))
|
||||
|
||||
(mf/defc component-ctx-menu
|
||||
[{:keys [menu-entries on-close show type] :as props}]
|
||||
(case type
|
||||
:context-menu
|
||||
[:& context-menu {:on-close on-close
|
||||
:show show
|
||||
:options
|
||||
(vec (for [entry menu-entries :when (not (nil? entry))]
|
||||
[(tr (:msg entry)) (:action entry)]))}]
|
||||
:dropdown
|
||||
[:& dropdown {:show show :on-close on-close}
|
||||
[:ul {:class (stl/css :custom-select-dropdown)}
|
||||
(for [entry menu-entries :when (not (nil? entry))]
|
||||
[:li {:key (uuid/next)
|
||||
:class (stl/css :dropdown-element)
|
||||
:on-click (:action entry)}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr (:msg entry))]])]]))
|
||||
|
||||
|
||||
(mf/defc component-menu
|
||||
[{:keys [shape swap-opened?] :as props}]
|
||||
(let [[ids values] [[(:id shape)] (select-keys shape component-attrs)]
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
[{:keys [shapes swap-opened?] :as props}]
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
workspace-data (deref refs/workspace-data)
|
||||
workspace-libraries (deref refs/workspace-libraries)
|
||||
|
||||
objects (deref refs/workspace-page-objects)
|
||||
touched? (cph/component-touched? objects (:id shape))
|
||||
can-update-main? (or (not components-v2) touched?)
|
||||
|
||||
id (first ids)
|
||||
state* (mf/use-state {:show-content true
|
||||
:menu-open false})
|
||||
state (deref state*)
|
||||
open? (:show-content state)
|
||||
menu-open? (:menu-open state)
|
||||
|
||||
shapes (filter ctk/instance-head? shapes)
|
||||
multi (> (count shapes) 1)
|
||||
copies (filter ctk/in-component-copy? shapes)
|
||||
can-swap? (and components-v2 (seq copies))
|
||||
|
||||
;; For when it's only one shape
|
||||
shape (first shapes)
|
||||
id (:id shape)
|
||||
shape-name (:name shape)
|
||||
component (ctf/resolve-component shape {:id current-file-id :data workspace-data} workspace-libraries)
|
||||
main-instance? (if components-v2 (ctk/main-instance? shape) true)
|
||||
|
||||
toggle-content
|
||||
(mf/use-fn #(swap! state* update :show-content not))
|
||||
|
||||
shape-name (:name shape)
|
||||
component-id (:component-id values)
|
||||
library-id (:component-file values)
|
||||
show? (some? component-id)
|
||||
main-instance? (if components-v2
|
||||
(ctk/main-instance? values)
|
||||
true)
|
||||
can-swap? (and components-v2 (not main-instance?))
|
||||
main-component? (:main-instance values)
|
||||
lacks-annotation? (nil? (:annotation values))
|
||||
|
||||
local-component? (= library-id current-file-id)
|
||||
|
||||
workspace-data (deref refs/workspace-data)
|
||||
workspace-libraries (deref refs/workspace-libraries)
|
||||
component (if local-component?
|
||||
(ctkl/get-component workspace-data component-id)
|
||||
(ctf/get-component workspace-libraries library-id component-id))
|
||||
is-dangling? (nil? component)
|
||||
lib-exists? (and (not local-component?)
|
||||
(some? (get workspace-libraries library-id)))
|
||||
|
||||
on-menu-click
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
|
@ -347,37 +389,10 @@
|
|||
(mf/use-callback
|
||||
#(swap! state* assoc :menu-open false))
|
||||
|
||||
do-detach-component
|
||||
#(st/emit! (dwl/detach-component id))
|
||||
menu-entries (cmm/generate-components-menu-entries shapes components-v2)
|
||||
show-menu? (seq menu-entries)]
|
||||
|
||||
do-reset-component
|
||||
#(st/emit! (dwl/reset-component id))
|
||||
|
||||
do-update-component
|
||||
#(st/emit! (dwl/update-component-sync id library-id))
|
||||
|
||||
do-restore-component
|
||||
#(st/emit! (dwl/restore-component library-id component-id)
|
||||
(dw/go-to-main-instance nil component-id))
|
||||
|
||||
do-update-remote-component
|
||||
#(st/emit! (modal/show
|
||||
{:type :confirm
|
||||
:message ""
|
||||
:title (tr "modals.update-remote-component.message")
|
||||
:hint (tr "modals.update-remote-component.hint")
|
||||
:cancel-label (tr "modals.update-remote-component.cancel")
|
||||
:accept-label (tr "modals.update-remote-component.accept")
|
||||
:accept-style :primary
|
||||
:on-accept do-update-component}))
|
||||
|
||||
do-show-component #(st/emit! (dw/go-to-component component-id))
|
||||
do-show-in-assets #(st/emit! (if components-v2
|
||||
(dw/show-component-in-assets component-id)
|
||||
(dw/go-to-component component-id)))
|
||||
do-create-annotation #(st/emit! (dw/set-annotations-id-for-create id))
|
||||
do-navigate-component-file #(st/emit! (dwl/nav-to-component-file library-id))]
|
||||
(when show?
|
||||
(when (seq shapes)
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
|
@ -403,94 +418,12 @@
|
|||
:on-click on-menu-click}
|
||||
i/menu-refactor]
|
||||
|
||||
[:& dropdown {:show menu-open?
|
||||
:on-close on-menu-close}
|
||||
[:ul {:class (stl/css :custom-select-dropdown)}
|
||||
(if main-component?
|
||||
[:*
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-show-in-assets}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.show-in-assets")]]
|
||||
(when (and components-v2 local-component? lacks-annotation?)
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-create-annotation}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.create-annotation")]])]
|
||||
|
||||
(if local-component?
|
||||
(if is-dangling?
|
||||
[:*
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-detach-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.detach-instance")]]
|
||||
(when can-update-main?
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-reset-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.reset-overrides")]])
|
||||
(when components-v2
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-restore-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.restore-main")]])]
|
||||
|
||||
[:*
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-detach-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.detach-instance")]]
|
||||
(when can-update-main?
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-reset-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.reset-overrides")]]
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-update-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.update-main")]])
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-show-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.show-main")]]])
|
||||
(if is-dangling?
|
||||
[:*
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-detach-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.detach-instance")]]
|
||||
(when can-update-main?
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-reset-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.reset-overrides")]])
|
||||
|
||||
(when (and components-v2 lib-exists?)
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-restore-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.restore-main")]])]
|
||||
[:*
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-detach-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.detach-instance")]]
|
||||
(when can-update-main?
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-reset-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.reset-overrides")]]
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-update-remote-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.update-main")]])
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-navigate-component-file}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.go-main")]]])))]]]]
|
||||
(when components-v2
|
||||
[:& component-annotation {:id id :values values :shape shape :component component}])])]
|
||||
[:& component-ctx-menu {:show menu-open?
|
||||
:on-close on-menu-close
|
||||
:menu-entries menu-entries
|
||||
:type :dropdown}]]]
|
||||
(when (and (not multi) components-v2)
|
||||
[:& component-annotation {:id id :shape shape :component component}])])]
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title {:class (stl/css-case :back swap-opened?)
|
||||
|
@ -500,63 +433,37 @@
|
|||
[:span
|
||||
i/arrow-slide])
|
||||
[:span (tr "workspace.options.component")]]
|
||||
[:span (if main-instance?
|
||||
(tr "workspace.options.component.main")
|
||||
(tr "workspace.options.component.copy"))]]
|
||||
(when-not multi
|
||||
[:span (if main-instance?
|
||||
(tr "workspace.options.component.main")
|
||||
(tr "workspace.options.component.copy"))])]
|
||||
[:div.element-set-content
|
||||
[:div.row-flex.component-row
|
||||
{:class (stl/css-case :copy can-swap?)
|
||||
:on-click #(when can-swap? (st/emit! (dwsp/open-specialized-panel :component-swap [shape])))}
|
||||
(if main-instance?
|
||||
i/component
|
||||
i/component-copy)
|
||||
[:div.component-name shape-name]
|
||||
[:div.row-actions
|
||||
{:on-click on-menu-click}
|
||||
i/actions
|
||||
;; WARNING: this menu is the same as the shape context menu.
|
||||
;; If you change it, you must change equally the file
|
||||
;; app/main/ui/workspace/context_menu.cljs
|
||||
[:& context-menu {:on-close on-menu-close
|
||||
:show menu-open?
|
||||
:options (if main-component?
|
||||
[[(tr "workspace.shape.menu.show-in-assets") do-show-in-assets]
|
||||
(when (and components-v2 local-component? lacks-annotation?)
|
||||
[(tr "workspace.shape.menu.create-annotation") do-create-annotation])]
|
||||
(if local-component?
|
||||
(if is-dangling?
|
||||
[[(tr "workspace.shape.menu.detach-instance") do-detach-component]
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.reset-overrides") do-reset-component])
|
||||
(when components-v2
|
||||
[(tr "workspace.shape.menu.restore-main") do-restore-component])]
|
||||
:on-click #(when can-swap? (st/emit! (dwsp/open-specialized-panel :component-swap shapes)))}
|
||||
(if multi
|
||||
i/component-copy
|
||||
(if main-instance?
|
||||
i/component
|
||||
i/component-copy))
|
||||
[:div.component-name (if multi
|
||||
(tr "settings.multiple")
|
||||
shape-name)]
|
||||
(when show-menu?
|
||||
[:div.row-actions
|
||||
{:on-click on-menu-click}
|
||||
i/actions
|
||||
[:& component-ctx-menu {:on-close on-menu-close
|
||||
:show menu-open?
|
||||
:menu-entries menu-entries
|
||||
:type :context-menu}]])
|
||||
|
||||
[[(tr "workspace.shape.menu.detach-instance") do-detach-component]
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.reset-overrides") do-reset-component])
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.update-main") do-update-component])
|
||||
[(tr "workspace.shape.menu.show-main") do-show-component]])
|
||||
|
||||
(if is-dangling?
|
||||
[[(tr "workspace.shape.menu.detach-instance") do-detach-component]
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.reset-overrides") do-reset-component])
|
||||
(when (and components-v2 lib-exists?)
|
||||
[(tr "workspace.shape.menu.restore-main") do-restore-component])]
|
||||
[[(tr "workspace.shape.menu.detach-instance") do-detach-component]
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.reset-overrides") do-reset-component])
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.update-main") do-update-remote-component])
|
||||
[(tr "workspace.shape.menu.go-main") do-navigate-component-file]])))}]]
|
||||
|
||||
(when can-swap?
|
||||
(when (and can-swap? (not multi))
|
||||
[:div.component-parent-name
|
||||
(cph/merge-path-item (:path component) (:name component))])]
|
||||
|
||||
(when swap-opened?
|
||||
[:& component-swap {:shapes [shape]}])
|
||||
[:& component-swap {:shapes shapes}])
|
||||
|
||||
(when (and (not swap-opened?) components-v2)
|
||||
[:& component-annotation {:id id :values values :shape shape :component component}])]]))))
|
||||
(when (and (not swap-opened?) (not multi) components-v2)
|
||||
[:& component-annotation {:id id :shape shape :component component}])]]))))
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
:values measure-values
|
||||
:type type
|
||||
:shape shape}]
|
||||
[:& component-menu {:shape shape}]
|
||||
[:& component-menu {:shapes [shape]}]
|
||||
(when (or (not is-layout-child?) is-layout-child-absolute?)
|
||||
[:& constraints-menu {:ids ids
|
||||
:values constraint-values}])
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
:options true)}
|
||||
[:& layer-menu {:type type :ids layer-ids :values layer-values}]
|
||||
[:& measures-menu {:type type :ids measure-ids :values measure-values :shape shape}]
|
||||
[:& component-menu {:shape shape}] ;;remove this in components-v2
|
||||
[:& component-menu {:shapes [shape]}] ;;remove this in components-v2
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values :multiple false}]
|
||||
|
||||
(when (and (= (count ids) 1) is-layout-child? is-grid-parent?)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.text :as txt]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.shape.attrs :refer [editable-attrs]]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
|
@ -19,6 +20,7 @@
|
|||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-attrs blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.component :refer [component-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.exports :refer [exports-attrs exports-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]]
|
||||
|
@ -342,7 +344,9 @@
|
|||
(get-attrs shapes objects-no-measures :stroke)
|
||||
(get-attrs shapes objects-no-measures :exports)
|
||||
(get-attrs shapes objects-no-measures :layout-container)
|
||||
(get-attrs shapes objects-no-measures :layout-item)])))]
|
||||
(get-attrs shapes objects-no-measures :layout-item)])))
|
||||
|
||||
components (filter ctk/instance-head? shapes)]
|
||||
|
||||
[:div {:class (stl/css-case new-css-system
|
||||
:options true)}
|
||||
|
@ -352,8 +356,12 @@
|
|||
(when-not (empty? measure-ids)
|
||||
[:& measures-menu {:type type :all-types all-types :ids measure-ids :values measure-values :shape shapes}])
|
||||
|
||||
(when-not (empty? components)
|
||||
[:& component-menu {:shapes components}])
|
||||
|
||||
[:& layout-container-menu {:type type :ids layout-container-ids :values layout-container-values :multiple true}]
|
||||
|
||||
|
||||
(when (or is-layout-child? has-flex-layout-container?)
|
||||
[:& layout-item-menu
|
||||
{:type type
|
||||
|
|
Loading…
Add table
Reference in a new issue