@@ -5,14 +5,13 @@ import cx from 'classnames';
5
5
// TODO: Resizing window doesn't properly reposition annotation popup on x axis, in EPUB view
6
6
function ViewPopup ( { id, rect, className, uniqueRef, padding, children, onRender } ) {
7
7
const [ popupPosition , setPopupPosition ] = useState ( null ) ;
8
- const [ update , setUpdate ] = useState ( ) ;
9
8
const containerRef = useRef ( ) ;
10
9
const xrect = useRef ( ) ;
11
10
12
11
const initialized = useRef ( false ) ;
13
-
14
12
const pos = useRef ( null ) ;
15
13
14
+ // Update the popup position when the `rect` changes
16
15
useEffect ( ( ) => {
17
16
if ( xrect . current ) {
18
17
let dx = rect [ 0 ] - xrect . current [ 0 ] ;
@@ -21,20 +20,24 @@ function ViewPopup({ id, rect, className, uniqueRef, padding, children, onRender
21
20
22
21
pos . current . left += dx ;
23
22
pos . current . top += dy ;
23
+
24
+ setPopupPosition ( { } ) ; // Trigger re-render
25
+ } else {
26
+ xrect . current = rect ;
24
27
}
25
- } ) ;
28
+ } , [ rect ] ) ;
26
29
27
30
useLayoutEffect ( ( ) => {
28
31
if ( initialized . current ) {
29
32
onRender && onRender ( ) ;
30
33
}
31
- } ) ;
34
+ } , [ popupPosition ] ) ;
32
35
33
36
useLayoutEffect ( ( ) => {
34
37
updatePopupPosition ( ) ;
35
38
// Editor needs more time to get its final dimensions
36
39
setTimeout ( updatePopupPosition , 0 ) ;
37
- } , [ uniqueRef ] ) ;
40
+ } , [ uniqueRef , rect ] ) ;
38
41
39
42
function updatePopupPosition ( ) {
40
43
if ( ! containerRef . current ) {
@@ -49,43 +52,56 @@ function ViewPopup({ id, rect, className, uniqueRef, padding, children, onRender
49
52
viewRect = [ 0 , 0 , viewRect . width , viewRect . height ] ;
50
53
51
54
let annotationCenterLeft = rect [ 0 ] + ( rect [ 2 ] - rect [ 0 ] ) / 2 ;
52
-
53
55
let left = annotationCenterLeft - width / 2 ;
54
56
55
- let isTop = true ;
56
-
57
+ let side ;
57
58
let top ;
58
- if ( rect [ 3 ] + height + padding < viewRect [ 3 ] ) {
59
+ if ( left < 0 ) {
60
+ side = 'right' ;
61
+ left = rect [ 2 ] + padding ;
62
+ top = rect [ 1 ] + ( ( rect [ 3 ] - rect [ 1 ] ) - height ) / 2 ;
63
+ if ( top < 0 ) {
64
+ top = rect [ 1 ] ;
65
+ } else if ( top + height > viewRect [ 3 ] ) {
66
+ top = ( rect [ 1 ] + ( rect [ 3 ] - rect [ 1 ] ) ) - height ;
67
+ }
68
+ } else if ( left + width > viewRect [ 2 ] ) {
69
+ side = 'left' ;
70
+ left = rect [ 0 ] - width - padding ;
71
+ top = rect [ 1 ] + ( ( rect [ 3 ] - rect [ 1 ] ) - height ) / 2 ;
72
+ if ( top < 0 ) {
73
+ top = rect [ 1 ] ;
74
+ } else if ( top + height > viewRect [ 3 ] ) {
75
+ top = ( rect [ 1 ] + ( rect [ 3 ] - rect [ 1 ] ) ) - height ;
76
+ }
77
+ } else if ( rect [ 3 ] + height + padding < viewRect [ 3 ] ) {
59
78
top = rect [ 3 ] + padding ;
60
- isTop = false ;
61
- }
62
- else if ( rect [ 1 ] - padding - height > 0 ) {
79
+ side = 'bottom' ;
80
+ } else if ( rect [ 1 ] - padding - height > 0 ) {
63
81
top = rect [ 1 ] - padding - height ;
64
- }
65
- else {
82
+ side = 'top' ;
83
+ } else {
66
84
top = rect [ 3 ] + padding ;
67
- isTop = false ;
85
+ side = 'top' ;
68
86
}
69
87
70
88
xrect . current = rect ;
89
+ pos . current = { top, left, side } ;
71
90
72
- pos . current = { top, left, isTop } ;
73
-
74
- setPopupPosition ( { } ) ;
91
+ setPopupPosition ( { } ) ; // Trigger re-render
75
92
initialized . current = true ;
76
93
}
77
94
78
-
79
95
let pointerClass = { } ;
80
96
if ( pos . current ) {
81
- pointerClass [ 'page-popup-' + ( pos . current . isTop ? 'top' : 'bottom' ) ] = true ;
97
+ pointerClass [ 'page-popup-' + pos . current . side ] = true ;
82
98
}
83
99
84
100
return (
85
101
< div
86
102
ref = { containerRef }
87
103
className = { cx ( 'view-popup' , className , { ...pointerClass } ) }
88
- style = { pos . current && { transform : `translate(${ pos . current . left } px, ${ pos . current . top } px)` } }
104
+ style = { pos . current ? { transform : `translate(${ pos . current . left } px, ${ pos . current . top } px)` } : { } }
89
105
>
90
106
{ children }
91
107
</ div >
0 commit comments