listpage-next 0.0.246 → 0.0.247
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/features/ChatClient/components/ChatContent/ClientContentHeader.js +3 -24
- package/dist/ui/Button/index.d.ts +1 -1
- package/dist/ui/Button/index.js +3 -1
- package/dist/ui/FileManager/FileManager.d.ts +7 -0
- package/dist/ui/FileManager/FileManager.js +278 -0
- package/dist/ui/FileManager/components/AddAssetModal.d.ts +11 -0
- package/dist/ui/FileManager/components/AddAssetModal.js +197 -0
- package/dist/ui/FileManager/components/AssetGrid.d.ts +11 -0
- package/dist/ui/FileManager/components/AssetGrid.js +188 -0
- package/dist/ui/FileManager/components/AssetSelectorModal.d.ts +12 -0
- package/dist/ui/FileManager/components/AssetSelectorModal.js +133 -0
- package/dist/ui/FileManager/components/Breadcrumbs.d.ts +10 -0
- package/dist/ui/FileManager/components/Breadcrumbs.js +25 -0
- package/dist/ui/FileManager/components/CreateFolderModal.d.ts +7 -0
- package/dist/ui/FileManager/components/CreateFolderModal.js +84 -0
- package/dist/ui/FileManager/components/DeleteConfirmModal.d.ts +9 -0
- package/dist/ui/FileManager/components/DeleteConfirmModal.js +33 -0
- package/dist/ui/FileManager/components/FileTypePreview.d.ts +7 -0
- package/dist/ui/FileManager/components/FileTypePreview.js +29 -0
- package/dist/ui/FileManager/components/FolderTree.d.ts +13 -0
- package/dist/ui/FileManager/components/FolderTree.js +137 -0
- package/dist/ui/FileManager/components/HeaderBar.d.ts +13 -0
- package/dist/ui/FileManager/components/HeaderBar.js +37 -0
- package/dist/ui/FileManager/components/InspectorPanel.d.ts +9 -0
- package/dist/ui/FileManager/components/InspectorPanel.js +119 -0
- package/dist/ui/FileManager/components/SearchInput.d.ts +7 -0
- package/dist/ui/FileManager/components/SearchInput.js +19 -0
- package/dist/ui/FileManager/components/Sidebar.d.ts +12 -0
- package/dist/ui/FileManager/components/Sidebar.js +79 -0
- package/dist/ui/FileManager/components/ViewModeToggle.d.ts +8 -0
- package/dist/ui/FileManager/components/ViewModeToggle.js +23 -0
- package/dist/ui/FileManager/index.d.ts +3 -0
- package/dist/ui/FileManager/index.js +3 -0
- package/dist/ui/FileManager/services/config.d.ts +8 -0
- package/dist/ui/FileManager/services/config.js +18 -0
- package/dist/ui/FileManager/services/storageService.d.ts +14 -0
- package/dist/ui/FileManager/services/storageService.js +249 -0
- package/dist/ui/FileManager/types.d.ts +36 -0
- package/dist/ui/FileManager/types.js +0 -0
- package/dist/ui/Modal/ConfirmModal.d.ts +11 -0
- package/dist/ui/Modal/ConfirmModal.js +62 -0
- package/dist/ui/Modal/Modal.d.ts +14 -0
- package/dist/ui/Modal/Modal.js +64 -0
- package/dist/ui/Modal/index.d.ts +2 -0
- package/dist/ui/Modal/index.js +3 -0
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/index.js +2 -1
- package/dist/ui.css +755 -0
- package/package.json +4 -2
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ChevronDown, ChevronRight, FolderIcon, FolderOpen, HardDrive, Plus } from "lucide-react";
|
|
3
|
+
import { useControllableValue } from "ahooks";
|
|
4
|
+
const FolderTree = ({ parentId, depth = 0, folders, expandedFolders: controlledExpandedFolders, currentFolderId, onNavigate, onToggleExpand: controlledOnToggleExpand, onAddFolder, showRoot = false })=>{
|
|
5
|
+
const [expandedFolders, onToggleExpand] = useControllableValue({
|
|
6
|
+
value: controlledExpandedFolders,
|
|
7
|
+
onChange: controlledOnToggleExpand
|
|
8
|
+
});
|
|
9
|
+
if (showRoot) {
|
|
10
|
+
const isRootExpanded = expandedFolders?.has('root');
|
|
11
|
+
const isActive = null === currentFolderId;
|
|
12
|
+
return /*#__PURE__*/ jsx("div", {
|
|
13
|
+
className: "flex flex-col",
|
|
14
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
15
|
+
children: [
|
|
16
|
+
/*#__PURE__*/ jsxs("div", {
|
|
17
|
+
className: `
|
|
18
|
+
flex items-center gap-2 px-3 py-1.5 rounded-md cursor-pointer text-sm select-none transition-colors
|
|
19
|
+
${isActive ? 'bg-indigo-500/20 text-indigo-300' : 'text-slate-400 hover:text-white hover:bg-slate-800/50'}
|
|
20
|
+
`,
|
|
21
|
+
style: {
|
|
22
|
+
paddingLeft: `${12 * depth + 12}px`
|
|
23
|
+
},
|
|
24
|
+
onClick: ()=>onNavigate(null),
|
|
25
|
+
children: [
|
|
26
|
+
/*#__PURE__*/ jsx("div", {
|
|
27
|
+
className: "p-0.5 rounded hover:bg-slate-700/50 visible",
|
|
28
|
+
onClick: (e)=>{
|
|
29
|
+
e.stopPropagation();
|
|
30
|
+
onToggleExpand('root');
|
|
31
|
+
},
|
|
32
|
+
children: isRootExpanded ? /*#__PURE__*/ jsx(ChevronDown, {
|
|
33
|
+
className: "w-3 h-3"
|
|
34
|
+
}) : /*#__PURE__*/ jsx(ChevronRight, {
|
|
35
|
+
className: "w-3 h-3"
|
|
36
|
+
})
|
|
37
|
+
}),
|
|
38
|
+
/*#__PURE__*/ jsx(HardDrive, {
|
|
39
|
+
className: "w-4 h-4"
|
|
40
|
+
}),
|
|
41
|
+
/*#__PURE__*/ jsx("span", {
|
|
42
|
+
className: "truncate flex-1",
|
|
43
|
+
children: '根目录'
|
|
44
|
+
}),
|
|
45
|
+
onAddFolder && /*#__PURE__*/ jsx("div", {
|
|
46
|
+
className: "p-1 hover:bg-slate-700 rounded text-slate-400 hover:text-white",
|
|
47
|
+
onClick: (e)=>{
|
|
48
|
+
e.stopPropagation();
|
|
49
|
+
onAddFolder(null);
|
|
50
|
+
},
|
|
51
|
+
children: /*#__PURE__*/ jsx(Plus, {
|
|
52
|
+
className: "w-4 h-4"
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
]
|
|
56
|
+
}),
|
|
57
|
+
isRootExpanded && /*#__PURE__*/ jsx(FolderTree, {
|
|
58
|
+
parentId: null,
|
|
59
|
+
depth: depth + 1,
|
|
60
|
+
folders: folders,
|
|
61
|
+
expandedFolders: expandedFolders,
|
|
62
|
+
currentFolderId: currentFolderId,
|
|
63
|
+
onNavigate: onNavigate,
|
|
64
|
+
onToggleExpand: onToggleExpand,
|
|
65
|
+
onAddFolder: onAddFolder,
|
|
66
|
+
showRoot: false
|
|
67
|
+
})
|
|
68
|
+
]
|
|
69
|
+
})
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const childFolders = folders.filter((f)=>f.parentId === parentId);
|
|
73
|
+
if (0 === childFolders.length) return null;
|
|
74
|
+
return /*#__PURE__*/ jsx("div", {
|
|
75
|
+
className: "flex flex-col",
|
|
76
|
+
children: childFolders.map((folder)=>{
|
|
77
|
+
const isExpanded = expandedFolders?.has(folder.id);
|
|
78
|
+
const isActive = currentFolderId === folder.id;
|
|
79
|
+
const hasChildren = folders.some((f)=>f.parentId === folder.id);
|
|
80
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
81
|
+
children: [
|
|
82
|
+
/*#__PURE__*/ jsxs("div", {
|
|
83
|
+
className: `
|
|
84
|
+
flex items-center gap-2 px-3 py-1.5 rounded-md cursor-pointer text-sm select-none transition-colors
|
|
85
|
+
${isActive ? 'bg-indigo-500/20 text-indigo-300' : 'text-slate-400 hover:text-white hover:bg-slate-800/50'}
|
|
86
|
+
`,
|
|
87
|
+
style: {
|
|
88
|
+
paddingLeft: `${12 * depth + 12}px`
|
|
89
|
+
},
|
|
90
|
+
onClick: ()=>onNavigate(folder.id),
|
|
91
|
+
children: [
|
|
92
|
+
/*#__PURE__*/ jsx("div", {
|
|
93
|
+
className: `p-0.5 rounded hover:bg-slate-700/50 ${hasChildren ? 'visible' : 'invisible'}`,
|
|
94
|
+
onClick: (e)=>onToggleExpand(folder.id),
|
|
95
|
+
children: isExpanded ? /*#__PURE__*/ jsx(ChevronDown, {
|
|
96
|
+
className: "w-3 h-3"
|
|
97
|
+
}) : /*#__PURE__*/ jsx(ChevronRight, {
|
|
98
|
+
className: "w-3 h-3"
|
|
99
|
+
})
|
|
100
|
+
}),
|
|
101
|
+
isActive || isExpanded ? /*#__PURE__*/ jsx(FolderOpen, {
|
|
102
|
+
className: `w-4 h-4 ${isActive ? 'text-indigo-400' : 'text-slate-400'}`
|
|
103
|
+
}) : /*#__PURE__*/ jsx(FolderIcon, {
|
|
104
|
+
className: "w-4 h-4"
|
|
105
|
+
}),
|
|
106
|
+
/*#__PURE__*/ jsx("span", {
|
|
107
|
+
className: "truncate flex-1",
|
|
108
|
+
children: folder.name
|
|
109
|
+
}),
|
|
110
|
+
onAddFolder && /*#__PURE__*/ jsx("div", {
|
|
111
|
+
className: "p-1 hover:bg-slate-700 rounded text-slate-400 hover:text-white",
|
|
112
|
+
onClick: (e)=>{
|
|
113
|
+
e.stopPropagation();
|
|
114
|
+
onAddFolder(folder);
|
|
115
|
+
},
|
|
116
|
+
children: /*#__PURE__*/ jsx(Plus, {
|
|
117
|
+
className: "w-4 h-4"
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
]
|
|
121
|
+
}),
|
|
122
|
+
isExpanded && /*#__PURE__*/ jsx(FolderTree, {
|
|
123
|
+
parentId: folder.id,
|
|
124
|
+
depth: depth + 1,
|
|
125
|
+
folders: folders,
|
|
126
|
+
expandedFolders: expandedFolders,
|
|
127
|
+
currentFolderId: currentFolderId,
|
|
128
|
+
onNavigate: onNavigate,
|
|
129
|
+
onToggleExpand: onToggleExpand,
|
|
130
|
+
onAddFolder: onAddFolder
|
|
131
|
+
})
|
|
132
|
+
]
|
|
133
|
+
}, folder.id);
|
|
134
|
+
})
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
export { FolderTree };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ViewMode } from '../types';
|
|
3
|
+
import { BreadcrumbItem } from './Breadcrumbs';
|
|
4
|
+
export interface HeaderBarProps {
|
|
5
|
+
breadcrumbs: BreadcrumbItem[];
|
|
6
|
+
search: string;
|
|
7
|
+
onSearchChange: (v: string) => void;
|
|
8
|
+
onNavigate: (folderId: string | null) => void;
|
|
9
|
+
onCreateFolder: () => void;
|
|
10
|
+
viewMode: ViewMode;
|
|
11
|
+
onChangeViewMode: (mode: ViewMode) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare const HeaderBar: React.FC<HeaderBarProps>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "react";
|
|
3
|
+
import { Breadcrumbs } from "./Breadcrumbs.js";
|
|
4
|
+
import { SearchInput } from "./SearchInput.js";
|
|
5
|
+
import { ViewModeToggle } from "./ViewModeToggle.js";
|
|
6
|
+
const HeaderBar = ({ breadcrumbs, search, onSearchChange, onNavigate, onCreateFolder, viewMode, onChangeViewMode })=>/*#__PURE__*/ jsxs("header", {
|
|
7
|
+
className: "h-16 border-b border-slate-800 bg-slate-900/50 backdrop-blur flex items-center justify-between px-6 shrink-0 z-10",
|
|
8
|
+
children: [
|
|
9
|
+
/*#__PURE__*/ jsxs("div", {
|
|
10
|
+
className: "flex items-center gap-4 flex-1",
|
|
11
|
+
children: [
|
|
12
|
+
search ? /*#__PURE__*/ jsx("div", {
|
|
13
|
+
className: "text-lg font-medium text-slate-200",
|
|
14
|
+
children: "搜索结果"
|
|
15
|
+
}) : /*#__PURE__*/ jsx(Breadcrumbs, {
|
|
16
|
+
items: breadcrumbs,
|
|
17
|
+
onNavigate: onNavigate
|
|
18
|
+
}),
|
|
19
|
+
/*#__PURE__*/ jsx("div", {
|
|
20
|
+
className: "h-6 w-px bg-slate-800 mx-2"
|
|
21
|
+
}),
|
|
22
|
+
/*#__PURE__*/ jsx(SearchInput, {
|
|
23
|
+
value: search,
|
|
24
|
+
onChange: onSearchChange
|
|
25
|
+
})
|
|
26
|
+
]
|
|
27
|
+
}),
|
|
28
|
+
/*#__PURE__*/ jsx("div", {
|
|
29
|
+
className: "flex items-center gap-3 ml-4",
|
|
30
|
+
children: /*#__PURE__*/ jsx(ViewModeToggle, {
|
|
31
|
+
viewMode: viewMode,
|
|
32
|
+
onChange: onChangeViewMode
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
]
|
|
36
|
+
});
|
|
37
|
+
export { HeaderBar };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FileSystemItem, Folder } from '../types';
|
|
3
|
+
interface InspectorPanelProps {
|
|
4
|
+
item: FileSystemItem;
|
|
5
|
+
folders: Folder[];
|
|
6
|
+
onDelete: (id: string, type: 'asset', name: string) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare const InspectorPanel: React.FC<InspectorPanelProps>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "react";
|
|
3
|
+
import dayjs from "dayjs";
|
|
4
|
+
import FileTypePreview from "./FileTypePreview.js";
|
|
5
|
+
const InspectorPanel = ({ item, folders, onDelete })=>{
|
|
6
|
+
if (!item || 'folder' === item.type) return null;
|
|
7
|
+
const asset = item;
|
|
8
|
+
return /*#__PURE__*/ jsx("aside", {
|
|
9
|
+
className: "w-80 bg-slate-900 border-l border-slate-800 overflow-y-auto shrink-0",
|
|
10
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
11
|
+
className: "p-6 space-y-6",
|
|
12
|
+
children: [
|
|
13
|
+
/*#__PURE__*/ jsx("div", {
|
|
14
|
+
className: "h-64 bg-slate-950 rounded-lg overflow-hidden border border-slate-800 shadow-lg relative flex items-center justify-center",
|
|
15
|
+
children: /*#__PURE__*/ jsx(FileTypePreview, {
|
|
16
|
+
asset: asset
|
|
17
|
+
})
|
|
18
|
+
}),
|
|
19
|
+
/*#__PURE__*/ jsxs("div", {
|
|
20
|
+
children: [
|
|
21
|
+
/*#__PURE__*/ jsx("h2", {
|
|
22
|
+
className: "text-lg font-bold text-white wrap-break-word",
|
|
23
|
+
children: asset.name
|
|
24
|
+
}),
|
|
25
|
+
/*#__PURE__*/ jsxs("p", {
|
|
26
|
+
className: "text-sm text-slate-500 mt-1",
|
|
27
|
+
children: [
|
|
28
|
+
"添加于 ",
|
|
29
|
+
dayjs(asset.createdAt).format('YYYY-MM-DD')
|
|
30
|
+
]
|
|
31
|
+
})
|
|
32
|
+
]
|
|
33
|
+
}),
|
|
34
|
+
/*#__PURE__*/ jsxs("div", {
|
|
35
|
+
className: "space-y-4",
|
|
36
|
+
children: [
|
|
37
|
+
/*#__PURE__*/ jsxs("div", {
|
|
38
|
+
children: [
|
|
39
|
+
/*#__PURE__*/ jsx("h3", {
|
|
40
|
+
className: "text-xs font-semibold text-slate-500 uppercase tracking-wider mb-2",
|
|
41
|
+
children: "属性"
|
|
42
|
+
}),
|
|
43
|
+
/*#__PURE__*/ jsxs("div", {
|
|
44
|
+
className: "grid grid-cols-2 gap-2 text-sm",
|
|
45
|
+
children: [
|
|
46
|
+
asset.width ? /*#__PURE__*/ jsxs("div", {
|
|
47
|
+
className: "bg-slate-800/50 p-2 rounded",
|
|
48
|
+
children: [
|
|
49
|
+
/*#__PURE__*/ jsx("span", {
|
|
50
|
+
className: "text-slate-500 block text-xs",
|
|
51
|
+
children: "尺寸"
|
|
52
|
+
}),
|
|
53
|
+
/*#__PURE__*/ jsxs("span", {
|
|
54
|
+
className: "text-slate-200",
|
|
55
|
+
children: [
|
|
56
|
+
asset.width,
|
|
57
|
+
" x ",
|
|
58
|
+
asset.height
|
|
59
|
+
]
|
|
60
|
+
})
|
|
61
|
+
]
|
|
62
|
+
}) : null,
|
|
63
|
+
/*#__PURE__*/ jsxs("div", {
|
|
64
|
+
className: "bg-slate-800/50 p-2 rounded",
|
|
65
|
+
children: [
|
|
66
|
+
/*#__PURE__*/ jsx("span", {
|
|
67
|
+
className: "text-slate-500 block text-xs",
|
|
68
|
+
children: "大小"
|
|
69
|
+
}),
|
|
70
|
+
/*#__PURE__*/ jsx("span", {
|
|
71
|
+
className: "text-slate-200",
|
|
72
|
+
children: asset.size
|
|
73
|
+
})
|
|
74
|
+
]
|
|
75
|
+
}),
|
|
76
|
+
/*#__PURE__*/ jsxs("div", {
|
|
77
|
+
className: "bg-slate-800/50 p-2 rounded",
|
|
78
|
+
children: [
|
|
79
|
+
/*#__PURE__*/ jsx("span", {
|
|
80
|
+
className: "text-slate-500 block text-xs",
|
|
81
|
+
children: "类型"
|
|
82
|
+
}),
|
|
83
|
+
/*#__PURE__*/ jsx("span", {
|
|
84
|
+
className: "text-slate-200 capitalize",
|
|
85
|
+
children: asset.type
|
|
86
|
+
})
|
|
87
|
+
]
|
|
88
|
+
}),
|
|
89
|
+
/*#__PURE__*/ jsxs("div", {
|
|
90
|
+
className: "bg-slate-800/50 p-2 rounded",
|
|
91
|
+
children: [
|
|
92
|
+
/*#__PURE__*/ jsx("span", {
|
|
93
|
+
className: "text-slate-500 block text-xs",
|
|
94
|
+
children: "位置"
|
|
95
|
+
}),
|
|
96
|
+
/*#__PURE__*/ jsx("span", {
|
|
97
|
+
className: "text-slate-200 truncate",
|
|
98
|
+
children: folders.find((f)=>f.id === asset.parentId)?.name || '根目录'
|
|
99
|
+
})
|
|
100
|
+
]
|
|
101
|
+
})
|
|
102
|
+
]
|
|
103
|
+
})
|
|
104
|
+
]
|
|
105
|
+
}),
|
|
106
|
+
/*#__PURE__*/ jsx("div", {
|
|
107
|
+
children: /*#__PURE__*/ jsx("button", {
|
|
108
|
+
onClick: ()=>onDelete(asset.id, 'asset', asset.name),
|
|
109
|
+
className: "w-full py-2 px-4 border border-red-900/50 text-red-400 hover:bg-red-900/20 rounded-lg text-sm transition-colors",
|
|
110
|
+
children: "删除文件"
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
]
|
|
114
|
+
})
|
|
115
|
+
]
|
|
116
|
+
})
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
export { InspectorPanel };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "react";
|
|
3
|
+
import { Search } from "lucide-react";
|
|
4
|
+
const SearchInput = ({ value, onChange })=>/*#__PURE__*/ jsxs("div", {
|
|
5
|
+
className: "relative w-64",
|
|
6
|
+
children: [
|
|
7
|
+
/*#__PURE__*/ jsx(Search, {
|
|
8
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-500"
|
|
9
|
+
}),
|
|
10
|
+
/*#__PURE__*/ jsx("input", {
|
|
11
|
+
type: "text",
|
|
12
|
+
placeholder: "搜索文件...",
|
|
13
|
+
value: value,
|
|
14
|
+
onChange: (e)=>onChange(e.target.value),
|
|
15
|
+
className: "w-full bg-slate-900 border-none rounded-lg pl-10 pr-4 py-1.5 text-sm text-slate-200 placeholder-slate-600 focus:ring-2 focus:ring-indigo-500/50 outline-none transition-all"
|
|
16
|
+
})
|
|
17
|
+
]
|
|
18
|
+
});
|
|
19
|
+
export { SearchInput };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { Folder } from '../types';
|
|
3
|
+
export interface SidebarProps {
|
|
4
|
+
title?: ReactNode;
|
|
5
|
+
folders: Folder[];
|
|
6
|
+
currentFolderId: string | null;
|
|
7
|
+
onNavigate: (folderId: string | null) => void;
|
|
8
|
+
onOpenAddModal: () => void;
|
|
9
|
+
onOpenCreateEmptyFolderModal?: (folder: Folder | null) => void;
|
|
10
|
+
}
|
|
11
|
+
declare const Sidebar: React.FC<SidebarProps>;
|
|
12
|
+
export default Sidebar;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Cloud, Plus } from "lucide-react";
|
|
4
|
+
import { FolderTree } from "./FolderTree.js";
|
|
5
|
+
const Sidebar_Sidebar = ({ title, folders, currentFolderId, onNavigate, onOpenAddModal, onOpenCreateEmptyFolderModal })=>{
|
|
6
|
+
const [expandedFolders, setExpandedFolders] = useState(new Set([
|
|
7
|
+
'root'
|
|
8
|
+
]));
|
|
9
|
+
const toggleExpand = (folderId)=>{
|
|
10
|
+
setExpandedFolders((prev)=>{
|
|
11
|
+
const next = new Set(prev);
|
|
12
|
+
if (next.has(folderId)) next.delete(folderId);
|
|
13
|
+
else next.add(folderId);
|
|
14
|
+
return next;
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
18
|
+
className: "w-64 bg-slate-900 border-r border-slate-800 h-full flex flex-col shrink-0",
|
|
19
|
+
children: [
|
|
20
|
+
/*#__PURE__*/ jsxs("div", {
|
|
21
|
+
className: "p-4 border-b border-slate-800 flex items-center gap-2",
|
|
22
|
+
children: [
|
|
23
|
+
/*#__PURE__*/ jsx("div", {
|
|
24
|
+
className: "w-8 h-8 bg-indigo-600 rounded-lg flex items-center justify-center shadow-lg shadow-indigo-500/20",
|
|
25
|
+
children: /*#__PURE__*/ jsx(Cloud, {
|
|
26
|
+
className: "text-white w-5 h-5"
|
|
27
|
+
})
|
|
28
|
+
}),
|
|
29
|
+
/*#__PURE__*/ jsx("h1", {
|
|
30
|
+
className: "text-xl font-bold tracking-tight text-white",
|
|
31
|
+
children: title
|
|
32
|
+
})
|
|
33
|
+
]
|
|
34
|
+
}),
|
|
35
|
+
/*#__PURE__*/ jsx("div", {
|
|
36
|
+
className: "p-4",
|
|
37
|
+
children: /*#__PURE__*/ jsxs("button", {
|
|
38
|
+
onClick: onOpenAddModal,
|
|
39
|
+
className: "w-full bg-indigo-600 hover:bg-indigo-500 text-white py-2 px-4 rounded-lg flex items-center justify-center gap-2 font-medium transition-colors shadow-lg shadow-indigo-900/20",
|
|
40
|
+
children: [
|
|
41
|
+
/*#__PURE__*/ jsx(Plus, {
|
|
42
|
+
className: "w-4 h-4"
|
|
43
|
+
}),
|
|
44
|
+
"上传文件"
|
|
45
|
+
]
|
|
46
|
+
})
|
|
47
|
+
}),
|
|
48
|
+
/*#__PURE__*/ jsx("div", {
|
|
49
|
+
className: "flex-1 overflow-y-auto px-3 py-2 space-y-6 scrollbar-thin",
|
|
50
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
51
|
+
children: [
|
|
52
|
+
/*#__PURE__*/ jsx("div", {
|
|
53
|
+
className: "flex items-center justify-between mb-2 px-3",
|
|
54
|
+
children: /*#__PURE__*/ jsx("h3", {
|
|
55
|
+
className: "text-xs font-semibold text-slate-500 uppercase tracking-wider",
|
|
56
|
+
children: "位置"
|
|
57
|
+
})
|
|
58
|
+
}),
|
|
59
|
+
/*#__PURE__*/ jsx("div", {
|
|
60
|
+
className: "space-y-0.5",
|
|
61
|
+
children: /*#__PURE__*/ jsx(FolderTree, {
|
|
62
|
+
parentId: null,
|
|
63
|
+
folders: folders,
|
|
64
|
+
expandedFolders: expandedFolders,
|
|
65
|
+
currentFolderId: currentFolderId,
|
|
66
|
+
onNavigate: onNavigate,
|
|
67
|
+
onToggleExpand: toggleExpand,
|
|
68
|
+
onAddFolder: onOpenCreateEmptyFolderModal,
|
|
69
|
+
showRoot: true
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
]
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
]
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
const Sidebar = Sidebar_Sidebar;
|
|
79
|
+
export { Sidebar as default };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "react";
|
|
3
|
+
import { Grid, List } from "lucide-react";
|
|
4
|
+
const ViewModeToggle = ({ viewMode, onChange })=>/*#__PURE__*/ jsxs("div", {
|
|
5
|
+
className: "flex bg-slate-800 rounded-lg p-1 border border-slate-700",
|
|
6
|
+
children: [
|
|
7
|
+
/*#__PURE__*/ jsx("button", {
|
|
8
|
+
onClick: ()=>onChange('grid'),
|
|
9
|
+
className: `p-1.5 rounded-md transition-all ${'grid' === viewMode ? 'bg-indigo-600 text-white shadow-sm' : 'text-slate-400 hover:text-white'}`,
|
|
10
|
+
children: /*#__PURE__*/ jsx(Grid, {
|
|
11
|
+
className: "w-4 h-4"
|
|
12
|
+
})
|
|
13
|
+
}),
|
|
14
|
+
/*#__PURE__*/ jsx("button", {
|
|
15
|
+
onClick: ()=>onChange('list'),
|
|
16
|
+
className: `p-1.5 rounded-md transition-all ${'list' === viewMode ? 'bg-indigo-600 text-white shadow-sm' : 'text-slate-400 hover:text-white'}`,
|
|
17
|
+
children: /*#__PURE__*/ jsx(List, {
|
|
18
|
+
className: "w-4 h-4"
|
|
19
|
+
})
|
|
20
|
+
})
|
|
21
|
+
]
|
|
22
|
+
});
|
|
23
|
+
export { ViewModeToggle };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
let storageConfig = null;
|
|
2
|
+
const getStorageConfig = ()=>{
|
|
3
|
+
if (storageConfig) return storageConfig;
|
|
4
|
+
const endpoint = 'https://xxx.xxx.xxx.xxx';
|
|
5
|
+
const accessKeyId = '';
|
|
6
|
+
const secretAccessKey = '';
|
|
7
|
+
const bucketName = '';
|
|
8
|
+
const region = 'us-east-1';
|
|
9
|
+
if (!endpoint || !accessKeyId || !secretAccessKey || !bucketName) throw new Error('Storage configuration is missing');
|
|
10
|
+
return {
|
|
11
|
+
endpoint,
|
|
12
|
+
accessKeyId,
|
|
13
|
+
secretAccessKey,
|
|
14
|
+
bucketName,
|
|
15
|
+
region
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export { getStorageConfig };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Asset, Folder, StorageAdapter } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Parses S3 keys into Assets and Folders hierarchy.
|
|
4
|
+
* In S3, folders are just keys ending in '/' or prefixes of other keys.
|
|
5
|
+
*/
|
|
6
|
+
export declare const listAssets: () => Promise<{
|
|
7
|
+
assets: Asset[];
|
|
8
|
+
folders: Folder[];
|
|
9
|
+
}>;
|
|
10
|
+
export declare const createFolder: (folderName: string, parentPath: string | null) => Promise<Folder>;
|
|
11
|
+
export declare const deleteFolder: (folderPath: string) => Promise<void>;
|
|
12
|
+
export declare const uploadObject: (file: File, folderId: string | null) => Promise<Partial<Asset>>;
|
|
13
|
+
export declare const deleteObject: (assetId: string) => Promise<void>;
|
|
14
|
+
export declare const adapter: StorageAdapter;
|