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.
Files changed (49) hide show
  1. package/dist/features/ChatClient/components/ChatContent/ClientContentHeader.js +3 -24
  2. package/dist/ui/Button/index.d.ts +1 -1
  3. package/dist/ui/Button/index.js +3 -1
  4. package/dist/ui/FileManager/FileManager.d.ts +7 -0
  5. package/dist/ui/FileManager/FileManager.js +278 -0
  6. package/dist/ui/FileManager/components/AddAssetModal.d.ts +11 -0
  7. package/dist/ui/FileManager/components/AddAssetModal.js +197 -0
  8. package/dist/ui/FileManager/components/AssetGrid.d.ts +11 -0
  9. package/dist/ui/FileManager/components/AssetGrid.js +188 -0
  10. package/dist/ui/FileManager/components/AssetSelectorModal.d.ts +12 -0
  11. package/dist/ui/FileManager/components/AssetSelectorModal.js +133 -0
  12. package/dist/ui/FileManager/components/Breadcrumbs.d.ts +10 -0
  13. package/dist/ui/FileManager/components/Breadcrumbs.js +25 -0
  14. package/dist/ui/FileManager/components/CreateFolderModal.d.ts +7 -0
  15. package/dist/ui/FileManager/components/CreateFolderModal.js +84 -0
  16. package/dist/ui/FileManager/components/DeleteConfirmModal.d.ts +9 -0
  17. package/dist/ui/FileManager/components/DeleteConfirmModal.js +33 -0
  18. package/dist/ui/FileManager/components/FileTypePreview.d.ts +7 -0
  19. package/dist/ui/FileManager/components/FileTypePreview.js +29 -0
  20. package/dist/ui/FileManager/components/FolderTree.d.ts +13 -0
  21. package/dist/ui/FileManager/components/FolderTree.js +137 -0
  22. package/dist/ui/FileManager/components/HeaderBar.d.ts +13 -0
  23. package/dist/ui/FileManager/components/HeaderBar.js +37 -0
  24. package/dist/ui/FileManager/components/InspectorPanel.d.ts +9 -0
  25. package/dist/ui/FileManager/components/InspectorPanel.js +119 -0
  26. package/dist/ui/FileManager/components/SearchInput.d.ts +7 -0
  27. package/dist/ui/FileManager/components/SearchInput.js +19 -0
  28. package/dist/ui/FileManager/components/Sidebar.d.ts +12 -0
  29. package/dist/ui/FileManager/components/Sidebar.js +79 -0
  30. package/dist/ui/FileManager/components/ViewModeToggle.d.ts +8 -0
  31. package/dist/ui/FileManager/components/ViewModeToggle.js +23 -0
  32. package/dist/ui/FileManager/index.d.ts +3 -0
  33. package/dist/ui/FileManager/index.js +3 -0
  34. package/dist/ui/FileManager/services/config.d.ts +8 -0
  35. package/dist/ui/FileManager/services/config.js +18 -0
  36. package/dist/ui/FileManager/services/storageService.d.ts +14 -0
  37. package/dist/ui/FileManager/services/storageService.js +249 -0
  38. package/dist/ui/FileManager/types.d.ts +36 -0
  39. package/dist/ui/FileManager/types.js +0 -0
  40. package/dist/ui/Modal/ConfirmModal.d.ts +11 -0
  41. package/dist/ui/Modal/ConfirmModal.js +62 -0
  42. package/dist/ui/Modal/Modal.d.ts +14 -0
  43. package/dist/ui/Modal/Modal.js +64 -0
  44. package/dist/ui/Modal/index.d.ts +2 -0
  45. package/dist/ui/Modal/index.js +3 -0
  46. package/dist/ui/index.d.ts +1 -0
  47. package/dist/ui/index.js +2 -1
  48. package/dist/ui.css +755 -0
  49. package/package.json +4 -2
