{"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 } 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';\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 | 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>;\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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"}