0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-18 10:41:29 -05:00

Refactor state management of workspace assets sidebar

This commit is contained in:
Andrey Antukh 2023-05-15 09:35:59 +02:00 committed by Alejandro Alonso
parent ef27301238
commit fcc4f4eed8
16 changed files with 1665 additions and 1368 deletions

View file

@ -43,4 +43,3 @@
(watch [_ _ _]
(->> (rp/cmd! :delete-share-link {:id id})
(rx/ignore)))))

View file

@ -237,34 +237,6 @@
(->> (rp/cmd! :get-team-shared-files {:team-id team-id})
(rx/map shared-files-fetched))))))
;; --- EVENT: Get files that use this shared-file
(defn clean-temp-shared
[]
(ptk/reify ::clean-temp-shared
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:dashboard-local :files-with-shared] nil))))
(defn library-using-files-fetched
[files]
(ptk/reify ::library-using-files-fetched
ptk/UpdateEvent
(update [_ state]
(let [files (d/index-by :id files)]
(assoc-in state [:dashboard-local :files-with-shared] files)))))
(defn fetch-libraries-using-files
[files]
(ptk/reify ::fetch-library-using-files
ptk/WatchEvent
(watch [_ _ _]
(->> (rx/from files)
(rx/map :id)
(rx/mapcat #(rp/cmd! :get-library-file-references {:file-id %}))
(rx/reduce into [])
(rx/map library-using-files-fetched)))))
;; --- EVENT: recent-files
(defn recent-files-fetched

View file

@ -181,13 +181,14 @@
(rx/of (dwn/initialize team-id id)
(dwsl/initialize))
;; Load team fonts. We must ensure custom fonts are fully loadad before starting the workspace load
;; Load team fonts. We must ensure custom fonts are fully loadad
;; before starting the workspace load.
(rx/merge
(rx/of (df/load-team-fonts team-id))
(->> stream
(rx/filter (ptk/type? :app.main.data.fonts/team-fonts-loaded))
(rx/take 1)
(rx/ignore))
(rx/of (df/load-team-fonts team-id)))
(rx/ignore)))
(rx/merge
;; Load all pages, independently if they are pointers or already
@ -218,8 +219,6 @@
(rx/merge-map
(fn [_]
(rx/merge
(rx/of (workspace-initialized))
(->> data
(filter (comp t/pointer? val))
(resolve-pointers id)
@ -249,8 +248,9 @@
(fn [pages-index]
(assoc-in file [:data :pages-index] pages-index))))))
(rx/reduce conj [])
(rx/map libraries-fetched))))))))
(rx/map libraries-fetched)))))))
(rx/of (workspace-initialized)))
(rx/take-until stoper)))))))
(defn- libraries-fetched
@ -1135,6 +1135,19 @@
qparams {:page-id page-id :layout (name layout)}]
(rx/of (rt/nav :workspace pparams qparams))))))
(defn navigate-to-library
"Open a new tab, and navigate to the workspace with the provided file"
[library-id]
(ptk/reify ::navigate-to-file
ptk/WatchEvent
(watch [_ state _]
(when-let [file (dm/get-in state [:workspace-libraries library-id])]
(let [params {:rname :workspace
:path-params {:project-id (:project-id file)
:file-id (:id file)}
:query-params {:page-id (dm/get-in file [:data :pages 0])}}]
(rx/of (rt/nav-new-window* params)))))))
(defn check-in-asset
[items element]
(let [items (or items #{})]
@ -1147,31 +1160,31 @@
(ptk/reify ::toggle-selected-assets
ptk/UpdateEvent
(update [_ state]
(update-in state [:workspace-global :selected-assets type] #(check-in-asset % asset)))))
(update-in state [:workspace-assets-selected type] #(check-in-asset % asset)))))
(defn select-single-asset
[asset type]
(ptk/reify ::select-single-asset
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-global :selected-assets type] #{asset}))))
(assoc-in state [:workspace-assets-selected type] #{asset}))))
(defn select-assets
[assets type]
(ptk/reify ::select-assets
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-global :selected-assets type] (into #{} assets)))))
(assoc-in state [:workspace-assets-selected type] (into #{} assets)))))
(defn unselect-all-assets
[]
(ptk/reify ::unselect-all-assets
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-global :selected-assets] {:components #{}
:graphics #{}
:colors #{}
:typographies #{}}))))
(assoc state :workspace-assets-selected {:components #{}
:graphics #{}
:colors #{}
:typographies #{}}))))
(defn go-to-main-instance
[page-id shape-id]
(dm/assert! (uuid? page-id))
@ -1216,8 +1229,8 @@
pparams {:file-id file-id :project-id project-id}
qparams {:page-id page-id :layout :assets}]
(rx/of (rt/nav :workspace pparams qparams)
(dwl/set-assets-box-open file-id :library true)
(dwl/set-assets-box-open file-id :components true)
(dwl/set-assets-section-open file-id :library true)
(dwl/set-assets-section-open file-id :components true)
(select-single-asset component-id :components))))))
ptk/EffectEvent
@ -1238,8 +1251,8 @@
pparams {:file-id file-id :project-id project-id}
qparams {:page-id page-id :layout :assets}]
(rx/of (rt/nav :workspace pparams qparams)
(dwl/set-assets-box-open file-id :library true)
(dwl/set-assets-box-open file-id :components true)
(dwl/set-assets-section-open file-id :library true)
(dwl/set-assets-section-open file-id :components true)
(select-single-asset component-id :components))))
ptk/EffectEvent
@ -2091,26 +2104,6 @@
(dissoc :page-item))]
(assoc state :workspace-local local)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; File Library persistent settings
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn set-file-library-listing-thumbs
[listing-thumbs?]
(ptk/reify ::set-file-library-listing-thumbs
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-global :file-library-listing-thumbs] listing-thumbs?))))
(defn set-file-library-reverse-sort
[reverse-sort?]
(ptk/reify ::set-file-library-reverse-sort
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-global :file-library-reverse-sort] reverse-sort?))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Components annotations
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -76,19 +76,19 @@
(declare sync-file)
(defn set-assets-box-open
[file-id box open?]
(ptk/reify ::set-assets-box-open
(defn set-assets-section-open
[file-id section open?]
(ptk/reify ::set-assets-section-open
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-global :assets-files-open file-id box] open?))))
(assoc-in state [:workspace-assets-open-status file-id section] open?))))
(defn set-assets-group-open
[file-id box path open?]
[file-id section path open?]
(ptk/reify ::set-assets-group-open
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-global :assets-files-open file-id :groups box path] open?))))
(assoc-in state [:workspace-assets-open-status file-id :groups section path] open?))))
(defn extract-path-if-missing
[item]
@ -951,12 +951,22 @@
(defn link-file-to-library
[file-id library-id]
(ptk/reify ::attach-library
;; NOTE: this event implements UpdateEvent protocol for perform an
;; optimistic update state for make the UI feel more responsive.
ptk/UpdateEvent
(update [_ state]
(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))
state)))
ptk/WatchEvent
(watch [_ state _]
(let [features (cond-> ffeat/enabled
(features/active-feature? state :components-v2)
(conj "components/v2"))]
(rx/concat
(rx/merge
(->> (rp/cmd! :link-file-to-library {:file-id file-id :library-id library-id})
(rx/ignore))
(->> (rp/cmd! :get-file {:id library-id :features features})

View file

@ -15,17 +15,22 @@
[app.common.pages.helpers :as cph]
[app.common.text :as txt]
[app.common.types.modifiers :as ctm]
[app.common.uuid :as uuid]
[app.main.data.events :as ev]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.modifiers :as dwm]
[app.main.data.workspace.selection :as dws]
[app.main.data.workspace.shapes :as dwsh]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.undo :as dwu]
[app.main.fonts :as fonts]
[app.util.router :as rt]
[app.util.text-editor :as ted]
[app.util.timers :as ts]
[beicon.core :as rx]
[cuerdas.core :as str]
[potok.core :as ptk]))
;; -- Attrs
@ -321,6 +326,7 @@
(cph/group-shape? shape) (cph/get-children-ids objects id))]
(rx/of (dch/update-shapes shape-ids #(update-text-content % update-node? d/txt-merge attrs))))))))
(defn migrate-node
[node]
(let [color-attrs (select-keys node [:fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient])]
@ -595,22 +601,97 @@
(rx/empty))))))
(defn update-attrs
[id attrs]
[id attrs]
(ptk/reify ::update-attrs
ptk/WatchEvent
(watch [_ _ _]
ptk/WatchEvent
(watch [_ _ _]
(rx/concat
(let [attrs (select-keys attrs root-attrs)]
(if-not (empty? attrs)
(rx/of (update-root-attrs {:id id :attrs attrs}))
(rx/empty)))
(let [attrs (select-keys attrs paragraph-attrs)]
(if-not (empty? attrs)
(rx/of (update-paragraph-attrs {:id id :attrs attrs}))
(rx/empty)))
(let [attrs (select-keys attrs text-attrs)]
(if-not (empty? attrs)
(rx/of (update-text-attrs {:id id :attrs attrs}))
(rx/empty)))))))
(defn apply-typography
"A higher level event that has the resposability of to apply the
specified typography to the selected shapes."
[typography file-id]
(ptk/reify ::apply-typography
ptk/WatchEvent
(watch [_ state _]
(let [editor-state (:workspace-editor-state state)
selected (wsh/lookup-selected state)
attrs (-> typography
(assoc :typography-ref-file file-id)
(assoc :typography-ref-id (:id typography))
(dissoc :id :name))]
(->> (rx/from (seq selected))
(rx/map (fn [id]
(let [editor (get editor-state id)]
(update-text-attrs {:id id :editor editor :attrs attrs})))))))))
(defn generate-typography-name
[{:keys [font-id font-variant-id] :as typography}]
(let [{:keys [name]} (fonts/get-font-data font-id)]
(assoc typography :name (str name " " (str/title font-variant-id)))))
(defn add-typography
"A higher level version of dwl/add-typography, and has mainly two
responsabilities: add the typography to the library and apply it to
the currently selected text shapes (being aware of the open text
editors."
[file-id]
(ptk/reify ::add-typography
ptk/WatchEvent
(watch [_ state _]
(let [selected (wsh/lookup-selected state)
objects (wsh/lookup-page-objects state)
xform (comp (keep (d/getf objects))
(filter cph/text-shape?))
shapes (into [] xform selected)
shape (first shapes)
values (current-text-values
{:editor-state (dm/get-in state [:workspace-editor-state (:id shape)])
:shape shape
:attrs text-attrs})
multiple? (or (> 1 (count shapes))
(d/seek (partial = :multiple)
(vals values)))
values (-> (d/without-nils values)
(select-keys
(d/concat-vec text-font-attrs
text-spacing-attrs
text-transform-attrs)))
typ-id (uuid/next)
typ (-> (if multiple?
txt/default-typography
(merge txt/default-typography values))
(generate-typography-name)
(assoc :id typ-id))]
(rx/concat
(let [attrs (select-keys attrs root-attrs)]
(if-not (empty? attrs)
(rx/of (update-root-attrs {:id id :attrs attrs}))
(rx/empty)))
(rx/of (dwl/add-typography typ)
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
:asset-type "typography"}))
(let [attrs (select-keys attrs paragraph-attrs)]
(if-not (empty? attrs)
(rx/of (update-paragraph-attrs {:id id :attrs attrs}))
(rx/empty)))
(when (not multiple?)
(rx/of (update-attrs (:id shape)
{:typography-ref-id typ-id
:typography-ref-file file-id}))))))))
(let [attrs (select-keys attrs text-attrs)]
(if-not (empty? attrs)
(rx/of (update-text-attrs {:id id :attrs attrs}))
(rx/empty)))))))

