diff --git a/desktop/plugins/public/ui-debugger/components/Visualization2D.tsx b/desktop/plugins/public/ui-debugger/components/Visualization2D.tsx
index e7e942d12..49585a6f5 100644
--- a/desktop/plugins/public/ui-debugger/components/Visualization2D.tsx
+++ b/desktop/plugins/public/ui-debugger/components/Visualization2D.tsx
@@ -13,6 +13,7 @@ import {Bounds, Coordinate, Id, NestedNode, Tag, UINode} from '../types';
import {produce, styled, theme, usePlugin, useValue} from 'flipper-plugin';
import {plugin} from '../index';
import {head, isEqual, throttle} from 'lodash';
+import {Dropdown, Menu} from 'antd';
export const Visualization2D: React.FC<
{
@@ -37,7 +38,8 @@ export const Visualization2D: React.FC<
useEffect(() => {
const mouseListener = throttle((ev: MouseEvent) => {
const domRect = rootNodeRef.current?.getBoundingClientRect();
- if (!focusState || !domRect) {
+
+ if (!focusState || !domRect || instance.isContextMenuOpen.get()) {
return;
}
const rawMouse = {x: ev.clientX, y: ev.clientY};
@@ -70,63 +72,68 @@ export const Visualization2D: React.FC<
return () => {
window.removeEventListener('mousemove', mouseListener);
};
- }, [instance.hoveredNodes, focusState, nodes]);
+ }, [instance.hoveredNodes, focusState, nodes, instance.isContextMenuOpen]);
if (!focusState) {
return null;
}
const snapshotNode = snapshot && nodes.get(snapshot.nodeId);
- return (
-
-
{
- e.stopPropagation();
- instance.hoveredNodes.set([]);
- }}
- style={{
- /**
- * This relative position is so the rootNode visualization 2DNode and outer border has a non static element to
- * position itself relative to.
- *
- * Subsequent Visualization2DNode are positioned relative to their parent as each one is position absolute
- * which despite the name acts are a reference point for absolute positioning...
- *
- * When focused the global offset of the focussed node is used to offset and size this 'root' node
- */
- position: 'relative',
- marginLeft: toPx(focusState.focusedRootGlobalOffset.x),
- marginTop: toPx(focusState.focusedRootGlobalOffset.y),
- width: toPx(focusState.focusedRoot.bounds.width),
- height: toPx(focusState.focusedRoot.bounds.height),
- overflow: 'hidden',
+ return (
+
+
- {snapshotNode && (
-

{
+ e.stopPropagation();
+ //the context menu triggers this callback but we dont want to remove hover effect
+ if (!instance.isContextMenuOpen.get()) {
+ instance.hoveredNodes.set([]);
+ }
+ }}
+ style={{
+ /**
+ * This relative position is so the rootNode visualization 2DNode and outer border has a non static element to
+ * position itself relative to.
+ *
+ * Subsequent Visualization2DNode are positioned relative to their parent as each one is position absolute
+ * which despite the name acts are a reference point for absolute positioning...
+ *
+ * When focused the global offset of the focussed node is used to offset and size this 'root' node
+ */
+ position: 'relative',
+ marginLeft: toPx(focusState.focusedRootGlobalOffset.x),
+ marginTop: toPx(focusState.focusedRootGlobalOffset.y),
+ width: toPx(focusState.focusedRoot.bounds.width),
+ height: toPx(focusState.focusedRoot.bounds.height),
+ overflow: 'hidden',
+ }}>
+ {snapshotNode && (
+

+ )}
+
- )}
-
+
-
+
);
};
@@ -230,6 +237,52 @@ function Visualization2DNode({
);
}
+const ContextMenu: React.FC<{nodes: Map}> = ({children}) => {
+ const instance = usePlugin(plugin);
+
+ const focusedNodeId = useValue(instance.focusedNode);
+ const hoveredNodeId = head(useValue(instance.hoveredNodes));
+ const nodes = useValue(instance.nodes);
+ const hoveredNode = hoveredNodeId ? nodes.get(hoveredNodeId) : null;
+ const isMenuOpen = useValue(instance.isContextMenuOpen);
+
+ return (
+ {
+ instance.isContextMenuOpen.set(open);
+ }}
+ trigger={['contextMenu']}
+ overlay={() => {
+ return (
+
+ );
+ }}>
+ {children}
+
+ );
+};
+
/**
* this is the border that shows the green or blue line, it is implemented as a sibling to the
* node itself so that it has the same size but the border doesnt affect the sizing of its children