From f585963de723ccab879da2e77c48dfdddff7c9df Mon Sep 17 00:00:00 2001 From: Chris Williams <chris.williams@airbnb.com> Date: Thu, 3 Dec 2020 13:03:00 -0800 Subject: [PATCH 1/4] fix(xychart/TooltipProvider): cancel debounced hideTooltip in showTooltip --- .../src/providers/TooltipProvider.tsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/visx-xychart/src/providers/TooltipProvider.tsx b/packages/visx-xychart/src/providers/TooltipProvider.tsx index 78ff62e55..f2062005e 100644 --- a/packages/visx-xychart/src/providers/TooltipProvider.tsx +++ b/packages/visx-xychart/src/providers/TooltipProvider.tsx @@ -24,8 +24,17 @@ export default function TooltipProvider<Datum extends object>({ hideTooltip: privateHideTooltip, } = useTooltip<TooltipData<Datum>>(undefined); + const debouncedHideTooltip = useRef<ReturnType<typeof debounce> | null>(null); + const showTooltip = useRef( ({ svgPoint, index, key, datum, distanceX, distanceY }: PointerEventParams<Datum>) => { + // cancel any hideTooltip calls so it won't hide after invoking the logic below + if (debouncedHideTooltip.current) { + console.log('cancel'); + debouncedHideTooltip.current.cancel(); + } + debouncedHideTooltip.current = null; + const distance = Math.sqrt((distanceX ?? Infinity ** 2) + (distanceY ?? Infinity ** 2)); updateTooltip(({ tooltipData: currData }) => ({ @@ -51,9 +60,10 @@ export default function TooltipProvider<Datum extends object>({ }, ); - const hideTooltip = useCallback(debounce(privateHideTooltip, hideTooltipDebounceMs), [ - privateHideTooltip, - ]); + const hideTooltip = useCallback(() => { + debouncedHideTooltip.current = debounce(privateHideTooltip, hideTooltipDebounceMs); + debouncedHideTooltip.current(); + }, [privateHideTooltip, hideTooltipDebounceMs]); return ( <TooltipContext.Provider From 9fd11f2a6f2038b1e5c8a1ae1d86754619bcd7cd Mon Sep 17 00:00:00 2001 From: Chris Williams <chris.williams@airbnb.com> Date: Thu, 3 Dec 2020 13:14:07 -0800 Subject: [PATCH 2/4] fix(xychart/Series): fix pointer event source event key and emitter logic --- .../src/components/series/private/BaseAreaSeries.tsx | 9 +++++---- .../src/components/series/private/BaseBarGroup.tsx | 9 +++++---- .../src/components/series/private/BaseBarSeries.tsx | 9 +++++---- .../src/components/series/private/BaseBarStack.tsx | 9 +++++---- .../src/components/series/private/BaseGlyphSeries.tsx | 9 +++++---- .../src/components/series/private/BaseLineSeries.tsx | 9 +++++---- 6 files changed, 30 insertions(+), 24 deletions(-) diff --git a/packages/visx-xychart/src/components/series/private/BaseAreaSeries.tsx b/packages/visx-xychart/src/components/series/private/BaseAreaSeries.tsx index 3e88fed39..b139b6f52 100644 --- a/packages/visx-xychart/src/components/series/private/BaseAreaSeries.tsx +++ b/packages/visx-xychart/src/components/series/private/BaseAreaSeries.tsx @@ -74,10 +74,11 @@ function BaseAreaSeries<XScale extends AxisScale, YScale extends AxisScale, Datu }, [hideTooltip, onPointerOutProps], ); + const ownEventSourceKey = `${AREASERIES_EVENT_SOURCE}-${dataKey}`; const pointerEventEmitters = usePointerEventEmitters({ - source: AREASERIES_EVENT_SOURCE, - onPointerMove: !!onPointerMoveProps && pointerEvents, - onPointerOut: !!onPointerOutProps && pointerEvents, + source: ownEventSourceKey, + onPointerMove: pointerEvents, // handle tooltip even if pointer prop isn't passed + onPointerOut: pointerEvents, onPointerUp: !!onPointerUpProps && pointerEvents, }); usePointerEventHandlers({ @@ -85,7 +86,7 @@ function BaseAreaSeries<XScale extends AxisScale, YScale extends AxisScale, Datu onPointerMove: pointerEvents ? onPointerMove : undefined, onPointerOut: pointerEvents ? onPointerOut : undefined, onPointerUp: pointerEvents ? onPointerUpProps : undefined, - sources: [XYCHART_EVENT_SOURCE, `${AREASERIES_EVENT_SOURCE}-${dataKey}`], + sources: [XYCHART_EVENT_SOURCE, ownEventSourceKey], }); const numericScaleBaseline = useMemo(() => getScaleBaseline(horizontal ? xScale : yScale), [ diff --git a/packages/visx-xychart/src/components/series/private/BaseBarGroup.tsx b/packages/visx-xychart/src/components/series/private/BaseBarGroup.tsx index 1c65b8848..fb2d2604c 100644 --- a/packages/visx-xychart/src/components/series/private/BaseBarGroup.tsx +++ b/packages/visx-xychart/src/components/series/private/BaseBarGroup.tsx @@ -115,10 +115,11 @@ export default function BaseBarGroup< }, [hideTooltip, onPointerOutProps], ); + const ownEventSourceKey = `${BARGROUP_EVENT_SOURCE}-${dataKeys.join('-')}}`; const pointerEventEmitters = usePointerEventEmitters({ - source: BARGROUP_EVENT_SOURCE, - onPointerMove: !!onPointerMoveProps && pointerEvents, - onPointerOut: !!onPointerOutProps && pointerEvents, + source: ownEventSourceKey, + onPointerMove: pointerEvents, // handle tooltip even if pointer prop isn't passed + onPointerOut: pointerEvents, onPointerUp: !!onPointerUpProps && pointerEvents, }); usePointerEventHandlers({ @@ -126,7 +127,7 @@ export default function BaseBarGroup< onPointerMove: pointerEvents ? onPointerMove : undefined, onPointerOut: pointerEvents ? onPointerOut : undefined, onPointerUp: pointerEvents ? onPointerUpProps : undefined, - sources: [XYCHART_EVENT_SOURCE, `${BARGROUP_EVENT_SOURCE}-${dataKeys.join('-')}`], + sources: [XYCHART_EVENT_SOURCE, ownEventSourceKey], }); const xZeroPosition = useMemo(() => (xScale ? getScaleBaseline(xScale) : 0), [xScale]); diff --git a/packages/visx-xychart/src/components/series/private/BaseBarSeries.tsx b/packages/visx-xychart/src/components/series/private/BaseBarSeries.tsx index 31074df7b..ebb0f3d71 100644 --- a/packages/visx-xychart/src/components/series/private/BaseBarSeries.tsx +++ b/packages/visx-xychart/src/components/series/private/BaseBarSeries.tsx @@ -107,10 +107,11 @@ function BaseBarSeries<XScale extends AxisScale, YScale extends AxisScale, Datum }, [hideTooltip, onPointerOutProps], ); + const ownEventSourceKey = `${BARSERIES_EVENT_SOURCE}-${dataKey}`; const pointerEventEmitters = usePointerEventEmitters({ - source: BARSERIES_EVENT_SOURCE, - onPointerMove: !!onPointerMoveProps && pointerEvents, - onPointerOut: !!onPointerOutProps && pointerEvents, + source: ownEventSourceKey, + onPointerMove: pointerEvents, // handle tooltip even if pointer prop isn't passed + onPointerOut: pointerEvents, onPointerUp: !!onPointerUpProps && pointerEvents, }); usePointerEventHandlers({ @@ -118,7 +119,7 @@ function BaseBarSeries<XScale extends AxisScale, YScale extends AxisScale, Datum onPointerMove: pointerEvents ? onPointerMove : undefined, onPointerOut: pointerEvents ? onPointerOut : undefined, onPointerUp: pointerEvents ? onPointerUpProps : undefined, - sources: [XYCHART_EVENT_SOURCE, `${BARSERIES_EVENT_SOURCE}-${dataKey}`], + sources: [XYCHART_EVENT_SOURCE, ownEventSourceKey], }); return ( diff --git a/packages/visx-xychart/src/components/series/private/BaseBarStack.tsx b/packages/visx-xychart/src/components/series/private/BaseBarStack.tsx index 92c95da96..1256d8c83 100644 --- a/packages/visx-xychart/src/components/series/private/BaseBarStack.tsx +++ b/packages/visx-xychart/src/components/series/private/BaseBarStack.tsx @@ -151,10 +151,11 @@ function BaseBarStack< }, [hideTooltip, onPointerOutProps], ); + const ownEventSourceKey = `${BARSTACK_EVENT_SOURCE}-${dataKeys.join('-')}`; const pointerEventEmitters = usePointerEventEmitters({ - source: BARSTACK_EVENT_SOURCE, - onPointerMove: !!onPointerMoveProps && pointerEvents, - onPointerOut: !!onPointerOutProps && pointerEvents, + source: ownEventSourceKey, + onPointerMove: pointerEvents, // should handle tooltip even if prop isn't passed + onPointerOut: pointerEvents, onPointerUp: !!onPointerUpProps && pointerEvents, }); usePointerEventHandlers({ @@ -162,7 +163,7 @@ function BaseBarStack< onPointerMove: pointerEvents ? onPointerMove : undefined, onPointerOut: pointerEvents ? onPointerOut : undefined, onPointerUp: pointerEvents ? onPointerUpProps : undefined, - sources: [XYCHART_EVENT_SOURCE, `${BARSTACK_EVENT_SOURCE}-${dataKeys.join('-')}`], + sources: [XYCHART_EVENT_SOURCE, ownEventSourceKey], }); // if scales and data are not available in the registry, bail diff --git a/packages/visx-xychart/src/components/series/private/BaseGlyphSeries.tsx b/packages/visx-xychart/src/components/series/private/BaseGlyphSeries.tsx index 036bd8aba..b0635defd 100644 --- a/packages/visx-xychart/src/components/series/private/BaseGlyphSeries.tsx +++ b/packages/visx-xychart/src/components/series/private/BaseGlyphSeries.tsx @@ -64,10 +64,11 @@ function BaseGlyphSeries<XScale extends AxisScale, YScale extends AxisScale, Dat }, [hideTooltip, onPointerOutProps], ); + const ownEventSourceKey = `${GLYPHSERIES_EVENT_SOURCE}-${dataKey}`; const pointerEventEmitters = usePointerEventEmitters({ - source: GLYPHSERIES_EVENT_SOURCE, - onPointerMove: !!onPointerMoveProps && pointerEvents, - onPointerOut: !!onPointerOutProps && pointerEvents, + source: ownEventSourceKey, + onPointerMove: pointerEvents, // handle tooltip even if pointer prop isn't passed + onPointerOut: pointerEvents, onPointerUp: !!onPointerUpProps && pointerEvents, }); usePointerEventHandlers({ @@ -75,7 +76,7 @@ function BaseGlyphSeries<XScale extends AxisScale, YScale extends AxisScale, Dat onPointerMove: pointerEvents ? onPointerMove : undefined, onPointerOut: pointerEvents ? onPointerOut : undefined, onPointerUp: pointerEvents ? onPointerUpProps : undefined, - sources: [XYCHART_EVENT_SOURCE, `${GLYPHSERIES_EVENT_SOURCE}-${dataKey}`], + sources: [XYCHART_EVENT_SOURCE, ownEventSourceKey], }); const glyphs = useMemo( diff --git a/packages/visx-xychart/src/components/series/private/BaseLineSeries.tsx b/packages/visx-xychart/src/components/series/private/BaseLineSeries.tsx index 308f6bad9..75e73935e 100644 --- a/packages/visx-xychart/src/components/series/private/BaseLineSeries.tsx +++ b/packages/visx-xychart/src/components/series/private/BaseLineSeries.tsx @@ -66,10 +66,11 @@ function BaseLineSeries<XScale extends AxisScale, YScale extends AxisScale, Datu }, [hideTooltip, onPointerOutProps], ); + const ownEventSourceKey = `${LINESERIES_EVENT_SOURCE}-${dataKey}`; const pointerEventEmitters = usePointerEventEmitters({ - source: LINESERIES_EVENT_SOURCE, - onPointerMove: !!onPointerMoveProps && pointerEvents, - onPointerOut: !!onPointerOutProps && pointerEvents, + source: ownEventSourceKey, + onPointerMove: pointerEvents, // handle tooltip even if pointer prop isn't passed + onPointerOut: pointerEvents, onPointerUp: !!onPointerUpProps && pointerEvents, }); usePointerEventHandlers<Datum>({ @@ -77,7 +78,7 @@ function BaseLineSeries<XScale extends AxisScale, YScale extends AxisScale, Datu onPointerMove: pointerEvents ? onPointerMove : undefined, onPointerOut: pointerEvents ? onPointerOut : undefined, onPointerUp: pointerEvents ? onPointerUpProps : undefined, - sources: [XYCHART_EVENT_SOURCE, `${LINESERIES_EVENT_SOURCE}-${dataKey}`], + sources: [XYCHART_EVENT_SOURCE, ownEventSourceKey], }); return ( From 7b664c412d3a9241562651352b4a0def1caef619 Mon Sep 17 00:00:00 2001 From: Chris Williams <chris.williams@airbnb.com> Date: Thu, 3 Dec 2020 13:25:05 -0800 Subject: [PATCH 3/4] fix(xychart/Series): don't emit pointer events unless prop handlers are passed --- .../src/components/series/private/BaseAreaSeries.tsx | 4 ++-- .../src/components/series/private/BaseBarGroup.tsx | 4 ++-- .../src/components/series/private/BaseBarSeries.tsx | 4 ++-- .../src/components/series/private/BaseBarStack.tsx | 4 ++-- .../src/components/series/private/BaseGlyphSeries.tsx | 4 ++-- .../src/components/series/private/BaseLineSeries.tsx | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/visx-xychart/src/components/series/private/BaseAreaSeries.tsx b/packages/visx-xychart/src/components/series/private/BaseAreaSeries.tsx index b139b6f52..7e3a13cd4 100644 --- a/packages/visx-xychart/src/components/series/private/BaseAreaSeries.tsx +++ b/packages/visx-xychart/src/components/series/private/BaseAreaSeries.tsx @@ -77,8 +77,8 @@ function BaseAreaSeries<XScale extends AxisScale, YScale extends AxisScale, Datu const ownEventSourceKey = `${AREASERIES_EVENT_SOURCE}-${dataKey}`; const pointerEventEmitters = usePointerEventEmitters({ source: ownEventSourceKey, - onPointerMove: pointerEvents, // handle tooltip even if pointer prop isn't passed - onPointerOut: pointerEvents, + onPointerMove: !!onPointerMoveProps && pointerEvents, + onPointerOut: !!onPointerOutProps && pointerEvents, onPointerUp: !!onPointerUpProps && pointerEvents, }); usePointerEventHandlers({ diff --git a/packages/visx-xychart/src/components/series/private/BaseBarGroup.tsx b/packages/visx-xychart/src/components/series/private/BaseBarGroup.tsx index fb2d2604c..eb85dc59b 100644 --- a/packages/visx-xychart/src/components/series/private/BaseBarGroup.tsx +++ b/packages/visx-xychart/src/components/series/private/BaseBarGroup.tsx @@ -118,8 +118,8 @@ export default function BaseBarGroup< const ownEventSourceKey = `${BARGROUP_EVENT_SOURCE}-${dataKeys.join('-')}}`; const pointerEventEmitters = usePointerEventEmitters({ source: ownEventSourceKey, - onPointerMove: pointerEvents, // handle tooltip even if pointer prop isn't passed - onPointerOut: pointerEvents, + onPointerMove: !!onPointerMoveProps && pointerEvents, + onPointerOut: !!onPointerOutProps && pointerEvents, onPointerUp: !!onPointerUpProps && pointerEvents, }); usePointerEventHandlers({ diff --git a/packages/visx-xychart/src/components/series/private/BaseBarSeries.tsx b/packages/visx-xychart/src/components/series/private/BaseBarSeries.tsx index ebb0f3d71..9670482dc 100644 --- a/packages/visx-xychart/src/components/series/private/BaseBarSeries.tsx +++ b/packages/visx-xychart/src/components/series/private/BaseBarSeries.tsx @@ -110,8 +110,8 @@ function BaseBarSeries<XScale extends AxisScale, YScale extends AxisScale, Datum const ownEventSourceKey = `${BARSERIES_EVENT_SOURCE}-${dataKey}`; const pointerEventEmitters = usePointerEventEmitters({ source: ownEventSourceKey, - onPointerMove: pointerEvents, // handle tooltip even if pointer prop isn't passed - onPointerOut: pointerEvents, + onPointerMove: !!onPointerMoveProps && pointerEvents, + onPointerOut: !!onPointerOutProps && pointerEvents, onPointerUp: !!onPointerUpProps && pointerEvents, }); usePointerEventHandlers({ diff --git a/packages/visx-xychart/src/components/series/private/BaseBarStack.tsx b/packages/visx-xychart/src/components/series/private/BaseBarStack.tsx index 1256d8c83..5b415431c 100644 --- a/packages/visx-xychart/src/components/series/private/BaseBarStack.tsx +++ b/packages/visx-xychart/src/components/series/private/BaseBarStack.tsx @@ -154,8 +154,8 @@ function BaseBarStack< const ownEventSourceKey = `${BARSTACK_EVENT_SOURCE}-${dataKeys.join('-')}`; const pointerEventEmitters = usePointerEventEmitters({ source: ownEventSourceKey, - onPointerMove: pointerEvents, // should handle tooltip even if prop isn't passed - onPointerOut: pointerEvents, + onPointerMove: !!onPointerMoveProps && pointerEvents, + onPointerOut: !!onPointerOutProps && pointerEvents, onPointerUp: !!onPointerUpProps && pointerEvents, }); usePointerEventHandlers({ diff --git a/packages/visx-xychart/src/components/series/private/BaseGlyphSeries.tsx b/packages/visx-xychart/src/components/series/private/BaseGlyphSeries.tsx index b0635defd..735e63a73 100644 --- a/packages/visx-xychart/src/components/series/private/BaseGlyphSeries.tsx +++ b/packages/visx-xychart/src/components/series/private/BaseGlyphSeries.tsx @@ -67,8 +67,8 @@ function BaseGlyphSeries<XScale extends AxisScale, YScale extends AxisScale, Dat const ownEventSourceKey = `${GLYPHSERIES_EVENT_SOURCE}-${dataKey}`; const pointerEventEmitters = usePointerEventEmitters({ source: ownEventSourceKey, - onPointerMove: pointerEvents, // handle tooltip even if pointer prop isn't passed - onPointerOut: pointerEvents, + onPointerMove: !!onPointerMoveProps && pointerEvents, + onPointerOut: !!onPointerOutProps && pointerEvents, onPointerUp: !!onPointerUpProps && pointerEvents, }); usePointerEventHandlers({ diff --git a/packages/visx-xychart/src/components/series/private/BaseLineSeries.tsx b/packages/visx-xychart/src/components/series/private/BaseLineSeries.tsx index 75e73935e..6cfc5334e 100644 --- a/packages/visx-xychart/src/components/series/private/BaseLineSeries.tsx +++ b/packages/visx-xychart/src/components/series/private/BaseLineSeries.tsx @@ -69,8 +69,8 @@ function BaseLineSeries<XScale extends AxisScale, YScale extends AxisScale, Datu const ownEventSourceKey = `${LINESERIES_EVENT_SOURCE}-${dataKey}`; const pointerEventEmitters = usePointerEventEmitters({ source: ownEventSourceKey, - onPointerMove: pointerEvents, // handle tooltip even if pointer prop isn't passed - onPointerOut: pointerEvents, + onPointerMove: !!onPointerMoveProps && pointerEvents, + onPointerOut: !!onPointerOutProps && pointerEvents, onPointerUp: !!onPointerUpProps && pointerEvents, }); usePointerEventHandlers<Datum>({ From 3769ad77f41f75e22352a9d02bd063b2eaf427e4 Mon Sep 17 00:00:00 2001 From: Chris Williams <chris.williams@airbnb.com> Date: Thu, 3 Dec 2020 14:22:16 -0800 Subject: [PATCH 4/4] fix(xychart/TooltipProvider): remove console.log --- packages/visx-xychart/src/providers/TooltipProvider.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/visx-xychart/src/providers/TooltipProvider.tsx b/packages/visx-xychart/src/providers/TooltipProvider.tsx index f2062005e..32f52b850 100644 --- a/packages/visx-xychart/src/providers/TooltipProvider.tsx +++ b/packages/visx-xychart/src/providers/TooltipProvider.tsx @@ -30,10 +30,9 @@ export default function TooltipProvider<Datum extends object>({ ({ svgPoint, index, key, datum, distanceX, distanceY }: PointerEventParams<Datum>) => { // cancel any hideTooltip calls so it won't hide after invoking the logic below if (debouncedHideTooltip.current) { - console.log('cancel'); debouncedHideTooltip.current.cancel(); + debouncedHideTooltip.current = null; } - debouncedHideTooltip.current = null; const distance = Math.sqrt((distanceX ?? Infinity ** 2) + (distanceY ?? Infinity ** 2));