/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format */ import {Id, UINode} from '../types'; import React from 'react'; import { HighlightManager, HighlightProvider, styled, theme, useHighlighter, usePlugin, useValue, } from 'flipper-plugin'; import {plugin} from '../index'; import {Glyph} from 'flipper'; export function Tree2({ nodes, rootId, selectedNode, onSelectNode, }: { nodes: Map; rootId: Id; selectedNode?: Id; onSelectNode: (node?: Id) => void; }) { const instance = usePlugin(plugin); const expandedNodes = useValue(instance.uiState.expandedNodes); const searchTerm = useValue(instance.uiState.searchTerm); const items = toTreeList(nodes, rootId, expandedNodes); return (
{items.map((treeNode) => ( ))}
); } export type TreeNode = UINode & { depth: number; isExpanded: boolean; }; function TreeItemContainer({ treeNode, selectedNode, hoveredNode, onSelectNode, }: { treeNode: TreeNode; selectedNode?: Id; hoveredNode?: Id; onSelectNode: (node?: Id) => void; }) { const instance = usePlugin(plugin); return ( { onSelectNode(treeNode.id); }} item={treeNode}> { instance.uiState.expandedNodes.update((draft) => { if (draft.has(treeNode.id)) { draft.delete(treeNode.id); } else { draft.add(treeNode.id); } }); }} /> {nodeIcon(treeNode)} ); } const TreeItem = styled.li<{ item: TreeNode; isHovered: boolean; isSelected: boolean; }>(({item, isHovered, isSelected}) => ({ display: 'flex', alignItems: 'center', height: '26px', paddingLeft: `${(item.depth + 1) * renderDepthOffset}px`, borderWidth: '1px', borderRadius: '3px', borderColor: isHovered ? theme.selectionBackgroundColor : 'transparent', borderStyle: 'solid', backgroundColor: isSelected ? theme.selectionBackgroundColor : theme.white, })); function Arrow(props: {onClick: () => void; expanded: boolean}) { return (
); } function HighlightedText(props: {text: string}) { const highlightManager: HighlightManager = useHighlighter(); return {highlightManager.render(props.text)}; } function nodeIcon(node: UINode) { if (node.tags.includes('Litho')) { return ; } } const DecorationImage = styled.img({ height: 12, marginRight: 5, width: 12, }); const renderDepthOffset = 4; function toTreeList( nodes: Map, rootId: Id, expandedNodes: Set, ): TreeNode[] { const root = nodes.get(rootId); if (root == null) { return []; } const stack = [[root, 0]] as [UINode, number][]; const res = [] as TreeNode[]; while (stack.length > 0) { const [cur, depth] = stack.pop()!!; const isExpanded = expandedNodes.has(cur.id); res.push({ ...cur, depth, isExpanded, }); if (isExpanded) { for (const childId of cur.children) { const child = nodes.get(childId); if (child != null) { stack.push([child, depth + 1]); } else { console.log('null', childId); } } } } return res; }