Skip to content

Commit

Permalink
bugfixes and improvements
Browse files Browse the repository at this point in the history
add overflow support,
prevent flash of sharp corners,
better support for transitions in transform and height / width
  • Loading branch information
drinking-code committed Mar 21, 2022
1 parent 7811799 commit 46ce13b
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 31 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ npm i react-round-div

| | Gzipped | Minified + Gzipped |
|----------------------------------|---------:|-------------------:|
| `react-round-div` | 7.71 KB | 5.18 KB |
| `react-round-div` + dependencies | 14.88 KB | **9.07 KB** |
| `react-round-div` | 7.81 KB | 5.27 KB |
| `react-round-div` + dependencies | 21.01 KB | **9.45 KB** |

## Usage

Expand All @@ -50,8 +50,6 @@ const App = () => {
export default App;
```

Also, [turn off or polyfill `url`, `path`, and `fs`](#webpack)

### Options

#### `dontConvertShadow`
Expand All @@ -76,6 +74,7 @@ There are a couple of css properties, that you can't reliably set _inline_ with

- the `background` property and all the properties it is a shorthand for
- the `border`, `border-image`, and all the properties they are a shorthand for
- `overflow`
- `box-shadow`
- `filter`, if you haven't set [`dontConvertShadow`](#dontconvertshadow)

Expand All @@ -85,4 +84,5 @@ set [`dontConvertShadow`](#dontconvertshadow). This may also change in future ve

### Intended differences to the html `<div>`

Unlike the html `<div>`, `RoundDiv` still rounds the corners of borders of there is a border image set. This looks great with gradients, but might clash with the use of actual images as borders.
Unlike the html `<div>`, `RoundDiv` still rounds the corners of borders if you have set a border image. This looks great with gradients, but might clash with the use of actual images as borders.
You may notice a flash of white in the border before the gradient is shown. To combat this, define a `border-color` for the element in addition to the `border-image` gradient. This gives the browser a fallback to show before the `RoundDiv` script generates the smooth corners.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-round-div",
"version": "1.3.0",
"version": "1.3.2",
"description": "Make your rounded corners look phenomenal with g2 continuity.",
"main": "dist/main.js",
"scripts": {
Expand Down
28 changes: 24 additions & 4 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
const [width, setWidth] = useState(0)
const [radius, setRadius] = useState(array(4, 0))
const [boxSizing, setBoxSizing] = useState('content-box')
const [overflow, setOverflow] = useState('visible')

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

Expand All @@ -38,6 +39,7 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
div,
style,
setBoxSizing,
setOverflow,
setPadding,
setHeight,
setWidth,
Expand All @@ -52,7 +54,11 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})

useEffect(() => {
const watcherId = attachCSSWatcher(updateStatesWithArgs, div.current) // todo: make this a react hook
updateStatesWithArgs()
const waitForDocumentComplete = setInterval(() => {
if (document.readyState !== 'complete') return
clearInterval(waitForDocumentComplete)
updateStatesWithArgs()
}, 1)
return () => {
detachCSSWatcher(watcherId)
}
Expand Down Expand Up @@ -102,7 +108,9 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
const pathIsEmpty = path.startsWith('Z') || path === ''
const divStyle = {
...style,
...(pathIsEmpty ? {} : {
...(pathIsEmpty ? {
borderImage: 'none',
} : {
...invisibleBorderStyles,
borderImage: 'none',
background: 'transparent',
Expand All @@ -112,6 +120,7 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
: 'none',
// drop shadow only
filter: dontConvertShadow ? '' : shadows[0].map(shadowData => `drop-shadow(${shadowData})`).join(' '),
overflow: 'visible',
})
}

Expand All @@ -128,7 +137,10 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})

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

return <div {...props} style={divStyle} ref={div} data-rrd-overwritten={pathIsEmpty ? 'false' : 'true'}>
if (div.current)
div.current.rrdOverwritten = !pathIsEmpty

return <div {...props} style={divStyle} ref={div}>
{pathIsEmpty ? null : <ShadowRoot>
<div style={{
transform: 'scale(1)'
Expand Down Expand Up @@ -168,7 +180,15 @@ export default function RoundDiv({style, children, dontConvertShadow, ...props})
transition,
}}/>
</div>
<slot style={{overflow: 'visible'}}/>
<div style={{
height: height - (border.width[0] + border.width[2]) * 2,
width: width - (border.width[1] + border.width[3]) * 2,
...invisibleBorderStyles,
transform: `translate(-${padding[3] + border.width[3]}px, -${padding[0] + border.width[0]}px)`,
clipPath: overflow === 'hidden' ? `path("${innerPath}")` : null,
}}>
<slot style={{overflow: 'visible'}}/>
</div>
</div>
</ShadowRoot>}
{children}
Expand Down
40 changes: 21 additions & 19 deletions src/updateStates.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,8 @@ import ReactDOM from 'react-dom'
import {lazySetArrayState, lazySetObjectsState} from './utils/react-utils'

export default function updateStates(args) {
const {div, setHeight, setWidth} = args
const boundingClientRect = div.current?.getBoundingClientRect()
let height, width;
if (boundingClientRect) {
height = boundingClientRect.height
width = boundingClientRect.width
setHeight(height)
setWidth(width)
}
const {div} = args
if (!div.current) return

const getNthStyle = (key, n, shorthand) => {
const styles = getAllCssPropertyDeclarationsForElement(key, div.current, shorthand)
Expand All @@ -33,7 +26,7 @@ export default function updateStates(args) {
lazySetBorderImage = newState => lazySetObjectsState(states.setBorderImage, newState),
lazySetShadows = newState => lazySetArrayState(states.setShadows, newState)

const oneIfStylesAreOverridden = args.div?.current?.dataset.rrdOverwritten === 'true' ? 1 : 0
const oneIfStylesAreOverridden = args.div?.current?.rrdOverwritten ? 1 : 0

ReactDOM.unstable_batchedUpdates(() => {
states.setPadding(
Expand All @@ -42,15 +35,6 @@ export default function updateStates(args) {
.map(n => toNumber(n, div.current) || 0)
)

lazySetRadius(
getBorderRadii(0)
.map(s => Math.min(
toNumber(s, div.current),
height / 2,
width / 2
))
)

states.setTransition(
getNthStyle('transition', 0)
)
Expand All @@ -59,6 +43,10 @@ export default function updateStates(args) {
getNthStyle('box-sizing', 0) || 'content-box'
)

states.setOverflow(
getNthStyle('overflow', oneIfStylesAreOverridden) || 'visible'
)

lazySetBackground(
Object.fromEntries([
'attachment',
Expand Down Expand Up @@ -94,6 +82,20 @@ export default function updateStates(args) {
border.width = border.width ?? Array(4).fill(0)
lazySetBorder(border)

const height = div.current?.clientHeight + border.width[0] + border.width[2],
width = div.current?.clientWidth + border.width[1] + border.width[3]
states.setHeight(height)
states.setWidth(width)

lazySetRadius(
getBorderRadii(0)
.map(s => Math.min(
toNumber(s, div.current),
height / 2,
width / 2
))
)

lazySetBorderImage(
Object.fromEntries([
'outset',
Expand Down

0 comments on commit 46ce13b

Please sign in to comment.