mirror of
https://github.com/penpot/penpot.git
synced 2025-06-11 22:01:38 +02:00
✨ Adds typography to libraries
This commit is contained in:
parent
4a4cff74e8
commit
718a676fa8
22 changed files with 831 additions and 642 deletions
|
@ -15,7 +15,6 @@
|
||||||
(defn- load-query-services
|
(defn- load-query-services
|
||||||
[]
|
[]
|
||||||
(require 'app.services.queries.media)
|
(require 'app.services.queries.media)
|
||||||
(require 'app.services.queries.colors)
|
|
||||||
(require 'app.services.queries.projects)
|
(require 'app.services.queries.projects)
|
||||||
(require 'app.services.queries.files)
|
(require 'app.services.queries.files)
|
||||||
(require 'app.services.queries.profile)
|
(require 'app.services.queries.profile)
|
||||||
|
@ -26,7 +25,6 @@
|
||||||
[]
|
[]
|
||||||
(require 'app.services.mutations.demo)
|
(require 'app.services.mutations.demo)
|
||||||
(require 'app.services.mutations.media)
|
(require 'app.services.mutations.media)
|
||||||
(require 'app.services.mutations.colors)
|
|
||||||
(require 'app.services.mutations.projects)
|
(require 'app.services.mutations.projects)
|
||||||
(require 'app.services.mutations.files)
|
(require 'app.services.mutations.files)
|
||||||
(require 'app.services.mutations.profile)
|
(require 'app.services.mutations.profile)
|
||||||
|
|
|
@ -1,150 +0,0 @@
|
||||||
;; 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.services.mutations.colors
|
|
||||||
(:require
|
|
||||||
[clojure.spec.alpha :as s]
|
|
||||||
[app.common.exceptions :as ex]
|
|
||||||
[app.common.spec :as us]
|
|
||||||
[app.common.uuid :as uuid]
|
|
||||||
[app.config :as cfg]
|
|
||||||
[app.db :as db]
|
|
||||||
[app.services.mutations :as sm]
|
|
||||||
[app.services.queries.teams :as teams]
|
|
||||||
[app.tasks :as tasks]
|
|
||||||
[app.util.time :as dt]))
|
|
||||||
|
|
||||||
;; --- Helpers & Specs
|
|
||||||
|
|
||||||
(s/def ::id ::us/uuid)
|
|
||||||
(s/def ::name ::us/string)
|
|
||||||
(s/def ::profile-id ::us/uuid)
|
|
||||||
(s/def ::team-id ::us/uuid)
|
|
||||||
(s/def ::library-id ::us/uuid)
|
|
||||||
(s/def ::content ::us/string)
|
|
||||||
|
|
||||||
;; --- Mutation: Create Color
|
|
||||||
|
|
||||||
(declare select-file-for-update)
|
|
||||||
(declare create-color)
|
|
||||||
|
|
||||||
(s/def ::create-color
|
|
||||||
(s/keys :req-un [::profile-id ::name ::content ::file-id]
|
|
||||||
:opt-un [::id]))
|
|
||||||
|
|
||||||
(sm/defmutation ::create-color
|
|
||||||
[{:keys [profile-id file-id] :as params}]
|
|
||||||
(db/with-atomic [conn db/pool]
|
|
||||||
(let [file (select-file-for-update conn file-id)]
|
|
||||||
(teams/check-edition-permissions! conn profile-id (:team-id file))
|
|
||||||
(create-color conn params))))
|
|
||||||
|
|
||||||
(def ^:private sql:create-color
|
|
||||||
"insert into color (id, name, file_id, content)
|
|
||||||
values ($1, $2, $3, $4) returning *")
|
|
||||||
|
|
||||||
(defn create-color
|
|
||||||
[conn {:keys [id name file-id content]}]
|
|
||||||
(let [id (or id (uuid/next))]
|
|
||||||
(db/insert! conn :color {:id id
|
|
||||||
:name name
|
|
||||||
:file-id file-id
|
|
||||||
:content content})))
|
|
||||||
|
|
||||||
(def ^:private sql:select-file-for-update
|
|
||||||
"select file.*,
|
|
||||||
project.team_id as team_id
|
|
||||||
from file
|
|
||||||
inner join project on (project.id = file.project_id)
|
|
||||||
where file.id = ?
|
|
||||||
for update of file")
|
|
||||||
|
|
||||||
(defn- select-file-for-update
|
|
||||||
[conn id]
|
|
||||||
(let [row (db/exec-one! conn [sql:select-file-for-update id])]
|
|
||||||
(when-not row
|
|
||||||
(ex/raise :type :not-found))
|
|
||||||
row))
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Mutation: Rename Color
|
|
||||||
|
|
||||||
(declare select-color-for-update)
|
|
||||||
|
|
||||||
(s/def ::rename-color
|
|
||||||
(s/keys :req-un [::id ::profile-id ::name]))
|
|
||||||
|
|
||||||
(sm/defmutation ::rename-color
|
|
||||||
[{:keys [id profile-id name] :as params}]
|
|
||||||
(db/with-atomic [conn db/pool]
|
|
||||||
(let [clr (select-color-for-update conn id)]
|
|
||||||
(teams/check-edition-permissions! conn profile-id (:team-id clr))
|
|
||||||
(db/update! conn :color
|
|
||||||
{:name name}
|
|
||||||
{:id id}))))
|
|
||||||
|
|
||||||
(def ^:private sql:select-color-for-update
|
|
||||||
"select c.*,
|
|
||||||
p.team_id as team_id
|
|
||||||
from color as c
|
|
||||||
inner join file as f on f.id = c.file_id
|
|
||||||
inner join project as p on p.id = f.project_id
|
|
||||||
where c.id = ?
|
|
||||||
for update of c")
|
|
||||||
|
|
||||||
(defn- select-color-for-update
|
|
||||||
[conn id]
|
|
||||||
(let [row (db/exec-one! conn [sql:select-color-for-update id])]
|
|
||||||
(when-not row
|
|
||||||
(ex/raise :type :not-found))
|
|
||||||
row))
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Mutation: Update Color
|
|
||||||
|
|
||||||
(s/def ::update-color
|
|
||||||
(s/keys :req-un [::profile-id ::id ::content]))
|
|
||||||
|
|
||||||
(sm/defmutation ::update-color
|
|
||||||
[{:keys [profile-id id content] :as params}]
|
|
||||||
(db/with-atomic [conn db/pool]
|
|
||||||
(let [clr (select-color-for-update conn id)
|
|
||||||
;; IMPORTANT: if the previous name was equal to the hex content,
|
|
||||||
;; we must rename it in addition to changing the value.
|
|
||||||
new-name (if (= (:name clr) (:content clr))
|
|
||||||
content
|
|
||||||
(:name clr))]
|
|
||||||
(teams/check-edition-permissions! conn profile-id (:team-id clr))
|
|
||||||
(db/update! conn :color
|
|
||||||
{:name new-name
|
|
||||||
:content content}
|
|
||||||
{:id id}))))
|
|
||||||
|
|
||||||
;; --- Delete Color
|
|
||||||
|
|
||||||
(declare delete-color)
|
|
||||||
|
|
||||||
(s/def ::delete-color
|
|
||||||
(s/keys :req-un [::id ::profile-id]))
|
|
||||||
|
|
||||||
(sm/defmutation ::delete-color
|
|
||||||
[{:keys [profile-id id] :as params}]
|
|
||||||
(db/with-atomic [conn db/pool]
|
|
||||||
(let [clr (select-color-for-update conn id)]
|
|
||||||
(teams/check-edition-permissions! conn profile-id (:team-id clr))
|
|
||||||
|
|
||||||
;; Schedule object deletion
|
|
||||||
(tasks/submit! conn {:name "delete-object"
|
|
||||||
:delay cfg/default-deletion-delay
|
|
||||||
:props {:id id :type :color}})
|
|
||||||
|
|
||||||
(db/update! conn :color
|
|
||||||
{:deleted-at (dt/now)}
|
|
||||||
{:id id})
|
|
||||||
nil)))
|
|
|
@ -245,7 +245,8 @@
|
||||||
[change]
|
[change]
|
||||||
(or (#{:add-color :mod-color :del-color
|
(or (#{:add-color :mod-color :del-color
|
||||||
:add-media :mod-media :del-media
|
:add-media :mod-media :del-media
|
||||||
:add-component :mod-component :del-component} (:type change))
|
:add-component :mod-component :del-component
|
||||||
|
:add-typography :mod-typography :del-typography} (:type change))
|
||||||
(and (= (:type change) :mod-obj)
|
(and (= (:type change) :mod-obj)
|
||||||
(some? (:component-id change)))))
|
(some? (:component-id change)))))
|
||||||
|
|
||||||
|
|
|
@ -1,104 +0,0 @@
|
||||||
;; 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) 2019 Andrey Antukh <niwi@niwi.nz>
|
|
||||||
|
|
||||||
(ns app.services.queries.colors
|
|
||||||
(:require
|
|
||||||
[clojure.spec.alpha :as s]
|
|
||||||
[promesa.core :as p]
|
|
||||||
[promesa.exec :as px]
|
|
||||||
[app.common.exceptions :as ex]
|
|
||||||
[app.common.spec :as us]
|
|
||||||
[app.common.uuid :as uuid]
|
|
||||||
[app.db :as db]
|
|
||||||
[app.services.queries :as sq]
|
|
||||||
[app.services.queries.teams :as teams]
|
|
||||||
[app.util.blob :as blob]
|
|
||||||
[app.util.data :as data]))
|
|
||||||
|
|
||||||
;; --- Helpers & Specs
|
|
||||||
|
|
||||||
(s/def ::id ::us/uuid)
|
|
||||||
(s/def ::profile-id ::us/uuid)
|
|
||||||
(s/def ::team-id ::us/uuid)
|
|
||||||
(s/def ::file-id ::us/uuid)
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Query: Colors (by file)
|
|
||||||
|
|
||||||
(declare retrieve-colors)
|
|
||||||
(declare retrieve-file)
|
|
||||||
|
|
||||||
(s/def ::colors
|
|
||||||
(s/keys :req-un [::profile-id ::file-id]))
|
|
||||||
|
|
||||||
(sq/defquery ::colors
|
|
||||||
[{:keys [profile-id file-id] :as params}]
|
|
||||||
(db/with-atomic [conn db/pool]
|
|
||||||
(let [file (retrieve-file conn file-id)]
|
|
||||||
(teams/check-read-permissions! conn profile-id (:team-id file))
|
|
||||||
(retrieve-colors conn file-id))))
|
|
||||||
|
|
||||||
(def ^:private sql:colors
|
|
||||||
"select *
|
|
||||||
from color
|
|
||||||
where color.deleted_at is null
|
|
||||||
and color.file_id = ?
|
|
||||||
order by created_at desc")
|
|
||||||
|
|
||||||
(defn- retrieve-colors
|
|
||||||
[conn file-id]
|
|
||||||
(db/exec! conn [sql:colors file-id]))
|
|
||||||
|
|
||||||
(def ^:private sql:retrieve-file
|
|
||||||
"select file.*,
|
|
||||||
project.team_id as team_id
|
|
||||||
from file
|
|
||||||
inner join project on (project.id = file.project_id)
|
|
||||||
where file.id = ?")
|
|
||||||
|
|
||||||
(defn- retrieve-file
|
|
||||||
[conn id]
|
|
||||||
(let [row (db/exec-one! conn [sql:retrieve-file id])]
|
|
||||||
(when-not row
|
|
||||||
(ex/raise :type :not-found))
|
|
||||||
row))
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Query: Color (by ID)
|
|
||||||
|
|
||||||
(declare retrieve-color)
|
|
||||||
|
|
||||||
(s/def ::id ::us/uuid)
|
|
||||||
(s/def ::color
|
|
||||||
(s/keys :req-un [::profile-id ::id]))
|
|
||||||
|
|
||||||
(sq/defquery ::color
|
|
||||||
[{:keys [profile-id id] :as params}]
|
|
||||||
(db/with-atomic [conn db/pool]
|
|
||||||
(let [color (retrieve-color conn id)]
|
|
||||||
(teams/check-read-permissions! conn profile-id (:team-id color))
|
|
||||||
color)))
|
|
||||||
|
|
||||||
(def ^:private sql:single-color
|
|
||||||
"select color.*,
|
|
||||||
p.team_id as team_id
|
|
||||||
from color as color
|
|
||||||
inner join file as f on (color.file_id = f.id)
|
|
||||||
inner join project as p on (p.id = f.project_id)
|
|
||||||
where color.deleted_at is null
|
|
||||||
and color.id = ?
|
|
||||||
order by created_at desc")
|
|
||||||
|
|
||||||
(defn retrieve-color
|
|
||||||
[conn id]
|
|
||||||
(let [row (db/exec-one! conn [sql:single-color id])]
|
|
||||||
(when-not row
|
|
||||||
(ex/raise :type :not-found))
|
|
||||||
row))
|
|
||||||
|
|
|
@ -299,6 +299,31 @@
|
||||||
(s/def :internal.file/recent-colors
|
(s/def :internal.file/recent-colors
|
||||||
(s/coll-of ::string :kind vector?))
|
(s/coll-of ::string :kind vector?))
|
||||||
|
|
||||||
|
(s/def :internal.typography/id ::id)
|
||||||
|
(s/def :internal.typography/name ::string)
|
||||||
|
(s/def :internal.typography/font-id ::string)
|
||||||
|
(s/def :internal.typography/font-family ::string)
|
||||||
|
(s/def :internal.typography/font-variant-id ::string)
|
||||||
|
(s/def :internal.typography/font-size ::string)
|
||||||
|
(s/def :internal.typography/font-weight ::string)
|
||||||
|
(s/def :internal.typography/font-style ::string)
|
||||||
|
(s/def :internal.typography/line-height ::string)
|
||||||
|
(s/def :internal.typography/letter-spacing ::string)
|
||||||
|
(s/def :internal.typography/text-transform ::string)
|
||||||
|
|
||||||
|
(s/def ::typography
|
||||||
|
(s/keys :req-un [:internal.typography/id
|
||||||
|
:internal.typography/name
|
||||||
|
:internal.typography/font-id
|
||||||
|
:internal.typography/font-family
|
||||||
|
:internal.typography/font-variant-id
|
||||||
|
:internal.typography/font-size
|
||||||
|
:internal.typography/font-weight
|
||||||
|
:internal.typography/font-style
|
||||||
|
:internal.typography/line-height
|
||||||
|
:internal.typography/letter-spacing
|
||||||
|
:internal.typography/text-transform]))
|
||||||
|
|
||||||
(s/def :internal.file/pages
|
(s/def :internal.file/pages
|
||||||
(s/coll-of ::uuid :kind vector?))
|
(s/coll-of ::uuid :kind vector?))
|
||||||
|
|
||||||
|
@ -412,6 +437,17 @@
|
||||||
(defmethod change-spec :del-component [_]
|
(defmethod change-spec :del-component [_]
|
||||||
(s/keys :req-un [::id]))
|
(s/keys :req-un [::id]))
|
||||||
|
|
||||||
|
(s/def :internal.changes.typography/typography ::typography)
|
||||||
|
|
||||||
|
(defmethod change-spec :add-typography [_]
|
||||||
|
(s/keys :req-un [:internal.changes.typography/typography]))
|
||||||
|
|
||||||
|
(defmethod change-spec :mod-typography [_]
|
||||||
|
(s/keys :req-un [:internal.changes.typography/typography]))
|
||||||
|
|
||||||
|
(defmethod change-spec :del-typography [_]
|
||||||
|
(s/keys :req-un [:internal.typography/id]))
|
||||||
|
|
||||||
(s/def ::change (s/multi-spec change-spec :type))
|
(s/def ::change (s/multi-spec change-spec :type))
|
||||||
(s/def ::changes (s/coll-of ::change))
|
(s/def ::changes (s/coll-of ::change))
|
||||||
|
|
||||||
|
@ -803,6 +839,8 @@
|
||||||
(subvec rc 1)
|
(subvec rc 1)
|
||||||
rc)))))
|
rc)))))
|
||||||
|
|
||||||
|
;; -- Media
|
||||||
|
|
||||||
(defmethod process-change :add-media
|
(defmethod process-change :add-media
|
||||||
[data {:keys [object]}]
|
[data {:keys [object]}]
|
||||||
(update data :media assoc (:id object) object))
|
(update data :media assoc (:id object) object))
|
||||||
|
@ -815,6 +853,8 @@
|
||||||
[data {:keys [id]}]
|
[data {:keys [id]}]
|
||||||
(update data :media dissoc id))
|
(update data :media dissoc id))
|
||||||
|
|
||||||
|
;; -- Components
|
||||||
|
|
||||||
(defmethod process-change :add-component
|
(defmethod process-change :add-component
|
||||||
[data {:keys [id name shapes]}]
|
[data {:keys [id name shapes]}]
|
||||||
(assoc-in data [:components id]
|
(assoc-in data [:components id]
|
||||||
|
@ -833,6 +873,22 @@
|
||||||
[data {:keys [id]}]
|
[data {:keys [id]}]
|
||||||
(d/dissoc-in data [:components id]))
|
(d/dissoc-in data [:components id]))
|
||||||
|
|
||||||
|
;; -- Typography
|
||||||
|
|
||||||
|
(defmethod process-change :add-typography
|
||||||
|
[data {:keys [typography]}]
|
||||||
|
(update data :typography assoc (:id typography) typography))
|
||||||
|
|
||||||
|
(defmethod process-change :mod-typography
|
||||||
|
[data {:keys [typography]}]
|
||||||
|
(d/update-in-when data [:typography (:id typography)] merge typography))
|
||||||
|
|
||||||
|
(defmethod process-change :del-typography
|
||||||
|
[data {:keys [id]}]
|
||||||
|
(update data :typography dissoc id))
|
||||||
|
|
||||||
|
;; -- Operations
|
||||||
|
|
||||||
(defmethod process-operation :set
|
(defmethod process-operation :set
|
||||||
[shape op]
|
[shape op]
|
||||||
(let [attr (:attr op)
|
(let [attr (:attr op)
|
||||||
|
|
7
frontend/resources/images/icons/unchain.svg
Normal file
7
frontend/resources/images/icons/unchain.svg
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<svg width="40" height="41" viewBox="0 0 40 41" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M27.3455 0.855913C24.5854 1.57398 22.3027 3.61844 21.0431 6.14402C20.1365 7.69681 19.033 9.20989 18.595 10.9747C18.5791 12.5077 20.6042 13.6713 21.8504 12.6729C22.6753 11.9726 23.1234 10.9544 23.7106 10.0663C24.635 8.50138 25.4362 6.73624 26.9321 5.62399C29.1019 4.25506 32.2456 4.42792 34.0446 6.34338C35.8577 8.1232 36.2905 11.1996 34.8418 13.3314C32.9321 16.6169 31.1617 19.9943 29.0399 23.1496C27.4127 25.0133 24.4999 25.5226 22.3148 24.3806C21.3889 23.9825 20.1292 23.8473 19.4164 24.7113C18.5786 25.6499 18.7897 27.3327 19.9352 27.9313C21.5038 28.8608 23.3602 29.3035 25.1804 29.2411C28.4779 29.143 31.7684 27.3471 33.3539 24.3955C35.2416 21.2163 37.1745 18.059 38.8823 14.7782C40.1672 12.4492 40.2813 9.54151 39.3961 7.06543C38.2811 3.73956 35.2239 1.14689 31.7426 0.612769C30.2794 0.366248 28.7587 0.444615 27.3455 0.855913Z"/>
|
||||||
|
<path d="M21.5425 15.5518C18.5342 14.718 15.2111 15.4777 12.7177 17.3188C9.61691 19.2557 6.23319 20.7461 3.34262 23.0045C0.406478 25.6204 -0.667 30.0993 0.749192 33.7793C2.05062 37.3431 5.55324 39.9812 9.32072 40.1837C11.3238 40.3507 13.3742 39.8349 15.0901 38.8156C16.7842 37.9099 18.4823 36.9731 20.0268 35.832C21.0495 34.7451 20.3594 32.7262 18.9072 32.4378C17.9352 32.2308 17.0769 32.9029 16.2329 33.269C14.3839 34.2493 12.6424 35.605 10.5346 35.969C7.95596 36.1495 5.28979 34.4567 4.60879 31.9141C3.8766 29.5283 4.92467 26.6732 7.15855 25.4846C10.4996 23.5458 13.7869 21.5028 17.2426 19.7703C19.6534 18.9028 22.5372 20.0004 23.8578 22.1732C24.4664 22.9945 25.6092 23.6365 26.6126 23.1317C27.7622 22.6301 28.2785 21.0176 27.4862 19.9962C26.1927 17.801 23.9992 16.1919 21.5425 15.5518Z"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.06066 4.93934C5.64645 4.35355 6.59619 4.35355 7.18198 4.93934L11.0607 8.81802C11.6464 9.40381 11.6464 10.3536 11.0607 10.9393C10.4749 11.5251 9.52513 11.5251 8.93934 10.9393L5.06066 7.06066C4.47487 6.47487 4.47487 5.52513 5.06066 4.93934Z" fill="black"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.5 0C14.3284 3.62117e-08 15 0.671573 15 1.5V6.98528C15 7.81371 14.3284 8.48528 13.5 8.48528C12.6716 8.48528 12 7.81371 12 6.98528V1.5C12 0.671573 12.6716 -3.62117e-08 13.5 0Z"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 13.5C0 12.6716 0.671573 12 1.5 12H6.98528C7.81371 12 8.48528 12.6716 8.48528 13.5C8.48528 14.3284 7.81371 15 6.98528 15H1.5C0.671573 15 0 14.3284 0 13.5Z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
|
@ -2801,5 +2801,8 @@
|
||||||
"ru" : "Кликни чтобы закончить фигуру",
|
"ru" : "Кликни чтобы закончить фигуру",
|
||||||
"es" : "Pulsar para cerrar la ruta"
|
"es" : "Pulsar para cerrar la ruta"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
"workspace.assets.typography": "Typographies",
|
||||||
|
"workspace.libraries.typography": "%s typographies"
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,8 +69,8 @@
|
||||||
font-size: $fs13;
|
font-size: $fs13;
|
||||||
padding: $small $x-small;
|
padding: $small $x-small;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.element-list {
|
.element-list {
|
||||||
|
@ -768,7 +768,7 @@
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.element-set-content .advanced-options {
|
.advanced-options {
|
||||||
background-color: #303236;
|
background-color: #303236;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
left: -8px;
|
left: -8px;
|
||||||
|
@ -876,3 +876,119 @@
|
||||||
.element-set-options-group:hover .element-set-actions {
|
.element-set-options-group:hover .element-set-actions {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.typography-entry {
|
||||||
|
margin: 0.5rem 0.3rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.typography-selection-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
&.is-selectable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.typography-sample {
|
||||||
|
font-size: 17px;
|
||||||
|
color: $color-white;
|
||||||
|
margin: 0 0.5rem;
|
||||||
|
|
||||||
|
font-family: sourcesanspro;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typography-name {
|
||||||
|
flex-grow: 1;
|
||||||
|
font-size: 11px;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.element-set-actions-button svg {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.asset-group {
|
||||||
|
.typography-entry {
|
||||||
|
margin: 0.25rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.element-set-content .font-option,
|
||||||
|
.element-set-content .size-option {
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
}
|
||||||
|
.element-set-content .variant-option {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-flex input.adv-typography-name {
|
||||||
|
font-size: 14px;
|
||||||
|
color: $color-gray-10;
|
||||||
|
width: 100%;
|
||||||
|
max-width: none;
|
||||||
|
margin: 0;
|
||||||
|
background: #303236;
|
||||||
|
border-top: none;
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.size-option .custom-select-dropdown {
|
||||||
|
position: fixed;
|
||||||
|
max-height: 15rem;
|
||||||
|
min-width: 6rem;
|
||||||
|
margin-top: 25px;
|
||||||
|
left: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typography-read-only-data {
|
||||||
|
font-size: 12px;
|
||||||
|
color: $color-white;
|
||||||
|
|
||||||
|
.typography-name {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-flex {
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: $color-gray-30;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: ':';
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.go-to-lib-button {
|
||||||
|
transition: border 0.3s, color 0.3s;
|
||||||
|
text-align: center;
|
||||||
|
background: $color-gray-60;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 1rem;
|
||||||
|
border: 1px solid $color-gray-60;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid $color-primary;
|
||||||
|
color: $color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,29 +25,6 @@
|
||||||
[app.main.data.modal :as md]
|
[app.main.data.modal :as md]
|
||||||
[app.common.pages-helpers :as cph]))
|
[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
|
(def clear-color-for-rename
|
||||||
(ptk/reify ::clear-color-for-rename
|
(ptk/reify ::clear-color-for-rename
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
|
@ -73,44 +50,6 @@
|
||||||
(-> state
|
(-> state
|
||||||
(update-in [:workspace-file :colors] #(d/replace-by-id % color))))))
|
(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]
|
(defn change-palette-size [size]
|
||||||
(s/assert #{:big :small} size)
|
(s/assert #{:big :small} size)
|
||||||
(ptk/reify ::change-palette-size
|
(ptk/reify ::change-palette-size
|
||||||
|
|
|
@ -73,9 +73,10 @@
|
||||||
(s/def ::layout-flags (s/coll-of ::layout-flag))
|
(s/def ::layout-flags (s/coll-of ::layout-flag))
|
||||||
|
|
||||||
(def default-layout
|
(def default-layout
|
||||||
#{:sitemap
|
#{;; :sitemap
|
||||||
:sitemap-pages
|
;; :sitemap-pages
|
||||||
:layers
|
;; :layers
|
||||||
|
:assets
|
||||||
:element-options
|
:element-options
|
||||||
:rules
|
:rules
|
||||||
:display-grid
|
:display-grid
|
||||||
|
|
|
@ -519,3 +519,56 @@
|
||||||
:callback do-dismiss}]
|
:callback do-dismiss}]
|
||||||
:sync-dialog))))))
|
: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/mapcat
|
||||||
#(rx/zip (rp/query :file-library {:file-id library-id})
|
#(rx/zip (rp/query :file-library {:file-id library-id})
|
||||||
(rp/query :media-objects {:file-id library-id
|
(rp/query :media-objects {:file-id library-id
|
||||||
:is-local false})
|
:is-local false}))))
|
||||||
(rp/query :colors {:file-id library-id}))))
|
|
||||||
(rx/map file-linked))))))
|
(rx/map file-linked))))))
|
||||||
|
|
||||||
(defn file-linked
|
(defn file-linked
|
||||||
|
|
|
@ -96,6 +96,9 @@
|
||||||
(register! :builtin local-fonts)
|
(register! :builtin local-fonts)
|
||||||
(register! :google google-fonts)
|
(register! :google google-fonts)
|
||||||
|
|
||||||
|
(defn get-font-data [id]
|
||||||
|
(get @fontsdb id))
|
||||||
|
|
||||||
(defn resolve-variants
|
(defn resolve-variants
|
||||||
[id]
|
[id]
|
||||||
(get-in @fontsdb [id :variants]))
|
(get-in @fontsdb [id :variants]))
|
||||||
|
@ -164,3 +167,8 @@
|
||||||
(defn ready [cb]
|
(defn ready [cb]
|
||||||
(-> (obj/get-in js/document ["fonts" "ready"])
|
(-> (obj/get-in js/document ["fonts" "ready"])
|
||||||
(p/then cb)))
|
(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] []))
|
(get-in state [:workspace-data :recent-colors] []))
|
||||||
st/state))
|
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
|
(def workspace-project
|
||||||
(l/derived :workspace-project st/state))
|
(l/derived :workspace-project st/state))
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
(def auto-width (icon-xref :auto-width))
|
(def auto-width (icon-xref :auto-width))
|
||||||
(def box (icon-xref :box))
|
(def box (icon-xref :box))
|
||||||
(def chain (icon-xref :chain))
|
(def chain (icon-xref :chain))
|
||||||
|
(def unchain (icon-xref :unchain))
|
||||||
(def chat (icon-xref :chat))
|
(def chat (icon-xref :chat))
|
||||||
(def circle (icon-xref :circle))
|
(def circle (icon-xref :circle))
|
||||||
(def close (icon-xref :close))
|
(def close (icon-xref :close))
|
||||||
|
|
|
@ -27,7 +27,8 @@
|
||||||
[library]
|
[library]
|
||||||
(let [components-count (count (get-in library [:data :components] []))
|
(let [components-count (count (get-in library [:data :components] []))
|
||||||
graphics-count (count (get-in library [:data :media] []))
|
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
|
;; Include a so this block has always some content
|
||||||
(str
|
(str
|
||||||
(str/join " · "
|
(str/join " · "
|
||||||
|
@ -39,7 +40,10 @@
|
||||||
(conj (tr "workspace.libraries.graphics" graphics-count))
|
(conj (tr "workspace.libraries.graphics" graphics-count))
|
||||||
|
|
||||||
(< 0 colors-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")))
|
"\u00A0")))
|
||||||
|
|
||||||
(mf/defc libraries-tab
|
(mf/defc libraries-tab
|
||||||
|
|
|
@ -289,12 +289,15 @@
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
|
|
||||||
|
|
||||||
(let [sidebar (dom/get-element "settings-bar")
|
(let [sidebar (dom/get-element "settings-bar")
|
||||||
|
assets (dom/get-element-by-class "assets-bar")
|
||||||
cpicker (dom/get-element-by-class "colorpicker-tooltip")
|
cpicker (dom/get-element-by-class "colorpicker-tooltip")
|
||||||
self (mf/ref-val self-ref)
|
self (mf/ref-val self-ref)
|
||||||
target (dom/get-target event)
|
target (dom/get-target event)
|
||||||
selecting? (mf/ref-val selecting-ref)]
|
selecting? (mf/ref-val selecting-ref)]
|
||||||
(when-not (or (.contains sidebar target)
|
(when-not (or (.contains sidebar target)
|
||||||
|
(.contains assets target)
|
||||||
(.contains self target)
|
(.contains self target)
|
||||||
(and cpicker (.contains cpicker target)))
|
(and cpicker (.contains cpicker target)))
|
||||||
(if selecting?
|
(if selecting?
|
||||||
|
@ -340,7 +343,8 @@
|
||||||
(when (not read-only?)
|
(when (not read-only?)
|
||||||
(let [content (js->clj val :keywordize-keys true)
|
(let [content (js->clj val :keywordize-keys true)
|
||||||
content (first content)]
|
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! state val)
|
||||||
(reset! content-var content)))))]
|
(reset! content-var content)))))]
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
[app.config :as cfg]
|
[app.config :as cfg]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.libraries :as dwl]
|
[app.main.data.workspace.libraries :as dwl]
|
||||||
|
[app.main.data.workspace.texts :as dwt]
|
||||||
[app.main.data.colors :as dc]
|
[app.main.data.colors :as dc]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
[app.main.ui.components.context-menu :refer [context-menu]]
|
[app.main.ui.components.context-menu :refer [context-menu]]
|
||||||
[app.main.ui.components.file-uploader :refer [file-uploader]]
|
[app.main.ui.components.file-uploader :refer [file-uploader]]
|
||||||
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
|
[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.icons :as i]
|
||||||
[app.main.ui.keyboard :as kbd]
|
[app.main.ui.keyboard :as kbd]
|
||||||
[app.main.ui.modal :as modal]
|
[app.main.ui.modal :as modal]
|
||||||
|
@ -41,7 +43,7 @@
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
(mf/defc components-box
|
(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
|
(let [state (mf/use-state {:menu-open false
|
||||||
:top nil
|
:top nil
|
||||||
:left nil
|
:left nil
|
||||||
|
@ -75,27 +77,28 @@
|
||||||
(dnd/set-allowed-effect! event "move")))]
|
(dnd/set-allowed-effect! event "move")))]
|
||||||
|
|
||||||
[:div.asset-group
|
[:div.asset-group
|
||||||
[:div.group-title
|
[:div.group-title {:class (when (not open?) "closed")}
|
||||||
(tr "workspace.assets.components")
|
[: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
|
[:span (str "\u00A0(") (count components) ")"]] ;; Unicode 00A0 is non-breaking space
|
||||||
[:div.group-grid.big
|
(when open?
|
||||||
(for [component components]
|
[:div.group-grid.big
|
||||||
[:div.grid-cell {:key (:id component)
|
(for [component components]
|
||||||
:draggable true
|
[:div.grid-cell {:key (:id component)
|
||||||
:on-context-menu (on-context-menu (:id component))
|
:draggable true
|
||||||
:on-drag-start (partial on-drag-start component)}
|
:on-context-menu (on-context-menu (:id component))
|
||||||
[:& exports/component-svg {:group (get-in component [:objects (:id component)])
|
:on-drag-start (partial on-drag-start component)}
|
||||||
:objects (:objects component)}]
|
[:& exports/component-svg {:group (get-in component [:objects (:id component)])
|
||||||
[:div.cell-name (:name component)]])
|
:objects (:objects component)}]
|
||||||
|
[:div.cell-name (:name component)]])])
|
||||||
|
|
||||||
(when local?
|
(when local?
|
||||||
[:& context-menu
|
[:& context-menu
|
||||||
{:selectable false
|
{:selectable false
|
||||||
:show (:menu-open @state)
|
:show (:menu-open @state)
|
||||||
:on-close #(swap! state assoc :menu-open false)
|
:on-close #(swap! state assoc :menu-open false)
|
||||||
:top (:top @state)
|
:top (:top @state)
|
||||||
:left (:left @state)
|
:left (:left @state)
|
||||||
:options [[(tr "workspace.assets.delete") on-delete]]}])]]))
|
:options [[(tr "workspace.assets.delete") on-delete]]}])]))
|
||||||
|
|
||||||
(mf/defc graphics-box
|
(mf/defc graphics-box
|
||||||
[{:keys [file-id local? objects open? on-open on-close] :as props}]
|
[{:keys [file-id local? objects open? on-open on-close] :as props}]
|
||||||
|
@ -326,6 +329,88 @@
|
||||||
:local? local?
|
:local? local?
|
||||||
:locale locale}])])]))
|
: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
|
(defn file-colors-ref
|
||||||
[id]
|
[id]
|
||||||
(l/derived (fn [state]
|
(l/derived (fn [state]
|
||||||
|
@ -354,6 +439,15 @@
|
||||||
(vals (get-in state [:workspace-libraries id :data :components])))))
|
(vals (get-in state [:workspace-libraries id :data :components])))))
|
||||||
st/state =))
|
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
|
(defn apply-filters
|
||||||
[coll filters]
|
[coll filters]
|
||||||
(->> coll
|
(->> coll
|
||||||
|
@ -369,7 +463,10 @@
|
||||||
router (mf/deref refs/router)
|
router (mf/deref refs/router)
|
||||||
toggle-open #(swap! open? not)
|
toggle-open #(swap! open? not)
|
||||||
|
|
||||||
toggles (mf/use-state #{:graphics :colors})
|
toggles (mf/use-state #{:components
|
||||||
|
:graphics
|
||||||
|
:colors
|
||||||
|
:typography})
|
||||||
|
|
||||||
url (rt/resolve router :workspace
|
url (rt/resolve router :workspace
|
||||||
{:project-id (:project-id file)
|
{:project-id (:project-id file)
|
||||||
|
@ -379,6 +476,9 @@
|
||||||
colors-ref (mf/use-memo (mf/deps (:id file)) #(file-colors-ref (:id file)))
|
colors-ref (mf/use-memo (mf/deps (:id file)) #(file-colors-ref (:id file)))
|
||||||
colors (apply-filters (mf/deref colors-ref) filters)
|
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-ref (mf/use-memo (mf/deps (:id file)) #(file-media-ref (:id file)))
|
||||||
media (apply-filters (mf/deref media-ref) filters)
|
media (apply-filters (mf/deref media-ref) filters)
|
||||||
|
|
||||||
|
@ -413,13 +513,20 @@
|
||||||
(str/empty? (:term filters))))
|
(str/empty? (:term filters))))
|
||||||
show-colors? (and (or (= (:box filters) :all)
|
show-colors? (and (or (= (:box filters) :all)
|
||||||
(= (:box filters) :colors))
|
(= (: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)
|
(or (> (count colors) 0)
|
||||||
(str/empty? (:term filters))))]
|
(str/empty? (:term filters))))]
|
||||||
[:div.tool-window-content
|
[:div.tool-window-content
|
||||||
(when show-components?
|
(when show-components?
|
||||||
[:& components-box {:file-id (:id file)
|
[:& components-box {:file-id (:id file)
|
||||||
:local? local?
|
: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?
|
(when show-graphics?
|
||||||
[:& graphics-box {:file-id (:id file)
|
[:& graphics-box {:file-id (:id file)
|
||||||
:local? local?
|
:local? local?
|
||||||
|
@ -436,6 +543,15 @@
|
||||||
:on-open #(swap! toggles conj :colors)
|
:on-open #(swap! toggles conj :colors)
|
||||||
:on-close #(swap! toggles disj :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?))
|
(when (and (not show-components?) (not show-graphics?) (not show-colors?))
|
||||||
[:div.asset-group
|
[:div.asset-group
|
||||||
[:div.group-title (t locale "workspace.assets.not-found")]])]))]))
|
[:div.group-title (t locale "workspace.assets.not-found")]])]))]))
|
||||||
|
@ -495,8 +611,10 @@
|
||||||
[:select.input-select {:value (:box @filters)
|
[:select.input-select {:value (:box @filters)
|
||||||
:on-change on-box-filter-change}
|
:on-change on-box-filter-change}
|
||||||
[:option {:value ":all"} (t locale "workspace.assets.box-filter-all")]
|
[:option {:value ":all"} (t locale "workspace.assets.box-filter-all")]
|
||||||
[:option {:value ":graphics"} (t locale "workspace.assets.box-filter-graphics")]
|
[:option {:value ":components"} (t locale "workspace.assets.components")]
|
||||||
[:option {:value ":colors"} (t locale "workspace.assets.box-filter-colors")]]]]
|
[: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
|
[:div.libraries-wrapper
|
||||||
[:& file-library
|
[:& file-library
|
||||||
|
|
|
@ -144,11 +144,11 @@
|
||||||
[:& text-menu {:ids text-ids
|
[:& text-menu {:ids text-ids
|
||||||
:type :multiple
|
:type :multiple
|
||||||
:editor nil
|
:editor nil
|
||||||
:font-values font-values
|
:values (merge font-values
|
||||||
:align-values align-values
|
align-values
|
||||||
:spacing-values spacing-values
|
spacing-values
|
||||||
:valign-values valign-values
|
valign-values
|
||||||
:decoration-values decoration-values
|
decoration-values
|
||||||
:transform-values transform-values
|
transform-values)
|
||||||
:shapes shapes}])]))
|
:shapes shapes}])]))
|
||||||
|
|
||||||
|
|
|
@ -14,20 +14,23 @@
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.common :as dwc]
|
[app.main.data.workspace.common :as dwc]
|
||||||
[app.main.data.workspace.texts :as dwt]
|
[app.main.data.workspace.texts :as dwt]
|
||||||
|
[app.main.data.workspace.libraries :as dwl]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]]
|
[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.fill :refer [fill-menu]]
|
||||||
[app.main.ui.workspace.sidebar.options.shadow :refer [shadow-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.util.dom :as dom]
|
||||||
[app.main.fonts :as fonts]
|
[app.main.fonts :as fonts]
|
||||||
[app.util.i18n :as i18n :refer [tr t]]
|
[app.util.i18n :as i18n :refer [tr t]]
|
||||||
["slate" :refer [Transforms]]))
|
["slate" :refer [Transforms]]))
|
||||||
|
|
||||||
|
(def text-typography-attrs [:typography-ref-id :typography-ref-file])
|
||||||
(def text-fill-attrs [:fill :opacity])
|
(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-font-attrs [:font-id :font-family :font-variant-id :font-size :font-weight :font-style])
|
||||||
(def text-align-attrs [:text-align])
|
(def text-align-attrs [:text-align])
|
||||||
|
@ -36,205 +39,52 @@
|
||||||
(def text-decoration-attrs [:text-decoration])
|
(def text-decoration-attrs [:text-decoration])
|
||||||
(def text-transform-attrs [:text-transform])
|
(def text-transform-attrs [:text-transform])
|
||||||
|
|
||||||
(defn- attr->string [value]
|
(def root-attrs (d/concat text-valign-attrs
|
||||||
(if (= value :multiple)
|
text-align-attrs))
|
||||||
""
|
(def paragraph-attrs text-align-attrs)
|
||||||
(str value)))
|
(def text-attrs (d/concat text-typography-attrs
|
||||||
|
text-font-attrs
|
||||||
(def ^:private editor-ref
|
text-align-attrs
|
||||||
(l/derived :editor refs/workspace-local))
|
text-spacing-attrs
|
||||||
|
text-decoration-attrs
|
||||||
(mf/defc font-select-optgroups
|
text-transform-attrs))
|
||||||
{::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)])]]]))
|
|
||||||
|
|
||||||
|
|
||||||
(mf/defc text-align-options
|
(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
|
(let [{:keys [text-align]} values
|
||||||
|
|
||||||
text-align (or text-align "left")
|
text-align (or text-align "left")
|
||||||
|
|
||||||
on-change
|
handle-change
|
||||||
(fn [event new-align]
|
(fn [event new-align]
|
||||||
(run! #(st/emit!
|
(on-change {:text-align new-align}))]
|
||||||
(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))]
|
|
||||||
|
|
||||||
;; --- Align
|
;; --- Align
|
||||||
[:div.row-flex.align-icons
|
[:div.row-flex.align-icons
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt (t locale "workspace.options.text-options.align-left")
|
{:alt (t locale "workspace.options.text-options.align-left")
|
||||||
:class (dom/classnames :current (= "left" text-align))
|
:class (dom/classnames :current (= "left" text-align))
|
||||||
:on-click #(on-change % "left")}
|
:on-click #(handle-change % "left")}
|
||||||
i/text-align-left]
|
i/text-align-left]
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt (t locale "workspace.options.text-options.align-center")
|
{:alt (t locale "workspace.options.text-options.align-center")
|
||||||
:class (dom/classnames :current (= "center" text-align))
|
:class (dom/classnames :current (= "center" text-align))
|
||||||
:on-click #(on-change % "center")}
|
:on-click #(handle-change % "center")}
|
||||||
i/text-align-center]
|
i/text-align-center]
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt (t locale "workspace.options.text-options.align-right")
|
{:alt (t locale "workspace.options.text-options.align-right")
|
||||||
:class (dom/classnames :current (= "right" text-align))
|
:class (dom/classnames :current (= "right" text-align))
|
||||||
:on-click #(on-change % "right")}
|
:on-click #(handle-change % "right")}
|
||||||
i/text-align-right]
|
i/text-align-right]
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt (t locale "workspace.options.text-options.align-justify")
|
{:alt (t locale "workspace.options.text-options.align-justify")
|
||||||
:class (dom/classnames :current (= "justify" text-align))
|
:class (dom/classnames :current (= "justify" text-align))
|
||||||
:on-click #(on-change % "justify")}
|
:on-click #(handle-change % "justify")}
|
||||||
i/text-align-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
|
(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
|
(let [{:keys [vertical-align]} values
|
||||||
|
|
||||||
to-single-value (fn [coll] (if (> (count coll) 1) nil (first coll)))
|
to-single-value (fn [coll] (if (> (count coll) 1) nil (first coll)))
|
||||||
|
@ -243,150 +93,171 @@
|
||||||
|
|
||||||
vertical-align (or vertical-align "top")
|
vertical-align (or vertical-align "top")
|
||||||
|
|
||||||
on-change-grow
|
handle-change-grow
|
||||||
(fn [event grow-type]
|
(fn [event grow-type]
|
||||||
(st/emit! (dwc/update-shapes ids #(assoc % :grow-type grow-type))))
|
(st/emit! (dwc/update-shapes ids #(assoc % :grow-type grow-type))))
|
||||||
|
|
||||||
on-change
|
handle-change
|
||||||
(fn [event new-align]
|
(fn [event new-align]
|
||||||
(run! #(st/emit! (dwt/update-root-attrs
|
(on-change {:vertical-align new-align}))]
|
||||||
{:id %
|
|
||||||
:editor editor
|
|
||||||
:attrs {:vertical-align new-align}}))
|
|
||||||
ids))]
|
|
||||||
|
|
||||||
[:div.row-flex
|
[:div.row-flex
|
||||||
[:div.align-icons
|
[:div.align-icons
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt (t locale "workspace.options.text-options.align-top")
|
{:alt (t locale "workspace.options.text-options.align-top")
|
||||||
:class (dom/classnames :current (= "top" vertical-align))
|
:class (dom/classnames :current (= "top" vertical-align))
|
||||||
:on-click #(on-change % "top")}
|
:on-click #(handle-change % "top")}
|
||||||
i/align-top]
|
i/align-top]
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt (t locale "workspace.options.text-options.align-middle")
|
{:alt (t locale "workspace.options.text-options.align-middle")
|
||||||
:class (dom/classnames :current (= "center" vertical-align))
|
:class (dom/classnames :current (= "center" vertical-align))
|
||||||
:on-click #(on-change % "center")}
|
:on-click #(handle-change % "center")}
|
||||||
i/align-middle]
|
i/align-middle]
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt (t locale "workspace.options.text-options.align-bottom")
|
{:alt (t locale "workspace.options.text-options.align-bottom")
|
||||||
:class (dom/classnames :current (= "bottom" vertical-align))
|
:class (dom/classnames :current (= "bottom" vertical-align))
|
||||||
:on-click #(on-change % "bottom")}
|
:on-click #(handle-change % "bottom")}
|
||||||
i/align-bottom]]
|
i/align-bottom]]
|
||||||
|
|
||||||
[:div.align-icons
|
[:div.align-icons
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt (t locale "workspace.options.text-options.grow-fixed")
|
{:alt (t locale "workspace.options.text-options.grow-fixed")
|
||||||
:class (dom/classnames :current (= :fixed grow-type))
|
:class (dom/classnames :current (= :fixed grow-type))
|
||||||
:on-click #(on-change-grow % :fixed)}
|
:on-click #(handle-change-grow % :fixed)}
|
||||||
i/auto-fix]
|
i/auto-fix]
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt (t locale "workspace.options.text-options.grow-auto-width")
|
{:alt (t locale "workspace.options.text-options.grow-auto-width")
|
||||||
:class (dom/classnames :current (= :auto-width grow-type))
|
: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]
|
i/auto-width]
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt (t locale "workspace.options.text-options.grow-auto-height")
|
{:alt (t locale "workspace.options.text-options.grow-auto-height")
|
||||||
:class (dom/classnames :current (= :auto-height grow-type))
|
: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]]]))
|
i/auto-height]]]))
|
||||||
|
|
||||||
(mf/defc text-decoration-options
|
(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
|
(let [{:keys [text-decoration]} values
|
||||||
|
|
||||||
text-decoration (or text-decoration "none")
|
text-decoration (or text-decoration "none")
|
||||||
|
|
||||||
on-change
|
handle-change
|
||||||
(fn [event type]
|
(fn [event type]
|
||||||
(run! #(st/emit! (dwt/update-text-attrs
|
(on-change {:text-decoration type}))]
|
||||||
{:id %
|
|
||||||
:editor editor
|
|
||||||
:attrs {:text-decoration type}}))
|
|
||||||
ids))]
|
|
||||||
[:div.row-flex
|
[:div.row-flex
|
||||||
[:span.element-set-subtitle (t locale "workspace.options.text-options.decoration")]
|
[:span.element-set-subtitle (t locale "workspace.options.text-options.decoration")]
|
||||||
[:div.align-icons
|
[:div.align-icons
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt (t locale "workspace.options.text-options.none")
|
{:alt (t locale "workspace.options.text-options.none")
|
||||||
:class (dom/classnames :current (= "none" text-decoration))
|
:class (dom/classnames :current (= "none" text-decoration))
|
||||||
:on-click #(on-change % "none")}
|
:on-click #(handle-change % "none")}
|
||||||
i/minus]
|
i/minus]
|
||||||
|
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt (t locale "workspace.options.text-options.underline")
|
{:alt (t locale "workspace.options.text-options.underline")
|
||||||
:class (dom/classnames :current (= "underline" text-decoration))
|
:class (dom/classnames :current (= "underline" text-decoration))
|
||||||
:on-click #(on-change % "underline")}
|
:on-click #(handle-change % "underline")}
|
||||||
i/underline]
|
i/underline]
|
||||||
|
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt (t locale "workspace.options.text-options.strikethrough")
|
{:alt (t locale "workspace.options.text-options.strikethrough")
|
||||||
:class (dom/classnames :current (= "line-through" text-decoration))
|
:class (dom/classnames :current (= "line-through" text-decoration))
|
||||||
:on-click #(on-change % "line-through")}
|
:on-click #(handle-change % "line-through")}
|
||||||
i/strikethrough]]]))
|
i/strikethrough]]]))
|
||||||
|
|
||||||
(mf/defc text-transform-options
|
(defn generate-typography-name [{:keys [font-id font-variant-id] :as typography}]
|
||||||
[{:keys [editor ids values locale] :as props}]
|
(let [{:keys [name]} (fonts/get-font-data font-id)]
|
||||||
(let [{:keys [text-transform]} values
|
(-> typography
|
||||||
|
(assoc :name (str name " " (str/title font-variant-id))))) )
|
||||||
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]]]))
|
|
||||||
|
|
||||||
(mf/defc text-menu
|
(mf/defc text-menu
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [ids
|
[{:keys [ids
|
||||||
type
|
type
|
||||||
editor
|
editor
|
||||||
font-values
|
values
|
||||||
align-values
|
|
||||||
spacing-values
|
|
||||||
valign-values
|
|
||||||
decoration-values
|
|
||||||
transform-values
|
|
||||||
shapes] :as props}]
|
shapes] :as props}]
|
||||||
(let [locale (mf/deref i18n/locale)
|
(let [locale (mf/deref i18n/locale)
|
||||||
|
typographies (mf/deref refs/workspace-file-typography)
|
||||||
|
shared-libs (mf/deref refs/workspace-libraries)
|
||||||
label (case type
|
label (case type
|
||||||
:multiple (t locale "workspace.options.text-options.title-selection")
|
:multiple (t locale "workspace.options.text-options.title-selection")
|
||||||
:group (t locale "workspace.options.text-options.title-group")
|
:group (t locale "workspace.options.text-options.title-group")
|
||||||
(t locale "workspace.options.text-options.title"))]
|
(t locale "workspace.options.text-options.title"))
|
||||||
[:div.element-set
|
|
||||||
[:div.element-set-title label]
|
emit-update!
|
||||||
[:div.element-set-content
|
(fn [id attrs]
|
||||||
[:& font-options {:editor editor :ids ids :values font-values :locale locale}]
|
(let [attrs (select-keys attrs root-attrs)]
|
||||||
[:& text-align-options {:editor editor :ids ids :values align-values :locale locale}]
|
(when-not (empty? attrs)
|
||||||
[:& spacing-options {:editor editor :ids ids :values spacing-values :locale locale}]
|
(st/emit! (dwt/update-root-attrs {:id id :editor editor :attrs attrs}))))
|
||||||
[:& 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}]
|
(let [attrs (select-keys attrs paragraph-attrs)]
|
||||||
[:& text-transform-options {:editor editor :ids ids :values transform-values :locale locale}]]]))
|
(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
|
(mf/defc options
|
||||||
[{:keys [shape] :as props}]
|
[{:keys [shape] :as props}]
|
||||||
|
@ -399,42 +270,25 @@
|
||||||
measure-values (select-keys shape measure-attrs)
|
measure-values (select-keys shape measure-attrs)
|
||||||
|
|
||||||
fill-values (dwt/current-text-values
|
fill-values (dwt/current-text-values
|
||||||
{:editor editor
|
{:editor editor
|
||||||
:shape shape
|
:shape shape
|
||||||
:attrs text-fill-attrs})
|
:attrs text-fill-attrs})
|
||||||
|
|
||||||
converted-fill-values {:fill-color (:fill fill-values)
|
converted-fill-values {:fill-color (:fill fill-values)
|
||||||
:fill-opacity (:opacity 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
|
text-values (merge
|
||||||
{:editor editor
|
(dwt/current-root-values
|
||||||
:shape shape
|
{:editor editor :shape shape
|
||||||
:attrs text-align-attrs})
|
: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
|
[:& measures-menu {:ids ids
|
||||||
:type type
|
:type type
|
||||||
|
@ -448,11 +302,5 @@
|
||||||
:values (select-keys shape [:shadow])}]
|
:values (select-keys shape [:shadow])}]
|
||||||
[:& text-menu {:ids ids
|
[:& text-menu {:ids ids
|
||||||
:type type
|
:type type
|
||||||
:editor editor
|
:values text-values
|
||||||
:font-values font-values
|
|
||||||
:align-values align-values
|
|
||||||
:spacing-values spacing-values
|
|
||||||
:valign-values valign-values
|
|
||||||
:decoration-values decoration-values
|
|
||||||
:transform-values transform-values
|
|
||||||
:shapes [shape]}]]))
|
: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]
|
[node]
|
||||||
(.-value node))
|
(.-value node))
|
||||||
|
|
||||||
|
(def get-target-val (comp get-value get-target))
|
||||||
|
|
||||||
(defn click
|
(defn click
|
||||||
"Click a node"
|
"Click a node"
|
||||||
[node]
|
[node]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue