@@ -3,6 +3,11 @@ import PropTypes from 'prop-types'
33import React from 'react'
44
55const NumberOrString = PropTypes . oneOfType ( [ PropTypes . string , PropTypes . number ] )
6+ const Percentage = ( props , propName , componentName ) => {
7+ if ( props [ propName ] && ! props [ propName ] . endsWith ( '%' ) ) {
8+ return new Error ( `Invalid prop ${ propName } supplied to ${ componentName } . Validation failed.` )
9+ }
10+ }
611
712/**
813 * ColorCorrection :: Props -> React.Element
@@ -35,7 +40,7 @@ const Glow = props =>
3540 < feMorphology in = { props . in } operator = 'dilate' radius = { props . spread } />
3641 < feGaussianBlur stdDeviation = { props . blur } />
3742 < ColorCorrection lightness = { props . lightness } opacity = { props . opacity } />
38- < feBlend in = 'SourceGraphic' mode = 'screen' result = { props . result } />
43+ < feBlend in = { props . in ?? 'SourceGraphic' } mode = 'screen' result = { props . result } />
3944 </ >
4045
4146Glow . propTypes = {
@@ -58,7 +63,7 @@ const GlowInset = props =>
5863 < feMorphology in = { props . in } operator = 'erode' radius = { props . threshold } />
5964 < feGaussianBlur stdDeviation = { props . blur } result = 'blur' />
6065 < ColorCorrection lightness = { props . lightness } opacity = { props . opacity } />
61- < feBlend in = 'SourceGraphic' mode = 'screen' result = { props . result } />
66+ < feBlend in = { props . in ?? 'SourceGraphic' } mode = 'screen' result = { props . result } />
6267 </ >
6368
6469GlowInset . propTypes = {
@@ -101,8 +106,8 @@ const Noise = ({ blend = 'multiply', color = 'black', ...props }) =>
101106 < feFlood floodColor = { color } />
102107 < ColorCorrection lightness = { props . lightness } opacity = { props . opacity } />
103108 < feComposite in2 = 'noise' operator = 'in' />
104- < feComposite in = { props . in } operator = 'in' />
105- < feBlend in = { props . in } mode = { blend } result = { props . result } />
109+ < feComposite in2 = { props . in ?? 'SourceGraphic' } operator = 'in' />
110+ < feBlend in = { props . in ?? 'SourceGraphic' } mode = { blend } result = { props . result } />
106111 </ >
107112
108113Noise . propTypes = {
@@ -137,7 +142,7 @@ const Shadow = ({ offsetX = 0, offsetY = 0, ...props }) =>
137142 < feComposite in2 = 'blur' operator = 'in' />
138143 < ColorCorrection opacity = { props . opacity } />
139144 < feOffset dx = { offsetX } dy = { offsetY } />
140- < feComposite in = { props . in } result = { props . result } />
145+ < feComposite in = { props . in ?? 'SourceGraphic' } result = { props . result } />
141146 </ >
142147
143148Shadow . propTypes = {
@@ -162,9 +167,9 @@ const ShadowInset = ({ offsetX = 0, offsetY = 0, ...props }) =>
162167 < feMorphology in = { props . in } operator = 'dilate' radius = { props . threshold } />
163168 < feGaussianBlur stdDeviation = { props . blur } />
164169 < feOffset dx = { offsetX } dy = { offsetY } />
165- < feComposite in = 'SourceGraphic' operator = 'out' />
166- < ColorCorrection lightness = { props . lightness } opacity = { props . opacity } />
167- < feBlend in = 'SourceGraphic' mode = 'multiply' result = { props . result } />
170+ < feComposite in = { props . in ?? 'SourceGraphic' } operator = 'out' />
171+ < ColorCorrection opacity = { props . opacity } />
172+ < feBlend in = { props . in ?? 'SourceGraphic' } mode = 'multiply' result = { props . result } />
168173 </ >
169174
170175ShadowInset . propTypes = {
@@ -190,35 +195,51 @@ const primitives = {
190195 'shadow-inset' : ShadowInset ,
191196}
192197
198+ const baseArea = { height : '100%' , width : '100%' , x : '0%' , y : '0%' }
199+ const largeArea = { height : '300%' , width : '300%' , x : '-100%' , y : '-100%' }
200+
193201/**
194202 * Filter :: Props -> React.Element
195203 *
196204 * Props => { name: String, [SVGFeAttribute]: SVGFeAttributeValue }
197205 *
198206 * It should not wrap the filter primitive inside a `<filter>` container if a
199207 * previous `in` or a following `result` filter primitive id is given as prop.
200- *
201- * Memo: the first primitive doesn't require a `in` prop, as it will default to
202- * `SourceGraphic` natively.
203208 */
204- const Filter = ( { name, id = name , ...props } ) => {
205-
206- if ( props . in || props . result ) {
209+ const Filter = ( { height : h , name, id = name , x : offsetX , y : offsetY , width : w , ...props } ) => {
210+
211+ const { height, x, y, width } = React . useMemo (
212+ ( ) => {
213+ if ( ( w ?? h ) && ( offsetX ?? offsetY ) ) {
214+ return {
215+ height : h ,
216+ width : w ,
217+ x : w ? `-${ ( w . slice ( 0 , - 1 ) - 100 ) / 2 } %` : '0%' ,
218+ y : h ? `-${ ( h . slice ( 0 , - 1 ) - 100 ) / 2 } %` : '0%' ,
219+ }
220+ } else if ( name . endsWith ( '-inset' ) ) {
221+ return baseArea
222+ }
223+ return largeArea
224+ } ,
225+ [ h , name , offsetX , offsetY , w ] )
226+
227+ if ( props . in ?? props . result ) {
207228 return primitives [ name ] ( props )
208229 }
209230
210- const { height, width, x, y } = id === 'glow'
211- ? { height : '300%' , width : '300%' , x : '-100%' , y : '-100%' }
212- : { height : '200%' , width : '200%' , x : '-50%' , y : '-50%' }
213-
214- return < filter id = { id } x = { x } y = { y } width = { width } height = { height } > { primitives [ name ] ( props ) } </ filter >
231+ return < filter id = { id } width = { width } height = { height } x = { offsetX ?? x } y = { offsetY ?? y } > { primitives [ name ] ( props ) } </ filter >
215232}
216233
217234Filter . propTypes = {
235+ height : Percentage ,
218236 id : PropTypes . string ,
219237 in : PropTypes . string ,
220238 name : PropTypes . oneOf ( Object . keys ( primitives ) ) ,
221239 result : PropTypes . string ,
240+ width : Percentage ,
241+ x : Percentage ,
242+ y : Percentage ,
222243}
223244
224245export default Filter
0 commit comments