@@ -24,10 +24,6 @@ const HeaderLeft = (props)=>{
24
24
  const onCollapsed = ()=>{
25
25
  setCollapsed(!collapsed);
26
26
  };
27
- const onSubmitTitleChange = async (newTitle)=>{
28
- await onTitleChange?.(newTitle);
29
- setTitle(newTitle);
30
- };
31
27
  const showActions = !!collapsed;
32
28
  const showTitle = !!title;
33
29
  return /*#__PURE__*/ jsxs(Left, {
@@ -56,23 +52,6 @@ const HeaderLeft = (props)=>{
56
52
  backgroundColor: '#0000001f'
57
53
  },
58
54
  type: "vertical"
59
- }),
60
- showTitle && /*#__PURE__*/ jsxs(NameContainer, {
61
- children: [
62
- /*#__PURE__*/ jsx(NameText, {
63
- children: /*#__PURE__*/ jsx(Button, {
64
- onClick: ()=>showUpdateTitleModal(title, onSubmitTitleChange),
65
- size: "small",
66
- type: "text",
67
- iconPosition: "end",
68
- icon: /*#__PURE__*/ jsx(EditOutlined, {}),
69
- children: title
70
- })
71
- }),
72
- /*#__PURE__*/ jsx(AiTipText, {
73
- children: "内容由 AI 生成"
74
- })
75
- ]
76
55
  })
77
56
  ]
78
57
  });
@@ -83,12 +62,12 @@ const ActionContainer = styled.div`
83
62
 
84
63
  gap: 4px;
85
64
  `;
86
- const NameContainer = styled.div`
65
+ styled.div`
87
66
  display: flex;
88
67
  align-items: flex-start;
89
68
  flex-direction: column;
90
69
  `;
91
- const NameText = styled.span`
70
+ styled.span`
92
71
  font-size: 14px;
93
72
  font-weight: 500;
94
73
  color: #000000;
@@ -97,7 +76,7 @@ const NameText = styled.span`
97
76
  ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
98
77
  'Segoe UI Symbol', 'Noto Color Emoji';
