Skip to content

Commit 8ef317c

Browse files
committed
better rendering, smaller package
1 parent ef816c1 commit 8ef317c

File tree

3 files changed

+49
-48
lines changed

3 files changed

+49
-48
lines changed

src/main.js

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
1919
const [height, setHeight] = useState(0)
2020
const [width, setWidth] = useState(0)
2121
const [radius, setRadius] = useState(array(4, 0))
22+
const [boxSizing, setBoxSizing] = useState('content-box')
2223

2324
const [transition, setTransition] = useState(array(4, 0))
2425

2526
const [background, setBackground] = useState({})
2627
const [border, setBorder] = useState({width: array(4, 0)})
2728
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))
3129
const [shadows, setShadows] = useState(array(2, []))
3230

3331
const [path, setPath] = useState('Z')
@@ -39,6 +37,7 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
3937
updateStates({
4038
div,
4139
style,
40+
setBoxSizing,
4241
setPadding,
4342
setHeight,
4443
setWidth,
@@ -77,27 +76,34 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
7776
).join(',')
7877
))
7978
setPath(generateSvgSquircle(height, width, radius))
80-
}, [height, width, radius, border.width])
79+
}, [height, width, radius, border, padding])
8180

8281
useEffect(() => {
82+
const currentSvgRef = svgRef.current
8383
// patch for webkit's svg bug
84-
if (svgRef.current)
84+
if (currentSvgRef)
8585
setTimeout(() => {
86-
const oldPosition = svgRef.current.style.position || ''
87-
svgRef.current.style.display = 'none'
88-
svgRef.current.style.position = 'absolute'
86+
const oldPosition = currentSvgRef.style.position || ''
87+
currentSvgRef.style.display = 'none'
88+
currentSvgRef.style.position = 'absolute'
8989
setTimeout(() => {
90-
svgRef.current.style.display = ''
91-
svgRef.current.style.position = oldPosition
90+
currentSvgRef.style.display = ''
91+
currentSvgRef.style.position = oldPosition
9292
}, 10)
9393
}, 0)
9494
}, [radius, border, borderImage])
9595

