88/* eslint-disable guard-for-in */
99// @ts -nocheck
1010
11- import React , { useState , useEffect } from 'react' ;
11+ import React , { useState , useEffect , useRef } from 'react' ;
1212import { Group } from '@visx/group' ;
1313import { hierarchy , Tree } from '@visx/hierarchy' ;
1414import { LinearGradient } from '@visx/gradient' ;
@@ -47,9 +47,9 @@ export default function ComponentMap({
4747 const [ orientation , setOrientation ] = useState ( 'vertical' ) ;
4848 const [ linkType , setLinkType ] = useState ( 'diagonal' ) ;
4949 const [ stepPercent , setStepPercent ] = useState ( 10 ) ;
50- const [ Tooltip , setTooltip ] = useState ( false ) ;
5150 const [ selectedNode , setSelectedNode ] = useState ( 'root' ) ;
5251 const [ , dispatch ] = useStoreContext ( ) ;
52+ const toolTipTimeoutID = useRef ( null ) ;
5353
5454 useEffect ( ( ) => {
5555 dispatch ( setCurrentTabInApp ( 'map' ) ) ;
@@ -191,7 +191,6 @@ export default function ComponentMap({
191191 < LinearGradient id = 'links-gradient' from = '#fd9b93' to = '#fe6e9e' />
192192 < rect
193193 onClick = { ( ) => {
194- setTooltip ( false ) ;
195194 hideTooltip ( ) ;
196195 } }
197196 width = { totalWidth }
@@ -266,7 +265,6 @@ export default function ComponentMap({
266265 onClick = { ( ) => {
267266 dispatch ( toggleExpanded ( node . data ) ) ;
268267 hideTooltip ( ) ;
269- setTooltip ( false ) ;
270268 } }
271269 />
272270 ) }
@@ -290,16 +288,48 @@ export default function ComponentMap({
290288 onClick = { ( ) => {
291289 dispatch ( toggleExpanded ( node . data ) ) ;
292290 hideTooltip ( ) ;
293- setTooltip ( false ) ;
294291 } }
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.
297314 handleMouseAndClickOver ( event ) ;
298315 } }
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 ) ;
303333 } }
304334 />
305335 ) }
@@ -329,33 +359,48 @@ export default function ComponentMap({
329359 top = { tooltipTop }
330360 left = { tooltipLeft }
331361 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+ } }
333383 >
334- < div
335- onClick = { ( ) => {
336- setTooltip ( false ) ;
337- hideTooltip ( ) ;
338- } }
339- >
384+ < div >
340385 < div style = { { } } >
341386 { ' ' }
342387 < strong > { tooltipData . name } </ strong > { ' ' }
343388 </ div >
344389 < div > Render time: { formatRenderTime ( tooltipData . componentData . actualDuration ) } </ div >
345390 < div className = 'stateTip' >
346- State:
347- { formatState ( tooltipData . state ) }
391+ State: { formatState ( tooltipData . state ) }
348392 </ div >
349393 < div style = { React . scrollStyle } >
350394 < div className = 'tooltipWrapper' >
351395 < h2 > Props:</ h2 >
352396 { formatData ( tooltipData . componentData . props , 'props' ) }
353397 </ div >
354-
398+
399+ { /* Currently no use for this field
355400 <div className='tooltipWrapper'>
356401 <h2>Initial Context:</h2>
357402 {formatData(tooltipData.componentData.context, 'context')}
358- </ div >
403+ </div> */ }
359404
360405 < div className = 'tooltipWrapper' >
361406 < h2 > State:</ h2 >
0 commit comments