From 8fdc8daa0f4f4a71db7b633c01600bf96ae38f4e Mon Sep 17 00:00:00 2001 From: LordMathis Date: Wed, 9 Oct 2024 22:34:19 +0200 Subject: [PATCH] Migrate FileTree --- frontend/package-lock.json | 32 +++++++ frontend/package.json | 1 + frontend/src/components/FileTree.js | 131 ++++++++++++++++++---------- 3 files changed, 117 insertions(+), 47 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d5badbe..10900a3 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -21,6 +21,7 @@ "@mantine/hooks": "^7.13.2", "@mantine/modals": "^7.13.2", "@mantine/notifications": "^7.13.2", + "@react-hook/resize-observer": "^2.0.2", "@tabler/icons-react": "^3.19.0", "codemirror": "^6.0.1", "katex": "^0.16.11", @@ -2568,6 +2569,37 @@ "integrity": "sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==", "license": "MIT" }, + "node_modules/@react-hook/latest": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@react-hook/latest/-/latest-1.0.3.tgz", + "integrity": "sha512-dy6duzl+JnAZcDbNTfmaP3xHiKtbXYOaz3G51MGVljh548Y8MWzTr+PHLOfvpypEVW9zwvl+VyKjbWKEVbV1Rg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/@react-hook/passive-layout-effect": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@react-hook/passive-layout-effect/-/passive-layout-effect-1.2.1.tgz", + "integrity": "sha512-IwEphTD75liO8g+6taS+4oqz+nnroocNfWVHWz7j+N+ZO2vYrc6PV1q7GQhuahL0IOR7JccFTsFKQ/mb6iZWAg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/@react-hook/resize-observer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@react-hook/resize-observer/-/resize-observer-2.0.2.tgz", + "integrity": "sha512-tzKKzxNpfE5TWmxuv+5Ae3IF58n0FQgQaWJmcbYkjXTRZATXxClnTprQ2uuYygYTpu1pqbBskpwMpj6jpT1djA==", + "license": "MIT", + "dependencies": { + "@react-hook/latest": "^1.0.2", + "@react-hook/passive-layout-effect": "^1.2.0" + }, + "peerDependencies": { + "react": ">=18" + } + }, "node_modules/@tabler/icons": { "version": "3.19.0", "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.19.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index aef4811..8cf8ff5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -34,6 +34,7 @@ "@mantine/hooks": "^7.13.2", "@mantine/modals": "^7.13.2", "@mantine/notifications": "^7.13.2", + "@react-hook/resize-observer": "^2.0.2", "@tabler/icons-react": "^3.19.0", "codemirror": "^6.0.1", "katex": "^0.16.11", diff --git a/frontend/src/components/FileTree.js b/frontend/src/components/FileTree.js index 30bfeaf..ae2e3ac 100644 --- a/frontend/src/components/FileTree.js +++ b/frontend/src/components/FileTree.js @@ -1,65 +1,102 @@ -import React from 'react'; +import React, { useRef, useState, useLayoutEffect } from 'react'; import { Tree } from 'react-arborist'; -import { Group, Text } from '@mantine/core'; import { IconFile, IconFolder, IconFolderOpen } from '@tabler/icons-react'; -import { isImageFile } from '../utils/fileHelpers'; +import { Tooltip } from '@mantine/core'; +import useResizeObserver from '@react-hook/resize-observer'; -const FileIcon = ({ isFolder, isOpen }) => { - if (isFolder) { - return isOpen ? ( - - ) : ( - - ); +const useSize = (target) => { + const [size, setSize] = useState(); + + useLayoutEffect(() => { + setSize(target.current.getBoundingClientRect()); + }, [target]); + + useResizeObserver(target, (entry) => setSize(entry.contentRect)); + return size; +}; + +const FileIcon = ({ node }) => { + if (node.isLeaf) { + return ; } - return ; + return node.isOpen ? ( + + ) : ( + + ); }; const Node = ({ node, style, dragHandle }) => { - const isFolder = Array.isArray(node.data.children); - return ( - node.toggle()} - sx={(theme) => ({ - cursor: 'pointer', - '&:hover': { - backgroundColor: - theme.colorScheme === 'dark' - ? theme.colors.dark[6] - : theme.colors.gray[0], - }, - })} - > - - {node.data.name} - + +
{ + if (node.isInternal) { + node.toggle(); + } else { + node.tree.props.onNodeClick(node); + } + }} + > + + + {node.data.name} + +
+
); }; const FileTree = ({ files, handleFileSelect }) => { - const handleNodeClick = (node) => { - if (!node.isInternal) { - handleFileSelect(node.data.path); - } - }; + const target = useRef(null); + const size = useSize(target); return ( - - {Node} - + {size && ( + { + if (!node.isInternal) { + handleFileSelect(node.data.path); + } + }} + onNodeClick={(node) => { + if (!node.isInternal) { + handleFileSelect(node.data.path); + } + }} + > + {Node} + + )} + ); };