diff --git a/common/src/app/common/files/helpers.cljc b/common/src/app/common/files/helpers.cljc index 05ceca6b2..46b9ac66e 100644 --- a/common/src/app/common/files/helpers.cljc +++ b/common/src/app/common/files/helpers.cljc @@ -92,9 +92,11 @@ (= :image (dm/get-prop shape :type)))) (defn svg-raw-shape? - [shape] - (and (some? shape) - (= :svg-raw (dm/get-prop shape :type)))) + ([objects id] + (svg-raw-shape? (get objects id))) + ([shape] + (and (some? shape) + (= :svg-raw (dm/get-prop shape :type))))) (defn path-shape? ([objects id] diff --git a/common/src/app/common/svg.cljc b/common/src/app/common/svg.cljc index 7974eaa28..6bca95aba 100644 --- a/common/src/app/common/svg.cljc +++ b/common/src/app/common/svg.cljc @@ -876,6 +876,12 @@ (if (map? node) (let [attrs (-> (format-styles attrs) (add-transform (:transform group-attrs))) + + ;; Don't inherit a property that is already in the style attribute + inherit-style (-> (:style group-attrs) (d/without-keys (keys attrs))) + inheritable-props (->> inheritable-props (remove #(contains? (:styles attrs) %))) + group-attrs (-> group-attrs (assoc :style inherit-style)) + attrs (d/deep-merge (select-keys group-attrs inheritable-props) attrs)] (assoc node :attrs attrs)) node)) @@ -988,7 +994,7 @@ (get-in node [:attrs :patternUnits]) (get-in node [:attrs :clipUnits]))] (cond-> node - (= "objectBoundingBox" units) + (or (= "objectBoundingBox" units) (nil? units)) (update :attrs fix-percent-attrs-numeric) (not= "objectBoundingBox" units) diff --git a/common/src/app/common/svg/shapes_builder.cljc b/common/src/app/common/svg/shapes_builder.cljc index 6cb5429aa..fc4b370ae 100644 --- a/common/src/app/common/svg/shapes_builder.cljc +++ b/common/src/app/common/svg/shapes_builder.cljc @@ -265,19 +265,19 @@ (gmt/transform-in (gpt/point svg-data))) origin (gpt/negate (gpt/point svg-data)) - rect (-> (parse-rect-attrs attrs) + vbox (parse-rect-attrs attrs) + rect (-> vbox (update :x - (:x origin)) (update :y - (:y origin))) props (-> (dissoc attrs :x :y :width :height :rx :ry :transform) (csvg/attrs->props))] - (cts/setup-shape (-> (calculate-rect-metadata rect transform) (assoc :type :rect) (assoc :name name) (assoc :frame-id frame-id) - (assoc :svg-viewbox rect) + (assoc :svg-viewbox vbox) (assoc :svg-attrs props) ;; We need to ensure fills are empty on import process ;; because setup-shape assings one by default. @@ -395,9 +395,9 @@ (str/trim (:stroke style))) color (cond - (= stroke "currentColor") clr/black - (= stroke "none") nil - :else (clr/parse stroke)) + (= stroke "currentColor") clr/black + (= stroke "none") nil + (clr/color-string? stroke) (clr/parse stroke)) opacity (when (some? color) (d/parse-double @@ -415,17 +415,21 @@ (get style :strokeLinecap)) linecap (some-> linecap str/trim keyword) - attrs (-> attrs - (dissoc :stroke) - (dissoc :strokeWidth) - (dissoc :strokeOpacity) - (update :style (fn [style] - (-> style - (dissoc :stroke) - (dissoc :strokeLinecap) - (dissoc :strokeWidth) - (dissoc :strokeOpacity)))) - (d/without-nils))] + attrs + (-> attrs + (cond-> linecap + (dissoc :strokeLinecap)) + (cond-> (some? color) + (dissoc :stroke :strokeWidth :strokeOpacity)) + (update + :style + (fn [style] + (-> style + (cond-> linecap + (dissoc :strokeLinecap)) + (cond-> (some? color) + (dissoc :stroke :strokeWidth :strokeOpacity))))) + (d/without-nils))] (cond-> (assoc shape :svg-attrs attrs) (some? color) @@ -467,6 +471,16 @@ (-> (update-in [:svg-attrs :style] dissoc :mixBlendMode) (assoc :blend-mode (-> (dm/get-in shape [:svg-attrs :style :mixBlendMode]) assert-valid-blend-mode))))) +(defn setup-other [shape] + (cond-> shape + (= (dm/get-in shape [:svg-attrs :display]) "none") + (-> (update-in [:svg-attrs :style] dissoc :display) + (assoc :hidden true)) + + (= (dm/get-in shape [:svg-attrs :style :display]) "none") + (-> (update :svg-attrs dissoc :display) + (assoc :hidden true)))) + (defn tag->name "Given a tag returns its layer name" [tag] @@ -525,6 +539,7 @@ (setup-fill) (setup-stroke) (setup-opacity) + (setup-other) (update :svg-attrs (fn [attrs] (if (empty? (:style attrs)) (dissoc attrs :style) diff --git a/frontend/src/app/main/ui/hooks.cljs b/frontend/src/app/main/ui/hooks.cljs index b5a46415e..d97fdad92 100644 --- a/frontend/src/app/main/ui/hooks.cljs +++ b/frontend/src/app/main/ui/hooks.cljs @@ -215,11 +215,15 @@ ([stream on-subscribe] (use-stream stream (mf/deps) on-subscribe)) ([stream deps on-subscribe] + (use-stream stream deps on-subscribe nil)) + ([stream deps on-subscribe on-dispose] (mf/use-effect deps (fn [] (let [sub (->> stream (rx/subs! on-subscribe))] - #(rx/dispose! sub)))))) + #(do + (rx/dispose! sub) + (when on-dispose (on-dispose)))))))) ;; https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state (defn use-previous diff --git a/frontend/src/app/main/ui/shapes/attrs.cljs b/frontend/src/app/main/ui/shapes/attrs.cljs index d7daebf3b..56127db66 100644 --- a/frontend/src/app/main/ui/shapes/attrs.cljs +++ b/frontend/src/app/main/ui/shapes/attrs.cljs @@ -157,7 +157,7 @@ [shape] (add-layer-styles! #js {} shape)) -(defn- get-svg-props +(defn get-svg-props [shape render-id] (let [attrs (get shape :svg-attrs {}) defs (get shape :svg-defs {})] diff --git a/frontend/src/app/main/ui/shapes/custom_stroke.cljs b/frontend/src/app/main/ui/shapes/custom_stroke.cljs index 91d4586ae..b75b8fa31 100644 --- a/frontend/src/app/main/ui/shapes/custom_stroke.cljs +++ b/frontend/src/app/main/ui/shapes/custom_stroke.cljs @@ -475,13 +475,17 @@ shape-shadow (get shape :shadow) shape-strokes (get shape :strokes) + svg-attrs (attrs/get-svg-props shape render-id) + style (-> (obj/get props "style") (obj/clone) (attrs/add-layer-styles! shape)) - props #js {:id stroke-id - :className "strokes" - :style style} + props (-> svg-attrs + (obj/merge! + {:id stroke-id + :className "strokes" + :style style})) props (if ^boolean (cfh/frame-shape? shape) props diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs index 01d95a9be..861d21f83 100644 --- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs @@ -299,11 +299,11 @@ (not (cfh/is-direct-child-of-root? shape)) (empty? (get shape :fills))))) - hover-shape (->> ids (remove remove-id?) (remove (partial cfh/hidden-parent? objects)) + (remove (partial cfh/svg-raw-shape? objects)) (remove #(and mod? (no-fill-nested-frames? %))) (filter #(or (empty? focus) (cpf/is-in-focus? objects focus %))) (first) @@ -315,6 +315,7 @@ (->> ids (remove #(group-empty-space? % objects ids)) (remove (partial cfh/hidden-parent? objects)) + (remove (partial cfh/svg-raw-shape? objects)) (remove #(and mod? (no-fill-nested-frames? %))) (filter #(or (empty? focus) (cpf/is-in-focus? objects focus %))) (first) diff --git a/frontend/src/app/worker/selection.cljs b/frontend/src/app/worker/selection.cljs index 6de386953..ea940b883 100644 --- a/frontend/src/app/worker/selection.cljs +++ b/frontend/src/app/worker/selection.cljs @@ -192,7 +192,10 @@ overlaps? (fn [shape] - (if (and (false? using-selrect?) (empty? (:fills shape))) + (if (and (false? using-selrect?) + (empty? (:fills shape)) + (not (contains? (-> shape :svg-attrs) :fill)) + (not (contains? (-> shape :svg-attrs :style) :fill))) (case (:type shape) ;; If the shape has no fills the overlap depends on the stroke :rect (and (overlaps-outer-shape? shape) (not (overlaps-inner-shape? shape)))