@burdenoff/microfe-files 2026.510.101
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/README.md +12 -0
- package/dist/config/index.d.ts +33 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +28 -0
- package/dist/config/index.js.map +1 -0
- package/dist/dev/main.d.ts +1 -0
- package/dist/dev/main.d.ts.map +1 -0
- package/dist/files/FilesRoot.d.ts +31 -0
- package/dist/files/FilesRoot.d.ts.map +1 -0
- package/dist/files/FilesRoot.js +63 -0
- package/dist/files/FilesRoot.js.map +1 -0
- package/dist/files/FilesRoutes.d.ts +12 -0
- package/dist/files/FilesRoutes.d.ts.map +1 -0
- package/dist/files/FilesRoutes.js +45 -0
- package/dist/files/FilesRoutes.js.map +1 -0
- package/dist/files/components/ActionMenu.d.ts +19 -0
- package/dist/files/components/ActionMenu.d.ts.map +1 -0
- package/dist/files/components/ActionMenu.js +73 -0
- package/dist/files/components/ActionMenu.js.map +1 -0
- package/dist/files/components/ConfirmDialog.d.ts +14 -0
- package/dist/files/components/ConfirmDialog.d.ts.map +1 -0
- package/dist/files/components/ConfirmDialog.js +85 -0
- package/dist/files/components/ConfirmDialog.js.map +1 -0
- package/dist/files/components/ContextMenu.d.ts +59 -0
- package/dist/files/components/ContextMenu.d.ts.map +1 -0
- package/dist/files/components/ContextMenu.js +136 -0
- package/dist/files/components/ContextMenu.js.map +1 -0
- package/dist/files/components/CopyDialog.d.ts +12 -0
- package/dist/files/components/CopyDialog.d.ts.map +1 -0
- package/dist/files/components/CopyDialog.js +139 -0
- package/dist/files/components/CopyDialog.js.map +1 -0
- package/dist/files/components/EmptyState.d.ts +8 -0
- package/dist/files/components/EmptyState.d.ts.map +1 -0
- package/dist/files/components/EmptyState.js +66 -0
- package/dist/files/components/EmptyState.js.map +1 -0
- package/dist/files/components/FileBrowser.d.ts +37 -0
- package/dist/files/components/FileBrowser.d.ts.map +1 -0
- package/dist/files/components/FileBrowser.js +421 -0
- package/dist/files/components/FileBrowser.js.map +1 -0
- package/dist/files/components/FileCard.d.ts +30 -0
- package/dist/files/components/FileCard.d.ts.map +1 -0
- package/dist/files/components/FileCard.js +233 -0
- package/dist/files/components/FileCard.js.map +1 -0
- package/dist/files/components/FileInfoPanel.d.ts +9 -0
- package/dist/files/components/FileInfoPanel.d.ts.map +1 -0
- package/dist/files/components/FileInfoPanel.js +224 -0
- package/dist/files/components/FileInfoPanel.js.map +1 -0
- package/dist/files/components/FileListItem.d.ts +46 -0
- package/dist/files/components/FileListItem.d.ts.map +1 -0
- package/dist/files/components/FileListItem.js +235 -0
- package/dist/files/components/FileListItem.js.map +1 -0
- package/dist/files/components/FilePreviewModal.d.ts +17 -0
- package/dist/files/components/FilePreviewModal.d.ts.map +1 -0
- package/dist/files/components/FilePreviewModal.js +175 -0
- package/dist/files/components/FilePreviewModal.js.map +1 -0
- package/dist/files/components/FileVersionPanel.d.ts +9 -0
- package/dist/files/components/FileVersionPanel.d.ts.map +1 -0
- package/dist/files/components/FileVersionPanel.js +227 -0
- package/dist/files/components/FileVersionPanel.js.map +1 -0
- package/dist/files/components/FolderCard.d.ts +34 -0
- package/dist/files/components/FolderCard.d.ts.map +1 -0
- package/dist/files/components/FolderCard.js +225 -0
- package/dist/files/components/FolderCard.js.map +1 -0
- package/dist/files/components/MoveDialog.d.ts +12 -0
- package/dist/files/components/MoveDialog.d.ts.map +1 -0
- package/dist/files/components/MoveDialog.js +123 -0
- package/dist/files/components/MoveDialog.js.map +1 -0
- package/dist/files/components/SearchBar.d.ts +13 -0
- package/dist/files/components/SearchBar.d.ts.map +1 -0
- package/dist/files/components/SearchBar.js +257 -0
- package/dist/files/components/SearchBar.js.map +1 -0
- package/dist/files/components/ShareDialog.d.ts +24 -0
- package/dist/files/components/ShareDialog.d.ts.map +1 -0
- package/dist/files/components/ShareDialog.js +201 -0
- package/dist/files/components/ShareDialog.js.map +1 -0
- package/dist/files/components/TabBar.d.ts +14 -0
- package/dist/files/components/TabBar.d.ts.map +1 -0
- package/dist/files/components/TabBar.js +65 -0
- package/dist/files/components/TabBar.js.map +1 -0
- package/dist/files/components/Toast.d.ts +14 -0
- package/dist/files/components/Toast.d.ts.map +1 -0
- package/dist/files/components/Toast.js +51 -0
- package/dist/files/components/Toast.js.map +1 -0
- package/dist/files/components/UploadQueue.d.ts +21 -0
- package/dist/files/components/UploadQueue.d.ts.map +1 -0
- package/dist/files/components/UploadQueue.js +171 -0
- package/dist/files/components/UploadQueue.js.map +1 -0
- package/dist/files/components/index.d.ts +43 -0
- package/dist/files/components/index.d.ts.map +1 -0
- package/dist/files/components/viewers/AudioPlayer.d.ts +8 -0
- package/dist/files/components/viewers/AudioPlayer.d.ts.map +1 -0
- package/dist/files/components/viewers/AudioPlayer.js +102 -0
- package/dist/files/components/viewers/AudioPlayer.js.map +1 -0
- package/dist/files/components/viewers/CodeViewer.d.ts +16 -0
- package/dist/files/components/viewers/CodeViewer.d.ts.map +1 -0
- package/dist/files/components/viewers/CodeViewer.js +113 -0
- package/dist/files/components/viewers/CodeViewer.js.map +1 -0
- package/dist/files/components/viewers/ImageViewer.d.ts +8 -0
- package/dist/files/components/viewers/ImageViewer.d.ts.map +1 -0
- package/dist/files/components/viewers/ImageViewer.js +138 -0
- package/dist/files/components/viewers/ImageViewer.js.map +1 -0
- package/dist/files/components/viewers/PDFViewer.d.ts +15 -0
- package/dist/files/components/viewers/PDFViewer.d.ts.map +1 -0
- package/dist/files/components/viewers/PDFViewer.js +80 -0
- package/dist/files/components/viewers/PDFViewer.js.map +1 -0
- package/dist/files/components/viewers/TextViewer.d.ts +8 -0
- package/dist/files/components/viewers/TextViewer.d.ts.map +1 -0
- package/dist/files/components/viewers/TextViewer.js +121 -0
- package/dist/files/components/viewers/TextViewer.js.map +1 -0
- package/dist/files/components/viewers/VideoPlayer.d.ts +8 -0
- package/dist/files/components/viewers/VideoPlayer.d.ts.map +1 -0
- package/dist/files/components/viewers/VideoPlayer.js +138 -0
- package/dist/files/components/viewers/VideoPlayer.js.map +1 -0
- package/dist/files/components/viewers/index.d.ts +7 -0
- package/dist/files/components/viewers/index.d.ts.map +1 -0
- package/dist/files/components/viewers/index.js +6 -0
- package/dist/files/graphql-types.d.ts +317 -0
- package/dist/files/graphql-types.d.ts.map +1 -0
- package/dist/files/hooks/useBatchOperations.d.ts +32 -0
- package/dist/files/hooks/useBatchOperations.d.ts.map +1 -0
- package/dist/files/hooks/useBatchOperations.js +18 -0
- package/dist/files/hooks/useBatchOperations.js.map +1 -0
- package/dist/files/hooks/useBinItems.d.ts +11 -0
- package/dist/files/hooks/useBinItems.d.ts.map +1 -0
- package/dist/files/hooks/useBinItems.js +27 -0
- package/dist/files/hooks/useBinItems.js.map +1 -0
- package/dist/files/hooks/useBrowsePage.d.ts +18 -0
- package/dist/files/hooks/useBrowsePage.d.ts.map +1 -0
- package/dist/files/hooks/useBrowsePage.js +34 -0
- package/dist/files/hooks/useBrowsePage.js.map +1 -0
- package/dist/files/hooks/useCopyFile.d.ts +14 -0
- package/dist/files/hooks/useCopyFile.d.ts.map +1 -0
- package/dist/files/hooks/useCopyFile.js +22 -0
- package/dist/files/hooks/useCopyFile.js.map +1 -0
- package/dist/files/hooks/useCreateFolder.d.ts +14 -0
- package/dist/files/hooks/useCreateFolder.d.ts.map +1 -0
- package/dist/files/hooks/useCreateFolder.js +14 -0
- package/dist/files/hooks/useCreateFolder.js.map +1 -0
- package/dist/files/hooks/useCreateFolderShare.d.ts +16 -0
- package/dist/files/hooks/useCreateFolderShare.d.ts.map +1 -0
- package/dist/files/hooks/useCreateFolderShare.js +14 -0
- package/dist/files/hooks/useCreateFolderShare.js.map +1 -0
- package/dist/files/hooks/useCreateShare.d.ts +16 -0
- package/dist/files/hooks/useCreateShare.d.ts.map +1 -0
- package/dist/files/hooks/useCreateShare.js +14 -0
- package/dist/files/hooks/useCreateShare.js.map +1 -0
- package/dist/files/hooks/useDeleteFile.d.ts +9 -0
- package/dist/files/hooks/useDeleteFile.d.ts.map +1 -0
- package/dist/files/hooks/useDeleteFile.js +20 -0
- package/dist/files/hooks/useDeleteFile.js.map +1 -0
- package/dist/files/hooks/useDeleteFolder.d.ts +10 -0
- package/dist/files/hooks/useDeleteFolder.d.ts.map +1 -0
- package/dist/files/hooks/useDeleteFolder.js +24 -0
- package/dist/files/hooks/useDeleteFolder.js.map +1 -0
- package/dist/files/hooks/useDragDrop.d.ts +31 -0
- package/dist/files/hooks/useDragDrop.d.ts.map +1 -0
- package/dist/files/hooks/useDragDrop.js +45 -0
- package/dist/files/hooks/useDragDrop.js.map +1 -0
- package/dist/files/hooks/useFileVersions.d.ts +52 -0
- package/dist/files/hooks/useFileVersions.d.ts.map +1 -0
- package/dist/files/hooks/useFileVersions.js +52 -0
- package/dist/files/hooks/useFileVersions.js.map +1 -0
- package/dist/files/hooks/useFiles.d.ts +18 -0
- package/dist/files/hooks/useFiles.d.ts.map +1 -0
- package/dist/files/hooks/useFolder.d.ts +7 -0
- package/dist/files/hooks/useFolder.d.ts.map +1 -0
- package/dist/files/hooks/useFolderPath.d.ts +2 -0
- package/dist/files/hooks/useFolderPath.d.ts.map +1 -0
- package/dist/files/hooks/useFoldersQuery.d.ts +7 -0
- package/dist/files/hooks/useFoldersQuery.d.ts.map +1 -0
- package/dist/files/hooks/useFoldersQuery.js +13 -0
- package/dist/files/hooks/useFoldersQuery.js.map +1 -0
- package/dist/files/hooks/useKeyboardNavigation.d.ts +17 -0
- package/dist/files/hooks/useKeyboardNavigation.d.ts.map +1 -0
- package/dist/files/hooks/useKeyboardNavigation.js +105 -0
- package/dist/files/hooks/useKeyboardNavigation.js.map +1 -0
- package/dist/files/hooks/useMoveFile.d.ts +10 -0
- package/dist/files/hooks/useMoveFile.d.ts.map +1 -0
- package/dist/files/hooks/useMoveFile.js +21 -0
- package/dist/files/hooks/useMoveFile.js.map +1 -0
- package/dist/files/hooks/useMoveFolder.d.ts +10 -0
- package/dist/files/hooks/useMoveFolder.d.ts.map +1 -0
- package/dist/files/hooks/useMoveFolder.js +21 -0
- package/dist/files/hooks/useMoveFolder.js.map +1 -0
- package/dist/files/hooks/usePermanentlyDeleteFile.d.ts +9 -0
- package/dist/files/hooks/usePermanentlyDeleteFile.d.ts.map +1 -0
- package/dist/files/hooks/usePermanentlyDeleteFile.js +18 -0
- package/dist/files/hooks/usePermanentlyDeleteFile.js.map +1 -0
- package/dist/files/hooks/usePermanentlyDeleteFolder.d.ts +9 -0
- package/dist/files/hooks/usePermanentlyDeleteFolder.d.ts.map +1 -0
- package/dist/files/hooks/usePermanentlyDeleteFolder.js +18 -0
- package/dist/files/hooks/usePermanentlyDeleteFolder.js.map +1 -0
- package/dist/files/hooks/useRecentFiles.d.ts +10 -0
- package/dist/files/hooks/useRecentFiles.d.ts.map +1 -0
- package/dist/files/hooks/useRecentFiles.js +24 -0
- package/dist/files/hooks/useRecentFiles.js.map +1 -0
- package/dist/files/hooks/useRenameFile.d.ts +10 -0
- package/dist/files/hooks/useRenameFile.d.ts.map +1 -0
- package/dist/files/hooks/useRenameFile.js +21 -0
- package/dist/files/hooks/useRenameFile.js.map +1 -0
- package/dist/files/hooks/useRenameFolder.d.ts +10 -0
- package/dist/files/hooks/useRenameFolder.d.ts.map +1 -0
- package/dist/files/hooks/useRenameFolder.js +21 -0
- package/dist/files/hooks/useRenameFolder.js.map +1 -0
- package/dist/files/hooks/useRestoreFile.d.ts +9 -0
- package/dist/files/hooks/useRestoreFile.d.ts.map +1 -0
- package/dist/files/hooks/useRestoreFile.js +21 -0
- package/dist/files/hooks/useRestoreFile.js.map +1 -0
- package/dist/files/hooks/useRestoreFolder.d.ts +9 -0
- package/dist/files/hooks/useRestoreFolder.d.ts.map +1 -0
- package/dist/files/hooks/useRestoreFolder.js +21 -0
- package/dist/files/hooks/useRestoreFolder.js.map +1 -0
- package/dist/files/hooks/useSearch.d.ts +15 -0
- package/dist/files/hooks/useSearch.d.ts.map +1 -0
- package/dist/files/hooks/useSearch.js +27 -0
- package/dist/files/hooks/useSearch.js.map +1 -0
- package/dist/files/hooks/useStarredItems.d.ts +10 -0
- package/dist/files/hooks/useStarredItems.d.ts.map +1 -0
- package/dist/files/hooks/useStarredItems.js +18 -0
- package/dist/files/hooks/useStarredItems.js.map +1 -0
- package/dist/files/hooks/useToast.d.ts +11 -0
- package/dist/files/hooks/useToast.d.ts.map +1 -0
- package/dist/files/hooks/useToast.js +28 -0
- package/dist/files/hooks/useToast.js.map +1 -0
- package/dist/files/hooks/useToggleStar.d.ts +10 -0
- package/dist/files/hooks/useToggleStar.d.ts.map +1 -0
- package/dist/files/hooks/useToggleStar.js +26 -0
- package/dist/files/hooks/useToggleStar.js.map +1 -0
- package/dist/files/hooks/useUploadFile.d.ts +25 -0
- package/dist/files/hooks/useUploadFile.d.ts.map +1 -0
- package/dist/files/hooks/useUploadFile.js +74 -0
- package/dist/files/hooks/useUploadFile.js.map +1 -0
- package/dist/files/index.d.ts +29 -0
- package/dist/files/index.d.ts.map +1 -0
- package/dist/files/index.js +3 -0
- package/dist/files/pages/BrowserPage.d.ts +5 -0
- package/dist/files/pages/BrowserPage.d.ts.map +1 -0
- package/dist/files/pages/BrowserPage.js +1014 -0
- package/dist/files/pages/BrowserPage.js.map +1 -0
- package/dist/files/pages/ShareAccessPage.d.ts +2 -0
- package/dist/files/pages/ShareAccessPage.d.ts.map +1 -0
- package/dist/files/pages/ShareAccessPage.js +162 -0
- package/dist/files/pages/ShareAccessPage.js.map +1 -0
- package/dist/files/providers/FilesProvider.d.ts +25 -0
- package/dist/files/providers/FilesProvider.d.ts.map +1 -0
- package/dist/files/providers/FilesProvider.js +18 -0
- package/dist/files/providers/FilesProvider.js.map +1 -0
- package/dist/files/store/filesStore.d.ts +99 -0
- package/dist/files/store/filesStore.d.ts.map +1 -0
- package/dist/files/store/filesStore.js +129 -0
- package/dist/files/store/filesStore.js.map +1 -0
- package/dist/files/types.d.ts +266 -0
- package/dist/files/types.d.ts.map +1 -0
- package/dist/files/utils/events.d.ts +6 -0
- package/dist/files/utils/events.d.ts.map +1 -0
- package/dist/files/utils/events.js +16 -0
- package/dist/files/utils/events.js.map +1 -0
- package/dist/files/utils/i18n.d.ts +5 -0
- package/dist/files/utils/i18n.d.ts.map +1 -0
- package/dist/files/utils/i18n.js +15 -0
- package/dist/files/utils/i18n.js.map +1 -0
- package/dist/files/utils/index.d.ts +74 -0
- package/dist/files/utils/index.d.ts.map +1 -0
- package/dist/files/utils/index.js +50 -0
- package/dist/files/utils/index.js.map +1 -0
- package/dist/files/utils/thumbnail.d.ts +5 -0
- package/dist/files/utils/thumbnail.d.ts.map +1 -0
- package/dist/files/utils/thumbnail.js +39 -0
- package/dist/files/utils/thumbnail.js.map +1 -0
- package/dist/files.d.ts +2 -0
- package/dist/files.js +6 -0
- package/dist/generated/global-operations.d.ts +2 -0
- package/dist/generated/global-operations.d.ts.map +1 -0
- package/dist/generated/global-types.d.ts +21253 -0
- package/dist/generated/global-types.d.ts.map +1 -0
- package/dist/generated/wspace-operations.d.ts +2706 -0
- package/dist/generated/wspace-operations.d.ts.map +1 -0
- package/dist/generated/wspace-operations.js +1085 -0
- package/dist/generated/wspace-operations.js.map +1 -0
- package/dist/generated/wspace-types.d.ts +55214 -0
- package/dist/generated/wspace-types.d.ts.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/shared/types/index.d.ts +101 -0
- package/dist/shared/types/index.d.ts.map +1 -0
- package/dist/utils/nativeBridge.d.ts +3 -0
- package/dist/utils/nativeBridge.d.ts.map +1 -0
- package/dist/utils/nativeBridge.js +2 -0
- package/package.json +126 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UploadQueue.js","names":[],"sources":["../../../src/files/components/UploadQueue.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport {\n Pause,\n Play,\n RotateCcw,\n X,\n CheckCircle,\n AlertCircle,\n Loader2,\n Image as ImageIcon,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { UploadItem } from \"../types\";\nimport { isImageType } from \"../utils\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface UploadProgressBarProps {\n item: UploadItem;\n onPause: (id: string) => void;\n onResume: (id: string) => void;\n onRetry: (id: string) => void;\n onCancel: (id: string) => void;\n}\n\nexport function UploadProgressBar({\n item,\n onPause,\n onResume,\n onRetry,\n onCancel,\n}: UploadProgressBarProps) {\n const { t } = useI18n();\n const progressRef = useRef<HTMLDivElement>(null);\n const isImage = isImageType(item.file.type);\n\n useEffect(() => {\n if (progressRef.current) {\n progressRef.current.style.width = `${item.progress}%`;\n }\n }, [item.progress]);\n\n const getStatusIcon = () => {\n switch (item.status) {\n case \"uploading\":\n return (\n <Loader2 className=\"size-4 animate-spin text-action-primary-bg\" />\n );\n case \"paused\":\n return <Pause className=\"size-4 text-status-warning-text\" />;\n case \"completed\":\n return <CheckCircle className=\"size-4 text-status-success-text\" />;\n case \"failed\":\n return <AlertCircle className=\"size-4 text-status-error-text\" />;\n default:\n return <Loader2 className=\"size-4 animate-spin text-text-tertiary\" />;\n }\n };\n\n const getStatusColor = () => {\n switch (item.status) {\n case \"uploading\":\n return \"bg-action-primary-bg\";\n case \"paused\":\n return \"bg-status-warning-bg\";\n case \"completed\":\n return \"bg-status-success-bg\";\n case \"failed\":\n return \"bg-status-error-bg\";\n default:\n return \"bg-text-tertiary\";\n }\n };\n\n const formatFileSize = (bytes: number) => {\n if (bytes === 0) return \"0 B\";\n const k = 1024;\n const sizes = [\"B\", \"KB\", \"MB\", \"GB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;\n };\n\n return (\n <div className=\"bg-bg-elevated border border-border-default rounded-lg p-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex-shrink-0 w-10 h-10 bg-bg-muted rounded flex items-center justify-center overflow-hidden\">\n {item.thumbnailUrl ? (\n <img\n src={item.thumbnailUrl}\n alt={item.file.name}\n className=\"w-full h-full object-cover\"\n />\n ) : isImage ? (\n <ImageIcon className=\"size-5 text-text-tertiary\" />\n ) : (\n <div className=\"w-full h-full bg-bg-accent\" />\n )}\n </div>\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center justify-between gap-2 mb-1.5\">\n <span className=\"text-sm font-medium text-text-primary truncate\">\n {item.file.name}\n </span>\n <span className=\"text-xs text-text-secondary whitespace-nowrap\">\n {formatFileSize(item.file.size)}\n </span>\n </div>\n\n <div className=\"relative h-1.5 bg-bg-muted rounded-full overflow-hidden\">\n <div\n ref={progressRef}\n className={`absolute inset-y-0 left-0 ${getStatusColor()} transition-all duration-300 ease-out rounded-full`}\n style={{ width: `${item.progress}%` }}\n />\n </div>\n\n <div className=\"flex items-center justify-between mt-1.5\">\n <span className=\"text-xs text-text-secondary\">\n {item.status === \"paused\" &&\n tWithFallback(t, \"files.upload.paused\", \"Paused\")}\n {item.status === \"uploading\" && `${item.progress}%`}\n {item.status === \"completed\" &&\n tWithFallback(t, \"files.upload.completed\", \"Completed\")}\n {item.status === \"failed\" &&\n (item.error ||\n tWithFallback(t, \"files.upload.failed\", \"Failed\"))}\n {item.status === \"pending\" &&\n tWithFallback(t, \"files.upload.pending\", \"Pending...\")}\n </span>\n </div>\n </div>\n\n <div className=\"flex items-center gap-1 flex-shrink-0\">\n {item.status === \"uploading\" && (\n <button\n onClick={() => onPause(item.id)}\n className=\"p-1.5 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors\"\n title={tWithFallback(t, \"files.upload.pause\", \"Pause\")}\n >\n <Pause className=\"size-4\" />\n </button>\n )}\n\n {item.status === \"paused\" && (\n <button\n onClick={() => onResume(item.id)}\n className=\"p-1.5 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors\"\n title={tWithFallback(t, \"files.upload.resume\", \"Resume\")}\n >\n <Play className=\"size-4\" />\n </button>\n )}\n\n {item.status === \"failed\" && (\n <button\n onClick={() => onRetry(item.id)}\n className=\"p-1.5 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors\"\n title={tWithFallback(t, \"files.upload.retry\", \"Retry\")}\n >\n <RotateCcw className=\"size-4\" />\n </button>\n )}\n\n {(item.status === \"pending\" ||\n item.status === \"paused\" ||\n item.status === \"failed\") && (\n <button\n onClick={() => onCancel(item.id)}\n className=\"p-1.5 text-text-secondary hover:text-status-error-text hover:bg-status-error-bg-subtle rounded transition-colors\"\n title={tWithFallback(t, \"files.upload.cancel\", \"Cancel\")}\n >\n <X className=\"size-4\" />\n </button>\n )}\n </div>\n </div>\n </div>\n );\n}\n\ninterface UploadQueueProps {\n items: UploadItem[];\n isOpen: boolean;\n onClose: () => void;\n onPause: (id: string) => void;\n onResume: (id: string) => void;\n onRetry: (id: string) => void;\n onCancel: (id: string) => void;\n}\n\nexport function UploadQueue({\n items,\n isOpen,\n onClose,\n onPause,\n onResume,\n onRetry,\n onCancel,\n}: UploadQueueProps) {\n const { t } = useI18n();\n if (!isOpen) return null;\n\n const completedCount = items.filter((i) => i.status === \"completed\").length;\n const failedCount = items.filter((i) => i.status === \"failed\").length;\n const activeCount = items.filter(\n (i) => i.status === \"uploading\" || i.status === \"pending\",\n ).length;\n\n return (\n <div className=\"fixed bottom-4 right-4 w-80 bg-bg-elevated border border-border-default rounded-lg shadow-xl z-50\">\n <div className=\"flex items-center justify-between p-3 border-b border-border-default\">\n <div>\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {tWithFallback(t, \"files.upload.uploads\", \"Uploads\")} ({activeCount}{\" \"}\n {tWithFallback(t, \"files.upload.active\", \"active\")})\n </h3>\n {completedCount > 0 && (\n <p className=\"text-xs text-status-success-text\">\n {completedCount}{\" \"}\n {tWithFallback(t, \"files.upload.completed\", \"completed\")}\n </p>\n )}\n {failedCount > 0 && (\n <p className=\"text-xs text-status-error-text\">\n {failedCount} {tWithFallback(t, \"files.upload.failed\", \"failed\")}\n </p>\n )}\n </div>\n <button\n onClick={onClose}\n className=\"p-1 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors\"\n >\n <X className=\"size-4\" />\n </button>\n </div>\n\n <div className=\"max-h-64 overflow-y-auto p-2 space-y-2\">\n {items.length === 0 ? (\n <p className=\"text-sm text-text-secondary text-center py-4\">\n {tWithFallback(t, \"files.upload.noUploads\", \"No uploads\")}\n </p>\n ) : (\n items.map((item) => (\n <UploadProgressBar\n key={item.id}\n item={item}\n onPause={onPause}\n onResume={onResume}\n onRetry={onRetry}\n onCancel={onCancel}\n />\n ))\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Files microfrontend components
|
|
3
|
+
*
|
|
4
|
+
* Priority 1: Core File Browser Components
|
|
5
|
+
*/
|
|
6
|
+
export { FileCard } from './FileCard';
|
|
7
|
+
export { FileListItem } from './FileListItem';
|
|
8
|
+
export { FolderCard } from './FolderCard';
|
|
9
|
+
export { FileBrowser } from './FileBrowser';
|
|
10
|
+
/**
|
|
11
|
+
* Priority 2 - Upload Components
|
|
12
|
+
*/
|
|
13
|
+
export { UploadQueue, UploadProgressBar } from './UploadQueue';
|
|
14
|
+
/**
|
|
15
|
+
* ROADMAP: Priority 3 - Preview Components
|
|
16
|
+
* - FilePreview
|
|
17
|
+
* - ImageViewer
|
|
18
|
+
* - PDFViewer
|
|
19
|
+
* - VideoPlayer
|
|
20
|
+
* - AudioPlayer
|
|
21
|
+
* - CodeViewer
|
|
22
|
+
* - TextViewer
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* ROADMAP: Priority 4 - Sharing Components
|
|
26
|
+
* - ShareDialog
|
|
27
|
+
* - PermissionMatrix
|
|
28
|
+
* - PublicLinkGenerator
|
|
29
|
+
* - ShareAnalytics
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* ROADMAP: Priority 5 - Versioning Components
|
|
33
|
+
* - VersionHistory
|
|
34
|
+
* - VersionDiff
|
|
35
|
+
* - RestoreDialog
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* ROADMAP: Priority 6 - Storage Components
|
|
39
|
+
* - StorageQuota
|
|
40
|
+
* - StorageBreakdown
|
|
41
|
+
* - LargeFilesReport
|
|
42
|
+
*/
|
|
43
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/files/components/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE/D;;;;;;;;;GASG;AAEH;;;;;;GAMG;AAEH;;;;;GAKG;AAEH;;;;;GAKG"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FileItem } from '../../types';
|
|
2
|
+
interface AudioPlayerProps {
|
|
3
|
+
file: FileItem;
|
|
4
|
+
url: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function AudioPlayer({ file, url }: AudioPlayerProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=AudioPlayer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudioPlayer.d.ts","sourceRoot":"","sources":["../../../../src/files/components/viewers/AudioPlayer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,UAAU,gBAAgB;IACxB,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,gBAAgB,2CAmJ1D"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { useEffect as e, useRef as t, useState as n } from "react";
|
|
2
|
+
import { Music as r, Pause as i, Play as a, Volume2 as o, VolumeX as s } from "lucide-react";
|
|
3
|
+
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
4
|
+
//#region src/files/components/viewers/AudioPlayer.tsx
|
|
5
|
+
function u({ file: u, url: d }) {
|
|
6
|
+
let f = t(null), [p, m] = n(!1), [h, g] = n(0), [_, v] = n(0), [y, b] = n(1), [x, S] = n(!1);
|
|
7
|
+
e(() => {
|
|
8
|
+
let e = f.current;
|
|
9
|
+
if (!e) return;
|
|
10
|
+
let t = () => g(e.currentTime), n = () => v(e.duration), r = () => m(!1);
|
|
11
|
+
return e.addEventListener("timeupdate", t), e.addEventListener("loadedmetadata", n), e.addEventListener("ended", r), () => {
|
|
12
|
+
e.removeEventListener("timeupdate", t), e.removeEventListener("loadedmetadata", n), e.removeEventListener("ended", r);
|
|
13
|
+
};
|
|
14
|
+
}, []);
|
|
15
|
+
let C = () => {
|
|
16
|
+
f.current && (p ? f.current.pause() : f.current.play(), m(!p));
|
|
17
|
+
}, w = (e) => {
|
|
18
|
+
f.current && (f.current.currentTime = e, g(e));
|
|
19
|
+
}, T = (e) => {
|
|
20
|
+
b(e), S(e === 0), f.current && (f.current.volume = e);
|
|
21
|
+
}, E = () => {
|
|
22
|
+
if (f.current) {
|
|
23
|
+
let e = !x;
|
|
24
|
+
S(e), f.current.muted = e;
|
|
25
|
+
}
|
|
26
|
+
}, D = (e) => `${Math.floor(e / 60)}:${Math.floor(e % 60).toString().padStart(2, "0")}`;
|
|
27
|
+
return /* @__PURE__ */ l("div", {
|
|
28
|
+
className: "flex flex-col h-full bg-bg-canvas",
|
|
29
|
+
children: [
|
|
30
|
+
/* @__PURE__ */ c("audio", {
|
|
31
|
+
ref: f,
|
|
32
|
+
src: d
|
|
33
|
+
}),
|
|
34
|
+
/* @__PURE__ */ l("div", {
|
|
35
|
+
className: "flex-1 flex flex-col items-center justify-center p-8",
|
|
36
|
+
children: [
|
|
37
|
+
/* @__PURE__ */ c("div", {
|
|
38
|
+
className: "size-64 rounded-lg bg-bg-muted flex items-center justify-center mb-8 shadow-lg",
|
|
39
|
+
children: /* @__PURE__ */ c(r, { className: "size-32 text-text-tertiary" })
|
|
40
|
+
}),
|
|
41
|
+
/* @__PURE__ */ c("h2", {
|
|
42
|
+
className: "text-xl font-semibold text-text-primary mb-2",
|
|
43
|
+
children: u.name
|
|
44
|
+
}),
|
|
45
|
+
/* @__PURE__ */ l("p", {
|
|
46
|
+
className: "text-sm text-text-secondary mb-1",
|
|
47
|
+
children: [(u.size / 1024 / 1024).toFixed(2), " MB"]
|
|
48
|
+
}),
|
|
49
|
+
/* @__PURE__ */ c("p", {
|
|
50
|
+
className: "text-sm text-text-secondary",
|
|
51
|
+
children: D(_)
|
|
52
|
+
})
|
|
53
|
+
]
|
|
54
|
+
}),
|
|
55
|
+
/* @__PURE__ */ l("div", {
|
|
56
|
+
className: "bg-bg-surface border-t border-border-default p-6",
|
|
57
|
+
children: [/* @__PURE__ */ l("div", {
|
|
58
|
+
className: "mb-4",
|
|
59
|
+
children: [/* @__PURE__ */ c("input", {
|
|
60
|
+
type: "range",
|
|
61
|
+
min: 0,
|
|
62
|
+
max: _ || 0,
|
|
63
|
+
value: h,
|
|
64
|
+
onChange: (e) => w(Number(e.target.value)),
|
|
65
|
+
className: "w-full h-2 bg-bg-muted rounded-lg appearance-none cursor-pointer accent-action-primary-bg"
|
|
66
|
+
}), /* @__PURE__ */ l("div", {
|
|
67
|
+
className: "flex justify-between mt-2 text-sm text-text-secondary",
|
|
68
|
+
children: [/* @__PURE__ */ c("span", { children: D(h) }), /* @__PURE__ */ c("span", { children: D(_) })]
|
|
69
|
+
})]
|
|
70
|
+
}), /* @__PURE__ */ l("div", {
|
|
71
|
+
className: "flex items-center justify-center gap-4",
|
|
72
|
+
children: [/* @__PURE__ */ c("button", {
|
|
73
|
+
onClick: C,
|
|
74
|
+
className: "p-4 text-text-inverse bg-action-primary-bg hover:bg-action-primary-bg-hover rounded-full transition-colors duration-200",
|
|
75
|
+
title: p ? "Pause" : "Play",
|
|
76
|
+
children: c(p ? i : a, { className: "size-6" })
|
|
77
|
+
}), /* @__PURE__ */ l("div", {
|
|
78
|
+
className: "flex items-center gap-2 ml-4",
|
|
79
|
+
children: [/* @__PURE__ */ c("button", {
|
|
80
|
+
onClick: E,
|
|
81
|
+
className: "p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200",
|
|
82
|
+
title: x ? "Unmute" : "Mute",
|
|
83
|
+
children: c(x ? s : o, { className: "size-5" })
|
|
84
|
+
}), /* @__PURE__ */ c("input", {
|
|
85
|
+
type: "range",
|
|
86
|
+
min: 0,
|
|
87
|
+
max: 1,
|
|
88
|
+
step: .1,
|
|
89
|
+
value: y,
|
|
90
|
+
onChange: (e) => T(Number(e.target.value)),
|
|
91
|
+
className: "w-24 h-1 bg-bg-muted rounded-lg appearance-none cursor-pointer accent-action-primary-bg"
|
|
92
|
+
})]
|
|
93
|
+
})]
|
|
94
|
+
})]
|
|
95
|
+
})
|
|
96
|
+
]
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
export { u as AudioPlayer };
|
|
101
|
+
|
|
102
|
+
//# sourceMappingURL=AudioPlayer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudioPlayer.js","names":[],"sources":["../../../../src/files/components/viewers/AudioPlayer.tsx"],"sourcesContent":["import { useState, useRef, useEffect } from \"react\";\nimport { Play, Pause, Volume2, VolumeX, Music } from \"lucide-react\";\nimport type { FileItem } from \"../../types\";\n\ninterface AudioPlayerProps {\n file: FileItem;\n url: string;\n}\n\nexport function AudioPlayer({ file, url }: AudioPlayerProps) {\n const audioRef = useRef<HTMLAudioElement>(null);\n const [isPlaying, setIsPlaying] = useState(false);\n const [currentTime, setCurrentTime] = useState(0);\n const [duration, setDuration] = useState(0);\n const [volume, setVolume] = useState(1);\n const [isMuted, setIsMuted] = useState(false);\n\n useEffect(() => {\n const audio = audioRef.current;\n if (!audio) return;\n\n const handleTimeUpdate = () => setCurrentTime(audio.currentTime);\n const handleLoadedMetadata = () => setDuration(audio.duration);\n const handleEnded = () => setIsPlaying(false);\n\n audio.addEventListener(\"timeupdate\", handleTimeUpdate);\n audio.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n audio.addEventListener(\"ended\", handleEnded);\n\n return () => {\n audio.removeEventListener(\"timeupdate\", handleTimeUpdate);\n audio.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n audio.removeEventListener(\"ended\", handleEnded);\n };\n }, []);\n\n const togglePlay = () => {\n if (audioRef.current) {\n if (isPlaying) {\n audioRef.current.pause();\n } else {\n audioRef.current.play();\n }\n setIsPlaying(!isPlaying);\n }\n };\n\n const handleSeek = (time: number) => {\n if (audioRef.current) {\n audioRef.current.currentTime = time;\n setCurrentTime(time);\n }\n };\n\n const handleVolumeChange = (newVolume: number) => {\n setVolume(newVolume);\n setIsMuted(newVolume === 0);\n if (audioRef.current) {\n audioRef.current.volume = newVolume;\n }\n };\n\n const toggleMute = () => {\n if (audioRef.current) {\n const newMuted = !isMuted;\n setIsMuted(newMuted);\n audioRef.current.muted = newMuted;\n }\n };\n\n const formatTime = (seconds: number): string => {\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins}:${secs.toString().padStart(2, \"0\")}`;\n };\n\n return (\n <div className=\"flex flex-col h-full bg-bg-canvas\">\n <audio ref={audioRef} src={url} />\n\n {/* Album Art Placeholder */}\n <div className=\"flex-1 flex flex-col items-center justify-center p-8\">\n <div className=\"size-64 rounded-lg bg-bg-muted flex items-center justify-center mb-8 shadow-lg\">\n <Music className=\"size-32 text-text-tertiary\" />\n </div>\n\n {/* Track Info */}\n <h2 className=\"text-xl font-semibold text-text-primary mb-2\">\n {file.name}\n </h2>\n <p className=\"text-sm text-text-secondary mb-1\">\n {(file.size / 1024 / 1024).toFixed(2)} MB\n </p>\n <p className=\"text-sm text-text-secondary\">{formatTime(duration)}</p>\n </div>\n\n {/* Controls */}\n <div className=\"bg-bg-surface border-t border-border-default p-6\">\n {/* Progress Bar */}\n <div className=\"mb-4\">\n <input\n type=\"range\"\n min={0}\n max={duration || 0}\n value={currentTime}\n onChange={(e) => handleSeek(Number(e.target.value))}\n className=\"w-full h-2 bg-bg-muted rounded-lg appearance-none cursor-pointer accent-action-primary-bg\"\n />\n <div className=\"flex justify-between mt-2 text-sm text-text-secondary\">\n <span>{formatTime(currentTime)}</span>\n <span>{formatTime(duration)}</span>\n </div>\n </div>\n\n {/* Control Buttons */}\n <div className=\"flex items-center justify-center gap-4\">\n {/* Play/Pause */}\n <button\n onClick={togglePlay}\n className=\"p-4 text-text-inverse bg-action-primary-bg hover:bg-action-primary-bg-hover rounded-full transition-colors duration-200\"\n title={isPlaying ? \"Pause\" : \"Play\"}\n >\n {isPlaying ? (\n <Pause className=\"size-6\" />\n ) : (\n <Play className=\"size-6\" />\n )}\n </button>\n\n {/* Volume Controls */}\n <div className=\"flex items-center gap-2 ml-4\">\n <button\n onClick={toggleMute}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200\"\n title={isMuted ? \"Unmute\" : \"Mute\"}\n >\n {isMuted ? (\n <VolumeX className=\"size-5\" />\n ) : (\n <Volume2 className=\"size-5\" />\n )}\n </button>\n <input\n type=\"range\"\n min={0}\n max={1}\n step={0.1}\n value={volume}\n onChange={(e) => handleVolumeChange(Number(e.target.value))}\n className=\"w-24 h-1 bg-bg-muted rounded-lg appearance-none cursor-pointer accent-action-primary-bg\"\n />\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { FileItem } from '../../types';
|
|
2
|
+
interface CodeViewerProps {
|
|
3
|
+
file: FileItem;
|
|
4
|
+
url: string;
|
|
5
|
+
language?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* CodeViewer - Displays code files with syntax highlighting
|
|
9
|
+
*
|
|
10
|
+
* Note: This is a simplified implementation with basic highlighting.
|
|
11
|
+
* For full syntax highlighting, install prism-react-renderer:
|
|
12
|
+
* bun add prism-react-renderer
|
|
13
|
+
*/
|
|
14
|
+
export declare function CodeViewer({ file, url, language }: CodeViewerProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=CodeViewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeViewer.d.ts","sourceRoot":"","sources":["../../../../src/files/components/viewers/CodeViewer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,UAAU,eAAe;IACvB,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,eAAe,2CA0GlE"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { useEffect as e, useState as t } from "react";
|
|
2
|
+
import { Check as n, Copy as r, WrapText as i } from "lucide-react";
|
|
3
|
+
import { Fragment as a, jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
4
|
+
//#region src/files/components/viewers/CodeViewer.tsx
|
|
5
|
+
function c({ file: c, url: u, language: d }) {
|
|
6
|
+
let [f, p] = t(""), [m, h] = t(!0), [g, _] = t(!1), [v, y] = t(!1), b = d || l(c.name);
|
|
7
|
+
return e(() => {
|
|
8
|
+
fetch(u).then((e) => e.text()).then((e) => {
|
|
9
|
+
p(e), h(!1);
|
|
10
|
+
}).catch(() => {
|
|
11
|
+
h(!1);
|
|
12
|
+
});
|
|
13
|
+
}, [u]), m ? /* @__PURE__ */ o("div", {
|
|
14
|
+
className: "flex items-center justify-center h-full bg-bg-canvas",
|
|
15
|
+
children: /* @__PURE__ */ o("span", {
|
|
16
|
+
className: "text-text-secondary",
|
|
17
|
+
children: "Loading code..."
|
|
18
|
+
})
|
|
19
|
+
}) : /* @__PURE__ */ s("div", {
|
|
20
|
+
className: "flex flex-col h-full bg-bg-canvas",
|
|
21
|
+
children: [
|
|
22
|
+
/* @__PURE__ */ s("div", {
|
|
23
|
+
className: "flex items-center justify-between p-3 bg-bg-surface border-b border-border-default",
|
|
24
|
+
children: [/* @__PURE__ */ s("div", {
|
|
25
|
+
className: "flex items-center gap-2",
|
|
26
|
+
children: [/* @__PURE__ */ o("span", {
|
|
27
|
+
className: "px-2 py-1 text-xs font-medium text-text-link bg-bg-accent rounded",
|
|
28
|
+
children: b || "Text"
|
|
29
|
+
}), /* @__PURE__ */ o("span", {
|
|
30
|
+
className: "text-sm text-text-secondary",
|
|
31
|
+
children: c.name
|
|
32
|
+
})]
|
|
33
|
+
}), /* @__PURE__ */ s("div", {
|
|
34
|
+
className: "flex items-center gap-2",
|
|
35
|
+
children: [/* @__PURE__ */ o("button", {
|
|
36
|
+
onClick: () => _(!g),
|
|
37
|
+
className: `p-2 rounded transition-colors duration-200 ${g ? "text-text-link bg-bg-accent" : "text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover"}`,
|
|
38
|
+
title: g ? "Disable word wrap" : "Enable word wrap",
|
|
39
|
+
"aria-label": g ? "Disable word wrap" : "Enable word wrap",
|
|
40
|
+
children: /* @__PURE__ */ o(i, { className: "size-4" })
|
|
41
|
+
}), /* @__PURE__ */ o("button", {
|
|
42
|
+
onClick: () => {
|
|
43
|
+
navigator.clipboard.writeText(f), y(!0), setTimeout(() => y(!1), 2e3);
|
|
44
|
+
},
|
|
45
|
+
className: "flex items-center gap-1.5 rounded px-3 py-1.5 text-sm font-medium text-text-inverse bg-action-primary-bg transition-colors duration-200 hover:bg-action-primary-bg-hover",
|
|
46
|
+
title: "Copy code",
|
|
47
|
+
"aria-label": "Copy code content",
|
|
48
|
+
children: v ? /* @__PURE__ */ s(a, { children: [/* @__PURE__ */ o(n, { className: "size-4" }), "Copied!"] }) : /* @__PURE__ */ s(a, { children: [/* @__PURE__ */ o(r, { className: "size-4" }), "Copy"] })
|
|
49
|
+
})]
|
|
50
|
+
})]
|
|
51
|
+
}),
|
|
52
|
+
/* @__PURE__ */ o("div", {
|
|
53
|
+
className: "flex-1 overflow-auto",
|
|
54
|
+
children: /* @__PURE__ */ o("pre", {
|
|
55
|
+
className: `p-4 text-sm font-mono leading-relaxed ${g ? "whitespace-pre-wrap" : "whitespace-pre"}`,
|
|
56
|
+
style: { tabSize: 2 },
|
|
57
|
+
children: f.split("\n").map((e, t) => /* @__PURE__ */ s("div", {
|
|
58
|
+
className: "flex",
|
|
59
|
+
children: [/* @__PURE__ */ o("span", {
|
|
60
|
+
className: "inline-block w-12 text-right pr-4 text-text-tertiary select-none",
|
|
61
|
+
children: t + 1
|
|
62
|
+
}), /* @__PURE__ */ o("span", {
|
|
63
|
+
className: "text-text-primary",
|
|
64
|
+
children: e || " "
|
|
65
|
+
})]
|
|
66
|
+
}, t))
|
|
67
|
+
})
|
|
68
|
+
}),
|
|
69
|
+
/* @__PURE__ */ s("div", {
|
|
70
|
+
className: "flex items-center justify-between p-3 bg-bg-surface border-t border-border-default text-xs text-text-secondary",
|
|
71
|
+
children: [/* @__PURE__ */ s("span", { children: [f.split("\n").length, " lines"] }), /* @__PURE__ */ s("span", { children: [(c.size / 1024).toFixed(2), " KB"] })]
|
|
72
|
+
})
|
|
73
|
+
]
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function l(e) {
|
|
77
|
+
return {
|
|
78
|
+
js: "JavaScript",
|
|
79
|
+
jsx: "React JSX",
|
|
80
|
+
ts: "TypeScript",
|
|
81
|
+
tsx: "React TSX",
|
|
82
|
+
py: "Python",
|
|
83
|
+
java: "Java",
|
|
84
|
+
cpp: "C++",
|
|
85
|
+
c: "C",
|
|
86
|
+
cs: "C#",
|
|
87
|
+
rb: "Ruby",
|
|
88
|
+
go: "Go",
|
|
89
|
+
rs: "Rust",
|
|
90
|
+
php: "PHP",
|
|
91
|
+
html: "HTML",
|
|
92
|
+
css: "CSS",
|
|
93
|
+
scss: "SCSS",
|
|
94
|
+
json: "JSON",
|
|
95
|
+
md: "Markdown",
|
|
96
|
+
yaml: "YAML",
|
|
97
|
+
yml: "YAML",
|
|
98
|
+
xml: "XML",
|
|
99
|
+
sql: "SQL",
|
|
100
|
+
sh: "Shell",
|
|
101
|
+
bash: "Bash",
|
|
102
|
+
vue: "Vue",
|
|
103
|
+
swift: "Swift",
|
|
104
|
+
kt: "Kotlin",
|
|
105
|
+
r: "R",
|
|
106
|
+
dart: "Dart",
|
|
107
|
+
lua: "Lua"
|
|
108
|
+
}[e.split(".").pop()?.toLowerCase() || ""] || "Text";
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { c as CodeViewer };
|
|
112
|
+
|
|
113
|
+
//# sourceMappingURL=CodeViewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeViewer.js","names":[],"sources":["../../../../src/files/components/viewers/CodeViewer.tsx"],"sourcesContent":["import { useState, useEffect } from \"react\";\nimport { Copy, Check, WrapText } from \"lucide-react\";\nimport type { FileItem } from \"../../types\";\n\ninterface CodeViewerProps {\n file: FileItem;\n url: string;\n language?: string;\n}\n\n/**\n * CodeViewer - Displays code files with syntax highlighting\n *\n * Note: This is a simplified implementation with basic highlighting.\n * For full syntax highlighting, install prism-react-renderer:\n * bun add prism-react-renderer\n */\nexport function CodeViewer({ file, url, language }: CodeViewerProps) {\n const [code, setCode] = useState(\"\");\n const [loading, setLoading] = useState(true);\n const [wordWrap, setWordWrap] = useState(false);\n const [copied, setCopied] = useState(false);\n\n const detectedLanguage = language || detectLanguage(file.name);\n\n useEffect(() => {\n fetch(url)\n .then((res) => res.text())\n .then((text) => {\n setCode(text);\n setLoading(false);\n })\n .catch(() => {\n setLoading(false);\n });\n }, [url]);\n\n const handleCopy = () => {\n navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n };\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center h-full bg-bg-canvas\">\n <span className=\"text-text-secondary\">Loading code...</span>\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col h-full bg-bg-canvas\">\n {/* Toolbar */}\n <div className=\"flex items-center justify-between p-3 bg-bg-surface border-b border-border-default\">\n <div className=\"flex items-center gap-2\">\n <span className=\"px-2 py-1 text-xs font-medium text-text-link bg-bg-accent rounded\">\n {detectedLanguage || \"Text\"}\n </span>\n <span className=\"text-sm text-text-secondary\">{file.name}</span>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setWordWrap(!wordWrap)}\n className={`p-2 rounded transition-colors duration-200 ${\n wordWrap\n ? \"text-text-link bg-bg-accent\"\n : \"text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover\"\n }`}\n title={wordWrap ? \"Disable word wrap\" : \"Enable word wrap\"}\n aria-label={wordWrap ? \"Disable word wrap\" : \"Enable word wrap\"}\n >\n <WrapText className=\"size-4\" />\n </button>\n\n <button\n onClick={handleCopy}\n className=\"flex items-center gap-1.5 rounded px-3 py-1.5 text-sm font-medium text-text-inverse bg-action-primary-bg transition-colors duration-200 hover:bg-action-primary-bg-hover\"\n title=\"Copy code\"\n aria-label=\"Copy code content\"\n >\n {copied ? (\n <>\n <Check className=\"size-4\" />\n Copied!\n </>\n ) : (\n <>\n <Copy className=\"size-4\" />\n Copy\n </>\n )}\n </button>\n </div>\n </div>\n\n {/* Code Content */}\n <div className=\"flex-1 overflow-auto\">\n <pre\n className={`p-4 text-sm font-mono leading-relaxed ${\n wordWrap ? \"whitespace-pre-wrap\" : \"whitespace-pre\"\n }`}\n style={{ tabSize: 2 }}\n >\n {code.split(\"\\n\").map((line, i) => (\n <div key={i} className=\"flex\">\n <span className=\"inline-block w-12 text-right pr-4 text-text-tertiary select-none\">\n {i + 1}\n </span>\n <span className=\"text-text-primary\">{line || \" \"}</span>\n </div>\n ))}\n </pre>\n </div>\n\n {/* Footer */}\n <div className=\"flex items-center justify-between p-3 bg-bg-surface border-t border-border-default text-xs text-text-secondary\">\n <span>{code.split(\"\\n\").length} lines</span>\n <span>{(file.size / 1024).toFixed(2)} KB</span>\n </div>\n </div>\n );\n}\n\nfunction detectLanguage(filename: string): string {\n const ext = filename.split(\".\").pop()?.toLowerCase();\n const languageMap: Record<string, string> = {\n js: \"JavaScript\",\n jsx: \"React JSX\",\n ts: \"TypeScript\",\n tsx: \"React TSX\",\n py: \"Python\",\n java: \"Java\",\n cpp: \"C++\",\n c: \"C\",\n cs: \"C#\",\n rb: \"Ruby\",\n go: \"Go\",\n rs: \"Rust\",\n php: \"PHP\",\n html: \"HTML\",\n css: \"CSS\",\n scss: \"SCSS\",\n json: \"JSON\",\n md: \"Markdown\",\n yaml: \"YAML\",\n yml: \"YAML\",\n xml: \"XML\",\n sql: \"SQL\",\n sh: \"Shell\",\n bash: \"Bash\",\n vue: \"Vue\",\n swift: \"Swift\",\n kt: \"Kotlin\",\n r: \"R\",\n dart: \"Dart\",\n lua: \"Lua\",\n };\n return languageMap[ext || \"\"] || \"Text\";\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FileItem } from '../../types';
|
|
2
|
+
interface ImageViewerProps {
|
|
3
|
+
file: FileItem;
|
|
4
|
+
url: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function ImageViewer({ file, url }: ImageViewerProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=ImageViewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageViewer.d.ts","sourceRoot":"","sources":["../../../../src/files/components/viewers/ImageViewer.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,UAAU,gBAAgB;IACxB,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,gBAAgB,2CA6J1D"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { useRef as e, useState as t } from "react";
|
|
2
|
+
import { AlertCircle as n, Minimize2 as r, RotateCw as i, ZoomIn as a, ZoomOut as o } from "lucide-react";
|
|
3
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
4
|
+
//#region src/files/components/viewers/ImageViewer.tsx
|
|
5
|
+
function l({ file: l, url: u }) {
|
|
6
|
+
let [d, f] = t(1), [p, m] = t(0), [h, g] = t({
|
|
7
|
+
x: 0,
|
|
8
|
+
y: 0
|
|
9
|
+
}), [_, v] = t(!1), [y, b] = t({
|
|
10
|
+
x: 0,
|
|
11
|
+
y: 0
|
|
12
|
+
}), [x, S] = t(null), C = e(null), [w, T] = t({
|
|
13
|
+
width: 0,
|
|
14
|
+
height: 0
|
|
15
|
+
}), E = () => f((e) => Math.min(e + .25, 4)), D = () => f((e) => Math.max(e - .25, .25)), O = () => {
|
|
16
|
+
f(1), g({
|
|
17
|
+
x: 0,
|
|
18
|
+
y: 0
|
|
19
|
+
}), m(0);
|
|
20
|
+
}, k = () => m((e) => (e + 90) % 360), A = (e) => {
|
|
21
|
+
d > 1 && (v(!0), b({
|
|
22
|
+
x: e.clientX - h.x,
|
|
23
|
+
y: e.clientY - h.y
|
|
24
|
+
}));
|
|
25
|
+
}, j = (e) => {
|
|
26
|
+
_ && d > 1 && g({
|
|
27
|
+
x: e.clientX - y.x,
|
|
28
|
+
y: e.clientY - y.y
|
|
29
|
+
});
|
|
30
|
+
}, M = () => {
|
|
31
|
+
v(!1);
|
|
32
|
+
};
|
|
33
|
+
return /* @__PURE__ */ c("div", {
|
|
34
|
+
className: "flex flex-col h-full bg-bg-canvas",
|
|
35
|
+
children: [
|
|
36
|
+
/* @__PURE__ */ c("div", {
|
|
37
|
+
className: "flex items-center justify-center gap-2 p-4 bg-bg-surface border-b border-border-default",
|
|
38
|
+
children: [
|
|
39
|
+
/* @__PURE__ */ s("button", {
|
|
40
|
+
onClick: D,
|
|
41
|
+
disabled: d <= .25,
|
|
42
|
+
className: "p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
43
|
+
title: "Zoom out",
|
|
44
|
+
children: /* @__PURE__ */ s(o, { className: "size-5" })
|
|
45
|
+
}),
|
|
46
|
+
/* @__PURE__ */ c("span", {
|
|
47
|
+
className: "min-w-16 text-center text-sm font-medium text-text-primary",
|
|
48
|
+
children: [Math.round(d * 100), "%"]
|
|
49
|
+
}),
|
|
50
|
+
/* @__PURE__ */ s("button", {
|
|
51
|
+
onClick: E,
|
|
52
|
+
disabled: d >= 4,
|
|
53
|
+
className: "p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
54
|
+
title: "Zoom in",
|
|
55
|
+
children: /* @__PURE__ */ s(a, { className: "size-5" })
|
|
56
|
+
}),
|
|
57
|
+
/* @__PURE__ */ s("div", { className: "w-px h-6 bg-border-default mx-2" }),
|
|
58
|
+
/* @__PURE__ */ s("button", {
|
|
59
|
+
onClick: O,
|
|
60
|
+
className: "p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200",
|
|
61
|
+
title: "Fit to screen",
|
|
62
|
+
children: /* @__PURE__ */ s(r, { className: "size-5" })
|
|
63
|
+
}),
|
|
64
|
+
/* @__PURE__ */ s("button", {
|
|
65
|
+
onClick: k,
|
|
66
|
+
className: "p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200",
|
|
67
|
+
title: "Rotate 90°",
|
|
68
|
+
children: /* @__PURE__ */ s(i, { className: "size-5" })
|
|
69
|
+
})
|
|
70
|
+
]
|
|
71
|
+
}),
|
|
72
|
+
/* @__PURE__ */ c("div", {
|
|
73
|
+
className: "flex-1 overflow-hidden flex items-center justify-center relative",
|
|
74
|
+
onMouseDown: A,
|
|
75
|
+
onMouseMove: j,
|
|
76
|
+
onMouseUp: M,
|
|
77
|
+
onMouseLeave: M,
|
|
78
|
+
style: { cursor: d > 1 ? _ ? "grabbing" : "grab" : "default" },
|
|
79
|
+
children: [/* @__PURE__ */ s("img", {
|
|
80
|
+
ref: C,
|
|
81
|
+
src: u,
|
|
82
|
+
alt: l.name,
|
|
83
|
+
onLoad: () => {
|
|
84
|
+
C.current && T({
|
|
85
|
+
width: C.current.naturalWidth,
|
|
86
|
+
height: C.current.naturalHeight
|
|
87
|
+
});
|
|
88
|
+
},
|
|
89
|
+
onError: () => {
|
|
90
|
+
S("Failed to load image from URL");
|
|
91
|
+
},
|
|
92
|
+
draggable: !1,
|
|
93
|
+
className: "max-w-full max-h-full object-contain transition-transform duration-200",
|
|
94
|
+
style: {
|
|
95
|
+
transform: `scale(${d}) rotate(${p}deg) translate(${h.x / d}px, ${h.y / d}px)`,
|
|
96
|
+
userSelect: "none"
|
|
97
|
+
}
|
|
98
|
+
}), x && /* @__PURE__ */ c("div", {
|
|
99
|
+
className: "absolute inset-0 flex flex-col items-center justify-center bg-bg-canvas/90 z-10",
|
|
100
|
+
children: [
|
|
101
|
+
/* @__PURE__ */ s(n, { className: "size-12 text-status-error-text mb-4" }),
|
|
102
|
+
/* @__PURE__ */ s("p", {
|
|
103
|
+
className: "text-text-primary font-medium mb-2",
|
|
104
|
+
children: "Failed to load image"
|
|
105
|
+
}),
|
|
106
|
+
/* @__PURE__ */ s("p", {
|
|
107
|
+
className: "text-text-secondary text-sm max-w-md text-center px-4",
|
|
108
|
+
children: x
|
|
109
|
+
}),
|
|
110
|
+
/* @__PURE__ */ s("a", {
|
|
111
|
+
href: u,
|
|
112
|
+
target: "_blank",
|
|
113
|
+
rel: "noopener noreferrer",
|
|
114
|
+
className: "mt-4 px-4 py-2 bg-action-primary-bg text-text-inverse rounded-lg hover:bg-action-primary-bg-hover",
|
|
115
|
+
children: "Open in new tab"
|
|
116
|
+
})
|
|
117
|
+
]
|
|
118
|
+
})]
|
|
119
|
+
}),
|
|
120
|
+
/* @__PURE__ */ c("div", {
|
|
121
|
+
className: "flex items-center justify-center gap-6 p-3 bg-bg-surface border-t border-border-default text-xs text-text-secondary",
|
|
122
|
+
children: [
|
|
123
|
+
/* @__PURE__ */ s("span", { children: l.name }),
|
|
124
|
+
w.width > 0 && /* @__PURE__ */ c("span", { children: [
|
|
125
|
+
w.width,
|
|
126
|
+
" × ",
|
|
127
|
+
w.height
|
|
128
|
+
] }),
|
|
129
|
+
/* @__PURE__ */ c("span", { children: [(l.size / 1024 / 1024).toFixed(2), " MB"] })
|
|
130
|
+
]
|
|
131
|
+
})
|
|
132
|
+
]
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
export { l as ImageViewer };
|
|
137
|
+
|
|
138
|
+
//# sourceMappingURL=ImageViewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageViewer.js","names":[],"sources":["../../../../src/files/components/viewers/ImageViewer.tsx"],"sourcesContent":["import { useState, useRef } from \"react\";\nimport {\n ZoomIn,\n ZoomOut,\n RotateCw,\n Maximize2,\n Minimize2,\n AlertCircle,\n} from \"lucide-react\";\nimport type { FileItem } from \"../../types\";\n\ninterface ImageViewerProps {\n file: FileItem;\n url: string;\n}\n\nexport function ImageViewer({ file, url }: ImageViewerProps) {\n const [zoom, setZoom] = useState(1);\n const [rotation, setRotation] = useState(0);\n const [position, setPosition] = useState({ x: 0, y: 0 });\n const [isDragging, setIsDragging] = useState(false);\n const [dragStart, setDragStart] = useState({ x: 0, y: 0 });\n const [imageError, setImageError] = useState<string | null>(null);\n const imageRef = useRef<HTMLImageElement>(null);\n const [imageDimensions, setImageDimensions] = useState({\n width: 0,\n height: 0,\n });\n\n const handleZoomIn = () => setZoom((prev) => Math.min(prev + 0.25, 4));\n const handleZoomOut = () => setZoom((prev) => Math.max(prev - 0.25, 0.25));\n const handleResetZoom = () => {\n setZoom(1);\n setPosition({ x: 0, y: 0 });\n setRotation(0);\n };\n const handleRotate = () => setRotation((prev) => (prev + 90) % 360);\n\n const handleMouseDown = (e: React.MouseEvent) => {\n if (zoom > 1) {\n setIsDragging(true);\n setDragStart({ x: e.clientX - position.x, y: e.clientY - position.y });\n }\n };\n\n const handleMouseMove = (e: React.MouseEvent) => {\n if (isDragging && zoom > 1) {\n setPosition({\n x: e.clientX - dragStart.x,\n y: e.clientY - dragStart.y,\n });\n }\n };\n\n const handleMouseUp = () => {\n setIsDragging(false);\n };\n\n const handleImageLoad = () => {\n if (imageRef.current) {\n setImageDimensions({\n width: imageRef.current.naturalWidth,\n height: imageRef.current.naturalHeight,\n });\n }\n };\n\n const handleImageError = () => {\n setImageError(`Failed to load image from URL`);\n };\n\n return (\n <div className=\"flex flex-col h-full bg-bg-canvas\">\n {/* Toolbar */}\n <div className=\"flex items-center justify-center gap-2 p-4 bg-bg-surface border-b border-border-default\">\n <button\n onClick={handleZoomOut}\n disabled={zoom <= 0.25}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed\"\n title=\"Zoom out\"\n >\n <ZoomOut className=\"size-5\" />\n </button>\n\n <span className=\"min-w-16 text-center text-sm font-medium text-text-primary\">\n {Math.round(zoom * 100)}%\n </span>\n\n <button\n onClick={handleZoomIn}\n disabled={zoom >= 4}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed\"\n title=\"Zoom in\"\n >\n <ZoomIn className=\"size-5\" />\n </button>\n\n <div className=\"w-px h-6 bg-border-default mx-2\" />\n\n <button\n onClick={handleResetZoom}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200\"\n title=\"Fit to screen\"\n >\n <Minimize2 className=\"size-5\" />\n </button>\n\n <button\n onClick={handleRotate}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200\"\n title=\"Rotate 90°\"\n >\n <RotateCw className=\"size-5\" />\n </button>\n </div>\n\n {/* Image Container */}\n <div\n className=\"flex-1 overflow-hidden flex items-center justify-center relative\"\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n style={{\n cursor: zoom > 1 ? (isDragging ? \"grabbing\" : \"grab\") : \"default\",\n }}\n >\n <img\n ref={imageRef}\n src={url}\n alt={file.name}\n onLoad={handleImageLoad}\n onError={handleImageError}\n draggable={false}\n className=\"max-w-full max-h-full object-contain transition-transform duration-200\"\n style={{\n transform: `scale(${zoom}) rotate(${rotation}deg) translate(${position.x / zoom}px, ${position.y / zoom}px)`,\n userSelect: \"none\",\n }}\n />\n {imageError && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center bg-bg-canvas/90 z-10\">\n <AlertCircle className=\"size-12 text-status-error-text mb-4\" />\n <p className=\"text-text-primary font-medium mb-2\">\n Failed to load image\n </p>\n <p className=\"text-text-secondary text-sm max-w-md text-center px-4\">\n {imageError}\n </p>\n <a\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"mt-4 px-4 py-2 bg-action-primary-bg text-text-inverse rounded-lg hover:bg-action-primary-bg-hover\"\n >\n Open in new tab\n </a>\n </div>\n )}\n </div>\n\n {/* Metadata */}\n <div className=\"flex items-center justify-center gap-6 p-3 bg-bg-surface border-t border-border-default text-xs text-text-secondary\">\n <span>{file.name}</span>\n {imageDimensions.width > 0 && (\n <span>\n {imageDimensions.width} × {imageDimensions.height}\n </span>\n )}\n <span>{(file.size / 1024 / 1024).toFixed(2)} MB</span>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;AAgBA,SAAgB,EAAY,EAAE,SAAM,UAAyB;CAC3D,IAAM,CAAC,GAAM,KAAW,EAAS,EAAE,EAC7B,CAAC,GAAU,KAAe,EAAS,EAAE,EACrC,CAAC,GAAU,KAAe,EAAS;EAAE,GAAG;EAAG,GAAG;EAAG,CAAC,EAClD,CAAC,GAAY,KAAiB,EAAS,GAAM,EAC7C,CAAC,GAAW,KAAgB,EAAS;EAAE,GAAG;EAAG,GAAG;EAAG,CAAC,EACpD,CAAC,GAAY,KAAiB,EAAwB,KAAK,EAC3D,IAAW,EAAyB,KAAK,EACzC,CAAC,GAAiB,KAAsB,EAAS;EACrD,OAAO;EACP,QAAQ;EACT,CAAC,EAEI,UAAqB,GAAS,MAAS,KAAK,IAAI,IAAO,KAAM,EAAE,CAAC,EAChE,UAAsB,GAAS,MAAS,KAAK,IAAI,IAAO,KAAM,IAAK,CAAC,EACpE,UAAwB;AAG5B,EAFA,EAAQ,EAAE,EACV,EAAY;GAAE,GAAG;GAAG,GAAG;GAAG,CAAC,EAC3B,EAAY,EAAE;IAEV,UAAqB,GAAa,OAAU,IAAO,MAAM,IAAI,EAE7D,KAAmB,MAAwB;AAC/C,EAAI,IAAO,MACT,EAAc,GAAK,EACnB,EAAa;GAAE,GAAG,EAAE,UAAU,EAAS;GAAG,GAAG,EAAE,UAAU,EAAS;GAAG,CAAC;IAIpE,KAAmB,MAAwB;AAC/C,EAAI,KAAc,IAAO,KACvB,EAAY;GACV,GAAG,EAAE,UAAU,EAAU;GACzB,GAAG,EAAE,UAAU,EAAU;GAC1B,CAAC;IAIA,UAAsB;AAC1B,IAAc,GAAM;;AAgBtB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GAEE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,UAAD;MACE,SAAS;MACT,UAAU,KAAQ;MAClB,WAAU;MACV,OAAM;gBAEN,kBAAC,GAAD,EAAS,WAAU,UAAW,CAAA;MACvB,CAAA;KAET,kBAAC,QAAD;MAAM,WAAU;gBAAhB,CACG,KAAK,MAAM,IAAO,IAAI,EAAC,IACnB;;KAEP,kBAAC,UAAD;MACE,SAAS;MACT,UAAU,KAAQ;MAClB,WAAU;MACV,OAAM;gBAEN,kBAAC,GAAD,EAAQ,WAAU,UAAW,CAAA;MACtB,CAAA;KAET,kBAAC,OAAD,EAAK,WAAU,mCAAoC,CAAA;KAEnD,kBAAC,UAAD;MACE,SAAS;MACT,WAAU;MACV,OAAM;gBAEN,kBAAC,GAAD,EAAW,WAAU,UAAW,CAAA;MACzB,CAAA;KAET,kBAAC,UAAD;MACE,SAAS;MACT,WAAU;MACV,OAAM;gBAEN,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA;MACxB,CAAA;KACL;;GAGN,kBAAC,OAAD;IACE,WAAU;IACV,aAAa;IACb,aAAa;IACb,WAAW;IACX,cAAc;IACd,OAAO,EACL,QAAQ,IAAO,IAAK,IAAa,aAAa,SAAU,WACzD;cARH,CAUE,kBAAC,OAAD;KACE,KAAK;KACL,KAAK;KACL,KAAK,EAAK;KACV,cAzEsB;AAC5B,MAAI,EAAS,WACX,EAAmB;OACjB,OAAO,EAAS,QAAQ;OACxB,QAAQ,EAAS,QAAQ;OAC1B,CAAC;;KAqEE,eAjEuB;AAC7B,QAAc,gCAAgC;;KAiExC,WAAW;KACX,WAAU;KACV,OAAO;MACL,WAAW,SAAS,EAAK,WAAW,EAAS,iBAAiB,EAAS,IAAI,EAAK,MAAM,EAAS,IAAI,EAAK;MACxG,YAAY;MACb;KACD,CAAA,EACD,KACC,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,GAAD,EAAa,WAAU,uCAAwC,CAAA;MAC/D,kBAAC,KAAD;OAAG,WAAU;iBAAqC;OAE9C,CAAA;MACJ,kBAAC,KAAD;OAAG,WAAU;iBACV;OACC,CAAA;MACJ,kBAAC,KAAD;OACE,MAAM;OACN,QAAO;OACP,KAAI;OACJ,WAAU;iBACX;OAEG,CAAA;MACA;OAEJ;;GAGN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,QAAD,EAAA,UAAO,EAAK,MAAY,CAAA;KACvB,EAAgB,QAAQ,KACvB,kBAAC,QAAD,EAAA,UAAA;MACG,EAAgB;MAAM;MAAI,EAAgB;MACtC,EAAA,CAAA;KAET,kBAAC,QAAD,EAAA,UAAA,EAAQ,EAAK,OAAO,OAAO,MAAM,QAAQ,EAAE,EAAC,MAAU,EAAA,CAAA;KAClD;;GACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FileItem } from '../../types';
|
|
2
|
+
interface PDFViewerProps {
|
|
3
|
+
file: FileItem;
|
|
4
|
+
url: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* PDFViewer - Displays PDF files
|
|
8
|
+
*
|
|
9
|
+
* Note: This uses <object> tag for better browser PDF compatibility.
|
|
10
|
+
* For a full-featured PDF viewer with more controls, install react-pdf:
|
|
11
|
+
* bun add react-pdf pdfjs-dist
|
|
12
|
+
*/
|
|
13
|
+
export declare function PDFViewer({ file, url }: PDFViewerProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=PDFViewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PDFViewer.d.ts","sourceRoot":"","sources":["../../../../src/files/components/viewers/PDFViewer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,UAAU,cAAc;IACtB,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,cAAc,2CA2EtD"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { useState as e } from "react";
|
|
2
|
+
import { ZoomIn as t, ZoomOut as n } from "lucide-react";
|
|
3
|
+
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
4
|
+
//#region src/files/components/viewers/PDFViewer.tsx
|
|
5
|
+
function a({ file: a, url: o }) {
|
|
6
|
+
let [s, c] = e(100), l = () => c((e) => Math.min(e + 25, 200)), u = () => c((e) => Math.max(e - 25, 50)), d = `${o}#view=FitH&zoom=${s}`;
|
|
7
|
+
return /* @__PURE__ */ i("div", {
|
|
8
|
+
className: "flex flex-col h-full bg-bg-canvas",
|
|
9
|
+
children: [
|
|
10
|
+
/* @__PURE__ */ i("div", {
|
|
11
|
+
className: "flex items-center justify-between p-4 bg-bg-surface border-b border-border-default",
|
|
12
|
+
children: [/* @__PURE__ */ i("div", {
|
|
13
|
+
className: "flex items-center gap-2",
|
|
14
|
+
children: [
|
|
15
|
+
/* @__PURE__ */ r("button", {
|
|
16
|
+
onClick: u,
|
|
17
|
+
disabled: s <= 50,
|
|
18
|
+
className: "p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
19
|
+
title: "Zoom out",
|
|
20
|
+
children: /* @__PURE__ */ r(n, { className: "size-5" })
|
|
21
|
+
}),
|
|
22
|
+
/* @__PURE__ */ i("span", {
|
|
23
|
+
className: "min-w-16 text-center text-sm font-medium text-text-primary",
|
|
24
|
+
children: [s, "%"]
|
|
25
|
+
}),
|
|
26
|
+
/* @__PURE__ */ r("button", {
|
|
27
|
+
onClick: l,
|
|
28
|
+
disabled: s >= 200,
|
|
29
|
+
className: "p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
30
|
+
title: "Zoom in",
|
|
31
|
+
children: /* @__PURE__ */ r(t, { className: "size-5" })
|
|
32
|
+
})
|
|
33
|
+
]
|
|
34
|
+
}), /* @__PURE__ */ r("span", {
|
|
35
|
+
className: "text-sm text-text-secondary",
|
|
36
|
+
children: a.name
|
|
37
|
+
})]
|
|
38
|
+
}),
|
|
39
|
+
/* @__PURE__ */ r("div", {
|
|
40
|
+
className: "flex-1 overflow-hidden",
|
|
41
|
+
children: /* @__PURE__ */ r("object", {
|
|
42
|
+
data: d,
|
|
43
|
+
type: "application/pdf",
|
|
44
|
+
className: "w-full h-full",
|
|
45
|
+
title: a.name,
|
|
46
|
+
children: /* @__PURE__ */ i("div", {
|
|
47
|
+
className: "flex flex-col items-center justify-center h-full gap-4 p-8",
|
|
48
|
+
children: [/* @__PURE__ */ i("div", {
|
|
49
|
+
className: "text-text-secondary text-center",
|
|
50
|
+
children: [/* @__PURE__ */ r("p", {
|
|
51
|
+
className: "font-text-lg font-weight-medium mb-2",
|
|
52
|
+
children: "Unable to display PDF"
|
|
53
|
+
}), /* @__PURE__ */ r("p", {
|
|
54
|
+
className: "font-text-sm",
|
|
55
|
+
children: "Your browser may not support embedded PDF viewing."
|
|
56
|
+
})]
|
|
57
|
+
}), /* @__PURE__ */ r("a", {
|
|
58
|
+
href: o,
|
|
59
|
+
download: a.name,
|
|
60
|
+
className: "px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-btn hover:bg-action-primary-bg-hover transition-colors",
|
|
61
|
+
children: "Download PDF"
|
|
62
|
+
})]
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
}),
|
|
66
|
+
/* @__PURE__ */ r("div", {
|
|
67
|
+
className: "flex items-center justify-center p-3 bg-bg-surface border-t border-border-default text-xs text-text-secondary",
|
|
68
|
+
children: /* @__PURE__ */ i("span", { children: [
|
|
69
|
+
"PDF Document · ",
|
|
70
|
+
(a.size / 1024 / 1024).toFixed(2),
|
|
71
|
+
" MB"
|
|
72
|
+
] })
|
|
73
|
+
})
|
|
74
|
+
]
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
export { a as PDFViewer };
|
|
79
|
+
|
|
80
|
+
//# sourceMappingURL=PDFViewer.js.map
|