8
8
/* eslint-disable guard-for-in */
9
9
// @ts -nocheck
10
10
11
- import React , { useState , useEffect } from 'react' ;
11
+ import React , { useState , useEffect , useRef } from 'react' ;
12
12
import { Group } from '@visx/group' ;
13
13
import { hierarchy , Tree } from '@visx/hierarchy' ;
14
14
import { LinearGradient } from '@visx/gradient' ;
@@ -47,9 +47,9 @@ export default function ComponentMap({
47
47
const [ orientation , setOrientation ] = useState ( 'vertical' ) ;
48
48
const [ linkType , setLinkType ] = useState ( 'diagonal' ) ;
49
49
const [ stepPercent , setStepPercent ] = useState ( 10 ) ;
50
- const [ Tooltip , setTooltip ] = useState ( false ) ;
51
50
const [ selectedNode , setSelectedNode ] = useState ( 'root' ) ;
52
51
const [ , dispatch ] = useStoreContext ( ) ;
52
+ const toolTipTimeoutID = useRef ( null ) ;
53
53
54
54
useEffect ( ( ) => {
55
55
dispatch ( setCurrentTabInApp ( 'map' ) ) ;
@@ -191,7 +191,6 @@ export default function ComponentMap({
191
191
< LinearGradient id = 'links-gradient' from = '#fd9b93' to = '#fe6e9e' />
192
192
< rect
193
193
onClick = { ( ) => {
194
- setTooltip ( false ) ;
195
194
hideTooltip ( ) ;
196
195
} }
197
196
width = { totalWidth }
@@ -266,7 +265,6 @@ export default function ComponentMap({
266
265
onClick = { ( ) => {
267
266
dispatch ( toggleExpanded ( node . data ) ) ;
268
267
hideTooltip ( ) ;
269
- setTooltip ( false ) ;
270
268
} }
271
269
/>
272
270
) }
@@ -290,16 +288,48 @@ export default function ComponentMap({
290
288
onClick = { ( ) => {
291
289
dispatch ( toggleExpanded ( node . data ) ) ;
292
290
hideTooltip ( ) ;
293
- setTooltip ( false ) ;
294
291
} }
295
- onMouseOver = { ( event ) => {
296
- setTooltip ( true ) ;
292
+ // Mouse Enter Rect (Component Node) -----------------------------------------------------------------------
293
+ /** This onMouseEnter event fires when the mouse first moves/hovers over a component node.
294
+ * The supplied event listener callback produces a Tooltip element for the current node. */
295
+
296
+ onMouseEnter = { ( event ) => {
297
+ /** This 'if' statement block checks to see if you've just left another component node
298
+ * by seeing if there's a current setTimeout waiting to close that component node's
299
+ * tooltip (see onMouseLeave immediately below).
300
+ * This setTimeout gives the mouse time to enter the tooltip element so the tooltip
301
+ * can persist. If instead of entering said tooltip element you've left the previous
302
+ * component node to enter this component node, this logic will clear the timeout event,
303
+ * and close the tooltip. */
304
+ if ( toolTipTimeoutID . current !== null ) {
305
+ clearTimeout ( toolTipTimeoutID . current ) ;
306
+ hideTooltip ( ) ;
307
+ }
308
+ /** The following line resets the toolTipTimeoutID.current to null, showing that there
309
+ * are no current setTimeouts running. I placed this outside of the above if statement
310
+ * to make sure there are no edge cases that would allow for the toolTipTimeoutID.current
311
+ * to hold onto an old reference. */
312
+ toolTipTimeoutID . current = null ;
313
+ //This generates a tooltip for the component node the mouse has entered.
297
314
handleMouseAndClickOver ( event ) ;
298
315
} }
299
- // with onmouseOver, this produces a hover over effect for the Tooltip
300
- onMouseOut = { ( ) => {
301
- hideTooltip ( ) ;
302
- setTooltip ( false ) ;
316
+
317
+ // Mouse Leave Rect (Component Node) --------------------------------------------------------------------------
318
+ /** This onMouseLeave event fires when the mouse leaves a component node.
319
+ * The supplied event listener callback generates a setTimeout call which gives the
320
+ * mouse a certain amount of time between leaving the current component node and
321
+ * closing the tooltip for that node.
322
+ * If the mouse enters the tooltip before the timeout delay has passed, the
323
+ * setTimeout event will be canceled. */
324
+ onMouseLeave = { ( ) => {
325
+ // This line invokes setTimeout and saves its ID to the useRef var toolTipTimeoutID
326
+ toolTipTimeoutID . current = setTimeout ( ( ) => {
327
+ // hideTooltip unmounts the tooltip
328
+ hideTooltip ( ) ;
329
+ // As the timeout has been executed, the timeoutID can be reset to null
330
+ toolTipTimeoutID . current = null ;
331
+ //There is a delay of 300 ms
332
+ } , 300 ) ;
303
333
} }
304
334
/>
305
335
) }
@@ -329,33 +359,48 @@ export default function ComponentMap({
329
359
top = { tooltipTop }
330
360
left = { tooltipLeft }
331
361
style = { tooltipStyles }
332
- onClick = { hideTooltip }
362
+
363
+ //------------- Mouse Over TooltipInPortal--------------------------------------------------------------------
364
+ /** This onMouseEnter fires when the mouse first moves/hovers over the tooltip
365
+ * The supplied event listener callback stops the setTimeout that was going to
366
+ * close the tooltip from firing */
367
+
368
+ onMouseEnter = { ( ) => {
369
+ // The setTimeoutID stored in toolTipTimeoutID.current is from the setTimeout initiated by leaving the
370
+ // component node that generated the tooltip. If you've triggered an onMouseEnter event in that tooltip,
371
+ clearTimeout ( toolTipTimeoutID . current ) ;
372
+ // This line resets the timeoutID to null
373
+ toolTipTimeoutID . current = null ;
374
+ } }
375
+
376
+ //------------- Mouse Leave TooltipInPortal -----------------------------------------------------------------
377
+ /** This onMouseLeave event fires when the mouse leaves the tooltip
378
+ * The supplied event listener callback unmounts the tooltip */
379
+ onMouseLeave = { ( ) => {
380
+ // hideTooltip unmounts the tooltip
381
+ hideTooltip ( ) ;
382
+ } }
333
383
>
334
- < div
335
- onClick = { ( ) => {
336
- setTooltip ( false ) ;
337
- hideTooltip ( ) ;
338
- } }
339
- >
384
+ < div >
340
385
< div style = { { } } >
341
386
{ ' ' }
342
387
< strong > { tooltipData . name } </ strong > { ' ' }
343
388
</ div >
344
389
< div > Render time: { formatRenderTime ( tooltipData . componentData . actualDuration ) } </ div >
345
390
< div className = 'stateTip' >
346
- State:
347
- { formatState ( tooltipData . state ) }
391
+ State: { formatState ( tooltipData . state ) }
348
392
</ div >
349
393
< div style = { React . scrollStyle } >
350
394
< div className = 'tooltipWrapper' >
351
395
< h2 > Props:</ h2 >
352
396
{ formatData ( tooltipData . componentData . props , 'props' ) }
353
397
</ div >
354
-
398
+
399
+ { /* Currently no use for this field
355
400
<div className='tooltipWrapper'>
356
401
<h2>Initial Context:</h2>
357
402
{formatData(tooltipData.componentData.context, 'context')}
358
- </ div >
403
+ </div> */ }
359
404
360
405
< div className = 'tooltipWrapper' >
361
406
< h2 > State:</ h2 >
0 commit comments