0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-10 14:51:37 -05:00

🎉 Allow to edit text properties of multiple shapes

This commit is contained in:
Andrés Moya 2020-07-08 10:21:18 +02:00
parent 0951ba95f0
commit 6020cc797d
6 changed files with 471 additions and 252 deletions

View file

@ -856,26 +856,28 @@
:else srect))))
(defn get-attrs-multi
[shapes attrs]
;; Extract some attributes of a list of shapes.
[values attrs]
;; Extract some attributes of a list of shape values.
;; For each attribute, if the value is the same in all shapes,
;; wll take this value. If there is any shape that is different,
;; the value of the attribute will be the keyword :multiple.
;;
;; Example:
;; (def shapes [{:stroke-color "#ff0000'
;; (def values [{:stroke-color "#ff0000'
;; :stroke-width 3
;; :x 1000 :y 2000}
;; {:stroke-width "#ff0000'
;; :stroke-width 5
;; :x 1500 :y 2000}])
;;
;; (get-attrs-multi shapes [:stroke-color :stroke-width :fill-color])
;; (get-attrs-multi values [:stroke-color :stroke-width :fill-color])
;; >>> {:stroke-color "#ff0000'
;; :stroke-width :multiple
;; :fill-color nil}
;;
(let [combine-value #(if (= %1 %2) %1 :multiple)
(let [defined-values (filter some? values)
combine-value #(if (= %1 %2) %1 :multiple)
combine-values (fn [attrs shape values]
(map #(combine-value (get shape %) (get values %)) attrs))
@ -883,5 +885,5 @@
reducer (fn [result shape]
(zipmap attrs (combine-values attrs shape result)))]
(reduce reducer (select-keys (first shapes) attrs) (rest shapes))))
(reduce reducer (select-keys (first defined-values) attrs) (rest defined-values))))

View file

@ -560,7 +560,7 @@
}
},
"errors.email-already-exists" : {
"used-in" : [ "src/uxbox/main/ui/auth.cljs:87", "src/uxbox/main/ui/settings/change_email.cljs:47" ],
"used-in" : [ "src/uxbox/main/ui/settings/change_email.cljs:47", "src/uxbox/main/ui/auth.cljs:87" ],
"translations" : {
"en" : "Email already used",
"fr" : "Adresse e-mail déjà utilisée",
@ -576,7 +576,7 @@
}
},
"errors.generic" : {
"used-in" : [ "src/uxbox/main/ui.cljs:202", "src/uxbox/main/ui/auth.cljs:91", "src/uxbox/main/ui/settings/profile.cljs:38" ],
"used-in" : [ "src/uxbox/main/ui.cljs:202", "src/uxbox/main/ui/settings/profile.cljs:38", "src/uxbox/main/ui/auth.cljs:91" ],
"translations" : {
"en" : "Something wrong has happened.",
"fr" : "Quelque chose c'est mal passé.",
@ -584,7 +584,7 @@
}
},
"errors.image-format-unsupported" : {
"used-in" : [ "src/uxbox/main/data/images.cljs:376", "src/uxbox/main/data/workspace/persistence.cljs:365", "src/uxbox/main/data/users.cljs:177" ],
"used-in" : [ "src/uxbox/main/data/workspace/persistence.cljs:365", "src/uxbox/main/data/users.cljs:177", "src/uxbox/main/data/images.cljs:376" ],
"translations" : {
"en" : "The image format is not supported (must be svg, jpg or png).",
"fr" : "Le format d'image n'est pas supporté (doit être svg, jpg ou png).",
@ -592,7 +592,7 @@
}
},
"errors.image-too-large" : {
"used-in" : [ "src/uxbox/main/data/images.cljs:374", "src/uxbox/main/data/workspace/persistence.cljs:363", "src/uxbox/main/data/users.cljs:175" ],
"used-in" : [ "src/uxbox/main/data/workspace/persistence.cljs:363", "src/uxbox/main/data/users.cljs:175", "src/uxbox/main/data/images.cljs:374" ],
"translations" : {
"en" : "The image is too large to be inserted (must be under 5mb).",
"fr" : "L'image est trop grande (doit être inférieure à 5 Mo).",
@ -632,7 +632,7 @@
}
},
"errors.unexpected-error" : {
"used-in" : [ "src/uxbox/main/data/images.cljs:385", "src/uxbox/main/data/workspace/persistence.cljs:334", "src/uxbox/main/data/workspace/persistence.cljs:374", "src/uxbox/main/data/users.cljs:185", "src/uxbox/main/ui/auth/register.cljs:54", "src/uxbox/main/ui/settings/change_email.cljs:51", "src/uxbox/main/ui/workspace/sidebar/options/exports.cljs:65" ],
"used-in" : [ "src/uxbox/main/data/workspace/persistence.cljs:334", "src/uxbox/main/data/workspace/persistence.cljs:374", "src/uxbox/main/data/users.cljs:185", "src/uxbox/main/data/images.cljs:385", "src/uxbox/main/ui/settings/change_email.cljs:51", "src/uxbox/main/ui/workspace/sidebar/options/exports.cljs:65", "src/uxbox/main/ui/auth/register.cljs:54" ],
"translations" : {
"en" : "An unexpected error occurred.",
"fr" : "Une erreur inattendue c'est produite",
@ -672,7 +672,7 @@
}
},
"image.loading" : {
"used-in" : [ "src/uxbox/main/data/images.cljs:393", "src/uxbox/main/data/workspace/persistence.cljs:341", "src/uxbox/main/data/workspace/persistence.cljs:382", "src/uxbox/main/data/users.cljs:191" ],
"used-in" : [ "src/uxbox/main/data/workspace/persistence.cljs:341", "src/uxbox/main/data/workspace/persistence.cljs:382", "src/uxbox/main/data/users.cljs:191", "src/uxbox/main/data/images.cljs:393" ],
"translations" : {
"en" : "Loading image...",
"fr" : "Chargement de l'image...",
@ -840,7 +840,7 @@
}
},
"settings.multiple" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:121", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:251", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:264", "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:132", "src/uxbox/main/ui/workspace/sidebar/options/rows/color_row.cljs:117", "src/uxbox/main/ui/workspace/sidebar/options/rows/color_row.cljs:126" ],
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:132", "src/uxbox/main/ui/workspace/sidebar/options/rows/color_row.cljs:117", "src/uxbox/main/ui/workspace/sidebar/options/rows/color_row.cljs:126", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:124", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:227", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:240" ],
"translations" : {
"en" : "Mixed",
"fr" : null,
@ -1394,165 +1394,13 @@
}
},
"workspace.options.fill" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:40", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:402" ],
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:50" ],
"translations" : {
"en" : "Fill",
"fr" : "Remplissage",
"es" : "Relleno"
}
},
"workspace.options.font-options" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:407" ],
"translations" : {
"en" : "Text",
"fr" : "Texte",
"es" : "Texto"
}
},
"workspace.options.font-options.align-bottom" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:311" ],
"translations" : {
"en" : "Align bottom",
"fr" : "Aligner en bas",
"es" : "Alinear abajo"
}
},
"workspace.options.font-options.align-center" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:183" ],
"translations" : {
"en" : "Align center",
"fr" : "Aligner au centre",
"es" : "Aliniear al centro"
}
},
"workspace.options.font-options.align-justify" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:193" ],
"translations" : {
"en" : "Justify",
"fr" : "Justifier",
"es" : "Justificar"
}
},
"workspace.options.font-options.align-left" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:178" ],
"translations" : {
"en" : "Align left",
"fr" : "Aligner à gauche",
"es" : "Alinear a la izquierda"
}
},
"workspace.options.font-options.align-middle" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:306" ],
"translations" : {
"en" : "Align middle",
"fr" : "Aligner au milieu",
"es" : "Alinear al centro"
}
},
"workspace.options.font-options.align-right" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:188" ],
"translations" : {
"en" : "Align right",
"fr" : "Aligner à droite",
"es" : "Alinear a la derecha"
}
},
"workspace.options.font-options.align-top" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:301" ],
"translations" : {
"en" : "Align top",
"fr" : "Aligner en haut",
"es" : "Alinear arriba"
}
},
"workspace.options.font-options.decoration" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:333" ],
"translations" : {
"en" : "Decoration",
"fr" : "Décoration",
"es" : "Decoración"
}
},
"workspace.options.font-options.letter-spacing" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:256" ],
"translations" : {
"en" : "Letter Spacing",
"fr" : "Espacement de caractères",
"es" : "Espaciado entre letras"
}
},
"workspace.options.font-options.line-height" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:243" ],
"translations" : {
"en" : "Line height",
"fr" : "Hauteur de ligne",
"es" : "Altura de línea"
}
},
"workspace.options.font-options.lowercase" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:383" ],
"translations" : {
"en" : "Lowercase",
"fr" : "Minuscule",
"es" : "Minúsculas"
}
},
"workspace.options.font-options.none" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:336", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:373" ],
"translations" : {
"en" : "None",
"fr" : "Aucune",
"es" : "Nada"
}
},
"workspace.options.font-options.strikethrough" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:348" ],
"translations" : {
"en" : "Strikethrough",
"fr" : "Barré",
"es" : "Tachado"
}
},
"workspace.options.font-options.text-case" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:370" ],
"translations" : {
"en" : "Case",
"fr" : "Casse",
"es" : "Mayús/minús"
}
},
"workspace.options.font-options.titlecase" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:388" ],
"translations" : {
"en" : "Titlecase",
"fr" : "Titre",
"es" : "Título"
}
},
"workspace.options.font-options.underline" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:342" ],
"translations" : {
"en" : "Underline",
"fr" : "Souligner",
"es" : "Subrayado"
}
},
"workspace.options.font-options.uppercase" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:378" ],
"translations" : {
"en" : "Uppercase",
"fr" : "Majuscule",
"es" : "Mayúsculas"
}
},
"workspace.options.font-options.vertical-align" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:298" ],
"translations" : {
"en" : "Vertical align",
"fr" : "Alignement vertical",
"es" : "Alineación vertical"
}
},
"workspace.options.grid.auto" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/frame_grid.cljs:40" ],
"translations" : {
@ -1722,7 +1570,7 @@
}
},
"workspace.options.group-fill" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:39" ],
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:49" ],
"translations" : {
"en" : "Group fill",
"fr" : null,
@ -1802,7 +1650,7 @@
}
},
"workspace.options.selection-fill" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:38" ],
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:48" ],
"translations" : {
"en" : "Selection fill",
"fr" : null,
@ -1897,6 +1745,172 @@
"es" : "Sólido"
}
},
"workspace.options.text-options.align-bottom" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:284" ],
"translations" : {
"en" : "Align bottom",
"fr" : "Aligner en bas",
"es" : "Alinear abajo"
}
},
"workspace.options.text-options.align-center" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:183" ],
"translations" : {
"en" : "Align center",
"fr" : "Aligner au centre",
"es" : "Aliniear al centro"
}
},
"workspace.options.text-options.align-justify" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:193" ],
"translations" : {
"en" : "Justify",
"fr" : "Justifier",
"es" : "Justificar"
}
},
"workspace.options.text-options.align-left" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:178" ],
"translations" : {
"en" : "Align left",
"fr" : "Aligner à gauche",
"es" : "Alinear a la izquierda"
}
},
"workspace.options.text-options.align-middle" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:279" ],
"translations" : {
"en" : "Align middle",
"fr" : "Aligner au milieu",
"es" : "Alinear al centro"
}
},
"workspace.options.text-options.align-right" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:188" ],
"translations" : {
"en" : "Align right",
"fr" : "Aligner à droite",
"es" : "Alinear a la derecha"
}
},
"workspace.options.text-options.align-top" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:274" ],
"translations" : {
"en" : "Align top",
"fr" : "Aligner en haut",
"es" : "Alinear arriba"
}
},
"workspace.options.text-options.decoration" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:303" ],
"translations" : {
"en" : "Decoration",
"fr" : "Décoration",
"es" : "Decoración"
}
},
"workspace.options.text-options.letter-spacing" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:232" ],
"translations" : {
"en" : "Letter Spacing",
"fr" : "Espacement de caractères",
"es" : "Espaciado entre letras"
}
},
"workspace.options.text-options.line-height" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:219" ],
"translations" : {
"en" : "Line height",
"fr" : "Hauteur de ligne",
"es" : "Altura de línea"
}
},
"workspace.options.text-options.lowercase" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:350" ],
"translations" : {
"en" : "Lowercase",
"fr" : "Minuscule",
"es" : "Minúsculas"
}
},
"workspace.options.text-options.none" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:306", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:340" ],
"translations" : {
"en" : "None",
"fr" : "Aucune",
"es" : "Nada"
}
},
"workspace.options.text-options.strikethrough" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:318" ],
"translations" : {
"en" : "Strikethrough",
"fr" : "Barré",
"es" : "Tachado"
}
},
"workspace.options.text-options.text-case" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:337" ],
"translations" : {
"en" : "Case",
"fr" : "Casse",
"es" : "Mayús/minús"
}
},
"workspace.options.text-options.title" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:375" ],
"translations" : {
"en" : "Text",
"fr" : "Texte",
"es" : "Texto"
}
},
"workspace.options.text-options.title-group" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:374" ],
"translations" : {
"en" : "Group text",
"es" : "Texto de grupo"
}
},
"workspace.options.text-options.title-selection" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:373" ],
"translations" : {
"en" : "Selection text",
"es" : "Texto de selección"
}
},
"workspace.options.text-options.titlecase" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:355" ],
"translations" : {
"en" : "Titlecase",
"fr" : "Titre",
"es" : "Título"
}
},
"workspace.options.text-options.underline" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:312" ],
"translations" : {
"en" : "Underline",
"fr" : "Souligner",
"es" : "Subrayado"
}
},
"workspace.options.text-options.uppercase" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:345" ],
"translations" : {
"en" : "Uppercase",
"fr" : "Majuscule",
"es" : "Mayúsculas"
}
},
"workspace.options.text-options.vertical-align" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:271" ],
"translations" : {
"en" : "Vertical align",
"fr" : "Alignement vertical",
"es" : "Alineación vertical"
}
},
"workspace.options.use-play-button" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/interactions.cljs:55" ],
"translations" : {

View file

@ -55,9 +55,9 @@
(let [change #(cond-> %
value (assoc :fill-color value)
opacity (assoc :fill-opacity opacity))
new-attrs (cond-> {}
value (assoc :fill value)
opacity (assoc :opacity opacity))]
converted-attrs (cond-> {}
value (assoc :fill value)
opacity (assoc :opacity opacity))]
(when-not (empty? other-ids)
(st/emit! (dwc/update-shapes ids change)))
@ -65,7 +65,7 @@
(run! #(st/emit! (dwt/update-text-attrs
{:id %
:editor editor
:attrs new-attrs}))
:attrs converted-attrs}))
text-ids))))]
[:div.element-set
[:div.element-set-title label]

View file

@ -13,26 +13,123 @@
[rumext.alpha :as mf]
[uxbox.common.geom.shapes :as geom]
[uxbox.main.refs :as refs]
[uxbox.main.data.workspace.texts :as dwt]
[uxbox.main.ui.workspace.sidebar.options.multiple :refer [get-shape-attrs]]
[uxbox.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]]
[uxbox.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]]
[uxbox.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]]))
[uxbox.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]]
[uxbox.main.ui.workspace.sidebar.options.text :refer [text-fill-attrs
text-font-attrs
text-align-attrs
text-spacing-attrs
text-valign-attrs
text-decoration-attrs
text-transform-attrs
text-menu]]))
(mf/defc options
[{:keys [shape] :as props}]
(let [child-ids (:shapes shape)
children (mf/deref (refs/objects-by-id child-ids))
type (:type shape)
measure-values (select-keys shape measure-attrs)
fill-values (geom/get-attrs-multi children fill-attrs)
stroke-values (geom/get-attrs-multi children stroke-attrs)]
[:*
[:& measures-menu {:ids [(:id shape)]
:type type
:values measure-values}]
[:& fill-menu {:ids child-ids
:type type
:values fill-values}]
[:& stroke-menu {:ids child-ids
:type type
:values stroke-values}]]))
text-ids (map :id (filter #(= (:type %) :text) children))
other-ids (map :id (filter #(not= (:type %) :text) children))
type (:type shape)
measure-values
(select-keys shape measure-attrs)
fill-values
(geom/get-attrs-multi children fill-attrs)
stroke-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
stroke-attrs
nil
nil
nil)
children)
stroke-attrs)
font-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-font-attrs
nil
dwt/current-text-values)
children)
text-font-attrs)
align-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-align-attrs
nil
dwt/current-paragraph-values)
children)
text-align-attrs)
spacing-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-spacing-attrs
nil
dwt/current-text-values)
children)
text-spacing-attrs)
valign-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-valign-attrs
nil
dwt/current-root-values)
children)
text-valign-attrs)
decoration-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-decoration-attrs
nil
dwt/current-text-values)
children)
text-decoration-attrs)
transform-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-transform-attrs
nil
dwt/current-text-values)
children)
text-transform-attrs)]
[:*
[:& measures-menu {:ids [(:id shape)]
:type type
:values measure-values}]
[:& fill-menu {:ids child-ids
:type type
:values fill-values}]
(when-not (empty? other-ids)
[:& stroke-menu {:ids child-ids
:type type
:values stroke-values}])
(when-not (empty? text-ids)
[:& text-menu {:ids text-ids
:type type
:editor nil
:font-values font-values
:align-values align-values
:spacing-values spacing-values
:valign-values valign-values
:decoration-values decoration-values
:transform-values transform-values}])]))

