diff --git a/public/app/plugins/panel/canvas/CanvasContextMenu.tsx b/public/app/plugins/panel/canvas/CanvasContextMenu.tsx index 29990ff9f60..d4eb898d069 100644 --- a/public/app/plugins/panel/canvas/CanvasContextMenu.tsx +++ b/public/app/plugins/panel/canvas/CanvasContextMenu.tsx @@ -2,6 +2,7 @@ import { css } from '@emotion/css'; import React, { useCallback, useEffect, useState } from 'react'; import { first } from 'rxjs/operators'; +import { SelectableValue } from '@grafana/data'; import { ContextMenu, MenuItem, MenuItemProps } from '@grafana/ui'; import { Scene } from 'app/features/canvas/runtime/scene'; @@ -108,13 +109,26 @@ export const CanvasContextMenu = ({ scene, panel }: Props) => { const submenuItems: Array< React.ReactElement, string | React.JSXElementConstructor> > = []; + + const onClickItem = (option: SelectableValue) => { + let offsetY = anchorPoint.y; + let offsetX = anchorPoint.x; + if (scene.div) { + const sceneContainerDimensions = scene.div.getBoundingClientRect(); + offsetY = offsetY - sceneContainerDimensions.top; + offsetX = offsetX - sceneContainerDimensions.left; + } + + onAddItem(option, rootLayer, { + ...anchorPoint, + y: offsetY, + x: offsetX, + }); + }; + typeOptions.map((option) => { submenuItems.push( - onAddItem(option, rootLayer)} - /> + onClickItem(option)} /> ); }); diff --git a/public/app/plugins/panel/canvas/utils.ts b/public/app/plugins/panel/canvas/utils.ts index 89e80963a04..3a695c10e42 100644 --- a/public/app/plugins/panel/canvas/utils.ts +++ b/public/app/plugins/panel/canvas/utils.ts @@ -14,6 +14,8 @@ import { ElementState } from '../../../features/canvas/runtime/element'; import { FrameState } from '../../../features/canvas/runtime/frame'; import { Scene, SelectionParams } from '../../../features/canvas/runtime/scene'; +import { AnchorPoint } from './types'; + export function doSelect(scene: Scene, element: ElementState | FrameState) { try { let selection: SelectionParams = { targets: [] }; @@ -74,10 +76,15 @@ export function getElementTypesOptions(items: CanvasElementItem[], current: stri return selectables; } -export function onAddItem(sel: SelectableValue, rootLayer: FrameState | undefined) { +export function onAddItem(sel: SelectableValue, rootLayer: FrameState | undefined, anchorPoint?: AnchorPoint) { const newItem = canvasElementRegistry.getIfExists(sel.value) ?? notFoundItem; const newElementOptions = newItem.getNewOptions() as CanvasElementOptions; newElementOptions.type = newItem.id; + + if (anchorPoint) { + newElementOptions.placement = { ...newElementOptions.placement, top: anchorPoint.y, left: anchorPoint.x }; + } + if (newItem.defaultSize) { newElementOptions.placement = { ...newElementOptions.placement, ...newItem.defaultSize }; }