{"version":3,"file":"GraphNG.mjs","sources":["../../../../src/graveyard/GraphNG/GraphNG.tsx"],"sourcesContent":["import { Component } from 'react';\nimport * as React from 'react';\nimport { Subscription } from 'rxjs';\nimport { throttleTime } from 'rxjs/operators';\nimport uPlot, { AlignedData } from 'uplot';\n\nimport {\n  DataFrame,\n  DataHoverClearEvent,\n  DataHoverEvent,\n  Field,\n  FieldMatcherID,\n  fieldMatchers,\n  FieldType,\n  LegacyGraphHoverEvent,\n  TimeRange,\n  TimeZone,\n} from '@grafana/data';\nimport { VizLegendOptions } from '@grafana/schema';\n\nimport { PanelContext, PanelContextRoot } from '../../components/PanelChrome/PanelContext';\nimport { VizLayout, VizLayoutLegendProps } from '../../components/VizLayout/VizLayout';\nimport { UPlotChart } from '../../components/uPlot/Plot';\nimport { AxisProps } from '../../components/uPlot/config/UPlotAxisBuilder';\nimport { Renderers, UPlotConfigBuilder } from '../../components/uPlot/config/UPlotConfigBuilder';\nimport { ScaleProps } from '../../components/uPlot/config/UPlotScaleBuilder';\nimport { findMidPointYPosition, pluginLog } from '../../components/uPlot/utils';\nimport { Themeable2 } from '../../types/theme';\n\nimport { GraphNGLegendEvent, XYFieldMatchers } from './types';\nimport { preparePlotFrame as defaultPreparePlotFrame } from './utils';\n\n/**\n * @deprecated\n * @internal -- not a public API\n */\nexport type PropDiffFn<T extends any = any> = (prev: T, next: T) => boolean;\n\n/** @deprecated */\nexport interface GraphNGProps extends Themeable2 {\n  frames: DataFrame[];\n  structureRev?: number; // a number that will change when the frames[] structure changes\n  width: number;\n  height: number;\n  timeRange: TimeRange;\n  timeZone: TimeZone[] | TimeZone;\n  legend: VizLegendOptions;\n  fields?: XYFieldMatchers; // default will assume timeseries data\n  renderers?: Renderers;\n  tweakScale?: (opts: ScaleProps, forField: Field) => ScaleProps;\n  tweakAxis?: (opts: AxisProps, forField: Field) => AxisProps;\n  onLegendClick?: (event: GraphNGLegendEvent) => void;\n  children?: (builder: UPlotConfigBuilder, alignedFrame: DataFrame) => React.ReactNode;\n  prepConfig: (alignedFrame: DataFrame, allFrames: DataFrame[], getTimeRange: () => TimeRange) => UPlotConfigBuilder;\n  propsToDiff?: Array<string | PropDiffFn>;\n  preparePlotFrame?: (frames: DataFrame[], dimFields: XYFieldMatchers) => DataFrame | null;\n  renderLegend: (config: UPlotConfigBuilder) => React.ReactElement<VizLayoutLegendProps> | null;\n\n  /**\n   * needed for propsToDiff to re-init the plot & config\n   * this is a generic approach to plot re-init, without having to specify which panel-level options\n   * should cause invalidation. we can drop this in favor of something like panelOptionsRev that gets passed in\n   * similar to structureRev. then we can drop propsToDiff entirely.\n   */\n  options?: Record<string, any>;\n}\n\nfunction sameProps(prevProps: any, nextProps: any, propsToDiff: Array<string | PropDiffFn> = []) {\n  for (const propName of propsToDiff) {\n    if (typeof propName === 'function') {\n      if (!propName(prevProps, nextProps)) {\n        return false;\n      }\n    } else if (nextProps[propName] !== prevProps[propName]) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\n/**\n * @internal -- not a public API\n * @deprecated\n */\nexport interface GraphNGState {\n  alignedFrame: DataFrame;\n  alignedData?: AlignedData;\n  config?: UPlotConfigBuilder;\n}\n\n/**\n * \"Time as X\" core component, expects ascending x\n * @deprecated\n */\nexport class GraphNG extends Component<GraphNGProps, GraphNGState> {\n  static contextType = PanelContextRoot;\n  panelContext: PanelContext = {} as PanelContext;\n  private plotInstance: React.RefObject<uPlot | null>;\n\n  private subscription = new Subscription();\n\n  constructor(props: GraphNGProps) {\n    super(props);\n    let state = this.prepState(props);\n    state.alignedData = state.config!.prepData!([state.alignedFrame]) as AlignedData;\n    this.state = state;\n    this.plotInstance = React.createRef();\n  }\n\n  getTimeRange = () => this.props.timeRange;\n\n  prepState(props: GraphNGProps, withConfig = true) {\n    let state: GraphNGState = null as any;\n\n    const { frames, fields, preparePlotFrame } = props;\n\n    const preparePlotFrameFn = preparePlotFrame || defaultPreparePlotFrame;\n\n    const alignedFrame = preparePlotFrameFn(\n      frames,\n      fields || {\n        x: fieldMatchers.get(FieldMatcherID.firstTimeField).get({}),\n        y: fieldMatchers.get(FieldMatcherID.byTypes).get(new Set([FieldType.number, FieldType.enum])),\n      },\n      props.timeRange\n    );\n    pluginLog('GraphNG', false, 'data aligned', alignedFrame);\n\n    if (alignedFrame) {\n      let config = this.state?.config;\n\n      if (withConfig) {\n        config = props.prepConfig(alignedFrame, this.props.frames, this.getTimeRange);\n        pluginLog('GraphNG', false, 'config prepared', config);\n      }\n\n      state = {\n        alignedFrame,\n        config,\n      };\n\n      pluginLog('GraphNG', false, 'data prepared', state.alignedData);\n    }\n\n    return state;\n  }\n\n  handleCursorUpdate(evt: DataHoverEvent | LegacyGraphHoverEvent) {\n    const time = evt.payload?.point?.time;\n    const u = this.plotInstance.current;\n    if (u && time) {\n      // Try finding left position on time axis\n      const left = u.valToPos(time, 'x');\n      let top;\n      if (left) {\n        // find midpoint between points at current idx\n        top = findMidPointYPosition(u, u.posToIdx(left));\n      }\n\n      if (!top || !left) {\n        return;\n      }\n\n      u.setCursor({\n        left,\n        top,\n      });\n    }\n  }\n\n  componentDidMount() {\n    this.panelContext = this.context as PanelContext;\n    const { eventBus } = this.panelContext;\n\n    this.subscription.add(\n      eventBus\n        .getStream(DataHoverEvent)\n        .pipe(throttleTime(50))\n        .subscribe({\n          next: (evt) => {\n            if (eventBus === evt.origin) {\n              return;\n            }\n            this.handleCursorUpdate(evt);\n          },\n        })\n    );\n\n    // Legacy events (from flot graph)\n    this.subscription.add(\n      eventBus\n        .getStream(LegacyGraphHoverEvent)\n        .pipe(throttleTime(50))\n        .subscribe({\n          next: (evt) => this.handleCursorUpdate(evt),\n        })\n    );\n\n    this.subscription.add(\n      eventBus\n        .getStream(DataHoverClearEvent)\n        .pipe(throttleTime(50))\n        .subscribe({\n          next: () => {\n            const u = this.plotInstance?.current;\n\n            // @ts-ignore\n            if (u && !u.cursor._lock) {\n              u.setCursor({\n                left: -10,\n                top: -10,\n              });\n            }\n          },\n        })\n    );\n  }\n\n  componentDidUpdate(prevProps: GraphNGProps) {\n    const { frames, structureRev, timeZone, propsToDiff } = this.props;\n\n    const propsChanged = !sameProps(prevProps, this.props, propsToDiff);\n\n    if (frames !== prevProps.frames || propsChanged || timeZone !== prevProps.timeZone) {\n      let newState = this.prepState(this.props, false);\n\n      if (newState) {\n        const shouldReconfig =\n          this.state.config === undefined ||\n          timeZone !== prevProps.timeZone ||\n          structureRev !== prevProps.structureRev ||\n          !structureRev ||\n          propsChanged;\n\n        if (shouldReconfig) {\n          newState.config = this.props.prepConfig(newState.alignedFrame, this.props.frames, this.getTimeRange);\n          pluginLog('GraphNG', false, 'config recreated', newState.config);\n        }\n\n        newState.alignedData = newState.config!.prepData!([newState.alignedFrame]) as AlignedData;\n\n        this.setState(newState);\n      }\n    }\n  }\n\n  componentWillUnmount() {\n    this.subscription.unsubscribe();\n  }\n\n  render() {\n    const { width, height, children, renderLegend } = this.props;\n    const { config, alignedFrame, alignedData } = this.state;\n\n    if (!config) {\n      return null;\n    }\n\n    return (\n      <VizLayout width={width} height={height} legend={renderLegend(config)}>\n        {(vizWidth: number, vizHeight: number) => (\n          <UPlotChart\n            config={config}\n            data={alignedData!}\n            width={vizWidth}\n            height={vizHeight}\n            plotRef={(u) => ((this.plotInstance as React.MutableRefObject<uPlot>).current = u)}\n          >\n            {children ? children(config, alignedFrame) : null}\n          </UPlotChart>\n        )}\n      </VizLayout>\n    );\n  }\n}\n"],"names":["preparePlotFrame","defaultPreparePlotFrame"],"mappings":"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"}