From 092a973f9a1fb973cab3af9c4be92af3e8200304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Tue, 1 Jun 2021 12:38:00 +0200 Subject: [PATCH] :tada: Add resize constraints to shapes --- common/src/app/common/geom/shapes.cljc | 1 + common/src/app/common/geom/shapes/rect.cljc | 5 + .../app/common/geom/shapes/transforms.cljc | 133 +++++++++++++++ common/src/app/common/pages/spec.cljc | 28 +++ .../partials/sidebar-element-options.scss | 150 +++++++++++++++++ .../app/main/data/workspace/transforms.cljs | 71 ++++---- .../sidebar/options/menus/measures.cljs | 159 ++++++++++++++++-- frontend/translations/en.po | 48 ++++++ frontend/translations/es.po | 50 +++++- 9 files changed, 602 insertions(+), 43 deletions(-) diff --git a/common/src/app/common/geom/shapes.cljc b/common/src/app/common/geom/shapes.cljc index 75fc70661..24165ff5c 100644 --- a/common/src/app/common/geom/shapes.cljc +++ b/common/src/app/common/geom/shapes.cljc @@ -188,6 +188,7 @@ (d/export gpr/center->rect) (d/export gtr/transform-shape) +(d/export gtr/calc-child-modifiers) (d/export gtr/transform-matrix) (d/export gtr/inverse-transform-matrix) (d/export gtr/transform-point-center) diff --git a/common/src/app/common/geom/shapes/rect.cljc b/common/src/app/common/geom/shapes/rect.cljc index 91e7d18a9..853f7d7f4 100644 --- a/common/src/app/common/geom/shapes/rect.cljc +++ b/common/src/app/common/geom/shapes/rect.cljc @@ -9,6 +9,11 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes.common :as gco])) +(defn left-of [rect] (:x rect)) +(defn right-of [rect] (+ (:x rect) (:width rect))) +(defn top-of [rect] (:y rect)) +(defn bottom-of [rect] (+ (:y rect) (:height rect))) + (defn rect->points [{:keys [x y width height]}] ;; (assert (number? x)) ;; (assert (number? y)) diff --git a/common/src/app/common/geom/shapes/transforms.cljc b/common/src/app/common/geom/shapes/transforms.cljc index cd78e72d9..09dfb3f8b 100644 --- a/common/src/app/common/geom/shapes/transforms.cljc +++ b/common/src/app/common/geom/shapes/transforms.cljc @@ -14,6 +14,7 @@ [app.common.geom.shapes.path :as gpa] [app.common.geom.shapes.rect :as gpr] [app.common.math :as mth] + [app.common.pages.spec :as spec] [app.common.text :as txt])) ;; --- Relative Movement @@ -362,6 +363,138 @@ (dissoc :modifiers))) shape)))) + +(defn calc-child-modifiers + [parent transformed-parent child parent-modifiers] + (let [parent-rect (:selrect parent) + transformed-parent-rect (:selrect transformed-parent) + child-rect (:selrect child) + + origin (:resize-origin parent-modifiers) + + orig-h (when origin + (cond + (mth/close? (:x origin) (gpr/left-of parent-rect)) :left + (mth/close? (:x origin) (gpr/right-of parent-rect)) :right + :else :middle)) + + orig-v (when origin + (cond + (mth/close? (:y origin) (gpr/top-of parent-rect)) :top + (mth/close? (:y origin) (gpr/bottom-of parent-rect)) :bottom + :else :middle)) + + delta-h (when orig-h + (cond (= orig-h :left) + (- (gpr/right-of transformed-parent-rect) (gpr/right-of parent-rect)) + + (= orig-h :right) + (- (gpr/left-of transformed-parent-rect) (gpr/left-of parent-rect)) + + :else 0)) + + delta-v (when orig-v + (cond (= orig-v :top) + (- (gpr/bottom-of transformed-parent-rect) (gpr/bottom-of parent-rect)) + + (= orig-v :bottom) + (- (gpr/top-of transformed-parent-rect) (gpr/top-of parent-rect)) + + :else 0)) + + constraints-h (get child :constraints-h (spec/default-constraints-h child)) + constraints-v (get child :constraints-v (spec/default-constraints-v child)) + + modifiers-h (case constraints-h + :left + (if (= orig-h :right) + {:displacement (gpt/point delta-h 0)} ;; we convert to matrix below + {}) + + :right + (if (= orig-h :left) + {:displacement (gpt/point delta-h 0)} + {}) + + :leftright + (cond (= orig-h :left) + {:resize-origin (gpt/point (gpr/left-of child-rect) (gpr/top-of child-rect)) + :resize-vector (gpt/point (/ (+ (:width child-rect) delta-h) + (:width child-rect)) + 1)} + + (= orig-h :right) + {:resize-origin (gpt/point (gpr/right-of child-rect) (gpr/top-of child-rect)) + :resize-vector (gpt/point (/ (- (:width child-rect) delta-h) + (:width child-rect)) + 1)} + + :else {}) + + :center + {:displacement (gpt/point (/ delta-h 2) 0)} + + :scale + (if (:resize-origin parent-modifiers) + {:resize-origin (:resize-origin parent-modifiers) + :resize-vector (gpt/point (:x (:resize-vector parent-modifiers)) 1)} + {}) + + {}) + + modifiers-v (case constraints-v + :top + (if (= orig-v :bottom) + {:displacement (gpt/point 0 delta-v)} + {}) + + :bottom + (if (= orig-v :top) + {:displacement (gpt/point 0 delta-v)} + {}) + + :topbottom + (cond (= orig-v :top) + {:resize-origin (gpt/point (gpr/left-of child-rect) (gpr/top-of child-rect)) + :resize-vector (gpt/point 1 + (/ (+ (:height child-rect) delta-v) + (:height child-rect)))} + + (= orig-v :bottom) + {:resize-origin (gpt/point (gpr/left-of child-rect) (gpr/bottom-of child-rect)) + :resize-vector (gpt/point 1 + (/ (- (:height child-rect) delta-v) + (:height child-rect)))} + + :else {}) + + :center + {:displacement (gpt/point 0 (/ delta-v 2))} + + :scale + (if (:resize-origin parent-modifiers) + {:resize-origin (:resize-origin parent-modifiers) + :resize-vector (gpt/point 1 (:y (:resize-vector parent-modifiers)))} + {}) + + {})] + + (cond-> {} + (or (:displacement modifiers-h) (:displacement modifiers-v)) + (assoc :displacement (gmt/translate-matrix + (gpt/point (get (:displacement modifiers-h) :x 0) + (get (:displacement modifiers-v) :y 0)))) + + (or (:resize-vector modifiers-h) (:resize-vector modifiers-v)) + (assoc :resize-origin (or (:resize-origin modifiers-h) ;; we assume that the origin is the same + (:resize-origin modifiers-v)) ;; in any direction + :resize-vector (gpt/point (get (:resize-vector modifiers-h) :x 1) + (get (:resize-vector modifiers-v) :y 1))) + (:displacement parent-modifiers) + (update :displacement #(if (nil? %) + (:displacement parent-modifiers) + (gmt/multiply % (:displacement parent-modifiers))))))) + (defn update-group-viewbox "Updates the viewbox for groups imported from SVG's" [{:keys [selrect svg-viewbox] :as group} new-selrect] diff --git a/common/src/app/common/pages/spec.cljc b/common/src/app/common/pages/spec.cljc index 24c523fd0..32c010cfd 100644 --- a/common/src/app/common/pages/spec.cljc +++ b/common/src/app/common/pages/spec.cljc @@ -9,6 +9,7 @@ [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.spec :as us] + [app.common.uuid :as uuid] [clojure.spec.alpha :as s])) ;; --- Specs @@ -195,6 +196,30 @@ (s/def :internal.shape/interactions (s/coll-of :internal.shape/interaction :kind vector?)) +;; Size constraints + +(s/def :internal.shape/constraints-h #{:left :right :leftright :center :scale}) +(s/def :internal.shape/constraints-v #{:top :bottom :topbottom :center :scale}) +(s/def :internal.shape/fixed-scroll boolean?) + +; Shapes in the top frame have no constraints. Shapes directly below some +; frame are left-top constrained. Else (shapes in a group) are scaled. +(defn default-constraints-h + [shape] + (if (= (:parent-id shape) uuid/zero) + nil + (if (= (:parent-id shape) (:frame-id shape)) + :left + :scale))) + +(defn default-constraints-v + [shape] + (if (= (:parent-id shape) uuid/zero) + nil + (if (= (:parent-id shape) (:frame-id shape)) + :top + :scale))) + ;; Page Data related (s/def :internal.shape/blocked boolean?) (s/def :internal.shape/collapsed boolean?) @@ -297,6 +322,9 @@ :internal.shape/locked :internal.shape/proportion :internal.shape/proportion-lock + :internal.shape/constraints-h + :internal.shape/constraints-v + :internal.shape/fixed-scroll :internal.shape/rx :internal.shape/ry :internal.shape/r1 diff --git a/frontend/resources/styles/main/partials/sidebar-element-options.scss b/frontend/resources/styles/main/partials/sidebar-element-options.scss index af2a9d22a..ff8060411 100644 --- a/frontend/resources/styles/main/partials/sidebar-element-options.scss +++ b/frontend/resources/styles/main/partials/sidebar-element-options.scss @@ -1257,4 +1257,154 @@ } } +.row-flex.align-top { + align-items: flex-start; +} +.constraints-widget { + min-width: 72px; + min-height: 72px; + position: relative; + background-color: $color-gray-60; + flex-grow: 0; + + .constraints-box { + width: 28px; + height: 28px; + position: absolute; + top: 22px; + left: 22px; + border: 2px solid $color-gray-50; + } + + .constraint-button { + position: absolute; + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + + &::after { + content: ' '; + background-color: $color-gray-20; + } + + &.active, + &:hover { + &::after { + background-color: $color-primary; + } + } + + &.top, + &.bottom { + width: 28px; + height: 22px; + left: calc(50% - 14px); + + &::after { + width: 3px; + height: 15px; + } + } + + &.top { + top: 0; + } + + &.bottom { + bottom: 0; + } + + &.left, + &.right { + width: 22px; + height: 28px; + top: calc(50% - 14px); + + &::after { + width: 15px; + height: 3px; + } + } + + &.left { + left: 0; + } + + &.right { + right: 0; + } + + &.centerv { + width: 28px; + height: 28px; + left: calc(50% - 14px); + top: calc(50% - 14px); + + &::after { + width: 3px; + height: 15px; + } + } + + &.centerh { + width: 28px; + height: 15px; + left: calc(50% - 14px); + top: calc(50% - 7px); + + &::after { + width: 15px; + height: 3px; + } + } + } +} + +.constraints-form { + display: flex; + flex-grow: 1; + flex-direction: column; + align-items: stretch; + justify-content: flex-start; + + .input-select { + font-size: $fs11; + margin: 0 $x-small; + } + + svg { + width: 15px; + height: 15px; + margin-left: $medium; + fill: $color-gray-20; + } + + .left-right svg { + transform: rotate(45deg); + } + + .top-down svg { + transform: rotate(-45deg); + } + + .fix-when { + font-size: $fs11; + cursor: pointer; + + span { + margin-left: $small; + } + + &:hover, + &.active { + color: $color-primary; + + svg { + fill: $color-primary; + } + } + } + +} diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 0e2c7f230..8f3955b10 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -151,8 +151,7 @@ :resize-origin origin :resize-transform shape-transform :resize-scale-text scale-text - :resize-transform-inverse shape-transform-inverse} - false)))) + :resize-transform-inverse shape-transform-inverse})))) ;; Unifies the instantaneous proportion lock modifier ;; activated by Shift key and the shapes own proportion @@ -426,10 +425,34 @@ ;; -- Apply modifiers +(defn- set-modifiers-recursive + [modif-tree objects shape modifiers] + (let [children (->> (get shape :shapes []) + (map #(get objects %))) + + transformed-shape (when (seq children) ; <- don't calculate it if not needed + (gsh/transform-shape + (assoc shape :modifiers (select-keys modifiers + [:resize-origin + :resize-vector])))) + + set-child (fn [modif-tree child] + (let [child-modifiers (gsh/calc-child-modifiers shape + transformed-shape + child + modifiers)] + (set-modifiers-recursive modif-tree + objects + child + child-modifiers)))] + + (reduce set-child + (update-in modif-tree [(:id shape) :modifiers] #(merge % modifiers)) + children))) + (defn set-modifiers - ([ids] (set-modifiers ids nil true)) - ([ids modifiers] (set-modifiers ids modifiers true)) - ([ids modifiers recurse-frames?] + ([ids] (set-modifiers ids nil)) + ([ids modifiers] (us/verify (s/coll-of uuid?) ids) (ptk/reify ::set-modifiers ptk/UpdateEvent @@ -438,25 +461,16 @@ page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) - ids (->> ids (into #{} (remove #(get-in objects [% :blocked] false)))) - - not-frame-id? - (fn [shape-id] - (let [shape (get objects shape-id)] - (or recurse-frames? (not (= :frame (:type shape)))))) - - ;; For each shape updates the modifiers given as arguments - update-shape - (fn [objects shape-id] - (update-in objects [shape-id :modifiers] #(merge % modifiers))) - - ;; ID's + Children but remove frame children if the flag is set to false - ids-with-children (concat ids (mapcat #(cp/get-children % objects) - (filter not-frame-id? ids)))] - - (update state :workspace-modifiers - #(reduce update-shape % ids-with-children))))))) + ids (->> ids (into #{} (remove #(get-in objects [% :blocked] false))))] + (reduce (fn [state id] + (update state :workspace-modifiers + #(set-modifiers-recursive % + objects + (get objects id) + modifiers))) + state + ids)))))) ;; Set-rotation is custom because applies different modifiers to each ;; shape adjusting their position. @@ -567,10 +581,7 @@ (fn [objects shape-id] (let [shape (get objects shape-id) modifier (gsh/resize-modifiers shape attr value)] - (-> objects - (assoc-in [shape-id :modifiers] modifier) - (cond-> (not (= :frame (:type shape))) - (update-children (cp/get-children shape-id objects) modifier)))))] + (set-modifiers-recursive objects objects shape modifier)))] (d/update-in-when state @@ -597,8 +608,7 @@ (rx/of (set-modifiers selected {:resize-vector (gpt/point -1.0 1.0) :resize-origin origin - :displacement (gmt/translate-matrix (gpt/point (- (:width selrect)) 0))} - false) + :displacement (gmt/translate-matrix (gpt/point (- (:width selrect)) 0))}) (apply-modifiers selected)))))) (defn flip-vertical-selected [] @@ -614,8 +624,7 @@ (rx/of (set-modifiers selected {:resize-vector (gpt/point 1.0 -1.0) :resize-origin origin - :displacement (gmt/translate-matrix (gpt/point 0 (- (:height selrect))))} - false) + :displacement (gmt/translate-matrix (gpt/point 0 (- (:height selrect))))}) (apply-modifiers selected)))))) (defn start-local-displacement [point] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs index 0d02a5419..f7e8fa632 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs @@ -6,6 +6,7 @@ (ns app.main.ui.workspace.sidebar.options.menus.measures (:require + [cuerdas.core :as str] [rumext.alpha :as mf] [app.main.ui.icons :as i] [app.main.store :as st] @@ -15,12 +16,14 @@ [app.util.data :refer [classnames]] [app.common.geom.shapes :as gsh] [app.common.geom.point :as gpt] + [app.common.pages.spec :as spec] + [app.common.uuid :as uuid] [app.main.data.workspace :as udw] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.changes :as dch] [app.main.ui.components.numeric-input :refer [numeric-input]] [app.common.math :as math] - [app.util.i18n :refer [t] :as i18n])) + [app.util.i18n :refer [tr] :as i18n])) (def measure-attrs [:proportion-lock :width :height @@ -28,7 +31,12 @@ :rotation :rx :ry :r1 :r2 :r3 :r4 - :selrect]) + :selrect + :constraints-h + :constraints-v + :fixed-scroll + :parent-id + :frame-id]) (defn- attr->string [attr values] (let [value (attr values)] @@ -42,7 +50,6 @@ (mf/defc measures-menu [{:keys [options ids ids-with-children values] :as props}] (let [options (or options #{:size :position :rotation :radius}) - locale (i18n/use-locale) ids-with-children (or ids-with-children ids) @@ -65,6 +72,13 @@ proportion-lock (:proportion-lock values) + in-frame? (not= (:parent-id values) uuid/zero) + first-level? (and in-frame? + (= (:parent-id values) (:frame-id values))) + + constraints-h (get values :constraints-h (spec/default-constraints-h values)) + constraints-v (get values :constraints-v (spec/default-constraints-v values)) + on-size-change (mf/use-callback (mf/deps ids) @@ -161,15 +175,75 @@ on-radius-r2-change #(on-radius-4-change % :r2) on-radius-r3-change #(on-radius-4-change % :r3) on-radius-r4-change #(on-radius-4-change % :r4) - select-all #(-> % (dom/get-target) (.select))] + select-all #(-> % (dom/get-target) (.select)) + + on-constraint-button-clicked + (mf/use-callback + (mf/deps [ids values]) + (fn [button] + (fn [event] + (let [constraints-h (get values :constraints-h :scale) + constraints-v (get values :constraints-v :scale) + + [constraint new-value] + (case button + :top (case constraints-v + :top [:constraints-v :scale] + :topbottom [:constraints-v :bottom] + :bottom [:constraints-v :topbottom] + [:constraints-v :top]) + :bottom (case constraints-v + :bottom [:constraints-v :scale] + :topbottom [:constraints-v :top] + :top [:constraints-v :topbottom] + [:constraints-v :bottom]) + :left (case constraints-h + :left [:constraints-h :scale] + :leftright [:constraints-h :right] + :right [:constraints-h :leftright] + [:constraints-h :left]) + :right (case constraints-h + :right [:constraints-h :scale] + :leftright [:constraints-h :left] + :left [:constraints-h :leftright] + [:constraints-h :right]) + :centerv (case constraints-v + :center [:constraints-v :scale] + [:constraints-v :center]) + :centerh (case constraints-h + :center [:constraints-h :scale] + [:constraints-h :center]))] + (st/emit! (dch/update-shapes + ids + #(assoc % constraint new-value))))))) + + on-constraint-select-changed + (mf/use-callback + (mf/deps [ids values]) + (fn [constraint] + (fn [event] + (let [value (-> (dom/get-target-val event) (keyword))] + (when-not (str/empty? value) + (st/emit! (dch/update-shapes + ids + #(assoc % constraint value)))))))) + + on-fixed-scroll-clicked + (mf/use-callback + (mf/deps [ids values]) + (fn [event] + (st/emit! (dch/update-shapes + ids + #(update % :fixed-scroll not)))))] + [:* [:div.element-set [:div.element-set-content ;; WIDTH & HEIGHT (when (options :size) [:div.row-flex - [:span.element-set-subtitle (t locale "workspace.options.size")] + [:span.element-set-subtitle (tr "workspace.options.size")] [:div.input-element.width [:> numeric-input {:min 1 :no-validate true @@ -197,7 +271,7 @@ ;; POSITION (when (options :position) [:div.row-flex - [:span.element-set-subtitle (t locale "workspace.options.position")] + [:span.element-set-subtitle (tr "workspace.options.position")] [:div.input-element.Xaxis [:> numeric-input {:no-validate true :placeholder "--" @@ -214,7 +288,7 @@ ;; ROTATION (when (options :rotation) [:div.row-flex - [:span.element-set-subtitle (t locale "workspace.options.rotation")] + [:span.element-set-subtitle (tr "workspace.options.rotation")] [:div.input-element.degrees [:> numeric-input {:no-validate true @@ -244,14 +318,14 @@ {:class (classnames :selected (and radius-1? (not radius-4?))) - :alt (t locale "workspace.options.radius.all-corners") + :alt (tr "workspace.options.radius.all-corners") :on-click on-switch-to-radius-1} i/radius-1] [:div.radius-icon.tooltip.tooltip-bottom {:class (classnames :selected (and radius-4? (not radius-1?))) - :alt (t locale "workspace.options.radius.single-corners") + :alt (tr "workspace.options.radius.single-corners") :on-click on-switch-to-radius-4} i/radius-4]] (if radius-1? @@ -291,5 +365,68 @@ :min 0 :on-click select-all :on-change on-radius-r4-change - :value (attr->string :r4 values)}]]]) - ]))]])) + :value (attr->string :r4 values)}]]])]))]] + + ;; CONSTRAINTS + (when in-frame? + [:div.element-set + [:div.element-set-title + [:span (tr "workspace.options.constraints")]] + + [:div.element-set-content + [:div.row-flex.align-top + + [:div.constraints-widget + [:div.constraints-box] + [:div.constraint-button.top + {:class (classnames :active (or (= constraints-v :top) + (= constraints-v :topbottom))) + :on-click (on-constraint-button-clicked :top)}] + [:div.constraint-button.bottom + {:class (classnames :active (or (= constraints-v :bottom) + (= constraints-v :topbottom))) + :on-click (on-constraint-button-clicked :bottom)}] + [:div.constraint-button.left + {:class (classnames :active (or (= constraints-h :left) + (= constraints-h :leftright))) + :on-click (on-constraint-button-clicked :left)}] + [:div.constraint-button.right + {:class (classnames :active (or (= constraints-h :right) + (= constraints-h :leftright))) + :on-click (on-constraint-button-clicked :right)}] + [:div.constraint-button.centerv + {:class (classnames :active (= constraints-v :center)) + :on-click (on-constraint-button-clicked :centerv)}] + [:div.constraint-button.centerh + {:class (classnames :active (= constraints-h :center)) + :on-click (on-constraint-button-clicked :centerh)}]] + + [:div.constraints-form + [:div.row-flex + [:span.left-right i/full-screen] + [:select.input-select {:on-change (on-constraint-select-changed :constraints-h) + :value (d/name constraints-h "scale")} + (when (= constraints-h :multiple) + [:option {:value ""} (tr "settings.multiple")]) + [:option {:value "left"} (tr "workspace.options.constraints.left")] + [:option {:value "right"} (tr "workspace.options.constraints.right")] + [:option {:value "leftright"} (tr "workspace.options.constraints.leftright")] + [:option {:value "center"} (tr "workspace.options.constraints.center")] + [:option {:value "scale"} (tr "workspace.options.constraints.scale")]]] + [:div.row-flex + [:span.top-bottom i/full-screen] + [:select.input-select {:on-change (on-constraint-select-changed :constraints-v) + :value (d/name constraints-v "scale")} + (when (= constraints-v :multiple) + [:option {:value ""} (tr "settings.multiple")]) + [:option {:value "top"} (tr "workspace.options.constraints.top")] + [:option {:value "bottom"} (tr "workspace.options.constraints.bottom")] + [:option {:value "topbottom"} (tr "workspace.options.constraints.topbottom")] + [:option {:value "center"} (tr "workspace.options.constraints.center")] + [:option {:value "scale"} (tr "workspace.options.constraints.scale")]]] + (when first-level? + [:div.row-flex + [:div.fix-when {:class (classnames :active (:fixed-scroll values)) + :on-click on-fixed-scroll-clicked} + i/pin + [:span (tr "workspace.options.constraints.fix-when-scrolling")]]])]]]])])) diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 5434901e7..a745b6c07 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -1884,6 +1884,54 @@ msgstr "Canvas background" msgid "workspace.options.component" msgstr "Component" +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints" +msgstr "Constraints" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.left" +msgstr "Left" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.right" +msgstr "Right" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.leftright" +msgstr "Left & Right" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.center" +msgstr "Center" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.scale" +msgstr "Scale" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.top" +msgstr "Top" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.bottom" +msgstr "Bottom" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.topbottom" +msgstr "Top & Bottom" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.center" +msgstr "Center" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.scale" +msgstr "Scale" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.fix-when-scrolling" +msgstr "Fix when scrolling" + #: src/app/main/ui/workspace/sidebar/options.cljs msgid "workspace.options.design" msgstr "Design" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index e1a658885..bb520ed39 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -1876,6 +1876,54 @@ msgstr "Color de fondo" msgid "workspace.options.component" msgstr "Componente" +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints" +msgstr "Restricciones" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.left" +msgstr "Izquierda" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.right" +msgstr "Derecha" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.leftright" +msgstr "Izq. y Der." + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.center" +msgstr "Centro" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.scale" +msgstr "Escalar" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.top" +msgstr "Arriba" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.bottom" +msgstr "Abajo" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.topbottom" +msgstr "Arriba y Abajo" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.center" +msgstr "Centro" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.scale" +msgstr "Escalar" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +msgid "workspace.options.constraints.fix-when-scrolling" +msgstr "Fijo al desplazar" + #: src/app/main/ui/workspace/sidebar/options.cljs msgid "workspace.options.design" msgstr "DiseƱo" @@ -2632,4 +2680,4 @@ msgid "workspace.updates.update" msgstr "Actualizar" msgid "workspace.viewport.click-to-close-path" -msgstr "Pulsar para cerrar la ruta" \ No newline at end of file +msgstr "Pulsar para cerrar la ruta"