96-
const pathIsEmpty = (path.startsWith('Z') || path === '')
96+
const invisibleBorderStyles = {
97+
borderWidth: border.width.map(v => v + 'px').join(' '),
98+
borderStyle: 'solid',
99+
borderColor: 'transparent',
100+
}
101+
102+
const pathIsEmpty = path.startsWith('Z') || path === ''
97103
const divStyle = {
98104
...style,
99105
...(pathIsEmpty ? {} : {
100-
border: 'none',
106+
...invisibleBorderStyles,
101107
borderImage: 'none',
102108
background: 'transparent',
103109
boxShadow: dontConvertShadow
@@ -110,8 +116,11 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
110116
}
111117

112118
const shapeComponentStyles = {
119+
// height: boxSizing === 'border-box' ? height : height - (border.width[0] + padding[0] + border.width[2] + padding[2]),
120+
// width: boxSizing === 'border-box' ? width : width - (border.width[1] + padding[1] + border.width[3] + padding[3]),
113121
height,
114122
width,
123+
padding: padding.map(n => n + 'px').join(' '),
115124
position: 'fixed',
116125
left: 0,
117126
top: 0,
@@ -121,13 +130,14 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
121130

122131
const widenedBorderWidth = border.width.map(v => v + Math.max(.5, v * .1))
123132

124-
return <div {...props} style={divStyle} ref={div}>
133+
return <div {...props} style={divStyle} ref={div} data-rrd-overwritten={pathIsEmpty ? 'false' : 'true'}>
125134
{pathIsEmpty ? null : <ShadowRoot>
126135
<div style={{
127136
transform: 'scale(1)'
128137
}}>
129138
<div style={{
130139
...shapeComponentStyles,
140+
...invisibleBorderStyles,
131141
clipPath: `path("${path}")`,
132142
// inset shadow only
133143
boxShadow: shadows[1].join(','),
@@ -139,11 +149,14 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
139149
}}/>
140150
<div style={{
141151
...shapeComponentStyles,
152+
...invisibleBorderStyles,
142153
clipPath: `path("${path}")`
143154
}}>
144155
<div style={{
145-
height: height - (widenedBorderWidth[0] + widenedBorderWidth[2]),
146-
width: width - (widenedBorderWidth[1] + widenedBorderWidth[3]),
156+
height,
157+
width,
158+
// boxSizing: 'border-box',
159+
transform: `translate(-${border.width[3]}px, -${border.width[0]}px)`,
147160
clipPath: `path("M0,0V${height}H${width}V0Z${innerPath}")`,
148161
borderRadius: radius.map(n => (n - 1) + 'px').join(' '),
149162
borderColor: border.color,

src/updateStates.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {
22
convertBorderWidth,
33
toNumber,
4-
htmlBorderRadiusNotSvgError,
54
separateInsetBoxShadow
65
} from './utils/css-utils';
76
import getAllCssPropertyDeclarationsForElement from './utils/styles-extractor';
@@ -34,17 +33,19 @@ export default function updateStates(args) {
3433
lazySetBorderImage = newState => lazySetObjectsState(states.setBorderImage, newState),
3534
lazySetShadows = newState => lazySetArrayState(states.setShadows, newState)
3635

36+
const oneIfStylesAreOverridden = args.div?.current?.dataset.rrdOverwritten === 'true' ? 1 : 0
37+
3738
ReactDOM.unstable_batchedUpdates(() => {
3839
states.setPadding(
3940
['top', 'right', 'bottom', 'left']
4041
.map(s => getNthStyle('padding-' + s, 0, 'padding'))
41-
.map(n => toNumber(n, div.current))
42+
.map(n => toNumber(n, div.current) || 0)
4243
)
4344

4445
lazySetRadius(
4546
getBorderRadii(0)
4647
.map(s => Math.min(
47-
toNumber(s, div.current, htmlBorderRadiusNotSvgError),
48+
toNumber(s, div.current),
4849
height / 2,
4950
width / 2
5051
))
@@ -54,6 +55,10 @@ export default function updateStates(args) {
5455
getNthStyle('transition', 0)
5556
)
5657

58+
states.setBoxSizing(
59+
getNthStyle('box-sizing', 0) || 'content-box'
60+
)
61+
5762
lazySetBackground(
5863
Object.fromEntries([
5964
'attachment',
@@ -65,7 +70,7 @@ export default function updateStates(args) {
6570
'repeat',
6671
'size'
6772
].map(key =>
68-
[key, getNthStyle('background-' + key, 1, 'background')]
73+
[key, getNthStyle('background-' + key, oneIfStylesAreOverridden, 'background')]
6974
))
7075
)
7176

@@ -74,7 +79,7 @@ export default function updateStates(args) {
7479
'style',
7580
'width',
7681
].map(key =>
77-
[key, getNthStyle('border-' + key, 1, 'border')]
82+
[key, getNthStyle('border-' + key, oneIfStylesAreOverridden, 'border')]
7883
))
7984
border.width = border.width?.split(' ')
8085
?.map(s => convertBorderWidth(s, div.current))
@@ -97,13 +102,13 @@ export default function updateStates(args) {
97102
'source',
98103
'width',
99104
].map(key =>
100-
[key, getNthStyle('border-image-' + key, 1, 'border-image')]
105+
[key, getNthStyle('border-image-' + key, oneIfStylesAreOverridden, 'border-image')]
101106
))
102107
)
103108

104109
lazySetShadows(
105110
separateInsetBoxShadow(
106-
getNthStyle('box-shadow', 1)
111+
getNthStyle('box-shadow', oneIfStylesAreOverridden)
107112
)
108113
)
109114
})

src/utils/css-utils.js

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,24 @@ import CSS_COLOR_NAMES from '../external/bobspace:html-colors';
22

33
const toPx = typeof document !== 'undefined' && require('../external/heygrady:units:length').default;
44

5-
const htmlLengthNotSvgErrorTemplate = (a, b) => `<RoundDiv> ${a} must be ${b ? `either ${b}, or` : ''} in one of the following units: ch, cm, em, ex, in, mm, pc, pt, px, rem, vh, vmax, vmin, vw.`
6-
const htmlBorderLengthNotSvgError =
7-
new Error(htmlLengthNotSvgErrorTemplate('border lengths', '"thin", "medium", "thick"'))
8-
export const htmlBorderRadiusNotSvgError =
9-
new Error(htmlLengthNotSvgErrorTemplate('border radii'))
10-
11-
export function toNumber(length, element, err) {
5+
export function toNumber(length, element) {
126
if (!length) return false
137
if (typeof length === 'number' || !length.match(/\D+/))
148
return Number(length);
15-
else if (length?.match(/(cap|ic|lh|rlh|vi|vm|vb|Q|mozmm)/g))
16-
if (err) throw err
17-
else return false
18-
else if (length?.match(/(\d+(\.\d+)?(ch|cm|em|ex|in|mm|pc|pt|px|rem|vh|vmax|vmin|vw)|0)/))
19-
if (typeof toPx === 'function')
20-
return toPx(element, length)
21-
else if (length.endsWith('px'))
22-
return Number(length.substring(0, length.length - 2))
23-
else
24-
return false
9+
return toPx(element, length)
2510
}
2611

2712
/** @returns {number} */
2813
export function convertBorderWidth(val, element) {
2914
if (!val) return 0
3015
// width is a word
31-
if (val?.toLowerCase() === 'thin')
32-
return 1
33-
else if (val?.toLowerCase() === 'medium')
34-
return 3
35-
else if (val?.toLowerCase() === 'thick')
36-
return 5
37-
// width is <length>
38-
else
39-
return toNumber(val, element, htmlBorderLengthNotSvgError) || 0
16+
return {
17+
thin: 1,
18+
medium: 3,
19+
thick: 5
20+
}[val?.toLowerCase()]
21+
// width is <length>
22+
?? (toNumber(val, element) || 0)
4023
}
4124

4225
export function separateInsetBoxShadow(val) {

0 commit comments

Comments
 (0)