QuickPositioning.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import { css } from '@emotion/css';
  2. import React from 'react';
  3. import { GrafanaTheme2 } from '@grafana/data/src';
  4. import { IconButton, useStyles2 } from '@grafana/ui/src';
  5. import { HorizontalConstraint, Placement, QuickPlacement, VerticalConstraint } from 'app/features/canvas';
  6. import { ElementState } from 'app/features/canvas/runtime/element';
  7. import { CanvasEditorOptions } from './elementEditor';
  8. type Props = {
  9. onPositionChange: (value: number | undefined, placement: keyof Placement) => void;
  10. element: ElementState;
  11. settings: CanvasEditorOptions;
  12. };
  13. export const QuickPositioning = ({ onPositionChange, element, settings }: Props) => {
  14. const styles = useStyles2(getStyles);
  15. const onQuickPositioningChange = (position: QuickPlacement) => {
  16. const defaultConstraint = { vertical: VerticalConstraint.Top, horizontal: HorizontalConstraint.Left };
  17. const originalConstraint = { ...element.options.constraint };
  18. element.options.constraint = defaultConstraint;
  19. element.setPlacementFromConstraint();
  20. switch (position) {
  21. case QuickPlacement.Top:
  22. onPositionChange(0, 'top');
  23. break;
  24. case QuickPlacement.Bottom:
  25. onPositionChange(getRightBottomPosition(element.options.placement?.height ?? 0, 'bottom'), 'top');
  26. break;
  27. case QuickPlacement.VerticalCenter:
  28. onPositionChange(getCenterPosition(element.options.placement?.height ?? 0, 'v'), 'top');
  29. break;
  30. case QuickPlacement.Left:
  31. onPositionChange(0, 'left');
  32. break;
  33. case QuickPlacement.Right:
  34. onPositionChange(getRightBottomPosition(element.options.placement?.width ?? 0, 'right'), 'left');
  35. break;
  36. case QuickPlacement.HorizontalCenter:
  37. onPositionChange(getCenterPosition(element.options.placement?.width ?? 0, 'h'), 'left');
  38. break;
  39. }
  40. element.options.constraint = originalConstraint;
  41. element.setPlacementFromConstraint();
  42. };
  43. // Basing this on scene will mean that center is based on root for the time being
  44. const getCenterPosition = (elementSize: number, align: 'h' | 'v') => {
  45. const sceneSize = align === 'h' ? settings.scene.width : settings.scene.height;
  46. return (sceneSize - elementSize) / 2;
  47. };
  48. const getRightBottomPosition = (elementSize: number, align: 'right' | 'bottom') => {
  49. const sceneSize = align === 'right' ? settings.scene.width : settings.scene.height;
  50. return sceneSize - elementSize;
  51. };
  52. return (
  53. <div className={styles.buttonGroup}>
  54. <IconButton
  55. name={'horizontal-align-left'}
  56. onClick={() => onQuickPositioningChange(QuickPlacement.Left)}
  57. className={styles.button}
  58. size={'lg'}
  59. tooltip={'Align left'}
  60. />
  61. <IconButton
  62. name={'horizontal-align-center'}
  63. onClick={() => onQuickPositioningChange(QuickPlacement.HorizontalCenter)}
  64. className={styles.button}
  65. size={'lg'}
  66. tooltip={'Align horizontal centers'}
  67. />
  68. <IconButton
  69. name={'horizontal-align-right'}
  70. onClick={() => onQuickPositioningChange(QuickPlacement.Right)}
  71. className={styles.button}
  72. size={'lg'}
  73. tooltip={'Align right'}
  74. />
  75. <IconButton
  76. name={'vertical-align-top'}
  77. onClick={() => onQuickPositioningChange(QuickPlacement.Top)}
  78. size={'lg'}
  79. tooltip={'Align top'}
  80. />
  81. <IconButton
  82. name={'vertical-align-center'}
  83. onClick={() => onQuickPositioningChange(QuickPlacement.VerticalCenter)}
  84. className={styles.button}
  85. size={'lg'}
  86. tooltip={'Align vertical centers'}
  87. />
  88. <IconButton
  89. name={'vertical-align-bottom'}
  90. onClick={() => onQuickPositioningChange(QuickPlacement.Bottom)}
  91. className={styles.button}
  92. size={'lg'}
  93. tooltip={'Align bottom'}
  94. />
  95. </div>
  96. );
  97. };
  98. const getStyles = (theme: GrafanaTheme2) => ({
  99. buttonGroup: css`
  100. display: flex;
  101. flex-wrap: wrap;
  102. padding: 12px 0 12px 0;
  103. `,
  104. button: css`
  105. margin-left: 5px;
  106. margin-right: 5px;
  107. `,
  108. });