🎉 Add new font selector to workspace.

This commit is contained in:
Andrey Antukh 2021-05-12 09:48:06 +02:00 committed by Alonso Torres
parent 8831f3241c
commit 2ea200be78
19 changed files with 800 additions and 199 deletions

View file

@ -13,6 +13,7 @@
[app.main.repo :as rp]
[app.main.data.events :as ev]
[app.main.data.users :as du]
[app.main.data.fonts :as df]
[app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt]
[app.util.time :as dt]
@ -86,6 +87,7 @@
ptk/WatchEvent
(watch [_ state stream]
(rx/merge
(ptk/watch (df/load-team-fonts id) state stream)
(ptk/watch (fetch-projects) state stream)
(ptk/watch (du/fetch-teams) state stream)
(ptk/watch (du/fetch-users {:team-id id}) state stream)))))

View file

@ -0,0 +1,57 @@
;; 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/.
;;
;; Copyright (c) UXBOX Labs SL
(ns app.main.data.fonts
(:require
[app.common.media :as cm]
[app.main.fonts :as fonts]
[app.main.repo :as rp]
[app.util.i18n :as i18n :refer [tr]]
[beicon.core :as rx]
[cljs.spec.alpha :as s]
[cuerdas.core :as str]
[potok.core :as ptk]))
(defn prepare-font-variant
[item]
{:id (str (:font-style item) "-" (:font-weight item))
:name (str (cm/font-weight->name (:font-weight item)) " "
(str/capital (:font-style item)))
:style (:font-style item)
:weight (str (:font-weight item))
::fonts/woff1-file-id (:woff1-file-id item)
::fonts/woff2-file-id (:woff2-file-id item)
::fonts/ttf-file-id (:ttf-file-id item)
::fonts/otf-file-id (:otf-file-id item)})
(defn prepare-font
[[id [item :as items]]]
{:id id
:name (:font-family item)
:family (:font-family item)
:variants (mapv prepare-font-variant items)})
(defn team-fonts-loaded
[fonts]
(ptk/reify ::team-fonts-loaded
ptk/EffectEvent
(effect [_ state stream]
(let [fonts (->> (group-by :font-id fonts)
(mapv prepare-font))]
(fonts/register! :custom fonts)))))
(defn load-team-fonts
[team-id]
(ptk/reify ::load-team-fonts
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/query :team-font-variants {:team-id team-id})
(rx/map team-fonts-loaded)))))
(defn get-fonts
[backend]
(get @fonts/fonts backend []))

View file

@ -1258,6 +1258,15 @@
(rx/of ::dwp/force-persist
(rt/nav :dashboard-projects {:team-id team-id})))))))
(defn go-to-dashboard-fonts
[]
(ptk/reify ::go-to-dashboard
ptk/WatchEvent
(watch [it state stream]
(let [team-id (:current-team-id state)]
(rx/of ::dwp/force-persist
(rt/nav :dashboard-fonts {:team-id team-id}))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Context Menu
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -15,6 +15,7 @@
[app.common.uuid :as uuid]
[app.main.data.dashboard :as dd]
[app.main.data.media :as di]
[app.main.data.fonts :as df]
[app.main.data.messages :as dm]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.common :as dwc]
@ -270,7 +271,8 @@
:project project
:libraries libraries}))
(rx/mapcat (fn [{:keys [project] :as bundle}]
(rx/of (ptk/data-event ::bundle-fetched bundle))))))))
(rx/of (ptk/data-event ::bundle-fetched bundle)
(df/load-team-fonts (:team-id project)))))))))
;; --- Set File shared

View file