View file

@ -13,28 +13,122 @@
[uxbox.common.geom.shapes :as geom]
[uxbox.main.data.workspace.texts :as dwt]
[uxbox.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]]
[uxbox.main.ui.workspace.sidebar.options.text :refer [text-fill-attrs]]
[uxbox.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]]
[uxbox.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]]))
[uxbox.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]]
[uxbox.main.ui.workspace.sidebar.options.text :refer [text-fill-attrs
text-font-attrs
text-align-attrs
text-spacing-attrs
text-valign-attrs
text-decoration-attrs
text-transform-attrs
text-menu]]))
(defn- get-attrs
[shape attrs text-attrs]
(defn get-shape-attrs
[shape attrs text-attrs convert-attrs extract-fn]
(if (not= (:type shape) :text)
(select-keys shape attrs)
(let [text-values (dwt/current-text-values {:editor nil
:shape shape
:attrs text-attrs})
converted-values (zipmap fill-attrs
(map #(% text-values) text-attrs))]
converted-values)))
(when attrs
(select-keys shape attrs))
(when text-attrs
(let [text-values (extract-fn {:editor nil
:shape shape
:attrs text-attrs})
converted-values (if convert-attrs
(zipmap convert-attrs
(map #(% text-values) text-attrs))
text-values)]
converted-values))))
(mf/defc options
{::mf/wrap [mf/memo]}
[{:keys [shapes] :as props}]
(let [ids (map :id shapes)
measure-values (geom/get-attrs-multi shapes measure-attrs)
fill-values (geom/get-attrs-multi (map #(get-attrs % fill-attrs text-fill-attrs) shapes) fill-attrs)
stroke-values (geom/get-attrs-multi shapes stroke-attrs)]
text-ids (map :id (filter #(= (:type %) :text) shapes))
other-ids (map :id (filter #(not= (:type %) :text) shapes))
measure-values
(geom/get-attrs-multi shapes measure-attrs)
fill-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
fill-attrs
text-fill-attrs
fill-attrs
dwt/current-text-values)
shapes)
fill-attrs)
stroke-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
stroke-attrs
nil
nil
nil)
shapes)
stroke-attrs)
font-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-font-attrs
nil
dwt/current-text-values)
shapes)
text-font-attrs)
align-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-align-attrs
nil
dwt/current-paragraph-values)
shapes)
text-align-attrs)
spacing-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-spacing-attrs
nil
dwt/current-text-values)
shapes)
text-spacing-attrs)
valign-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-valign-attrs
nil
dwt/current-root-values)
shapes)
text-valign-attrs)
decoration-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-decoration-attrs
nil
dwt/current-text-values)
shapes)
text-decoration-attrs)
transform-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-transform-attrs
nil
dwt/current-text-values)
shapes)
text-transform-attrs)]
[:*
[:& measures-menu {:ids ids
:type :multiple
@ -42,7 +136,18 @@
[:& fill-menu {:ids ids
:type :multiple
:values fill-values}]
[:& stroke-menu {:ids ids
(when-not (empty? other-ids)
[:& stroke-menu {:ids other-ids
:type :multiple
:values stroke-values}])
(when-not (empty? text-ids)
[:& text-menu {:ids text-ids
:type :multiple
:values stroke-values}]]))
:editor nil
:font-values font-values
:align-values align-values
:spacing-values spacing-values
:valign-values valign-values
:decoration-values decoration-values
:transform-values transform-values}])]))

