Files
grafana/public/app/plugins/panel/canvas/editor/QuickPositioning.tsx
Adela Almasan b1ba0bc7b0 Canvas: Quick positioning (#48992)
Co-authored-by: nmarrs <nathanielmarrs@gmail.com>
2022-05-23 15:31:39 -07:00

123 lines
4.0 KiB
TypeScript

import { css } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2 } from '@grafana/data/src';
import { IconButton, useStyles2 } from '@grafana/ui/src';
import { HorizontalConstraint, Placement, QuickPlacement, VerticalConstraint } from 'app/features/canvas';
import { ElementState } from 'app/features/canvas/runtime/element';
import { CanvasEditorOptions } from './elementEditor';
type Props = {
onPositionChange: (value: number | undefined, placement: keyof Placement) => void;
element: ElementState;
settings: CanvasEditorOptions;
};
export const QuickPositioning = ({ onPositionChange, element, settings }: Props) => {
const styles = useStyles2(getStyles);
const onQuickPositioningChange = (position: QuickPlacement) => {
const defaultConstraint = { vertical: VerticalConstraint.Top, horizontal: HorizontalConstraint.Left };
const originalConstraint = { ...element.options.constraint };
element.options.constraint = defaultConstraint;
element.setPlacementFromConstraint();
switch (position) {
case QuickPlacement.Top:
onPositionChange(0, 'top');
break;
case QuickPlacement.Bottom:
onPositionChange(getRightBottomPosition(element.options.placement?.height ?? 0, 'bottom'), 'top');
break;
case QuickPlacement.VerticalCenter:
onPositionChange(getCenterPosition(element.options.placement?.height ?? 0, 'v'), 'top');
break;
case QuickPlacement.Left:
onPositionChange(0, 'left');
break;
case QuickPlacement.Right:
onPositionChange(getRightBottomPosition(element.options.placement?.width ?? 0, 'right'), 'left');
break;
case QuickPlacement.HorizontalCenter:
onPositionChange(getCenterPosition(element.options.placement?.width ?? 0, 'h'), 'left');
break;
}
element.options.constraint = originalConstraint;
element.setPlacementFromConstraint();
};
// Basing this on scene will mean that center is based on root for the time being
const getCenterPosition = (elementSize: number, align: 'h' | 'v') => {
const sceneSize = align === 'h' ? settings.scene.width : settings.scene.height;
return (sceneSize - elementSize) / 2;
};
const getRightBottomPosition = (elementSize: number, align: 'right' | 'bottom') => {
const sceneSize = align === 'right' ? settings.scene.width : settings.scene.height;
return sceneSize - elementSize;
};
return (
<div className={styles.buttonGroup}>
<IconButton
name={'horizontal-align-left'}
onClick={() => onQuickPositioningChange(QuickPlacement.Left)}
className={styles.button}
size={'lg'}
tooltip={'Align left'}
/>
<IconButton
name={'horizontal-align-center'}
onClick={() => onQuickPositioningChange(QuickPlacement.HorizontalCenter)}
className={styles.button}
size={'lg'}
tooltip={'Align horizontal centers'}
/>
<IconButton
name={'horizontal-align-right'}
onClick={() => onQuickPositioningChange(QuickPlacement.Right)}
className={styles.button}
size={'lg'}
tooltip={'Align right'}
/>
<IconButton
name={'vertical-align-top'}
onClick={() => onQuickPositioningChange(QuickPlacement.Top)}
size={'lg'}
tooltip={'Align top'}
/>
<IconButton
name={'vertical-align-center'}
onClick={() => onQuickPositioningChange(QuickPlacement.VerticalCenter)}
className={styles.button}
size={'lg'}
tooltip={'Align vertical centers'}
/>
<IconButton
name={'vertical-align-bottom'}
onClick={() => onQuickPositioningChange(QuickPlacement.Bottom)}
className={styles.button}
size={'lg'}
tooltip={'Align bottom'}
/>
</div>
);
};
const getStyles = (theme: GrafanaTheme2) => ({
buttonGroup: css`
display: flex;
flex-wrap: wrap;
padding: 12px 0 12px 0;
`,
button: css`
margin-left: 5px;
margin-right: 5px;
`,
});