diff --git a/common/src/app/common/geom/shapes.cljc b/common/src/app/common/geom/shapes.cljc index f0776af5a9..1bf496b992 100644 --- a/common/src/app/common/geom/shapes.cljc +++ b/common/src/app/common/geom/shapes.cljc @@ -205,3 +205,6 @@ ;; Modifiers (dm/export gsm/set-objects-modifiers) + +;; Rect +(dm/export grc/rect->points) diff --git a/common/src/app/common/geom/shapes/bounds.cljc b/common/src/app/common/geom/shapes/bounds.cljc index 4b35744d30..3fc8342a91 100644 --- a/common/src/app/common/geom/shapes/bounds.cljc +++ b/common/src/app/common/geom/shapes/bounds.cljc @@ -107,9 +107,7 @@ margin (if ignore-margin? 0 - (->> strokes - (map #(shape-stroke-margin % stroke-width)) - (reduce d/max 0))) + (shape-stroke-margin shape stroke-width)) shadow-width (->> (:shadow shape) @@ -125,8 +123,8 @@ 0)) (reduce d/max 0))] - {:horizontal (+ stroke-width margin shadow-width) - :vertical (+ stroke-width margin shadow-height)}))) + {:horizontal (mth/ceil (+ stroke-width margin shadow-width)) + :vertical (mth/ceil (+ stroke-width margin shadow-height))}))) (defn- add-padding [bounds padding] diff --git a/common/test/common_tests/types_shape_interactions_test.cljc b/common/test/common_tests/types_shape_interactions_test.cljc index a9dc8a2d63..289ca7544d 100644 --- a/common/test/common_tests/types_shape_interactions_test.cljc +++ b/common/test/common_tests/types_shape_interactions_test.cljc @@ -6,6 +6,7 @@ (ns common-tests.types-shape-interactions-test (:require + [app.common.math :as mth] [app.common.exceptions :as ex] [app.common.geom.point :as gpt] [app.common.geom.rect :as grc] @@ -332,56 +333,56 @@ (t/testing "Overlay top-center relative to auto" (let [i2 (ctsi/set-overlay-pos-type interaction-auto :top-center base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 35)) - (t/is (= (:y overlay-pos) 0)) + (t/is (mth/close? (:x overlay-pos) 35)) + (t/is (mth/close? (:y overlay-pos) 0)) (t/is (= snap-v :top)) (t/is (= snap-h :center)))) (t/testing "Overlay top-right relative to auto" (let [i2 (ctsi/set-overlay-pos-type interaction-auto :top-right base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 70)) - (t/is (= (:y overlay-pos) 0)) + (t/is (mth/close? (:x overlay-pos) 70)) + (t/is (mth/close? (:y overlay-pos) 0)) (t/is (= snap-v :top)) (t/is (= snap-h :right)))) (t/testing "Overlay bottom-left relative to auto" (let [i2 (ctsi/set-overlay-pos-type interaction-auto :bottom-left base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 0)) - (t/is (= (:y overlay-pos) 80)) + (t/is (mth/close? (:x overlay-pos) 0)) + (t/is (mth/close? (:y overlay-pos) 80)) (t/is (= snap-v :bottom)) (t/is (= snap-h :left)))) (t/testing "Overlay bottom-center relative to auto" (let [i2 (ctsi/set-overlay-pos-type interaction-auto :bottom-center base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 35)) - (t/is (= (:y overlay-pos) 80)) + (t/is (mth/close? (:x overlay-pos) 35)) + (t/is (mth/close? (:y overlay-pos) 80)) (t/is (= snap-v :bottom)) (t/is (= snap-h :center)))) (t/testing "Overlay bottom-right relative to auto" (let [i2 (ctsi/set-overlay-pos-type interaction-auto :bottom-right base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 70)) - (t/is (= (:y overlay-pos) 80)) + (t/is (mth/close? (:x overlay-pos) 70)) + (t/is (mth/close? (:y overlay-pos) 80)) (t/is (= snap-v :bottom)) (t/is (= snap-h :right)))) (t/testing "Overlay center relative to auto" (let [i2 (ctsi/set-overlay-pos-type interaction-auto :center base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 35)) - (t/is (= (:y overlay-pos) 40)) + (t/is (mth/close? (:x overlay-pos) 35)) + (t/is (mth/close? (:y overlay-pos) 40)) (t/is (= snap-v :center)) (t/is (= snap-h :center)))) (t/testing "Overlay manual relative to auto" (let [i2 (ctsi/set-overlay-pos-type interaction-auto :center base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 35)) - (t/is (= (:y overlay-pos) 40)) + (t/is (mth/close? (:x overlay-pos) 35)) + (t/is (mth/close? (:y overlay-pos) 40)) (t/is (= snap-v :center)) (t/is (= snap-h :center)))) @@ -390,64 +391,64 @@ (ctsi/set-overlay-pos-type :manual base-frame objects) (ctsi/set-overlay-position (gpt/point 12 62))) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 17)) - (t/is (= (:y overlay-pos) 67)) + (t/is (mth/close? (:x overlay-pos) 17)) + (t/is (mth/close? (:y overlay-pos) 67)) (t/is (= snap-v :top)) (t/is (= snap-h :left)))) (t/testing "Overlay top-left relative to base-frame" (let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :top-left base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 5)) - (t/is (= (:y overlay-pos) 5)) + (t/is (mth/close? (:x overlay-pos) 5)) + (t/is (mth/close? (:y overlay-pos) 5)) (t/is (= snap-v :top)) (t/is (= snap-h :left)))) (t/testing "Overlay top-center relative to base-frame" (let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :top-center base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 40)) - (t/is (= (:y overlay-pos) 5)) + (t/is (mth/close? (:x overlay-pos) 40)) + (t/is (mth/close? (:y overlay-pos) 5)) (t/is (= snap-v :top)) (t/is (= snap-h :center)))) (t/testing "Overlay top-right relative to base-frame" (let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :top-right base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 75)) - (t/is (= (:y overlay-pos) 5)) + (t/is (mth/close? (:x overlay-pos) 75)) + (t/is (mth/close? (:y overlay-pos) 5)) (t/is (= snap-v :top)) (t/is (= snap-h :right)))) (t/testing "Overlay bottom-left relative to base-frame" (let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :bottom-left base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 5)) - (t/is (= (:y overlay-pos) 85)) + (t/is (mth/close? (:x overlay-pos) 5)) + (t/is (mth/close? (:y overlay-pos) 85)) (t/is (= snap-v :bottom)) (t/is (= snap-h :left)))) (t/testing "Overlay bottom-center relative to base-frame" (let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :bottom-center base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 40)) - (t/is (= (:y overlay-pos) 85)) + (t/is (mth/close? (:x overlay-pos) 40)) + (t/is (mth/close? (:y overlay-pos) 85)) (t/is (= snap-v :bottom)) (t/is (= snap-h :center)))) (t/testing "Overlay bottom-right relative to base-frame" (let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :bottom-right base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 75)) - (t/is (= (:y overlay-pos) 85)) + (t/is (mth/close? (:x overlay-pos) 75)) + (t/is (mth/close? (:y overlay-pos) 85)) (t/is (= snap-v :bottom)) (t/is (= snap-h :right)))) (t/testing "Overlay center relative to base-frame" (let [i2 (ctsi/set-overlay-pos-type interaction-base-frame :center base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 40)) - (t/is (= (:y overlay-pos) 45)) + (t/is (mth/close? (:x overlay-pos) 40)) + (t/is (mth/close? (:y overlay-pos) 45)) (t/is (= snap-v :center)) (t/is (= snap-h :center)))) @@ -456,64 +457,64 @@ (ctsi/set-overlay-pos-type :manual base-frame objects) (ctsi/set-overlay-position (gpt/point 12 62))) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects base-frame base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 17)) - (t/is (= (:y overlay-pos) 67)) + (t/is (mth/close? (:x overlay-pos) 17)) + (t/is (mth/close? (:y overlay-pos) 67)) (t/is (= snap-v :top)) (t/is (= snap-h :left)))) (t/testing "Overlay top-left relative to popup" (let [i2 (ctsi/set-overlay-pos-type interaction-popup :top-left base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 15)) - (t/is (= (:y overlay-pos) 15)) + (t/is (mth/close? (:x overlay-pos) 15)) + (t/is (mth/close? (:y overlay-pos) 15)) (t/is (= snap-v :top)) (t/is (= snap-h :left)))) (t/testing "Overlay top-center relative to popup" (let [i2 (ctsi/set-overlay-pos-type interaction-popup :top-center base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 25)) - (t/is (= (:y overlay-pos) 15)) + (t/is (mth/close? (:x overlay-pos) 25)) + (t/is (mth/close? (:y overlay-pos) 15)) (t/is (= snap-v :top)) (t/is (= snap-h :center)))) (t/testing "Overlay top-right relative to popup" (let [i2 (ctsi/set-overlay-pos-type interaction-popup :top-right base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 35)) - (t/is (= (:y overlay-pos) 15)) + (t/is (mth/close? (:x overlay-pos) 35)) + (t/is (mth/close? (:y overlay-pos) 15)) (t/is (= snap-v :top)) (t/is (= snap-h :right)))) (t/testing "Overlay bottom-left relative to popup" (let [i2 (ctsi/set-overlay-pos-type interaction-popup :bottom-left base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 15)) - (t/is (= (:y overlay-pos) 45)) + (t/is (mth/close? (:x overlay-pos) 15)) + (t/is (mth/close? (:y overlay-pos) 45)) (t/is (= snap-v :bottom)) (t/is (= snap-h :left)))) (t/testing "Overlay bottom-center relative to popup" (let [i2 (ctsi/set-overlay-pos-type interaction-popup :bottom-center base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 25)) - (t/is (= (:y overlay-pos) 45)) + (t/is (mth/close? (:x overlay-pos) 25)) + (t/is (mth/close? (:y overlay-pos) 45)) (t/is (= snap-v :bottom)) (t/is (= snap-h :center)))) (t/testing "Overlay bottom-right relative to popup" (let [i2 (ctsi/set-overlay-pos-type interaction-popup :bottom-right base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 35)) - (t/is (= (:y overlay-pos) 45)) + (t/is (mth/close? (:x overlay-pos) 35)) + (t/is (mth/close? (:y overlay-pos) 45)) (t/is (= snap-v :bottom)) (t/is (= snap-h :right)))) (t/testing "Overlay center relative to popup" (let [i2 (ctsi/set-overlay-pos-type interaction-popup :center base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 25)) - (t/is (= (:y overlay-pos) 30)) + (t/is (mth/close? (:x overlay-pos) 25)) + (t/is (mth/close? (:y overlay-pos) 30)) (t/is (= snap-v :center)) (t/is (= snap-h :center)))) @@ -522,64 +523,64 @@ (ctsi/set-overlay-pos-type :manual base-frame objects) (ctsi/set-overlay-position (gpt/point 12 62))) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 27)) - (t/is (= (:y overlay-pos) 77)) + (t/is (mth/close? (:x overlay-pos) 27)) + (t/is (mth/close? (:y overlay-pos) 77)) (t/is (= snap-v :top)) (t/is (= snap-h :left)))) (t/testing "Overlay top-left relative to popup" (let [i2 (ctsi/set-overlay-pos-type interaction-popup :top-left base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects popup base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 15)) - (t/is (= (:y overlay-pos) 15)) + (t/is (mth/close? (:x overlay-pos) 15)) + (t/is (mth/close? (:y overlay-pos) 15)) (t/is (= snap-v :top)) (t/is (= snap-h :left)))) (t/testing "Overlay top-center relative to rect" (let [i2 (ctsi/set-overlay-pos-type interaction-rect :top-center base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 25)) - (t/is (= (:y overlay-pos) 15)) + (t/is (mth/close? (:x overlay-pos) 25)) + (t/is (mth/close? (:y overlay-pos) 15)) (t/is (= snap-v :top)) (t/is (= snap-h :center)))) (t/testing "Overlay top-right relative to rect" (let [i2 (ctsi/set-overlay-pos-type interaction-rect :top-right base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 35)) - (t/is (= (:y overlay-pos) 15)) + (t/is (mth/close? (:x overlay-pos) 35)) + (t/is (mth/close? (:y overlay-pos) 15)) (t/is (= snap-v :top)) (t/is (= snap-h :right)))) (t/testing "Overlay bottom-left relative to rect" (let [i2 (ctsi/set-overlay-pos-type interaction-rect :bottom-left base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 15)) - (t/is (= (:y overlay-pos) 45)) + (t/is (mth/close? (:x overlay-pos) 15)) + (t/is (mth/close? (:y overlay-pos) 45)) (t/is (= snap-v :bottom)) (t/is (= snap-h :left)))) (t/testing "Overlay bottom-center relative to rect" (let [i2 (ctsi/set-overlay-pos-type interaction-rect :bottom-center base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 25)) - (t/is (= (:y overlay-pos) 45)) + (t/is (mth/close? (:x overlay-pos) 25)) + (t/is (mth/close? (:y overlay-pos) 45)) (t/is (= snap-v :bottom)) (t/is (= snap-h :center)))) (t/testing "Overlay bottom-right relative to rect" (let [i2 (ctsi/set-overlay-pos-type interaction-rect :bottom-right base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 35)) - (t/is (= (:y overlay-pos) 45)) + (t/is (mth/close? (:x overlay-pos) 35)) + (t/is (mth/close? (:y overlay-pos) 45)) (t/is (= snap-v :bottom)) (t/is (= snap-h :right)))) (t/testing "Overlay center relative to rect" (let [i2 (ctsi/set-overlay-pos-type interaction-rect :center base-frame objects) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 25)) - (t/is (= (:y overlay-pos) 30)) + (t/is (mth/close? (:x overlay-pos) 25)) + (t/is (mth/close? (:y overlay-pos) 30)) (t/is (= snap-v :center)) (t/is (= snap-h :center)))) @@ -588,8 +589,8 @@ (ctsi/set-overlay-pos-type :manual base-frame objects) (ctsi/set-overlay-position (gpt/point 12 62))) [overlay-pos [snap-v snap-h]] (ctsi/calc-overlay-position i2 rect objects rect base-frame overlay-frame frame-offset)] - (t/is (= (:x overlay-pos) 17)) - (t/is (= (:y overlay-pos) 67)) + (t/is (mth/close? (:x overlay-pos) 17)) + (t/is (mth/close? (:y overlay-pos) 67)) (t/is (= snap-v :top)) (t/is (= snap-h :left)))))) diff --git a/frontend/src/app/main/ui/frame_preview.cljs b/frontend/src/app/main/ui/frame_preview.cljs index 805b73a1e2..12f3a00548 100644 --- a/frontend/src/app/main/ui/frame_preview.cljs +++ b/frontend/src/app/main/ui/frame_preview.cljs @@ -25,12 +25,11 @@ handle-load (mf/use-callback (fn [data width height] - (prn "handle-load" data) (reset! last-data* data) (let [iframe-dom (mf/ref-val iframe-ref)] (when iframe-dom - (-> iframe-dom (aset "width" width)) - (-> iframe-dom (aset "height" height)) + (-> iframe-dom (aset "width" (+ width 64))) + (-> iframe-dom (aset "height" (+ height 64))) (-> iframe-dom .-contentWindow .-document .open) (-> iframe-dom .-contentWindow .-document (.write data)) (-> iframe-dom .-contentWindow .-document .close))))) @@ -59,13 +58,13 @@ [:div {:style {:display "flex" :width "100%" :height "100%" :flex-direction "column" :overflow "auto" :align-items "center"}} [:input {:id "zoom-input" :ref zoom-ref - :type "range" :min 1 :max 200 :default-value 100 + :type "range" :min 1 :max 400 :default-value 100 :on-change change-zoom :style {:max-width "500px"}}] [:div {:style {:width "100%" :height "100%" :overflow "auto"}} [:iframe {:ref load-ref - :frameborder "0" + :frame-border "0" :scrolling "no" - :style {:transform-origin "top center" + :style {:transform-origin "top left" :transform (str "scale(" zoom ")")}}]]])) diff --git a/frontend/src/app/util/code_gen/common.cljs b/frontend/src/app/util/code_gen/common.cljs index 5abbe40fb1..4a9bc1f997 100644 --- a/frontend/src/app/util/code_gen/common.cljs +++ b/frontend/src/app/util/code_gen/common.cljs @@ -58,5 +58,6 @@ [objects shape] ;; Layout children with a transform should be wrapped (and (ctl/any-layout-immediate-child? objects shape) + (not (ctl/layout-absolute? shape)) (not (gmt/unit? (:transform shape))))) diff --git a/frontend/src/app/util/code_gen/markup_html.cljs b/frontend/src/app/util/code_gen/markup_html.cljs index 3229bf70a9..028cbf2205 100644 --- a/frontend/src/app/util/code_gen/markup_html.cljs +++ b/frontend/src/app/util/code_gen/markup_html.cljs @@ -23,68 +23,69 @@ (generate-html objects shape 0)) ([objects shape level] - (let [indent (str/repeat " " level) - maybe-reverse (if (ctl/any-layout? shape) reverse identity) + (when (and (some? shape) (some? (:selrect shape))) + (let [indent (str/repeat " " level) + maybe-reverse (if (ctl/any-layout? shape) reverse identity) - shape-html - (cond - (cgc/svg-markup? shape) - (let [svg-markup (generate-svg objects shape)] + shape-html + (cond + (cgc/svg-markup? shape) + (let [svg-markup (generate-svg objects shape)] + (dm/fmt "%