= ({
// Add uPlot hooks to the config, or re-add when the config changed
useLayoutEffect(() => {
- config.addHook('setCursor', (u) => {
- const bbox = plotCtx.getCanvasBoundingBox();
- if (!bbox) {
- return;
- }
+ if (config.tooltipInterpolator) {
+ // Custom toolitp positioning
+ config.addHook('setCursor', (u) => {
+ config.tooltipInterpolator!(setFocusedSeriesIdx, setFocusedPointIdx, (clear) => {
+ if (clear) {
+ setCoords(null);
+ return;
+ }
- const { x, y } = positionTooltip(u, bbox);
+ const bbox = plotCtx.getCanvasBoundingBox();
+ if (!bbox) {
+ return;
+ }
- if (x !== undefined && y !== undefined) {
- setCoords({ x, y });
- } else {
- setCoords(null);
- }
+ const { x, y } = positionTooltip(u, bbox);
+ if (x !== undefined && y !== undefined) {
+ setCoords({ x, y });
+ }
+ })(u);
+ });
+ } else {
+ // default series/datapoint idx retireval
+ config.addHook('setCursor', (u) => {
+ const bbox = plotCtx.getCanvasBoundingBox();
+ if (!bbox) {
+ return;
+ }
- setFocusedPointIdx(u.cursor.idx === undefined ? u.posToIdx(u.cursor.left || 0) : u.cursor.idx);
- });
+ const { x, y } = positionTooltip(u, bbox);
- config.addHook('setSeries', (_, idx) => {
- setFocusedSeriesIdx(idx);
- });
- }, [plotCtx, config]);
+ if (x !== undefined && y !== undefined) {
+ setCoords({ x, y });
+ } else {
+ setCoords(null);
+ }
+
+ setFocusedPointIdx(u.cursor.idx === undefined ? u.posToIdx(u.cursor.left || 0) : u.cursor.idx);
+ });
+
+ config.addHook('setSeries', (_, idx) => {
+ setFocusedSeriesIdx(idx);
+ });
+ }
+ }, [plotCtx, config, setFocusedPointIdx, setFocusedSeriesIdx, setCoords]);
const plotInstance = plotCtx.plot;
if (!plotInstance || focusedPointIdx === null) {
diff --git a/packages/grafana-ui/src/components/uPlot/types.ts b/packages/grafana-ui/src/components/uPlot/types.ts
index 591bbe73b69..33d346cf291 100755
--- a/packages/grafana-ui/src/components/uPlot/types.ts
+++ b/packages/grafana-ui/src/components/uPlot/types.ts
@@ -27,3 +27,9 @@ export abstract class PlotConfigBuilder {
constructor(public props: P) {}
abstract getConfig(): T;
}
+
+export type TooltipInterpolator = (
+ updateActiveSeriesIdx: (sIdx: number | null) => void,
+ updateActiveDatapointIdx: (dIdx: number | null) => void,
+ updateTooltipPosition: (clear?: boolean) => void
+) => (u: uPlot) => void;
diff --git a/public/app/plugins/panel/barchart/BarChartPanel.tsx b/public/app/plugins/panel/barchart/BarChartPanel.tsx
index 78f6d9e9f73..2b9c181c016 100755
--- a/public/app/plugins/panel/barchart/BarChartPanel.tsx
+++ b/public/app/plugins/panel/barchart/BarChartPanel.tsx
@@ -1,6 +1,6 @@
import React, { useCallback, useMemo } from 'react';
-import { FieldType, PanelProps, VizOrientation } from '@grafana/data';
-import { BarChart, BarChartOptions, GraphNGLegendEvent } from '@grafana/ui';
+import { FieldType, PanelProps, TimeRange, VizOrientation } from '@grafana/data';
+import { BarChart, BarChartOptions, GraphNGLegendEvent, TooltipPlugin } from '@grafana/ui';
import { hideSeriesConfigFactory } from '../timeseries/overrides/hideSeriesConfigFactory';
interface Props extends PanelProps {}
@@ -14,6 +14,7 @@ export const BarChartPanel: React.FunctionComponent = ({
width,
height,
fieldConfig,
+ timeZone,
onFieldConfigChange,
}) => {
const orientation = useMemo(() => {
@@ -57,13 +58,19 @@ export const BarChartPanel: React.FunctionComponent = ({
return (
+ >
+ {(config, alignedFrame) => {
+ return ;
+ }}
+
);
};
diff --git a/public/app/plugins/panel/barchart/module.tsx b/public/app/plugins/panel/barchart/module.tsx
index 45dd597b7f1..deccba21f30 100755
--- a/public/app/plugins/panel/barchart/module.tsx
+++ b/public/app/plugins/panel/barchart/module.tsx
@@ -15,6 +15,7 @@ import {
graphFieldOptions,
commonOptionsBuilder,
} from '@grafana/ui';
+
import { defaultBarChartFieldConfig } from '@grafana/ui/src/components/BarChart/types';
export const plugin = new PanelPlugin(BarChartPanel)
@@ -119,6 +120,7 @@ export const plugin = new PanelPlugin(BarC
},
});
+ commonOptionsBuilder.addTooltipOptions(builder);
commonOptionsBuilder.addLegendOptions(builder);
});