import { KeyboardEventCode } from '@vev/utils'; import { isString } from 'lodash'; import React, { useEffect, useRef, useState } from 'react'; import { SilkeBox } from '../silke-box'; import { SilkeIcon, SilkeIcons } from '../silke-icon'; import { SilkeShortcuts } from './silke-shortcuts'; import { SilkeTooltip, SilkeTooltipProps } from './silke-tooltip'; import DOMPurify from 'dompurify'; type SilkeIconTooltipProps = { icon?: SilkeIcons; tooltip: React.ReactNode; tooltipTitle?: string; shortcut?: KeyboardEventCode[] | KeyboardEventCode; show?: boolean; /** If interaction content in the tooltip then this should be set to true */ interactive?: boolean; noMargin?: boolean; } & Omit; /** * Shows an icon with a tooltip anchored to it */ export function SilkeIconTooltip({ icon = 'tooltip', interactive, shortcut, show, tooltip, tooltipTitle, size, noMargin, ...rest }: SilkeIconTooltipProps) { const ref = useRef(null); const contentRef = useRef(null); const [hoveringIcon, setHoveringIcon] = useState(show ?? false); const [hoveringContent, setHoveringContent] = useState(false); /** * `shortcut`, if any, as an array */ const shortcutArray = shortcut ? typeof shortcut === 'string' ? [shortcut] : shortcut : undefined; useEffect(() => { const el = ref.current; if (el) { let timeout = 0; const handleMouseOver = () => { clearTimeout(timeout); setHoveringIcon(true); }; const handleMouseOut = () => { clearTimeout(timeout); timeout = self.setTimeout(() => setHoveringIcon(false), interactive ? 400 : 1); }; el.addEventListener('mouseover', handleMouseOver, { passive: true }); el.addEventListener('mouseleave', handleMouseOut, { passive: true }); return () => { el.removeEventListener('mouseover', handleMouseOver); el.removeEventListener('mouseleave', handleMouseOver); }; } }, [ref, interactive]); useEffect(() => { const contentEl = contentRef.current; if (interactive && contentEl) { const handleMouseOver = () => setHoveringContent(true); const handleMouseOut = () => setHoveringContent(false); contentEl.addEventListener('mouseover', handleMouseOver, { passive: true }); contentEl.addEventListener('mouseleave', handleMouseOut, { passive: true }); return () => { contentEl.removeEventListener('mouseover', handleMouseOver); contentEl.removeEventListener('mouseleave', handleMouseOut); }; } }, [show, interactive, contentRef.current]); useEffect(() => { if (show !== undefined) setHoveringIcon(show); }, [show]); return ( <> {isString(tooltip) ? ( ) : ( {tooltip} )} ); }