import type { ReactNode } from 'react' import * as React from 'react' const TooltipContext = React.createContext({ open: false, onOpenChange: (_open: boolean) => {}, }) type TooltipProps = { children?: ReactNode open?: boolean onOpenChange?: (open: boolean) => void } export const Tooltip = ({ children, open, onOpenChange }: TooltipProps) => { const [localOpen, setLocalOpen] = React.useState(false) const resolvedOpen = open ?? localOpen const handleOpenChange = React.useCallback((nextOpen: boolean) => { setLocalOpen(nextOpen) onOpenChange?.(nextOpen) }, [onOpenChange]) return ( {children} ) } export const TooltipTrigger = ({ children, render, nativeButton: _nativeButton, ...props }: React.HTMLAttributes & { children?: ReactNode, render?: React.ReactElement, nativeButton?: boolean }) => { const { open, onOpenChange } = React.useContext(TooltipContext) const node = render ?? children if (React.isValidElement(node)) { const triggerElement = node as React.ReactElement> const childProps = (triggerElement.props ?? {}) as React.HTMLAttributes return React.cloneElement(triggerElement, { ...props, ...childProps, onMouseEnter: (event: React.MouseEvent) => { childProps.onMouseEnter?.(event) props.onMouseEnter?.(event) onOpenChange(true) }, onMouseLeave: (event: React.MouseEvent) => { childProps.onMouseLeave?.(event) props.onMouseLeave?.(event) onOpenChange(false) }, onClick: (event: React.MouseEvent) => { childProps.onClick?.(event) props.onClick?.(event) onOpenChange(!open) }, }) } return ( { props.onMouseEnter?.(event) onOpenChange(true) }} onMouseLeave={(event) => { props.onMouseLeave?.(event) onOpenChange(false) }} onClick={(event) => { props.onClick?.(event) onOpenChange(!open) }} > {node} ) } export const TooltipContent = ({ children, ...props }: React.HTMLAttributes & { children?: ReactNode }) => { const { open } = React.useContext(TooltipContext) if (!open) return null return
{children}
} export const TooltipProvider = ({ children }: { children?: ReactNode }) => <>{children}