@@ -3,6 +3,7 @@ import PT from "prop-types";
3
3
import cn from "classnames" ;
4
4
import { usePopper } from "react-popper" ;
5
5
import Button from "components/Button" ;
6
+ import Tooltip from "components/Tooltip" ;
6
7
import IconArrowDown from "../../assets/images/icon-arrow-down-narrow.svg" ;
7
8
import { useClickOutside } from "utils/hooks" ;
8
9
import { negate , stopPropagation } from "utils/misc" ;
@@ -39,48 +40,6 @@ const ActionsMenu = ({
39
40
setIsOpen ( negate ) ;
40
41
} , [ ] ) ;
41
42
42
- const onItemClick = useCallback (
43
- ( event ) => {
44
- let index = + event . target . dataset . actionIndex ;
45
- let item = items [ index ] ;
46
- if ( ! item || item . disabled || item . separator ) {
47
- return ;
48
- }
49
- closeMenu ( ) ;
50
- item . action ?. ( ) ;
51
- } ,
52
- [ items , closeMenu ]
53
- ) ;
54
-
55
- const menuItems = useMemo (
56
- ( ) =>
57
- items . map ( ( item , index ) => {
58
- if ( item . hidden ) {
59
- return null ;
60
- } else if ( item . separator ) {
61
- return < div key = { index } className = { compStyles . separator } /> ;
62
- } else {
63
- return (
64
- < div
65
- key = { index }
66
- data-action-index = { index }
67
- onClick = { onItemClick }
68
- role = "button"
69
- tabIndex = { 0 }
70
- className = { cn (
71
- compStyles . item ,
72
- { [ compStyles . itemDisabled ] : item . disabled } ,
73
- item . className
74
- ) }
75
- >
76
- { item . label }
77
- </ div >
78
- ) ;
79
- }
80
- } ) ,
81
- [ items , onItemClick ]
82
- ) ;
83
-
84
43
return (
85
44
< div
86
45
className = { compStyles . container }
@@ -104,8 +63,8 @@ const ActionsMenu = ({
104
63
</ Button >
105
64
{ isOpen && (
106
65
< Menu
107
- items = { menuItems }
108
- onClickOutside = { closeMenu }
66
+ close = { closeMenu }
67
+ items = { items }
109
68
referenceElement = { referenceElement }
110
69
strategy = { popupStrategy }
111
70
/>
@@ -123,6 +82,7 @@ ActionsMenu.propTypes = {
123
82
label : PT . string ,
124
83
action : PT . func ,
125
84
separator : PT . bool ,
85
+ disabled : PT . bool ,
126
86
hidden : PT . bool ,
127
87
} )
128
88
) ,
@@ -138,7 +98,7 @@ export default ActionsMenu;
138
98
* @param {Object } props component properties
139
99
* @returns {JSX.Element }
140
100
*/
141
- const Menu = ( { items , onClickOutside , referenceElement, strategy } ) => {
101
+ const Menu = ( { close , items , referenceElement, strategy } ) => {
142
102
const [ popperElement , setPopperElement ] = useState ( null ) ;
143
103
const [ arrowElement , setArrowElement ] = useState ( null ) ;
144
104
const { styles, attributes } = usePopper ( referenceElement , popperElement , {
@@ -180,7 +140,73 @@ const Menu = ({ items, onClickOutside, referenceElement, strategy }) => {
180
140
] ,
181
141
} ) ;
182
142
183
- useClickOutside ( popperElement , onClickOutside , [ ] ) ;
143
+ const onClickItem = useCallback (
144
+ ( event ) => {
145
+ let targetData = event . target . dataset ;
146
+ let index = + targetData . actionIndex ;
147
+ let item = items [ index ] ;
148
+ if ( ! item || targetData . disabled || item . separator ) {
149
+ return ;
150
+ }
151
+ close ( ) ;
152
+ item . action ?. ( ) ;
153
+ } ,
154
+ [ close , items ]
155
+ ) ;
156
+
157
+ useClickOutside ( popperElement , close , [ ] ) ;
158
+
159
+ const menuItems = useMemo ( ( ) => {
160
+ return items . map ( ( item , index ) => {
161
+ if ( item . hidden ) {
162
+ return null ;
163
+ } else if ( item . separator ) {
164
+ return < div key = { index } className = { compStyles . separator } /> ;
165
+ } else {
166
+ let reasonsDisabled = item . checkDisabled ?. ( ) ;
167
+ let disabled = ! ! item . disabled || ! ! reasonsDisabled ;
168
+ let attrs = {
169
+ key : index ,
170
+ "data-action-index" : index ,
171
+ onClick : onClickItem ,
172
+ role : "button" ,
173
+ tabIndex : 0 ,
174
+ className : cn (
175
+ compStyles . item ,
176
+ { [ compStyles . itemDisabled ] : disabled } ,
177
+ item . className
178
+ ) ,
179
+ } ;
180
+ if ( disabled ) {
181
+ attrs [ "data-disabled" ] = true ;
182
+ }
183
+ return (
184
+ < div { ...attrs } >
185
+ { reasonsDisabled ? (
186
+ < Tooltip
187
+ content = {
188
+ reasonsDisabled . length === 1 ? (
189
+ reasonsDisabled [ 0 ]
190
+ ) : (
191
+ < ul >
192
+ { reasonsDisabled . map ( ( text , index ) => (
193
+ < li key = { index } > { text } </ li >
194
+ ) ) }
195
+ </ ul >
196
+ )
197
+ }
198
+ strategy = "fixed"
199
+ >
200
+ { item . label }
201
+ </ Tooltip >
202
+ ) : (
203
+ item . label
204
+ ) }
205
+ </ div >
206
+ ) ;
207
+ }
208
+ } ) ;
209
+ } , [ items , onClickItem ] ) ;
184
210
185
211
return (
186
212
< div
@@ -189,7 +215,7 @@ const Menu = ({ items, onClickOutside, referenceElement, strategy }) => {
189
215
style = { styles . popper }
190
216
{ ...attributes . popper }
191
217
>
192
- < div className = { compStyles . items } > { items } </ div >
218
+ < div className = { compStyles . items } > { menuItems } </ div >
193
219
< div
194
220
ref = { setArrowElement }
195
221
style = { styles . arrow }
@@ -200,8 +226,17 @@ const Menu = ({ items, onClickOutside, referenceElement, strategy }) => {
200
226
} ;
201
227
202
228
Menu . propTypes = {
203
- items : PT . array . isRequired ,
204
- onClickOutside : PT . func . isRequired ,
229
+ close : PT . func . isRequired ,
230
+ items : PT . arrayOf (
231
+ PT . shape ( {
232
+ label : PT . string ,
233
+ action : PT . func ,
234
+ checkDisabled : PT . func ,
235
+ disabled : PT . bool ,
236
+ separator : PT . bool ,
237
+ hidden : PT . bool ,
238
+ } )
239
+ ) ,
205
240
referenceElement : PT . object ,
206
241
strategy : PT . oneOf ( [ "absolute" , "fixed" ] ) ,
207
242
} ;
0 commit comments