View file

@ -26,8 +26,12 @@
["slate" :refer [Transforms]]))
(def text-fill-attrs [:fill :opacity])
(def text-font-attrs [:font-id :font-family :font-variant-id :font-size :font-weight :font-style])
(def text-align-attrs [:text-align])
(def text-spacing-attrs [:line-height :letter-spacing])
(def text-valign-attrs [:vertical-align])
(def text-decoration-attrs [:text-decoration])
(def text-transform-attrs [:text-transform])
(defn- attr->string [value]
(if (= value :multiple)
@ -171,22 +175,22 @@
;; --- Align
[:div.row-flex.align-icons
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-left")
{:alt (t locale "workspace.options.text-options.align-left")
:class (dom/classnames :current (= "left" text-align))
:on-click #(on-change % "left")}
i/text-align-left]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-center")
{:alt (t locale "workspace.options.text-options.align-center")
:class (dom/classnames :current (= "center" text-align))
:on-click #(on-change % "center")}
i/text-align-center]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-right")
{:alt (t locale "workspace.options.text-options.align-right")
:class (dom/classnames :current (= "right" text-align))
:on-click #(on-change % "right")}
i/text-align-right]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-justify")
{:alt (t locale "workspace.options.text-options.align-justify")
:class (dom/classnames :current (= "justify" text-align))
:on-click #(on-change % "justify")}
i/text-align-justify]]))
@ -212,7 +216,7 @@
[:div.row-flex
[:div.input-icon
[:span.icon-before.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.line-height")}
{:alt (t locale "workspace.options.text-options.line-height")}
i/line-height]
[:input.input-text
{:type "number"
@ -225,7 +229,7 @@
[:div.input-icon
[:span.icon-before.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.letter-spacing")}
{:alt (t locale "workspace.options.text-options.letter-spacing")}
i/letter-spacing]
[:input.input-text
{:type "number"
@ -264,20 +268,20 @@
ids))]
[:div.row-flex
[:span.element-set-subtitle (t locale "workspace.options.font-options.vertical-align")]
[:span.element-set-subtitle (t locale "workspace.options.text-options.vertical-align")]
[:div.align-icons
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-top")
{:alt (t locale "workspace.options.text-options.align-top")
:class (dom/classnames :current (= "top" vertical-align))
:on-click #(on-change % "top")}
i/align-top]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-middle")
{:alt (t locale "workspace.options.text-options.align-middle")
:class (dom/classnames :current (= "center" vertical-align))
:on-click #(on-change % "center")}
i/align-middle]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-bottom")
{:alt (t locale "workspace.options.text-options.align-bottom")
:class (dom/classnames :current (= "bottom" vertical-align))
:on-click #(on-change % "bottom")}
i/align-bottom]]]))
@ -296,22 +300,22 @@
:attrs {:text-decoration type}}))
ids))]
[:div.row-flex
[:span.element-set-subtitle (t locale "workspace.options.font-options.decoration")]
[:span.element-set-subtitle (t locale "workspace.options.text-options.decoration")]
[:div.align-icons
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.none")
{:alt (t locale "workspace.options.text-options.none")
:class (dom/classnames :current (= "none" text-decoration))
:on-click #(on-change % "none")}
i/minus]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.underline")
{:alt (t locale "workspace.options.text-options.underline")
:class (dom/classnames :current (= "underline" text-decoration))
:on-click #(on-change % "underline")}
i/underline]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.strikethrough")
{:alt (t locale "workspace.options.text-options.strikethrough")
:class (dom/classnames :current (= "line-through" text-decoration))
:on-click #(on-change % "line-through")}
i/strikethrough]]]))
@ -330,25 +334,25 @@
:attrs {:text-transform type}}))
ids))]
[:div.row-flex
[:span.element-set-subtitle (t locale "workspace.options.font-options.text-case")]
[:span.element-set-subtitle (t locale "workspace.options.text-options.text-case")]
[:div.align-icons
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.none")
{: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.font-options.uppercase")
{: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.font-options.lowercase")
{: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.font-options.titlecase")
{:alt (t locale "workspace.options.text-options.titlecase")
:class (dom/classnames :current (= "capitalize" text-transform))
:on-click #(on-change % "capitalize")}
i/titlecase]]]))
@ -358,26 +362,26 @@
[{:keys [ids
type
editor
fill-values
font-values
align-values
spacing-values
valign-values
decoration-values
transform-values] :as props}]
(let [locale (mf/deref i18n/locale)]
[:*
[:& fill-menu {:ids ids :type type :values fill-values :editor editor}]
[:div.element-set
[:div.element-set-title (t locale "workspace.options.font-options")]
[:div.element-set-content
[:& font-options {:editor editor :ids ids :values font-values :locale locale}]
[:& text-align-options {:editor editor :ids ids :values align-values :locale locale}]
[:& spacing-options {:editor editor :ids ids :values spacing-values :locale locale}]
[:& vertical-align-options {:editor editor :ids ids :values valign-values :locale locale}]
[:& text-decoration-options {:editor editor :ids ids :values decoration-values :locale locale}]
[:& text-transform-options {:editor editor :ids ids :values transform-values :locale locale}]]]]))
(let [locale (mf/deref i18n/locale)
label (case type
:multiple (t locale "workspace.options.text-options.title-selection")
:group (t locale "workspace.options.text-options.title-group")
(t locale "workspace.options.text-options.title"))]
[:div.element-set
[:div.element-set-title label]
[:div.element-set-content
[:& font-options {:editor editor :ids ids :values font-values :locale locale}]
[:& text-align-options {:editor editor :ids ids :values align-values :locale locale}]
[:& spacing-options {:editor editor :ids ids :values spacing-values :locale locale}]
[:& vertical-align-options {:editor editor :ids ids :values valign-values :locale locale}]
[:& text-decoration-options {:editor editor :ids ids :values decoration-values :locale locale}]
[:& text-transform-options {:editor editor :ids ids :values transform-values :locale locale}]]]))
(mf/defc options
[{:keys [shape] :as props}]
@ -387,15 +391,12 @@
local (deref refs/workspace-local)
editor (get-in local [:editors (:id shape)])
_ (println "hay editor" (clj->js (not (nil? editor))))
measure-values (select-keys shape measure-attrs)
fill-values (dwt/current-text-values
{:editor editor
:shape shape
:attrs [:fill
:opacity]})
:attrs text-fill-attrs})
converted-fill-values {:fill-color (:fill fill-values)
:fill-opacity (:opacity fill-values)}
@ -403,43 +404,43 @@
font-values (dwt/current-text-values
{:editor editor
:shape shape
:attrs [:font-id
:font-size
:font-variant-id]})
:attrs text-font-attrs})
align-values (dwt/current-paragraph-values
{:editor editor
:shape shape
:attrs [:text-align]})
:attrs text-align-attrs})
spacing-values (dwt/current-text-values
{:editor editor
:shape shape
:attrs [:line-height
:letter-spacing]})
:attrs text-spacing-attrs})
valign-values (dwt/current-root-values
{:editor editor
:shape shape
:attrs [:vertical-align]})
:attrs text-valign-attrs})
decoration-values (dwt/current-text-values
{:editor editor
:shape shape
:attrs [:text-decoration]})
:attrs text-decoration-attrs})
transform-values (dwt/current-text-values
{:editor editor
:shape shape
:attrs [:text-transform]})]
[:div
:attrs text-transform-attrs})]
[:*
[:& measures-menu {:ids ids
:type type
:values measure-values}]
[:& fill-menu {:ids ids
:type type
:values converted-fill-values
:editor editor}]
[:& text-menu {:ids ids
:type type
:editor editor
:fill-values converted-fill-values
:font-values font-values
:align-values align-values
:spacing-values spacing-values