@@ -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,75 @@ 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 disabled = ! ! item . disabled ;
167
+ let reasonsDisabled = Array . isArray ( item . disabled )
168
+ ? item . disabled
169
+ : null ;
170
+ let attrs = {
171
+ key : index ,
172
+ "data-action-index" : index ,
173
+ onClick : onClickItem ,
174
+ role : "button" ,
175
+ tabIndex : 0 ,
176
+ className : cn (
177
+ compStyles . item ,
178
+ { [ compStyles . itemDisabled ] : disabled } ,
179
+ item . className
180
+ ) ,
181
+ } ;
182
+ if ( disabled ) {
183
+ attrs [ "data-disabled" ] = true ;
184
+ }
185
+ return (
186
+ < div { ...attrs } >
187
+ { reasonsDisabled ? (
188
+ < Tooltip
189
+ content = {
190
+ reasonsDisabled . length === 1 ? (
191
+ reasonsDisabled [ 0 ]
192
+ ) : (
193
+ < ul >
194
+ { reasonsDisabled . map ( ( text , index ) => (
195
+ < li key = { index } > { text } </ li >
196
+ ) ) }
197
+ </ ul >
198
+ )
199
+ }
200
+ strategy = "fixed"
201
+ >
202
+ { item . label }
203
+ </ Tooltip >
204
+ ) : (
205
+ item . label
206
+ ) }
207
+ </ div >
208
+ ) ;
209
+ }
210
+ } ) ;
211
+ } , [ items , onClickItem ] ) ;
184
212
185
213
return (
186
214
< div
@@ -189,7 +217,7 @@ const Menu = ({ items, onClickOutside, referenceElement, strategy }) => {
189
217
style = { styles . popper }
190
218
{ ...attributes . popper }
191
219
>
192
- < div className = { compStyles . items } > { items } </ div >
220
+ < div className = { compStyles . items } > { menuItems } </ div >
193
221
< div
194
222
ref = { setArrowElement }
195
223
style = { styles . arrow }
@@ -200,8 +228,17 @@ const Menu = ({ items, onClickOutside, referenceElement, strategy }) => {
200
228
} ;
201
229
202
230
Menu . propTypes = {
203
- items : PT . array . isRequired ,
204
- onClickOutside : PT . func . isRequired ,
231
+ close : PT . func . isRequired ,
232
+ items : PT . arrayOf (
233
+ PT . shape ( {
234
+ label : PT . string ,
235
+ action : PT . func ,
236
+ checkDisabled : PT . func ,
237
+ disabled : PT . bool ,
238
+ separator : PT . bool ,
239
+ hidden : PT . bool ,
240
+ } )
241
+ ) ,
205
242
referenceElement : PT . object ,
206
243
strategy : PT . oneOf ( [ "absolute" , "fixed" ] ) ,
207
244
} ;
0 commit comments