import React , { RefObject } from 'react' ; import { ChartType } from '../chart_types' ; import { GoalState } from '../chart_types/goal_chart/state/chart_state' ; import { HeatmapState } from '../chart_types/heatmap/state/chart_state' ; import { PartitionState } from '../chart_types/partition_chart/state/chart_state' ; import { WordcloudState } from '../chart_types/wordcloud/state/chart_state' ; import { XYAxisChartState } from '../chart_types/xy_chart/state/chart_state' ; import { CategoryKey } from '../common/category' ; import { Color } from '../common/colors' ; import { LegendItem , LegendItemExtraValues } from '../common/legend' ; import { SeriesIdentifier , SeriesKey } from '../common/series_id' ; import { AnchorPosition } from '../components/portal/types' ; import { TooltipInfo } from '../components/tooltip/types' ; import { DEFAULT_SETTINGS_SPEC , PointerEvent , Spec } from '../specs' ; import { keepDistinct } from '../utils/common' ; import { Dimensions } from '../utils/dimensions' ; import { Logger } from '../utils/logger' ; import { Point } from '../utils/point' ; import { StateActions } from './actions' ; import { CHART_RENDERED } from './actions/chart' ; import { UPDATE_PARENT_DIMENSION } from './actions/chart_settings' ; import { CLEAR_TEMPORARY_COLORS , SET_PERSISTED_COLOR , SET_TEMPORARY_COLOR } from './actions/colors' ; import { DOMElement } from './actions/dom_element' ; import { EXTERNAL_POINTER_EVENT } from './actions/events' ; import { LegendPath } from './actions/legend' ; import { REMOVE_SPEC , SPEC_PARSED , SPEC_UNMOUNTED , UPSERT_SPEC } from './actions/specs' ; import { Z_INDEX_EVENT } from './actions/z_index' ; import { interactionsReducer } from './reducers/interactions' ; import { getInternalIsInitializedSelector , InitStatus } from './selectors/get_internal_is_intialized' ; import { getLegendItemsSelector } from './selectors/get_legend_items' ; import { LegendItemLabel } from './selectors/get_legend_items_labels' ; import { DebugState } from './types' ; import { getInitialPointerState } from './utils' ; internal export type BackwardRef = ( ) => React . RefObject < HTMLDivElement > ; internal export interface InternalChartState { /**
     * The chart type
     */ chartType : ChartType ; isInitialized ( globalState ) : InitStatus ; param containerRef param forwardStageRef chartRenderer ( containerRef , forwardStageRef ) : JSX . Element | null ; param globalState isBrushAvailable ( globalState ) : boolean ; param globalState isBrushing ( globalState ) : boolean ; param globalState isChartEmpty ( globalState ) : boolean ; param globalState getLegendItemsLabels ( globalState ) : LegendItemLabel [ ] ; param globalState getLegendItems ( globalState ) : LegendItem [ ] ; param globalState getLegendExtraValues ( globalState ) : Map < SeriesKey , LegendItemExtraValues > ; param globalState getPointerCursor ( globalState ) : string ; param globalState isTooltipVisible ( globalState ) : { visible : boolean ; isExternal : boolean ; } ; param globalState getTooltipInfo ( globalState ) : TooltipInfo | undefined ; param globalState getTooltipAnchor ( globalState ) : AnchorPosition | null ; param globalState eventCallbacks ( globalState ) : void ; param globalState getMainProjectionArea ( globalState ) : Dimensions ; param globalState getProjectionContainerArea ( globalState ) : Dimensions ; param globalState getBrushArea ( globalState ) : Dimensions | null ; param globalState getDebugState ( globalState ) : DebugState ; /**
     * Get the series types for the screen reader summary component
     */ getChartTypeDescription ( globalState ) : string ; } internal export interface SpecList { [ specId ] : Spec ; } internal export interface PointerState { position : Point ; time : number ; } internal export interface DragState { start : PointerState ; end : PointerState ; } internal export interface PointerStates { dragging : boolean ; current : PointerState ; down : PointerState | null ; up : PointerState | null ; lastDrag : DragState | null ; lastClick : PointerState | null ; } internal export interface InteractionsState { pointer : PointerStates ; highlightedLegendPath : LegendPath ; deselectedDataSeries : SeriesIdentifier [ ] ; hoveredDOMElement : DOMElement | null ; drilldown : CategoryKey [ ] ; prevDrilldown : CategoryKey [ ] ; } internal export interface ExternalEventsState { pointer : PointerEvent | null ; } internal export interface ColorOverrides { temporary : Record < SeriesKey , Color | null > ; persisted : Record < SeriesKey , Color > ; } internal export type ChartId = string ; internal export interface GlobalChartState { /**
     * a unique ID for each chart used by re-reselect to memoize selector per chart
     */ chartId : ChartId ; /**
     * The Z-Index of the chart component
     */ zIndex : number ; /**
     * true when all all the specs are parsed ad stored into the specs object
     */ specsInitialized : boolean ; specParsing : boolean ; /**
     * true if the chart is rendered on dom
     */ chartRendered : boolean ; /**
     * incremental count of the chart rendering
     */ chartRenderedCount : number ; /**
     * the map of parsed specs
     */ specs : SpecList ; /**
     * the chart type depending on the used specs
     */ chartType : ChartType | null ; /**
     * a chart-type-dependant class that is used to render and share chart-type dependant functions
     */ internalChartState : InternalChartState | null ; /**
     * the dimensions of the parent container, including the legend
     */ parentDimensions : Dimensions ; /**
     * the state of the interactions
     */ interactions : InteractionsState ; /**
     * external event state
     */ externalEvents : ExternalEventsState ; /**
     * Color map used to persist color picker changes
     */ colors : ColorOverrides ; } internal export const getInitialState = ( chartId ) : GlobalChartState => ( { chartId , zIndex : 0 , specsInitialized : false , specParsing : false , chartRendered : false , chartRenderedCount : 0 , specs : { [ DEFAULT_SETTINGS_SPEC . id ] : DEFAULT_SETTINGS_SPEC , } , colors : { temporary : { } , persisted : { } , } , chartType : null , internalChartState : null , interactions : { pointer : getInitialPointerState ( ) , highlightedLegendPath : [ ] , deselectedDataSeries : [ ] , hoveredDOMElement : null , drilldown : [ ] , prevDrilldown : [ ] , } , externalEvents : { pointer : null , } , parentDimensions : { height : 0 , width : 0 , left : 0 , top : 0 , } , } ) ; internal export const chartStoreReducer = ( chartId ) => { const initialState = getInitialState ( chartId ) ; return ( state = initialState , action ) : GlobalChartState => { switch ( action . type ) { case Z_INDEX_EVENT : return { ... state , zIndex : action . zIndex , } ; case SPEC_PARSED : const chartType = chartTypeFromSpecs ( state . specs ) ; return { ... state , specsInitialized : true , specParsing : false , chartType , internalChartState : state . chartType === chartType ? state . internalChartState : newInternalState ( chartType ) , } ; case SPEC_UNMOUNTED : return { ... state , specsInitialized : false , chartRendered : false , } ; case UPSERT_SPEC : return { ... state , specsInitialized : false , chartRendered : false , specParsing : true , specs : state . specParsing ? { ... state . specs , [ action . spec . id ] : action . spec } : { [ DEFAULT_SETTINGS_SPEC . id ] : DEFAULT_SETTINGS_SPEC , [ action . spec . id ] : action . spec } , } ; case REMOVE_SPEC : const { [ action . id ] : specToRemove , ... rest } = state . specs ; return { ... state , specsInitialized : false , chartRendered : false , specParsing : false , specs : { ... rest , } , } ; case CHART_RENDERED : const count = state . chartRendered ? state . chartRenderedCount : state . chartRenderedCount + 1 ; return { ... state , chartRendered : true , chartRenderedCount : count , } ; case UPDATE_PARENT_DIMENSION : return { ... state , interactions : { ... state . interactions , prevDrilldown : state . interactions . drilldown } , parentDimensions : { ... action . dimensions , } , } ; case EXTERNAL_POINTER_EVENT : return { ... state , externalEvents : { ... state . externalEvents , pointer : action . event . chartId === chartId ? null : action . event , } , } ; case CLEAR_TEMPORARY_COLORS : return { ... state , colors : { ... state . colors , temporary : { } , } , } ; case SET_TEMPORARY_COLOR : return { ... state , colors : { ... state . colors , temporary : { ... state . colors . temporary , ... action . keys . reduce < Record < string , Color | null > > ( ( acc , curr ) => { acc [ curr ] = action . color ; return acc ; } , { } ) , } , } , } ; case SET_PERSISTED_COLOR : const persisted = action . keys . reduce < Record < string , Color > > ( ( acc , curr ) => { if ( action . color ) { acc [ curr ] = action . color ; } else { delete acc [ curr ] ; } return acc ; } , state . colors . persisted ) ; return { ... state , colors : { ... state . colors , persisted , } , } ; default : return getInternalIsInitializedSelector ( state ) === InitStatus . Initialized ? { ... state , interactions : interactionsReducer ( state , action , getLegendItemsSelector ( state ) ) , } : state ; } } ; } ; function chartTypeFromSpecs ( specs ) { const nonGlobalTypes = Object . values ( specs ) . map ( ( s ) => s . chartType ) . filter ( ( type ) => type !== ChartType . Global ) . filter ( keepDistinct ) ; if ( nonGlobalTypes . length !== 1 ) { Logger . warn ( `${ nonGlobalTypes . length === 0 ? 'Zero' : 'Multiple' } chart types in the same configuration` ) ; return null ; } return nonGlobalTypes [ 0 ] ; } const constructors = { [ ChartType . Goal ] : ( ) => new GoalState ( ) , [ ChartType . Partition ] : ( ) => new PartitionState ( ) , [ ChartType . XYAxis ] : ( ) => new XYAxisChartState ( ) , [ ChartType . Heatmap ] : ( ) => new HeatmapState ( ) , [ ChartType . Wordcloud ] : ( ) => new WordcloudState ( ) , [ ChartType . Global ] : ( ) => null , } ; function newInternalState ( chartType ) { return chartType ? constructors [ chartType ] ( ) : null ; }