@huyooo/file-explorer-frontend-react 0.4.2

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 (46) hide show
  1. package/dist/index.css +1740 -0
  2. package/dist/index.css.map +1 -0
  3. package/dist/index.d.ts +562 -0
  4. package/dist/index.js +3453 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/style.css +3 -0
  7. package/package.json +58 -0
  8. package/src/components/Breadcrumb.css +61 -0
  9. package/src/components/Breadcrumb.tsx +38 -0
  10. package/src/components/CompressDialog.css +264 -0
  11. package/src/components/CompressDialog.tsx +222 -0
  12. package/src/components/ContextMenu.css +155 -0
  13. package/src/components/ContextMenu.tsx +375 -0
  14. package/src/components/FileGrid.css +267 -0
  15. package/src/components/FileGrid.tsx +277 -0
  16. package/src/components/FileIcon.css +41 -0
  17. package/src/components/FileIcon.tsx +86 -0
  18. package/src/components/FileInfoDialog.css +252 -0
  19. package/src/components/FileInfoDialog.tsx +202 -0
  20. package/src/components/FileList.css +226 -0
  21. package/src/components/FileList.tsx +228 -0
  22. package/src/components/FileListView.css +36 -0
  23. package/src/components/FileListView.tsx +355 -0
  24. package/src/components/FileSidebar.css +94 -0
  25. package/src/components/FileSidebar.tsx +66 -0
  26. package/src/components/ProgressDialog.css +211 -0
  27. package/src/components/ProgressDialog.tsx +183 -0
  28. package/src/components/SortIndicator.css +7 -0
  29. package/src/components/SortIndicator.tsx +19 -0
  30. package/src/components/StatusBar.css +20 -0
  31. package/src/components/StatusBar.tsx +21 -0
  32. package/src/components/Toolbar.css +150 -0
  33. package/src/components/Toolbar.tsx +127 -0
  34. package/src/components/Window.css +246 -0
  35. package/src/components/Window.tsx +335 -0
  36. package/src/hooks/useApplicationIcon.ts +80 -0
  37. package/src/hooks/useDragAndDrop.ts +104 -0
  38. package/src/hooks/useMediaPlayer.ts +164 -0
  39. package/src/hooks/useSelection.ts +112 -0
  40. package/src/hooks/useWindowDrag.ts +60 -0
  41. package/src/hooks/useWindowResize.ts +126 -0
  42. package/src/index.css +3 -0
  43. package/src/index.ts +34 -0
  44. package/src/types/index.ts +274 -0
  45. package/src/utils/fileTypeIcon.ts +309 -0
  46. package/src/utils/folderTypeIcon.ts +132 -0
