import clsx from 'clsx'; import styles from './TooltipShared.module.css'; import type { display } from 'objdiff-wasm'; import React, { useMemo } from 'react'; import { Tooltip } from 'react-tooltip'; export type TooltipTriggerProps = { 'data-tooltip-id': string; 'data-tooltip-content': string; }; export type TooltipCallback = (content: T) => display.HoverItem[] | null; export type TooltipProps = Omit< React.ComponentProps, 'id' | 'render' > & { callback: TooltipCallback; }; export function createTooltip(): { Tooltip: React.FC>; useTooltip: (content: T) => TooltipTriggerProps; } { const id = generateRandomString(10); return { Tooltip: ({ callback, className, ...props }) => ( { const items = useMemo(() => { if (!content) { return null; } const parsedContent = JSON.parse(content) as T; return callback(parsedContent); }, [callback, content]); if (!items || items.length === 0) { return null; } return ; }} /> ), useTooltip: (content: T) => ({ 'data-tooltip-id': id, 'data-tooltip-content': JSON.stringify(content), }), }; } const TooltipContent = ({ items }: { items: display.HoverItem[] }) => { const out = []; for (const [i, item] of items.entries()) { let inner: React.ReactNode; switch (item.tag) { case 'text': { let labelClass: string | null = null; let valueClass: string | null = null; switch (item.val.color) { case 'special': labelClass = styles.labelColorSpecial; break; case 'insert': labelClass = styles.labelColorInsert; break; case 'delete': labelClass = styles.labelColorDelete; break; case 'emphasized': valueClass = styles.valueColorEmphasized; break; default: break; } if (item.val.label) { inner = ( <> {item.val.label} {': '} {item.val.value} ); } else { inner = ( {item.val.value} ); } break; } case 'separator': inner =
; break; default: console.warn('Unhandled context item', item); inner = null; break; } out.push(
{inner}
, ); } return
{out}
; }; const TooltipContentMemo = React.memo(TooltipContent); function generateRandomString(length: number): string { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * characters.length)); } return result; }