@@ -26,31 +26,110 @@ const Wrapper = styled.div`
26
26
27
27
const Tooltip = ( {
28
28
children,
29
- text,
30
- delay,
31
29
className,
30
+ disableFocusListener,
31
+ disableMouseListener,
32
+ enterDelay,
33
+ leaveDelay,
34
+ onBlur,
35
+ onClose,
36
+ onFocus,
37
+ onMouseEnter,
38
+ onMouseLeave,
39
+ onOpen,
32
40
style,
41
+ testId,
42
+ text,
33
43
...otherProps
34
44
} ) => {
35
45
const [ show , setShow ] = useState ( false ) ;
36
- const [ delayTimer , setDelayTimer ] = useState ( null ) ;
46
+ const [ openTimer , setOpenTimer ] = useState ( null ) ;
47
+ const [ closeTimer , setCloseTimer ] = useState ( null ) ;
48
+
49
+ const isUsingFocus = ! disableFocusListener ;
50
+ const isUsingMouse = ! disableMouseListener ;
51
+
52
+ const handleOpen = evt => {
53
+ clearTimeout ( openTimer ) ;
54
+ clearTimeout ( closeTimer ) ;
37
55
38
- const handleEnter = ( ) => {
39
56
const timer = setTimeout ( ( ) => {
40
57
setShow ( true ) ;
41
- } , delay ) ;
42
58
43
- setDelayTimer ( timer ) ;
59
+ if ( onOpen ) {
60
+ onOpen ( evt ) ;
61
+ }
62
+ } , enterDelay ) ;
63
+
64
+ setOpenTimer ( timer ) ;
65
+ } ;
66
+
67
+ const handleEnter = evt => {
68
+ evt . persist ( ) ;
69
+
70
+ if ( evt . type === 'focus' && onFocus ) {
71
+ onFocus ( evt ) ;
72
+ } else if ( evt . type === 'mouseenter' && onMouseEnter ) {
73
+ onMouseEnter ( evt ) ;
74
+ }
75
+
76
+ handleOpen ( evt ) ;
77
+ } ;
78
+
79
+ const handleClose = evt => {
80
+ clearTimeout ( openTimer ) ;
81
+ clearTimeout ( closeTimer ) ;
82
+
83
+ const timer = setTimeout ( ( ) => {
84
+ setShow ( false ) ;
85
+
86
+ if ( onClose ) {
87
+ onClose ( evt ) ;
88
+ }
89
+ } , leaveDelay ) ;
90
+
91
+ setCloseTimer ( timer ) ;
44
92
} ;
45
93
46
- const handleLeave = ( ) => {
47
- clearTimeout ( delayTimer ) ;
48
- setShow ( false ) ;
94
+ const handleLeave = evt => {
95
+ evt . persist ( ) ;
96
+
97
+ if ( evt . type === 'blur' && onBlur ) {
98
+ onBlur ( evt ) ;
99
+ } else if ( evt . type === 'mouseleave' && onMouseLeave ) {
100
+ onMouseLeave ( evt ) ;
101
+ }
102
+
103
+ handleClose ( evt ) ;
49
104
} ;
50
105
106
+ // set callbacks for onBlur and onFocus, unless disableFocusListener is true
107
+ const blurCb = isUsingFocus ? handleLeave : undefined ;
108
+ const focusCb = isUsingFocus ? handleEnter : undefined ;
109
+
110
+ // set callbacks for onMouseEnter and onMouseLeave, unless disableMouseListener is true
111
+ const mouseEnterCb = isUsingMouse ? handleEnter : undefined ;
112
+ const mouseLeaveCb = isUsingMouse ? handleLeave : undefined ;
113
+
114
+ // set the wrapper's tabIndex for focus events, unless disableFocusListener is true
115
+ const tabIndex = isUsingFocus ? '0' : undefined ;
116
+
51
117
return (
52
- < Wrapper onMouseEnter = { handleEnter } onMouseLeave = { handleLeave } >
53
- < Tip show = { show } className = { className } style = { style } { ...otherProps } >
118
+ < Wrapper
119
+ data-testid = { testId ? `${ testId } Wrapper` : undefined }
120
+ onBlur = { blurCb }
121
+ onFocus = { focusCb }
122
+ onMouseEnter = { mouseEnterCb }
123
+ onMouseLeave = { mouseLeaveCb }
124
+ tabIndex = { tabIndex }
125
+ >
126
+ < Tip
127
+ className = { className }
128
+ data-testid = { testId }
129
+ show = { show }
130
+ style = { style }
131
+ { ...otherProps }
132
+ >
54
133
{ text }
55
134
</ Tip >
56
135
{ children }
@@ -59,17 +138,37 @@ const Tooltip = ({
59
138
} ;
60
139
61
140
Tooltip . defaultProps = {
62
- delay : 1000 ,
63
141
className : '' ,
64
- style : { }
142
+ disableFocusListener : false ,
143
+ disableMouseListener : false ,
144
+ enterDelay : 1000 ,
145
+ leaveDelay : 0 ,
146
+ onBlur : undefined ,
147
+ onClose : undefined ,
148
+ onFocus : undefined ,
149
+ onMouseEnter : undefined ,
150
+ onMouseLeave : undefined ,
151
+ onOpen : undefined ,
152
+ style : { } ,
153
+ testId : undefined
65
154
} ;
66
155
67
156
Tooltip . propTypes = {
68
157
children : propTypes . node . isRequired ,
69
- text : propTypes . string . isRequired ,
70
158
className : propTypes . string ,
71
- style : propTypes . shape ( [ propTypes . string , propTypes . number ] ) ,
72
- delay : propTypes . number
159
+ disableFocusListener : propTypes . bool ,
160
+ disableMouseListener : propTypes . bool ,
161
+ enterDelay : propTypes . number ,
162
+ leaveDelay : propTypes . number ,
163
+ onBlur : propTypes . func ,
164
+ onClose : propTypes . func ,
165
+ onFocus : propTypes . func ,
166
+ onMouseEnter : propTypes . func ,
167
+ onMouseLeave : propTypes . func ,
168
+ onOpen : propTypes . func ,
169
+ style : propTypes . shape ( { } ) ,
170
+ testId : propTypes . string ,
171
+ text : propTypes . string . isRequired
73
172
} ;
74
173
75
174
export default Tooltip ;
0 commit comments