Переглянути джерело

fix: tooltip onMouseLeave not trigger sometimes when moving mouse quickly will cause hide not work (#2306)

代强 1 рік тому
батько
коміт
c473cfc689

+ 13 - 2
packages/semi-foundation/tooltip/foundation.ts

@@ -29,7 +29,7 @@ export interface TooltipAdapter<P = Record<string, any>, S = Record<string, any>
     notifyVisibleChange(isVisible: any): void;
     getPopupContainerRect(): PopupContainerDOMRect;
     containerIsBody(): boolean;
-    off(arg0: string): void;
+    off(arg0: string, arg1?: () => void): void;
     canMotion(): boolean;
     registerScrollHandler(arg: () => Record<string, any>): void;
     unregisterScrollHandler(): void;
@@ -66,7 +66,8 @@ export interface TooltipAdapter<P = Record<string, any>, S = Record<string, any>
     setInitialFocus(): void;
     notifyEscKeydown(event: any): void;
     getTriggerNode(): any;
-    setId(): void
+    setId(): void;
+    getTriggerDOM(): HTMLElement|null
 }
 
 export type Position = ArrayElement<typeof strings.POSITION_SET>;
@@ -312,6 +313,16 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
     show = () => {
         const content = this.getProp('content');
         const trigger = this.getProp('trigger');
+        if (trigger==="hover") {
+            const checkTriggerIsHover = () => {
+                const triggerDOM = this._adapter.getTriggerDOM();
+                if (trigger && !triggerDOM.matches(":hover")) {
+                    this.hide();
+                }
+                this._adapter.off("portalInserted", checkTriggerIsHover);
+            };
+            this._adapter.on('portalInserted', checkTriggerIsHover);
+        }
         const clickTriggerToHide = this.getProp('clickTriggerToHide');
         const { visible, displayNone } = this.getStates();
         if (displayNone) {

+ 3 - 1
packages/semi-foundation/utils/Event.ts

@@ -44,7 +44,9 @@ export default class Event {
         if (!this._eventMap.has(event)) {
             return false;
         }
-        this._eventMap.get(event).forEach(callback => callback(...args));
+        const callbacks = [...this._eventMap.get(event)];
+        // clone to avoid someone writing  the logic of deleting callback in callbacks into his or her callback code, for example the once func above
+        callbacks.forEach(callback => callback(...args));
         return true;
     }
 }

+ 3 - 1
packages/semi-ui/overflowList/index.tsx

@@ -1,4 +1,4 @@
-import React, { CSSProperties, ReactNode, MutableRefObject, RefCallback, Key, ReactElement } from 'react';
+import React, { CSSProperties, ReactNode, MutableRefObject, RefCallback, ReactElement } from 'react';
 import cls from 'classnames';
 import BaseComponent from '../_base/baseComponent';
 import PropTypes from 'prop-types';
@@ -20,6 +20,8 @@ const RenderMode = strings.MODE_MAP;
 export type { ReactIntersectionObserverProps } from './intersectionObserver';
 export type OverflowItem = Record<string, any>;
 
+type Key = string|number
+
 export interface OverflowListProps {
     className?: string;
     collapseFrom?: 'start' | 'end';

+ 8 - 0
packages/semi-ui/tooltip/index.tsx

@@ -457,6 +457,14 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
             },
             setId: () => {
                 this.setState({ id: getUuidShort() });
+            },
+            getTriggerDOM: ()=>{
+                if (this.triggerEl.current) {
+                    return ReactDOM.findDOMNode(this.triggerEl.current as ReactInstance) as HTMLElement;
+                } else {
+                    return null;
+                }
+
             }
         };
     }