1
- import { useId , useRef , useState } from 'react'
1
+ import { useCallback , useId , useRef , useState } from 'react'
2
2
import {
3
3
areNum ,
4
- getNewPosition ,
4
+ getNewPosition as getNewPos ,
5
5
getDefsTestId ,
6
- toSecondDecimal ,
6
+ toSecondDecimal as toSecondDec ,
7
7
useIsomorphicLayoutEffect ,
8
+ getHiddenParent ,
8
9
} from './utils'
9
10
import { RatingClasses , OrientationProps } from './constants'
10
11
import { RatingItemProps , SvgData } from './internalTypes'
@@ -19,34 +20,78 @@ export function RatingItem({
19
20
const strokeOffset = itemStrokeWidth > 0 ? - ( itemStrokeWidth / 2 ) : 0
20
21
const translateOffset = itemStrokeWidth > 0 ? `${ strokeOffset } ${ strokeOffset } ` : '0 0'
21
22
22
- const svgRef = useRef < SVGPathElement | null > ( null )
23
23
const uniqId = useId ( )
24
24
25
- const [ svgData , setSvgData ] = useState < SvgData | null > ( null )
25
+ const groupRef = useRef < SVGPathElement | null > ( null )
26
+ const [ svgData , _setSvgData ] = useState < SvgData | null > ( null )
26
27
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 ( {
43
43
viewBox,
44
44
translateData,
45
45
} )
46
46
}
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 )
47
68
}
48
69
} , [ itemShapes , itemStrokeWidth , hasHF ] )
49
70
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
+
50
95
/* Props */
51
96
52
97
function getHFAttr ( ) {
@@ -106,7 +151,7 @@ export function RatingItem({
106
151
</ defs >
107
152
) }
108
153
109
- < g ref = { svgRef } shapeRendering = "geometricPrecision" { ...getTransform ( ) } { ...getHFAttr ( ) } >
154
+ < g ref = { groupRef } shapeRendering = "geometricPrecision" { ...getTransform ( ) } { ...getHFAttr ( ) } >
110
155
{ itemShapes }
111
156
</ g >
112
157
</ svg >
0 commit comments