From 758bbd63c5010f5112f509c80f468e66b6a12a0c Mon Sep 17 00:00:00 2001 From: gabrieljablonski Date: Tue, 28 Mar 2023 18:22:47 -0300 Subject: [PATCH] feat: forward ref to be used on `render` --- src/components/Tooltip/Tooltip.tsx | 24 ++++++++++++++++++- src/components/Tooltip/TooltipTypes.d.ts | 3 ++- .../TooltipController/TooltipController.tsx | 6 +++-- .../TooltipControllerTypes.d.ts | 8 +++++-- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/components/Tooltip/Tooltip.tsx b/src/components/Tooltip/Tooltip.tsx index c46d9cc5..d11bb279 100644 --- a/src/components/Tooltip/Tooltip.tsx +++ b/src/components/Tooltip/Tooltip.tsx @@ -34,6 +34,7 @@ const Tooltip = ({ afterHide, // props handled by controller content, + contentRef, isOpen, setIsOpen, activeAnchor, @@ -425,7 +426,7 @@ const Tooltip = ({ } }, [id, anchorSelect, activeAnchor]) - useEffect(() => { + const updateTooltipPosition = () => { if (position) { // if `position` is set, override regular and `float` positioning handleTooltipPosition(position) @@ -468,8 +469,29 @@ const Tooltip = ({ } setActualPlacement(computedStylesData.place as PlacesType) }) + } + + useEffect(() => { + updateTooltipPosition() }, [show, activeAnchor, content, externalStyles, place, offset, positionStrategy, position]) + useEffect(() => { + if (!contentRef?.current) { + return () => null + } + const documentObserver = new MutationObserver(() => { + updateTooltipPosition() + }) + documentObserver.observe(contentRef.current, { + attributes: true, + childList: true, + subtree: true, + }) + return () => { + documentObserver.disconnect() + } + }, [content, contentRef?.current]) + useEffect(() => { const anchorById = document.querySelector(`[id='${anchorId}']`) const anchors = [...anchorsBySelect, anchorById] diff --git a/src/components/Tooltip/TooltipTypes.d.ts b/src/components/Tooltip/TooltipTypes.d.ts index 2045a5f9..bcdf4970 100644 --- a/src/components/Tooltip/TooltipTypes.d.ts +++ b/src/components/Tooltip/TooltipTypes.d.ts @@ -1,4 +1,4 @@ -import type { ElementType, ReactNode, CSSProperties } from 'react' +import type { ElementType, ReactNode, CSSProperties, RefObject } from 'react' export type PlacesType = 'top' | 'right' | 'bottom' | 'left' @@ -40,6 +40,7 @@ export interface ITooltip { className?: string classNameArrow?: string content?: ChildrenType + contentRef?: RefObject place?: PlacesType offset?: number id?: string diff --git a/src/components/TooltipController/TooltipController.tsx b/src/components/TooltipController/TooltipController.tsx index 68552eaf..4a1916b6 100644 --- a/src/components/TooltipController/TooltipController.tsx +++ b/src/components/TooltipController/TooltipController.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import { Tooltip } from 'components/Tooltip' import type { EventsType, @@ -205,8 +205,9 @@ const TooltipController = ({ * children should be lower priority so that it can be used as the "default" content */ let renderedContent: ChildrenType = children + const contentRef = useRef(null) if (render) { - renderedContent = render({ content: tooltipContent ?? null, activeAnchor }) + renderedContent = render({ ref: contentRef, content: tooltipContent ?? null, activeAnchor }) } else if (tooltipContent) { renderedContent = tooltipContent } @@ -221,6 +222,7 @@ const TooltipController = ({ className, classNameArrow, content: renderedContent, + contentRef, place: tooltipPlace, variant: tooltipVariant, offset: tooltipOffset, diff --git a/src/components/TooltipController/TooltipControllerTypes.d.ts b/src/components/TooltipController/TooltipControllerTypes.d.ts index 4612bb78..8f19e483 100644 --- a/src/components/TooltipController/TooltipControllerTypes.d.ts +++ b/src/components/TooltipController/TooltipControllerTypes.d.ts @@ -1,4 +1,4 @@ -import type { CSSProperties } from 'react' +import type { CSSProperties, RefObject } from 'react' import type { PlacesType, @@ -19,7 +19,11 @@ export interface ITooltipController { * @deprecated Use `children` or `render` instead */ html?: string - render?: (render: { content: string | null; activeAnchor: HTMLElement | null }) => ChildrenType + render?: (render: { + ref?: RefObject + content: string | null + activeAnchor: HTMLElement | null + }) => ChildrenType place?: PlacesType offset?: number id?: string