mirror of
https://github.com/penpot/penpot.git
synced 2025-01-04 13:50:12 -05:00
Merge pull request #5443 from penpot/niwinz-enhancements-1
✨ Several improvements
This commit is contained in:
commit
25a672b958
39 changed files with 420 additions and 410 deletions
|
@ -20,8 +20,8 @@
|
|||
:git/url "https://github.com/funcool/beicon.git"}
|
||||
|
||||
funcool/rumext
|
||||
{:git/tag "v2.14"
|
||||
:git/sha "0016623"
|
||||
{:git/tag "v2.15"
|
||||
:git/sha "28783a7"
|
||||
:git/url "https://github.com/funcool/rumext.git"}
|
||||
|
||||
instaparse/instaparse {:mvn/version "1.5.0"}
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
[app.main.ui.confirm]
|
||||
[app.main.ui.css-cursors :as cur]
|
||||
[app.main.ui.delete-shared]
|
||||
[app.main.ui.modal :refer [modal]]
|
||||
[app.main.ui.routes :as rt]
|
||||
[app.main.worker :as worker]
|
||||
[app.plugins :as plugins]
|
||||
|
@ -52,14 +51,9 @@
|
|||
(let [el (dom/get-element "app")]
|
||||
(mf/create-root el)))
|
||||
|
||||
(defonce modal-root
|
||||
(let [el (dom/get-element "modal")]
|
||||
(mf/create-root el)))
|
||||
|
||||
(defn init-ui
|
||||
[]
|
||||
(mf/render! app-root (mf/element ui/app))
|
||||
(mf/render! modal-root (mf/element modal)))
|
||||
(mf/render! app-root (mf/element ui/app)))
|
||||
|
||||
(defn- initialize-profile
|
||||
"Event used mainly on application bootstrap; it fetches the profile
|
||||
|
@ -132,9 +126,7 @@
|
|||
;; The hard flag will force to unmount the whole UI and will redraw every component
|
||||
(when hard?
|
||||
(mf/unmount! app-root)
|
||||
(mf/unmount! modal-root)
|
||||
(set! app-root (mf/create-root (dom/get-element "app")))
|
||||
(set! modal-root (mf/create-root (dom/get-element "modal"))))
|
||||
(set! app-root (mf/create-root (dom/get-element "app"))))
|
||||
(st/emit! (ev/initialize))
|
||||
(init-ui)))
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
(let [current-file-id (get state :current-file-id)
|
||||
path (if (= file-id current-file-id)
|
||||
[:workspace-data]
|
||||
[:workspace-libraries file-id :data])
|
||||
[:libraries file-id :data])
|
||||
|
||||
undo-changes (if pending
|
||||
(->> pending
|
||||
|
@ -159,14 +159,14 @@
|
|||
(let [file (:workspace-file state)]
|
||||
(if (= (:id file) file-id)
|
||||
(:revn file)
|
||||
(dm/get-in state [:workspace-libraries file-id :revn]))))
|
||||
(dm/get-in state [:libraries file-id :revn]))))
|
||||
|
||||
(defn- resolve-file-vern
|
||||
[state file-id]
|
||||
(let [file (:workspace-file state)]
|
||||
(if (= (:id file) file-id)
|
||||
(:vern file)
|
||||
(dm/get-in state [:workspace-libraries file-id :vern]))))
|
||||
(dm/get-in state [:libraries file-id :vern]))))
|
||||
|
||||
(defn commit-changes
|
||||
"Schedules a list of changes to execute now, and add the corresponding undo changes to
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
(if-let [current-file-id (:current-file-id state)]
|
||||
(if (= file-id current-file-id)
|
||||
(update-in state [:workspace-file :revn] max revn)
|
||||
(d/update-in-when state [:workspace-libraries file-id :revn] max revn))
|
||||
(d/update-in-when state [:libraries file-id :revn] max revn))
|
||||
state))
|
||||
|
||||
ptk/EffectEvent
|
||||
|
|
|
@ -172,7 +172,7 @@
|
|||
(ptk/reify ::libraries-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc state :workspace-libraries (d/index-by :id libraries)))
|
||||
(assoc state :libraries (d/index-by :id libraries)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
|
@ -363,7 +363,7 @@
|
|||
:workspace-data
|
||||
:workspace-editor-state
|
||||
:workspace-file
|
||||
:workspace-libraries
|
||||
:libraries
|
||||
:workspace-media-objects
|
||||
:workspace-persistence
|
||||
:workspace-presence
|
||||
|
@ -572,7 +572,7 @@
|
|||
(let [file-data
|
||||
(if (= file-id (:current-file-id state))
|
||||
(:workspace-data state)
|
||||
(get-in state [:workspace-libraries file-id :data]))
|
||||
(get-in state [:libraries file-id :data]))
|
||||
|
||||
changes
|
||||
(-> (pcb/empty-changes it)
|
||||
|
|
|
@ -59,11 +59,11 @@
|
|||
;; Change this to :info :debug or :trace to debug this module, or :warn to reset to default
|
||||
(log/set-level! :warn)
|
||||
|
||||
(defn- pretty-file
|
||||
(defn- debug-pretty-file
|
||||
[file-id state]
|
||||
(if (= file-id (:current-file-id state))
|
||||
"<local>"
|
||||
(str "<" (get-in state [:workspace-libraries file-id :name]) ">")))
|
||||
(str "<" (get-in state [:libraries file-id :name]) ">")))
|
||||
|
||||
(defn- log-changes
|
||||
[changes file]
|
||||
|
@ -760,9 +760,9 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update-in [:workspace-libraries library-id]
|
||||
(update-in [:libraries library-id]
|
||||
assoc :modified-at modified-at :revn revn)
|
||||
(d/update-in-when [:workspace-libraries library-id :data]
|
||||
(d/update-in-when [:libraries library-id :data]
|
||||
ch/process-changes changes)))
|
||||
|
||||
ptk/WatchEvent
|
||||
|
@ -898,7 +898,7 @@
|
|||
current-file? (= current-file-id file-id)
|
||||
data (if current-file?
|
||||
(get state :workspace-data)
|
||||
(get-in state [:workspace-libraries file-id :data]))
|
||||
(get-in state [:libraries file-id :data]))
|
||||
component (ctkl/get-component data component-id)
|
||||
page-id (:main-instance-page component)
|
||||
root-id (:main-instance-id component)]
|
||||
|
@ -1022,7 +1022,7 @@
|
|||
(watch [_ state _]
|
||||
(let [undo-id (js/Symbol)]
|
||||
(log/info :msg "COMPONENT-SWAP"
|
||||
:file (pretty-file file-id state)
|
||||
:file (debug-pretty-file file-id state)
|
||||
:id-new-component id-new-component
|
||||
:undo-id undo-id)
|
||||
(rx/concat
|
||||
|
@ -1068,15 +1068,15 @@
|
|||
(update [_ state]
|
||||
(if (and (not= library-id (:current-file-id state))
|
||||
(nil? asset-id))
|
||||
(d/assoc-in-when state [:workspace-libraries library-id :synced-at] (dt/now))
|
||||
(d/assoc-in-when state [:libraries library-id :synced-at] (dt/now))
|
||||
state))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(when (and (some? file-id) (some? library-id)) ; Prevent race conditions while navigating out of the file
|
||||
(log/info :msg "SYNC-FILE"
|
||||
:file (pretty-file file-id state)
|
||||
:library (pretty-file library-id state)
|
||||
:file (debug-pretty-file file-id state)
|
||||
:library (debug-pretty-file library-id state)
|
||||
:asset-type asset-type
|
||||
:asset-id asset-id
|
||||
:undo-group undo-group)
|
||||
|
@ -1172,7 +1172,7 @@
|
|||
(let [file-data (:workspace-data state)
|
||||
ignore-until (dm/get-in state [:workspace-file :ignore-sync-until])
|
||||
libraries-need-sync (filter #(seq (assets-need-sync % file-data ignore-until))
|
||||
(vals (get state :workspace-libraries)))
|
||||
(vals (get state :libraries)))
|
||||
do-more-info #(modal/show! :libraries-dialog {:starting-tab "updates"})
|
||||
do-update #(do (apply st/emit! (map (fn [library]
|
||||
(sync-file (:current-file-id state)
|
||||
|
@ -1359,7 +1359,7 @@
|
|||
(let [libraries (:workspace-shared-files state)
|
||||
library (d/seek #(= (:id %) library-id) libraries)]
|
||||
(if library
|
||||
(update state :workspace-libraries assoc library-id (dissoc library :library-summary))
|
||||
(update state :libraries assoc library-id (dissoc library :library-summary))
|
||||
state)))
|
||||
|
||||
ptk/WatchEvent
|
||||
|
@ -1373,7 +1373,7 @@
|
|||
(rx/merge-map fpmap/resolve-file)
|
||||
(rx/map (fn [file]
|
||||
(fn [state]
|
||||
(assoc-in state [:workspace-libraries library-id] file)))))
|
||||
(assoc-in state [:libraries library-id] file)))))
|
||||
(->> (rp/cmd! :get-file-object-thumbnails {:file-id library-id :tag "component"})
|
||||
(rx/map (fn [thumbnails]
|
||||
(fn [state]
|
||||
|
@ -1391,7 +1391,7 @@
|
|||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(d/dissoc-in state [:workspace-libraries library-id]))
|
||||
(d/dissoc-in state [:libraries library-id]))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
|
|
|
@ -314,6 +314,6 @@
|
|||
(ptk/reify ::handle-library-change
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(when (contains? (:workspace-libraries state) file-id)
|
||||
(when (contains? (:libraries state) file-id)
|
||||
(rx/of (dwl/ext-library-changed file-id modified-at revn changes)
|
||||
(dwl/notify-sync-file file-id))))))
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
(defn lookup-library-objects
|
||||
[state file-id page-id]
|
||||
(dm/get-in state [:workspace-libraries file-id :data :pages-index page-id :objects]))
|
||||
(dm/get-in state [:libraries file-id :data :pages-index page-id :objects]))
|
||||
|
||||
(defn lookup-objects
|
||||
[state file-id page-id]
|
||||
|
@ -108,7 +108,7 @@
|
|||
[state file-id]
|
||||
(if (= file-id (:current-file-id state))
|
||||
(get state :workspace-data)
|
||||
(dm/get-in state [:workspace-libraries file-id :data])))
|
||||
(dm/get-in state [:libraries file-id :data])))
|
||||
|
||||
(defn get-file-full
|
||||
"Get the data content of the given file (it may be the current file
|
||||
|
@ -117,13 +117,13 @@
|
|||
(if (= file-id (:current-file-id state))
|
||||
(-> (get state :workspace-file)
|
||||
(assoc :data (get state :workspace-data)))
|
||||
(dm/get-in state [:workspace-libraries file-id :data])))
|
||||
(dm/get-in state [:libraries file-id :data])))
|
||||
|
||||
(defn get-libraries
|
||||
"Retrieve all libraries, including the local file."
|
||||
[state]
|
||||
(let [{:keys [id] :as local} (:workspace-data state)]
|
||||
(-> (:workspace-libraries state)
|
||||
(-> (:libraries state)
|
||||
(assoc id {:id id
|
||||
:data local}))))
|
||||
|
||||
|
|
|
@ -233,10 +233,8 @@
|
|||
(l/derived :workspace-data st/state))
|
||||
|
||||
(def workspace-file-colors
|
||||
(l/derived (fn [data]
|
||||
(when data
|
||||
(->> (:colors data)
|
||||
(d/mapm #(assoc %2 :file-id (:id data))))))
|
||||
(l/derived (fn [{:keys [id] :as data}]
|
||||
(some-> (:colors data) (update-vals #(assoc % :file-id id))))
|
||||
workspace-data
|
||||
=))
|
||||
|
||||
|
@ -246,6 +244,8 @@
|
|||
(dm/get-in state [:recent-colors file-id])))
|
||||
st/state))
|
||||
|
||||
;; FIXME: fonts are not prefixed, so the recent font list is shared
|
||||
;; across all teams. This may not be expected behavior
|
||||
(def workspace-recent-fonts
|
||||
(l/derived (fn [data]
|
||||
(get data :recent-fonts []))
|
||||
|
@ -254,25 +254,9 @@
|
|||
(def workspace-file-typography
|
||||
(l/derived :typographies workspace-data))
|
||||
|
||||
(def workspace-local-library
|
||||
(l/derived (fn [state]
|
||||
(select-keys (:workspace-data state)
|
||||
[:id
|
||||
:colors
|
||||
:media
|
||||
:typographies
|
||||
:components]))
|
||||
st/state =))
|
||||
|
||||
(def workspace-libraries
|
||||
(l/derived :workspace-libraries st/state))
|
||||
|
||||
(def workspace-presence
|
||||
(l/derived :workspace-presence st/state))
|
||||
|
||||
(def workspace-snap-data
|
||||
(l/derived :workspace-snap-data st/state))
|
||||
|
||||
(def workspace-page
|
||||
(l/derived (fn [state]
|
||||
(let [page-id (:current-page-id state)
|
||||
|
@ -618,13 +602,6 @@
|
|||
[id]
|
||||
(l/derived #(get % id) workspace-grid-edition))
|
||||
|
||||
;; FIXME: remove
|
||||
(def current-file-id
|
||||
(l/derived :current-file-id st/state))
|
||||
|
||||
(def current-project-id
|
||||
(l/derived :current-project-id st/state))
|
||||
|
||||
(def workspace-preview-blend
|
||||
(l/derived :workspace-preview-blend st/state))
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
[app.main.ui.dashboard.team :refer [team-settings-page* team-members-page* team-invitations-page* webhooks-page*]]
|
||||
[app.main.ui.dashboard.templates :refer [templates-section*]]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.modal :refer [modal-container*]]
|
||||
[app.main.ui.workspace.plugins]
|
||||
[app.plugins.register :as preg]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -240,6 +241,7 @@
|
|||
(use-plugin-register plugin-url team-id (:id default-project))
|
||||
|
||||
[:& (mf/provider ctx/current-project-id) {:value project-id}
|
||||
[:> modal-container*]
|
||||
;; NOTE: dashboard events and other related functions assumes
|
||||
;; that the team is a implicit context variable that is
|
||||
;; available using react context or accessing
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
(ns app.main.ui.modal
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.main.data.modal :as dm]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.store :as st]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.keyboard :as k]
|
||||
|
@ -20,13 +21,13 @@
|
|||
[event allow-click-outside]
|
||||
(when (and (k/esc? event) (not allow-click-outside))
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dm/hide))))
|
||||
(st/emit! (modal/hide))))
|
||||
|
||||
(defn- on-pop-state
|
||||
[event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dm/hide))
|
||||
(st/emit! (modal/hide))
|
||||
(.forward js/history))
|
||||
|
||||
(defn- on-click-outside
|
||||
|
@ -41,15 +42,14 @@
|
|||
(= (.-button event) 0))
|
||||
(dom/stop-propagation event)
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (dm/hide)))))
|
||||
(st/emit! (modal/hide)))))
|
||||
|
||||
(mf/defc modal-wrapper
|
||||
{::mf/wrap-props false
|
||||
(mf/defc modal-wrapper*
|
||||
{::mf/props :obj
|
||||
::mf/wrap [mf/memo]}
|
||||
[props]
|
||||
(let [data (unchecked-get props "data")
|
||||
wrapper-ref (mf/use-ref nil)
|
||||
components (mf/deref dm/components)
|
||||
[{:keys [data]}]
|
||||
(let [wrapper-ref (mf/use-ref nil)
|
||||
components (mf/deref modal/components)
|
||||
|
||||
allow-click-outside (:allow-click-outside data)
|
||||
|
||||
|
@ -61,31 +61,29 @@
|
|||
(fn [event]
|
||||
(on-esc-clicked event allow-click-outside))]
|
||||
|
||||
(mf/use-layout-effect
|
||||
(mf/deps allow-click-outside)
|
||||
(fn []
|
||||
(let [keys [(events/listen js/window EventType.POPSTATE on-pop-state)
|
||||
(events/listen js/document EventType.KEYDOWN handle-keydown)
|
||||
(mf/with-effect [allow-click-outside]
|
||||
(let [keys [(events/listen js/window EventType.POPSTATE on-pop-state)
|
||||
(events/listen js/document EventType.KEYDOWN handle-keydown)
|
||||
|
||||
;; Changing to js/document breaks the color picker
|
||||
(events/listen (dom/get-root) EventType.POINTERDOWN handle-click-outside)
|
||||
;; Changing to js/document breaks the color picker
|
||||
(events/listen (dom/get-root) EventType.POINTERDOWN handle-click-outside)
|
||||
|
||||
(events/listen js/document EventType.CONTEXTMENU handle-click-outside)]]
|
||||
#(doseq [key keys]
|
||||
(events/unlistenByKey key)))))
|
||||
(events/listen js/document EventType.CONTEXTMENU handle-click-outside)]]
|
||||
(fn []
|
||||
(run! events/unlistenByKey keys))))
|
||||
|
||||
(when-let [component (get components (:type data))]
|
||||
[:div {:ref wrapper-ref
|
||||
:class (stl/css :modal-wrapper)}
|
||||
(mf/element component (:props data))])))
|
||||
|
||||
(def modal-ref
|
||||
(l/derived ::dm/modal st/state))
|
||||
(def ^:private ref:modal
|
||||
(l/derived ::modal/modal st/state))
|
||||
|
||||
(mf/defc modal
|
||||
{::mf/wrap-props false}
|
||||
(mf/defc modal-container*
|
||||
{::mf/props :obj}
|
||||
[]
|
||||
(let [modal (mf/deref modal-ref)]
|
||||
(when modal
|
||||
[:& modal-wrapper {:data modal
|
||||
:key (:id modal)}])))
|
||||
(when-let [modal (mf/deref ref:modal)]
|
||||
(mf/portal
|
||||
(mf/html [:> modal-wrapper* {:data modal :key (dm/str (:id modal))}])
|
||||
(.-body js/document))))
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[app.main.router :as rt]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.modal :refer [modal-container*]]
|
||||
[app.main.ui.settings.access-tokens :refer [access-tokens-page]]
|
||||
[app.main.ui.settings.change-email]
|
||||
[app.main.ui.settings.delete-account]
|
||||
|
@ -41,25 +42,29 @@
|
|||
(when (nil? profile)
|
||||
(st/emit! (rt/nav :auth-login))))
|
||||
|
||||
[:section {:class (stl/css :dashboard-layout-refactor :dashboard)}
|
||||
[:& sidebar {:profile profile
|
||||
:section section}]
|
||||
[:*
|
||||
[:> modal-container*]
|
||||
[:section {:class (stl/css :dashboard-layout-refactor :dashboard)}
|
||||
|
||||
[:div {:class (stl/css :dashboard-content)}
|
||||
[:& header]
|
||||
[:section {:class (stl/css :dashboard-container)}
|
||||
(case section
|
||||
:settings-profile
|
||||
[:& profile-page]
|
||||
|
||||
:settings-feedback
|
||||
[:& feedback-page]
|
||||
[:& sidebar {:profile profile
|
||||
:section section}]
|
||||
|
||||
:settings-password
|
||||
[:& password-page]
|
||||
[:div {:class (stl/css :dashboard-content)}
|
||||
[:& header]
|
||||
[:section {:class (stl/css :dashboard-container)}
|
||||
(case section
|
||||
:settings-profile
|
||||
[:& profile-page]
|
||||
|
||||
:settings-options
|
||||
[:& options-page]
|
||||
:settings-feedback
|
||||
[:& feedback-page]
|
||||
|
||||
:settings-access-tokens
|
||||
[:& access-tokens-page])]]]))
|
||||
:settings-password
|
||||
[:& password-page]
|
||||
|
||||
:settings-options
|
||||
[:& options-page]
|
||||
|
||||
:settings-access-tokens
|
||||
[:& access-tokens-page])]]]]))
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
[app.main.ui.ds.product.loader :refer [loader*]]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.modal :refer [modal-container*]]
|
||||
[app.main.ui.viewer.comments :refer [comments-layer comments-sidebar*]]
|
||||
[app.main.ui.viewer.header :as header]
|
||||
[app.main.ui.viewer.inspect :as inspect]
|
||||
|
@ -633,7 +634,9 @@
|
|||
|
||||
(if-let [data (mf/deref refs/viewer-data)]
|
||||
(let [props (obj/merge props #js {:data data :key (dm/str file-id)})]
|
||||
[:> viewer-content* props])
|
||||
[:*
|
||||
[:> modal-container*]
|
||||
[:> viewer-content* props]])
|
||||
|
||||
[:> loader* {:title (tr "labels.loading")
|
||||
:overlay true}]))
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
mf/deref)
|
||||
colors-library-ws (-> (mf/use-memo
|
||||
(mf/deps (:file-id color))
|
||||
#(make-colors-library-ref :workspace-libraries (:file-id color)))
|
||||
#(make-colors-library-ref :libraries (:file-id color)))
|
||||
mf/deref)]
|
||||
(or colors-library-v colors-library-ws)))
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
file-typographies-viewer (mf/deref file-typographies-ref)
|
||||
file-typographies-workspace (mf/deref refs/workspace-file-typography)
|
||||
|
||||
file-library-workspace (get (mf/deref refs/workspace-libraries) (:typography-ref-file style))
|
||||
file-library-workspace (get (mf/deref refs/libraries) (:typography-ref-file style))
|
||||
typography-external-lib (get-in file-library-workspace [:data :typographies (:typography-ref-id style)])
|
||||
|
||||
color-format (mf/use-state :hex)
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
(ns app.main.ui.viewer.inspect.right-sidebar
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.refs :as refs]
|
||||
|
@ -29,14 +28,14 @@
|
|||
(if (= from :workspace)
|
||||
(let [workspace-data (deref refs/workspace-data)
|
||||
{:keys [id] :as local} workspace-data
|
||||
libraries (deref refs/workspace-libraries)]
|
||||
libraries (deref refs/libraries)]
|
||||
(-> libraries
|
||||
(assoc id {:id id
|
||||
:data local})))
|
||||
(let [viewer-data (deref refs/viewer-data)
|
||||
local (get-in viewer-data [:file :data])
|
||||
id (deref refs/current-file-id)
|
||||
libraries (:libraries viewer-data)]
|
||||
id (get local :id)
|
||||
libraries (:libraries viewer-data)]
|
||||
(-> libraries
|
||||
(assoc id {:id id
|
||||
:data local})))))
|
||||
|
@ -48,17 +47,13 @@
|
|||
objects (or objects (:objects page))
|
||||
shapes (or shapes
|
||||
(resolve-shapes objects selected))
|
||||
|
||||
first-shape (first shapes)
|
||||
page-id (or page-id (:id page))
|
||||
file-id (or file-id (:id file))
|
||||
|
||||
libraries (get-libraries from)
|
||||
|
||||
file (mf/deref refs/viewer-file)
|
||||
components-v2 (dm/get-in file [:data :options :components-v2])
|
||||
main-instance? (if components-v2
|
||||
(ctk/main-instance? first-shape)
|
||||
true)
|
||||
main-instance? (ctk/main-instance? first-shape)
|
||||
|
||||
handle-change-tab
|
||||
(mf/use-fn
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
[app.main.ui.ds.product.loader :refer [loader*]]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.hooks.resize :refer [use-resize-observer]]
|
||||
[app.main.ui.modal :refer [modal-container*]]
|
||||
[app.main.ui.workspace.colorpicker]
|
||||
[app.main.ui.workspace.context-menu :refer [context-menu]]
|
||||
[app.main.ui.workspace.coordinates :as coordinates]
|
||||
|
@ -162,7 +163,7 @@
|
|||
|
||||
|
||||
(mf/defc workspace*
|
||||
{::mf/wrap-props false
|
||||
{::mf/props :obj
|
||||
::mf/wrap [mf/memo]}
|
||||
[{:keys [project-id file-id page-id layout-name]}]
|
||||
|
||||
|
@ -211,6 +212,7 @@
|
|||
[:& (mf/provider ctx/components-v2) {:value components-v2?}
|
||||
[:& (mf/provider ctx/design-tokens) {:value design-tokens?}
|
||||
[:& (mf/provider ctx/workspace-read-only?) {:value read-only?}
|
||||
[:> modal-container*]
|
||||
[:section {:class (stl/css :workspace)
|
||||
:style {:background-color background-color
|
||||
:touch-action "none"}}
|
||||
|
|
|
@ -157,7 +157,7 @@
|
|||
[{:keys [size width selected] :as props}]
|
||||
(let [recent-colors (mf/deref refs/workspace-recent-colors)
|
||||
file-colors (mf/deref refs/workspace-file-colors)
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
shared-libs (mf/deref refs/libraries)
|
||||
colors (mf/use-state [])]
|
||||
|
||||
(mf/with-effect [selected shared-libs]
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
[{:keys [show-menu? close-menu on-select-palette selected]}]
|
||||
(let [recent-colors (mf/deref refs/workspace-recent-colors)
|
||||
file-colors (mf/deref refs/workspace-file-colors)
|
||||
shared-libs (mf/deref refs/workspace-libraries)]
|
||||
shared-libs (mf/deref refs/libraries)]
|
||||
[:& dropdown {:show show-menu?
|
||||
:on-close close-menu}
|
||||
[:ul {:class (stl/css :palette-menu)}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
(let [selected (h/use-shared-state mdc/colorpicker-selected-broadcast-key :recent)
|
||||
current-colors (mf/use-state [])
|
||||
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
shared-libs (mf/deref refs/libraries)
|
||||
file-colors (mf/deref refs/workspace-file-colors)
|
||||
recent-colors (mf/deref refs/workspace-recent-colors)
|
||||
recent-colors (h/use-equal-memo (filter #(or (:gradient %) (:color %) (:image %)) recent-colors))
|
||||
|
|
|
@ -49,14 +49,15 @@
|
|||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event))
|
||||
|
||||
(mf/defc menu-entry
|
||||
{::mf/props :obj}
|
||||
(mf/defc menu-entry*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [title shortcut on-click on-pointer-enter on-pointer-leave
|
||||
on-unmount children selected? icon disabled value]}]
|
||||
on-unmount children is-selected icon disabled value]}]
|
||||
(let [submenu-ref (mf/use-ref nil)
|
||||
hovering? (mf/use-ref false)
|
||||
on-pointer-enter
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(mf/set-ref-val! hovering? true)
|
||||
(let [submenu-node (mf/ref-val submenu-ref)]
|
||||
|
@ -65,7 +66,7 @@
|
|||
(when on-pointer-enter (on-pointer-enter))))
|
||||
|
||||
on-pointer-leave
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(mf/set-ref-val! hovering? false)
|
||||
(let [submenu-node (mf/ref-val submenu-ref)]
|
||||
|
@ -77,7 +78,7 @@
|
|||
(when on-pointer-leave (on-pointer-leave))))
|
||||
|
||||
set-dom-node
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn [dom]
|
||||
(let [submenu-node (mf/ref-val submenu-ref)]
|
||||
(when (and (some? dom) (some? submenu-node))
|
||||
|
@ -97,8 +98,8 @@
|
|||
:on-pointer-leave on-pointer-leave}
|
||||
[:span
|
||||
{:class (stl/css :icon-wrapper)}
|
||||
(if selected? [:span {:class (stl/css :selected-icon)}
|
||||
i/tick]
|
||||
(if is-selected [:span {:class (stl/css :selected-icon)}
|
||||
i/tick]
|
||||
[:span {:class (stl/css :selected-icon)}])
|
||||
[:span {:class (stl/css :shape-icon)} icon]]
|
||||
[:span {:class (stl/css :title)} title]]
|
||||
|
@ -126,34 +127,40 @@
|
|||
:on-context-menu prevent-default}
|
||||
children])])))
|
||||
|
||||
(mf/defc menu-separator
|
||||
(mf/defc menu-separator*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[]
|
||||
[:li {:class (stl/css :separator)}])
|
||||
|
||||
(mf/defc context-menu-edit
|
||||
[_]
|
||||
(mf/defc context-menu-edit*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[]
|
||||
(let [do-copy #(st/emit! (dw/copy-selected))
|
||||
do-cut #(st/emit! (dw/copy-selected)
|
||||
(dw/delete-selected))
|
||||
do-paste #(st/emit! (dw/paste-from-clipboard))
|
||||
do-duplicate #(st/emit! (dw/duplicate-selected true))]
|
||||
[:*
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.copy")
|
||||
:shortcut (sc/get-tooltip :copy)
|
||||
:on-click do-copy}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.cut")
|
||||
:shortcut (sc/get-tooltip :cut)
|
||||
:on-click do-cut}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.paste")
|
||||
:shortcut (sc/get-tooltip :paste)
|
||||
:on-click do-paste}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.duplicate")
|
||||
:shortcut (sc/get-tooltip :duplicate)
|
||||
:on-click do-duplicate}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.copy")
|
||||
:shortcut (sc/get-tooltip :copy)
|
||||
:on-click do-copy}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.cut")
|
||||
:shortcut (sc/get-tooltip :cut)
|
||||
:on-click do-cut}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.paste")
|
||||
:shortcut (sc/get-tooltip :paste)
|
||||
:on-click do-paste}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.duplicate")
|
||||
:shortcut (sc/get-tooltip :duplicate)
|
||||
:on-click do-duplicate}]
|
||||
|
||||
[:& menu-separator]]))
|
||||
[:> menu-separator* {}]]))
|
||||
|
||||
(mf/defc context-menu-layer-position
|
||||
(mf/defc context-menu-layer-position*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [do-bring-forward (mf/use-fn #(st/emit! (dw/vertical-order-selected :up)))
|
||||
do-bring-to-front (mf/use-fn #(st/emit! (dw/vertical-order-selected :top)))
|
||||
|
@ -173,46 +180,50 @@
|
|||
|
||||
[:*
|
||||
(when (> (count hover-objs) 1)
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.select-layer")}
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.select-layer")}
|
||||
(for [object hover-objs]
|
||||
[:& menu-entry {:title (:name object)
|
||||
:key (dm/str (:id object))
|
||||
:selected? (some #(= object %) shapes)
|
||||
:on-click (select-shapes (:id object))
|
||||
:on-pointer-enter (on-pointer-enter (:id object))
|
||||
:on-pointer-leave (on-pointer-leave (:id object))
|
||||
:on-unmount (on-unmount (:id object))
|
||||
:icon (sic/element-icon {:shape object})}])])
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.forward")
|
||||
:shortcut (sc/get-tooltip :bring-forward)
|
||||
:on-click do-bring-forward}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.front")
|
||||
:shortcut (sc/get-tooltip :bring-front)
|
||||
:on-click do-bring-to-front}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.backward")
|
||||
:shortcut (sc/get-tooltip :bring-backward)
|
||||
:on-click do-send-backward}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.back")
|
||||
:shortcut (sc/get-tooltip :bring-back)
|
||||
:on-click do-send-to-back}]
|
||||
[:> menu-entry* {:title (:name object)
|
||||
:key (dm/str (:id object))
|
||||
:is-selected (some #(= object %) shapes)
|
||||
:on-click (select-shapes (:id object))
|
||||
:on-pointer-enter (on-pointer-enter (:id object))
|
||||
:on-pointer-leave (on-pointer-leave (:id object))
|
||||
:on-unmount (on-unmount (:id object))
|
||||
:icon (sic/element-icon {:shape object})}])])
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.forward")
|
||||
:shortcut (sc/get-tooltip :bring-forward)
|
||||
:on-click do-bring-forward}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.front")
|
||||
:shortcut (sc/get-tooltip :bring-front)
|
||||
:on-click do-bring-to-front}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.backward")
|
||||
:shortcut (sc/get-tooltip :bring-backward)
|
||||
:on-click do-send-backward}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.back")
|
||||
:shortcut (sc/get-tooltip :bring-back)
|
||||
:on-click do-send-to-back}]
|
||||
|
||||
[:& menu-separator]]))
|
||||
[:> menu-separator* {}]]))
|
||||
|
||||
(mf/defc context-menu-flip
|
||||
(mf/defc context-menu-flip*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[]
|
||||
(let [do-flip-vertical #(st/emit! (dw/flip-vertical-selected))
|
||||
do-flip-horizontal #(st/emit! (dw/flip-horizontal-selected))]
|
||||
[:*
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.flip-vertical")
|
||||
:shortcut (sc/get-tooltip :flip-vertical)
|
||||
:on-click do-flip-vertical}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.flip-vertical")
|
||||
:shortcut (sc/get-tooltip :flip-vertical)
|
||||
:on-click do-flip-vertical}]
|
||||
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.flip-horizontal")
|
||||
:shortcut (sc/get-tooltip :flip-horizontal)
|
||||
:on-click do-flip-horizontal}]
|
||||
[:& menu-separator]]))
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.flip-horizontal")
|
||||
:shortcut (sc/get-tooltip :flip-horizontal)
|
||||
:on-click do-flip-horizontal}]
|
||||
[:> menu-separator* {}]]))
|
||||
|
||||
(mf/defc context-menu-thumbnail
|
||||
(mf/defc context-menu-thumbnail*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [single? (= (count shapes) 1)
|
||||
has-frame? (some cfh/frame-shape? shapes)
|
||||
|
@ -220,26 +231,29 @@
|
|||
(when (and single? has-frame?)
|
||||
[:*
|
||||
(if (every? :use-for-thumbnail shapes)
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.thumbnail-remove")
|
||||
:on-click do-toggle-thumbnail}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.thumbnail-set")
|
||||
:shortcut (sc/get-tooltip :thumbnail-set)
|
||||
:on-click do-toggle-thumbnail}])
|
||||
[:& menu-separator]])))
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.thumbnail-remove")
|
||||
:on-click do-toggle-thumbnail}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.thumbnail-set")
|
||||
:shortcut (sc/get-tooltip :thumbnail-set)
|
||||
:on-click do-toggle-thumbnail}])
|
||||
[:> menu-separator* {}]])))
|
||||
|
||||
(mf/defc context-menu-rename
|
||||
(mf/defc context-menu-rename*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [do-rename #(st/emit! (dw/start-rename-selected))]
|
||||
(when (= (count shapes) 1)
|
||||
[:*
|
||||
[:& menu-separator]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.rename")
|
||||
:shortcut (sc/get-tooltip :rename)
|
||||
:on-click do-rename}]])))
|
||||
[:> menu-separator* {}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.rename")
|
||||
:shortcut (sc/get-tooltip :rename)
|
||||
:on-click do-rename}]])))
|
||||
|
||||
(mf/defc context-menu-group
|
||||
(mf/defc context-menu-group*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
|
||||
(let [multiple? (> (count shapes) 1)
|
||||
single? (= (count shapes) 1)
|
||||
|
||||
|
@ -266,42 +280,46 @@
|
|||
(when (not any-in-copy?)
|
||||
[:*
|
||||
(when (or has-bool? has-group? has-mask? has-frame?)
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.ungroup")
|
||||
:shortcut (sc/get-tooltip :ungroup)
|
||||
:on-click do-remove-group}])
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.ungroup")
|
||||
:shortcut (sc/get-tooltip :ungroup)
|
||||
:on-click do-remove-group}])
|
||||
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.group")
|
||||
:shortcut (sc/get-tooltip :group)
|
||||
:on-click do-create-group}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.group")
|
||||
:shortcut (sc/get-tooltip :group)
|
||||
:on-click do-create-group}]
|
||||
|
||||
(when (or multiple? (and is-group? (not has-mask?)) is-bool?)
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.mask")
|
||||
:shortcut (sc/get-tooltip :mask)
|
||||
:on-click do-mask-group}])
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.mask")
|
||||
:shortcut (sc/get-tooltip :mask)
|
||||
:on-click do-mask-group}])
|
||||
|
||||
(when has-mask?
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.unmask")
|
||||
:shortcut (sc/get-tooltip :unmask)
|
||||
:on-click do-unmask-group}])
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.unmask")
|
||||
:shortcut (sc/get-tooltip :unmask)
|
||||
:on-click do-unmask-group}])
|
||||
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.create-artboard-from-selection")
|
||||
:shortcut (sc/get-tooltip :artboard-selection)
|
||||
:on-click do-create-artboard-from-selection}]
|
||||
[:& menu-separator]])]))
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.create-artboard-from-selection")
|
||||
:shortcut (sc/get-tooltip :artboard-selection)
|
||||
:on-click do-create-artboard-from-selection}]
|
||||
[:> menu-separator* {}]])]))
|
||||
|
||||
(mf/defc context-focus-mode-menu
|
||||
[{:keys []}]
|
||||
(mf/defc context-focus-mode-menu*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[]
|
||||
(let [focus (mf/deref refs/workspace-focus-selected)
|
||||
do-toggle-focus-mode #(st/emit! (dw/toggle-focus-mode))]
|
||||
|
||||
[:& menu-entry {:title (if (empty? focus)
|
||||
(tr "workspace.focus.focus-on")
|
||||
(tr "workspace.focus.focus-off"))
|
||||
:shortcut (sc/get-tooltip :toggle-focus-mode)
|
||||
:on-click do-toggle-focus-mode}]))
|
||||
[:> menu-entry* {:title (if (empty? focus)
|
||||
(tr "workspace.focus.focus-on")
|
||||
(tr "workspace.focus.focus-off"))
|
||||
:shortcut (sc/get-tooltip :toggle-focus-mode)
|
||||
:on-click do-toggle-focus-mode}]))
|
||||
|
||||
(mf/defc context-menu-path
|
||||
[{:keys [shapes disable-flatten? disable-booleans?]}]
|
||||
(mf/defc context-menu-path*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [shapes disable-flatten disable-booleans]}]
|
||||
(let [multiple? (> (count shapes) 1)
|
||||
single? (= (count shapes) 1)
|
||||
|
||||
|
@ -330,37 +348,39 @@
|
|||
(st/emit! (dw/change-bool-type (-> shapes first :id) bool-type))))]
|
||||
[:*
|
||||
(when (and single? (not is-frame?))
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.edit")
|
||||
:shortcut (sc/get-tooltip :start-editing)
|
||||
:on-click do-start-editing}])
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.edit")
|
||||
:shortcut (sc/get-tooltip :start-editing)
|
||||
:on-click do-start-editing}])
|
||||
|
||||
(when-not (or disable-flatten? has-frame? has-path?)
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.transform-to-path")
|
||||
:on-click do-transform-to-path}])
|
||||
(when-not (or disable-flatten has-frame? has-path?)
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.transform-to-path")
|
||||
:on-click do-transform-to-path}])
|
||||
|
||||
(when (and (not disable-booleans?)
|
||||
(when (and (not disable-booleans)
|
||||
(or multiple? (and single? (or is-group? is-bool?))))
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.path")}
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.union")
|
||||
:shortcut (sc/get-tooltip :bool-union)
|
||||
:on-click (make-do-bool :union)}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.difference")
|
||||
:shortcut (sc/get-tooltip :bool-difference)
|
||||
:on-click (make-do-bool :difference)}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.intersection")
|
||||
:shortcut (sc/get-tooltip :bool-intersection)
|
||||
:on-click (make-do-bool :intersection)}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.exclude")
|
||||
:shortcut (sc/get-tooltip :bool-exclude)
|
||||
:on-click (make-do-bool :exclude)}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.path")}
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.union")
|
||||
:shortcut (sc/get-tooltip :bool-union)
|
||||
:on-click (make-do-bool :union)}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.difference")
|
||||
:shortcut (sc/get-tooltip :bool-difference)
|
||||
:on-click (make-do-bool :difference)}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.intersection")
|
||||
:shortcut (sc/get-tooltip :bool-intersection)
|
||||
:on-click (make-do-bool :intersection)}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.exclude")
|
||||
:shortcut (sc/get-tooltip :bool-exclude)
|
||||
:on-click (make-do-bool :exclude)}]
|
||||
|
||||
(when (and single? is-bool? (not disable-flatten?))
|
||||
(when (and single? is-bool? (not disable-flatten))
|
||||
[:*
|
||||
[:& menu-separator]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.flatten")
|
||||
:on-click do-transform-to-path}]])])]))
|
||||
[:> menu-separator* {}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.flatten")
|
||||
:on-click do-transform-to-path}]])])]))
|
||||
|
||||
(mf/defc context-menu-layer-options
|
||||
(mf/defc context-menu-layer-options*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [ids (mapv :id shapes)
|
||||
do-show-shape #(st/emit! (dw/update-shape-flags ids {:hidden false}))
|
||||
|
@ -369,23 +389,24 @@
|
|||
do-unlock-shape #(st/emit! (dw/update-shape-flags ids {:blocked false}))]
|
||||
[:*
|
||||
(if (every? :hidden shapes)
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.show")
|
||||
:shortcut (sc/get-tooltip :toggle-visibility)
|
||||
:on-click do-show-shape}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.hide")
|
||||
:shortcut (sc/get-tooltip :toggle-visibility)
|
||||
:on-click do-hide-shape}])
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.show")
|
||||
:shortcut (sc/get-tooltip :toggle-visibility)
|
||||
:on-click do-show-shape}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.hide")
|
||||
:shortcut (sc/get-tooltip :toggle-visibility)
|
||||
:on-click do-hide-shape}])
|
||||
|
||||
(if (every? :blocked shapes)
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.unlock")
|
||||
:shortcut (sc/get-tooltip :toggle-lock)
|
||||
:on-click do-unlock-shape}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.lock")
|
||||
:shortcut (sc/get-tooltip :toggle-lock)
|
||||
:on-click do-lock-shape}])]))
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.unlock")
|
||||
:shortcut (sc/get-tooltip :toggle-lock)
|
||||
:on-click do-unlock-shape}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.lock")
|
||||
:shortcut (sc/get-tooltip :toggle-lock)
|
||||
:on-click do-lock-shape}])]))
|
||||
|
||||
(mf/defc context-menu-prototype
|
||||
{::mf/props :obj}
|
||||
(mf/defc context-menu-prototype*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [flows (mf/deref refs/workspace-page-flows)
|
||||
options-mode (mf/deref refs/options-mode-global)
|
||||
|
@ -400,13 +421,14 @@
|
|||
|
||||
(when (and prototype? is-frame?)
|
||||
(if-let [flow (ctp/get-frame-flow flows (-> shapes first :id))]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.delete-flow-start")
|
||||
:on-click (do-remove-flow flow)}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.flow-start")
|
||||
:on-click do-add-flow}]))))
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.delete-flow-start")
|
||||
:on-click (do-remove-flow flow)}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.flow-start")
|
||||
:on-click do-add-flow}]))))
|
||||
|
||||
(mf/defc context-menu-layout
|
||||
{::mf/props :obj}
|
||||
(mf/defc context-menu-layout*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [single? (= (count shapes) 1)
|
||||
objects (deref refs/workspace-page-objects)
|
||||
|
@ -438,27 +460,29 @@
|
|||
(if (or ^boolean has-flex?
|
||||
^boolean has-grid?)
|
||||
[:div
|
||||
[:& menu-separator]
|
||||
[:> menu-separator* {}]
|
||||
(if has-flex?
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.remove-flex")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-flex)
|
||||
:on-click on-remove-layout}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.remove-grid")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-grid)
|
||||
:on-click on-remove-layout}])]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.remove-flex")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-flex)
|
||||
:on-click on-remove-layout}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.remove-grid")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-grid)
|
||||
:on-click on-remove-layout}])]
|
||||
|
||||
[:div
|
||||
[:& menu-separator]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.add-flex")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-flex)
|
||||
:value "flex"
|
||||
:on-click on-add-layout}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.add-grid")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-grid)
|
||||
:value "grid"
|
||||
:on-click on-add-layout}]]))]))
|
||||
[:> menu-separator* {}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.add-flex")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-flex)
|
||||
:value "flex"
|
||||
:on-click on-add-layout}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.add-grid")
|
||||
:shortcut (sc/get-tooltip :toggle-layout-grid)
|
||||
:value "grid"
|
||||
:on-click on-add-layout}]]))]))
|
||||
|
||||
(mf/defc context-menu-component
|
||||
(mf/defc context-menu-component*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [components-v2 (features/use-feature "components/v2")
|
||||
single? (= (count shapes) 1)
|
||||
|
@ -471,59 +495,66 @@
|
|||
[:*
|
||||
(when can-make-component ;; We don't want to change the structure of component copies
|
||||
[:*
|
||||
[:& menu-separator]
|
||||
[:> menu-separator* {}]
|
||||
|
||||
[:& 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-component")
|
||||
:shortcut (sc/get-tooltip :create-component)
|
||||
:on-click do-add-component}]
|
||||
(when (not single?)
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.create-multiple-components")
|
||||
:on-click do-add-multiple-components}])])
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.create-multiple-components")
|
||||
:on-click do-add-multiple-components}])])
|
||||
|
||||
(when (seq components-menu-entries)
|
||||
[:*
|
||||
[:& menu-separator]
|
||||
[:> menu-separator* {}]
|
||||
(for [entry components-menu-entries :when (not (nil? entry))]
|
||||
[:& menu-entry {:key (uuid/next)
|
||||
:title (:title entry)
|
||||
:shortcut (when (contains? entry :shortcut) (sc/get-tooltip (:shortcut entry)))
|
||||
:on-click (:action entry)}])])]))
|
||||
[:> menu-entry* {:key (uuid/next)
|
||||
:title (:title entry)
|
||||
:shortcut (when (contains? entry :shortcut) (sc/get-tooltip (:shortcut entry)))
|
||||
:on-click (:action entry)}])])]))
|
||||
|
||||
(mf/defc context-menu-delete
|
||||
(mf/defc context-menu-delete*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[]
|
||||
(let [do-delete #(st/emit! (dw/delete-selected))]
|
||||
[:*
|
||||
[:& menu-separator]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.delete")
|
||||
:shortcut (sc/get-tooltip :delete)
|
||||
:on-click do-delete}]]))
|
||||
[:> menu-separator* {}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.delete")
|
||||
:shortcut (sc/get-tooltip :delete)
|
||||
:on-click do-delete}]]))
|
||||
|
||||
(mf/defc shape-context-menu
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [mdata] :as props}]
|
||||
(let [{:keys [disable-booleans? disable-flatten?]} mdata
|
||||
(mf/defc shape-context-menu*
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/private true
|
||||
::mf/props :obj}
|
||||
[{:keys [mdata]}]
|
||||
(let [{:keys [disable-booleans disable-flatten]} mdata
|
||||
shapes (mf/deref refs/selected-objects)
|
||||
props #js {:shapes shapes
|
||||
:disable-booleans? disable-booleans?
|
||||
:disable-flatten? disable-flatten?}]
|
||||
props (mf/spread-props
|
||||
{:shapes shapes
|
||||
:disable-booleans disable-booleans
|
||||
:disable-flatten disable-flatten})]
|
||||
(when-not (empty? shapes)
|
||||
[:*
|
||||
[:> context-menu-edit props]
|
||||
[:> context-menu-layer-position props]
|
||||
[:> context-menu-flip props]
|
||||
[:> context-menu-thumbnail props]
|
||||
[:> context-menu-rename props]
|
||||
[:> context-menu-group props]
|
||||
[:> context-focus-mode-menu props]
|
||||
[:> context-menu-path props]
|
||||
[:> context-menu-layer-options props]
|
||||
[:> context-menu-prototype props]
|
||||
[:> context-menu-layout props]
|
||||
[:> context-menu-component props]
|
||||
[:> context-menu-delete props]])))
|
||||
[:> context-menu-edit* props]
|
||||
[:> context-menu-layer-position* props]
|
||||
[:> context-menu-flip* props]
|
||||
[:> context-menu-thumbnail* props]
|
||||
[:> context-menu-rename* props]
|
||||
[:> context-menu-group* props]
|
||||
[:> context-focus-mode-menu* props]
|
||||
[:> context-menu-path* props]
|
||||
[:> context-menu-layer-options* props]
|
||||
[:> context-menu-prototype* props]
|
||||
[:> context-menu-layout* props]
|
||||
[:> context-menu-component* props]
|
||||
[:> context-menu-delete* props]])))
|
||||
|
||||
(mf/defc page-item-context-menu
|
||||
[{:keys [mdata] :as props}]
|
||||
(mf/defc page-item-context-menu*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [mdata]}]
|
||||
(let [page (:page mdata)
|
||||
deletable? (:deletable? mdata)
|
||||
id (:id page)
|
||||
|
@ -540,13 +571,13 @@
|
|||
|
||||
[:*
|
||||
(when deletable?
|
||||
[:& menu-entry {:title (tr "workspace.assets.delete")
|
||||
:on-click do-delete}])
|
||||
[:> menu-entry* {:title (tr "workspace.assets.delete")
|
||||
:on-click do-delete}])
|
||||
|
||||
[:& menu-entry {:title (tr "workspace.assets.rename")
|
||||
:on-click do-rename}]
|
||||
[:& menu-entry {:title (tr "workspace.assets.duplicate")
|
||||
:on-click do-duplicate}]]))
|
||||
[:> menu-entry* {:title (tr "workspace.assets.rename")
|
||||
:on-click do-rename}]
|
||||
[:> menu-entry* {:title (tr "workspace.assets.duplicate")
|
||||
:on-click do-duplicate}]]))
|
||||
|
||||
(mf/defc viewport-context-menu*
|
||||
{::mf/props :obj}
|
||||
|
@ -559,68 +590,72 @@
|
|||
do-toggle-focus-mode #(st/emit! (dw/toggle-focus-mode))]
|
||||
[:*
|
||||
(when-not ^boolean read-only?
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.paste")
|
||||
:shortcut (sc/get-tooltip :paste)
|
||||
:on-click do-paste}])
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.hide-ui")
|
||||
:shortcut (sc/get-tooltip :hide-ui)
|
||||
:on-click do-hide-ui}]
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.paste")
|
||||
:shortcut (sc/get-tooltip :paste)
|
||||
:on-click do-paste}])
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.hide-ui")
|
||||
:shortcut (sc/get-tooltip :hide-ui)
|
||||
:on-click do-hide-ui}]
|
||||
|
||||
(when (d/not-empty? focus)
|
||||
[:& menu-entry {:title (tr "workspace.focus.focus-off")
|
||||
:shortcut (sc/get-tooltip :toggle-focus-mode)
|
||||
:on-click do-toggle-focus-mode}])]))
|
||||
[:> menu-entry* {:title (tr "workspace.focus.focus-off")
|
||||
:shortcut (sc/get-tooltip :toggle-focus-mode)
|
||||
:on-click do-toggle-focus-mode}])]))
|
||||
|
||||
(mf/defc grid-track-context-menu
|
||||
[{:keys [mdata] :as props}]
|
||||
(mf/defc grid-track-context-menu*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [mdata]}]
|
||||
(let [{:keys [type index grid-id]} mdata
|
||||
do-delete-track
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps grid-id type index)
|
||||
(fn []
|
||||
(st/emit! (dwsl/remove-layout-track [grid-id] type index))))
|
||||
|
||||
do-add-track-before
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps grid-id type index)
|
||||
(fn []
|
||||
(st/emit! (dwsl/add-layout-track [grid-id] type ctl/default-track-value index))))
|
||||
|
||||
do-add-track-after
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps grid-id type index)
|
||||
(fn []
|
||||
(st/emit! (dwsl/add-layout-track [grid-id] type ctl/default-track-value (inc index)))))
|
||||
|
||||
do-duplicate-track
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps grid-id type index)
|
||||
(fn []
|
||||
(st/emit! (dwsl/duplicate-layout-track [grid-id] type index))))
|
||||
|
||||
do-delete-track-shapes
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps grid-id type index)
|
||||
(fn []
|
||||
(st/emit! (dwsl/remove-layout-track [grid-id] type index {:with-shapes? true}))))]
|
||||
|
||||
(if (= type :column)
|
||||
[:*
|
||||
[:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.duplicate") :on-click do-duplicate-track}]
|
||||
[:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.add-before") :on-click do-add-track-before}]
|
||||
[:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.add-after") :on-click do-add-track-after}]
|
||||
[:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.delete") :on-click do-delete-track}]
|
||||
[:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.delete-shapes") :on-click do-delete-track-shapes}]]
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-track.column.duplicate") :on-click do-duplicate-track}]
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-track.column.add-before") :on-click do-add-track-before}]
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-track.column.add-after") :on-click do-add-track-after}]
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-track.column.delete") :on-click do-delete-track}]
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-track.column.delete-shapes") :on-click do-delete-track-shapes}]]
|
||||
|
||||
[:*
|
||||
[:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.duplicate") :on-click do-duplicate-track}]
|
||||
[:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.add-before") :on-click do-add-track-before}]
|
||||
[:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.add-after") :on-click do-add-track-after}]
|
||||
[:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.delete") :on-click do-delete-track}]
|
||||
[:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.delete-shapes") :on-click do-delete-track-shapes}]])))
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-track.row.duplicate") :on-click do-duplicate-track}]
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-track.row.add-before") :on-click do-add-track-before}]
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-track.row.add-after") :on-click do-add-track-after}]
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-track.row.delete") :on-click do-delete-track}]
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-track.row.delete-shapes") :on-click do-delete-track-shapes}]])))
|
||||
|
||||
(mf/defc grid-cells-context-menu
|
||||
[{:keys [mdata] :as props}]
|
||||
(mf/defc grid-cells-context-menu*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [mdata]}]
|
||||
(let [{:keys [grid cells]} mdata
|
||||
|
||||
single? (= (count cells) 1)
|
||||
|
@ -631,29 +666,29 @@
|
|||
#(ctl/valid-area-cells? cells))
|
||||
|
||||
do-merge-cells
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps grid cells)
|
||||
(fn []
|
||||
(st/emit! (dwsl/merge-cells (:id grid) (map :id cells)))))
|
||||
|
||||
do-create-board
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps grid cells)
|
||||
(fn []
|
||||
(st/emit! (dwsl/create-cell-board (:id grid) (map :id cells)))))]
|
||||
[:*
|
||||
(when (not single?)
|
||||
[:& menu-entry {:title (tr "workspace.context-menu.grid-cells.merge")
|
||||
:on-click do-merge-cells
|
||||
:disabled (not can-merge?)}])
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-cells.merge")
|
||||
:on-click do-merge-cells
|
||||
:disabled (not can-merge?)}])
|
||||
|
||||
(when single?
|
||||
[:& menu-entry {:title (tr "workspace.context-menu.grid-cells.area")
|
||||
:on-click do-merge-cells}])
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-cells.area")
|
||||
:on-click do-merge-cells}])
|
||||
|
||||
[:& menu-entry {:title (tr "workspace.context-menu.grid-cells.create-board")
|
||||
:on-click do-create-board
|
||||
:disabled (and (not single?) (not can-merge?))}]]))
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-cells.create-board")
|
||||
:on-click do-create-board
|
||||
:disabled (and (not single?) (not can-merge?))}]]))
|
||||
|
||||
|
||||
;; FIXME: optimize because it is rendered always
|
||||
|
@ -688,8 +723,8 @@
|
|||
(if ^boolean read-only?
|
||||
[:> viewport-context-menu* {:mdata mdata}]
|
||||
(case (:kind mdata)
|
||||
:shape [:& shape-context-menu {:mdata mdata}]
|
||||
:page [:& page-item-context-menu {:mdata mdata}]
|
||||
:grid-track [:& grid-track-context-menu {:mdata mdata}]
|
||||
:grid-cells [:& grid-cells-context-menu {:mdata mdata}]
|
||||
[:& viewport-context-menu* {:mdata mdata}]))]]]))
|
||||
:shape [:> shape-context-menu* {:mdata mdata}]
|
||||
:page [:> page-item-context-menu* {:mdata mdata}]
|
||||
:grid-track [:> grid-track-context-menu* {:mdata mdata}]
|
||||
:grid-cells [:> grid-cells-context-menu* {:mdata mdata}]
|
||||
[:> viewport-context-menu* {:mdata mdata}]))]]]))
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
(let [fdata (let [{:keys [id] :as wfile} (:workspace-data state)]
|
||||
(if (= id library-id)
|
||||
wfile
|
||||
(dm/get-in state [:workspace-libraries library-id :data])))]
|
||||
(dm/get-in state [:libraries library-id :data])))]
|
||||
{:colors (-> fdata :colors vals)
|
||||
:media (-> fdata :media vals)
|
||||
:components (ctkl/components-seq fdata)
|
||||
|
@ -557,7 +557,7 @@
|
|||
file-id (:id file)
|
||||
shared? (:is-shared file)
|
||||
|
||||
libraries (mf/deref refs/workspace-libraries)
|
||||
libraries (mf/deref refs/libraries)
|
||||
libraries (mf/with-memo [libraries]
|
||||
(d/removem (fn [[_ val]] (:is-indirect val)) libraries))
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [filters]}]
|
||||
(let [libraries (mf/deref refs/workspace-libraries)
|
||||
(let [libraries (mf/deref refs/libraries)
|
||||
libraries (mf/with-memo [libraries]
|
||||
(->> (vals libraries)
|
||||
(remove :is-indirect)
|
||||
|
@ -88,7 +88,7 @@
|
|||
section (:section filters)
|
||||
ordering (:ordering filters)
|
||||
reverse-sort? (= :desc ordering)
|
||||
num-libs (count (mf/deref refs/workspace-libraries))
|
||||
num-libs (count (mf/deref refs/libraries))
|
||||
|
||||
toggle-ordering
|
||||
(mf/use-fn
|
||||
|
|
|
@ -315,17 +315,17 @@
|
|||
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)
|
||||
libraries (deref refs/libraries)
|
||||
current-file {:id current-file-id :data workspace-data}
|
||||
|
||||
find-component (fn [shape include-deleted?]
|
||||
(ctf/resolve-component
|
||||
shape current-file workspace-libraries {:include-deleted? include-deleted?}))
|
||||
shape current-file libraries {:include-deleted? include-deleted?}))
|
||||
|
||||
local-or-exists (fn [shape]
|
||||
(let [library-id (:component-file shape)]
|
||||
(or (= library-id current-file-id)
|
||||
(some? (get workspace-libraries library-id)))))
|
||||
(some? (get libraries library-id)))))
|
||||
|
||||
restorable-copies (->> copies
|
||||
(filter #(nil? (find-component % false)))
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
(if components-v2
|
||||
(ctf/get-component-page data component)
|
||||
component)])
|
||||
(let [data (dm/get-in @refs/workspace-libraries [file-id :data])
|
||||
(let [data (dm/get-in @refs/libraries [file-id :data])
|
||||
root-shape (ctf/get-component-root data component)
|
||||
container (if components-v2
|
||||
(ctf/get-component-page data component)
|
||||
|
@ -466,7 +466,7 @@
|
|||
(fn [component event]
|
||||
|
||||
(let [file-data
|
||||
(d/nilv (dm/get-in @refs/workspace-libraries [file-id :data]) @refs/workspace-data)
|
||||
(d/nilv (dm/get-in @refs/libraries [file-id :data]) @refs/workspace-data)
|
||||
|
||||
shape-main
|
||||
(ctf/get-component-root file-data component)]
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
[{:keys [selected objects page-id file-id selected-shapes shapes-with-children]}]
|
||||
(let [sp-panel (mf/deref refs/specialized-panel)
|
||||
drawing (mf/deref refs/workspace-drawing)
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
shared-libs (mf/deref refs/libraries)
|
||||
edition (mf/deref refs/selected-edition)
|
||||
edit-grid? (ctl/grid-layout? objects edition)
|
||||
grid-edition (mf/deref refs/workspace-grid-edition)
|
||||
|
|
|
@ -272,7 +272,7 @@
|
|||
(letfn [(get-libraries [state]
|
||||
(let [file (:workspace-file state)
|
||||
data (:workspace-data state)
|
||||
libs (:workspace-libraries state)]
|
||||
libs (:libraries state)]
|
||||
(assoc libs (:id file)
|
||||
(assoc file :data data))))]
|
||||
(l/derived get-libraries st/state)))
|
||||
|
@ -524,7 +524,7 @@
|
|||
(let [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)
|
||||
libraries (deref refs/libraries)
|
||||
|
||||
state* (mf/use-state {:show-content true
|
||||
:menu-open false})
|
||||
|
@ -544,7 +544,7 @@
|
|||
component (ctf/resolve-component shape
|
||||
{:id current-file-id
|
||||
:data workspace-data}
|
||||
workspace-libraries
|
||||
libraries
|
||||
{:include-deleted? true})
|
||||
main-instance? (if components-v2 (ctk/main-instance? shape) true)
|
||||
|
||||
|
|
|
@ -184,7 +184,7 @@
|
|||
|
||||
(let [file-id (mf/use-ctx ctx/current-file-id)
|
||||
typographies (mf/deref refs/workspace-file-typography)
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
shared-libs (mf/deref refs/libraries)
|
||||
label (case type
|
||||
:multiple (tr "workspace.options.text-options.title-selection")
|
||||
:group (tr "workspace.options.text-options.title-group")
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
disable-drag on-focus on-blur select-only select-on-focus]}]
|
||||
(let [current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
file-colors (mf/deref refs/workspace-file-colors)
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
shared-libs (mf/deref refs/libraries)
|
||||
hover-detach (mf/use-state false)
|
||||
on-change (h/use-ref-callback on-change)
|
||||
src-colors (if (= (:file-id color) current-file-id)
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
(mf/deref refs/workspace-v2-editor-state)
|
||||
(mf/deref refs/workspace-editor-state))
|
||||
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
shared-libs (mf/deref refs/libraries)
|
||||
|
||||
editor-state (when (not (features/active-feature? @st/state "text-editor/v2"))
|
||||
(get state-map (:id shape)))
|
||||
|
|
|
@ -183,7 +183,7 @@
|
|||
[{:keys [size width selected] :as props}]
|
||||
(let [selected-ids (mf/deref refs/selected-shapes)
|
||||
file-typographies (mf/deref refs/workspace-file-typography)
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
shared-libs (mf/deref refs/libraries)
|
||||
current-file-id (mf/use-ctx ctx/current-file-id)]
|
||||
[:& palette {:current-file-id current-file-id
|
||||
:selected-ids selected-ids
|
||||
|
|
|
@ -14,11 +14,10 @@
|
|||
[app.util.i18n :refer [tr]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
||||
(mf/defc text-palette-ctx-menu
|
||||
[{:keys [show-menu? close-menu on-select-palette selected]}]
|
||||
(let [file-typographies (mf/deref refs/workspace-file-typography)
|
||||
shared-libs (mf/deref refs/workspace-libraries)]
|
||||
(let [typographies (mf/deref refs/workspace-file-typography)
|
||||
shared-libs (mf/deref refs/libraries)]
|
||||
[:& dropdown {:show show-menu?
|
||||
:on-close close-menu}
|
||||
[:ul {:class (stl/css :text-context-menu)}
|
||||
|
@ -49,7 +48,7 @@
|
|||
[:span {:class (stl/css :lib-name)}
|
||||
(tr "workspace.libraries.colors.file-library")]
|
||||
[:span {:class (stl/css :lib-num)}
|
||||
(dm/str "(" (count file-typographies) ")")]]
|
||||
(dm/str "(" (count typographies) ")")]]
|
||||
(when (= selected :file)
|
||||
[:span {:class (stl/css :icon-wrapper)}
|
||||
i/tick])]]]))
|
||||
|
|
|
@ -622,7 +622,7 @@
|
|||
:hover-disabled? hover-disabled?}])])
|
||||
|
||||
(when show-gradient-handlers?
|
||||
[:& gradients/gradient-handlers
|
||||
[:> gradients/gradient-handlers*
|
||||
{:id (first selected)
|
||||
:zoom zoom}])
|
||||
|
||||
|
|
|
@ -441,8 +441,9 @@
|
|||
:r (/ 4 zoom)
|
||||
:fill "var(--app-white)"}]))]))
|
||||
|
||||
(mf/defc gradient-handlers*
|
||||
[{:keys [zoom stops gradient editing shape] :as kk}]
|
||||
(mf/defc gradient-handlers-impl*
|
||||
{::mf/props :obj}
|
||||
[{:keys [zoom stops gradient editing shape]}]
|
||||
(let [transform (gsh/transform-matrix shape)
|
||||
transform-inverse (gsh/inverse-transform-matrix shape)
|
||||
|
||||
|
@ -509,8 +510,9 @@
|
|||
:on-change-finish on-change-finish
|
||||
:on-change-width on-change-width}]))
|
||||
|
||||
(mf/defc gradient-handlers
|
||||
{::mf/wrap [mf/memo]}
|
||||
(mf/defc gradient-handlers*
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/props :obj}
|
||||
[{:keys [id zoom]}]
|
||||
(let [shape-ref (mf/use-memo (mf/deps id) #(refs/object-by-id id))
|
||||
shape (mf/deref shape-ref)
|
||||
|
@ -520,7 +522,7 @@
|
|||
editing-stop (:editing-stop state)]
|
||||
|
||||
(when (and (some? gradient) (= id (:shape-id gradient)))
|
||||
[:& gradient-handlers*
|
||||
[:> gradient-handlers-impl*
|
||||
{:zoom zoom
|
||||
:gradient gradient
|
||||
:stops stops
|
||||
|
|
|
@ -617,7 +617,7 @@
|
|||
:hover-disabled? hover-disabled?}])])
|
||||
|
||||
(when show-gradient-handlers?
|
||||
[:& gradients/gradient-handlers
|
||||
[:> gradients/gradient-handlers*
|
||||
{:id (first selected)
|
||||
:zoom zoom}])
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
(map #(obj/get % "$id"))
|
||||
(mapcat #(cfh/get-children-with-self objects %)))
|
||||
file-id (:current-file-id @st/state)
|
||||
shared-libs (:workspace-libraries @st/state)]
|
||||
shared-libs (:libraries @st/state)]
|
||||
|
||||
(->> (ctc/extract-all-colors shapes file-id shared-libs)
|
||||
(group-by :attrs)
|
||||
|
@ -182,7 +182,7 @@
|
|||
|
||||
:else
|
||||
(let [file-id (:current-file-id @st/state)
|
||||
shared-libs (:workspace-libraries @st/state)
|
||||
shared-libs (:libraries @st/state)
|
||||
objects (u/locate-objects)
|
||||
shapes
|
||||
(->> shapes
|
||||
|
|
|
@ -929,7 +929,7 @@
|
|||
:connected
|
||||
{:get
|
||||
(fn []
|
||||
(let [libraries (get @st/state :workspace-libraries)]
|
||||
(let [libraries (get @st/state :libraries)]
|
||||
(apply array (->> libraries keys (map (partial library-proxy plugin-id))))))}
|
||||
|
||||
:availableLibraries
|
||||
|
@ -937,7 +937,7 @@
|
|||
(let [team-id (:current-team-id @st/state)]
|
||||
(js/Promise.
|
||||
(fn [resolve reject]
|
||||
(let [current-libs (into #{} (map first) (get @st/state :workspace-libraries))]
|
||||
(let [current-libs (into #{} (map first) (get @st/state :libraries))]
|
||||
(->> (rp/cmd! :get-team-shared-files {:team-id team-id})
|
||||
(rx/map (fn [result]
|
||||
(->> result
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
(if (= id (:current-file-id @st/state))
|
||||
(-> (:workspace-file @st/state)
|
||||
(assoc :data (:workspace-data @st/state)))
|
||||
(dm/get-in @st/state [:workspace-libraries id])))
|
||||
(dm/get-in @st/state [:libraries id])))
|
||||
|
||||
(defn locate-page
|
||||
[file-id id]
|
||||
|
@ -65,10 +65,10 @@
|
|||
(defn locate-component
|
||||
[objects shape]
|
||||
(let [current-file-id (:current-file-id @st/state)
|
||||
workspace-data (:workspace-data @st/state)
|
||||
workspace-libraries (:workspace-libraries @st/state)
|
||||
root (ctn/get-instance-root objects shape)]
|
||||
[root (ctf/resolve-component root {:id current-file-id :data workspace-data} workspace-libraries {:include-deleted? true})]))
|
||||
workspace-data (:workspace-data @st/state)
|
||||
libraries (:libraries @st/state)
|
||||
root (ctn/get-instance-root objects shape)]
|
||||
[root (ctf/resolve-component root {:id current-file-id :data workspace-data} libraries {:include-deleted? true})]))
|
||||
|
||||
(defn proxy->file
|
||||
[proxy]
|
||||
|
|
|
@ -248,7 +248,7 @@
|
|||
(let [page-id (get state :current-page-id)
|
||||
file (assoc (get state :workspace-file)
|
||||
:data (get state :workspace-data))
|
||||
libraries (get state :workspace-libraries)]
|
||||
libraries (get state :libraries)]
|
||||
(ctf/dump-tree file page-id libraries {:show-ids show-ids
|
||||
:show-touched show-touched
|
||||
:show-modified show-modified}))))
|
||||
|
@ -266,7 +266,7 @@
|
|||
(let [page-id (get state :current-page-id)
|
||||
file (assoc (get state :workspace-file)
|
||||
:data (get state :workspace-data))
|
||||
libraries (get state :workspace-libraries)
|
||||
libraries (get state :libraries)
|
||||
shape-id (if (some? shape-id)
|
||||
(uuid/uuid shape-id)
|
||||
(let [objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
|
@ -383,7 +383,7 @@
|
|||
([shape-id]
|
||||
(let [file (assoc (get @st/state :workspace-file)
|
||||
:data (get @st/state :workspace-data))
|
||||
libraries (get @st/state :workspace-libraries)]
|
||||
libraries (get @st/state :libraries)]
|
||||
|
||||
(try
|
||||
(->> (if-let [shape-id (some-> shape-id parse-uuid)]
|
||||
|
@ -417,7 +417,7 @@
|
|||
fdata (get state :workspace-data)
|
||||
|
||||
file (assoc file :data fdata)
|
||||
libs (get state :workspace-libraries)
|
||||
libs (get state :libraries)
|
||||
|
||||
errors (cfv/validate-file file libs)
|
||||
_ (l/dbg :hint "repair current file" :errors (count errors))
|
||||
|
|
Loading…
Reference in a new issue