Only render a single context menu for the entire tree

Summary: There is no reason to have a context menu rendered by react for each item in the tree, its pretty wastefull. It also means less props drilled to the tree node

Reviewed By: lblasa

Differential Revision: D41872778

fbshipit-source-id: b13491a310c03334d7f3056207f5de23d20c3e61
This commit is contained in:
Luke De Feo
2022-12-12 07:28:37 -08:00
committed by Facebook GitHub Bot
parent 040240ec34
commit ed35623bef

View File

@@ -83,6 +83,12 @@ export function Tree2({
<HighlightProvider <HighlightProvider
text={searchTerm} text={searchTerm}
highlightColor={theme.searchHighlightBackground.yellow}> highlightColor={theme.searchHighlightBackground.yellow}>
<ContextMenu
focusedNode={focusedNode}
hoveredNode={hoveredNode}
nodes={nodes}
onContextMenuOpen={instance.uiActions.onContextMenuOpen}
onFocusNode={instance.uiActions.onFocusNode}>
<div <div
onMouseLeave={() => { onMouseLeave={() => {
if (isContextMenuOpen === false) { if (isContextMenuOpen === false) {
@@ -96,18 +102,16 @@ export function Tree2({
treeNode={treeNode} treeNode={treeNode}
selectedNode={selectedNode} selectedNode={selectedNode}
hoveredNode={hoveredNode} hoveredNode={hoveredNode}
focusedNode={focusedNode}
isUsingKBToScroll={isUsingKBToScroll} isUsingKBToScroll={isUsingKBToScroll}
isContextMenuOpen={isContextMenuOpen} isContextMenuOpen={isContextMenuOpen}
onSelectNode={onSelectNode} onSelectNode={onSelectNode}
onExpandNode={instance.uiActions.onExpandNode} onExpandNode={instance.uiActions.onExpandNode}
onCollapseNode={instance.uiActions.onCollapseNode} onCollapseNode={instance.uiActions.onCollapseNode}
onContextMenuOpen={instance.uiActions.onContextMenuOpen}
onFocusNode={instance.uiActions.onFocusNode}
onHoverNode={instance.uiActions.onHoverNode} onHoverNode={instance.uiActions.onHoverNode}
/> />
))} ))}
</div> </div>
</ContextMenu>
</HighlightProvider> </HighlightProvider>
); );
} }
@@ -138,11 +142,8 @@ function TreeItemContainer({
treeNode, treeNode,
selectedNode, selectedNode,
hoveredNode, hoveredNode,
focusedNode,
isUsingKBToScroll, isUsingKBToScroll,
isContextMenuOpen, isContextMenuOpen,
onFocusNode,
onContextMenuOpen,
onSelectNode, onSelectNode,
onExpandNode, onExpandNode,
onCollapseNode, onCollapseNode,
@@ -152,32 +153,20 @@ function TreeItemContainer({
treeNode: TreeNode; treeNode: TreeNode;
selectedNode?: Id; selectedNode?: Id;
hoveredNode?: Id; hoveredNode?: Id;
focusedNode?: Id;
isUsingKBToScroll: RefObject<boolean>; isUsingKBToScroll: RefObject<boolean>;
isContextMenuOpen: boolean; isContextMenuOpen: boolean;
onFocusNode: (id?: Id) => void;
onContextMenuOpen: (open: boolean) => void;
onSelectNode: (node?: Id) => void; onSelectNode: (node?: Id) => void;
onExpandNode: (node: Id) => void; onExpandNode: (node: Id) => void;
onCollapseNode: (node: Id) => void; onCollapseNode: (node: Id) => void;
onHoverNode: (node: Id) => void; onHoverNode: (node: Id) => void;
}) { }) {
return ( return (
<ContextMenu
onContextMenuOpen={onContextMenuOpen}
onFocusNode={onFocusNode}
focusedNode={focusedNode}
hoveredNode={hoveredNode}
node={treeNode}>
<TreeItem <TreeItem
ref={innerRef} ref={innerRef}
isSelected={treeNode.id === selectedNode} isSelected={treeNode.id === selectedNode}
isHovered={hoveredNode === treeNode.id} isHovered={hoveredNode === treeNode.id}
onMouseEnter={() => { onMouseEnter={() => {
if ( if (isUsingKBToScroll.current === false && isContextMenuOpen == false) {
isUsingKBToScroll.current === false &&
isContextMenuOpen == false
) {
onHoverNode(treeNode.id); onHoverNode(treeNode.id);
} }
}} }}
@@ -200,7 +189,6 @@ function TreeItemContainer({
<HighlightedText text={treeNode.name} /> <HighlightedText text={treeNode.name} />
<InlineAttributes attributes={treeNode.inlineAttributes} /> <InlineAttributes attributes={treeNode.inlineAttributes} />
</TreeItem> </TreeItem>
</ContextMenu>
); );
} }
@@ -291,13 +279,13 @@ const DecorationImage = styled.img({
const renderDepthOffset = 4; const renderDepthOffset = 4;
const ContextMenu: React.FC<{ const ContextMenu: React.FC<{
node: TreeNode; nodes: Map<Id, UINode>;
hoveredNode?: Id; hoveredNode?: Id;
focusedNode?: Id; focusedNode?: Id;
onFocusNode: (id?: Id) => void; onFocusNode: (id?: Id) => void;
onContextMenuOpen: (open: boolean) => void; onContextMenuOpen: (open: boolean) => void;
}> = ({ }> = ({
node, nodes,
hoveredNode, hoveredNode,
children, children,
focusedNode, focusedNode,
@@ -311,12 +299,12 @@ const ContextMenu: React.FC<{
}} }}
overlay={() => ( overlay={() => (
<Menu> <Menu>
{focusedNode !== hoveredNode && ( {hoveredNode != null && focusedNode !== hoveredNode && (
<UIDebuggerMenuItem <UIDebuggerMenuItem
key="focus" key="focus"
text={`Focus ${node.name}`} text={`Focus ${nodes.get(hoveredNode)?.name}`}
onClick={() => { onClick={() => {
onFocusNode(node.id); onFocusNode(hoveredNode);
}} }}
/> />
)} )}