0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-21 06:02:32 -05:00

Merge pull request #5443 from penpot/niwinz-enhancements-1

 Several improvements
This commit is contained in:
Alejandro 2024-12-11 07:29:14 +01:00 committed by GitHub
commit 25a672b958
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
39 changed files with 420 additions and 410 deletions

View file

@ -20,8 +20,8 @@
:git/url "https://github.com/funcool/beicon.git"} :git/url "https://github.com/funcool/beicon.git"}
funcool/rumext funcool/rumext
{:git/tag "v2.14" {:git/tag "v2.15"
:git/sha "0016623" :git/sha "28783a7"
:git/url "https://github.com/funcool/rumext.git"} :git/url "https://github.com/funcool/rumext.git"}
instaparse/instaparse {:mvn/version "1.5.0"} instaparse/instaparse {:mvn/version "1.5.0"}

View file

@ -23,7 +23,6 @@
[app.main.ui.confirm] [app.main.ui.confirm]
[app.main.ui.css-cursors :as cur] [app.main.ui.css-cursors :as cur]
[app.main.ui.delete-shared] [app.main.ui.delete-shared]
[app.main.ui.modal :refer [modal]]
[app.main.ui.routes :as rt] [app.main.ui.routes :as rt]
[app.main.worker :as worker] [app.main.worker :as worker]
[app.plugins :as plugins] [app.plugins :as plugins]
@ -52,14 +51,9 @@
(let [el (dom/get-element "app")] (let [el (dom/get-element "app")]
(mf/create-root el))) (mf/create-root el)))
(defonce modal-root
(let [el (dom/get-element "modal")]
(mf/create-root el)))
(defn init-ui (defn init-ui
[] []
(mf/render! app-root (mf/element ui/app)) (mf/render! app-root (mf/element ui/app)))
(mf/render! modal-root (mf/element modal)))
(defn- initialize-profile (defn- initialize-profile
"Event used mainly on application bootstrap; it fetches the 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 ;; The hard flag will force to unmount the whole UI and will redraw every component
(when hard? (when hard?
(mf/unmount! app-root) (mf/unmount! app-root)
(mf/unmount! modal-root) (set! app-root (mf/create-root (dom/get-element "app"))))
(set! app-root (mf/create-root (dom/get-element "app")))
(set! modal-root (mf/create-root (dom/get-element "modal"))))
(st/emit! (ev/initialize)) (st/emit! (ev/initialize))
(init-ui))) (init-ui)))

View file

