@ai-group/chat-sdk 3.4.4 → 3.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/FolderTree/DirectoryTree.d.ts +2 -0
- package/dist/cjs/components/FolderTree/DirectoryTree.js +50 -2
- package/dist/cjs/components/FolderTree/DirectoryTree.js.map +2 -2
- package/dist/cjs/components/FolderTree/index.js +6 -2
- package/dist/cjs/components/FolderTree/index.js.map +2 -2
- package/dist/cjs/components/FolderTree/styles.js +16 -0
- package/dist/cjs/components/FolderTree/styles.js.map +2 -2
- package/dist/cjs/components/FolderTree/types.d.ts +23 -0
- package/dist/cjs/components/FolderTree/types.js.map +1 -1
- package/dist/esm/components/FolderTree/DirectoryTree.d.ts +2 -0
- package/dist/esm/components/FolderTree/DirectoryTree.js +51 -2
- package/dist/esm/components/FolderTree/DirectoryTree.js.map +1 -1
- package/dist/esm/components/FolderTree/index.js +6 -2
- package/dist/esm/components/FolderTree/index.js.map +1 -1
- package/dist/esm/components/FolderTree/styles.js +1 -1
- package/dist/esm/components/FolderTree/styles.js.map +1 -1
- package/dist/esm/components/FolderTree/types.d.ts +23 -0
- package/dist/esm/components/FolderTree/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -15,6 +15,8 @@ export interface DirectoryTreeComponentProps {
|
|
|
15
15
|
directoryTitle?: FolderTreeProps["directoryTitle"];
|
|
16
16
|
moreActions?: FolderTreeProps["moreActions"];
|
|
17
17
|
width?: number | string;
|
|
18
|
+
draggable?: FolderTreeProps["draggable"];
|
|
19
|
+
onDrop?: FolderTreeProps["onDrop"];
|
|
18
20
|
}
|
|
19
21
|
declare const DirectoryTreeComponent: React.FC<DirectoryTreeComponentProps>;
|
|
20
22
|
export default DirectoryTreeComponent;
|
|
@@ -52,7 +52,9 @@ var DirectoryTreeComponent = ({
|
|
|
52
52
|
directoryIcons,
|
|
53
53
|
directoryTitle,
|
|
54
54
|
moreActions,
|
|
55
|
-
width
|
|
55
|
+
width,
|
|
56
|
+
draggable,
|
|
57
|
+
onDrop
|
|
56
58
|
}) => {
|
|
57
59
|
const styles = (0, import_styles.useStyles)();
|
|
58
60
|
const isFolder = (node) => {
|
|
@@ -130,6 +132,8 @@ var DirectoryTreeComponent = ({
|
|
|
130
132
|
title: titleContent,
|
|
131
133
|
icon: getIcon(node),
|
|
132
134
|
isLeaf: !isFolder(node),
|
|
135
|
+
/** 保存原始节点数据用于拖拽回调 */
|
|
136
|
+
_originalNode: node,
|
|
133
137
|
children: node.children ? convertToTreeData(node.children, pathSegments) : void 0
|
|
134
138
|
};
|
|
135
139
|
});
|
|
@@ -137,6 +141,48 @@ var DirectoryTreeComponent = ({
|
|
|
137
141
|
[buildPathSegments, getIcon, moreActions, styles]
|
|
138
142
|
);
|
|
139
143
|
const treeDataConverted = convertToTreeData(treeData);
|
|
144
|
+
const dragMode = draggable === true ? "file" : draggable || false;
|
|
145
|
+
const draggableConfig = dragMode ? {
|
|
146
|
+
icon: false,
|
|
147
|
+
nodeDraggable: (node) => {
|
|
148
|
+
if (dragMode === "file")
|
|
149
|
+
return !!node.isLeaf;
|
|
150
|
+
if (dragMode === "folder")
|
|
151
|
+
return !node.isLeaf;
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
} : false;
|
|
155
|
+
const handleDrop = (0, import_react.useCallback)(
|
|
156
|
+
(info) => {
|
|
157
|
+
if (!onDrop)
|
|
158
|
+
return;
|
|
159
|
+
const dragNode = info.dragNode;
|
|
160
|
+
const dropNode = info.node;
|
|
161
|
+
const originalDragNode = dragNode._originalNode;
|
|
162
|
+
const originalDropNode = dropNode._originalNode;
|
|
163
|
+
if (!originalDragNode || !originalDropNode)
|
|
164
|
+
return;
|
|
165
|
+
const dragKey = String(dragNode.key);
|
|
166
|
+
const dropKey = String(dropNode.key);
|
|
167
|
+
const dragFileName = originalDragNode.path;
|
|
168
|
+
let newPath;
|
|
169
|
+
if (!dropNode.isLeaf && info.dropToGap === false) {
|
|
170
|
+
newPath = `${dropKey}/${dragFileName}`;
|
|
171
|
+
} else {
|
|
172
|
+
const dropParentPath = dropKey.includes("/") ? dropKey.substring(0, dropKey.lastIndexOf("/")) : "";
|
|
173
|
+
newPath = dropParentPath ? `${dropParentPath}/${dragFileName}` : dragFileName;
|
|
174
|
+
}
|
|
175
|
+
onDrop({
|
|
176
|
+
fileName: originalDragNode.title,
|
|
177
|
+
extra: originalDragNode.extra,
|
|
178
|
+
oldPath: dragKey,
|
|
179
|
+
newPath,
|
|
180
|
+
dragNode: originalDragNode,
|
|
181
|
+
dropNode: originalDropNode
|
|
182
|
+
});
|
|
183
|
+
},
|
|
184
|
+
[onDrop]
|
|
185
|
+
);
|
|
140
186
|
const titleNode = directoryTitle === false || directoryTitle === null ? null : typeof directoryTitle === "function" ? directoryTitle() : directoryTitle;
|
|
141
187
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: (0, import_clsx.default)(styles.directoryPanel, className), style: { width }, children: [
|
|
142
188
|
titleNode && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.directoryTitle, children: titleNode }),
|
|
@@ -152,7 +198,9 @@ var DirectoryTreeComponent = ({
|
|
|
152
198
|
blockNode: true,
|
|
153
199
|
showLine,
|
|
154
200
|
switcherIcon,
|
|
155
|
-
defaultExpandAll
|
|
201
|
+
defaultExpandAll,
|
|
202
|
+
draggable: draggableConfig,
|
|
203
|
+
onDrop: dragMode ? handleDrop : void 0
|
|
156
204
|
}
|
|
157
205
|
) })
|
|
158
206
|
] });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/FolderTree/DirectoryTree.tsx"],
|
|
4
|
-
"sourcesContent": ["import React, { useCallback } from \"react\";\nimport { Tree, Dropdown } from \"antd\";\nimport {\n FileOutlined,\n FolderOutlined,\n MoreOutlined,\n} from \"@ant-design/icons\";\nimport type { TreeProps } from \"antd\";\nimport type { DataNode } from \"antd/es/tree\";\nimport clsx from \"clsx\";\nimport type { FolderTreeData, FolderTreeProps } from \"./types\";\nimport { useStyles } from \"./styles\";\n\nconst { DirectoryTree: AntDirectoryTree } = Tree;\n\nexport interface DirectoryTreeComponentProps {\n treeData: FolderTreeData[];\n directoryIcons?: FolderTreeProps[\"directoryIcons\"];\n selectedKeys?: string[];\n expandedKeys?: string[];\n onSelect?: TreeProps[\"onSelect\"];\n onExpand?: TreeProps[\"onExpand\"];\n showLine?: FolderTreeProps[\"showLine\"];\n switcherIcon?: FolderTreeProps[\"switcherIcon\"];\n defaultExpandAll?: boolean;\n className?: string;\n directoryTitle?: FolderTreeProps[\"directoryTitle\"];\n moreActions?: FolderTreeProps[\"moreActions\"];\n width?: number | string;\n}\n\nconst DirectoryTreeComponent: React.FC<DirectoryTreeComponentProps> = ({\n treeData,\n selectedKeys,\n expandedKeys,\n onSelect,\n onExpand,\n showLine = false,\n switcherIcon,\n defaultExpandAll = true,\n className,\n directoryIcons,\n directoryTitle,\n moreActions,\n width,\n}) => {\n const styles = useStyles();\n\n const isFolder = (node: FolderTreeData): boolean => {\n return !!node.children && node.children.length > 0;\n };\n\n const getIcon = useCallback(\n (node: FolderTreeData) => {\n if (directoryIcons === false || directoryIcons === null) {\n return null;\n }\n if (isFolder(node)) {\n const icon = directoryIcons?.directory;\n if (typeof icon === \"function\") return icon();\n return icon || <FolderOutlined />;\n }\n const filePath = node.path.toLowerCase();\n const extension = filePath.split(\".\").pop();\n if (extension) {\n const icon = directoryIcons?.[extension];\n if (icon) return typeof icon === \"function\" ? icon() : icon;\n }\n return <FileOutlined />;\n },\n [directoryIcons]\n );\n\n const buildPathSegments = useCallback(\n (node: FolderTreeData, parentSegments: string[] = []): string[] => {\n if (node.path === \"/\" && parentSegments.length === 0) {\n return [\"/\"];\n }\n return [...parentSegments, node.path].filter((s) => s !== \"\");\n },\n []\n );\n\n const convertToTreeData = useCallback(\n (nodes: FolderTreeData[], parentSegments: string[] = []): DataNode[] => {\n return nodes.map((node) => {\n const pathSegments = buildPathSegments(node, parentSegments);\n const fullPath = pathSegments.join(\"/\").replace(/^\\/+/, \"\");\n\n const titleContent = (\n <span\n className={clsx(\n styles.treeNodeTitle,\n moreActions && styles.treeNodeTitleHover\n )}\n >\n <span>{node.title}</span>\n {moreActions && (\n <Dropdown\n menu={moreActions(node)}\n trigger={[\"click\"]}\n placement=\"bottomRight\"\n >\n <span\n className={clsx(styles.moreIcon, \"folder-tree-more-icon\")}\n onClick={(e) => e.stopPropagation()}\n >\n <MoreOutlined />\n </span>\n </Dropdown>\n )}\n </span>\n );\n\n return {\n ...node,\n key: fullPath,\n path: fullPath,\n pathSegments,\n title: titleContent,\n icon: getIcon(node),\n isLeaf: !isFolder(node),\n children: node.children\n ? convertToTreeData(node.children, pathSegments)\n : undefined,\n };\n });\n },\n [buildPathSegments, getIcon, moreActions, styles]\n );\n\n const treeDataConverted = convertToTreeData(treeData);\n\n const titleNode =\n directoryTitle === false || directoryTitle === null\n ? null\n : typeof directoryTitle === \"function\"\n ? directoryTitle()\n : directoryTitle;\n\n return (\n <div className={clsx(styles.directoryPanel, className)} style={{ width }}>\n {titleNode && <div className={styles.directoryTitle}>{titleNode}</div>}\n <div className={styles.directoryTreeContent}>\n <AntDirectoryTree\n treeData={treeDataConverted}\n selectedKeys={selectedKeys}\n expandedKeys={expandedKeys}\n onSelect={onSelect}\n onExpand={onExpand}\n multiple={false}\n blockNode\n showLine={showLine as any}\n switcherIcon={switcherIcon}\n defaultExpandAll={defaultExpandAll}\n />\n </div>\n </div>\n );\n};\n\nexport default DirectoryTreeComponent;\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAmC;AACnC,kBAA+B;AAC/B,mBAIO;AAGP,kBAAiB;AAEjB,oBAA0B;
|
|
4
|
+
"sourcesContent": ["import React, { useCallback } from \"react\";\nimport { Tree, Dropdown } from \"antd\";\nimport {\n FileOutlined,\n FolderOutlined,\n MoreOutlined,\n} from \"@ant-design/icons\";\nimport type { TreeProps } from \"antd\";\nimport type { DataNode } from \"antd/es/tree\";\nimport clsx from \"clsx\";\nimport type { FolderTreeData, FolderTreeProps } from \"./types\";\nimport { useStyles } from \"./styles\";\n\nconst { DirectoryTree: AntDirectoryTree } = Tree;\n\nexport interface DirectoryTreeComponentProps {\n treeData: FolderTreeData[];\n directoryIcons?: FolderTreeProps[\"directoryIcons\"];\n selectedKeys?: string[];\n expandedKeys?: string[];\n onSelect?: TreeProps[\"onSelect\"];\n onExpand?: TreeProps[\"onExpand\"];\n showLine?: FolderTreeProps[\"showLine\"];\n switcherIcon?: FolderTreeProps[\"switcherIcon\"];\n defaultExpandAll?: boolean;\n className?: string;\n directoryTitle?: FolderTreeProps[\"directoryTitle\"];\n moreActions?: FolderTreeProps[\"moreActions\"];\n width?: number | string;\n draggable?: FolderTreeProps[\"draggable\"];\n onDrop?: FolderTreeProps[\"onDrop\"];\n}\n\nconst DirectoryTreeComponent: React.FC<DirectoryTreeComponentProps> = ({\n treeData,\n selectedKeys,\n expandedKeys,\n onSelect,\n onExpand,\n showLine = false,\n switcherIcon,\n defaultExpandAll = true,\n className,\n directoryIcons,\n directoryTitle,\n moreActions,\n width,\n draggable,\n onDrop,\n}) => {\n const styles = useStyles();\n\n const isFolder = (node: FolderTreeData): boolean => {\n return !!node.children && node.children.length > 0;\n };\n\n const getIcon = useCallback(\n (node: FolderTreeData) => {\n if (directoryIcons === false || directoryIcons === null) {\n return null;\n }\n if (isFolder(node)) {\n const icon = directoryIcons?.directory;\n if (typeof icon === \"function\") return icon();\n return icon || <FolderOutlined />;\n }\n const filePath = node.path.toLowerCase();\n const extension = filePath.split(\".\").pop();\n if (extension) {\n const icon = directoryIcons?.[extension];\n if (icon) return typeof icon === \"function\" ? icon() : icon;\n }\n return <FileOutlined />;\n },\n [directoryIcons]\n );\n\n const buildPathSegments = useCallback(\n (node: FolderTreeData, parentSegments: string[] = []): string[] => {\n if (node.path === \"/\" && parentSegments.length === 0) {\n return [\"/\"];\n }\n return [...parentSegments, node.path].filter((s) => s !== \"\");\n },\n []\n );\n\n const convertToTreeData = useCallback(\n (nodes: FolderTreeData[], parentSegments: string[] = []): DataNode[] => {\n return nodes.map((node) => {\n const pathSegments = buildPathSegments(node, parentSegments);\n const fullPath = pathSegments.join(\"/\").replace(/^\\/+/, \"\");\n\n const titleContent = (\n <span\n className={clsx(\n styles.treeNodeTitle,\n moreActions && styles.treeNodeTitleHover\n )}\n >\n <span>{node.title}</span>\n {moreActions && (\n <Dropdown\n menu={moreActions(node)}\n trigger={[\"click\"]}\n placement=\"bottomRight\"\n >\n <span\n className={clsx(styles.moreIcon, \"folder-tree-more-icon\")}\n onClick={(e) => e.stopPropagation()}\n >\n <MoreOutlined />\n </span>\n </Dropdown>\n )}\n </span>\n );\n\n return {\n ...node,\n key: fullPath,\n path: fullPath,\n pathSegments,\n title: titleContent,\n icon: getIcon(node),\n isLeaf: !isFolder(node),\n /** 保存原始节点数据用于拖拽回调 */\n _originalNode: node,\n children: node.children\n ? convertToTreeData(node.children, pathSegments)\n : undefined,\n };\n });\n },\n [buildPathSegments, getIcon, moreActions, styles]\n );\n\n const treeDataConverted = convertToTreeData(treeData);\n\n // ====== 拖拽配置 ======\n const dragMode = draggable === true ? \"file\" : draggable || false;\n\n const draggableConfig = dragMode\n ? {\n icon: false,\n nodeDraggable: (node: DataNode) => {\n if (dragMode === \"file\") return !!node.isLeaf;\n if (dragMode === \"folder\") return !node.isLeaf;\n return true; // 'all'\n },\n }\n : false;\n\n const handleDrop: TreeProps[\"onDrop\"] = useCallback(\n (info: Parameters<NonNullable<TreeProps[\"onDrop\"]>>[0]) => {\n if (!onDrop) return;\n\n const dragNode = info.dragNode as DataNode & { _originalNode?: FolderTreeData };\n const dropNode = info.node as DataNode & { _originalNode?: FolderTreeData };\n\n const originalDragNode = dragNode._originalNode;\n const originalDropNode = dropNode._originalNode;\n if (!originalDragNode || !originalDropNode) return;\n\n // dragNode 的原始完整路径\n const dragKey = String(dragNode.key);\n // 计算新路径:如果 drop 到文件夹上(非叶子),新路径为 dropNode路径/dragNode文件名\n // 如果 drop 到文件旁边,新路径为 dropNode 的父路径/dragNode文件名\n const dropKey = String(dropNode.key);\n const dragFileName = originalDragNode.path;\n let newPath: string;\n\n if (!dropNode.isLeaf && info.dropToGap === false) {\n // 拖入文件夹内部\n newPath = `${dropKey}/${dragFileName}`;\n } else {\n // 拖到节点旁边(同级)\n const dropParentPath = dropKey.includes(\"/\")\n ? dropKey.substring(0, dropKey.lastIndexOf(\"/\"))\n : \"\";\n newPath = dropParentPath\n ? `${dropParentPath}/${dragFileName}`\n : dragFileName;\n }\n\n onDrop({\n fileName: originalDragNode.title,\n extra: originalDragNode.extra,\n oldPath: dragKey,\n newPath,\n dragNode: originalDragNode,\n dropNode: originalDropNode,\n });\n },\n [onDrop],\n );\n\n const titleNode =\n directoryTitle === false || directoryTitle === null\n ? null\n : typeof directoryTitle === \"function\"\n ? directoryTitle()\n : directoryTitle;\n\n return (\n <div className={clsx(styles.directoryPanel, className)} style={{ width }}>\n {titleNode && <div className={styles.directoryTitle}>{titleNode}</div>}\n <div className={styles.directoryTreeContent}>\n <AntDirectoryTree\n treeData={treeDataConverted}\n selectedKeys={selectedKeys}\n expandedKeys={expandedKeys}\n onSelect={onSelect}\n onExpand={onExpand}\n multiple={false}\n blockNode\n showLine={showLine as any}\n switcherIcon={switcherIcon}\n defaultExpandAll={defaultExpandAll}\n draggable={draggableConfig}\n onDrop={dragMode ? handleDrop : undefined}\n />\n </div>\n </div>\n );\n};\n\nexport default DirectoryTreeComponent;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["clsx"]
|
|
7
7
|
}
|
|
@@ -63,7 +63,9 @@ var FolderTree = (props) => {
|
|
|
63
63
|
moreActions,
|
|
64
64
|
showLine,
|
|
65
65
|
switcherIcon,
|
|
66
|
-
showPreview = true
|
|
66
|
+
showPreview = true,
|
|
67
|
+
draggable,
|
|
68
|
+
onDrop
|
|
67
69
|
} = props;
|
|
68
70
|
const styles = (0, import_styles.useStyles)();
|
|
69
71
|
const findNodeAndValidate = (0, import_react.useCallback)(
|
|
@@ -225,7 +227,9 @@ var FolderTree = (props) => {
|
|
|
225
227
|
moreActions,
|
|
226
228
|
showLine,
|
|
227
229
|
switcherIcon,
|
|
228
|
-
width: directoryTreeWidth
|
|
230
|
+
width: directoryTreeWidth,
|
|
231
|
+
draggable,
|
|
232
|
+
onDrop
|
|
229
233
|
}
|
|
230
234
|
),
|
|
231
235
|
showPreview && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/FolderTree/index.tsx"],
|
|
4
|
-
"sourcesContent": ["import React, { useCallback, useEffect, useState } from \"react\";\nimport type { TreeProps } from \"antd\";\nimport clsx from \"clsx\";\nimport type { FolderTreeData, FolderTreeProps } from \"./types\";\nimport DirectoryTreeComponent from \"./DirectoryTree\";\nimport FilePreview from \"./FilePreview\";\nimport { useStyles } from \"./styles\";\n\nexport type {\n FolderTreeData,\n FolderTreeProps,\n FileContentService,\n} from \"./types\";\n\nconst FolderTree: React.FC<FolderTreeProps> = (props) => {\n const {\n className,\n style,\n treeData,\n directoryIcons,\n previewRender,\n directoryTitle,\n previewTitle,\n selectable = true,\n defaultSelectedFile,\n defaultExpandAll = true,\n selectedFile,\n onSelectedFileChange,\n directoryTreeWidth = 280,\n emptyRender,\n defaultExpandedPaths,\n expandedPaths,\n onExpandedPathsChange,\n onFileClick,\n onFolderClick,\n fileContentService,\n moreActions,\n showLine,\n switcherIcon,\n showPreview = true,\n } = props;\n\n const styles = useStyles();\n\n // ====== 工具函数 ======\n const findNodeAndValidate = useCallback(\n (\n path: string | string[],\n validateAsFile = false,\n ): { node: FolderTreeData | undefined; isValid: boolean } => {\n if (!path) return { node: undefined, isValid: false };\n const segments = Array.isArray(path)\n ? path.filter(Boolean)\n : path.split(\"/\").filter(Boolean);\n if (segments.length === 0) return { node: undefined, isValid: false };\n\n const findNode = (\n nodes: FolderTreeData[],\n index = 0,\n ): FolderTreeData | undefined => {\n if (index >= segments.length) return undefined;\n const currentSegment = segments[index];\n for (const node of nodes) {\n if (node.path === currentSegment) {\n return index === segments.length - 1\n ? node\n : node.children\n ? findNode(node.children, index + 1)\n : undefined;\n }\n }\n return undefined;\n };\n\n const node = findNode(treeData);\n const isValid = validateAsFile\n ? !!node && (!node?.children || node.children.length === 0)\n : !!node;\n return { node, isValid };\n },\n [treeData],\n );\n\n const isValidSelectedFile = (filePath?: string[]): boolean =>\n !!(\n filePath &&\n filePath.length > 0 &&\n findNodeAndValidate(filePath, true).isValid\n );\n\n // ====== State ======\n const [selectedFileState, setSelectedFileState] = useState<string[]>(() =>\n isValidSelectedFile(selectedFile || defaultSelectedFile)\n ? selectedFile || defaultSelectedFile || []\n : [],\n );\n const [expandedPathsState, setExpandedPaths] = useState<string[] | undefined>(\n expandedPaths || defaultExpandedPaths,\n );\n const [validSelectedFile, setValidSelectedFile] = useState<boolean>(\n isValidSelectedFile(selectedFile || defaultSelectedFile),\n );\n const [fileContent, setFileContent] = useState<string>(\"\");\n const [loadingContent, setLoadingContent] = useState<boolean>(false);\n\n // 受控模式同步\n useEffect(() => {\n if (selectedFile !== undefined) {\n setSelectedFileState(selectedFile);\n setValidSelectedFile(isValidSelectedFile(selectedFile));\n }\n }, [selectedFile, treeData]);\n\n useEffect(() => {\n if (expandedPaths !== undefined) {\n setExpandedPaths(expandedPaths);\n }\n }, [expandedPaths]);\n\n // ====== 加载文件内容 ======\n useEffect(() => {\n const loadContent = async () => {\n if (!validSelectedFile || selectedFileState.length === 0) {\n setFileContent(\"\");\n setLoadingContent(false);\n return;\n }\n\n const filePath = selectedFileState.join(\"/\");\n const segments = filePath.split(\"/\").filter((s) => s !== \"\");\n const { node } = findNodeAndValidate(segments);\n\n if (fileContentService) {\n setLoadingContent(true);\n try {\n const content = await fileContentService.loadFileContent(filePath);\n setFileContent(content);\n } catch (error) {\n setFileContent(\n `// 加载错误: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n );\n } finally {\n setLoadingContent(false);\n }\n } else if (node?.content) {\n setFileContent(node.content);\n setLoadingContent(false);\n } else {\n setFileContent(\"\");\n setLoadingContent(false);\n }\n };\n\n loadContent();\n }, [\n validSelectedFile,\n selectedFileState,\n treeData,\n fileContentService,\n findNodeAndValidate,\n ]);\n\n // ====== 事件处理 ======\n const handleSelect: TreeProps[\"onSelect\"] = (_keys, info) => {\n const keys = _keys as string[];\n const nodes = Array.isArray(info.selectedNodes)\n ? info.selectedNodes\n : [info.selectedNodes];\n\n const isFolder = nodes.some((node) => !node.isLeaf);\n if (isFolder) {\n if (nodes.length === 1) {\n const node = nodes[0] as unknown as FolderTreeData;\n onFolderClick?.(node.path, node.extra);\n }\n return;\n }\n\n const pathArray = keys[0]?.split(\"/\").filter(Boolean) || [];\n if (pathArray.length === 0) return;\n\n // 从原始 treeData 中查找节点,避免拿到 antd 包装后的 JSX title\n const { node: originalNode } = findNodeAndValidate(pathArray);\n const fileName = originalNode?.title;\n const nodeContent = originalNode?.content;\n\n onSelectedFileChange?.({\n path: pathArray,\n title: fileName,\n content: nodeContent,\n extra: originalNode?.extra,\n });\n\n const isControlled = selectedFile !== undefined;\n if (!isControlled) {\n setValidSelectedFile(true);\n setSelectedFileState(pathArray);\n }\n\n if (originalNode) {\n onFileClick?.(\n keys[0],\n originalNode.content,\n originalNode.extra,\n );\n }\n };\n\n const handleExpand: TreeProps[\"onExpand\"] = (keys) => {\n const newPaths = keys as string[];\n setExpandedPaths(newPaths);\n onExpandedPathsChange?.(newPaths);\n };\n\n return (\n <div\n className={clsx(\n styles.container,\n !showPreview && styles.containerNoPreview,\n className,\n )}\n style={{\n ...style,\n ...(style?.background\n ? ({\n \"--folder-tree-directory-bg\": style.background,\n } as React.CSSProperties)\n : {}),\n ...(style?.backgroundColor\n ? ({\n \"--folder-tree-directory-bg\": style.backgroundColor,\n } as React.CSSProperties)\n : {}),\n }}\n >\n <DirectoryTreeComponent\n treeData={treeData}\n directoryIcons={directoryIcons}\n selectedKeys={\n selectable && selectedFileState && validSelectedFile\n ? [selectedFileState.join(\"/\")]\n : []\n }\n expandedKeys={expandedPathsState}\n onSelect={handleSelect}\n onExpand={handleExpand}\n defaultExpandAll={defaultExpandAll}\n directoryTitle={directoryTitle}\n moreActions={moreActions}\n showLine={showLine}\n switcherIcon={switcherIcon}\n width={directoryTreeWidth}\n />\n {showPreview && (\n <FilePreview\n selectedFile={validSelectedFile ? selectedFileState : []}\n fileContent={fileContent}\n loading={loadingContent}\n previewTitle={previewTitle}\n previewRender={previewRender}\n emptyRender={emptyRender}\n getFileNode={(path) => {\n if (!path || path.length === 0) return undefined;\n const { node } = findNodeAndValidate(path);\n return node\n ? { title: node.title, path: node.path, content: node.content }\n : undefined;\n }}\n />\n )}\n </div>\n );\n};\n\nexport default FolderTree;\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAwD;AAExD,kBAAiB;AAEjB,2BAAmC;AACnC,yBAAwB;AACxB,oBAA0B;
|
|
4
|
+
"sourcesContent": ["import React, { useCallback, useEffect, useState } from \"react\";\nimport type { TreeProps } from \"antd\";\nimport clsx from \"clsx\";\nimport type { FolderTreeData, FolderTreeProps } from \"./types\";\nimport DirectoryTreeComponent from \"./DirectoryTree\";\nimport FilePreview from \"./FilePreview\";\nimport { useStyles } from \"./styles\";\n\nexport type {\n FolderTreeData,\n FolderTreeProps,\n FileContentService,\n} from \"./types\";\n\nconst FolderTree: React.FC<FolderTreeProps> = (props) => {\n const {\n className,\n style,\n treeData,\n directoryIcons,\n previewRender,\n directoryTitle,\n previewTitle,\n selectable = true,\n defaultSelectedFile,\n defaultExpandAll = true,\n selectedFile,\n onSelectedFileChange,\n directoryTreeWidth = 280,\n emptyRender,\n defaultExpandedPaths,\n expandedPaths,\n onExpandedPathsChange,\n onFileClick,\n onFolderClick,\n fileContentService,\n moreActions,\n showLine,\n switcherIcon,\n showPreview = true,\n draggable,\n onDrop,\n } = props;\n\n const styles = useStyles();\n\n // ====== 工具函数 ======\n const findNodeAndValidate = useCallback(\n (\n path: string | string[],\n validateAsFile = false,\n ): { node: FolderTreeData | undefined; isValid: boolean } => {\n if (!path) return { node: undefined, isValid: false };\n const segments = Array.isArray(path)\n ? path.filter(Boolean)\n : path.split(\"/\").filter(Boolean);\n if (segments.length === 0) return { node: undefined, isValid: false };\n\n const findNode = (\n nodes: FolderTreeData[],\n index = 0,\n ): FolderTreeData | undefined => {\n if (index >= segments.length) return undefined;\n const currentSegment = segments[index];\n for (const node of nodes) {\n if (node.path === currentSegment) {\n return index === segments.length - 1\n ? node\n : node.children\n ? findNode(node.children, index + 1)\n : undefined;\n }\n }\n return undefined;\n };\n\n const node = findNode(treeData);\n const isValid = validateAsFile\n ? !!node && (!node?.children || node.children.length === 0)\n : !!node;\n return { node, isValid };\n },\n [treeData],\n );\n\n const isValidSelectedFile = (filePath?: string[]): boolean =>\n !!(\n filePath &&\n filePath.length > 0 &&\n findNodeAndValidate(filePath, true).isValid\n );\n\n // ====== State ======\n const [selectedFileState, setSelectedFileState] = useState<string[]>(() =>\n isValidSelectedFile(selectedFile || defaultSelectedFile)\n ? selectedFile || defaultSelectedFile || []\n : [],\n );\n const [expandedPathsState, setExpandedPaths] = useState<string[] | undefined>(\n expandedPaths || defaultExpandedPaths,\n );\n const [validSelectedFile, setValidSelectedFile] = useState<boolean>(\n isValidSelectedFile(selectedFile || defaultSelectedFile),\n );\n const [fileContent, setFileContent] = useState<string>(\"\");\n const [loadingContent, setLoadingContent] = useState<boolean>(false);\n\n // 受控模式同步\n useEffect(() => {\n if (selectedFile !== undefined) {\n setSelectedFileState(selectedFile);\n setValidSelectedFile(isValidSelectedFile(selectedFile));\n }\n }, [selectedFile, treeData]);\n\n useEffect(() => {\n if (expandedPaths !== undefined) {\n setExpandedPaths(expandedPaths);\n }\n }, [expandedPaths]);\n\n // ====== 加载文件内容 ======\n useEffect(() => {\n const loadContent = async () => {\n if (!validSelectedFile || selectedFileState.length === 0) {\n setFileContent(\"\");\n setLoadingContent(false);\n return;\n }\n\n const filePath = selectedFileState.join(\"/\");\n const segments = filePath.split(\"/\").filter((s) => s !== \"\");\n const { node } = findNodeAndValidate(segments);\n\n if (fileContentService) {\n setLoadingContent(true);\n try {\n const content = await fileContentService.loadFileContent(filePath);\n setFileContent(content);\n } catch (error) {\n setFileContent(\n `// 加载错误: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n );\n } finally {\n setLoadingContent(false);\n }\n } else if (node?.content) {\n setFileContent(node.content);\n setLoadingContent(false);\n } else {\n setFileContent(\"\");\n setLoadingContent(false);\n }\n };\n\n loadContent();\n }, [\n validSelectedFile,\n selectedFileState,\n treeData,\n fileContentService,\n findNodeAndValidate,\n ]);\n\n // ====== 事件处理 ======\n const handleSelect: TreeProps[\"onSelect\"] = (_keys, info) => {\n const keys = _keys as string[];\n const nodes = Array.isArray(info.selectedNodes)\n ? info.selectedNodes\n : [info.selectedNodes];\n\n const isFolder = nodes.some((node) => !node.isLeaf);\n if (isFolder) {\n if (nodes.length === 1) {\n const node = nodes[0] as unknown as FolderTreeData;\n onFolderClick?.(node.path, node.extra);\n }\n return;\n }\n\n const pathArray = keys[0]?.split(\"/\").filter(Boolean) || [];\n if (pathArray.length === 0) return;\n\n // 从原始 treeData 中查找节点,避免拿到 antd 包装后的 JSX title\n const { node: originalNode } = findNodeAndValidate(pathArray);\n const fileName = originalNode?.title;\n const nodeContent = originalNode?.content;\n\n onSelectedFileChange?.({\n path: pathArray,\n title: fileName,\n content: nodeContent,\n extra: originalNode?.extra,\n });\n\n const isControlled = selectedFile !== undefined;\n if (!isControlled) {\n setValidSelectedFile(true);\n setSelectedFileState(pathArray);\n }\n\n if (originalNode) {\n onFileClick?.(\n keys[0],\n originalNode.content,\n originalNode.extra,\n );\n }\n };\n\n const handleExpand: TreeProps[\"onExpand\"] = (keys) => {\n const newPaths = keys as string[];\n setExpandedPaths(newPaths);\n onExpandedPathsChange?.(newPaths);\n };\n\n return (\n <div\n className={clsx(\n styles.container,\n !showPreview && styles.containerNoPreview,\n className,\n )}\n style={{\n ...style,\n ...(style?.background\n ? ({\n \"--folder-tree-directory-bg\": style.background,\n } as React.CSSProperties)\n : {}),\n ...(style?.backgroundColor\n ? ({\n \"--folder-tree-directory-bg\": style.backgroundColor,\n } as React.CSSProperties)\n : {}),\n }}\n >\n <DirectoryTreeComponent\n treeData={treeData}\n directoryIcons={directoryIcons}\n selectedKeys={\n selectable && selectedFileState && validSelectedFile\n ? [selectedFileState.join(\"/\")]\n : []\n }\n expandedKeys={expandedPathsState}\n onSelect={handleSelect}\n onExpand={handleExpand}\n defaultExpandAll={defaultExpandAll}\n directoryTitle={directoryTitle}\n moreActions={moreActions}\n showLine={showLine}\n switcherIcon={switcherIcon}\n width={directoryTreeWidth}\n draggable={draggable}\n onDrop={onDrop}\n />\n {showPreview && (\n <FilePreview\n selectedFile={validSelectedFile ? selectedFileState : []}\n fileContent={fileContent}\n loading={loadingContent}\n previewTitle={previewTitle}\n previewRender={previewRender}\n emptyRender={emptyRender}\n getFileNode={(path) => {\n if (!path || path.length === 0) return undefined;\n const { node } = findNodeAndValidate(path);\n return node\n ? { title: node.title, path: node.path, content: node.content }\n : undefined;\n }}\n />\n )}\n </div>\n );\n};\n\nexport default FolderTree;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["node", "clsx", "DirectoryTreeComponent", "FilePreview"]
|
|
7
7
|
}
|
|
@@ -79,6 +79,22 @@ var useStyles = (0, import_common.withBasicStyles)(() => ({
|
|
|
79
79
|
border-radius: 4px;
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
+
/* 拖拽指示线:蓝色虚线 */
|
|
83
|
+
.ant-tree .ant-tree-drop-indicator {
|
|
84
|
+
background: transparent !important;
|
|
85
|
+
border: 1px dashed #1677ff;
|
|
86
|
+
height: 2px;
|
|
87
|
+
}
|
|
88
|
+
/* 拖拽悬停目标:蓝色虚线边框 */
|
|
89
|
+
.ant-tree .ant-tree-treenode.drag-over > .ant-tree-node-content-wrapper {
|
|
90
|
+
outline: 1px dashed #1677ff;
|
|
91
|
+
outline-offset: -1px;
|
|
92
|
+
border-radius: 4px;
|
|
93
|
+
}
|
|
94
|
+
/* 拖拽中的节点半透明 */
|
|
95
|
+
.ant-tree .ant-tree-treenode-dragging {
|
|
96
|
+
opacity: 0.4;
|
|
97
|
+
}
|
|
82
98
|
`,
|
|
83
99
|
previewPanel: import_css.css`
|
|
84
100
|
flex: 1;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/FolderTree/styles.tsx"],
|
|
4
|
-
"sourcesContent": ["import { css } from \"@emotion/css\";\nimport { withBasicStyles } from \"@/styles/common\";\n\nexport const useStyles = withBasicStyles(() => ({\n container: css`\n display: flex;\n width: 100%;\n height: 500px;\n border: 1px solid #e8e8e8;\n border-radius: 8px;\n overflow: hidden;\n background: #fff;\n `,\n containerNoPreview: css`\n height: auto;\n border: none;\n border-radius: 0;\n & > *:first-child {\n border-right: none;\n }\n `,\n directoryPanel: css`\n height: 100%;\n overflow: auto;\n border-right: 1px solid #e8e8e8;\n background: var(--folder-tree-directory-bg, #fafafa);\n `,\n directoryTitle: css`\n padding: 12px 16px;\n font-weight: 600;\n font-size: 14px;\n border-bottom: 1px solid #e8e8e8;\n color: #333;\n `,\n directoryTreeContent: css`\n padding: 4px 0;\n .ant-tree {\n background: transparent;\n }\n .ant-tree-switcher {\n margin-right: 0;\n }\n .ant-tree .ant-tree-node-content-wrapper {\n display: inline-flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n padding-left: 0;\n }\n .ant-tree .ant-tree-title {\n flex: 1;\n min-width: 0;\n }\n .ant-tree-directory .ant-tree-treenode {\n &::before {\n border-radius: 4px;\n }\n }\n `,\n previewPanel: css`\n flex: 1;\n height: 100%;\n overflow: auto;\n display: flex;\n flex-direction: column;\n `,\n previewTitle: css`\n padding: 10px 16px;\n font-size: 13px;\n font-weight: 500;\n border-bottom: 1px solid #e8e8e8;\n display: flex;\n align-items: center;\n justify-content: space-between;\n color: #333;\n background: #fff;\n `,\n previewContent: css`\n flex: 1;\n overflow: auto;\n padding: 16px;\n font-size: 13px;\n line-height: 1.6;\n `,\n emptyContainer: css`\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n `,\n loadingContainer: css`\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n `,\n treeNodeTitle: css`\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding-right: 4px;\n `,\n moreIcon: css`\n opacity: 0;\n cursor: pointer;\n padding: 2px 4px;\n border-radius: 4px;\n color: #999;\n font-size: 14px;\n transition: all 0.2s;\n &:hover {\n color: #333;\n background: rgba(0, 0, 0, 0.04);\n }\n `,\n treeNodeTitleHover: css`\n &:hover .folder-tree-more-icon {\n opacity: 1;\n }\n `,\n copyBtn: css`\n cursor: pointer;\n color: #999;\n font-size: 14px;\n &:hover {\n color: #1677ff;\n }\n `,\n}));\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAoB;AACpB,oBAAgC;AAEzB,IAAM,gBAAY,+BAAgB,OAAO;AAAA,EAC9C,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASX,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQpB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhB,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import { css } from \"@emotion/css\";\nimport { withBasicStyles } from \"@/styles/common\";\n\nexport const useStyles = withBasicStyles(() => ({\n container: css`\n display: flex;\n width: 100%;\n height: 500px;\n border: 1px solid #e8e8e8;\n border-radius: 8px;\n overflow: hidden;\n background: #fff;\n `,\n containerNoPreview: css`\n height: auto;\n border: none;\n border-radius: 0;\n & > *:first-child {\n border-right: none;\n }\n `,\n directoryPanel: css`\n height: 100%;\n overflow: auto;\n border-right: 1px solid #e8e8e8;\n background: var(--folder-tree-directory-bg, #fafafa);\n `,\n directoryTitle: css`\n padding: 12px 16px;\n font-weight: 600;\n font-size: 14px;\n border-bottom: 1px solid #e8e8e8;\n color: #333;\n `,\n directoryTreeContent: css`\n padding: 4px 0;\n .ant-tree {\n background: transparent;\n }\n .ant-tree-switcher {\n margin-right: 0;\n }\n .ant-tree .ant-tree-node-content-wrapper {\n display: inline-flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n padding-left: 0;\n }\n .ant-tree .ant-tree-title {\n flex: 1;\n min-width: 0;\n }\n .ant-tree-directory .ant-tree-treenode {\n &::before {\n border-radius: 4px;\n }\n }\n /* 拖拽指示线:蓝色虚线 */\n .ant-tree .ant-tree-drop-indicator {\n background: transparent !important;\n border: 1px dashed #1677ff;\n height: 2px;\n }\n /* 拖拽悬停目标:蓝色虚线边框 */\n .ant-tree .ant-tree-treenode.drag-over > .ant-tree-node-content-wrapper {\n outline: 1px dashed #1677ff;\n outline-offset: -1px;\n border-radius: 4px;\n }\n /* 拖拽中的节点半透明 */\n .ant-tree .ant-tree-treenode-dragging {\n opacity: 0.4;\n }\n `,\n previewPanel: css`\n flex: 1;\n height: 100%;\n overflow: auto;\n display: flex;\n flex-direction: column;\n `,\n previewTitle: css`\n padding: 10px 16px;\n font-size: 13px;\n font-weight: 500;\n border-bottom: 1px solid #e8e8e8;\n display: flex;\n align-items: center;\n justify-content: space-between;\n color: #333;\n background: #fff;\n `,\n previewContent: css`\n flex: 1;\n overflow: auto;\n padding: 16px;\n font-size: 13px;\n line-height: 1.6;\n `,\n emptyContainer: css`\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n `,\n loadingContainer: css`\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n `,\n treeNodeTitle: css`\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding-right: 4px;\n `,\n moreIcon: css`\n opacity: 0;\n cursor: pointer;\n padding: 2px 4px;\n border-radius: 4px;\n color: #999;\n font-size: 14px;\n transition: all 0.2s;\n &:hover {\n color: #333;\n background: rgba(0, 0, 0, 0.04);\n }\n `,\n treeNodeTitleHover: css`\n &:hover .folder-tree-more-icon {\n opacity: 1;\n }\n `,\n copyBtn: css`\n cursor: pointer;\n color: #999;\n font-size: 14px;\n &:hover {\n color: #1677ff;\n }\n `,\n}));\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAoB;AACpB,oBAAgC;AAEzB,IAAM,gBAAY,+BAAgB,OAAO;AAAA,EAC9C,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASX,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQpB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhB,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyCtB,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWd,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlB,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMf,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaV,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKpB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQX,EAAE;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -80,4 +80,27 @@ export interface FolderTreeProps {
|
|
|
80
80
|
switcherIcon?: React.ReactNode | ((props: any) => React.ReactNode);
|
|
81
81
|
/** 是否显示文件预览面板,默认 true */
|
|
82
82
|
showPreview?: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* 拖拽模式
|
|
85
|
+
* - true | 'file': 只有文件(叶子节点)可拖拽
|
|
86
|
+
* - 'folder': 只有文件夹可拖拽
|
|
87
|
+
* - 'all': 文件和文件夹都可拖拽
|
|
88
|
+
* - false | undefined: 禁用拖拽
|
|
89
|
+
*/
|
|
90
|
+
draggable?: boolean | "file" | "folder" | "all";
|
|
91
|
+
/** 拖拽完成回调 */
|
|
92
|
+
onDrop?: (info: {
|
|
93
|
+
/** 被拖拽节点的文件名 */
|
|
94
|
+
fileName: React.ReactNode;
|
|
95
|
+
/** 被拖拽节点的 extra 数据 */
|
|
96
|
+
extra: any;
|
|
97
|
+
/** 拖拽前的完整路径 */
|
|
98
|
+
oldPath: string;
|
|
99
|
+
/** 拖拽完成后的新路径 */
|
|
100
|
+
newPath: string;
|
|
101
|
+
/** 被拖拽的节点 */
|
|
102
|
+
dragNode: FolderTreeData;
|
|
103
|
+
/** 目标节点 */
|
|
104
|
+
dropNode: FolderTreeData;
|
|
105
|
+
}) => void;
|
|
83
106
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/FolderTree/types.ts"],
|
|
4
|
-
"sourcesContent": ["import type { DropdownProps } from \"antd\";\nimport type React from \"react\";\n\n/** 文件树节点数据 */\nexport interface FolderTreeData<T = any> {\n title: React.ReactNode;\n path: string;\n content?: string;\n extra?: T;\n children?: FolderTreeData<T>[];\n}\n\n/** 文件内容加载服务 */\nexport interface FileContentService {\n loadFileContent(filePath: string): Promise<string>;\n}\n\n/** FolderTree 组件属性 */\nexport interface FolderTreeProps {\n /** 自定义类名 */\n className?: string;\n /** 自定义样式 */\n style?: React.CSSProperties;\n\n /** 树形数据 */\n treeData: FolderTreeData[];\n\n /** 自定义文件/文件夹图标,false 禁用图标 */\n directoryIcons?:\n | false\n | Record<\"directory\" | string, React.ReactNode | (() => React.ReactNode)>;\n\n /** 是否可选中文件 */\n selectable?: boolean;\n /** 受控:当前选中的文件路径 */\n selectedFile?: string[];\n /** 默认选中的文件路径 */\n defaultSelectedFile?: string[];\n /** 选中文件变化回调 */\n onSelectedFileChange?: (file: {\n path: string[];\n title?: React.ReactNode;\n content?: string;\n extra?: any;\n }) => void;\n\n /** 受控:展开的路径 */\n expandedPaths?: string[];\n /** 默认展开的路径 */\n defaultExpandedPaths?: string[];\n /** 默认是否展开所有节点 */\n defaultExpandAll?: boolean;\n /** 展开路径变化回调 */\n onExpandedPathsChange?: (paths: string[]) => void;\n\n /** 目录树面板宽度 */\n directoryTreeWidth?: number | string;\n\n /** 文件内容加载服务 */\n fileContentService?: FileContentService;\n\n /** 空状态渲染 */\n emptyRender?: false | React.ReactNode | (() => React.ReactNode);\n /** 自定义文件预览渲染 */\n previewRender?:\n | React.ReactNode\n | ((\n file: {\n content?: string;\n path: string[];\n title?: React.ReactNode;\n language: string;\n },\n info: { originNode: React.ReactNode },\n ) => React.ReactNode);\n\n /** 自定义目录标题 */\n directoryTitle?: false | React.ReactNode | (() => React.ReactNode);\n /** 自定义预览标题 */\n previewTitle?:\n | false\n | React.ReactNode\n | ((info: {\n title: React.ReactNode;\n path: string[];\n content: string;\n }) => React.ReactNode);\n\n /** 文件点击回调 */\n onFileClick?: (filePath: string, content?: string, extra?: any) => void;\n /** 文件夹点击回调 */\n onFolderClick?: (folderPath: string, extra?: any) => void;\n\n /** 更多操作菜单,传入节点返回 Dropdown menu 配置 */\n moreActions?: (node: FolderTreeData) => DropdownProps[\"menu\"];\n\n /** 是否显示连接线 */\n showLine?: boolean | { showLeafIcon?: boolean | React.ReactNode };\n /** 自定义展开/收起图标 */\n switcherIcon?: React.ReactNode | ((props: any) => React.ReactNode);\n\n /** 是否显示文件预览面板,默认 true */\n showPreview?: boolean;\n}\n"],
|
|
4
|
+
"sourcesContent": ["import type { DropdownProps } from \"antd\";\nimport type React from \"react\";\n\n/** 文件树节点数据 */\nexport interface FolderTreeData<T = any> {\n title: React.ReactNode;\n path: string;\n content?: string;\n extra?: T;\n children?: FolderTreeData<T>[];\n}\n\n/** 文件内容加载服务 */\nexport interface FileContentService {\n loadFileContent(filePath: string): Promise<string>;\n}\n\n/** FolderTree 组件属性 */\nexport interface FolderTreeProps {\n /** 自定义类名 */\n className?: string;\n /** 自定义样式 */\n style?: React.CSSProperties;\n\n /** 树形数据 */\n treeData: FolderTreeData[];\n\n /** 自定义文件/文件夹图标,false 禁用图标 */\n directoryIcons?:\n | false\n | Record<\"directory\" | string, React.ReactNode | (() => React.ReactNode)>;\n\n /** 是否可选中文件 */\n selectable?: boolean;\n /** 受控:当前选中的文件路径 */\n selectedFile?: string[];\n /** 默认选中的文件路径 */\n defaultSelectedFile?: string[];\n /** 选中文件变化回调 */\n onSelectedFileChange?: (file: {\n path: string[];\n title?: React.ReactNode;\n content?: string;\n extra?: any;\n }) => void;\n\n /** 受控:展开的路径 */\n expandedPaths?: string[];\n /** 默认展开的路径 */\n defaultExpandedPaths?: string[];\n /** 默认是否展开所有节点 */\n defaultExpandAll?: boolean;\n /** 展开路径变化回调 */\n onExpandedPathsChange?: (paths: string[]) => void;\n\n /** 目录树面板宽度 */\n directoryTreeWidth?: number | string;\n\n /** 文件内容加载服务 */\n fileContentService?: FileContentService;\n\n /** 空状态渲染 */\n emptyRender?: false | React.ReactNode | (() => React.ReactNode);\n /** 自定义文件预览渲染 */\n previewRender?:\n | React.ReactNode\n | ((\n file: {\n content?: string;\n path: string[];\n title?: React.ReactNode;\n language: string;\n },\n info: { originNode: React.ReactNode },\n ) => React.ReactNode);\n\n /** 自定义目录标题 */\n directoryTitle?: false | React.ReactNode | (() => React.ReactNode);\n /** 自定义预览标题 */\n previewTitle?:\n | false\n | React.ReactNode\n | ((info: {\n title: React.ReactNode;\n path: string[];\n content: string;\n }) => React.ReactNode);\n\n /** 文件点击回调 */\n onFileClick?: (filePath: string, content?: string, extra?: any) => void;\n /** 文件夹点击回调 */\n onFolderClick?: (folderPath: string, extra?: any) => void;\n\n /** 更多操作菜单,传入节点返回 Dropdown menu 配置 */\n moreActions?: (node: FolderTreeData) => DropdownProps[\"menu\"];\n\n /** 是否显示连接线 */\n showLine?: boolean | { showLeafIcon?: boolean | React.ReactNode };\n /** 自定义展开/收起图标 */\n switcherIcon?: React.ReactNode | ((props: any) => React.ReactNode);\n\n /** 是否显示文件预览面板,默认 true */\n showPreview?: boolean;\n\n /**\n * 拖拽模式\n * - true | 'file': 只有文件(叶子节点)可拖拽\n * - 'folder': 只有文件夹可拖拽\n * - 'all': 文件和文件夹都可拖拽\n * - false | undefined: 禁用拖拽\n */\n draggable?: boolean | \"file\" | \"folder\" | \"all\";\n\n /** 拖拽完成回调 */\n onDrop?: (info: {\n /** 被拖拽节点的文件名 */\n fileName: React.ReactNode;\n /** 被拖拽节点的 extra 数据 */\n extra: any;\n /** 拖拽前的完整路径 */\n oldPath: string;\n /** 拖拽完成后的新路径 */\n newPath: string;\n /** 被拖拽的节点 */\n dragNode: FolderTreeData;\n /** 目标节点 */\n dropNode: FolderTreeData;\n }) => void;\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -15,6 +15,8 @@ export interface DirectoryTreeComponentProps {
|
|
|
15
15
|
directoryTitle?: FolderTreeProps["directoryTitle"];
|
|
16
16
|
moreActions?: FolderTreeProps["moreActions"];
|
|
17
17
|
width?: number | string;
|
|
18
|
+
draggable?: FolderTreeProps["draggable"];
|
|
19
|
+
onDrop?: FolderTreeProps["onDrop"];
|
|
18
20
|
}
|
|
19
21
|
declare const DirectoryTreeComponent: React.FC<DirectoryTreeComponentProps>;
|
|
20
22
|
export default DirectoryTreeComponent;
|
|
@@ -23,7 +23,9 @@ var DirectoryTreeComponent = function DirectoryTreeComponent(_ref) {
|
|
|
23
23
|
directoryIcons = _ref.directoryIcons,
|
|
24
24
|
directoryTitle = _ref.directoryTitle,
|
|
25
25
|
moreActions = _ref.moreActions,
|
|
26
|
-
width = _ref.width
|
|
26
|
+
width = _ref.width,
|
|
27
|
+
draggable = _ref.draggable,
|
|
28
|
+
onDrop = _ref.onDrop;
|
|
27
29
|
var styles = useStyles();
|
|
28
30
|
var isFolder = function isFolder(node) {
|
|
29
31
|
return !!node.children && node.children.length > 0;
|
|
@@ -83,11 +85,56 @@ var DirectoryTreeComponent = function DirectoryTreeComponent(_ref) {
|
|
|
83
85
|
title: titleContent,
|
|
84
86
|
icon: getIcon(node),
|
|
85
87
|
isLeaf: !isFolder(node),
|
|
88
|
+
/** 保存原始节点数据用于拖拽回调 */
|
|
89
|
+
_originalNode: node,
|
|
86
90
|
children: node.children ? convertToTreeData(node.children, pathSegments) : undefined
|
|
87
91
|
});
|
|
88
92
|
});
|
|
89
93
|
}, [buildPathSegments, getIcon, moreActions, styles]);
|
|
90
94
|
var treeDataConverted = convertToTreeData(treeData);
|
|
95
|
+
|
|
96
|
+
// ====== 拖拽配置 ======
|
|
97
|
+
var dragMode = draggable === true ? "file" : draggable || false;
|
|
98
|
+
var draggableConfig = dragMode ? {
|
|
99
|
+
icon: false,
|
|
100
|
+
nodeDraggable: function nodeDraggable(node) {
|
|
101
|
+
if (dragMode === "file") return !!node.isLeaf;
|
|
102
|
+
if (dragMode === "folder") return !node.isLeaf;
|
|
103
|
+
return true; // 'all'
|
|
104
|
+
}
|
|
105
|
+
} : false;
|
|
106
|
+
var handleDrop = useCallback(function (info) {
|
|
107
|
+
if (!onDrop) return;
|
|
108
|
+
var dragNode = info.dragNode;
|
|
109
|
+
var dropNode = info.node;
|
|
110
|
+
var originalDragNode = dragNode._originalNode;
|
|
111
|
+
var originalDropNode = dropNode._originalNode;
|
|
112
|
+
if (!originalDragNode || !originalDropNode) return;
|
|
113
|
+
|
|
114
|
+
// dragNode 的原始完整路径
|
|
115
|
+
var dragKey = String(dragNode.key);
|
|
116
|
+
// 计算新路径:如果 drop 到文件夹上(非叶子),新路径为 dropNode路径/dragNode文件名
|
|
117
|
+
// 如果 drop 到文件旁边,新路径为 dropNode 的父路径/dragNode文件名
|
|
118
|
+
var dropKey = String(dropNode.key);
|
|
119
|
+
var dragFileName = originalDragNode.path;
|
|
120
|
+
var newPath;
|
|
121
|
+
if (!dropNode.isLeaf && info.dropToGap === false) {
|
|
122
|
+
// 拖入文件夹内部
|
|
123
|
+
newPath = "".concat(dropKey, "/").concat(dragFileName);
|
|
124
|
+
} else {
|
|
125
|
+
// 拖到节点旁边(同级)
|
|
126
|
+
var dropParentPath = dropKey.includes("/") ? dropKey.substring(0, dropKey.lastIndexOf("/")) : "";
|
|
127
|
+
newPath = dropParentPath ? "".concat(dropParentPath, "/").concat(dragFileName) : dragFileName;
|
|
128
|
+
}
|
|
129
|
+
onDrop({
|
|
130
|
+
fileName: originalDragNode.title,
|
|
131
|
+
extra: originalDragNode.extra,
|
|
132
|
+
oldPath: dragKey,
|
|
133
|
+
newPath: newPath,
|
|
134
|
+
dragNode: originalDragNode,
|
|
135
|
+
dropNode: originalDropNode
|
|
136
|
+
});
|
|
137
|
+
}, [onDrop]);
|
|
91
138
|
var titleNode = directoryTitle === false || directoryTitle === null ? null : typeof directoryTitle === "function" ? directoryTitle() : directoryTitle;
|
|
92
139
|
return /*#__PURE__*/_jsxs("div", {
|
|
93
140
|
className: clsx(styles.directoryPanel, className),
|
|
@@ -109,7 +156,9 @@ var DirectoryTreeComponent = function DirectoryTreeComponent(_ref) {
|
|
|
109
156
|
blockNode: true,
|
|
110
157
|
showLine: showLine,
|
|
111
158
|
switcherIcon: switcherIcon,
|
|
112
|
-
defaultExpandAll: defaultExpandAll
|
|
159
|
+
defaultExpandAll: defaultExpandAll,
|
|
160
|
+
draggable: draggableConfig,
|
|
161
|
+
onDrop: dragMode ? handleDrop : undefined
|
|
113
162
|
})
|
|
114
163
|
})]
|
|
115
164
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useCallback","Tree","Dropdown","FileOutlined","FolderOutlined","MoreOutlined","clsx","useStyles","jsx","_jsx","jsxs","_jsxs","AntDirectoryTree","DirectoryTree","DirectoryTreeComponent","_ref","treeData","selectedKeys","expandedKeys","onSelect","onExpand","_ref$showLine","showLine","switcherIcon","_ref$defaultExpandAll","defaultExpandAll","className","directoryIcons","directoryTitle","moreActions","width","styles","isFolder","node","children","length","getIcon","icon","directory","filePath","path","toLowerCase","extension","split","pop","buildPathSegments","parentSegments","arguments","undefined","concat","_toConsumableArray","filter","s","convertToTreeData","nodes","map","pathSegments","fullPath","join","replace","titleContent","treeNodeTitle","treeNodeTitleHover","title","menu","trigger","placement","moreIcon","onClick","e","stopPropagation","_objectSpread","key","isLeaf","treeDataConverted","titleNode","directoryPanel","style","directoryTreeContent","multiple","blockNode"],"sources":["../../../../src/components/FolderTree/DirectoryTree.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\nimport { Tree, Dropdown } from \"antd\";\nimport {\n FileOutlined,\n FolderOutlined,\n MoreOutlined,\n} from \"@ant-design/icons\";\nimport type { TreeProps } from \"antd\";\nimport type { DataNode } from \"antd/es/tree\";\nimport clsx from \"clsx\";\nimport type { FolderTreeData, FolderTreeProps } from \"./types\";\nimport { useStyles } from \"./styles\";\n\nconst { DirectoryTree: AntDirectoryTree } = Tree;\n\nexport interface DirectoryTreeComponentProps {\n treeData: FolderTreeData[];\n directoryIcons?: FolderTreeProps[\"directoryIcons\"];\n selectedKeys?: string[];\n expandedKeys?: string[];\n onSelect?: TreeProps[\"onSelect\"];\n onExpand?: TreeProps[\"onExpand\"];\n showLine?: FolderTreeProps[\"showLine\"];\n switcherIcon?: FolderTreeProps[\"switcherIcon\"];\n defaultExpandAll?: boolean;\n className?: string;\n directoryTitle?: FolderTreeProps[\"directoryTitle\"];\n moreActions?: FolderTreeProps[\"moreActions\"];\n width?: number | string;\n}\n\nconst DirectoryTreeComponent: React.FC<DirectoryTreeComponentProps> = ({\n treeData,\n selectedKeys,\n expandedKeys,\n onSelect,\n onExpand,\n showLine = false,\n switcherIcon,\n defaultExpandAll = true,\n className,\n directoryIcons,\n directoryTitle,\n moreActions,\n width,\n}) => {\n const styles = useStyles();\n\n const isFolder = (node: FolderTreeData): boolean => {\n return !!node.children && node.children.length > 0;\n };\n\n const getIcon = useCallback(\n (node: FolderTreeData) => {\n if (directoryIcons === false || directoryIcons === null) {\n return null;\n }\n if (isFolder(node)) {\n const icon = directoryIcons?.directory;\n if (typeof icon === \"function\") return icon();\n return icon || <FolderOutlined />;\n }\n const filePath = node.path.toLowerCase();\n const extension = filePath.split(\".\").pop();\n if (extension) {\n const icon = directoryIcons?.[extension];\n if (icon) return typeof icon === \"function\" ? icon() : icon;\n }\n return <FileOutlined />;\n },\n [directoryIcons]\n );\n\n const buildPathSegments = useCallback(\n (node: FolderTreeData, parentSegments: string[] = []): string[] => {\n if (node.path === \"/\" && parentSegments.length === 0) {\n return [\"/\"];\n }\n return [...parentSegments, node.path].filter((s) => s !== \"\");\n },\n []\n );\n\n const convertToTreeData = useCallback(\n (nodes: FolderTreeData[], parentSegments: string[] = []): DataNode[] => {\n return nodes.map((node) => {\n const pathSegments = buildPathSegments(node, parentSegments);\n const fullPath = pathSegments.join(\"/\").replace(/^\\/+/, \"\");\n\n const titleContent = (\n <span\n className={clsx(\n styles.treeNodeTitle,\n moreActions && styles.treeNodeTitleHover\n )}\n >\n <span>{node.title}</span>\n {moreActions && (\n <Dropdown\n menu={moreActions(node)}\n trigger={[\"click\"]}\n placement=\"bottomRight\"\n >\n <span\n className={clsx(styles.moreIcon, \"folder-tree-more-icon\")}\n onClick={(e) => e.stopPropagation()}\n >\n <MoreOutlined />\n </span>\n </Dropdown>\n )}\n </span>\n );\n\n return {\n ...node,\n key: fullPath,\n path: fullPath,\n pathSegments,\n title: titleContent,\n icon: getIcon(node),\n isLeaf: !isFolder(node),\n children: node.children\n ? convertToTreeData(node.children, pathSegments)\n : undefined,\n };\n });\n },\n [buildPathSegments, getIcon, moreActions, styles]\n );\n\n const treeDataConverted = convertToTreeData(treeData);\n\n const titleNode =\n directoryTitle === false || directoryTitle === null\n ? null\n : typeof directoryTitle === \"function\"\n ? directoryTitle()\n : directoryTitle;\n\n return (\n <div className={clsx(styles.directoryPanel, className)} style={{ width }}>\n {titleNode && <div className={styles.directoryTitle}>{titleNode}</div>}\n <div className={styles.directoryTreeContent}>\n <AntDirectoryTree\n treeData={treeDataConverted}\n selectedKeys={selectedKeys}\n expandedKeys={expandedKeys}\n onSelect={onSelect}\n onExpand={onExpand}\n multiple={false}\n blockNode\n showLine={showLine as any}\n switcherIcon={switcherIcon}\n defaultExpandAll={defaultExpandAll}\n />\n </div>\n </div>\n );\n};\n\nexport default DirectoryTreeComponent;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["React","useCallback","Tree","Dropdown","FileOutlined","FolderOutlined","MoreOutlined","clsx","useStyles","jsx","_jsx","jsxs","_jsxs","AntDirectoryTree","DirectoryTree","DirectoryTreeComponent","_ref","treeData","selectedKeys","expandedKeys","onSelect","onExpand","_ref$showLine","showLine","switcherIcon","_ref$defaultExpandAll","defaultExpandAll","className","directoryIcons","directoryTitle","moreActions","width","draggable","onDrop","styles","isFolder","node","children","length","getIcon","icon","directory","filePath","path","toLowerCase","extension","split","pop","buildPathSegments","parentSegments","arguments","undefined","concat","_toConsumableArray","filter","s","convertToTreeData","nodes","map","pathSegments","fullPath","join","replace","titleContent","treeNodeTitle","treeNodeTitleHover","title","menu","trigger","placement","moreIcon","onClick","e","stopPropagation","_objectSpread","key","isLeaf","_originalNode","treeDataConverted","dragMode","draggableConfig","nodeDraggable","handleDrop","info","dragNode","dropNode","originalDragNode","originalDropNode","dragKey","String","dropKey","dragFileName","newPath","dropToGap","dropParentPath","includes","substring","lastIndexOf","fileName","extra","oldPath","titleNode","directoryPanel","style","directoryTreeContent","multiple","blockNode"],"sources":["../../../../src/components/FolderTree/DirectoryTree.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\nimport { Tree, Dropdown } from \"antd\";\nimport {\n FileOutlined,\n FolderOutlined,\n MoreOutlined,\n} from \"@ant-design/icons\";\nimport type { TreeProps } from \"antd\";\nimport type { DataNode } from \"antd/es/tree\";\nimport clsx from \"clsx\";\nimport type { FolderTreeData, FolderTreeProps } from \"./types\";\nimport { useStyles } from \"./styles\";\n\nconst { DirectoryTree: AntDirectoryTree } = Tree;\n\nexport interface DirectoryTreeComponentProps {\n treeData: FolderTreeData[];\n directoryIcons?: FolderTreeProps[\"directoryIcons\"];\n selectedKeys?: string[];\n expandedKeys?: string[];\n onSelect?: TreeProps[\"onSelect\"];\n onExpand?: TreeProps[\"onExpand\"];\n showLine?: FolderTreeProps[\"showLine\"];\n switcherIcon?: FolderTreeProps[\"switcherIcon\"];\n defaultExpandAll?: boolean;\n className?: string;\n directoryTitle?: FolderTreeProps[\"directoryTitle\"];\n moreActions?: FolderTreeProps[\"moreActions\"];\n width?: number | string;\n draggable?: FolderTreeProps[\"draggable\"];\n onDrop?: FolderTreeProps[\"onDrop\"];\n}\n\nconst DirectoryTreeComponent: React.FC<DirectoryTreeComponentProps> = ({\n treeData,\n selectedKeys,\n expandedKeys,\n onSelect,\n onExpand,\n showLine = false,\n switcherIcon,\n defaultExpandAll = true,\n className,\n directoryIcons,\n directoryTitle,\n moreActions,\n width,\n draggable,\n onDrop,\n}) => {\n const styles = useStyles();\n\n const isFolder = (node: FolderTreeData): boolean => {\n return !!node.children && node.children.length > 0;\n };\n\n const getIcon = useCallback(\n (node: FolderTreeData) => {\n if (directoryIcons === false || directoryIcons === null) {\n return null;\n }\n if (isFolder(node)) {\n const icon = directoryIcons?.directory;\n if (typeof icon === \"function\") return icon();\n return icon || <FolderOutlined />;\n }\n const filePath = node.path.toLowerCase();\n const extension = filePath.split(\".\").pop();\n if (extension) {\n const icon = directoryIcons?.[extension];\n if (icon) return typeof icon === \"function\" ? icon() : icon;\n }\n return <FileOutlined />;\n },\n [directoryIcons]\n );\n\n const buildPathSegments = useCallback(\n (node: FolderTreeData, parentSegments: string[] = []): string[] => {\n if (node.path === \"/\" && parentSegments.length === 0) {\n return [\"/\"];\n }\n return [...parentSegments, node.path].filter((s) => s !== \"\");\n },\n []\n );\n\n const convertToTreeData = useCallback(\n (nodes: FolderTreeData[], parentSegments: string[] = []): DataNode[] => {\n return nodes.map((node) => {\n const pathSegments = buildPathSegments(node, parentSegments);\n const fullPath = pathSegments.join(\"/\").replace(/^\\/+/, \"\");\n\n const titleContent = (\n <span\n className={clsx(\n styles.treeNodeTitle,\n moreActions && styles.treeNodeTitleHover\n )}\n >\n <span>{node.title}</span>\n {moreActions && (\n <Dropdown\n menu={moreActions(node)}\n trigger={[\"click\"]}\n placement=\"bottomRight\"\n >\n <span\n className={clsx(styles.moreIcon, \"folder-tree-more-icon\")}\n onClick={(e) => e.stopPropagation()}\n >\n <MoreOutlined />\n </span>\n </Dropdown>\n )}\n </span>\n );\n\n return {\n ...node,\n key: fullPath,\n path: fullPath,\n pathSegments,\n title: titleContent,\n icon: getIcon(node),\n isLeaf: !isFolder(node),\n /** 保存原始节点数据用于拖拽回调 */\n _originalNode: node,\n children: node.children\n ? convertToTreeData(node.children, pathSegments)\n : undefined,\n };\n });\n },\n [buildPathSegments, getIcon, moreActions, styles]\n );\n\n const treeDataConverted = convertToTreeData(treeData);\n\n // ====== 拖拽配置 ======\n const dragMode = draggable === true ? \"file\" : draggable || false;\n\n const draggableConfig = dragMode\n ? {\n icon: false,\n nodeDraggable: (node: DataNode) => {\n if (dragMode === \"file\") return !!node.isLeaf;\n if (dragMode === \"folder\") return !node.isLeaf;\n return true; // 'all'\n },\n }\n : false;\n\n const handleDrop: TreeProps[\"onDrop\"] = useCallback(\n (info: Parameters<NonNullable<TreeProps[\"onDrop\"]>>[0]) => {\n if (!onDrop) return;\n\n const dragNode = info.dragNode as DataNode & { _originalNode?: FolderTreeData };\n const dropNode = info.node as DataNode & { _originalNode?: FolderTreeData };\n\n const originalDragNode = dragNode._originalNode;\n const originalDropNode = dropNode._originalNode;\n if (!originalDragNode || !originalDropNode) return;\n\n // dragNode 的原始完整路径\n const dragKey = String(dragNode.key);\n // 计算新路径:如果 drop 到文件夹上(非叶子),新路径为 dropNode路径/dragNode文件名\n // 如果 drop 到文件旁边,新路径为 dropNode 的父路径/dragNode文件名\n const dropKey = String(dropNode.key);\n const dragFileName = originalDragNode.path;\n let newPath: string;\n\n if (!dropNode.isLeaf && info.dropToGap === false) {\n // 拖入文件夹内部\n newPath = `${dropKey}/${dragFileName}`;\n } else {\n // 拖到节点旁边(同级)\n const dropParentPath = dropKey.includes(\"/\")\n ? dropKey.substring(0, dropKey.lastIndexOf(\"/\"))\n : \"\";\n newPath = dropParentPath\n ? `${dropParentPath}/${dragFileName}`\n : dragFileName;\n }\n\n onDrop({\n fileName: originalDragNode.title,\n extra: originalDragNode.extra,\n oldPath: dragKey,\n newPath,\n dragNode: originalDragNode,\n dropNode: originalDropNode,\n });\n },\n [onDrop],\n );\n\n const titleNode =\n directoryTitle === false || directoryTitle === null\n ? null\n : typeof directoryTitle === \"function\"\n ? directoryTitle()\n : directoryTitle;\n\n return (\n <div className={clsx(styles.directoryPanel, className)} style={{ width }}>\n {titleNode && <div className={styles.directoryTitle}>{titleNode}</div>}\n <div className={styles.directoryTreeContent}>\n <AntDirectoryTree\n treeData={treeDataConverted}\n selectedKeys={selectedKeys}\n expandedKeys={expandedKeys}\n onSelect={onSelect}\n onExpand={onExpand}\n multiple={false}\n blockNode\n showLine={showLine as any}\n switcherIcon={switcherIcon}\n defaultExpandAll={defaultExpandAll}\n draggable={draggableConfig}\n onDrop={dragMode ? handleDrop : undefined}\n />\n </div>\n </div>\n );\n};\n\nexport default DirectoryTreeComponent;\n"],"mappings":"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"}
|
|
@@ -38,7 +38,9 @@ var FolderTree = function FolderTree(props) {
|
|
|
38
38
|
showLine = props.showLine,
|
|
39
39
|
switcherIcon = props.switcherIcon,
|
|
40
40
|
_props$showPreview = props.showPreview,
|
|
41
|
-
showPreview = _props$showPreview === void 0 ? true : _props$showPreview
|
|
41
|
+
showPreview = _props$showPreview === void 0 ? true : _props$showPreview,
|
|
42
|
+
draggable = props.draggable,
|
|
43
|
+
onDrop = props.onDrop;
|
|
42
44
|
var styles = useStyles();
|
|
43
45
|
|
|
44
46
|
// ====== 工具函数 ======
|
|
@@ -249,7 +251,9 @@ var FolderTree = function FolderTree(props) {
|
|
|
249
251
|
moreActions: moreActions,
|
|
250
252
|
showLine: showLine,
|
|
251
253
|
switcherIcon: switcherIcon,
|
|
252
|
-
width: directoryTreeWidth
|
|
254
|
+
width: directoryTreeWidth,
|
|
255
|
+
draggable: draggable,
|
|
256
|
+
onDrop: onDrop
|
|
253
257
|
}), showPreview && /*#__PURE__*/_jsx(FilePreview, {
|
|
254
258
|
selectedFile: validSelectedFile ? selectedFileState : [],
|
|
255
259
|
fileContent: fileContent,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useCallback","useEffect","useState","clsx","DirectoryTreeComponent","FilePreview","useStyles","jsx","_jsx","jsxs","_jsxs","FolderTree","props","className","style","treeData","directoryIcons","previewRender","directoryTitle","previewTitle","_props$selectable","selectable","defaultSelectedFile","_props$defaultExpandA","defaultExpandAll","selectedFile","onSelectedFileChange","_props$directoryTreeW","directoryTreeWidth","emptyRender","defaultExpandedPaths","expandedPaths","onExpandedPathsChange","onFileClick","onFolderClick","fileContentService","moreActions","showLine","switcherIcon","_props$showPreview","showPreview","styles","findNodeAndValidate","path","validateAsFile","arguments","length","undefined","node","isValid","segments","Array","isArray","filter","Boolean","split","findNode","nodes","index","currentSegment","_iterator","_createForOfIteratorHelper","_step","s","n","done","value","children","err","e","f","isValidSelectedFile","filePath","_useState","_useState2","_slicedToArray","selectedFileState","setSelectedFileState","_useState3","_useState4","expandedPathsState","setExpandedPaths","_useState5","_useState6","validSelectedFile","setValidSelectedFile","_useState7","_useState8","fileContent","setFileContent","_useState9","_useState10","loadingContent","setLoadingContent","loadContent","_ref","_asyncToGenerator","_regeneratorRuntime","mark","_callee","_findNodeAndValidate","content","wrap","_callee$","_context","prev","next","abrupt","join","loadFileContent","sent","t0","concat","Error","message","finish","stop","apply","handleSelect","_keys","info","_keys$","keys","selectedNodes","isFolder","some","isLeaf","extra","pathArray","_findNodeAndValidate2","originalNode","fileName","title","nodeContent","isControlled","handleExpand","newPaths","container","containerNoPreview","_objectSpread","background","backgroundColor","selectedKeys","expandedKeys","onSelect","onExpand","width","loading","getFileNode","_findNodeAndValidate3"],"sources":["../../../../src/components/FolderTree/index.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useState } from \"react\";\nimport type { TreeProps } from \"antd\";\nimport clsx from \"clsx\";\nimport type { FolderTreeData, FolderTreeProps } from \"./types\";\nimport DirectoryTreeComponent from \"./DirectoryTree\";\nimport FilePreview from \"./FilePreview\";\nimport { useStyles } from \"./styles\";\n\nexport type {\n FolderTreeData,\n FolderTreeProps,\n FileContentService,\n} from \"./types\";\n\nconst FolderTree: React.FC<FolderTreeProps> = (props) => {\n const {\n className,\n style,\n treeData,\n directoryIcons,\n previewRender,\n directoryTitle,\n previewTitle,\n selectable = true,\n defaultSelectedFile,\n defaultExpandAll = true,\n selectedFile,\n onSelectedFileChange,\n directoryTreeWidth = 280,\n emptyRender,\n defaultExpandedPaths,\n expandedPaths,\n onExpandedPathsChange,\n onFileClick,\n onFolderClick,\n fileContentService,\n moreActions,\n showLine,\n switcherIcon,\n showPreview = true,\n } = props;\n\n const styles = useStyles();\n\n // ====== 工具函数 ======\n const findNodeAndValidate = useCallback(\n (\n path: string | string[],\n validateAsFile = false,\n ): { node: FolderTreeData | undefined; isValid: boolean } => {\n if (!path) return { node: undefined, isValid: false };\n const segments = Array.isArray(path)\n ? path.filter(Boolean)\n : path.split(\"/\").filter(Boolean);\n if (segments.length === 0) return { node: undefined, isValid: false };\n\n const findNode = (\n nodes: FolderTreeData[],\n index = 0,\n ): FolderTreeData | undefined => {\n if (index >= segments.length) return undefined;\n const currentSegment = segments[index];\n for (const node of nodes) {\n if (node.path === currentSegment) {\n return index === segments.length - 1\n ? node\n : node.children\n ? findNode(node.children, index + 1)\n : undefined;\n }\n }\n return undefined;\n };\n\n const node = findNode(treeData);\n const isValid = validateAsFile\n ? !!node && (!node?.children || node.children.length === 0)\n : !!node;\n return { node, isValid };\n },\n [treeData],\n );\n\n const isValidSelectedFile = (filePath?: string[]): boolean =>\n !!(\n filePath &&\n filePath.length > 0 &&\n findNodeAndValidate(filePath, true).isValid\n );\n\n // ====== State ======\n const [selectedFileState, setSelectedFileState] = useState<string[]>(() =>\n isValidSelectedFile(selectedFile || defaultSelectedFile)\n ? selectedFile || defaultSelectedFile || []\n : [],\n );\n const [expandedPathsState, setExpandedPaths] = useState<string[] | undefined>(\n expandedPaths || defaultExpandedPaths,\n );\n const [validSelectedFile, setValidSelectedFile] = useState<boolean>(\n isValidSelectedFile(selectedFile || defaultSelectedFile),\n );\n const [fileContent, setFileContent] = useState<string>(\"\");\n const [loadingContent, setLoadingContent] = useState<boolean>(false);\n\n // 受控模式同步\n useEffect(() => {\n if (selectedFile !== undefined) {\n setSelectedFileState(selectedFile);\n setValidSelectedFile(isValidSelectedFile(selectedFile));\n }\n }, [selectedFile, treeData]);\n\n useEffect(() => {\n if (expandedPaths !== undefined) {\n setExpandedPaths(expandedPaths);\n }\n }, [expandedPaths]);\n\n // ====== 加载文件内容 ======\n useEffect(() => {\n const loadContent = async () => {\n if (!validSelectedFile || selectedFileState.length === 0) {\n setFileContent(\"\");\n setLoadingContent(false);\n return;\n }\n\n const filePath = selectedFileState.join(\"/\");\n const segments = filePath.split(\"/\").filter((s) => s !== \"\");\n const { node } = findNodeAndValidate(segments);\n\n if (fileContentService) {\n setLoadingContent(true);\n try {\n const content = await fileContentService.loadFileContent(filePath);\n setFileContent(content);\n } catch (error) {\n setFileContent(\n `// 加载错误: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n );\n } finally {\n setLoadingContent(false);\n }\n } else if (node?.content) {\n setFileContent(node.content);\n setLoadingContent(false);\n } else {\n setFileContent(\"\");\n setLoadingContent(false);\n }\n };\n\n loadContent();\n }, [\n validSelectedFile,\n selectedFileState,\n treeData,\n fileContentService,\n findNodeAndValidate,\n ]);\n\n // ====== 事件处理 ======\n const handleSelect: TreeProps[\"onSelect\"] = (_keys, info) => {\n const keys = _keys as string[];\n const nodes = Array.isArray(info.selectedNodes)\n ? info.selectedNodes\n : [info.selectedNodes];\n\n const isFolder = nodes.some((node) => !node.isLeaf);\n if (isFolder) {\n if (nodes.length === 1) {\n const node = nodes[0] as unknown as FolderTreeData;\n onFolderClick?.(node.path, node.extra);\n }\n return;\n }\n\n const pathArray = keys[0]?.split(\"/\").filter(Boolean) || [];\n if (pathArray.length === 0) return;\n\n // 从原始 treeData 中查找节点,避免拿到 antd 包装后的 JSX title\n const { node: originalNode } = findNodeAndValidate(pathArray);\n const fileName = originalNode?.title;\n const nodeContent = originalNode?.content;\n\n onSelectedFileChange?.({\n path: pathArray,\n title: fileName,\n content: nodeContent,\n extra: originalNode?.extra,\n });\n\n const isControlled = selectedFile !== undefined;\n if (!isControlled) {\n setValidSelectedFile(true);\n setSelectedFileState(pathArray);\n }\n\n if (originalNode) {\n onFileClick?.(\n keys[0],\n originalNode.content,\n originalNode.extra,\n );\n }\n };\n\n const handleExpand: TreeProps[\"onExpand\"] = (keys) => {\n const newPaths = keys as string[];\n setExpandedPaths(newPaths);\n onExpandedPathsChange?.(newPaths);\n };\n\n return (\n <div\n className={clsx(\n styles.container,\n !showPreview && styles.containerNoPreview,\n className,\n )}\n style={{\n ...style,\n ...(style?.background\n ? ({\n \"--folder-tree-directory-bg\": style.background,\n } as React.CSSProperties)\n : {}),\n ...(style?.backgroundColor\n ? ({\n \"--folder-tree-directory-bg\": style.backgroundColor,\n } as React.CSSProperties)\n : {}),\n }}\n >\n <DirectoryTreeComponent\n treeData={treeData}\n directoryIcons={directoryIcons}\n selectedKeys={\n selectable && selectedFileState && validSelectedFile\n ? [selectedFileState.join(\"/\")]\n : []\n }\n expandedKeys={expandedPathsState}\n onSelect={handleSelect}\n onExpand={handleExpand}\n defaultExpandAll={defaultExpandAll}\n directoryTitle={directoryTitle}\n moreActions={moreActions}\n showLine={showLine}\n switcherIcon={switcherIcon}\n width={directoryTreeWidth}\n />\n {showPreview && (\n <FilePreview\n selectedFile={validSelectedFile ? selectedFileState : []}\n fileContent={fileContent}\n loading={loadingContent}\n previewTitle={previewTitle}\n previewRender={previewRender}\n emptyRender={emptyRender}\n getFileNode={(path) => {\n if (!path || path.length === 0) return undefined;\n const { node } = findNodeAndValidate(path);\n return node\n ? { title: node.title, path: node.path, content: node.content }\n : undefined;\n }}\n />\n )}\n </div>\n );\n};\n\nexport default FolderTree;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["React","useCallback","useEffect","useState","clsx","DirectoryTreeComponent","FilePreview","useStyles","jsx","_jsx","jsxs","_jsxs","FolderTree","props","className","style","treeData","directoryIcons","previewRender","directoryTitle","previewTitle","_props$selectable","selectable","defaultSelectedFile","_props$defaultExpandA","defaultExpandAll","selectedFile","onSelectedFileChange","_props$directoryTreeW","directoryTreeWidth","emptyRender","defaultExpandedPaths","expandedPaths","onExpandedPathsChange","onFileClick","onFolderClick","fileContentService","moreActions","showLine","switcherIcon","_props$showPreview","showPreview","draggable","onDrop","styles","findNodeAndValidate","path","validateAsFile","arguments","length","undefined","node","isValid","segments","Array","isArray","filter","Boolean","split","findNode","nodes","index","currentSegment","_iterator","_createForOfIteratorHelper","_step","s","n","done","value","children","err","e","f","isValidSelectedFile","filePath","_useState","_useState2","_slicedToArray","selectedFileState","setSelectedFileState","_useState3","_useState4","expandedPathsState","setExpandedPaths","_useState5","_useState6","validSelectedFile","setValidSelectedFile","_useState7","_useState8","fileContent","setFileContent","_useState9","_useState10","loadingContent","setLoadingContent","loadContent","_ref","_asyncToGenerator","_regeneratorRuntime","mark","_callee","_findNodeAndValidate","content","wrap","_callee$","_context","prev","next","abrupt","join","loadFileContent","sent","t0","concat","Error","message","finish","stop","apply","handleSelect","_keys","info","_keys$","keys","selectedNodes","isFolder","some","isLeaf","extra","pathArray","_findNodeAndValidate2","originalNode","fileName","title","nodeContent","isControlled","handleExpand","newPaths","container","containerNoPreview","_objectSpread","background","backgroundColor","selectedKeys","expandedKeys","onSelect","onExpand","width","loading","getFileNode","_findNodeAndValidate3"],"sources":["../../../../src/components/FolderTree/index.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useState } from \"react\";\nimport type { TreeProps } from \"antd\";\nimport clsx from \"clsx\";\nimport type { FolderTreeData, FolderTreeProps } from \"./types\";\nimport DirectoryTreeComponent from \"./DirectoryTree\";\nimport FilePreview from \"./FilePreview\";\nimport { useStyles } from \"./styles\";\n\nexport type {\n FolderTreeData,\n FolderTreeProps,\n FileContentService,\n} from \"./types\";\n\nconst FolderTree: React.FC<FolderTreeProps> = (props) => {\n const {\n className,\n style,\n treeData,\n directoryIcons,\n previewRender,\n directoryTitle,\n previewTitle,\n selectable = true,\n defaultSelectedFile,\n defaultExpandAll = true,\n selectedFile,\n onSelectedFileChange,\n directoryTreeWidth = 280,\n emptyRender,\n defaultExpandedPaths,\n expandedPaths,\n onExpandedPathsChange,\n onFileClick,\n onFolderClick,\n fileContentService,\n moreActions,\n showLine,\n switcherIcon,\n showPreview = true,\n draggable,\n onDrop,\n } = props;\n\n const styles = useStyles();\n\n // ====== 工具函数 ======\n const findNodeAndValidate = useCallback(\n (\n path: string | string[],\n validateAsFile = false,\n ): { node: FolderTreeData | undefined; isValid: boolean } => {\n if (!path) return { node: undefined, isValid: false };\n const segments = Array.isArray(path)\n ? path.filter(Boolean)\n : path.split(\"/\").filter(Boolean);\n if (segments.length === 0) return { node: undefined, isValid: false };\n\n const findNode = (\n nodes: FolderTreeData[],\n index = 0,\n ): FolderTreeData | undefined => {\n if (index >= segments.length) return undefined;\n const currentSegment = segments[index];\n for (const node of nodes) {\n if (node.path === currentSegment) {\n return index === segments.length - 1\n ? node\n : node.children\n ? findNode(node.children, index + 1)\n : undefined;\n }\n }\n return undefined;\n };\n\n const node = findNode(treeData);\n const isValid = validateAsFile\n ? !!node && (!node?.children || node.children.length === 0)\n : !!node;\n return { node, isValid };\n },\n [treeData],\n );\n\n const isValidSelectedFile = (filePath?: string[]): boolean =>\n !!(\n filePath &&\n filePath.length > 0 &&\n findNodeAndValidate(filePath, true).isValid\n );\n\n // ====== State ======\n const [selectedFileState, setSelectedFileState] = useState<string[]>(() =>\n isValidSelectedFile(selectedFile || defaultSelectedFile)\n ? selectedFile || defaultSelectedFile || []\n : [],\n );\n const [expandedPathsState, setExpandedPaths] = useState<string[] | undefined>(\n expandedPaths || defaultExpandedPaths,\n );\n const [validSelectedFile, setValidSelectedFile] = useState<boolean>(\n isValidSelectedFile(selectedFile || defaultSelectedFile),\n );\n const [fileContent, setFileContent] = useState<string>(\"\");\n const [loadingContent, setLoadingContent] = useState<boolean>(false);\n\n // 受控模式同步\n useEffect(() => {\n if (selectedFile !== undefined) {\n setSelectedFileState(selectedFile);\n setValidSelectedFile(isValidSelectedFile(selectedFile));\n }\n }, [selectedFile, treeData]);\n\n useEffect(() => {\n if (expandedPaths !== undefined) {\n setExpandedPaths(expandedPaths);\n }\n }, [expandedPaths]);\n\n // ====== 加载文件内容 ======\n useEffect(() => {\n const loadContent = async () => {\n if (!validSelectedFile || selectedFileState.length === 0) {\n setFileContent(\"\");\n setLoadingContent(false);\n return;\n }\n\n const filePath = selectedFileState.join(\"/\");\n const segments = filePath.split(\"/\").filter((s) => s !== \"\");\n const { node } = findNodeAndValidate(segments);\n\n if (fileContentService) {\n setLoadingContent(true);\n try {\n const content = await fileContentService.loadFileContent(filePath);\n setFileContent(content);\n } catch (error) {\n setFileContent(\n `// 加载错误: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n );\n } finally {\n setLoadingContent(false);\n }\n } else if (node?.content) {\n setFileContent(node.content);\n setLoadingContent(false);\n } else {\n setFileContent(\"\");\n setLoadingContent(false);\n }\n };\n\n loadContent();\n }, [\n validSelectedFile,\n selectedFileState,\n treeData,\n fileContentService,\n findNodeAndValidate,\n ]);\n\n // ====== 事件处理 ======\n const handleSelect: TreeProps[\"onSelect\"] = (_keys, info) => {\n const keys = _keys as string[];\n const nodes = Array.isArray(info.selectedNodes)\n ? info.selectedNodes\n : [info.selectedNodes];\n\n const isFolder = nodes.some((node) => !node.isLeaf);\n if (isFolder) {\n if (nodes.length === 1) {\n const node = nodes[0] as unknown as FolderTreeData;\n onFolderClick?.(node.path, node.extra);\n }\n return;\n }\n\n const pathArray = keys[0]?.split(\"/\").filter(Boolean) || [];\n if (pathArray.length === 0) return;\n\n // 从原始 treeData 中查找节点,避免拿到 antd 包装后的 JSX title\n const { node: originalNode } = findNodeAndValidate(pathArray);\n const fileName = originalNode?.title;\n const nodeContent = originalNode?.content;\n\n onSelectedFileChange?.({\n path: pathArray,\n title: fileName,\n content: nodeContent,\n extra: originalNode?.extra,\n });\n\n const isControlled = selectedFile !== undefined;\n if (!isControlled) {\n setValidSelectedFile(true);\n setSelectedFileState(pathArray);\n }\n\n if (originalNode) {\n onFileClick?.(\n keys[0],\n originalNode.content,\n originalNode.extra,\n );\n }\n };\n\n const handleExpand: TreeProps[\"onExpand\"] = (keys) => {\n const newPaths = keys as string[];\n setExpandedPaths(newPaths);\n onExpandedPathsChange?.(newPaths);\n };\n\n return (\n <div\n className={clsx(\n styles.container,\n !showPreview && styles.containerNoPreview,\n className,\n )}\n style={{\n ...style,\n ...(style?.background\n ? ({\n \"--folder-tree-directory-bg\": style.background,\n } as React.CSSProperties)\n : {}),\n ...(style?.backgroundColor\n ? ({\n \"--folder-tree-directory-bg\": style.backgroundColor,\n } as React.CSSProperties)\n : {}),\n }}\n >\n <DirectoryTreeComponent\n treeData={treeData}\n directoryIcons={directoryIcons}\n selectedKeys={\n selectable && selectedFileState && validSelectedFile\n ? [selectedFileState.join(\"/\")]\n : []\n }\n expandedKeys={expandedPathsState}\n onSelect={handleSelect}\n onExpand={handleExpand}\n defaultExpandAll={defaultExpandAll}\n directoryTitle={directoryTitle}\n moreActions={moreActions}\n showLine={showLine}\n switcherIcon={switcherIcon}\n width={directoryTreeWidth}\n draggable={draggable}\n onDrop={onDrop}\n />\n {showPreview && (\n <FilePreview\n selectedFile={validSelectedFile ? selectedFileState : []}\n fileContent={fileContent}\n loading={loadingContent}\n previewTitle={previewTitle}\n previewRender={previewRender}\n emptyRender={emptyRender}\n getFileNode={(path) => {\n if (!path || path.length === 0) return undefined;\n const { node } = findNodeAndValidate(path);\n return node\n ? { title: node.title, path: node.path, content: node.content }\n : undefined;\n }}\n />\n )}\n </div>\n );\n};\n\nexport default FolderTree;\n"],"mappings":";;;;;AAAA,OAAOA,KAAK,IAAIC,WAAW,EAAEC,SAAS,EAAEC,QAAQ,QAAQ,OAAO;AAE/D,OAAOC,IAAI,MAAM,MAAM;AAEvB,OAAOC,sBAAsB;AAC7B,OAAOC,WAAW;AAClB,SAASC,SAAS;AAAmB,SAAAC,GAAA,IAAAC,IAAA;AAAA,SAAAC,IAAA,IAAAC,KAAA;AAQrC,IAAMC,UAAqC,GAAG,SAAxCA,UAAqCA,CAAIC,KAAK,EAAK;EACvD,IACEC,SAAS,GA0BPD,KAAK,CA1BPC,SAAS;IACTC,KAAK,GAyBHF,KAAK,CAzBPE,KAAK;IACLC,QAAQ,GAwBNH,KAAK,CAxBPG,QAAQ;IACRC,cAAc,GAuBZJ,KAAK,CAvBPI,cAAc;IACdC,aAAa,GAsBXL,KAAK,CAtBPK,aAAa;IACbC,cAAc,GAqBZN,KAAK,CArBPM,cAAc;IACdC,YAAY,GAoBVP,KAAK,CApBPO,YAAY;IAAAC,iBAAA,GAoBVR,KAAK,CAnBPS,UAAU;IAAVA,UAAU,GAAAD,iBAAA,cAAG,IAAI,GAAAA,iBAAA;IACjBE,mBAAmB,GAkBjBV,KAAK,CAlBPU,mBAAmB;IAAAC,qBAAA,GAkBjBX,KAAK,CAjBPY,gBAAgB;IAAhBA,gBAAgB,GAAAD,qBAAA,cAAG,IAAI,GAAAA,qBAAA;IACvBE,YAAY,GAgBVb,KAAK,CAhBPa,YAAY;IACZC,oBAAoB,GAelBd,KAAK,CAfPc,oBAAoB;IAAAC,qBAAA,GAelBf,KAAK,CAdPgB,kBAAkB;IAAlBA,kBAAkB,GAAAD,qBAAA,cAAG,GAAG,GAAAA,qBAAA;IACxBE,WAAW,GAaTjB,KAAK,CAbPiB,WAAW;IACXC,oBAAoB,GAYlBlB,KAAK,CAZPkB,oBAAoB;IACpBC,aAAa,GAWXnB,KAAK,CAXPmB,aAAa;IACbC,qBAAqB,GAUnBpB,KAAK,CAVPoB,qBAAqB;IACrBC,WAAW,GASTrB,KAAK,CATPqB,WAAW;IACXC,aAAa,GAQXtB,KAAK,CARPsB,aAAa;IACbC,kBAAkB,GAOhBvB,KAAK,CAPPuB,kBAAkB;IAClBC,WAAW,GAMTxB,KAAK,CANPwB,WAAW;IACXC,QAAQ,GAKNzB,KAAK,CALPyB,QAAQ;IACRC,YAAY,GAIV1B,KAAK,CAJP0B,YAAY;IAAAC,kBAAA,GAIV3B,KAAK,CAHP4B,WAAW;IAAXA,WAAW,GAAAD,kBAAA,cAAG,IAAI,GAAAA,kBAAA;IAClBE,SAAS,GAEP7B,KAAK,CAFP6B,SAAS;IACTC,MAAM,GACJ9B,KAAK,CADP8B,MAAM;EAGR,IAAMC,MAAM,GAAGrC,SAAS,CAAC,CAAC;;EAE1B;EACA,IAAMsC,mBAAmB,GAAG5C,WAAW,CACrC,UACE6C,IAAuB,EAEoC;IAAA,IAD3DC,cAAc,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,KAAK;IAEtB,IAAI,CAACF,IAAI,EAAE,OAAO;MAAEK,IAAI,EAAED,SAAS;MAAEE,OAAO,EAAE;IAAM,CAAC;IACrD,IAAMC,QAAQ,GAAGC,KAAK,CAACC,OAAO,CAACT,IAAI,CAAC,GAChCA,IAAI,CAACU,MAAM,CAACC,OAAO,CAAC,GACpBX,IAAI,CAACY,KAAK,CAAC,GAAG,CAAC,CAACF,MAAM,CAACC,OAAO,CAAC;IACnC,IAAIJ,QAAQ,CAACJ,MAAM,KAAK,CAAC,EAAE,OAAO;MAAEE,IAAI,EAAED,SAAS;MAAEE,OAAO,EAAE;IAAM,CAAC;IAErE,IAAMO,QAAQ,GAAG,SAAXA,QAAQA,CACZC,KAAuB,EAEQ;MAAA,IAD/BC,KAAK,GAAAb,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,CAAC;MAET,IAAIa,KAAK,IAAIR,QAAQ,CAACJ,MAAM,EAAE,OAAOC,SAAS;MAC9C,IAAMY,cAAc,GAAGT,QAAQ,CAACQ,KAAK,CAAC;MAAC,IAAAE,SAAA,GAAAC,0BAAA,CACpBJ,KAAK;QAAAK,KAAA;MAAA;QAAxB,KAAAF,SAAA,CAAAG,CAAA,MAAAD,KAAA,GAAAF,SAAA,CAAAI,CAAA,IAAAC,IAAA,GAA0B;UAAA,IAAfjB,KAAI,GAAAc,KAAA,CAAAI,KAAA;UACb,IAAIlB,KAAI,CAACL,IAAI,KAAKgB,cAAc,EAAE;YAChC,OAAOD,KAAK,KAAKR,QAAQ,CAACJ,MAAM,GAAG,CAAC,GAChCE,KAAI,GACJA,KAAI,CAACmB,QAAQ,GACXX,QAAQ,CAACR,KAAI,CAACmB,QAAQ,EAAET,KAAK,GAAG,CAAC,CAAC,GAClCX,SAAS;UACjB;QACF;MAAC,SAAAqB,GAAA;QAAAR,SAAA,CAAAS,CAAA,CAAAD,GAAA;MAAA;QAAAR,SAAA,CAAAU,CAAA;MAAA;MACD,OAAOvB,SAAS;IAClB,CAAC;IAED,IAAMC,IAAI,GAAGQ,QAAQ,CAAC3C,QAAQ,CAAC;IAC/B,IAAMoC,OAAO,GAAGL,cAAc,GAC1B,CAAC,CAACI,IAAI,KAAK,EAACA,IAAI,aAAJA,IAAI,eAAJA,IAAI,CAAEmB,QAAQ,KAAInB,IAAI,CAACmB,QAAQ,CAACrB,MAAM,KAAK,CAAC,CAAC,GACzD,CAAC,CAACE,IAAI;IACV,OAAO;MAAEA,IAAI,EAAJA,IAAI;MAAEC,OAAO,EAAPA;IAAQ,CAAC;EAC1B,CAAC,EACD,CAACpC,QAAQ,CACX,CAAC;EAED,IAAM0D,mBAAmB,GAAG,SAAtBA,mBAAmBA,CAAIC,QAAmB;IAAA,OAC9C,CAAC,EACCA,QAAQ,IACRA,QAAQ,CAAC1B,MAAM,GAAG,CAAC,IACnBJ,mBAAmB,CAAC8B,QAAQ,EAAE,IAAI,CAAC,CAACvB,OAAO,CAC5C;EAAA;;EAEH;EACA,IAAAwB,SAAA,GAAkDzE,QAAQ,CAAW;MAAA,OACnEuE,mBAAmB,CAAChD,YAAY,IAAIH,mBAAmB,CAAC,GACpDG,YAAY,IAAIH,mBAAmB,IAAI,EAAE,GACzC,EAAE;IAAA,CACR,CAAC;IAAAsD,UAAA,GAAAC,cAAA,CAAAF,SAAA;IAJMG,iBAAiB,GAAAF,UAAA;IAAEG,oBAAoB,GAAAH,UAAA;EAK9C,IAAAI,UAAA,GAA+C9E,QAAQ,CACrD6B,aAAa,IAAID,oBACnB,CAAC;IAAAmD,UAAA,GAAAJ,cAAA,CAAAG,UAAA;IAFME,kBAAkB,GAAAD,UAAA;IAAEE,gBAAgB,GAAAF,UAAA;EAG3C,IAAAG,UAAA,GAAkDlF,QAAQ,CACxDuE,mBAAmB,CAAChD,YAAY,IAAIH,mBAAmB,CACzD,CAAC;IAAA+D,UAAA,GAAAR,cAAA,CAAAO,UAAA;IAFME,iBAAiB,GAAAD,UAAA;IAAEE,oBAAoB,GAAAF,UAAA;EAG9C,IAAAG,UAAA,GAAsCtF,QAAQ,CAAS,EAAE,CAAC;IAAAuF,UAAA,GAAAZ,cAAA,CAAAW,UAAA;IAAnDE,WAAW,GAAAD,UAAA;IAAEE,cAAc,GAAAF,UAAA;EAClC,IAAAG,UAAA,GAA4C1F,QAAQ,CAAU,KAAK,CAAC;IAAA2F,WAAA,GAAAhB,cAAA,CAAAe,UAAA;IAA7DE,cAAc,GAAAD,WAAA;IAAEE,iBAAiB,GAAAF,WAAA;;EAExC;EACA5F,SAAS,CAAC,YAAM;IACd,IAAIwB,YAAY,KAAKwB,SAAS,EAAE;MAC9B8B,oBAAoB,CAACtD,YAAY,CAAC;MAClC8D,oBAAoB,CAACd,mBAAmB,CAAChD,YAAY,CAAC,CAAC;IACzD;EACF,CAAC,EAAE,CAACA,YAAY,EAAEV,QAAQ,CAAC,CAAC;EAE5Bd,SAAS,CAAC,YAAM;IACd,IAAI8B,aAAa,KAAKkB,SAAS,EAAE;MAC/BkC,gBAAgB,CAACpD,aAAa,CAAC;IACjC;EACF,CAAC,EAAE,CAACA,aAAa,CAAC,CAAC;;EAEnB;EACA9B,SAAS,CAAC,YAAM;IACd,IAAM+F,WAAW;MAAA,IAAAC,IAAA,GAAAC,iBAAA,eAAAC,mBAAA,GAAAC,IAAA,CAAG,SAAAC,QAAA;QAAA,IAAA3B,QAAA,EAAAtB,QAAA,EAAAkD,oBAAA,EAAApD,IAAA,EAAAqD,OAAA;QAAA,OAAAJ,mBAAA,GAAAK,IAAA,UAAAC,SAAAC,QAAA;UAAA,kBAAAA,QAAA,CAAAC,IAAA,GAAAD,QAAA,CAAAE,IAAA;YAAA;cAAA,MACd,CAACtB,iBAAiB,IAAIR,iBAAiB,CAAC9B,MAAM,KAAK,CAAC;gBAAA0D,QAAA,CAAAE,IAAA;gBAAA;cAAA;cACtDjB,cAAc,CAAC,EAAE,CAAC;cAClBI,iBAAiB,CAAC,KAAK,CAAC;cAAC,OAAAW,QAAA,CAAAG,MAAA;YAAA;cAIrBnC,QAAQ,GAAGI,iBAAiB,CAACgC,IAAI,CAAC,GAAG,CAAC;cACtC1D,QAAQ,GAAGsB,QAAQ,CAACjB,KAAK,CAAC,GAAG,CAAC,CAACF,MAAM,CAAC,UAACU,CAAC;gBAAA,OAAKA,CAAC,KAAK,EAAE;cAAA,EAAC;cAAAqC,oBAAA,GAC3C1D,mBAAmB,CAACQ,QAAQ,CAAC,EAAtCF,IAAI,GAAAoD,oBAAA,CAAJpD,IAAI;cAAA,KAERf,kBAAkB;gBAAAuE,QAAA,CAAAE,IAAA;gBAAA;cAAA;cACpBb,iBAAiB,CAAC,IAAI,CAAC;cAACW,QAAA,CAAAC,IAAA;cAAAD,QAAA,CAAAE,IAAA;cAAA,OAEAzE,kBAAkB,CAAC4E,eAAe,CAACrC,QAAQ,CAAC;YAAA;cAA5D6B,OAAO,GAAAG,QAAA,CAAAM,IAAA;cACbrB,cAAc,CAACY,OAAO,CAAC;cAACG,QAAA,CAAAE,IAAA;cAAA;YAAA;cAAAF,QAAA,CAAAC,IAAA;cAAAD,QAAA,CAAAO,EAAA,GAAAP,QAAA;cAExBf,cAAc,iCAAAuB,MAAA,CAEVR,QAAA,CAAAO,EAAA,YAAiBE,KAAK,GAAGT,QAAA,CAAAO,EAAA,CAAMG,OAAO,GAAG,eAAe,CAE5D,CAAC;YAAC;cAAAV,QAAA,CAAAC,IAAA;cAEFZ,iBAAiB,CAAC,KAAK,CAAC;cAAC,OAAAW,QAAA,CAAAW,MAAA;YAAA;cAAAX,QAAA,CAAAE,IAAA;cAAA;YAAA;cAEtB,IAAI1D,IAAI,aAAJA,IAAI,eAAJA,IAAI,CAAEqD,OAAO,EAAE;gBACxBZ,cAAc,CAACzC,IAAI,CAACqD,OAAO,CAAC;gBAC5BR,iBAAiB,CAAC,KAAK,CAAC;cAC1B,CAAC,MAAM;gBACLJ,cAAc,CAAC,EAAE,CAAC;gBAClBI,iBAAiB,CAAC,KAAK,CAAC;cAC1B;YAAC;YAAA;cAAA,OAAAW,QAAA,CAAAY,IAAA;UAAA;QAAA,GAAAjB,OAAA;MAAA,CACF;MAAA,gBAhCKL,WAAWA,CAAA;QAAA,OAAAC,IAAA,CAAAsB,KAAA,OAAAxE,SAAA;MAAA;IAAA,GAgChB;IAEDiD,WAAW,CAAC,CAAC;EACf,CAAC,EAAE,CACDV,iBAAiB,EACjBR,iBAAiB,EACjB/D,QAAQ,EACRoB,kBAAkB,EAClBS,mBAAmB,CACpB,CAAC;;EAEF;EACA,IAAM4E,YAAmC,GAAG,SAAtCA,YAAmCA,CAAIC,KAAK,EAAEC,IAAI,EAAK;IAAA,IAAAC,MAAA;IAC3D,IAAMC,IAAI,GAAGH,KAAiB;IAC9B,IAAM9D,KAAK,GAAGN,KAAK,CAACC,OAAO,CAACoE,IAAI,CAACG,aAAa,CAAC,GAC3CH,IAAI,CAACG,aAAa,GAClB,CAACH,IAAI,CAACG,aAAa,CAAC;IAExB,IAAMC,QAAQ,GAAGnE,KAAK,CAACoE,IAAI,CAAC,UAAC7E,IAAI;MAAA,OAAK,CAACA,IAAI,CAAC8E,MAAM;IAAA,EAAC;IACnD,IAAIF,QAAQ,EAAE;MACZ,IAAInE,KAAK,CAACX,MAAM,KAAK,CAAC,EAAE;QACtB,IAAME,IAAI,GAAGS,KAAK,CAAC,CAAC,CAA8B;QAClDzB,aAAa,aAAbA,aAAa,eAAbA,aAAa,CAAGgB,IAAI,CAACL,IAAI,EAAEK,IAAI,CAAC+E,KAAK,CAAC;MACxC;MACA;IACF;IAEA,IAAMC,SAAS,GAAG,EAAAP,MAAA,GAAAC,IAAI,CAAC,CAAC,CAAC,cAAAD,MAAA,uBAAPA,MAAA,CAASlE,KAAK,CAAC,GAAG,CAAC,CAACF,MAAM,CAACC,OAAO,CAAC,KAAI,EAAE;IAC3D,IAAI0E,SAAS,CAAClF,MAAM,KAAK,CAAC,EAAE;;IAE5B;IACA,IAAAmF,qBAAA,GAA+BvF,mBAAmB,CAACsF,SAAS,CAAC;MAA/CE,YAAY,GAAAD,qBAAA,CAAlBjF,IAAI;IACZ,IAAMmF,QAAQ,GAAGD,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEE,KAAK;IACpC,IAAMC,WAAW,GAAGH,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAE7B,OAAO;IAEzC7E,oBAAoB,aAApBA,oBAAoB,eAApBA,oBAAoB,CAAG;MACrBmB,IAAI,EAAEqF,SAAS;MACfI,KAAK,EAAED,QAAQ;MACf9B,OAAO,EAAEgC,WAAW;MACpBN,KAAK,EAAEG,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEH;IACvB,CAAC,CAAC;IAEF,IAAMO,YAAY,GAAG/G,YAAY,KAAKwB,SAAS;IAC/C,IAAI,CAACuF,YAAY,EAAE;MACjBjD,oBAAoB,CAAC,IAAI,CAAC;MAC1BR,oBAAoB,CAACmD,SAAS,CAAC;IACjC;IAEA,IAAIE,YAAY,EAAE;MAChBnG,WAAW,aAAXA,WAAW,eAAXA,WAAW,CACT2F,IAAI,CAAC,CAAC,CAAC,EACPQ,YAAY,CAAC7B,OAAO,EACpB6B,YAAY,CAACH,KACf,CAAC;IACH;EACF,CAAC;EAED,IAAMQ,YAAmC,GAAG,SAAtCA,YAAmCA,CAAIb,IAAI,EAAK;IACpD,IAAMc,QAAQ,GAAGd,IAAgB;IACjCzC,gBAAgB,CAACuD,QAAQ,CAAC;IAC1B1G,qBAAqB,aAArBA,qBAAqB,eAArBA,qBAAqB,CAAG0G,QAAQ,CAAC;EACnC,CAAC;EAED,oBACEhI,KAAA;IACEG,SAAS,EAAEV,IAAI,CACbwC,MAAM,CAACgG,SAAS,EAChB,CAACnG,WAAW,IAAIG,MAAM,CAACiG,kBAAkB,EACzC/H,SACF,CAAE;IACFC,KAAK,EAAA+H,aAAA,CAAAA,aAAA,CAAAA,aAAA,KACA/H,KAAK,GACJA,KAAK,aAALA,KAAK,eAALA,KAAK,CAAEgI,UAAU,GAChB;MACC,4BAA4B,EAAEhI,KAAK,CAACgI;IACtC,CAAC,GACD,CAAC,CAAC,GACFhI,KAAK,aAALA,KAAK,eAALA,KAAK,CAAEiI,eAAe,GACrB;MACC,4BAA4B,EAAEjI,KAAK,CAACiI;IACtC,CAAC,GACD,CAAC,CAAC,CACN;IAAA1E,QAAA,gBAEF7D,IAAA,CAACJ,sBAAsB;MACrBW,QAAQ,EAAEA,QAAS;MACnBC,cAAc,EAAEA,cAAe;MAC/BgI,YAAY,EACV3H,UAAU,IAAIyD,iBAAiB,IAAIQ,iBAAiB,GAChD,CAACR,iBAAiB,CAACgC,IAAI,CAAC,GAAG,CAAC,CAAC,GAC7B,EACL;MACDmC,YAAY,EAAE/D,kBAAmB;MACjCgE,QAAQ,EAAE1B,YAAa;MACvB2B,QAAQ,EAAEV,YAAa;MACvBjH,gBAAgB,EAAEA,gBAAiB;MACnCN,cAAc,EAAEA,cAAe;MAC/BkB,WAAW,EAAEA,WAAY;MACzBC,QAAQ,EAAEA,QAAS;MACnBC,YAAY,EAAEA,YAAa;MAC3B8G,KAAK,EAAExH,kBAAmB;MAC1Ba,SAAS,EAAEA,SAAU;MACrBC,MAAM,EAAEA;IAAO,CAChB,CAAC,EACDF,WAAW,iBACVhC,IAAA,CAACH,WAAW;MACVoB,YAAY,EAAE6D,iBAAiB,GAAGR,iBAAiB,GAAG,EAAG;MACzDY,WAAW,EAAEA,WAAY;MACzB2D,OAAO,EAAEvD,cAAe;MACxB3E,YAAY,EAAEA,YAAa;MAC3BF,aAAa,EAAEA,aAAc;MAC7BY,WAAW,EAAEA,WAAY;MACzByH,WAAW,EAAE,SAAAA,YAACzG,IAAI,EAAK;QACrB,IAAI,CAACA,IAAI,IAAIA,IAAI,CAACG,MAAM,KAAK,CAAC,EAAE,OAAOC,SAAS;QAChD,IAAAsG,qBAAA,GAAiB3G,mBAAmB,CAACC,IAAI,CAAC;UAAlCK,IAAI,GAAAqG,qBAAA,CAAJrG,IAAI;QACZ,OAAOA,IAAI,GACP;UAAEoF,KAAK,EAAEpF,IAAI,CAACoF,KAAK;UAAEzF,IAAI,EAAEK,IAAI,CAACL,IAAI;UAAE0D,OAAO,EAAErD,IAAI,CAACqD;QAAQ,CAAC,GAC7DtD,SAAS;MACf;IAAE,CACH,CACF;EAAA,CACE,CAAC;AAEV,CAAC;AAED,eAAetC,UAAU"}
|
|
@@ -8,7 +8,7 @@ export var useStyles = withBasicStyles(function () {
|
|
|
8
8
|
containerNoPreview: css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n height: auto;\n border: none;\n border-radius: 0;\n & > *:first-child {\n border-right: none;\n }\n "]))),
|
|
9
9
|
directoryPanel: css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n height: 100%;\n overflow: auto;\n border-right: 1px solid #e8e8e8;\n background: var(--folder-tree-directory-bg, #fafafa);\n "]))),
|
|
10
10
|
directoryTitle: css(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n padding: 12px 16px;\n font-weight: 600;\n font-size: 14px;\n border-bottom: 1px solid #e8e8e8;\n color: #333;\n "]))),
|
|
11
|
-
directoryTreeContent: css(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n padding: 4px 0;\n .ant-tree {\n background: transparent;\n }\n .ant-tree-switcher {\n margin-right: 0;\n }\n .ant-tree .ant-tree-node-content-wrapper {\n display: inline-flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n padding-left: 0;\n }\n .ant-tree .ant-tree-title {\n flex: 1;\n min-width: 0;\n }\n .ant-tree-directory .ant-tree-treenode {\n &::before {\n border-radius: 4px;\n }\n }\n "]))),
|
|
11
|
+
directoryTreeContent: css(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n padding: 4px 0;\n .ant-tree {\n background: transparent;\n }\n .ant-tree-switcher {\n margin-right: 0;\n }\n .ant-tree .ant-tree-node-content-wrapper {\n display: inline-flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n padding-left: 0;\n }\n .ant-tree .ant-tree-title {\n flex: 1;\n min-width: 0;\n }\n .ant-tree-directory .ant-tree-treenode {\n &::before {\n border-radius: 4px;\n }\n }\n /* \u62D6\u62FD\u6307\u793A\u7EBF\uFF1A\u84DD\u8272\u865A\u7EBF */\n .ant-tree .ant-tree-drop-indicator {\n background: transparent !important;\n border: 1px dashed #1677ff;\n height: 2px;\n }\n /* \u62D6\u62FD\u60AC\u505C\u76EE\u6807\uFF1A\u84DD\u8272\u865A\u7EBF\u8FB9\u6846 */\n .ant-tree .ant-tree-treenode.drag-over > .ant-tree-node-content-wrapper {\n outline: 1px dashed #1677ff;\n outline-offset: -1px;\n border-radius: 4px;\n }\n /* \u62D6\u62FD\u4E2D\u7684\u8282\u70B9\u534A\u900F\u660E */\n .ant-tree .ant-tree-treenode-dragging {\n opacity: 0.4;\n }\n "]))),
|
|
12
12
|
previewPanel: css(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral(["\n flex: 1;\n height: 100%;\n overflow: auto;\n display: flex;\n flex-direction: column;\n "]))),
|
|
13
13
|
previewTitle: css(_templateObject7 || (_templateObject7 = _taggedTemplateLiteral(["\n padding: 10px 16px;\n font-size: 13px;\n font-weight: 500;\n border-bottom: 1px solid #e8e8e8;\n display: flex;\n align-items: center;\n justify-content: space-between;\n color: #333;\n background: #fff;\n "]))),
|
|
14
14
|
previewContent: css(_templateObject8 || (_templateObject8 = _taggedTemplateLiteral(["\n flex: 1;\n overflow: auto;\n padding: 16px;\n font-size: 13px;\n line-height: 1.6;\n "]))),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["css","withBasicStyles","useStyles","container","_templateObject","_taggedTemplateLiteral","containerNoPreview","_templateObject2","directoryPanel","_templateObject3","directoryTitle","_templateObject4","directoryTreeContent","_templateObject5","previewPanel","_templateObject6","previewTitle","_templateObject7","previewContent","_templateObject8","emptyContainer","_templateObject9","loadingContainer","_templateObject10","treeNodeTitle","_templateObject11","moreIcon","_templateObject12","treeNodeTitleHover","_templateObject13","copyBtn","_templateObject14"],"sources":["../../../../src/components/FolderTree/styles.tsx"],"sourcesContent":["import { css } from \"@emotion/css\";\nimport { withBasicStyles } from \"@/styles/common\";\n\nexport const useStyles = withBasicStyles(() => ({\n container: css`\n display: flex;\n width: 100%;\n height: 500px;\n border: 1px solid #e8e8e8;\n border-radius: 8px;\n overflow: hidden;\n background: #fff;\n `,\n containerNoPreview: css`\n height: auto;\n border: none;\n border-radius: 0;\n & > *:first-child {\n border-right: none;\n }\n `,\n directoryPanel: css`\n height: 100%;\n overflow: auto;\n border-right: 1px solid #e8e8e8;\n background: var(--folder-tree-directory-bg, #fafafa);\n `,\n directoryTitle: css`\n padding: 12px 16px;\n font-weight: 600;\n font-size: 14px;\n border-bottom: 1px solid #e8e8e8;\n color: #333;\n `,\n directoryTreeContent: css`\n padding: 4px 0;\n .ant-tree {\n background: transparent;\n }\n .ant-tree-switcher {\n margin-right: 0;\n }\n .ant-tree .ant-tree-node-content-wrapper {\n display: inline-flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n padding-left: 0;\n }\n .ant-tree .ant-tree-title {\n flex: 1;\n min-width: 0;\n }\n .ant-tree-directory .ant-tree-treenode {\n &::before {\n border-radius: 4px;\n }\n }\n `,\n previewPanel: css`\n flex: 1;\n height: 100%;\n overflow: auto;\n display: flex;\n flex-direction: column;\n `,\n previewTitle: css`\n padding: 10px 16px;\n font-size: 13px;\n font-weight: 500;\n border-bottom: 1px solid #e8e8e8;\n display: flex;\n align-items: center;\n justify-content: space-between;\n color: #333;\n background: #fff;\n `,\n previewContent: css`\n flex: 1;\n overflow: auto;\n padding: 16px;\n font-size: 13px;\n line-height: 1.6;\n `,\n emptyContainer: css`\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n `,\n loadingContainer: css`\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n `,\n treeNodeTitle: css`\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding-right: 4px;\n `,\n moreIcon: css`\n opacity: 0;\n cursor: pointer;\n padding: 2px 4px;\n border-radius: 4px;\n color: #999;\n font-size: 14px;\n transition: all 0.2s;\n &:hover {\n color: #333;\n background: rgba(0, 0, 0, 0.04);\n }\n `,\n treeNodeTitleHover: css`\n &:hover .folder-tree-more-icon {\n opacity: 1;\n }\n `,\n copyBtn: css`\n cursor: pointer;\n color: #999;\n font-size: 14px;\n &:hover {\n color: #1677ff;\n }\n `,\n}));\n"],"mappings":";;AAAA,SAASA,GAAG,QAAQ,cAAc;AAClC,SAASC,eAAe;AAExB,OAAO,IAAMC,SAAS,GAAGD,eAAe,CAAC;EAAA,OAAO;IAC9CE,SAAS,EAAEH,GAAG,CAAAI,eAAA,KAAAA,eAAA,GAAAC,sBAAA,6KAQb;IACDC,kBAAkB,EAAEN,GAAG,CAAAO,gBAAA,KAAAA,gBAAA,GAAAF,sBAAA,oIAOtB;IACDG,cAAc,EAAER,GAAG,CAAAS,gBAAA,KAAAA,gBAAA,GAAAJ,sBAAA,qJAKlB;IACDK,cAAc,EAAEV,GAAG,CAAAW,gBAAA,KAAAA,gBAAA,GAAAN,sBAAA,2IAMlB;IACDO,oBAAoB,EAAEZ,GAAG,CAAAa,gBAAA,KAAAA,gBAAA,GAAAR,sBAAA,
|
|
1
|
+
{"version":3,"names":["css","withBasicStyles","useStyles","container","_templateObject","_taggedTemplateLiteral","containerNoPreview","_templateObject2","directoryPanel","_templateObject3","directoryTitle","_templateObject4","directoryTreeContent","_templateObject5","previewPanel","_templateObject6","previewTitle","_templateObject7","previewContent","_templateObject8","emptyContainer","_templateObject9","loadingContainer","_templateObject10","treeNodeTitle","_templateObject11","moreIcon","_templateObject12","treeNodeTitleHover","_templateObject13","copyBtn","_templateObject14"],"sources":["../../../../src/components/FolderTree/styles.tsx"],"sourcesContent":["import { css } from \"@emotion/css\";\nimport { withBasicStyles } from \"@/styles/common\";\n\nexport const useStyles = withBasicStyles(() => ({\n container: css`\n display: flex;\n width: 100%;\n height: 500px;\n border: 1px solid #e8e8e8;\n border-radius: 8px;\n overflow: hidden;\n background: #fff;\n `,\n containerNoPreview: css`\n height: auto;\n border: none;\n border-radius: 0;\n & > *:first-child {\n border-right: none;\n }\n `,\n directoryPanel: css`\n height: 100%;\n overflow: auto;\n border-right: 1px solid #e8e8e8;\n background: var(--folder-tree-directory-bg, #fafafa);\n `,\n directoryTitle: css`\n padding: 12px 16px;\n font-weight: 600;\n font-size: 14px;\n border-bottom: 1px solid #e8e8e8;\n color: #333;\n `,\n directoryTreeContent: css`\n padding: 4px 0;\n .ant-tree {\n background: transparent;\n }\n .ant-tree-switcher {\n margin-right: 0;\n }\n .ant-tree .ant-tree-node-content-wrapper {\n display: inline-flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n padding-left: 0;\n }\n .ant-tree .ant-tree-title {\n flex: 1;\n min-width: 0;\n }\n .ant-tree-directory .ant-tree-treenode {\n &::before {\n border-radius: 4px;\n }\n }\n /* 拖拽指示线:蓝色虚线 */\n .ant-tree .ant-tree-drop-indicator {\n background: transparent !important;\n border: 1px dashed #1677ff;\n height: 2px;\n }\n /* 拖拽悬停目标:蓝色虚线边框 */\n .ant-tree .ant-tree-treenode.drag-over > .ant-tree-node-content-wrapper {\n outline: 1px dashed #1677ff;\n outline-offset: -1px;\n border-radius: 4px;\n }\n /* 拖拽中的节点半透明 */\n .ant-tree .ant-tree-treenode-dragging {\n opacity: 0.4;\n }\n `,\n previewPanel: css`\n flex: 1;\n height: 100%;\n overflow: auto;\n display: flex;\n flex-direction: column;\n `,\n previewTitle: css`\n padding: 10px 16px;\n font-size: 13px;\n font-weight: 500;\n border-bottom: 1px solid #e8e8e8;\n display: flex;\n align-items: center;\n justify-content: space-between;\n color: #333;\n background: #fff;\n `,\n previewContent: css`\n flex: 1;\n overflow: auto;\n padding: 16px;\n font-size: 13px;\n line-height: 1.6;\n `,\n emptyContainer: css`\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n `,\n loadingContainer: css`\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n `,\n treeNodeTitle: css`\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding-right: 4px;\n `,\n moreIcon: css`\n opacity: 0;\n cursor: pointer;\n padding: 2px 4px;\n border-radius: 4px;\n color: #999;\n font-size: 14px;\n transition: all 0.2s;\n &:hover {\n color: #333;\n background: rgba(0, 0, 0, 0.04);\n }\n `,\n treeNodeTitleHover: css`\n &:hover .folder-tree-more-icon {\n opacity: 1;\n }\n `,\n copyBtn: css`\n cursor: pointer;\n color: #999;\n font-size: 14px;\n &:hover {\n color: #1677ff;\n }\n `,\n}));\n"],"mappings":";;AAAA,SAASA,GAAG,QAAQ,cAAc;AAClC,SAASC,eAAe;AAExB,OAAO,IAAMC,SAAS,GAAGD,eAAe,CAAC;EAAA,OAAO;IAC9CE,SAAS,EAAEH,GAAG,CAAAI,eAAA,KAAAA,eAAA,GAAAC,sBAAA,6KAQb;IACDC,kBAAkB,EAAEN,GAAG,CAAAO,gBAAA,KAAAA,gBAAA,GAAAF,sBAAA,oIAOtB;IACDG,cAAc,EAAER,GAAG,CAAAS,gBAAA,KAAAA,gBAAA,GAAAJ,sBAAA,qJAKlB;IACDK,cAAc,EAAEV,GAAG,CAAAW,gBAAA,KAAAA,gBAAA,GAAAN,sBAAA,2IAMlB;IACDO,oBAAoB,EAAEZ,GAAG,CAAAa,gBAAA,KAAAA,gBAAA,GAAAR,sBAAA,4mCAwCxB;IACDS,YAAY,EAAEd,GAAG,CAAAe,gBAAA,KAAAA,gBAAA,GAAAV,sBAAA,mHAMhB;IACDW,YAAY,EAAEhB,GAAG,CAAAiB,gBAAA,KAAAA,gBAAA,GAAAZ,sBAAA,qPAUhB;IACDa,cAAc,EAAElB,GAAG,CAAAmB,gBAAA,KAAAA,gBAAA,GAAAd,sBAAA,gHAMlB;IACDe,cAAc,EAAEpB,GAAG,CAAAqB,gBAAA,KAAAA,gBAAA,GAAAhB,sBAAA,2GAKlB;IACDiB,gBAAgB,EAAEtB,GAAG,CAAAuB,iBAAA,KAAAA,iBAAA,GAAAlB,sBAAA,2GAKpB;IACDmB,aAAa,EAAExB,GAAG,CAAAyB,iBAAA,KAAAA,iBAAA,GAAApB,sBAAA,wHAKjB;IACDqB,QAAQ,EAAE1B,GAAG,CAAA2B,iBAAA,KAAAA,iBAAA,GAAAtB,sBAAA,wPAYZ;IACDuB,kBAAkB,EAAE5B,GAAG,CAAA6B,iBAAA,KAAAA,iBAAA,GAAAxB,sBAAA,4EAItB;IACDyB,OAAO,EAAE9B,GAAG,CAAA+B,iBAAA,KAAAA,iBAAA,GAAA1B,sBAAA;EAQd,CAAC;AAAA,CAAC,CAAC"}
|
|
@@ -80,4 +80,27 @@ export interface FolderTreeProps {
|
|
|
80
80
|
switcherIcon?: React.ReactNode | ((props: any) => React.ReactNode);
|
|
81
81
|
/** 是否显示文件预览面板,默认 true */
|
|
82
82
|
showPreview?: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* 拖拽模式
|
|
85
|
+
* - true | 'file': 只有文件(叶子节点)可拖拽
|
|
86
|
+
* - 'folder': 只有文件夹可拖拽
|
|
87
|
+
* - 'all': 文件和文件夹都可拖拽
|
|
88
|
+
* - false | undefined: 禁用拖拽
|
|
89
|
+
*/
|
|
90
|
+
draggable?: boolean | "file" | "folder" | "all";
|
|
91
|
+
/** 拖拽完成回调 */
|
|
92
|
+
onDrop?: (info: {
|
|
93
|
+
/** 被拖拽节点的文件名 */
|
|
94
|
+
fileName: React.ReactNode;
|
|
95
|
+
/** 被拖拽节点的 extra 数据 */
|
|
96
|
+
extra: any;
|
|
97
|
+
/** 拖拽前的完整路径 */
|
|
98
|
+
oldPath: string;
|
|
99
|
+
/** 拖拽完成后的新路径 */
|
|
100
|
+
newPath: string;
|
|
101
|
+
/** 被拖拽的节点 */
|
|
102
|
+
dragNode: FolderTreeData;
|
|
103
|
+
/** 目标节点 */
|
|
104
|
+
dropNode: FolderTreeData;
|
|
105
|
+
}) => void;
|
|
83
106
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["../../../../src/components/FolderTree/types.ts"],"sourcesContent":["import type { DropdownProps } from \"antd\";\nimport type React from \"react\";\n\n/** 文件树节点数据 */\nexport interface FolderTreeData<T = any> {\n title: React.ReactNode;\n path: string;\n content?: string;\n extra?: T;\n children?: FolderTreeData<T>[];\n}\n\n/** 文件内容加载服务 */\nexport interface FileContentService {\n loadFileContent(filePath: string): Promise<string>;\n}\n\n/** FolderTree 组件属性 */\nexport interface FolderTreeProps {\n /** 自定义类名 */\n className?: string;\n /** 自定义样式 */\n style?: React.CSSProperties;\n\n /** 树形数据 */\n treeData: FolderTreeData[];\n\n /** 自定义文件/文件夹图标,false 禁用图标 */\n directoryIcons?:\n | false\n | Record<\"directory\" | string, React.ReactNode | (() => React.ReactNode)>;\n\n /** 是否可选中文件 */\n selectable?: boolean;\n /** 受控:当前选中的文件路径 */\n selectedFile?: string[];\n /** 默认选中的文件路径 */\n defaultSelectedFile?: string[];\n /** 选中文件变化回调 */\n onSelectedFileChange?: (file: {\n path: string[];\n title?: React.ReactNode;\n content?: string;\n extra?: any;\n }) => void;\n\n /** 受控:展开的路径 */\n expandedPaths?: string[];\n /** 默认展开的路径 */\n defaultExpandedPaths?: string[];\n /** 默认是否展开所有节点 */\n defaultExpandAll?: boolean;\n /** 展开路径变化回调 */\n onExpandedPathsChange?: (paths: string[]) => void;\n\n /** 目录树面板宽度 */\n directoryTreeWidth?: number | string;\n\n /** 文件内容加载服务 */\n fileContentService?: FileContentService;\n\n /** 空状态渲染 */\n emptyRender?: false | React.ReactNode | (() => React.ReactNode);\n /** 自定义文件预览渲染 */\n previewRender?:\n | React.ReactNode\n | ((\n file: {\n content?: string;\n path: string[];\n title?: React.ReactNode;\n language: string;\n },\n info: { originNode: React.ReactNode },\n ) => React.ReactNode);\n\n /** 自定义目录标题 */\n directoryTitle?: false | React.ReactNode | (() => React.ReactNode);\n /** 自定义预览标题 */\n previewTitle?:\n | false\n | React.ReactNode\n | ((info: {\n title: React.ReactNode;\n path: string[];\n content: string;\n }) => React.ReactNode);\n\n /** 文件点击回调 */\n onFileClick?: (filePath: string, content?: string, extra?: any) => void;\n /** 文件夹点击回调 */\n onFolderClick?: (folderPath: string, extra?: any) => void;\n\n /** 更多操作菜单,传入节点返回 Dropdown menu 配置 */\n moreActions?: (node: FolderTreeData) => DropdownProps[\"menu\"];\n\n /** 是否显示连接线 */\n showLine?: boolean | { showLeafIcon?: boolean | React.ReactNode };\n /** 自定义展开/收起图标 */\n switcherIcon?: React.ReactNode | ((props: any) => React.ReactNode);\n\n /** 是否显示文件预览面板,默认 true */\n showPreview?: boolean;\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"names":[],"sources":["../../../../src/components/FolderTree/types.ts"],"sourcesContent":["import type { DropdownProps } from \"antd\";\nimport type React from \"react\";\n\n/** 文件树节点数据 */\nexport interface FolderTreeData<T = any> {\n title: React.ReactNode;\n path: string;\n content?: string;\n extra?: T;\n children?: FolderTreeData<T>[];\n}\n\n/** 文件内容加载服务 */\nexport interface FileContentService {\n loadFileContent(filePath: string): Promise<string>;\n}\n\n/** FolderTree 组件属性 */\nexport interface FolderTreeProps {\n /** 自定义类名 */\n className?: string;\n /** 自定义样式 */\n style?: React.CSSProperties;\n\n /** 树形数据 */\n treeData: FolderTreeData[];\n\n /** 自定义文件/文件夹图标,false 禁用图标 */\n directoryIcons?:\n | false\n | Record<\"directory\" | string, React.ReactNode | (() => React.ReactNode)>;\n\n /** 是否可选中文件 */\n selectable?: boolean;\n /** 受控:当前选中的文件路径 */\n selectedFile?: string[];\n /** 默认选中的文件路径 */\n defaultSelectedFile?: string[];\n /** 选中文件变化回调 */\n onSelectedFileChange?: (file: {\n path: string[];\n title?: React.ReactNode;\n content?: string;\n extra?: any;\n }) => void;\n\n /** 受控:展开的路径 */\n expandedPaths?: string[];\n /** 默认展开的路径 */\n defaultExpandedPaths?: string[];\n /** 默认是否展开所有节点 */\n defaultExpandAll?: boolean;\n /** 展开路径变化回调 */\n onExpandedPathsChange?: (paths: string[]) => void;\n\n /** 目录树面板宽度 */\n directoryTreeWidth?: number | string;\n\n /** 文件内容加载服务 */\n fileContentService?: FileContentService;\n\n /** 空状态渲染 */\n emptyRender?: false | React.ReactNode | (() => React.ReactNode);\n /** 自定义文件预览渲染 */\n previewRender?:\n | React.ReactNode\n | ((\n file: {\n content?: string;\n path: string[];\n title?: React.ReactNode;\n language: string;\n },\n info: { originNode: React.ReactNode },\n ) => React.ReactNode);\n\n /** 自定义目录标题 */\n directoryTitle?: false | React.ReactNode | (() => React.ReactNode);\n /** 自定义预览标题 */\n previewTitle?:\n | false\n | React.ReactNode\n | ((info: {\n title: React.ReactNode;\n path: string[];\n content: string;\n }) => React.ReactNode);\n\n /** 文件点击回调 */\n onFileClick?: (filePath: string, content?: string, extra?: any) => void;\n /** 文件夹点击回调 */\n onFolderClick?: (folderPath: string, extra?: any) => void;\n\n /** 更多操作菜单,传入节点返回 Dropdown menu 配置 */\n moreActions?: (node: FolderTreeData) => DropdownProps[\"menu\"];\n\n /** 是否显示连接线 */\n showLine?: boolean | { showLeafIcon?: boolean | React.ReactNode };\n /** 自定义展开/收起图标 */\n switcherIcon?: React.ReactNode | ((props: any) => React.ReactNode);\n\n /** 是否显示文件预览面板,默认 true */\n showPreview?: boolean;\n\n /**\n * 拖拽模式\n * - true | 'file': 只有文件(叶子节点)可拖拽\n * - 'folder': 只有文件夹可拖拽\n * - 'all': 文件和文件夹都可拖拽\n * - false | undefined: 禁用拖拽\n */\n draggable?: boolean | \"file\" | \"folder\" | \"all\";\n\n /** 拖拽完成回调 */\n onDrop?: (info: {\n /** 被拖拽节点的文件名 */\n fileName: React.ReactNode;\n /** 被拖拽节点的 extra 数据 */\n extra: any;\n /** 拖拽前的完整路径 */\n oldPath: string;\n /** 拖拽完成后的新路径 */\n newPath: string;\n /** 被拖拽的节点 */\n dragNode: FolderTreeData;\n /** 目标节点 */\n dropNode: FolderTreeData;\n }) => void;\n}\n"],"mappings":""}
|