View file

@ -187,18 +187,9 @@
(def editing-page-item
(l/derived :page-item workspace-local))
(def file-library-listing-thumbs?
(l/derived :file-library-listing-thumbs workspace-global))
(def file-library-reverse-sort?
(l/derived :file-library-reverse-sort workspace-global))
(def current-hover-ids
(l/derived :hover-ids context-menu))
(def selected-assets
(l/derived :selected-assets workspace-global))
(def workspace-layout
(l/derived :workspace-layout st/state))
@ -212,10 +203,9 @@
data (:workspace-data state)]
(-> file
(dissoc :data)
(assoc :options (:options data)
:components (:components data)
:pages (:pages data)
:pages-index (:pages-index data)))))
;; FIXME: still used in sitemaps but sitemaps
;; should declare its own lense for it
(assoc :pages (:pages data)))))
st/state =))
(def workspace-data
@ -395,9 +385,7 @@
(def selected-objects
(letfn [(selector [{:keys [selected objects]}]
(->> selected
(map #(get objects %))
(filterv (comp not nil?))))]
(into [] (keep (d/getf objects)) selected))]
(l/derived selector selected-data =)))
(def selected-shapes-with-children

View file

@ -98,12 +98,12 @@
(let [num-shared (filter #(:is-shared %) files)]
(if (< 0 (count num-shared))
(do (st/emit! (dd/fetch-libraries-using-files files))
(st/emit! (modal/show
{:type :delete-shared
:origin :delete
:on-accept delete-fn
:count-libraries (count num-shared)})))
(st/emit! (modal/show
{:type :delete-shared-libraries
:origin :delete
:ids (into #{} (map :id) files)
:on-accept delete-fn
:count-libraries (count num-shared)}))
(if multi?
(st/emit! (modal/show
@ -161,10 +161,10 @@
(fn [event]
(dom/prevent-default event)
(dom/stop-propagation event)
(st/emit! (dd/fetch-libraries-using-files files))
(st/emit! (modal/show
{:type :delete-shared
{:type :delete-shared-libraries
:origin :unpublish
:ids (into #{} (map :id) files)
:on-accept del-shared
:count-libraries file-count})))

View file

@ -6,88 +6,101 @@
(ns app.main.ui.delete-shared
(:require
[app.main.data.dashboard :as dd]
[app.common.data.macros :as dm]
[app.main.data.modal :as modal]
[app.main.refs :as refs]
[app.main.repo :as rp]
[app.main.store :as st]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as k]
[beicon.core :as rx]
[goog.events :as events]
[rumext.v2 :as mf])
(:import goog.events.EventType))
[rumext.v2 :as mf]))
(def ^:private noop (constantly nil))
(mf/defc delete-shared-dialog
{::mf/register modal/components
::mf/register-as :delete-shared}
[{:keys [on-accept
on-cancel
accept-style
origin
count-libraries] :as props}]
(let [on-accept (or on-accept identity)
on-cancel (or on-cancel identity)
cancel-label (tr "labels.cancel")
accept-style (or accept-style :danger)
dashboard-local (mf/deref refs/dashboard-local)
files->shared (:files-with-shared dashboard-local)
::mf/register-as :delete-shared-libraries
::mf/wrap-props false}
[{:keys [ids on-accept on-cancel accept-style origin count-libraries]}]
(let [references* (mf/use-state {})
references (deref references*)
is-delete? (= origin :delete)
count-files (count (keys files->shared))
on-accept (or on-accept noop)
on-cancel (or on-cancel noop)
title (if is-delete?
(tr "modals.delete-shared-confirm.title" (i18n/c count-libraries))
(tr "modals.unpublish-shared-confirm.title" (i18n/c count-libraries)))
message (if is-delete?
(tr "modals.delete-shared-confirm.message" (i18n/c count-libraries))
(tr "modals.unpublish-shared-confirm.message" (i18n/c count-libraries)))
accept-label (if is-delete?
(tr "modals.delete-shared-confirm.accept" (i18n/c count-libraries))
(tr "modals.unpublish-shared-confirm.accept" (i18n/c count-libraries)))
no-files-message (if is-delete?
(tr "modals.delete-shared-confirm.no-files-message" (i18n/c count-libraries))
(tr "modals.unpublish-shared-confirm.no-files-message" (i18n/c count-libraries)))
scd-message (if is-delete?
(if (= count-files 1)
(tr "modals.delete-shared-confirm.scd-message" (i18n/c count-libraries))
(tr "modals.delete-shared-confirm.scd-message-many" (i18n/c count-libraries)))
(if (= count-files 1)
(tr "modals.unpublish-shared-confirm.scd-message" (i18n/c count-libraries))
(tr "modals.unpublish-shared-confirm.scd-message-many" (i18n/c count-libraries))))
hint (if is-delete?
(if (= count-files 1)
(tr "modals.delete-shared-confirm.hint" (i18n/c count-libraries))
cancel-label (tr "labels.cancel")
accept-style (or accept-style :danger)
is-delete? (= origin :delete)
count-files (count (keys references))
title (if ^boolean is-delete?
(tr "modals.delete-shared-confirm.title" (i18n/c count-libraries))
(tr "modals.unpublish-shared-confirm.title" (i18n/c count-libraries)))
subtitle (if ^boolean is-delete?
(tr "modals.delete-shared-confirm.message" (i18n/c count-libraries))
(tr "modals.unpublish-shared-confirm.message" (i18n/c count-libraries)))
accept-label (if ^boolean is-delete?
(tr "modals.delete-shared-confirm.accept" (i18n/c count-libraries))
(tr "modals.unpublish-shared-confirm.accept" (i18n/c count-libraries)))
no-files-msg (if ^boolean is-delete?
(tr "modals.delete-shared-confirm.no-files-message" (i18n/c count-libraries))
(tr "modals.unpublish-shared-confirm.no-files-message" (i18n/c count-libraries)))
scd-msg (if ^boolean is-delete?
(if (= count-files 1)
(tr "modals.delete-shared-confirm.scd-message" (i18n/c count-libraries))
(tr "modals.delete-shared-confirm.scd-message-many" (i18n/c count-libraries)))
(if (= count-files 1)
(tr "modals.unpublish-shared-confirm.scd-message" (i18n/c count-libraries))
(tr "modals.unpublish-shared-confirm.scd-message-many" (i18n/c count-libraries))))
hint (if ^boolean is-delete?
(if (= count-files 1)
(tr "modals.delete-shared-confirm.hint" (i18n/c count-libraries))
(tr "modals.delete-shared-confirm.hint-many" (i18n/c count-libraries)))
(if (= count-files 1)
(tr "modals.unpublish-shared-confirm.hint" (i18n/c count-libraries))
(tr "modals.unpublish-shared-confirm.hint-many" (i18n/c count-libraries))))
(if (= count-files 1)
(tr "modals.unpublish-shared-confirm.hint" (i18n/c count-libraries))
(tr "modals.unpublish-shared-confirm.hint-many" (i18n/c count-libraries))))
accept-fn
(mf/use-callback
(mf/use-fn
(mf/deps on-accept)
(fn [event]
(dom/prevent-default event)
(st/emit! (modal/hide))
(on-accept props)))
(on-accept)))
cancel-fn
(mf/use-callback
(mf/use-fn
(mf/deps on-cancel)
(fn [event]
(dom/prevent-default event)
(st/emit! (modal/hide))
(on-cancel props)))]
(on-cancel)))]
(mf/with-effect
(mf/with-effect [ids]
(->> (rx/from ids)
(rx/map #(array-map :file-id %))
(rx/mapcat #(rp/cmd! :get-library-file-references %))
(rx/mapcat identity)
(rx/map (juxt :id :name))
(rx/reduce conj [])
(rx/subs #(reset! references* %))))
(mf/with-effect [accept-fn]
(letfn [(on-keydown [event]
(when (k/enter? event)
(dom/prevent-default event)
(dom/stop-propagation event)
(st/emit! (modal/hide))
(on-accept props)))]
(let [key (events/listen js/document EventType.KEYDOWN on-keydown)]
(fn []
(events/unlistenByKey key)
(st/emit! (dd/clean-temp-shared))))))
(accept-fn)))]
(let [key (events/listen js/document "keydown" on-keydown)]
(partial events/unlistenByKey key))))
[:div.modal-overlay
[:div.modal-container.confirm-dialog
@ -98,23 +111,23 @@
{:on-click cancel-fn} i/close]]
[:div.modal-content.delete-shared
(when (and (string? message) (not= message ""))
[:h3 message])
(when (and (string? subtitle) (not= subtitle ""))
[:h3 subtitle])
(when (not= 0 count-libraries)
(if (> (count files->shared) 0)
(if (pos? (count references))
[:*
[:div
(when (and (string? scd-message) (not= scd-message ""))
[:h3 scd-message])
(when (and (string? scd-msg) (not= scd-msg ""))
[:h3 scd-msg])
[:ul.file-list
(for [[id file] files->shared]
(for [[file-id file-name] references]
[:li.modal-item-element
{:key id}
[:span "- " (:name file)]])]]
{:key (dm/str file-id)}
[:span "- " file-name]])]]
(when (and (string? hint) (not= hint ""))
[:h3 hint])]
[:*
[:h3 no-files-message]]))]
[:h3 no-files-msg]]))]
[:div.modal-footer
[:div.action-buttons

View file

@ -36,7 +36,6 @@
[app.util.dom :as dom]
[app.util.globals :as globals]
[app.util.i18n :as i18n :refer [tr]]
[app.util.object :as obj]
[app.util.router :as rt]
[debug :refer [debug?]]
[goog.events :as events]
@ -47,14 +46,11 @@
(mf/defc workspace-content
{::mf/wrap-props false}
[props]
[{:keys [file layout page-id wglobal]}]
(let [selected (mf/deref refs/selected-shapes)
file (obj/get props "file")
layout (obj/get props "layout")
page-id (obj/get props "page-id")
{:keys [vport] :as wlocal} (mf/deref refs/workspace-local)
{:keys [options-mode] :as wglobal} (obj/get props "wglobal")
{:keys [options-mode]} wglobal
colorpalette? (:colorpalette layout)
textpalette? (:textpalette layout)

View file

@ -9,7 +9,6 @@
[app.common.pages.helpers :as cph]
[app.common.uuid :as uuid]
[app.config :as cf]
[app.main.data.dashboard :as dd]
[app.main.data.events :as ev]
[app.main.data.exports :as de]
[app.main.data.modal :as modal]
@ -108,6 +107,7 @@
;; --- Header Users
;; FIXME: refactor & optimizations
(mf/defc menu
[{:keys [layout project file team-id] :as props}]
(let [show-menu? (mf/use-state false)
@ -122,9 +122,6 @@
add-shared-fn
#(st/emit! (dwl/set-file-shared (:id file) true))
on-add-shared
(mf/use-fn
(mf/deps file)
@ -144,10 +141,10 @@
(fn [event]
(dom/prevent-default event)
(dom/stop-propagation event)
(st/emit! (dd/fetch-libraries-using-files [file]))
(st/emit! (modal/show
{:type :delete-shared
{:type :delete-shared-libraries
:origin :unpublish
:ids #{(:id file)}
:on-accept #(st/emit! (dwl/set-file-shared (:id file) false))
:count-libraries 1}))))

View file

@ -7,13 +7,13 @@
(ns app.main.ui.workspace.libraries
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.types.components-list :as ctkl]
[app.main.data.dashboard :as dd]
[app.main.data.modal :as modal]
[app.main.data.workspace.libraries :as dwl]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.icons :as i] [app.main.ui.workspace.sidebar.assets :as a]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd]
@ -22,243 +22,302 @@
[okulary.core :as l]
[rumext.v2 :as mf]))
(def workspace-file
(def ref:workspace-file
(l/derived :workspace-file st/state))
(defn library-str
(defn create-file-library-ref
[library-id]
(letfn [(getter-fn [state]
(let [fdata (let [{:keys [id] :as wfile} (:workspace-data state)]
(if (= id library-id)
wfile
(dm/get-in state [:workspace-libraries library-id :data])))]
{:colors (-> fdata :colors vals)
:media (-> fdata :media vals)
:components (ctkl/components-seq fdata)
:typographies (-> fdata :typographies vals)}))]
(l/derived getter-fn st/state =)))
(defn- describe-library
[components-count graphics-count colors-count typography-count]
(str
(str/join " · "
(cond-> []
(< 0 components-count)
(pos? components-count)
(conj (tr "workspace.libraries.components" components-count))
(< 0 graphics-count)
(pos? graphics-count)
(conj (tr "workspace.libraries.graphics" graphics-count))
(< 0 colors-count)
(pos? colors-count)
(conj (tr "workspace.libraries.colors" colors-count))
(< 0 typography-count)
(pos? typography-count)
(conj (tr "workspace.libraries.typography" typography-count))))
"\u00A0"))
(defn local-library-str
(defn- describe-linked-library
[library]
(let [components-count (count (or (ctkl/components-seq (:data library)) []))
graphics-count (count (get-in library [:data :media] []))
colors-count (count (get-in library [:data :colors] []))
typography-count (count (get-in library [:data :typographies] []))]
(library-str components-count graphics-count colors-count typography-count)))
graphics-count (count (dm/get-in library [:data :media] []))
colors-count (count (dm/get-in library [:data :colors] []))
typography-count (count (dm/get-in library [:data :typographies] []))]
(describe-library components-count graphics-count colors-count typography-count)))
(defn external-library-str
(defn- describe-external-library
[library]
(let [components-count (get-in library [:library-summary :components :count] 0)
graphics-count (get-in library [:library-summary :media :count] 0)
colors-count (get-in library [:library-summary :colors :count] 0)
typography-count (get-in library [:library-summary :typographies :count] 0)]
(library-str components-count graphics-count colors-count typography-count)))
(let [components-count (dm/get-in library [:library-summary :components :count] 0)
graphics-count (dm/get-in library [:library-summary :media :count] 0)
colors-count (dm/get-in library [:library-summary :colors :count] 0)
typography-count (dm/get-in library [:library-summary :typographies :count] 0)]
(describe-library components-count graphics-count colors-count typography-count)))
(mf/defc libraries-tab
[{:keys [file colors typographies media components libraries shared-files] :as props}]
(let [search-term (mf/use-state "")
{::mf/wrap-props false}
[{:keys [file-id shared? linked-libraries shared-libraries]}]
(let [search-term* (mf/use-state "")
search-term (deref search-term*)
sorted-libraries (->> (vals libraries)
(sort-by #(str/lower (:name %))))
library-ref (mf/with-memo [file-id]
(create-file-library-ref file-id))
library (deref library-ref)
colors (:colors library)
components (:components library)
media (:media library)
typographies (:typographies library)
filtered-files (->> shared-files
(filter #(not= (:id %) (:id file)))
(filter #(nil? (get libraries (:id %))))
(filter #(matches-search (:name %) @search-term))
(sort-by #(str/lower (:name %))))
shared-libraries
(mf/with-memo [shared-libraries linked-libraries file-id search-term]
(->> shared-libraries
(remove #(= (:id %) file-id))
(remove #(contains? linked-libraries (:id %)))
(filter #(matches-search (:name %) search-term))
(sort-by (comp str/lower :name))))
on-search-term-change
(mf/use-callback
linked-libraries
(mf/with-memo [linked-libraries]
(->> (vals linked-libraries)
(sort-by (comp str/lower :name))))
change-search-term
(mf/use-fn
(fn [event]
(let [value (-> (dom/get-target event)
(dom/get-value))]
(reset! search-term value))))
(reset! search-term* value))))
on-search-clear
(mf/use-callback
(fn [_]
(reset! search-term "")))
clear-search-term
(mf/use-fn #(reset! search-term* ""))
link-library
(mf/use-callback (mf/deps file) #(st/emit! (dwl/link-file-to-library (:id file) %)))
(mf/use-fn
(mf/deps file-id)
(fn [event]
(let [library-id (some-> (dom/get-target event)
(dom/get-data "library-id")
(parse-uuid))]
(st/emit! (dwl/link-file-to-library file-id library-id)))))
unlink-library
(mf/use-callback
(mf/deps file)
(fn [library-id]
(st/emit! (dwl/unlink-file-from-library (:id file) library-id)
(dwl/sync-file (:id file) library-id))))
add-shared
(mf/use-callback
(mf/deps file)
#(st/emit! (dwl/set-file-shared (:id file) true)))
del-shared
(mf/use-callback
(mf/deps file)
(fn [_]
(st/emit! (dd/fetch-libraries-using-files [file]))
(st/emit! (modal/show
{:type :delete-shared
:origin :unpublish
:on-accept (fn []
(st/emit! (dwl/set-file-shared (:id file) false))
(modal/show! :libraries-dialog {}))
:on-cancel #(modal/show! :libraries-dialog {})
:count-libraries 1}))))
handle-key-down
(mf/use-callback
(mf/use-fn
(mf/deps file-id)
(fn [event]
(let [enter? (kbd/enter? event)
esc? (kbd/esc? event)
input-node (dom/event->target event)]
(let [library-id (some-> (dom/get-target event)
(dom/get-data "library-id")
(parse-uuid))]
(st/emit! (dwl/unlink-file-from-library file-id library-id)
(dwl/sync-file file-id library-id)))))
(when enter?
on-delete-accept
(mf/use-fn
(mf/deps file-id)
#(st/emit! (dwl/set-file-shared file-id false)
(modal/show :libraries-dialog {})))
on-delete-cancel
(mf/use-fn #(st/emit! (modal/show :libraries-dialog {})))
publish
(mf/use-fn
(mf/deps file-id)
#(st/emit! (dwl/set-file-shared file-id true)))
unpublish
(mf/use-fn
(mf/deps file-id)
(fn [_]
(st/emit! (modal/show
{:type :delete-shared-libraries
:ids #{file-id}
:origin :unpublish
:on-accept on-delete-accept
:on-cancel on-delete-cancel
:count-libraries 1}))))
handle-key-down
(mf/use-fn
(fn [event]
(let [enter? (kbd/enter? event)
esc? (kbd/esc? event)
input-node (dom/event->target event)]
(when ^boolean enter?
(dom/blur! input-node))
(when esc?
(when ^boolean esc?
(dom/blur! input-node)))))]
[:*
[:div.section
[:div.section-title (tr "workspace.libraries.in-this-file")]
[:div.section-list
[:div.section-list-item
[:div
[:div {:data-kaka "1"}
[:div.item-name (tr "workspace.libraries.file-library")]
[:div.item-contents (library-str (count components) (count media) (count colors) (count typographies) )]]
[:div.item-contents (describe-library
(count components)
(count media)
(count colors)
(count typographies))]]
[:div
(if (:is-shared file)
(if ^boolean shared?
[:input.item-button {:type "button"
:value (tr "common.unpublish")
:on-click del-shared}]
:on-click unpublish}]
[:input.item-button {:type "button"
:value (tr "common.publish")
:on-click add-shared}])]]
:on-click publish}])]]
(for [library sorted-libraries]
[:div.section-list-item {:key (:id library)}
[:div.item-name (:name library)]
[:div.item-contents (local-library-str library)]
(for [{:keys [id name] :as library} linked-libraries]
[:div.section-list-item {:key (dm/str id)}
[:div.item-name name]
[:div.item-contents (describe-linked-library library)]
[:input.item-button {:type "button"
:value (tr "labels.remove")
:on-click #(unlink-library (:id library))}]])
]]
:data-library-id (dm/str id)
:on-click unlink-library}]])]]
[:div.section
[:div.section-title (tr "workspace.libraries.shared-libraries")]
[:div.libraries-search
[:input.search-input
{:placeholder (tr "workspace.libraries.search-shared-libraries")
:type "text"
:value @search-term
:on-change on-search-term-change
:value search-term
:on-change change-search-term
:on-key-down handle-key-down}]
(if (str/empty? @search-term)
(if (str/empty? search-term)
[:div.search-icon
i/search]
[:div.search-icon.search-close
{:on-click on-search-clear}
{:on-click clear-search-term}
i/close])]
(if (> (count filtered-files) 0)
(if (seq shared-libraries)
[:div.section-list
(for [file filtered-files]
[:div.section-list-item {:key (:id file)}
[:div.item-name (:name file)]
[:div.item-contents (external-library-str file)]
(for [{:keys [id name] :as library} shared-libraries]
[:div.section-list-item {:key (dm/str id)}
[:div.item-name name]
[:div.item-contents (describe-external-library library)]
[:input.item-button {:type "button"
:value (tr "workspace.libraries.add")
:on-click #(link-library (:id file))}]])]
:data-library-id (dm/str id)
:on-click link-library}]])]
[:div.section-list-empty
(if (nil? shared-files)
(if (nil? shared-libraries)
i/loader-pencil
[:* i/library
(if (str/empty? @search-term)
(if (str/empty? search-term)
(tr "workspace.libraries.no-shared-libraries-available")
(tr "workspace.libraries.no-matches-for" @search-term))])])]]))
(tr "workspace.libraries.no-matches-for" search-term))])])]]))
(mf/defc updates-tab
[{:keys [file libraries] :as props}]
(let [libraries-need-sync (filter #(> (:modified-at %) (:synced-at %))
(vals libraries))
update-library #(st/emit! (dwl/sync-file (:id file) %))]
[:div.section
(if (empty? libraries-need-sync)
[:div.section-list-empty
i/library
(tr "workspace.libraries.no-libraries-need-sync")]
[:*
[:div.section-title (tr "workspace.libraries.library")]
[:div.section-list
(for [library libraries-need-sync]
[:div.section-list-item {:key (:id library)}
[:div.item-name (:name library)]
[:div.item-contents (external-library-str library)]
[:input.item-button {:type "button"
:value (tr "workspace.libraries.update")
:on-click #(update-library (:id library))}]])]])]))
{::mf/wrap-props false}
[{:keys [file-id libraries]}]
(let [libraries (mf/with-memo [libraries]
(filter #(> (:modified-at %) (:synced-at %)) (vals libraries)))
update (mf/use-fn
(mf/deps file-id)
(fn [event]
(let [library-id (some-> (dom/get-target event)
(dom/get-data "library-id")
(parse-uuid))]
(st/emit! (dwl/sync-file file-id library-id)))))]
[:div.section
(if (empty? libraries)
[:div.section-list-empty
i/library
(tr "workspace.libraries.no-libraries-need-sync")]
[:*
[:div.section-title (tr "workspace.libraries.library")]
[:div.section-list
(for [{:keys [id name] :as library} libraries]
[:div.section-list-item {:key (dm/str id)}
[:div.item-name name]
[:div.item-contents (describe-external-library library)]
[:input.item-button {:type "button"
:value (tr "workspace.libraries.update")
:data-library-id (dm/str id)
:on-click update}]])]])]))
(mf/defc libraries-dialog
{::mf/register modal/components
::mf/register-as :libraries-dialog}
[{:keys [] :as ctx}]
(let [selected-tab (mf/use-state :libraries)
project (mf/deref refs/workspace-project)
file (mf/deref workspace-file)
[]
(let [project (mf/deref refs/workspace-project)
file (mf/deref ref:workspace-file)
libraries (->> (mf/deref refs/workspace-libraries)
(d/removem (fn [[_ val]] (:is-indirect val))))
shared-files (mf/deref refs/workspace-shared-files)
team-id (:team-id project)
file-id (:id file)
shared? (:is-shared file)
colors-ref (mf/use-memo (mf/deps (:id file)) #(a/file-colors-ref (:id file)))
colors (mf/deref colors-ref)
selected-tab* (mf/use-state :libraries)
selected-tab (deref selected-tab*)
typography-ref (mf/use-memo (mf/deps (:id file)) #(a/file-typography-ref (:id file)))
typographies (mf/deref typography-ref)
libraries (mf/deref refs/workspace-libraries)
libraries (mf/with-memo [libraries]
(d/removem (fn [[_ val]] (:is-indirect val)) libraries))
media-ref (mf/use-memo (mf/deps (:id file)) #(a/file-media-ref (:id file)))
media (mf/deref media-ref)
;; NOTE: we really don't need react on shared files
shared-libraries
(mf/deref refs/workspace-shared-files)
components-ref (mf/use-memo (mf/deps (:id file)) #(a/file-components-ref (:id file)))
components (mf/deref components-ref)
select-libraries-tab
(mf/use-fn #(reset! selected-tab* :libraries))
change-tab #(reset! selected-tab %)
close #(modal/hide!)]
select-updates-tab
(mf/use-fn #(reset! selected-tab* :updates))
(mf/use-effect
(mf/deps project)
(fn []
(when (:team-id project)
(st/emit! (dwl/fetch-shared-files {:team-id (:team-id project)})))))
close-dialog
(mf/use-fn #(modal/hide!))]
(mf/with-effect [team-id]
(when team-id
(st/emit! (dwl/fetch-shared-files {:team-id team-id}))))
[:div.modal-overlay
[:div.modal.libraries-dialog
[:a.close {:on-click close} i/close]
[:a.close {:on-click close-dialog} i/close]
[:div.modal-content
[:div.libraries-header
[:div.header-item
{:class (dom/classnames :active (= @selected-tab :libraries))
:on-click #(change-tab :libraries)}
{:class (dom/classnames :active (= selected-tab :libraries))
:on-click select-libraries-tab}
(tr "workspace.libraries.libraries")]
[:div.header-item
{:class (dom/classnames :active (= @selected-tab :updates))
:on-click #(change-tab :updates)}
{:class (dom/classnames :active (= selected-tab :updates))
:on-click select-updates-tab}
(tr "workspace.libraries.updates")]]
[:div.libraries-content
(case @selected-tab
(case selected-tab
:libraries
[:& libraries-tab {:file file
:colors colors
:typographies typographies
:media media
:components components
:libraries libraries
:shared-files shared-files}]
[:& libraries-tab {:file-id file-id
:shared? shared?
:linked-libraries libraries
:shared-libraries shared-libraries}]
:updates
[:& updates-tab {:file file
[:& updates-tab {:file-id file-id
:libraries libraries}])]]]]))

File diff suppressed because it is too large Load diff

View file

@ -18,15 +18,16 @@
(mf/defc collapsed-button
{::mf/wrap-props false}
[]
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
(if new-css-system
(let [new-css? (mf/use-ctx ctx/new-css-system)
on-click (mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))]
(if ^boolean new-css?
[:div {:class (dom/classnames (css :collapsed-sidebar) true)}
[:div {:class (dom/classnames (css :collapsed-title) true)}
[:button {:class (dom/classnames (css :collapsed-button) true)
:on-click #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar))
:on-click on-click
:aria-label (tr "workspace.sidebar.expand")}
i/arrow-refactor]]]
[:button.collapse-sidebar.collapsed
{:on-click #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar))
{:on-click on-click
:aria-label (tr "workspace.sidebar.expand")}
i/arrow-slide])))
i/arrow-slide])))

View file

@ -14,7 +14,6 @@
[app.main.data.workspace.shortcuts :as sc]
[app.main.data.workspace.texts :as dwt]
[app.main.data.workspace.undo :as dwu]
[app.main.fonts :as fonts]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.context :as ctx]
@ -23,7 +22,6 @@
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.timers :as ts]
[cuerdas.core :as str]
[rumext.v2 :as mf]))
(mf/defc text-align-options
@ -159,11 +157,6 @@
:on-click #(handle-change % "line-through")}
i/strikethrough]]))
(defn generate-typography-name
[{:keys [font-id font-variant-id] :as typography}]
(let [{:keys [name]} (fonts/get-font-data font-id)]
(assoc typography :name (str name " " (str/title font-variant-id)))))
(mf/defc text-menu
{::mf/wrap [mf/memo]}
[{:keys [ids type values] :as props}]
@ -215,7 +208,7 @@
dwt/text-spacing-attrs
dwt/text-transform-attrs)))
typography (merge txt/default-typography set-values)
typography (generate-typography-name typography)
typography (dwt/generate-typography-name typography)
id (uuid/next)]
(st/emit! (dwl/add-typography (assoc typography :id id) false))
(run! #(emit-update! % {:typography-ref-id id

View file

@ -13,6 +13,7 @@
[app.common.text :as txt]
[app.main.data.fonts :as fts]
[app.main.data.shortcuts :as dsc]
[app.main.data.workspace :as dw]
[app.main.fonts :as fonts]
[app.main.refs :as refs]
[app.main.store :as st]
@ -24,8 +25,6 @@
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd]
[app.util.object :as obj]
[app.util.router :as rt]
[app.util.strings :as ust]
[app.util.timers :as tm]
[cuerdas.core :as str]
@ -38,7 +37,7 @@
(ust/format-precision value 2)))
(defn select-all [event]
(dom/select-text! (dom/get-target event)))
(some-> event dom/get-target dom/select-text!))
(defn- get-next-font
[{:keys [id] :as current} fonts]
@ -229,8 +228,8 @@
[:div.fonts-list
[:> rvt/AutoSizer {}
(fn [props]
(let [width (obj/get props "width")
height (obj/get props "height")
(let [width (unchecked-get props "width")
height (unchecked-get props "height")
render #(row-renderer fonts @selected on-select-and-close %)]
(mf/html
[:> rvt/List #js {:height height
@ -241,9 +240,9 @@
:rowRenderer render}])))]]]]))
(defn row-renderer
[fonts selected on-select props]
(let [index (obj/get props "index")
key (obj/get props "key")
style (obj/get props "style")
(let [index (unchecked-get props "index")
key (unchecked-get props "key")
style (unchecked-get props "style")
font (nth fonts index)]
(mf/html
[:& font-item {:key key
@ -253,7 +252,8 @@
:current? (= (:id font) (:id selected))}])))
(mf/defc font-options
[{:keys [values on-change on-blur show-recent] :as props}]
{::mf/wrap-props false}
[{:keys [values on-change on-blur show-recent]}]
(let [{:keys [font-id font-size font-variant-id]} values
font-id (or font-id (:font-id txt/default-text-attrs))
@ -371,7 +371,8 @@
(mf/defc spacing-options
[{:keys [values on-change on-blur] :as props}]
{::mf/wrap-props false}
[{:keys [values on-change on-blur]}]
(let [{:keys [line-height
letter-spacing]} values
@ -416,7 +417,8 @@
:on-blur on-blur}]]]))
(mf/defc text-transform-options
[{:keys [values on-change on-blur] :as props}]
{::mf/wrap-props false}
[{:keys [values on-change on-blur]}]
(let [text-transform (or (:text-transform values) "none")
handle-change
(fn [_ type]
@ -446,6 +448,7 @@
i/titlecase]]))
(mf/defc typography-options
{::mf/wrap-props false}
[{:keys [ids editor values on-change on-blur show-recent]}]
(let [opts #js {:editor editor
:ids ids
@ -460,19 +463,18 @@
[:div.row-flex
[:> text-transform-options opts]]]))
;; TODO: this need to be refactored, right now combines too much logic
;; and has a dropdown that behaves like a modal but is not a modal.
;; In summary, this need to a good UX/UI/IMPL rework.
(mf/defc typography-entry
[{:keys [typography local? selected? on-click on-change on-detach on-context-menu editing? focus-name? file open?]}]
(let [hover-detach (mf/use-state false)
{::mf/wrap-props false}
[{:keys [file-id typography local? selected? on-click on-change on-detach on-context-menu editing? focus-name? external-open*]}]
(let [hover-detach* (mf/use-state false)
hover-detach? (deref hover-detach*)
name-input-ref (mf/use-ref)
on-change-ref (mf/use-ref nil)
workspace-read-only? (mf/use-ctx ctx/workspace-read-only?)
editable? (and local? (not workspace-read-only?))
open? (if (nil? open?) (mf/use-state editing?) open?)
read-only? (mf/use-ctx ctx/workspace-read-only?)
editable? (and local? (not read-only?))
open* (mf/use-state editing?)
open? (deref open*)
on-name-blur
(mf/use-callback
@ -480,11 +482,36 @@
(fn [event]
(let [name (dom/get-target-val event)]
(when-not (str/blank? name)
(on-change {:name name})))))]
(on-change {:name name})))))
on-pointer-enter
(mf/use-fn #(reset! hover-detach* true))
on-pointer-leave
(mf/use-fn #(reset! hover-detach* false))
on-open
(mf/use-fn #(reset! open* true))
on-close
(mf/use-fn #(reset! open* false))
navigate-to-library
(mf/use-fn
(mf/deps file-id)
(fn []
(when file-id
(st/emit! (dw/navigate-to-library file-id)))))
]
(mf/with-effect [editing?]
(when editing?
(reset! open? editing?)))
(reset! open* editing?)))
(mf/with-effect [open?]
(when (some? external-open*)
(reset! external-open* open?)))
(mf/with-effect [focus-name?]
(when focus-name?
@ -493,15 +520,12 @@
(dom/focus! node)
(dom/select-text! node)))))
(mf/with-effect [on-change]
(mf/set-ref-val! on-change-ref {:on-change on-change}))
[:*
[:div.element-set-options-group.typography-entry
{:class (when selected? "selected")
:style {:display (when @open? "none")}}
{:class (when ^boolean selected? "selected")
:style {:display (when ^boolean open? "none")}}
[:div.typography-selection-wrapper
{:class (when on-click "is-selectable")
{:class (when ^boolean on-click "is-selectable")
:on-click on-click
:on-context-menu on-context-menu}
[:div.typography-sample
@ -511,20 +535,36 @@
(tr "workspace.assets.typography.sample")]
[:div.typography-name {:title (:name typography)}(:name typography)]]
[:div.element-set-actions
(when on-detach
(when ^boolean on-detach
[:div.element-set-actions-button
{:on-pointer-enter #(reset! hover-detach true)
:on-pointer-leave #(reset! hover-detach false)
{:on-pointer-enter on-pointer-enter
:on-pointer-leave on-pointer-leave
:on-click on-detach}
(if @hover-detach i/unchain i/chain)])
(if ^boolean hover-detach? i/unchain i/chain)])
[:div.element-set-actions-button
{:on-click #(reset! open? true)}
{:on-click on-open}
i/actions]]]
[:& advanced-options {:visible? @open?
:on-close #(reset! open? false)}
(if (not editable?)
[:& advanced-options {:visible? open? :on-close on-close}
(if ^boolean editable?
[:*
[:div.element-set-content
[:div.row-flex
[:input.element-name.adv-typography-name
{:type "text"
:ref name-input-ref
:default-value (:name typography)
:on-blur on-name-blur}]
[:div.element-set-actions-button
{:on-click on-close}
i/actions]]]
[:& typography-options {:values typography
:on-change on-change
:show-recent false}]]
[:div.element-set-content.typography-read-only-data
[:div.row-flex.typography-name
[:span {:title (:name typography)} (:name typography)]]
@ -534,7 +574,7 @@
[:span (:font-id typography)]]
[:div.element-set-actions-button.actions-inside
{:on-click #(reset! open? false)}
{:on-click on-close}
i/actions]
[:div.row-flex
@ -560,25 +600,7 @@
(when-not local?
[:div.row-flex
[:a.go-to-lib-button
{:on-click #(st/emit! (rt/nav-new-window* {:rname :workspace
:path-params {:project-id (:project-id file)
:file-id (:id file)}
:query-params {:page-id (get-in file [:data :pages 0])}}))}
{:on-click navigate-to-library}
(tr "workspace.assets.typography.go-to-edit")]])]
[:*
[:div.element-set-content
[:div.row-flex
[:input.element-name.adv-typography-name
{:type "text"
:ref name-input-ref
:default-value (:name typography)
:on-blur on-name-blur}]
[:div.element-set-actions-button
{:on-click #(reset! open? false)}
i/actions]]]
[:& typography-options {:values typography
:on-change on-change
:show-recent false}]])]]))
)]]))

View file

@ -224,7 +224,7 @@
(defn on-context-menu
[hover hover-ids workspace-read-only?]
(mf/use-callback
(mf/use-fn
(mf/deps @hover @hover-ids workspace-read-only?)
(fn [event]
(if workspace-read-only?