@ -79,7 +79,7 @@
(let [current-file-id (get state :current-file-id) (let [current-file-id (get state :current-file-id)
path (if (= file-id current-file-id) path (if (= file-id current-file-id)
[:workspace-data] [:workspace-data]
[:workspace-libraries file-id :data]) [:libraries file-id :data])
undo-changes (if pending undo-changes (if pending
(->> pending (->> pending
@ -159,14 +159,14 @@
(let [file (:workspace-file state)] (let [file (:workspace-file state)]
(if (= (:id file) file-id) (if (= (:id file) file-id)
(:revn file) (:revn file)
(dm/get-in state [:workspace-libraries file-id :revn])))) (dm/get-in state [:libraries file-id :revn]))))
(defn- resolve-file-vern (defn- resolve-file-vern
[state file-id] [state file-id]
(let [file (:workspace-file state)] (let [file (:workspace-file state)]
(if (= (:id file) file-id) (if (= (:id file) file-id)
(:vern file) (:vern file)
(dm/get-in state [:workspace-libraries file-id :vern])))) (dm/get-in state [:libraries file-id :vern]))))
(defn commit-changes (defn commit-changes
"Schedules a list of changes to execute now, and add the corresponding undo changes to "Schedules a list of changes to execute now, and add the corresponding undo changes to

View file

@ -52,7 +52,7 @@
(if-let [current-file-id (:current-file-id state)] (if-let [current-file-id (:current-file-id state)]
(if (= file-id current-file-id) (if (= file-id current-file-id)
(update-in state [:workspace-file :revn] max revn) (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)) state))
ptk/EffectEvent ptk/EffectEvent

View file

@ -172,7 +172,7 @@
(ptk/reify ::libraries-fetched (ptk/reify ::libraries-fetched
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(assoc state :workspace-libraries (d/index-by :id libraries))) (assoc state :libraries (d/index-by :id libraries)))
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
@ -363,7 +363,7 @@
:workspace-data :workspace-data
:workspace-editor-state :workspace-editor-state
:workspace-file :workspace-file
:workspace-libraries :libraries
:workspace-media-objects :workspace-media-objects
:workspace-persistence :workspace-persistence
:workspace-presence :workspace-presence
@ -572,7 +572,7 @@
(let [file-data (let [file-data
(if (= file-id (:current-file-id state)) (if (= file-id (:current-file-id state))
(:workspace-data state) (:workspace-data state)
(get-in state [:workspace-libraries file-id :data])) (get-in state [:libraries file-id :data]))
changes changes
(-> (pcb/empty-changes it) (-> (pcb/empty-changes it)

View file

@ -59,11 +59,11 @@
;; Change this to :info :debug or :trace to debug this module, or :warn to reset to default ;; Change this to :info :debug or :trace to debug this module, or :warn to reset to default
(log/set-level! :warn) (log/set-level! :warn)
(defn- pretty-file (defn- debug-pretty-file
[file-id state] [file-id state]
(if (= file-id (:current-file-id state)) (if (= file-id (:current-file-id state))
"<local>" "<local>"
(str "<" (get-in state [:workspace-libraries file-id :name]) ">"))) (str "<" (get-in state [:libraries file-id :name]) ">")))
(defn- log-changes (defn- log-changes
[changes file] [changes file]
@ -760,9 +760,9 @@
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(-> state (-> state
(update-in [:workspace-libraries library-id] (update-in [:libraries library-id]
assoc :modified-at modified-at :revn revn) 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))) ch/process-changes changes)))
ptk/WatchEvent ptk/WatchEvent
@ -898,7 +898,7 @@
current-file? (= current-file-id file-id) current-file? (= current-file-id file-id)
data (if current-file? data (if current-file?
(get state :workspace-data) (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) component (ctkl/get-component data component-id)
page-id (:main-instance-page component) page-id (:main-instance-page component)
root-id (:main-instance-id component)] root-id (:main-instance-id component)]
@ -1022,7 +1022,7 @@
(watch [_ state _] (watch [_ state _]
(let [undo-id (js/Symbol)] (let [undo-id (js/Symbol)]
(log/info :msg "COMPONENT-SWAP" (log/info :msg "COMPONENT-SWAP"
:file (pretty-file file-id state) :file (debug-pretty-file file-id state)
:id-new-component id-new-component :id-new-component id-new-component
:undo-id undo-id) :undo-id undo-id)
(rx/concat (rx/concat
@ -1068,15 +1068,15 @@
(update [_ state] (update [_ state]
(if (and (not= library-id (:current-file-id state)) (if (and (not= library-id (:current-file-id state))
(nil? asset-id)) (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)) state))
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
(when (and (some? file-id) (some? library-id)) ; Prevent race conditions while navigating out of the file (when (and (some? file-id) (some? library-id)) ; Prevent race conditions while navigating out of the file
(log/info :msg "SYNC-FILE" (log/info :msg "SYNC-FILE"
:file (pretty-file file-id state) :file (debug-pretty-file file-id state)
:library (pretty-file library-id state) :library (debug-pretty-file library-id state)
:asset-type asset-type :asset-type asset-type
:asset-id asset-id :asset-id asset-id
:undo-group undo-group) :undo-group undo-group)
@ -1172,7 +1172,7 @@
(let [file-data (:workspace-data state) (let [file-data (:workspace-data state)
ignore-until (dm/get-in state [:workspace-file :ignore-sync-until]) ignore-until (dm/get-in state [:workspace-file :ignore-sync-until])
libraries-need-sync (filter #(seq (assets-need-sync % file-data ignore-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-more-info #(modal/show! :libraries-dialog {:starting-tab "updates"})
do-update #(do (apply st/emit! (map (fn [library] do-update #(do (apply st/emit! (map (fn [library]
(sync-file (:current-file-id state) (sync-file (:current-file-id state)
@ -1359,7 +1359,7 @@
(let [libraries (:workspace-shared-files state) (let [libraries (:workspace-shared-files state)
library (d/seek #(= (:id %) library-id) libraries)] library (d/seek #(= (:id %) library-id) libraries)]
(if library (if library
(update state :workspace-libraries assoc library-id (dissoc library :library-summary)) (update state :libraries assoc library-id (dissoc library :library-summary))
state))) state)))
ptk/WatchEvent ptk/WatchEvent
@ -1373,7 +1373,7 @@
(rx/merge-map fpmap/resolve-file) (rx/merge-map fpmap/resolve-file)
(rx/map (fn [file] (rx/map (fn [file]
(fn [state] (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"}) (->> (rp/cmd! :get-file-object-thumbnails {:file-id library-id :tag "component"})
(rx/map (fn [thumbnails] (rx/map (fn [thumbnails]
(fn [state] (fn [state]
@ -1391,7 +1391,7 @@
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(d/dissoc-in state [:workspace-libraries library-id])) (d/dissoc-in state [:libraries library-id]))
ptk/WatchEvent ptk/WatchEvent
(watch [_ _ _] (watch [_ _ _]

View file

@ -314,6 +314,6 @@
(ptk/reify ::handle-library-change (ptk/reify ::handle-library-change
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (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) (rx/of (dwl/ext-library-changed file-id modified-at revn changes)
(dwl/notify-sync-file file-id)))))) (dwl/notify-sync-file file-id))))))

View file

@ -29,7 +29,7 @@
(defn lookup-library-objects (defn lookup-library-objects
[state file-id page-id] [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 (defn lookup-objects
[state file-id page-id] [state file-id page-id]
@ -108,7 +108,7 @@
[state file-id] [state file-id]
(if (= file-id (:current-file-id state)) (if (= file-id (:current-file-id state))
(get state :workspace-data) (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 (defn get-file-full
"Get the data content of the given file (it may be the current file "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)) (if (= file-id (:current-file-id state))
(-> (get state :workspace-file) (-> (get state :workspace-file)
(assoc :data (get state :workspace-data))) (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 (defn get-libraries
"Retrieve all libraries, including the local file." "Retrieve all libraries, including the local file."
[state] [state]
(let [{:keys [id] :as local} (:workspace-data state)] (let [{:keys [id] :as local} (:workspace-data state)]
(-> (:workspace-libraries state) (-> (:libraries state)
(assoc id {:id id (assoc id {:id id
:data local})))) :data local}))))

View file

@ -233,10 +233,8 @@
(l/derived :workspace-data st/state)) (l/derived :workspace-data st/state))
(def workspace-file-colors (def workspace-file-colors
(l/derived (fn [data] (l/derived (fn [{:keys [id] :as data}]
(when data (some-> (:colors data) (update-vals #(assoc % :file-id id))))
(->> (:colors data)
(d/mapm #(assoc %2 :file-id (:id data))))))
workspace-data workspace-data
=)) =))
@ -246,6 +244,8 @@
(dm/get-in state [:recent-colors file-id]))) (dm/get-in state [:recent-colors file-id])))
st/state)) 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 (def workspace-recent-fonts
(l/derived (fn [data] (l/derived (fn [data]
(get data :recent-fonts [])) (get data :recent-fonts []))
@ -254,25 +254,9 @@
(def workspace-file-typography (def workspace-file-typography
(l/derived :typographies workspace-data)) (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 (def workspace-presence
(l/derived :workspace-presence st/state)) (l/derived :workspace-presence st/state))
(def workspace-snap-data
(l/derived :workspace-snap-data st/state))
(def workspace-page (def workspace-page
(l/derived (fn [state] (l/derived (fn [state]
(let [page-id (:current-page-id state) (let [page-id (:current-page-id state)
@ -618,13 +602,6 @@
[id] [id]
(l/derived #(get % id) workspace-grid-edition)) (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 (def workspace-preview-blend
(l/derived :workspace-preview-blend st/state)) (l/derived :workspace-preview-blend st/state))

View file

@ -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.team :refer [team-settings-page* team-members-page* team-invitations-page* webhooks-page*]]
[app.main.ui.dashboard.templates :refer [templates-section*]] [app.main.ui.dashboard.templates :refer [templates-section*]]
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.modal :refer [modal-container*]]
[app.main.ui.workspace.plugins] [app.main.ui.workspace.plugins]
[app.plugins.register :as preg] [app.plugins.register :as preg]
[app.util.dom :as dom] [app.util.dom :as dom]
@ -240,6 +241,7 @@
(use-plugin-register plugin-url team-id (:id default-project)) (use-plugin-register plugin-url team-id (:id default-project))
[:& (mf/provider ctx/current-project-id) {:value project-id} [:& (mf/provider ctx/current-project-id) {:value project-id}
[:> modal-container*]
;; NOTE: dashboard events and other related functions assumes ;; NOTE: dashboard events and other related functions assumes
;; that the team is a implicit context variable that is ;; that the team is a implicit context variable that is
;; available using react context or accessing ;; available using react context or accessing

View file

@ -7,7 +7,8 @@
(ns app.main.ui.modal (ns app.main.ui.modal
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (: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.main.store :as st]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.keyboard :as k] [app.util.keyboard :as k]
@ -20,13 +21,13 @@
[event allow-click-outside] [event allow-click-outside]
(when (and (k/esc? event) (not allow-click-outside)) (when (and (k/esc? event) (not allow-click-outside))
(dom/stop-propagation event) (dom/stop-propagation event)
(st/emit! (dm/hide)))) (st/emit! (modal/hide))))
(defn- on-pop-state (defn- on-pop-state
[event] [event]
(dom/prevent-default event) (dom/prevent-default event)
(dom/stop-propagation event) (dom/stop-propagation event)
(st/emit! (dm/hide)) (st/emit! (modal/hide))
(.forward js/history)) (.forward js/history))
(defn- on-click-outside (defn- on-click-outside
@ -41,15 +42,14 @@
(= (.-button event) 0)) (= (.-button event) 0))
(dom/stop-propagation event) (dom/stop-propagation event)
(dom/prevent-default event) (dom/prevent-default event)
(st/emit! (dm/hide))))) (st/emit! (modal/hide)))))
(mf/defc modal-wrapper (mf/defc modal-wrapper*
{::mf/wrap-props false {::mf/props :obj
::mf/wrap [mf/memo]} ::mf/wrap [mf/memo]}
[props] [{:keys [data]}]
(let [data (unchecked-get props "data") (let [wrapper-ref (mf/use-ref nil)
wrapper-ref (mf/use-ref nil) components (mf/deref modal/components)
components (mf/deref dm/components)
allow-click-outside (:allow-click-outside data) allow-click-outside (:allow-click-outside data)
@ -61,31 +61,29 @@
(fn [event] (fn [event]
(on-esc-clicked event allow-click-outside))] (on-esc-clicked event allow-click-outside))]
(mf/use-layout-effect (mf/with-effect [allow-click-outside]
(mf/deps allow-click-outside) (let [keys [(events/listen js/window EventType.POPSTATE on-pop-state)
(fn [] (events/listen js/document EventType.KEYDOWN handle-keydown)
(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 ;; Changing to js/document breaks the color picker
(events/listen (dom/get-root) EventType.POINTERDOWN handle-click-outside) (events/listen (dom/get-root) EventType.POINTERDOWN handle-click-outside)
(events/listen js/document EventType.CONTEXTMENU handle-click-outside)]] (events/listen js/document EventType.CONTEXTMENU handle-click-outside)]]
#(doseq [key keys] (fn []
(events/unlistenByKey key))))) (run! events/unlistenByKey keys))))
(when-let [component (get components (:type data))] (when-let [component (get components (:type data))]
[:div {:ref wrapper-ref [:div {:ref wrapper-ref
:class (stl/css :modal-wrapper)} :class (stl/css :modal-wrapper)}
(mf/element component (:props data))]))) (mf/element component (:props data))])))
(def modal-ref (def ^:private ref:modal
(l/derived ::dm/modal st/state)) (l/derived ::modal/modal st/state))
(mf/defc modal (mf/defc modal-container*
{::mf/wrap-props false} {::mf/props :obj}
[] []
(let [modal (mf/deref modal-ref)] (when-let [modal (mf/deref ref:modal)]
(when modal (mf/portal
[:& modal-wrapper {:data modal (mf/html [:> modal-wrapper* {:data modal :key (dm/str (:id modal))}])
:key (:id modal)}]))) (.-body js/document))))

View file

@ -12,6 +12,7 @@
[app.main.router :as rt] [app.main.router :as rt]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.hooks :as hooks] [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.access-tokens :refer [access-tokens-page]]
[app.main.ui.settings.change-email] [app.main.ui.settings.change-email]
[app.main.ui.settings.delete-account] [app.main.ui.settings.delete-account]
@ -41,25 +42,29 @@
(when (nil? profile) (when (nil? profile)
(st/emit! (rt/nav :auth-login)))) (st/emit! (rt/nav :auth-login))))
[:section {:class (stl/css :dashboard-layout-refactor :dashboard)} [:*
[:& sidebar {:profile profile [:> modal-container*]
:section section}] [: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 [:& sidebar {:profile profile
[:& feedback-page] :section section}]
:settings-password [:div {:class (stl/css :dashboard-content)}
[:& password-page] [:& header]
[:section {:class (stl/css :dashboard-container)}
(case section
:settings-profile
[:& profile-page]
:settings-options :settings-feedback
[:& options-page] [:& feedback-page]
:settings-access-tokens :settings-password
[:& access-tokens-page])]]])) [:& password-page]
:settings-options
[:& options-page]
:settings-access-tokens
[:& access-tokens-page])]]]]))

View file

@ -25,6 +25,7 @@
[app.main.ui.ds.product.loader :refer [loader*]] [app.main.ui.ds.product.loader :refer [loader*]]
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.icons :as i] [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.comments :refer [comments-layer comments-sidebar*]]
[app.main.ui.viewer.header :as header] [app.main.ui.viewer.header :as header]
[app.main.ui.viewer.inspect :as inspect] [app.main.ui.viewer.inspect :as inspect]
@ -633,7 +634,9 @@
(if-let [data (mf/deref refs/viewer-data)] (if-let [data (mf/deref refs/viewer-data)]
(let [props (obj/merge props #js {:data data :key (dm/str file-id)})] (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") [:> loader* {:title (tr "labels.loading")
:overlay true}])) :overlay true}]))

View file

@ -39,7 +39,7 @@
mf/deref) mf/deref)
colors-library-ws (-> (mf/use-memo colors-library-ws (-> (mf/use-memo
(mf/deps (:file-id color)) (mf/deps (:file-id color))
#(make-colors-library-ref :workspace-libraries (:file-id color))) #(make-colors-library-ref :libraries (:file-id color)))
mf/deref)] mf/deref)]
(or colors-library-v colors-library-ws))) (or colors-library-v colors-library-ws)))

View file

@ -59,7 +59,7 @@
file-typographies-viewer (mf/deref file-typographies-ref) file-typographies-viewer (mf/deref file-typographies-ref)
file-typographies-workspace (mf/deref refs/workspace-file-typography) 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)]) typography-external-lib (get-in file-library-workspace [:data :typographies (:typography-ref-id style)])
color-format (mf/use-state :hex) color-format (mf/use-state :hex)

View file

@ -7,7 +7,6 @@
(ns app.main.ui.viewer.inspect.right-sidebar (ns app.main.ui.viewer.inspect.right-sidebar
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.data.macros :as dm]
[app.common.types.component :as ctk] [app.common.types.component :as ctk]
[app.main.data.event :as ev] [app.main.data.event :as ev]
[app.main.refs :as refs] [app.main.refs :as refs]
@ -29,14 +28,14 @@
(if (= from :workspace) (if (= from :workspace)
(let [workspace-data (deref refs/workspace-data) (let [workspace-data (deref refs/workspace-data)
{:keys [id] :as local} workspace-data {:keys [id] :as local} workspace-data
libraries (deref refs/workspace-libraries)] libraries (deref refs/libraries)]
(-> libraries (-> libraries
(assoc id {:id id (assoc id {:id id
:data local}))) :data local})))
(let [viewer-data (deref refs/viewer-data) (let [viewer-data (deref refs/viewer-data)
local (get-in viewer-data [:file :data]) local (get-in viewer-data [:file :data])
id (deref refs/current-file-id) id (get local :id)
libraries (:libraries viewer-data)] libraries (:libraries viewer-data)]
(-> libraries (-> libraries
(assoc id {:id id (assoc id {:id id
:data local}))))) :data local})))))
@ -48,17 +47,13 @@
objects (or objects (:objects page)) objects (or objects (:objects page))
shapes (or shapes shapes (or shapes
(resolve-shapes objects selected)) (resolve-shapes objects selected))
first-shape (first shapes) first-shape (first shapes)
page-id (or page-id (:id page)) page-id (or page-id (:id page))
file-id (or file-id (:id file)) file-id (or file-id (:id file))
libraries (get-libraries from) libraries (get-libraries from)
main-instance? (ctk/main-instance? first-shape)
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)
handle-change-tab handle-change-tab
(mf/use-fn (mf/use-fn

View file

@ -19,6 +19,7 @@
[app.main.ui.ds.product.loader :refer [loader*]] [app.main.ui.ds.product.loader :refer [loader*]]
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.hooks.resize :refer [use-resize-observer]] [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.colorpicker]
[app.main.ui.workspace.context-menu :refer [context-menu]] [app.main.ui.workspace.context-menu :refer [context-menu]]
[app.main.ui.workspace.coordinates :as coordinates] [app.main.ui.workspace.coordinates :as coordinates]
@ -162,7 +163,7 @@
(mf/defc workspace* (mf/defc workspace*
{::mf/wrap-props false {::mf/props :obj
::mf/wrap [mf/memo]} ::mf/wrap [mf/memo]}
[{:keys [project-id file-id page-id layout-name]}] [{:keys [project-id file-id page-id layout-name]}]
@ -211,6 +212,7 @@
[:& (mf/provider ctx/components-v2) {:value components-v2?} [:& (mf/provider ctx/components-v2) {:value components-v2?}
[:& (mf/provider ctx/design-tokens) {:value design-tokens?} [:& (mf/provider ctx/design-tokens) {:value design-tokens?}
[:& (mf/provider ctx/workspace-read-only?) {:value read-only?} [:& (mf/provider ctx/workspace-read-only?) {:value read-only?}
[:> modal-container*]
[:section {:class (stl/css :workspace) [:section {:class (stl/css :workspace)
:style {:background-color background-color :style {:background-color background-color
:touch-action "none"}} :touch-action "none"}}

View file

@ -157,7 +157,7 @@
[{:keys [size width selected] :as props}] [{:keys [size width selected] :as props}]
(let [recent-colors (mf/deref refs/workspace-recent-colors) (let [recent-colors (mf/deref refs/workspace-recent-colors)
file-colors (mf/deref refs/workspace-file-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 [])] colors (mf/use-state [])]
(mf/with-effect [selected shared-libs] (mf/with-effect [selected shared-libs]

View file

@ -19,7 +19,7 @@
[{:keys [show-menu? close-menu on-select-palette selected]}] [{:keys [show-menu? close-menu on-select-palette selected]}]
(let [recent-colors (mf/deref refs/workspace-recent-colors) (let [recent-colors (mf/deref refs/workspace-recent-colors)
file-colors (mf/deref refs/workspace-file-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? [:& dropdown {:show show-menu?
:on-close close-menu} :on-close close-menu}
[:ul {:class (stl/css :palette-menu)} [:ul {:class (stl/css :palette-menu)}

View file

@ -30,7 +30,7 @@
(let [selected (h/use-shared-state mdc/colorpicker-selected-broadcast-key :recent) (let [selected (h/use-shared-state mdc/colorpicker-selected-broadcast-key :recent)
current-colors (mf/use-state []) 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) file-colors (mf/deref refs/workspace-file-colors)
recent-colors (mf/deref refs/workspace-recent-colors) recent-colors (mf/deref refs/workspace-recent-colors)
recent-colors (h/use-equal-memo (filter #(or (:gradient %) (:color %) (:image %)) recent-colors)) recent-colors (h/use-equal-memo (filter #(or (:gradient %) (:color %) (:image %)) recent-colors))

View file

@ -49,14 +49,15 @@
(dom/prevent-default event) (dom/prevent-default event)
(dom/stop-propagation event)) (dom/stop-propagation event))
(mf/defc menu-entry (mf/defc menu-entry*
{::mf/props :obj} {::mf/props :obj
::mf/private true}
[{:keys [title shortcut on-click on-pointer-enter on-pointer-leave [{: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) (let [submenu-ref (mf/use-ref nil)
hovering? (mf/use-ref false) hovering? (mf/use-ref false)
on-pointer-enter on-pointer-enter
(mf/use-callback (mf/use-fn
(fn [] (fn []
(mf/set-ref-val! hovering? true) (mf/set-ref-val! hovering? true)
(let [submenu-node (mf/ref-val submenu-ref)] (let [submenu-node (mf/ref-val submenu-ref)]
@ -65,7 +66,7 @@
(when on-pointer-enter (on-pointer-enter)))) (when on-pointer-enter (on-pointer-enter))))
on-pointer-leave on-pointer-leave
(mf/use-callback (mf/use-fn
(fn [] (fn []
(mf/set-ref-val! hovering? false) (mf/set-ref-val! hovering? false)
(let [submenu-node (mf/ref-val submenu-ref)] (let [submenu-node (mf/ref-val submenu-ref)]
@ -77,7 +78,7 @@
(when on-pointer-leave (on-pointer-leave)))) (when on-pointer-leave (on-pointer-leave))))
set-dom-node set-dom-node
(mf/use-callback (mf/use-fn
(fn [dom] (fn [dom]
(let [submenu-node (mf/ref-val submenu-ref)] (let [submenu-node (mf/ref-val submenu-ref)]
(when (and (some? dom) (some? submenu-node)) (when (and (some? dom) (some? submenu-node))
@ -97,8 +98,8 @@
:on-pointer-leave on-pointer-leave} :on-pointer-leave on-pointer-leave}
[:span [:span
{:class (stl/css :icon-wrapper)} {:class (stl/css :icon-wrapper)}
(if selected? [:span {:class (stl/css :selected-icon)} (if is-selected [:span {:class (stl/css :selected-icon)}
i/tick] i/tick]
[:span {:class (stl/css :selected-icon)}]) [:span {:class (stl/css :selected-icon)}])
[:span {:class (stl/css :shape-icon)} icon]] [:span {:class (stl/css :shape-icon)} icon]]
[:span {:class (stl/css :title)} title]] [:span {:class (stl/css :title)} title]]
@ -126,34 +127,40 @@
:on-context-menu prevent-default} :on-context-menu prevent-default}
children])]))) children])])))
(mf/defc menu-separator (mf/defc menu-separator*
{::mf/props :obj
::mf/private true}
[] []
[:li {:class (stl/css :separator)}]) [: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)) (let [do-copy #(st/emit! (dw/copy-selected))
do-cut #(st/emit! (dw/copy-selected) do-cut #(st/emit! (dw/copy-selected)
(dw/delete-selected)) (dw/delete-selected))
do-paste #(st/emit! (dw/paste-from-clipboard)) do-paste #(st/emit! (dw/paste-from-clipboard))
do-duplicate #(st/emit! (dw/duplicate-selected true))] do-duplicate #(st/emit! (dw/duplicate-selected true))]
[:* [:*
[:& menu-entry {:title (tr "workspace.shape.menu.copy") [:> menu-entry* {:title (tr "workspace.shape.menu.copy")
:shortcut (sc/get-tooltip :copy) :shortcut (sc/get-tooltip :copy)
:on-click do-copy}] :on-click do-copy}]
[:& menu-entry {:title (tr "workspace.shape.menu.cut") [:> menu-entry* {:title (tr "workspace.shape.menu.cut")
:shortcut (sc/get-tooltip :cut) :shortcut (sc/get-tooltip :cut)
:on-click do-cut}] :on-click do-cut}]
[:& menu-entry {:title (tr "workspace.shape.menu.paste") [:> menu-entry* {:title (tr "workspace.shape.menu.paste")
:shortcut (sc/get-tooltip :paste) :shortcut (sc/get-tooltip :paste)
:on-click do-paste}] :on-click do-paste}]
[:& menu-entry {:title (tr "workspace.shape.menu.duplicate") [:> menu-entry* {:title (tr "workspace.shape.menu.duplicate")
:shortcut (sc/get-tooltip :duplicate) :shortcut (sc/get-tooltip :duplicate)
:on-click do-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]}] [{:keys [shapes]}]
(let [do-bring-forward (mf/use-fn #(st/emit! (dw/vertical-order-selected :up))) (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))) do-bring-to-front (mf/use-fn #(st/emit! (dw/vertical-order-selected :top)))
@ -173,46 +180,50 @@
[:* [:*
(when (> (count hover-objs) 1) (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] (for [object hover-objs]
[:& menu-entry {:title (:name object) [:> menu-entry* {:title (:name object)
:key (dm/str (:id object)) :key (dm/str (:id object))
:selected? (some #(= object %) shapes) :is-selected (some #(= object %) shapes)
:on-click (select-shapes (:id object)) :on-click (select-shapes (:id object))
:on-pointer-enter (on-pointer-enter (:id object)) :on-pointer-enter (on-pointer-enter (:id object))
:on-pointer-leave (on-pointer-leave (:id object)) :on-pointer-leave (on-pointer-leave (:id object))
:on-unmount (on-unmount (:id object)) :on-unmount (on-unmount (:id object))
:icon (sic/element-icon {:shape object})}])]) :icon (sic/element-icon {:shape object})}])])
[:& menu-entry {:title (tr "workspace.shape.menu.forward") [:> menu-entry* {:title (tr "workspace.shape.menu.forward")
:shortcut (sc/get-tooltip :bring-forward) :shortcut (sc/get-tooltip :bring-forward)
:on-click do-bring-forward}] :on-click do-bring-forward}]
[:& menu-entry {:title (tr "workspace.shape.menu.front") [:> menu-entry* {:title (tr "workspace.shape.menu.front")
:shortcut (sc/get-tooltip :bring-front) :shortcut (sc/get-tooltip :bring-front)
:on-click do-bring-to-front}] :on-click do-bring-to-front}]
[:& menu-entry {:title (tr "workspace.shape.menu.backward") [:> menu-entry* {:title (tr "workspace.shape.menu.backward")
:shortcut (sc/get-tooltip :bring-backward) :shortcut (sc/get-tooltip :bring-backward)
:on-click do-send-backward}] :on-click do-send-backward}]
[:& menu-entry {:title (tr "workspace.shape.menu.back") [:> menu-entry* {:title (tr "workspace.shape.menu.back")
:shortcut (sc/get-tooltip :bring-back) :shortcut (sc/get-tooltip :bring-back)
:on-click do-send-to-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)) (let [do-flip-vertical #(st/emit! (dw/flip-vertical-selected))
do-flip-horizontal #(st/emit! (dw/flip-horizontal-selected))] do-flip-horizontal #(st/emit! (dw/flip-horizontal-selected))]
[:* [:*
[:& menu-entry {:title (tr "workspace.shape.menu.flip-vertical") [:> menu-entry* {:title (tr "workspace.shape.menu.flip-vertical")
:shortcut (sc/get-tooltip :flip-vertical) :shortcut (sc/get-tooltip :flip-vertical)
:on-click do-flip-vertical}] :on-click do-flip-vertical}]
[:& menu-entry {:title (tr "workspace.shape.menu.flip-horizontal") [:> menu-entry* {:title (tr "workspace.shape.menu.flip-horizontal")
:shortcut (sc/get-tooltip :flip-horizontal) :shortcut (sc/get-tooltip :flip-horizontal)
:on-click do-flip-horizontal}] :on-click do-flip-horizontal}]
[:& menu-separator]])) [:> menu-separator* {}]]))
(mf/defc context-menu-thumbnail (mf/defc context-menu-thumbnail*
{::mf/props :obj
::mf/private true}
[{:keys [shapes]}] [{:keys [shapes]}]
(let [single? (= (count shapes) 1) (let [single? (= (count shapes) 1)
has-frame? (some cfh/frame-shape? shapes) has-frame? (some cfh/frame-shape? shapes)
@ -220,26 +231,29 @@
(when (and single? has-frame?) (when (and single? has-frame?)
[:* [:*
(if (every? :use-for-thumbnail shapes) (if (every? :use-for-thumbnail shapes)
[:& menu-entry {:title (tr "workspace.shape.menu.thumbnail-remove") [:> menu-entry* {:title (tr "workspace.shape.menu.thumbnail-remove")
:on-click do-toggle-thumbnail}] :on-click do-toggle-thumbnail}]
[:& menu-entry {:title (tr "workspace.shape.menu.thumbnail-set") [:> menu-entry* {:title (tr "workspace.shape.menu.thumbnail-set")
:shortcut (sc/get-tooltip :thumbnail-set) :shortcut (sc/get-tooltip :thumbnail-set)
:on-click do-toggle-thumbnail}]) :on-click do-toggle-thumbnail}])
[:& menu-separator]]))) [:> menu-separator* {}]])))
(mf/defc context-menu-rename (mf/defc context-menu-rename*
{::mf/props :obj
::mf/private true}
[{:keys [shapes]}] [{:keys [shapes]}]
(let [do-rename #(st/emit! (dw/start-rename-selected))] (let [do-rename #(st/emit! (dw/start-rename-selected))]
(when (= (count shapes) 1) (when (= (count shapes) 1)
[:* [:*
[:& menu-separator] [:> menu-separator* {}]
[:& menu-entry {:title (tr "workspace.shape.menu.rename") [:> menu-entry* {:title (tr "workspace.shape.menu.rename")
:shortcut (sc/get-tooltip :rename) :shortcut (sc/get-tooltip :rename)
:on-click do-rename}]]))) :on-click do-rename}]])))
(mf/defc context-menu-group (mf/defc context-menu-group*
{::mf/props :obj
::mf/private true}
[{:keys [shapes]}] [{:keys [shapes]}]
(let [multiple? (> (count shapes) 1) (let [multiple? (> (count shapes) 1)
single? (= (count shapes) 1) single? (= (count shapes) 1)
@ -266,42 +280,46 @@
(when (not any-in-copy?) (when (not any-in-copy?)
[:* [:*
(when (or has-bool? has-group? has-mask? has-frame?) (when (or has-bool? has-group? has-mask? has-frame?)
[:& menu-entry {:title (tr "workspace.shape.menu.ungroup") [:> menu-entry* {:title (tr "workspace.shape.menu.ungroup")
:shortcut (sc/get-tooltip :ungroup) :shortcut (sc/get-tooltip :ungroup)
:on-click do-remove-group}]) :on-click do-remove-group}])
[:& menu-entry {:title (tr "workspace.shape.menu.group") [:> menu-entry* {:title (tr "workspace.shape.menu.group")
:shortcut (sc/get-tooltip :group) :shortcut (sc/get-tooltip :group)
:on-click do-create-group}] :on-click do-create-group}]
(when (or multiple? (and is-group? (not has-mask?)) is-bool?) (when (or multiple? (and is-group? (not has-mask?)) is-bool?)
[:& menu-entry {:title (tr "workspace.shape.menu.mask") [:> menu-entry* {:title (tr "workspace.shape.menu.mask")
:shortcut (sc/get-tooltip :mask) :shortcut (sc/get-tooltip :mask)
:on-click do-mask-group}]) :on-click do-mask-group}])
(when has-mask? (when has-mask?
[:& menu-entry {:title (tr "workspace.shape.menu.unmask") [:> menu-entry* {:title (tr "workspace.shape.menu.unmask")
:shortcut (sc/get-tooltip :unmask) :shortcut (sc/get-tooltip :unmask)
:on-click do-unmask-group}]) :on-click do-unmask-group}])
[:& menu-entry {:title (tr "workspace.shape.menu.create-artboard-from-selection") [:> menu-entry* {:title (tr "workspace.shape.menu.create-artboard-from-selection")
:shortcut (sc/get-tooltip :artboard-selection) :shortcut (sc/get-tooltip :artboard-selection)
:on-click do-create-artboard-from-selection}] :on-click do-create-artboard-from-selection}]
[:& menu-separator]])])) [:> menu-separator* {}]])]))
(mf/defc context-focus-mode-menu (mf/defc context-focus-mode-menu*
[{:keys []}] {::mf/props :obj
::mf/private true}
[]
(let [focus (mf/deref refs/workspace-focus-selected) (let [focus (mf/deref refs/workspace-focus-selected)
do-toggle-focus-mode #(st/emit! (dw/toggle-focus-mode))] do-toggle-focus-mode #(st/emit! (dw/toggle-focus-mode))]
[:& menu-entry {:title (if (empty? focus) [:> menu-entry* {:title (if (empty? focus)
(tr "workspace.focus.focus-on") (tr "workspace.focus.focus-on")
(tr "workspace.focus.focus-off")) (tr "workspace.focus.focus-off"))
:shortcut (sc/get-tooltip :toggle-focus-mode) :shortcut (sc/get-tooltip :toggle-focus-mode)
:on-click do-toggle-focus-mode}])) :on-click do-toggle-focus-mode}]))
(mf/defc context-menu-path (mf/defc context-menu-path*
[{:keys [shapes disable-flatten? disable-booleans?]}] {::mf/props :obj
::mf/private true}
[{:keys [shapes disable-flatten disable-booleans]}]
(let [multiple? (> (count shapes) 1) (let [multiple? (> (count shapes) 1)
single? (= (count shapes) 1) single? (= (count shapes) 1)
@ -330,37 +348,39 @@
(st/emit! (dw/change-bool-type (-> shapes first :id) bool-type))))] (st/emit! (dw/change-bool-type (-> shapes first :id) bool-type))))]
[:* [:*
(when (and single? (not is-frame?)) (when (and single? (not is-frame?))
[:& menu-entry {:title (tr "workspace.shape.menu.edit") [:> menu-entry* {:title (tr "workspace.shape.menu.edit")
:shortcut (sc/get-tooltip :start-editing) :shortcut (sc/get-tooltip :start-editing)
:on-click do-start-editing}]) :on-click do-start-editing}])
(when-not (or disable-flatten? has-frame? has-path?) (when-not (or disable-flatten has-frame? has-path?)
[:& menu-entry {:title (tr "workspace.shape.menu.transform-to-path") [:> menu-entry* {:title (tr "workspace.shape.menu.transform-to-path")
:on-click do-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?)))) (or multiple? (and single? (or is-group? is-bool?))))
[:& menu-entry {:title (tr "workspace.shape.menu.path")} [:> menu-entry* {:title (tr "workspace.shape.menu.path")}
[:& menu-entry {:title (tr "workspace.shape.menu.union") [:> menu-entry* {:title (tr "workspace.shape.menu.union")
:shortcut (sc/get-tooltip :bool-union) :shortcut (sc/get-tooltip :bool-union)
:on-click (make-do-bool :union)}] :on-click (make-do-bool :union)}]
[:& menu-entry {:title (tr "workspace.shape.menu.difference") [:> menu-entry* {:title (tr "workspace.shape.menu.difference")
:shortcut (sc/get-tooltip :bool-difference) :shortcut (sc/get-tooltip :bool-difference)
:on-click (make-do-bool :difference)}] :on-click (make-do-bool :difference)}]
[:& menu-entry {:title (tr "workspace.shape.menu.intersection") [:> menu-entry* {:title (tr "workspace.shape.menu.intersection")
:shortcut (sc/get-tooltip :bool-intersection) :shortcut (sc/get-tooltip :bool-intersection)
:on-click (make-do-bool :intersection)}] :on-click (make-do-bool :intersection)}]
[:& menu-entry {:title (tr "workspace.shape.menu.exclude") [:> menu-entry* {:title (tr "workspace.shape.menu.exclude")
:shortcut (sc/get-tooltip :bool-exclude) :shortcut (sc/get-tooltip :bool-exclude)
:on-click (make-do-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-separator* {}]
[:& menu-entry {:title (tr "workspace.shape.menu.flatten") [:> menu-entry* {:title (tr "workspace.shape.menu.flatten")
:on-click do-transform-to-path}]])])])) :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]}] [{:keys [shapes]}]
(let [ids (mapv :id shapes) (let [ids (mapv :id shapes)
do-show-shape #(st/emit! (dw/update-shape-flags ids {:hidden false})) 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}))] do-unlock-shape #(st/emit! (dw/update-shape-flags ids {:blocked false}))]
[:* [:*
(if (every? :hidden shapes) (if (every? :hidden shapes)
[:& menu-entry {:title (tr "workspace.shape.menu.show") [:> menu-entry* {:title (tr "workspace.shape.menu.show")
:shortcut (sc/get-tooltip :toggle-visibility) :shortcut (sc/get-tooltip :toggle-visibility)
:on-click do-show-shape}] :on-click do-show-shape}]
[:& menu-entry {:title (tr "workspace.shape.menu.hide") [:> menu-entry* {:title (tr "workspace.shape.menu.hide")
:shortcut (sc/get-tooltip :toggle-visibility) :shortcut (sc/get-tooltip :toggle-visibility)
:on-click do-hide-shape}]) :on-click do-hide-shape}])
(if (every? :blocked shapes) (if (every? :blocked shapes)
[:& menu-entry {:title (tr "workspace.shape.menu.unlock") [:> menu-entry* {:title (tr "workspace.shape.menu.unlock")
:shortcut (sc/get-tooltip :toggle-lock) :shortcut (sc/get-tooltip :toggle-lock)
:on-click do-unlock-shape}] :on-click do-unlock-shape}]
[:& menu-entry {:title (tr "workspace.shape.menu.lock") [:> menu-entry* {:title (tr "workspace.shape.menu.lock")
:shortcut (sc/get-tooltip :toggle-lock) :shortcut (sc/get-tooltip :toggle-lock)
:on-click do-lock-shape}])])) :on-click do-lock-shape}])]))
(mf/defc context-menu-prototype (mf/defc context-menu-prototype*
{::mf/props :obj} {::mf/props :obj
::mf/private true}
[{:keys [shapes]}] [{:keys [shapes]}]
(let [flows (mf/deref refs/workspace-page-flows) (let [flows (mf/deref refs/workspace-page-flows)
options-mode (mf/deref refs/options-mode-global) options-mode (mf/deref refs/options-mode-global)
@ -400,13 +421,14 @@
(when (and prototype? is-frame?) (when (and prototype? is-frame?)
(if-let [flow (ctp/get-frame-flow flows (-> shapes first :id))] (if-let [flow (ctp/get-frame-flow flows (-> shapes first :id))]
[:& menu-entry {:title (tr "workspace.shape.menu.delete-flow-start") [:> menu-entry* {:title (tr "workspace.shape.menu.delete-flow-start")
:on-click (do-remove-flow flow)}] :on-click (do-remove-flow flow)}]
[:& menu-entry {:title (tr "workspace.shape.menu.flow-start") [:> menu-entry* {:title (tr "workspace.shape.menu.flow-start")
:on-click do-add-flow}])))) :on-click do-add-flow}]))))
(mf/defc context-menu-layout (mf/defc context-menu-layout*
{::mf/props :obj} {::mf/props :obj
::mf/private true}
[{:keys [shapes]}] [{:keys [shapes]}]
(let [single? (= (count shapes) 1) (let [single? (= (count shapes) 1)
objects (deref refs/workspace-page-objects) objects (deref refs/workspace-page-objects)
@ -438,27 +460,29 @@
(if (or ^boolean has-flex? (if (or ^boolean has-flex?
^boolean has-grid?) ^boolean has-grid?)
[:div [:div
[:& menu-separator] [:> menu-separator* {}]
(if has-flex? (if has-flex?
[:& menu-entry {:title (tr "workspace.shape.menu.remove-flex") [:> menu-entry* {:title (tr "workspace.shape.menu.remove-flex")
:shortcut (sc/get-tooltip :toggle-layout-flex) :shortcut (sc/get-tooltip :toggle-layout-flex)
:on-click on-remove-layout}] :on-click on-remove-layout}]
[:& menu-entry {:title (tr "workspace.shape.menu.remove-grid") [:> menu-entry* {:title (tr "workspace.shape.menu.remove-grid")
:shortcut (sc/get-tooltip :toggle-layout-grid) :shortcut (sc/get-tooltip :toggle-layout-grid)
:on-click on-remove-layout}])] :on-click on-remove-layout}])]
[:div [:div
[:& menu-separator] [:> menu-separator* {}]
[:& menu-entry {:title (tr "workspace.shape.menu.add-flex") [:> menu-entry* {:title (tr "workspace.shape.menu.add-flex")
:shortcut (sc/get-tooltip :toggle-layout-flex) :shortcut (sc/get-tooltip :toggle-layout-flex)
:value "flex" :value "flex"
:on-click on-add-layout}] :on-click on-add-layout}]
[:& menu-entry {:title (tr "workspace.shape.menu.add-grid") [:> menu-entry* {:title (tr "workspace.shape.menu.add-grid")
:shortcut (sc/get-tooltip :toggle-layout-grid) :shortcut (sc/get-tooltip :toggle-layout-grid)
:value "grid" :value "grid"
:on-click on-add-layout}]]))])) :on-click on-add-layout}]]))]))
(mf/defc context-menu-component (mf/defc context-menu-component*
{::mf/props :obj
::mf/private true}
[{:keys [shapes]}] [{:keys [shapes]}]
(let [components-v2 (features/use-feature "components/v2") (let [components-v2 (features/use-feature "components/v2")
single? (= (count shapes) 1) single? (= (count shapes) 1)
@ -471,59 +495,66 @@
[:* [:*
(when can-make-component ;; We don't want to change the structure of component copies (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") [:> menu-entry* {:title (tr "workspace.shape.menu.create-component")
:shortcut (sc/get-tooltip :create-component) :shortcut (sc/get-tooltip :create-component)
:on-click do-add-component}] :on-click do-add-component}]
(when (not single?) (when (not single?)
[:& menu-entry {:title (tr "workspace.shape.menu.create-multiple-components") [:> menu-entry* {:title (tr "workspace.shape.menu.create-multiple-components")
:on-click do-add-multiple-components}])]) :on-click do-add-multiple-components}])])
(when (seq components-menu-entries) (when (seq components-menu-entries)
[:* [:*
[:& menu-separator] [:> menu-separator* {}]
(for [entry components-menu-entries :when (not (nil? entry))] (for [entry components-menu-entries :when (not (nil? entry))]
[:& menu-entry {:key (uuid/next) [:> menu-entry* {:key (uuid/next)
:title (:title entry) :title (:title entry)
:shortcut (when (contains? entry :shortcut) (sc/get-tooltip (:shortcut entry))) :shortcut (when (contains? entry :shortcut) (sc/get-tooltip (:shortcut entry)))
:on-click (:action 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))] (let [do-delete #(st/emit! (dw/delete-selected))]
[:* [:*
[:& menu-separator] [:> menu-separator* {}]
[:& menu-entry {:title (tr "workspace.shape.menu.delete") [:> menu-entry* {:title (tr "workspace.shape.menu.delete")
:shortcut (sc/get-tooltip :delete) :shortcut (sc/get-tooltip :delete)
:on-click do-delete}]])) :on-click do-delete}]]))
(mf/defc shape-context-menu (mf/defc shape-context-menu*
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]
[{:keys [mdata] :as props}] ::mf/private true
(let [{:keys [disable-booleans? disable-flatten?]} mdata ::mf/props :obj}
[{:keys [mdata]}]
(let [{:keys [disable-booleans disable-flatten]} mdata
shapes (mf/deref refs/selected-objects) shapes (mf/deref refs/selected-objects)
props #js {:shapes shapes props (mf/spread-props
:disable-booleans? disable-booleans? {:shapes shapes
:disable-flatten? disable-flatten?}] :disable-booleans disable-booleans
:disable-flatten disable-flatten})]
(when-not (empty? shapes) (when-not (empty? shapes)
[:* [:*
[:> context-menu-edit props] [:> context-menu-edit* props]
[:> context-menu-layer-position props] [:> context-menu-layer-position* props]
[:> context-menu-flip props] [:> context-menu-flip* props]
[:> context-menu-thumbnail props] [:> context-menu-thumbnail* props]
[:> context-menu-rename props] [:> context-menu-rename* props]
[:> context-menu-group props] [:> context-menu-group* props]
[:> context-focus-mode-menu props] [:> context-focus-mode-menu* props]
[:> context-menu-path props] [:> context-menu-path* props]
[:> context-menu-layer-options props] [:> context-menu-layer-options* props]
[:> context-menu-prototype props] [:> context-menu-prototype* props]
[:> context-menu-layout props] [:> context-menu-layout* props]
[:> context-menu-component props] [:> context-menu-component* props]
[:> context-menu-delete props]]))) [:> context-menu-delete* props]])))
(mf/defc page-item-context-menu (mf/defc page-item-context-menu*
[{:keys [mdata] :as props}] {::mf/props :obj
::mf/private true}
[{:keys [mdata]}]
(let [page (:page mdata) (let [page (:page mdata)
deletable? (:deletable? mdata) deletable? (:deletable? mdata)
id (:id page) id (:id page)
@ -540,13 +571,13 @@
[:* [:*
(when deletable? (when deletable?
[:& menu-entry {:title (tr "workspace.assets.delete") [:> menu-entry* {:title (tr "workspace.assets.delete")
:on-click do-delete}]) :on-click do-delete}])
[:& menu-entry {:title (tr "workspace.assets.rename") [:> menu-entry* {:title (tr "workspace.assets.rename")
:on-click do-rename}] :on-click do-rename}]
[:& menu-entry {:title (tr "workspace.assets.duplicate") [:> menu-entry* {:title (tr "workspace.assets.duplicate")
:on-click do-duplicate}]])) :on-click do-duplicate}]]))
(mf/defc viewport-context-menu* (mf/defc viewport-context-menu*
{::mf/props :obj} {::mf/props :obj}
@ -559,68 +590,72 @@
do-toggle-focus-mode #(st/emit! (dw/toggle-focus-mode))] do-toggle-focus-mode #(st/emit! (dw/toggle-focus-mode))]
[:* [:*
(when-not ^boolean read-only? (when-not ^boolean read-only?
[:& menu-entry {:title (tr "workspace.shape.menu.paste") [:> menu-entry* {:title (tr "workspace.shape.menu.paste")
:shortcut (sc/get-tooltip :paste) :shortcut (sc/get-tooltip :paste)
:on-click do-paste}]) :on-click do-paste}])
[:& menu-entry {:title (tr "workspace.shape.menu.hide-ui") [:> menu-entry* {:title (tr "workspace.shape.menu.hide-ui")
:shortcut (sc/get-tooltip :hide-ui) :shortcut (sc/get-tooltip :hide-ui)
:on-click do-hide-ui}] :on-click do-hide-ui}]
(when (d/not-empty? focus) (when (d/not-empty? focus)
[:& menu-entry {:title (tr "workspace.focus.focus-off") [:> menu-entry* {:title (tr "workspace.focus.focus-off")
:shortcut (sc/get-tooltip :toggle-focus-mode) :shortcut (sc/get-tooltip :toggle-focus-mode)
:on-click do-toggle-focus-mode}])])) :on-click do-toggle-focus-mode}])]))
(mf/defc grid-track-context-menu (mf/defc grid-track-context-menu*
[{:keys [mdata] :as props}] {::mf/props :obj
::mf/private true}
[{:keys [mdata]}]
(let [{:keys [type index grid-id]} mdata (let [{:keys [type index grid-id]} mdata
do-delete-track do-delete-track
(mf/use-callback (mf/use-fn
(mf/deps grid-id type index) (mf/deps grid-id type index)
(fn [] (fn []
(st/emit! (dwsl/remove-layout-track [grid-id] type index)))) (st/emit! (dwsl/remove-layout-track [grid-id] type index))))
do-add-track-before do-add-track-before
(mf/use-callback (mf/use-fn
(mf/deps grid-id type index) (mf/deps grid-id type index)
(fn [] (fn []
(st/emit! (dwsl/add-layout-track [grid-id] type ctl/default-track-value index)))) (st/emit! (dwsl/add-layout-track [grid-id] type ctl/default-track-value index))))
do-add-track-after do-add-track-after
(mf/use-callback (mf/use-fn
(mf/deps grid-id type index) (mf/deps grid-id type index)
(fn [] (fn []
(st/emit! (dwsl/add-layout-track [grid-id] type ctl/default-track-value (inc index))))) (st/emit! (dwsl/add-layout-track [grid-id] type ctl/default-track-value (inc index)))))
do-duplicate-track do-duplicate-track
(mf/use-callback (mf/use-fn
(mf/deps grid-id type index) (mf/deps grid-id type index)
(fn [] (fn []
(st/emit! (dwsl/duplicate-layout-track [grid-id] type index)))) (st/emit! (dwsl/duplicate-layout-track [grid-id] type index))))
do-delete-track-shapes do-delete-track-shapes
(mf/use-callback (mf/use-fn
(mf/deps grid-id type index) (mf/deps grid-id type index)
(fn [] (fn []
(st/emit! (dwsl/remove-layout-track [grid-id] type index {:with-shapes? true}))))] (st/emit! (dwsl/remove-layout-track [grid-id] type index {:with-shapes? true}))))]
(if (= type :column) (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.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-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.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") :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.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.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-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.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") :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.delete-shapes") :on-click do-delete-track-shapes}]])))
(mf/defc grid-cells-context-menu (mf/defc grid-cells-context-menu*
[{:keys [mdata] :as props}] {::mf/props :obj
::mf/private true}
[{:keys [mdata]}]
(let [{:keys [grid cells]} mdata (let [{:keys [grid cells]} mdata
single? (= (count cells) 1) single? (= (count cells) 1)
@ -631,29 +666,29 @@
#(ctl/valid-area-cells? cells)) #(ctl/valid-area-cells? cells))
do-merge-cells do-merge-cells
(mf/use-callback (mf/use-fn
(mf/deps grid cells) (mf/deps grid cells)
(fn [] (fn []
(st/emit! (dwsl/merge-cells (:id grid) (map :id cells))))) (st/emit! (dwsl/merge-cells (:id grid) (map :id cells)))))
do-create-board do-create-board
(mf/use-callback (mf/use-fn
(mf/deps grid cells) (mf/deps grid cells)
(fn [] (fn []
(st/emit! (dwsl/create-cell-board (:id grid) (map :id cells)))))] (st/emit! (dwsl/create-cell-board (:id grid) (map :id cells)))))]
[:* [:*
(when (not single?) (when (not single?)
[:& menu-entry {:title (tr "workspace.context-menu.grid-cells.merge") [:> menu-entry* {:title (tr "workspace.context-menu.grid-cells.merge")
:on-click do-merge-cells :on-click do-merge-cells
:disabled (not can-merge?)}]) :disabled (not can-merge?)}])
(when single? (when single?
[:& menu-entry {:title (tr "workspace.context-menu.grid-cells.area") [:> menu-entry* {:title (tr "workspace.context-menu.grid-cells.area")
:on-click do-merge-cells}]) :on-click do-merge-cells}])
[:& menu-entry {:title (tr "workspace.context-menu.grid-cells.create-board") [:> menu-entry* {:title (tr "workspace.context-menu.grid-cells.create-board")
:on-click do-create-board :on-click do-create-board
:disabled (and (not single?) (not can-merge?))}]])) :disabled (and (not single?) (not can-merge?))}]]))
;; FIXME: optimize because it is rendered always ;; FIXME: optimize because it is rendered always
@ -688,8 +723,8 @@
(if ^boolean read-only? (if ^boolean read-only?
[:> viewport-context-menu* {:mdata mdata}] [:> viewport-context-menu* {:mdata mdata}]
(case (:kind mdata) (case (:kind mdata)
:shape [:& shape-context-menu {:mdata mdata}] :shape [:> shape-context-menu* {:mdata mdata}]
:page [:& page-item-context-menu {:mdata mdata}] :page [:> page-item-context-menu* {:mdata mdata}]
:grid-track [:& grid-track-context-menu {:mdata mdata}] :grid-track [:> grid-track-context-menu* {:mdata mdata}]
:grid-cells [:& grid-cells-context-menu {:mdata mdata}] :grid-cells [:> grid-cells-context-menu* {:mdata mdata}]
[:& viewport-context-menu* {:mdata mdata}]))]]])) [:> viewport-context-menu* {:mdata mdata}]))]]]))

View file

@ -62,7 +62,7 @@
(let [fdata (let [{:keys [id] :as wfile} (:workspace-data state)] (let [fdata (let [{:keys [id] :as wfile} (:workspace-data state)]
(if (= id library-id) (if (= id library-id)
wfile wfile
(dm/get-in state [:workspace-libraries library-id :data])))] (dm/get-in state [:libraries library-id :data])))]
{:colors (-> fdata :colors vals) {:colors (-> fdata :colors vals)
:media (-> fdata :media vals) :media (-> fdata :media vals)
:components (ctkl/components-seq fdata) :components (ctkl/components-seq fdata)
@ -557,7 +557,7 @@
file-id (:id file) file-id (:id file)
shared? (:is-shared file) shared? (:is-shared file)
libraries (mf/deref refs/workspace-libraries) libraries (mf/deref refs/libraries)
libraries (mf/with-memo [libraries] libraries (mf/with-memo [libraries]
(d/removem (fn [[_ val]] (:is-indirect val)) libraries)) (d/removem (fn [[_ val]] (:is-indirect val)) libraries))

View file

@ -31,7 +31,7 @@
::mf/props :obj ::mf/props :obj
::mf/private true} ::mf/private true}
[{:keys [filters]}] [{:keys [filters]}]
(let [libraries (mf/deref refs/workspace-libraries) (let [libraries (mf/deref refs/libraries)
libraries (mf/with-memo [libraries] libraries (mf/with-memo [libraries]
(->> (vals libraries) (->> (vals libraries)
(remove :is-indirect) (remove :is-indirect)
@ -88,7 +88,7 @@
section (:section filters) section (:section filters)
ordering (:ordering filters) ordering (:ordering filters)
reverse-sort? (= :desc ordering) reverse-sort? (= :desc ordering)
num-libs (count (mf/deref refs/workspace-libraries)) num-libs (count (mf/deref refs/libraries))
toggle-ordering toggle-ordering
(mf/use-fn (mf/use-fn

View file

@ -315,17 +315,17 @@
current-file-id (mf/use-ctx ctx/current-file-id) current-file-id (mf/use-ctx ctx/current-file-id)
objects (deref refs/workspace-page-objects) objects (deref refs/workspace-page-objects)
workspace-data (deref refs/workspace-data) 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} current-file {:id current-file-id :data workspace-data}
find-component (fn [shape include-deleted?] find-component (fn [shape include-deleted?]
(ctf/resolve-component (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] local-or-exists (fn [shape]
(let [library-id (:component-file shape)] (let [library-id (:component-file shape)]
(or (= library-id current-file-id) (or (= library-id current-file-id)
(some? (get workspace-libraries library-id))))) (some? (get libraries library-id)))))
restorable-copies (->> copies restorable-copies (->> copies
(filter #(nil? (find-component % false))) (filter #(nil? (find-component % false)))

View file

@ -50,7 +50,7 @@
(if components-v2 (if components-v2
(ctf/get-component-page data component) (ctf/get-component-page data component)
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) root-shape (ctf/get-component-root data component)
container (if components-v2 container (if components-v2
(ctf/get-component-page data component) (ctf/get-component-page data component)
@ -466,7 +466,7 @@
(fn [component event] (fn [component event]
(let [file-data (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 shape-main
(ctf/get-component-root file-data component)] (ctf/get-component-root file-data component)]

View file

@ -78,7 +78,7 @@
[{:keys [selected objects page-id file-id selected-shapes shapes-with-children]}] [{:keys [selected objects page-id file-id selected-shapes shapes-with-children]}]
(let [sp-panel (mf/deref refs/specialized-panel) (let [sp-panel (mf/deref refs/specialized-panel)
drawing (mf/deref refs/workspace-drawing) 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) edition (mf/deref refs/selected-edition)
edit-grid? (ctl/grid-layout? objects edition) edit-grid? (ctl/grid-layout? objects edition)
grid-edition (mf/deref refs/workspace-grid-edition) grid-edition (mf/deref refs/workspace-grid-edition)

View file

@ -272,7 +272,7 @@
(letfn [(get-libraries [state] (letfn [(get-libraries [state]
(let [file (:workspace-file state) (let [file (:workspace-file state)
data (:workspace-data state) data (:workspace-data state)
libs (:workspace-libraries state)] libs (:libraries state)]
(assoc libs (:id file) (assoc libs (:id file)
(assoc file :data data))))] (assoc file :data data))))]
(l/derived get-libraries st/state))) (l/derived get-libraries st/state)))
@ -524,7 +524,7 @@
(let [current-file-id (mf/use-ctx ctx/current-file-id) (let [current-file-id (mf/use-ctx ctx/current-file-id)
components-v2 (mf/use-ctx ctx/components-v2) components-v2 (mf/use-ctx ctx/components-v2)
workspace-data (deref refs/workspace-data) workspace-data (deref refs/workspace-data)
workspace-libraries (deref refs/workspace-libraries) libraries (deref refs/libraries)
state* (mf/use-state {:show-content true state* (mf/use-state {:show-content true
:menu-open false}) :menu-open false})
@ -544,7 +544,7 @@
component (ctf/resolve-component shape component (ctf/resolve-component shape
{:id current-file-id {:id current-file-id
:data workspace-data} :data workspace-data}
workspace-libraries libraries
{:include-deleted? true}) {:include-deleted? true})
main-instance? (if components-v2 (ctk/main-instance? shape) true) main-instance? (if components-v2 (ctk/main-instance? shape) true)

View file

@ -184,7 +184,7 @@
(let [file-id (mf/use-ctx ctx/current-file-id) (let [file-id (mf/use-ctx ctx/current-file-id)
typographies (mf/deref refs/workspace-file-typography) typographies (mf/deref refs/workspace-file-typography)
shared-libs (mf/deref refs/workspace-libraries) shared-libs (mf/deref refs/libraries)
label (case type label (case type
:multiple (tr "workspace.options.text-options.title-selection") :multiple (tr "workspace.options.text-options.title-selection")
:group (tr "workspace.options.text-options.title-group") :group (tr "workspace.options.text-options.title-group")

View file

@ -51,7 +51,7 @@
disable-drag on-focus on-blur select-only select-on-focus]}] disable-drag on-focus on-blur select-only select-on-focus]}]
(let [current-file-id (mf/use-ctx ctx/current-file-id) (let [current-file-id (mf/use-ctx ctx/current-file-id)
file-colors (mf/deref refs/workspace-file-colors) 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) hover-detach (mf/use-state false)
on-change (h/use-ref-callback on-change) on-change (h/use-ref-callback on-change)
src-colors (if (= (:file-id color) current-file-id) src-colors (if (= (:file-id color) current-file-id)

View file

@ -53,7 +53,7 @@
(mf/deref refs/workspace-v2-editor-state) (mf/deref refs/workspace-v2-editor-state)
(mf/deref refs/workspace-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")) editor-state (when (not (features/active-feature? @st/state "text-editor/v2"))
(get state-map (:id shape))) (get state-map (:id shape)))

View file

@ -183,7 +183,7 @@
[{:keys [size width selected] :as props}] [{:keys [size width selected] :as props}]
(let [selected-ids (mf/deref refs/selected-shapes) (let [selected-ids (mf/deref refs/selected-shapes)
file-typographies (mf/deref refs/workspace-file-typography) 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)] current-file-id (mf/use-ctx ctx/current-file-id)]
[:& palette {:current-file-id current-file-id [:& palette {:current-file-id current-file-id
:selected-ids selected-ids :selected-ids selected-ids

View file

@ -14,11 +14,10 @@
[app.util.i18n :refer [tr]] [app.util.i18n :refer [tr]]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(mf/defc text-palette-ctx-menu (mf/defc text-palette-ctx-menu
[{:keys [show-menu? close-menu on-select-palette selected]}] [{:keys [show-menu? close-menu on-select-palette selected]}]
(let [file-typographies (mf/deref refs/workspace-file-typography) (let [typographies (mf/deref refs/workspace-file-typography)
shared-libs (mf/deref refs/workspace-libraries)] shared-libs (mf/deref refs/libraries)]
[:& dropdown {:show show-menu? [:& dropdown {:show show-menu?
:on-close close-menu} :on-close close-menu}
[:ul {:class (stl/css :text-context-menu)} [:ul {:class (stl/css :text-context-menu)}
@ -49,7 +48,7 @@
[:span {:class (stl/css :lib-name)} [:span {:class (stl/css :lib-name)}
(tr "workspace.libraries.colors.file-library")] (tr "workspace.libraries.colors.file-library")]
[:span {:class (stl/css :lib-num)} [:span {:class (stl/css :lib-num)}
(dm/str "(" (count file-typographies) ")")]] (dm/str "(" (count typographies) ")")]]
(when (= selected :file) (when (= selected :file)
[:span {:class (stl/css :icon-wrapper)} [:span {:class (stl/css :icon-wrapper)}
i/tick])]]])) i/tick])]]]))

View file

@ -622,7 +622,7 @@
:hover-disabled? hover-disabled?}])]) :hover-disabled? hover-disabled?}])])
(when show-gradient-handlers? (when show-gradient-handlers?
[:& gradients/gradient-handlers [:> gradients/gradient-handlers*
{:id (first selected) {:id (first selected)
:zoom zoom}]) :zoom zoom}])

View file

@ -441,8 +441,9 @@
:r (/ 4 zoom) :r (/ 4 zoom)
:fill "var(--app-white)"}]))])) :fill "var(--app-white)"}]))]))
(mf/defc gradient-handlers* (mf/defc gradient-handlers-impl*
[{:keys [zoom stops gradient editing shape] :as kk}] {::mf/props :obj}
[{:keys [zoom stops gradient editing shape]}]
(let [transform (gsh/transform-matrix shape) (let [transform (gsh/transform-matrix shape)
transform-inverse (gsh/inverse-transform-matrix shape) transform-inverse (gsh/inverse-transform-matrix shape)
@ -509,8 +510,9 @@
:on-change-finish on-change-finish :on-change-finish on-change-finish
:on-change-width on-change-width}])) :on-change-width on-change-width}]))
(mf/defc gradient-handlers (mf/defc gradient-handlers*
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]
::mf/props :obj}
[{:keys [id zoom]}] [{:keys [id zoom]}]
(let [shape-ref (mf/use-memo (mf/deps id) #(refs/object-by-id id)) (let [shape-ref (mf/use-memo (mf/deps id) #(refs/object-by-id id))
shape (mf/deref shape-ref) shape (mf/deref shape-ref)
@ -520,7 +522,7 @@
editing-stop (:editing-stop state)] editing-stop (:editing-stop state)]
(when (and (some? gradient) (= id (:shape-id gradient))) (when (and (some? gradient) (= id (:shape-id gradient)))
[:& gradient-handlers* [:> gradient-handlers-impl*
{:zoom zoom {:zoom zoom
:gradient gradient :gradient gradient
:stops stops :stops stops

View file

@ -617,7 +617,7 @@
:hover-disabled? hover-disabled?}])]) :hover-disabled? hover-disabled?}])])
(when show-gradient-handlers? (when show-gradient-handlers?
[:& gradients/gradient-handlers [:> gradients/gradient-handlers*
{:id (first selected) {:id (first selected)
:zoom zoom}]) :zoom zoom}])

View file

@ -160,7 +160,7 @@
(map #(obj/get % "$id")) (map #(obj/get % "$id"))
(mapcat #(cfh/get-children-with-self objects %))) (mapcat #(cfh/get-children-with-self objects %)))
file-id (:current-file-id @st/state) 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) (->> (ctc/extract-all-colors shapes file-id shared-libs)
(group-by :attrs) (group-by :attrs)
@ -182,7 +182,7 @@
:else :else
(let [file-id (:current-file-id @st/state) (let [file-id (:current-file-id @st/state)
shared-libs (:workspace-libraries @st/state) shared-libs (:libraries @st/state)
objects (u/locate-objects) objects (u/locate-objects)
shapes shapes
(->> shapes (->> shapes

View file

@ -929,7 +929,7 @@
:connected :connected
{:get {:get
(fn [] (fn []
(let [libraries (get @st/state :workspace-libraries)] (let [libraries (get @st/state :libraries)]
(apply array (->> libraries keys (map (partial library-proxy plugin-id))))))} (apply array (->> libraries keys (map (partial library-proxy plugin-id))))))}
:availableLibraries :availableLibraries
@ -937,7 +937,7 @@
(let [team-id (:current-team-id @st/state)] (let [team-id (:current-team-id @st/state)]
(js/Promise. (js/Promise.
(fn [resolve reject] (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}) (->> (rp/cmd! :get-team-shared-files {:team-id team-id})
(rx/map (fn [result] (rx/map (fn [result]
(->> result (->> result

View file

@ -20,7 +20,7 @@
(if (= id (:current-file-id @st/state)) (if (= id (:current-file-id @st/state))
(-> (:workspace-file @st/state) (-> (:workspace-file @st/state)
(assoc :data (:workspace-data @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 (defn locate-page
[file-id id] [file-id id]
@ -65,10 +65,10 @@
(defn locate-component (defn locate-component
[objects shape] [objects shape]
(let [current-file-id (:current-file-id @st/state) (let [current-file-id (:current-file-id @st/state)
workspace-data (:workspace-data @st/state) workspace-data (:workspace-data @st/state)
workspace-libraries (:workspace-libraries @st/state) libraries (:libraries @st/state)
root (ctn/get-instance-root objects shape)] root (ctn/get-instance-root objects shape)]
[root (ctf/resolve-component root {:id current-file-id :data workspace-data} workspace-libraries {:include-deleted? true})])) [root (ctf/resolve-component root {:id current-file-id :data workspace-data} libraries {:include-deleted? true})]))
(defn proxy->file (defn proxy->file
[proxy] [proxy]

View file

@ -248,7 +248,7 @@
(let [page-id (get state :current-page-id) (let [page-id (get state :current-page-id)
file (assoc (get state :workspace-file) file (assoc (get state :workspace-file)
:data (get state :workspace-data)) :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 (ctf/dump-tree file page-id libraries {:show-ids show-ids
:show-touched show-touched :show-touched show-touched
:show-modified show-modified})))) :show-modified show-modified}))))
@ -266,7 +266,7 @@
(let [page-id (get state :current-page-id) (let [page-id (get state :current-page-id)
file (assoc (get state :workspace-file) file (assoc (get state :workspace-file)
:data (get state :workspace-data)) :data (get state :workspace-data))
libraries (get state :workspace-libraries) libraries (get state :libraries)
shape-id (if (some? shape-id) shape-id (if (some? shape-id)
(uuid/uuid shape-id) (uuid/uuid shape-id)
(let [objects (get-in state [:workspace-data :pages-index page-id :objects]) (let [objects (get-in state [:workspace-data :pages-index page-id :objects])
@ -383,7 +383,7 @@
([shape-id] ([shape-id]
(let [file (assoc (get @st/state :workspace-file) (let [file (assoc (get @st/state :workspace-file)
:data (get @st/state :workspace-data)) :data (get @st/state :workspace-data))
libraries (get @st/state :workspace-libraries)] libraries (get @st/state :libraries)]
(try (try
(->> (if-let [shape-id (some-> shape-id parse-uuid)] (->> (if-let [shape-id (some-> shape-id parse-uuid)]
@ -417,7 +417,7 @@
fdata (get state :workspace-data) fdata (get state :workspace-data)
file (assoc file :data fdata) file (assoc file :data fdata)
libs (get state :workspace-libraries) libs (get state :libraries)
errors (cfv/validate-file file libs) errors (cfv/validate-file file libs)
_ (l/dbg :hint "repair current file" :errors (count errors)) _ (l/dbg :hint "repair current file" :errors (count errors))