99
78
  `;
100
- const AiTipText = styled.span`
79
+ styled.span`
101
80
  font-size: 11px;
102
81
  color: #00000080;
103
82
  padding: 0 8px;
@@ -4,7 +4,7 @@ export interface ButtonProps {
4
4
  disabled?: boolean;
5
5
  loading?: boolean;
6
6
  children?: ReactNode;
7
- type?: 'primary' | 'secondary';
7
+ type?: 'primary' | 'secondary' | 'error' | 'text';
8
8
  size?: 'large' | 'medium' | 'small';
9
9
  }
10
10
  export declare const Button: (props: ButtonProps) => import("react/jsx-runtime").JSX.Element;
@@ -6,7 +6,9 @@ const Button = (props)=>{
6
6
  const [loading, setLoading] = useState(false);
7
7
  const typeClass = {
8
8
  primary: 'bg-blue-600 hover:bg-blue-500 text-white shadow-lg shadow-blue-900/20 transition-all transform hover:scale-[1.02] active:scale-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 flex items-center gap-2',
9
- secondary: 'border border-gray-700 text-gray-300 hover:bg-gray-800 hover:text-white active:bg-gray-700 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-500 focus-visible:ring-offset-2 flex items-center gap-2'
9
+ secondary: 'border border-gray-700 text-gray-300 hover:bg-gray-800 hover:text-white active:bg-gray-700 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-500 focus-visible:ring-offset-2 flex items-center gap-2',
10
+ error: 'bg-red-600 hover:bg-red-500 text-white rounded-lg text-sm font-medium transition-colors shadow-lg shadow-red-900/20',
11
+ text: 'text-slate-300 hover:text-white transition-colors text-sm font-medium'
10
12
  };
11
13
  const sizeClass = {
12
14
  large: 'px-6 py-2.5 rounded-lg',
@@ -0,0 +1,7 @@
1
+ import { ReactNode } from 'react';
2
+ import { StorageAdapter } from './types';
3
+ export interface FileManagerProps {
4
+ title?: ReactNode;
5
+ storage: StorageAdapter;
6
+ }
7
+ export declare function FileManager({ title, storage }: FileManagerProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,278 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useState } from "react";
3
+ import { useRequest } from "ahooks";
4
+ import { Loader2 } from "lucide-react";
5
+ import Sidebar from "./components/Sidebar.js";
6
+ import { AssetGrid } from "./components/AssetGrid.js";
7
+ import { AddAssetModal } from "./components/AddAssetModal.js";
8
+ import { CreateFolderModal } from "./components/CreateFolderModal.js";
9
+ import { DeleteConfirmModal } from "./components/DeleteConfirmModal.js";
10
+ import { InspectorPanel } from "./components/InspectorPanel.js";
11
+ import { HeaderBar } from "./components/HeaderBar.js";
12
+ function FileManager({ title, storage }) {
13
+ const [assets, setAssets] = useState([]);
14
+ const [folders, setFolders] = useState([]);
15
+ const [currentFolderId, setCurrentFolderId] = useState(null);
16
+ const [filters, setFilters] = useState({
17
+ search: '',
18
+ source: 'all'
19
+ });
20
+ const [viewMode, setViewMode] = useState('grid');
21
+ const [isAddModalOpen, setIsAddModalOpen] = useState(false);
22
+ const [isCreateFolderModalOpen, setIsCreateFolderModalOpen] = useState(false);
23
+ const [createFolderParentId, setCreateFolderParentId] = useState(void 0);
24
+ const [deleteModalState, setDeleteModalState] = useState({
25
+ isOpen: false,
26
+ itemId: null,
27
+ itemType: null,
28
+ itemName: ''
29
+ });
30
+ const [selectedItem, setSelectedItem] = useState(null);
31
+ const { loading } = useRequest(()=>storage.listAssets(), {
32
+ onSuccess: ({ assets: remoteAssets, folders: remoteFolders })=>{
33
+ setAssets(remoteAssets);
34
+ setFolders(remoteFolders);
35
+ }
36
+ });
37
+ useEffect(()=>{
38
+ if (selectedItem && 'image' === selectedItem.type) {
39
+ const item = selectedItem;
40
+ if (!item.width || !item.height) {
41
+ const img = new Image();
42
+ img.src = item.url;
43
+ img.onload = ()=>{
44
+ setAssets((prev)=>prev.map((a)=>a.id === item.id ? {
45
+ ...a,
46
+ width: img.naturalWidth,
47
+ height: img.naturalHeight
48
+ } : a));
49
+ setSelectedItem((prev)=>{
50
+ if (prev && prev.id === item.id) return {
51
+ ...prev,
52
+ width: img.naturalWidth,
53
+ height: img.naturalHeight
54
+ };
55
+ return prev;
56
+ });
57
+ };
58
+ }
59
+ }
60
+ }, [
61
+ selectedItem?.id
62
+ ]);
63
+ const breadcrumbs = useMemo(()=>{
64
+ const path = [];
65
+ let currentId = currentFolderId;
66
+ while(currentId){
67
+ const folder = folders.find((f)=>f.id === currentId);
68
+ if (folder) {
69
+ path.unshift({
70
+ id: folder.id,
71
+ name: folder.name
72
+ });
73
+ currentId = folder.parentId;
74
+ } else break;
75
+ }
76
+ return [
77
+ {
78
+ id: null,
79
+ name: '根目录'
80
+ },
81
+ ...path
82
+ ];
83
+ }, [
84
+ folders,
85
+ currentFolderId
86
+ ]);
87
+ const currentViewItems = useMemo(()=>{
88
+ const currentFolders = folders.filter((f)=>f.parentId === currentFolderId);
89
+ const currentAssets = assets.filter((a)=>a.parentId === currentFolderId);
90
+ let items = [
91
+ ...currentFolders,
92
+ ...currentAssets
93
+ ];
94
+ if (filters.search) {
95
+ const allFolders = folders.filter((f)=>f.name.toLowerCase().includes(filters.search.toLowerCase()));
96
+ const allAssets = assets.filter((a)=>a.name.toLowerCase().includes(filters.search.toLowerCase()));
97
+ return [
98
+ ...allFolders,
99
+ ...allAssets
100
+ ];
101
+ }
102
+ if ('all' !== filters.source) return items.filter((item)=>{
103
+ if ('folder' === item.type) return false;
104
+ return item.source === filters.source;
105
+ });
106
+ return items;
107
+ }, [
108
+ assets,
109
+ folders,
110
+ currentFolderId,
111
+ filters
112
+ ]);
113
+ const handleAddAsset = (newAsset)=>{
114
+ setAssets((prev)=>[
115
+ newAsset,
116
+ ...prev
117
+ ]);
118
+ };
119
+ const handleBatchImport = (newAssets, newFolders)=>{
120
+ setFolders((prev)=>{
121
+ const exists = new Set(prev.map((f)=>f.id));
122
+ const uniqueNew = newFolders.filter((f)=>!exists.has(f.id));
123
+ return [
124
+ ...prev,
125
+ ...uniqueNew
126
+ ];
127
+ });
128
+ setAssets((prev)=>[
129
+ ...newAssets,
130
+ ...prev
131
+ ]);
132
+ };
133
+ const handleCreateFolder = async (name)=>{
134
+ try {
135
+ const parentId = void 0 === createFolderParentId ? currentFolderId : createFolderParentId;
136
+ const newFolder = await storage.createFolder(name, parentId);
137
+ setFolders((prev)=>[
138
+ ...prev,
139
+ newFolder
140
+ ]);
141
+ } catch (e) {
142
+ alert('创建文件夹失败');
143
+ }
144
+ };
145
+ const handleDeleteRequest = (id, type, name)=>{
146
+ setDeleteModalState({
147
+ isOpen: true,
148
+ itemId: id,
149
+ itemType: type,
150
+ itemName: name
151
+ });
152
+ };
153
+ const executeDelete = async ()=>{
154
+ const { itemId, itemType } = deleteModalState;
155
+ if (!itemId || !itemType) return;
156
+ if ('folder' === itemType) try {
157
+ await storage.deleteFolder(itemId);
158
+ setFolders((prev)=>prev.filter((f)=>f.id !== itemId));
159
+ setFolders((prev)=>prev.filter((f)=>!f.id.startsWith(itemId)));
160
+ setAssets((prev)=>prev.filter((a)=>!a.parentId?.startsWith(itemId)));
161
+ } catch (e) {
162
+ console.error(e);
163
+ }
164
+ else {
165
+ const asset = assets.find((a)=>a.id === itemId);
166
+ setAssets((prev)=>prev.filter((a)=>a.id !== itemId));
167
+ if (asset) await storage.deleteObject(asset.id);
168
+ }
169
+ if (selectedItem?.id === itemId) setSelectedItem(null);
170
+ setDeleteModalState({
171
+ isOpen: false,
172
+ itemId: null,
173
+ itemType: null,
174
+ itemName: ''
175
+ });
176
+ };
177
+ const handleNavigate = (folderId)=>{
178
+ setCurrentFolderId(folderId);
179
+ setSelectedItem(null);
180
+ setFilters((prev)=>({
181
+ ...prev,
182
+ search: ''
183
+ }));
184
+ };
185
+ return /*#__PURE__*/ jsxs("div", {
186
+ className: "flex h-screen bg-slate-950 text-slate-200 font-sans",
187
+ children: [
188
+ /*#__PURE__*/ jsx(Sidebar, {
189
+ title: title,
190
+ folders: folders,
191
+ currentFolderId: currentFolderId,
192
+ onNavigate: handleNavigate,
193
+ onOpenAddModal: ()=>setIsAddModalOpen(true),
194
+ onOpenCreateEmptyFolderModal: (folder)=>{
195
+ setIsCreateFolderModalOpen(true);
196
+ setCreateFolderParentId(folder ? folder.id : null);
197
+ }
198
+ }),
199
+ /*#__PURE__*/ jsxs("div", {
200
+ className: "flex-1 flex flex-col min-w-0 bg-slate-950",
201
+ children: [
202
+ /*#__PURE__*/ jsx(HeaderBar, {
203
+ breadcrumbs: breadcrumbs,
204
+ search: filters.search,
205
+ onSearchChange: (v)=>setFilters((prev)=>({
206
+ ...prev,
207
+ search: v
208
+ })),
209
+ onNavigate: handleNavigate,
210
+ onCreateFolder: ()=>{
211
+ setIsCreateFolderModalOpen(true);
212
+ setCreateFolderParentId(void 0);
213
+ },
214
+ viewMode: viewMode,
215
+ onChangeViewMode: setViewMode
216
+ }),
217
+ /*#__PURE__*/ jsxs("div", {
218
+ className: "flex-1 flex overflow-hidden relative",
219
+ children: [
220
+ /*#__PURE__*/ jsx("main", {
221
+ className: "flex-1 relative overflow-hidden flex flex-col",
222
+ children: /*#__PURE__*/ jsx("div", {
223
+ className: "flex-1 overflow-hidden",
224
+ children: loading ? /*#__PURE__*/ jsxs("div", {
225
+ className: "flex flex-col items-center justify-center h-full text-slate-500 space-y-4",
226
+ children: [
227
+ /*#__PURE__*/ jsx(Loader2, {
228
+ className: "w-10 h-10 animate-spin text-indigo-500"
229
+ }),
230
+ /*#__PURE__*/ jsx("p", {
231
+ children: "正在加载数据..."
232
+ })
233
+ ]
234
+ }) : /*#__PURE__*/ jsx(AssetGrid, {
235
+ items: currentViewItems,
236
+ viewMode: viewMode,
237
+ onSelect: setSelectedItem,
238
+ onNavigate: handleNavigate,
239
+ onDelete: handleDeleteRequest
240
+ })
241
+ })
242
+ }),
243
+ selectedItem && 'folder' !== selectedItem.type && /*#__PURE__*/ jsx(InspectorPanel, {
244
+ item: selectedItem,
245
+ folders: folders,
246
+ onDelete: (id, type, name)=>handleDeleteRequest(id, type, name)
247
+ })
248
+ ]
249
+ })
250
+ ]
251
+ }),
252
+ /*#__PURE__*/ jsx(AddAssetModal, {
253
+ isOpen: isAddModalOpen,
254
+ onClose: ()=>setIsAddModalOpen(false),
255
+ onAdd: handleAddAsset,
256
+ onBatchAdd: handleBatchImport,
257
+ currentFolderId: currentFolderId,
258
+ storage: storage
259
+ }),
260
+ /*#__PURE__*/ jsx(CreateFolderModal, {
261
+ isOpen: isCreateFolderModalOpen,
262
+ onClose: ()=>setIsCreateFolderModalOpen(false),
263
+ onCreate: handleCreateFolder
264
+ }),
265
+ /*#__PURE__*/ jsx(DeleteConfirmModal, {
266
+ isOpen: deleteModalState.isOpen,
267
+ onClose: ()=>setDeleteModalState((prev)=>({
268
+ ...prev,
269
+ isOpen: false
270
+ })),
271
+ onConfirm: executeDelete,
272
+ itemName: deleteModalState.itemName,
273
+ itemType: deleteModalState.itemType
274
+ })
275
+ ]
276
+ });
277
+ }
278
+ export { FileManager };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { Asset, Folder, StorageAdapter } from '../types';
3
+ export interface AddAssetModalProps {
4
+ isOpen: boolean;
5
+ onClose: () => void;
6
+ onAdd: (asset: Asset) => void;
7
+ onBatchAdd: (assets: Asset[], folders: Folder[]) => void;
8
+ currentFolderId: string | null;
9
+ storage: StorageAdapter;
10
+ }
11
+ export declare const AddAssetModal: React.FC<AddAssetModalProps>;
@@ -0,0 +1,197 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useRef, useState } from "react";
3
+ import { FolderPlus, Loader2, Upload, X } from "lucide-react";
4
+ const AddAssetModal = ({ isOpen, onClose, onAdd, onBatchAdd, currentFolderId, storage })=>{
5
+ const [loading, setLoading] = useState(false);
6
+ const [status, setStatus] = useState('');
7
+ const fileInputRef = useRef(null);
8
+ const folderInputRef = useRef(null);
9
+ if (!isOpen) return null;
10
+ const handleFileUpload = async (e)=>{
11
+ const file = e.target.files?.[0];
12
+ if (!file) return;
13
+ setLoading(true);
14
+ setStatus('正在上传到服务器...');
15
+ try {
16
+ const uploadedAsset = await storage.uploadObject(file, currentFolderId);
17
+ let name = uploadedAsset.name || file.name;
18
+ const newAsset = {
19
+ ...uploadedAsset,
20
+ name: name
21
+ };
22
+ onAdd(newAsset);
23
+ setLoading(false);
24
+ onClose();
25
+ } catch (error) {
26
+ console.error(error);
27
+ setStatus('文件处理出错');
28
+ setLoading(false);
29
+ }
30
+ };
31
+ const handleFolderUpload = async (e)=>{
32
+ const files = e.target.files;
33
+ if (!files || 0 === files.length) return;
34
+ setLoading(true);
35
+ setStatus('正在解析目录结构...');
36
+ const newFolders = [];
37
+ const newAssets = [];
38
+ const createdFolderPaths = new Set();
39
+ try {
40
+ const totalFiles = files.length;
41
+ for(let i = 0; i < files.length; i++){
42
+ const file = files[i];
43
+ const relativePath = file.webkitRelativePath;
44
+ const rootPrefix = currentFolderId || '';
45
+ const fileParts = relativePath.split('/');
46
+ fileParts.pop();
47
+ const relativeFolder = fileParts.join('/');
48
+ const targetFolderId = relativeFolder ? `${rootPrefix}${relativeFolder}/` : rootPrefix;
49
+ setStatus(`正在上传 (${i + 1}/${totalFiles}): ${file.name}`);
50
+ const uploadedAsset = await storage.uploadObject(file, targetFolderId);
51
+ newAssets.push({
52
+ ...uploadedAsset,
53
+ name: file.name
54
+ });
55
+ }
56
+ for(let i = 0; i < files.length; i++){
57
+ const parts = files[i].webkitRelativePath.split('/');
58
+ parts.pop();
59
+ let currentPath = currentFolderId || '';
60
+ for (const part of parts){
61
+ const parent = currentPath || null;
62
+ currentPath += `${part}/`;
63
+ if (!createdFolderPaths.has(currentPath)) {
64
+ newFolders.push({
65
+ id: currentPath,
66
+ name: part,
67
+ parentId: parent,
68
+ createdAt: new Date().toISOString(),
69
+ type: 'folder'
70
+ });
71
+ createdFolderPaths.add(currentPath);
72
+ }
73
+ }
74
+ }
75
+ onBatchAdd(newAssets, newFolders);
76
+ setLoading(false);
77
+ onClose();
78
+ } catch (error) {
79
+ console.error('Batch upload failed', error);
80
+ setStatus('上传过程中出错');
81
+ setLoading(false);
82
+ }
83
+ };
84
+ return /*#__PURE__*/ jsx("div", {
85
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm p-4",
86
+ children: /*#__PURE__*/ jsxs("div", {
87
+ className: "bg-slate-900 border border-slate-700 w-full max-w-2xl rounded-2xl shadow-2xl overflow-hidden flex flex-col max-h-[90vh]",
88
+ children: [
89
+ /*#__PURE__*/ jsxs("div", {
90
+ className: "flex items-center justify-between p-6 border-b border-slate-800 bg-slate-900",
91
+ children: [
92
+ /*#__PURE__*/ jsx("h2", {
93
+ className: "text-xl font-bold text-white",
94
+ children: currentFolderId ? '上传文件到当前文件夹' : '上传文件到根目录'
95
+ }),
96
+ /*#__PURE__*/ jsx("button", {
97
+ onClick: onClose,
98
+ className: "text-slate-400 hover:text-white transition-colors",
99
+ children: /*#__PURE__*/ jsx(X, {
100
+ className: "w-6 h-6"
101
+ })
102
+ })
103
+ ]
104
+ }),
105
+ /*#__PURE__*/ jsx("div", {
106
+ className: "flex border-b border-slate-800",
107
+ children: /*#__PURE__*/ jsx("button", {
108
+ className: "flex-1 py-4 text-sm font-medium transition-colors border-b-2 border-indigo-500 text-indigo-400 bg-slate-800/50",
109
+ children: /*#__PURE__*/ jsxs("div", {
110
+ className: "flex items-center justify-center gap-2",
111
+ children: [
112
+ /*#__PURE__*/ jsx(Upload, {
113
+ className: "w-4 h-4"
114
+ }),
115
+ "上传文件"
116
+ ]
117
+ })
118
+ })
119
+ }),
120
+ /*#__PURE__*/ jsx("div", {
121
+ className: "p-8 overflow-y-auto",
122
+ children: loading ? /*#__PURE__*/ jsxs("div", {
123
+ className: "flex flex-col items-center justify-center py-12 space-y-4",
124
+ children: [
125
+ /*#__PURE__*/ jsx(Loader2, {
126
+ className: "w-12 h-12 text-indigo-500 animate-spin"
127
+ }),
128
+ /*#__PURE__*/ jsx("p", {
129
+ className: "text-slate-300 animate-pulse",
130
+ children: status
131
+ })
132
+ ]
133
+ }) : /*#__PURE__*/ jsxs("div", {
134
+ className: "flex gap-4",
135
+ children: [
136
+ /*#__PURE__*/ jsxs("div", {
137
+ className: "flex-1 border-2 border-dashed border-slate-700 rounded-xl p-8 flex flex-col items-center justify-center text-center hover:border-indigo-500 hover:bg-slate-800/30 transition-all cursor-pointer group",
138
+ onClick: ()=>fileInputRef.current?.click(),
139
+ children: [
140
+ /*#__PURE__*/ jsx("input", {
141
+ type: "file",
142
+ ref: fileInputRef,
143
+ className: "hidden",
144
+ onChange: handleFileUpload
145
+ }),
146
+ /*#__PURE__*/ jsx("div", {
147
+ className: "w-16 h-16 bg-slate-800 rounded-full flex items-center justify-center mb-4 group-hover:bg-indigo-500/20 transition-colors",
148
+ children: /*#__PURE__*/ jsx(Upload, {
149
+ className: "w-8 h-8 text-slate-400 group-hover:text-indigo-400"
150
+ })
151
+ }),
152
+ /*#__PURE__*/ jsx("h3", {
153
+ className: "text-lg font-medium text-white mb-2",
154
+ children: "上传文件"
155
+ }),
156
+ /*#__PURE__*/ jsx("p", {
157
+ className: "text-sm text-slate-500",
158
+ children: "图片、视频、音频、模型等"
159
+ })
160
+ ]
161
+ }),
162
+ /*#__PURE__*/ jsxs("div", {
163
+ className: "flex-1 border-2 border-dashed border-slate-700 rounded-xl p-8 flex flex-col items-center justify-center text-center hover:border-indigo-500 hover:bg-slate-800/30 transition-all cursor-pointer group",
164
+ onClick: ()=>folderInputRef.current?.click(),
165
+ children: [
166
+ /*#__PURE__*/ jsx("input", {
167
+ type: "file",
168
+ ref: folderInputRef,
169
+ className: "hidden",
170
+ webkitdirectory: "",
171
+ directory: "",
172
+ onChange: handleFolderUpload
173
+ }),
174
+ /*#__PURE__*/ jsx("div", {
175
+ className: "w-16 h-16 bg-slate-800 rounded-full flex items-center justify-center mb-4 group-hover:bg-indigo-500/20 transition-colors",
176
+ children: /*#__PURE__*/ jsx(FolderPlus, {
177
+ className: "w-8 h-8 text-slate-400 group-hover:text-indigo-400"
178
+ })
179
+ }),
180
+ /*#__PURE__*/ jsx("h3", {
181
+ className: "text-lg font-medium text-white mb-2",
182
+ children: "上传文件夹"
183
+ }),
184
+ /*#__PURE__*/ jsx("p", {
185
+ className: "text-sm text-slate-500",
186
+ children: "保留目录结构上传"
187
+ })
188
+ ]
189
+ })
190
+ ]
191
+ })
192
+ })
193
+ ]
194
+ })
195
+ });
196
+ };
197
+ export { AddAssetModal };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { ViewMode, FileSystemItem } from '../types';
3
+ export interface AssetGridProps {
4
+ items: FileSystemItem[];
5
+ viewMode: ViewMode;
6
+ onSelect: (item: FileSystemItem) => void;
7
+ onNavigate: (folderId: string) => void;
8
+ onDelete?: (id: string, type: 'folder' | 'asset', name: string) => void;
9
+ selectedIds?: Set<string>;
10
+ }
11
+ export declare const AssetGrid: React.FC<AssetGridProps>;