@@ -13,15 +13,19 @@ import {
13
13
import cn from "classnames" ;
14
14
import { TransitionHooks , useFixedPositioning } from "@react-md/transition" ;
15
15
import {
16
- HorizontalPosition ,
16
+ ABOVE_CENTER_ANCHOR ,
17
+ BELOW_CENTER_ANCHOR ,
18
+ CENTER_LEFT_ANCHOR ,
19
+ CENTER_RIGHT_ANCHOR ,
17
20
HoverModeEventHandlers ,
18
21
HoverModeOnlyReturnValue ,
22
+ PositionAnchor ,
23
+ SimplePosition ,
19
24
unitToNumber ,
20
25
useHoverMode ,
21
26
useOnUnmount ,
22
27
UserInteractionMode ,
23
28
useUserInteractionMode ,
24
- VerticalPosition ,
25
29
} from "@react-md/utils" ;
26
30
27
31
import {
@@ -39,11 +43,27 @@ import {
39
43
useTooltipPosition ,
40
44
} from "./useTooltipPosition" ;
41
45
46
+ /** @internal */
47
+ function getAnchor ( position : SimplePosition ) : PositionAnchor {
48
+ switch ( position ) {
49
+ case "above" :
50
+ return ABOVE_CENTER_ANCHOR ;
51
+ case "below" :
52
+ return BELOW_CENTER_ANCHOR ;
53
+ case "left" :
54
+ return CENTER_LEFT_ANCHOR ;
55
+ case "right" :
56
+ return CENTER_RIGHT_ANCHOR ;
57
+ default :
58
+ throw new Error ( `Invalid position: ${ position } ` ) ;
59
+ }
60
+ }
61
+
42
62
/**
43
63
* @internal
44
64
* @remarks \@since 2.8.0
45
65
*/
46
- export type TooltipInitiated = UserInteractionMode | null ;
66
+ export type TooltipInitiatedBy = UserInteractionMode | null ;
47
67
48
68
/** @remarks \@since 2.8.0 */
49
69
export type TooltipTouchEventHandlers < E extends HTMLElement > = Pick <
@@ -302,7 +322,7 @@ export function useTooltip<E extends HTMLElement>({
302
322
onEntered,
303
323
onExited,
304
324
disableSwapping,
305
- disableHoverMode,
325
+ disableHoverMode : disabled ,
306
326
disableAutoSpacing = process . env . NODE_ENV === "test" ,
307
327
} : TooltipHookOptions < E > ) : TooltipHookReturnValue < E > {
308
328
const containerRef = useRef < E | null > ( null ) ;
@@ -311,54 +331,52 @@ export function useTooltip<E extends HTMLElement>({
311
331
defaultPosition,
312
332
threshold,
313
333
} ) ;
314
- const horizontal = position === "left" || position === "right" ;
315
334
const mode = useUserInteractionMode ( ) ;
316
- const [ touched , setTouched ] = useState ( false ) ;
317
- const initiated = useRef < TooltipInitiated > ( null ) ;
335
+ const [ initiatedBy , setInitiatedBy ] = useState < TooltipInitiatedBy > ( null ) ;
318
336
const windowFocusEvent = useRef ( false ) ;
319
337
const timeout = useRef < number | undefined > ( undefined ) ;
320
338
const {
321
339
visible,
322
340
setVisible,
323
341
handlers : mouseHandlers ,
342
+ disableHoverMode,
324
343
...others
325
344
} = useHoverMode < E > ( {
326
- disabled : disableHoverMode ,
345
+ disabled,
327
346
onMouseEnter : ( event ) => {
328
347
onMouseEnter ?.( event ) ;
329
- if ( initiated . current !== null ) {
348
+ if ( initiatedBy !== null ) {
330
349
event . stopPropagation ( ) ;
331
350
return ;
332
351
}
333
352
334
- initiated . current = "mouse" ;
335
353
containerRef . current = event . currentTarget ;
336
354
updatePosition ( event . currentTarget ) ;
355
+ setInitiatedBy ( "mouse" ) ;
337
356
} ,
338
357
onMouseLeave : ( event ) => {
339
358
onMouseLeave ?.( event ) ;
340
- if ( initiated . current !== "mouse" ) {
359
+ if ( initiatedBy !== "mouse" ) {
341
360
event . stopPropagation ( ) ;
342
361
return ;
343
362
}
344
363
345
- initiated . current = null ;
364
+ setInitiatedBy ( null ) ;
346
365
} ,
347
366
} ) ;
348
367
const hide = useCallback ( ( ) => {
349
- initiated . current = null ;
350
368
window . clearTimeout ( timeout . current ) ;
351
369
setVisible ( false ) ;
370
+ setInitiatedBy ( null ) ;
352
371
} , [ setVisible ] ) ;
353
372
354
373
const onBlur = ( event : FocusEvent < E > ) : void => {
355
374
propOnBlur ?.( event ) ;
356
375
357
- if ( initiated . current !== "keyboard" ) {
376
+ if ( initiatedBy !== "keyboard" ) {
358
377
return ;
359
378
}
360
379
361
- window . clearTimeout ( timeout . current ) ;
362
380
hide ( ) ;
363
381
} ;
364
382
const onFocus = ( event : FocusEvent < E > ) : void => {
@@ -371,11 +389,11 @@ export function useTooltip<E extends HTMLElement>({
371
389
return ;
372
390
}
373
391
374
- if ( mode !== "keyboard" || initiated . current !== null ) {
392
+ if ( mode !== "keyboard" || initiatedBy !== null ) {
375
393
return ;
376
394
}
377
395
378
- initiated . current = "keyboard" ;
396
+ setInitiatedBy ( "keyboard" ) ;
379
397
window . clearTimeout ( timeout . current ) ;
380
398
containerRef . current = event . currentTarget ;
381
399
updatePosition ( event . currentTarget ) ;
@@ -387,11 +405,10 @@ export function useTooltip<E extends HTMLElement>({
387
405
const onKeyDown = ( event : KeyboardEvent < E > ) : void => {
388
406
propOnKeyDown ?.( event ) ;
389
407
390
- if ( initiated . current !== "keyboard" || event . key !== "Escape" ) {
408
+ if ( initiatedBy !== "keyboard" || event . key !== "Escape" ) {
391
409
return ;
392
410
}
393
411
394
- window . clearTimeout ( timeout . current ) ;
395
412
hide ( ) ;
396
413
} ;
397
414
@@ -402,8 +419,7 @@ export function useTooltip<E extends HTMLElement>({
402
419
return ;
403
420
}
404
421
405
- initiated . current = "touch" ;
406
- setTouched ( true ) ;
422
+ setInitiatedBy ( "touch" ) ;
407
423
window . clearTimeout ( timeout . current ) ;
408
424
timeout . current = window . setTimeout ( ( ) => {
409
425
setVisible ( true ) ;
@@ -453,43 +469,27 @@ export function useTooltip<E extends HTMLElement>({
453
469
} ;
454
470
} , [ hide , mode ] ) ;
455
471
useEffect ( ( ) => {
456
- if ( mode !== "touch" ) {
472
+ if ( initiatedBy !== "touch" ) {
457
473
return ;
458
474
}
459
475
476
+ window . addEventListener ( "touchmove" , hide ) ;
460
477
window . addEventListener ( "touchend" , hide ) ;
461
478
return ( ) => {
479
+ window . removeEventListener ( "touchmove" , hide ) ;
462
480
window . removeEventListener ( "touchend" , hide ) ;
463
481
} ;
464
- } , [ hide , mode ] ) ;
465
- useEffect ( ( ) => {
466
- if ( ! touched ) {
467
- return ;
468
- }
469
-
470
- // need to cancel the tooltip appearance if a touchmove event occurs before
471
- // the tooltip appears since it means the page will scroll
472
- const handler = ( ) : void => {
473
- initiated . current = null ;
474
- window . clearTimeout ( timeout . current ) ;
475
- setTouched ( false ) ;
476
- setVisible ( false ) ;
477
- } ;
482
+ } , [ hide , initiatedBy , setVisible ] ) ;
478
483
479
- window . addEventListener ( "touchmove" , handler ) ;
480
- return ( ) => {
481
- window . removeEventListener ( "touchmove" , handler ) ;
482
- } ;
483
- } , [ setVisible , touched ] ) ;
484
+ useOnUnmount ( ( ) => {
485
+ window . clearTimeout ( timeout . current ) ;
486
+ } ) ;
484
487
485
488
const { updateStyle : _u , ...positionProps } = useFixedPositioning ( {
486
489
style,
487
- anchor : {
488
- x : horizontal ? ( position as HorizontalPosition ) : "center" ,
489
- y : horizontal ? "center" : ( position as VerticalPosition ) ,
490
- } ,
490
+ anchor : getAnchor ( position ) ,
491
491
disableSwapping : disableSwapping ?? ! ! determinedPosition ,
492
- fixedTo : containerRef . current ,
492
+ fixedTo : containerRef ,
493
493
getOptions : ( node ) => {
494
494
let tooltipSpacing = dense ? denseSpacing : spacing ;
495
495
/* istanbul ignore next */
@@ -516,10 +516,6 @@ export function useTooltip<E extends HTMLElement>({
516
516
onExited,
517
517
} ) ;
518
518
519
- useOnUnmount ( ( ) => {
520
- window . clearTimeout ( timeout . current ) ;
521
- } ) ;
522
-
523
519
const tooltipHandlers : Required < TooltippedElementEventHandlers < E > > = {
524
520
...mouseHandlers ,
525
521
onFocus,
@@ -550,5 +546,6 @@ export function useTooltip<E extends HTMLElement>({
550
546
handlers : tooltipHandlers ,
551
547
elementProps,
552
548
tooltipProps,
549
+ disableHoverMode,
553
550
} ;
554
551
}
0 commit comments