From ff65c066f59557127142dba8a5424f89f327d2cc Mon Sep 17 00:00:00 2001 From: Jeremy Myers Date: Tue, 25 Jul 2023 16:59:54 -0400 Subject: [PATCH] fix(tooltip): handle multiple points (#979) * add optional prop used to override findNearestDatum logic in the useEventHandlers hook Allows consumers to pass in custom logic or visx's findNearestDatumXY for more accurate tooltip behavior --- packages/visx-xychart/src/components/XYChart.tsx | 15 ++++++++++++--- .../src/components/series/GlyphSeries.tsx | 4 +++- .../components/series/private/BaseGlyphSeries.tsx | 6 +++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/visx-xychart/src/components/XYChart.tsx b/packages/visx-xychart/src/components/XYChart.tsx index 4a474e6d0..483f4a85e 100644 --- a/packages/visx-xychart/src/components/XYChart.tsx +++ b/packages/visx-xychart/src/components/XYChart.tsx @@ -2,11 +2,11 @@ import React, { useContext, useEffect } from 'react'; import ParentSize from '@visx/responsive/lib/components/ParentSize'; import { ResizeObserverPolyfill } from '@visx/responsive/lib/types'; -import { AxisScaleOutput } from '@visx/axis'; +import { AxisScale, AxisScaleOutput } from '@visx/axis'; import { ScaleConfig } from '@visx/scale'; import DataContext from '../context/DataContext'; -import { Margin, EventHandlerParams } from '../types'; +import { Margin, EventHandlerParams, NearestDatumArgs, NearestDatumReturnType } from '../types'; import useEventEmitter from '../hooks/useEventEmitter'; import EventEmitterProvider from '../providers/EventEmitterProvider'; import TooltipContext from '../context/TooltipContext'; @@ -25,6 +25,8 @@ export type XYChartProps< XScaleConfig extends ScaleConfig, YScaleConfig extends ScaleConfig, Datum extends object, + XScale extends AxisScale, + YScale extends AxisScale, > = { /** aria-label for the chart svg element. */ accessibilityLabel?: string; @@ -90,6 +92,9 @@ export type XYChartProps< * into this component. */ resizeObserverPolyfill?: ResizeObserverPolyfill; + + /** Passed to useEventHandlers to override findNearestDatum logic */ + findNearestDatumOverride?: (params: NearestDatumArgs,) => NearestDatumReturnType; }; const allowedEventSources = [XYCHART_EVENT_SOURCE]; @@ -98,7 +103,9 @@ export default function XYChart< XScaleConfig extends ScaleConfig, YScaleConfig extends ScaleConfig, Datum extends object, ->(props: XYChartProps) { + XScale extends AxisScale, + YScale extends AxisScale, +>(props: XYChartProps) { const { accessibilityLabel = 'XYChart', captureEvents = true, @@ -117,6 +124,7 @@ export default function XYChart< yScale, // pass prop to context so it can be used anywhere resizeObserverPolyfill: resizeObserverPolyfillProp, + findNearestDatumOverride, } = props; const { setDimensions, resizeObserverPolyfill } = useContext(DataContext); const tooltipContext = useContext(TooltipContext); @@ -137,6 +145,7 @@ export default function XYChart< onPointerUp, onPointerDown, allowedSources: allowedEventSources, + findNearestDatum: findNearestDatumOverride, }); // if Context or dimensions are not available, wrap self in the needed providers diff --git a/packages/visx-xychart/src/components/series/GlyphSeries.tsx b/packages/visx-xychart/src/components/series/GlyphSeries.tsx index 59eef1933..07f15863e 100644 --- a/packages/visx-xychart/src/components/series/GlyphSeries.tsx +++ b/packages/visx-xychart/src/components/series/GlyphSeries.tsx @@ -1,6 +1,6 @@ import { AxisScale } from '@visx/axis'; import React, { useCallback } from 'react'; -import { GlyphProps, GlyphsProps } from '../../types'; +import { GlyphProps, GlyphsProps, NearestDatumArgs, NearestDatumReturnType } from '../../types'; import BaseGlyphSeries, { BaseGlyphSeriesProps } from './private/BaseGlyphSeries'; import defaultRenderGlyph from './private/defaultRenderGlyph'; @@ -13,6 +13,8 @@ export default function GlyphSeries< ...props }: Omit, 'renderGlyphs'> & { renderGlyph?: React.FC>; + /** Passed to useEventHandlers to override findNearestDatum logic */ + findNearestDatumOverride?: (params: NearestDatumArgs,) => NearestDatumReturnType; }) { const renderGlyphs = useCallback( ({ diff --git a/packages/visx-xychart/src/components/series/private/BaseGlyphSeries.tsx b/packages/visx-xychart/src/components/series/private/BaseGlyphSeries.tsx index 7dfd73620..124c625e1 100644 --- a/packages/visx-xychart/src/components/series/private/BaseGlyphSeries.tsx +++ b/packages/visx-xychart/src/components/series/private/BaseGlyphSeries.tsx @@ -1,7 +1,7 @@ import React, { useContext, useMemo } from 'react'; import { AxisScale } from '@visx/axis'; import DataContext from '../../../context/DataContext'; -import { GlyphProps, GlyphsProps, SeriesProps } from '../../../types'; +import { GlyphProps, GlyphsProps, SeriesProps, NearestDatumArgs, NearestDatumReturnType } from '../../../types'; import withRegisteredData, { WithRegisteredDataProps } from '../../../enhancers/withRegisteredData'; import getScaledValueFactory from '../../../utils/getScaledValueFactory'; import isValidNumber from '../../../typeguards/isValidNumber'; @@ -19,6 +19,8 @@ export type BaseGlyphSeriesProps< size?: number | ((d: Datum) => number); /** Function which handles rendering glyphs. */ renderGlyphs: (glyphsProps: GlyphsProps) => React.ReactNode; + /** Passed to useEventHandlers to override findNearestDatum logic */ + findNearestDatumOverride?: (params: NearestDatumArgs,) => NearestDatumReturnType; }; export function BaseGlyphSeries< @@ -42,6 +44,7 @@ export function BaseGlyphSeries< xScale, yAccessor, yScale, + findNearestDatumOverride, }: BaseGlyphSeriesProps & WithRegisteredDataProps) { const { colorScale, theme, horizontal } = useContext(DataContext); const getScaledX = useMemo(() => getScaledValueFactory(xScale, xAccessor), [xScale, xAccessor]); @@ -60,6 +63,7 @@ export function BaseGlyphSeries< onPointerDown, source: ownEventSourceKey, allowedSources: [XYCHART_EVENT_SOURCE, ownEventSourceKey], + findNearestDatum: findNearestDatumOverride, }); const glyphs = useMemo(