import { TooltipInfo } from '../../../../components/tooltip/types' ; import { PointerEvent , isPointerOutEvent , TooltipValue , TooltipValueFormatter , isFollowTooltipType , SettingsSpec , getTooltipType , getShowNullValues , } from '../../../../specs' ; import { TooltipType } from '../../../../specs/constants' ; import { GlobalChartState } from '../../../../state/chart_state' ; import { createCustomCachedSelector } from '../../../../state/create_selector' ; import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation' ; import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs' ; import { getTooltipHeaderFormatterSelector } from '../../../../state/selectors/get_tooltip_header_formatter' ; import { Rotation } from '../../../../utils/common' ; import { isValidPointerOverEvent } from '../../../../utils/events' ; import { IndexedGeometry } from '../../../../utils/geometry' ; import { Point } from '../../../../utils/point' ; import { getTooltipCompareFn } from '../../../../utils/series_sort' ; import { isPointOnGeometry } from '../../rendering/utils' ; import { formatTooltip } from '../../tooltip/tooltip' ; import { defaultXYLegendSeriesSort } from '../../utils/default_series_sort_fn' ; import { DataSeries } from '../../utils/series' ; import { BasicSeriesSpec , AxisSpec } from '../../utils/specs' ; import { getAxesSpecForSpecId , getSpecDomainGroupId , getSpecsById } from '../utils/spec' ; import { ComputedScales } from '../utils/types' ; import { getComputedScalesSelector } from './get_computed_scales' ; import { getElementAtCursorPositionSelector } from './get_elements_at_cursor_pos' ; import { getOrientedProjectedPointerPositionSelector } from './get_oriented_projected_pointer_position' ; import { getProjectedPointerPositionSelector } from './get_projected_pointer_position' ; import { getSiDataSeriesMapSelector } from './get_si_dataseries_map' ; import { getSeriesSpecsSelector , getAxisSpecsSelector } from './get_specs' ; import { hasSingleSeriesSelector } from './has_single_series' ; const EMPTY_VALUES = Object . freeze ( { tooltip : { header : null , values : [ ] , } , highlightedGeometries : [ ] , } ) ; internal export interface TooltipAndHighlightedGeoms { tooltip : TooltipInfo ; highlightedGeometries : IndexedGeometry [ ] ; } const getExternalPointerEventStateSelector = ( state ) => state . externalEvents . pointer ; internal export const getTooltipInfoAndGeometriesSelector = createCustomCachedSelector ( [ getSeriesSpecsSelector , getAxisSpecsSelector , getSettingsSpecSelector , getProjectedPointerPositionSelector , getOrientedProjectedPointerPositionSelector , getChartRotationSelector , hasSingleSeriesSelector , getComputedScalesSelector , getElementAtCursorPositionSelector , getSiDataSeriesMapSelector , getExternalPointerEventStateSelector , getTooltipHeaderFormatterSelector , ] , getTooltipAndHighlightFromValue ) ; function getTooltipAndHighlightFromValue ( seriesSpecs , axesSpecs , settings , projectedPointerPosition , orientedProjectedPointerPosition , chartRotation , hasSingleSeries , scales , matchingGeoms , serialIdentifierDataSeriesMap , externalPointerEvent , tooltipHeaderFormatter ? ) { if ( ! scales . xScale || ! scales . yScales ) { return EMPTY_VALUES ; } let { x , y } = orientedProjectedPointerPosition ; let tooltipType = getTooltipType ( settings ) ; if ( isValidPointerOverEvent ( scales . xScale , externalPointerEvent ) ) { tooltipType = getTooltipType ( settings , true ) ; const scaledX = scales . xScale . pureScale ( externalPointerEvent . x ) ; if ( Number . isNaN ( scaledX ) ) { return EMPTY_VALUES ; } x = scaledX ; y = 0 ; } else if ( projectedPointerPosition . x === - 1 || projectedPointerPosition . y === - 1 ) { return EMPTY_VALUES ; } if ( tooltipType === TooltipType . None && ! externalPointerEvent ) { return EMPTY_VALUES ; } if ( matchingGeoms . length === 0 ) { return EMPTY_VALUES ; } let header = null ; const highlightedGeometries = [ ] ; const xValues = new Set < any > ( ) ; const hideNullValues = ! getShowNullValues ( settings ) ; const values = matchingGeoms . reduce < TooltipValue [ ] > ( ( acc , indexedGeometry ) => { if ( hideNullValues && indexedGeometry . value . y === null ) { return acc ; } const { seriesIdentifier : { specId } , } = indexedGeometry ; const spec = getSpecsById < BasicSeriesSpec > ( seriesSpecs , specId ) ; if ( ! spec ) { return acc ; } const { xAxis , yAxis } = getAxesSpecForSpecId ( axesSpecs , spec . groupId , chartRotation ) ; const yScale = scales . yScales . get ( getSpecDomainGroupId ( spec ) ) ; if ( ! yScale ) { return acc ; } let isHighlighted = false ; if ( ( ! externalPointerEvent || isPointerOutEvent ( externalPointerEvent ) ) && isPointOnGeometry ( x , y , indexedGeometry , settings . pointBuffer ) ) { isHighlighted = true ; highlightedGeometries . push ( indexedGeometry ) ; } if ( ! isHighlighted && isFollowTooltipType ( tooltipType ) ) { return acc ; } const formattedTooltip = formatTooltip ( indexedGeometry , spec , false , isHighlighted , hasSingleSeries , yAxis ) ; if ( ! header ) { const formatterAxis = tooltipHeaderFormatter ? undefined : xAxis ; header = formatTooltip ( indexedGeometry , spec , true , false , hasSingleSeries , formatterAxis ) ; } xValues . add ( indexedGeometry . value . x ) ; return [ ... acc , formattedTooltip ] ; } , [ ] ) ; if ( values . length > 1 && xValues . size === values . length ) { header = null ; } const tooltipSortFn = getTooltipCompareFn ( ( a , b ) => { const aDs = serialIdentifierDataSeriesMap [ a . key ] ; const bDs = serialIdentifierDataSeriesMap [ b . key ] ; return defaultXYLegendSeriesSort ( aDs , bDs ) ; } ) ; const sortedTooltipValues = values . sort ( ( a , b ) => { return tooltipSortFn ( a . seriesIdentifier , b . seriesIdentifier ) ; } ) ; return { tooltip : { header , values : sortedTooltipValues , } , highlightedGeometries , } ; } internal export const getTooltipInfoSelector = createCustomCachedSelector ( [ getTooltipInfoAndGeometriesSelector ] , ( { tooltip } ) : TooltipInfo => tooltip ) ; internal export const getHighlightedGeomsSelector = createCustomCachedSelector ( [ getTooltipInfoAndGeometriesSelector ] , ( { highlightedGeometries } ) : IndexedGeometry [ ] => highlightedGeometries ) ;