diff --git a/CHANGES.md b/CHANGES.md index 150041742..4be1cebe0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,7 +4,13 @@ ### :bug: Bugs fixed - Fix components groups items show the component name in list mode [Taiga #4770](https://tree.taiga.io/project/penpot/issue/4770) - +- Fix typing CMD+Z on MacOS turns the cursor into a Zoom cursor [Taiga #4778](https://tree.taiga.io/project/penpot/issue/4778) +- Fix white space on small screens [Taiga #4774](https://tree.taiga.io/project/penpot/issue/4774) +- Fix button spacing on delete acount modal [Taiga #4762](https://tree.taiga.io/project/penpot/issue/4762) +- Fix invitations input on team management and onboarding modal [Taiga #4760](https://tree.taiga.io/project/penpot/issue/4760) +- Fix weird numeration creating new elements in dashboard [Taiga #4755](https://tree.taiga.io/project/penpot/issue/4755) +- Fix can move shape with lens zoom active [Taiga #4787](https://tree.taiga.io/project/penpot/issue/4787) +- Fix social links broken [Taiga #4759](https://tree.taiga.io/project/penpot/issue/4759) ## 1.17.0 diff --git a/README.md b/README.md index cf16d463d..2a535c03c 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Being web based, Penpot is not dependent on operating systems or local installat Using SVG as no other design and prototyping tool does, Penpot files sport compatibility with most of the vectorial tools, are tech friendly and extremely easy to use on the web. We make sure you will always own your work.

- Open Source + Open Source

