diff --git a/public/app/core/components/SplitPaneWrapper/SplitPaneWrapper.tsx b/public/app/core/components/SplitPaneWrapper/SplitPaneWrapper.tsx index 7724b1cbaf2..51d1786d274 100644 --- a/public/app/core/components/SplitPaneWrapper/SplitPaneWrapper.tsx +++ b/public/app/core/components/SplitPaneWrapper/SplitPaneWrapper.tsx @@ -1,28 +1,23 @@ import { css, cx } from '@emotion/css'; -import React, { createRef, MutableRefObject, PureComponent, ReactNode } from 'react'; -import SplitPane from 'react-split-pane'; +import React, { createRef, MutableRefObject, PureComponent } from 'react'; +import SplitPane, { Split } from 'react-split-pane'; import { GrafanaTheme2 } from '@grafana/data'; import { config } from 'app/core/config'; -enum Pane { - Right, - Top, -} - interface Props { - leftPaneComponents: ReactNode[] | ReactNode; - rightPaneComponents: ReactNode; - uiState: { topPaneSize: number; rightPaneSize: number }; - rightPaneVisible?: boolean; - updateUiState: (uiState: { topPaneSize?: number; rightPaneSize?: number }) => void; + splitOrientation?: Split; + paneSize: number; + splitVisible?: boolean; + maxSize?: number; + primary?: 'first' | 'second'; + onDragFinished?: (size?: number) => void; + secondaryPaneStyle?: React.CSSProperties; } export class SplitPaneWrapper extends PureComponent { + //requestAnimationFrame reference rafToken: MutableRefObject = createRef(); - static defaultProps = { - rightPaneVisible: true, - }; componentDidMount() { window.addEventListener('resize', this.updateSplitPaneSize); @@ -41,86 +36,41 @@ export class SplitPaneWrapper extends PureComponent { }); }; - onDragFinished = (pane: Pane, size?: number) => { + onDragFinished = (size?: number) => { document.body.style.cursor = 'auto'; - // When the drag handle is just clicked size is undefined - if (!size) { - return; - } - - const { updateUiState } = this.props; - if (pane === Pane.Top) { - updateUiState({ - topPaneSize: size / window.innerHeight, - }); - } else { - updateUiState({ - rightPaneSize: size / window.innerWidth, - }); + if (this.props.onDragFinished && size !== undefined) { + this.props.onDragFinished(size); } }; onDragStarted = () => { - document.body.style.cursor = 'row-resize'; + document.body.style.cursor = this.props.splitOrientation === 'horizontal' ? 'row-resize' : 'col-resize'; }; - renderHorizontalSplit() { - const { leftPaneComponents, uiState } = this.props; - const styles = getStyles(config.theme2); - const topPaneSize = uiState.topPaneSize >= 1 ? uiState.topPaneSize : uiState.topPaneSize * window.innerHeight; - - /* - Guesstimate the height of the browser window minus - panel toolbar and editor toolbar (~120px). This is to prevent resizing - the preview window beyond the browser window. - */ - - if (Array.isArray(leftPaneComponents)) { - return ( - this.onDragFinished(Pane.Top, size)} - > - {leftPaneComponents} - - ); - } - - return
{leftPaneComponents}
; - } - render() { - const { rightPaneVisible, rightPaneComponents, uiState } = this.props; + const { paneSize, splitOrientation, maxSize, primary, secondaryPaneStyle } = this.props; // Limit options pane width to 90% of screen. const styles = getStyles(config.theme2); // Need to handle when width is relative. ie a percentage of the viewport - const rightPaneSize = - uiState.rightPaneSize <= 1 ? uiState.rightPaneSize * window.innerWidth : uiState.rightPaneSize; - - if (!rightPaneVisible) { - return this.renderHorizontalSplit(); - } + const paneSizePx = + paneSize <= 1 + ? paneSize * (splitOrientation === 'horizontal' ? window.innerHeight : window.innerWidth) + : paneSize; return ( (document.body.style.cursor = 'col-resize')} - onDragFinished={(size) => this.onDragFinished(Pane.Right, size)} + split={splitOrientation} + maxSize={maxSize} + size={paneSizePx} + primary={primary} + resizerClassName={splitOrientation === 'horizontal' ? styles.resizerH : styles.resizerV} + onDragStarted={() => this.onDragStarted()} + onDragFinished={(size) => this.onDragFinished(size)} + pane2Style={secondaryPaneStyle} > - {this.renderHorizontalSplit()} - {rightPaneComponents} + {this.props.children} ); } diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx index 0ff0ddc03cf..d92b0bd48ab 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx @@ -47,7 +47,7 @@ import { PanelEditorTableView } from './PanelEditorTableView'; import { PanelEditorTabs } from './PanelEditorTabs'; import { VisualizationButton } from './VisualizationButton'; import { discardPanelChanges, initPanelEditor, updatePanelEditorUIState } from './state/actions'; -import { toggleTableView } from './state/reducers'; +import { PanelEditorUIState, toggleTableView } from './state/reducers'; import { getPanelEditorTabs } from './state/selectors'; import { DisplayMode, displayModes, PanelEditorTab } from './types'; import { calculatePanelSize } from './utils'; @@ -438,8 +438,27 @@ export class PanelEditorUnconnected extends PureComponent { ); } + renderHorizontalSplit(uiState: PanelEditorUIState, styles: EditorStyles) { + return ( + { + if (size) { + updatePanelEditorUIState({ topPaneSize: size / window.innerHeight }); + } + }} + > + {this.renderPanelAndEditor(styles)} + + ); + } + render() { - const { initDone, updatePanelEditorUIState, uiState, theme, sectionNav, pageNav, className } = this.props; + const { initDone, uiState, theme, sectionNav, pageNav, className, updatePanelEditorUIState } = this.props; const styles = getStyles(theme, this.props); if (!initDone) { @@ -457,13 +476,24 @@ export class PanelEditorUnconnected extends PureComponent { >
- + {!uiState.isPanelOptionsVisible ? ( + this.renderHorizontalSplit(uiState, styles) + ) : ( + { + if (size) { + updatePanelEditorUIState({ rightPaneSize: size / window.innerWidth }); + } + }} + > + {this.renderHorizontalSplit(uiState, styles)} + {this.renderOptionsPane()} + + )}
{this.state.showSaveLibraryPanelModal && (