@ -8,16 +8,22 @@
"Fonts management and loading logic."
(:require-macros [app.main.fonts :refer [preload-gfonts]])
(:require
[app.config :as cf]
[app.common.data :as d]
[app.util.dom :as dom]
[app.util.object :as obj]
[app.util.timers :as ts]
[app.util.logging :as log]
[lambdaisland.uri :as u]
[goog.events :as gev]
[beicon.core :as rx]
[clojure.set :as set]
[cuerdas.core :as str]
[okulary.core :as l]
[promesa.core :as p]))
(log/set-level! :trace)
(def google-fonts
(preload-gfonts "fonts/gfonts.2020.04.23.json"))
@ -38,22 +44,27 @@
{:id "blackitalic" :name "black (italic)" :weight "900" :style "italic"}]}])
(defonce fontsdb (l/atom {}))
(defonce fontsview (l/atom {}))
(defonce fonts (l/atom []))
(defn- materialize-fontsview
[db]
(reset! fontsview (reduce-kv (fn [acc k v]
(assoc acc k (sort-by :name v)))
{}
(group-by :backend (vals db)))))
(add-watch fontsdb "main"
(fn [_ _ _ db]
(ts/schedule #(materialize-fontsview db))))
(->> (vals db)
(sort-by :name)
(map-indexed #(assoc %2 :index %1))
(vec)
(reset! fonts))))
(defn- remove-fonts
[db backend]
(reduce-kv #(cond-> %1 (= backend (:backend %3)) (dissoc %2)) db db))
(defn register!
[backend fonts]
(let [fonts (map #(assoc % :backend backend) fonts)]
(swap! fontsdb #(merge % (d/index-by :id fonts)))))
(swap! fontsdb
(fn [db]
(let [db (reduce-kv #(cond-> %1 (= backend (:backend %3)) (dissoc %2)) db db)
fonts (map #(assoc % :backend backend) fonts)]
(merge db (d/index-by :id fonts))))))
(register! :builtin local-fonts)
(register! :google google-fonts)
@ -67,13 +78,15 @@
(defn resolve-fonts
[backend]
(get @fontsview backend))
(get @fonts backend))
;; --- Fonts Loader
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; FONTS LOADING
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defonce loaded (l/atom #{}))
(defn- create-link-node
(defn- create-link-element
[uri]
(let [node (.createElement js/document "link")]
(unchecked-set node "href" uri)
@ -81,32 +94,107 @@
(unchecked-set node "type" "text/css")
node))
(defn gfont-url [family variants]
(defn- create-style-element
[css]
(let [node (.createElement js/document "style")]
(unchecked-set node "innerHTML" css)
node))
(defn- load-font-css!
"Creates a link element and attaches it to the dom for correctly
load external css resource."
[url on-loaded]
(let [node (create-link-element url)
head (.-head ^js js/document)]
(gev/listenOnce node "load" (fn [event]
(when (fn? on-loaded)
(on-loaded))))
(dom/append-child! head node)))
(defn- add-font-css!
"Creates a style element and attaches it to the dom."
[css]
(let [head (.-head ^js js/document)]
(->> (create-style-element css)
(dom/append-child! head))))
;; --- LOADER: BUILTIN
(defmulti ^:private load-font :backend)
(defmethod load-font :default
[{:keys [backend] :as font}]
(log/warn :msg "no implementation found for" :backend backend))
(defmethod load-font :builtin
[{:keys [id ::on-loaded] :as font}]
(log/debug :action "load-font" :font-id id :backend "builtin")
;; (js/console.log "[debug:fonts]: loading builtin font" id)
(when (fn? on-loaded)
(on-loaded id)))
;; --- LOADER: GOOGLE
(defn generate-gfonts-url
[{:keys [family variants]}]
(let [base (str "https://fonts.googleapis.com/css?family=" family)
variants (str/join "," (map :id variants))]
(str base ":" variants "&display=block")))
(defmulti ^:private load-font :backend)
(defmethod load-font :builtin
[{:keys [id ::on-loaded] :as font}]
(js/console.log "[debug:fonts]: loading builtin font" id)
(when (fn? on-loaded)
(on-loaded id)))
(defmethod load-font :google
[{:keys [id family variants ::on-loaded] :as font}]
(when (exists? js/window)
(js/console.log "[debug:fonts]: loading google font" id)
(let [node (create-link-node (gfont-url family variants))]
(.addEventListener node "load" (fn [event] (when (fn? on-loaded)
(on-loaded id))))
(.append (.-head js/document) node)
(log/debug :action "load-font" :font-id id :backend "google")
(let [url (generate-gfonts-url font)]
(load-font-css! url (partial on-loaded id))
nil)))
(defmethod load-font :default
[{:keys [backend] :as font}]
(js/console.warn "no implementation found for" backend))
;; --- LOADER: CUSTOM
(def font-css-template
"@font-face {
font-family: '%(family)s';
font-style: %(style)s;
font-weight: %(weight)s;
font-display: block;
src: url(%(woff2-uri)s) format('woff2'),
url(%(woff1-uri)s) format('woff'),
url(%(ttf-uri)s) format('ttf'),
url(%(otf-uri)s) format('otf');
}")
(defn- font-id->uri
[font-id]
(str (u/join cf/public-uri "assets/by-id/" font-id)))
(defn generate-custom-font-variant-css
[family variant]
(str/fmt font-css-template
{:family family
:style (:style variant)
:weight (:weight variant)
:woff2-uri (font-id->uri (::woff2-file-id variant))
:woff1-uri (font-id->uri (::woff1-file-id variant))
:ttf-uri (font-id->uri (::ttf-file-id variant))
:otf-uri (font-id->uri (::otf-file-id variant))}))
(defn- generate-custom-font-css
[{:keys [family variants] :as font}]
(->> variants
(map #(generate-custom-font-variant-css family %))
(str/join "\n")))
(defmethod load-font :custom
[{:keys [id family variants ::on-loaded] :as font}]
(when (exists? js/window)
(js/console.log "[debug:fonts]: loading google font" id)
(let [css (generate-custom-font-css font)]
(add-font-css! css))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; LOAD API
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn ensure-loaded!
([id]
@ -119,7 +207,8 @@
(load-font (assoc font ::on-loaded on-loaded))
(swap! loaded conj id)))))
(defn ready [cb]
(defn ready
[cb]
(-> (obj/get-in js/document ["fonts" "ready"])
(p/then cb)))

View file

@ -13,7 +13,7 @@
[props]
(let [children (gobj/get props "children")
on-close (gobj/get props "on-close")
ref (gobj/get props "container")
ref (gobj/get props "container")
on-click
(fn [event]

View file

@ -62,7 +62,7 @@
"Given a font and the variant-id, retrieves the style CSS for it."
[{:keys [id backend family variants] :as font} font-variant-id]
(if (= :google backend)
(let [uri (fonts/gfont-url family [{:id font-variant-id}])]
(let [uri (fonts/generate-gfonts-url {:family family :variants [{:id font-variant-id}]})]
(->> (http/send! {:method :get
:mode :cors
:omit-default-headers true

View file

@ -128,7 +128,6 @@
:on-click #(handle-change % "rtl")}
i/text-direction-rtl]]))
(mf/defc vertical-align
[{:keys [shapes ids values on-change] :as props}]
(let [{:keys [vertical-align]} values
@ -225,63 +224,73 @@
(tr "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 :attrs attrs}))))
(mf/use-callback
(fn [id attrs]
(let [attrs (select-keys attrs root-attrs)]
(when-not (empty? attrs)
(st/emit! (dwt/update-root-attrs {:id id :attrs attrs}))))
(let [attrs (select-keys attrs paragraph-attrs)]
(when-not (empty? attrs)
(st/emit! (dwt/update-paragraph-attrs {:id id :attrs attrs}))))
(let [attrs (select-keys attrs paragraph-attrs)]
(when-not (empty? attrs)
(st/emit! (dwt/update-paragraph-attrs {:id id :attrs attrs}))))
(let [attrs (select-keys attrs text-attrs)]
(when-not (empty? attrs)
(st/emit! (dwt/update-text-attrs {:id id :attrs attrs})))))
(let [attrs (select-keys attrs text-attrs)]
(when-not (empty? attrs)
(st/emit! (dwt/update-text-attrs {:id id :attrs attrs}))))))
on-change
(mf/use-callback
(mf/deps ids)
(fn [attrs]
(run! #(emit-update! % attrs) ids)))
typography
(cond
(and (:typography-ref-id values)
(not= (:typography-ref-id values) :multiple)
(not= (:typography-ref-file values) file-id))
(-> shared-libs
(get-in [(:typography-ref-file values) :data :typographies (:typography-ref-id values)])
(assoc :file-id (:typography-ref-file values)))
(mf/use-memo
(mf/deps values file-id shared-libs)
(fn []
(cond
(and (:typography-ref-id values)
(not= (:typography-ref-id values) :multiple)
(not= (:typography-ref-file values) file-id))
(-> shared-libs
(get-in [(:typography-ref-file values) :data :typographies (:typography-ref-id values)])
(assoc :file-id (:typography-ref-file values)))
(and (:typography-ref-id values)
(not= (:typography-ref-id values) :multiple)
(= (:typography-ref-file values) file-id))
(get typographies (:typography-ref-id values)))
(and (:typography-ref-id values)
(not= (:typography-ref-id values) :multiple)
(= (:typography-ref-file values) file-id))
(get typographies (:typography-ref-id values)))))
on-convert-to-typography
(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 txt/default-typography setted-values)
typography (generate-typography-name typography)]
(let [id (uuid/next)]
(st/emit! (dwl/add-typography (assoc typography :id id) false))
(run! #(emit-update! % {:typography-ref-id id
:typography-ref-file file-id}) ids)))))
(fn [event]
(let [setted-values (-> (d/without-nils values)
(select-keys
(d/concat text-font-attrs
text-spacing-attrs
text-transform-attrs)))
typography (merge txt/default-typography setted-values)
typography (generate-typography-name typography)]
(let [id (uuid/next)]
(st/emit! (dwl/add-typography (assoc typography :id id) false))
(run! #(emit-update! % {:typography-ref-id id
:typography-ref-file file-id}) ids))))
handle-detach-typography
(fn []
(run! #(emit-update! % {:typography-ref-file nil
:typography-ref-id nil})
ids))
(mf/use-callback
(mf/deps on-change)
(fn []
(on-change {:typography-ref-file nil
:typography-ref-id nil})))
handle-change-typography
(fn [changes]
(st/emit! (dwl/update-typography (merge typography changes) file-id)))
(mf/use-callback
(mf/deps typography file-id)
(fn [changes]
(st/emit! (dwl/update-typography (merge typography changes) file-id))))
opts #js {:ids ids
:values values
:on-change (fn [attrs]
(run! #(emit-update! % attrs) ids))}]
:on-change on-change}]
[:div.element-set
[:div.element-set-title

View file

@ -6,20 +6,30 @@
(ns app.main.ui.workspace.sidebar.options.menus.typography
(:require
["react-virtualized" :as rvt]
[app.common.exceptions :as ex]
[app.common.data :as d]
[app.common.pages :as cp]
[app.common.text :as txt]
[app.main.data.workspace.texts :as dwt]
[app.main.data.shortcuts :as dsc]
[app.main.data.fonts :as df]
[app.main.data.workspace :as dw]
[app.main.fonts :as fonts]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.components.editable-select :refer [editable-select]]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.common :refer [advanced-options]]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [t]]
[app.util.object :as obj]
[app.util.timers :as tm]
[app.util.keyboard :as kbd]
[app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt]
[app.util.timers :as ts]
[goog.events :as events]
[cuerdas.core :as str]
[rumext.alpha :as mf]))
@ -28,74 +38,279 @@
""
(str value)))
(mf/defc font-select-optgroups
(defn- get-next-font
[{:keys [id] :as current} fonts]
(if (seq fonts)
(let [index (d/index-of-pred fonts #(= (:id %) id))
index (or index -1)
next (ex/ignoring (nth fonts (inc index)))]
(or next (first fonts)))
current))
(defn- get-prev-font
[{:keys [id] :as current} fonts]
(if (seq fonts)
(let [index (d/index-of-pred fonts #(= (:id %) id))
next (ex/ignoring (nth fonts (dec index)))]
(or next (peek fonts)))
current))
(mf/defc font-item
{::mf/wrap [mf/memo]}
[{:keys [locale] :as props}]
[:*
[:optgroup {:label (t locale "workspace.options.text-options.preset")}
(for [font fonts/local-fonts]
[:option {:value (:id font)
:key (:id font)}
(:name font)])]
[:optgroup {:label (t locale "workspace.options.text-options.google")}
(for [font (fonts/resolve-fonts :google)]
[:option {:value (:id font)
:key (:id font)}
(:name font)])]])
[{:keys [font current? on-click style]}]
(let [item-ref (mf/use-ref)
on-click (mf/use-callback (mf/deps font) #(on-click font))]
(mf/use-effect
(mf/deps current?)
(fn []
(when current?
(let [element (mf/ref-val item-ref)]
(when-not (dom/is-in-viewport? element)
(dom/scroll-into-view! element))))))
[:div.font-item {:ref item-ref
:style style
:class (when current? "selected")
:on-click on-click}
[:span.icon (when current? i/tick)]
[:span.label (:name font)]]))
(declare row-renderer)
(defn filter-fonts
[{:keys [term backends]} fonts]
(let [xform (cond-> (map identity)
(seq term)
(comp (filter #(str/includes? (str/lower (:name %)) term)))
(seq backends)
(comp (filter #(contains? backends (:backend %)))))]
(into [] xform fonts)))
(defn- toggle-backend
[backends id]
(if (contains? backends id)
(disj backends id)
(conj backends id)))
(mf/defc font-selector
[{:keys [on-select on-close current-font] :as props}]
(let [selected (mf/use-state current-font)
state (mf/use-state {:term "" :backends #{}})
flist (mf/use-ref)
input (mf/use-ref)
ddown (mf/use-ref)
fonts (mf/use-memo (mf/deps @state) #(filter-fonts @state @fonts/fonts))
select-next
(mf/use-callback
(mf/deps fonts)
(fn [event]
(dom/stop-propagation event)
(dom/prevent-default event)
(swap! selected get-next-font fonts)))
select-prev
(mf/use-callback
(mf/deps fonts)
(fn [event]
(dom/stop-propagation event)
(dom/prevent-default event)
(swap! selected get-prev-font fonts)))
on-key-down
(mf/use-callback
(mf/deps fonts)
(fn [event]
(cond
(kbd/up-arrow? event) (select-prev event)
(kbd/down-arrow? event) (select-next event)
(kbd/esc? event) (on-close)
(kbd/enter? event) (on-close)
:else (dom/focus! (mf/ref-val input)))))
on-filter-change
(mf/use-callback
(mf/deps)
(fn [event]
(let [value (dom/get-target-val event)]
(swap! state assoc :term value))))
on-select-and-close
(mf/use-callback
(mf/deps on-select on-close)
(fn [font]
(on-select font)
(on-close)))
]
(mf/use-effect
(mf/deps fonts)
(fn []
(let [key (events/listen js/document "keydown" on-key-down)]
#(events/unlistenByKey key))))
(mf/use-effect
(mf/deps @selected)
(fn []
(when-let [inst (mf/ref-val flist)]
(when-let [index (:index @selected)]
(.scrollToRow ^js inst index)))))
(mf/use-effect
(mf/deps @selected)
(fn []
(on-select @selected)))
(mf/use-effect
(fn []
(st/emit! (dsc/push-shortcuts :typography {}))
(fn []
(st/emit! (dsc/pop-shortcuts :typography)))))
(mf/use-effect
(fn []
(let [index (d/index-of-pred fonts #(= (:id %) (:id current-font)))
inst (mf/ref-val flist)]
(tm/schedule
#(let [offset (.getOffsetForRow ^js inst #js {:alignment "center" :index index})]
(.scrollToPosition ^js inst offset))))))
[:div.font-selector
[:div.font-selector-dropdown
[:header
[:input {:placeholder "Search font"
:value (:term @state)
:ref input
:spell-check false
:on-change on-filter-change}]
#_[:div.options
{:on-click #(swap! state assoc :show-options true)
:class (when (seq (:backends @state)) "active")}
i/picker-hsv]
#_[:& dropdown {:show (:show-options @state false)
:on-close #(swap! state dissoc :show-options)}
(let [backends (:backends @state)]
[:div.backend-filters.dropdown {:ref ddown}
[:div.backend-filter
{:class (when (backends :custom) "selected")
:on-click #(swap! state update :backends toggle-backend :custom)}
[:div.checkbox-icon i/tick]
[:div.backend-name (tr "labels.custom-fonts")]]
[:div.backend-filter
{:class (when (backends :google) "selected")
:on-click #(swap! state update :backends toggle-backend :google)}
[:div.checkbox-icon i/tick]
[:div.backend-name "Google Fonts"]]])]]
[:hr]
[:div.fonts-list
[:> rvt/AutoSizer {}
(fn [props]
(let [width (obj/get props "width")
height (obj/get props "height")
render #(row-renderer fonts @selected on-select-and-close %)]
(mf/html
[:> rvt/List #js {:height height
:ref flist
:width width
:rowCount (count fonts)
:rowHeight 32
: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")
font (nth fonts index)]
(mf/html
[:& font-item {:key key
:font font
:style style
:on-click on-select
:current? (= (:id font) (:id selected))}])))
(mf/defc font-options
[{:keys [editor ids values locale on-change] :as props}]
(let [{:keys [font-id
font-size
font-variant-id]} values
[{:keys [editor ids values on-change] :as props}]
(let [{:keys [font-id font-size font-variant-id]} values
font-id (or font-id (:font-id txt/default-text-attrs))
font-size (or font-size (:font-size txt/default-text-attrs))
font-id (or font-id (:font-id txt/default-text-attrs))
font-size (or font-size (:font-size txt/default-text-attrs))
font-variant-id (or font-variant-id (:font-variant-id txt/default-text-attrs))
fonts (mf/deref fonts/fontsdb)
font (get fonts font-id)
fonts (mf/deref fonts/fontsdb)
font (get fonts font-id)
open-selector? (mf/use-state false)
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})))
(mf/use-callback
(mf/deps on-change fonts)
(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))))))
(mf/use-callback
(mf/deps fonts change-font)
(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)})))
(mf/use-callback
(mf/deps on-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)})))]
(mf/use-callback
(mf/deps font on-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)}))))
on-font-select
(mf/use-callback
(mf/deps change-font)
(fn [font*]
(when (not= font font*)
(change-font (:id font*)))))
on-font-selector-close
(mf/use-callback
#(reset! open-selector? false))]
[:*
(when @open-selector?
[:& font-selector
{:current-font font
:on-close on-font-selector-close
:on-select on-font-select}])
[: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 {:locale locale}]]]
[:div.input-select.font-option
{:on-click #(reset! open-selector? true)}
(:name font)]]
[:div.row-flex
(let [size-options [8 9 10 11 12 14 18 24 36 48 72]
@ -121,7 +336,7 @@
(mf/defc spacing-options
[{:keys [editor ids values locale on-change] :as props}]
[{:keys [editor ids values on-change] :as props}]
(let [{:keys [line-height
letter-spacing]} values
@ -136,7 +351,7 @@
[:div.spacing-options
[:div.input-icon
[:span.icon-before.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.text-options.line-height")}
{:alt (tr "workspace.options.text-options.line-height")}
i/line-height]
[:input.input-text
{:type "number"
@ -144,12 +359,12 @@
:min "0"
:max "200"
:value (attr->string line-height)
:placeholder (t locale "settings.multiple")
:placeholder (tr "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")}
{:alt (tr "workspace.options.text-options.letter-spacing")}
i/letter-spacing]
[:input.input-text
{:type "number"
@ -157,11 +372,11 @@
:min "0"
:max "200"
:value (attr->string letter-spacing)
:placeholder (t locale "settings.multiple")
:placeholder (tr "settings.multiple")
:on-change #(handle-change % :letter-spacing)}]]]))
(mf/defc text-transform-options
[{:keys [editor ids values locale on-change] :as props}]
[{:keys [editor ids values on-change] :as props}]
(let [{:keys [text-transform]} values
text-transform (or text-transform "none")
@ -171,35 +386,32 @@
(on-change {:text-transform type}))]
[:div.align-icons
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.text-options.none")
{:alt (tr "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")
{:alt (tr "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")
{:alt (tr "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")
{:alt (tr "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
(let [opts #js {:editor editor
:ids ids
:values values
:locale locale
:on-change on-change}]
[:div.element-set-content
[:> font-options opts]
[:div.row-flex
@ -209,8 +421,7 @@
(mf/defc typography-entry
[{:keys [typography read-only? selected? on-click on-change on-detach on-context-menu editting? focus-name? file]}]
(let [locale (mf/deref i18n/locale)
open? (mf/use-state editting?)
(let [open? (mf/use-state editting?)
hover-detach (mf/use-state false)
name-input-ref (mf/use-ref nil)
value (mf/use-state (cp/merge-path-item (:path typography) (:name typography)))
@ -255,7 +466,7 @@
{:style {:font-family (:font-family typography)
:font-weight (:font-weight typography)
:font-style (:font-style typography)}}
(t locale "workspace.assets.typography.sample")]
(tr "workspace.assets.typography.sample")]
[:div.typography-name (:name typography)]]
[:div.element-set-actions
(when on-detach
@ -277,32 +488,32 @@
[:span (:name typography)]]
[:div.row-flex
[:span.label (t locale "workspace.assets.typography.font-id")]
[:span.label (tr "workspace.assets.typography.font-id")]
[:span (:font-id typography)]]
[:div.row-flex
[:span.label (t locale "workspace.assets.typography.font-variant-id")]
[:span.label (tr "workspace.assets.typography.font-variant-id")]
[:span (:font-variant-id typography)]]
[:div.row-flex
[:span.label (t locale "workspace.assets.typography.font-size")]
[:span.label (tr "workspace.assets.typography.font-size")]
[:span (:font-size typography)]]
[:div.row-flex
[:span.label (t locale "workspace.assets.typography.line-height")]
[:span.label (tr "workspace.assets.typography.line-height")]
[:span (:line-height typography)]]
[:div.row-flex
[:span.label (t locale "workspace.assets.typography.letter-spacing")]
[:span.label (tr "workspace.assets.typography.letter-spacing")]
[:span (:letter-spacing typography)]]
[:div.row-flex
[:span.label (t locale "workspace.assets.typography.text-transform")]
[:span.label (tr "workspace.assets.typography.text-transform")]
[:span (:text-transform typography)]]
[:div.go-to-lib-button
{:on-click handle-go-to-edit}
(t locale "workspace.assets.typography.go-to-edit")]]
(tr "workspace.assets.typography.go-to-edit")]]
[:*
[:div.element-set-content

View file

@ -190,7 +190,6 @@
(defn setup-shortcuts
[path-editing? drawing-path?]
(hooks/use-shortcuts ::workspace wsc/shortcuts)
(mf/use-effect
(mf/deps path-editing? drawing-path?)
(fn []