@@ -93,7 +93,7 @@ You will find the following categories: - [Penpot in your language](https://community.penpot.app/c/penpot-in-your-language/12)

- Community + Community

## Contributing ## diff --git a/backend/resources/app/emails-mjml/change-email/en.mjml b/backend/resources/app/emails-mjml/change-email/en.mjml index 392452a0a..f69c418dc 100644 --- a/backend/resources/app/emails-mjml/change-email/en.mjml +++ b/backend/resources/app/emails-mjml/change-email/en.mjml @@ -48,8 +48,8 @@ - - + + diff --git a/backend/resources/app/emails-mjml/invite-to-team/en.mjml b/backend/resources/app/emails-mjml/invite-to-team/en.mjml index 82816304c..886c7d1d6 100644 --- a/backend/resources/app/emails-mjml/invite-to-team/en.mjml +++ b/backend/resources/app/emails-mjml/invite-to-team/en.mjml @@ -41,8 +41,8 @@ - - + + diff --git a/backend/resources/app/emails-mjml/password-recovery/en.mjml b/backend/resources/app/emails-mjml/password-recovery/en.mjml index f43b8eade..89bc817b5 100644 --- a/backend/resources/app/emails-mjml/password-recovery/en.mjml +++ b/backend/resources/app/emails-mjml/password-recovery/en.mjml @@ -50,8 +50,8 @@ - - + + diff --git a/backend/resources/app/emails-mjml/register/en.mjml b/backend/resources/app/emails-mjml/register/en.mjml index cb539fc2d..38b774e13 100644 --- a/backend/resources/app/emails-mjml/register/en.mjml +++ b/backend/resources/app/emails-mjml/register/en.mjml @@ -47,8 +47,8 @@ - - + + diff --git a/backend/resources/app/emails/change-email/en.html b/backend/resources/app/emails/change-email/en.html index 3120f86ba..ad95fa641 100644 --- a/backend/resources/app/emails/change-email/en.html +++ b/backend/resources/app/emails/change-email/en.html @@ -103,9 +103,9 @@ @@ -143,7 +143,7 @@ - + @@ -157,9 +157,9 @@ @@ -225,7 +225,7 @@
- + @@ -239,9 +239,9 @@ @@ -271,7 +271,7 @@
- + @@ -285,9 +285,9 @@ @@ -425,7 +425,7 @@
@@ -321,7 +321,7 @@
@@ -341,7 +341,7 @@
@@ -361,7 +361,7 @@
@@ -370,7 +370,7 @@
@@ -381,7 +381,7 @@
- +
@@ -390,7 +390,7 @@
@@ -401,7 +401,7 @@
- +
@@ -411,9 +411,9 @@
- + @@ -439,9 +439,9 @@ diff --git a/backend/resources/app/emails/invite-to-team/en.html b/backend/resources/app/emails/invite-to-team/en.html index 340ac3429..881af47f4 100644 --- a/backend/resources/app/emails/invite-to-team/en.html +++ b/backend/resources/app/emails/invite-to-team/en.html @@ -103,9 +103,9 @@ @@ -143,7 +143,7 @@
- + @@ -157,9 +157,9 @@ @@ -215,7 +215,7 @@
- + @@ -229,9 +229,9 @@ @@ -261,7 +261,7 @@
- + @@ -275,9 +275,9 @@ @@ -415,7 +415,7 @@
@@ -311,7 +311,7 @@
@@ -331,7 +331,7 @@
@@ -351,7 +351,7 @@
@@ -360,7 +360,7 @@
@@ -371,7 +371,7 @@
- +
@@ -380,7 +380,7 @@
@@ -391,7 +391,7 @@
- +
@@ -401,9 +401,9 @@
- + @@ -429,9 +429,9 @@ diff --git a/backend/resources/app/emails/password-recovery/en.html b/backend/resources/app/emails/password-recovery/en.html index 2b2db5a21..14fe1a5f2 100644 --- a/backend/resources/app/emails/password-recovery/en.html +++ b/backend/resources/app/emails/password-recovery/en.html @@ -103,9 +103,9 @@ @@ -143,7 +143,7 @@
- + @@ -157,9 +157,9 @@ @@ -220,7 +220,7 @@
- + @@ -234,9 +234,9 @@ @@ -266,7 +266,7 @@
- + @@ -280,9 +280,9 @@ @@ -420,7 +420,7 @@
@@ -316,7 +316,7 @@
@@ -336,7 +336,7 @@
@@ -356,7 +356,7 @@
@@ -365,7 +365,7 @@
@@ -376,7 +376,7 @@
- +
@@ -385,7 +385,7 @@
@@ -396,7 +396,7 @@
- +
@@ -406,9 +406,9 @@
- + @@ -434,9 +434,9 @@ diff --git a/backend/resources/app/emails/register/en.html b/backend/resources/app/emails/register/en.html index d60e1dac8..4a425b69f 100644 --- a/backend/resources/app/emails/register/en.html +++ b/backend/resources/app/emails/register/en.html @@ -103,9 +103,9 @@ @@ -143,7 +143,7 @@
- + @@ -157,9 +157,9 @@ @@ -215,7 +215,7 @@
- + @@ -229,9 +229,9 @@ @@ -261,7 +261,7 @@
- + @@ -275,9 +275,9 @@ @@ -415,7 +415,7 @@
@@ -311,7 +311,7 @@
@@ -331,7 +331,7 @@
@@ -351,7 +351,7 @@
@@ -360,7 +360,7 @@
@@ -371,7 +371,7 @@
- +
@@ -380,7 +380,7 @@
@@ -391,7 +391,7 @@
- +
@@ -401,9 +401,9 @@
- + @@ -429,9 +429,9 @@ diff --git a/backend/src/app/rpc/commands/teams.clj b/backend/src/app/rpc/commands/teams.clj index ff07667e6..9ab23583c 100644 --- a/backend/src/app/rpc/commands/teams.clj +++ b/backend/src/app/rpc/commands/teams.clj @@ -473,7 +473,7 @@ (s/def ::team-id ::us/uuid) (s/def ::member-id ::us/uuid) ;; Temporarily disabled viewer role -;; https://tree.taiga.io/project/uxboxproject/issue/1083 +;; https://tree.taiga.io/project/penpot/issue/1083 ;; (s/def ::role #{:owner :admin :editor :viewer}) (s/def ::role #{:owner :admin :editor}) diff --git a/backend/test/backend_tests/rpc_comment_test.clj b/backend/test/backend_tests/rpc_comment_test.clj index d088f8b06..0cb812bad 100644 --- a/backend/test/backend_tests/rpc_comment_test.clj +++ b/backend/test/backend_tests/rpc_comment_test.clj @@ -154,7 +154,7 @@ (t/is (th/success? out)) (let [[thread :as result] (:result out)] (t/is (= 1 (count result))) - (t/is (= "Page-1" (:page-name thread))) + (t/is (= "Page 1" (:page-name thread))) (t/is (= "hello world" (:content thread))) (t/is (= 2 (:count-comments thread))) (t/is (true? (:is-resolved thread)))))) diff --git a/common/src/app/common/file_builder.cljc b/common/src/app/common/file_builder.cljc index 627ffc8a8..e2d61fa43 100644 --- a/common/src/app/common/file_builder.cljc +++ b/common/src/app/common/file_builder.cljc @@ -200,7 +200,7 @@ (assert (nil? (:current-component-id file))) (let [page-id (or (:id data) (uuid/next)) - page (-> (ctp/make-empty-page page-id "Page-1") + page (-> (ctp/make-empty-page page-id "Page 1") (d/deep-merge data))] (-> file (commit-change diff --git a/common/src/app/common/geom/shapes.cljc b/common/src/app/common/geom/shapes.cljc index be95e3416..5158ed32e 100644 --- a/common/src/app/common/geom/shapes.cljc +++ b/common/src/app/common/geom/shapes.cljc @@ -43,13 +43,13 @@ (defn bounding-box "Returns a rect that wraps the shape after all transformations applied." [shape] - ; TODO: perhaps we need to store this calculation in a shape attribute + ;; TODO: perhaps we need to store this calculation in a shape attribute (gpr/points->rect (:points shape))) (defn left-bound "Returns the lowest x coord of the shape BEFORE applying transformations." - ; TODO: perhaps some day we want after transformations, but for the - ; moment it's enough as is now. + ;; TODO: perhaps some day we want after transformations, but for the + ;; moment it's enough as is now. [shape] (or (:x shape) (:x (:selrect shape)))) ; Paths don't have :x attribute @@ -106,8 +106,8 @@ ([attr val1 val2 precision] (let [close-val? (fn [num1 num2] - (when (and (number? num1) (number? num2)) - (< (mth/abs (- num1 num2)) precision)))] + (when (and (number? num1) (number? num2)) + (< (mth/abs (- num1 num2)) precision)))] (cond (and (number? val1) (number? val2)) (close-val? val1 val2) diff --git a/common/src/app/common/geom/shapes/constraints.cljc b/common/src/app/common/geom/shapes/constraints.cljc index 6cdf6c5d9..6c4f24cc3 100644 --- a/common/src/app/common/geom/shapes/constraints.cljc +++ b/common/src/app/common/geom/shapes/constraints.cljc @@ -210,7 +210,7 @@ ;; after-vec will contain the side length of the grown side ;; we scale the shape by the diference and translate it by the start ;; displacement (so its left+top position is constant) - scale (/ (gpt/length after-vec) (gpt/length before-vec)) + scale (/ (gpt/length after-vec) (max 0.01 (gpt/length before-vec))) resize-origin (gpo/origin child-points-after) @@ -268,11 +268,11 @@ scale-x (if (= :scale constraints-h) 1 - (/ (gpo/width-points child-bb-before) (gpo/width-points child-bb-after))) + (/ (gpo/width-points child-bb-before) (max 0.01 (gpo/width-points child-bb-after)))) scale-y (if (= :scale constraints-v) 1 - (/ (gpo/height-points child-bb-before) (gpo/height-points child-bb-after))) + (/ (gpo/height-points child-bb-before) (max 0.01 (gpo/height-points child-bb-after)))) resize-vector (gpt/point scale-x scale-y) resize-origin (gpo/origin transformed-child-bounds) diff --git a/common/src/app/common/geom/shapes/flex_layout/lines.cljc b/common/src/app/common/geom/shapes/flex_layout/lines.cljc index a31e13ca5..00349c995 100644 --- a/common/src/app/common/geom/shapes/flex_layout/lines.cljc +++ b/common/src/app/common/geom/shapes/flex_layout/lines.cljc @@ -238,6 +238,30 @@ (and col? (< total-min-width rest-layout-width total-max-width) (not (ctl/auto-width? parent))) (distribute-space :line-width :line-min-width :line-max-width total-min-width rest-layout-width)) + ;; Add information to limit the growth of width: 100% shapes to the bounds of the layout + layout-lines + (cond + row? + (->> layout-lines + (reduce + (fn [[result rest-layout-height] {:keys [line-height] :as line}] + [(conj result (assoc line :to-bound-height rest-layout-height)) + (- rest-layout-height line-height layout-gap-row)]) + [[] layout-height]) + (first)) + + col? + (->> layout-lines + (reduce + (fn [[result rest-layout-width] {:keys [line-width] :as line}] + [(conj result (assoc line :to-bound-width rest-layout-width)) + (- rest-layout-width line-width layout-gap-col)]) + [[] layout-width]) + (first)) + + :else + layout-lines) + [total-width total-height] (->> layout-lines (reduce add-lines [0 0])) base-p (flp/get-base-line parent layout-bounds total-width total-height num-lines)] diff --git a/common/src/app/common/geom/shapes/flex_layout/modifiers.cljc b/common/src/app/common/geom/shapes/flex_layout/modifiers.cljc index 072eed1b3..72994b873 100644 --- a/common/src/app/common/geom/shapes/flex_layout/modifiers.cljc +++ b/common/src/app/common/geom/shapes/flex_layout/modifiers.cljc @@ -20,7 +20,7 @@ transform-inverse child child-origin child-width - {:keys [children-data line-width] :as layout-data}] + {:keys [children-data line-width to-bound-width] :as layout-data}] (cond (ctl/row? parent) @@ -30,8 +30,9 @@ :modifiers (ctm/resize-modifiers (gpt/point fill-scale 1) child-origin transform transform-inverse)}) (ctl/col? parent) - (let [target-width (max (- line-width (ctl/child-width-margin child)) 0.01) - max-width (ctl/child-max-width child) + (let [line-width (min line-width (or to-bound-width line-width)) + target-width (max (- line-width (ctl/child-width-margin child)) 0.01) + max-width (max (ctl/child-max-width child) 0.01) target-width (min max-width target-width) fill-scale (/ target-width child-width)] {:width target-width @@ -43,7 +44,7 @@ transform transform-inverse child child-origin child-height - {:keys [children-data line-height] :as layout-data}] + {:keys [children-data line-height to-bound-height] :as layout-data}] (cond (ctl/col? parent) @@ -53,8 +54,9 @@ :modifiers (ctm/resize-modifiers (gpt/point 1 fill-scale) child-origin transform transform-inverse)}) (ctl/row? parent) - (let [target-height (max (- line-height (ctl/child-height-margin child)) 0.01) - max-height (ctl/child-max-height child) + (let [line-height (min line-height (or to-bound-height line-height)) + target-height (max (- line-height (ctl/child-height-margin child)) 0.01) + max-height (max (ctl/child-max-height child) 0.01) target-height (min max-height target-height) fill-scale (/ target-height child-height)] {:height target-height @@ -71,8 +73,13 @@ (when (or (ctl/fill-width? child) (ctl/fill-height? child)) (gtr/calculate-geometry @parent-bounds)) - fill-width (when (ctl/fill-width? child) (calc-fill-width-data parent transform transform-inverse child child-origin child-width layout-line)) - fill-height (when (ctl/fill-height? child) (calc-fill-height-data parent transform transform-inverse child child-origin child-height layout-line)) + fill-width + (when (ctl/fill-width? child) + (calc-fill-width-data parent transform transform-inverse child child-origin child-width layout-line)) + + fill-height + (when (ctl/fill-height? child) + (calc-fill-height-data parent transform transform-inverse child child-origin child-height layout-line)) child-width (or (:width fill-width) child-width) child-height (or (:height fill-height) child-height) diff --git a/common/src/app/common/geom/shapes/flex_layout/positions.cljc b/common/src/app/common/geom/shapes/flex_layout/positions.cljc index 2e2e44bfd..77ce23d0b 100644 --- a/common/src/app/common/geom/shapes/flex_layout/positions.cljc +++ b/common/src/app/common/geom/shapes/flex_layout/positions.cljc @@ -20,9 +20,13 @@ hv (partial gpo/start-hv layout-bounds) vv (partial gpo/start-vv layout-bounds) - end? (ctl/content-end? parent) - center? (ctl/content-center? parent) - around? (ctl/content-around? parent) + wrap? (ctl/wrap? parent) + + end? (or (and wrap? (ctl/content-end? parent)) + (and (not wrap?) (ctl/align-items-end? parent))) + center? (or (and wrap? (ctl/content-center? parent)) + (and (not wrap?) (ctl/align-items-center? parent))) + around? (and wrap? (ctl/content-around? parent)) ;; Adjust the totals so it takes into account the gaps [layout-gap-row layout-gap-col] (ctl/gaps parent) diff --git a/common/src/app/common/geom/shapes/points.cljc b/common/src/app/common/geom/shapes/points.cljc index d04ad06a0..206494d49 100644 --- a/common/src/app/common/geom/shapes/points.cljc +++ b/common/src/app/common/geom/shapes/points.cljc @@ -54,11 +54,11 @@ (defn width-points [[p0 p1 _ _]] - (gpt/length (gpt/to-vec p0 p1))) + (max 0.01 (gpt/length (gpt/to-vec p0 p1)))) (defn height-points [[p0 _ _ p3]] - (gpt/length (gpt/to-vec p0 p3))) + (max 0.01 (gpt/length (gpt/to-vec p0 p3)))) (defn pad-points [[p0 p1 p2 p3 :as points] pad-top pad-right pad-bottom pad-left] diff --git a/common/src/app/common/math.cljc b/common/src/app/common/math.cljc index 7760a974c..d3f724ee9 100644 --- a/common/src/app/common/math.cljc +++ b/common/src/app/common/math.cljc @@ -34,7 +34,7 @@ (defn abs [v] #?(:cljs (js/Math.abs v) - :clj (Math/abs v))) + :clj (Math/abs (double v)))) (defn sin "Returns the sine of a number" diff --git a/common/src/app/common/pages.cljc b/common/src/app/common/pages.cljc index 0af339722..2d52f03c4 100644 --- a/common/src/app/common/pages.cljc +++ b/common/src/app/common/pages.cljc @@ -19,6 +19,8 @@ (dm/export common/file-version) (dm/export common/default-color) (dm/export common/component-sync-attrs) +(dm/export common/retrieve-used-names) +(dm/export common/generate-unique-name) ;; Focus (dm/export focus/focus-objects) diff --git a/common/src/app/common/pages/common.cljc b/common/src/app/common/pages/common.cljc index c738b22d4..7e392cc92 100644 --- a/common/src/app/common/pages/common.cljc +++ b/common/src/app/common/pages/common.cljc @@ -7,7 +7,10 @@ (ns app.common.pages.common (:require [app.common.colors :as clr] - [app.common.uuid :as uuid])) + [app.common.data :as d] + [app.common.spec :as us] + [app.common.uuid :as uuid] + [clojure.spec.alpha :as s])) (def file-version 20) (def default-color clr/gray-20) @@ -580,3 +583,31 @@ :layout-item-min-w :layout-item-align-self}}) +(defn retrieve-used-names + "Return a set with the all unique names used in the + elements (any entity thas has a :name)" + [elements] + (into #{} (comp (map :name) (remove nil?)) (vals elements))) + +(defn- extract-numeric-suffix + [basename] + (if-let [[_ p1 p2] (re-find #"(.*) ([0-9]+)$" basename)] + [p1 (+ 1 (d/parse-integer p2))] + [basename 1])) + +(s/def ::set-of-strings + (s/every ::us/string :kind set?)) + +(defn generate-unique-name + "A unique name generator" + [used basename] + (us/assert! ::set-of-strings used) + (us/assert! ::us/string basename) + (if-not (contains? used basename) + basename + (let [[prefix initial] (extract-numeric-suffix basename)] + (loop [counter initial] + (let [candidate (str prefix " " counter)] + (if (contains? used candidate) + (recur (inc counter)) + candidate)))))) diff --git a/common/src/app/common/pages/helpers.cljc b/common/src/app/common/pages/helpers.cljc index 973c1a714..f3f6f0dbb 100644 --- a/common/src/app/common/pages/helpers.cljc +++ b/common/src/app/common/pages/helpers.cljc @@ -109,6 +109,20 @@ (recur (conj result parent-id) parent-id) result)))) +(defn get-parent-ids-with-index + "Returns a tuple with the list of parents and a map with the position within each parent" + [objects shape-id] + (loop [parent-list [] + parent-indices {} + current shape-id] + (let [parent-id (dm/get-in objects [current :parent-id]) + parent (get objects parent-id)] + (if (and (some? parent) (not= parent-id current)) + (let [parent-list (conj parent-list parent-id) + parent-indices (assoc parent-indices parent-id (d/index-of (:shapes parent) current))] + (recur parent-list parent-indices parent-id)) + [parent-list parent-indices])))) + (defn get-siblings-ids [objects id] (let [parent (get-parent objects id)] diff --git a/common/src/app/common/types/container.cljc b/common/src/app/common/types/container.cljc index 53185b092..7c9950a8b 100644 --- a/common/src/app/common/types/container.cljc +++ b/common/src/app/common/types/container.cljc @@ -9,6 +9,7 @@ [app.common.data.macros :as dm] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] + [app.common.pages.common :as common] [app.common.spec :as us] [app.common.types.shape-tree :as ctst] [clojure.spec.alpha :as s])) @@ -130,7 +131,7 @@ delta (gpt/subtract position orig-pos) objects (:objects container) - unames (volatile! (ctst/retrieve-used-names objects)) + unames (volatile! (common/retrieve-used-names objects)) frame-id (ctst/frame-id-by-position objects (gpt/add orig-pos delta)) frame-ids-map (volatile! {}) diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index d2143101b..8bc075b1e 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -73,7 +73,7 @@ ([file-id page-id] (let [page (when (some? page-id) - (ctp/make-empty-page page-id "Page-1"))] + (ctp/make-empty-page page-id "Page 1"))] (cond-> (-> empty-file-data (assoc :id file-id)) diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc index 8d619cc6c..9be46671f 100644 --- a/common/src/app/common/types/shape/layout.cljc +++ b/common/src/app/common/types/shape/layout.cljc @@ -275,6 +275,21 @@ (or (= :stretch layout-align-content) (nil? layout-align-content))) +(defn align-items-center? + [{:keys [layout-align-items]}] + (= layout-align-items :center)) + +(defn align-items-start? + [{:keys [layout-align-items]}] + (= layout-align-items :start)) + +(defn align-items-end? + [{:keys [layout-align-items]}] + (= layout-align-items :end)) + +(defn align-items-stretch? + [{:keys [layout-align-items]}] + (= layout-align-items :stretch)) (defn reverse? [{:keys [layout-flex-dir]}] diff --git a/common/src/app/common/types/shape_tree.cljc b/common/src/app/common/types/shape_tree.cljc index aebcb9d1c..e6a41b5d8 100644 --- a/common/src/app/common/types/shape_tree.cljc +++ b/common/src/app/common/types/shape_tree.cljc @@ -132,43 +132,34 @@ (defn get-base [objects id-a id-b] - (let [parents-a (reverse (cons id-a (cph/get-parent-ids objects id-a))) - parents-b (reverse (cons id-b (cph/get-parent-ids objects id-b))) + (let [[parents-a parents-a-index] (cph/get-parent-ids-with-index objects id-a) + [parents-b parents-b-index] (cph/get-parent-ids-with-index objects id-b) - [base base-child-a base-child-b] - (loop [parents-a (rest parents-a) - parents-b (rest parents-b) - base uuid/zero] - (cond - (not= (first parents-a) (first parents-b)) - [base (first parents-a) (first parents-b)] + parents-a (cons id-a parents-a) + parents-b (into #{id-b} parents-b) - (or (empty? parents-a) (empty? parents-b)) - [uuid/zero (first parents-a) (first parents-b)] + ;; Search for the common frame in order + base (or (d/seek parents-b parents-a) uuid/zero) - :else - (recur (rest parents-a) (rest parents-b) (first parents-a)))) + idx-a (get parents-a-index base) + idx-b (get parents-b-index base)] - index-base-a (when base-child-a (cph/get-position-on-parent objects base-child-a)) - index-base-b (when base-child-b (cph/get-position-on-parent objects base-child-b))] - - [base index-base-a index-base-b])) + [base idx-a idx-b])) (defn is-shape-over-shape? [objects base-shape-id over-shape-id] (let [[base index-a index-b] (get-base objects base-shape-id over-shape-id)] (cond + ;; The base the base shape, so the other item is bellow (= base base-shape-id) - (let [object (get objects base-shape-id)] - (or (cph/frame-shape? object) - (cph/root-frame? object))) + false + ;; The base is the testing over, so it's over (= base over-shape-id) - (let [object (get objects over-shape-id)] - (or (not (cph/frame-shape? object)) - (not (cph/root-frame? object)))) + true + ;; Check which index is lower :else (< index-a index-b)))) @@ -284,35 +275,6 @@ [frame] (not (mth/almost-zero? (:rotation frame 0)))) -(defn retrieve-used-names - [objects] - (into #{} (comp (map :name) (remove nil?)) (vals objects))) - -(defn- extract-numeric-suffix - [basename] - (if-let [[_ p1 p2] (re-find #"(.*)-([0-9]+)$" basename)] - [p1 (+ 1 (d/parse-integer p2))] - [basename 1])) - -(s/def ::set-of-strings - (s/every ::us/string :kind set?)) - -(defn generate-unique-name - "A unique name generator" - [used basename] - (us/assert! ::set-of-strings used) - (us/assert! ::us/string basename) - ;; We have add a condition because UX doesn't want numbers on - ;; layer names. - (if-not (contains? used basename) - basename - (let [[prefix initial] (extract-numeric-suffix basename)] - (loop [counter initial] - (let [candidate (str prefix "-" counter)] - (if (contains? used candidate) - (recur (inc counter)) - candidate)))))) - (defn clone-object "Gets a copy of the object and all its children, with new ids and with the parent-children links correctly set. Admits functions diff --git a/common/test/common_tests/helpers/files.cljc b/common/test/common_tests/helpers/files.cljc index 694505139..66fe15034 100644 --- a/common/test/common_tests/helpers/files.cljc +++ b/common/test/common_tests/helpers/files.cljc @@ -126,7 +126,7 @@ (fn [file-data] (let [id (uuid/next) props (merge {:id id - :name "Color-1" + :name "Color 1" :color "#000000" :opacity 1} props)] @@ -140,7 +140,7 @@ (fn [file-data] (let [id (uuid/next) props (merge {:id id - :name "Typography-1" + :name "Typography 1" :font-id "sourcesanspro" :font-family "sourcesanspro" :font-size "14" diff --git a/common/test/common_tests/types_file_test.cljc b/common/test/common_tests/types_file_test.cljc index d4af3db5b..bf8a04423 100644 --- a/common/test/common_tests/types_file_test.cljc +++ b/common/test/common_tests/types_file_test.cljc @@ -101,7 +101,7 @@ ;; false) (t/is (= (count pages) 2)) - (t/is (= (:name (first pages)) "Page-1")) + (t/is (= (:name (first pages)) "Page 1")) (t/is (= (:name (second pages)) "Library backup")) (t/is (= (count components) 1)) diff --git a/frontend/resources/styles/main/partials/dashboard-team.scss b/frontend/resources/styles/main/partials/dashboard-team.scss index ed8733583..edc8d4f5a 100644 --- a/frontend/resources/styles/main/partials/dashboard-team.scss +++ b/frontend/resources/styles/main/partials/dashboard-team.scss @@ -29,7 +29,35 @@ .custom-input { width: 100%; - height: 115px; + min-height: 116px; + max-height: 176px; + overflow-y: hidden; + input { + &.no-padding { + padding-top: 12px; + } + min-height: 40px; + } + .selected-items { + gap: 8px; + padding: 8px; + max-height: 132px; + overflow-y: scroll; + .selected-item { + .around { + height: 24px; + display: flex; + align-items: center; + justify-content: flex-start; + width: fit-content; + .icon { + display: flex; + align-items: center; + justify-content: center; + } + } + } + } } .custom-select { diff --git a/frontend/resources/styles/main/partials/modal.scss b/frontend/resources/styles/main/partials/modal.scss index 456364fb6..580ffe0f6 100644 --- a/frontend/resources/styles/main/partials/modal.scss +++ b/frontend/resources/styles/main/partials/modal.scss @@ -184,6 +184,7 @@ .modal-footer .action-buttons { justify-content: space-around; + gap: 15px; } .fields-container { @@ -1541,8 +1542,52 @@ .onboarding-team-members { .team-left { + padding: 42px 64px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: auto; form { - margin-top: 32px; + margin-top: 5px; + .invite-row { + .custom-input { + width: 100%; + min-height: 80px; + height: fit-content; + max-height: 176px; + overflow-y: hidden; + input { + &.no-padding { + padding-top: 12px; + } + min-height: 40px; + } + .selected-items { + gap: 7px; + padding: 7px; + max-height: 132px; + overflow-y: scroll; + .selected-item { + .around { + height: 24px; + display: flex; + align-items: center; + justify-content: flex-start; + width: fit-content; + .icon { + display: flex; + align-items: center; + justify-content: center; + } + } + } + } + } + } + .buttons { + margin-top: 12px; + } } } } diff --git a/frontend/resources/styles/main/partials/workspace.scss b/frontend/resources/styles/main/partials/workspace.scss index 1128ba62f..1331b47e0 100644 --- a/frontend/resources/styles/main/partials/workspace.scss +++ b/frontend/resources/styles/main/partials/workspace.scss @@ -17,7 +17,7 @@ $height-palette-max: 80px; #workspace { width: 100vw; - height: 100vh; + height: 100%; user-select: none; background-color: $color-canvas; display: grid; @@ -37,6 +37,8 @@ $height-palette-max: 80px; .left-toolbar { grid-area: toolbar; width: $width-left-toolbar; + overflow-y: scroll; + overflow-x: hidden; } .settings-bar.settings-bar-left { diff --git a/frontend/src/app/main/data/dashboard.cljs b/frontend/src/app/main/data/dashboard.cljs index 3cd752a52..659b2afe9 100644 --- a/frontend/src/app/main/data/dashboard.cljs +++ b/frontend/src/app/main/data/dashboard.cljs @@ -7,6 +7,7 @@ (ns app.main.data.dashboard (:require [app.common.data :as d] + [app.common.pages :as cp] [app.common.spec :as us] [app.common.uuid :as uuid] [app.config :as cf] @@ -664,10 +665,12 @@ (ptk/reify ::create-project ptk/WatchEvent (watch [_ state _] - (let [name (name (gensym (str (tr "dashboard.new-project-prefix") " "))) - team-id (:current-team-id state) - params {:name name - :team-id team-id} + (let [projects (get state :dashboard-projects) + unames (cp/retrieve-used-names projects) + name (cp/generate-unique-name unames (str (tr "dashboard.new-project-prefix") " 1")) + team-id (:current-team-id state) + params {:name name + :team-id team-id} {:keys [on-success on-error] :or {on-success identity on-error rx/throw}} (meta params)] @@ -875,7 +878,9 @@ :or {on-success identity on-error rx/throw}} (meta params) - name (name (gensym (str (tr "dashboard.new-file-prefix") " "))) + files (get state :dashboard-files) + unames (cp/retrieve-used-names files) + name (cp/generate-unique-name unames (str (tr "dashboard.new-file-prefix") " 1")) features (cond-> #{} (features/active-feature? state :components-v2) (conj "components/v2")) @@ -1067,8 +1072,12 @@ pparams (:path-params route) in-project? (contains? pparams :project-id) name (if in-project? - (name (gensym (str (tr "dashboard.new-file-prefix") " "))) - (name (gensym (str (tr "dashboard.new-project-prefix") " ")))) + (let [files (get state :dashboard-files) + unames (cp/retrieve-used-names files)] + (cp/generate-unique-name unames (str (tr "dashboard.new-file-prefix") " 1"))) + (let [projects (get state :dashboard-projects) + unames (cp/retrieve-used-names projects)] + (cp/generate-unique-name unames (str (tr "dashboard.new-project-prefix") " 1")))) params (if in-project? {:project-id (:project-id pparams) :name name} diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index a57ec88d6..08c17de41 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -15,6 +15,7 @@ [app.common.geom.proportions :as gpp] [app.common.geom.shapes :as gsh] [app.common.logging :as log] + [app.common.pages :as cp] [app.common.pages.changes-builder :as pcb] [app.common.pages.helpers :as cph] [app.common.spec :as us] @@ -408,8 +409,8 @@ ptk/WatchEvent (watch [it state _] (let [pages (get-in state [:workspace-data :pages-index]) - unames (ctst/retrieve-used-names pages) - name (ctst/generate-unique-name unames "Page-1") + unames (cp/retrieve-used-names pages) + name (cp/generate-unique-name unames "Page 1") changes (-> (pcb/empty-changes it) (pcb/add-empty-page id name))] @@ -423,9 +424,9 @@ (watch [it state _] (let [id (uuid/next) pages (get-in state [:workspace-data :pages-index]) - unames (ctst/retrieve-used-names pages) + unames (cp/retrieve-used-names pages) page (get-in state [:workspace-data :pages-index page-id]) - name (ctst/generate-unique-name unames (:name page)) + name (cp/generate-unique-name unames (:name page)) no_thumbnails_objects (->> (:objects page) (d/mapm (fn [_ val] (dissoc val :use-for-thumbnail?)))) diff --git a/frontend/src/app/main/data/workspace/interactions.cljs b/frontend/src/app/main/data/workspace/interactions.cljs index 3eefbff6c..9a141f22d 100644 --- a/frontend/src/app/main/data/workspace/interactions.cljs +++ b/frontend/src/app/main/data/workspace/interactions.cljs @@ -8,6 +8,7 @@ (:require [app.common.data :as d] [app.common.geom.point :as gpt] + [app.common.pages :as cp] [app.common.pages.changes-builder :as pcb] [app.common.pages.helpers :as cph] [app.common.spec :as us] @@ -33,7 +34,7 @@ flows (get-in page [:options :flows] []) unames (into #{} (map :name flows)) - name (ctst/generate-unique-name unames "Flow-1") + name (cp/generate-unique-name unames "Flow 1") new-flow {:id (uuid/next) :name name diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 78c80455a..261b3ba5b 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -73,7 +73,7 @@ (pcb/with-objects objects))] (let [group-name (if (= 1 (count shapes)) (:name (first shapes)) - "Component-1")] + "Component 1")] (dwg/prepare-create-group it objects page-id diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 48d1b4424..6ad54b229 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -15,7 +15,6 @@ [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.common.types.page :as ctp] - [app.common.types.shape-tree :as ctt] [app.common.types.shape.interactions :as ctsi] [app.common.uuid :as uuid] [app.main.data.modal :as md] @@ -290,7 +289,7 @@ move to the desired position, and recalculate parents and frames as needed." [all-objects page ids delta it] (let [shapes (map (d/getf all-objects) ids) - unames (volatile! (ctt/retrieve-used-names (:objects page))) + unames (volatile! (cp/retrieve-used-names (:objects page))) update-unames! (fn [new-name] (vswap! unames conj new-name)) all-ids (reduce #(into %1 (cons %2 (cph/get-children-ids all-objects %2))) (d/ordered-set) ids) ids-map (into {} (map #(vector % (uuid/next))) all-ids) @@ -367,7 +366,7 @@ (let [update-flows (fn [flows] (reduce (fn [flows frame] - (let [name (ctt/generate-unique-name @unames "Flow-1") + (let [name (cp/generate-unique-name @unames "Flow 1") _ (vswap! unames conj name) new-flow {:id (uuid/next) :name name diff --git a/frontend/src/app/main/data/workspace/shape_layout.cljs b/frontend/src/app/main/data/workspace/shape_layout.cljs index 9734c6179..6e7c6df84 100644 --- a/frontend/src/app/main/data/workspace/shape_layout.cljs +++ b/frontend/src/app/main/data/workspace/shape_layout.cljs @@ -271,16 +271,89 @@ (ptk/data-event :layout/update ids) (dwu/commit-undo-transaction undo-id)))))) +(defn fix-child-sizing + [objects parent-changes shape] + + (let [parent (-> (cph/get-parent objects (:id shape)) + (d/deep-merge parent-changes)) + + auto-width? (ctl/auto-width? parent) + auto-height? (ctl/auto-height? parent) + col? (ctl/col? parent) + row? (ctl/row? parent) + + all-children (->> parent :shapes (map (d/getf objects)))] + + (cond-> shape + ;; If the parent is hug width and the direction column + ;; change to fixed when ALL children are fill + (and col? auto-width? (every? ctl/fill-width? all-children)) + (assoc :layout-item-h-sizing :fix) + + ;; If the parent is hug height and the direction is column + ;; change to fixed when ANY children is fill + (and col? auto-height? (ctl/fill-height? shape)) + (assoc :layout-item-v-sizing :fix) + + ;; If the parent is hug width and the direction row + ;; change to fixed when ANY children is fill + (and row? auto-width? (ctl/fill-width? shape)) + (assoc :layout-item-h-sizing :fix) + + ;; If the parent is hug height and the direction row + ;; change to fixed when ALL children are fill + (and row? auto-height? (every? ctl/fill-height? all-children)) + (assoc :layout-item-v-sizing :fix)))) + +(defn fix-parent-sizing + [objects ids-set changes parent] + + (let [auto-width? (ctl/auto-width? parent) + auto-height? (ctl/auto-height? parent) + col? (ctl/col? parent) + row? (ctl/row? parent) + + all-children + (->> parent :shapes + (map (d/getf objects)) + (map (fn [shape] + (if (contains? ids-set (:id shape)) + (d/deep-merge shape changes) + shape))))] + + (cond-> parent + ;; Col layout and parent is hug-width if all children are fill-width + ;; change parent to fixed + (and col? auto-width? (every? ctl/fill-width? all-children)) + (assoc :layout-item-h-sizing :fix) + + ;; Col layout and parent is hug-height if any children is fill-height + ;; change parent to fixed + (and col? auto-height? (some ctl/fill-height? all-children)) + (assoc :layout-item-v-sizing :fix) + + ;; Row layout and parent is hug-width if any children is fill-width + ;; change parent to fixed + (and row? auto-width? (some ctl/fill-width? all-children)) + (assoc :layout-item-h-sizing :fix) + + ;; Row layout and parent is hug-height if all children are fill-height + ;; change parent to fixed + (and row? auto-height? (every? ctl/fill-height? all-children)) + (assoc :layout-item-v-sizing :fix)))) + (defn update-layout-child [ids changes] (ptk/reify ::update-layout-child ptk/WatchEvent (watch [_ state _] (let [objects (wsh/lookup-page-objects state) + children-ids (->> ids (mapcat #(cph/get-children-ids objects %))) parent-ids (->> ids (map #(cph/get-parent-id objects %))) - layout-ids (->> ids (filter (comp ctl/layout? (d/getf objects)))) undo-id (js/Symbol)] (rx/of (dwu/start-undo-transaction undo-id) (dwc/update-shapes ids #(d/deep-merge (or % {}) changes)) - (ptk/data-event :layout/update (d/concat-vec layout-ids parent-ids)) + (dwc/update-shapes children-ids (partial fix-child-sizing objects changes)) + (dwc/update-shapes parent-ids (partial fix-parent-sizing objects (set ids) changes)) + (ptk/data-event :layout/update ids) (dwu/commit-undo-transaction undo-id)))))) diff --git a/frontend/src/app/main/data/workspace/svg_upload.cljs b/frontend/src/app/main/data/workspace/svg_upload.cljs index 07b510349..e807d1937 100644 --- a/frontend/src/app/main/data/workspace/svg_upload.cljs +++ b/frontend/src/app/main/data/workspace/svg_upload.cljs @@ -12,6 +12,7 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.math :as mth] + [app.common.pages :as cp] [app.common.pages.changes-builder :as pcb] [app.common.pages.helpers :as cph] [app.common.spec :as us :refer [max-safe-int min-safe-int]] @@ -493,7 +494,7 @@ (- y vb-y (/ vb-height 2)) y)) - unames (ctst/retrieve-used-names objects) + unames (cp/retrieve-used-names objects) svg-name (str/replace (:name svg-data) ".svg" "") diff --git a/frontend/src/app/main/data/workspace/thumbnails.cljs b/frontend/src/app/main/data/workspace/thumbnails.cljs index 78740ac67..d012264d0 100644 --- a/frontend/src/app/main/data/workspace/thumbnails.cljs +++ b/frontend/src/app/main/data/workspace/thumbnails.cljs @@ -77,6 +77,11 @@ ;; Delete the thumbnail first so if we interrupt we can regenerate after (->> (rp/cmd! :upsert-file-object-thumbnail params) (rx/catch #(rx/empty))) + + ;; Remove the thumbnail temporary. If the user changes pages the thumbnail is regenerated + (rx/of #(update % :workspace-thumbnails assoc object-id nil)) + + ;; Send the update to the back-end (->> blob-result (rx/merge-map (fn [blob] diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index 262aa8139..59c91bbd6 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -484,6 +484,15 @@ (some (partial ctl/layout-immediate-child? objects)))) workspace-page-objects)) +(defn all-layout-child? + [ids] + (l/derived + (fn [objects] + (->> ids + (map (d/getf objects)) + (every? (partial ctl/layout-immediate-child? objects)))) + workspace-page-objects)) + (defn get-flex-child-viewer [ids page-id] (l/derived diff --git a/frontend/src/app/main/ui/components/forms.cljs b/frontend/src/app/main/ui/components/forms.cljs index f25358719..fab3f476c 100644 --- a/frontend/src/app/main/ui/components/forms.cljs +++ b/frontend/src/app/main/ui/components/forms.cljs @@ -130,7 +130,7 @@ (cond (and touched? (:message error)) [:span.error {:id (dm/str "error-" input-name) - :data-test (clojure.string/join [data-test "-error"]) }(tr (:message error))] + :data-test (clojure.string/join [data-test "-error"])} (tr (:message error))] (string? hint) [:span.hint hint])]])) @@ -328,7 +328,13 @@ remove-item! (mf/use-fn (fn [item] - (swap! items #(into [] (remove (fn [x] (= x item))) %))))] + (swap! items #(into [] (remove (fn [x] (= x item))) %)))) + + manage-key-down + (mf/use-fn + (fn [item event] + (when (kbd/enter? event) + (remove-item! item))))] (mf/with-effect [result @value] (let [val (cond-> @value trim str/trim) @@ -337,14 +343,6 @@ (update-form! values))) [:div {:class klass} - (when-let [items (seq @items)] - [:div.selected-items - (for [item items] - [:div.selected-item {:key (:text item)} - [:span.around {:class (when-not (:valid item) "invalid")} - [:span.text (:text item)] - [:span.icon {:on-click #(remove-item! item)} i/cross]]])]) - [:input {:id (name input-name) :class in-klass :type "text" @@ -355,4 +353,14 @@ :value @value :on-change on-change :placeholder (when empty? label)}] - [:label {:for (name input-name)} label]])) + [:label {:for (name input-name)} label] + + (when-let [items (seq @items)] + [:div.selected-items + (for [item items] + [:div.selected-item {:key (:text item) + :tab-index "0" + :on-key-down (partial manage-key-down item)} + [:span.around {:class (when-not (:valid item) "invalid")} + [:span.text (:text item)] + [:span.icon {:on-click #(remove-item! item)} i/cross]]])])])) diff --git a/frontend/src/app/main/ui/dashboard/team.cljs b/frontend/src/app/main/ui/dashboard/team.cljs index 983b73d04..da8d7c0e1 100644 --- a/frontend/src/app/main/ui/dashboard/team.cljs +++ b/frontend/src/app/main/ui/dashboard/team.cljs @@ -82,7 +82,7 @@ (when (:is-admin permissions) {:value "admin" :label (tr "labels.admin")}) ;; Temporarily disabled viewer roles - ;; https://tree.taiga.io/project/uxboxproject/issue/1083 + ;; https://tree.taiga.io/project/penpot/issue/1083 ;; {:value "viewer" :label (tr "labels.viewer")} ] (filterv identity))) @@ -209,7 +209,7 @@ [:li {:on-click set-admin} (tr "labels.admin")] [:li {:on-click set-editor} (tr "labels.editor")] ;; Temporarily disabled viewer role - ;; https://tree.taiga.io/project/uxboxproject/issue/1083 + ;; https://tree.taiga.io/project/penpot/issue/1083 ;; [:li {:on-click set-viewer} (tr "labels.viewer")] (when you-owner? [:li {:on-click (partial set-owner member)} (tr "labels.owner")])]]])) diff --git a/frontend/src/app/main/ui/workspace/shapes/frame/thumbnail_render.cljs b/frontend/src/app/main/ui/workspace/shapes/frame/thumbnail_render.cljs index 0900b8b75..697998f20 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame/thumbnail_render.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame/thumbnail_render.cljs @@ -27,23 +27,21 @@ (defn- draw-thumbnail-canvas! [canvas-node img-node] - (ts/raf - (fn [] - (try - (when (and (some? canvas-node) (some? img-node)) - (let [canvas-context (.getContext canvas-node "2d") - canvas-width (.-width canvas-node) - canvas-height (.-height canvas-node)] - (.clearRect canvas-context 0 0 canvas-width canvas-height) - (.drawImage canvas-context img-node 0 0 canvas-width canvas-height) + (try + (when (and (some? canvas-node) (some? img-node)) + (let [canvas-context (.getContext canvas-node "2d") + canvas-width (.-width canvas-node) + canvas-height (.-height canvas-node)] + (.clearRect canvas-context 0 0 canvas-width canvas-height) + (.drawImage canvas-context img-node 0 0 canvas-width canvas-height) - ;; Set a true on the next animation frame, we make sure the drawImage is completed - (ts/raf - #(dom/set-data! canvas-node "ready" "true")) - true)) - (catch :default err - (.error js/console err) - false))))) + ;; Set a true on the next animation frame, we make sure the drawImage is completed + (ts/raf + #(dom/set-data! canvas-node "ready" "true")) + true)) + (catch :default err + (.error js/console err) + false))) (defn- remove-image-loading "Remove the changes related to change a url for its embed value. This is necessary @@ -78,8 +76,12 @@ (gsh/selection-rect (concat [shape] all-children)) (-> shape :points gsh/points->selrect)) - fixed-width (mth/clamp width 250 2000) - fixed-height (/ (* height fixed-width) width) + [fixed-width fixed-height] + (if (> width height) + [(mth/clamp width 250 2000) + (/ (* height (mth/clamp width 250 2000)) width)] + [(/ (* width (mth/clamp height 250 2000)) height) + (mth/clamp height 250 2000)]) image-url (mf/use-state nil) observer-ref (mf/use-var nil) @@ -91,6 +93,10 @@ thumbnail-data-ref (mf/use-memo (mf/deps page-id id) #(refs/thumbnail-frame-data page-id id)) thumbnail-data (mf/deref thumbnail-data-ref) + ;; We only need the zoom level in Safari. For other browsers we don't want to activate this because + ;; will render for every zoom change + zoom (when (cf/check-browser? :safari) (mf/deref refs/selected-zoom)) + prev-thumbnail-data (hooks/use-previous thumbnail-data) ;; State to indicate to the parent that should render the frame @@ -108,7 +114,9 @@ (let [canvas-node (mf/ref-val frame-canvas-ref) img-node (mf/ref-val frame-image-ref)] (when (draw-thumbnail-canvas! canvas-node img-node) - (reset! image-url nil) + (when-not (cf/check-browser? :safari) + (reset! image-url nil)) + (when @show-frame-thumbnail (reset! show-frame-thumbnail false)) ;; If we don't have the thumbnail data saved (normally the first load) we update the data @@ -266,12 +274,16 @@ {:key (dm/str "thumbnail-canvas-" (:id shape)) :ref frame-canvas-ref :data-object-id (dm/str page-id (:id shape)) - :width fixed-width - :height fixed-height - ;; DEBUG - :style {:filter (when (and (not (cf/check-browser? :safari)) (debug? :thumbnails)) "invert(1)") - :width "100%" - :height "100%"}}]] + :width width + :height height + :style {;; Safari has a problem with the positioning of the canvas. All this is to fix Safari behavior + ;; https://bugs.webkit.org/show_bug.cgi?id=23113 + :display (when (cf/check-browser? :safari) "none") + :position "fixed" + :transform-origin "top left" + :transform (when (cf/check-browser? :safari) (dm/fmt "scale(%)" zoom)) + ;; DEBUG + :filter (when (debug? :thumbnails) "invert(1)")}}]] ;; Safari don't support filters so instead we add a rectangle around the thumbnail (when (and (cf/check-browser? :safari) (debug? :thumbnails)) @@ -285,10 +297,10 @@ (when (some? @image-url) [:foreignObject {:x x :y y - :width width - :height height} + :width fixed-width + :height fixed-height} [:img {:ref frame-image-ref :src @image-url - :width width - :height height + :width fixed-width + :height fixed-height :on-load on-image-load}]])])])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs index f8e76adf1..3ca283c50 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs @@ -11,6 +11,7 @@ [app.common.geom.shapes :as gsh] [app.common.pages.common :as cpc] [app.common.text :as txt] + [app.common.types.shape.layout :as ctl] [app.main.data.workspace.texts :as dwt] [app.main.refs :as refs] [app.main.ui.hooks :as hooks] @@ -26,7 +27,7 @@ [app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-attrs shadow-menu]] [app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu]] [app.main.ui.workspace.sidebar.options.menus.text :as ot] - [rumext.v2 :as mf])) + [rumext.v2 :as mf])) ;; Define how to read each kind of attribute depending on the shape type: ;; - shape: read the attribute directly from the shape. @@ -298,6 +299,13 @@ has-text? (contains? all-types :text) + has-layout-container? (->> shapes (some ctl/layout?)) + + all-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/all-layout-child? ids)) + all-layout-child? (mf/deref all-layout-child-ref) + + all-layout-container? (->> shapes (every? ctl/layout?)) + [measure-ids measure-values] (get-attrs shapes objects :measure) [layer-ids layer-values @@ -332,14 +340,15 @@ (when-not (empty? measure-ids) [:& measures-menu {:type type :all-types all-types :ids measure-ids :values measure-values :shape shapes}]) - [:& layout-container-menu {:type type :ids layout-container-ids :values layout-container-values :multiple true}] + (when has-layout-container? + [:& layout-container-menu {:type type :ids layout-container-ids :values layout-container-values :multiple true}]) - (when is-layout-child? + (when (or is-layout-child? has-layout-container?) [:& layout-item-menu {:type type :ids layout-item-ids - :is-layout-child? true - :is-layout-container? true + :is-layout-child? all-layout-child? + :is-layout-container? all-layout-container? :values layout-item-values}]) (when-not (or (empty? constraint-ids) is-layout-child?) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index f54cc621a..bde29f132 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -162,14 +162,14 @@ on-drag-over (actions/on-drag-over) on-drop (actions/on-drop file) on-mouse-down (actions/on-mouse-down @hover selected edition drawing-tool text-editing? node-editing? - drawing-path? create-comment? space? panning workspace-read-only?) + drawing-path? create-comment? space? panning z? workspace-read-only?) on-mouse-up (actions/on-mouse-up disable-paste) on-pointer-down (actions/on-pointer-down) on-pointer-enter (actions/on-pointer-enter in-viewport?) on-pointer-leave (actions/on-pointer-leave in-viewport?) on-pointer-move (actions/on-pointer-move move-stream) on-pointer-up (actions/on-pointer-up) - on-move-selected (actions/on-move-selected hover hover-ids selected space? workspace-read-only?) + on-move-selected (actions/on-move-selected hover hover-ids selected space? z? workspace-read-only?) on-menu-selected (actions/on-menu-selected hover hover-ids selected workspace-read-only?) on-frame-enter (actions/on-frame-enter frame-hover) diff --git a/frontend/src/app/main/ui/workspace/viewport/actions.cljs b/frontend/src/app/main/ui/workspace/viewport/actions.cljs index 4c9ab2cf5..8cf782224 100644 --- a/frontend/src/app/main/ui/workspace/viewport/actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/actions.cljs @@ -34,70 +34,71 @@ (defn on-mouse-down [{:keys [id blocked hidden type]} selected edition drawing-tool text-editing? - node-editing? drawing-path? create-comment? space? panning workspace-read-only?] + node-editing? drawing-path? create-comment? space? panning z? workspace-read-only?] (mf/use-callback (mf/deps id blocked hidden type selected edition drawing-tool text-editing? - node-editing? drawing-path? create-comment? @space? + node-editing? drawing-path? create-comment? @z? @space? panning workspace-read-only?) (fn [bevent] (when (or (dom/class? (dom/get-target bevent) "viewport-controls") (dom/class? (dom/get-target bevent) "viewport-selrect")) (dom/stop-propagation bevent) - (let [event (.-nativeEvent bevent) - ctrl? (kbd/ctrl? event) - meta? (kbd/meta? event) - shift? (kbd/shift? event) - alt? (kbd/alt? event) - mod? (kbd/mod? event) + (when-not @z? + (let [event (.-nativeEvent bevent) + ctrl? (kbd/ctrl? event) + meta? (kbd/meta? event) + shift? (kbd/shift? event) + alt? (kbd/alt? event) + mod? (kbd/mod? event) - left-click? (and (not panning) (= 1 (.-which event))) - middle-click? (and (not panning) (= 2 (.-which event)))] + left-click? (and (not panning) (= 1 (.-which event))) + middle-click? (and (not panning) (= 2 (.-which event)))] - (cond - (or middle-click? (and left-click? @space?)) - (do - (dom/prevent-default bevent) - (if mod? - (let [raw-pt (dom/get-client-position event) - pt (uwvv/point->viewport raw-pt)] - (st/emit! (dw/start-zooming pt))) - (st/emit! (dw/start-panning)))) + (cond + (or middle-click? (and left-click? @space?)) + (do + (dom/prevent-default bevent) + (if mod? + (let [raw-pt (dom/get-client-position event) + pt (uwvv/point->viewport raw-pt)] + (st/emit! (dw/start-zooming pt))) + (st/emit! (dw/start-panning)))) - left-click? - (do - (st/emit! (ms/->MouseEvent :down ctrl? shift? alt? meta?)) + left-click? + (do + (st/emit! (ms/->MouseEvent :down ctrl? shift? alt? meta?)) - (when (and (not= edition id) text-editing?) - (st/emit! dw/clear-edition-mode)) + (when (and (not= edition id) text-editing?) + (st/emit! dw/clear-edition-mode)) - (when (and (not text-editing?) - (not blocked) - (not hidden) - (not create-comment?) - (not drawing-path?)) - (cond - node-editing? + (when (and (not text-editing?) + (not blocked) + (not hidden) + (not create-comment?) + (not drawing-path?)) + (cond + node-editing? ;; Handle path node area selection - (when-not workspace-read-only? - (st/emit! (dwdp/handle-area-selection shift?))) + (when-not workspace-read-only? + (st/emit! (dwdp/handle-area-selection shift?))) - drawing-tool - (when-not workspace-read-only? - (st/emit! (dd/start-drawing drawing-tool))) + drawing-tool + (when-not workspace-read-only? + (st/emit! (dd/start-drawing drawing-tool))) - (or (not id) mod?) - (st/emit! (dw/handle-area-selection shift? mod?)) + (or (not id) mod?) + (st/emit! (dw/handle-area-selection shift? mod?)) - (not drawing-tool) - (when-not workspace-read-only? - (st/emit! (dw/start-move-selected id shift?)))))))))))) + (not drawing-tool) + (when-not workspace-read-only? + (st/emit! (dw/start-move-selected id shift?))))))))))))) (defn on-move-selected - [hover hover-ids selected space? workspace-read-only?] + [hover hover-ids selected space? z? workspace-read-only?] (mf/use-callback - (mf/deps @hover @hover-ids selected @space? workspace-read-only?) + (mf/deps @hover @hover-ids selected @space? @z? workspace-read-only?) (fn [bevent] (let [event (.-nativeEvent bevent) shift? (kbd/shift? event) @@ -110,7 +111,7 @@ (not @space?)) (dom/prevent-default bevent) (dom/stop-propagation bevent) - (when-not workspace-read-only? + (when-not (or workspace-read-only? @z?) (st/emit! (dw/start-move-selected)))))))) (defn on-frame-select diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs index d4dd8c624..e7270e7b9 100644 --- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs @@ -109,7 +109,8 @@ (defn setup-keyboard [alt? mod? space? z?] (hooks/use-stream ms/keyboard-alt #(reset! alt? %)) - (hooks/use-stream ms/keyboard-mod #(reset! mod? %)) + (hooks/use-stream ms/keyboard-mod #((reset! mod? %) + (when-not % (reset! z? false)))) ;; In mac after command+z there is no event for the release of the z key (hooks/use-stream ms/keyboard-space #(reset! space? %)) (hooks/use-stream ms/keyboard-z #(reset! z? %))) diff --git a/frontend/test/frontend_tests/state_components_sync_test.cljs b/frontend/test/frontend_tests/state_components_sync_test.cljs index bdf8a9b4a..538a809e9 100644 --- a/frontend/test/frontend_tests/state_components_sync_test.cljs +++ b/frontend/test/frontend_tests/state_components_sync_test.cljs @@ -166,12 +166,12 @@ ; ; [Page] ; Root Frame - ; Component-1* #--> Component-1 + ; Component 1* #--> Component 1 ; #{:shapes-group} ; Rect 2 ---> Rect 2 ; - ; [Component-1] - ; Component-1 + ; [Component 1] + ; Component 1 ; Rect 1 ; Rect 2 ; @@ -180,14 +180,14 @@ new-state (thp/id :instance1))] - (t/is (= (:name group) "Component-1")) + (t/is (= (:name group) "Component 1")) (t/is (= (:touched group) #{:shapes-group})) (t/is (not= (:shape-ref group) nil)) (t/is (= (:name shape2) "Rect 2")) (t/is (= (:touched shape2) nil)) (t/is (not= (:shape-ref shape2) nil)) - (t/is (= (:name c-group) "Component-1")) + (t/is (= (:name c-group) "Component 1")) (t/is (= (:touched c-group) nil)) (t/is (= (:shape-ref c-group) nil)) (t/is (= (:name c-shape2) "Rect 1")) @@ -227,14 +227,14 @@ ; ; [Page] ; Root Frame - ; Component-1* #--> Component-1 + ; Component 1* #--> Component 1 ; #{:shapes-group} ; Rect 2 ---> Rect 2 ; Rect 1 ---> Rect 1 ; Rect 3 ---> Rect 3 ; - ; [Component-1] - ; Component-1 + ; [Component 1] + ; Component 1 ; Rect 1 ; Rect 2 ; Rect 3 @@ -245,7 +245,7 @@ new-state (thp/id :instance1))] - (t/is (= (:name group) "Component-1")) + (t/is (= (:name group) "Component 1")) (t/is (= (:touched group) #{:shapes-group})) (t/is (= (:name shape1) "Rect 2")) (t/is (= (:touched shape1) nil)) @@ -257,7 +257,7 @@ (t/is (= (:touched shape3) nil)) (t/is (not= (:shape-ref shape3) nil)) - (t/is (= (:name c-group) "Component-1")) + (t/is (= (:name c-group) "Component 1")) (t/is (= (:touched c-group) nil)) (t/is (= (:shape-ref c-group) nil)) (t/is (= (:name c-shape1) "Rect 1")) @@ -389,7 +389,7 @@ new-state (thp/id :instance2))] - ; TODO: get and check the instance inside component [Group-1] + ; TODO: get and check the instance inside component [Group 1] (t/is (= (:name instance2) "Group")) (t/is (= (:touched instance2) nil)) @@ -478,7 +478,7 @@ new-state (thp/id :instance2))] - ; TODO: get and check the instance inside component [Group-1] + ; TODO: get and check the instance inside component [Group 1] (t/is (= (:name instance2) "Group")) (t/is (= (:touched instance2) nil)) @@ -567,7 +567,7 @@ new-state (thp/id :instance2))] - ; TODO: get and check the instance inside component [Group-1] + ; TODO: get and check the instance inside component [Group 1] (t/is (= (:name instance2) "Group")) (t/is (= (:touched instance2) nil)) @@ -737,12 +737,12 @@ ; ; [Page] ; Root Frame - ; Component-1 #--> Component-1 + ; Component 1 #--> Component 1 ; Rect 1 ---> Rect 1 ; Rect 2 ---> Rect 2 ; - ; [Component-1] - ; Component-1 + ; [Component 1] + ; Component 1 ; Rect 1 ; Rect 2 ; @@ -752,7 +752,7 @@ new-state (thp/id :instance1))] - (t/is (= (:name group) "Component-1")) + (t/is (= (:name group) "Component 1")) (t/is (= (:touched group) nil)) (t/is (not= (:shape-ref group) nil)) (t/is (= (:name shape1) "Rect 1")) @@ -762,7 +762,7 @@ (t/is (= (:touched shape2) nil)) (t/is (not= (:shape-ref shape2) nil)) - (t/is (= (:name c-group) "Component-1")) + (t/is (= (:name c-group) "Component 1")) (t/is (= (:touched c-group) nil)) (t/is (= (:shape-ref c-group) nil)) (t/is (= (:name c-shape1) "Rect 1")) @@ -803,13 +803,13 @@ ; ; [Page] ; Root Frame - ; Component-1 #--> Component-1 + ; Component 1 #--> Component 1 ; Rect 1 ---> Rect 1 ; Rect 2 ---> Rect 2 ; Rect 3 ---> Rect 3 ; - ; [Component-1] - ; Component-1 + ; [Component 1] + ; Component 1 ; Rect 1 ; Rect 2 ; Rect 3 @@ -819,7 +819,7 @@ new-state (thp/id :instance1))] - (t/is (= (:name group) "Component-1")) + (t/is (= (:name group) "Component 1")) (t/is (= (:touched group) nil)) (t/is (not= (:shape-ref group) nil)) (t/is (= (:name shape1) "Rect 1")) @@ -832,7 +832,7 @@ (t/is (= (:touched shape3) nil)) (t/is (not= (:shape-ref shape3) nil)) - (t/is (= (:name c-group) "Component-1")) + (t/is (= (:name c-group) "Component 1")) (t/is (= (:touched c-group) nil)) (t/is (= (:shape-ref c-group) nil)) (t/is (= (:name c-shape1) "Rect 1")) @@ -1144,7 +1144,7 @@ new-state (thp/id :instance2))] - ; TODO: get and check the instance inside component [Group-1] + ; TODO: get and check the instance inside component [Group 1] (t/is (= (:name instance2) "Group")) (t/is (= (:touched instance2) nil)) @@ -1517,11 +1517,11 @@ ; ; [Page] ; Root Frame - ; Component-1 #--> Component-1 + ; Component 1 #--> Component 1 ; Rect 2 ---> Rect 2 ; - ; [Component-1] - ; Component-1 + ; [Component 1] + ; Component 1 ; Rect 2 ; (let [[[group shape2] [c-group c-shape2] component] @@ -1529,14 +1529,14 @@ new-state (thp/id :instance1))] - (t/is (= (:name group) "Component-1")) + (t/is (= (:name group) "Component 1")) (t/is (= (:touched group) nil)) (t/is (not= (:shape-ref group) nil)) (t/is (= (:name shape2) "Rect 2")) (t/is (= (:touched shape2) nil)) (t/is (not= (:shape-ref shape2) nil)) - (t/is (= (:name c-group) "Component-1")) + (t/is (= (:name c-group) "Component 1")) (t/is (= (:touched c-group) nil)) (t/is (= (:shape-ref c-group) nil)) (t/is (= (:name c-shape2) "Rect 2")) @@ -1576,13 +1576,13 @@ ; ; [Page] ; Root Frame - ; Component-1 #--> Component-1 + ; Component 1 #--> Component 1 ; Rect 2 ---> Rect 2 ; Rect 1 ---> Rect 1 ; Rect 3 ---> Rect 3 ; - ; [Component-1] - ; Component-1 + ; [Component 1] + ; Component 1 ; Rect 2 ; Rect 1 ; Rect 3 @@ -1592,7 +1592,7 @@ new-state (thp/id :instance1))] - (t/is (= (:name group) "Component-1")) + (t/is (= (:name group) "Component 1")) (t/is (= (:touched group) nil)) (t/is (not= (:shape-ref group) nil)) (t/is (= (:touched shape1) nil)) @@ -1605,7 +1605,7 @@ (t/is (not= (:shape-ref shape3) nil)) (t/is (= (:name shape3) "Rect 3")) - (t/is (= (:name c-group) "Component-1")) + (t/is (= (:name c-group) "Component 1")) (t/is (= (:touched c-group) nil)) (t/is (= (:shape-ref c-group) nil)) (t/is (= (:name c-shape1) "Rect 2")) @@ -1737,7 +1737,7 @@ new-state (thp/id :instance2))] - ; TODO: get and check the instance inside component [Group-1] + ; TODO: get and check the instance inside component [Group 1] (t/is (= (:name instance2) "Group")) (t/is (= (:touched instance2) nil)) @@ -1826,7 +1826,7 @@ new-state (thp/id :instance2))] - ; TODO: get and check the instance inside component [Group-1] + ; TODO: get and check the instance inside component [Group 1] (t/is (= (:name instance2) "Group")) (t/is (= (:touched instance2) nil)) @@ -1916,7 +1916,7 @@ new-state (thp/id :instance2))] - ; TODO: get and check the instance inside component [Group-1] + ; TODO: get and check the instance inside component [Group 1] (t/is (= (:name instance2) "Group")) (t/is (= (:touched instance2) nil)) diff --git a/frontend/test/frontend_tests/state_components_test.cljs b/frontend/test/frontend_tests/state_components_test.cljs index 8b83e1e75..e0bfdfe84 100644 --- a/frontend/test/frontend_tests/state_components_test.cljs +++ b/frontend/test/frontend_tests/state_components_test.cljs @@ -30,7 +30,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"})) + {:name "Rect 1"})) store (the/prepare-store state done (fn [new-state] @@ -43,12 +43,12 @@ ; ; [Page] ; Root Frame - ; Rect-1 #--> Rect-1 - ; Rect-1 ---> Rect-1 + ; Rect 1 #--> Rect 1 + ; Rect 1 ---> Rect 1 ; - ; [Rect-1] - ; Rect-1 - ; Rect-1 + ; [Rect 1] + ; Rect 1 + ; Rect 1 ; (let [shape1 (thp/get-shape new-state :shape1) @@ -59,11 +59,11 @@ file (wsh/get-local-file new-state)] - (t/is (= (:name shape1) "Rect-1")) - (t/is (= (:name group) "Rect-1")) - (t/is (= (:name component) "Rect-1")) - (t/is (= (:name c-shape1) "Rect-1")) - (t/is (= (:name c-group) "Rect-1")) + (t/is (= (:name shape1) "Rect 1")) + (t/is (= (:name group) "Rect 1")) + (t/is (= (:name component) "Rect 1")) + (t/is (= (:name c-shape1) "Rect 1")) + (t/is (= (:name c-group) "Rect 1")) (thl/is-from-file group file))))] @@ -81,7 +81,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"}))] + {:name "Rect 1"}))] (->> state (the/do-update (dw/select-shape (thp/id :shape1))) @@ -97,11 +97,11 @@ file (wsh/get-local-file new-state)] - (t/is (= (:name shape1) "Rect-1")) - (t/is (= (:name group) "Component-1")) - (t/is (= (:name component) "Component-1")) - (t/is (= (:name c-shape1) "Rect-1")) - (t/is (= (:name c-group) "Component-1")) + (t/is (= (:name shape1) "Rect 1")) + (t/is (= (:name group) "Component 1")) + (t/is (= (:name component) "Component 1")) + (t/is (= (:name c-shape1) "Rect 1")) + (t/is (= (:name c-group) "Component 1")) (thl/is-from-file group file)))) @@ -113,7 +113,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"}) + {:name "Rect 1"}) (thp/sample-shape :shape2 :rect {:name "Rect-2"})) @@ -123,13 +123,13 @@ ; ; [Page] ; Root Frame - ; Component-1 #--> Component-1 - ; Rect-1 ---> Rect-1 + ; Component 1 #--> Component 1 + ; Rect 1 ---> Rect 1 ; Rect-2 ---> Rect-2 ; - ; [Component-1] - ; Component-1 - ; Rect-1 + ; [Component 1] + ; Component 1 + ; Rect 1 ; Rect-2 ; (let [shape1 (thp/get-shape new-state :shape1) @@ -143,12 +143,12 @@ file (wsh/get-local-file new-state)] - (t/is (= (:name group) "Component-1")) - (t/is (= (:name shape1) "Rect-1")) + (t/is (= (:name group) "Component 1")) + (t/is (= (:name shape1) "Rect 1")) (t/is (= (:name shape2) "Rect-2")) - (t/is (= (:name component) "Component-1")) - (t/is (= (:name c-group) "Component-1")) - (t/is (= (:name c-shape1) "Rect-1")) + (t/is (= (:name component) "Component 1")) + (t/is (= (:name c-group) "Component 1")) + (t/is (= (:name c-shape1) "Rect 1")) (t/is (= (:name c-shape2) "Rect-2")) (thl/is-from-file group file))))] @@ -166,7 +166,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"}) + {:name "Rect 1"}) (thp/sample-shape :shape2 :rect {:name "Rect-2"}) (thp/group-shapes :group1 @@ -180,12 +180,12 @@ ; [Page] ; Root Frame ; Group #--> Group - ; Rect-1 ---> Rect-1 + ; Rect 1 ---> Rect 1 ; Rect-2 ---> Rect-2 ; ; [Group] ; Group - ; Rect-1 + ; Rect 1 ; Rect-2 ; (let [[[group shape1 shape2] @@ -197,11 +197,11 @@ file (wsh/get-local-file new-state)] - (t/is (= (:name shape1) "Rect-1")) + (t/is (= (:name shape1) "Rect 1")) (t/is (= (:name shape2) "Rect-2")) (t/is (= (:name group) "Group")) (t/is (= (:name component) "Group")) - (t/is (= (:name c-shape1) "Rect-1")) + (t/is (= (:name c-shape1) "Rect 1")) (t/is (= (:name c-shape2) "Rect-2")) (t/is (= (:name c-group) "Group")) @@ -219,7 +219,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"}) + {:name "Rect 1"}) (thp/make-component :instance1 :component1 [(thp/id :shape1)])) @@ -229,18 +229,18 @@ ; ; [Page] ; Root Frame - ; Rect-1 #--> Rect-1 - ; Rect-1 @--> Rect-1 - ; Rect-1 ---> Rect-1 + ; Rect 1 #--> Rect 1 + ; Rect 1 @--> Rect 1 + ; Rect 1 ---> Rect 1 ; - ; [Rect-1] - ; Rect-1 - ; Rect-1 + ; [Rect 1] + ; Rect 1 + ; Rect 1 ; - ; [Rect-1] - ; Rect-1 - ; Rect-1 @--> Rect-1 - ; Rect-1 ---> Rect-1 + ; [Rect 1] + ; Rect 1 + ; Rect 1 @--> Rect 1 + ; Rect 1 ---> Rect 1 ; (let [[[instance1 shape1] [c-instance1 c-shape1] @@ -257,19 +257,19 @@ new-state (:parent-id instance1))] - (t/is (= (:name shape1) "Rect-1")) - (t/is (= (:name instance1) "Rect-1")) - (t/is (= (:name component1) "Rect-1")) - (t/is (= (:name c-shape1) "Rect-1")) - (t/is (= (:name c-instance1) "Rect-1")) + (t/is (= (:name shape1) "Rect 1")) + (t/is (= (:name instance1) "Rect 1")) + (t/is (= (:name component1) "Rect 1")) + (t/is (= (:name c-shape1) "Rect 1")) + (t/is (= (:name c-instance1) "Rect 1")) - (t/is (= (:name shape1') "Rect-1")) - (t/is (= (:name instance1') "Rect-1")) - (t/is (= (:name instance2) "Rect-1")) - (t/is (= (:name component2) "Rect-1")) - (t/is (= (:name c-shape1') "Rect-1")) - (t/is (= (:name c-instance1') "Rect-1")) - (t/is (= (:name c-instance2) "Rect-1")))))] + (t/is (= (:name shape1') "Rect 1")) + (t/is (= (:name instance1') "Rect 1")) + (t/is (= (:name instance2) "Rect 1")) + (t/is (= (:name component2) "Rect 1")) + (t/is (= (:name c-shape1') "Rect 1")) + (t/is (= (:name c-instance1') "Rect 1")) + (t/is (= (:name c-instance2) "Rect 1")))))] (ptk/emit! store @@ -283,7 +283,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"}) + {:name "Rect 1"}) (thp/make-component :instance1 :component-1 [(thp/id :shape1)])) @@ -296,11 +296,11 @@ ; [Page] ; Root Frame ; Rect-2 #--> Renamed component - ; Rect-1 ---> Rect-1 + ; Rect 1 ---> Rect 1 ; ; [Renamed] ; Renamed component - ; Rect-1 + ; Rect 1 (let [libs (wsh/get-libraries new-state) component (cph/get-component libs (:component-file instance1) @@ -319,7 +319,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"}) + {:name "Rect 1"}) (thp/make-component :instance1 :component-1 [(thp/id :shape1)])) @@ -332,16 +332,16 @@ ; ; [Page] ; Root Frame - ; Rect-1 #--> Rect-1 - ; Rect-1 ---> Rect-1 + ; Rect 1 #--> Rect 1 + ; Rect 1 ---> Rect 1 ; - ; [Rect-1] - ; Rect-1 - ; Rect-1 + ; [Rect 1] + ; Rect 1 + ; Rect 1 ; - ; [Rect-1] - ; Rect-1 - ; Rect-1 + ; [Rect 1] + ; Rect 1 + ; Rect 1 ; (let [new-component-id (->> (get-in new-state [:workspace-data @@ -363,7 +363,7 @@ new-state new-component-id)] - (t/is (= (:name component2) "Rect-1")))))] + (t/is (= (:name component2) "Rect 1")))))] (ptk/emit! store @@ -376,7 +376,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"}) + {:name "Rect 1"}) (thp/make-component :instance1 :component-1 [(thp/id :shape1)])) @@ -392,7 +392,7 @@ ; [Page] ; Root Frame ; Rect-2 - ; Rect-1 + ; Rect 1 ; (let [[instance1 shape1] (thl/resolve-noninstance @@ -420,7 +420,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"}) + {:name "Rect 1"}) (thp/make-component :instance1 :component-1 [(thp/id :shape1)])) @@ -434,14 +434,14 @@ ; ; [Page] ; Root Frame - ; Rect-1 #--> Rect-1 - ; Rect-1 ---> Rect-1 - ; Rect-1 #--> Rect-1 - ; Rect-1 ---> Rect-1 + ; Rect 1 #--> Rect 1 + ; Rect 1 ---> Rect 1 + ; Rect 1 #--> Rect 1 + ; Rect 1 ---> Rect 1 ; - ; [Rect-1] - ; Rect-1 - ; Rect-1 + ; [Rect 1] + ; Rect 1 + ; Rect 1 ; (let [new-instance-id (-> new-state wsh/lookup-selected @@ -456,10 +456,10 @@ (t/is (not= (:id instance1) (:id instance2))) (t/is (= (:id component) component-id)) - (t/is (= (:name instance2) "Rect-1")) - (t/is (= (:name shape2) "Rect-1")) - (t/is (= (:name c-instance2) "Rect-1")) - (t/is (= (:name c-shape2) "Rect-1")) + (t/is (= (:name instance2) "Rect 1")) + (t/is (= (:name shape2) "Rect 1")) + (t/is (= (:name c-instance2) "Rect 1")) + (t/is (= (:name c-shape2) "Rect 1")) (t/is (= (:component-file instance2) thp/current-file-id)))))] @@ -476,7 +476,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"}) + {:name "Rect 1"}) (thp/make-component :instance1 :component-1 [(thp/id :shape1)]) (thp/move-to-library :lib1 "Library 1") @@ -491,8 +491,8 @@ ; ; [Page] ; Root Frame - ; Rect-1 #--> Rect-1 - ; Rect-1 ---> Rect-1 + ; Rect 1 #--> Rect 1 + ; Rect 1 ---> Rect 1 ; (let [new-instance-id (-> new-state wsh/lookup-selected @@ -506,10 +506,10 @@ new-instance-id)] (t/is (= (:id component) component-id)) - (t/is (= (:name instance2) "Rect-1")) - (t/is (= (:name shape2) "Rect-1")) - (t/is (= (:name c-instance2) "Rect-1")) - (t/is (= (:name c-shape2) "Rect-1")) + (t/is (= (:name instance2) "Rect 1")) + (t/is (= (:name shape2) "Rect 1")) + (t/is (= (:name c-instance2) "Rect 1")) + (t/is (= (:name c-shape2) "Rect 1")) (t/is (= (:component-file instance2) library-id)))))] (ptk/emit! @@ -525,7 +525,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"}) + {:name "Rect 1"}) (thp/make-component :instance1 :component-1 [(thp/id :shape1)])) @@ -539,11 +539,11 @@ ; [Page] ; Root Frame ; Rect-2 - ; Rect-1 + ; Rect 1 ; ; [Rect-2] ; Rect-2 - ; Rect-1 + ; Rect 1 ; (let [[instance1 shape1] (thl/resolve-noninstance @@ -564,7 +564,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"})) + {:name "Rect 1"})) file (wsh/get-local-file state) instance1 (thp/get-shape state :instance1) @@ -577,17 +577,17 @@ ; [Page] ; Root Frame ; Group #--> Group - ; Rect-1 @--> Rect-1 - ; Rect-1 ---> Rect-1 + ; Rect 1 @--> Rect 1 + ; Rect 1 ---> Rect 1 ; - ; [Rect-1] - ; Rect-1 - ; Rect-1 + ; [Rect 1] + ; Rect 1 + ; Rect 1 ; ; [Group] ; Group - ; Rect-1 @--> Rect-1 - ; Rect-1 ---> Rect-1 + ; Rect 1 @--> Rect 1 + ; Rect 1 ---> Rect 1 ; (let [page (thp/current-page new-state) shape1 (thp/get-shape new-state :shape1) @@ -601,12 +601,12 @@ (:parent-id parent1))] (t/is (= (:name group) "Group")) - (t/is (= (:name shape1) "Rect-1")) - (t/is (= (:name shape2) "Rect-1")) + (t/is (= (:name shape1) "Rect 1")) + (t/is (= (:name shape2) "Rect 1")) (t/is (= (:name component) "Group")) (t/is (= (:name c-group) "Group")) - (t/is (= (:name c-shape1) "Rect-1")) - (t/is (= (:name c-shape2) "Rect-1")))))] + (t/is (= (:name c-shape1) "Rect 1")) + (t/is (= (:name c-shape2) "Rect 1")))))] (ptk/emit! store @@ -622,7 +622,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"}) + {:name "Rect 1"}) (thp/make-component :instance1 :component-1 [(thp/id :shape1)]) (thp/group-shapes :group1 @@ -641,21 +641,21 @@ ; ; [Page] ; Root Frame - ; Rect-1 #--> Rect-1 - ; Rect-1 @--> Rect-1 - ; Rect-1 ---> Rect-1 - ; Rect-1 #--> Rect-1 - ; Rect-1 @--> Rect-1 - ; Rect-1 ---> Rect-1 + ; Rect 1 #--> Rect 1 + ; Rect 1 @--> Rect 1 + ; Rect 1 ---> Rect 1 + ; Rect 1 #--> Rect 1 + ; Rect 1 @--> Rect 1 + ; Rect 1 ---> Rect 1 ; - ; [Rect-1] - ; Rect-1 - ; Rect-1 + ; [Rect 1] + ; Rect 1 + ; Rect 1 ; - ; [Rect-1] - ; Rect-1 - ; Rect-1 @--> Rect-1 - ; Rect-1 ---> Rect-1 + ; [Rect 1] + ; Rect 1 + ; Rect 1 @--> Rect 1 + ; Rect 1 ---> Rect 1 ; (let [new-instance-id (-> new-state wsh/lookup-selected @@ -672,12 +672,12 @@ (t/is (not= (:id instance1) (:id instance3))) (t/is (= (:id component) component-id)) - (t/is (= (:name instance3) "Rect-1")) - (t/is (= (:name shape3) "Rect-1")) - (t/is (= (:name shape4) "Rect-1")) - (t/is (= (:name c-instance3) "Rect-1")) - (t/is (= (:name c-shape3) "Rect-1")) - (t/is (= (:name c-shape4) "Rect-1")))))] + (t/is (= (:name instance3) "Rect 1")) + (t/is (= (:name shape3) "Rect 1")) + (t/is (= (:name shape4) "Rect 1")) + (t/is (= (:name c-instance3) "Rect 1")) + (t/is (= (:name c-shape3) "Rect 1")) + (t/is (= (:name c-shape4) "Rect 1")))))] (ptk/emit! store @@ -692,7 +692,7 @@ (let [state (-> thp/initial-state (thp/sample-page) (thp/sample-shape :shape1 :rect - {:name "Rect-1"}) + {:name "Rect 1"}) (thp/make-component :instance1 :component-1 [(thp/id :shape1)]) (thp/move-to-library :lib1 "Library 1") @@ -711,13 +711,13 @@ ; [Page] ; Root Frame ; Group #--> Group - ; Rect-1 @--> Rect-1 - ; Rect-1 ---> Rect-1 + ; Rect 1 @--> Rect 1 + ; Rect 1 ---> Rect 1 ; ; [Group] ; Group - ; Rect-1 @--> Rect-1 - ; Rect-1 ---> Rect-1 + ; Rect 1 @--> Rect 1 + ; Rect 1 ---> Rect 1 ; (let [instance2 (thp/get-shape new-state :instance2) @@ -727,11 +727,11 @@ (:parent-id instance2))] (t/is (= (:name group1) "Group")) - (t/is (= (:name shape1) "Rect-1")) - (t/is (= (:name shape2) "Rect-1")) + (t/is (= (:name shape1) "Rect 1")) + (t/is (= (:name shape2) "Rect 1")) (t/is (= (:name c-group1) "Group")) - (t/is (= (:name c-shape1) "Rect-1")) - (t/is (= (:name c-shape2) "Rect-1")) + (t/is (= (:name c-shape1) "Rect 1")) + (t/is (= (:name c-shape2) "Rect 1")) (t/is (= (:component-file group1) thp/current-file-id)) (t/is (= (:component-file shape1) library-id)) (t/is (= (:component-file shape2) nil)) diff --git a/frontend/test/frontend_tests/util_snap_data_test.cljs b/frontend/test/frontend_tests/util_snap_data_test.cljs index 1ede8838a..31c4b03ba 100644 --- a/frontend/test/frontend_tests/util_snap_data_test.cljs +++ b/frontend/test/frontend_tests/util_snap_data_test.cljs @@ -19,7 +19,7 @@ (t/testing "Add empty page (only root-frame)" (let [page (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/get-current-page)) data (-> (sd/make-snap-data) @@ -28,7 +28,7 @@ (t/testing "Create simple shape on root" (let [file (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/create-rect {:x 0 :y 0 @@ -57,7 +57,7 @@ (t/testing "Add page with single empty frame" (let [file (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/add-artboard {:x 0 :y 0 @@ -81,7 +81,7 @@ (t/testing "Add page with some shapes inside frames" (let [file (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/add-artboard {:x 0 :y 0 @@ -112,7 +112,7 @@ (t/testing "Add a global guide" (let [file (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/add-guide {:position 50 :axis :x}) (fb/add-artboard {:x 200 :y 200 :width 100 :height 100}) (fb/close-artboard)) @@ -140,7 +140,7 @@ (t/testing "Add a frame guide" (let [file (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/add-artboard {:x 200 :y 200 :width 100 :height 100}) (fb/close-artboard)) @@ -171,7 +171,7 @@ (t/deftest test-update-index (t/testing "Create frame on root and then remove it." (let [file (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/add-artboard {:x 0 :y 0 @@ -201,7 +201,7 @@ (t/testing "Create simple shape on root. Then remove it" (let [file (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/create-rect {:x 0 :y 0 @@ -229,7 +229,7 @@ (t/testing "Create shape inside frame, then remove it" (let [file (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/add-artboard {:x 0 :y 0 @@ -260,7 +260,7 @@ (t/testing "Create global guide then remove it" (let [file (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/add-guide {:position 50 :axis :x})) guide-id (:last-id file) @@ -293,7 +293,7 @@ (t/testing "Create frame guide then remove it" (let [file (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/add-artboard {:x 200 :y 200 :width 100 :height 100}) (fb/close-artboard)) @@ -324,7 +324,7 @@ (t/testing "Update frame coordinates" (let [file (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/add-artboard {:x 0 :y 0 @@ -358,7 +358,7 @@ (t/testing "Update shape coordinates" (let [file (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/create-rect {:x 0 :y 0 @@ -388,7 +388,7 @@ (t/testing "Update global guide" (let [guide {:position 50 :axis :x} file (-> (fb/create-file "Test") - (fb/add-page {:name "Page-1"}) + (fb/add-page {:name "Page 1"}) (fb/add-guide guide)) guide-id (:last-id file)