@@ -0,0 +1,80 @@
1
+ import { useState, useCallback, useEffect } from 'react';
2
+ import type { FileItem } from '../types';
3
+ import { FileType } from '../types';
4
+
5
+ // 扩展 Window 类型
6
+ declare global {
7
+ interface Window {
8
+ fileExplorerAPI?: {
9
+ getApplicationIcon?: (appPath: string) => Promise<string | null>;
10
+ };
11
+ }
12
+ }
13
+
14
+ /**
15
+ * 应用程序图标管理 hook
16
+ */
17
+ export function useApplicationIcon(items: FileItem[]) {
18
+ // 应用程序图标缓存(避免重复请求)
19
+ const appIconCache = new Map<string, string>();
20
+
21
+ // 使用响应式的图标 URL 映射
22
+ const [appIconUrls, setAppIconUrls] = useState<Map<string, string>>(new Map());
23
+
24
+ /**
25
+ * 为应用程序获取图标
26
+ */
27
+ const loadApplicationIcon = useCallback(async (item: FileItem) => {
28
+ if (item.type !== FileType.APPLICATION || !item.id) return;
29
+
30
+ // 检查缓存
31
+ if (appIconCache.has(item.id)) {
32
+ const cachedUrl = appIconCache.get(item.id);
33
+ if (cachedUrl) {
34
+ setAppIconUrls(prev => new Map(prev).set(item.id, cachedUrl));
35
+ }
36
+ return;
37
+ }
38
+
39
+ // 检查响应式映射
40
+ if (appIconUrls.has(item.id)) {
41
+ return;
42
+ }
43
+
44
+ if (typeof window.fileExplorerAPI !== 'undefined' && window.fileExplorerAPI.getApplicationIcon) {
45
+ try {
46
+ const iconUrl = await window.fileExplorerAPI.getApplicationIcon(item.id);
47
+ if (iconUrl) {
48
+ appIconCache.set(item.id, iconUrl);
49
+ setAppIconUrls(prev => new Map(prev).set(item.id, iconUrl));
50
+ }
51
+ } catch (error) {
52
+ console.error(`Failed to load application icon for ${item.name}:`, error);
53
+ }
54
+ }
55
+ }, [appIconUrls]);
56
+
57
+ /**
58
+ * 监听 items 变化,为应用程序加载图标
59
+ */
60
+ useEffect(() => {
61
+ items.forEach(item => {
62
+ if (item.type === FileType.APPLICATION && !appIconUrls.has(item.id)) {
63
+ loadApplicationIcon(item);
64
+ }
65
+ });
66
+ }, [items, appIconUrls, loadApplicationIcon]);
67
+
68
+ /**
69
+ * 获取应用程序图标的响应式 URL
70
+ */
71
+ const getAppIconUrl = useCallback((item: FileItem): string | undefined => {
72
+ return appIconUrls.get(item.id);
73
+ }, [appIconUrls]);
74
+
75
+ return {
76
+ getAppIconUrl,
77
+ loadApplicationIcon
78
+ };
79
+ }
80
+
@@ -0,0 +1,104 @@
1
+ import { useState, useCallback } from 'react';
2
+ import type { FileItem } from '../types';
3
+ import { FileType } from '../types';
4
+
5
+ /**
6
+ * 拖拽操作管理
7
+ */
8
+ export function useDragAndDrop(
9
+ getSelectedIds: () => Set<string>,
10
+ onSelect: (id: string, multi: boolean, range: boolean) => void,
11
+ onMove: (targetFolderId: string, itemIds: Set<string>) => void
12
+ ) {
13
+ const [dragOverId, setDragOverId] = useState<string | null>(null);
14
+ const [isDragging, setIsDragging] = useState(false);
15
+
16
+ /**
17
+ * 开始拖拽
18
+ */
19
+ const handleDragStart = useCallback((e: React.DragEvent, itemId: string) => {
20
+ if (!e.dataTransfer) return;
21
+
22
+ const selectedIds = getSelectedIds();
23
+
24
+ // 如果拖拽的项目未被选中,先选中它
25
+ if (!selectedIds.has(itemId)) {
26
+ onSelect(itemId, false, false);
27
+ }
28
+
29
+ // 设置拖拽数据
30
+ const draggedIds = selectedIds.has(itemId) ? selectedIds : new Set([itemId]);
31
+ e.dataTransfer.setData('text/plain', JSON.stringify([...draggedIds]));
32
+ e.dataTransfer.effectAllowed = 'move';
33
+
34
+ setIsDragging(true);
35
+ }, [getSelectedIds, onSelect]);
36
+
37
+ /**
38
+ * 拖拽经过
39
+ */
40
+ const handleDragOver = useCallback((e: React.DragEvent, item: FileItem) => {
41
+ if (!isDragging) return;
42
+
43
+ // 只有文件夹可以作为放置目标
44
+ if (item.type === FileType.FOLDER) {
45
+ const selectedIds = getSelectedIds();
46
+ // 不能拖拽到自己身上
47
+ if (!selectedIds.has(item.id)) {
48
+ e.preventDefault();
49
+ setDragOverId(item.id);
50
+ }
51
+ }
52
+ }, [isDragging, getSelectedIds]);
53
+
54
+ /**
55
+ * 拖拽离开
56
+ */
57
+ const handleDragLeave = useCallback(() => {
58
+ setDragOverId(null);
59
+ }, []);
60
+
61
+ /**
62
+ * 放置
63
+ */
64
+ const handleDrop = useCallback((e: React.DragEvent, targetItem: FileItem) => {
65
+ setDragOverId(null);
66
+ setIsDragging(false);
67
+
68
+ if (!e.dataTransfer || targetItem.type !== FileType.FOLDER) return;
69
+
70
+ const data = e.dataTransfer.getData('text/plain');
71
+ if (!data) return;
72
+
73
+ try {
74
+ const draggedIds: string[] = JSON.parse(data);
75
+ const itemIds = new Set(draggedIds);
76
+
77
+ // 不能移动到自己
78
+ if (itemIds.has(targetItem.id)) return;
79
+
80
+ onMove(targetItem.id, itemIds);
81
+ } catch {
82
+ // 忽略解析错误
83
+ }
84
+ }, [onMove]);
85
+
86
+ /**
87
+ * 拖拽结束
88
+ */
89
+ const handleDragEnd = useCallback(() => {
90
+ setDragOverId(null);
91
+ setIsDragging(false);
92
+ }, []);
93
+
94
+ return {
95
+ dragOverId,
96
+ isDragging,
97
+ handleDragStart,
98
+ handleDragOver,
99
+ handleDragLeave,
100
+ handleDrop,
101
+ handleDragEnd
102
+ };
103
+ }
104
+
@@ -0,0 +1,164 @@
1
+ import { useState, useCallback, useEffect, useRef } from 'react';
2
+ import { FileType } from '../types';
3
+
4
+ /**
5
+ * 媒体播放器功能管理
6
+ */
7
+ export function useMediaPlayer(
8
+ mediaType: FileType,
9
+ mediaRef: React.RefObject<HTMLVideoElement | HTMLAudioElement>
10
+ ) {
11
+ const [isPlaying, setIsPlaying] = useState(false);
12
+ const [progress, setProgress] = useState(0);
13
+ const [currentTime, setCurrentTime] = useState(0);
14
+ const [duration, setDuration] = useState(0);
15
+ const [isMuted, setIsMuted] = useState(false);
16
+ const [volume, setVolume] = useState(1);
17
+ const [lastVolume, setLastVolume] = useState(1);
18
+ const [showControls, setShowControls] = useState(false);
19
+
20
+ const isAudio = mediaType === FileType.MUSIC;
21
+
22
+ /**
23
+ * 更新播放进度
24
+ */
25
+ const updateProgress = useCallback(() => {
26
+ const media = mediaRef.current;
27
+ if (media) {
28
+ const curr = media.currentTime;
29
+ const dur = media.duration;
30
+ setCurrentTime(curr);
31
+ if (dur && !isNaN(dur)) {
32
+ setDuration(dur);
33
+ setProgress((curr / dur) * 100);
34
+ }
35
+ }
36
+ }, [mediaRef]);
37
+
38
+ /**
39
+ * 切换播放/暂停
40
+ */
41
+ const togglePlay = useCallback(() => {
42
+ const media = mediaRef.current;
43
+ if (media) {
44
+ if (isPlaying) {
45
+ media.pause();
46
+ setIsPlaying(false);
47
+ } else {
48
+ media.play();
49
+ setIsPlaying(true);
50
+ }
51
+ }
52
+ }, [isPlaying, mediaRef]);
53
+
54
+ /**
55
+ * 切换静音
56
+ */
57
+ const toggleMute = useCallback(() => {
58
+ const media = mediaRef.current;
59
+ if (media) {
60
+ if (isMuted) {
61
+ const volToRestore = lastVolume || 1;
62
+ media.volume = volToRestore;
63
+ media.muted = false;
64
+ setVolume(volToRestore);
65
+ setIsMuted(false);
66
+ } else {
67
+ setLastVolume(volume);
68
+ media.volume = 0;
69
+ media.muted = true;
70
+ setVolume(0);
71
+ setIsMuted(true);
72
+ }
73
+ }
74
+ }, [isMuted, lastVolume, volume, mediaRef]);
75
+
76
+ /**
77
+ * 音量变化
78
+ */
79
+ const handleVolumeChange = useCallback((val: number) => {
80
+ setVolume(val);
81
+ const media = mediaRef.current;
82
+ if (media) {
83
+ media.volume = val;
84
+ if (val === 0) {
85
+ setIsMuted(true);
86
+ media.muted = true;
87
+ } else {
88
+ setIsMuted(false);
89
+ media.muted = false;
90
+ }
91
+ }
92
+ }, [mediaRef]);
93
+
94
+ /**
95
+ * 跳转到指定时间
96
+ */
97
+ const seekTo = useCallback((time: number) => {
98
+ const media = mediaRef.current;
99
+ if (media && duration) {
100
+ media.currentTime = time;
101
+ setCurrentTime(time);
102
+ setProgress((time / duration) * 100);
103
+ }
104
+ }, [duration, mediaRef]);
105
+
106
+ /**
107
+ * 格式化时间显示
108
+ */
109
+ const formatTime = useCallback((time: number) => {
110
+ if (isNaN(time)) return '0:00';
111
+ const minutes = Math.floor(time / 60);
112
+ const seconds = Math.floor(time % 60);
113
+ return `${minutes}:${seconds.toString().padStart(2, '0')}`;
114
+ }, []);
115
+
116
+ /**
117
+ * 自动播放
118
+ */
119
+ const autoPlay = useCallback(() => {
120
+ const media = mediaRef.current;
121
+ if ((mediaType === FileType.VIDEO || isAudio) && media) {
122
+ media.volume = volume;
123
+ media.play().catch(() => {});
124
+ setIsPlaying(true);
125
+ }
126
+ }, [mediaType, isAudio, volume, mediaRef]);
127
+
128
+ /**
129
+ * 监听媒体事件
130
+ */
131
+ useEffect(() => {
132
+ const media = mediaRef.current;
133
+ if (media) {
134
+ media.addEventListener('timeupdate', updateProgress);
135
+ media.addEventListener('loadedmetadata', updateProgress);
136
+ media.addEventListener('ended', () => {
137
+ setIsPlaying(false);
138
+ });
139
+ return () => {
140
+ media.removeEventListener('timeupdate', updateProgress);
141
+ media.removeEventListener('loadedmetadata', updateProgress);
142
+ };
143
+ }
144
+ }, [mediaRef, updateProgress]);
145
+
146
+ return {
147
+ isPlaying,
148
+ progress,
149
+ currentTime,
150
+ duration,
151
+ isMuted,
152
+ volume,
153
+ showControls,
154
+ isAudio,
155
+ togglePlay,
156
+ toggleMute,
157
+ handleVolumeChange,
158
+ seekTo,
159
+ formatTime,
160
+ autoPlay,
161
+ updateProgress
162
+ };
163
+ }
164
+
@@ -0,0 +1,112 @@
1
+ import { useState, useCallback } from 'react';
2
+ import type { FileItem } from '../types';
3
+
4
+ /**
5
+ * 文件选择状态管理
6
+ */
7
+ export function useSelection() {
8
+ const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
9
+ const [lastSelectedId, setLastSelectedId] = useState<string | null>(null);
10
+ const [editingId, setEditingId] = useState<string | null>(null);
11
+
12
+ /**
13
+ * 清除选择
14
+ */
15
+ const clearSelection = useCallback(() => {
16
+ setSelectedIds(new Set());
17
+ setLastSelectedId(null);
18
+ }, []);
19
+
20
+ /**
21
+ * 选择项目
22
+ * @param id 项目 ID(null 表示清除选择)
23
+ * @param items 当前显示的项目列表
24
+ * @param multi 是否多选(Cmd/Ctrl)
25
+ * @param range 是否范围选择(Shift)
26
+ */
27
+ const selectItem = useCallback((
28
+ id: string | null,
29
+ items: FileItem[],
30
+ multi: boolean = false,
31
+ range: boolean = false
32
+ ) => {
33
+ if (!id) {
34
+ clearSelection();
35
+ return;
36
+ }
37
+
38
+ setSelectedIds(prev => {
39
+ setLastSelectedId(prevLast => {
40
+ // 范围选择
41
+ if (range && prevLast) {
42
+ const indexA = items.findIndex(i => i.id === prevLast);
43
+ const indexB = items.findIndex(i => i.id === id);
44
+
45
+ if (indexA !== -1 && indexB !== -1) {
46
+ const start = Math.min(indexA, indexB);
47
+ const end = Math.max(indexA, indexB);
48
+ const newSet = new Set(multi ? prev : []);
49
+ for (let i = start; i <= end; i++) {
50
+ const item = items[i];
51
+ if (item) {
52
+ newSet.add(item.id);
53
+ }
54
+ }
55
+ setSelectedIds(newSet);
56
+ return id;
57
+ }
58
+ }
59
+
60
+ // 多选切换
61
+ if (multi) {
62
+ const newSet = new Set(prev);
63
+ if (newSet.has(id)) {
64
+ newSet.delete(id);
65
+ } else {
66
+ newSet.add(id);
67
+ }
68
+ setSelectedIds(newSet);
69
+ return id;
70
+ }
71
+
72
+ // 单选
73
+ setSelectedIds(new Set([id]));
74
+ return id;
75
+ });
76
+ return prev;
77
+ });
78
+ }, [clearSelection]);
79
+
80
+ /**
81
+ * 全选
82
+ */
83
+ const selectAll = useCallback((items: FileItem[]) => {
84
+ setSelectedIds(new Set(items.map(i => i.id)));
85
+ }, []);
86
+
87
+ /**
88
+ * 设置编辑状态
89
+ */
90
+ const setEditing = useCallback((id: string | null) => {
91
+ setEditingId(id);
92
+ }, []);
93
+
94
+ /**
95
+ * 检查是否选中
96
+ */
97
+ const isSelected = useCallback((id: string): boolean => {
98
+ return selectedIds.has(id);
99
+ }, [selectedIds]);
100
+
101
+ return {
102
+ selectedIds,
103
+ lastSelectedId,
104
+ editingId,
105
+ clearSelection,
106
+ selectItem,
107
+ selectAll,
108
+ setEditing,
109
+ isSelected
110
+ };
111
+ }
112
+
@@ -0,0 +1,60 @@
1
+ import { useState, useCallback, useEffect } from 'react';
2
+
3
+ /**
4
+ * 窗口拖拽功能管理
5
+ */
6
+ export function useWindowDrag() {
7
+ const [position, setPosition] = useState({ x: 0, y: 0 });
8
+ const [isDragging, setIsDragging] = useState(false);
9
+
10
+ /**
11
+ * 鼠标移动处理
12
+ */
13
+ const handleMouseMove = useCallback((e: MouseEvent) => {
14
+ if (!isDragging) return;
15
+ setPosition(prev => ({
16
+ x: prev.x + e.movementX,
17
+ y: prev.y + e.movementY
18
+ }));
19
+ }, [isDragging]);
20
+
21
+ /**
22
+ * 鼠标释放处理
23
+ */
24
+ const handleMouseUp = useCallback(() => {
25
+ setIsDragging(false);
26
+ }, []);
27
+
28
+ /**
29
+ * 开始拖拽
30
+ */
31
+ const startDrag = useCallback((e: React.MouseEvent) => {
32
+ const target = e.target as HTMLElement;
33
+ // 检查是否点击在可拖拽区域,但排除按钮
34
+ if (target.closest('.draggable-area') && !target.closest('button')) {
35
+ e.preventDefault();
36
+ setIsDragging(true);
37
+ }
38
+ }, []);
39
+
40
+ /**
41
+ * 监听拖拽状态变化
42
+ */
43
+ useEffect(() => {
44
+ if (isDragging) {
45
+ window.addEventListener('mousemove', handleMouseMove);
46
+ window.addEventListener('mouseup', handleMouseUp);
47
+ return () => {
48
+ window.removeEventListener('mousemove', handleMouseMove);
49
+ window.removeEventListener('mouseup', handleMouseUp);
50
+ };
51
+ }
52
+ }, [isDragging, handleMouseMove, handleMouseUp]);
53
+
54
+ return {
55
+ position,
56
+ isDragging,
57
+ startDrag
58
+ };
59
+ }
60
+
@@ -0,0 +1,126 @@
1
+ import { useState, useCallback, useEffect } from 'react';
2
+
3
+ type ResizeDirection = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw';
4
+
5
+ /**
6
+ * 窗口调整大小功能管理
7
+ */
8
+ export function useWindowResize(
9
+ initialWidth: number,
10
+ initialHeight: number,
11
+ minWidth: number,
12
+ minHeight: number,
13
+ maxWidth: number,
14
+ maxHeight: number
15
+ ) {
16
+ const [width, setWidth] = useState(initialWidth);
17
+ const [height, setHeight] = useState(initialHeight);
18
+ const [isResizing, setIsResizing] = useState(false);
19
+ const [resizeDirection, setResizeDirection] = useState<ResizeDirection | null>(null);
20
+ const [startX, setStartX] = useState(0);
21
+ const [startY, setStartY] = useState(0);
22
+ const [startWidth, setStartWidth] = useState(0);
23
+ const [startHeight, setStartHeight] = useState(0);
24
+
25
+ /**
26
+ * 鼠标移动处理
27
+ */
28
+ const handleMouseMove = useCallback((e: MouseEvent) => {
29
+ if (!isResizing || !resizeDirection) return;
30
+
31
+ const deltaX = e.clientX - startX;
32
+ const deltaY = e.clientY - startY;
33
+
34
+ let newWidth = startWidth;
35
+ let newHeight = startHeight;
36
+
37
+ const direction = resizeDirection;
38
+
39
+ // 处理水平方向
40
+ if (direction.includes('e')) {
41
+ newWidth = Math.min(Math.max(startWidth + deltaX, minWidth), maxWidth);
42
+ } else if (direction.includes('w')) {
43
+ newWidth = Math.min(Math.max(startWidth - deltaX, minWidth), maxWidth);
44
+ }
45
+
46
+ // 处理垂直方向
47
+ if (direction.includes('s')) {
48
+ newHeight = Math.min(Math.max(startHeight + deltaY, minHeight), maxHeight);
49
+ } else if (direction.includes('n')) {
50
+ newHeight = Math.min(Math.max(startHeight - deltaY, minHeight), maxHeight);
51
+ }
52
+
53
+ setWidth(newWidth);
54
+ setHeight(newHeight);
55
+ }, [isResizing, resizeDirection, startX, startY, startWidth, startHeight, minWidth, minHeight, maxWidth, maxHeight]);
56
+
57
+ /**
58
+ * 鼠标释放处理
59
+ */
60
+ const handleMouseUp = useCallback(() => {
61
+ setIsResizing(false);
62
+ setResizeDirection(null);
63
+ }, []);
64
+
65
+ /**
66
+ * 开始调整大小
67
+ */
68
+ const startResize = useCallback((
69
+ e: React.MouseEvent,
70
+ direction: ResizeDirection,
71
+ currentWidth: number,
72
+ currentHeight: number
73
+ ) => {
74
+ e.preventDefault();
75
+ e.stopPropagation();
76
+ setIsResizing(true);
77
+ setResizeDirection(direction);
78
+ setStartX(e.clientX);
79
+ setStartY(e.clientY);
80
+ setStartWidth(currentWidth);
81
+ setStartHeight(currentHeight);
82
+ }, []);
83
+
84
+ /**
85
+ * 获取对应方向的鼠标样式
86
+ */
87
+ const getCursorForDirection = useCallback((direction: ResizeDirection): string => {
88
+ const cursors: Record<ResizeDirection, string> = {
89
+ n: 'n-resize',
90
+ s: 's-resize',
91
+ e: 'e-resize',
92
+ w: 'w-resize',
93
+ ne: 'ne-resize',
94
+ nw: 'nw-resize',
95
+ se: 'se-resize',
96
+ sw: 'sw-resize'
97
+ };
98
+ return cursors[direction];
99
+ }, []);
100
+
101
+ /**
102
+ * 监听调整大小状态变化
103
+ */
104
+ useEffect(() => {
105
+ if (isResizing) {
106
+ window.addEventListener('mousemove', handleMouseMove);
107
+ window.addEventListener('mouseup', handleMouseUp);
108
+ document.body.style.cursor = getCursorForDirection(resizeDirection || 'se');
109
+ document.body.style.userSelect = 'none';
110
+ return () => {
111
+ window.removeEventListener('mousemove', handleMouseMove);
112
+ window.removeEventListener('mouseup', handleMouseUp);
113
+ document.body.style.cursor = '';
114
+ document.body.style.userSelect = '';
115
+ };
116
+ }
117
+ }, [isResizing, resizeDirection, handleMouseMove, handleMouseUp, getCursorForDirection]);
118
+
119
+ return {
120
+ width,
121
+ height,
122
+ isResizing,
123
+ startResize
124
+ };
125
+ }
126
+
package/src/index.css ADDED
@@ -0,0 +1,3 @@
1
+ /* Base styles for file-explorer-frontend-react */
2
+ /* This file will be copied to dist/style.css during build */
3
+
package/src/index.ts ADDED
@@ -0,0 +1,34 @@
1
+ // Types
2
+ export * from './types';
3
+
4
+ // Core Components
5
+ export { FileListView, type FileListViewHandle } from './components/FileListView';
6
+ export { FileSidebar } from './components/FileSidebar';
7
+ export { Toolbar } from './components/Toolbar';
8
+ export { Breadcrumb } from './components/Breadcrumb';
9
+ export { StatusBar } from './components/StatusBar';
10
+
11
+ // Base Components
12
+ export { FileIcon } from './components/FileIcon';
13
+ export { FileGrid } from './components/FileGrid';
14
+ export { FileList } from './components/FileList';
15
+ export { ContextMenu } from './components/ContextMenu';
16
+ export { SortIndicator } from './components/SortIndicator';
17
+
18
+ // Window Component
19
+ export { Window } from './components/Window';
20
+
21
+ // Dialog Components
22
+ export { CompressDialog } from './components/CompressDialog';
23
+ export type { CompressOptions, CompressFormat, CompressLevel } from './types';
24
+ export { ProgressDialog, type ProgressInfo, type ProgressStatus } from './components/ProgressDialog';
25
+ export { FileInfoDialog, type FileInfoDialogProps } from './components/FileInfoDialog';
26
+
27
+ // Hooks
28
+ export { useSelection } from './hooks/useSelection';
29
+ export { useDragAndDrop } from './hooks/useDragAndDrop';
30
+ export { useMediaPlayer } from './hooks/useMediaPlayer';
31
+ export { useWindowDrag } from './hooks/useWindowDrag';
32
+ export { useWindowResize } from './hooks/useWindowResize';
33
+ export { useApplicationIcon } from './hooks/useApplicationIcon';
34
+