@ai-group/chat-sdk 3.5.9 → 3.5.11
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.js +12 -2
- package/dist/cjs/components/FolderTree/DirectoryTree.js.map +2 -2
- package/dist/cjs/components/FolderTree/index.js +37 -19
- package/dist/cjs/components/FolderTree/index.js.map +2 -2
- package/dist/cjs/components/FolderTree/types.d.ts +3 -0
- package/dist/cjs/components/FolderTree/types.js.map +1 -1
- package/dist/esm/components/FolderTree/DirectoryTree.js +1 -1
- package/dist/esm/components/FolderTree/DirectoryTree.js.map +1 -1
- package/dist/esm/components/FolderTree/index.js +40 -16
- package/dist/esm/components/FolderTree/index.js.map +1 -1
- package/dist/esm/components/FolderTree/types.d.ts +3 -0
- package/dist/esm/components/FolderTree/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -65,7 +65,7 @@ var DirectoryTreeComponent = ({
|
|
|
65
65
|
}) => {
|
|
66
66
|
const styles = (0, import_styles.useStyles)();
|
|
67
67
|
const isFolder = (node) => {
|
|
68
|
-
return !!node.children && node.children.length > 0;
|
|
68
|
+
return !!node.children && node.children.length > 0 || node.type === "folder";
|
|
69
69
|
};
|
|
70
70
|
const getIcon = (0, import_react.useCallback)(
|
|
71
71
|
(node) => {
|
|
@@ -179,7 +179,17 @@ var DirectoryTreeComponent = ({
|
|
|
179
179
|
},
|
|
180
180
|
[expandedKeys, onExpand]
|
|
181
181
|
);
|
|
182
|
-
const {
|
|
182
|
+
const {
|
|
183
|
+
onDragStart,
|
|
184
|
+
onDragEnd,
|
|
185
|
+
onItemDragEnter,
|
|
186
|
+
onItemDragOver,
|
|
187
|
+
onItemDragLeave,
|
|
188
|
+
onItemDrop,
|
|
189
|
+
onContainerDragOver,
|
|
190
|
+
onContainerDrop,
|
|
191
|
+
canDragNode
|
|
192
|
+
} = (0, import_useFolderDrag.useFolderDrag)({
|
|
183
193
|
dragMode,
|
|
184
194
|
onDrop: handleDragDrop,
|
|
185
195
|
onDragEnterExpand: handleDragEnterExpand
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/FolderTree/DirectoryTree.tsx"],
|
|
4
|
-
"sourcesContent": ["import React, { useCallback, useMemo } from \"react\";\nimport { Tree, Dropdown, Input } from \"antd\";\nimport { FileOutlined, FolderOutlined, MoreOutlined } from \"@ant-design/icons\";\nimport type { TreeProps } from \"antd\";\nimport type { DataNode } from \"antd/es/tree\";\nimport clsx from \"clsx\";\nimport type {\n FolderTreeData,\n FolderTreeProps,\n EditNodeInfo,\n CreateNodeContext,\n} from \"./types\";\nimport { useStyles } from \"./styles\";\nimport { useFolderDrag, type DropPosition } from \"./useFolderDrag\";\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 editNode?: EditNodeInfo | null;\n /** 编辑值变化回调 */\n onEditValueChange?: (value: string) => void;\n /** 编辑确认回调 */\n onEditConfirm?: () => void;\n /** 编辑取消回调 */\n onEditCancel?: () => void;\n /** 新建上下文 */\n createInfo?: CreateNodeContext | null;\n /** 开始重命名回调(由父组件注入) */\n onStartRename?: (fullPath: string, node: FolderTreeData) => void;\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 editNode,\n onEditValueChange,\n onEditConfirm,\n onEditCancel,\n createInfo,\n onStartRename,\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 renderInlineInput = useCallback(\n (value: string) => (\n <span className={styles.treeNodeTitle}>\n <Input\n size=\"small\"\n value={value}\n onChange={(e) => onEditValueChange?.(e.target.value)}\n onBlur={() => onEditConfirm?.()}\n onPressEnter={() => onEditConfirm?.()}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n e.stopPropagation();\n onEditCancel?.();\n }\n }}\n autoFocus\n className={styles.inlineInput}\n onClick={(e) => e.stopPropagation()}\n onSelect={(e) => e.stopPropagation()}\n onFocus={(e) => e.stopPropagation()}\n />\n </span>\n ),\n [onEditValueChange, onEditConfirm, onEditCancel, styles],\n );\n\n // ====== 拖拽模式 ======\n const dragMode = draggable === true ? \"file\" : draggable || false;\n\n // ====== 自定义拖拽 hook ======\n const handleDragDrop = useCallback(\n (dragNode: DataNode, dropNode: DataNode, dropPosition: DropPosition) => {\n const dragNd = dragNode as DataNode & { _originalNode?: FolderTreeData };\n const dropNd = dropNode as DataNode & { _originalNode?: FolderTreeData };\n const originalDragNode = dragNd._originalNode;\n const originalDropNode = dropNd._originalNode;\n if (!originalDragNode) return;\n\n const dragKey = String(dragNode.key);\n const dropKey = String(dropNode.key);\n const dragFileName = originalDragNode.path;\n let newPath: string;\n\n // 拖到底部 drop zone:放在根级别末尾\n if (!originalDropNode && dropKey === \"__bottom_placeholder__\") {\n newPath = dragFileName;\n onDrop?.({\n fileName: originalDragNode.title,\n extra: originalDragNode.extra,\n oldPath: dragKey,\n newPath,\n dragNode: originalDragNode,\n dropNode: { title: \"\", path: \"\" },\n });\n return;\n }\n\n if (!originalDropNode) return;\n\n if (!dropNode.isLeaf && dropPosition === 0) {\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 handleDragEnterExpand = useCallback(\n (nodeKey: string) => {\n const isExpanded = expandedKeys?.includes(nodeKey);\n if (!isExpanded) {\n onExpand?.([...(expandedKeys || []), nodeKey], {\n node: null as any,\n expanded: true,\n nativeEvent: null as any,\n });\n }\n },\n [expandedKeys, onExpand],\n );\n\n const { onDragStart, onDragEnd, onItemDragEnter, onItemDragOver, onItemDragLeave, onItemDrop, onContainerDragOver, onContainerDrop, canDragNode } =\n useFolderDrag({\n dragMode,\n onDrop: handleDragDrop,\n onDragEnterExpand: handleDragEnterExpand,\n });\n\n // ====== 转换树数据 ======\n // 注意:convertToTreeData 不依赖拖拽状态,拖拽效果通过 DOM 操作实现\n const convertToTreeData = useCallback(\n (\n nodes: FolderTreeData[],\n parentSegments: string[] = [],\n parentKey: string = \"\",\n ): DataNode[] => {\n const result = nodes.map((node) => {\n const pathSegments = buildPathSegments(node, parentSegments);\n const fullPath = pathSegments.join(\"/\").replace(/^\\/+/, \"\");\n\n const isEditing = editNode && editNode.key === fullPath;\n\n const nodeChildren = node.children\n ? convertToTreeData(node.children, pathSegments, fullPath)\n : undefined;\n\n const baseNode: any = {\n key: fullPath,\n path: fullPath,\n pathSegments,\n icon: getIcon(node),\n isLeaf: !isFolder(node),\n _originalNode: node,\n children: nodeChildren,\n };\n\n // 编辑态:直接渲染 inline input\n if (isEditing) {\n baseNode.title = renderInlineInput(editNode!.currentValue);\n return baseNode;\n }\n\n // title 内容(按钮、菜单等)\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 startRename: () => onStartRename?.(fullPath, node),\n })}\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 // 启用拖拽时:在 title 外层包裹具有 data-node-key 属性的容器,\n // 用于 DOM 查询和事件绑定。拖拽状态通过 CSS class 控制。\n if (dragMode) {\n const nodeData = baseNode as DataNode & {\n _isTempNode?: boolean;\n };\n const draggableDiv = canDragNode(nodeData);\n\n baseNode.title = (\n <div\n className={clsx(\n styles.treeNodeWrapper,\n draggableDiv && styles.dragNodeHandle,\n )}\n data-node-key={fullPath}\n draggable={draggableDiv}\n onDragStart={draggableDiv ? (e) => onDragStart(e, baseNode) : undefined}\n onDragEnd={draggableDiv ? onDragEnd : undefined}\n onDragEnter={(e) => onItemDragEnter(e, baseNode)}\n onDragOver={(e) => onItemDragOver(e, baseNode)}\n onDragLeave={onItemDragLeave}\n onDrop={(e) => onItemDrop(e, baseNode)}\n >\n {titleContent}\n </div>\n );\n } else {\n baseNode.title = titleContent;\n }\n\n return baseNode;\n });\n\n // 新建模式:在目标父节点下插入临时节点\n if (createInfo && editNode && editNode.mode === \"create\") {\n const targetParentKey = createInfo.parentKey;\n if (\n targetParentKey === parentKey ||\n (targetParentKey === \"\" && parentKey === \"\") ||\n (targetParentKey === \"/\" && parentKey === \"\")\n ) {\n const tempNode: any = {\n key: editNode.key,\n title: renderInlineInput(editNode.currentValue),\n icon:\n createInfo.type === \"folder\" ? (\n <FolderOutlined />\n ) : (\n <FileOutlined />\n ),\n isLeaf: createInfo.type === \"file\",\n path: editNode.key,\n pathSegments: [editNode.key],\n _originalNode: null,\n _isTempNode: true,\n };\n result.push(tempNode);\n }\n }\n\n return result;\n },\n [\n buildPathSegments,\n getIcon,\n moreActions,\n styles,\n editNode,\n renderInlineInput,\n createInfo,\n onStartRename,\n dragMode,\n canDragNode,\n onDragStart,\n onDragEnd,\n onItemDragEnter,\n onItemDragOver,\n onItemDragLeave,\n onItemDrop,\n ],\n );\n\n const treeDataConverted = useMemo(\n () => convertToTreeData(treeData, [], \"\"),\n [treeData, convertToTreeData],\n );\n\n const handleSelect: TreeProps[\"onSelect\"] = useCallback(\n (keys: any, info: any) => {\n // 编辑态不响应选中\n if (editNode) return;\n // 临时节点不可选中\n const node = info.node as DataNode & { _isTempNode?: boolean };\n if (node._isTempNode) return;\n // 点击 moreActions 区域不触发选中\n const target = info.nativeEvent?.target as HTMLElement | null;\n if (\n target &&\n (target.closest(\".folder-tree-more-icon\") ||\n target.closest(\".ant-dropdown\"))\n ) {\n return;\n }\n onSelect?.(keys, info);\n },\n [onSelect, editNode],\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 onDragOver={dragMode ? onContainerDragOver : undefined}\n onDrop={dragMode ? onContainerDrop : undefined}\n >\n <AntDirectoryTree\n style={\n {\n \"--ant-tree-directory-node-selected-bg\": \"rgba(0,0,0,0.03)\",\n \"--ant-tree-directory-node-selected-color\": \"#1a1c1e\",\n } as React.CSSProperties\n }\n treeData={treeDataConverted}\n selectedKeys={selectedKeys}\n expandedKeys={expandedKeys}\n onSelect={handleSelect}\n onExpand={onExpand}\n multiple={false}\n blockNode\n showLine={showLine as any}\n switcherIcon={switcherIcon}\n defaultExpandAll={defaultExpandAll}\n draggable={false}\n />\n </div>\n </div>\n );\n};\n\nexport default DirectoryTreeComponent;"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA4C;AAC5C,kBAAsC;AACtC,mBAA2D;AAG3D,kBAAiB;AAOjB,oBAA0B;AAC1B,2BAAiD;
|
|
4
|
+
"sourcesContent": ["import React, { useCallback, useMemo } from \"react\";\nimport { Tree, Dropdown, Input } from \"antd\";\nimport { FileOutlined, FolderOutlined, MoreOutlined } from \"@ant-design/icons\";\nimport type { TreeProps } from \"antd\";\nimport type { DataNode } from \"antd/es/tree\";\nimport clsx from \"clsx\";\nimport type {\n FolderTreeData,\n FolderTreeProps,\n EditNodeInfo,\n CreateNodeContext,\n} from \"./types\";\nimport { useStyles } from \"./styles\";\nimport { useFolderDrag, type DropPosition } from \"./useFolderDrag\";\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 editNode?: EditNodeInfo | null;\n /** 编辑值变化回调 */\n onEditValueChange?: (value: string) => void;\n /** 编辑确认回调 */\n onEditConfirm?: () => void;\n /** 编辑取消回调 */\n onEditCancel?: () => void;\n /** 新建上下文 */\n createInfo?: CreateNodeContext | null;\n /** 开始重命名回调(由父组件注入) */\n onStartRename?: (fullPath: string, node: FolderTreeData) => void;\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 editNode,\n onEditValueChange,\n onEditConfirm,\n onEditCancel,\n createInfo,\n onStartRename,\n}) => {\n const styles = useStyles();\n\n const isFolder = (node: FolderTreeData): boolean => {\n return (\n (!!node.children && node.children.length > 0) || node.type === \"folder\"\n );\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 renderInlineInput = useCallback(\n (value: string) => (\n <span className={styles.treeNodeTitle}>\n <Input\n size=\"small\"\n value={value}\n onChange={(e) => onEditValueChange?.(e.target.value)}\n onBlur={() => onEditConfirm?.()}\n onPressEnter={() => onEditConfirm?.()}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n e.stopPropagation();\n onEditCancel?.();\n }\n }}\n autoFocus\n className={styles.inlineInput}\n onClick={(e) => e.stopPropagation()}\n onSelect={(e) => e.stopPropagation()}\n onFocus={(e) => e.stopPropagation()}\n />\n </span>\n ),\n [onEditValueChange, onEditConfirm, onEditCancel, styles],\n );\n\n // ====== 拖拽模式 ======\n const dragMode = draggable === true ? \"file\" : draggable || false;\n\n // ====== 自定义拖拽 hook ======\n const handleDragDrop = useCallback(\n (dragNode: DataNode, dropNode: DataNode, dropPosition: DropPosition) => {\n const dragNd = dragNode as DataNode & { _originalNode?: FolderTreeData };\n const dropNd = dropNode as DataNode & { _originalNode?: FolderTreeData };\n const originalDragNode = dragNd._originalNode;\n const originalDropNode = dropNd._originalNode;\n if (!originalDragNode) return;\n\n const dragKey = String(dragNode.key);\n const dropKey = String(dropNode.key);\n const dragFileName = originalDragNode.path;\n let newPath: string;\n\n // 拖到底部 drop zone:放在根级别末尾\n if (!originalDropNode && dropKey === \"__bottom_placeholder__\") {\n newPath = dragFileName;\n onDrop?.({\n fileName: originalDragNode.title,\n extra: originalDragNode.extra,\n oldPath: dragKey,\n newPath,\n dragNode: originalDragNode,\n dropNode: { title: \"\", path: \"\" },\n });\n return;\n }\n\n if (!originalDropNode) return;\n\n if (!dropNode.isLeaf && dropPosition === 0) {\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 handleDragEnterExpand = useCallback(\n (nodeKey: string) => {\n const isExpanded = expandedKeys?.includes(nodeKey);\n if (!isExpanded) {\n onExpand?.([...(expandedKeys || []), nodeKey], {\n node: null as any,\n expanded: true,\n nativeEvent: null as any,\n });\n }\n },\n [expandedKeys, onExpand],\n );\n\n const {\n onDragStart,\n onDragEnd,\n onItemDragEnter,\n onItemDragOver,\n onItemDragLeave,\n onItemDrop,\n onContainerDragOver,\n onContainerDrop,\n canDragNode,\n } = useFolderDrag({\n dragMode,\n onDrop: handleDragDrop,\n onDragEnterExpand: handleDragEnterExpand,\n });\n\n // ====== 转换树数据 ======\n // 注意:convertToTreeData 不依赖拖拽状态,拖拽效果通过 DOM 操作实现\n const convertToTreeData = useCallback(\n (\n nodes: FolderTreeData[],\n parentSegments: string[] = [],\n parentKey: string = \"\",\n ): DataNode[] => {\n const result = nodes.map((node) => {\n const pathSegments = buildPathSegments(node, parentSegments);\n const fullPath = pathSegments.join(\"/\").replace(/^\\/+/, \"\");\n\n const isEditing = editNode && editNode.key === fullPath;\n\n const nodeChildren = node.children\n ? convertToTreeData(node.children, pathSegments, fullPath)\n : undefined;\n\n const baseNode: any = {\n key: fullPath,\n path: fullPath,\n pathSegments,\n icon: getIcon(node),\n isLeaf: !isFolder(node),\n _originalNode: node,\n children: nodeChildren,\n };\n\n // 编辑态:直接渲染 inline input\n if (isEditing) {\n baseNode.title = renderInlineInput(editNode!.currentValue);\n return baseNode;\n }\n\n // title 内容(按钮、菜单等)\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 startRename: () => onStartRename?.(fullPath, node),\n })}\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 // 启用拖拽时:在 title 外层包裹具有 data-node-key 属性的容器,\n // 用于 DOM 查询和事件绑定。拖拽状态通过 CSS class 控制。\n if (dragMode) {\n const nodeData = baseNode as DataNode & {\n _isTempNode?: boolean;\n };\n const draggableDiv = canDragNode(nodeData);\n\n baseNode.title = (\n <div\n className={clsx(\n styles.treeNodeWrapper,\n draggableDiv && styles.dragNodeHandle,\n )}\n data-node-key={fullPath}\n draggable={draggableDiv}\n onDragStart={\n draggableDiv ? (e) => onDragStart(e, baseNode) : undefined\n }\n onDragEnd={draggableDiv ? onDragEnd : undefined}\n onDragEnter={(e) => onItemDragEnter(e, baseNode)}\n onDragOver={(e) => onItemDragOver(e, baseNode)}\n onDragLeave={onItemDragLeave}\n onDrop={(e) => onItemDrop(e, baseNode)}\n >\n {titleContent}\n </div>\n );\n } else {\n baseNode.title = titleContent;\n }\n\n return baseNode;\n });\n\n // 新建模式:在目标父节点下插入临时节点\n if (createInfo && editNode && editNode.mode === \"create\") {\n const targetParentKey = createInfo.parentKey;\n if (\n targetParentKey === parentKey ||\n (targetParentKey === \"\" && parentKey === \"\") ||\n (targetParentKey === \"/\" && parentKey === \"\")\n ) {\n const tempNode: any = {\n key: editNode.key,\n title: renderInlineInput(editNode.currentValue),\n icon:\n createInfo.type === \"folder\" ? (\n <FolderOutlined />\n ) : (\n <FileOutlined />\n ),\n isLeaf: createInfo.type === \"file\",\n path: editNode.key,\n pathSegments: [editNode.key],\n _originalNode: null,\n _isTempNode: true,\n };\n result.push(tempNode);\n }\n }\n\n return result;\n },\n [\n buildPathSegments,\n getIcon,\n moreActions,\n styles,\n editNode,\n renderInlineInput,\n createInfo,\n onStartRename,\n dragMode,\n canDragNode,\n onDragStart,\n onDragEnd,\n onItemDragEnter,\n onItemDragOver,\n onItemDragLeave,\n onItemDrop,\n ],\n );\n\n const treeDataConverted = useMemo(\n () => convertToTreeData(treeData, [], \"\"),\n [treeData, convertToTreeData],\n );\n\n const handleSelect: TreeProps[\"onSelect\"] = useCallback(\n (keys: any, info: any) => {\n // 编辑态不响应选中\n if (editNode) return;\n // 临时节点不可选中\n const node = info.node as DataNode & { _isTempNode?: boolean };\n if (node._isTempNode) return;\n // 点击 moreActions 区域不触发选中\n const target = info.nativeEvent?.target as HTMLElement | null;\n if (\n target &&\n (target.closest(\".folder-tree-more-icon\") ||\n target.closest(\".ant-dropdown\"))\n ) {\n return;\n }\n onSelect?.(keys, info);\n },\n [onSelect, editNode],\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\n className={styles.directoryTreeContent}\n onDragOver={dragMode ? onContainerDragOver : undefined}\n onDrop={dragMode ? onContainerDrop : undefined}\n >\n <AntDirectoryTree\n style={\n {\n \"--ant-tree-directory-node-selected-bg\": \"rgba(0,0,0,0.03)\",\n \"--ant-tree-directory-node-selected-color\": \"#1a1c1e\",\n } as React.CSSProperties\n }\n treeData={treeDataConverted}\n selectedKeys={selectedKeys}\n expandedKeys={expandedKeys}\n onSelect={handleSelect}\n onExpand={onExpand}\n multiple={false}\n blockNode\n showLine={showLine as any}\n switcherIcon={switcherIcon}\n defaultExpandAll={defaultExpandAll}\n draggable={false}\n />\n </div>\n </div>\n );\n};\n\nexport default DirectoryTreeComponent;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["clsx"]
|
|
7
7
|
}
|
|
@@ -38,6 +38,18 @@ var import_DirectoryTree = __toESM(require("./DirectoryTree"));
|
|
|
38
38
|
var import_FilePreview = __toESM(require("./FilePreview"));
|
|
39
39
|
var import_styles = require("./styles");
|
|
40
40
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
41
|
+
function getAllExpandedKeys(nodes, parentPath = "") {
|
|
42
|
+
const keys = [];
|
|
43
|
+
nodes.forEach((node) => {
|
|
44
|
+
var _a;
|
|
45
|
+
const currentPath = parentPath ? `${parentPath}/${node.path}` : node.path;
|
|
46
|
+
if ((_a = node.children) == null ? void 0 : _a.length) {
|
|
47
|
+
keys.push(currentPath);
|
|
48
|
+
keys.push(...getAllExpandedKeys(node.children, currentPath));
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return keys;
|
|
52
|
+
}
|
|
41
53
|
var FolderTree = (0, import_react.forwardRef)((props, ref) => {
|
|
42
54
|
const {
|
|
43
55
|
className,
|
|
@@ -144,6 +156,7 @@ var FolderTree = (0, import_react.forwardRef)((props, ref) => {
|
|
|
144
156
|
setCreateContext(null);
|
|
145
157
|
setEditNode({
|
|
146
158
|
key: fullPath,
|
|
159
|
+
type: node.type || "file",
|
|
147
160
|
originalTitle: titleStr,
|
|
148
161
|
currentValue: titleStr,
|
|
149
162
|
mode: "rename"
|
|
@@ -154,25 +167,33 @@ var FolderTree = (0, import_react.forwardRef)((props, ref) => {
|
|
|
154
167
|
const [selectedFileState, setSelectedFileState] = (0, import_react.useState)(
|
|
155
168
|
() => isValidSelectedFile(selectedFile || defaultSelectedFile) ? selectedFile || defaultSelectedFile || [] : []
|
|
156
169
|
);
|
|
157
|
-
const
|
|
158
|
-
|
|
170
|
+
const controlled = expandedPaths !== void 0;
|
|
171
|
+
const [expandedPathsState, setExpandedPathsState] = (0, import_react.useState)(
|
|
172
|
+
defaultExpandedPaths || []
|
|
159
173
|
);
|
|
160
174
|
const [validSelectedFile, setValidSelectedFile] = (0, import_react.useState)(
|
|
161
175
|
isValidSelectedFile(selectedFile || defaultSelectedFile)
|
|
162
176
|
);
|
|
163
177
|
const [fileContent, setFileContent] = (0, import_react.useState)("");
|
|
164
178
|
const [loadingContent, setLoadingContent] = (0, import_react.useState)(false);
|
|
179
|
+
const initializedExpandRef = (0, import_react.useRef)(false);
|
|
165
180
|
(0, import_react.useEffect)(() => {
|
|
166
181
|
if (selectedFile !== void 0) {
|
|
167
182
|
setSelectedFileState(selectedFile);
|
|
168
183
|
setValidSelectedFile(isValidSelectedFile(selectedFile));
|
|
169
184
|
}
|
|
170
|
-
}, [selectedFile,
|
|
185
|
+
}, [selectedFile, isValidSelectedFile]);
|
|
186
|
+
(0, import_react.useEffect)(() => {
|
|
187
|
+
if (!controlled && defaultExpandAll && !initializedExpandRef.current && treeData.length > 0) {
|
|
188
|
+
initializedExpandRef.current = true;
|
|
189
|
+
setExpandedPathsState(getAllExpandedKeys(treeData));
|
|
190
|
+
}
|
|
191
|
+
}, [controlled, defaultExpandAll, treeData]);
|
|
171
192
|
(0, import_react.useEffect)(() => {
|
|
172
|
-
if (
|
|
173
|
-
|
|
193
|
+
if (controlled) {
|
|
194
|
+
setExpandedPathsState(expandedPaths);
|
|
174
195
|
}
|
|
175
|
-
}, [expandedPaths]);
|
|
196
|
+
}, [controlled, expandedPaths]);
|
|
176
197
|
(0, import_react.useEffect)(() => {
|
|
177
198
|
const loadContent = async () => {
|
|
178
199
|
if (!validSelectedFile || selectedFileState.length === 0) {
|
|
@@ -241,18 +262,13 @@ var FolderTree = (0, import_react.forwardRef)((props, ref) => {
|
|
|
241
262
|
setSelectedFileState(pathArray);
|
|
242
263
|
}
|
|
243
264
|
if (originalNode) {
|
|
244
|
-
onFileClick == null ? void 0 : onFileClick(
|
|
245
|
-
keys[0],
|
|
246
|
-
originalNode.content,
|
|
247
|
-
originalNode.extra
|
|
248
|
-
);
|
|
265
|
+
onFileClick == null ? void 0 : onFileClick(keys[0], originalNode.content, originalNode.extra);
|
|
249
266
|
}
|
|
250
267
|
};
|
|
251
|
-
const isExpandedControlled = expandedPaths !== void 0;
|
|
252
268
|
const handleExpand = (keys) => {
|
|
253
269
|
const newPaths = keys;
|
|
254
|
-
if (
|
|
255
|
-
|
|
270
|
+
if (!controlled) {
|
|
271
|
+
setExpandedPathsState(newPaths);
|
|
256
272
|
}
|
|
257
273
|
onExpandedPathsChange == null ? void 0 : onExpandedPathsChange(newPaths);
|
|
258
274
|
};
|
|
@@ -269,21 +285,23 @@ var FolderTree = (0, import_react.forwardRef)((props, ref) => {
|
|
|
269
285
|
});
|
|
270
286
|
setEditNode({
|
|
271
287
|
key: tempKey,
|
|
288
|
+
type: options.type || "folder",
|
|
272
289
|
originalTitle: "",
|
|
273
290
|
currentValue: defaultName,
|
|
274
291
|
mode: "create"
|
|
275
292
|
});
|
|
276
|
-
if (
|
|
277
|
-
|
|
293
|
+
if (!controlled && parentPath && parentPath !== "/") {
|
|
294
|
+
setExpandedPathsState((prev) => {
|
|
278
295
|
const current = prev || [];
|
|
279
|
-
if (current.includes(parentPath))
|
|
296
|
+
if (current.includes(parentPath)) {
|
|
280
297
|
return current;
|
|
298
|
+
}
|
|
281
299
|
return [...current, parentPath];
|
|
282
300
|
});
|
|
283
301
|
}
|
|
284
302
|
}
|
|
285
303
|
}),
|
|
286
|
-
[]
|
|
304
|
+
[controlled]
|
|
287
305
|
);
|
|
288
306
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
289
307
|
"div",
|
|
@@ -309,7 +327,7 @@ var FolderTree = (0, import_react.forwardRef)((props, ref) => {
|
|
|
309
327
|
treeData,
|
|
310
328
|
directoryIcons,
|
|
311
329
|
selectedKeys: selectable && selectedFileState && validSelectedFile ? [selectedFileState.join("/")] : [],
|
|
312
|
-
expandedKeys:
|
|
330
|
+
expandedKeys: controlled ? expandedPaths : expandedPathsState,
|
|
313
331
|
onSelect: handleSelect,
|
|
314
332
|
onExpand: handleExpand,
|
|
315
333
|
defaultExpandAll,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/FolderTree/index.tsx"],
|
|
4
|
-
"sourcesContent": ["import React, {\n useCallback,\n useEffect,\n useState,\n forwardRef,\n useImperativeHandle,\n} from \"react\";\nimport type { TreeProps } from \"antd\";\nimport clsx from \"clsx\";\nimport type {\n FolderTreeData,\n FolderTreeProps,\n FolderTreeRef,\n EditNodeInfo,\n CreateNodeContext,\n} from \"./types\";\nimport DirectoryTreeComponent from \"./DirectoryTree\";\nimport FilePreview from \"./FilePreview\";\nimport { useStyles } from \"./styles\";\n\nexport type {\n FolderTreeData,\n FolderTreeProps,\n FileContentService,\n FolderTreeRef,\n} from \"./types\";\n\nconst FolderTree = forwardRef<FolderTreeRef, FolderTreeProps>((props, ref) => {\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 onRename,\n onCreate,\n } = props;\n\n const styles = useStyles();\n\n // ====== 编辑态状态 ======\n const [editNode, setEditNode] = useState<EditNodeInfo | null>(null);\n const [createContext, setCreateContext] = useState<CreateNodeContext | null>(\n null\n );\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 // ====== 编辑态逻辑 ======\n\n // 当 treeData 变化时,检查编辑节点是否还存在\n useEffect(() => {\n if (!editNode) return;\n const { node } = findNodeAndValidate(editNode.key);\n if (!node) {\n setEditNode(null);\n setCreateContext(null);\n }\n }, [treeData]);\n\n // 编辑值变化\n const handleEditValueChange = useCallback((value: string) => {\n setEditNode((prev) => (prev ? { ...prev, currentValue: value } : null));\n }, []);\n\n // 确认编辑\n const handleEditConfirm = useCallback(() => {\n if (!editNode) return;\n const newValue = editNode.currentValue.trim();\n\n if (editNode.mode === \"rename\") {\n const { node } = findNodeAndValidate(editNode.key);\n onRename?.({\n key: editNode.key,\n oldTitle: editNode.originalTitle,\n newTitle: newValue,\n node: node!,\n });\n } else if (editNode.mode === \"create\" && createContext) {\n onCreate?.({\n parentKey: createContext.parentKey,\n name: newValue,\n type: createContext.type,\n extra: createContext.extra,\n });\n }\n\n setEditNode(null);\n setCreateContext(null);\n }, [editNode, createContext, findNodeAndValidate, onRename, onCreate]);\n\n // 取消编辑\n const handleEditCancel = useCallback(() => {\n setEditNode(null);\n setCreateContext(null);\n }, []);\n\n // 开始重命名\n const handleStartRename = useCallback(\n (fullPath: string, node: FolderTreeData) => {\n const titleStr =\n typeof node.title === \"string\" ? node.title : String(node.path);\n setCreateContext(null);\n setEditNode({\n key: fullPath,\n originalTitle: titleStr,\n currentValue: titleStr,\n mode: \"rename\",\n });\n },\n []\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 isExpandedControlled = expandedPaths !== undefined;\n\n const handleExpand: TreeProps[\"onExpand\"] = (keys) => {\n const newPaths = keys as string[];\n if (isExpandedControlled) {\n setExpandedPaths(newPaths);\n }\n onExpandedPathsChange?.(newPaths);\n };\n\n // ====== 命令式 API ======\n useImperativeHandle(\n ref,\n () => ({\n createNode: (parentPath, options) => {\n const defaultName =\n options.defaultName ||\n (options.type === \"folder\" ? \"新建文件夹\" : \"新建文件\");\n const tempKey = `__create__${parentPath || \"root\"}__${Date.now()}`;\n\n setCreateContext({\n parentKey: parentPath,\n type: options.type,\n extra: options.extra,\n });\n setEditNode({\n key: tempKey,\n originalTitle: \"\",\n currentValue: defaultName,\n mode: \"create\",\n });\n\n // 自动展开父文件夹(仅在受控模式下需要,非受控模式由 defaultExpandAll 处理)\n if (isExpandedControlled && parentPath && parentPath !== \"/\") {\n setExpandedPaths((prev) => {\n const current = prev || [];\n if (current.includes(parentPath)) return current;\n return [...current, parentPath];\n });\n }\n },\n }),\n []\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={isExpandedControlled ? expandedPathsState : undefined}\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 editNode={editNode}\n onEditValueChange={handleEditValueChange}\n onEditConfirm={handleEditConfirm}\n onEditCancel={handleEditCancel}\n createInfo={createContext}\n onStartRename={handleStartRename}\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\nFolderTree.displayName = \"FolderTree\";\n\nexport default FolderTree;\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import React, {\n useRef,\n useCallback,\n useEffect,\n useState,\n forwardRef,\n useImperativeHandle,\n} from \"react\";\nimport type { TreeProps } from \"antd\";\nimport clsx from \"clsx\";\nimport type {\n FolderTreeData,\n FolderTreeProps,\n FolderTreeRef,\n EditNodeInfo,\n CreateNodeContext,\n} from \"./types\";\nimport DirectoryTreeComponent from \"./DirectoryTree\";\nimport FilePreview from \"./FilePreview\";\nimport { useStyles } from \"./styles\";\n\nexport type {\n FolderTreeData,\n FolderTreeProps,\n FileContentService,\n FolderTreeRef,\n} from \"./types\";\n\nfunction getAllExpandedKeys(\n nodes: FolderTreeData[],\n parentPath = \"\",\n): string[] {\n const keys: string[] = [];\n\n nodes.forEach((node) => {\n const currentPath = parentPath ? `${parentPath}/${node.path}` : node.path;\n\n if (node.children?.length) {\n keys.push(currentPath);\n keys.push(...getAllExpandedKeys(node.children, currentPath));\n }\n });\n\n return keys;\n}\n\nconst FolderTree = forwardRef<FolderTreeRef, FolderTreeProps>((props, ref) => {\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 onRename,\n onCreate,\n } = props;\n\n const styles = useStyles();\n\n // ====== 编辑态状态 ======\n const [editNode, setEditNode] = useState<EditNodeInfo | null>(null);\n const [createContext, setCreateContext] = useState<CreateNodeContext | null>(\n null,\n );\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 // ====== 编辑态逻辑 ======\n\n // 当 treeData 变化时,检查编辑节点是否还存在\n useEffect(() => {\n if (!editNode) return;\n const { node } = findNodeAndValidate(editNode.key);\n if (!node) {\n setEditNode(null);\n setCreateContext(null);\n }\n }, [treeData]);\n\n // 编辑值变化\n const handleEditValueChange = useCallback((value: string) => {\n setEditNode((prev) => (prev ? { ...prev, currentValue: value } : null));\n }, []);\n\n // 确认编辑\n const handleEditConfirm = useCallback(() => {\n if (!editNode) return;\n const newValue = editNode.currentValue.trim();\n\n if (editNode.mode === \"rename\") {\n const { node } = findNodeAndValidate(editNode.key);\n onRename?.({\n key: editNode.key,\n oldTitle: editNode.originalTitle,\n newTitle: newValue,\n node: node!,\n });\n } else if (editNode.mode === \"create\" && createContext) {\n onCreate?.({\n parentKey: createContext.parentKey,\n name: newValue,\n type: createContext.type,\n extra: createContext.extra,\n });\n }\n\n setEditNode(null);\n setCreateContext(null);\n }, [editNode, createContext, findNodeAndValidate, onRename, onCreate]);\n\n // 取消编辑\n const handleEditCancel = useCallback(() => {\n setEditNode(null);\n setCreateContext(null);\n }, []);\n\n // 开始重命名\n const handleStartRename = useCallback(\n (fullPath: string, node: FolderTreeData) => {\n const titleStr =\n typeof node.title === \"string\" ? node.title : String(node.path);\n setCreateContext(null);\n setEditNode({\n key: fullPath,\n type: node.type || \"file\",\n originalTitle: titleStr,\n currentValue: titleStr,\n mode: \"rename\",\n });\n },\n [],\n );\n\n // ====== State ======\n const [selectedFileState, setSelectedFileState] = useState<string[]>(() =>\n isValidSelectedFile(selectedFile || defaultSelectedFile)\n ? selectedFile || defaultSelectedFile || []\n : [],\n );\n const controlled = expandedPaths !== undefined;\n\n const [expandedPathsState, setExpandedPathsState] = useState<string[]>(\n 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 const initializedExpandRef = useRef(false);\n\n // 受控模式同步\n useEffect(() => {\n if (selectedFile !== undefined) {\n setSelectedFileState(selectedFile);\n setValidSelectedFile(isValidSelectedFile(selectedFile));\n }\n }, [selectedFile, isValidSelectedFile]);\n\n useEffect(() => {\n if (\n !controlled &&\n defaultExpandAll &&\n !initializedExpandRef.current &&\n treeData.length > 0\n ) {\n initializedExpandRef.current = true;\n\n setExpandedPathsState(getAllExpandedKeys(treeData));\n }\n }, [controlled, defaultExpandAll, treeData]);\n\n useEffect(() => {\n if (controlled) {\n setExpandedPathsState(expandedPaths);\n }\n }, [controlled, 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?.(keys[0], originalNode.content, originalNode.extra);\n }\n };\n\n const handleExpand: TreeProps[\"onExpand\"] = (keys) => {\n const newPaths = keys as string[];\n\n if (!controlled) {\n setExpandedPathsState(newPaths);\n }\n\n onExpandedPathsChange?.(newPaths);\n };\n\n // ====== 命令式 API ======\n useImperativeHandle(\n ref,\n () => ({\n createNode: (parentPath, options) => {\n const defaultName =\n options.defaultName ||\n (options.type === \"folder\" ? \"新建文件夹\" : \"新建文件\");\n const tempKey = `__create__${parentPath || \"root\"}__${Date.now()}`;\n\n setCreateContext({\n parentKey: parentPath,\n type: options.type,\n extra: options.extra,\n });\n setEditNode({\n key: tempKey,\n type: options.type || \"folder\",\n originalTitle: \"\",\n currentValue: defaultName,\n mode: \"create\",\n });\n\n // 自动展开父文件夹(仅在受控模式下需要,非受控模式由 defaultExpandAll 处理)\n if (!controlled && parentPath && parentPath !== \"/\") {\n setExpandedPathsState((prev) => {\n const current = prev || [];\n\n if (current.includes(parentPath)) {\n return current;\n }\n\n return [...current, parentPath];\n });\n }\n },\n }),\n [controlled],\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={controlled ? expandedPaths : 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 editNode={editNode}\n onEditValueChange={handleEditValueChange}\n onEditConfirm={handleEditConfirm}\n onEditCancel={handleEditCancel}\n createInfo={createContext}\n onStartRename={handleStartRename}\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\nFolderTree.displayName = \"FolderTree\";\n\nexport default FolderTree;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["node", "clsx", "DirectoryTreeComponent", "FilePreview"]
|
|
7
7
|
}
|
|
@@ -5,6 +5,7 @@ export interface FolderTreeData<T = any> {
|
|
|
5
5
|
title: React.ReactNode;
|
|
6
6
|
path: string;
|
|
7
7
|
content?: string;
|
|
8
|
+
type?: "folder" | "file";
|
|
8
9
|
extra?: T;
|
|
9
10
|
children?: FolderTreeData<T>[];
|
|
10
11
|
}
|
|
@@ -18,6 +19,8 @@ export interface EditNodeInfo {
|
|
|
18
19
|
key: string;
|
|
19
20
|
/** 原始标题 */
|
|
20
21
|
originalTitle: string;
|
|
22
|
+
/** 文件类型 */
|
|
23
|
+
type: "folder" | "file";
|
|
21
24
|
/** 当前输入值 */
|
|
22
25
|
currentValue: string;
|
|
23
26
|
/** 编辑模式:重命名或新建 */
|
|
@@ -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/** 编辑节点信息 */\nexport interface EditNodeInfo {\n /** 完整路径 key */\n key: string;\n /** 原始标题 */\n originalTitle: string;\n /** 当前输入值 */\n currentValue: string;\n /** 编辑模式:重命名或新建 */\n mode: \"rename\" | \"create\";\n}\n\n/** 新建上下文 */\nexport interface CreateNodeContext {\n /** 父节点 key */\n parentKey: string;\n /** 节点类型 */\n type: \"file\" | \"folder\";\n /** 附加数据 */\n extra?: any;\n}\n\n/** FolderTree 命令式 API */\nexport interface FolderTreeRef {\n /**\n * 在指定父路径下新建文件或文件夹\n * @param parentPath - 父节点完整路径(空字符串或 \"/\" 表示根路径)\n * @param options.type - 节点类型\n * @param options.defaultName - 默认名称\n * @param options.extra - 自定义附加数据\n */\n createNode: (\n parentPath: string,\n options: {\n type: \"file\" | \"folder\";\n defaultName?: string;\n extra?: any;\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 type?: \"folder\" | \"file\";\n extra?: T;\n children?: FolderTreeData<T>[];\n}\n\n/** 文件内容加载服务 */\nexport interface FileContentService {\n loadFileContent(filePath: string): Promise<string>;\n}\n\n/** 编辑节点信息 */\nexport interface EditNodeInfo {\n /** 完整路径 key */\n key: string;\n /** 原始标题 */\n originalTitle: string;\n /** 文件类型 */\n type: \"folder\" | \"file\";\n /** 当前输入值 */\n currentValue: string;\n /** 编辑模式:重命名或新建 */\n mode: \"rename\" | \"create\";\n}\n\n/** 新建上下文 */\nexport interface CreateNodeContext {\n /** 父节点 key */\n parentKey: string;\n /** 节点类型 */\n type: \"file\" | \"folder\";\n /** 附加数据 */\n extra?: any;\n}\n\n/** FolderTree 命令式 API */\nexport interface FolderTreeRef {\n /**\n * 在指定父路径下新建文件或文件夹\n * @param parentPath - 父节点完整路径(空字符串或 \"/\" 表示根路径)\n * @param options.type - 节点类型\n * @param options.defaultName - 默认名称\n * @param options.extra - 自定义附加数据\n */\n createNode: (\n parentPath: string,\n options: {\n type: \"file\" | \"folder\";\n defaultName?: string;\n extra?: any;\n },\n ) => void;\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?: (\n node: FolderTreeData,\n actions?: { startRename: () => void },\n ) => 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 onRename?: (info: {\n /** 节点完整路径 key */\n key: string;\n /** 原始标题 */\n oldTitle: React.ReactNode;\n /** 新标题 */\n newTitle: string;\n /** 原始节点数据 */\n node: FolderTreeData;\n }) => void;\n\n /** 新建确认回调,失焦或回车时触发 */\n onCreate?: (info: {\n /** 父节点 key */\n parentKey: string;\n /** 用户输入的名称 */\n name: string;\n /** 节点类型 */\n type: \"file\" | \"folder\";\n /** 附加数据 */\n extra?: any;\n }) => void;\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
|
}
|
|
@@ -34,7 +34,7 @@ var DirectoryTreeComponent = function DirectoryTreeComponent(_ref) {
|
|
|
34
34
|
onStartRename = _ref.onStartRename;
|
|
35
35
|
var styles = useStyles();
|
|
36
36
|
var isFolder = function isFolder(node) {
|
|
37
|
-
return !!node.children && node.children.length > 0;
|
|
37
|
+
return !!node.children && node.children.length > 0 || node.type === "folder";
|
|
38
38
|
};
|
|
39
39
|
var getIcon = useCallback(function (node) {
|
|
40
40
|
if (directoryIcons === false || directoryIcons === null) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useCallback","useMemo","Tree","Dropdown","Input","FileOutlined","FolderOutlined","MoreOutlined","clsx","useStyles","useFolderDrag","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","editNode","onEditValueChange","onEditConfirm","onEditCancel","createInfo","onStartRename","styles","isFolder","node","children","length","getIcon","icon","directory","filePath","path","toLowerCase","extension","split","pop","buildPathSegments","parentSegments","arguments","undefined","concat","_toConsumableArray","filter","s","renderInlineInput","value","treeNodeTitle","size","onChange","e","target","onBlur","onPressEnter","onKeyDown","key","stopPropagation","autoFocus","inlineInput","onClick","onFocus","dragMode","handleDragDrop","dragNode","dropNode","dropPosition","dragNd","dropNd","originalDragNode","_originalNode","originalDropNode","dragKey","String","dropKey","dragFileName","newPath","fileName","title","extra","oldPath","isLeaf","dropParentPath","includes","substring","lastIndexOf","handleDragEnterExpand","nodeKey","isExpanded","expanded","nativeEvent","_useFolderDrag","onDragEnterExpand","onDragStart","onDragEnd","onItemDragEnter","onItemDragOver","onItemDragLeave","onItemDrop","onContainerDragOver","onContainerDrop","canDragNode","convertToTreeData","nodes","parentKey","result","map","pathSegments","fullPath","join","replace","isEditing","nodeChildren","baseNode","currentValue","titleContent","treeNodeTitleHover","menu","startRename","trigger","placement","moreIcon","nodeData","draggableDiv","treeNodeWrapper","dragNodeHandle","onDragEnter","onDragOver","onDragLeave","mode","targetParentKey","tempNode","type","_isTempNode","push","treeDataConverted","handleSelect","keys","info","_info$nativeEvent","closest","titleNode","directoryPanel","style","directoryTreeContent","multiple","blockNode"],"sources":["../../../../src/components/FolderTree/DirectoryTree.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport { Tree, Dropdown, Input } from \"antd\";\nimport { FileOutlined, FolderOutlined, MoreOutlined } from \"@ant-design/icons\";\nimport type { TreeProps } from \"antd\";\nimport type { DataNode } from \"antd/es/tree\";\nimport clsx from \"clsx\";\nimport type {\n FolderTreeData,\n FolderTreeProps,\n EditNodeInfo,\n CreateNodeContext,\n} from \"./types\";\nimport { useStyles } from \"./styles\";\nimport { useFolderDrag, type DropPosition } from \"./useFolderDrag\";\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 editNode?: EditNodeInfo | null;\n /** 编辑值变化回调 */\n onEditValueChange?: (value: string) => void;\n /** 编辑确认回调 */\n onEditConfirm?: () => void;\n /** 编辑取消回调 */\n onEditCancel?: () => void;\n /** 新建上下文 */\n createInfo?: CreateNodeContext | null;\n /** 开始重命名回调(由父组件注入) */\n onStartRename?: (fullPath: string, node: FolderTreeData) => void;\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 editNode,\n onEditValueChange,\n onEditConfirm,\n onEditCancel,\n createInfo,\n onStartRename,\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 renderInlineInput = useCallback(\n (value: string) => (\n <span className={styles.treeNodeTitle}>\n <Input\n size=\"small\"\n value={value}\n onChange={(e) => onEditValueChange?.(e.target.value)}\n onBlur={() => onEditConfirm?.()}\n onPressEnter={() => onEditConfirm?.()}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n e.stopPropagation();\n onEditCancel?.();\n }\n }}\n autoFocus\n className={styles.inlineInput}\n onClick={(e) => e.stopPropagation()}\n onSelect={(e) => e.stopPropagation()}\n onFocus={(e) => e.stopPropagation()}\n />\n </span>\n ),\n [onEditValueChange, onEditConfirm, onEditCancel, styles],\n );\n\n // ====== 拖拽模式 ======\n const dragMode = draggable === true ? \"file\" : draggable || false;\n\n // ====== 自定义拖拽 hook ======\n const handleDragDrop = useCallback(\n (dragNode: DataNode, dropNode: DataNode, dropPosition: DropPosition) => {\n const dragNd = dragNode as DataNode & { _originalNode?: FolderTreeData };\n const dropNd = dropNode as DataNode & { _originalNode?: FolderTreeData };\n const originalDragNode = dragNd._originalNode;\n const originalDropNode = dropNd._originalNode;\n if (!originalDragNode) return;\n\n const dragKey = String(dragNode.key);\n const dropKey = String(dropNode.key);\n const dragFileName = originalDragNode.path;\n let newPath: string;\n\n // 拖到底部 drop zone:放在根级别末尾\n if (!originalDropNode && dropKey === \"__bottom_placeholder__\") {\n newPath = dragFileName;\n onDrop?.({\n fileName: originalDragNode.title,\n extra: originalDragNode.extra,\n oldPath: dragKey,\n newPath,\n dragNode: originalDragNode,\n dropNode: { title: \"\", path: \"\" },\n });\n return;\n }\n\n if (!originalDropNode) return;\n\n if (!dropNode.isLeaf && dropPosition === 0) {\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 handleDragEnterExpand = useCallback(\n (nodeKey: string) => {\n const isExpanded = expandedKeys?.includes(nodeKey);\n if (!isExpanded) {\n onExpand?.([...(expandedKeys || []), nodeKey], {\n node: null as any,\n expanded: true,\n nativeEvent: null as any,\n });\n }\n },\n [expandedKeys, onExpand],\n );\n\n const { onDragStart, onDragEnd, onItemDragEnter, onItemDragOver, onItemDragLeave, onItemDrop, onContainerDragOver, onContainerDrop, canDragNode } =\n useFolderDrag({\n dragMode,\n onDrop: handleDragDrop,\n onDragEnterExpand: handleDragEnterExpand,\n });\n\n // ====== 转换树数据 ======\n // 注意:convertToTreeData 不依赖拖拽状态,拖拽效果通过 DOM 操作实现\n const convertToTreeData = useCallback(\n (\n nodes: FolderTreeData[],\n parentSegments: string[] = [],\n parentKey: string = \"\",\n ): DataNode[] => {\n const result = nodes.map((node) => {\n const pathSegments = buildPathSegments(node, parentSegments);\n const fullPath = pathSegments.join(\"/\").replace(/^\\/+/, \"\");\n\n const isEditing = editNode && editNode.key === fullPath;\n\n const nodeChildren = node.children\n ? convertToTreeData(node.children, pathSegments, fullPath)\n : undefined;\n\n const baseNode: any = {\n key: fullPath,\n path: fullPath,\n pathSegments,\n icon: getIcon(node),\n isLeaf: !isFolder(node),\n _originalNode: node,\n children: nodeChildren,\n };\n\n // 编辑态:直接渲染 inline input\n if (isEditing) {\n baseNode.title = renderInlineInput(editNode!.currentValue);\n return baseNode;\n }\n\n // title 内容(按钮、菜单等)\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 startRename: () => onStartRename?.(fullPath, node),\n })}\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 // 启用拖拽时:在 title 外层包裹具有 data-node-key 属性的容器,\n // 用于 DOM 查询和事件绑定。拖拽状态通过 CSS class 控制。\n if (dragMode) {\n const nodeData = baseNode as DataNode & {\n _isTempNode?: boolean;\n };\n const draggableDiv = canDragNode(nodeData);\n\n baseNode.title = (\n <div\n className={clsx(\n styles.treeNodeWrapper,\n draggableDiv && styles.dragNodeHandle,\n )}\n data-node-key={fullPath}\n draggable={draggableDiv}\n onDragStart={draggableDiv ? (e) => onDragStart(e, baseNode) : undefined}\n onDragEnd={draggableDiv ? onDragEnd : undefined}\n onDragEnter={(e) => onItemDragEnter(e, baseNode)}\n onDragOver={(e) => onItemDragOver(e, baseNode)}\n onDragLeave={onItemDragLeave}\n onDrop={(e) => onItemDrop(e, baseNode)}\n >\n {titleContent}\n </div>\n );\n } else {\n baseNode.title = titleContent;\n }\n\n return baseNode;\n });\n\n // 新建模式:在目标父节点下插入临时节点\n if (createInfo && editNode && editNode.mode === \"create\") {\n const targetParentKey = createInfo.parentKey;\n if (\n targetParentKey === parentKey ||\n (targetParentKey === \"\" && parentKey === \"\") ||\n (targetParentKey === \"/\" && parentKey === \"\")\n ) {\n const tempNode: any = {\n key: editNode.key,\n title: renderInlineInput(editNode.currentValue),\n icon:\n createInfo.type === \"folder\" ? (\n <FolderOutlined />\n ) : (\n <FileOutlined />\n ),\n isLeaf: createInfo.type === \"file\",\n path: editNode.key,\n pathSegments: [editNode.key],\n _originalNode: null,\n _isTempNode: true,\n };\n result.push(tempNode);\n }\n }\n\n return result;\n },\n [\n buildPathSegments,\n getIcon,\n moreActions,\n styles,\n editNode,\n renderInlineInput,\n createInfo,\n onStartRename,\n dragMode,\n canDragNode,\n onDragStart,\n onDragEnd,\n onItemDragEnter,\n onItemDragOver,\n onItemDragLeave,\n onItemDrop,\n ],\n );\n\n const treeDataConverted = useMemo(\n () => convertToTreeData(treeData, [], \"\"),\n [treeData, convertToTreeData],\n );\n\n const handleSelect: TreeProps[\"onSelect\"] = useCallback(\n (keys: any, info: any) => {\n // 编辑态不响应选中\n if (editNode) return;\n // 临时节点不可选中\n const node = info.node as DataNode & { _isTempNode?: boolean };\n if (node._isTempNode) return;\n // 点击 moreActions 区域不触发选中\n const target = info.nativeEvent?.target as HTMLElement | null;\n if (\n target &&\n (target.closest(\".folder-tree-more-icon\") ||\n target.closest(\".ant-dropdown\"))\n ) {\n return;\n }\n onSelect?.(keys, info);\n },\n [onSelect, editNode],\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 onDragOver={dragMode ? onContainerDragOver : undefined}\n onDrop={dragMode ? onContainerDrop : undefined}\n >\n <AntDirectoryTree\n style={\n {\n \"--ant-tree-directory-node-selected-bg\": \"rgba(0,0,0,0.03)\",\n \"--ant-tree-directory-node-selected-color\": \"#1a1c1e\",\n } as React.CSSProperties\n }\n treeData={treeDataConverted}\n selectedKeys={selectedKeys}\n expandedKeys={expandedKeys}\n onSelect={handleSelect}\n onExpand={onExpand}\n multiple={false}\n blockNode\n showLine={showLine as any}\n switcherIcon={switcherIcon}\n defaultExpandAll={defaultExpandAll}\n draggable={false}\n />\n </div>\n </div>\n );\n};\n\nexport default DirectoryTreeComponent;"],"mappings":";AAAA,OAAOA,KAAK,IAAIC,WAAW,EAAEC,OAAO,QAAQ,OAAO;AACnD,SAASC,IAAI,EAAEC,QAAQ,EAAEC,KAAK,QAAQ,MAAM;AAC5C,SAASC,YAAY,EAAEC,cAAc,EAAEC,YAAY,QAAQ,mBAAmB;AAG9E,OAAOC,IAAI,MAAM,MAAM;AAOvB,SAASC,SAAS;AAClB,SAASC,aAAa;AAA6C,SAAAC,GAAA,IAAAC,IAAA;AAAA,SAAAC,IAAA,IAAAC,KAAA;AAEnE,IAAuBC,gBAAgB,GAAKb,IAAI,CAAxCc,aAAa;AAgCrB,IAAMC,sBAA6D,GAAG,SAAhEA,sBAA6DA,CAAAC,IAAA,EAsB7D;EAAA,IArBJC,QAAQ,GAAAD,IAAA,CAARC,QAAQ;IACRC,YAAY,GAAAF,IAAA,CAAZE,YAAY;IACZC,YAAY,GAAAH,IAAA,CAAZG,YAAY;IACZC,QAAQ,GAAAJ,IAAA,CAARI,QAAQ;IACRC,QAAQ,GAAAL,IAAA,CAARK,QAAQ;IAAAC,aAAA,GAAAN,IAAA,CACRO,QAAQ;IAARA,QAAQ,GAAAD,aAAA,cAAG,KAAK,GAAAA,aAAA;IAChBE,YAAY,GAAAR,IAAA,CAAZQ,YAAY;IAAAC,qBAAA,GAAAT,IAAA,CACZU,gBAAgB;IAAhBA,gBAAgB,GAAAD,qBAAA,cAAG,IAAI,GAAAA,qBAAA;IACvBE,SAAS,GAAAX,IAAA,CAATW,SAAS;IACTC,cAAc,GAAAZ,IAAA,CAAdY,cAAc;IACdC,cAAc,GAAAb,IAAA,CAAda,cAAc;IACdC,WAAW,GAAAd,IAAA,CAAXc,WAAW;IACXC,KAAK,GAAAf,IAAA,CAALe,KAAK;IACLC,SAAS,GAAAhB,IAAA,CAATgB,SAAS;IACTC,MAAM,GAAAjB,IAAA,CAANiB,MAAM;IACNC,QAAQ,GAAAlB,IAAA,CAARkB,QAAQ;IACRC,iBAAiB,GAAAnB,IAAA,CAAjBmB,iBAAiB;IACjBC,aAAa,GAAApB,IAAA,CAAboB,aAAa;IACbC,YAAY,GAAArB,IAAA,CAAZqB,YAAY;IACZC,UAAU,GAAAtB,IAAA,CAAVsB,UAAU;IACVC,aAAa,GAAAvB,IAAA,CAAbuB,aAAa;EAEb,IAAMC,MAAM,GAAGjC,SAAS,CAAC,CAAC;EAE1B,IAAMkC,QAAQ,GAAG,SAAXA,QAAQA,CAAIC,IAAoB,EAAc;IAClD,OAAO,CAAC,CAACA,IAAI,CAACC,QAAQ,IAAID,IAAI,CAACC,QAAQ,CAACC,MAAM,GAAG,CAAC;EACpD,CAAC;EAED,IAAMC,OAAO,GAAG/C,WAAW,CACzB,UAAC4C,IAAoB,EAAK;IACxB,IAAId,cAAc,KAAK,KAAK,IAAIA,cAAc,KAAK,IAAI,EAAE;MACvD,OAAO,IAAI;IACb;IACA,IAAIa,QAAQ,CAACC,IAAI,CAAC,EAAE;MAClB,IAAMI,IAAI,GAAGlB,cAAc,aAAdA,cAAc,uBAAdA,cAAc,CAAEmB,SAAS;MACtC,IAAI,OAAOD,IAAI,KAAK,UAAU,EAAE,OAAOA,IAAI,CAAC,CAAC;MAC7C,OAAOA,IAAI,iBAAIpC,IAAA,CAACN,cAAc,IAAE,CAAC;IACnC;IACA,IAAM4C,QAAQ,GAAGN,IAAI,CAACO,IAAI,CAACC,WAAW,CAAC,CAAC;IACxC,IAAMC,SAAS,GAAGH,QAAQ,CAACI,KAAK,CAAC,GAAG,CAAC,CAACC,GAAG,CAAC,CAAC;IAC3C,IAAIF,SAAS,EAAE;MACb,IAAML,KAAI,GAAGlB,cAAc,aAAdA,cAAc,uBAAdA,cAAc,CAAGuB,SAAS,CAAC;MACxC,IAAIL,KAAI,EAAE,OAAO,OAAOA,KAAI,KAAK,UAAU,GAAGA,KAAI,CAAC,CAAC,GAAGA,KAAI;IAC7D;IACA,oBAAOpC,IAAA,CAACP,YAAY,IAAE,CAAC;EACzB,CAAC,EACD,CAACyB,cAAc,CACjB,CAAC;EAED,IAAM0B,iBAAiB,GAAGxD,WAAW,CACnC,UAAC4C,IAAoB,EAA8C;IAAA,IAA5Ca,cAAwB,GAAAC,SAAA,CAAAZ,MAAA,QAAAY,SAAA,QAAAC,SAAA,GAAAD,SAAA,MAAG,EAAE;IAClD,IAAId,IAAI,CAACO,IAAI,KAAK,GAAG,IAAIM,cAAc,CAACX,MAAM,KAAK,CAAC,EAAE;MACpD,OAAO,CAAC,GAAG,CAAC;IACd;IACA,OAAO,GAAAc,MAAA,CAAAC,kBAAA,CAAIJ,cAAc,IAAEb,IAAI,CAACO,IAAI,GAAEW,MAAM,CAAC,UAACC,CAAC;MAAA,OAAKA,CAAC,KAAK,EAAE;IAAA,EAAC;EAC/D,CAAC,EACD,EACF,CAAC;EAED,IAAMC,iBAAiB,GAAGhE,WAAW,CACnC,UAACiE,KAAa;IAAA,oBACZrD,IAAA;MAAMiB,SAAS,EAAEa,MAAM,CAACwB,aAAc;MAAArB,QAAA,eACpCjC,IAAA,CAACR,KAAK;QACJ+D,IAAI,EAAC,OAAO;QACZF,KAAK,EAAEA,KAAM;QACbG,QAAQ,EAAE,SAAAA,SAACC,CAAC;UAAA,OAAKhC,iBAAiB,aAAjBA,iBAAiB,uBAAjBA,iBAAiB,CAAGgC,CAAC,CAACC,MAAM,CAACL,KAAK,CAAC;QAAA,CAAC;QACrDM,MAAM,EAAE,SAAAA,OAAA;UAAA,OAAMjC,aAAa,aAAbA,aAAa,uBAAbA,aAAa,CAAG,CAAC;QAAA,CAAC;QAChCkC,YAAY,EAAE,SAAAA,aAAA;UAAA,OAAMlC,aAAa,aAAbA,aAAa,uBAAbA,aAAa,CAAG,CAAC;QAAA,CAAC;QACtCmC,SAAS,EAAE,SAAAA,UAACJ,CAAC,EAAK;UAChB,IAAIA,CAAC,CAACK,GAAG,KAAK,QAAQ,EAAE;YACtBL,CAAC,CAACM,eAAe,CAAC,CAAC;YACnBpC,YAAY,aAAZA,YAAY,eAAZA,YAAY,CAAG,CAAC;UAClB;QACF,CAAE;QACFqC,SAAS;QACT/C,SAAS,EAAEa,MAAM,CAACmC,WAAY;QAC9BC,OAAO,EAAE,SAAAA,QAACT,CAAC;UAAA,OAAKA,CAAC,CAACM,eAAe,CAAC,CAAC;QAAA,CAAC;QACpCrD,QAAQ,EAAE,SAAAA,SAAC+C,CAAC;UAAA,OAAKA,CAAC,CAACM,eAAe,CAAC,CAAC;QAAA,CAAC;QACrCI,OAAO,EAAE,SAAAA,QAACV,CAAC;UAAA,OAAKA,CAAC,CAACM,eAAe,CAAC,CAAC;QAAA;MAAC,CACrC;IAAC,CACE,CAAC;EAAA,CACR,EACD,CAACtC,iBAAiB,EAAEC,aAAa,EAAEC,YAAY,EAAEG,MAAM,CACzD,CAAC;;EAED;EACA,IAAMsC,QAAQ,GAAG9C,SAAS,KAAK,IAAI,GAAG,MAAM,GAAGA,SAAS,IAAI,KAAK;;EAEjE;EACA,IAAM+C,cAAc,GAAGjF,WAAW,CAChC,UAACkF,QAAkB,EAAEC,QAAkB,EAAEC,YAA0B,EAAK;IACtE,IAAMC,MAAM,GAAGH,QAAyD;IACxE,IAAMI,MAAM,GAAGH,QAAyD;IACxE,IAAMI,gBAAgB,GAAGF,MAAM,CAACG,aAAa;IAC7C,IAAMC,gBAAgB,GAAGH,MAAM,CAACE,aAAa;IAC7C,IAAI,CAACD,gBAAgB,EAAE;IAEvB,IAAMG,OAAO,GAAGC,MAAM,CAACT,QAAQ,CAACR,GAAG,CAAC;IACpC,IAAMkB,OAAO,GAAGD,MAAM,CAACR,QAAQ,CAACT,GAAG,CAAC;IACpC,IAAMmB,YAAY,GAAGN,gBAAgB,CAACpC,IAAI;IAC1C,IAAI2C,OAAe;;IAEnB;IACA,IAAI,CAACL,gBAAgB,IAAIG,OAAO,KAAK,wBAAwB,EAAE;MAC7DE,OAAO,GAAGD,YAAY;MACtB1D,MAAM,aAANA,MAAM,eAANA,MAAM,CAAG;QACP4D,QAAQ,EAAER,gBAAgB,CAACS,KAAK;QAChCC,KAAK,EAAEV,gBAAgB,CAACU,KAAK;QAC7BC,OAAO,EAAER,OAAO;QAChBI,OAAO,EAAPA,OAAO;QACPZ,QAAQ,EAAEK,gBAAgB;QAC1BJ,QAAQ,EAAE;UAAEa,KAAK,EAAE,EAAE;UAAE7C,IAAI,EAAE;QAAG;MAClC,CAAC,CAAC;MACF;IACF;IAEA,IAAI,CAACsC,gBAAgB,EAAE;IAEvB,IAAI,CAACN,QAAQ,CAACgB,MAAM,IAAIf,YAAY,KAAK,CAAC,EAAE;MAC1C;MACAU,OAAO,MAAAlC,MAAA,CAAMgC,OAAO,OAAAhC,MAAA,CAAIiC,YAAY,CAAE;IACxC,CAAC,MAAM;MACL;MACA,IAAMO,cAAc,GAAGR,OAAO,CAACS,QAAQ,CAAC,GAAG,CAAC,GACxCT,OAAO,CAACU,SAAS,CAAC,CAAC,EAAEV,OAAO,CAACW,WAAW,CAAC,GAAG,CAAC,CAAC,GAC9C,EAAE;MACNT,OAAO,GAAGM,cAAc,MAAAxC,MAAA,CACjBwC,cAAc,OAAAxC,MAAA,CAAIiC,YAAY,IACjCA,YAAY;IAClB;IAEA1D,MAAM,aAANA,MAAM,eAANA,MAAM,CAAG;MACP4D,QAAQ,EAAER,gBAAgB,CAACS,KAAK;MAChCC,KAAK,EAAEV,gBAAgB,CAACU,KAAK;MAC7BC,OAAO,EAAER,OAAO;MAChBI,OAAO,EAAPA,OAAO;MACPZ,QAAQ,EAAEK,gBAAgB;MAC1BJ,QAAQ,EAAEM;IACZ,CAAC,CAAC;EACJ,CAAC,EACD,CAACtD,MAAM,CACT,CAAC;EAED,IAAMqE,qBAAqB,GAAGxG,WAAW,CACvC,UAACyG,OAAe,EAAK;IACnB,IAAMC,UAAU,GAAGrF,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEgF,QAAQ,CAACI,OAAO,CAAC;IAClD,IAAI,CAACC,UAAU,EAAE;MACfnF,QAAQ,aAARA,QAAQ,eAARA,QAAQ,IAAAqC,MAAA,CAAAC,kBAAA,CAAQxC,YAAY,IAAI,EAAE,IAAGoF,OAAO,IAAG;QAC7C7D,IAAI,EAAE,IAAW;QACjB+D,QAAQ,EAAE,IAAI;QACdC,WAAW,EAAE;MACf,CAAC,CAAC;IACJ;EACF,CAAC,EACD,CAACvF,YAAY,EAAEE,QAAQ,CACzB,CAAC;EAED,IAAAsF,cAAA,GACEnG,aAAa,CAAC;MACZsE,QAAQ,EAARA,QAAQ;MACR7C,MAAM,EAAE8C,cAAc;MACtB6B,iBAAiB,EAAEN;IACrB,CAAC,CAAC;IALIO,WAAW,GAAAF,cAAA,CAAXE,WAAW;IAAEC,SAAS,GAAAH,cAAA,CAATG,SAAS;IAAEC,eAAe,GAAAJ,cAAA,CAAfI,eAAe;IAAEC,cAAc,GAAAL,cAAA,CAAdK,cAAc;IAAEC,eAAe,GAAAN,cAAA,CAAfM,eAAe;IAAEC,UAAU,GAAAP,cAAA,CAAVO,UAAU;IAAEC,mBAAmB,GAAAR,cAAA,CAAnBQ,mBAAmB;IAAEC,eAAe,GAAAT,cAAA,CAAfS,eAAe;IAAEC,WAAW,GAAAV,cAAA,CAAXU,WAAW;;EAO/I;EACA;EACA,IAAMC,iBAAiB,GAAGxH,WAAW,CACnC,UACEyH,KAAuB,EAGR;IAAA,IAFfhE,cAAwB,GAAAC,SAAA,CAAAZ,MAAA,QAAAY,SAAA,QAAAC,SAAA,GAAAD,SAAA,MAAG,EAAE;IAAA,IAC7BgE,SAAiB,GAAAhE,SAAA,CAAAZ,MAAA,QAAAY,SAAA,QAAAC,SAAA,GAAAD,SAAA,MAAG,EAAE;IAEtB,IAAMiE,MAAM,GAAGF,KAAK,CAACG,GAAG,CAAC,UAAChF,IAAI,EAAK;MACjC,IAAMiF,YAAY,GAAGrE,iBAAiB,CAACZ,IAAI,EAAEa,cAAc,CAAC;MAC5D,IAAMqE,QAAQ,GAAGD,YAAY,CAACE,IAAI,CAAC,GAAG,CAAC,CAACC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;MAE3D,IAAMC,SAAS,GAAG7F,QAAQ,IAAIA,QAAQ,CAACsC,GAAG,KAAKoD,QAAQ;MAEvD,IAAMI,YAAY,GAAGtF,IAAI,CAACC,QAAQ,GAC9B2E,iBAAiB,CAAC5E,IAAI,CAACC,QAAQ,EAAEgF,YAAY,EAAEC,QAAQ,CAAC,GACxDnE,SAAS;MAEb,IAAMwE,QAAa,GAAG;QACpBzD,GAAG,EAAEoD,QAAQ;QACb3E,IAAI,EAAE2E,QAAQ;QACdD,YAAY,EAAZA,YAAY;QACZ7E,IAAI,EAAED,OAAO,CAACH,IAAI,CAAC;QACnBuD,MAAM,EAAE,CAACxD,QAAQ,CAACC,IAAI,CAAC;QACvB4C,aAAa,EAAE5C,IAAI;QACnBC,QAAQ,EAAEqF;MACZ,CAAC;;MAED;MACA,IAAID,SAAS,EAAE;QACbE,QAAQ,CAACnC,KAAK,GAAGhC,iBAAiB,CAAC5B,QAAQ,CAAEgG,YAAY,CAAC;QAC1D,OAAOD,QAAQ;MACjB;;MAEA;MACA,IAAME,YAAY,gBAChBvH,KAAA;QACEe,SAAS,EAAErB,IAAI,CACbkC,MAAM,CAACwB,aAAa,EACpBlC,WAAW,IAAIU,MAAM,CAAC4F,kBACxB,CAAE;QAAAzF,QAAA,gBAEFjC,IAAA;UAAAiC,QAAA,EAAOD,IAAI,CAACoD;QAAK,CAAO,CAAC,EACxBhE,WAAW,iBACVpB,IAAA,CAACT,QAAQ;UACPoI,IAAI,EAAEvG,WAAW,CAACY,IAAI,EAAE;YACtB4F,WAAW,EAAE,SAAAA,YAAA;cAAA,OAAM/F,aAAa,aAAbA,aAAa,uBAAbA,aAAa,CAAGqF,QAAQ,EAAElF,IAAI,CAAC;YAAA;UACpD,CAAC,CAAE;UACH6F,OAAO,EAAE,CAAC,OAAO,CAAE;UACnBC,SAAS,EAAC,aAAa;UAAA7F,QAAA,eAEvBjC,IAAA;YACEiB,SAAS,EAAErB,IAAI,CAACkC,MAAM,CAACiG,QAAQ,EAAE,uBAAuB,CAAE;YAC1D7D,OAAO,EAAE,SAAAA,QAACT,CAAC;cAAA,OAAKA,CAAC,CAACM,eAAe,CAAC,CAAC;YAAA,CAAC;YAAA9B,QAAA,eAEpCjC,IAAA,CAACL,YAAY,IAAE;UAAC,CACZ;QAAC,CACC,CACX;MAAA,CACG,CACP;;MAED;MACA;MACA,IAAIyE,QAAQ,EAAE;QACZ,IAAM4D,QAAQ,GAAGT,QAEhB;QACD,IAAMU,YAAY,GAAGtB,WAAW,CAACqB,QAAQ,CAAC;QAE1CT,QAAQ,CAACnC,KAAK,gBACZpF,IAAA;UACEiB,SAAS,EAAErB,IAAI,CACbkC,MAAM,CAACoG,eAAe,EACtBD,YAAY,IAAInG,MAAM,CAACqG,cACzB,CAAE;UACF,iBAAejB,QAAS;UACxB5F,SAAS,EAAE2G,YAAa;UACxB9B,WAAW,EAAE8B,YAAY,GAAG,UAACxE,CAAC;YAAA,OAAK0C,WAAW,CAAC1C,CAAC,EAAE8D,QAAQ,CAAC;UAAA,IAAGxE,SAAU;UACxEqD,SAAS,EAAE6B,YAAY,GAAG7B,SAAS,GAAGrD,SAAU;UAChDqF,WAAW,EAAE,SAAAA,YAAC3E,CAAC;YAAA,OAAK4C,eAAe,CAAC5C,CAAC,EAAE8D,QAAQ,CAAC;UAAA,CAAC;UACjDc,UAAU,EAAE,SAAAA,WAAC5E,CAAC;YAAA,OAAK6C,cAAc,CAAC7C,CAAC,EAAE8D,QAAQ,CAAC;UAAA,CAAC;UAC/Ce,WAAW,EAAE/B,eAAgB;UAC7BhF,MAAM,EAAE,SAAAA,OAACkC,CAAC;YAAA,OAAK+C,UAAU,CAAC/C,CAAC,EAAE8D,QAAQ,CAAC;UAAA,CAAC;UAAAtF,QAAA,EAEtCwF;QAAY,CACV,CACN;MACH,CAAC,MAAM;QACLF,QAAQ,CAACnC,KAAK,GAAGqC,YAAY;MAC/B;MAEA,OAAOF,QAAQ;IACjB,CAAC,CAAC;;IAEF;IACA,IAAI3F,UAAU,IAAIJ,QAAQ,IAAIA,QAAQ,CAAC+G,IAAI,KAAK,QAAQ,EAAE;MACxD,IAAMC,eAAe,GAAG5G,UAAU,CAACkF,SAAS;MAC5C,IACE0B,eAAe,KAAK1B,SAAS,IAC5B0B,eAAe,KAAK,EAAE,IAAI1B,SAAS,KAAK,EAAG,IAC3C0B,eAAe,KAAK,GAAG,IAAI1B,SAAS,KAAK,EAAG,EAC7C;QACA,IAAM2B,QAAa,GAAG;UACpB3E,GAAG,EAAEtC,QAAQ,CAACsC,GAAG;UACjBsB,KAAK,EAAEhC,iBAAiB,CAAC5B,QAAQ,CAACgG,YAAY,CAAC;UAC/CpF,IAAI,EACFR,UAAU,CAAC8G,IAAI,KAAK,QAAQ,gBAC1B1I,IAAA,CAACN,cAAc,IAAE,CAAC,gBAElBM,IAAA,CAACP,YAAY,IAAE,CAChB;UACH8F,MAAM,EAAE3D,UAAU,CAAC8G,IAAI,KAAK,MAAM;UAClCnG,IAAI,EAAEf,QAAQ,CAACsC,GAAG;UAClBmD,YAAY,EAAE,CAACzF,QAAQ,CAACsC,GAAG,CAAC;UAC5Bc,aAAa,EAAE,IAAI;UACnB+D,WAAW,EAAE;QACf,CAAC;QACD5B,MAAM,CAAC6B,IAAI,CAACH,QAAQ,CAAC;MACvB;IACF;IAEA,OAAO1B,MAAM;EACf,CAAC,EACD,CACEnE,iBAAiB,EACjBT,OAAO,EACPf,WAAW,EACXU,MAAM,EACNN,QAAQ,EACR4B,iBAAiB,EACjBxB,UAAU,EACVC,aAAa,EACbuC,QAAQ,EACRuC,WAAW,EACXR,WAAW,EACXC,SAAS,EACTC,eAAe,EACfC,cAAc,EACdC,eAAe,EACfC,UAAU,CAEd,CAAC;EAED,IAAMqC,iBAAiB,GAAGxJ,OAAO,CAC/B;IAAA,OAAMuH,iBAAiB,CAACrG,QAAQ,EAAE,EAAE,EAAE,EAAE,CAAC;EAAA,GACzC,CAACA,QAAQ,EAAEqG,iBAAiB,CAC9B,CAAC;EAED,IAAMkC,YAAmC,GAAG1J,WAAW,CACrD,UAAC2J,IAAS,EAAEC,IAAS,EAAK;IAAA,IAAAC,iBAAA;IACxB;IACA,IAAIzH,QAAQ,EAAE;IACd;IACA,IAAMQ,IAAI,GAAGgH,IAAI,CAAChH,IAA4C;IAC9D,IAAIA,IAAI,CAAC2G,WAAW,EAAE;IACtB;IACA,IAAMjF,MAAM,IAAAuF,iBAAA,GAAGD,IAAI,CAAChD,WAAW,cAAAiD,iBAAA,uBAAhBA,iBAAA,CAAkBvF,MAA4B;IAC7D,IACEA,MAAM,KACLA,MAAM,CAACwF,OAAO,CAAC,wBAAwB,CAAC,IACvCxF,MAAM,CAACwF,OAAO,CAAC,eAAe,CAAC,CAAC,EAClC;MACA;IACF;IACAxI,QAAQ,aAARA,QAAQ,eAARA,QAAQ,CAAGqI,IAAI,EAAEC,IAAI,CAAC;EACxB,CAAC,EACD,CAACtI,QAAQ,EAAEc,QAAQ,CACrB,CAAC;EAED,IAAM2H,SAAS,GACbhI,cAAc,KAAK,KAAK,IAAIA,cAAc,KAAK,IAAI,GAC/C,IAAI,GACJ,OAAOA,cAAc,KAAK,UAAU,GAClCA,cAAc,CAAC,CAAC,GAChBA,cAAc;EAEtB,oBACEjB,KAAA;IAAKe,SAAS,EAAErB,IAAI,CAACkC,MAAM,CAACsH,cAAc,EAAEnI,SAAS,CAAE;IAACoI,KAAK,EAAE;MAAEhI,KAAK,EAALA;IAAM,CAAE;IAAAY,QAAA,GACtEkH,SAAS,iBAAInJ,IAAA;MAAKiB,SAAS,EAAEa,MAAM,CAACX,cAAe;MAAAc,QAAA,EAAEkH;IAAS,CAAM,CAAC,eACtEnJ,IAAA;MAAKiB,SAAS,EAAEa,MAAM,CAACwH,oBAAqB;MAC1CjB,UAAU,EAAEjE,QAAQ,GAAGqC,mBAAmB,GAAG1D,SAAU;MACvDxB,MAAM,EAAE6C,QAAQ,GAAGsC,eAAe,GAAG3D,SAAU;MAAAd,QAAA,eAE/CjC,IAAA,CAACG,gBAAgB;QACfkJ,KAAK,EACH;UACE,uCAAuC,EAAE,kBAAkB;UAC3D,0CAA0C,EAAE;QAC9C,CACD;QACD9I,QAAQ,EAAEsI,iBAAkB;QAC5BrI,YAAY,EAAEA,YAAa;QAC3BC,YAAY,EAAEA,YAAa;QAC3BC,QAAQ,EAAEoI,YAAa;QACvBnI,QAAQ,EAAEA,QAAS;QACnB4I,QAAQ,EAAE,KAAM;QAChBC,SAAS;QACT3I,QAAQ,EAAEA,QAAgB;QAC1BC,YAAY,EAAEA,YAAa;QAC3BE,gBAAgB,EAAEA,gBAAiB;QACnCM,SAAS,EAAE;MAAM,CAClB;IAAC,CACG,CAAC;EAAA,CACL,CAAC;AAEV,CAAC;AAED,eAAejB,sBAAsB"}
|
|
1
|
+
{"version":3,"names":["React","useCallback","useMemo","Tree","Dropdown","Input","FileOutlined","FolderOutlined","MoreOutlined","clsx","useStyles","useFolderDrag","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","editNode","onEditValueChange","onEditConfirm","onEditCancel","createInfo","onStartRename","styles","isFolder","node","children","length","type","getIcon","icon","directory","filePath","path","toLowerCase","extension","split","pop","buildPathSegments","parentSegments","arguments","undefined","concat","_toConsumableArray","filter","s","renderInlineInput","value","treeNodeTitle","size","onChange","e","target","onBlur","onPressEnter","onKeyDown","key","stopPropagation","autoFocus","inlineInput","onClick","onFocus","dragMode","handleDragDrop","dragNode","dropNode","dropPosition","dragNd","dropNd","originalDragNode","_originalNode","originalDropNode","dragKey","String","dropKey","dragFileName","newPath","fileName","title","extra","oldPath","isLeaf","dropParentPath","includes","substring","lastIndexOf","handleDragEnterExpand","nodeKey","isExpanded","expanded","nativeEvent","_useFolderDrag","onDragEnterExpand","onDragStart","onDragEnd","onItemDragEnter","onItemDragOver","onItemDragLeave","onItemDrop","onContainerDragOver","onContainerDrop","canDragNode","convertToTreeData","nodes","parentKey","result","map","pathSegments","fullPath","join","replace","isEditing","nodeChildren","baseNode","currentValue","titleContent","treeNodeTitleHover","menu","startRename","trigger","placement","moreIcon","nodeData","draggableDiv","treeNodeWrapper","dragNodeHandle","onDragEnter","onDragOver","onDragLeave","mode","targetParentKey","tempNode","_isTempNode","push","treeDataConverted","handleSelect","keys","info","_info$nativeEvent","closest","titleNode","directoryPanel","style","directoryTreeContent","multiple","blockNode"],"sources":["../../../../src/components/FolderTree/DirectoryTree.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport { Tree, Dropdown, Input } from \"antd\";\nimport { FileOutlined, FolderOutlined, MoreOutlined } from \"@ant-design/icons\";\nimport type { TreeProps } from \"antd\";\nimport type { DataNode } from \"antd/es/tree\";\nimport clsx from \"clsx\";\nimport type {\n FolderTreeData,\n FolderTreeProps,\n EditNodeInfo,\n CreateNodeContext,\n} from \"./types\";\nimport { useStyles } from \"./styles\";\nimport { useFolderDrag, type DropPosition } from \"./useFolderDrag\";\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 editNode?: EditNodeInfo | null;\n /** 编辑值变化回调 */\n onEditValueChange?: (value: string) => void;\n /** 编辑确认回调 */\n onEditConfirm?: () => void;\n /** 编辑取消回调 */\n onEditCancel?: () => void;\n /** 新建上下文 */\n createInfo?: CreateNodeContext | null;\n /** 开始重命名回调(由父组件注入) */\n onStartRename?: (fullPath: string, node: FolderTreeData) => void;\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 editNode,\n onEditValueChange,\n onEditConfirm,\n onEditCancel,\n createInfo,\n onStartRename,\n}) => {\n const styles = useStyles();\n\n const isFolder = (node: FolderTreeData): boolean => {\n return (\n (!!node.children && node.children.length > 0) || node.type === \"folder\"\n );\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 renderInlineInput = useCallback(\n (value: string) => (\n <span className={styles.treeNodeTitle}>\n <Input\n size=\"small\"\n value={value}\n onChange={(e) => onEditValueChange?.(e.target.value)}\n onBlur={() => onEditConfirm?.()}\n onPressEnter={() => onEditConfirm?.()}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n e.stopPropagation();\n onEditCancel?.();\n }\n }}\n autoFocus\n className={styles.inlineInput}\n onClick={(e) => e.stopPropagation()}\n onSelect={(e) => e.stopPropagation()}\n onFocus={(e) => e.stopPropagation()}\n />\n </span>\n ),\n [onEditValueChange, onEditConfirm, onEditCancel, styles],\n );\n\n // ====== 拖拽模式 ======\n const dragMode = draggable === true ? \"file\" : draggable || false;\n\n // ====== 自定义拖拽 hook ======\n const handleDragDrop = useCallback(\n (dragNode: DataNode, dropNode: DataNode, dropPosition: DropPosition) => {\n const dragNd = dragNode as DataNode & { _originalNode?: FolderTreeData };\n const dropNd = dropNode as DataNode & { _originalNode?: FolderTreeData };\n const originalDragNode = dragNd._originalNode;\n const originalDropNode = dropNd._originalNode;\n if (!originalDragNode) return;\n\n const dragKey = String(dragNode.key);\n const dropKey = String(dropNode.key);\n const dragFileName = originalDragNode.path;\n let newPath: string;\n\n // 拖到底部 drop zone:放在根级别末尾\n if (!originalDropNode && dropKey === \"__bottom_placeholder__\") {\n newPath = dragFileName;\n onDrop?.({\n fileName: originalDragNode.title,\n extra: originalDragNode.extra,\n oldPath: dragKey,\n newPath,\n dragNode: originalDragNode,\n dropNode: { title: \"\", path: \"\" },\n });\n return;\n }\n\n if (!originalDropNode) return;\n\n if (!dropNode.isLeaf && dropPosition === 0) {\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 handleDragEnterExpand = useCallback(\n (nodeKey: string) => {\n const isExpanded = expandedKeys?.includes(nodeKey);\n if (!isExpanded) {\n onExpand?.([...(expandedKeys || []), nodeKey], {\n node: null as any,\n expanded: true,\n nativeEvent: null as any,\n });\n }\n },\n [expandedKeys, onExpand],\n );\n\n const {\n onDragStart,\n onDragEnd,\n onItemDragEnter,\n onItemDragOver,\n onItemDragLeave,\n onItemDrop,\n onContainerDragOver,\n onContainerDrop,\n canDragNode,\n } = useFolderDrag({\n dragMode,\n onDrop: handleDragDrop,\n onDragEnterExpand: handleDragEnterExpand,\n });\n\n // ====== 转换树数据 ======\n // 注意:convertToTreeData 不依赖拖拽状态,拖拽效果通过 DOM 操作实现\n const convertToTreeData = useCallback(\n (\n nodes: FolderTreeData[],\n parentSegments: string[] = [],\n parentKey: string = \"\",\n ): DataNode[] => {\n const result = nodes.map((node) => {\n const pathSegments = buildPathSegments(node, parentSegments);\n const fullPath = pathSegments.join(\"/\").replace(/^\\/+/, \"\");\n\n const isEditing = editNode && editNode.key === fullPath;\n\n const nodeChildren = node.children\n ? convertToTreeData(node.children, pathSegments, fullPath)\n : undefined;\n\n const baseNode: any = {\n key: fullPath,\n path: fullPath,\n pathSegments,\n icon: getIcon(node),\n isLeaf: !isFolder(node),\n _originalNode: node,\n children: nodeChildren,\n };\n\n // 编辑态:直接渲染 inline input\n if (isEditing) {\n baseNode.title = renderInlineInput(editNode!.currentValue);\n return baseNode;\n }\n\n // title 内容(按钮、菜单等)\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 startRename: () => onStartRename?.(fullPath, node),\n })}\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 // 启用拖拽时:在 title 外层包裹具有 data-node-key 属性的容器,\n // 用于 DOM 查询和事件绑定。拖拽状态通过 CSS class 控制。\n if (dragMode) {\n const nodeData = baseNode as DataNode & {\n _isTempNode?: boolean;\n };\n const draggableDiv = canDragNode(nodeData);\n\n baseNode.title = (\n <div\n className={clsx(\n styles.treeNodeWrapper,\n draggableDiv && styles.dragNodeHandle,\n )}\n data-node-key={fullPath}\n draggable={draggableDiv}\n onDragStart={\n draggableDiv ? (e) => onDragStart(e, baseNode) : undefined\n }\n onDragEnd={draggableDiv ? onDragEnd : undefined}\n onDragEnter={(e) => onItemDragEnter(e, baseNode)}\n onDragOver={(e) => onItemDragOver(e, baseNode)}\n onDragLeave={onItemDragLeave}\n onDrop={(e) => onItemDrop(e, baseNode)}\n >\n {titleContent}\n </div>\n );\n } else {\n baseNode.title = titleContent;\n }\n\n return baseNode;\n });\n\n // 新建模式:在目标父节点下插入临时节点\n if (createInfo && editNode && editNode.mode === \"create\") {\n const targetParentKey = createInfo.parentKey;\n if (\n targetParentKey === parentKey ||\n (targetParentKey === \"\" && parentKey === \"\") ||\n (targetParentKey === \"/\" && parentKey === \"\")\n ) {\n const tempNode: any = {\n key: editNode.key,\n title: renderInlineInput(editNode.currentValue),\n icon:\n createInfo.type === \"folder\" ? (\n <FolderOutlined />\n ) : (\n <FileOutlined />\n ),\n isLeaf: createInfo.type === \"file\",\n path: editNode.key,\n pathSegments: [editNode.key],\n _originalNode: null,\n _isTempNode: true,\n };\n result.push(tempNode);\n }\n }\n\n return result;\n },\n [\n buildPathSegments,\n getIcon,\n moreActions,\n styles,\n editNode,\n renderInlineInput,\n createInfo,\n onStartRename,\n dragMode,\n canDragNode,\n onDragStart,\n onDragEnd,\n onItemDragEnter,\n onItemDragOver,\n onItemDragLeave,\n onItemDrop,\n ],\n );\n\n const treeDataConverted = useMemo(\n () => convertToTreeData(treeData, [], \"\"),\n [treeData, convertToTreeData],\n );\n\n const handleSelect: TreeProps[\"onSelect\"] = useCallback(\n (keys: any, info: any) => {\n // 编辑态不响应选中\n if (editNode) return;\n // 临时节点不可选中\n const node = info.node as DataNode & { _isTempNode?: boolean };\n if (node._isTempNode) return;\n // 点击 moreActions 区域不触发选中\n const target = info.nativeEvent?.target as HTMLElement | null;\n if (\n target &&\n (target.closest(\".folder-tree-more-icon\") ||\n target.closest(\".ant-dropdown\"))\n ) {\n return;\n }\n onSelect?.(keys, info);\n },\n [onSelect, editNode],\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\n className={styles.directoryTreeContent}\n onDragOver={dragMode ? onContainerDragOver : undefined}\n onDrop={dragMode ? onContainerDrop : undefined}\n >\n <AntDirectoryTree\n style={\n {\n \"--ant-tree-directory-node-selected-bg\": \"rgba(0,0,0,0.03)\",\n \"--ant-tree-directory-node-selected-color\": \"#1a1c1e\",\n } as React.CSSProperties\n }\n treeData={treeDataConverted}\n selectedKeys={selectedKeys}\n expandedKeys={expandedKeys}\n onSelect={handleSelect}\n onExpand={onExpand}\n multiple={false}\n blockNode\n showLine={showLine as any}\n switcherIcon={switcherIcon}\n defaultExpandAll={defaultExpandAll}\n draggable={false}\n />\n </div>\n </div>\n );\n};\n\nexport default DirectoryTreeComponent;\n"],"mappings":"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"}
|
|
@@ -1,16 +1,29 @@
|
|
|
1
|
-
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
|
2
1
|
import _regeneratorRuntime from "@babel/runtime/helpers/esm/regeneratorRuntime";
|
|
3
2
|
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
|
|
4
3
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
5
4
|
import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIteratorHelper";
|
|
6
5
|
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
7
|
-
import
|
|
6
|
+
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
|
7
|
+
import React, { useRef, useCallback, useEffect, useState, forwardRef, useImperativeHandle } from "react";
|
|
8
8
|
import clsx from "clsx";
|
|
9
9
|
import DirectoryTreeComponent from "./DirectoryTree";
|
|
10
10
|
import FilePreview from "./FilePreview";
|
|
11
11
|
import { useStyles } from "./styles";
|
|
12
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
13
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
+
function getAllExpandedKeys(nodes) {
|
|
15
|
+
var parentPath = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";
|
|
16
|
+
var keys = [];
|
|
17
|
+
nodes.forEach(function (node) {
|
|
18
|
+
var _node$children;
|
|
19
|
+
var currentPath = parentPath ? "".concat(parentPath, "/").concat(node.path) : node.path;
|
|
20
|
+
if ((_node$children = node.children) !== null && _node$children !== void 0 && _node$children.length) {
|
|
21
|
+
keys.push(currentPath);
|
|
22
|
+
keys.push.apply(keys, _toConsumableArray(getAllExpandedKeys(node.children, currentPath)));
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return keys;
|
|
26
|
+
}
|
|
14
27
|
var FolderTree = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
15
28
|
var className = props.className,
|
|
16
29
|
style = props.style,
|
|
@@ -158,6 +171,7 @@ var FolderTree = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
|
158
171
|
setCreateContext(null);
|
|
159
172
|
setEditNode({
|
|
160
173
|
key: fullPath,
|
|
174
|
+
type: node.type || "file",
|
|
161
175
|
originalTitle: titleStr,
|
|
162
176
|
currentValue: titleStr,
|
|
163
177
|
mode: "rename"
|
|
@@ -171,10 +185,11 @@ var FolderTree = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
|
171
185
|
_useState6 = _slicedToArray(_useState5, 2),
|
|
172
186
|
selectedFileState = _useState6[0],
|
|
173
187
|
setSelectedFileState = _useState6[1];
|
|
174
|
-
var
|
|
188
|
+
var controlled = expandedPaths !== undefined;
|
|
189
|
+
var _useState7 = useState(defaultExpandedPaths || []),
|
|
175
190
|
_useState8 = _slicedToArray(_useState7, 2),
|
|
176
191
|
expandedPathsState = _useState8[0],
|
|
177
|
-
|
|
192
|
+
setExpandedPathsState = _useState8[1];
|
|
178
193
|
var _useState9 = useState(isValidSelectedFile(selectedFile || defaultSelectedFile)),
|
|
179
194
|
_useState10 = _slicedToArray(_useState9, 2),
|
|
180
195
|
validSelectedFile = _useState10[0],
|
|
@@ -187,6 +202,7 @@ var FolderTree = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
|
187
202
|
_useState14 = _slicedToArray(_useState13, 2),
|
|
188
203
|
loadingContent = _useState14[0],
|
|
189
204
|
setLoadingContent = _useState14[1];
|
|
205
|
+
var initializedExpandRef = useRef(false);
|
|
190
206
|
|
|
191
207
|
// 受控模式同步
|
|
192
208
|
useEffect(function () {
|
|
@@ -194,12 +210,18 @@ var FolderTree = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
|
194
210
|
setSelectedFileState(selectedFile);
|
|
195
211
|
setValidSelectedFile(isValidSelectedFile(selectedFile));
|
|
196
212
|
}
|
|
197
|
-
}, [selectedFile,
|
|
213
|
+
}, [selectedFile, isValidSelectedFile]);
|
|
198
214
|
useEffect(function () {
|
|
199
|
-
if (
|
|
200
|
-
|
|
215
|
+
if (!controlled && defaultExpandAll && !initializedExpandRef.current && treeData.length > 0) {
|
|
216
|
+
initializedExpandRef.current = true;
|
|
217
|
+
setExpandedPathsState(getAllExpandedKeys(treeData));
|
|
201
218
|
}
|
|
202
|
-
}, [
|
|
219
|
+
}, [controlled, defaultExpandAll, treeData]);
|
|
220
|
+
useEffect(function () {
|
|
221
|
+
if (controlled) {
|
|
222
|
+
setExpandedPathsState(expandedPaths);
|
|
223
|
+
}
|
|
224
|
+
}, [controlled, expandedPaths]);
|
|
203
225
|
|
|
204
226
|
// ====== 加载文件内容 ======
|
|
205
227
|
useEffect(function () {
|
|
@@ -305,11 +327,10 @@ var FolderTree = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
|
305
327
|
onFileClick === null || onFileClick === void 0 || onFileClick(keys[0], originalNode.content, originalNode.extra);
|
|
306
328
|
}
|
|
307
329
|
};
|
|
308
|
-
var isExpandedControlled = expandedPaths !== undefined;
|
|
309
330
|
var handleExpand = function handleExpand(keys) {
|
|
310
331
|
var newPaths = keys;
|
|
311
|
-
if (
|
|
312
|
-
|
|
332
|
+
if (!controlled) {
|
|
333
|
+
setExpandedPathsState(newPaths);
|
|
313
334
|
}
|
|
314
335
|
onExpandedPathsChange === null || onExpandedPathsChange === void 0 || onExpandedPathsChange(newPaths);
|
|
315
336
|
};
|
|
@@ -327,22 +348,25 @@ var FolderTree = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
|
327
348
|
});
|
|
328
349
|
setEditNode({
|
|
329
350
|
key: tempKey,
|
|
351
|
+
type: options.type || "folder",
|
|
330
352
|
originalTitle: "",
|
|
331
353
|
currentValue: defaultName,
|
|
332
354
|
mode: "create"
|
|
333
355
|
});
|
|
334
356
|
|
|
335
357
|
// 自动展开父文件夹(仅在受控模式下需要,非受控模式由 defaultExpandAll 处理)
|
|
336
|
-
if (
|
|
337
|
-
|
|
358
|
+
if (!controlled && parentPath && parentPath !== "/") {
|
|
359
|
+
setExpandedPathsState(function (prev) {
|
|
338
360
|
var current = prev || [];
|
|
339
|
-
if (current.includes(parentPath))
|
|
361
|
+
if (current.includes(parentPath)) {
|
|
362
|
+
return current;
|
|
363
|
+
}
|
|
340
364
|
return [].concat(_toConsumableArray(current), [parentPath]);
|
|
341
365
|
});
|
|
342
366
|
}
|
|
343
367
|
}
|
|
344
368
|
};
|
|
345
|
-
}, []);
|
|
369
|
+
}, [controlled]);
|
|
346
370
|
return /*#__PURE__*/_jsxs("div", {
|
|
347
371
|
className: clsx(styles.container, !showPreview && styles.containerNoPreview, className),
|
|
348
372
|
style: _objectSpread(_objectSpread(_objectSpread({}, style), style !== null && style !== void 0 && style.background ? {
|
|
@@ -354,7 +378,7 @@ var FolderTree = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
|
354
378
|
treeData: treeData,
|
|
355
379
|
directoryIcons: directoryIcons,
|
|
356
380
|
selectedKeys: selectable && selectedFileState && validSelectedFile ? [selectedFileState.join("/")] : [],
|
|
357
|
-
expandedKeys:
|
|
381
|
+
expandedKeys: controlled ? expandedPaths : expandedPathsState,
|
|
358
382
|
onSelect: handleSelect,
|
|
359
383
|
onExpand: handleExpand,
|
|
360
384
|
defaultExpandAll: defaultExpandAll,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useCallback","useEffect","useState","forwardRef","useImperativeHandle","clsx","DirectoryTreeComponent","FilePreview","useStyles","jsx","_jsx","jsxs","_jsxs","FolderTree","props","ref","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","onRename","onCreate","styles","_useState","_useState2","_slicedToArray","editNode","setEditNode","_useState3","_useState4","createContext","setCreateContext","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","_findNodeAndValidate","key","handleEditValueChange","prev","_objectSpread","currentValue","handleEditConfirm","newValue","trim","mode","_findNodeAndValidate2","oldTitle","originalTitle","newTitle","parentKey","name","type","extra","handleEditCancel","handleStartRename","fullPath","titleStr","title","String","_useState5","_useState6","selectedFileState","setSelectedFileState","_useState7","_useState8","expandedPathsState","setExpandedPaths","_useState9","_useState10","validSelectedFile","setValidSelectedFile","_useState11","_useState12","fileContent","setFileContent","_useState13","_useState14","loadingContent","setLoadingContent","loadContent","_ref","_asyncToGenerator","_regeneratorRuntime","mark","_callee","_findNodeAndValidate3","content","wrap","_callee$","_context","next","abrupt","join","loadFileContent","sent","t0","concat","Error","message","finish","stop","apply","handleSelect","_keys","info","_keys$","keys","selectedNodes","isFolder","some","isLeaf","pathArray","_findNodeAndValidate4","originalNode","fileName","nodeContent","isControlled","isExpandedControlled","handleExpand","newPaths","createNode","parentPath","options","defaultName","tempKey","Date","now","current","includes","_toConsumableArray","container","containerNoPreview","background","backgroundColor","selectedKeys","expandedKeys","onSelect","onExpand","width","onEditValueChange","onEditConfirm","onEditCancel","createInfo","onStartRename","loading","getFileNode","_findNodeAndValidate5","displayName"],"sources":["../../../../src/components/FolderTree/index.tsx"],"sourcesContent":["import React, {\n useCallback,\n useEffect,\n useState,\n forwardRef,\n useImperativeHandle,\n} from \"react\";\nimport type { TreeProps } from \"antd\";\nimport clsx from \"clsx\";\nimport type {\n FolderTreeData,\n FolderTreeProps,\n FolderTreeRef,\n EditNodeInfo,\n CreateNodeContext,\n} from \"./types\";\nimport DirectoryTreeComponent from \"./DirectoryTree\";\nimport FilePreview from \"./FilePreview\";\nimport { useStyles } from \"./styles\";\n\nexport type {\n FolderTreeData,\n FolderTreeProps,\n FileContentService,\n FolderTreeRef,\n} from \"./types\";\n\nconst FolderTree = forwardRef<FolderTreeRef, FolderTreeProps>((props, ref) => {\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 onRename,\n onCreate,\n } = props;\n\n const styles = useStyles();\n\n // ====== 编辑态状态 ======\n const [editNode, setEditNode] = useState<EditNodeInfo | null>(null);\n const [createContext, setCreateContext] = useState<CreateNodeContext | null>(\n null\n );\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 // ====== 编辑态逻辑 ======\n\n // 当 treeData 变化时,检查编辑节点是否还存在\n useEffect(() => {\n if (!editNode) return;\n const { node } = findNodeAndValidate(editNode.key);\n if (!node) {\n setEditNode(null);\n setCreateContext(null);\n }\n }, [treeData]);\n\n // 编辑值变化\n const handleEditValueChange = useCallback((value: string) => {\n setEditNode((prev) => (prev ? { ...prev, currentValue: value } : null));\n }, []);\n\n // 确认编辑\n const handleEditConfirm = useCallback(() => {\n if (!editNode) return;\n const newValue = editNode.currentValue.trim();\n\n if (editNode.mode === \"rename\") {\n const { node } = findNodeAndValidate(editNode.key);\n onRename?.({\n key: editNode.key,\n oldTitle: editNode.originalTitle,\n newTitle: newValue,\n node: node!,\n });\n } else if (editNode.mode === \"create\" && createContext) {\n onCreate?.({\n parentKey: createContext.parentKey,\n name: newValue,\n type: createContext.type,\n extra: createContext.extra,\n });\n }\n\n setEditNode(null);\n setCreateContext(null);\n }, [editNode, createContext, findNodeAndValidate, onRename, onCreate]);\n\n // 取消编辑\n const handleEditCancel = useCallback(() => {\n setEditNode(null);\n setCreateContext(null);\n }, []);\n\n // 开始重命名\n const handleStartRename = useCallback(\n (fullPath: string, node: FolderTreeData) => {\n const titleStr =\n typeof node.title === \"string\" ? node.title : String(node.path);\n setCreateContext(null);\n setEditNode({\n key: fullPath,\n originalTitle: titleStr,\n currentValue: titleStr,\n mode: \"rename\",\n });\n },\n []\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 isExpandedControlled = expandedPaths !== undefined;\n\n const handleExpand: TreeProps[\"onExpand\"] = (keys) => {\n const newPaths = keys as string[];\n if (isExpandedControlled) {\n setExpandedPaths(newPaths);\n }\n onExpandedPathsChange?.(newPaths);\n };\n\n // ====== 命令式 API ======\n useImperativeHandle(\n ref,\n () => ({\n createNode: (parentPath, options) => {\n const defaultName =\n options.defaultName ||\n (options.type === \"folder\" ? \"新建文件夹\" : \"新建文件\");\n const tempKey = `__create__${parentPath || \"root\"}__${Date.now()}`;\n\n setCreateContext({\n parentKey: parentPath,\n type: options.type,\n extra: options.extra,\n });\n setEditNode({\n key: tempKey,\n originalTitle: \"\",\n currentValue: defaultName,\n mode: \"create\",\n });\n\n // 自动展开父文件夹(仅在受控模式下需要,非受控模式由 defaultExpandAll 处理)\n if (isExpandedControlled && parentPath && parentPath !== \"/\") {\n setExpandedPaths((prev) => {\n const current = prev || [];\n if (current.includes(parentPath)) return current;\n return [...current, parentPath];\n });\n }\n },\n }),\n []\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={isExpandedControlled ? expandedPathsState : undefined}\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 editNode={editNode}\n onEditValueChange={handleEditValueChange}\n onEditConfirm={handleEditConfirm}\n onEditCancel={handleEditCancel}\n createInfo={createContext}\n onStartRename={handleStartRename}\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\nFolderTree.displayName = \"FolderTree\";\n\nexport default FolderTree;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["React","useRef","useCallback","useEffect","useState","forwardRef","useImperativeHandle","clsx","DirectoryTreeComponent","FilePreview","useStyles","jsx","_jsx","jsxs","_jsxs","getAllExpandedKeys","nodes","parentPath","arguments","length","undefined","keys","forEach","node","_node$children","currentPath","concat","path","children","push","apply","_toConsumableArray","FolderTree","props","ref","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","onRename","onCreate","styles","_useState","_useState2","_slicedToArray","editNode","setEditNode","_useState3","_useState4","createContext","setCreateContext","findNodeAndValidate","validateAsFile","isValid","segments","Array","isArray","filter","Boolean","split","findNode","index","currentSegment","_iterator","_createForOfIteratorHelper","_step","s","n","done","value","err","e","f","isValidSelectedFile","filePath","_findNodeAndValidate","key","handleEditValueChange","prev","_objectSpread","currentValue","handleEditConfirm","newValue","trim","mode","_findNodeAndValidate2","oldTitle","originalTitle","newTitle","parentKey","name","type","extra","handleEditCancel","handleStartRename","fullPath","titleStr","title","String","_useState5","_useState6","selectedFileState","setSelectedFileState","controlled","_useState7","_useState8","expandedPathsState","setExpandedPathsState","_useState9","_useState10","validSelectedFile","setValidSelectedFile","_useState11","_useState12","fileContent","setFileContent","_useState13","_useState14","loadingContent","setLoadingContent","initializedExpandRef","current","loadContent","_ref","_asyncToGenerator","_regeneratorRuntime","mark","_callee","_findNodeAndValidate3","content","wrap","_callee$","_context","next","abrupt","join","loadFileContent","sent","t0","Error","message","finish","stop","handleSelect","_keys","info","_keys$","selectedNodes","isFolder","some","isLeaf","pathArray","_findNodeAndValidate4","originalNode","fileName","nodeContent","isControlled","handleExpand","newPaths","createNode","options","defaultName","tempKey","Date","now","includes","container","containerNoPreview","background","backgroundColor","selectedKeys","expandedKeys","onSelect","onExpand","width","onEditValueChange","onEditConfirm","onEditCancel","createInfo","onStartRename","loading","getFileNode","_findNodeAndValidate5","displayName"],"sources":["../../../../src/components/FolderTree/index.tsx"],"sourcesContent":["import React, {\n useRef,\n useCallback,\n useEffect,\n useState,\n forwardRef,\n useImperativeHandle,\n} from \"react\";\nimport type { TreeProps } from \"antd\";\nimport clsx from \"clsx\";\nimport type {\n FolderTreeData,\n FolderTreeProps,\n FolderTreeRef,\n EditNodeInfo,\n CreateNodeContext,\n} from \"./types\";\nimport DirectoryTreeComponent from \"./DirectoryTree\";\nimport FilePreview from \"./FilePreview\";\nimport { useStyles } from \"./styles\";\n\nexport type {\n FolderTreeData,\n FolderTreeProps,\n FileContentService,\n FolderTreeRef,\n} from \"./types\";\n\nfunction getAllExpandedKeys(\n nodes: FolderTreeData[],\n parentPath = \"\",\n): string[] {\n const keys: string[] = [];\n\n nodes.forEach((node) => {\n const currentPath = parentPath ? `${parentPath}/${node.path}` : node.path;\n\n if (node.children?.length) {\n keys.push(currentPath);\n keys.push(...getAllExpandedKeys(node.children, currentPath));\n }\n });\n\n return keys;\n}\n\nconst FolderTree = forwardRef<FolderTreeRef, FolderTreeProps>((props, ref) => {\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 onRename,\n onCreate,\n } = props;\n\n const styles = useStyles();\n\n // ====== 编辑态状态 ======\n const [editNode, setEditNode] = useState<EditNodeInfo | null>(null);\n const [createContext, setCreateContext] = useState<CreateNodeContext | null>(\n null,\n );\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 // ====== 编辑态逻辑 ======\n\n // 当 treeData 变化时,检查编辑节点是否还存在\n useEffect(() => {\n if (!editNode) return;\n const { node } = findNodeAndValidate(editNode.key);\n if (!node) {\n setEditNode(null);\n setCreateContext(null);\n }\n }, [treeData]);\n\n // 编辑值变化\n const handleEditValueChange = useCallback((value: string) => {\n setEditNode((prev) => (prev ? { ...prev, currentValue: value } : null));\n }, []);\n\n // 确认编辑\n const handleEditConfirm = useCallback(() => {\n if (!editNode) return;\n const newValue = editNode.currentValue.trim();\n\n if (editNode.mode === \"rename\") {\n const { node } = findNodeAndValidate(editNode.key);\n onRename?.({\n key: editNode.key,\n oldTitle: editNode.originalTitle,\n newTitle: newValue,\n node: node!,\n });\n } else if (editNode.mode === \"create\" && createContext) {\n onCreate?.({\n parentKey: createContext.parentKey,\n name: newValue,\n type: createContext.type,\n extra: createContext.extra,\n });\n }\n\n setEditNode(null);\n setCreateContext(null);\n }, [editNode, createContext, findNodeAndValidate, onRename, onCreate]);\n\n // 取消编辑\n const handleEditCancel = useCallback(() => {\n setEditNode(null);\n setCreateContext(null);\n }, []);\n\n // 开始重命名\n const handleStartRename = useCallback(\n (fullPath: string, node: FolderTreeData) => {\n const titleStr =\n typeof node.title === \"string\" ? node.title : String(node.path);\n setCreateContext(null);\n setEditNode({\n key: fullPath,\n type: node.type || \"file\",\n originalTitle: titleStr,\n currentValue: titleStr,\n mode: \"rename\",\n });\n },\n [],\n );\n\n // ====== State ======\n const [selectedFileState, setSelectedFileState] = useState<string[]>(() =>\n isValidSelectedFile(selectedFile || defaultSelectedFile)\n ? selectedFile || defaultSelectedFile || []\n : [],\n );\n const controlled = expandedPaths !== undefined;\n\n const [expandedPathsState, setExpandedPathsState] = useState<string[]>(\n 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 const initializedExpandRef = useRef(false);\n\n // 受控模式同步\n useEffect(() => {\n if (selectedFile !== undefined) {\n setSelectedFileState(selectedFile);\n setValidSelectedFile(isValidSelectedFile(selectedFile));\n }\n }, [selectedFile, isValidSelectedFile]);\n\n useEffect(() => {\n if (\n !controlled &&\n defaultExpandAll &&\n !initializedExpandRef.current &&\n treeData.length > 0\n ) {\n initializedExpandRef.current = true;\n\n setExpandedPathsState(getAllExpandedKeys(treeData));\n }\n }, [controlled, defaultExpandAll, treeData]);\n\n useEffect(() => {\n if (controlled) {\n setExpandedPathsState(expandedPaths);\n }\n }, [controlled, 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?.(keys[0], originalNode.content, originalNode.extra);\n }\n };\n\n const handleExpand: TreeProps[\"onExpand\"] = (keys) => {\n const newPaths = keys as string[];\n\n if (!controlled) {\n setExpandedPathsState(newPaths);\n }\n\n onExpandedPathsChange?.(newPaths);\n };\n\n // ====== 命令式 API ======\n useImperativeHandle(\n ref,\n () => ({\n createNode: (parentPath, options) => {\n const defaultName =\n options.defaultName ||\n (options.type === \"folder\" ? \"新建文件夹\" : \"新建文件\");\n const tempKey = `__create__${parentPath || \"root\"}__${Date.now()}`;\n\n setCreateContext({\n parentKey: parentPath,\n type: options.type,\n extra: options.extra,\n });\n setEditNode({\n key: tempKey,\n type: options.type || \"folder\",\n originalTitle: \"\",\n currentValue: defaultName,\n mode: \"create\",\n });\n\n // 自动展开父文件夹(仅在受控模式下需要,非受控模式由 defaultExpandAll 处理)\n if (!controlled && parentPath && parentPath !== \"/\") {\n setExpandedPathsState((prev) => {\n const current = prev || [];\n\n if (current.includes(parentPath)) {\n return current;\n }\n\n return [...current, parentPath];\n });\n }\n },\n }),\n [controlled],\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={controlled ? expandedPaths : 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 editNode={editNode}\n onEditValueChange={handleEditValueChange}\n onEditConfirm={handleEditConfirm}\n onEditCancel={handleEditCancel}\n createInfo={createContext}\n onStartRename={handleStartRename}\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\nFolderTree.displayName = \"FolderTree\";\n\nexport default FolderTree;\n"],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ export interface FolderTreeData<T = any> {
|
|
|
5
5
|
title: React.ReactNode;
|
|
6
6
|
path: string;
|
|
7
7
|
content?: string;
|
|
8
|
+
type?: "folder" | "file";
|
|
8
9
|
extra?: T;
|
|
9
10
|
children?: FolderTreeData<T>[];
|
|
10
11
|
}
|
|
@@ -18,6 +19,8 @@ export interface EditNodeInfo {
|
|
|
18
19
|
key: string;
|
|
19
20
|
/** 原始标题 */
|
|
20
21
|
originalTitle: string;
|
|
22
|
+
/** 文件类型 */
|
|
23
|
+
type: "folder" | "file";
|
|
21
24
|
/** 当前输入值 */
|
|
22
25
|
currentValue: string;
|
|
23
26
|
/** 编辑模式:重命名或新建 */
|
|
@@ -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/** 编辑节点信息 */\nexport interface EditNodeInfo {\n /** 完整路径 key */\n key: string;\n /** 原始标题 */\n originalTitle: string;\n /** 当前输入值 */\n currentValue: string;\n /** 编辑模式:重命名或新建 */\n mode: \"rename\" | \"create\";\n}\n\n/** 新建上下文 */\nexport interface CreateNodeContext {\n /** 父节点 key */\n parentKey: string;\n /** 节点类型 */\n type: \"file\" | \"folder\";\n /** 附加数据 */\n extra?: any;\n}\n\n/** FolderTree 命令式 API */\nexport interface FolderTreeRef {\n /**\n * 在指定父路径下新建文件或文件夹\n * @param parentPath - 父节点完整路径(空字符串或 \"/\" 表示根路径)\n * @param options.type - 节点类型\n * @param options.defaultName - 默认名称\n * @param options.extra - 自定义附加数据\n */\n createNode: (\n parentPath: string,\n options: {\n type: \"file\" | \"folder\";\n defaultName?: string;\n extra?: any;\n }
|
|
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 type?: \"folder\" | \"file\";\n extra?: T;\n children?: FolderTreeData<T>[];\n}\n\n/** 文件内容加载服务 */\nexport interface FileContentService {\n loadFileContent(filePath: string): Promise<string>;\n}\n\n/** 编辑节点信息 */\nexport interface EditNodeInfo {\n /** 完整路径 key */\n key: string;\n /** 原始标题 */\n originalTitle: string;\n /** 文件类型 */\n type: \"folder\" | \"file\";\n /** 当前输入值 */\n currentValue: string;\n /** 编辑模式:重命名或新建 */\n mode: \"rename\" | \"create\";\n}\n\n/** 新建上下文 */\nexport interface CreateNodeContext {\n /** 父节点 key */\n parentKey: string;\n /** 节点类型 */\n type: \"file\" | \"folder\";\n /** 附加数据 */\n extra?: any;\n}\n\n/** FolderTree 命令式 API */\nexport interface FolderTreeRef {\n /**\n * 在指定父路径下新建文件或文件夹\n * @param parentPath - 父节点完整路径(空字符串或 \"/\" 表示根路径)\n * @param options.type - 节点类型\n * @param options.defaultName - 默认名称\n * @param options.extra - 自定义附加数据\n */\n createNode: (\n parentPath: string,\n options: {\n type: \"file\" | \"folder\";\n defaultName?: string;\n extra?: any;\n },\n ) => void;\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?: (\n node: FolderTreeData,\n actions?: { startRename: () => void },\n ) => 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 onRename?: (info: {\n /** 节点完整路径 key */\n key: string;\n /** 原始标题 */\n oldTitle: React.ReactNode;\n /** 新标题 */\n newTitle: string;\n /** 原始节点数据 */\n node: FolderTreeData;\n }) => void;\n\n /** 新建确认回调,失焦或回车时触发 */\n onCreate?: (info: {\n /** 父节点 key */\n parentKey: string;\n /** 用户输入的名称 */\n name: string;\n /** 节点类型 */\n type: \"file\" | \"folder\";\n /** 附加数据 */\n extra?: any;\n }) => void;\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":""}
|