diff --git a/packages/scenes-react/src/components/VizPanel.test.tsx b/packages/scenes-react/src/components/VizPanel.test.tsx
index 7c79a1428..30b308866 100644
--- a/packages/scenes-react/src/components/VizPanel.test.tsx
+++ b/packages/scenes-react/src/components/VizPanel.test.tsx
@@ -1,8 +1,8 @@
import React from 'react';
import { render } from '@testing-library/react';
import { SceneContextObject } from '../contexts/SceneContextObject';
-import { VizConfigBuilders, VizPanel as VizPanelObject } from '@grafana/scenes';
-import { VizPanel } from './VizPanel';
+import { VizConfigBuilders, VizPanel as VizPanelObject, VizPanelMenu } from '@grafana/scenes';
+import { VizPanel, VizPanelProps } from './VizPanel';
import { PanelPlugin } from '@grafana/data';
import { TestContextProvider } from '../utils/testUtils';
@@ -55,4 +55,113 @@ describe('VizPanel', () => {
expect(scene.state.children.length).toBe(0);
});
+
+ it('Should render with titleItems', () => {
+ const scene = new SceneContextObject();
+ const viz = VizConfigBuilders.timeseries().build();
+ const titleItems =
Title Item
;
+
+ const { rerender, unmount } = render(
+
+
+
+ );
+
+ const panel = scene.state.children[0] as VizPanelObject;
+ expect(panel.state.titleItems).toEqual(titleItems);
+
+ rerender(
+
+
+
+ );
+
+ expect(panel.state.titleItems).toEqual(undefined);
+
+ unmount();
+
+ expect(scene.state.children.length).toBe(0);
+ });
+
+ it('Should render with headerActions', () => {
+ const scene = new SceneContextObject();
+ const viz = VizConfigBuilders.timeseries().build();
+ const headerActions = ;
+
+ const { rerender, unmount } = render(
+
+
+
+ );
+
+ const panel = scene.state.children[0] as VizPanelObject;
+ expect(panel.state.headerActions).toEqual(headerActions);
+
+ rerender(
+
+
+
+ );
+
+ unmount();
+
+ expect(scene.state.children.length).toBe(0);
+ });
+
+ it('Should render VizPanelProps', () => {
+ const scene = new SceneContextObject();
+ const viz = VizConfigBuilders.timeseries().build();
+ const headerActions = ;
+ const seriesLimit = 1;
+ const collapsed = true;
+ const collapsible = true;
+ const hoverHeader = true;
+ const description = 'description';
+ const menu = new VizPanelMenu({});
+ const title = 'title';
+ const props: VizPanelProps = {
+ title,
+ viz,
+ headerActions,
+ seriesLimit,
+ collapsed,
+ collapsible,
+ hoverHeader,
+ description,
+ menu,
+ };
+
+ const { rerender, unmount } = render(
+
+
+
+ );
+
+ const panel = scene.state.children[0] as VizPanelObject;
+ expect(panel.state.headerActions).toEqual(headerActions);
+ expect(panel.state.collapsed).toEqual(collapsed);
+ expect(panel.state.seriesLimit).toEqual(seriesLimit);
+ expect(panel.state.collapsible).toEqual(collapsible);
+ expect(panel.state.hoverHeader).toEqual(hoverHeader);
+ expect(panel.state.description).toEqual(description);
+ expect(panel.state.menu).toEqual(menu);
+
+ rerender(
+
+
+
+ );
+
+ expect(panel.state.headerActions).toEqual(undefined);
+ expect(panel.state.collapsed).toEqual(undefined);
+ expect(panel.state.seriesLimit).toEqual(undefined);
+ expect(panel.state.collapsible).toEqual(undefined);
+ expect(panel.state.hoverHeader).toEqual(undefined);
+ expect(panel.state.description).toEqual(undefined);
+ expect(panel.state.menu).toEqual(undefined);
+
+ unmount();
+
+ expect(scene.state.children.length).toBe(0);
+ });
});
diff --git a/packages/scenes-react/src/components/VizPanel.tsx b/packages/scenes-react/src/components/VizPanel.tsx
index 8b74bbbcd..21abf5462 100644
--- a/packages/scenes-react/src/components/VizPanel.tsx
+++ b/packages/scenes-react/src/components/VizPanel.tsx
@@ -1,5 +1,6 @@
import React, { useEffect, useId } from 'react';
import {
+ VizPanelMenu,
SceneDataProvider,
VizPanel as VizPanelObject,
VizPanelState,
@@ -9,18 +10,47 @@ import {
} from '@grafana/scenes';
import { usePrevious } from 'react-use';
import { getPanelOptionsWithDefaults } from '@grafana/data';
+import { PanelContext } from '@grafana/ui';
import { writeSceneLog } from '../utils';
import { useSceneContext } from '../hooks/hooks';
export interface VizPanelProps {
title: string;
+ description?: string;
dataProvider?: SceneDataProvider;
viz: VizConfig;
+ displayMode?: 'default' | 'transparent';
+ hoverHeader?: boolean;
+ hoverHeaderOffset?: number;
+ menu?: VizPanelMenu;
+ titleItems?: React.ReactNode;
+ seriesLimit?: number;
+ seriesLimitShowAll?: boolean;
headerActions?: React.ReactNode;
+ extendPanelContext?: (vizPanel: VizPanelObject, context: PanelContext) => void;
+ collapsible?: boolean;
+ collapsed?: boolean;
}
export function VizPanel(props: VizPanelProps) {
- const { title, viz, dataProvider, headerActions } = props;
+ const {
+ title,
+ description,
+ viz,
+ dataProvider,
+ displayMode,
+ hoverHeader,
+ hoverHeaderOffset,
+ headerActions,
+ menu,
+ titleItems,
+ extendPanelContext,
+ seriesLimit,
+ seriesLimitShowAll,
+ collapsible,
+ collapsed,
+ } = props;
+
const scene = useSceneContext();
const key = useId();
const prevProps = usePrevious(props);
@@ -30,13 +60,24 @@ export function VizPanel(props: VizPanelProps) {
if (!panel) {
panel = new VizPanelObject({
key: key,
- title: title,
pluginId: viz.pluginId,
- pluginVersion: viz.pluginVersion,
+ title: title,
+ titleItems: titleItems,
+ description: description,
options: viz.options,
fieldConfig: viz.fieldConfig,
+ pluginVersion: viz.pluginVersion,
$data: getDataProviderForVizPanel(dataProvider),
+ displayMode: displayMode,
+ hoverHeader: hoverHeader,
+ hoverHeaderOffset: hoverHeaderOffset,
headerActions: headerActions,
+ menu: menu,
+ extendPanelContext: extendPanelContext,
+ collapsible: collapsible,
+ collapsed: collapsed,
+ seriesLimit: seriesLimit,
+ seriesLimitShowAll: seriesLimitShowAll,
});
}
@@ -54,6 +95,30 @@ export function VizPanel(props: VizPanelProps) {
stateUpdate.title = title;
}
+ if (description !== prevProps.description) {
+ stateUpdate.description = description;
+ }
+
+ if (displayMode !== prevProps.displayMode) {
+ stateUpdate.displayMode = displayMode;
+ }
+
+ if (hoverHeader !== prevProps.hoverHeader) {
+ stateUpdate.hoverHeader = hoverHeader;
+ }
+
+ if (hoverHeaderOffset !== prevProps.hoverHeaderOffset) {
+ stateUpdate.hoverHeaderOffset = hoverHeaderOffset;
+ }
+
+ if (menu !== prevProps.menu) {
+ stateUpdate.menu = menu;
+ }
+
+ if (titleItems !== prevProps.titleItems) {
+ stateUpdate.titleItems = titleItems;
+ }
+
if (headerActions !== prevProps.headerActions) {
stateUpdate.headerActions = headerActions;
}
@@ -62,6 +127,22 @@ export function VizPanel(props: VizPanelProps) {
stateUpdate.$data = getDataProviderForVizPanel(dataProvider);
}
+ if (seriesLimit !== prevProps.seriesLimit) {
+ stateUpdate.seriesLimit = seriesLimit;
+ }
+
+ if (seriesLimitShowAll !== prevProps.seriesLimitShowAll) {
+ stateUpdate.seriesLimitShowAll = seriesLimitShowAll;
+ }
+
+ if (collapsible !== prevProps.collapsible) {
+ stateUpdate.collapsible = collapsible;
+ }
+
+ if (collapsed !== prevProps.collapsed) {
+ stateUpdate.collapsed = collapsed;
+ }
+
if (viz !== prevProps.viz) {
if (viz.pluginId === prevProps.viz.pluginId) {
const plugin = panel.getPlugin();
@@ -84,7 +165,24 @@ export function VizPanel(props: VizPanelProps) {
panel.setState(stateUpdate);
writeSceneLog('VizPanel', 'Updating VizPanel state', stateUpdate);
}
- }, [panel, title, headerActions, viz, dataProvider, prevProps]);
+ }, [
+ panel,
+ title,
+ description,
+ displayMode,
+ hoverHeader,
+ hoverHeaderOffset,
+ headerActions,
+ menu,
+ titleItems,
+ viz,
+ dataProvider,
+ seriesLimit,
+ seriesLimitShowAll,
+ collapsible,
+ collapsed,
+ prevProps,
+ ]);
return ;
}