@@ -35,13 +35,16 @@ interface ClosePathAction {
35
35
36
36
type Action = ToggleAction | OpenPathAction | ClosePathAction
37
37
38
+ type Placement = 'top' | 'bottom' | 'start' | 'end'
39
+
38
40
/**
39
41
* @ignore
40
42
*/
41
43
interface NestedMenuState {
42
44
items : Items
43
45
isOpen : boolean
44
46
currentPath : string [ ]
47
+ placement : Placement
45
48
}
46
49
47
50
/**
@@ -75,6 +78,7 @@ interface NestedMenuProps {
75
78
items ?: Items
76
79
isOpen ?: boolean
77
80
defaultOpenPath ?: string [ ]
81
+ placement ?: Placement
78
82
}
79
83
80
84
// interface HitAreaProps {
@@ -90,11 +94,13 @@ export const useNestedMenu = ({
90
94
items = [ ] ,
91
95
isOpen = false ,
92
96
defaultOpenPath = [ ] ,
97
+ placement = 'end' ,
93
98
} : NestedMenuProps ) => {
94
99
const [ state , dispatch ] = React . useReducer ( reducer , {
95
100
items,
96
101
isOpen,
97
102
currentPath : defaultOpenPath ,
103
+ placement,
98
104
} )
99
105
100
106
const globalClickHandler = React . useCallback (
@@ -183,25 +189,61 @@ export const useNestedMenu = ({
183
189
184
190
const getMenuOffsetStyles = ( currentItem ?: MenuItem ) => {
185
191
const item = currentItem ? itemRefs . current [ currentItem . id ] : null
186
- const level =
187
- state . currentPath . length === 0
188
- ? 0 // root menu
189
- : currentItem && state . currentPath . includes ( currentItem . id )
190
- ? 1 // submenu, indent
191
- : 0
192
192
const button = toggleButtonRef . current as HTMLElement
193
193
194
194
const dir = getDirection ( )
195
- const direction = dir === 'ltr' ? 'left' : 'right'
196
- const rootX =
195
+ const rootXEnd =
197
196
dir === 'ltr'
198
197
? button . getBoundingClientRect ( ) . right
199
198
: window . innerWidth - button . getBoundingClientRect ( ) . left
200
199
200
+ let vertical : string = 'top'
201
+ let horizontal : string = dir === 'ltr' ? 'left' : 'right'
202
+ let verticalValue = item ? 0 : button . getBoundingClientRect ( ) . top
203
+ let horizontalValue = item ? item . getBoundingClientRect ( ) . width : rootXEnd
204
+
205
+ if ( dir === 'ltr' ) {
206
+ if ( placement === 'top' ) {
207
+ vertical = item ? 'top' : 'bottom'
208
+ verticalValue = item ? 0 : window . innerHeight - button . getBoundingClientRect ( ) . top
209
+ horizontalValue = item
210
+ ? item . getBoundingClientRect ( ) . width
211
+ : button . getBoundingClientRect ( ) . left
212
+ } else if ( placement === 'bottom' ) {
213
+ verticalValue = item ? 0 : button . getBoundingClientRect ( ) . bottom
214
+ horizontalValue = item
215
+ ? item . getBoundingClientRect ( ) . width
216
+ : button . getBoundingClientRect ( ) . left
217
+ } else if ( placement === 'start' ) {
218
+ horizontal = item ? 'left' : 'right'
219
+ horizontalValue = item
220
+ ? item . getBoundingClientRect ( ) . width
221
+ : window . innerWidth - button . getBoundingClientRect ( ) . left
222
+ }
223
+ } else {
224
+ if ( placement === 'top' ) {
225
+ vertical = item ? 'top' : 'bottom'
226
+ horizontal = 'right'
227
+ verticalValue = item ? 0 : window . innerHeight - button . getBoundingClientRect ( ) . top
228
+ horizontalValue = item
229
+ ? item . getBoundingClientRect ( ) . width
230
+ : window . innerWidth - button . getBoundingClientRect ( ) . right
231
+ } else if ( placement === 'bottom' ) {
232
+ verticalValue = item ? 0 : button . getBoundingClientRect ( ) . bottom
233
+ horizontalValue = item
234
+ ? item . getBoundingClientRect ( ) . width
235
+ : window . innerWidth - button . getBoundingClientRect ( ) . right
236
+ } else if ( placement === 'start' ) {
237
+ horizontal = item ? 'right' : 'left'
238
+ horizontalValue = item
239
+ ? item . getBoundingClientRect ( ) . width
240
+ : button . getBoundingClientRect ( ) . right
241
+ }
242
+ }
243
+
201
244
return {
202
- top : item ? 0 : button . getBoundingClientRect ( ) . top ,
203
- [ direction ] : item ? button . getBoundingClientRect ( ) . width * level : rootX ,
204
- width : button . getBoundingClientRect ( ) . width ,
245
+ [ vertical ] : verticalValue ,
246
+ [ horizontal ] : horizontalValue ,
205
247
}
206
248
}
207
249
0 commit comments