1
- import React , { useMemo , useState } from 'react' ;
1
+ import React , { useMemo , useState , useContext } from 'react' ;
2
2
import { CSSTransitionProps } from 'react-transition-group/CSSTransition' ;
3
3
import OverlayTrigger , { OverlayTriggerProps , OverlayTriggerRef } from '@uiw/react-overlay-trigger' ;
4
4
import Icon from '@uiw/react-icon' ;
5
5
import { IProps } from '@uiw/utils' ;
6
6
import { MenuItem , MenuItemProps , TagType } from './MenuItem' ;
7
- import Menu , { MenuProps } from './Menu' ;
7
+ import { MenuProps , Menu , ThemeContext } from './Menu' ;
8
8
import './style/submenu.less' ;
9
9
10
10
export interface SubMenuProps < T extends TagType > extends IProps , MenuItemProps < T > {
@@ -49,6 +49,7 @@ function IconView({ prefixCls, collapse, isOpen }: { prefixCls?: string; collaps
49
49
[ prefixCls , collapse , isOpen ] ,
50
50
) ;
51
51
}
52
+
52
53
export const SubMenu = React . forwardRef ( function < Tag extends TagType = 'a' > (
53
54
props : SubMenuProps < Tag > ,
54
55
ref : React . Ref < HTMLLIElement > ,
@@ -72,7 +73,20 @@ export const SubMenu = React.forwardRef(function <Tag extends TagType = 'a'>(
72
73
className : [ prefixCls ? `${ prefixCls } -overlay` : null ] . filter ( Boolean ) . join ( ' ' ) . trim ( ) ,
73
74
} ;
74
75
const popupRef = React . useRef < OverlayTriggerRef > ( null ) ;
76
+ const refNode = React . useRef < HTMLElement | null > ( ) ;
77
+ const currentHeight = React . useRef < number > ( 0 ) ;
78
+ const elementSource = React . useRef < EventTarget | null > ( ) ;
75
79
const [ isOpen , setIsOpen ] = useState ( ! ! overlayProps . isOpen ) ;
80
+ const { height, setContextHeight, ele } = useContext ( ThemeContext ) ;
81
+
82
+ React . useEffect ( ( ) => {
83
+ if ( refNode . current && refNode . current . style && ele === elementSource . current ) {
84
+ const currentHeight = refNode . current ! . style . height ;
85
+ if ( height + 'px' === currentHeight ) return ;
86
+ refNode . current ! . style . height = Number ( currentHeight . substr ( 0 , currentHeight . length - 2 ) ) + height + 'px' ;
87
+ }
88
+ } , [ height ] ) ;
89
+
76
90
useMemo ( ( ) => {
77
91
if ( collapse ) setIsOpen ( false ) ;
78
92
} , [ collapse ] ) ;
@@ -93,21 +107,28 @@ export const SubMenu = React.forwardRef(function <Tag extends TagType = 'a'>(
93
107
}
94
108
function onExiting ( node : HTMLElement ) {
95
109
node . style . height = '0px' ;
110
+ setContextHeight ( {
111
+ height : - currentHeight . current ,
112
+ ele : elementSource . current ! ,
113
+ } ) ;
96
114
}
97
115
function onEnter ( node : HTMLElement ) {
98
116
node . style . height = '1px' ;
99
117
setIsOpen ( true ) ;
118
+ currentHeight . current = popupRef . current ! . overlayDom . current ! . getBoundingClientRect ( ) . height ;
119
+ setContextHeight ( {
120
+ height : currentHeight . current ,
121
+ ele : elementSource . current ! ,
122
+ } ) ;
100
123
}
101
124
function onEntering ( node : HTMLElement ) {
102
125
node . style . height = `${ node . scrollHeight } px` ;
103
126
}
104
127
function onEntered ( node : HTMLElement ) {
105
- node . style . height = 'initial' ;
106
- if ( popupRef . current && popupRef . current . overlayDom ) {
107
- node . style . height = popupRef . current . overlayDom . current ! . getBoundingClientRect ( ) . height + 'px' ;
108
- }
128
+ // node.style.height = 'initial';
129
+ node . style . height = currentHeight . current + 'px' ;
130
+ refNode . current = node ;
109
131
}
110
-
111
132
if ( ! collapse ) {
112
133
delete menuProps . onClick ;
113
134
menuProps . bordered = false ;
@@ -130,36 +151,46 @@ export const SubMenu = React.forwardRef(function <Tag extends TagType = 'a'>(
130
151
menuProps . onClick = onClick ;
131
152
}
132
153
return (
133
- < li data-menu = "subitem" ref = { ref } >
134
- < OverlayTrigger
135
- placement = "rightTop"
136
- autoAdjustOverflow
137
- disabled = { disabled }
138
- isOpen = { isOpen }
139
- usePortal = { false }
140
- isOutside
141
- { ...overlayTriggerProps }
142
- { ...overlayProps }
143
- ref = { popupRef }
144
- overlay = { < Menu { ...menuProps } style = { ! collapse ? { paddingLeft : inlineIndent } : { } } /> }
145
- >
146
- < MenuItem
147
- { ...other }
148
- ref = { null }
154
+ < div
155
+ onClick = { ( e ) => {
156
+ if ( collapse ) {
157
+ e . stopPropagation ( ) ;
158
+ return ;
159
+ }
160
+ elementSource . current = e . target ;
161
+ } }
162
+ >
163
+ < li data-menu = "subitem" ref = { ref } >
164
+ < OverlayTrigger
165
+ placement = "rightTop"
166
+ autoAdjustOverflow
149
167
disabled = { disabled }
150
- isSubMenuItem
151
- addonAfter = { < IconView collapse = { collapse } prefixCls = { prefixCls } isOpen = { isOpen } /> }
152
- className = { [
153
- prefixCls ? `${ prefixCls } -title` : null ,
154
- ! collapse ? `${ prefixCls } -collapse-title` : null ,
155
- className ,
156
- ]
157
- . filter ( Boolean )
158
- . join ( ' ' )
159
- . trim ( ) }
160
- />
161
- </ OverlayTrigger >
162
- </ li >
168
+ isOpen = { isOpen }
169
+ usePortal = { false }
170
+ isOutside
171
+ { ...overlayTriggerProps }
172
+ { ...overlayProps }
173
+ ref = { popupRef }
174
+ overlay = { < Menu { ...menuProps } style = { ! collapse ? { paddingLeft : inlineIndent } : { } } /> }
175
+ >
176
+ < MenuItem
177
+ { ...other }
178
+ ref = { null }
179
+ disabled = { disabled }
180
+ isSubMenuItem
181
+ addonAfter = { < IconView collapse = { collapse } prefixCls = { prefixCls } isOpen = { isOpen } /> }
182
+ className = { [
183
+ prefixCls ? `${ prefixCls } -title` : null ,
184
+ ! collapse ? `${ prefixCls } -collapse-title` : null ,
185
+ className ,
186
+ ]
187
+ . filter ( Boolean )
188
+ . join ( ' ' )
189
+ . trim ( ) }
190
+ />
191
+ </ OverlayTrigger >
192
+ </ li >
193
+ </ div >
163
194
) ;
164
195
} ) ;
165
196
0 commit comments