Skip to content

Commit e1f7cf8

Browse files
committed
fix #10, #17, bump 1.4.0
1 parent c18c1b9 commit e1f7cf8

File tree

3 files changed

+88
-23
lines changed

3 files changed

+88
-23
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@smastrom/react-rating",
3-
"version": "1.3.3",
3+
"version": "1.4.0",
44
"private": false,
55
"keywords": [
66
"react",

src/RatingItem.tsx

+67-22
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { useId, useRef, useState } from 'react'
1+
import { useCallback, useId, useRef, useState } from 'react'
22
import {
33
areNum,
4-
getNewPosition,
4+
getNewPosition as getNewPos,
55
getDefsTestId,
6-
toSecondDecimal,
6+
toSecondDecimal as toSecondDec,
77
useIsomorphicLayoutEffect,
8+
getHiddenParent,
89
} from './utils'
910
import { RatingClasses, OrientationProps } from './constants'
1011
import { RatingItemProps, SvgData } from './internalTypes'
@@ -19,34 +20,78 @@ export function RatingItem({
1920
const strokeOffset = itemStrokeWidth > 0 ? -(itemStrokeWidth / 2) : 0
2021
const translateOffset = itemStrokeWidth > 0 ? `${strokeOffset} ${strokeOffset}` : '0 0'
2122

22-
const svgRef = useRef<SVGPathElement | null>(null)
2323
const uniqId = useId()
2424

25-
const [svgData, setSvgData] = useState<SvgData | null>(null)
25+
const groupRef = useRef<SVGPathElement | null>(null)
26+
const [svgData, _setSvgData] = useState<SvgData | null>(null)
2627

27-
useIsomorphicLayoutEffect(() => {
28-
if (svgRef.current) {
29-
const {
30-
width: svgWidth,
31-
height: svgHeight,
32-
x: svgXPos,
33-
y: svgYPos,
34-
} = svgRef.current.getBBox()
35-
36-
if (areNum(svgWidth, svgHeight, svgXPos, svgYPos)) {
37-
const viewBox = `${translateOffset} ${toSecondDecimal(
38-
svgWidth + itemStrokeWidth
39-
)} ${toSecondDecimal(svgHeight + itemStrokeWidth)}`
40-
const translateData = `${getNewPosition(svgXPos)} ${getNewPosition(svgYPos)}`
41-
42-
setSvgData({
28+
const [isHiddenParentDetected, setIsHiddenParentDetected] = useState(false)
29+
const mutationObserver = useRef<MutationObserver | null>(null)
30+
const hiddenParent = useRef<HTMLElement | SVGElement | null>(null)
31+
32+
const setSvgData = useCallback(
33+
(el: SVGPathElement) => {
34+
const { width: w, height: h, x, y } = el.getBBox()
35+
36+
if (areNum(w, h, x, y)) {
37+
const viewBox = `${translateOffset} ${toSecondDec(w + itemStrokeWidth)} ${toSecondDec(
38+
h + itemStrokeWidth
39+
)}`
40+
const translateData = `${getNewPos(x)} ${getNewPos(y)}`
41+
42+
_setSvgData({
4343
viewBox,
4444
translateData,
4545
})
4646
}
47+
},
48+
[itemStrokeWidth, translateOffset]
49+
)
50+
51+
useIsomorphicLayoutEffect(() => {
52+
if (groupRef.current) {
53+
const { width: w, height: h, x, y } = groupRef.current.getBBox()
54+
55+
const isHidden = w === 0 && h === 0 && x === 0 && y === 0
56+
57+
if (isHidden) {
58+
const _hiddenParent = getHiddenParent(groupRef.current)
59+
if (_hiddenParent) {
60+
hiddenParent.current = _hiddenParent
61+
setIsHiddenParentDetected(true)
62+
}
63+
} else {
64+
setIsHiddenParentDetected(false)
65+
}
66+
67+
setSvgData(groupRef.current)
4768
}
4869
}, [itemShapes, itemStrokeWidth, hasHF])
4970

71+
useIsomorphicLayoutEffect(() => {
72+
if (isHiddenParentDetected && hiddenParent.current) {
73+
mutationObserver.current = new MutationObserver((mutations, observer) => {
74+
mutations.forEach(() => {
75+
const isDisplayNone =
76+
window.getComputedStyle(hiddenParent.current as Element).display === 'none'
77+
78+
if (!isDisplayNone) {
79+
setSvgData(groupRef.current as SVGPathElement)
80+
observer.disconnect()
81+
}
82+
})
83+
})
84+
85+
mutationObserver.current.observe(hiddenParent.current, {
86+
attributes: true,
87+
})
88+
89+
return () => {
90+
mutationObserver.current?.disconnect()
91+
}
92+
}
93+
}, [isHiddenParentDetected, setSvgData])
94+
5095
/* Props */
5196

5297
function getHFAttr() {
@@ -106,7 +151,7 @@ export function RatingItem({
106151
</defs>
107152
)}
108153

109-
<g ref={svgRef} shapeRendering="geometricPrecision" {...getTransform()} {...getHFAttr()}>
154+
<g ref={groupRef} shapeRendering="geometricPrecision" {...getTransform()} {...getHFAttr()}>
110155
{itemShapes}
111156
</g>
112157
</svg>

src/utils.ts

+20
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,23 @@ export function getDefsTestId() {
7979
} /* c8 ignore next */
8080
return {}
8181
}
82+
83+
export function getHiddenParent(
84+
el: HTMLElement | SVGElement | null
85+
): SVGElement | HTMLElement | null {
86+
if (!el || !el.parentElement) return null
87+
88+
let nextParent = el?.parentElement as HTMLElement | SVGElement | null
89+
90+
// eslint-disable-next-line no-constant-condition
91+
while (true) {
92+
if (!nextParent) break
93+
94+
const isParentDisplayNone = window.getComputedStyle(nextParent).display === 'none'
95+
if (isParentDisplayNone) break
96+
97+
nextParent = nextParent.parentElement
98+
}
99+
100+
return nextParent
101+
}

0 commit comments

Comments
 (0)