@@ -9,7 +9,7 @@ import PropTypes from 'lib/PropTypes';
9
9
import React , { useState , useEffect , useRef } from 'react' ;
10
10
import styles from 'components/ContextMenu/ContextMenu.scss' ;
11
11
12
- const getPositionToFitVisibleScreen = ( ref , offset = 0 ) => {
12
+ const getPositionToFitVisibleScreen = ( ref , offset = 0 , mainItemCount = 0 , subItemCount = 0 ) => {
13
13
if ( ref . current ) {
14
14
const elBox = ref . current . getBoundingClientRect ( ) ;
15
15
let y = 0 ;
@@ -24,17 +24,24 @@ const getPositionToFitVisibleScreen = (ref, offset = 0) => {
24
24
y = upperLimit - elBox . top ;
25
25
}
26
26
27
- // Apply offset only if it doesn't push the element offscreen again
28
27
const projectedTop = elBox . top + y + offset ;
29
28
const projectedBottom = projectedTop + elBox . height ;
30
29
31
- if ( projectedTop >= upperLimit && projectedBottom <= lowerLimit ) {
30
+ const shouldApplyOffset = subItemCount > mainItemCount ;
31
+ if ( shouldApplyOffset && projectedTop >= upperLimit && projectedBottom <= lowerLimit ) {
32
32
y += offset ;
33
33
}
34
34
35
35
const prevEl = ref . current . previousSibling ;
36
36
if ( prevEl ) {
37
37
const prevElBox = prevEl . getBoundingClientRect ( ) ;
38
+ const prevElStyle = window . getComputedStyle ( prevEl ) ;
39
+ const prevElTop = parseInt ( prevElStyle . top , 10 ) ;
40
+
41
+ if ( ! shouldApplyOffset ) {
42
+ y = prevElTop + offset ;
43
+ }
44
+
38
45
const showOnRight = prevElBox . x + prevElBox . width + elBox . width < window . innerWidth ;
39
46
return {
40
47
x : showOnRight ? prevElBox . width : - elBox . width ,
@@ -46,23 +53,28 @@ const getPositionToFitVisibleScreen = (ref, offset = 0) => {
46
53
}
47
54
} ;
48
55
49
- const MenuSection = ( { level, items, path, setPath, hide } ) => {
56
+ const MenuSection = ( { level, items, path, setPath, hide, parentItemCount = 0 } ) => {
50
57
const sectionRef = useRef ( null ) ;
51
58
const [ position , setPosition ] = useState ( ) ;
52
59
53
60
useEffect ( ( ) => {
54
- const newPosition = getPositionToFitVisibleScreen ( sectionRef , path [ level ] * 30 ) ;
61
+ const newPosition = getPositionToFitVisibleScreen (
62
+ sectionRef ,
63
+ path [ level ] * 30 ,
64
+ parentItemCount ,
65
+ items . length
66
+ ) ;
55
67
newPosition && setPosition ( newPosition ) ;
56
68
} , [ sectionRef ] ) ;
57
69
58
70
const style = position
59
71
? {
60
- left : position . x ,
61
- top : position . y ,
62
- maxHeight : '80vh' ,
63
- overflowY : 'scroll' ,
64
- opacity : 1 ,
65
- }
72
+ left : position . x ,
73
+ top : position . y ,
74
+ maxHeight : '80vh' ,
75
+ overflowY : 'scroll' ,
76
+ opacity : 1 ,
77
+ }
66
78
: { } ;
67
79
68
80
return (
@@ -108,6 +120,8 @@ const MenuSection = ({ level, items, path, setPath, hide }) => {
108
120
const ContextMenu = ( { x, y, items } ) => {
109
121
const [ path , setPath ] = useState ( [ 0 ] ) ;
110
122
const [ visible , setVisible ] = useState ( true ) ;
123
+ const menuRef = useRef ( null ) ;
124
+
111
125
useEffect ( ( ) => {
112
126
setVisible ( true ) ;
113
127
} , [ items ] ) ;
@@ -117,10 +131,6 @@ const ContextMenu = ({ x, y, items }) => {
117
131
setPath ( [ 0 ] ) ;
118
132
} ;
119
133
120
- //#region Closing menu after clicking outside it
121
-
122
- const menuRef = useRef ( null ) ;
123
-
124
134
function handleClickOutside ( event ) {
125
135
if ( menuRef . current && ! menuRef . current . contains ( event . target ) ) {
126
136
hide ( ) ;
@@ -134,8 +144,6 @@ const ContextMenu = ({ x, y, items }) => {
134
144
} ;
135
145
} ) ;
136
146
137
- //#endregion
138
-
139
147
if ( ! visible ) {
140
148
return null ;
141
149
}
@@ -158,14 +166,19 @@ const ContextMenu = ({ x, y, items }) => {
158
166
} }
159
167
>
160
168
{ path . map ( ( position , level ) => {
169
+ const itemsForLevel = getItemsFromLevel ( level ) ;
170
+ const parentItemCount =
171
+ level === 0 ? items . length : getItemsFromLevel ( level - 1 ) . length ;
172
+
161
173
return (
162
174
< MenuSection
163
175
key = { `section-${ position } -${ level } ` }
164
176
path = { path }
165
177
setPath = { setPath }
166
178
level = { level }
167
- items = { getItemsFromLevel ( level ) }
179
+ items = { itemsForLevel }
168
180
hide = { hide }
181
+ parentItemCount = { parentItemCount }
169
182
/>
170
183
) ;
171
184
} ) }
0 commit comments