@burdenoff/microfe-files 2026.525.3 → 2026.527.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/dist/files/components/ActionMenu.js +3 -1
- package/dist/files/components/ActionMenu.js.map +1 -1
- package/dist/files/components/ContextMenu.js +16 -112
- package/dist/files/components/ContextMenu.js.map +1 -1
- package/dist/files/components/CopyDialog.js +8 -0
- package/dist/files/components/CopyDialog.js.map +1 -1
- package/dist/files/components/EmptyState.js +2 -0
- package/dist/files/components/EmptyState.js.map +1 -1
- package/dist/files/components/FileBrowser.js +6 -1
- package/dist/files/components/FileBrowser.js.map +1 -1
- package/dist/files/components/FileCard.js +4 -0
- package/dist/files/components/FileCard.js.map +1 -1
- package/dist/files/components/FileInfoPanel.js +2 -0
- package/dist/files/components/FileInfoPanel.js.map +1 -1
- package/dist/files/components/FileListItem.js +6 -0
- package/dist/files/components/FileListItem.js.map +1 -1
- package/dist/files/components/FilePreviewModal.js +9 -3
- package/dist/files/components/FilePreviewModal.js.map +1 -1
- package/dist/files/components/FileVersionPanel.js +5 -0
- package/dist/files/components/FileVersionPanel.js.map +1 -1
- package/dist/files/components/FolderCard.js +3 -0
- package/dist/files/components/FolderCard.js.map +1 -1
- package/dist/files/components/MoveDialog.js +8 -0
- package/dist/files/components/MoveDialog.js.map +1 -1
- package/dist/files/components/SearchBar.js +4 -0
- package/dist/files/components/SearchBar.js.map +1 -1
- package/dist/files/components/ShareDialog.js +109 -104
- package/dist/files/components/ShareDialog.js.map +1 -1
- package/dist/files/components/TabBar.js +1 -0
- package/dist/files/components/TabBar.js.map +1 -1
- package/dist/files/components/Toast.js +1 -0
- package/dist/files/components/Toast.js.map +1 -1
- package/dist/files/components/UploadQueue.js +5 -0
- package/dist/files/components/UploadQueue.js.map +1 -1
- package/dist/files/components/contextMenuItems.js +103 -0
- package/dist/files/components/contextMenuItems.js.map +1 -0
- package/dist/files/components/viewers/AudioPlayer.js +4 -1
- package/dist/files/components/viewers/AudioPlayer.js.map +1 -1
- package/dist/files/components/viewers/CodeViewer.js +2 -0
- package/dist/files/components/viewers/CodeViewer.js.map +1 -1
- package/dist/files/components/viewers/ImageViewer.js +4 -0
- package/dist/files/components/viewers/ImageViewer.js.map +1 -1
- package/dist/files/components/viewers/PDFViewer.js +2 -0
- package/dist/files/components/viewers/PDFViewer.js.map +1 -1
- package/dist/files/components/viewers/TextViewer.js +4 -2
- package/dist/files/components/viewers/TextViewer.js.map +1 -1
- package/dist/files/components/viewers/VideoPlayer.js +5 -1
- package/dist/files/components/viewers/VideoPlayer.js.map +1 -1
- package/dist/files/hooks/useBatchOperations.js.map +1 -1
- package/dist/files/hooks/useFileVersions.js.map +1 -1
- package/dist/files/pages/BrowserPage.js +18 -2
- package/dist/files/pages/BrowserPage.js.map +1 -1
- package/dist/files/pages/ShareAccessPage.js +6 -5
- package/dist/files/pages/ShareAccessPage.js.map +1 -1
- package/dist/files/utils/index.js +1 -1
- package/dist/files/utils/index.js.map +1 -1
- package/dist/files/utils/thumbnail.js.map +1 -1
- package/dist/files.js +2 -1
- package/dist/translations/en.js +259 -0
- package/dist/translations/en.js.map +1 -0
- package/package.json +1 -4
- package/dist/files/components/viewers/index.js +0 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileBrowser.js","names":[],"sources":["../../../src/files/components/FileBrowser.tsx"],"sourcesContent":["import { type FC, useState } from \"react\";\nimport { Grid3x3, Loader2, Star } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem, FolderItem } from \"../types\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { FileCard } from \"./FileCard\";\nimport { FileListItem } from \"./FileListItem\";\nimport { FolderCard } from \"./FolderCard\";\nimport { ActionMenu } from \"./ActionMenu\";\nimport {\n ContextMenu,\n createFileMenuItems,\n createFolderMenuItems,\n} from \"./ContextMenu\";\nimport { sortFiles } from \"../utils\";\nimport { tWithFallback } from \"../utils/i18n\";\nimport {\n useDragDrop,\n type DragData,\n type DragOperation,\n} from \"../hooks/useDragDrop\";\n\ninterface FileBrowserProps {\n files: FileItem[];\n folders: FolderItem[];\n loading?: boolean;\n error?: Error | null;\n preserveSortOrder?: boolean;\n onFilePreview?: (file: FileItem) => void;\n onFileShare?: (file: FileItem) => void;\n onFileDelete?: (file: FileItem) => void;\n onFileRestore?: (file: FileItem) => void;\n onFileFavorite?: (file: FileItem) => void;\n onFileRename?: (file: FileItem) => void;\n onFileDownload?: (file: FileItem) => void;\n onFileCopy?: (file: FileItem) => void;\n onFileMove?: (file: FileItem) => void;\n onFileInfo?: (file: FileItem) => void;\n onFileActivity?: (file: FileItem) => void;\n onFolderOpen?: (folder: FolderItem) => void;\n onFolderShare?: (folder: FolderItem) => void;\n onFolderDelete?: (folder: FolderItem) => void;\n onFolderRestore?: (folder: FolderItem) => void;\n onFolderRename?: (folder: FolderItem) => void;\n onFolderFavorite?: (folder: FolderItem) => void;\n onFolderCopy?: (folder: FolderItem) => void;\n onFolderMove?: (folder: FolderItem) => void;\n onFolderInfo?: (folder: FolderItem) => void;\n onFolderActivity?: (folder: FolderItem) => void;\n onMoveFile?: (fileId: string, targetFolderId: string) => Promise<void>;\n onCopyFile?: (fileId: string, targetFolderId: string) => Promise<void>;\n onMoveFolder?: (folderId: string, targetFolderId: string) => Promise<void>;\n onCopyFolder?: (folderId: string, targetFolderId: string) => Promise<void>;\n}\n\nexport const FileBrowser: FC<FileBrowserProps> = ({\n files,\n folders,\n loading = false,\n error = null,\n preserveSortOrder = false,\n onFilePreview,\n onFileShare,\n onFileDelete,\n onFileRestore,\n onFileFavorite,\n onFileRename,\n onFileDownload,\n onFileCopy,\n onFileMove,\n onFileInfo,\n onFileActivity,\n onFolderOpen,\n onFolderShare,\n onFolderDelete,\n onFolderRestore,\n onFolderRename,\n onFolderFavorite,\n onFolderCopy,\n onFolderMove,\n onFolderInfo,\n onFolderActivity,\n onMoveFile,\n onCopyFile,\n onMoveFolder,\n onCopyFolder,\n}) => {\n const { t } = useI18n();\n const { viewMode, sortBy, sortDirection, selectedFiles, selectedFolders } =\n useFilesStore();\n\n const [openMenuId, setOpenMenuId] = useState<string | null>(null);\n const [dragState, setDragState] = useState<{\n draggedItem: DragData | null;\n dropTargetFolderId: string | null;\n }>({ draggedItem: null, dropTargetFolderId: null });\n const [contextMenu, setContextMenu] = useState<{\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n x: number;\n y: number;\n } | null>(null);\n\n const { draggedItem, startDrag, endDrag, handleDrop } = useDragDrop({\n onMoveFile,\n onCopyFile,\n onMoveFolder,\n onCopyFolder,\n });\n\n const handleFileDragStart = (file: FileItem, operation: DragOperation) => {\n startDrag({ type: \"file\", item: file, operation });\n setDragState({\n draggedItem: { type: \"file\", item: file, operation },\n dropTargetFolderId: null,\n });\n };\n\n const handleFolderDragStart = (\n folder: FolderItem,\n operation: DragOperation,\n ) => {\n startDrag({ type: \"folder\", item: folder, operation });\n setDragState({\n draggedItem: { type: \"folder\", item: folder, operation },\n dropTargetFolderId: null,\n });\n };\n\n const handleDragEnd = () => {\n endDrag();\n setDragState({ draggedItem: null, dropTargetFolderId: null });\n };\n\n const handleFolderDrop = async (folder: FolderItem) => {\n if (draggedItem) {\n await handleDrop(folder.id);\n setDragState({ draggedItem: null, dropTargetFolderId: null });\n }\n };\n\n const handleFolderDragOver = (folderId: string) => {\n setDragState((prev) => ({ ...prev, dropTargetFolderId: folderId }));\n };\n\n const handleFolderDragLeave = () => {\n setDragState((prev) => ({ ...prev, dropTargetFolderId: null }));\n };\n\n const handleFileContextMenu = (file: FileItem, x: number, y: number) => {\n setContextMenu({ item: file, type: \"file\", x, y });\n };\n\n const handleFolderContextMenu = (\n folder: FolderItem,\n x: number,\n y: number,\n ) => {\n setContextMenu({ item: folder, type: \"folder\", x, y });\n };\n\n const closeContextMenu = () => {\n setContextMenu(null);\n };\n\n const fileCanRead = (file: FileItem) =>\n file.canRead === true || file.canUpdate === true || file.canWrite === true;\n const fileCanUpdate = (file: FileItem) =>\n file.canUpdate === true || file.canWrite === true;\n const fileCanShare = (file: FileItem) =>\n file.canShare === true || fileCanUpdate(file);\n const fileCanDelete = (file: FileItem) => file.canDelete === true;\n\n const folderCanRead = (folder: FolderItem) =>\n folder.canRead === true || folder.permissions?.canRead === true;\n const folderCanUpdate = (folder: FolderItem) =>\n folder.canUpdate === true || folder.permissions?.canWrite === true;\n const folderCanShare = (folder: FolderItem) =>\n folder.permissions?.canShare === true || folderCanUpdate(folder);\n const folderCanDelete = (folder: FolderItem) =>\n folder.canDelete === true || folder.permissions?.canDelete === true;\n\n const getContextMenuItems = () => {\n if (!contextMenu) return [];\n if (contextMenu.type === \"file\") {\n const file = contextMenu.item as FileItem;\n return createFileMenuItems(\n {\n onShare:\n onFileShare && fileCanShare(file)\n ? () => onFileShare(file)\n : undefined,\n onDownload:\n onFileDownload && fileCanRead(file)\n ? () => onFileDownload(file)\n : undefined,\n onCopy:\n onFileCopy && fileCanRead(file)\n ? () => onFileCopy(file)\n : undefined,\n onRename:\n onFileRename && fileCanUpdate(file)\n ? () => onFileRename(file)\n : undefined,\n onStar:\n onFileFavorite && fileCanUpdate(file)\n ? () => onFileFavorite(file)\n : undefined,\n onMove:\n onFileMove && fileCanUpdate(file)\n ? () => onFileMove(file)\n : undefined,\n onInfo: onFileInfo ? () => onFileInfo(file) : undefined,\n onActivity: onFileActivity ? () => onFileActivity(file) : undefined,\n onDelete:\n onFileDelete && fileCanDelete(file)\n ? () => onFileDelete(file)\n : undefined,\n onRestore:\n onFileRestore && fileCanUpdate(file)\n ? () => onFileRestore(file)\n : undefined,\n isStarred: file.starred,\n },\n t,\n );\n } else {\n const folder = contextMenu.item as FolderItem;\n return createFolderMenuItems(\n {\n onShare:\n onFolderShare && folderCanShare(folder)\n ? () => onFolderShare(folder)\n : undefined,\n onRename:\n onFolderRename && folderCanUpdate(folder)\n ? () => onFolderRename(folder)\n : undefined,\n onStar:\n onFolderFavorite && folderCanUpdate(folder)\n ? () => onFolderFavorite(folder)\n : undefined,\n onMove:\n onFolderMove && folderCanUpdate(folder)\n ? () => onFolderMove(folder)\n : undefined,\n onInfo: onFolderInfo ? () => onFolderInfo(folder) : undefined,\n onDelete:\n onFolderDelete && folderCanDelete(folder)\n ? () => onFolderDelete(folder)\n : undefined,\n onRestore:\n onFolderRestore && folderCanUpdate(folder)\n ? () => onFolderRestore(folder)\n : undefined,\n isStarred: folder.starred,\n },\n t,\n );\n }\n };\n\n const sortedFiles = preserveSortOrder\n ? files\n : sortFiles(files, sortBy, sortDirection);\n const sortedFolders = preserveSortOrder\n ? folders\n : sortFiles(folders, sortBy, sortDirection);\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center min-h-[500px]\">\n <div className=\"flex flex-col items-center gap-4\">\n <Loader2 className=\"size-10 animate-spin text-action-primary-bg\" />\n <span className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.browser.loading\", \"Loading files…\")}\n </span>\n </div>\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center min-h-[500px]\">\n <div className=\"text-center max-w-md\">\n <div className=\"mb-3 text-xl font-semibold text-status-error-text\">\n {tWithFallback(\n t,\n \"files.browser.loadError\",\n \"Failed to load files\",\n )}\n </div>\n <p className=\"mb-6 text-sm text-text-secondary\">\n {error.message ||\n tWithFallback(\n t,\n \"files.browser.unexpectedError\",\n \"An unexpected error occurred\",\n )}\n </p>\n <button\n onClick={() => window.location.reload()}\n className=\"rounded-lg bg-action-primary-bg px-6 py-2.5 text-sm font-medium text-text-inverse transition-colors hover:bg-action-primary-bg-hover\"\n >\n {tWithFallback(t, \"files.browser.retry\", \"Retry\")}\n </button>\n </div>\n </div>\n );\n }\n\n if (files.length === 0 && folders.length === 0) {\n return (\n <>\n {contextMenu && (\n <ContextMenu\n x={contextMenu.x}\n y={contextMenu.y}\n onClose={closeContextMenu}\n items={getContextMenuItems()}\n />\n )}\n </>\n );\n }\n\n if (viewMode !== \"list\") {\n return (\n <div className=\"@container bg-bg-canvas p-page-padding\">\n <div className=\"grid grid-cols-2 @md:grid-cols-3 @lg:grid-cols-4 @xl:grid-cols-5 gap-4\">\n {sortedFolders.map((folder) => (\n <FolderCard\n key={folder.id}\n folder={folder}\n isSelected={selectedFolders.has(folder.id)}\n isDragging={draggedItem?.item.id === folder.id}\n isDropTarget={dragState.dropTargetFolderId === folder.id}\n draggedItem={draggedItem}\n onOpen={folderCanRead(folder) ? onFolderOpen : undefined}\n onShare={folderCanShare(folder) ? onFolderShare : undefined}\n onDelete={folderCanDelete(folder) ? onFolderDelete : undefined}\n onRestore={folderCanUpdate(folder) ? onFolderRestore : undefined}\n onRename={folderCanUpdate(folder) ? onFolderRename : undefined}\n onFavorite={\n folderCanUpdate(folder) ? onFolderFavorite : undefined\n }\n onCopy={onFolderCopy}\n onMove={folderCanUpdate(folder) ? onFolderMove : undefined}\n onInfo={onFolderInfo}\n onActivity={onFolderActivity}\n onDragStart={\n folderCanUpdate(folder) ? handleFolderDragStart : undefined\n }\n onDragEnd={handleDragEnd}\n onDrop={folderCanUpdate(folder) ? handleFolderDrop : undefined}\n onContextMenu={handleFolderContextMenu}\n />\n ))}\n\n {sortedFiles.map((file) => (\n <FileCard\n key={file.id}\n file={file}\n isSelected={selectedFiles.has(file.id)}\n isDragging={draggedItem?.item.id === file.id}\n onPreview={fileCanRead(file) ? onFilePreview : undefined}\n onShare={fileCanShare(file) ? onFileShare : undefined}\n onDelete={fileCanDelete(file) ? onFileDelete : undefined}\n onRestore={fileCanUpdate(file) ? onFileRestore : undefined}\n onFavorite={fileCanUpdate(file) ? onFileFavorite : undefined}\n onRename={fileCanUpdate(file) ? onFileRename : undefined}\n onDownload={fileCanRead(file) ? onFileDownload : undefined}\n onCopy={fileCanRead(file) ? onFileCopy : undefined}\n onMove={fileCanUpdate(file) ? onFileMove : undefined}\n onInfo={onFileInfo}\n onActivity={onFileActivity}\n onDragStart={\n fileCanUpdate(file) ? handleFileDragStart : undefined\n }\n onDragEnd={handleDragEnd}\n onContextMenu={handleFileContextMenu}\n />\n ))}\n </div>\n {contextMenu && (\n <ContextMenu\n x={contextMenu.x}\n y={contextMenu.y}\n onClose={closeContextMenu}\n items={getContextMenuItems()}\n />\n )}\n </div>\n );\n }\n\n if (viewMode === \"list\") {\n return (\n <div className=\"@container bg-bg-canvas\">\n <div className=\"hidden @md:flex items-center gap-3 px-3 py-2 bg-bg-surface border-b border-border-subtle text-text-secondary font-text-sm font-weight-medium\">\n <div className=\"flex-shrink-0 w-4\" />\n <div className=\"flex-shrink-0 w-6\" />\n <div className=\"flex-1\">\n {tWithFallback(t, \"files.browser.name\", \"Name\")}\n </div>\n <div className=\"hidden @lg:block flex-shrink-0 w-40\">\n {tWithFallback(t, \"files.browser.owner\", \"Owner\")}\n </div>\n <div className=\"hidden @md:block flex-shrink-0 w-24 text-right\">\n {tWithFallback(t, \"files.browser.size\", \"Size\")}\n </div>\n <div className=\"hidden @lg:block flex-shrink-0 w-32 text-right\">\n {tWithFallback(t, \"files.browser.modified\", \"Modified\")}\n </div>\n <div className=\"flex-shrink-0 w-32\" />\n </div>\n\n <div className=\"divide-y divide-border-subtle\">\n {sortedFolders.map((folder) => (\n <div\n key={folder.id}\n className={`group flex items-center gap-3 border-b border-border-subtle bg-bg-surface p-3 transition-colors hover:bg-bg-sunken focus-within:bg-bg-sunken ${dragState.dropTargetFolderId === folder.id && draggedItem?.item.id !== folder.id ? \"bg-action-primary-bg/10\" : \"\"} ${draggedItem?.item.id === folder.id ? \"opacity-50\" : \"\"}`}\n onClick={() => {\n if (folderCanRead(folder)) onFolderOpen?.(folder);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n if (folderCanRead(folder)) onFolderOpen?.(folder);\n }\n }}\n onDragOver={(e) => {\n if (\n draggedItem &&\n draggedItem.item.id !== folder.id &&\n folderCanUpdate(folder)\n ) {\n e.preventDefault();\n handleFolderDragOver(folder.id);\n }\n }}\n onDragLeave={handleFolderDragLeave}\n onDrop={async (e) => {\n e.preventDefault();\n if (\n draggedItem &&\n draggedItem.item.id !== folder.id &&\n folderCanUpdate(folder)\n ) {\n await handleFolderDrop(folder);\n }\n }}\n onContextMenu={(e) => {\n e.preventDefault();\n handleFolderContextMenu(folder, e.clientX, e.clientY);\n }}\n role=\"button\"\n tabIndex={0}\n aria-label={tWithFallback(\n t,\n \"files.browser.openFolder\",\n \"Open folder\",\n )}\n >\n <div className=\"flex-shrink-0\">\n <input\n type=\"checkbox\"\n checked={selectedFolders.has(folder.id)}\n onChange={(e) => {\n e.stopPropagation();\n useFilesStore.getState().toggleFolderSelection(folder.id);\n }}\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 ${folder.name}`}\n />\n </div>\n <Grid3x3 className=\"size-6 text-action-primary-bg flex-shrink-0\" />\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 {folder.name}\n </span>\n {folder.starred && (\n <Star className=\"size-3 flex-shrink-0 fill-yellow-400 text-yellow-400\" />\n )}\n </div>\n </div>\n <div className=\"hidden @lg:block flex-shrink-0 w-40\">\n {folder.createdBy && (\n <div className=\"flex items-center gap-2\">\n {folder.createdBy.avatar && (\n <img\n src={folder.createdBy.avatar}\n alt={folder.createdBy.name}\n className=\"size-6 rounded-full\"\n />\n )}\n <span className=\"font-text-sm text-text-secondary truncate\">\n {folder.createdBy.name}\n </span>\n </div>\n )}\n </div>\n <div className=\"hidden @md:block flex-shrink-0 w-24 text-right\">\n <span className=\"font-text-sm text-text-secondary\">\n {folder.filesCount ?? 0}{\" \"}\n {tWithFallback(t, \"files.browser.items\", \"items\")}\n </span>\n </div>\n <div className=\"hidden @lg:block flex-shrink-0 w-32 text-right\">\n <span className=\"font-text-sm text-text-secondary\">\n {new Date(folder.updatedAt).toLocaleDateString()}\n </span>\n </div>\n\n <div className=\"flex w-32 flex-shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100\">\n {folderCanShare(folder) && onFolderShare && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onFolderShare(folder);\n }}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(\n t,\n \"files.browser.share\",\n \"Share\",\n )}\n title={tWithFallback(\n t,\n \"files.browser.shareFolder\",\n \"Share folder\",\n )}\n >\n <svg\n className=\"size-4 text-text-primary\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z\"\n />\n </svg>\n </button>\n )}\n\n {folderCanUpdate(folder) && onFolderRename && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onFolderRename(folder);\n }}\n className=\"hidden @md:block p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(\n t,\n \"files.browser.rename\",\n \"Rename\",\n )}\n title={tWithFallback(t, \"files.browser.rename\", \"Rename\")}\n >\n <svg\n className=\"size-4 text-text-primary\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n </button>\n )}\n\n {folderCanDelete(folder) && onFolderDelete && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onFolderDelete(folder);\n }}\n className=\"p-1.5 hover:bg-action-danger-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(\n t,\n \"files.browser.delete\",\n \"Delete\",\n )}\n title={tWithFallback(t, \"files.browser.delete\", \"Delete\")}\n >\n <svg\n className=\"size-4 text-status-error-text\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n </button>\n )}\n\n <div onClick={(e) => e.stopPropagation()}>\n <ActionMenu\n items={createFolderMenuItems(\n {\n onShare:\n folderCanShare(folder) && onFolderShare\n ? () => onFolderShare(folder)\n : undefined,\n onRename:\n folderCanUpdate(folder) && onFolderRename\n ? () => onFolderRename(folder)\n : undefined,\n onStar:\n folderCanUpdate(folder) && onFolderFavorite\n ? () => onFolderFavorite(folder)\n : undefined,\n onMove:\n folderCanUpdate(folder) && onFolderMove\n ? () => onFolderMove(folder)\n : undefined,\n onInfo: () => onFolderInfo?.(folder),\n onRestore:\n folderCanUpdate(folder) && onFolderRestore\n ? () => onFolderRestore(folder)\n : undefined,\n onDelete:\n folderCanDelete(folder) && onFolderDelete\n ? () => onFolderDelete(folder)\n : undefined,\n isStarred: folder.starred,\n },\n t,\n )}\n isOpen={openMenuId === folder.id}\n onToggle={(open) => setOpenMenuId(open ? folder.id : null)}\n />\n </div>\n </div>\n </div>\n ))}\n\n {sortedFiles.map((file) => (\n <FileListItem\n key={file.id}\n file={file}\n isSelected={selectedFiles.has(file.id)}\n isDragging={draggedItem?.item.id === file.id}\n onPreview={fileCanRead(file) ? onFilePreview : undefined}\n onShare={fileCanShare(file) ? onFileShare : undefined}\n onDelete={fileCanDelete(file) ? onFileDelete : undefined}\n onRestore={fileCanUpdate(file) ? onFileRestore : undefined}\n onFavorite={fileCanUpdate(file) ? onFileFavorite : undefined}\n onRename={fileCanUpdate(file) ? onFileRename : undefined}\n onDownload={fileCanRead(file) ? onFileDownload : undefined}\n onCopy={fileCanRead(file) ? onFileCopy : undefined}\n onMove={fileCanUpdate(file) ? onFileMove : undefined}\n onInfo={onFileInfo}\n onActivity={onFileActivity}\n onDragStart={\n fileCanUpdate(file) ? handleFileDragStart : undefined\n }\n onDragEnd={handleDragEnd}\n onContextMenu={handleFileContextMenu}\n />\n ))}\n </div>\n {contextMenu && (\n <ContextMenu\n x={contextMenu.x}\n y={contextMenu.y}\n onClose={closeContextMenu}\n items={getContextMenuItems()}\n />\n )}\n </div>\n );\n }\n\n return null;\n};\n"],"mappings":";;;;;;;;;;;;;;AAuDA,IAAa,KAAqC,EAChD,UACA,YACA,cAAU,IACV,WAAQ,MACR,wBAAoB,IACpB,kBACA,gBACA,iBACA,kBACA,mBACA,iBACA,mBACA,eACA,eACA,eACA,mBACA,iBACA,kBACA,mBACA,oBACA,mBACA,qBACA,kBACA,iBACA,iBACA,sBACA,gBACA,gBACA,kBACA,uBACI;CACJ,IAAM,EAAE,SAAM,IAAS,EACjB,EAAE,aAAU,WAAQ,mBAAe,kBAAe,uBACtD,GAAe,EAEX,CAAC,IAAY,MAAiB,EAAwB,KAAK,EAC3D,CAAC,GAAW,KAAgB,EAG/B;EAAE,aAAa;EAAM,oBAAoB;EAAM,CAAC,EAC7C,CAAC,GAAa,KAAkB,EAK5B,KAAK,EAET,EAAE,gBAAa,eAAW,aAAS,mBAAe,GAAY;EAClE;EACA;EACA;EACA;EACD,CAAC,EAEI,MAAuB,GAAgB,MAA6B;AAExE,EADA,GAAU;GAAE,MAAM;GAAQ,MAAM;GAAM;GAAW,CAAC,EAClD,EAAa;GACX,aAAa;IAAE,MAAM;IAAQ,MAAM;IAAM;IAAW;GACpD,oBAAoB;GACrB,CAAC;IAGE,MACJ,GACA,MACG;AAEH,EADA,GAAU;GAAE,MAAM;GAAU,MAAM;GAAQ;GAAW,CAAC,EACtD,EAAa;GACX,aAAa;IAAE,MAAM;IAAU,MAAM;IAAQ;IAAW;GACxD,oBAAoB;GACrB,CAAC;IAGE,UAAsB;AAE1B,EADA,IAAS,EACT,EAAa;GAAE,aAAa;GAAM,oBAAoB;GAAM,CAAC;IAGzD,IAAmB,OAAO,MAAuB;AACrD,EAAI,MACF,MAAM,GAAW,EAAO,GAAG,EAC3B,EAAa;GAAE,aAAa;GAAM,oBAAoB;GAAM,CAAC;IAI3D,MAAwB,MAAqB;AACjD,KAAc,OAAU;GAAE,GAAG;GAAM,oBAAoB;GAAU,EAAE;IAG/D,WAA8B;AAClC,KAAc,OAAU;GAAE,GAAG;GAAM,oBAAoB;GAAM,EAAE;IAG3D,KAAyB,GAAgB,GAAW,MAAc;AACtE,IAAe;GAAE,MAAM;GAAM,MAAM;GAAQ;GAAG;GAAG,CAAC;IAG9C,KACJ,GACA,GACA,MACG;AACH,IAAe;GAAE,MAAM;GAAQ,MAAM;GAAU;GAAG;GAAG,CAAC;IAGlD,UAAyB;AAC7B,IAAe,KAAK;IAGhB,KAAe,MACnB,EAAK,YAAY,MAAQ,EAAK,cAAc,MAAQ,EAAK,aAAa,IAClE,KAAiB,MACrB,EAAK,cAAc,MAAQ,EAAK,aAAa,IACzC,KAAgB,MACpB,EAAK,aAAa,MAAQ,EAAc,EAAK,EACzC,KAAiB,MAAmB,EAAK,cAAc,IAEvD,KAAiB,MACrB,EAAO,YAAY,MAAQ,EAAO,aAAa,YAAY,IACvD,KAAmB,MACvB,EAAO,cAAc,MAAQ,EAAO,aAAa,aAAa,IAC1D,KAAkB,MACtB,EAAO,aAAa,aAAa,MAAQ,EAAgB,EAAO,EAC5D,KAAmB,MACvB,EAAO,cAAc,MAAQ,EAAO,aAAa,cAAc,IAE3D,UAA4B;AAChC,MAAI,CAAC,EAAa,QAAO,EAAE;AAC3B,MAAI,EAAY,SAAS,QAAQ;GAC/B,IAAM,IAAO,EAAY;AACzB,UAAO,GACL;IACE,SACE,KAAe,EAAa,EAAK,SACvB,EAAY,EAAK,GACvB,KAAA;IACN,YACE,KAAkB,EAAY,EAAK,SACzB,EAAe,EAAK,GAC1B,KAAA;IACN,QACE,KAAc,EAAY,EAAK,SACrB,EAAW,EAAK,GACtB,KAAA;IACN,UACE,KAAgB,EAAc,EAAK,SACzB,EAAa,EAAK,GACxB,KAAA;IACN,QACE,KAAkB,EAAc,EAAK,SAC3B,EAAe,EAAK,GAC1B,KAAA;IACN,QACE,KAAc,EAAc,EAAK,SACvB,EAAW,EAAK,GACtB,KAAA;IACN,QAAQ,UAAmB,EAAW,EAAK,GAAG,KAAA;IAC9C,YAAY,UAAuB,EAAe,EAAK,GAAG,KAAA;IAC1D,UACE,KAAgB,EAAc,EAAK,SACzB,EAAa,EAAK,GACxB,KAAA;IACN,WACE,KAAiB,EAAc,EAAK,SAC1B,EAAc,EAAK,GACzB,KAAA;IACN,WAAW,EAAK;IACjB,EACD,EACD;SACI;GACL,IAAM,IAAS,EAAY;AAC3B,UAAO,EACL;IACE,SACE,KAAiB,EAAe,EAAO,SAC7B,EAAc,EAAO,GAC3B,KAAA;IACN,UACE,KAAkB,EAAgB,EAAO,SAC/B,EAAe,EAAO,GAC5B,KAAA;IACN,QACE,KAAoB,EAAgB,EAAO,SACjC,EAAiB,EAAO,GAC9B,KAAA;IACN,QACE,KAAgB,EAAgB,EAAO,SAC7B,EAAa,EAAO,GAC1B,KAAA;IACN,QAAQ,UAAqB,EAAa,EAAO,GAAG,KAAA;IACpD,UACE,KAAkB,EAAgB,EAAO,SAC/B,EAAe,EAAO,GAC5B,KAAA;IACN,WACE,KAAmB,EAAgB,EAAO,SAChC,EAAgB,EAAO,GAC7B,KAAA;IACN,WAAW,EAAO;IACnB,EACD,EACD;;IAIC,KAAc,KAChB,IACA,EAAU,GAAO,GAAQ,GAAc,EACrC,KAAgB,KAClB,IACA,EAAU,GAAS,GAAQ,GAAc;AAsa7C,QApaI,KAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,IAAD,EAAS,WAAU,+CAAgD,CAAA,EACnE,kBAAC,QAAD;IAAM,WAAU;cACb,EAAc,GAAG,yBAAyB,iBAAiB;IACvD,CAAA,CACH;;EACF,CAAA,GAIN,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eACZ,EACC,GACA,2BACA,uBACD;KACG,CAAA;IACN,kBAAC,KAAD;KAAG,WAAU;eACV,EAAM,WACL,EACE,GACA,iCACA,+BACD;KACD,CAAA;IACJ,kBAAC,UAAD;KACE,eAAe,OAAO,SAAS,QAAQ;KACvC,WAAU;eAET,EAAc,GAAG,uBAAuB,QAAQ;KAC1C,CAAA;IACL;;EACF,CAAA,GAIN,EAAM,WAAW,KAAK,EAAQ,WAAW,IAEzC,kBAAA,IAAA,EAAA,UACG,KACC,kBAAC,GAAD;EACE,GAAG,EAAY;EACf,GAAG,EAAY;EACf,SAAS;EACT,OAAO,GAAqB;EAC5B,CAAA,EAEH,CAAA,GAIH,MAAa,SAsEb,MAAa,SAEb,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,OAAD,EAAK,WAAU,qBAAsB,CAAA;KACrC,kBAAC,OAAD,EAAK,WAAU,qBAAsB,CAAA;KACrC,kBAAC,OAAD;MAAK,WAAU;gBACZ,EAAc,GAAG,sBAAsB,OAAO;MAC3C,CAAA;KACN,kBAAC,OAAD;MAAK,WAAU;gBACZ,EAAc,GAAG,uBAAuB,QAAQ;MAC7C,CAAA;KACN,kBAAC,OAAD;MAAK,WAAU;gBACZ,EAAc,GAAG,sBAAsB,OAAO;MAC3C,CAAA;KACN,kBAAC,OAAD;MAAK,WAAU;gBACZ,EAAc,GAAG,0BAA0B,WAAW;MACnD,CAAA;KACN,kBAAC,OAAD,EAAK,WAAU,sBAAuB,CAAA;KAClC;;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,GAAc,KAAK,MAClB,kBAAC,OAAD;KAEE,WAAW,gJAAgJ,EAAU,uBAAuB,EAAO,MAAM,GAAa,KAAK,OAAO,EAAO,KAAK,4BAA4B,GAAG,GAAG,GAAa,KAAK,OAAO,EAAO,KAAK,eAAe;KACpU,eAAe;AACb,MAAI,EAAc,EAAO,IAAE,IAAe,EAAO;;KAEnD,YAAY,MAAU;AACpB,OAAI,EAAM,QAAQ,WAAW,EAAM,QAAQ,SACzC,EAAM,gBAAgB,EAClB,EAAc,EAAO,IAAE,IAAe,EAAO;;KAGrD,aAAa,MAAM;AACjB,MACE,KACA,EAAY,KAAK,OAAO,EAAO,MAC/B,EAAgB,EAAO,KAEvB,EAAE,gBAAgB,EAClB,GAAqB,EAAO,GAAG;;KAGnC,aAAa;KACb,QAAQ,OAAO,MAAM;AAEnB,MADA,EAAE,gBAAgB,EAEhB,KACA,EAAY,KAAK,OAAO,EAAO,MAC/B,EAAgB,EAAO,IAEvB,MAAM,EAAiB,EAAO;;KAGlC,gBAAgB,MAAM;AAEpB,MADA,EAAE,gBAAgB,EAClB,EAAwB,GAAQ,EAAE,SAAS,EAAE,QAAQ;;KAEvD,MAAK;KACL,UAAU;KACV,cAAY,EACV,GACA,4BACA,cACD;eA3CH;MA6CE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,SAAD;QACE,MAAK;QACL,SAAS,EAAgB,IAAI,EAAO,GAAG;QACvC,WAAW,MAAM;AAEf,SADA,EAAE,iBAAiB,EACnB,EAAc,UAAU,CAAC,sBAAsB,EAAO,GAAG;;QAE3D,WAAU;QACV,cAAY,UAAU,EAAO;QAC7B,CAAA;OACE,CAAA;MACN,kBAAC,IAAD,EAAS,WAAU,+CAAgD,CAAA;MACnE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAO;SACH,CAAA,EACN,EAAO,WACN,kBAAC,IAAD,EAAM,WAAU,wDAAyD,CAAA,CAEvE;;OACF,CAAA;MACN,kBAAC,OAAD;OAAK,WAAU;iBACZ,EAAO,aACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACG,EAAO,UAAU,UAChB,kBAAC,OAAD;SACE,KAAK,EAAO,UAAU;SACtB,KAAK,EAAO,UAAU;SACtB,WAAU;SACV,CAAA,EAEJ,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAO,UAAU;SACb,CAAA,CACH;;OAEJ,CAAA;MACN,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,QAAD;QAAM,WAAU;kBAAhB;SACG,EAAO,cAAc;SAAG;SACxB,EAAc,GAAG,uBAAuB,QAAQ;SAC5C;;OACH,CAAA;MACN,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,QAAD;QAAM,WAAU;kBACb,IAAI,KAAK,EAAO,UAAU,CAAC,oBAAoB;QAC3C,CAAA;OACH,CAAA;MAEN,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACG,EAAe,EAAO,IAAI,KACzB,kBAAC,UAAD;SACE,UAAU,MAAM;AAEd,UADA,EAAE,iBAAiB,EACnB,EAAc,EAAO;;SAEvB,WAAU;SACV,cAAY,EACV,GACA,uBACA,QACD;SACD,OAAO,EACL,GACA,6BACA,eACD;mBAED,kBAAC,OAAD;UACE,WAAU;UACV,MAAK;UACL,SAAQ;UACR,QAAO;oBAEP,kBAAC,QAAD;WACE,eAAc;WACd,gBAAe;WACf,aAAa;WACb,GAAE;WACF,CAAA;UACE,CAAA;SACC,CAAA;QAGV,EAAgB,EAAO,IAAI,KAC1B,kBAAC,UAAD;SACE,UAAU,MAAM;AAEd,UADA,EAAE,iBAAiB,EACnB,EAAe,EAAO;;SAExB,WAAU;SACV,cAAY,EACV,GACA,wBACA,SACD;SACD,OAAO,EAAc,GAAG,wBAAwB,SAAS;mBAEzD,kBAAC,OAAD;UACE,WAAU;UACV,MAAK;UACL,SAAQ;UACR,QAAO;oBAEP,kBAAC,QAAD;WACE,eAAc;WACd,gBAAe;WACf,aAAa;WACb,GAAE;WACF,CAAA;UACE,CAAA;SACC,CAAA;QAGV,EAAgB,EAAO,IAAI,KAC1B,kBAAC,UAAD;SACE,UAAU,MAAM;AAEd,UADA,EAAE,iBAAiB,EACnB,EAAe,EAAO;;SAExB,WAAU;SACV,cAAY,EACV,GACA,wBACA,SACD;SACD,OAAO,EAAc,GAAG,wBAAwB,SAAS;mBAEzD,kBAAC,OAAD;UACE,WAAU;UACV,MAAK;UACL,SAAQ;UACR,QAAO;oBAEP,kBAAC,QAAD;WACE,eAAc;WACd,gBAAe;WACf,aAAa;WACb,GAAE;WACF,CAAA;UACE,CAAA;SACC,CAAA;QAGX,kBAAC,OAAD;SAAK,UAAU,MAAM,EAAE,iBAAiB;mBACtC,kBAAC,IAAD;UACE,OAAO,EACL;WACE,SACE,EAAe,EAAO,IAAI,UAChB,EAAc,EAAO,GAC3B,KAAA;WACN,UACE,EAAgB,EAAO,IAAI,UACjB,EAAe,EAAO,GAC5B,KAAA;WACN,QACE,EAAgB,EAAO,IAAI,UACjB,EAAiB,EAAO,GAC9B,KAAA;WACN,QACE,EAAgB,EAAO,IAAI,UACjB,EAAa,EAAO,GAC1B,KAAA;WACN,cAAc,IAAe,EAAO;WACpC,WACE,EAAgB,EAAO,IAAI,UACjB,EAAgB,EAAO,GAC7B,KAAA;WACN,UACE,EAAgB,EAAO,IAAI,UACjB,EAAe,EAAO,GAC5B,KAAA;WACN,WAAW,EAAO;WACnB,EACD,EACD;UACD,QAAQ,OAAe,EAAO;UAC9B,WAAW,MAAS,GAAc,IAAO,EAAO,KAAK,KAAK;UAC1D,CAAA;SACE,CAAA;QACF;;MACF;OApOC,EAAO,GAoOR,CACN,EAED,GAAY,KAAK,MAChB,kBAAC,IAAD;KAEQ;KACN,YAAY,EAAc,IAAI,EAAK,GAAG;KACtC,YAAY,GAAa,KAAK,OAAO,EAAK;KAC1C,WAAW,EAAY,EAAK,GAAG,IAAgB,KAAA;KAC/C,SAAS,EAAa,EAAK,GAAG,IAAc,KAAA;KAC5C,UAAU,EAAc,EAAK,GAAG,IAAe,KAAA;KAC/C,WAAW,EAAc,EAAK,GAAG,IAAgB,KAAA;KACjD,YAAY,EAAc,EAAK,GAAG,IAAiB,KAAA;KACnD,UAAU,EAAc,EAAK,GAAG,IAAe,KAAA;KAC/C,YAAY,EAAY,EAAK,GAAG,IAAiB,KAAA;KACjD,QAAQ,EAAY,EAAK,GAAG,IAAa,KAAA;KACzC,QAAQ,EAAc,EAAK,GAAG,IAAa,KAAA;KAC3C,QAAQ;KACR,YAAY;KACZ,aACE,EAAc,EAAK,GAAG,KAAsB,KAAA;KAE9C,WAAW;KACX,eAAe;KACf,EApBK,EAAK,GAoBV,CACF,CACE;;GACL,KACC,kBAAC,GAAD;IACE,GAAG,EAAY;IACf,GAAG,EAAY;IACf,SAAS;IACT,OAAO,GAAqB;IAC5B,CAAA;GAEA;MAIH,OAxWH,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,GAAc,KAAK,MAClB,kBAAC,IAAD;IAEU;IACR,YAAY,EAAgB,IAAI,EAAO,GAAG;IAC1C,YAAY,GAAa,KAAK,OAAO,EAAO;IAC5C,cAAc,EAAU,uBAAuB,EAAO;IACzC;IACb,QAAQ,EAAc,EAAO,GAAG,IAAe,KAAA;IAC/C,SAAS,EAAe,EAAO,GAAG,IAAgB,KAAA;IAClD,UAAU,EAAgB,EAAO,GAAG,IAAiB,KAAA;IACrD,WAAW,EAAgB,EAAO,GAAG,IAAkB,KAAA;IACvD,UAAU,EAAgB,EAAO,GAAG,IAAiB,KAAA;IACrD,YACE,EAAgB,EAAO,GAAG,IAAmB,KAAA;IAE/C,QAAQ;IACR,QAAQ,EAAgB,EAAO,GAAG,IAAe,KAAA;IACjD,QAAQ;IACR,YAAY;IACZ,aACE,EAAgB,EAAO,GAAG,KAAwB,KAAA;IAEpD,WAAW;IACX,QAAQ,EAAgB,EAAO,GAAG,IAAmB,KAAA;IACrD,eAAe;IACf,EAxBK,EAAO,GAwBZ,CACF,EAED,GAAY,KAAK,MAChB,kBAAC,IAAD;IAEQ;IACN,YAAY,EAAc,IAAI,EAAK,GAAG;IACtC,YAAY,GAAa,KAAK,OAAO,EAAK;IAC1C,WAAW,EAAY,EAAK,GAAG,IAAgB,KAAA;IAC/C,SAAS,EAAa,EAAK,GAAG,IAAc,KAAA;IAC5C,UAAU,EAAc,EAAK,GAAG,IAAe,KAAA;IAC/C,WAAW,EAAc,EAAK,GAAG,IAAgB,KAAA;IACjD,YAAY,EAAc,EAAK,GAAG,IAAiB,KAAA;IACnD,UAAU,EAAc,EAAK,GAAG,IAAe,KAAA;IAC/C,YAAY,EAAY,EAAK,GAAG,IAAiB,KAAA;IACjD,QAAQ,EAAY,EAAK,GAAG,IAAa,KAAA;IACzC,QAAQ,EAAc,EAAK,GAAG,IAAa,KAAA;IAC3C,QAAQ;IACR,YAAY;IACZ,aACE,EAAc,EAAK,GAAG,KAAsB,KAAA;IAE9C,WAAW;IACX,eAAe;IACf,EApBK,EAAK,GAoBV,CACF,CACE;MACL,KACC,kBAAC,GAAD;GACE,GAAG,EAAY;GACf,GAAG,EAAY;GACf,SAAS;GACT,OAAO,GAAqB;GAC5B,CAAA,CAEA"}
|
|
1
|
+
{"version":3,"file":"FileBrowser.js","names":[],"sources":["../../../src/files/components/FileBrowser.tsx"],"sourcesContent":["import { type FC, useState } from \"react\";\nimport { Grid3x3, Loader2, Star } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem, FolderItem } from \"../types\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { FileCard } from \"./FileCard\";\nimport { FileListItem } from \"./FileListItem\";\nimport { FolderCard } from \"./FolderCard\";\nimport { ActionMenu } from \"./ActionMenu\";\nimport { ContextMenu } from \"./ContextMenu\";\nimport { createFileMenuItems, createFolderMenuItems } from \"./contextMenuItems\";\nimport { sortFiles } from \"../utils\";\nimport { tWithFallback } from \"../utils/i18n\";\nimport {\n useDragDrop,\n type DragData,\n type DragOperation,\n} from \"../hooks/useDragDrop\";\n\ninterface FileBrowserProps {\n files: FileItem[];\n folders: FolderItem[];\n loading?: boolean;\n error?: Error | null;\n preserveSortOrder?: boolean;\n onFilePreview?: (file: FileItem) => void;\n onFileShare?: (file: FileItem) => void;\n onFileDelete?: (file: FileItem) => void;\n onFileRestore?: (file: FileItem) => void;\n onFileFavorite?: (file: FileItem) => void;\n onFileRename?: (file: FileItem) => void;\n onFileDownload?: (file: FileItem) => void;\n onFileCopy?: (file: FileItem) => void;\n onFileMove?: (file: FileItem) => void;\n onFileInfo?: (file: FileItem) => void;\n onFileActivity?: (file: FileItem) => void;\n onFolderOpen?: (folder: FolderItem) => void;\n onFolderShare?: (folder: FolderItem) => void;\n onFolderDelete?: (folder: FolderItem) => void;\n onFolderRestore?: (folder: FolderItem) => void;\n onFolderRename?: (folder: FolderItem) => void;\n onFolderFavorite?: (folder: FolderItem) => void;\n onFolderCopy?: (folder: FolderItem) => void;\n onFolderMove?: (folder: FolderItem) => void;\n onFolderInfo?: (folder: FolderItem) => void;\n onFolderActivity?: (folder: FolderItem) => void;\n onMoveFile?: (fileId: string, targetFolderId: string) => Promise<void>;\n onCopyFile?: (fileId: string, targetFolderId: string) => Promise<void>;\n onMoveFolder?: (folderId: string, targetFolderId: string) => Promise<void>;\n onCopyFolder?: (folderId: string, targetFolderId: string) => Promise<void>;\n}\n\nexport const FileBrowser: FC<FileBrowserProps> = ({\n files,\n folders,\n loading = false,\n error = null,\n preserveSortOrder = false,\n onFilePreview,\n onFileShare,\n onFileDelete,\n onFileRestore,\n onFileFavorite,\n onFileRename,\n onFileDownload,\n onFileCopy,\n onFileMove,\n onFileInfo,\n onFileActivity,\n onFolderOpen,\n onFolderShare,\n onFolderDelete,\n onFolderRestore,\n onFolderRename,\n onFolderFavorite,\n onFolderCopy,\n onFolderMove,\n onFolderInfo,\n onFolderActivity,\n onMoveFile,\n onCopyFile,\n onMoveFolder,\n onCopyFolder,\n}) => {\n const { t } = useI18n();\n const { viewMode, sortBy, sortDirection, selectedFiles, selectedFolders } =\n useFilesStore();\n\n const [openMenuId, setOpenMenuId] = useState<string | null>(null);\n const [dragState, setDragState] = useState<{\n draggedItem: DragData | null;\n dropTargetFolderId: string | null;\n }>({ draggedItem: null, dropTargetFolderId: null });\n const [contextMenu, setContextMenu] = useState<{\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n x: number;\n y: number;\n } | null>(null);\n\n const { draggedItem, startDrag, endDrag, handleDrop } = useDragDrop({\n onMoveFile,\n onCopyFile,\n onMoveFolder,\n onCopyFolder,\n });\n\n const handleFileDragStart = (file: FileItem, operation: DragOperation) => {\n startDrag({ type: \"file\", item: file, operation });\n setDragState({\n draggedItem: { type: \"file\", item: file, operation },\n dropTargetFolderId: null,\n });\n };\n\n const handleFolderDragStart = (\n folder: FolderItem,\n operation: DragOperation,\n ) => {\n startDrag({ type: \"folder\", item: folder, operation });\n setDragState({\n draggedItem: { type: \"folder\", item: folder, operation },\n dropTargetFolderId: null,\n });\n };\n\n const handleDragEnd = () => {\n endDrag();\n setDragState({ draggedItem: null, dropTargetFolderId: null });\n };\n\n const handleFolderDrop = async (folder: FolderItem) => {\n if (draggedItem) {\n await handleDrop(folder.id);\n setDragState({ draggedItem: null, dropTargetFolderId: null });\n }\n };\n\n const handleFolderDragOver = (folderId: string) => {\n setDragState((prev) => ({ ...prev, dropTargetFolderId: folderId }));\n };\n\n const handleFolderDragLeave = () => {\n setDragState((prev) => ({ ...prev, dropTargetFolderId: null }));\n };\n\n const handleFileContextMenu = (file: FileItem, x: number, y: number) => {\n setContextMenu({ item: file, type: \"file\", x, y });\n };\n\n const handleFolderContextMenu = (\n folder: FolderItem,\n x: number,\n y: number,\n ) => {\n setContextMenu({ item: folder, type: \"folder\", x, y });\n };\n\n const closeContextMenu = () => {\n setContextMenu(null);\n };\n\n const fileCanRead = (file: FileItem) =>\n file.canRead === true || file.canUpdate === true || file.canWrite === true;\n const fileCanUpdate = (file: FileItem) =>\n file.canUpdate === true || file.canWrite === true;\n const fileCanShare = (file: FileItem) =>\n file.canShare === true || fileCanUpdate(file);\n const fileCanDelete = (file: FileItem) => file.canDelete === true;\n\n const folderCanRead = (folder: FolderItem) =>\n folder.canRead === true || folder.permissions?.canRead === true;\n const folderCanUpdate = (folder: FolderItem) =>\n folder.canUpdate === true || folder.permissions?.canWrite === true;\n const folderCanShare = (folder: FolderItem) =>\n folder.permissions?.canShare === true || folderCanUpdate(folder);\n const folderCanDelete = (folder: FolderItem) =>\n folder.canDelete === true || folder.permissions?.canDelete === true;\n\n const getContextMenuItems = () => {\n if (!contextMenu) return [];\n if (contextMenu.type === \"file\") {\n const file = contextMenu.item as FileItem;\n return createFileMenuItems(\n {\n onShare:\n onFileShare && fileCanShare(file)\n ? () => onFileShare(file)\n : undefined,\n onDownload:\n onFileDownload && fileCanRead(file)\n ? () => onFileDownload(file)\n : undefined,\n onCopy:\n onFileCopy && fileCanRead(file)\n ? () => onFileCopy(file)\n : undefined,\n onRename:\n onFileRename && fileCanUpdate(file)\n ? () => onFileRename(file)\n : undefined,\n onStar:\n onFileFavorite && fileCanUpdate(file)\n ? () => onFileFavorite(file)\n : undefined,\n onMove:\n onFileMove && fileCanUpdate(file)\n ? () => onFileMove(file)\n : undefined,\n onInfo: onFileInfo ? () => onFileInfo(file) : undefined,\n onActivity: onFileActivity ? () => onFileActivity(file) : undefined,\n onDelete:\n onFileDelete && fileCanDelete(file)\n ? () => onFileDelete(file)\n : undefined,\n onRestore:\n onFileRestore && fileCanUpdate(file)\n ? () => onFileRestore(file)\n : undefined,\n isStarred: file.starred,\n },\n t,\n );\n } else {\n const folder = contextMenu.item as FolderItem;\n return createFolderMenuItems(\n {\n onShare:\n onFolderShare && folderCanShare(folder)\n ? () => onFolderShare(folder)\n : undefined,\n onRename:\n onFolderRename && folderCanUpdate(folder)\n ? () => onFolderRename(folder)\n : undefined,\n onStar:\n onFolderFavorite && folderCanUpdate(folder)\n ? () => onFolderFavorite(folder)\n : undefined,\n onMove:\n onFolderMove && folderCanUpdate(folder)\n ? () => onFolderMove(folder)\n : undefined,\n onInfo: onFolderInfo ? () => onFolderInfo(folder) : undefined,\n onDelete:\n onFolderDelete && folderCanDelete(folder)\n ? () => onFolderDelete(folder)\n : undefined,\n onRestore:\n onFolderRestore && folderCanUpdate(folder)\n ? () => onFolderRestore(folder)\n : undefined,\n isStarred: folder.starred,\n },\n t,\n );\n }\n };\n\n const sortedFiles = preserveSortOrder\n ? files\n : sortFiles(files, sortBy, sortDirection);\n const sortedFolders = preserveSortOrder\n ? folders\n : sortFiles(folders, sortBy, sortDirection);\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center min-h-[500px]\">\n <div className=\"flex flex-col items-center gap-4\">\n <Loader2 className=\"size-10 animate-spin text-action-primary-bg\" />\n <span className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.browser.loading\", \"Loading files…\")}\n </span>\n </div>\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center min-h-[500px]\">\n <div className=\"text-center max-w-md\">\n <div className=\"mb-3 text-xl font-semibold text-status-error-text\">\n {tWithFallback(\n t,\n \"files.browser.loadError\",\n \"Failed to load files\",\n )}\n </div>\n <p className=\"mb-6 text-sm text-text-secondary\">\n {error.message ||\n tWithFallback(\n t,\n \"files.browser.unexpectedError\",\n \"An unexpected error occurred\",\n )}\n </p>\n <button\n type=\"button\"\n onClick={() => window.location.reload()}\n className=\"rounded-lg bg-action-primary-bg px-6 py-2.5 text-sm font-medium text-text-inverse transition-colors hover:bg-action-primary-bg-hover\"\n >\n {tWithFallback(t, \"files.browser.retry\", \"Retry\")}\n </button>\n </div>\n </div>\n );\n }\n\n if (files.length === 0 && folders.length === 0) {\n return (\n <>\n {contextMenu && (\n <ContextMenu\n x={contextMenu.x}\n y={contextMenu.y}\n onClose={closeContextMenu}\n items={getContextMenuItems()}\n />\n )}\n </>\n );\n }\n\n if (viewMode !== \"list\") {\n return (\n <div className=\"@container bg-bg-canvas p-page-padding\">\n <div className=\"grid grid-cols-2 @md:grid-cols-3 @lg:grid-cols-4 @xl:grid-cols-5 gap-4\">\n {sortedFolders.map((folder) => (\n <FolderCard\n key={folder.id}\n folder={folder}\n isSelected={selectedFolders.has(folder.id)}\n isDragging={draggedItem?.item.id === folder.id}\n isDropTarget={dragState.dropTargetFolderId === folder.id}\n draggedItem={draggedItem}\n onOpen={folderCanRead(folder) ? onFolderOpen : undefined}\n onShare={folderCanShare(folder) ? onFolderShare : undefined}\n onDelete={folderCanDelete(folder) ? onFolderDelete : undefined}\n onRestore={folderCanUpdate(folder) ? onFolderRestore : undefined}\n onRename={folderCanUpdate(folder) ? onFolderRename : undefined}\n onFavorite={\n folderCanUpdate(folder) ? onFolderFavorite : undefined\n }\n onCopy={onFolderCopy}\n onMove={folderCanUpdate(folder) ? onFolderMove : undefined}\n onInfo={onFolderInfo}\n onActivity={onFolderActivity}\n onDragStart={\n folderCanUpdate(folder) ? handleFolderDragStart : undefined\n }\n onDragEnd={handleDragEnd}\n onDrop={folderCanUpdate(folder) ? handleFolderDrop : undefined}\n onContextMenu={handleFolderContextMenu}\n />\n ))}\n\n {sortedFiles.map((file) => (\n <FileCard\n key={file.id}\n file={file}\n isSelected={selectedFiles.has(file.id)}\n isDragging={draggedItem?.item.id === file.id}\n onPreview={fileCanRead(file) ? onFilePreview : undefined}\n onShare={fileCanShare(file) ? onFileShare : undefined}\n onDelete={fileCanDelete(file) ? onFileDelete : undefined}\n onRestore={fileCanUpdate(file) ? onFileRestore : undefined}\n onFavorite={fileCanUpdate(file) ? onFileFavorite : undefined}\n onRename={fileCanUpdate(file) ? onFileRename : undefined}\n onDownload={fileCanRead(file) ? onFileDownload : undefined}\n onCopy={fileCanRead(file) ? onFileCopy : undefined}\n onMove={fileCanUpdate(file) ? onFileMove : undefined}\n onInfo={onFileInfo}\n onActivity={onFileActivity}\n onDragStart={\n fileCanUpdate(file) ? handleFileDragStart : undefined\n }\n onDragEnd={handleDragEnd}\n onContextMenu={handleFileContextMenu}\n />\n ))}\n </div>\n {contextMenu && (\n <ContextMenu\n x={contextMenu.x}\n y={contextMenu.y}\n onClose={closeContextMenu}\n items={getContextMenuItems()}\n />\n )}\n </div>\n );\n }\n\n if (viewMode === \"list\") {\n return (\n <div className=\"@container bg-bg-canvas\">\n <div className=\"hidden @md:flex items-center gap-3 px-3 py-2 bg-bg-surface border-b border-border-subtle text-text-secondary font-text-sm font-weight-medium\">\n <div className=\"flex-shrink-0 w-4\" />\n <div className=\"flex-shrink-0 w-6\" />\n <div className=\"flex-1\">\n {tWithFallback(t, \"files.browser.name\", \"Name\")}\n </div>\n <div className=\"hidden @lg:block flex-shrink-0 w-40\">\n {tWithFallback(t, \"files.browser.owner\", \"Owner\")}\n </div>\n <div className=\"hidden @md:block flex-shrink-0 w-24 text-right\">\n {tWithFallback(t, \"files.browser.size\", \"Size\")}\n </div>\n <div className=\"hidden @lg:block flex-shrink-0 w-32 text-right\">\n {tWithFallback(t, \"files.browser.modified\", \"Modified\")}\n </div>\n <div className=\"flex-shrink-0 w-32\" />\n </div>\n\n <div className=\"divide-y divide-border-subtle\">\n {sortedFolders.map((folder) => (\n <div\n key={folder.id}\n className={`group flex items-center gap-3 border-b border-border-subtle bg-bg-surface p-3 transition-colors hover:bg-bg-sunken focus-within:bg-bg-sunken ${dragState.dropTargetFolderId === folder.id && draggedItem?.item.id !== folder.id ? \"bg-action-primary-bg/10\" : \"\"} ${draggedItem?.item.id === folder.id ? \"opacity-50\" : \"\"}`}\n onClick={() => {\n if (folderCanRead(folder)) onFolderOpen?.(folder);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n if (folderCanRead(folder)) onFolderOpen?.(folder);\n }\n }}\n onDragOver={(e) => {\n if (\n draggedItem &&\n draggedItem.item.id !== folder.id &&\n folderCanUpdate(folder)\n ) {\n e.preventDefault();\n handleFolderDragOver(folder.id);\n }\n }}\n onDragLeave={handleFolderDragLeave}\n onDrop={async (e) => {\n e.preventDefault();\n if (\n draggedItem &&\n draggedItem.item.id !== folder.id &&\n folderCanUpdate(folder)\n ) {\n await handleFolderDrop(folder);\n }\n }}\n onContextMenu={(e) => {\n e.preventDefault();\n handleFolderContextMenu(folder, e.clientX, e.clientY);\n }}\n role=\"button\"\n tabIndex={0}\n aria-label={tWithFallback(\n t,\n \"files.browser.openFolder\",\n \"Open folder\",\n )}\n >\n <div className=\"flex-shrink-0\">\n <input\n type=\"checkbox\"\n checked={selectedFolders.has(folder.id)}\n onChange={(e) => {\n e.stopPropagation();\n useFilesStore.getState().toggleFolderSelection(folder.id);\n }}\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 ${folder.name}`}\n />\n </div>\n <Grid3x3 className=\"size-6 text-action-primary-bg flex-shrink-0\" />\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 {folder.name}\n </span>\n {folder.starred && (\n <Star className=\"size-3 flex-shrink-0 fill-yellow-400 text-yellow-400\" />\n )}\n </div>\n </div>\n <div className=\"hidden @lg:block flex-shrink-0 w-40\">\n {folder.createdBy && (\n <div className=\"flex items-center gap-2\">\n {folder.createdBy.avatar && (\n <img\n src={folder.createdBy.avatar}\n alt={folder.createdBy.name}\n className=\"size-6 rounded-full\"\n />\n )}\n <span className=\"font-text-sm text-text-secondary truncate\">\n {folder.createdBy.name}\n </span>\n </div>\n )}\n </div>\n <div className=\"hidden @md:block flex-shrink-0 w-24 text-right\">\n <span className=\"font-text-sm text-text-secondary\">\n {folder.filesCount ?? 0}{\" \"}\n {tWithFallback(t, \"files.browser.items\", \"items\")}\n </span>\n </div>\n <div className=\"hidden @lg:block flex-shrink-0 w-32 text-right\">\n <span className=\"font-text-sm text-text-secondary\">\n {new Date(folder.updatedAt).toLocaleDateString()}\n </span>\n </div>\n\n <div className=\"flex w-32 flex-shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100\">\n {folderCanShare(folder) && onFolderShare && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onFolderShare(folder);\n }}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(\n t,\n \"files.browser.share\",\n \"Share\",\n )}\n title={tWithFallback(\n t,\n \"files.browser.shareFolder\",\n \"Share folder\",\n )}\n >\n <svg\n className=\"size-4 text-text-primary\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z\"\n />\n </svg>\n </button>\n )}\n\n {folderCanUpdate(folder) && onFolderRename && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onFolderRename(folder);\n }}\n className=\"hidden @md:block p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(\n t,\n \"files.browser.rename\",\n \"Rename\",\n )}\n title={tWithFallback(t, \"files.browser.rename\", \"Rename\")}\n >\n <svg\n className=\"size-4 text-text-primary\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n </button>\n )}\n\n {folderCanDelete(folder) && onFolderDelete && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onFolderDelete(folder);\n }}\n className=\"p-1.5 hover:bg-action-danger-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(\n t,\n \"files.browser.delete\",\n \"Delete\",\n )}\n title={tWithFallback(t, \"files.browser.delete\", \"Delete\")}\n >\n <svg\n className=\"size-4 text-status-error-text\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n </button>\n )}\n\n <div onClick={(e) => e.stopPropagation()}>\n <ActionMenu\n items={createFolderMenuItems(\n {\n onShare:\n folderCanShare(folder) && onFolderShare\n ? () => onFolderShare(folder)\n : undefined,\n onRename:\n folderCanUpdate(folder) && onFolderRename\n ? () => onFolderRename(folder)\n : undefined,\n onStar:\n folderCanUpdate(folder) && onFolderFavorite\n ? () => onFolderFavorite(folder)\n : undefined,\n onMove:\n folderCanUpdate(folder) && onFolderMove\n ? () => onFolderMove(folder)\n : undefined,\n onInfo: () => onFolderInfo?.(folder),\n onRestore:\n folderCanUpdate(folder) && onFolderRestore\n ? () => onFolderRestore(folder)\n : undefined,\n onDelete:\n folderCanDelete(folder) && onFolderDelete\n ? () => onFolderDelete(folder)\n : undefined,\n isStarred: folder.starred,\n },\n t,\n )}\n isOpen={openMenuId === folder.id}\n onToggle={(open) => setOpenMenuId(open ? folder.id : null)}\n />\n </div>\n </div>\n </div>\n ))}\n\n {sortedFiles.map((file) => (\n <FileListItem\n key={file.id}\n file={file}\n isSelected={selectedFiles.has(file.id)}\n isDragging={draggedItem?.item.id === file.id}\n onPreview={fileCanRead(file) ? onFilePreview : undefined}\n onShare={fileCanShare(file) ? onFileShare : undefined}\n onDelete={fileCanDelete(file) ? onFileDelete : undefined}\n onRestore={fileCanUpdate(file) ? onFileRestore : undefined}\n onFavorite={fileCanUpdate(file) ? onFileFavorite : undefined}\n onRename={fileCanUpdate(file) ? onFileRename : undefined}\n onDownload={fileCanRead(file) ? onFileDownload : undefined}\n onCopy={fileCanRead(file) ? onFileCopy : undefined}\n onMove={fileCanUpdate(file) ? onFileMove : undefined}\n onInfo={onFileInfo}\n onActivity={onFileActivity}\n onDragStart={\n fileCanUpdate(file) ? handleFileDragStart : undefined\n }\n onDragEnd={handleDragEnd}\n onContextMenu={handleFileContextMenu}\n />\n ))}\n </div>\n {contextMenu && (\n <ContextMenu\n x={contextMenu.x}\n y={contextMenu.y}\n onClose={closeContextMenu}\n items={getContextMenuItems()}\n />\n )}\n </div>\n );\n }\n\n return null;\n};\n"],"mappings":"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"}
|
|
@@ -185,6 +185,7 @@ var C = ({ file: C, isSelected: w = !1, isDragging: T = !1, onSelect: E, onPrevi
|
|
|
185
185
|
className: "absolute bottom-3 right-3 flex items-center gap-1 bg-bg-elevated border border-border-subtle rounded shadow-elevation-2 p-1",
|
|
186
186
|
children: [
|
|
187
187
|
N && /* @__PURE__ */ b("button", {
|
|
188
|
+
type: "button",
|
|
188
189
|
onClick: (e) => Y(e, () => N(C)),
|
|
189
190
|
className: "p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors",
|
|
190
191
|
"aria-label": i(V, "files.card.download", "Download"),
|
|
@@ -192,6 +193,7 @@ var C = ({ file: C, isSelected: w = !1, isDragging: T = !1, onSelect: E, onPrevi
|
|
|
192
193
|
children: /* @__PURE__ */ b(d, { className: "size-4 text-text-primary" })
|
|
193
194
|
}),
|
|
194
195
|
O && /* @__PURE__ */ b("button", {
|
|
196
|
+
type: "button",
|
|
195
197
|
onClick: (e) => Y(e, () => O(C)),
|
|
196
198
|
className: "p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors",
|
|
197
199
|
"aria-label": i(V, "files.card.share", "Share"),
|
|
@@ -199,6 +201,7 @@ var C = ({ file: C, isSelected: w = !1, isDragging: T = !1, onSelect: E, onPrevi
|
|
|
199
201
|
children: /* @__PURE__ */ b(g, { className: "size-4 text-text-primary" })
|
|
200
202
|
}),
|
|
201
203
|
j && /* @__PURE__ */ b("button", {
|
|
204
|
+
type: "button",
|
|
202
205
|
onClick: (e) => Y(e, () => j(C)),
|
|
203
206
|
className: "p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors",
|
|
204
207
|
"aria-label": C.starred ? i(V, "files.card.unfavorite", "Unfavorite") : i(V, "files.card.favorite", "Favorite"),
|
|
@@ -206,6 +209,7 @@ var C = ({ file: C, isSelected: w = !1, isDragging: T = !1, onSelect: E, onPrevi
|
|
|
206
209
|
children: /* @__PURE__ */ b(_, { className: `size-4 ${C.starred ? "fill-status-warning-text text-status-warning-text" : "text-text-primary"}` })
|
|
207
210
|
}),
|
|
208
211
|
A && /* @__PURE__ */ b("button", {
|
|
212
|
+
type: "button",
|
|
209
213
|
onClick: (e) => Y(e, () => A(C)),
|
|
210
214
|
className: "p-1.5 hover:bg-status-success-bg-subtle rounded transition-colors",
|
|
211
215
|
"aria-label": i(V, "files.card.restore", "Restore"),
|
|
@@ -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 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 handleClick = () => {\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 <div\n className={`@container group relative cursor-pointer overflow-hidden rounded-card border bg-bg-surface shadow-elevation-1 transition-shadow hover:shadow-elevation-2 focus-within:shadow-elevation-2 ${isDragging ? \"opacity-50\" : \"border-border-subtle\"}`}\n onClick={handleClick}\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 handleClick();\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>{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 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 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 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 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 </div>\n );\n};\n"],"mappings":"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"}
|
|
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 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 handleClick = () => {\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 <div\n className={`@container group relative cursor-pointer overflow-hidden rounded-card border bg-bg-surface shadow-elevation-1 transition-shadow hover:shadow-elevation-2 focus-within:shadow-elevation-2 ${isDragging ? \"opacity-50\" : \"border-border-subtle\"}`}\n onClick={handleClick}\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 handleClick();\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>{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 </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -38,6 +38,7 @@ function _({ item: n, type: _, onClose: v }) {
|
|
|
38
38
|
className: "text-lg font-semibold text-text-primary",
|
|
39
39
|
children: b ? e(y, "files.info.fileInfo", "File Information") : e(y, "files.info.folderInfo", "Folder Information")
|
|
40
40
|
}), /* @__PURE__ */ p("button", {
|
|
41
|
+
type: "button",
|
|
41
42
|
onClick: v,
|
|
42
43
|
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",
|
|
43
44
|
"aria-label": e(y, "files.info.closePanel", "Close information panel"),
|
|
@@ -189,6 +190,7 @@ function _({ item: n, type: _, onClose: v }) {
|
|
|
189
190
|
b && x && /* @__PURE__ */ p("div", {
|
|
190
191
|
className: "pt-6 border-t border-border-default",
|
|
191
192
|
children: /* @__PURE__ */ m("button", {
|
|
193
|
+
type: "button",
|
|
192
194
|
onClick: () => w(!0),
|
|
193
195
|
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",
|
|
194
196
|
children: [/* @__PURE__ */ p(o, { className: "size-4" }), e(y, "files.info.viewVersionHistory", "View Version History")]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileInfoPanel.js","names":[],"sources":["../../../src/files/components/FileInfoPanel.tsx"],"sourcesContent":["import { useEffect, 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 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 useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n if (showVersionHistory) {\n setShowVersionHistory(false);\n return;\n }\n\n onClose();\n }\n };\n\n document.addEventListener(\"keydown\", handleEscape);\n return () => document.removeEventListener(\"keydown\", handleEscape);\n }, [onClose, showVersionHistory]);\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-default bg-bg-surface shadow-2xl animate-in slide-in-from-right duration-300 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 bg-bg-surface border-b border-border-default 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 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 <div className=\"flex items-center justify-center py-8 bg-bg-muted rounded-lg\">\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 </div>\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 */}\n <div className=\"pt-6 border-t border-border-default\">\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">\n {tWithFallback(t, \"files.info.properties\", \"Properties\")}\n </h4>\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 </div>\n\n {/* Version History Button (Files only) */}\n {isFile && file && (\n <div className=\"pt-6 border-t border-border-default\">\n <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":[],"sources":["../../../src/files/components/FileInfoPanel.tsx"],"sourcesContent":["import { useEffect, 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 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 useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n if (showVersionHistory) {\n setShowVersionHistory(false);\n return;\n }\n\n onClose();\n }\n };\n\n document.addEventListener(\"keydown\", handleEscape);\n return () => document.removeEventListener(\"keydown\", handleEscape);\n }, [onClose, showVersionHistory]);\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-default bg-bg-surface shadow-2xl animate-in slide-in-from-right duration-300 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 bg-bg-surface border-b border-border-default 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 <div className=\"flex items-center justify-center py-8 bg-bg-muted rounded-lg\">\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 </div>\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 */}\n <div className=\"pt-6 border-t border-border-default\">\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">\n {tWithFallback(t, \"files.info.properties\", \"Properties\")}\n </h4>\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 </div>\n\n {/* Version History Button (Files only) */}\n {isFile && file && (\n <div className=\"pt-6 border-t border-border-default\">\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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"}
|
|
@@ -177,6 +177,7 @@ var S = ({ file: S, isSelected: C = !1, isDragging: w = !1, onSelect: T, onPrevi
|
|
|
177
177
|
className: "flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100",
|
|
178
178
|
children: [
|
|
179
179
|
S.canRead && M && /* @__PURE__ */ y("button", {
|
|
180
|
+
type: "button",
|
|
180
181
|
onClick: (e) => K(e, () => M(S)),
|
|
181
182
|
className: "p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors",
|
|
182
183
|
"aria-label": i(B, "files.card.download", "Download"),
|
|
@@ -184,6 +185,7 @@ var S = ({ file: S, isSelected: C = !1, isDragging: w = !1, onSelect: T, onPrevi
|
|
|
184
185
|
children: /* @__PURE__ */ y(d, { className: "size-4 text-text-primary" })
|
|
185
186
|
}),
|
|
186
187
|
D && /* @__PURE__ */ y("button", {
|
|
188
|
+
type: "button",
|
|
187
189
|
onClick: (e) => K(e, () => D(S)),
|
|
188
190
|
className: "p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors",
|
|
189
191
|
"aria-label": i(B, "files.card.share", "Share"),
|
|
@@ -191,6 +193,7 @@ var S = ({ file: S, isSelected: C = !1, isDragging: w = !1, onSelect: T, onPrevi
|
|
|
191
193
|
children: /* @__PURE__ */ y(g, { className: "size-4 text-text-primary" })
|
|
192
194
|
}),
|
|
193
195
|
A && /* @__PURE__ */ y("button", {
|
|
196
|
+
type: "button",
|
|
194
197
|
onClick: (e) => K(e, () => A(S)),
|
|
195
198
|
className: "p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors",
|
|
196
199
|
"aria-label": S.starred ? i(B, "files.card.unfavorite", "Unfavorite") : i(B, "files.card.favorite", "Favorite"),
|
|
@@ -198,6 +201,7 @@ var S = ({ file: S, isSelected: C = !1, isDragging: w = !1, onSelect: T, onPrevi
|
|
|
198
201
|
children: /* @__PURE__ */ y(_, { className: `size-4 ${S.starred ? "fill-status-warning-bg text-status-warning-bg" : "text-text-primary"}` })
|
|
199
202
|
}),
|
|
200
203
|
k && /* @__PURE__ */ y("button", {
|
|
204
|
+
type: "button",
|
|
201
205
|
onClick: (e) => K(e, () => k(S)),
|
|
202
206
|
className: "p-1.5 hover:bg-status-success-bg-subtle rounded transition-colors",
|
|
203
207
|
"aria-label": i(B, "files.card.restore", "Restore"),
|
|
@@ -205,6 +209,7 @@ var S = ({ file: S, isSelected: C = !1, isDragging: w = !1, onSelect: T, onPrevi
|
|
|
205
209
|
children: /* @__PURE__ */ y(h, { className: "size-4 text-status-success-text" })
|
|
206
210
|
}),
|
|
207
211
|
S.canWrite && j && /* @__PURE__ */ y("button", {
|
|
212
|
+
type: "button",
|
|
208
213
|
onClick: (e) => K(e, () => j(S)),
|
|
209
214
|
className: "hidden @md:block p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors",
|
|
210
215
|
"aria-label": i(B, "files.card.rename", "Rename"),
|
|
@@ -212,6 +217,7 @@ var S = ({ file: S, isSelected: C = !1, isDragging: w = !1, onSelect: T, onPrevi
|
|
|
212
217
|
children: /* @__PURE__ */ y(f, { className: "size-4 text-text-primary" })
|
|
213
218
|
}),
|
|
214
219
|
S.canDelete && O && /* @__PURE__ */ y("button", {
|
|
220
|
+
type: "button",
|
|
215
221
|
onClick: (e) => K(e, () => O(S)),
|
|
216
222
|
className: "p-1.5 hover:bg-action-danger-bg-hover rounded transition-colors",
|
|
217
223
|
"aria-label": i(B, "files.card.delete", "Delete"),
|
|
@@ -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 handleClick = () => {\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-subtle bg-bg-surface p-3 transition-colors hover:bg-bg-sunken focus-within:bg-bg-sunken ${isDragging ? \"opacity-50\" : \"\"}`}\n onClick={handleClick}\n onContextMenu={handleContextMenu}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n handleClick();\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\">\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 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 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 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 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 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 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":[],"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 handleClick = () => {\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-subtle bg-bg-surface p-3 transition-colors hover:bg-bg-sunken focus-within:bg-bg-sunken ${isDragging ? \"opacity-50\" : \"\"}`}\n onClick={handleClick}\n onContextMenu={handleContextMenu}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n handleClick();\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\">\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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"}
|