mirror of
https://github.com/penpot/penpot.git
synced 2025-06-10 16:11:39 +02:00
✨ Adds typography to libraries
This commit is contained in:
parent
4a4cff74e8
commit
718a676fa8
22 changed files with 831 additions and 642 deletions
|
@ -25,29 +25,6 @@
|
|||
[app.main.data.modal :as md]
|
||||
[app.common.pages-helpers :as cph]))
|
||||
|
||||
(declare create-color-result)
|
||||
|
||||
(defn create-color
|
||||
[file-id color]
|
||||
(s/assert (s/nilable uuid?) file-id)
|
||||
(ptk/reify ::create-color
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
|
||||
(->> (rp/mutation! :create-color {:file-id file-id
|
||||
:content color
|
||||
:name color})
|
||||
(rx/map (partial create-color-result file-id))))))
|
||||
|
||||
(defn create-color-result
|
||||
[file-id color]
|
||||
(ptk/reify ::create-color-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update-in [:workspace-file :colors] #(conj % color))
|
||||
(assoc-in [:workspace-local :color-for-rename] (:id color))))))
|
||||
|
||||
(def clear-color-for-rename
|
||||
(ptk/reify ::clear-color-for-rename
|
||||
ptk/UpdateEvent
|
||||
|
@ -73,44 +50,6 @@
|
|||
(-> state
|
||||
(update-in [:workspace-file :colors] #(d/replace-by-id % color))))))
|
||||
|
||||
(declare update-color-result)
|
||||
|
||||
(defn update-color
|
||||
[file-id color-id content]
|
||||
(ptk/reify ::update-color
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> (rp/mutation! :update-color {:id color-id
|
||||
:content content})
|
||||
(rx/map (partial update-color-result file-id))))))
|
||||
|
||||
(defn update-color-result
|
||||
[file-id color]
|
||||
(ptk/reify ::update-color-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update-in [:workspace-file :colors] #(d/replace-by-id % color))))))
|
||||
|
||||
(declare delete-color-result)
|
||||
|
||||
(defn delete-color
|
||||
[file-id color-id]
|
||||
(ptk/reify ::delete-color
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> (rp/mutation! :delete-color {:id color-id})
|
||||
(rx/map #(delete-color-result file-id color-id))))))
|
||||
|
||||
(defn delete-color-result
|
||||
[file-id color-id]
|
||||
(ptk/reify ::delete-color-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update-in [:workspace-file :colors]
|
||||
(fn [colors] (filter #(not= (:id %) color-id) colors)))))))
|
||||
|
||||
(defn change-palette-size [size]
|
||||
(s/assert #{:big :small} size)
|
||||
(ptk/reify ::change-palette-size
|
||||
|
|
|
@ -73,9 +73,10 @@
|
|||
(s/def ::layout-flags (s/coll-of ::layout-flag))
|
||||
|
||||
(def default-layout
|
||||
#{:sitemap
|
||||
:sitemap-pages
|
||||
:layers
|
||||
#{;; :sitemap
|
||||
;; :sitemap-pages
|
||||
;; :layers
|
||||
:assets
|
||||
:element-options
|
||||
:rules
|
||||
:display-grid
|
||||
|
|
|
@ -519,3 +519,56 @@
|
|||
:callback do-dismiss}]
|
||||
:sync-dialog))))))
|
||||
|
||||
|
||||
(def default-typography
|
||||
{:name "Source Sans Pro Regular"
|
||||
:font-id "sourcesanspro"
|
||||
:font-family "sourcesanspro"
|
||||
:font-variant-id "regular"
|
||||
:font-size "14"
|
||||
:font-weight "400"
|
||||
:font-style "normal"
|
||||
:line-height "1.2"
|
||||
:letter-spacing "0"
|
||||
:text-transform "none"})
|
||||
|
||||
(defn add-typography
|
||||
[typography]
|
||||
(let [typography (update typography :id #(or % (uuid/next)))]
|
||||
(us/assert ::cp/typography typography)
|
||||
(ptk/reify ::add-typography
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(let [rchg {:type :add-typography
|
||||
:typography typography}
|
||||
uchg {:type :del-typography
|
||||
:id (:id typography)}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true})))))))
|
||||
|
||||
(defn update-typography
|
||||
[typography]
|
||||
(us/assert ::cp/typography typography)
|
||||
|
||||
(ptk/reify ::update-typography
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [prev (get-in state [:workspace-data :typography (:id typography)])
|
||||
rchg {:type :mod-typography
|
||||
:typography typography}
|
||||
uchg {:type :mod-typography
|
||||
:typography prev}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true})
|
||||
(sync-file nil))))))
|
||||
|
||||
(defn delete-typography
|
||||
[id]
|
||||
(us/assert ::us/uuid id)
|
||||
(ptk/reify ::delete-typography
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [prev (get-in state [:workspace-data :typography id])
|
||||
rchg {:type :del-typography
|
||||
:id id}
|
||||
uchg {:type :add-typography
|
||||
:typography prev}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
|
|
|
@ -300,8 +300,7 @@
|
|||
(rx/mapcat
|
||||
#(rx/zip (rp/query :file-library {:file-id library-id})
|
||||
(rp/query :media-objects {:file-id library-id
|
||||
:is-local false})
|
||||
(rp/query :colors {:file-id library-id}))))
|
||||
:is-local false}))))
|
||||
(rx/map file-linked))))))
|
||||
|
||||
(defn file-linked
|
||||
|
|
|
@ -96,6 +96,9 @@
|
|||
(register! :builtin local-fonts)
|
||||
(register! :google google-fonts)
|
||||
|
||||
(defn get-font-data [id]
|
||||
(get @fontsdb id))
|
||||
|
||||
(defn resolve-variants
|
||||
[id]
|
||||
(get-in @fontsdb [id :variants]))
|
||||
|
@ -164,3 +167,8 @@
|
|||
(defn ready [cb]
|
||||
(-> (obj/get-in js/document ["fonts" "ready"])
|
||||
(p/then cb)))
|
||||
|
||||
(defn get-default-variant [{:keys [variants]}]
|
||||
(or
|
||||
(d/seek #(or (= (:id %) "regular") (= (:name %) "regular")) variants)
|
||||
(first variants)))
|
||||
|
|
|
@ -97,6 +97,12 @@
|
|||
(get-in state [:workspace-data :recent-colors] []))
|
||||
st/state))
|
||||
|
||||
(def workspace-file-typography
|
||||
(l/derived (fn [state]
|
||||
(when-let [file (:workspace-file state)]
|
||||
(get-in file [:data :typography])))
|
||||
st/state))
|
||||
|
||||
(def workspace-project
|
||||
(l/derived :workspace-project st/state))
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
(def auto-width (icon-xref :auto-width))
|
||||
(def box (icon-xref :box))
|
||||
(def chain (icon-xref :chain))
|
||||
(def unchain (icon-xref :unchain))
|
||||
(def chat (icon-xref :chat))
|
||||
(def circle (icon-xref :circle))
|
||||
(def close (icon-xref :close))
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
[library]
|
||||
(let [components-count (count (get-in library [:data :components] []))
|
||||
graphics-count (count (get-in library [:data :media] []))
|
||||
colors-count (count (get-in library [:data :colors] []))]
|
||||
colors-count (count (get-in library [:data :colors] []))
|
||||
typography-count (count (get-in library [:data :typography] []))]
|
||||
;; Include a so this block has always some content
|
||||
(str
|
||||
(str/join " · "
|
||||
|
@ -39,7 +40,10 @@
|
|||
(conj (tr "workspace.libraries.graphics" graphics-count))
|
||||
|
||||
(< 0 colors-count)
|
||||
(conj (tr "workspace.libraries.colors" colors-count))))
|
||||
(conj (tr "workspace.libraries.colors" colors-count))
|
||||
|
||||
(< 0 typography-count)
|
||||
(conj (tr "workspace.libraries.typography" typography-count))))
|
||||
"\u00A0")))
|
||||
|
||||
(mf/defc libraries-tab
|
||||
|
|
|
@ -289,12 +289,15 @@
|
|||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
|
||||
|
||||
(let [sidebar (dom/get-element "settings-bar")
|
||||
assets (dom/get-element-by-class "assets-bar")
|
||||
cpicker (dom/get-element-by-class "colorpicker-tooltip")
|
||||
self (mf/ref-val self-ref)
|
||||
target (dom/get-target event)
|
||||
selecting? (mf/ref-val selecting-ref)]
|
||||
(when-not (or (.contains sidebar target)
|
||||
(.contains assets target)
|
||||
(.contains self target)
|
||||
(and cpicker (.contains cpicker target)))
|
||||
(if selecting?
|
||||
|
@ -340,7 +343,8 @@
|
|||
(when (not read-only?)
|
||||
(let [content (js->clj val :keywordize-keys true)
|
||||
content (first content)]
|
||||
(st/emit! (dw/update-shape id {:content content}))
|
||||
;; Append timestamp so we can react to cursor change events
|
||||
(st/emit! (dw/update-shape id {:content (assoc content :ts (js->clj (.now js/Date)))}))
|
||||
(reset! state val)
|
||||
(reset! content-var content)))))]
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
[app.config :as cfg]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.data.colors :as dc]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
|
@ -26,6 +27,7 @@
|
|||
[app.main.ui.components.context-menu :refer [context-menu]]
|
||||
[app.main.ui.components.file-uploader :refer [file-uploader]]
|
||||
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
|
||||
[app.main.ui.workspace.sidebar.options.typography :refer [typography-entry]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.keyboard :as kbd]
|
||||
[app.main.ui.modal :as modal]
|
||||
|
@ -41,7 +43,7 @@
|
|||
[rumext.alpha :as mf]))
|
||||
|
||||
(mf/defc components-box
|
||||
[{:keys [file-id local? components] :as props}]
|
||||
[{:keys [file-id local? components open? on-open on-close] :as props}]
|
||||
(let [state (mf/use-state {:menu-open false
|
||||
:top nil
|
||||
:left nil
|
||||
|
@ -75,27 +77,28 @@
|
|||
(dnd/set-allowed-effect! event "move")))]
|
||||
|
||||
[:div.asset-group
|
||||
[:div.group-title
|
||||
(tr "workspace.assets.components")
|
||||
[:div.group-title {:class (when (not open?) "closed")}
|
||||
[:span {:on-click #(if open? (on-close) (on-open))} i/arrow-slide (tr "workspace.assets.components")]
|
||||
[:span (str "\u00A0(") (count components) ")"]] ;; Unicode 00A0 is non-breaking space
|
||||
[:div.group-grid.big
|
||||
(for [component components]
|
||||
[:div.grid-cell {:key (:id component)
|
||||
:draggable true
|
||||
:on-context-menu (on-context-menu (:id component))
|
||||
:on-drag-start (partial on-drag-start component)}
|
||||
[:& exports/component-svg {:group (get-in component [:objects (:id component)])
|
||||
:objects (:objects component)}]
|
||||
[:div.cell-name (:name component)]])
|
||||
(when open?
|
||||
[:div.group-grid.big
|
||||
(for [component components]
|
||||
[:div.grid-cell {:key (:id component)
|
||||
:draggable true
|
||||
:on-context-menu (on-context-menu (:id component))
|
||||
:on-drag-start (partial on-drag-start component)}
|
||||
[:& exports/component-svg {:group (get-in component [:objects (:id component)])
|
||||
:objects (:objects component)}]
|
||||
[:div.cell-name (:name component)]])])
|
||||
|
||||
(when local?
|
||||
[:& context-menu
|
||||
{:selectable false
|
||||
:show (:menu-open @state)
|
||||
:on-close #(swap! state assoc :menu-open false)
|
||||
:top (:top @state)
|
||||
:left (:left @state)
|
||||
:options [[(tr "workspace.assets.delete") on-delete]]}])]]))
|
||||
(when local?
|
||||
[:& context-menu
|
||||
{:selectable false
|
||||
:show (:menu-open @state)
|
||||
:on-close #(swap! state assoc :menu-open false)
|
||||
:top (:top @state)
|
||||
:left (:left @state)
|
||||
:options [[(tr "workspace.assets.delete") on-delete]]}])]))
|
||||
|
||||
(mf/defc graphics-box
|
||||
[{:keys [file-id local? objects open? on-open on-close] :as props}]
|
||||
|
@ -326,6 +329,88 @@
|
|||
:local? local?
|
||||
:locale locale}])])]))
|
||||
|
||||
(mf/defc typography-box
|
||||
[{:keys [file-id local? typographies locale open? on-open on-close] :as props}]
|
||||
|
||||
(let [state (mf/use-state {:detail-open? false
|
||||
:menu-open? false
|
||||
:top nil
|
||||
:left nil})
|
||||
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
|
||||
add-typography
|
||||
(mf/use-callback
|
||||
(mf/deps file-id)
|
||||
(fn [value opacity]
|
||||
(st/emit! (dwl/add-typography dwl/default-typography))))
|
||||
|
||||
handle-change
|
||||
(mf/use-callback
|
||||
(mf/deps file-id)
|
||||
(fn [typography changes]
|
||||
(st/emit! (dwl/update-typography (merge typography changes)))))
|
||||
|
||||
handle-typography-selection
|
||||
(fn [typography]
|
||||
(let [attrs (merge
|
||||
{:typography-ref-file (when-not local? file-id)
|
||||
:typography-ref-id (:id typography)}
|
||||
(d/without-keys typography [:id :name]))]
|
||||
(run! #(st/emit! (dwt/update-text-attrs {:id % :editor nil :attrs attrs}))
|
||||
selected)))
|
||||
|
||||
on-context-menu
|
||||
(fn [id event]
|
||||
|
||||
(when local?
|
||||
(let [pos (dom/get-client-position event)
|
||||
top (:y pos)
|
||||
left (- (:x pos) 20)]
|
||||
(dom/prevent-default event)
|
||||
(swap! state assoc
|
||||
:menu-open? true
|
||||
:top top
|
||||
:left left
|
||||
:id id))))
|
||||
|
||||
closed-typography-edit
|
||||
(mf/use-callback
|
||||
(mf/deps file-id)
|
||||
(fn [event] ))
|
||||
|
||||
handle-rename-typography-clicked (fn [])
|
||||
handle-edit-typography-clicked (fn [] )
|
||||
handle-delete-typography (fn []
|
||||
(st/emit! (dwl/delete-typography (:id @state))))]
|
||||
|
||||
[:div.asset-group
|
||||
[:div.group-title {:class (when (not open?) "closed")}
|
||||
[:span {:on-click #(if open? (on-close) (on-open))} i/arrow-slide "Typography" #_(t locale "workspace.assets.typography")]
|
||||
[:span.num-assets (str "\u00A0(") (count typographies) ")"] ;; Unicode 00A0 is non-breaking space
|
||||
(when local?
|
||||
[:div.group-button {:on-click add-typography} i/plus])]
|
||||
|
||||
[:& context-menu
|
||||
{:selectable false
|
||||
:show (:menu-open? @state)
|
||||
:on-close #(swap! state assoc :menu-open? false)
|
||||
:top (:top @state)
|
||||
:left (:left @state)
|
||||
:options [[(t locale "workspace.assets.rename") handle-rename-typography-clicked]
|
||||
[(t locale "workspace.assets.edit") handle-edit-typography-clicked]
|
||||
[(t locale "workspace.assets.delete") handle-delete-typography]]}]
|
||||
(when open?
|
||||
[:div.group-list
|
||||
(for [typography (sort-by (comp - :ts) typographies)]
|
||||
[:& typography-entry
|
||||
{:key (:id typography)
|
||||
:typography typography
|
||||
:read-only? (not local?)
|
||||
:on-context-menu #(on-context-menu (:id typography) %)
|
||||
:on-change #(handle-change typography %)
|
||||
:on-select #(handle-typography-selection typography)}])])]))
|
||||
|
||||
(defn file-colors-ref
|
||||
[id]
|
||||
(l/derived (fn [state]
|
||||
|
@ -354,6 +439,15 @@
|
|||
(vals (get-in state [:workspace-libraries id :data :components])))))
|
||||
st/state =))
|
||||
|
||||
(defn file-typography-ref
|
||||
[id]
|
||||
(l/derived (fn [state]
|
||||
(let [wfile (:workspace-file state)]
|
||||
(if (= (:id wfile) id)
|
||||
(vals (get-in wfile [:data :typography]))
|
||||
(vals (get-in state [:workspace-libraries id :data :typography])))))
|
||||
st/state =))
|
||||
|
||||
(defn apply-filters
|
||||
[coll filters]
|
||||
(->> coll
|
||||
|
@ -369,7 +463,10 @@
|
|||
router (mf/deref refs/router)
|
||||
toggle-open #(swap! open? not)
|
||||
|
||||
toggles (mf/use-state #{:graphics :colors})
|
||||
toggles (mf/use-state #{:components
|
||||
:graphics
|
||||
:colors
|
||||
:typography})
|
||||
|
||||
url (rt/resolve router :workspace
|
||||
{:project-id (:project-id file)
|
||||
|
@ -379,6 +476,9 @@
|
|||
colors-ref (mf/use-memo (mf/deps (:id file)) #(file-colors-ref (:id file)))
|
||||
colors (apply-filters (mf/deref colors-ref) filters)
|
||||
|
||||
typography-ref (mf/use-memo (mf/deps (:id file)) #(file-typography-ref (:id file)))
|
||||
typographies (apply-filters (mf/deref typography-ref) filters)
|
||||
|
||||
media-ref (mf/use-memo (mf/deps (:id file)) #(file-media-ref (:id file)))
|
||||
media (apply-filters (mf/deref media-ref) filters)
|
||||
|
||||
|
@ -413,13 +513,20 @@
|
|||
(str/empty? (:term filters))))
|
||||
show-colors? (and (or (= (:box filters) :all)
|
||||
(= (:box filters) :colors))
|
||||
(or (> (count colors) 0)
|
||||
(str/empty? (:term filters))))
|
||||
show-typography? (and (or (= (:box filters) :all)
|
||||
(= (:box filters) :typography))
|
||||
(or (> (count colors) 0)
|
||||
(str/empty? (:term filters))))]
|
||||
[:div.tool-window-content
|
||||
(when show-components?
|
||||
[:& components-box {:file-id (:id file)
|
||||
:local? local?
|
||||
:components components}])
|
||||
:components components
|
||||
:open? (contains? @toggles :components)
|
||||
:on-open #(swap! toggles conj :components)
|
||||
:on-close #(swap! toggles disj :components)}])
|
||||
(when show-graphics?
|
||||
[:& graphics-box {:file-id (:id file)
|
||||
:local? local?
|
||||
|
@ -436,6 +543,15 @@
|
|||
:on-open #(swap! toggles conj :colors)
|
||||
:on-close #(swap! toggles disj :colors)}])
|
||||
|
||||
(when show-typography?
|
||||
[:& typography-box {:file-id (:id file)
|
||||
:local? local?
|
||||
:locale locale
|
||||
:typographies typographies
|
||||
:open? (contains? @toggles :typography)
|
||||
:on-open #(swap! toggles conj :typography)
|
||||
:on-close #(swap! toggles disj :typography)}])
|
||||
|
||||
(when (and (not show-components?) (not show-graphics?) (not show-colors?))
|
||||
[:div.asset-group
|
||||
[:div.group-title (t locale "workspace.assets.not-found")]])]))]))
|
||||
|
@ -495,8 +611,10 @@
|
|||
[:select.input-select {:value (:box @filters)
|
||||
:on-change on-box-filter-change}
|
||||
[:option {:value ":all"} (t locale "workspace.assets.box-filter-all")]
|
||||
[:option {:value ":graphics"} (t locale "workspace.assets.box-filter-graphics")]
|
||||
[:option {:value ":colors"} (t locale "workspace.assets.box-filter-colors")]]]]
|
||||
[:option {:value ":components"} (t locale "workspace.assets.components")]
|
||||
[:option {:value ":graphics"} (t locale "workspace.assets.graphics")]
|
||||
[:option {:value ":colors"} (t locale "workspace.assets.colors")]
|
||||
[:option {:value ":typography"} (t locale "workspace.assets.typography")]]]]
|
||||
|
||||
[:div.libraries-wrapper
|
||||
[:& file-library
|
||||
|
|
|
@ -144,11 +144,11 @@
|
|||
[:& text-menu {:ids text-ids
|
||||
:type :multiple
|
||||
:editor nil
|
||||
:font-values font-values
|
||||
:align-values align-values
|
||||
:spacing-values spacing-values
|
||||
:valign-values valign-values
|
||||
:decoration-values decoration-values
|
||||
:transform-values transform-values
|
||||
:values (merge font-values
|
||||
align-values
|
||||
spacing-values
|
||||
valign-values
|
||||
decoration-values
|
||||
transform-values)
|
||||
:shapes shapes}])]))
|
||||
|
||||
|
|
|
@ -14,20 +14,23 @@
|
|||
[okulary.core :as l]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.common.data :as d]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.store :as st]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.fill :refer [fill-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]]
|
||||
[app.main.ui.components.editable-select :refer [editable-select]]
|
||||
[app.main.ui.workspace.sidebar.options.typography :refer [typography-entry typography-options]]
|
||||
[app.util.dom :as dom]
|
||||
[app.main.fonts :as fonts]
|
||||
[app.util.i18n :as i18n :refer [tr t]]
|
||||
["slate" :refer [Transforms]]))
|
||||
|
||||
(def text-typography-attrs [:typography-ref-id :typography-ref-file])
|
||||
(def text-fill-attrs [:fill :opacity])
|
||||
(def text-font-attrs [:font-id :font-family :font-variant-id :font-size :font-weight :font-style])
|
||||
(def text-align-attrs [:text-align])
|
||||
|
@ -36,205 +39,52 @@
|
|||
(def text-decoration-attrs [:text-decoration])
|
||||
(def text-transform-attrs [:text-transform])
|
||||
|
||||
(defn- attr->string [value]
|
||||
(if (= value :multiple)
|
||||
""
|
||||
(str value)))
|
||||
|
||||
(def ^:private editor-ref
|
||||
(l/derived :editor refs/workspace-local))
|
||||
|
||||
(mf/defc font-select-optgroups
|
||||
{::mf/wrap [mf/memo]}
|
||||
[]
|
||||
[:*
|
||||
[:optgroup {:label "Local"}
|
||||
(for [font fonts/local-fonts]
|
||||
[:option {:value (:id font)
|
||||
:key (:id font)}
|
||||
(:name font)])]
|
||||
[:optgroup {:label "Google"}
|
||||
(for [font (fonts/resolve-fonts :google)]
|
||||
[:option {:value (:id font)
|
||||
:key (:id font)}
|
||||
(:name font)])]])
|
||||
|
||||
(mf/defc font-options
|
||||
[{:keys [editor ids values locale] :as props}]
|
||||
(let [{:keys [font-id
|
||||
font-size
|
||||
font-variant-id]} values
|
||||
|
||||
font-id (or font-id "sourcesanspro")
|
||||
font-size (or font-size "14")
|
||||
font-variant-id (or font-variant-id "regular")
|
||||
|
||||
fonts (mf/deref fonts/fontsdb)
|
||||
font (get fonts font-id)
|
||||
|
||||
change-font
|
||||
(fn [new-font-id]
|
||||
(run! #(st/emit! (dwt/update-text-attrs
|
||||
{:id %
|
||||
:editor editor
|
||||
:attrs {:font-id new-font-id
|
||||
:font-family (:family (get fonts new-font-id))
|
||||
:font-variant-id nil
|
||||
:font-weight nil
|
||||
:font-style nil}}))
|
||||
ids))
|
||||
|
||||
on-font-family-change
|
||||
(fn [event]
|
||||
(let [new-font-id (-> (dom/get-target event)
|
||||
(dom/get-value))]
|
||||
(when-not (str/empty? new-font-id)
|
||||
(let [font (get fonts new-font-id)]
|
||||
(fonts/ensure-loaded! new-font-id (partial change-font new-font-id))))))
|
||||
|
||||
on-font-size-change
|
||||
(fn [new-font-size]
|
||||
(when-not (str/empty? new-font-size)
|
||||
(run! #(st/emit! (dwt/update-text-attrs
|
||||
{:id %
|
||||
:editor editor
|
||||
:attrs {:font-size (str new-font-size)}}))
|
||||
ids)))
|
||||
|
||||
on-font-variant-change
|
||||
(fn [event]
|
||||
(let [new-variant-id (-> (dom/get-target event)
|
||||
(dom/get-value))
|
||||
variant (d/seek #(= new-variant-id (:id %)) (:variants font))]
|
||||
|
||||
(run! #(st/emit! (dwt/update-text-attrs
|
||||
{:id %
|
||||
:editor editor
|
||||
:attrs {:font-id (:id font)
|
||||
:font-family (:family font)
|
||||
:font-variant-id new-variant-id
|
||||
:font-weight (:weight variant)
|
||||
:font-style (:style variant)}}))
|
||||
ids)))]
|
||||
|
||||
[:*
|
||||
[:div.row-flex
|
||||
[:select.input-select {:value (attr->string font-id)
|
||||
:on-change on-font-family-change}
|
||||
(when (= font-id :multiple)
|
||||
[:option {:value ""} (t locale "settings.multiple")])
|
||||
[:& font-select-optgroups]]]
|
||||
|
||||
[:div.row-flex
|
||||
(let [size-options [8 9 10 11 12 14 18 24 36 48 72]
|
||||
size-options (if (= font-size :multiple) (concat [{:value "" :label "--"}] size-options) size-options)]
|
||||
[:& editable-select
|
||||
{:value (attr->string font-size)
|
||||
:class "input-option"
|
||||
:options size-options
|
||||
:type "number"
|
||||
:placeholder "--"
|
||||
:on-change on-font-size-change}])
|
||||
|
||||
[:select.input-select {:value (attr->string font-variant-id)
|
||||
:on-change on-font-variant-change}
|
||||
(when (= font-size :multiple)
|
||||
[:option {:value ""} "--"])
|
||||
(for [variant (:variants font)]
|
||||
[:option {:value (:id variant)
|
||||
:key (pr-str variant)}
|
||||
(:name variant)])]]]))
|
||||
|
||||
(def root-attrs (d/concat text-valign-attrs
|
||||
text-align-attrs))
|
||||
(def paragraph-attrs text-align-attrs)
|
||||
(def text-attrs (d/concat text-typography-attrs
|
||||
text-font-attrs
|
||||
text-align-attrs
|
||||
text-spacing-attrs
|
||||
text-decoration-attrs
|
||||
text-transform-attrs))
|
||||
|
||||
(mf/defc text-align-options
|
||||
[{:keys [editor ids values locale] :as props}]
|
||||
[{:keys [editor ids values locale on-change] :as props}]
|
||||
(let [{:keys [text-align]} values
|
||||
|
||||
text-align (or text-align "left")
|
||||
|
||||
on-change
|
||||
handle-change
|
||||
(fn [event new-align]
|
||||
(run! #(st/emit!
|
||||
(dwt/update-root-attrs
|
||||
{:id %
|
||||
:editor editor
|
||||
:attrs {:text-align new-align}})
|
||||
(dwt/update-paragraph-attrs
|
||||
{:id %
|
||||
:editor editor
|
||||
:attrs {:text-align new-align}}))
|
||||
ids))]
|
||||
(on-change {:text-align new-align}))]
|
||||
|
||||
;; --- Align
|
||||
[:div.row-flex.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.align-left")
|
||||
:class (dom/classnames :current (= "left" text-align))
|
||||
:on-click #(on-change % "left")}
|
||||
:on-click #(handle-change % "left")}
|
||||
i/text-align-left]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.align-center")
|
||||
:class (dom/classnames :current (= "center" text-align))
|
||||
:on-click #(on-change % "center")}
|
||||
:on-click #(handle-change % "center")}
|
||||
i/text-align-center]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.align-right")
|
||||
:class (dom/classnames :current (= "right" text-align))
|
||||
:on-click #(on-change % "right")}
|
||||
:on-click #(handle-change % "right")}
|
||||
i/text-align-right]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.align-justify")
|
||||
:class (dom/classnames :current (= "justify" text-align))
|
||||
:on-click #(on-change % "justify")}
|
||||
:on-click #(handle-change % "justify")}
|
||||
i/text-align-justify]]))
|
||||
|
||||
|
||||
(mf/defc spacing-options
|
||||
[{:keys [editor ids values locale] :as props}]
|
||||
(let [{:keys [line-height
|
||||
letter-spacing]} values
|
||||
|
||||
line-height (or line-height "1.2")
|
||||
letter-spacing (or letter-spacing "0")
|
||||
|
||||
on-change
|
||||
(fn [event attr]
|
||||
(let [new-spacing (-> (dom/get-target event)
|
||||
(dom/get-value))]
|
||||
(run! #(st/emit! (dwt/update-text-attrs
|
||||
{:id %
|
||||
:editor editor
|
||||
:attrs {attr new-spacing}}))
|
||||
ids)))]
|
||||
[:div.row-flex
|
||||
[:div.input-icon
|
||||
[:span.icon-before.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.line-height")}
|
||||
i/line-height]
|
||||
[:input.input-text
|
||||
{:type "number"
|
||||
:step "0.1"
|
||||
:min "0"
|
||||
:max "200"
|
||||
:value (attr->string line-height)
|
||||
:placeholder (t locale "settings.multiple")
|
||||
:on-change #(on-change % :line-height)}]]
|
||||
|
||||
[:div.input-icon
|
||||
[:span.icon-before.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.letter-spacing")}
|
||||
i/letter-spacing]
|
||||
[:input.input-text
|
||||
{:type "number"
|
||||
:step "0.1"
|
||||
:min "0"
|
||||
:max "200"
|
||||
:value (attr->string letter-spacing)
|
||||
:placeholder (t locale "settings.multiple")
|
||||
:on-change #(on-change % :letter-spacing)}]]]))
|
||||
|
||||
(mf/defc additional-options
|
||||
[{:keys [shapes editor ids values locale] :as props}]
|
||||
[{:keys [shapes editor ids values locale on-change] :as props}]
|
||||
(let [{:keys [vertical-align]} values
|
||||
|
||||
to-single-value (fn [coll] (if (> (count coll) 1) nil (first coll)))
|
||||
|
@ -243,150 +93,171 @@
|
|||
|
||||
vertical-align (or vertical-align "top")
|
||||
|
||||
on-change-grow
|
||||
handle-change-grow
|
||||
(fn [event grow-type]
|
||||
(st/emit! (dwc/update-shapes ids #(assoc % :grow-type grow-type))))
|
||||
|
||||
on-change
|
||||
handle-change
|
||||
(fn [event new-align]
|
||||
(run! #(st/emit! (dwt/update-root-attrs
|
||||
{:id %
|
||||
:editor editor
|
||||
:attrs {:vertical-align new-align}}))
|
||||
ids))]
|
||||
(on-change {:vertical-align new-align}))]
|
||||
|
||||
[:div.row-flex
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.align-top")
|
||||
:class (dom/classnames :current (= "top" vertical-align))
|
||||
:on-click #(on-change % "top")}
|
||||
:on-click #(handle-change % "top")}
|
||||
i/align-top]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.align-middle")
|
||||
:class (dom/classnames :current (= "center" vertical-align))
|
||||
:on-click #(on-change % "center")}
|
||||
:on-click #(handle-change % "center")}
|
||||
i/align-middle]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.align-bottom")
|
||||
:class (dom/classnames :current (= "bottom" vertical-align))
|
||||
:on-click #(on-change % "bottom")}
|
||||
:on-click #(handle-change % "bottom")}
|
||||
i/align-bottom]]
|
||||
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.grow-fixed")
|
||||
:class (dom/classnames :current (= :fixed grow-type))
|
||||
:on-click #(on-change-grow % :fixed)}
|
||||
:on-click #(handle-change-grow % :fixed)}
|
||||
i/auto-fix]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.grow-auto-width")
|
||||
:class (dom/classnames :current (= :auto-width grow-type))
|
||||
:on-click #(on-change-grow % :auto-width)}
|
||||
:on-click #(handle-change-grow % :auto-width)}
|
||||
i/auto-width]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.grow-auto-height")
|
||||
:class (dom/classnames :current (= :auto-height grow-type))
|
||||
:on-click #(on-change-grow % :auto-height)}
|
||||
:on-click #(handle-change-grow % :auto-height)}
|
||||
i/auto-height]]]))
|
||||
|
||||
(mf/defc text-decoration-options
|
||||
[{:keys [editor ids values locale] :as props}]
|
||||
[{:keys [editor ids values locale on-change] :as props}]
|
||||
(let [{:keys [text-decoration]} values
|
||||
|
||||
text-decoration (or text-decoration "none")
|
||||
|
||||
on-change
|
||||
handle-change
|
||||
(fn [event type]
|
||||
(run! #(st/emit! (dwt/update-text-attrs
|
||||
{:id %
|
||||
:editor editor
|
||||
:attrs {:text-decoration type}}))
|
||||
ids))]
|
||||
(on-change {:text-decoration type}))]
|
||||
[:div.row-flex
|
||||
[:span.element-set-subtitle (t locale "workspace.options.text-options.decoration")]
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.none")
|
||||
:class (dom/classnames :current (= "none" text-decoration))
|
||||
:on-click #(on-change % "none")}
|
||||
:on-click #(handle-change % "none")}
|
||||
i/minus]
|
||||
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.underline")
|
||||
:class (dom/classnames :current (= "underline" text-decoration))
|
||||
:on-click #(on-change % "underline")}
|
||||
:on-click #(handle-change % "underline")}
|
||||
i/underline]
|
||||
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.strikethrough")
|
||||
:class (dom/classnames :current (= "line-through" text-decoration))
|
||||
:on-click #(on-change % "line-through")}
|
||||
:on-click #(handle-change % "line-through")}
|
||||
i/strikethrough]]]))
|
||||
|
||||
(mf/defc text-transform-options
|
||||
[{:keys [editor ids values locale] :as props}]
|
||||
(let [{:keys [text-transform]} values
|
||||
|
||||
text-transform (or text-transform "none")
|
||||
|
||||
on-change
|
||||
(fn [event type]
|
||||
(run! #(st/emit! (dwt/update-text-attrs
|
||||
{:id %
|
||||
:editor editor
|
||||
:attrs {:text-transform type}}))
|
||||
ids))]
|
||||
[:div.row-flex
|
||||
[:span.element-set-subtitle (t locale "workspace.options.text-options.text-case")]
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.none")
|
||||
:class (dom/classnames :current (= "none" text-transform))
|
||||
:on-click #(on-change % "none")}
|
||||
i/minus]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.uppercase")
|
||||
:class (dom/classnames :current (= "uppercase" text-transform))
|
||||
:on-click #(on-change % "uppercase")}
|
||||
i/uppercase]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.lowercase")
|
||||
:class (dom/classnames :current (= "lowercase" text-transform))
|
||||
:on-click #(on-change % "lowercase")}
|
||||
i/lowercase]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.titlecase")
|
||||
:class (dom/classnames :current (= "capitalize" text-transform))
|
||||
:on-click #(on-change % "capitalize")}
|
||||
i/titlecase]]]))
|
||||
(defn generate-typography-name [{:keys [font-id font-variant-id] :as typography}]
|
||||
(let [{:keys [name]} (fonts/get-font-data font-id)]
|
||||
(-> typography
|
||||
(assoc :name (str name " " (str/title font-variant-id))))) )
|
||||
|
||||
(mf/defc text-menu
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [ids
|
||||
type
|
||||
editor
|
||||
font-values
|
||||
align-values
|
||||
spacing-values
|
||||
valign-values
|
||||
decoration-values
|
||||
transform-values
|
||||
values
|
||||
shapes] :as props}]
|
||||
(let [locale (mf/deref i18n/locale)
|
||||
typographies (mf/deref refs/workspace-file-typography)
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
label (case type
|
||||
:multiple (t locale "workspace.options.text-options.title-selection")
|
||||
:group (t locale "workspace.options.text-options.title-group")
|
||||
(t locale "workspace.options.text-options.title"))]
|
||||
[:div.element-set
|
||||
[:div.element-set-title label]
|
||||
[:div.element-set-content
|
||||
[:& font-options {:editor editor :ids ids :values font-values :locale locale}]
|
||||
[:& text-align-options {:editor editor :ids ids :values align-values :locale locale}]
|
||||
[:& spacing-options {:editor editor :ids ids :values spacing-values :locale locale}]
|
||||
[:& additional-options {:shapes shapes :editor editor :ids ids :values valign-values :locale locale}]
|
||||
[:& text-decoration-options {:editor editor :ids ids :values decoration-values :locale locale}]
|
||||
[:& text-transform-options {:editor editor :ids ids :values transform-values :locale locale}]]]))
|
||||
(t locale "workspace.options.text-options.title"))
|
||||
|
||||
emit-update!
|
||||
(fn [id attrs]
|
||||
(let [attrs (select-keys attrs root-attrs)]
|
||||
(when-not (empty? attrs)
|
||||
(st/emit! (dwt/update-root-attrs {:id id :editor editor :attrs attrs}))))
|
||||
|
||||
(let [attrs (select-keys attrs paragraph-attrs)]
|
||||
(when-not (empty? attrs)
|
||||
(st/emit! (dwt/update-paragraph-attrs {:id id :editor editor :attrs attrs}))))
|
||||
|
||||
(let [attrs (select-keys attrs text-attrs)]
|
||||
(when-not (empty? attrs)
|
||||
(st/emit! (dwt/update-text-attrs {:id id :editor editor :attrs attrs})))))
|
||||
|
||||
typography (cond
|
||||
(and (:typography-ref-id values)
|
||||
(:typography-ref-file values))
|
||||
(-> shared-libs
|
||||
(get-in [(:typography-ref-file values) :data :typography (:typography-ref-id values)])
|
||||
(assoc :file-id (:typography-ref-file values)))
|
||||
|
||||
(:typography-ref-id values)
|
||||
(get typographies (:typography-ref-id values)))
|
||||
|
||||
|
||||
handle-click
|
||||
(mf/use-callback
|
||||
(mf/deps values)
|
||||
(fn [event]
|
||||
(let [setted-values (-> (d/without-nils values)
|
||||
(select-keys
|
||||
(d/concat text-font-attrs
|
||||
text-spacing-attrs
|
||||
text-transform-attrs)))
|
||||
typography (merge dwl/default-typography setted-values)
|
||||
typography (generate-typography-name typography)]
|
||||
(let [id (uuid/next)]
|
||||
(st/emit! (dwl/add-typography (assoc typography :id id)))
|
||||
(run! #(emit-update! % {:typography-ref-id id}) ids)))))
|
||||
|
||||
handle-deattach-typography
|
||||
(fn []
|
||||
(run! #(emit-update! % {:typography-ref-file nil
|
||||
:typography-ref-id nil})
|
||||
ids))
|
||||
|
||||
handle-change-typography
|
||||
(fn [changes]
|
||||
(st/emit! (dwl/update-typography (merge typography changes))))
|
||||
|
||||
opts #js {:editor editor
|
||||
:ids ids
|
||||
:values values
|
||||
:on-change (fn [attrs]
|
||||
(run! #(emit-update! % attrs) ids))
|
||||
:locale locale}]
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span label]
|
||||
[:div.add-page {:on-click handle-click} i/close]]
|
||||
|
||||
(if typography
|
||||
[:& typography-entry {:typography typography
|
||||
:on-deattach handle-deattach-typography
|
||||
:on-change handle-change-typography}]
|
||||
[:> typography-options opts])
|
||||
|
||||
[:div.element-set-content
|
||||
[:> text-align-options opts]
|
||||
[:> additional-options opts]
|
||||
[:> text-decoration-options opts]]]))
|
||||
|
||||
(mf/defc options
|
||||
[{:keys [shape] :as props}]
|
||||
|
@ -399,42 +270,25 @@
|
|||
measure-values (select-keys shape measure-attrs)
|
||||
|
||||
fill-values (dwt/current-text-values
|
||||
{:editor editor
|
||||
:shape shape
|
||||
:attrs text-fill-attrs})
|
||||
{:editor editor
|
||||
:shape shape
|
||||
:attrs text-fill-attrs})
|
||||
|
||||
converted-fill-values {:fill-color (:fill fill-values)
|
||||
:fill-opacity (:opacity fill-values)}
|
||||
|
||||
font-values (dwt/current-text-values
|
||||
{:editor editor
|
||||
:shape shape
|
||||
:attrs text-font-attrs})
|
||||
|
||||
align-values (dwt/current-paragraph-values
|
||||
{:editor editor
|
||||
:shape shape
|
||||
:attrs text-align-attrs})
|
||||
text-values (merge
|
||||
(dwt/current-root-values
|
||||
{:editor editor :shape shape
|
||||
:attrs root-attrs})
|
||||
(dwt/current-text-values
|
||||
{:editor editor :shape shape
|
||||
:attrs paragraph-attrs})
|
||||
(dwt/current-text-values
|
||||
{:editor editor :shape shape
|
||||
:attrs text-attrs}))]
|
||||
|
||||
spacing-values (dwt/current-text-values
|
||||
{:editor editor
|
||||
:shape shape
|
||||
:attrs text-spacing-attrs})
|
||||
|
||||
valign-values (dwt/current-root-values
|
||||
{:editor editor
|
||||
:shape shape
|
||||
:attrs text-valign-attrs})
|
||||
|
||||
decoration-values (dwt/current-text-values
|
||||
{:editor editor
|
||||
:shape shape
|
||||
:attrs text-decoration-attrs})
|
||||
|
||||
transform-values (dwt/current-text-values
|
||||
{:editor editor
|
||||
:shape shape
|
||||
:attrs text-transform-attrs})]
|
||||
[:*
|
||||
[:& measures-menu {:ids ids
|
||||
:type type
|
||||
|
@ -448,11 +302,5 @@
|
|||
:values (select-keys shape [:shadow])}]
|
||||
[:& text-menu {:ids ids
|
||||
:type type
|
||||
:editor editor
|
||||
:font-values font-values
|
||||
:align-values align-values
|
||||
:spacing-values spacing-values
|
||||
:valign-values valign-values
|
||||
:decoration-values decoration-values
|
||||
:transform-values transform-values
|
||||
:values text-values
|
||||
:shapes [shape]}]]))
|
||||
|
|
|
@ -0,0 +1,279 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2020 UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.typography
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[cuerdas.core :as str]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.common.data :as d]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.ui.components.editable-select :refer [editable-select]]
|
||||
[app.main.ui.workspace.sidebar.options.common :refer [advanced-options]]
|
||||
[app.util.dom :as dom]
|
||||
[app.main.fonts :as fonts]
|
||||
[app.util.i18n :as i18n :refer [t]]))
|
||||
|
||||
(defn- attr->string [value]
|
||||
(if (= value :multiple)
|
||||
""
|
||||
(str value)))
|
||||
|
||||
(mf/defc font-select-optgroups
|
||||
{::mf/wrap [mf/memo]}
|
||||
[]
|
||||
[:*
|
||||
[:optgroup {:label "Local"}
|
||||
(for [font fonts/local-fonts]
|
||||
[:option {:value (:id font)
|
||||
:key (:id font)}
|
||||
(:name font)])]
|
||||
[:optgroup {:label "Google"}
|
||||
(for [font (fonts/resolve-fonts :google)]
|
||||
[:option {:value (:id font)
|
||||
:key (:id font)}
|
||||
(:name font)])]])
|
||||
|
||||
(mf/defc font-options
|
||||
[{:keys [editor ids values locale on-change] :as props}]
|
||||
(let [{:keys [font-id
|
||||
font-size
|
||||
font-variant-id]} values
|
||||
|
||||
font-id (or font-id "sourcesanspro")
|
||||
font-size (or font-size "14")
|
||||
font-variant-id (or font-variant-id "regular")
|
||||
|
||||
fonts (mf/deref fonts/fontsdb)
|
||||
font (get fonts font-id)
|
||||
|
||||
change-font
|
||||
(fn [new-font-id]
|
||||
(let [{:keys [family] :as font} (get fonts new-font-id)
|
||||
{:keys [id name weight style]} (fonts/get-default-variant font)]
|
||||
(on-change {:font-id new-font-id
|
||||
:font-family family
|
||||
:font-variant-id (or id name)
|
||||
:font-weight weight
|
||||
:font-style style})))
|
||||
|
||||
on-font-family-change
|
||||
(fn [event]
|
||||
(let [new-font-id (dom/get-target-val event)]
|
||||
(when-not (str/empty? new-font-id)
|
||||
(let [font (get fonts new-font-id)]
|
||||
(fonts/ensure-loaded! new-font-id (partial change-font new-font-id))))))
|
||||
|
||||
on-font-size-change
|
||||
(fn [new-font-size]
|
||||
(when-not (str/empty? new-font-size)
|
||||
(on-change {:font-size (str new-font-size)})))
|
||||
|
||||
on-font-variant-change
|
||||
(fn [event]
|
||||
(let [new-variant-id (dom/get-target-val event)
|
||||
variant (d/seek #(= new-variant-id (:id %)) (:variants font))]
|
||||
(on-change {:font-id (:id font)
|
||||
:font-family (:family font)
|
||||
:font-variant-id new-variant-id
|
||||
:font-weight (:weight variant)
|
||||
:font-style (:style variant)})))]
|
||||
|
||||
[:*
|
||||
[:div.row-flex
|
||||
[:select.input-select.font-option
|
||||
{:value (attr->string font-id)
|
||||
:on-change on-font-family-change}
|
||||
(when (= font-id :multiple)
|
||||
[:option {:value ""} (t locale "settings.multiple")])
|
||||
[:& font-select-optgroups]]]
|
||||
|
||||
[:div.row-flex
|
||||
(let [size-options [8 9 10 11 12 14 18 24 36 48 72]
|
||||
size-options (if (= font-size :multiple) (into [{:value "" :label "--"}] size-options) size-options)]
|
||||
[:& editable-select
|
||||
{:value (attr->string font-size)
|
||||
:class "input-option size-option"
|
||||
:options size-options
|
||||
:type "number"
|
||||
:placeholder "--"
|
||||
:on-change on-font-size-change}])
|
||||
|
||||
[:select.input-select.variant-option
|
||||
{:value (attr->string font-variant-id)
|
||||
:on-change on-font-variant-change}
|
||||
(when (= font-size :multiple)
|
||||
[:option {:value ""} "--"])
|
||||
(for [variant (:variants font)]
|
||||
[:option {:value (:id variant)
|
||||
:key (pr-str variant)}
|
||||
(:name variant)])]]]))
|
||||
|
||||
|
||||
(mf/defc spacing-options
|
||||
[{:keys [editor ids values locale on-change] :as props}]
|
||||
(let [{:keys [line-height
|
||||
letter-spacing]} values
|
||||
|
||||
line-height (or line-height "1.2")
|
||||
letter-spacing (or letter-spacing "0")
|
||||
|
||||
handle-change
|
||||
(fn [event attr]
|
||||
(let [new-spacing (dom/get-target-val event)]
|
||||
(on-change {attr new-spacing})))]
|
||||
|
||||
[:div.row-flex
|
||||
[:div.input-icon
|
||||
[:span.icon-before.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.line-height")}
|
||||
i/line-height]
|
||||
[:input.input-text
|
||||
{:type "number"
|
||||
:step "0.1"
|
||||
:min "0"
|
||||
:max "200"
|
||||
:value (attr->string line-height)
|
||||
:placeholder (t locale "settings.multiple")
|
||||
:on-change #(handle-change % :line-height)}]]
|
||||
|
||||
[:div.input-icon
|
||||
[:span.icon-before.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.letter-spacing")}
|
||||
i/letter-spacing]
|
||||
[:input.input-text
|
||||
{:type "number"
|
||||
:step "0.1"
|
||||
:min "0"
|
||||
:max "200"
|
||||
:value (attr->string letter-spacing)
|
||||
:placeholder (t locale "settings.multiple")
|
||||
:on-change #(handle-change % :letter-spacing)}]]]))
|
||||
|
||||
(mf/defc text-transform-options
|
||||
[{:keys [editor ids values locale on-change] :as props}]
|
||||
(let [{:keys [text-transform]} values
|
||||
|
||||
text-transform (or text-transform "none")
|
||||
|
||||
handle-change
|
||||
(fn [event type]
|
||||
(on-change {:text-transform type}))]
|
||||
[:div.row-flex
|
||||
[:span.element-set-subtitle (t locale "workspace.options.text-options.text-case")]
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.none")
|
||||
:class (dom/classnames :current (= "none" text-transform))
|
||||
:on-click #(handle-change % "none")}
|
||||
i/minus]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.uppercase")
|
||||
:class (dom/classnames :current (= "uppercase" text-transform))
|
||||
:on-click #(handle-change % "uppercase")}
|
||||
i/uppercase]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.lowercase")
|
||||
:class (dom/classnames :current (= "lowercase" text-transform))
|
||||
:on-click #(handle-change % "lowercase")}
|
||||
i/lowercase]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (t locale "workspace.options.text-options.titlecase")
|
||||
:class (dom/classnames :current (= "capitalize" text-transform))
|
||||
:on-click #(handle-change % "capitalize")}
|
||||
i/titlecase]]]))
|
||||
|
||||
(mf/defc typography-options
|
||||
[{:keys [ids editor values on-change]}]
|
||||
(let [locale (mf/deref i18n/locale)
|
||||
opts #js {:editor editor
|
||||
:ids ids
|
||||
:values values
|
||||
:locale locale
|
||||
:on-change on-change}]
|
||||
|
||||
[:div.element-set-content
|
||||
[:> font-options opts]
|
||||
[:> spacing-options opts]
|
||||
[:> text-transform-options opts]]))
|
||||
|
||||
|
||||
(mf/defc typography-entry
|
||||
[{:keys [typography read-only? on-select on-change on-deattach on-context-menu]}]
|
||||
(let [open? (mf/use-state false)
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
hover-deattach (mf/use-state false)]
|
||||
[:*
|
||||
[:div.element-set-options-group.typography-entry
|
||||
[:div.typography-selection-wrapper
|
||||
{:class (when on-select "is-selectable")
|
||||
:on-click on-select
|
||||
:on-context-menu on-context-menu}
|
||||
[:div.typography-sample
|
||||
{:style {:font-family (:font-family typography)
|
||||
:font-weight (:font-weight typography)
|
||||
:font-style (:font-style typography)}}
|
||||
"Ag"]
|
||||
[:div.typography-name (:name typography)]]
|
||||
[:div.element-set-actions
|
||||
(when on-deattach
|
||||
[:div.element-set-actions-button
|
||||
{:on-mouse-enter #(reset! hover-deattach true)
|
||||
:on-mouse-leave #(reset! hover-deattach false)
|
||||
:on-click on-deattach}
|
||||
(if @hover-deattach i/unchain i/chain)])
|
||||
|
||||
[:div.element-set-actions-button
|
||||
{:on-click #(reset! open? true)}
|
||||
i/actions]]]
|
||||
|
||||
[:& advanced-options {:visible? @open?
|
||||
:on-close #(reset! open? false)}
|
||||
(if read-only?
|
||||
[:div.element-set-content.typography-read-only-data
|
||||
[:div.row-flex.typography-name
|
||||
[:spang (:name typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label "Font"]
|
||||
[:span (:font-id typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label "Size"]
|
||||
[:span (:font-size typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label "Line Height"]
|
||||
[:span (:line-height typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label "Letter spacing"]
|
||||
[:span (:letter-spacing typography)]]
|
||||
|
||||
[:div.row-flex
|
||||
[:span.label "Text transform"]
|
||||
[:span (:text-transform typography)]]
|
||||
|
||||
[:div.go-to-lib-button
|
||||
"Go to style library file to edit"]]
|
||||
|
||||
[:*
|
||||
[:div.element-set-content
|
||||
[:div.row-flex
|
||||
[:input.element-name.adv-typography-name
|
||||
{:type "text"
|
||||
:value (:name typography)
|
||||
:on-change #(on-change {:name (dom/get-target-val %)})}]]]
|
||||
[:& typography-options {:values typography
|
||||
:on-change on-change}]]
|
||||
)
|
||||
|
||||
]]))
|
|
@ -76,6 +76,8 @@
|
|||
[node]
|
||||
(.-value node))
|
||||
|
||||
(def get-target-val (comp get-value get-target))
|
||||
|
||||
(defn click
|
||||
"Click a node"
|
||||
[node]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue