@burdenoff/microfe-files 2026.1014.12 → 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":"FileCard.js","names":[],"sources":["../../../src/files/components/FileCard.tsx"],"sourcesContent":["import { type FC, useState, useMemo } from \"react\";\nimport {\n Download,\n Share2,\n Trash2,\n Star,\n RotateCcw,\n Copy,\n Edit,\n FolderInput,\n Info,\n Activity,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport type { FileItem } from \"../types\";\nimport { formatFileSize, formatFileDate, getFileIcon } from \"../utils\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { ActionMenu } from \"./ActionMenu\";\nimport { getDragOperation } from \"../hooks/useDragDrop\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface FileCardProps {\n file: FileItem;\n isSelected?: boolean;\n isDragging?: boolean;\n onSelect?: (fileId: string) => void;\n onPreview?: (file: FileItem) => void;\n onShare?: (file: FileItem) => void;\n onDelete?: (file: FileItem) => void;\n onRestore?: (file: FileItem) => void;\n onFavorite?: (file: FileItem) => void;\n onRename?: (file: FileItem) => void;\n onDownload?: (file: FileItem) => void;\n onCopy?: (file: FileItem) => void;\n onMove?: (file: FileItem) => void;\n onInfo?: (file: FileItem) => void;\n onActivity?: (file: FileItem) => void;\n onDragStart?: (file: FileItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onContextMenu?: (file: FileItem, x: number, y: number) => void;\n}\n\ninterface DraggableFileCardProps extends Omit<\n FileCardProps,\n \"onDragStart\" | \"onDragEnd\"\n> {\n onDragStart?: (file: FileItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onContextMenu?: (file: FileItem, x: number, y: number) => void;\n}\n\nexport const FileCard: FC<DraggableFileCardProps> = ({\n file,\n isSelected = false,\n isDragging = false,\n onSelect,\n onPreview,\n onShare,\n onDelete,\n onRestore,\n onFavorite,\n onRename,\n onDownload,\n onCopy,\n onMove,\n onInfo,\n onActivity,\n onDragStart,\n onDragEnd,\n onContextMenu,\n}) => {\n const { t } = useI18n();\n const [showActions, setShowActions] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const { toggleFileSelection } = useFilesStore();\n\n const openPreview = () => {\n if (onPreview) {\n onPreview(file);\n }\n };\n\n const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n e.stopPropagation();\n if (onSelect) {\n onSelect(file.id);\n } else {\n toggleFileSelection(file.id);\n }\n };\n\n const handleActionClick = (e: React.MouseEvent, action: () => void) => {\n e.stopPropagation();\n action();\n setShowActions(false);\n };\n\n const handleDragStart = (e: React.DragEvent<HTMLDivElement>) => {\n e.dataTransfer.effectAllowed = \"copyMove\";\n e.dataTransfer.setData(\"application/x-file-id\", file.id);\n e.dataTransfer.setData(\"application/x-file-type\", \"file\");\n const operation = getDragOperation(e);\n e.dataTransfer.setData(\"application/x-drag-operation\", operation);\n onDragStart?.(file, operation);\n };\n\n const handleDragEnd = () => {\n onDragEnd?.();\n };\n\n const handleContextMenu = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onContextMenu?.(file, e.clientX, e.clientY);\n };\n\n const FileIconComponent = getFileIcon(file.mimeType);\n\n // Memoize menu items to prevent re-renders\n const menuItems = useMemo(\n () => [\n ...(onDownload\n ? [\n {\n label: tWithFallback(t, \"files.card.download\", \"Download\"),\n icon: <Download className=\"size-4\" />,\n onClick: () => onDownload(file),\n },\n ]\n : []),\n ...(onShare\n ? [\n {\n label: tWithFallback(t, \"files.card.share\", \"Share\"),\n icon: <Share2 className=\"size-4\" />,\n onClick: () => onShare(file),\n },\n ]\n : []),\n ...(onCopy\n ? [\n {\n label: tWithFallback(t, \"files.card.makeCopy\", \"Make a copy\"),\n icon: <Copy className=\"size-4\" />,\n onClick: () => onCopy(file),\n },\n ]\n : []),\n ...(onMove\n ? [\n {\n label: tWithFallback(t, \"files.card.moveTo\", \"Move to\"),\n icon: <FolderInput className=\"size-4\" />,\n onClick: () => onMove(file),\n },\n ]\n : []),\n ...(onRename\n ? [\n {\n label: tWithFallback(t, \"files.card.rename\", \"Rename\"),\n icon: <Edit className=\"size-4\" />,\n onClick: () => onRename(file),\n divider: true,\n },\n ]\n : []),\n ...(onFavorite\n ? [\n {\n label: file.starred\n ? tWithFallback(\n t,\n \"files.card.removeFromStarred\",\n \"Remove from starred\",\n )\n : tWithFallback(t, \"files.card.addToStarred\", \"Add to starred\"),\n icon: <Star className=\"size-4\" />,\n onClick: () => onFavorite(file),\n },\n ]\n : []),\n ...(onInfo\n ? [\n {\n label: tWithFallback(t, \"files.card.details\", \"Details\"),\n icon: <Info className=\"size-4\" />,\n onClick: () => onInfo(file),\n },\n ]\n : []),\n ...(onActivity\n ? [\n {\n label: tWithFallback(t, \"files.card.activity\", \"Activity\"),\n icon: <Activity className=\"size-4\" />,\n onClick: () => onActivity(file),\n },\n ]\n : []),\n ...(onDelete\n ? [\n {\n label: tWithFallback(t, \"files.card.delete\", \"Delete\"),\n icon: <Trash2 className=\"size-4\" />,\n onClick: () => onDelete(file),\n variant: \"danger\" as const,\n divider: true,\n },\n ]\n : []),\n ...(onRestore\n ? [\n {\n label: tWithFallback(t, \"files.card.restore\", \"Restore\"),\n icon: <RotateCcw className=\"size-4\" />,\n onClick: () => onRestore(file),\n },\n ]\n : []),\n ],\n [\n file,\n onDownload,\n onShare,\n onCopy,\n onMove,\n onRename,\n onFavorite,\n onInfo,\n onActivity,\n onDelete,\n onRestore,\n t,\n ],\n );\n\n return (\n <GlassCard\n treatment=\"insight\"\n className={`@container group cursor-pointer overflow-hidden border-border-seam focus-within:shadow-elevation-2 ${isDragging ? \"opacity-50\" : \"\"}`}\n onClick={openPreview}\n onContextMenu={handleContextMenu}\n onMouseEnter={() => setShowActions(true)}\n onMouseLeave={() => setShowActions(false)}\n onFocus={() => setShowActions(true)}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget)) {\n setShowActions(false);\n }\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n openPreview();\n }\n }}\n draggable={Boolean(onDragStart)}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n role=\"button\"\n tabIndex={0}\n aria-label={`Preview ${file.name}`}\n >\n {/* Selection checkbox */}\n <div\n className={`absolute top-2 left-2 z-10 transition-opacity ${\n isSelected\n ? \"opacity-100\"\n : \"opacity-0 group-hover:opacity-100 group-focus-within:opacity-100\"\n }`}\n >\n <input\n type=\"checkbox\"\n checked={isSelected}\n onChange={handleCheckboxChange}\n className=\"size-4 rounded border-border-default bg-bg-surface text-action-primary-bg focus:ring-2 focus:ring-action-primary-bg focus:ring-offset-2\"\n aria-label={`Select ${file.name}`}\n />\n </div>\n\n {/* Favorite indicator */}\n {file.starred && (\n <div className=\"absolute top-2 right-2 z-10\">\n <Star className=\"size-4 fill-yellow-400 text-yellow-400\" />\n </div>\n )}\n\n {/* Thumbnail or icon */}\n <div className=\"aspect-[4/3] bg-bg-sunken flex items-center justify-center overflow-hidden\">\n {file.thumbnailUrl ? (\n <img\n src={file.thumbnailUrl}\n alt={file.name}\n className=\"h-full w-full object-contain p-2\"\n />\n ) : (\n <FileIconComponent className=\"size-12 @md:size-16 text-text-muted\" />\n )}\n </div>\n\n {/* File info */}\n <div className=\"p-3 @md:p-4\">\n <h3 className=\"font-text-md font-weight-medium text-text-primary truncate mb-1\">\n {file.name}\n </h3>\n\n <div className=\"hidden @sm:flex items-center gap-2 text-text-secondary font-text-sm\">\n <span className=\"tabular-nums\">{formatFileSize(file.size)}</span>\n <span className=\"text-border-subtle\">•</span>\n <span>{formatFileDate(file.updatedAt)}</span>\n </div>\n\n {/* Extended metadata on larger containers */}\n <div className=\"hidden @md:flex items-center gap-2 mt-2 text-text-muted font-text-xs\">\n {file.createdBy && (\n <div className=\"flex items-center gap-1\">\n {file.createdBy.avatar && (\n <img\n src={file.createdBy.avatar}\n alt={file.createdBy.name}\n className=\"size-4 rounded-full\"\n />\n )}\n <span>{file.createdBy.name}</span>\n </div>\n )}\n {file.isShared && (\n <>\n <span className=\"text-border-subtle\">•</span>\n <Share2 className=\"size-3\" />\n <span>{tWithFallback(t, \"files.card.shared\", \"Shared\")}</span>\n </>\n )}\n </div>\n\n {/* Tags */}\n {file.tags && file.tags.length > 0 && (\n <div className=\"hidden @lg:flex flex-wrap gap-1 mt-2\">\n {file.tags.slice(0, 3).map((tag) => (\n <span\n key={tag}\n className=\"px-2 py-0.5 bg-bg-accent text-text-primary font-text-xs rounded-sm\"\n >\n {tag}\n </span>\n ))}\n {file.tags.length > 3 && (\n <span className=\"px-2 py-0.5 text-text-muted font-text-xs\">\n +{file.tags.length - 3}\n </span>\n )}\n </div>\n )}\n </div>\n\n {/* Action buttons (on hover) with dropdown menu */}\n {showActions && (\n <div className=\"absolute bottom-3 right-3 flex items-center gap-1 bg-bg-elevated border border-border-subtle rounded shadow-elevation-2 p-1\">\n {onDownload && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onDownload(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.download\", \"Download\")}\n title={tWithFallback(t, \"files.card.download\", \"Download\")}\n >\n <Download className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {onShare && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onShare(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.share\", \"Share\")}\n title={tWithFallback(t, \"files.card.share\", \"Share\")}\n >\n <Share2 className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {onFavorite && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onFavorite(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={\n file.starred\n ? tWithFallback(t, \"files.card.unfavorite\", \"Unfavorite\")\n : tWithFallback(t, \"files.card.favorite\", \"Favorite\")\n }\n title={\n file.starred\n ? tWithFallback(t, \"files.card.unfavorite\", \"Unfavorite\")\n : tWithFallback(t, \"files.card.favorite\", \"Favorite\")\n }\n >\n <Star\n className={`size-4 ${\n file.starred\n ? \"fill-status-warning-text text-status-warning-text\"\n : \"text-text-primary\"\n }`}\n />\n </button>\n )}\n\n {onRestore && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onRestore(file))}\n className=\"p-1.5 hover:bg-status-success-bg-subtle rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n title={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n >\n <RotateCcw className=\"size-4 text-status-success-text\" />\n </button>\n )}\n\n {/* More options dropdown */}\n <div onClick={(e) => e.stopPropagation()}>\n <ActionMenu\n items={menuItems}\n align=\"right\"\n triggerClassName=\"p-1.5\"\n isOpen={menuOpen}\n onToggle={setMenuOpen}\n />\n </div>\n </div>\n )}\n </GlassCard>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FileCard.js","names":["_Fragment","FileCard","useI18n","showActions","setShowActions","useState","menuOpen","setMenuOpen","cardRef","useRef","handleMenuToggle","open","card","useFilesStore","openPreview","onPreview","file","handleCheckboxChange","onSelect","toggleFileSelection","handleActionClick","action","handleDragStart","operation","getDragOperation","onDragStart","handleDragEnd","handleContextMenu","onContextMenu","FileIconComponent","getFileIcon","menuItems","useMemo","onDownload","tWithFallback","t","Download","onShare","Share2","onCopy","Copy","onMove","FolderInput","onRename","Edit","onFavorite","Star","onInfo","Info","onActivity","Activity","onDelete","Trash2","onRestore","RotateCcw","GlassCard","isDragging","event","isSelected","formatFileSize","formatFileDate","Fragment","tag","ActionMenu"],"sources":["../../../src/files/components/FileCard.tsx"],"sourcesContent":["import { type FC, useState, useMemo, useRef } from \"react\";\nimport {\n Download,\n Share2,\n Trash2,\n Star,\n RotateCcw,\n Copy,\n Edit,\n FolderInput,\n Info,\n Activity,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport type { FileItem } from \"../types\";\nimport { formatFileSize, formatFileDate, getFileIcon } from \"../utils\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { ActionMenu } from \"./ActionMenu\";\nimport { getDragOperation } from \"../hooks/useDragDrop\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface FileCardProps {\n file: FileItem;\n isSelected?: boolean;\n isDragging?: boolean;\n onSelect?: (fileId: string) => void;\n onPreview?: (file: FileItem) => void;\n onShare?: (file: FileItem) => void;\n onDelete?: (file: FileItem) => void;\n onRestore?: (file: FileItem) => void;\n onFavorite?: (file: FileItem) => void;\n onRename?: (file: FileItem) => void;\n onDownload?: (file: FileItem) => void;\n onCopy?: (file: FileItem) => void;\n onMove?: (file: FileItem) => void;\n onInfo?: (file: FileItem) => void;\n onActivity?: (file: FileItem) => void;\n onDragStart?: (file: FileItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onContextMenu?: (file: FileItem, x: number, y: number) => void;\n}\n\ninterface DraggableFileCardProps extends Omit<\n FileCardProps,\n \"onDragStart\" | \"onDragEnd\"\n> {\n onDragStart?: (file: FileItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onContextMenu?: (file: FileItem, x: number, y: number) => void;\n}\n\nexport const FileCard: FC<DraggableFileCardProps> = ({\n file,\n isSelected = false,\n isDragging = false,\n onSelect,\n onPreview,\n onShare,\n onDelete,\n onRestore,\n onFavorite,\n onRename,\n onDownload,\n onCopy,\n onMove,\n onInfo,\n onActivity,\n onDragStart,\n onDragEnd,\n onContextMenu,\n}) => {\n const { t } = useI18n();\n const [showActions, setShowActions] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const cardRef = useRef<HTMLDivElement>(null);\n const handleMenuToggle = (open: boolean) => {\n setMenuOpen(open);\n if (!open) {\n const card = cardRef.current;\n setShowActions(\n Boolean(\n card &&\n (card.matches(\":hover\") ||\n card.contains(card.ownerDocument.activeElement)),\n ),\n );\n }\n };\n const { toggleFileSelection } = useFilesStore();\n\n const openPreview = () => {\n if (onPreview) {\n onPreview(file);\n }\n };\n\n const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n e.stopPropagation();\n if (onSelect) {\n onSelect(file.id);\n } else {\n toggleFileSelection(file.id);\n }\n };\n\n const handleActionClick = (e: React.MouseEvent, action: () => void) => {\n e.stopPropagation();\n action();\n setShowActions(false);\n };\n\n const handleDragStart = (e: React.DragEvent<HTMLDivElement>) => {\n e.dataTransfer.effectAllowed = \"copyMove\";\n e.dataTransfer.setData(\"application/x-file-id\", file.id);\n e.dataTransfer.setData(\"application/x-file-type\", \"file\");\n const operation = getDragOperation(e);\n e.dataTransfer.setData(\"application/x-drag-operation\", operation);\n onDragStart?.(file, operation);\n };\n\n const handleDragEnd = () => {\n onDragEnd?.();\n };\n\n const handleContextMenu = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onContextMenu?.(file, e.clientX, e.clientY);\n };\n\n const FileIconComponent = getFileIcon(file.mimeType);\n\n // Memoize menu items to prevent re-renders\n const menuItems = useMemo(\n () => [\n ...(onDownload\n ? [\n {\n label: tWithFallback(t, \"files.card.download\", \"Download\"),\n icon: <Download className=\"size-4\" />,\n onClick: () => onDownload(file),\n },\n ]\n : []),\n ...(onShare\n ? [\n {\n label: tWithFallback(t, \"files.card.share\", \"Share\"),\n icon: <Share2 className=\"size-4\" />,\n onClick: () => onShare(file),\n },\n ]\n : []),\n ...(onCopy\n ? [\n {\n label: tWithFallback(t, \"files.card.makeCopy\", \"Make a copy\"),\n icon: <Copy className=\"size-4\" />,\n onClick: () => onCopy(file),\n },\n ]\n : []),\n ...(onMove\n ? [\n {\n label: tWithFallback(t, \"files.card.moveTo\", \"Move to\"),\n icon: <FolderInput className=\"size-4\" />,\n onClick: () => onMove(file),\n },\n ]\n : []),\n ...(onRename\n ? [\n {\n label: tWithFallback(t, \"files.card.rename\", \"Rename\"),\n icon: <Edit className=\"size-4\" />,\n onClick: () => onRename(file),\n divider: true,\n },\n ]\n : []),\n ...(onFavorite\n ? [\n {\n label: file.starred\n ? tWithFallback(\n t,\n \"files.card.removeFromStarred\",\n \"Remove from starred\",\n )\n : tWithFallback(t, \"files.card.addToStarred\", \"Add to starred\"),\n icon: <Star className=\"size-4\" />,\n onClick: () => onFavorite(file),\n },\n ]\n : []),\n ...(onInfo\n ? [\n {\n label: tWithFallback(t, \"files.card.details\", \"Details\"),\n icon: <Info className=\"size-4\" />,\n onClick: () => onInfo(file),\n },\n ]\n : []),\n ...(onActivity\n ? [\n {\n label: tWithFallback(t, \"files.card.activity\", \"Activity\"),\n icon: <Activity className=\"size-4\" />,\n onClick: () => onActivity(file),\n },\n ]\n : []),\n ...(onDelete\n ? [\n {\n label: tWithFallback(t, \"files.card.delete\", \"Delete\"),\n icon: <Trash2 className=\"size-4\" />,\n onClick: () => onDelete(file),\n variant: \"danger\" as const,\n divider: true,\n },\n ]\n : []),\n ...(onRestore\n ? [\n {\n label: tWithFallback(t, \"files.card.restore\", \"Restore\"),\n icon: <RotateCcw className=\"size-4\" />,\n onClick: () => onRestore(file),\n },\n ]\n : []),\n ],\n [\n file,\n onDownload,\n onShare,\n onCopy,\n onMove,\n onRename,\n onFavorite,\n onInfo,\n onActivity,\n onDelete,\n onRestore,\n t,\n ],\n );\n\n return (\n <GlassCard\n ref={cardRef}\n treatment=\"insight\"\n className={`@container group cursor-pointer overflow-hidden border-border-seam focus-within:shadow-elevation-2 ${isDragging ? \"opacity-50\" : \"\"}`}\n onClick={openPreview}\n onContextMenu={handleContextMenu}\n onMouseEnter={() => setShowActions(true)}\n onMouseLeave={() => {\n if (!menuOpen) setShowActions(false);\n }}\n onFocus={() => setShowActions(true)}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget) && !menuOpen) {\n setShowActions(false);\n }\n }}\n onKeyDown={(event) => {\n if (event.target !== event.currentTarget) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n openPreview();\n }\n }}\n draggable={Boolean(onDragStart)}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n role=\"button\"\n tabIndex={0}\n aria-label={`Preview ${file.name}`}\n >\n {/* Selection checkbox */}\n <div\n className={`absolute top-2 left-2 z-10 transition-opacity ${\n isSelected\n ? \"opacity-100\"\n : \"opacity-0 group-hover:opacity-100 group-focus-within:opacity-100\"\n }`}\n >\n <input\n type=\"checkbox\"\n checked={isSelected}\n onChange={handleCheckboxChange}\n className=\"size-4 rounded border-border-default bg-bg-surface text-action-primary-bg focus:ring-2 focus:ring-action-primary-bg focus:ring-offset-2\"\n aria-label={`Select ${file.name}`}\n />\n </div>\n\n {/* Favorite indicator */}\n {file.starred && (\n <div className=\"absolute top-2 right-2 z-10\">\n <Star className=\"size-4 fill-yellow-400 text-yellow-400\" />\n </div>\n )}\n\n {/* Thumbnail or icon */}\n <div className=\"aspect-[4/3] bg-bg-sunken flex items-center justify-center overflow-hidden\">\n {file.thumbnailUrl ? (\n <img\n src={file.thumbnailUrl}\n alt={file.name}\n className=\"h-full w-full object-contain p-2\"\n />\n ) : (\n <FileIconComponent className=\"size-12 @md:size-16 text-text-muted\" />\n )}\n </div>\n\n {/* File info */}\n <div className=\"p-3 @md:p-4\">\n <h3 className=\"font-text-md font-weight-medium text-text-primary truncate mb-1\">\n {file.name}\n </h3>\n\n <div className=\"hidden @sm:flex items-center gap-2 text-text-secondary font-text-sm\">\n <span className=\"tabular-nums\">{formatFileSize(file.size)}</span>\n <span className=\"text-border-subtle\">•</span>\n <span>{formatFileDate(file.updatedAt)}</span>\n </div>\n\n {/* Extended metadata on larger containers */}\n <div className=\"hidden @md:flex items-center gap-2 mt-2 text-text-muted font-text-xs\">\n {file.createdBy && (\n <div className=\"flex items-center gap-1\">\n {file.createdBy.avatar && (\n <img\n src={file.createdBy.avatar}\n alt={file.createdBy.name}\n className=\"size-4 rounded-full\"\n />\n )}\n <span>{file.createdBy.name}</span>\n </div>\n )}\n {file.isShared && (\n <>\n <span className=\"text-border-subtle\">•</span>\n <Share2 className=\"size-3\" />\n <span>{tWithFallback(t, \"files.card.shared\", \"Shared\")}</span>\n </>\n )}\n </div>\n\n {/* Tags */}\n {file.tags && file.tags.length > 0 && (\n <div className=\"hidden @lg:flex flex-wrap gap-1 mt-2\">\n {file.tags.slice(0, 3).map((tag) => (\n <span\n key={tag}\n className=\"px-2 py-0.5 bg-bg-accent text-text-primary font-text-xs rounded-sm\"\n >\n {tag}\n </span>\n ))}\n {file.tags.length > 3 && (\n <span className=\"px-2 py-0.5 text-text-muted font-text-xs\">\n +{file.tags.length - 3}\n </span>\n )}\n </div>\n )}\n </div>\n\n {/* Action buttons (on hover) with dropdown menu */}\n {showActions && (\n <div className=\"absolute bottom-3 right-3 flex items-center gap-1 bg-bg-elevated border border-border-subtle rounded shadow-elevation-2 p-1\">\n {onDownload && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onDownload(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.download\", \"Download\")}\n title={tWithFallback(t, \"files.card.download\", \"Download\")}\n >\n <Download className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {onShare && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onShare(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.share\", \"Share\")}\n title={tWithFallback(t, \"files.card.share\", \"Share\")}\n >\n <Share2 className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {onFavorite && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onFavorite(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={\n file.starred\n ? tWithFallback(t, \"files.card.unfavorite\", \"Unfavorite\")\n : tWithFallback(t, \"files.card.favorite\", \"Favorite\")\n }\n title={\n file.starred\n ? tWithFallback(t, \"files.card.unfavorite\", \"Unfavorite\")\n : tWithFallback(t, \"files.card.favorite\", \"Favorite\")\n }\n >\n <Star\n className={`size-4 ${\n file.starred\n ? \"fill-status-warning-text text-status-warning-text\"\n : \"text-text-primary\"\n }`}\n />\n </button>\n )}\n\n {onRestore && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onRestore(file))}\n className=\"p-1.5 hover:bg-status-success-bg-subtle rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n title={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n >\n <RotateCcw className=\"size-4 text-status-success-text\" />\n </button>\n )}\n\n {/* More options dropdown */}\n <div onClick={(e) => e.stopPropagation()}>\n <ActionMenu\n items={menuItems}\n align=\"right\"\n triggerClassName=\"p-1.5\"\n isOpen={menuOpen}\n onToggle={handleMenuToggle}\n />\n </div>\n </div>\n )}\n </GlassCard>\n );\n};\n"],"mappings":"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"}
|
|
@@ -4,6 +4,6 @@ interface FileInfoPanelProps {
|
|
|
4
4
|
type: "file" | "folder";
|
|
5
5
|
onClose: () => void;
|
|
6
6
|
}
|
|
7
|
-
export declare function FileInfoPanel({ item, type, onClose }: FileInfoPanelProps): import(
|
|
7
|
+
export declare function FileInfoPanel({ item, type, onClose }: FileInfoPanelProps): import('react').JSX.Element;
|
|
8
8
|
export {};
|
|
9
9
|
//# sourceMappingURL=FileInfoPanel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileInfoPanel.d.ts","sourceRoot":"","sources":["../../../src/files/components/FileInfoPanel.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAQrD,UAAU,kBAAkB;IAC1B,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5B,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,kBAAkB,+
|
|
1
|
+
{"version":3,"file":"FileInfoPanel.d.ts","sourceRoot":"","sources":["../../../src/files/components/FileInfoPanel.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAQrD,UAAU,kBAAkB;IAC1B,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5B,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,kBAAkB,+BA0SxE"}
|
|
@@ -8,11 +8,7 @@ import { GlassCard as _, ShowMore as v } from "@burdenoff/fe-libs/ui";
|
|
|
8
8
|
var y = n(() => import("./FileVersionPanel.js").then((e) => ({ default: e.FileVersionPanel })));
|
|
9
9
|
function b({ item: n, type: b, onClose: x }) {
|
|
10
10
|
let { t: S } = g(), C = b === "file", w = C ? n : null, T = C ? null : n, [E, D] = a(!1), O = i(() => {
|
|
11
|
-
|
|
12
|
-
D(!1);
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
x();
|
|
11
|
+
E ? D(!1) : x();
|
|
16
12
|
});
|
|
17
13
|
r(() => {
|
|
18
14
|
let e = (e) => {
|
|
@@ -52,7 +48,7 @@ function b({ item: n, type: b, onClose: x }) {
|
|
|
52
48
|
/* @__PURE__ */ m(_, {
|
|
53
49
|
treatment: "metric",
|
|
54
50
|
className: "flex items-center justify-center py-8",
|
|
55
|
-
children: C && w?.mimeType.startsWith("image/") ? /* @__PURE__ */ m("img", {
|
|
51
|
+
children: C && w?.mimeType.startsWith("image/") && (w.downloadUrl || w.url) ? /* @__PURE__ */ m("img", {
|
|
56
52
|
src: w.downloadUrl || w.url,
|
|
57
53
|
alt: n.name,
|
|
58
54
|
className: "max-w-full max-h-48 object-contain rounded"
|
|
@@ -85,7 +81,7 @@ function b({ item: n, type: b, onClose: x }) {
|
|
|
85
81
|
children: e(S, "files.info.size", "Size")
|
|
86
82
|
}), /* @__PURE__ */ m("p", {
|
|
87
83
|
className: "text-sm text-text-secondary",
|
|
88
|
-
children: ((e) => e < 1024 ? `${e} B` : e <
|
|
84
|
+
children: ((e) => e < 1024 ? `${e} B` : e < 1048576 ? `${(e / 1024).toFixed(2)} KB` : e < 1073741824 ? `${(e / 1024 / 1024).toFixed(2)} MB` : `${(e / 1024 / 1024 / 1024).toFixed(2)} GB`)(w.size)
|
|
89
85
|
})] })]
|
|
90
86
|
}),
|
|
91
87
|
!C && T && /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ h("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileInfoPanel.js","names":[],"sources":["../../../src/files/components/FileInfoPanel.tsx"],"sourcesContent":["import { useEffect, useEffectEvent, useState, lazy, Suspense } from \"react\";\nimport {\n X,\n FileText,\n Calendar,\n User,\n HardDrive,\n Link as LinkIcon,\n Clock,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { GlassCard, ShowMore } from \"@burdenoff/fe-libs/ui\";\nimport type { FileItem, FolderItem } from \"../types\";\nimport { tWithFallback } from \"../utils/i18n\";\n\n// Lazy load FileVersionPanel to avoid loading heavy dependencies until needed\nconst FileVersionPanel = lazy(() =>\n import(\"./FileVersionPanel\").then((m) => ({ default: m.FileVersionPanel })),\n);\n\ninterface FileInfoPanelProps {\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n onClose: () => void;\n}\n\nexport function FileInfoPanel({ item, type, onClose }: FileInfoPanelProps) {\n const { t } = useI18n();\n const isFile = type === \"file\";\n const file = isFile ? (item as FileItem) : null;\n const folder = !isFile ? (item as FolderItem) : null;\n const [showVersionHistory, setShowVersionHistory] = useState(false);\n\n const onEscape = useEffectEvent(() => {\n if (showVersionHistory) {\n setShowVersionHistory(false);\n return;\n }\n onClose();\n });\n\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onEscape();\n }\n };\n\n document.addEventListener(\"keydown\", handleEscape);\n return () => document.removeEventListener(\"keydown\", handleEscape);\n }, []);\n\n const formatDate = (date: string) => {\n return new Date(date).toLocaleString(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n };\n\n const formatSize = (bytes: number) => {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / 1024 / 1024).toFixed(2)} MB`;\n return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;\n };\n\n return (\n <div\n className=\"fixed inset-y-0 right-0 z-[9999] w-full max-w-full overflow-y-auto border-l border-border-seam bg-bg-surface shadow-2xl animate-in slide-in-from-right duration-200 sm:w-96 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]\"\n role=\"dialog\"\n aria-modal=\"false\"\n aria-label={\n isFile\n ? tWithFallback(t, \"files.info.fileInfo\", \"File information\")\n : tWithFallback(t, \"files.info.folderInfo\", \"Folder information\")\n }\n >\n {/* Header */}\n <div className=\"sticky top-0 z-10 bg-bg-surface border-b border-border-seam px-6 py-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {isFile\n ? tWithFallback(t, \"files.info.fileInfo\", \"File Information\")\n : tWithFallback(t, \"files.info.folderInfo\", \"Folder Information\")}\n </h2>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1.5 rounded-md border border-border-default text-text-secondary bg-bg-elevated hover:bg-action-ghost-bg-hover hover:text-text-primary transition-colors shadow-sm\"\n aria-label={tWithFallback(\n t,\n \"files.info.closePanel\",\n \"Close information panel\",\n )}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Content */}\n <div className=\"p-6 space-y-6\">\n {/* Preview/Icon */}\n <GlassCard\n treatment=\"metric\"\n className=\"flex items-center justify-center py-8\"\n >\n {isFile && file?.mimeType.startsWith(\"image/\") ? (\n <img\n src={file.downloadUrl || file.url}\n alt={item.name}\n className=\"max-w-full max-h-48 object-contain rounded\"\n />\n ) : (\n <FileText className=\"size-20 text-text-muted\" />\n )}\n </GlassCard>\n\n {/* Name */}\n <div>\n <h3 className=\"text-xl font-semibold text-text-primary break-words\">\n {item.name}\n </h3>\n {item.description && (\n <p className=\"mt-2 text-sm text-text-secondary\">\n {item.description}\n </p>\n )}\n </div>\n\n {/* Details */}\n <div className=\"space-y-4\">\n <div className=\"flex items-start gap-3\">\n <FileText className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.type\", \"Type\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {isFile\n ? file?.mimeType ||\n tWithFallback(t, \"files.info.unknown\", \"Unknown\")\n : tWithFallback(t, \"files.info.folder\", \"Folder\")}\n </p>\n </div>\n </div>\n\n {isFile && file && (\n <div className=\"flex items-start gap-3\">\n <HardDrive className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.size\", \"Size\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {formatSize(file.size)}\n </p>\n </div>\n </div>\n )}\n\n {!isFile && folder && (\n <>\n <div className=\"flex items-start gap-3\">\n <FileText className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.contents\", \"Contents\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {folder.filesCount}{\" \"}\n {tWithFallback(t, \"files.info.files\", \"files\")},{\" \"}\n {folder.subfoldersCount}{\" \"}\n {tWithFallback(t, \"files.info.folders\", \"folders\")}\n </p>\n </div>\n </div>\n\n {folder.path && (\n <div className=\"flex items-start gap-3\">\n <LinkIcon className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.path\", \"Path\")}\n </p>\n <p className=\"text-sm text-text-secondary break-all\">\n {folder.path}\n </p>\n </div>\n </div>\n )}\n </>\n )}\n\n <div className=\"flex items-start gap-3\">\n <Calendar className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.created\", \"Created\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {formatDate(item.createdAt)}\n </p>\n </div>\n </div>\n\n {item.updatedAt && (\n <div className=\"flex items-start gap-3\">\n <Calendar className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.modified\", \"Modified\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {formatDate(item.updatedAt)}\n </p>\n </div>\n </div>\n )}\n\n <div className=\"flex items-start gap-3\">\n <User className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.owner\", \"Owner\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {item.createdBy?.name ||\n item.createdById ||\n tWithFallback(t, \"files.info.unknown\", \"Unknown\")}\n </p>\n </div>\n </div>\n </div>\n\n {/* Additional Info — secondary properties tucked behind progressive\n disclosure to keep the rail focused on the essentials. */}\n <div className=\"pt-6 border-t border-border-seam\">\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">\n {tWithFallback(t, \"files.info.properties\", \"Properties\")}\n </h4>\n <ShowMore collapsedHeight={56}>\n <dl className=\"space-y-2\">\n <div className=\"flex justify-between\">\n <dt className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.info.status\", \"Status\")}\n </dt>\n <dd className=\"text-sm font-medium text-text-primary\">\n {item.status}\n </dd>\n </div>\n <div className=\"flex justify-between\">\n <dt className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.info.visibility\", \"Visibility\")}\n </dt>\n <dd className=\"text-sm font-medium text-text-primary\">\n {item.visibility}\n </dd>\n </div>\n <div className=\"flex justify-between\">\n <dt className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.info.starred\", \"Starred\")}\n </dt>\n <dd className=\"text-sm font-medium text-text-primary\">\n {item.starred\n ? tWithFallback(t, \"files.info.yes\", \"Yes\")\n : tWithFallback(t, \"files.info.no\", \"No\")}\n </dd>\n </div>\n </dl>\n </ShowMore>\n </div>\n\n {/* Version History Button (Files only) */}\n {isFile && file && (\n <div className=\"pt-6 border-t border-border-seam\">\n <button\n type=\"button\"\n onClick={() => setShowVersionHistory(true)}\n className=\"w-full flex items-center justify-center gap-2 px-4 py-3 text-sm font-medium text-action-primary-text bg-action-primary-bg/10 hover:bg-action-primary-bg/20 rounded-lg transition-all duration-200\"\n >\n <Clock className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.info.viewVersionHistory\",\n \"View Version History\",\n )}\n </button>\n </div>\n )}\n </div>\n\n {/* Version History Modal */}\n {isFile && file && showVersionHistory && (\n <Suspense\n fallback={\n <div className=\"fixed inset-0 z-50 bg-bg-overlay flex items-center justify-center\">\n <div className=\"bg-bg-surface rounded-lg p-8 animate-in fade-in zoom-in duration-200\">\n <div className=\"flex items-center gap-3\">\n <Clock className=\"size-6 text-action-primary-bg animate-spin\" />\n <span className=\"text-text-primary\">\n {tWithFallback(\n t,\n \"files.info.loadingVersionHistory\",\n \"Loading version history...\",\n )}\n </span>\n </div>\n </div>\n </div>\n }\n >\n <FileVersionPanel\n file={file}\n onClose={() => setShowVersionHistory(false)}\n />\n </Suspense>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FileInfoPanel.js","names":["_Fragment","LinkIcon","FileVersionPanel","lazy","m","FileInfoPanel","useI18n","isFile","type","file","item","folder","showVersionHistory","setShowVersionHistory","useState","onEscape","useEffectEvent","onClose","handleEscape","event","formatDate","date","tWithFallback","t","X","GlassCard","FileText","HardDrive","bytes","Fragment","Link","Calendar","User","ShowMore","Clock","Suspense"],"sources":["../../../src/files/components/FileInfoPanel.tsx"],"sourcesContent":["import { useEffect, useEffectEvent, useState, lazy, Suspense } from \"react\";\nimport {\n X,\n FileText,\n Calendar,\n User,\n HardDrive,\n Link as LinkIcon,\n Clock,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { GlassCard, ShowMore } from \"@burdenoff/fe-libs/ui\";\nimport type { FileItem, FolderItem } from \"../types\";\nimport { tWithFallback } from \"../utils/i18n\";\n\n// Lazy load FileVersionPanel to avoid loading heavy dependencies until needed\nconst FileVersionPanel = lazy(() =>\n import(\"./FileVersionPanel\").then((m) => ({ default: m.FileVersionPanel })),\n);\n\ninterface FileInfoPanelProps {\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n onClose: () => void;\n}\n\nexport function FileInfoPanel({ item, type, onClose }: FileInfoPanelProps) {\n const { t } = useI18n();\n const isFile = type === \"file\";\n const file = isFile ? (item as FileItem) : null;\n const folder = !isFile ? (item as FolderItem) : null;\n const [showVersionHistory, setShowVersionHistory] = useState(false);\n\n const onEscape = useEffectEvent(() => {\n if (showVersionHistory) {\n setShowVersionHistory(false);\n return;\n }\n onClose();\n });\n\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onEscape();\n }\n };\n\n document.addEventListener(\"keydown\", handleEscape);\n return () => document.removeEventListener(\"keydown\", handleEscape);\n }, []);\n\n const formatDate = (date: string) => {\n return new Date(date).toLocaleString(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n };\n\n const formatSize = (bytes: number) => {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / 1024 / 1024).toFixed(2)} MB`;\n return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;\n };\n\n return (\n <div\n className=\"fixed inset-y-0 right-0 z-[9999] w-full max-w-full overflow-y-auto border-l border-border-seam bg-bg-surface shadow-2xl animate-in slide-in-from-right duration-200 sm:w-96 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]\"\n role=\"dialog\"\n aria-modal=\"false\"\n aria-label={\n isFile\n ? tWithFallback(t, \"files.info.fileInfo\", \"File information\")\n : tWithFallback(t, \"files.info.folderInfo\", \"Folder information\")\n }\n >\n {/* Header */}\n <div className=\"sticky top-0 z-10 bg-bg-surface border-b border-border-seam px-6 py-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {isFile\n ? tWithFallback(t, \"files.info.fileInfo\", \"File Information\")\n : tWithFallback(t, \"files.info.folderInfo\", \"Folder Information\")}\n </h2>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1.5 rounded-md border border-border-default text-text-secondary bg-bg-elevated hover:bg-action-ghost-bg-hover hover:text-text-primary transition-colors shadow-sm\"\n aria-label={tWithFallback(\n t,\n \"files.info.closePanel\",\n \"Close information panel\",\n )}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Content */}\n <div className=\"p-6 space-y-6\">\n {/* Preview/Icon */}\n <GlassCard\n treatment=\"metric\"\n className=\"flex items-center justify-center py-8\"\n >\n {isFile &&\n file?.mimeType.startsWith(\"image/\") &&\n (file.downloadUrl || file.url) ? (\n <img\n src={file.downloadUrl || file.url}\n alt={item.name}\n className=\"max-w-full max-h-48 object-contain rounded\"\n />\n ) : (\n <FileText className=\"size-20 text-text-muted\" />\n )}\n </GlassCard>\n\n {/* Name */}\n <div>\n <h3 className=\"text-xl font-semibold text-text-primary break-words\">\n {item.name}\n </h3>\n {item.description && (\n <p className=\"mt-2 text-sm text-text-secondary\">\n {item.description}\n </p>\n )}\n </div>\n\n {/* Details */}\n <div className=\"space-y-4\">\n <div className=\"flex items-start gap-3\">\n <FileText className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.type\", \"Type\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {isFile\n ? file?.mimeType ||\n tWithFallback(t, \"files.info.unknown\", \"Unknown\")\n : tWithFallback(t, \"files.info.folder\", \"Folder\")}\n </p>\n </div>\n </div>\n\n {isFile && file && (\n <div className=\"flex items-start gap-3\">\n <HardDrive className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.size\", \"Size\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {formatSize(file.size)}\n </p>\n </div>\n </div>\n )}\n\n {!isFile && folder && (\n <>\n <div className=\"flex items-start gap-3\">\n <FileText className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.contents\", \"Contents\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {folder.filesCount}{\" \"}\n {tWithFallback(t, \"files.info.files\", \"files\")},{\" \"}\n {folder.subfoldersCount}{\" \"}\n {tWithFallback(t, \"files.info.folders\", \"folders\")}\n </p>\n </div>\n </div>\n\n {folder.path && (\n <div className=\"flex items-start gap-3\">\n <LinkIcon className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.path\", \"Path\")}\n </p>\n <p className=\"text-sm text-text-secondary break-all\">\n {folder.path}\n </p>\n </div>\n </div>\n )}\n </>\n )}\n\n <div className=\"flex items-start gap-3\">\n <Calendar className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.created\", \"Created\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {formatDate(item.createdAt)}\n </p>\n </div>\n </div>\n\n {item.updatedAt && (\n <div className=\"flex items-start gap-3\">\n <Calendar className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.modified\", \"Modified\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {formatDate(item.updatedAt)}\n </p>\n </div>\n </div>\n )}\n\n <div className=\"flex items-start gap-3\">\n <User className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.owner\", \"Owner\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {item.createdBy?.name ||\n item.createdById ||\n tWithFallback(t, \"files.info.unknown\", \"Unknown\")}\n </p>\n </div>\n </div>\n </div>\n\n {/* Additional Info — secondary properties tucked behind progressive\n disclosure to keep the rail focused on the essentials. */}\n <div className=\"pt-6 border-t border-border-seam\">\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">\n {tWithFallback(t, \"files.info.properties\", \"Properties\")}\n </h4>\n <ShowMore collapsedHeight={56}>\n <dl className=\"space-y-2\">\n <div className=\"flex justify-between\">\n <dt className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.info.status\", \"Status\")}\n </dt>\n <dd className=\"text-sm font-medium text-text-primary\">\n {item.status}\n </dd>\n </div>\n <div className=\"flex justify-between\">\n <dt className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.info.visibility\", \"Visibility\")}\n </dt>\n <dd className=\"text-sm font-medium text-text-primary\">\n {item.visibility}\n </dd>\n </div>\n <div className=\"flex justify-between\">\n <dt className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.info.starred\", \"Starred\")}\n </dt>\n <dd className=\"text-sm font-medium text-text-primary\">\n {item.starred\n ? tWithFallback(t, \"files.info.yes\", \"Yes\")\n : tWithFallback(t, \"files.info.no\", \"No\")}\n </dd>\n </div>\n </dl>\n </ShowMore>\n </div>\n\n {/* Version History Button (Files only) */}\n {isFile && file && (\n <div className=\"pt-6 border-t border-border-seam\">\n <button\n type=\"button\"\n onClick={() => setShowVersionHistory(true)}\n className=\"w-full flex items-center justify-center gap-2 px-4 py-3 text-sm font-medium text-action-primary-text bg-action-primary-bg/10 hover:bg-action-primary-bg/20 rounded-lg transition-all duration-200\"\n >\n <Clock className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.info.viewVersionHistory\",\n \"View Version History\",\n )}\n </button>\n </div>\n )}\n </div>\n\n {/* Version History Modal */}\n {isFile && file && showVersionHistory && (\n <Suspense\n fallback={\n <div className=\"fixed inset-0 z-50 bg-bg-overlay flex items-center justify-center\">\n <div className=\"bg-bg-surface rounded-lg p-8 animate-in fade-in zoom-in duration-200\">\n <div className=\"flex items-center gap-3\">\n <Clock className=\"size-6 text-action-primary-bg animate-spin\" />\n <span className=\"text-text-primary\">\n {tWithFallback(\n t,\n \"files.info.loadingVersionHistory\",\n \"Loading version history...\",\n )}\n </span>\n </div>\n </div>\n </div>\n }\n >\n <FileVersionPanel\n file={file}\n onClose={() => setShowVersionHistory(false)}\n />\n </Suspense>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;AAgBA,IAAME,IAAmBC,QACvB,OAAO,wBAAqB,CAAC,MAAM,OAAO,EAAE,SAASC,EAAE,iBAAiB,EAAE,CAC5E;AAQA,SAAgBC,EAAc,EAAE,SAAM,SAAM,cAA+B;CACzE,IAAM,EAAE,SAAMC,EAAQ,GAChBC,IAASC,MAAS,QAClBC,IAAOF,IAAUG,IAAoB,MACrCC,IAAUJ,IAAgC,OAAtBG,GACpB,CAACE,GAAoBC,KAAyBC,EAAS,EAAK,GAE5DC,IAAWC,QAAqB;EACpC,AAAIJ,IACFC,EAAsB,EAAK,IAG7BI,EAAQ;CACV,CAAC;CAED,QAAgB;EACd,IAAMC,KAAgB,MAAyB;GAC7C,AAAIC,EAAM,QAAQ,YAChBJ,EAAS;EAEb;EAGA,OADA,SAAS,iBAAiB,WAAWG,CAAY,SACpC,SAAS,oBAAoB,WAAWA,CAAY;CACnE,GAAG,CAAC,CAAC;CAEL,IAAME,KAAc,MACX,IAAI,KAAKC,CAAI,CAAC,CAAC,eAAe,SAAS;EAC5C,MAAM;EACN,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;CACV,CAAC;CAWH,OACE,kBAAC,OAAD;EACE,WAAU;EACV,MAAK;EACL,cAAW;EACX,cACEd,IACIe,EAAcC,GAAG,uBAAuB,kBAAkB,IAC1DD,EAAcC,GAAG,yBAAyB,oBAAoB;EAPtE,UAAA;GAWE,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;KACX,UAAAhB,IACGe,EAAcC,GAAG,uBAAuB,kBAAkB,IAC1DD,EAAcC,GAAG,yBAAyB,oBAAoB;IAChE,CAAA,GACJ,kBAAC,UAAD;KACE,MAAK;KACL,SAASN;KACT,WAAU;KACV,cAAYK,EACVC,GACA,yBACA,yBACF;KAEA,UAAA,kBAACC,GAAD,EAAG,WAAU,SAAU,CAAA;IACjB,CAAA,CACL;;GAGL,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KAEE,kBAACC,GAAD;MACE,WAAU;MACV,WAAU;MAET,UAAAlB,KACDE,GAAM,SAAS,WAAW,QAAQ,MACjCA,EAAK,eAAeA,EAAK,OACxB,kBAAC,OAAD;OACE,KAAKA,EAAK,eAAeA,EAAK;OAC9B,KAAKC,EAAK;OACV,WAAU;MACX,CAAA,IAED,kBAACgB,GAAD,EAAU,WAAU,0BAA2B,CAAA;KAExC,CAAA;KAGX,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;MACX,UAAAhB,EAAK;KACJ,CAAA,GACHA,EAAK,eACJ,kBAAC,KAAD;MAAG,WAAU;MACV,UAAAA,EAAK;KACL,CAAA,CAEF,EAAA,CAAA;KAGL,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA;OACE,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAACgB,GAAD,EAAU,WAAU,gCAAiC,CAAA,GACrD,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAJ,EAAcC,GAAG,mBAAmB,MAAM;QAC1C,CAAA,GACH,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAhB,IACGE,GAAM,YACNa,EAAcC,GAAG,sBAAsB,SAAS,IAChDD,EAAcC,GAAG,qBAAqB,QAAQ;QACjD,CAAA,CACA,EAAA,CAAA,CACF;;OAEJhB,KAAUE,KACT,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAACkB,GAAD,EAAW,WAAU,gCAAiC,CAAA,GACtD,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAL,EAAcC,GAAG,mBAAmB,MAAM;QAC1C,CAAA,GACH,kBAAC,KAAD;SAAG,WAAU;SACV,YAjGG,MACdK,IAAQ,OAAa,GAAGA,EAAM,MAC9BA,IAAQ,UAAoB,IAAIA,IAAQ,KAAA,CAAM,QAAQ,CAAC,EAAE,OACzDA,IAAQ,aACH,IAAIA,IAAQ,OAAO,KAAA,CAAM,QAAQ,CAAC,EAAE,OACtC,IAAIA,IAAQ,OAAO,OAAO,KAAA,CAAM,QAAQ,CAAC,EAAE,KA4FnC,CAAWnB,EAAK,IAAI;QACpB,CAAA,CACA,EAAA,CAAA,CACF;;OAGN,CAACF,KAAUI,KACV,kBAAAX,GAAA,EAAA,UAAA,CACE,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAAC0B,GAAD,EAAU,WAAU,gCAAiC,CAAA,GACrD,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAJ,EAAcC,GAAG,uBAAuB,UAAU;QAClD,CAAA,GACH,kBAAC,KAAD;SAAG,WAAU;SAAb,UAAA;UACGZ,EAAO;UAAY;UACnBW,EAAcC,GAAG,oBAAoB,OAAO;UAAE;UAAE;UAChDZ,EAAO;UAAiB;UACxBW,EAAcC,GAAG,sBAAsB,SAAS;SAChD;QACA,CAAA,CAAA,EAAA,CAAA,CACF;OAEJ,CAAA,GAAAZ,EAAO,QACN,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAACV,GAAD,EAAU,WAAU,gCAAiC,CAAA,GACrD,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAqB,EAAcC,GAAG,mBAAmB,MAAM;QAC1C,CAAA,GACH,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAZ,EAAO;QACP,CAAA,CACA,EAAA,CAAA,CACF;OAEP,CAAA,CAAA,EAAA,CAAA;OAGJ,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAACoB,GAAD,EAAU,WAAU,gCAAiC,CAAA,GACrD,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAT,EAAcC,GAAG,sBAAsB,SAAS;QAChD,CAAA,GACH,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAH,EAAWV,EAAK,SAAS;QACzB,CAAA,CACA,EAAA,CAAA,CACF;;OAEJA,EAAK,aACJ,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAACqB,GAAD,EAAU,WAAU,gCAAiC,CAAA,GACrD,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAT,EAAcC,GAAG,uBAAuB,UAAU;QAClD,CAAA,GACH,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAH,EAAWV,EAAK,SAAS;QACzB,CAAA,CACA,EAAA,CAAA,CACF;;OAGP,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAACsB,GAAD,EAAM,WAAU,gCAAiC,CAAA,GACjD,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAV,EAAcC,GAAG,oBAAoB,OAAO;QAC5C,CAAA,GACH,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAb,EAAK,WAAW,QACfA,EAAK,eACLY,EAAcC,GAAG,sBAAsB,SAAS;QACjD,CAAA,CACA,EAAA,CAAA,CACF;;MACF;;KAIL,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,kBAAC,MAAD;OAAI,WAAU;OACX,UAAAD,EAAcC,GAAG,yBAAyB,YAAY;MACrD,CAAA,GACJ,kBAACU,GAAD;OAAU,iBAAiB;OACzB,UAAA,kBAAC,MAAD;QAAI,WAAU;QAAd,UAAA;SACE,kBAAC,OAAD;UAAK,WAAU;UAAf,UAAA,CACE,kBAAC,MAAD;WAAI,WAAU;WACX,UAAAX,EAAcC,GAAG,qBAAqB,QAAQ;UAC7C,CAAA,GACJ,kBAAC,MAAD;WAAI,WAAU;WACX,UAAAb,EAAK;UACJ,CAAA,CACD;;SACL,kBAAC,OAAD;UAAK,WAAU;UAAf,UAAA,CACE,kBAAC,MAAD;WAAI,WAAU;WACX,UAAAY,EAAcC,GAAG,yBAAyB,YAAY;UACrD,CAAA,GACJ,kBAAC,MAAD;WAAI,WAAU;WACX,UAAAb,EAAK;UACJ,CAAA,CACD;;SACL,kBAAC,OAAD;UAAK,WAAU;UAAf,UAAA,CACE,kBAAC,MAAD;WAAI,WAAU;WACX,UAAAY,EAAcC,GAAG,sBAAsB,SAAS;UAC/C,CAAA,GACJ,kBAAC,MAAD;WAAI,WAAU;WACX,UAAAb,EAAK,UACFY,EAAcC,GAAG,kBAAkB,KAAK,IACxCD,EAAcC,GAAG,iBAAiB,IAAI;UACxC,CAAA,CACD;;QACH;;MACI,CAAA,CACP;;KAGJhB,KAAUE,KACT,kBAAC,OAAD;MAAK,WAAU;MACb,UAAA,kBAAC,UAAD;OACE,MAAK;OACL,eAAeI,EAAsB,EAAI;OACzC,WAAU;OAHZ,UAAA,CAKE,kBAACqB,GAAD,EAAO,WAAU,SAAU,CAAA,GAC1BZ,EACCC,GACA,iCACA,sBACF,CACM;;KACL,CAAA;IAEJ;;GAGJhB,KAAUE,KAAQG,KACjB,kBAACuB,GAAD;IACE,UACE,kBAAC,OAAD;KAAK,WAAU;KACb,UAAA,kBAAC,OAAD;MAAK,WAAU;MACb,UAAA,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,kBAACD,GAAD,EAAO,WAAU,6CAA8C,CAAA,GAC/D,kBAAC,QAAD;QAAM,WAAU;QACb,UAAAZ,EACCC,GACA,oCACA,4BACF;OACI,CAAA,CACH;;KACF,CAAA;IACF,CAAA;IAGP,UAAA,kBAACrB,GAAD;KACQ;KACN,eAAeW,EAAsB,EAAK;IAC3C,CAAA;GACO,CAAA;EAET;;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileListItem.d.ts","sourceRoot":"","sources":["../../../src/files/components/FileListItem.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,EAAqB,MAAM,OAAO,CAAC;AAcnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAOzC,UAAU,iBAAiB;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACpC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACrC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACtC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACnE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAChE;AAED,UAAU,0BAA2B,SAAQ,IAAI,CAC/C,iBAAiB,EACjB,aAAa,GAAG,WAAW,CAC5B;IACC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACnE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,0BAA0B,
|
|
1
|
+
{"version":3,"file":"FileListItem.d.ts","sourceRoot":"","sources":["../../../src/files/components/FileListItem.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,EAAqB,MAAM,OAAO,CAAC;AAcnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAOzC,UAAU,iBAAiB;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACpC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACrC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACtC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACnE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAChE;AAED,UAAU,0BAA2B,SAAQ,IAAI,CAC/C,iBAAiB,EACjB,aAAa,GAAG,WAAW,CAC5B;IACC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACnE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,0BAA0B,CAuYvD,CAAC"}
|
|
@@ -96,7 +96,7 @@ var S = ({ file: S, isSelected: C = !1, isDragging: w = !1, onSelect: T, onPrevi
|
|
|
96
96
|
onClick: W,
|
|
97
97
|
onContextMenu: Y,
|
|
98
98
|
onKeyDown: (e) => {
|
|
99
|
-
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), W());
|
|
99
|
+
e.target === e.currentTarget && (e.key === "Enter" || e.key === " ") && (e.preventDefault(), W());
|
|
100
100
|
},
|
|
101
101
|
draggable: !!L,
|
|
102
102
|
onDragStart: q,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileListItem.js","names":[],"sources":["../../../src/files/components/FileListItem.tsx"],"sourcesContent":["import { type FC, useMemo, useState } from \"react\";\nimport {\n Download,\n Share2,\n Trash2,\n Star,\n RotateCcw,\n Edit,\n Copy,\n FolderInput,\n Info,\n Activity,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem } from \"../types\";\nimport { formatFileSize, formatFileDate, getFileIcon } from \"../utils\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { ActionMenu } from \"./ActionMenu\";\nimport { getDragOperation } from \"../hooks/useDragDrop\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface FileListItemProps {\n file: FileItem;\n isSelected?: boolean;\n isDragging?: boolean;\n onSelect?: (fileId: string) => void;\n onPreview?: (file: FileItem) => void;\n onShare?: (file: FileItem) => void;\n onDelete?: (file: FileItem) => void;\n onRestore?: (file: FileItem) => void;\n onFavorite?: (file: FileItem) => void;\n onRename?: (file: FileItem) => void;\n onDownload?: (file: FileItem) => void;\n onCopy?: (file: FileItem) => void;\n onMove?: (file: FileItem) => void;\n onInfo?: (file: FileItem) => void;\n onActivity?: (file: FileItem) => void;\n onDragStart?: (file: FileItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onContextMenu?: (file: FileItem, x: number, y: number) => void;\n}\n\ninterface DraggableFileListItemProps extends Omit<\n FileListItemProps,\n \"onDragStart\" | \"onDragEnd\"\n> {\n onDragStart?: (file: FileItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n}\n\nexport const FileListItem: FC<DraggableFileListItemProps> = ({\n file,\n isSelected = false,\n isDragging = false,\n onSelect,\n onPreview,\n onShare,\n onDelete,\n onRestore,\n onFavorite,\n onRename,\n onDownload,\n onCopy,\n onMove,\n onInfo,\n onActivity,\n onDragStart,\n onDragEnd,\n onContextMenu,\n}) => {\n const { t } = useI18n();\n const [menuOpen, setMenuOpen] = useState(false);\n const { toggleFileSelection } = useFilesStore();\n\n const openPreview = () => {\n if (onPreview) {\n onPreview(file);\n }\n };\n\n const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n e.stopPropagation();\n if (onSelect) {\n onSelect(file.id);\n } else {\n toggleFileSelection(file.id);\n }\n };\n\n const handleActionClick = (e: React.MouseEvent, action: () => void) => {\n e.stopPropagation();\n action();\n };\n\n const handleDragStart = (e: React.DragEvent<HTMLDivElement>) => {\n e.dataTransfer.effectAllowed = \"copyMove\";\n e.dataTransfer.setData(\"application/x-file-id\", file.id);\n e.dataTransfer.setData(\"application/x-file-type\", \"file\");\n const operation = getDragOperation(e);\n e.dataTransfer.setData(\"application/x-drag-operation\", operation);\n onDragStart?.(file, operation);\n };\n\n const handleDragEnd = () => {\n onDragEnd?.();\n };\n\n const handleContextMenu = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onContextMenu?.(file, e.clientX, e.clientY);\n };\n\n const FileIconComponent = getFileIcon(file.mimeType);\n\n // Memoize menu items to prevent re-renders\n const menuItems = useMemo(\n () => [\n ...(onShare\n ? [\n {\n label: tWithFallback(t, \"files.card.share\", \"Share\"),\n icon: <Share2 className=\"size-4\" />,\n onClick: () => onShare(file),\n },\n ]\n : []),\n ...(onDownload\n ? [\n {\n label: tWithFallback(t, \"files.card.download\", \"Download\"),\n icon: <Download className=\"size-4\" />,\n onClick: () => onDownload(file),\n },\n ]\n : []),\n ...(onCopy\n ? [\n {\n label: tWithFallback(t, \"files.card.makeCopy\", \"Make a copy\"),\n icon: <Copy className=\"size-4\" />,\n onClick: () => onCopy(file),\n },\n ]\n : []),\n ...(onMove\n ? [\n {\n label: tWithFallback(t, \"files.card.moveTo\", \"Move to\"),\n icon: <FolderInput className=\"size-4\" />,\n onClick: () => onMove(file),\n },\n ]\n : []),\n ...(onRename\n ? [\n {\n label: tWithFallback(t, \"files.card.rename\", \"Rename\"),\n icon: <Edit className=\"size-4\" />,\n onClick: () => onRename(file),\n divider: true,\n },\n ]\n : []),\n ...(onFavorite\n ? [\n {\n label: file.starred\n ? tWithFallback(\n t,\n \"files.card.removeFromStarred\",\n \"Remove from starred\",\n )\n : tWithFallback(t, \"files.card.addToStarred\", \"Add to starred\"),\n icon: <Star className=\"size-4\" />,\n onClick: () => onFavorite(file),\n },\n ]\n : []),\n ...(onInfo\n ? [\n {\n label: tWithFallback(t, \"files.card.details\", \"Details\"),\n icon: <Info className=\"size-4\" />,\n onClick: () => onInfo(file),\n },\n ]\n : []),\n ...(onActivity\n ? [\n {\n label: tWithFallback(t, \"files.card.activity\", \"Activity\"),\n icon: <Activity className=\"size-4\" />,\n onClick: () => onActivity(file),\n },\n ]\n : []),\n ...(onDelete\n ? [\n {\n label: tWithFallback(t, \"files.card.delete\", \"Delete\"),\n icon: <Trash2 className=\"size-4\" />,\n onClick: () => onDelete(file),\n variant: \"danger\" as const,\n divider: true,\n },\n ]\n : []),\n ...(onRestore\n ? [\n {\n label: tWithFallback(t, \"files.card.restore\", \"Restore\"),\n icon: <RotateCcw className=\"size-4\" />,\n onClick: () => onRestore(file),\n },\n ]\n : []),\n ],\n [\n file,\n onShare,\n onDownload,\n onCopy,\n onMove,\n onRename,\n onFavorite,\n onInfo,\n onActivity,\n onDelete,\n onRestore,\n t,\n ],\n );\n\n return (\n <div\n className={`@container group flex items-center gap-3 border-b border-border-seam bg-bg-surface p-3 transition-colors hover:bg-bg-sunken focus-within:bg-bg-sunken ${isDragging ? \"opacity-50\" : \"\"}`}\n onClick={openPreview}\n onContextMenu={handleContextMenu}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n openPreview();\n }\n }}\n draggable={Boolean(onDragStart)}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n role=\"button\"\n tabIndex={0}\n aria-label={`Preview ${file.name}`}\n >\n {/* Selection checkbox */}\n <div className=\"flex-shrink-0\">\n <input\n type=\"checkbox\"\n checked={isSelected}\n onChange={handleCheckboxChange}\n className=\"size-4 rounded border-border-default bg-bg-surface text-action-primary-bg focus:ring-2 focus:ring-action-primary-bg focus:ring-offset-2\"\n aria-label={`Select ${file.name}`}\n />\n </div>\n\n {/* File icon */}\n <div className=\"flex-shrink-0\">\n {file.thumbnailUrl ? (\n <img\n src={file.thumbnailUrl}\n alt={file.name}\n className=\"size-8 object-cover rounded\"\n />\n ) : (\n <FileIconComponent className=\"size-6 text-text-muted\" />\n )}\n </div>\n\n {/* File name - takes remaining space */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-text-md font-weight-medium text-text-primary truncate\">\n {file.name}\n </span>\n {file.starred && (\n <Star className=\"size-3 flex-shrink-0 fill-yellow-400 text-yellow-400\" />\n )}\n {file.isShared && (\n <Share2 className=\"size-3 flex-shrink-0 text-text-muted\" />\n )}\n </div>\n\n {/* Tags - visible on medium+ containers */}\n {file.tags && file.tags.length > 0 && (\n <div className=\"hidden @md:flex flex-wrap gap-1 mt-1\">\n {file.tags.slice(0, 3).map((tag) => (\n <span\n key={tag}\n className=\"px-1.5 py-0.5 bg-bg-accent text-text-primary font-text-xs rounded-sm\"\n >\n {tag}\n </span>\n ))}\n {file.tags.length > 3 && (\n <span className=\"text-text-muted font-text-xs\">\n +{file.tags.length - 3}\n </span>\n )}\n </div>\n )}\n </div>\n\n {/* Owner - visible on large+ containers */}\n {file.createdBy && (\n <div className=\"hidden @lg:flex items-center gap-2 flex-shrink-0 w-40\">\n {file.createdBy.avatar && (\n <img\n src={file.createdBy.avatar}\n alt={file.createdBy.name}\n className=\"size-6 rounded-full\"\n />\n )}\n <span className=\"font-text-sm text-text-secondary truncate\">\n {file.createdBy.name}\n </span>\n </div>\n )}\n\n {/* Size - visible on medium+ containers */}\n <div className=\"hidden @md:block flex-shrink-0 w-24 text-right\">\n <span className=\"font-text-sm text-text-secondary tabular-nums\">\n {formatFileSize(file.size)}\n </span>\n </div>\n\n {/* Modified date - visible on large+ containers */}\n <div className=\"hidden @lg:block flex-shrink-0 w-32 text-right\">\n <span className=\"font-text-sm text-text-secondary\">\n {formatFileDate(file.updatedAt)}\n </span>\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-1\">\n <div className=\"flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100\">\n {file.canRead && onDownload && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onDownload(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.download\", \"Download\")}\n title={tWithFallback(t, \"files.card.download\", \"Download\")}\n >\n <Download className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {onShare && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onShare(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.share\", \"Share\")}\n title={tWithFallback(t, \"files.card.share\", \"Share\")}\n >\n <Share2 className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {onFavorite && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onFavorite(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={\n file.starred\n ? tWithFallback(t, \"files.card.unfavorite\", \"Unfavorite\")\n : tWithFallback(t, \"files.card.favorite\", \"Favorite\")\n }\n title={\n file.starred\n ? tWithFallback(t, \"files.card.unfavorite\", \"Unfavorite\")\n : tWithFallback(t, \"files.card.favorite\", \"Favorite\")\n }\n >\n <Star\n className={`size-4 ${\n file.starred\n ? \"fill-status-warning-bg text-status-warning-bg\"\n : \"text-text-primary\"\n }`}\n />\n </button>\n )}\n\n {onRestore && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onRestore(file))}\n className=\"p-1.5 hover:bg-status-success-bg-subtle rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n title={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n >\n <RotateCcw className=\"size-4 text-status-success-text\" />\n </button>\n )}\n\n {file.canWrite && onRename && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onRename(file))}\n className=\"hidden @md:block p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.rename\", \"Rename\")}\n title={tWithFallback(t, \"files.card.rename\", \"Rename\")}\n >\n <Edit className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {file.canDelete && onDelete && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onDelete(file))}\n className=\"p-1.5 hover:bg-action-danger-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.delete\", \"Delete\")}\n title={tWithFallback(t, \"files.card.delete\", \"Delete\")}\n >\n <Trash2 className=\"size-4 text-status-error-text\" />\n </button>\n )}\n </div>\n\n {/* More actions dropdown - always visible */}\n <ActionMenu\n items={menuItems}\n align=\"right\"\n isOpen={menuOpen}\n onToggle={setMenuOpen}\n />\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FileListItem.js","names":["FileListItem","useI18n","menuOpen","setMenuOpen","useState","useFilesStore","openPreview","onPreview","file","handleCheckboxChange","onSelect","toggleFileSelection","handleActionClick","action","handleDragStart","operation","getDragOperation","onDragStart","handleDragEnd","handleContextMenu","onContextMenu","FileIconComponent","getFileIcon","menuItems","useMemo","onShare","tWithFallback","t","Share2","onDownload","Download","onCopy","Copy","onMove","FolderInput","onRename","Edit","onFavorite","Star","onInfo","Info","onActivity","Activity","onDelete","Trash2","onRestore","RotateCcw","isDragging","event","isSelected","tag","formatFileSize","formatFileDate","ActionMenu"],"sources":["../../../src/files/components/FileListItem.tsx"],"sourcesContent":["import { type FC, useMemo, useState } from \"react\";\nimport {\n Download,\n Share2,\n Trash2,\n Star,\n RotateCcw,\n Edit,\n Copy,\n FolderInput,\n Info,\n Activity,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem } from \"../types\";\nimport { formatFileSize, formatFileDate, getFileIcon } from \"../utils\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { ActionMenu } from \"./ActionMenu\";\nimport { getDragOperation } from \"../hooks/useDragDrop\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface FileListItemProps {\n file: FileItem;\n isSelected?: boolean;\n isDragging?: boolean;\n onSelect?: (fileId: string) => void;\n onPreview?: (file: FileItem) => void;\n onShare?: (file: FileItem) => void;\n onDelete?: (file: FileItem) => void;\n onRestore?: (file: FileItem) => void;\n onFavorite?: (file: FileItem) => void;\n onRename?: (file: FileItem) => void;\n onDownload?: (file: FileItem) => void;\n onCopy?: (file: FileItem) => void;\n onMove?: (file: FileItem) => void;\n onInfo?: (file: FileItem) => void;\n onActivity?: (file: FileItem) => void;\n onDragStart?: (file: FileItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onContextMenu?: (file: FileItem, x: number, y: number) => void;\n}\n\ninterface DraggableFileListItemProps extends Omit<\n FileListItemProps,\n \"onDragStart\" | \"onDragEnd\"\n> {\n onDragStart?: (file: FileItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n}\n\nexport const FileListItem: FC<DraggableFileListItemProps> = ({\n file,\n isSelected = false,\n isDragging = false,\n onSelect,\n onPreview,\n onShare,\n onDelete,\n onRestore,\n onFavorite,\n onRename,\n onDownload,\n onCopy,\n onMove,\n onInfo,\n onActivity,\n onDragStart,\n onDragEnd,\n onContextMenu,\n}) => {\n const { t } = useI18n();\n const [menuOpen, setMenuOpen] = useState(false);\n const { toggleFileSelection } = useFilesStore();\n\n const openPreview = () => {\n if (onPreview) {\n onPreview(file);\n }\n };\n\n const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n e.stopPropagation();\n if (onSelect) {\n onSelect(file.id);\n } else {\n toggleFileSelection(file.id);\n }\n };\n\n const handleActionClick = (e: React.MouseEvent, action: () => void) => {\n e.stopPropagation();\n action();\n };\n\n const handleDragStart = (e: React.DragEvent<HTMLDivElement>) => {\n e.dataTransfer.effectAllowed = \"copyMove\";\n e.dataTransfer.setData(\"application/x-file-id\", file.id);\n e.dataTransfer.setData(\"application/x-file-type\", \"file\");\n const operation = getDragOperation(e);\n e.dataTransfer.setData(\"application/x-drag-operation\", operation);\n onDragStart?.(file, operation);\n };\n\n const handleDragEnd = () => {\n onDragEnd?.();\n };\n\n const handleContextMenu = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onContextMenu?.(file, e.clientX, e.clientY);\n };\n\n const FileIconComponent = getFileIcon(file.mimeType);\n\n // Memoize menu items to prevent re-renders\n const menuItems = useMemo(\n () => [\n ...(onShare\n ? [\n {\n label: tWithFallback(t, \"files.card.share\", \"Share\"),\n icon: <Share2 className=\"size-4\" />,\n onClick: () => onShare(file),\n },\n ]\n : []),\n ...(onDownload\n ? [\n {\n label: tWithFallback(t, \"files.card.download\", \"Download\"),\n icon: <Download className=\"size-4\" />,\n onClick: () => onDownload(file),\n },\n ]\n : []),\n ...(onCopy\n ? [\n {\n label: tWithFallback(t, \"files.card.makeCopy\", \"Make a copy\"),\n icon: <Copy className=\"size-4\" />,\n onClick: () => onCopy(file),\n },\n ]\n : []),\n ...(onMove\n ? [\n {\n label: tWithFallback(t, \"files.card.moveTo\", \"Move to\"),\n icon: <FolderInput className=\"size-4\" />,\n onClick: () => onMove(file),\n },\n ]\n : []),\n ...(onRename\n ? [\n {\n label: tWithFallback(t, \"files.card.rename\", \"Rename\"),\n icon: <Edit className=\"size-4\" />,\n onClick: () => onRename(file),\n divider: true,\n },\n ]\n : []),\n ...(onFavorite\n ? [\n {\n label: file.starred\n ? tWithFallback(\n t,\n \"files.card.removeFromStarred\",\n \"Remove from starred\",\n )\n : tWithFallback(t, \"files.card.addToStarred\", \"Add to starred\"),\n icon: <Star className=\"size-4\" />,\n onClick: () => onFavorite(file),\n },\n ]\n : []),\n ...(onInfo\n ? [\n {\n label: tWithFallback(t, \"files.card.details\", \"Details\"),\n icon: <Info className=\"size-4\" />,\n onClick: () => onInfo(file),\n },\n ]\n : []),\n ...(onActivity\n ? [\n {\n label: tWithFallback(t, \"files.card.activity\", \"Activity\"),\n icon: <Activity className=\"size-4\" />,\n onClick: () => onActivity(file),\n },\n ]\n : []),\n ...(onDelete\n ? [\n {\n label: tWithFallback(t, \"files.card.delete\", \"Delete\"),\n icon: <Trash2 className=\"size-4\" />,\n onClick: () => onDelete(file),\n variant: \"danger\" as const,\n divider: true,\n },\n ]\n : []),\n ...(onRestore\n ? [\n {\n label: tWithFallback(t, \"files.card.restore\", \"Restore\"),\n icon: <RotateCcw className=\"size-4\" />,\n onClick: () => onRestore(file),\n },\n ]\n : []),\n ],\n [\n file,\n onShare,\n onDownload,\n onCopy,\n onMove,\n onRename,\n onFavorite,\n onInfo,\n onActivity,\n onDelete,\n onRestore,\n t,\n ],\n );\n\n return (\n <div\n className={`@container group flex items-center gap-3 border-b border-border-seam bg-bg-surface p-3 transition-colors hover:bg-bg-sunken focus-within:bg-bg-sunken ${isDragging ? \"opacity-50\" : \"\"}`}\n onClick={openPreview}\n onContextMenu={handleContextMenu}\n onKeyDown={(event) => {\n if (event.target !== event.currentTarget) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n openPreview();\n }\n }}\n draggable={Boolean(onDragStart)}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n role=\"button\"\n tabIndex={0}\n aria-label={`Preview ${file.name}`}\n >\n {/* Selection checkbox */}\n <div className=\"flex-shrink-0\">\n <input\n type=\"checkbox\"\n checked={isSelected}\n onChange={handleCheckboxChange}\n className=\"size-4 rounded border-border-default bg-bg-surface text-action-primary-bg focus:ring-2 focus:ring-action-primary-bg focus:ring-offset-2\"\n aria-label={`Select ${file.name}`}\n />\n </div>\n\n {/* File icon */}\n <div className=\"flex-shrink-0\">\n {file.thumbnailUrl ? (\n <img\n src={file.thumbnailUrl}\n alt={file.name}\n className=\"size-8 object-cover rounded\"\n />\n ) : (\n <FileIconComponent className=\"size-6 text-text-muted\" />\n )}\n </div>\n\n {/* File name - takes remaining space */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-text-md font-weight-medium text-text-primary truncate\">\n {file.name}\n </span>\n {file.starred && (\n <Star className=\"size-3 flex-shrink-0 fill-yellow-400 text-yellow-400\" />\n )}\n {file.isShared && (\n <Share2 className=\"size-3 flex-shrink-0 text-text-muted\" />\n )}\n </div>\n\n {/* Tags - visible on medium+ containers */}\n {file.tags && file.tags.length > 0 && (\n <div className=\"hidden @md:flex flex-wrap gap-1 mt-1\">\n {file.tags.slice(0, 3).map((tag) => (\n <span\n key={tag}\n className=\"px-1.5 py-0.5 bg-bg-accent text-text-primary font-text-xs rounded-sm\"\n >\n {tag}\n </span>\n ))}\n {file.tags.length > 3 && (\n <span className=\"text-text-muted font-text-xs\">\n +{file.tags.length - 3}\n </span>\n )}\n </div>\n )}\n </div>\n\n {/* Owner - visible on large+ containers */}\n {file.createdBy && (\n <div className=\"hidden @lg:flex items-center gap-2 flex-shrink-0 w-40\">\n {file.createdBy.avatar && (\n <img\n src={file.createdBy.avatar}\n alt={file.createdBy.name}\n className=\"size-6 rounded-full\"\n />\n )}\n <span className=\"font-text-sm text-text-secondary truncate\">\n {file.createdBy.name}\n </span>\n </div>\n )}\n\n {/* Size - visible on medium+ containers */}\n <div className=\"hidden @md:block flex-shrink-0 w-24 text-right\">\n <span className=\"font-text-sm text-text-secondary tabular-nums\">\n {formatFileSize(file.size)}\n </span>\n </div>\n\n {/* Modified date - visible on large+ containers */}\n <div className=\"hidden @lg:block flex-shrink-0 w-32 text-right\">\n <span className=\"font-text-sm text-text-secondary\">\n {formatFileDate(file.updatedAt)}\n </span>\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-1\">\n <div className=\"flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100\">\n {file.canRead && onDownload && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onDownload(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.download\", \"Download\")}\n title={tWithFallback(t, \"files.card.download\", \"Download\")}\n >\n <Download className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {onShare && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onShare(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.share\", \"Share\")}\n title={tWithFallback(t, \"files.card.share\", \"Share\")}\n >\n <Share2 className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {onFavorite && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onFavorite(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={\n file.starred\n ? tWithFallback(t, \"files.card.unfavorite\", \"Unfavorite\")\n : tWithFallback(t, \"files.card.favorite\", \"Favorite\")\n }\n title={\n file.starred\n ? tWithFallback(t, \"files.card.unfavorite\", \"Unfavorite\")\n : tWithFallback(t, \"files.card.favorite\", \"Favorite\")\n }\n >\n <Star\n className={`size-4 ${\n file.starred\n ? \"fill-status-warning-bg text-status-warning-bg\"\n : \"text-text-primary\"\n }`}\n />\n </button>\n )}\n\n {onRestore && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onRestore(file))}\n className=\"p-1.5 hover:bg-status-success-bg-subtle rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n title={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n >\n <RotateCcw className=\"size-4 text-status-success-text\" />\n </button>\n )}\n\n {file.canWrite && onRename && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onRename(file))}\n className=\"hidden @md:block p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.rename\", \"Rename\")}\n title={tWithFallback(t, \"files.card.rename\", \"Rename\")}\n >\n <Edit className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {file.canDelete && onDelete && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onDelete(file))}\n className=\"p-1.5 hover:bg-action-danger-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.delete\", \"Delete\")}\n title={tWithFallback(t, \"files.card.delete\", \"Delete\")}\n >\n <Trash2 className=\"size-4 text-status-error-text\" />\n </button>\n )}\n </div>\n\n {/* More actions dropdown - always visible */}\n <ActionMenu\n items={menuItems}\n align=\"right\"\n isOpen={menuOpen}\n onToggle={setMenuOpen}\n />\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;AAkDA,IAAaA,KAAgD,EAC3D,SACA,gBAAa,IACb,gBAAa,IACb,aACA,cACA,YACA,aACA,cACA,eACA,aACA,eACA,WACA,WACA,WACA,eACA,gBACA,cACA,uBACI;CACJ,IAAM,EAAE,SAAMC,EAAQ,GAChB,CAACC,GAAUC,KAAeC,EAAS,EAAK,GACxC,EAAE,2BAAwBC,EAAc,GAExCC,UAAoB;EACxB,AAAIC,KACFA,EAAUC,CAAI;CAElB,GAEMC,KAAwB,MAA2C;EAEvE,AADA,EAAE,gBAAgB,GACdC,IACFA,EAASF,EAAK,EAAE,IAEhBG,EAAoBH,EAAK,EAAE;CAE/B,GAEMI,KAAqB,GAAqB,MAAuB;EAErE,AADA,EAAE,gBAAgB,GAClBC,EAAO;CACT,GAEMC,KAAmB,MAAuC;EAG9D,AAFA,EAAE,aAAa,gBAAgB,YAC/B,EAAE,aAAa,QAAQ,yBAAyBN,EAAK,EAAE,GACvD,EAAE,aAAa,QAAQ,2BAA2B,MAAM;EACxD,IAAMO,IAAYC,EAAiB,CAAC;EAEpC,AADA,EAAE,aAAa,QAAQ,gCAAgCD,CAAS,GAChEE,IAAcT,GAAMO,CAAS;CAC/B,GAEMG,UAAsB;EAC1B,IAAY;CACd,GAEMC,KAAqB,MAAwB;EAGjD,AAFA,EAAE,eAAe,GACjB,EAAE,gBAAgB,GAClBC,IAAgBZ,GAAM,EAAE,SAAS,EAAE,OAAO;CAC5C,GAEMa,IAAoBC,EAAYd,EAAK,QAAQ,GAG7Ce,IAAYC,QACV;EACJ,GAAIC,IACA,CACE;GACE,OAAOC,EAAcC,GAAG,oBAAoB,OAAO;GACnD,MAAM,kBAACC,GAAD,EAAQ,WAAU,SAAU,CAAA;GAClC,eAAeH,EAAQjB,CAAI;EAC7B,CACF,IACA,CAAC;EACL,GAAIqB,IACA,CACE;GACE,OAAOH,EAAcC,GAAG,uBAAuB,UAAU;GACzD,MAAM,kBAACG,GAAD,EAAU,WAAU,SAAU,CAAA;GACpC,eAAeD,EAAWrB,CAAI;EAChC,CACF,IACA,CAAC;EACL,GAAIuB,IACA,CACE;GACE,OAAOL,EAAcC,GAAG,uBAAuB,aAAa;GAC5D,MAAM,kBAACK,GAAD,EAAM,WAAU,SAAU,CAAA;GAChC,eAAeD,EAAOvB,CAAI;EAC5B,CACF,IACA,CAAC;EACL,GAAIyB,IACA,CACE;GACE,OAAOP,EAAcC,GAAG,qBAAqB,SAAS;GACtD,MAAM,kBAACO,GAAD,EAAa,WAAU,SAAU,CAAA;GACvC,eAAeD,EAAOzB,CAAI;EAC5B,CACF,IACA,CAAC;EACL,GAAI2B,IACA,CACE;GACE,OAAOT,EAAcC,GAAG,qBAAqB,QAAQ;GACrD,MAAM,kBAACS,GAAD,EAAM,WAAU,SAAU,CAAA;GAChC,eAAeD,EAAS3B,CAAI;GAC5B,SAAS;EACX,CACF,IACA,CAAC;EACL,GAAI6B,IACA,CACE;GACE,OAAO7B,EAAK,UACRkB,EACEC,GACA,gCACA,qBACF,IACAD,EAAcC,GAAG,2BAA2B,gBAAgB;GAChE,MAAM,kBAACW,GAAD,EAAM,WAAU,SAAU,CAAA;GAChC,eAAeD,EAAW7B,CAAI;EAChC,CACF,IACA,CAAC;EACL,GAAI+B,IACA,CACE;GACE,OAAOb,EAAcC,GAAG,sBAAsB,SAAS;GACvD,MAAM,kBAACa,GAAD,EAAM,WAAU,SAAU,CAAA;GAChC,eAAeD,EAAO/B,CAAI;EAC5B,CACF,IACA,CAAC;EACL,GAAIiC,IACA,CACE;GACE,OAAOf,EAAcC,GAAG,uBAAuB,UAAU;GACzD,MAAM,kBAACe,GAAD,EAAU,WAAU,SAAU,CAAA;GACpC,eAAeD,EAAWjC,CAAI;EAChC,CACF,IACA,CAAC;EACL,GAAImC,IACA,CACE;GACE,OAAOjB,EAAcC,GAAG,qBAAqB,QAAQ;GACrD,MAAM,kBAACiB,GAAD,EAAQ,WAAU,SAAU,CAAA;GAClC,eAAeD,EAASnC,CAAI;GAC5B,SAAS;GACT,SAAS;EACX,CACF,IACA,CAAC;EACL,GAAIqC,IACA,CACE;GACE,OAAOnB,EAAcC,GAAG,sBAAsB,SAAS;GACvD,MAAM,kBAACmB,GAAD,EAAW,WAAU,SAAU,CAAA;GACrC,eAAeD,EAAUrC,CAAI;EAC/B,CACF,IACA,CAAC;CACP,GACA;EACEA;EACAiB;EACAI;EACAE;EACAE;EACAE;EACAE;EACAE;EACAE;EACAE;EACAE;EACAlB;CACF,CACF;CAEA,OACE,kBAAC,OAAD;EACE,WAAW,yJAAyJoB,IAAa,eAAe;EAChM,SAASzC;EACT,eAAea;EACf,YAAY,MAAU;GACpB,AAAI6B,EAAM,WAAWA,EAAM,kBACvBA,EAAM,QAAQ,WAAWA,EAAM,QAAQ,SACzCA,EAAM,eAAe,GACrB1C,EAAY;EAEhB;EACA,WAAW,EAAQW;EACnB,aAAaH;EACb,WAAWI;EACX,MAAK;EACL,UAAU;EACV,cAAY,WAAWV,EAAK;EAhB9B,UAAA;GAmBE,kBAAC,OAAD;IAAK,WAAU;IACb,UAAA,kBAAC,SAAD;KACE,MAAK;KACL,SAASyC;KACT,UAAUxC;KACV,WAAU;KACV,cAAY,UAAUD,EAAK;IAC5B,CAAA;GACE,CAAA;GAGL,kBAAC,OAAD;IAAK,WAAU;IACZ,UAAAA,EAAK,eACJ,kBAAC,OAAD;KACE,KAAKA,EAAK;KACV,KAAKA,EAAK;KACV,WAAU;IACX,CAAA,IAED,kBAACa,GAAD,EAAmB,WAAU,yBAA0B,CAAA;GAEtD,CAAA;GAGL,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACE,kBAAC,QAAD;OAAM,WAAU;OACb,UAAAb,EAAK;MACF,CAAA;MACLA,EAAK,WACJ,kBAAC8B,GAAD,EAAM,WAAU,uDAAwD,CAAA;MAEzE9B,EAAK,YACJ,kBAACoB,GAAD,EAAQ,WAAU,uCAAwC,CAAA;KAEzD;IAGJ,CAAA,GAAApB,EAAK,QAAQA,EAAK,KAAK,SAAS,KAC/B,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACGA,EAAK,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,MAC1B,kBAAC,QAAD;MAEE,WAAU;MAET,UAAA0C;KACG,GAJCA,CAID,CACP,GACA1C,EAAK,KAAK,SAAS,KAClB,kBAAC,QAAD;MAAM,WAAU;MAAhB,UAAA,CAA+C,KAC3CA,EAAK,KAAK,SAAS,CACjB;KAEL,CAAA,CAAA;IAEJ,CAAA,CAAA;;GAGJA,EAAK,aACJ,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACGA,EAAK,UAAU,UACd,kBAAC,OAAD;KACE,KAAKA,EAAK,UAAU;KACpB,KAAKA,EAAK,UAAU;KACpB,WAAU;IACX,CAAA,GAEH,kBAAC,QAAD;KAAM,WAAU;KACb,UAAAA,EAAK,UAAU;IACZ,CAAA,CACH;;GAIP,kBAAC,OAAD;IAAK,WAAU;IACb,UAAA,kBAAC,QAAD;KAAM,WAAU;KACb,UAAA2C,EAAe3C,EAAK,IAAI;IACrB,CAAA;GACH,CAAA;GAGL,kBAAC,OAAD;IAAK,WAAU;IACb,UAAA,kBAAC,QAAD;KAAM,WAAU;KACb,UAAA4C,EAAe5C,EAAK,SAAS;IAC1B,CAAA;GACH,CAAA;GAGL,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACGA,EAAK,WAAWqB,KACf,kBAAC,UAAD;OACE,MAAK;OACL,UAAU,MAAMjB,EAAkB,SAASiB,EAAWrB,CAAI,CAAC;OAC3D,WAAU;OACV,cAAYkB,EAAcC,GAAG,uBAAuB,UAAU;OAC9D,OAAOD,EAAcC,GAAG,uBAAuB,UAAU;OAEzD,UAAA,kBAACG,GAAD,EAAU,WAAU,2BAA4B,CAAA;MAC1C,CAAA;MAGTL,KACC,kBAAC,UAAD;OACE,MAAK;OACL,UAAU,MAAMb,EAAkB,SAASa,EAAQjB,CAAI,CAAC;OACxD,WAAU;OACV,cAAYkB,EAAcC,GAAG,oBAAoB,OAAO;OACxD,OAAOD,EAAcC,GAAG,oBAAoB,OAAO;OAEnD,UAAA,kBAACC,GAAD,EAAQ,WAAU,2BAA4B,CAAA;MACxC,CAAA;MAGTS,KACC,kBAAC,UAAD;OACE,MAAK;OACL,UAAU,MAAMzB,EAAkB,SAASyB,EAAW7B,CAAI,CAAC;OAC3D,WAAU;OACV,cACEA,EAAK,UACDkB,EAAcC,GAAG,yBAAyB,YAAY,IACtDD,EAAcC,GAAG,uBAAuB,UAAU;OAExD,OACEnB,EAAK,UACDkB,EAAcC,GAAG,yBAAyB,YAAY,IACtDD,EAAcC,GAAG,uBAAuB,UAAU;OAGxD,UAAA,kBAACW,GAAD,EACE,WAAW,UACT9B,EAAK,UACD,kDACA,sBAEP,CAAA;MACK,CAAA;MAGTqC,KACC,kBAAC,UAAD;OACE,MAAK;OACL,UAAU,MAAMjC,EAAkB,SAASiC,EAAUrC,CAAI,CAAC;OAC1D,WAAU;OACV,cAAYkB,EAAcC,GAAG,sBAAsB,SAAS;OAC5D,OAAOD,EAAcC,GAAG,sBAAsB,SAAS;OAEvD,UAAA,kBAACmB,GAAD,EAAW,WAAU,kCAAmC,CAAA;MAClD,CAAA;MAGTtC,EAAK,YAAY2B,KAChB,kBAAC,UAAD;OACE,MAAK;OACL,UAAU,MAAMvB,EAAkB,SAASuB,EAAS3B,CAAI,CAAC;OACzD,WAAU;OACV,cAAYkB,EAAcC,GAAG,qBAAqB,QAAQ;OAC1D,OAAOD,EAAcC,GAAG,qBAAqB,QAAQ;OAErD,UAAA,kBAACS,GAAD,EAAM,WAAU,2BAA4B,CAAA;MACtC,CAAA;MAGT5B,EAAK,aAAamC,KACjB,kBAAC,UAAD;OACE,MAAK;OACL,UAAU,MAAM/B,EAAkB,SAAS+B,EAASnC,CAAI,CAAC;OACzD,WAAU;OACV,cAAYkB,EAAcC,GAAG,qBAAqB,QAAQ;OAC1D,OAAOD,EAAcC,GAAG,qBAAqB,QAAQ;OAErD,UAAA,kBAACiB,GAAD,EAAQ,WAAU,gCAAiC,CAAA;MAC7C,CAAA;KAEP;IAGL,CAAA,GAAA,kBAACS,GAAD;KACE,OAAO9B;KACP,OAAM;KACN,QAAQrB;KACR,UAAUC;IACX,CAAA,CACE;;EACF;;AAET"}
|
|
@@ -12,6 +12,6 @@ interface FilePreviewModalProps {
|
|
|
12
12
|
onClick: () => void;
|
|
13
13
|
}>;
|
|
14
14
|
}
|
|
15
|
-
export declare function FilePreviewModal({ file, onClose, onDownload, onShare, onStar, onDelete, customActions, }: FilePreviewModalProps): import(
|
|
15
|
+
export declare function FilePreviewModal({ file, onClose, onDownload, onShare, onStar, onDelete, customActions, }: FilePreviewModalProps): import('react').JSX.Element;
|
|
16
16
|
export {};
|
|
17
17
|
//# sourceMappingURL=FilePreviewModal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilePreviewModal.d.ts","sourceRoot":"","sources":["../../../src/files/components/FilePreviewModal.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AASzC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,aAAa,CAAC,EAAE,KAAK,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;QACtB,OAAO,EAAE,MAAM,IAAI,CAAC;KACrB,CAAC,CAAC;CACJ;
|
|
1
|
+
{"version":3,"file":"FilePreviewModal.d.ts","sourceRoot":"","sources":["../../../src/files/components/FilePreviewModal.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AASzC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,aAAa,CAAC,EAAE,KAAK,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;QACtB,OAAO,EAAE,MAAM,IAAI,CAAC;KACrB,CAAC,CAAC;CACJ;AAwGD,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,OAAO,EACP,UAAU,EACV,OAAO,EACP,MAAM,EACN,QAAQ,EACR,aAAa,GACd,EAAE,qBAAqB,+BAyMvB"}
|
|
@@ -122,6 +122,11 @@ function v({ file: v, onClose: y, onDownload: b, onShare: x, onStar: S, onDelete
|
|
|
122
122
|
}), /* @__PURE__ */ p("div", {
|
|
123
123
|
className: "flex-1 overflow-hidden",
|
|
124
124
|
children: (() => {
|
|
125
|
+
if (!D) return /* @__PURE__ */ p("div", {
|
|
126
|
+
role: "status",
|
|
127
|
+
className: "p-8 text-text-secondary",
|
|
128
|
+
children: e(T, "files.file.errors.downloadUrlUnavailable", "Download URL is unavailable")
|
|
129
|
+
});
|
|
125
130
|
switch (E) {
|
|
126
131
|
case "image": return /* @__PURE__ */ p(t, {
|
|
127
132
|
file: v,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilePreviewModal.js","names":[],"sources":["../../../src/files/components/FilePreviewModal.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport { X, Download, Share2, Star, Trash2 } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem } from \"../types\";\nimport { tWithFallback } from \"../utils/i18n\";\nimport { ImageViewer } from \"./viewers/ImageViewer\";\nimport { PDFViewer } from \"./viewers/PDFViewer\";\nimport { VideoPlayer } from \"./viewers/VideoPlayer\";\nimport { AudioPlayer } from \"./viewers/AudioPlayer\";\nimport { CodeViewer } from \"./viewers/CodeViewer\";\nimport { TextViewer } from \"./viewers/TextViewer\";\n\ninterface FilePreviewModalProps {\n file: FileItem;\n onClose: () => void;\n onDownload: () => void;\n onShare?: () => void;\n onStar?: () => void;\n onDelete?: () => void;\n customActions?: Array<{\n label: string;\n icon: React.ReactNode;\n onClick: () => void;\n }>;\n}\n\ntype PreviewType =\n | \"image\"\n | \"pdf\"\n | \"video\"\n | \"audio\"\n | \"code\"\n | \"text\"\n | \"unsupported\";\n\nfunction getFilePreviewType(mimeType: string, filename: string): PreviewType {\n // Image files\n if (mimeType.startsWith(\"image/\")) {\n return \"image\";\n }\n\n // PDF files\n if (mimeType === \"application/pdf\") {\n return \"pdf\";\n }\n\n // Video files\n if (mimeType.startsWith(\"video/\")) {\n return \"video\";\n }\n\n // Audio files\n if (mimeType.startsWith(\"audio/\")) {\n return \"audio\";\n }\n\n // Code files (by extension)\n const codeExtensions = [\n \"js\",\n \"jsx\",\n \"ts\",\n \"tsx\",\n \"py\",\n \"java\",\n \"cpp\",\n \"c\",\n \"cs\",\n \"rb\",\n \"go\",\n \"rs\",\n \"php\",\n \"html\",\n \"css\",\n \"scss\",\n \"json\",\n \"yaml\",\n \"yml\",\n \"xml\",\n \"sql\",\n \"sh\",\n \"bash\",\n \"vue\",\n \"swift\",\n \"kt\",\n \"r\",\n \"dart\",\n \"lua\",\n ];\n const ext = filename.split(\".\").pop()?.toLowerCase();\n if (ext && codeExtensions.includes(ext)) {\n return \"code\";\n }\n\n // Text files\n if (\n mimeType.startsWith(\"text/\") ||\n mimeType === \"application/json\" ||\n mimeType === \"application/xml\"\n ) {\n return \"text\";\n }\n\n return \"unsupported\";\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: \"jsx\",\n ts: \"typescript\",\n tsx: \"tsx\",\n py: \"python\",\n java: \"java\",\n cpp: \"cpp\",\n c: \"c\",\n cs: \"csharp\",\n rb: \"ruby\",\n go: \"go\",\n rs: \"rust\",\n php: \"php\",\n html: \"html\",\n css: \"css\",\n json: \"json\",\n md: \"markdown\",\n yaml: \"yaml\",\n yml: \"yaml\",\n xml: \"xml\",\n sql: \"sql\",\n sh: \"bash\",\n };\n return languageMap[ext || \"\"] || \"text\";\n}\n\nexport function FilePreviewModal({\n file,\n onClose,\n onDownload,\n onShare,\n onStar,\n onDelete,\n customActions,\n}: FilePreviewModalProps) {\n const { t } = useI18n();\n const previewType = getFilePreviewType(file.mimeType, file.name);\n const url = file.downloadUrl || file.url;\n\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onClose();\n }\n };\n\n document.addEventListener(\"keydown\", handleEscape);\n return () => document.removeEventListener(\"keydown\", handleEscape);\n }, [onClose]);\n\n const renderPreview = () => {\n switch (previewType) {\n case \"image\":\n return <ImageViewer file={file} url={url} />;\n case \"pdf\":\n return <PDFViewer file={file} url={url} />;\n case \"video\":\n return <VideoPlayer file={file} url={url} />;\n case \"audio\":\n return <AudioPlayer file={file} url={url} />;\n case \"code\":\n return (\n <CodeViewer\n file={file}\n url={url}\n language={detectLanguage(file.name)}\n />\n );\n case \"text\":\n return <TextViewer file={file} url={url} />;\n default:\n return (\n <div className=\"flex flex-col items-center justify-center h-full bg-bg-canvas p-8\">\n <div className=\"bg-bg-surface p-8 rounded-lg text-center max-w-md\">\n <p className=\"text-text-secondary mb-4\">\n {tWithFallback(\n t,\n \"files.preview.notAvailable\",\n \"Preview not available for this file type.\",\n )}\n </p>\n <p className=\"text-sm text-text-tertiary mb-6\">{file.mimeType}</p>\n <button\n type=\"button\"\n onClick={onDownload}\n className=\"px-4 py-2 bg-action-primary-bg text-text-inverse rounded-lg hover:bg-action-primary-bg-hover transition-colors duration-200\"\n >\n {tWithFallback(\n t,\n \"files.preview.downloadFile\",\n \"Download File\",\n )}\n </button>\n </div>\n </div>\n );\n }\n };\n\n return (\n <div\n className=\"fixed inset-0 bg-bg-overlay flex flex-col z-[100] animate-in fade-in duration-200\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={`Preview ${file.name}`}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 bg-bg-elevated/90 backdrop-blur-sm border-b border-border-default\">\n <div className=\"flex items-center gap-4 flex-1 min-w-0\">\n <h2 className=\"text-base font-medium text-text-primary truncate\">\n {file.name}\n </h2>\n <span className=\"text-sm text-text-secondary flex-shrink-0\">\n {(file.size / 1024 / 1024).toFixed(2)} MB\n </span>\n </div>\n\n <div className=\"flex items-center gap-2\">\n {/* Custom Actions */}\n {customActions?.map((action) => (\n <button\n type=\"button\"\n key={action.label}\n onClick={action.onClick}\n className=\"flex items-center gap-1.5 px-3 py-2 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n title={action.label}\n >\n {action.icon}\n <span>{action.label}</span>\n </button>\n ))}\n\n {/* Standard Actions */}\n <button\n type=\"button\"\n onClick={onDownload}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n title={tWithFallback(\n t,\n \"files.common.actions.download\",\n \"Download\",\n )}\n aria-label={tWithFallback(\n t,\n \"files.preview.downloadFile\",\n \"Download file\",\n )}\n >\n <Download className=\"size-5\" />\n </button>\n {onShare && (\n <button\n type=\"button\"\n onClick={onShare}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n title={tWithFallback(t, \"files.common.actions.share\", \"Share\")}\n aria-label={tWithFallback(\n t,\n \"files.preview.shareFile\",\n \"Share file\",\n )}\n >\n <Share2 className=\"size-5\" />\n </button>\n )}\n {onStar && (\n <button\n type=\"button\"\n onClick={onStar}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n title={\n file.starred\n ? tWithFallback(t, \"files.preview.removeStar\", \"Remove star\")\n : tWithFallback(t, \"files.preview.addStar\", \"Add star\")\n }\n aria-label={\n file.starred\n ? tWithFallback(t, \"files.preview.removeStar\", \"Remove star\")\n : tWithFallback(t, \"files.preview.addStar\", \"Add star\")\n }\n >\n <Star\n className={`size-5 ${\n file.starred\n ? \"fill-status-warning-text text-status-warning-text\"\n : \"\"\n }`}\n />\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n onClick={onDelete}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n title={tWithFallback(t, \"files.common.actions.delete\", \"Delete\")}\n aria-label={tWithFallback(\n t,\n \"files.preview.deleteFile\",\n \"Delete file\",\n )}\n >\n <Trash2 className=\"size-5\" />\n </button>\n )}\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200 ml-2\"\n title={tWithFallback(t, \"files.common.actions.close\", \"Close\")}\n aria-label={tWithFallback(\n t,\n \"files.preview.close\",\n \"Close preview\",\n )}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-hidden\">{renderPreview()}</div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FilePreviewModal.js","names":["getFilePreviewType","mimeType","codeExtensions","ext","filename","detectLanguage","FilePreviewModal","useI18n","previewType","file","url","useEffect","handleEscape","event","onClose","customActions","action","onDownload","tWithFallback","t","Download","onShare","Share2","onStar","Star","onDelete","Trash2","X","ImageViewer","PDFViewer","VideoPlayer","AudioPlayer","CodeViewer","TextViewer"],"sources":["../../../src/files/components/FilePreviewModal.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport { X, Download, Share2, Star, Trash2 } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem } from \"../types\";\nimport { tWithFallback } from \"../utils/i18n\";\nimport { ImageViewer } from \"./viewers/ImageViewer\";\nimport { PDFViewer } from \"./viewers/PDFViewer\";\nimport { VideoPlayer } from \"./viewers/VideoPlayer\";\nimport { AudioPlayer } from \"./viewers/AudioPlayer\";\nimport { CodeViewer } from \"./viewers/CodeViewer\";\nimport { TextViewer } from \"./viewers/TextViewer\";\n\ninterface FilePreviewModalProps {\n file: FileItem;\n onClose: () => void;\n onDownload: () => void;\n onShare?: () => void;\n onStar?: () => void;\n onDelete?: () => void;\n customActions?: Array<{\n label: string;\n icon: React.ReactNode;\n onClick: () => void;\n }>;\n}\n\ntype PreviewType =\n \"image\" | \"pdf\" | \"video\" | \"audio\" | \"code\" | \"text\" | \"unsupported\";\n\nfunction getFilePreviewType(mimeType: string, filename: string): PreviewType {\n // Image files\n if (mimeType.startsWith(\"image/\")) {\n return \"image\";\n }\n\n // PDF files\n if (mimeType === \"application/pdf\") {\n return \"pdf\";\n }\n\n // Video files\n if (mimeType.startsWith(\"video/\")) {\n return \"video\";\n }\n\n // Audio files\n if (mimeType.startsWith(\"audio/\")) {\n return \"audio\";\n }\n\n // Code files (by extension)\n const codeExtensions = [\n \"js\",\n \"jsx\",\n \"ts\",\n \"tsx\",\n \"py\",\n \"java\",\n \"cpp\",\n \"c\",\n \"cs\",\n \"rb\",\n \"go\",\n \"rs\",\n \"php\",\n \"html\",\n \"css\",\n \"scss\",\n \"json\",\n \"yaml\",\n \"yml\",\n \"xml\",\n \"sql\",\n \"sh\",\n \"bash\",\n \"vue\",\n \"swift\",\n \"kt\",\n \"r\",\n \"dart\",\n \"lua\",\n ];\n const ext = filename.split(\".\").pop()?.toLowerCase();\n if (ext && codeExtensions.includes(ext)) {\n return \"code\";\n }\n\n // Text files\n if (\n mimeType.startsWith(\"text/\") ||\n mimeType === \"application/json\" ||\n mimeType === \"application/xml\"\n ) {\n return \"text\";\n }\n\n return \"unsupported\";\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: \"jsx\",\n ts: \"typescript\",\n tsx: \"tsx\",\n py: \"python\",\n java: \"java\",\n cpp: \"cpp\",\n c: \"c\",\n cs: \"csharp\",\n rb: \"ruby\",\n go: \"go\",\n rs: \"rust\",\n php: \"php\",\n html: \"html\",\n css: \"css\",\n json: \"json\",\n md: \"markdown\",\n yaml: \"yaml\",\n yml: \"yaml\",\n xml: \"xml\",\n sql: \"sql\",\n sh: \"bash\",\n };\n return languageMap[ext || \"\"] || \"text\";\n}\n\nexport function FilePreviewModal({\n file,\n onClose,\n onDownload,\n onShare,\n onStar,\n onDelete,\n customActions,\n}: FilePreviewModalProps) {\n const { t } = useI18n();\n const previewType = getFilePreviewType(file.mimeType, file.name);\n const url = file.downloadUrl || file.url;\n\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onClose();\n }\n };\n\n document.addEventListener(\"keydown\", handleEscape);\n return () => document.removeEventListener(\"keydown\", handleEscape);\n }, [onClose]);\n\n const renderPreview = () => {\n if (!url)\n return (\n <div role=\"status\" className=\"p-8 text-text-secondary\">\n {tWithFallback(\n t,\n \"files.file.errors.downloadUrlUnavailable\",\n \"Download URL is unavailable\",\n )}\n </div>\n );\n switch (previewType) {\n case \"image\":\n return <ImageViewer file={file} url={url} />;\n case \"pdf\":\n return <PDFViewer file={file} url={url} />;\n case \"video\":\n return <VideoPlayer file={file} url={url} />;\n case \"audio\":\n return <AudioPlayer file={file} url={url} />;\n case \"code\":\n return (\n <CodeViewer\n file={file}\n url={url}\n language={detectLanguage(file.name)}\n />\n );\n case \"text\":\n return <TextViewer file={file} url={url} />;\n default:\n return (\n <div className=\"flex flex-col items-center justify-center h-full bg-bg-canvas p-8\">\n <div className=\"bg-bg-surface p-8 rounded-lg text-center max-w-md\">\n <p className=\"text-text-secondary mb-4\">\n {tWithFallback(\n t,\n \"files.preview.notAvailable\",\n \"Preview not available for this file type.\",\n )}\n </p>\n <p className=\"text-sm text-text-tertiary mb-6\">{file.mimeType}</p>\n <button\n type=\"button\"\n onClick={onDownload}\n className=\"px-4 py-2 bg-action-primary-bg text-text-inverse rounded-lg hover:bg-action-primary-bg-hover transition-colors duration-200\"\n >\n {tWithFallback(\n t,\n \"files.preview.downloadFile\",\n \"Download File\",\n )}\n </button>\n </div>\n </div>\n );\n }\n };\n\n return (\n <div\n className=\"fixed inset-0 bg-bg-overlay flex flex-col z-[100] animate-in fade-in duration-200\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={`Preview ${file.name}`}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 bg-bg-elevated/90 backdrop-blur-sm border-b border-border-default\">\n <div className=\"flex items-center gap-4 flex-1 min-w-0\">\n <h2 className=\"text-base font-medium text-text-primary truncate\">\n {file.name}\n </h2>\n <span className=\"text-sm text-text-secondary flex-shrink-0\">\n {(file.size / 1024 / 1024).toFixed(2)} MB\n </span>\n </div>\n\n <div className=\"flex items-center gap-2\">\n {/* Custom Actions */}\n {customActions?.map((action) => (\n <button\n type=\"button\"\n key={action.label}\n onClick={action.onClick}\n className=\"flex items-center gap-1.5 px-3 py-2 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n title={action.label}\n >\n {action.icon}\n <span>{action.label}</span>\n </button>\n ))}\n\n {/* Standard Actions */}\n <button\n type=\"button\"\n onClick={onDownload}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n title={tWithFallback(\n t,\n \"files.common.actions.download\",\n \"Download\",\n )}\n aria-label={tWithFallback(\n t,\n \"files.preview.downloadFile\",\n \"Download file\",\n )}\n >\n <Download className=\"size-5\" />\n </button>\n {onShare && (\n <button\n type=\"button\"\n onClick={onShare}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n title={tWithFallback(t, \"files.common.actions.share\", \"Share\")}\n aria-label={tWithFallback(\n t,\n \"files.preview.shareFile\",\n \"Share file\",\n )}\n >\n <Share2 className=\"size-5\" />\n </button>\n )}\n {onStar && (\n <button\n type=\"button\"\n onClick={onStar}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n title={\n file.starred\n ? tWithFallback(t, \"files.preview.removeStar\", \"Remove star\")\n : tWithFallback(t, \"files.preview.addStar\", \"Add star\")\n }\n aria-label={\n file.starred\n ? tWithFallback(t, \"files.preview.removeStar\", \"Remove star\")\n : tWithFallback(t, \"files.preview.addStar\", \"Add star\")\n }\n >\n <Star\n className={`size-5 ${\n file.starred\n ? \"fill-status-warning-text text-status-warning-text\"\n : \"\"\n }`}\n />\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n onClick={onDelete}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n title={tWithFallback(t, \"files.common.actions.delete\", \"Delete\")}\n aria-label={tWithFallback(\n t,\n \"files.preview.deleteFile\",\n \"Delete file\",\n )}\n >\n <Trash2 className=\"size-5\" />\n </button>\n )}\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200 ml-2\"\n title={tWithFallback(t, \"files.common.actions.close\", \"Close\")}\n aria-label={tWithFallback(\n t,\n \"files.preview.close\",\n \"Close preview\",\n )}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-hidden\">{renderPreview()}</div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;AA6BA,SAASA,EAAmB,GAAkB,GAA+B;CAE3E,IAAIC,EAAS,WAAW,QAAQ,GAC9B,OAAO;CAIT,IAAIA,MAAa,mBACf,OAAO;CAIT,IAAIA,EAAS,WAAW,QAAQ,GAC9B,OAAO;CAIT,IAAIA,EAAS,WAAW,QAAQ,GAC9B,OAAO;CAIT,IAAMC,IAAiB,2IA8BvB,GACMC,IAAMC,EAAS,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,YAAY;CAcnD,OAbID,KAAOD,EAAe,SAASC,CAAG,IAC7B,SAKPF,EAAS,WAAW,OAAO,KAC3BA,MAAa,sBACbA,MAAa,oBAEN,SAGF;AACT;AAEA,SAASI,EAAe,GAA0B;CA0BhD,OAAO;EAvBL,IAAI;EACJ,KAAK;EACL,IAAI;EACJ,KAAK;EACL,IAAI;EACJ,MAAM;EACN,KAAK;EACL,GAAG;EACH,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,KAAK;EACL,MAAM;EACN,KAAK;EACL,MAAM;EACN,IAAI;EACJ,MAAM;EACN,KAAK;EACL,KAAK;EACL,KAAK;EACL,IAAI;CAEC,EAzBKD,EAAS,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,YAAY,KAyBzB,OAAO;AACnC;AAEA,SAAgBE,EAAiB,EAC/B,SACA,YACA,eACA,YACA,WACA,aACA,oBACwB;CACxB,IAAM,EAAE,SAAMC,EAAQ,GAChBC,IAAcR,EAAmBS,EAAK,UAAUA,EAAK,IAAI,GACzDC,IAAMD,EAAK,eAAeA,EAAK;CAwErC,OAtEAE,QAAgB;EACd,IAAMC,KAAgB,MAAyB;GAC7C,AAAIC,EAAM,QAAQ,YAChBC,EAAQ;EAEZ;EAGA,OADA,SAAS,iBAAiB,WAAWF,CAAY,SACpC,SAAS,oBAAoB,WAAWA,CAAY;CACnE,GAAG,CAACE,CAAO,CAAC,GA8DV,kBAAC,OAAD;EACE,WAAU;EACV,MAAK;EACL,cAAW;EACX,cAAY,WAAWL,EAAK;EAJ9B,UAAA,CAOE,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;KACX,UAAAA,EAAK;IACJ,CAAA,GACJ,kBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA,EACIA,EAAK,OAAO,OAAO,KAAA,CAAM,QAAQ,CAAC,GAAE,KAClC;IACH,CAAA,CAAA;GAEL,CAAA,GAAA,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KAEGM,GAAe,KAAK,MACnB,kBAAC,UAAD;MACE,MAAK;MAEL,SAASC,EAAO;MAChB,WAAU;MACV,OAAOA,EAAO;MALhB,UAAA,CAOGA,EAAO,MACR,kBAAC,QAAD,EAAA,UAAOA,EAAO,MAAY,CAAA,CACpB;KAPD,GAAAA,EAAO,KAON,CACT;KAGD,kBAAC,UAAD;MACE,MAAK;MACL,SAASC;MACT,WAAU;MACV,OAAOC,EACLC,GACA,iCACA,UACF;MACA,cAAYD,EACVC,GACA,8BACA,eACF;MAEA,UAAA,kBAACC,GAAD,EAAU,WAAU,SAAU,CAAA;KACxB,CAAA;KACPC,KACC,kBAAC,UAAD;MACE,MAAK;MACL,SAASA;MACT,WAAU;MACV,OAAOH,EAAcC,GAAG,8BAA8B,OAAO;MAC7D,cAAYD,EACVC,GACA,2BACA,YACF;MAEA,UAAA,kBAACG,GAAD,EAAQ,WAAU,SAAU,CAAA;KACtB,CAAA;KAETC,KACC,kBAAC,UAAD;MACE,MAAK;MACL,SAASA;MACT,WAAU;MACV,OACEd,EAAK,UACDS,EAAcC,GAAG,4BAA4B,aAAa,IAC1DD,EAAcC,GAAG,yBAAyB,UAAU;MAE1D,cACEV,EAAK,UACDS,EAAcC,GAAG,4BAA4B,aAAa,IAC1DD,EAAcC,GAAG,yBAAyB,UAAU;MAG1D,UAAA,kBAACK,GAAD,EACE,WAAW,UACTf,EAAK,UACD,sDACA,KAEP,CAAA;KACK,CAAA;KAETgB,KACC,kBAAC,UAAD;MACE,MAAK;MACL,SAASA;MACT,WAAU;MACV,OAAOP,EAAcC,GAAG,+BAA+B,QAAQ;MAC/D,cAAYD,EACVC,GACA,4BACA,aACF;MAEA,UAAA,kBAACO,GAAD,EAAQ,WAAU,SAAU,CAAA;KACtB,CAAA;KAEV,kBAAC,UAAD;MACE,MAAK;MACL,SAASZ;MACT,WAAU;MACV,OAAOI,EAAcC,GAAG,8BAA8B,OAAO;MAC7D,cAAYD,EACVC,GACA,uBACA,eACF;MAEA,UAAA,kBAACQ,GAAD,EAAG,WAAU,SAAU,CAAA;KACjB,CAAA;IACL;GACF,CAAA,CAAA;EAGL,CAAA,GAAA,kBAAC,OAAD;GAAK,WAAU;GAA0B,iBAtLjB;IAC1B,IAAI,CAACjB,GACH,OACE,kBAAC,OAAD;KAAK,MAAK;KAAS,WAAU;KAC1B,UAAAQ,EACCC,GACA,4CACA,6BACF;IACG,CAAA;IAET,QAAQX,GAAR;KACE,KAAK,SACH,OAAO,kBAACoB,GAAD;MAAmB;MAAW;KAAM,CAAA;KAC7C,KAAK,OACH,OAAO,kBAACC,GAAD;MAAiB;MAAW;KAAM,CAAA;KAC3C,KAAK,SACH,OAAO,kBAACC,GAAD;MAAmB;MAAW;KAAM,CAAA;KAC7C,KAAK,SACH,OAAO,kBAACC,GAAD;MAAmB;MAAW;KAAM,CAAA;KAC7C,KAAK,QACH,OACE,kBAACC,GAAD;MACQ;MACD;MACL,UAAU3B,EAAeI,EAAK,IAAI;KACnC,CAAA;KAEL,KAAK,QACH,OAAO,kBAACwB,GAAD;MAAkB;MAAW;KAAM,CAAA;KAC5C,SACE,OACE,kBAAC,OAAD;MAAK,WAAU;MACb,UAAA,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA;QACE,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAf,EACCC,GACA,8BACA,2CACF;QACC,CAAA;QACH,kBAAC,KAAD;SAAG,WAAU;SAAmC,UAAAV,EAAK;QAAY,CAAA;QACjE,kBAAC,UAAD;SACE,MAAK;SACL,SAASQ;SACT,WAAU;SAET,UAAAC,EACCC,GACA,8BACA,eACF;QACM,CAAA;OACL;;KACF,CAAA;IAEX;GACF,EA6H6C,CAAc;EAAO,CAAA,CAC3D;;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileVersionPanel.d.ts","sourceRoot":"","sources":["../../../src/files/components/FileVersionPanel.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FileVersionPanel.d.ts","sourceRoot":"","sources":["../../../src/files/components/FileVersionPanel.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,EAAY,MAAM,OAAO,CAAC;AAc1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAYzC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CAuYtD,CAAC"}
|