mp-lens
Version:
微信小程序分析工具 (Unused Code, Dependencies, Visualization)
149 lines • 8.01 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TreeView = TreeView;
const jsx_runtime_1 = require("preact/jsx-runtime");
const hooks_1 = require("preact/hooks");
const TreeView_module_css_1 = __importDefault(require("./TreeView.module.css")); // Import CSS module
// Recursive TreeNode component
function TreeNode({ node, onNodeSelect, selectedNodeId, isExpanded, toggleNode, isNodeExpandedCheck, depth, // Current nesting depth
}) {
var _a;
console.log('TreeNode depth', depth);
const isSelected = node.id === selectedNodeId;
const hasChildren = node.children && node.children.length > 0;
const indentSize = 20; // Pixels per depth level
const handleNodeClick = () => {
onNodeSelect(node);
};
// Renamed from handleToggleClick for clarity
const handleNodeDoubleClick = (e) => {
e.stopPropagation(); // Prevent potential text selection issues
// Only toggle if the node actually has children
if (hasChildren) {
toggleNode(node.id);
}
};
// Add separate handler for triangle toggle click
const handleToggleClick = (e) => {
e.stopPropagation(); // Prevent the node selection
if (hasChildren) {
toggleNode(node.id);
}
};
return ((0, jsx_runtime_1.jsxs)("li", { children: [(0, jsx_runtime_1.jsxs)("div", { "data-node-id": node.id, onClick: handleNodeClick, onDblClick: handleNodeDoubleClick, className: `${TreeView_module_css_1.default.treeNodeItem} ${isSelected ? TreeView_module_css_1.default.selected : ''}`, title: `ID: ${node.id}`, style: { paddingLeft: `${depth * indentSize}px` }, children: [hasChildren && (
// Restore the onClick handler for the toggle span
(0, jsx_runtime_1.jsx)("span", { className: TreeView_module_css_1.default.toggle, onClick: handleToggleClick, children: isExpanded ? '▼' : '▶' })), !hasChildren && (0, jsx_runtime_1.jsx)("span", { className: TreeView_module_css_1.default.toggle, children: "\u00A0" }), " ", (0, jsx_runtime_1.jsx)("span", { className: TreeView_module_css_1.default.label, children: node.label })] }), hasChildren && isExpanded && ((0, jsx_runtime_1.jsx)("ul", { children: (_a = node.children) === null || _a === void 0 ? void 0 : _a.map((child) => ((0, jsx_runtime_1.jsx)(TreeNode, { node: child, onNodeSelect: onNodeSelect, selectedNodeId: selectedNodeId, isExpanded: isNodeExpandedCheck(child.id), toggleNode: toggleNode, isNodeExpandedCheck: isNodeExpandedCheck, depth: depth + 1 }, child.id))) }))] }));
}
// Helper function to collect all expandable node IDs
function getAllExpandableNodeIds(node) {
const ids = new Set();
function traverse(currentNode) {
if (currentNode.children && currentNode.children.length > 0) {
ids.add(currentNode.id);
currentNode.children.forEach(traverse);
}
}
traverse(node);
return ids;
}
// *** NEW: Helper function to find ancestor IDs ***
function findAncestorIds(targetId, rootNode) {
const path = [];
function traverse(currentNode) {
// Add current node to path temporarily
path.push(currentNode.id);
if (currentNode.id === targetId) {
// Found the target, path is complete (excluding target itself)
path.pop(); // Remove targetId from the path of ancestors
return true;
}
if (currentNode.children) {
for (const child of currentNode.children) {
if (traverse(child)) {
// Found in this subtree, keep path as is
return true;
}
}
}
// Not found in this subtree, backtrack
path.pop();
return false;
}
traverse(rootNode);
return path; // Return the collected ancestor IDs
}
// Main TreeView component - manages expansion state
function TreeView({ data, onNodeSelect, selectedNodeId, onExpandAll, onCollapseAll, }) {
const [expandedNodes, setExpandedNodes] = (0, hooks_1.useState)(new Set([data.id]));
// Calculate all expandable node IDs once
const allExpandableIds = (0, hooks_1.useMemo)(() => getAllExpandableNodeIds(data), [data]);
// *** useEffect to expand ancestors when selectedNodeId changes ***
(0, hooks_1.useEffect)(() => {
if (selectedNodeId && data) {
// Find the path of ancestors for the selected node
const ancestors = findAncestorIds(selectedNodeId, data);
if (ancestors.length > 0) {
setExpandedNodes((prevExpanded) => {
const newExpanded = new Set(prevExpanded);
// Add all ancestors to the set
ancestors.forEach((id) => newExpanded.add(id));
// Avoid creating new set if no changes needed
if (ancestors.every((id) => prevExpanded.has(id))) {
return prevExpanded;
}
console.log('[TreeView] Expanding ancestors:', ancestors);
return newExpanded;
});
}
}
// Dependency: selectedNodeId (prop) and data (prop, unlikely to change but good practice)
}, [selectedNodeId, data]);
// Scroll to selected node when it changes
(0, hooks_1.useEffect)(() => {
if (selectedNodeId) {
// Use a timeout to ensure the DOM has been updated after any potential expansions
const timer = setTimeout(() => {
const element = document.querySelector(`[data-node-id="${selectedNodeId}"]`);
if (element) {
element.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
});
}
}, 100); // A small delay is sometimes necessary
return () => clearTimeout(timer); // Cleanup timeout
}
}, [selectedNodeId]);
const toggleNode = (nodeId) => {
setExpandedNodes((prev) => {
const newSet = new Set(prev);
if (newSet.has(nodeId)) {
newSet.delete(nodeId);
}
else {
newSet.add(nodeId);
}
return newSet;
});
};
// Implement expand/collapse all logic using useCallback
const handleExpandAll = (0, hooks_1.useCallback)(() => {
setExpandedNodes(allExpandableIds);
// Call external handler if provided (though maybe not needed if state managed here)
if (onExpandAll)
onExpandAll();
}, [allExpandableIds, onExpandAll]);
const handleCollapseAll = (0, hooks_1.useCallback)(() => {
setExpandedNodes(new Set([data.id])); // Keep root expanded
// Call external handler if provided
if (onCollapseAll)
onCollapseAll();
}, [data.id, onCollapseAll]);
// Helper function to pass down expansion state
const isNodeExpanded = (nodeId) => expandedNodes.has(nodeId);
return ((0, jsx_runtime_1.jsxs)("div", { className: TreeView_module_css_1.default.treeView, children: [(0, jsx_runtime_1.jsxs)("div", { className: TreeView_module_css_1.default.treeControls, children: [(0, jsx_runtime_1.jsx)("button", { onClick: handleExpandAll, children: "Expand All" }), (0, jsx_runtime_1.jsx)("button", { onClick: handleCollapseAll, children: "Collapse All" })] }), (0, jsx_runtime_1.jsx)("div", { className: TreeView_module_css_1.default.treeContainer, children: (0, jsx_runtime_1.jsx)("ul", { children: (0, jsx_runtime_1.jsx)(TreeNode, { node: data, onNodeSelect: onNodeSelect, selectedNodeId: selectedNodeId, isExpanded: isNodeExpanded(data.id), toggleNode: toggleNode, isNodeExpandedCheck: isNodeExpanded, depth: 0 }, data.id) }) })] }));
}
//# sourceMappingURL=TreeView.js.map