diff --git a/src/lib/molecules/Tooltip/Tooltip.test.tsx b/src/lib/molecules/Tooltip/Tooltip.test.tsx index 77bfda27..4b1cf01a 100644 --- a/src/lib/molecules/Tooltip/Tooltip.test.tsx +++ b/src/lib/molecules/Tooltip/Tooltip.test.tsx @@ -60,13 +60,6 @@ describe('Tooltip', () => { expect(provider().find(`.${position}`).exists()).toBeTruthy(); }); - it('handle onClick', () => { - const jestFn = jest.fn(); - const wrapper = setup.setProps({ onClick: jestFn }); - wrapper.find('.test').simulate('click'); - expect(jestFn).toHaveBeenCalled(); - }); - it('handle onMouseEnter', () => { setup.find('.test').simulate('mouseEnter'); expect(provider().find('.tooltip-c-p').exists()).toBeTruthy(); diff --git a/src/lib/molecules/Tooltip/Tooltip.tsx b/src/lib/molecules/Tooltip/Tooltip.tsx index c9c4f7e0..98fe37be 100644 --- a/src/lib/molecules/Tooltip/Tooltip.tsx +++ b/src/lib/molecules/Tooltip/Tooltip.tsx @@ -3,12 +3,13 @@ import React, { useContext, CSSProperties, JSX, - MouseEvent, FC, - PointerEvent, cloneElement, Children, - Fragment + Fragment, + useEffect, + RefObject, + useMemo } from 'react'; import { shift, flip, offset } from '@floating-ui/core'; import { FloatingPortal, autoUpdate, useFloating } from '@floating-ui/react'; @@ -16,10 +17,6 @@ import { Placement } from '@floating-ui/utils'; import { ReferenceType } from '@floating-ui/react-dom'; import { isForwardRef } from 'react-is'; -// Utils -//@ts-ignore -import { noop } from 'utils'; - // Hooks //@ts-ignore import { useDeviceType } from 'hooks'; @@ -82,39 +79,49 @@ export interface ITooltipProps { * In case of `false` value, the children component will rendered without Tooltip. */ isVisible?: boolean; - /** - * The action will triggered when the Tooltip component will clicked. - */ - onClick?: (e: MouseEvent) => void; } -const FindAndMergeRef = void }>( +type JSXWithRef = JSX.Element & { ref: RefObject }; + +const FindAndSetRef = ( children: JSX.Element | JSX.Element[], childProps: T, componentRef: (node: ReferenceType | null) => void -) => - Children.map(children, (el, i) => { - const newProps = { - ...childProps, - onClick: (e: PointerEvent) => childProps?.onClick(e, el), - ref: i === 0 ? componentRef : {} +) => { + return Children.map(children, (node, i) => { + const el = node as JSXWithRef; + + let newProps = { + ...childProps }; if (el?.type === Fragment && el.props.children) { - return FindAndMergeRef(el.props.children, childProps, componentRef); + return FindAndSetRef(el.props.children, newProps, componentRef); } + if (isForwardRef(el)) { - return FindAndMergeRef(el.type.render(el.props), newProps, componentRef); + return FindAndSetRef(el.type.render(el.props, el.ref), newProps, componentRef); } + if (typeof el?.type === 'string') { + if (!el.ref && i === 0) { + newProps = { ...newProps, ref: componentRef }; + } + return cloneElement(el, newProps); } + if (typeof el?.type === 'function') { - return FindAndMergeRef(el.type(el.props), newProps, componentRef); + if (!el.ref) { + newProps = { ...newProps, ref: componentRef }; + } + + return cloneElement(el.type(el.props), newProps); } return el && cloneElement(el, newProps); }); +}; const Tooltip: FC = ({ children, @@ -125,7 +132,6 @@ const Tooltip: FC = ({ title, customPosition, alwaysShow, - onClick = noop, padding = 5, screenType = 'desktop', isVisible = true, @@ -135,10 +141,9 @@ const Tooltip: FC = ({ const { geneUIProviderRef } = useContext(GeneUIDesignSystemContext); const { isMobile } = useDeviceType(screenType); const [isPopoverOpen, setIsPopoverState] = useState(false); + const mouseEnterHandler = () => !alwaysShow && setIsPopoverState(true); - const mouseLeaveHandler = () => { - !alwaysShow && setIsPopoverState(false); - }; + const mouseLeaveHandler = () => !alwaysShow && setIsPopoverState(false); const { refs, floatingStyles, context } = useFloating({ open: alwaysShow || isPopoverOpen, @@ -169,17 +174,23 @@ const Tooltip: FC = ({ const childProps = { onMouseEnter: mouseEnterHandler, - onMouseLeave: mouseLeaveHandler, - onClick: (e: PointerEvent, el: JSX.Element) => { - const { onClick: onClickHandler } = el?.props; - typeof onClickHandler === 'function' && onClickHandler(e); - onClick(e); - } + onMouseLeave: mouseLeaveHandler }; + const component = useMemo(() => FindAndSetRef(children, childProps, refs.setReference), [children, childProps]); + + useEffect(() => { + component.forEach((element: JSX.Element) => { + const node = element as JSXWithRef; + if (node?.ref?.current) { + refs.setReference(node.ref.current as ReferenceType); + } + }); + }, [component]); + return ( <> - {FindAndMergeRef(children, childProps, refs.setReference)} + {component} {isVisible && (alwaysShow || isPopoverOpen) && ( {checkNudged({ nudgedLeft: context.x, nudgedTop: context.y }) && ( @@ -188,7 +199,8 @@ const Tooltip: FC = ({ ref={refs.setFloating} style={{ ...style, - ...floatingStyles + ...floatingStyles, + zIndex: 400 //TODO: Remove after 3.0.0 }} {...props} >