@@ -3,52 +3,49 @@ import React, {useRef, useEffect, useState} from 'react'
33const ShadowRoot = typeof window !== 'undefined' ? require ( 'react-shadow-root' ) . default : ( ) => 0
44
55import generateSvgSquircle from './generator'
6- import getMaskPaths from './mask-generator'
76import { attachCSSWatcher , detachCSSWatcher } from './styleSheetWatcher'
87import updateStates from './updateStates'
98
10- import { lazySetObjectsState } from './utils/react-utils'
119import { camelise } from './utils/string-manipulation'
1210
1311/**
1412 * @function RoundDiv
1513 * @extends React.PureComponent
1614 * */
1715export default function RoundDiv ( { style, children, dontConvertShadow, ...props } ) {
16+ const array = ( length , defaultValue ) => Array ( length ) . fill ( defaultValue )
1817 // welcome to react states hell
19- // const [position, setPosition] = useState([0, 0])
20- const [ padding , setPadding ] = useState ( Array ( 4 ) . fill ( 0 ) )
18+ const [ padding , setPadding ] = useState ( array ( 4 , 0 ) )
2119 const [ height , setHeight ] = useState ( 0 )
2220 const [ width , setWidth ] = useState ( 0 )
23- const [ radius , setRadius ] = useState ( Array ( 4 ) . fill ( 0 ) )
21+ const [ radius , setRadius ] = useState ( array ( 4 , 0 ) )
2422
25- const [ transition , setTransition ] = useState ( Array ( 4 ) . fill ( 0 ) )
23+ const [ transition , setTransition ] = useState ( array ( 4 , 0 ) )
2624
27- const [ borderColor , setBorderColor ] = useState ( Array ( 4 ) . fill ( 'transparent' ) )
28- const [ borderOpacity , setBorderOpacity ] = useState ( Array ( 4 ) . fill ( 0 ) )
29- const [ borderWidth , setBorderWidth ] = useState ( Array ( 4 ) . fill ( 0 ) )
3025 const [ background , setBackground ] = useState ( { } )
31- const [ shadows , setShadows ] = useState ( Array ( 2 ) . fill ( [ ] ) )
26+ const [ border , setBorder ] = useState ( { width : array ( 4 , 0 ) } )
27+ const [ borderImage , setBorderImage ] = useState ( { } )
28+ // const [borderColor, setBorderColor] = useState(array(4, 'transparent'))
29+ // const [borderOpacity, setBorderOpacity] = useState(array(4, 0))
30+ // const [borderWidth, setBorderWidth] = useState(array(4, 0))
31+ const [ shadows , setShadows ] = useState ( array ( 2 , [ ] ) )
3232
3333 const [ path , setPath ] = useState ( 'Z' )
3434 const [ innerPath , setInnerPath ] = useState ( 'Z' )
35- const [ maskPaths , setMaskPaths ] = useState ( 'Z' )
3635
3736 const div = useRef ( )
3837
3938 const updateStatesWithArgs = ( ) => {
4039 updateStates ( {
4140 div,
4241 style,
43- // setPosition,
4442 setPadding,
4543 setHeight,
4644 setWidth,
4745 setRadius,
4846 setBackground,
49- setBorderColor,
50- setBorderWidth,
51- setBorderOpacity,
47+ setBorder,
48+ setBorderImage,
5249 setShadows,
5350 setTransition,
5451 } )
@@ -65,23 +62,22 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
6562 const svgRef = useRef ( ) ;
6663
6764 useEffect ( ( ) => {
68- lazySetObjectsState ( setMaskPaths , getMaskPaths ( borderWidth , height , width , radius ) )
6965 setInnerPath ( generateSvgSquircle (
70- height - ( borderWidth [ 0 ] + borderWidth [ 2 ] ) ,
71- width - ( borderWidth [ 1 ] + borderWidth [ 3 ] ) ,
66+ height - ( border . width [ 0 ] + border . width [ 2 ] ) ,
67+ width - ( border . width [ 1 ] + border . width [ 3 ] ) ,
7268 radius . map ( ( val , i ) =>
7369 Math . max ( 0 ,
74- val - Math . max ( borderWidth [ i ] , borderWidth [ i === 0 ? 3 : i - 1 ] )
70+ val - Math . max ( border . width [ i ] , border . width [ i === 0 ? 3 : i - 1 ] )
7571 )
7672 )
7773 ) . replace (
7874 / ( \d + ( \. \d + ) ? ) , ( \d + ( \. \d + ) ? ) / g,
7975 match => match . split ( ',' ) . map ( ( number , i ) =>
80- Number ( number ) + ( i === 0 ? borderWidth [ 3 ] : borderWidth [ 0 ] )
76+ Number ( number ) + ( i === 0 ? border . width [ 3 ] : border . width [ 0 ] )
8177 ) . join ( ',' )
8278 ) )
8379 setPath ( generateSvgSquircle ( height , width , radius ) )
84- } , [ height , width , radius , borderWidth ] )
80+ } , [ height , width , radius , border . width ] )
8581
8682 useEffect ( ( ) => {
8783 // patch for webkit's svg bug
@@ -95,13 +91,14 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
9591 svgRef . current . style . position = oldPosition
9692 } , 10 )
9793 } , 0 )
98- } , [ radius , borderWidth , borderColor , borderOpacity ] )
94+ } , [ radius , border , borderImage ] )
9995
10096 const pathIsEmpty = ( path . startsWith ( 'Z' ) || path === '' )
10197 const divStyle = {
10298 ...style ,
10399 ...( pathIsEmpty ? { } : {
104- borderColor : 'transparent' ,
100+ border : 'none' ,
101+ borderImage : 'none' ,
105102 background : 'transparent' ,
106103 boxShadow : dontConvertShadow
107104 // "box-shadow" must be overridden for the style extraction to work (with nth: 1, and not nth: 0)
@@ -118,10 +115,12 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
118115 position : 'fixed' ,
119116 left : 0 ,
120117 top : 0 ,
121- transform : `translate(-${ padding [ 3 ] + borderWidth [ 3 ] } px, -${ padding [ 0 ] + borderWidth [ 0 ] } px)` ,
118+ transform : `translate(-${ padding [ 3 ] + border . width [ 3 ] } px, -${ padding [ 0 ] + border . width [ 0 ] } px)` ,
122119 zIndex : - 1 ,
123120 }
124121
122+ const widenedBorderWidth = border . width . map ( v => v + Math . max ( .5 , v * .1 ) )
123+
125124 return < div { ...props } style = { divStyle } ref = { div } >
126125 { pathIsEmpty ? null : < ShadowRoot >
127126 < div style = { {
@@ -138,34 +137,27 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
138137 } ) ) ) ,
139138 transition,
140139 } } />
141- < svg viewBox = { `0 0 ${ width } ${ height } ` } style = { {
140+ < div style = { {
142141 ...shapeComponentStyles ,
143- overflow : 'visible' ,
144- } }
145- preserveAspectRatio = { 'xMidYMid slice' } ref = { svgRef } >
146- < defs >
147- < clipPath id = "inner" >
148- < path d = { `M0,0V${ height } H${ width } V0Z` + innerPath } fillRule = { 'evenodd' } />
149- </ clipPath >
150- < clipPath id = "outer" >
151- < path d = { path } fillRule = { 'evenodd' } />
152- </ clipPath >
153- </ defs >
154- < g clipPath = { 'url(#outer)' } >
155- { Object . keys ( maskPaths ) . map ( ( key , i ) => {
156- if ( borderColor [ i ] === borderColor [ i - 1 ] ) return ''
157-
158- let path = maskPaths [ key ]
159- while ( borderColor [ i ] === borderColor [ i + 1 ] ) {
160- path += maskPaths [ Object . keys ( maskPaths ) [ i + 1 ] ]
161- i ++
162- }
163-
164- return < path d = { path } clipPath = { 'url(#inner)' } key = { key }
165- fill = { borderColor [ i ] } opacity = { borderOpacity [ i ] } />
166- } ) }
167- </ g >
168- </ svg >
142+ clipPath : `path("${ path } ")`
143+ } } >
144+ < div style = { {
145+ height : height - ( widenedBorderWidth [ 0 ] + widenedBorderWidth [ 2 ] ) ,
146+ width : width - ( widenedBorderWidth [ 1 ] + widenedBorderWidth [ 3 ] ) ,
147+ clipPath : `path("M0,0V${ height } H${ width } V0Z${ innerPath } ")` ,
148+ borderRadius : radius . map ( n => ( n - 1 ) + 'px' ) . join ( ' ' ) ,
149+ borderColor : border . color ,
150+ borderWidth : widenedBorderWidth . map ( v => v + 'px' ) . join ( ' ' ) ,
151+ borderStyle : border . style ,
152+ ...( Object . fromEntries ( Object . keys ( borderImage ) . map ( key => {
153+ return [
154+ camelise ( 'border-image-' + key ) ,
155+ borderImage [ key ] + ( key === 'slice' ? ' fill' : '' )
156+ ]
157+ } ) ) ) ,
158+ transition,
159+ } } />
160+ </ div >
169161 < slot style = { { overflow : 'visible' } } />
170162 </ div >
171163 </ ShadowRoot > }
0 commit comments