import { css, cx } from '@emotion/css';
import React, { CSSProperties, useEffect } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { config, useChromeHeaderHeight } from '@grafana/runtime';
import { useSceneObjectState } from '@grafana/scenes';
import { ElementSelectionContext, useStyles2 } from '@grafana/ui';
import NativeScrollbar, { DivScrollElement } from 'app/core/components/NativeScrollbar';
import { useSnappingSplitter } from '../panel-edit/splitter/useSnappingSplitter';
import { DashboardScene } from '../scene/DashboardScene';
import { NavToolbarActions } from '../scene/NavToolbarActions';
import { DashboardEditPaneRenderer } from './DashboardEditPane';
import { useEditPaneCollapsed } from './shared';
interface Props {
dashboard: DashboardScene;
isEditing?: boolean;
body?: React.ReactNode;
controls?: React.ReactNode;
}
export function DashboardEditPaneSplitter({ dashboard, isEditing, body, controls }: Props) {
const headerHeight = useChromeHeaderHeight();
const { editPane } = dashboard.state;
const styles = useStyles2(getStyles, headerHeight ?? 0);
const [isCollapsed, setIsCollapsed] = useEditPaneCollapsed();
if (!config.featureToggles.dashboardNewLayouts) {
return (
);
}
const { containerProps, primaryProps, secondaryProps, splitterProps, splitterState, onToggleCollapse } =
useSnappingSplitter({
direction: 'row',
dragPosition: 'end',
initialSize: 0.8,
handleSize: 'sm',
collapsed: isCollapsed,
paneOptions: {
collapseBelowPixels: 250,
snapOpenToPixels: 400,
},
});
useEffect(() => {
setIsCollapsed(splitterState.collapsed);
}, [splitterState.collapsed, setIsCollapsed]);
const { selectionContext } = useSceneObjectState(editPane, { shouldActivateOrKeepAlive: true });
const containerStyle: CSSProperties = {};
if (!isEditing) {
primaryProps.style.flexGrow = 1;
primaryProps.style.width = '100%';
primaryProps.style.minWidth = 'unset';
containerStyle.overflow = 'unset';
}
const onBodyRef = (ref: HTMLDivElement) => {
dashboard.onSetScrollRef(new DivScrollElement(ref));
};
return (
{
if (evt.shiftKey) {
return;
}
editPane.clearSelection();
}}
>
{controls}
{isEditing && (
<>
0}
/>
>
)}
);
}
function getStyles(theme: GrafanaTheme2, headerHeight: number) {
return {
canvasWrappperOld: css({
label: 'canvas-wrapper-old',
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
}),
canvasWithSplitter: css({
overflow: 'unset',
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
}),
canvasWithSplitterEditing: css({
overflow: 'unset',
}),
bodyWrapper: css({
label: 'body-wrapper',
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
position: 'relative',
}),
body: css({
label: 'body',
display: 'flex',
flexGrow: 1,
gap: '8px',
boxSizing: 'border-box',
flexDirection: 'column',
padding: theme.spacing(0, 2, 2, 2),
}),
bodyEditing: css({
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0,
overflow: 'auto',
scrollbarWidth: 'thin',
// The fixed controls headers is otherwise rendered over the selection outlinem, Maybe there is an other solution
paddingTop: '2px',
}),
editPane: css({
flexDirection: 'column',
borderLeft: `1px solid ${theme.colors.border.weak}`,
background: theme.colors.background.primary,
}),
controlsWrapperSticky: css({
[theme.breakpoints.up('md')]: {
position: 'sticky',
zIndex: theme.zIndex.activePanel,
background: theme.colors.background.canvas,
top: headerHeight,
},
}),
};
}