From cac5f4908a54374d114d7a11e66d648979013039 Mon Sep 17 00:00:00 2001 From: Nick Partridge Date: Mon, 29 Jan 2024 10:35:43 -0700 Subject: [PATCH] perf(tooltip): improve placement logic (#2310) --- .../src/components/portal/tooltip_portal.tsx | 10 +++--- .../charts/src/components/tooltip/tooltip.tsx | 19 ++--------- .../state/selectors/get_tooltip_settings.ts | 34 +++++++++++++++++++ 3 files changed, 42 insertions(+), 21 deletions(-) create mode 100644 packages/charts/src/state/selectors/get_tooltip_settings.ts diff --git a/packages/charts/src/components/portal/tooltip_portal.tsx b/packages/charts/src/components/portal/tooltip_portal.tsx index 7decd8ad7f..fadee71f55 100644 --- a/packages/charts/src/components/portal/tooltip_portal.tsx +++ b/packages/charts/src/components/portal/tooltip_portal.tsx @@ -103,17 +103,17 @@ const TooltipPortalComponent = ({ */ useEffect(() => { document.body.appendChild(portalNode); - }); + }, [portalNode]); /** * Popper instance used to manage position of tooltip. */ const popper = useRef(null); - const popperSettings = useMemo( + const popperSettings = useMemo(() => { // @ts-ignore - nesting limitation - () => mergePartial(DEFAULT_POPPER_SETTINGS, settings), - [settings], - ); + return mergePartial(DEFAULT_POPPER_SETTINGS, settings); + }, [settings]); + const destroyPopper = useCallback(() => { if (popper.current) { popper.current.destroy(); diff --git a/packages/charts/src/components/tooltip/tooltip.tsx b/packages/charts/src/components/tooltip/tooltip.tsx index 057c501d4c..35048e6b3a 100644 --- a/packages/charts/src/components/tooltip/tooltip.tsx +++ b/packages/charts/src/components/tooltip/tooltip.tsx @@ -30,7 +30,7 @@ import { } from './types'; import { Colors } from '../../common/colors'; import { SeriesIdentifier } from '../../common/series_id'; -import { BaseDatum, DEFAULT_TOOLTIP_SPEC, SettingsSpec, TooltipProps, TooltipSpec, TooltipValue } from '../../specs'; +import { BaseDatum, DEFAULT_TOOLTIP_SPEC, TooltipProps, TooltipSpec, TooltipValue } from '../../specs'; import { onPointerMove as onPointerMoveAction } from '../../state/actions/mouse'; import { toggleSelectedTooltipItem as toggleSelectedTooltipItemAction, @@ -45,8 +45,8 @@ import { getInternalIsInitializedSelector, InitStatus } from '../../state/select import { getInternalIsTooltipVisibleSelector } from '../../state/selectors/get_internal_is_tooltip_visible'; import { getInternalTooltipAnchorPositionSelector } from '../../state/selectors/get_internal_tooltip_anchor_position'; import { getInternalTooltipInfoSelector } from '../../state/selectors/get_internal_tooltip_info'; -import { getSettingsSpecSelector } from '../../state/selectors/get_settings_spec'; import { getTooltipSelectedItems } from '../../state/selectors/get_tooltip_selected_items'; +import { getTooltipSettings } from '../../state/selectors/get_tooltip_settings'; import { getTooltipSpecSelector } from '../../state/selectors/get_tooltip_spec'; import { isBrushingSelector } from '../../state/selectors/is_brushing'; import { Datum, hasMostlyRTLItems, isDefined, Rotation } from '../../utils/common'; @@ -329,19 +329,6 @@ export const TooltipComponent = { isExternal, isBrushing: false, zIndex: state.zIndex, - settings: getTooltipSettings(tooltip, getSettingsSpecSelector(state), isExternal), + settings: getTooltipSettings(state), tooltipTheme, rotation: getChartRotationSelector(state), chartId: state.chartId, diff --git a/packages/charts/src/state/selectors/get_tooltip_settings.ts b/packages/charts/src/state/selectors/get_tooltip_settings.ts new file mode 100644 index 0000000000..4d1533fc01 --- /dev/null +++ b/packages/charts/src/state/selectors/get_tooltip_settings.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Selector } from 're-reselect'; + +import { getInternalIsTooltipVisibleSelector } from './get_internal_is_tooltip_visible'; +import { getSettingsSpecSelector } from './get_settings_spec'; +import { getTooltipSpecSelector } from './get_tooltip_spec'; +import type { TooltipProps } from '../../specs'; +import { GlobalChartState } from '../chart_state'; +import { createCustomCachedSelector } from '../create_selector'; + +const getChartId: Selector = ({ chartId }) => chartId; + +/** @internal */ +const getTooltipSettingsSingleton = createCustomCachedSelector([getChartId], (): Record => ({})); + +/** @internal */ +export const getTooltipSettings = createCustomCachedSelector( + [getTooltipSettingsSingleton, getTooltipSpecSelector, getSettingsSpecSelector, getInternalIsTooltipVisibleSelector], + (settingsBase, tooltip, { externalPointerEvents }, { isExternal }): TooltipProps => { + if (!isExternal) return tooltip; + + return Object.assign(settingsBase, { + ...tooltip, + ...externalPointerEvents.tooltip, + }); + }, +);