@@ -13,15 +13,19 @@ import {
1313import cn from "classnames" ;
1414import { TransitionHooks , useFixedPositioning } from "@react-md/transition" ;
1515import {
16- HorizontalPosition ,
16+ ABOVE_CENTER_ANCHOR ,
17+ BELOW_CENTER_ANCHOR ,
18+ CENTER_LEFT_ANCHOR ,
19+ CENTER_RIGHT_ANCHOR ,
1720 HoverModeEventHandlers ,
1821 HoverModeOnlyReturnValue ,
22+ PositionAnchor ,
23+ SimplePosition ,
1924 unitToNumber ,
2025 useHoverMode ,
2126 useOnUnmount ,
2227 UserInteractionMode ,
2328 useUserInteractionMode ,
24- VerticalPosition ,
2529} from "@react-md/utils" ;
2630
2731import {
@@ -39,11 +43,27 @@ import {
3943 useTooltipPosition ,
4044} from "./useTooltipPosition" ;
4145
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+
4262/**
4363 * @internal
4464 * @remarks \@since 2.8.0
4565 */
46- export type TooltipInitiated = UserInteractionMode | null ;
66+ export type TooltipInitiatedBy = UserInteractionMode | null ;
4767
4868/** @remarks \@since 2.8.0 */
4969export type TooltipTouchEventHandlers < E extends HTMLElement > = Pick <
@@ -302,7 +322,7 @@ export function useTooltip<E extends HTMLElement>({
302322 onEntered,
303323 onExited,
304324 disableSwapping,
305- disableHoverMode,
325+ disableHoverMode : disabled ,
306326 disableAutoSpacing = process . env . NODE_ENV === "test" ,
307327} : TooltipHookOptions < E > ) : TooltipHookReturnValue < E > {
308328 const containerRef = useRef < E | null > ( null ) ;
@@ -311,54 +331,52 @@ export function useTooltip<E extends HTMLElement>({
311331 defaultPosition,
312332 threshold,
313333 } ) ;
314- const horizontal = position === "left" || position === "right" ;
315334 const mode = useUserInteractionMode ( ) ;
316- const [ touched , setTouched ] = useState ( false ) ;
317- const initiated = useRef < TooltipInitiated > ( null ) ;
335+ const [ initiatedBy , setInitiatedBy ] = useState < TooltipInitiatedBy > ( null ) ;
318336 const windowFocusEvent = useRef ( false ) ;
319337 const timeout = useRef < number | undefined > ( undefined ) ;
320338 const {
321339 visible,
322340 setVisible,
323341 handlers : mouseHandlers ,
342+ disableHoverMode,
324343 ...others
325344 } = useHoverMode < E > ( {
326- disabled : disableHoverMode ,
345+ disabled,
327346 onMouseEnter : ( event ) => {
328347 onMouseEnter ?.( event ) ;
329- if ( initiated . current !== null ) {
348+ if ( initiatedBy !== null ) {
330349 event . stopPropagation ( ) ;
331350 return ;
332351 }
333352
334- initiated . current = "mouse" ;
335353 containerRef . current = event . currentTarget ;
336354 updatePosition ( event . currentTarget ) ;
355+ setInitiatedBy ( "mouse" ) ;
337356 } ,
338357 onMouseLeave : ( event ) => {
339358 onMouseLeave ?.( event ) ;
340- if ( initiated . current !== "mouse" ) {
359+ if ( initiatedBy !== "mouse" ) {
341360 event . stopPropagation ( ) ;
342361 return ;
343362 }
344363
345- initiated . current = null ;
364+ setInitiatedBy ( null ) ;
346365 } ,
347366 } ) ;
348367 const hide = useCallback ( ( ) => {
349- initiated . current = null ;
350368 window . clearTimeout ( timeout . current ) ;
351369 setVisible ( false ) ;
370+ setInitiatedBy ( null ) ;
352371 } , [ setVisible ] ) ;
353372
354373 const onBlur = ( event : FocusEvent < E > ) : void => {
355374 propOnBlur ?.( event ) ;
356375
357- if ( initiated . current !== "keyboard" ) {
376+ if ( initiatedBy !== "keyboard" ) {
358377 return ;
359378 }
360379
361- window . clearTimeout ( timeout . current ) ;
362380 hide ( ) ;
363381 } ;
364382 const onFocus = ( event : FocusEvent < E > ) : void => {
@@ -371,11 +389,11 @@ export function useTooltip<E extends HTMLElement>({
371389 return ;
372390 }
373391
374- if ( mode !== "keyboard" || initiated . current !== null ) {
392+ if ( mode !== "keyboard" || initiatedBy !== null ) {
375393 return ;
376394 }
377395
378- initiated . current = "keyboard" ;
396+ setInitiatedBy ( "keyboard" ) ;
379397 window . clearTimeout ( timeout . current ) ;
380398 containerRef . current = event . currentTarget ;
381399 updatePosition ( event . currentTarget ) ;
@@ -387,11 +405,10 @@ export function useTooltip<E extends HTMLElement>({
387405 const onKeyDown = ( event : KeyboardEvent < E > ) : void => {
388406 propOnKeyDown ?.( event ) ;
389407
390- if ( initiated . current !== "keyboard" || event . key !== "Escape" ) {
408+ if ( initiatedBy !== "keyboard" || event . key !== "Escape" ) {
391409 return ;
392410 }
393411
394- window . clearTimeout ( timeout . current ) ;
395412 hide ( ) ;
396413 } ;
397414
@@ -402,8 +419,7 @@ export function useTooltip<E extends HTMLElement>({
402419 return ;
403420 }
404421
405- initiated . current = "touch" ;
406- setTouched ( true ) ;
422+ setInitiatedBy ( "touch" ) ;
407423 window . clearTimeout ( timeout . current ) ;
408424 timeout . current = window . setTimeout ( ( ) => {
409425 setVisible ( true ) ;
@@ -453,43 +469,27 @@ export function useTooltip<E extends HTMLElement>({
453469 } ;
454470 } , [ hide , mode ] ) ;
455471 useEffect ( ( ) => {
456- if ( mode !== "touch" ) {
472+ if ( initiatedBy !== "touch" ) {
457473 return ;
458474 }
459475
476+ window . addEventListener ( "touchmove" , hide ) ;
460477 window . addEventListener ( "touchend" , hide ) ;
461478 return ( ) => {
479+ window . removeEventListener ( "touchmove" , hide ) ;
462480 window . removeEventListener ( "touchend" , hide ) ;
463481 } ;
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 ] ) ;
478483
479- window . addEventListener ( "touchmove" , handler ) ;
480- return ( ) => {
481- window . removeEventListener ( "touchmove" , handler ) ;
482- } ;
483- } , [ setVisible , touched ] ) ;
484+ useOnUnmount ( ( ) => {
485+ window . clearTimeout ( timeout . current ) ;
486+ } ) ;
484487
485488 const { updateStyle : _u , ...positionProps } = useFixedPositioning ( {
486489 style,
487- anchor : {
488- x : horizontal ? ( position as HorizontalPosition ) : "center" ,
489- y : horizontal ? "center" : ( position as VerticalPosition ) ,
490- } ,
490+ anchor : getAnchor ( position ) ,
491491 disableSwapping : disableSwapping ?? ! ! determinedPosition ,
492- fixedTo : containerRef . current ,
492+ fixedTo : containerRef ,
493493 getOptions : ( node ) => {
494494 let tooltipSpacing = dense ? denseSpacing : spacing ;
495495 /* istanbul ignore next */
@@ -516,10 +516,6 @@ export function useTooltip<E extends HTMLElement>({
516516 onExited,
517517 } ) ;
518518
519- useOnUnmount ( ( ) => {
520- window . clearTimeout ( timeout . current ) ;
521- } ) ;
522-
523519 const tooltipHandlers : Required < TooltippedElementEventHandlers < E > > = {
524520 ...mouseHandlers ,
525521 onFocus,
@@ -550,5 +546,6 @@ export function useTooltip<E extends HTMLElement>({
550546 handlers : tooltipHandlers ,
551547 elementProps,
552548 tooltipProps,
549+ disableHoverMode,
553550 } ;
554551}
0 commit comments