import React, { useMemo } from 'react' import { useGG, tooltipState, themeState, TooltipContent, XTooltip, YTooltip, TooltipContainer, TooltipProps, TooltipPosition, } from '@graphique/graphique' import { useAtom } from 'jotai' import { mean, min, max } from 'd3-array' import { DefaultTooltip } from './DefaultTooltip' import { type GeomAes } from '../types' export { LineMarker } from './LineMarker' interface Props { x: (d: Datum) => number | undefined y: (d: Datum) => number | undefined aes: GeomAes } export const Tooltip = ({ x, y, aes }: Props) => { const { ggState } = useGG() || {} const { id, copiedScales, width, height, margin, scales } = ggState || { height: 0, } const [{ datum, position, xAxis, xFormat, yFormat, content }] = useAtom>(tooltipState) const [{ geoms, defaultStroke }] = useAtom(themeState) const left = useMemo( () => x ? min([datum && x(datum[0]), width - (margin?.right ?? 0)] as number[]) : undefined, [datum, x, width], ) const hasYVal = useMemo(() => (y ? datum?.some(y) : undefined), [datum, y]) const datumInGroups = useMemo(() => { const groups = scales?.strokeScale?.domain() ?? scales?.strokeDasharrayScale?.domain() ?? geoms?.line?.usableGroups return groups ? datum?.filter((d) => { const group = geoms?.line?.groupAccessor?.(d) const inGroups = groups.includes(group as string) return inGroups }) : datum }, [datum, geoms, scales]) const meanYVal = useMemo( () => (y && datumInGroups && mean(datumInGroups.map(y))) || 0, [datumInGroups, y], ) const xVal = useMemo( () => datum && datum[0] && aes?.x && aes.x(datum[0]), [datum, aes], ) const cappedYVal = max([0, min([meanYVal, height]) as number]) as number const lineVals = useMemo(() => { const vals = datumInGroups ?.filter( (d) => aes?.y && typeof aes.y(d) !== 'undefined' && aes.y(d) !== null, ) .map((md) => { const group = aes?.stroke?.(md) ?? aes?.strokeDasharray?.(md) ?? geoms?.line?.groupAccessor?.(md) const dashArray = geoms?.line?.strokeDasharray ?? (aes.strokeDasharray && copiedScales?.strokeDasharrayScale ? copiedScales.strokeDasharrayScale(aes.strokeDasharray(md)) : undefined) const stroke = geoms?.line?.stroke ?? (aes.stroke && copiedScales?.strokeScale ? copiedScales.strokeScale(aes.stroke(md)) : defaultStroke) const mark = ( ) return { datum, group, mark, x: xVal, y: aes?.y && aes.y(md), formattedY: aes?.y && (yFormat ? yFormat(aes.y(md)) : aes.y(md)), formattedX: xFormat ? xFormat(xVal) : xVal?.toString(), } }) return vals as TooltipContent[] }, [ datum, datumInGroups, xVal, aes, yFormat, xFormat, copiedScales, geoms, defaultStroke, ]) const tooltipValue = content ? (
{content(lineVals)}
) : ( ) return datum ? ( <> {xAxis && margin && left && ( {xFormat && xFormat(xVal)} ) : ( xAxis(xVal) ) } /> )} {left && hasYVal && ( )} ) : null }