mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 05:50:35 +00:00
🐛 Fix inner shadow covering the shape in the SVG renderer (#12141)
* 🐛 Fix inner shadow covering the shape in the SVG renderer The svg filter components moved to the `*` syntax (#9448), but filter-entry* still built their props as a raw JS object with kebab-case keys. Raw JS props skip the kebab to camel conversion, so the components read nil for filterId and filterIn, and no filter primitive got its result or in2. With the chain broken, an inner shadow was blended over the empty flood instead of the shape, hiding the fill (and a board's children) under the shadow color. Exports using these filters broke the same way. Pass the props in camelCase. Closes #11967 AI-assisted-by: claude-opus-5-5 * ♻️ Build filter entry props with mf/props Use mf/props instead of a raw JS object so the props keep the kebab-case keys used across the codebase. The macro converts them to camelCase at compile time, so there is no runtime cost, and the comment about the manual conversion is no longer needed. AI-assisted-by: claude-opus-5-5
This commit is contained in:
parent
f62f4024be
commit
dcf0b197eb
@ -116,9 +116,9 @@
|
||||
:result filter-id}])
|
||||
|
||||
(mf/defc filter-entry* [{:keys [entry]}]
|
||||
(let [props #js {:filter-id (:id entry)
|
||||
:filter-in (:filter-in entry)
|
||||
:params (:params entry)}]
|
||||
(let [props (mf/props {:filter-id (:id entry)
|
||||
:filter-in (:filter-in entry)
|
||||
:params (:params entry)})]
|
||||
(case (:type entry)
|
||||
:drop-shadow [:> drop-shadow-filter* props]
|
||||
:inner-shadow [:> inner-shadow-filter* props]
|
||||
|
||||
@ -124,6 +124,7 @@
|
||||
[frontend-tests.ui.routes-test]
|
||||
[frontend-tests.ui.settings-password-schema-test]
|
||||
[frontend-tests.ui.settings-shortcuts-test]
|
||||
[frontend-tests.ui.shape-filters-test]
|
||||
[frontend-tests.ui.shortcuts-labels-test]
|
||||
[frontend-tests.ui.sidebar-scroll-test]
|
||||
[frontend-tests.ui.stroke-menu-test]
|
||||
@ -273,6 +274,7 @@
|
||||
'frontend-tests.text-editor-paste-guard-test
|
||||
'frontend-tests.ui.settings-password-schema-test
|
||||
'frontend-tests.ui.settings-shortcuts-test
|
||||
'frontend-tests.ui.shape-filters-test
|
||||
'frontend-tests.ui.shortcuts-labels-test
|
||||
'frontend-tests.ui.sidebar-scroll-test
|
||||
'frontend-tests.ui.stroke-menu-test
|
||||
|
||||
47
frontend/test/frontend_tests/ui/shape_filters_test.cljs
Normal file
47
frontend/test/frontend_tests/ui/shape_filters_test.cljs
Normal file
@ -0,0 +1,47 @@
|
||||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS SUBSIDIARY SL
|
||||
|
||||
(ns frontend-tests.ui.shape-filters-test
|
||||
(:require
|
||||
["react-dom/server" :as rds]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.ui.shapes.filters :as filters]
|
||||
[cljs.test :as t :include-macros true]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn- render-filter
|
||||
[shadow-style]
|
||||
(let [shape (-> (cts/setup-shape {:type :rect :x 0 :y 0 :width 100 :height 100})
|
||||
(assoc :fills [{:fill-color "#4488ff" :fill-opacity 1}]
|
||||
:shadow [{:id (uuid/next)
|
||||
:style shadow-style
|
||||
:offset-x 4 :offset-y 4 :blur 4 :spread 0
|
||||
:hidden false
|
||||
:color {:color "#000000" :opacity 0.5}}]))]
|
||||
(rds/renderToStaticMarkup
|
||||
(mf/element filters/filters* #js {:filterId "filter" :shape shape}))))
|
||||
|
||||
(defn- tags
|
||||
[markup tag]
|
||||
(re-seq (re-pattern (str "<" tag "[^>]*>")) markup))
|
||||
|
||||
;; Each filter primitive must name its result and read the previous one, or
|
||||
;; the chain breaks: an inner shadow then covers the shape fill with the
|
||||
;; shadow color (#11967).
|
||||
|
||||
(t/deftest inner-shadow-filter-chain-is-wired
|
||||
(let [markup (render-filter :inner-shadow)
|
||||
blends (tags markup "feBlend")]
|
||||
(t/is (str/includes? (first (tags markup "feFlood")) "result="))
|
||||
(t/is (= 2 (count blends)))
|
||||
(t/is (every? #(str/includes? % "in2=") blends))
|
||||
(t/is (every? #(str/includes? % "result=") blends))))
|
||||
|
||||
(t/deftest drop-shadow-filter-chain-is-wired
|
||||
(let [blends (tags (render-filter :drop-shadow) "feBlend")]
|
||||
(t/is (every? #(and (str/includes? % "in2=") (str/includes? % "result=")) blends))))
|
||||
Loading…
x
Reference in New Issue
Block a user