@burdenoff/microfe-files 2026.1014.11 → 2026.1016.1
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 +37 -0
- package/dist/config/index.js.map +1 -1
- package/dist/files/FilesRoot.js +17 -10
- package/dist/files/FilesRoot.js.map +1 -1
- package/dist/files/FilesRoutes.d.ts +1 -1
- package/dist/files/FilesRoutes.js.map +1 -1
- package/dist/files/components/ActionMenu.js.map +1 -1
- package/dist/files/components/ConfirmDialog.d.ts +1 -1
- package/dist/files/components/ConfirmDialog.js.map +1 -1
- package/dist/files/components/ContextMenu.d.ts +1 -1
- package/dist/files/components/ContextMenu.js.map +1 -1
- package/dist/files/components/CopyDialog.js.map +1 -1
- package/dist/files/components/EmptyState.d.ts +1 -1
- package/dist/files/components/EmptyState.js.map +1 -1
- package/dist/files/components/FileBrowser.js +2 -1
- package/dist/files/components/FileBrowser.js.map +1 -1
- package/dist/files/components/FileCard.d.ts.map +1 -1
- package/dist/files/components/FileCard.js +150 -142
- package/dist/files/components/FileCard.js.map +1 -1
- package/dist/files/components/FileInfoPanel.d.ts +1 -1
- package/dist/files/components/FileInfoPanel.d.ts.map +1 -1
- package/dist/files/components/FileInfoPanel.js +3 -7
- package/dist/files/components/FileInfoPanel.js.map +1 -1
- package/dist/files/components/FileListItem.d.ts.map +1 -1
- package/dist/files/components/FileListItem.js +1 -1
- package/dist/files/components/FileListItem.js.map +1 -1
- package/dist/files/components/FilePreviewModal.d.ts +1 -1
- package/dist/files/components/FilePreviewModal.d.ts.map +1 -1
- package/dist/files/components/FilePreviewModal.js +5 -0
- package/dist/files/components/FilePreviewModal.js.map +1 -1
- package/dist/files/components/FileVersionPanel.d.ts.map +1 -1
- package/dist/files/components/FileVersionPanel.js +122 -121
- package/dist/files/components/FileVersionPanel.js.map +1 -1
- package/dist/files/components/FolderCard.d.ts.map +1 -1
- package/dist/files/components/FolderCard.js +1 -1
- package/dist/files/components/FolderCard.js.map +1 -1
- package/dist/files/components/MoveDialog.js +2 -2
- package/dist/files/components/MoveDialog.js.map +1 -1
- package/dist/files/components/SearchBar.d.ts +1 -1
- package/dist/files/components/SearchBar.d.ts.map +1 -1
- package/dist/files/components/SearchBar.js +132 -128
- package/dist/files/components/SearchBar.js.map +1 -1
- package/dist/files/components/ShareDialog.d.ts +1 -1
- package/dist/files/components/ShareDialog.js.map +1 -1
- package/dist/files/components/StorageBanner.js.map +1 -1
- package/dist/files/components/TabBar.d.ts +1 -1
- package/dist/files/components/TabBar.js.map +1 -1
- package/dist/files/components/Toast.d.ts +1 -1
- package/dist/files/components/Toast.js.map +1 -1
- package/dist/files/components/UploadQueue.d.ts +1 -1
- package/dist/files/components/UploadQueue.js +1 -1
- package/dist/files/components/UploadQueue.js.map +1 -1
- package/dist/files/components/contextMenuItems.d.ts +4 -4
- package/dist/files/components/contextMenuItems.js.map +1 -1
- package/dist/files/components/viewers/AudioPlayer.d.ts +1 -1
- package/dist/files/components/viewers/AudioPlayer.js.map +1 -1
- package/dist/files/components/viewers/CodeViewer.d.ts +1 -1
- package/dist/files/components/viewers/CodeViewer.js.map +1 -1
- package/dist/files/components/viewers/ImageViewer.d.ts +1 -1
- package/dist/files/components/viewers/ImageViewer.js.map +1 -1
- package/dist/files/components/viewers/PDFViewer.d.ts +1 -1
- package/dist/files/components/viewers/PDFViewer.js.map +1 -1
- package/dist/files/components/viewers/TextViewer.d.ts +1 -1
- package/dist/files/components/viewers/TextViewer.js.map +1 -1
- package/dist/files/components/viewers/VideoPlayer.d.ts +1 -1
- package/dist/files/components/viewers/VideoPlayer.js.map +1 -1
- package/dist/files/graphql-types.d.ts +2 -17
- package/dist/files/graphql-types.d.ts.map +1 -1
- package/dist/files/hooks/useBatchOperations.d.ts +6 -1
- package/dist/files/hooks/useBatchOperations.d.ts.map +1 -1
- package/dist/files/hooks/useBatchOperations.js +8 -7
- package/dist/files/hooks/useBatchOperations.js.map +1 -1
- package/dist/files/hooks/useBinItems.d.ts.map +1 -1
- package/dist/files/hooks/useBinItems.js +14 -12
- package/dist/files/hooks/useBinItems.js.map +1 -1
- package/dist/files/hooks/useBrowsePage.d.ts +131 -8
- package/dist/files/hooks/useBrowsePage.d.ts.map +1 -1
- package/dist/files/hooks/useBrowsePage.js +23 -22
- package/dist/files/hooks/useBrowsePage.js.map +1 -1
- package/dist/files/hooks/useCopyFile.d.ts +22 -1
- package/dist/files/hooks/useCopyFile.d.ts.map +1 -1
- package/dist/files/hooks/useCopyFile.js +9 -8
- package/dist/files/hooks/useCopyFile.js.map +1 -1
- package/dist/files/hooks/useCreateFolder.d.ts +23 -1
- package/dist/files/hooks/useCreateFolder.d.ts.map +1 -1
- package/dist/files/hooks/useCreateFolder.js +16 -9
- package/dist/files/hooks/useCreateFolder.js.map +1 -1
- package/dist/files/hooks/useCreateFolderShare.d.ts +20 -1
- package/dist/files/hooks/useCreateFolderShare.d.ts.map +1 -1
- package/dist/files/hooks/useCreateFolderShare.js +22 -7
- package/dist/files/hooks/useCreateFolderShare.js.map +1 -1
- package/dist/files/hooks/useCreateShare.d.ts +19 -1
- package/dist/files/hooks/useCreateShare.d.ts.map +1 -1
- package/dist/files/hooks/useCreateShare.js +22 -7
- package/dist/files/hooks/useCreateShare.js.map +1 -1
- package/dist/files/hooks/useDeleteFile.d.ts +1 -1
- package/dist/files/hooks/useDeleteFile.d.ts.map +1 -1
- package/dist/files/hooks/useDeleteFile.js +8 -7
- package/dist/files/hooks/useDeleteFile.js.map +1 -1
- package/dist/files/hooks/useDeleteFolder.d.ts +1 -1
- package/dist/files/hooks/useDeleteFolder.d.ts.map +1 -1
- package/dist/files/hooks/useDeleteFolder.js +9 -8
- package/dist/files/hooks/useDeleteFolder.js.map +1 -1
- package/dist/files/hooks/useDragDrop.js.map +1 -1
- package/dist/files/hooks/useFileVersions.d.ts +36 -9
- package/dist/files/hooks/useFileVersions.d.ts.map +1 -1
- package/dist/files/hooks/useFileVersions.js +14 -13
- package/dist/files/hooks/useFileVersions.js.map +1 -1
- package/dist/files/hooks/useFoldersQuery.d.ts +8 -4
- package/dist/files/hooks/useFoldersQuery.d.ts.map +1 -1
- package/dist/files/hooks/useFoldersQuery.js +7 -6
- package/dist/files/hooks/useFoldersQuery.js.map +1 -1
- package/dist/files/hooks/useKeyboardNavigation.js +7 -8
- package/dist/files/hooks/useKeyboardNavigation.js.map +1 -1
- package/dist/files/hooks/useMoveFile.d.ts +22 -1
- package/dist/files/hooks/useMoveFile.d.ts.map +1 -1
- package/dist/files/hooks/useMoveFile.js +9 -8
- package/dist/files/hooks/useMoveFile.js.map +1 -1
- package/dist/files/hooks/useMoveFolder.d.ts +22 -1
- package/dist/files/hooks/useMoveFolder.d.ts.map +1 -1
- package/dist/files/hooks/useMoveFolder.js +9 -8
- package/dist/files/hooks/useMoveFolder.js.map +1 -1
- package/dist/files/hooks/usePermanentlyDeleteFile.d.ts +1 -1
- package/dist/files/hooks/usePermanentlyDeleteFile.d.ts.map +1 -1
- package/dist/files/hooks/usePermanentlyDeleteFile.js +8 -7
- package/dist/files/hooks/usePermanentlyDeleteFile.js.map +1 -1
- package/dist/files/hooks/usePermanentlyDeleteFolder.d.ts +1 -1
- package/dist/files/hooks/usePermanentlyDeleteFolder.d.ts.map +1 -1
- package/dist/files/hooks/usePermanentlyDeleteFolder.js +8 -7
- package/dist/files/hooks/usePermanentlyDeleteFolder.js.map +1 -1
- package/dist/files/hooks/useRecentFiles.d.ts.map +1 -1
- package/dist/files/hooks/useRecentFiles.js +13 -11
- package/dist/files/hooks/useRecentFiles.js.map +1 -1
- package/dist/files/hooks/useRenameFile.d.ts +22 -1
- package/dist/files/hooks/useRenameFile.d.ts.map +1 -1
- package/dist/files/hooks/useRenameFile.js +9 -8
- package/dist/files/hooks/useRenameFile.js.map +1 -1
- package/dist/files/hooks/useRenameFolder.d.ts +22 -1
- package/dist/files/hooks/useRenameFolder.d.ts.map +1 -1
- package/dist/files/hooks/useRenameFolder.js +9 -8
- package/dist/files/hooks/useRenameFolder.js.map +1 -1
- package/dist/files/hooks/useRestoreFile.d.ts +22 -1
- package/dist/files/hooks/useRestoreFile.d.ts.map +1 -1
- package/dist/files/hooks/useRestoreFile.js +8 -7
- package/dist/files/hooks/useRestoreFile.js.map +1 -1
- package/dist/files/hooks/useRestoreFolder.d.ts +22 -1
- package/dist/files/hooks/useRestoreFolder.d.ts.map +1 -1
- package/dist/files/hooks/useRestoreFolder.js +8 -7
- package/dist/files/hooks/useRestoreFolder.js.map +1 -1
- package/dist/files/hooks/useSearch.d.ts +2 -3
- package/dist/files/hooks/useSearch.d.ts.map +1 -1
- package/dist/files/hooks/useSearch.js +14 -12
- package/dist/files/hooks/useSearch.js.map +1 -1
- package/dist/files/hooks/useStarredItems.d.ts +2 -3
- package/dist/files/hooks/useStarredItems.d.ts.map +1 -1
- package/dist/files/hooks/useStarredItems.js +12 -10
- package/dist/files/hooks/useStarredItems.js.map +1 -1
- package/dist/files/hooks/useStorageQuota.d.ts.map +1 -1
- package/dist/files/hooks/useStorageQuota.js +17 -16
- package/dist/files/hooks/useStorageQuota.js.map +1 -1
- package/dist/files/hooks/useToast.js.map +1 -1
- package/dist/files/hooks/useToggleStar.d.ts +43 -1
- package/dist/files/hooks/useToggleStar.d.ts.map +1 -1
- package/dist/files/hooks/useToggleStar.js +9 -8
- package/dist/files/hooks/useToggleStar.js.map +1 -1
- package/dist/files/hooks/useUploadFile.d.ts +23 -1
- package/dist/files/hooks/useUploadFile.d.ts.map +1 -1
- package/dist/files/hooks/useUploadFile.js +28 -27
- package/dist/files/hooks/useUploadFile.js.map +1 -1
- package/dist/files/hooks/useUploadQueueState.d.ts +32 -0
- package/dist/files/hooks/useUploadQueueState.d.ts.map +1 -0
- package/dist/files/hooks/useUploadQueueState.js +61 -0
- package/dist/files/hooks/useUploadQueueState.js.map +1 -0
- package/dist/files/index.js +4 -3
- package/dist/files/pages/BrowserPage.d.ts +1 -1
- package/dist/files/pages/BrowserPage.d.ts.map +1 -1
- package/dist/files/pages/BrowserPage.js +383 -387
- package/dist/files/pages/BrowserPage.js.map +1 -1
- package/dist/files/pages/ShareAccessPage.d.ts +1 -1
- package/dist/files/pages/ShareAccessPage.js.map +1 -1
- package/dist/files/providers/FilesProvider.js.map +1 -1
- package/dist/files/store/filesStore.js.map +1 -1
- package/dist/files/types.d.ts.map +1 -1
- package/dist/files/utils/events.js.map +1 -1
- package/dist/files/utils/fileViewModel.d.ts +7 -0
- package/dist/files/utils/fileViewModel.d.ts.map +1 -0
- package/dist/files/utils/fileViewModel.js +34 -0
- package/dist/files/utils/fileViewModel.js.map +1 -0
- package/dist/files/utils/i18n.js.map +1 -1
- package/dist/files/utils/index.js +19 -19
- package/dist/files/utils/index.js.map +1 -1
- package/dist/files/utils/quotaUtils.js +1 -2
- package/dist/files/utils/thumbnail.js +19 -23
- package/dist/files/utils/thumbnail.js.map +1 -1
- package/dist/files/utils/uploadDigest.js +1 -1
- package/dist/files/utils/uploadDigest.js.map +1 -1
- package/dist/generated/global-operations.d.ts +4 -1
- package/dist/generated/global-operations.d.ts.map +1 -1
- package/dist/generated/global-types.d.ts +16 -21
- package/dist/generated/global-types.d.ts.map +1 -1
- package/dist/generated/wspace-operations.d.ts +503 -1784
- package/dist/generated/wspace-operations.d.ts.map +1 -1
- package/dist/generated/wspace-operations.js +15278 -1110
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.d.ts +90013 -24889
- package/dist/generated/wspace-types.d.ts.map +1 -1
- package/dist/generated/wspace-types.js +16 -0
- package/dist/generated/wspace-types.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/shared/hooks/useTr.js.map +1 -1
- package/dist/translations/en.js.map +1 -1
- package/dist/utils/nativeBridge.js +1 -2
- package/package.json +24 -22
- package/dist/files.d.ts +0 -2
|
@@ -1 +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\";\nimport { useTr } from \"../../../shared/hooks/useTr\";\n\ninterface ImageViewerProps {\n file: FileItem;\n url: string;\n}\n\nexport function ImageViewer({ file, url }: ImageViewerProps) {\n const tr = useTr();\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(\n tr(\"files.preview.image.loadError\", \"Failed to load image from URL\"),\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-center gap-2 p-4 bg-bg-surface border-b border-border-default\">\n <button\n type=\"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={tr(\"files.preview.image.zoomOut\", \"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 type=\"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={tr(\"files.preview.image.zoomIn\", \"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 type=\"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={tr(\"files.preview.image.fitToScreen\", \"Fit to screen\")}\n >\n <Minimize2 className=\"size-5\" />\n </button>\n\n <button\n type=\"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={tr(\"files.preview.image.rotate\", \"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 {tr(\"files.preview.image.failedToLoad\", \"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 {tr(\"files.preview.image.openInNewTab\", \"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":";;;;;AAiBA,
|
|
1
|
+
{"version":3,"file":"ImageViewer.js","names":["ImageViewer","tr","useTr","zoom","setZoom","useState","rotation","setRotation","position","setPosition","isDragging","setIsDragging","dragStart","setDragStart","imageError","setImageError","imageRef","useRef","imageDimensions","setImageDimensions","handleZoomIn","prev","handleZoomOut","handleResetZoom","handleRotate","handleMouseDown","handleMouseMove","handleMouseUp","ZoomOut","ZoomIn","Minimize2","RotateCw","url","file","AlertCircle"],"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\";\nimport { useTr } from \"../../../shared/hooks/useTr\";\n\ninterface ImageViewerProps {\n file: FileItem;\n url: string;\n}\n\nexport function ImageViewer({ file, url }: ImageViewerProps) {\n const tr = useTr();\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(\n tr(\"files.preview.image.loadError\", \"Failed to load image from URL\"),\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-center gap-2 p-4 bg-bg-surface border-b border-border-default\">\n <button\n type=\"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={tr(\"files.preview.image.zoomOut\", \"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 type=\"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={tr(\"files.preview.image.zoomIn\", \"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 type=\"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={tr(\"files.preview.image.fitToScreen\", \"Fit to screen\")}\n >\n <Minimize2 className=\"size-5\" />\n </button>\n\n <button\n type=\"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={tr(\"files.preview.image.rotate\", \"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 {tr(\"files.preview.image.failedToLoad\", \"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 {tr(\"files.preview.image.openInNewTab\", \"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":"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"}
|
|
@@ -10,6 +10,6 @@ interface PDFViewerProps {
|
|
|
10
10
|
* For a full-featured PDF viewer with more controls, install react-pdf:
|
|
11
11
|
* bun add react-pdf pdfjs-dist
|
|
12
12
|
*/
|
|
13
|
-
export declare function PDFViewer({ file, url }: PDFViewerProps): import(
|
|
13
|
+
export declare function PDFViewer({ file, url }: PDFViewerProps): import('react').JSX.Element;
|
|
14
14
|
export {};
|
|
15
15
|
//# sourceMappingURL=PDFViewer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PDFViewer.js","names":[],"sources":["../../../../src/files/components/viewers/PDFViewer.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { ZoomIn, ZoomOut } from \"lucide-react\";\nimport type { FileItem } from \"../../types\";\nimport { useTr } from \"../../../shared/hooks/useTr\";\n\ninterface PDFViewerProps {\n file: FileItem;\n url: string;\n}\n\n/**\n * PDFViewer - Displays PDF files\n *\n * Note: This uses <object> tag for better browser PDF compatibility.\n * For a full-featured PDF viewer with more controls, install react-pdf:\n * bun add react-pdf pdfjs-dist\n */\nexport function PDFViewer({ file, url }: PDFViewerProps) {\n const tr = useTr();\n const [scale, setScale] = useState(100);\n\n const handleZoomIn = () => setScale((prev) => Math.min(prev + 25, 200));\n const handleZoomOut = () => setScale((prev) => Math.max(prev - 25, 50));\n\n // Create zoom-adjusted URL\n const pdfUrl = `${url}#view=FitH&zoom=${scale}`;\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-4 bg-bg-surface border-b border-border-default\">\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleZoomOut}\n disabled={scale <= 50}\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={tr(\"files.preview.pdf.zoomOut\", \"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 {scale}%\n </span>\n\n <button\n type=\"button\"\n onClick={handleZoomIn}\n disabled={scale >= 200}\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={tr(\"files.preview.pdf.zoomIn\", \"Zoom in\")}\n >\n <ZoomIn className=\"size-5\" />\n </button>\n </div>\n\n <span className=\"text-sm text-text-secondary\">{file.name}</span>\n </div>\n\n {/* PDF Object - Using object tag instead of iframe for better compatibility */}\n <div className=\"flex-1 overflow-hidden\">\n <object\n data={pdfUrl}\n type=\"application/pdf\"\n className=\"w-full h-full\"\n title={file.name}\n >\n {/* Fallback content if PDF cannot be displayed */}\n <div className=\"flex flex-col items-center justify-center h-full gap-4 p-8\">\n <div className=\"text-text-secondary text-center\">\n <p className=\"font-text-lg font-weight-medium mb-2\">\n {tr(\n \"files.preview.pdf.unableToDisplay\",\n \"Unable to display PDF\",\n )}\n </p>\n <p className=\"font-text-sm\">\n {tr(\n \"files.preview.pdf.browserUnsupported\",\n \"Your browser may not support embedded PDF viewing.\",\n )}\n </p>\n </div>\n <a\n href={url}\n download={file.name}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-btn hover:bg-action-primary-bg-hover transition-colors\"\n >\n {tr(\"files.preview.pdf.download\", \"Download PDF\")}\n </a>\n </div>\n </object>\n </div>\n\n {/* Info Footer */}\n <div className=\"flex items-center justify-center p-3 bg-bg-surface border-t border-border-default text-xs text-text-secondary\">\n <span>\n {tr(\"files.preview.pdf.documentLabel\", \"PDF Document\")} ·{\" \"}\n {(file.size / 1024 / 1024).toFixed(2)} MB\n </span>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAiBA,
|
|
1
|
+
{"version":3,"file":"PDFViewer.js","names":["PDFViewer","tr","useTr","scale","setScale","useState","handleZoomIn","prev","handleZoomOut","pdfUrl","url","ZoomOut","ZoomIn","file"],"sources":["../../../../src/files/components/viewers/PDFViewer.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { ZoomIn, ZoomOut } from \"lucide-react\";\nimport type { FileItem } from \"../../types\";\nimport { useTr } from \"../../../shared/hooks/useTr\";\n\ninterface PDFViewerProps {\n file: FileItem;\n url: string;\n}\n\n/**\n * PDFViewer - Displays PDF files\n *\n * Note: This uses <object> tag for better browser PDF compatibility.\n * For a full-featured PDF viewer with more controls, install react-pdf:\n * bun add react-pdf pdfjs-dist\n */\nexport function PDFViewer({ file, url }: PDFViewerProps) {\n const tr = useTr();\n const [scale, setScale] = useState(100);\n\n const handleZoomIn = () => setScale((prev) => Math.min(prev + 25, 200));\n const handleZoomOut = () => setScale((prev) => Math.max(prev - 25, 50));\n\n // Create zoom-adjusted URL\n const pdfUrl = `${url}#view=FitH&zoom=${scale}`;\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-4 bg-bg-surface border-b border-border-default\">\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleZoomOut}\n disabled={scale <= 50}\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={tr(\"files.preview.pdf.zoomOut\", \"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 {scale}%\n </span>\n\n <button\n type=\"button\"\n onClick={handleZoomIn}\n disabled={scale >= 200}\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={tr(\"files.preview.pdf.zoomIn\", \"Zoom in\")}\n >\n <ZoomIn className=\"size-5\" />\n </button>\n </div>\n\n <span className=\"text-sm text-text-secondary\">{file.name}</span>\n </div>\n\n {/* PDF Object - Using object tag instead of iframe for better compatibility */}\n <div className=\"flex-1 overflow-hidden\">\n <object\n data={pdfUrl}\n type=\"application/pdf\"\n className=\"w-full h-full\"\n title={file.name}\n >\n {/* Fallback content if PDF cannot be displayed */}\n <div className=\"flex flex-col items-center justify-center h-full gap-4 p-8\">\n <div className=\"text-text-secondary text-center\">\n <p className=\"font-text-lg font-weight-medium mb-2\">\n {tr(\n \"files.preview.pdf.unableToDisplay\",\n \"Unable to display PDF\",\n )}\n </p>\n <p className=\"font-text-sm\">\n {tr(\n \"files.preview.pdf.browserUnsupported\",\n \"Your browser may not support embedded PDF viewing.\",\n )}\n </p>\n </div>\n <a\n href={url}\n download={file.name}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-btn hover:bg-action-primary-bg-hover transition-colors\"\n >\n {tr(\"files.preview.pdf.download\", \"Download PDF\")}\n </a>\n </div>\n </object>\n </div>\n\n {/* Info Footer */}\n <div className=\"flex items-center justify-center p-3 bg-bg-surface border-t border-border-default text-xs text-text-secondary\">\n <span>\n {tr(\"files.preview.pdf.documentLabel\", \"PDF Document\")} ·{\" \"}\n {(file.size / 1024 / 1024).toFixed(2)} MB\n </span>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAiBA,SAAgBA,EAAU,EAAE,SAAM,UAAuB;CACvD,IAAMC,IAAKC,EAAM,GACX,CAACC,GAAOC,KAAYC,EAAS,GAAG,GAEhCC,UAAqBF,GAAU,MAAS,KAAK,IAAIG,IAAO,IAAI,GAAG,CAAC,GAChEC,UAAsBJ,GAAU,MAAS,KAAK,IAAIG,IAAO,IAAI,EAAE,CAAC,GAGhEE,IAAS,GAAGC,EAAI,kBAAkBP;CAExC,OACE,kBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GAEE,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACE,kBAAC,UAAD;OACE,MAAK;OACL,SAASK;OACT,UAAUL,KAAS;OACnB,WAAU;OACV,OAAOF,EAAG,6BAA6B,UAAU;OAEjD,UAAA,kBAACU,GAAD,EAAS,WAAU,SAAU,CAAA;MACvB,CAAA;MAER,kBAAC,QAAD;OAAM,WAAU;OAAhB,UAAA,CACGR,GAAM,GACH;;MAEN,kBAAC,UAAD;OACE,MAAK;OACL,SAASG;OACT,UAAUH,KAAS;OACnB,WAAU;OACV,OAAOF,EAAG,4BAA4B,SAAS;OAE/C,UAAA,kBAACW,GAAD,EAAQ,WAAU,SAAU,CAAA;MACtB,CAAA;KACL;IAEL,CAAA,GAAA,kBAAC,QAAD;KAAM,WAAU;KAA+B,UAAAC,EAAK;IAAW,CAAA,CAC5D;;GAGL,kBAAC,OAAD;IAAK,WAAU;IACb,UAAA,kBAAC,UAAD;KACE,MAAMJ;KACN,MAAK;KACL,WAAU;KACV,OAAOI,EAAK;KAGZ,UAAA,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;QACV,UAAAZ,EACC,qCACA,uBACF;OACC,CAAA,GACH,kBAAC,KAAD;QAAG,WAAU;QACV,UAAAA,EACC,wCACA,oDACF;OACC,CAAA,CACA;MACL,CAAA,GAAA,kBAAC,KAAD;OACE,MAAMS;OACN,UAAUG,EAAK;OACf,WAAU;OAET,UAAAZ,EAAG,8BAA8B,cAAc;MAC/C,CAAA,CACA;;IACC,CAAA;GACL,CAAA;GAGL,kBAAC,OAAD;IAAK,WAAU;IACb,UAAA,kBAAC,QAAD,EAAA,UAAA;KACGA,EAAG,mCAAmC,cAAc;KAAE;KAAG;MACxDY,EAAK,OAAO,OAAO,KAAA,CAAM,QAAQ,CAAC;KAAE;IAClC,EAAA,CAAA;GACH,CAAA;EACF;;AAET"}
|
|
@@ -3,6 +3,6 @@ interface TextViewerProps {
|
|
|
3
3
|
file: FileItem;
|
|
4
4
|
url: string;
|
|
5
5
|
}
|
|
6
|
-
export declare function TextViewer({ file, url }: TextViewerProps): import(
|
|
6
|
+
export declare function TextViewer({ file, url }: TextViewerProps): import('react').JSX.Element;
|
|
7
7
|
export {};
|
|
8
8
|
//# sourceMappingURL=TextViewer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextViewer.js","names":[],"sources":["../../../../src/files/components/viewers/TextViewer.tsx"],"sourcesContent":["import { useState, useEffect, useMemo } from \"react\";\nimport { Copy, Check, WrapText, Search } from \"lucide-react\";\nimport type { FileItem } from \"../../types\";\nimport { useTr } from \"../../../shared/hooks/useTr\";\n\ninterface TextViewerProps {\n file: FileItem;\n url: string;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nexport function TextViewer({ file, url }: TextViewerProps) {\n const tr = useTr();\n const [content, setContent] = useState(\"\");\n const [loading, setLoading] = useState(true);\n const [wordWrap, setWordWrap] = useState(true);\n const [searchTerm, setSearchTerm] = useState(\"\");\n const [showSearch, setShowSearch] = useState(false);\n const [copied, setCopied] = useState(false);\n\n useEffect(() => {\n fetch(url)\n .then((res) => res.text())\n .then((text) => {\n setContent(text);\n setLoading(false);\n })\n .catch(() => {\n setLoading(false);\n });\n }, [url]);\n\n const handleCopy = () => {\n navigator.clipboard.writeText(content);\n setCopied(true);\n };\n\n // Cleanup timeout on unmount to prevent React state update warning\n useEffect(() => {\n if (copied) {\n const timer = setTimeout(() => setCopied(false), 2000);\n return () => clearTimeout(timer);\n }\n return undefined;\n }, [copied]);\n\n // Highlight search matches\n const highlightedLines = useMemo(() => {\n const lines = content.split(\"\\n\");\n\n if (!searchTerm.trim()) {\n return lines.map((line) => [{ text: line, isMatch: false }]);\n }\n\n const matcher = new RegExp(`(${escapeRegExp(searchTerm)})`, \"gi\");\n return lines.map((line) =>\n line.split(matcher).map((part) => ({\n text: part,\n isMatch: part.toLowerCase() === searchTerm.toLowerCase(),\n })),\n );\n }, [content, searchTerm]);\n\n const matchCount = useMemo(() => {\n if (!searchTerm.trim()) return 0;\n const regex = new RegExp(searchTerm, \"gi\");\n return (content.match(regex) || []).length;\n }, [content, searchTerm]);\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\">\n {tr(\"files.preview.text.loading\", \"Loading text...\")}\n </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=\"text-sm text-text-secondary\">{file.name}</span>\n </div>\n\n <div className=\"flex items-center gap-2\">\n {showSearch && (\n <div className=\"flex items-center gap-2 px-2 py-1 border border-border-default rounded\">\n <Search className=\"size-4 text-text-secondary\" />\n <input\n type=\"text\"\n value={searchTerm}\n onChange={(e) => setSearchTerm(e.target.value)}\n placeholder={tr(\n \"files.preview.text.searchPlaceholder\",\n \"Search...\",\n )}\n aria-label={tr(\"files.preview.text.searchAria\", \"Search text\")}\n className=\"w-40 bg-transparent text-sm text-text-primary placeholder:text-text-tertiary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n />\n {matchCount > 0 && (\n <span className=\"text-xs text-text-secondary\">\n {matchCount}{\" \"}\n {matchCount > 1\n ? tr(\"files.preview.text.matches\", \"matches\")\n : tr(\"files.preview.text.match\", \"match\")}\n </span>\n )}\n </div>\n )}\n\n <button\n type=\"button\"\n onClick={() => setShowSearch(!showSearch)}\n className={`p-2 rounded transition-colors duration-200 ${\n showSearch\n ? \"text-text-link bg-bg-accent\"\n : \"text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover\"\n }`}\n title={tr(\"files.preview.text.search\", \"Search\")}\n aria-label={tr(\n \"files.preview.text.searchWithinFile\",\n \"Search within text file\",\n )}\n >\n <Search className=\"size-4\" />\n </button>\n\n <button\n type=\"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={\n wordWrap\n ? tr(\"files.preview.text.disableWordWrap\", \"Disable word wrap\")\n : tr(\"files.preview.text.enableWordWrap\", \"Enable word wrap\")\n }\n aria-label={\n wordWrap\n ? tr(\"files.preview.text.disableWordWrap\", \"Disable word wrap\")\n : tr(\"files.preview.text.enableWordWrap\", \"Enable word wrap\")\n }\n >\n <WrapText className=\"size-4\" />\n </button>\n\n <button\n type=\"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={tr(\"files.preview.text.copyText\", \"Copy text\")}\n aria-label={tr(\n \"files.preview.text.copyTextContent\",\n \"Copy text content\",\n )}\n >\n {copied ? (\n <>\n <Check className=\"size-4\" />\n {tr(\"files.preview.text.copied\", \"Copied!\")}\n </>\n ) : (\n <>\n <Copy className=\"size-4\" />\n {tr(\"files.preview.text.copy\", \"Copy\")}\n </>\n )}\n </button>\n </div>\n </div>\n\n {/* Text Content */}\n <div className=\"flex-1 overflow-auto\">\n <pre\n className={`p-4 text-sm font-mono leading-relaxed text-text-primary ${\n wordWrap ? \"whitespace-pre-wrap\" : \"whitespace-pre\"\n }`}\n >\n {highlightedLines.map((segments, lineIndex) => (\n <div key={lineIndex}>\n {segments.length === 0\n ? \" \"\n : segments.map((segment, partIndex) =>\n segment.isMatch ? (\n <mark\n key={`${lineIndex}-${partIndex}`}\n className=\"bg-status-warning-bg text-text-primary\"\n >\n {segment.text}\n </mark>\n ) : (\n <span key={`${lineIndex}-${partIndex}`}>\n {segment.text || \" \"}\n </span>\n ),\n )}\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>\n {content.split(\"\\n\").length} {tr(\"files.preview.text.lines\", \"lines\")}\n </span>\n <span>{(file.size / 1024).toFixed(2)} KB</span>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TextViewer.js","names":["_Fragment","escapeRegExp","value","TextViewer","tr","useTr","content","setContent","useState","loading","setLoading","wordWrap","setWordWrap","searchTerm","setSearchTerm","showSearch","setShowSearch","copied","setCopied","url","res","text","handleCopy","timer","highlightedLines","useMemo","lines","line","matcher","part","matchCount","regex","file","Search","WrapText","Fragment","Check","Copy","segments","segment","lineIndex","partIndex"],"sources":["../../../../src/files/components/viewers/TextViewer.tsx"],"sourcesContent":["import { useState, useEffect, useMemo } from \"react\";\nimport { Copy, Check, WrapText, Search } from \"lucide-react\";\nimport type { FileItem } from \"../../types\";\nimport { useTr } from \"../../../shared/hooks/useTr\";\n\ninterface TextViewerProps {\n file: FileItem;\n url: string;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nexport function TextViewer({ file, url }: TextViewerProps) {\n const tr = useTr();\n const [content, setContent] = useState(\"\");\n const [loading, setLoading] = useState(true);\n const [wordWrap, setWordWrap] = useState(true);\n const [searchTerm, setSearchTerm] = useState(\"\");\n const [showSearch, setShowSearch] = useState(false);\n const [copied, setCopied] = useState(false);\n\n useEffect(() => {\n fetch(url)\n .then((res) => res.text())\n .then((text) => {\n setContent(text);\n setLoading(false);\n })\n .catch(() => {\n setLoading(false);\n });\n }, [url]);\n\n const handleCopy = () => {\n navigator.clipboard.writeText(content);\n setCopied(true);\n };\n\n // Cleanup timeout on unmount to prevent React state update warning\n useEffect(() => {\n if (copied) {\n const timer = setTimeout(() => setCopied(false), 2000);\n return () => clearTimeout(timer);\n }\n return undefined;\n }, [copied]);\n\n // Highlight search matches\n const highlightedLines = useMemo(() => {\n const lines = content.split(\"\\n\");\n\n if (!searchTerm.trim()) {\n return lines.map((line) => [{ text: line, isMatch: false }]);\n }\n\n const matcher = new RegExp(`(${escapeRegExp(searchTerm)})`, \"gi\");\n return lines.map((line) =>\n line.split(matcher).map((part) => ({\n text: part,\n isMatch: part.toLowerCase() === searchTerm.toLowerCase(),\n })),\n );\n }, [content, searchTerm]);\n\n const matchCount = useMemo(() => {\n if (!searchTerm.trim()) return 0;\n const regex = new RegExp(searchTerm, \"gi\");\n return (content.match(regex) || []).length;\n }, [content, searchTerm]);\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\">\n {tr(\"files.preview.text.loading\", \"Loading text...\")}\n </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=\"text-sm text-text-secondary\">{file.name}</span>\n </div>\n\n <div className=\"flex items-center gap-2\">\n {showSearch && (\n <div className=\"flex items-center gap-2 px-2 py-1 border border-border-default rounded\">\n <Search className=\"size-4 text-text-secondary\" />\n <input\n type=\"text\"\n value={searchTerm}\n onChange={(e) => setSearchTerm(e.target.value)}\n placeholder={tr(\n \"files.preview.text.searchPlaceholder\",\n \"Search...\",\n )}\n aria-label={tr(\"files.preview.text.searchAria\", \"Search text\")}\n className=\"w-40 bg-transparent text-sm text-text-primary placeholder:text-text-tertiary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n />\n {matchCount > 0 && (\n <span className=\"text-xs text-text-secondary\">\n {matchCount}{\" \"}\n {matchCount > 1\n ? tr(\"files.preview.text.matches\", \"matches\")\n : tr(\"files.preview.text.match\", \"match\")}\n </span>\n )}\n </div>\n )}\n\n <button\n type=\"button\"\n onClick={() => setShowSearch(!showSearch)}\n className={`p-2 rounded transition-colors duration-200 ${\n showSearch\n ? \"text-text-link bg-bg-accent\"\n : \"text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover\"\n }`}\n title={tr(\"files.preview.text.search\", \"Search\")}\n aria-label={tr(\n \"files.preview.text.searchWithinFile\",\n \"Search within text file\",\n )}\n >\n <Search className=\"size-4\" />\n </button>\n\n <button\n type=\"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={\n wordWrap\n ? tr(\"files.preview.text.disableWordWrap\", \"Disable word wrap\")\n : tr(\"files.preview.text.enableWordWrap\", \"Enable word wrap\")\n }\n aria-label={\n wordWrap\n ? tr(\"files.preview.text.disableWordWrap\", \"Disable word wrap\")\n : tr(\"files.preview.text.enableWordWrap\", \"Enable word wrap\")\n }\n >\n <WrapText className=\"size-4\" />\n </button>\n\n <button\n type=\"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={tr(\"files.preview.text.copyText\", \"Copy text\")}\n aria-label={tr(\n \"files.preview.text.copyTextContent\",\n \"Copy text content\",\n )}\n >\n {copied ? (\n <>\n <Check className=\"size-4\" />\n {tr(\"files.preview.text.copied\", \"Copied!\")}\n </>\n ) : (\n <>\n <Copy className=\"size-4\" />\n {tr(\"files.preview.text.copy\", \"Copy\")}\n </>\n )}\n </button>\n </div>\n </div>\n\n {/* Text Content */}\n <div className=\"flex-1 overflow-auto\">\n <pre\n className={`p-4 text-sm font-mono leading-relaxed text-text-primary ${\n wordWrap ? \"whitespace-pre-wrap\" : \"whitespace-pre\"\n }`}\n >\n {highlightedLines.map((segments, lineIndex) => (\n <div key={lineIndex}>\n {segments.length === 0\n ? \" \"\n : segments.map((segment, partIndex) =>\n segment.isMatch ? (\n <mark\n key={`${lineIndex}-${partIndex}`}\n className=\"bg-status-warning-bg text-text-primary\"\n >\n {segment.text}\n </mark>\n ) : (\n <span key={`${lineIndex}-${partIndex}`}>\n {segment.text || \" \"}\n </span>\n ),\n )}\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>\n {content.split(\"\\n\").length} {tr(\"files.preview.text.lines\", \"lines\")}\n </span>\n <span>{(file.size / 1024).toFixed(2)} KB</span>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -3,6 +3,6 @@ interface VideoPlayerProps {
|
|
|
3
3
|
file: FileItem;
|
|
4
4
|
url: string;
|
|
5
5
|
}
|
|
6
|
-
export declare function VideoPlayer({ file, url }: VideoPlayerProps): import(
|
|
6
|
+
export declare function VideoPlayer({ file, url }: VideoPlayerProps): import('react').JSX.Element;
|
|
7
7
|
export {};
|
|
8
8
|
//# sourceMappingURL=VideoPlayer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoPlayer.js","names":[],"sources":["../../../../src/files/components/viewers/VideoPlayer.tsx"],"sourcesContent":["import { useState, useRef, useEffect } from \"react\";\nimport { Play, Pause, Volume2, VolumeX, Maximize } from \"lucide-react\";\nimport type { FileItem } from \"../../types\";\nimport { useTr } from \"../../../shared/hooks/useTr\";\n\ninterface VideoPlayerProps {\n file: FileItem;\n url: string;\n}\n\nexport function VideoPlayer({ file, url }: VideoPlayerProps) {\n const tr = useTr();\n const videoRef = useRef<HTMLVideoElement>(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 const [playbackRate, setPlaybackRate] = useState(1);\n\n useEffect(() => {\n const video = videoRef.current;\n if (!video) return;\n\n const handleTimeUpdate = () => setCurrentTime(video.currentTime);\n const handleLoadedMetadata = () => setDuration(video.duration);\n const handleEnded = () => setIsPlaying(false);\n\n video.addEventListener(\"timeupdate\", handleTimeUpdate);\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"ended\", handleEnded);\n\n return () => {\n video.removeEventListener(\"timeupdate\", handleTimeUpdate);\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"ended\", handleEnded);\n };\n }, []);\n\n const togglePlay = () => {\n if (videoRef.current) {\n if (isPlaying) {\n videoRef.current.pause();\n } else {\n videoRef.current.play();\n }\n setIsPlaying(!isPlaying);\n }\n };\n\n const handleSeek = (time: number) => {\n if (videoRef.current) {\n videoRef.current.currentTime = time;\n setCurrentTime(time);\n }\n };\n\n const handleVolumeChange = (newVolume: number) => {\n setVolume(newVolume);\n setIsMuted(newVolume === 0);\n if (videoRef.current) {\n videoRef.current.volume = newVolume;\n }\n };\n\n const toggleMute = () => {\n if (videoRef.current) {\n const newMuted = !isMuted;\n setIsMuted(newMuted);\n videoRef.current.muted = newMuted;\n }\n };\n\n const handlePlaybackRateChange = (rate: number) => {\n setPlaybackRate(rate);\n if (videoRef.current) {\n videoRef.current.playbackRate = rate;\n }\n };\n\n const handleFullscreen = () => {\n if (videoRef.current) {\n videoRef.current.requestFullscreen();\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 h-full flex-col bg-bg-canvas\">\n {/* Video */}\n <div className=\"flex-1 flex items-center justify-center\">\n <video\n ref={videoRef}\n src={url}\n aria-label={file.name}\n className=\"max-w-full max-h-full\"\n onClick={togglePlay}\n >\n <track kind=\"captions\" />\n </video>\n </div>\n\n {/* Controls */}\n <div className=\"bg-bg-surface border-t border-border-default p-4\">\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 aria-label={tr(\"files.preview.video.seek\", \"Seek\")}\n className=\"w-full h-1 bg-bg-sunken rounded-lg appearance-none cursor-pointer accent-action-primary-bg\"\n />\n <div className=\"flex justify-between mt-1 text-xs 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-between\">\n <div className=\"flex items-center gap-2\">\n {/* Play/Pause */}\n <button\n type=\"button\"\n onClick={togglePlay}\n className=\"p-2 text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200\"\n title={\n isPlaying\n ? tr(\"files.preview.video.pause\", \"Pause\")\n : tr(\"files.preview.video.play\", \"Play\")\n }\n aria-label={\n isPlaying\n ? tr(\"files.preview.video.pauseVideo\", \"Pause video\")\n : tr(\"files.preview.video.playVideo\", \"Play video\")\n }\n >\n {isPlaying ? (\n <Pause className=\"size-5\" />\n ) : (\n <Play className=\"size-5\" />\n )}\n </button>\n\n {/* Volume */}\n <div className=\"flex items-center gap-2\">\n <button\n type=\"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={\n isMuted\n ? tr(\"files.preview.video.unmute\", \"Unmute\")\n : tr(\"files.preview.video.mute\", \"Mute\")\n }\n aria-label={\n isMuted\n ? tr(\"files.preview.video.unmuteVideo\", \"Unmute video\")\n : tr(\"files.preview.video.muteVideo\", \"Mute video\")\n }\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 aria-label={tr(\"files.preview.video.volume\", \"Volume\")}\n className=\"w-20 h-1 bg-bg-sunken rounded-lg appearance-none cursor-pointer accent-action-primary-bg\"\n />\n </div>\n\n {/* Playback Speed */}\n <select\n aria-label={tr(\n \"files.preview.video.playbackRate\",\n \"Playback speed\",\n )}\n value={playbackRate}\n onChange={(e) => handlePlaybackRateChange(Number(e.target.value))}\n className=\"px-2 py-1 text-sm bg-bg-surface border border-border-default rounded text-text-primary scheme-normal dark:scheme-dark cursor-pointer [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n >\n <option value=\"0.5\">0.5x</option>\n <option value=\"0.75\">0.75x</option>\n <option value=\"1\">1x</option>\n <option value=\"1.25\">1.25x</option>\n <option value=\"1.5\">1.5x</option>\n <option value=\"2\">2x</option>\n </select>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-text-secondary\">{file.name}</span>\n <button\n type=\"button\"\n onClick={handleFullscreen}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200\"\n title={tr(\"files.preview.video.fullscreen\", \"Fullscreen\")}\n aria-label={tr(\n \"files.preview.video.openFullscreen\",\n \"Open fullscreen\",\n )}\n >\n <Maximize className=\"size-5\" />\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"VideoPlayer.js","names":["VideoPlayer","tr","useTr","videoRef","useRef","isPlaying","setIsPlaying","useState","currentTime","setCurrentTime","duration","setDuration","volume","setVolume","isMuted","setIsMuted","playbackRate","setPlaybackRate","video","handleTimeUpdate","handleLoadedMetadata","handleEnded","togglePlay","handleSeek","time","handleVolumeChange","newVolume","toggleMute","newMuted","handlePlaybackRateChange","rate","handleFullscreen","formatTime","seconds","url","file","jsx","Pause","Play","VolumeX","Volume2","Maximize"],"sources":["../../../../src/files/components/viewers/VideoPlayer.tsx"],"sourcesContent":["import { useState, useRef, useEffect } from \"react\";\nimport { Play, Pause, Volume2, VolumeX, Maximize } from \"lucide-react\";\nimport type { FileItem } from \"../../types\";\nimport { useTr } from \"../../../shared/hooks/useTr\";\n\ninterface VideoPlayerProps {\n file: FileItem;\n url: string;\n}\n\nexport function VideoPlayer({ file, url }: VideoPlayerProps) {\n const tr = useTr();\n const videoRef = useRef<HTMLVideoElement>(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 const [playbackRate, setPlaybackRate] = useState(1);\n\n useEffect(() => {\n const video = videoRef.current;\n if (!video) return;\n\n const handleTimeUpdate = () => setCurrentTime(video.currentTime);\n const handleLoadedMetadata = () => setDuration(video.duration);\n const handleEnded = () => setIsPlaying(false);\n\n video.addEventListener(\"timeupdate\", handleTimeUpdate);\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"ended\", handleEnded);\n\n return () => {\n video.removeEventListener(\"timeupdate\", handleTimeUpdate);\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"ended\", handleEnded);\n };\n }, []);\n\n const togglePlay = () => {\n if (videoRef.current) {\n if (isPlaying) {\n videoRef.current.pause();\n } else {\n videoRef.current.play();\n }\n setIsPlaying(!isPlaying);\n }\n };\n\n const handleSeek = (time: number) => {\n if (videoRef.current) {\n videoRef.current.currentTime = time;\n setCurrentTime(time);\n }\n };\n\n const handleVolumeChange = (newVolume: number) => {\n setVolume(newVolume);\n setIsMuted(newVolume === 0);\n if (videoRef.current) {\n videoRef.current.volume = newVolume;\n }\n };\n\n const toggleMute = () => {\n if (videoRef.current) {\n const newMuted = !isMuted;\n setIsMuted(newMuted);\n videoRef.current.muted = newMuted;\n }\n };\n\n const handlePlaybackRateChange = (rate: number) => {\n setPlaybackRate(rate);\n if (videoRef.current) {\n videoRef.current.playbackRate = rate;\n }\n };\n\n const handleFullscreen = () => {\n if (videoRef.current) {\n videoRef.current.requestFullscreen();\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 h-full flex-col bg-bg-canvas\">\n {/* Video */}\n <div className=\"flex-1 flex items-center justify-center\">\n <video\n ref={videoRef}\n src={url}\n aria-label={file.name}\n className=\"max-w-full max-h-full\"\n onClick={togglePlay}\n >\n <track kind=\"captions\" />\n </video>\n </div>\n\n {/* Controls */}\n <div className=\"bg-bg-surface border-t border-border-default p-4\">\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 aria-label={tr(\"files.preview.video.seek\", \"Seek\")}\n className=\"w-full h-1 bg-bg-sunken rounded-lg appearance-none cursor-pointer accent-action-primary-bg\"\n />\n <div className=\"flex justify-between mt-1 text-xs 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-between\">\n <div className=\"flex items-center gap-2\">\n {/* Play/Pause */}\n <button\n type=\"button\"\n onClick={togglePlay}\n className=\"p-2 text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200\"\n title={\n isPlaying\n ? tr(\"files.preview.video.pause\", \"Pause\")\n : tr(\"files.preview.video.play\", \"Play\")\n }\n aria-label={\n isPlaying\n ? tr(\"files.preview.video.pauseVideo\", \"Pause video\")\n : tr(\"files.preview.video.playVideo\", \"Play video\")\n }\n >\n {isPlaying ? (\n <Pause className=\"size-5\" />\n ) : (\n <Play className=\"size-5\" />\n )}\n </button>\n\n {/* Volume */}\n <div className=\"flex items-center gap-2\">\n <button\n type=\"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={\n isMuted\n ? tr(\"files.preview.video.unmute\", \"Unmute\")\n : tr(\"files.preview.video.mute\", \"Mute\")\n }\n aria-label={\n isMuted\n ? tr(\"files.preview.video.unmuteVideo\", \"Unmute video\")\n : tr(\"files.preview.video.muteVideo\", \"Mute video\")\n }\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 aria-label={tr(\"files.preview.video.volume\", \"Volume\")}\n className=\"w-20 h-1 bg-bg-sunken rounded-lg appearance-none cursor-pointer accent-action-primary-bg\"\n />\n </div>\n\n {/* Playback Speed */}\n <select\n aria-label={tr(\n \"files.preview.video.playbackRate\",\n \"Playback speed\",\n )}\n value={playbackRate}\n onChange={(e) => handlePlaybackRateChange(Number(e.target.value))}\n className=\"px-2 py-1 text-sm bg-bg-surface border border-border-default rounded text-text-primary scheme-normal dark:scheme-dark cursor-pointer [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n >\n <option value=\"0.5\">0.5x</option>\n <option value=\"0.75\">0.75x</option>\n <option value=\"1\">1x</option>\n <option value=\"1.25\">1.25x</option>\n <option value=\"1.5\">1.5x</option>\n <option value=\"2\">2x</option>\n </select>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-text-secondary\">{file.name}</span>\n <button\n type=\"button\"\n onClick={handleFullscreen}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200\"\n title={tr(\"files.preview.video.fullscreen\", \"Fullscreen\")}\n aria-label={tr(\n \"files.preview.video.openFullscreen\",\n \"Open fullscreen\",\n )}\n >\n <Maximize className=\"size-5\" />\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { FileFilterInput } from '../generated/wspace-types';
|
|
2
|
+
export type { FileFilterInput, FolderFilterInput, } from '../generated/wspace-types';
|
|
1
3
|
type FileStatus = "ACTIVE" | "ARCHIVED" | "DELETED";
|
|
2
4
|
type FileVisibility = "PUBLIC" | "PRIVATE" | "WORKSPACE";
|
|
3
5
|
type FolderStatus = "ACTIVE" | "ARCHIVED" | "DELETED";
|
|
@@ -47,26 +49,10 @@ export interface PaginationInput {
|
|
|
47
49
|
limit?: number;
|
|
48
50
|
cursor?: string;
|
|
49
51
|
}
|
|
50
|
-
export interface FileFilterInput {
|
|
51
|
-
workspaceId?: string;
|
|
52
|
-
folderId?: string | null;
|
|
53
|
-
mimeType?: string[];
|
|
54
|
-
extensions?: string[];
|
|
55
|
-
uploadedBy?: string[];
|
|
56
|
-
status?: FileStatus[];
|
|
57
|
-
visibility?: FileVisibility[];
|
|
58
|
-
search?: string;
|
|
59
|
-
}
|
|
60
52
|
export interface FileSortInput {
|
|
61
53
|
field: "name" | "size" | "createdAt" | "updatedAt";
|
|
62
54
|
direction: "asc" | "desc";
|
|
63
55
|
}
|
|
64
|
-
export interface FolderFilterInput {
|
|
65
|
-
workspaceId?: string;
|
|
66
|
-
parentFolderId?: string | null;
|
|
67
|
-
status?: FolderStatus[];
|
|
68
|
-
search?: string;
|
|
69
|
-
}
|
|
70
56
|
export interface FolderSortInput {
|
|
71
57
|
field: "name" | "createdAt" | "updatedAt";
|
|
72
58
|
direction: "asc" | "desc";
|
|
@@ -273,5 +259,4 @@ export interface MoveFilesInput {
|
|
|
273
259
|
fileIds: string[];
|
|
274
260
|
targetFolderId: string | null;
|
|
275
261
|
}
|
|
276
|
-
export {};
|
|
277
262
|
//# sourceMappingURL=graphql-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphql-types.d.ts","sourceRoot":"","sources":["../../src/files/graphql-types.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AACpD,KAAK,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;AACzD,KAAK,YAAY,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AACtD,KAAK,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;AACvD,KAAK,YAAY,
|
|
1
|
+
{"version":3,"file":"graphql-types.d.ts","sourceRoot":"","sources":["../../src/files/graphql-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export declare const useBulkDelete: () => {
|
|
2
|
-
mutateAsync: (ids: string[]) => Promise<
|
|
2
|
+
mutateAsync: (ids: string[]) => Promise<{
|
|
3
|
+
success: boolean;
|
|
4
|
+
successCount: number;
|
|
5
|
+
failedCount: number;
|
|
6
|
+
errors: Array<string> | null;
|
|
7
|
+
} | undefined>;
|
|
3
8
|
isPending: boolean;
|
|
4
9
|
error: import('@apollo/client').ErrorLike | undefined;
|
|
5
10
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBatchOperations.d.ts","sourceRoot":"","sources":["../../../src/files/hooks/useBatchOperations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useBatchOperations.d.ts","sourceRoot":"","sources":["../../../src/files/hooks/useBatchOperations.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,aAAa;uBASG,MAAM,EAAE;;;;;;;;CAUpC,CAAC"}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BulkDeleteFilesDocument as e } from "../../generated/wspace-operations.js";
|
|
2
|
+
import { useMutation as t } from "@apollo/client/react";
|
|
2
3
|
//#region src/files/hooks/useBatchOperations.ts
|
|
3
|
-
var
|
|
4
|
-
let [
|
|
4
|
+
var n = () => {
|
|
5
|
+
let [n, { loading: r, error: i }] = t(e, { refetchQueries: [
|
|
5
6
|
"GetFiles",
|
|
6
7
|
"GetFolders",
|
|
7
8
|
"GetBinFiles"
|
|
8
9
|
] });
|
|
9
10
|
return {
|
|
10
|
-
mutateAsync: async (e) => (await
|
|
11
|
-
isPending:
|
|
12
|
-
error:
|
|
11
|
+
mutateAsync: async (e) => (await n({ variables: { ids: e } })).data?.bulkDeleteFiles,
|
|
12
|
+
isPending: r,
|
|
13
|
+
error: i
|
|
13
14
|
};
|
|
14
15
|
};
|
|
15
16
|
//#endregion
|
|
16
|
-
export {
|
|
17
|
+
export { n as useBulkDelete };
|
|
17
18
|
|
|
18
19
|
//# sourceMappingURL=useBatchOperations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBatchOperations.js","names":[],"sources":["../../../src/files/hooks/useBatchOperations.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"useBatchOperations.js","names":["useBulkDelete","bulkDeleteFilesMutation","useMutation","BulkDeleteFilesDocument","loading"],"sources":["../../../src/files/hooks/useBatchOperations.ts"],"sourcesContent":["import { useMutation } from \"@apollo/client/react\";\nimport { BulkDeleteFilesDocument } from \"../../generated/wspace-operations\";\n\nexport const useBulkDelete = () => {\n const [bulkDeleteFilesMutation, { loading, error }] = useMutation(\n BulkDeleteFilesDocument,\n {\n refetchQueries: [\"GetFiles\", \"GetFolders\", \"GetBinFiles\"],\n },\n );\n\n return {\n mutateAsync: async (ids: string[]) => {\n const result = await bulkDeleteFilesMutation({\n variables: { ids },\n });\n\n return result.data?.bulkDeleteFiles;\n },\n isPending: loading,\n error,\n };\n};\n"],"mappings":";;;AAGA,IAAaA,UAAsB;CACjC,IAAM,CAACC,GAAyB,EAAE,YAAS,cAAWC,EACpDC,GACA,EACE,gBAAgB;EAAC;EAAY;EAAc;CAAa,EAC1D,CACF;CAEA,OAAO;EACL,aAAa,OAAO,OAKX,MAJcF,EAAwB,EAC3C,WAAW,EAAE,OAAI,EACnB,CAAC,EAAA,CAEa,MAAM;EAEtB,WAAWG;EACX;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBinItems.d.ts","sourceRoot":"","sources":["../../../src/files/hooks/useBinItems.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useBinItems.d.ts","sourceRoot":"","sources":["../../../src/files/hooks/useBinItems.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAErD,eAAO,MAAM,WAAW,GAAI,UAAU;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE;;;;WA+CpC,KAAK,GAAG,IAAI;;CAG/B,CAAC"}
|
|
@@ -1,27 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { fileViewModel as e, folderViewModel as t } from "../utils/fileViewModel.js";
|
|
2
|
+
import { GetFilesBinPageDocument as n } from "../../generated/wspace-operations.js";
|
|
3
|
+
import { useQuery as r } from "@apollo/client/react";
|
|
2
4
|
//#region src/files/hooks/useBinItems.ts
|
|
3
|
-
var
|
|
4
|
-
let
|
|
5
|
+
var i = (i) => {
|
|
6
|
+
let a = r(n, {
|
|
5
7
|
variables: {
|
|
6
8
|
filePagination: { limit: 100 },
|
|
7
9
|
folderPagination: { limit: 100 }
|
|
8
10
|
},
|
|
9
|
-
skip:
|
|
10
|
-
}),
|
|
11
|
-
return
|
|
11
|
+
skip: i?.skip
|
|
12
|
+
}), o = [...a.data?.getFiles?.files.map(e) || [], ...a.data?.getFolders?.folders.map(t) || []];
|
|
13
|
+
return o.sort((e, t) => {
|
|
12
14
|
let n = new Date(e.updatedAt || e.updatedAt || 0).getTime();
|
|
13
15
|
return new Date(t.updatedAt || t.updatedAt || 0).getTime() - n;
|
|
14
16
|
}), {
|
|
15
|
-
files:
|
|
16
|
-
folders:
|
|
17
|
-
isLoading:
|
|
18
|
-
error:
|
|
17
|
+
files: o.filter((e) => "mimeType" in e),
|
|
18
|
+
folders: o.filter((e) => !("mimeType" in e)),
|
|
19
|
+
isLoading: a.loading,
|
|
20
|
+
error: a.error ?? null,
|
|
19
21
|
refetch: async () => {
|
|
20
|
-
await
|
|
22
|
+
await a.refetch();
|
|
21
23
|
}
|
|
22
24
|
};
|
|
23
25
|
};
|
|
24
26
|
//#endregion
|
|
25
|
-
export {
|
|
27
|
+
export { i as useBinItems };
|
|
26
28
|
|
|
27
29
|
//# sourceMappingURL=useBinItems.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBinItems.js","names":[],"sources":["../../../src/files/hooks/useBinItems.ts"],"sourcesContent":["/**\n * Bin Items Hook\n *\n * Fetches soft-deleted files and folders (status: DELETED) for the trash/bin view.\n * Uses getFiles and getFolders with status filter.\n * Items are sorted by updatedAt (most recently deleted first).\n */\n\nimport {
|
|
1
|
+
{"version":3,"file":"useBinItems.js","names":["useBinItems","query","useQuery","GetFilesBinPageDocument","options","allItems","fileViewModel","folderViewModel","dateA","a","b","item"],"sources":["../../../src/files/hooks/useBinItems.ts"],"sourcesContent":["import { fileViewModel, folderViewModel } from \"../utils/fileViewModel\";\n/**\n * Bin Items Hook\n *\n * Fetches soft-deleted files and folders (status: DELETED) for the trash/bin view.\n * Uses getFiles and getFolders with status filter.\n * Items are sorted by updatedAt (most recently deleted first).\n */\n\nimport { useQuery } from \"@apollo/client/react\";\nimport { GetFilesBinPageDocument } from \"../../generated/wspace-operations\";\nimport type { FileItem, FolderItem } from \"../types\";\n\nexport const useBinItems = (options?: { skip?: boolean }) => {\n const query = useQuery(GetFilesBinPageDocument, {\n variables: {\n filePagination: { limit: 100 },\n folderPagination: { limit: 100 },\n },\n skip: options?.skip,\n });\n\n // Combine files and folders and sort by updatedAt (most recently deleted first)\n const allItems: (FileItem | FolderItem)[] = [\n ...(query.data?.getFiles?.files.map(fileViewModel) || []),\n ...(query.data?.getFolders?.folders.map(folderViewModel) || []),\n ];\n\n // Sort by updatedAt DESC to show recently deleted items first\n allItems.sort((a, b) => {\n const dateA = new Date(\n (a as FileItem).updatedAt || (a as FolderItem).updatedAt || 0,\n ).getTime();\n const dateB = new Date(\n (b as FileItem).updatedAt || (b as FolderItem).updatedAt || 0,\n ).getTime();\n return dateB - dateA;\n });\n\n // Split back into files and folders\n const files = allItems.filter((item): item is FileItem => \"mimeType\" in item);\n const folders = allItems.filter(\n (item): item is FolderItem => !(\"mimeType\" in item),\n );\n\n // Extract files and folders from query results\n const isLoading = query.loading;\n\n // Combine errors\n const error = query.error ?? null;\n\n // Refetch function that refreshes both queries\n const refetch = async () => {\n await query.refetch();\n };\n\n return {\n files,\n folders,\n isLoading,\n error: error as Error | null,\n refetch,\n };\n};\n"],"mappings":";;;;AAaA,IAAaA,KAAe,MAAiC;CAC3D,IAAMC,IAAQC,EAASC,GAAyB;EAC9C,WAAW;GACT,gBAAgB,EAAE,OAAO,IAAI;GAC7B,kBAAkB,EAAE,OAAO,IAAI;EACjC;EACA,MAAMC,GAAS;CACjB,CAAC,GAGKC,IAAsC,CAC1C,GAAIJ,EAAM,MAAM,UAAU,MAAM,IAAIK,CAAa,KAAK,CAAC,GACvD,GAAIL,EAAM,MAAM,YAAY,QAAQ,IAAIM,CAAe,KAAK,CAAC,CAC/D;CA8BA,OA3BAF,EAAS,MAAM,GAAG,MAAM;EACtB,IAAMG,IAAQ,IAAI,KACfC,EAAe,aAAcA,EAAiB,aAAa,CAC9D,CAAC,CAAC,QAAQ;EAIV,OAHc,IAAI,KACfC,EAAe,aAAcA,EAAiB,aAAa,CAC9D,CAAC,CAAC,QACK,IAAQF;CACjB,CAAC,GAmBM;EACL,OAjBYH,EAAS,QAAQ,MAA2B,cAAcM,CAiBtE;EACA,SAjBcN,EAAS,QACtB,MAA6B,EAAE,cAAcM,EAgB9C;EACA,WAbgBV,EAAM;EAcf,OAXKA,EAAM,SAAS;EAY3B,qBAT0B;GAC1B,MAAMA,EAAM,QAAQ;EACtB;CAQA;AACF"}
|
|
@@ -5,17 +5,140 @@ type BrowsePageOptions = {
|
|
|
5
5
|
};
|
|
6
6
|
export declare const useBrowsePage: ({ folderId, pageSize, skip, }: BrowsePageOptions) => {
|
|
7
7
|
data: {
|
|
8
|
-
filesList:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
filesList: {
|
|
9
|
+
total: number;
|
|
10
|
+
page: number;
|
|
11
|
+
limit: number;
|
|
12
|
+
hasMore: boolean;
|
|
13
|
+
files: Array<{
|
|
14
|
+
id: string;
|
|
15
|
+
workspaceId: string;
|
|
16
|
+
folderId: string | null;
|
|
17
|
+
status: import('../../generated/wspace-types').FileStatus;
|
|
18
|
+
canRead: boolean | null;
|
|
19
|
+
canUpdate: boolean | null;
|
|
20
|
+
canDelete: boolean | null;
|
|
21
|
+
name: string;
|
|
22
|
+
description: string | null;
|
|
23
|
+
mimeType: string;
|
|
24
|
+
extension: string;
|
|
25
|
+
size: string;
|
|
26
|
+
downloadUrl: string | null;
|
|
27
|
+
visibility: import('../../generated/wspace-types').FileVisibility;
|
|
28
|
+
starred: boolean;
|
|
29
|
+
downloadCount: number;
|
|
30
|
+
viewCount: number;
|
|
31
|
+
uploadedById: string;
|
|
32
|
+
createdAt: string;
|
|
33
|
+
updatedAt: string;
|
|
34
|
+
s3Key: string;
|
|
35
|
+
}>;
|
|
36
|
+
} | {
|
|
37
|
+
total: number;
|
|
38
|
+
page: number;
|
|
39
|
+
limit: number;
|
|
40
|
+
hasMore: boolean;
|
|
41
|
+
files: Array<{
|
|
42
|
+
id: string;
|
|
43
|
+
workspaceId: string;
|
|
44
|
+
folderId: string | null;
|
|
45
|
+
status: import('../../generated/wspace-types').FileStatus;
|
|
46
|
+
canRead: boolean | null;
|
|
47
|
+
canUpdate: boolean | null;
|
|
48
|
+
canDelete: boolean | null;
|
|
49
|
+
name: string;
|
|
50
|
+
description: string | null;
|
|
51
|
+
mimeType: string;
|
|
52
|
+
extension: string;
|
|
53
|
+
size: string;
|
|
54
|
+
downloadUrl: string | null;
|
|
55
|
+
visibility: import('../../generated/wspace-types').FileVisibility;
|
|
56
|
+
starred: boolean;
|
|
57
|
+
downloadCount: number;
|
|
58
|
+
viewCount: number;
|
|
59
|
+
uploadedById: string;
|
|
60
|
+
createdAt: string;
|
|
61
|
+
updatedAt: string;
|
|
62
|
+
s3Key: string;
|
|
63
|
+
}>;
|
|
64
|
+
};
|
|
65
|
+
foldersList: {
|
|
66
|
+
total: number;
|
|
67
|
+
page: number;
|
|
68
|
+
limit: number;
|
|
69
|
+
hasMore: boolean;
|
|
70
|
+
folders: Array<{
|
|
71
|
+
id: string;
|
|
72
|
+
workspaceId: string;
|
|
73
|
+
parentFolderId: string | null;
|
|
74
|
+
status: import('../../generated/wspace-types').FolderStatus;
|
|
75
|
+
canRead: boolean | null;
|
|
76
|
+
canUpdate: boolean | null;
|
|
77
|
+
canDelete: boolean | null;
|
|
78
|
+
name: string;
|
|
79
|
+
description: string | null;
|
|
80
|
+
path: string;
|
|
81
|
+
level: number;
|
|
82
|
+
visibility: import('../../generated/wspace-types').FileVisibility;
|
|
83
|
+
color: string | null;
|
|
84
|
+
icon: string | null;
|
|
85
|
+
starred: boolean;
|
|
86
|
+
filesCount: number | null;
|
|
87
|
+
subfoldersCount: number | null;
|
|
88
|
+
createdById: string;
|
|
89
|
+
createdAt: string;
|
|
90
|
+
updatedAt: string;
|
|
91
|
+
}>;
|
|
92
|
+
} | {
|
|
93
|
+
total: number;
|
|
94
|
+
page: number;
|
|
95
|
+
limit: number;
|
|
96
|
+
hasMore: boolean;
|
|
97
|
+
folders: Array<{
|
|
98
|
+
id: string;
|
|
99
|
+
workspaceId: string;
|
|
100
|
+
parentFolderId: string | null;
|
|
101
|
+
status: import('../../generated/wspace-types').FolderStatus;
|
|
102
|
+
canRead: boolean | null;
|
|
103
|
+
canUpdate: boolean | null;
|
|
104
|
+
canDelete: boolean | null;
|
|
105
|
+
name: string;
|
|
106
|
+
description: string | null;
|
|
107
|
+
path: string;
|
|
108
|
+
level: number;
|
|
109
|
+
visibility: import('../../generated/wspace-types').FileVisibility;
|
|
110
|
+
color: string | null;
|
|
111
|
+
icon: string | null;
|
|
112
|
+
starred: boolean;
|
|
113
|
+
filesCount: number | null;
|
|
114
|
+
subfoldersCount: number | null;
|
|
115
|
+
createdById: string;
|
|
116
|
+
createdAt: string;
|
|
117
|
+
updatedAt: string;
|
|
118
|
+
}>;
|
|
119
|
+
};
|
|
120
|
+
folderPath: {
|
|
121
|
+
depth: number;
|
|
122
|
+
folders: Array<{
|
|
123
|
+
id: string;
|
|
124
|
+
name: string;
|
|
125
|
+
}>;
|
|
126
|
+
} | undefined;
|
|
127
|
+
currentFolder: {
|
|
128
|
+
id: string;
|
|
129
|
+
name: string;
|
|
130
|
+
} | null | undefined;
|
|
12
131
|
} | undefined;
|
|
13
132
|
loading: boolean;
|
|
14
133
|
error: import('@apollo/client').ErrorLike | undefined;
|
|
15
|
-
refetch: (
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
134
|
+
refetch: import('@apollo/client/react/internal').RefetchFunction<import('../../generated/wspace-operations').GetFilesRootBrowsePageQuery, {
|
|
135
|
+
filePagination?: import('../../generated/wspace-types').PaginationInput | null | undefined;
|
|
136
|
+
folderPagination?: import('../../generated/wspace-types').PaginationInput | null | undefined;
|
|
137
|
+
}, undefined> | import('@apollo/client/react/internal').RefetchFunction<import('../../generated/wspace-operations').GetFilesFolderBrowsePageQuery, {
|
|
138
|
+
folderId: string;
|
|
139
|
+
filePagination?: import('../../generated/wspace-types').PaginationInput | null | undefined;
|
|
140
|
+
folderPagination?: import('../../generated/wspace-types').PaginationInput | null | undefined;
|
|
141
|
+
}, undefined>;
|
|
19
142
|
};
|
|
20
143
|
export {};
|
|
21
144
|
//# sourceMappingURL=useBrowsePage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBrowsePage.d.ts","sourceRoot":"","sources":["../../../src/files/hooks/useBrowsePage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useBrowsePage.d.ts","sourceRoot":"","sources":["../../../src/files/hooks/useBrowsePage.ts"],"names":[],"mappings":"AAOA,KAAK,iBAAiB,GAAG;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,+BAI3B,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CnB,CAAC"}
|