import { css } from '@emotion/css'; import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { Stack } from '@grafana/experimental'; import { Button, ToolbarButton, useStyles2 } from '@grafana/ui'; import { SceneObjectBase } from '../core/SceneObjectBase'; import { SceneObject, SceneLayoutChildState, SceneComponentProps, SceneLayout } from '../core/types'; interface NestedSceneState extends SceneLayoutChildState { title: string; isCollapsed?: boolean; canCollapse?: boolean; canRemove?: boolean; body: SceneLayout; actions?: SceneObject[]; } export class NestedScene extends SceneObjectBase { public static Component = NestedSceneRenderer; public onToggle = () => { this.setState({ isCollapsed: !this.state.isCollapsed, placement: { ...this.state.placement, ySizing: this.state.isCollapsed ? 'fill' : 'content', }, }); }; /** Removes itself from its parent's children array */ public onRemove = () => { const parent = this.parent!; if ('children' in parent.state) { parent.setState({ children: parent.state.children.filter((x) => x !== this), }); } }; } export function NestedSceneRenderer({ model, isEditing }: SceneComponentProps) { const { title, isCollapsed, canCollapse, canRemove, body, actions } = model.useState(); const styles = useStyles2(getStyles); const toolbarActions = (actions ?? []).map((action) => ); if (canRemove) { toolbarActions.push( ); } return (
{title}
{canCollapse && (
)}
{toolbarActions}
{!isCollapsed && }
); } const getStyles = (theme: GrafanaTheme2) => ({ row: css({ display: 'flex', flexDirection: 'column', flexGrow: 1, gap: theme.spacing(1), cursor: 'pointer', }), toggle: css({}), title: css({ fontSize: theme.typography.h5.fontSize, }), rowHeader: css({ display: 'flex', alignItems: 'center', gap: theme.spacing(2), }), actions: css({ display: 'flex', alignItems: 'center', gap: theme.spacing(1), justifyContent: 'flex-end', flexGrow: 1, }), });