@burdenoff/microfe-files 2026.528.2 → 2026.530.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.
@@ -580,6 +580,7 @@ function d() {
580
580
  children: [
581
581
  /* @__PURE__ */ l("div", {
582
582
  className: "bg-bg-surface border-b border-border-default px-4 py-3 sm:px-6 sm:py-4",
583
+ "data-tour": "files-breadcrumb-nav",
583
584
  children: /* @__PURE__ */ l("div", {
584
585
  className: "flex items-center gap-2 sm:gap-4",
585
586
  children: /* @__PURE__ */ u("div", {
@@ -609,10 +610,13 @@ function d() {
609
610
  })
610
611
  })
611
612
  }),
612
- /* @__PURE__ */ l(Ce, {
613
- activeTab: v,
614
- onTabChange: it,
615
- tabs: at
613
+ /* @__PURE__ */ l("div", {
614
+ "data-tour": "files-tab-bar",
615
+ children: /* @__PURE__ */ l(Ce, {
616
+ activeTab: v,
617
+ onTabChange: it,
618
+ tabs: at
619
+ })
616
620
  }),
617
621
  /* @__PURE__ */ u("div", {
618
622
  className: "bg-bg-surface border-b border-border-default px-4 py-2 sm:px-6 sm:py-3",
@@ -621,6 +625,7 @@ function d() {
621
625
  className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 sm:gap-inline-gap",
622
626
  children: [/* @__PURE__ */ l("div", {
623
627
  className: "w-full sm:flex-1 min-w-0 order-2 sm:order-1",
628
+ "data-tour": "files-search-bar",
624
629
  children: /* @__PURE__ */ l("div", {
625
630
  className: "relative w-full max-w-2xl",
626
631
  children: /* @__PURE__ */ l(ke, {
@@ -649,6 +654,7 @@ function d() {
649
654
  type: "button",
650
655
  onClick: Zt,
651
656
  className: "flex items-center gap-1 sm:gap-2 px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-lg hover:bg-action-ghost-bg-hover hover:border-border-default transition-all duration-200 shadow-sm",
657
+ "data-tour": "files-new-folder-button",
652
658
  children: [/* @__PURE__ */ l(Ve, { className: "size-4" }), /* @__PURE__ */ l("span", {
653
659
  className: "hidden sm:inline",
654
660
  children: a(d, "files.browser.actions.newFolder", "New Folder")
@@ -659,6 +665,7 @@ function d() {
659
665
  onClick: Wt,
660
666
  disabled: wt,
661
667
  className: "flex items-center gap-1 sm:gap-2 px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-lg hover:bg-action-ghost-bg-hover hover:border-border-default transition-all duration-200 shadow-sm disabled:opacity-50 disabled:cursor-not-allowed",
668
+ "data-tour": "files-upload-files-button",
662
669
  children: wt ? /* @__PURE__ */ u(c, { children: [/* @__PURE__ */ l(s, { className: "size-4 animate-spin" }), /* @__PURE__ */ l("span", {
663
670
  className: "hidden sm:inline",
664
671
  children: a(d, "files.browser.upload.uploading", "Uploading...")
@@ -678,6 +685,7 @@ function d() {
678
685
  ] }),
679
686
  /* @__PURE__ */ u("div", {
680
687
  className: "flex items-center border border-border-default rounded-lg overflow-hidden",
688
+ "data-tour": "files-view-mode-toggle",
681
689
  children: [/* @__PURE__ */ l("button", {
682
690
  type: "button",
683
691
  onClick: () => nt("grid"),
@@ -797,6 +805,7 @@ function d() {
797
805
  }),
798
806
  /* @__PURE__ */ u("div", {
799
807
  className: "px-2 sm:px-4 md:px-6 py-3 sm:py-4",
808
+ "data-tour": "files-browser-grid",
800
809
  children: [/* @__PURE__ */ l(Se, {
801
810
  files: D,
802
811
  folders: O,
@@ -1 +1 @@
1
- {"version":3,"file":"BrowserPage.js","names":[],"sources":["../../../src/files/pages/BrowserPage.tsx"],"sourcesContent":["import { useState, useEffect, useMemo } from \"react\";\nimport { useParams, useNavigate } from \"react-router-dom\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { useKeyboardNavigation } from \"../hooks/useKeyboardNavigation\";\nimport {\n Upload,\n FolderPlus,\n FolderUp,\n Grid3x3,\n List,\n Search,\n X,\n Loader2,\n Trash2,\n Home,\n FileDown,\n FolderX,\n} from \"lucide-react\";\nimport { useFilesContext } from \"../providers/FilesProvider\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { useBrowsePage } from \"../hooks/useBrowsePage\";\nimport { useRecentFiles } from \"../hooks/useRecentFiles\";\nimport { useStarredItems } from \"../hooks/useStarredItems\";\nimport { useBinItems } from \"../hooks/useBinItems\";\nimport { useCreateFolder } from \"../hooks/useCreateFolder\";\nimport { useUploadFile } from \"../hooks/useUploadFile\";\nimport { useDeleteFile } from \"../hooks/useDeleteFile\";\nimport { useDeleteFolder } from \"../hooks/useDeleteFolder\";\nimport { useRestoreFile } from \"../hooks/useRestoreFile\";\nimport { useRestoreFolder } from \"../hooks/useRestoreFolder\";\nimport { usePermanentlyDeleteFile } from \"../hooks/usePermanentlyDeleteFile\";\nimport { usePermanentlyDeleteFolder } from \"../hooks/usePermanentlyDeleteFolder\";\nimport { useToggleStar } from \"../hooks/useToggleStar\";\nimport { useRenameFile } from \"../hooks/useRenameFile\";\nimport { useRenameFolder } from \"../hooks/useRenameFolder\";\nimport { type CreateShareInput, useCreateShare } from \"../hooks/useCreateShare\";\nimport {\n type CreateFolderShareInput,\n useCreateFolderShare,\n} from \"../hooks/useCreateFolderShare\";\nimport { useCopyFile } from \"../hooks/useCopyFile\";\nimport { useMoveFile } from \"../hooks/useMoveFile\";\nimport { useMoveFolder } from \"../hooks/useMoveFolder\";\nimport { useBulkDelete } from \"../hooks/useBatchOperations\";\nimport { type SearchFilters, useSearch } from \"../hooks/useSearch\";\nimport { useToast } from \"../hooks/useToast\";\nimport { FileBrowser } from \"../components/FileBrowser\";\nimport { TabBar, type TabView } from \"../components/TabBar\";\nimport { ShareDialog, type ShareDialogInput } from \"../components/ShareDialog\";\nimport { FilePreviewModal } from \"../components/FilePreviewModal\";\nimport { FileInfoPanel } from \"../components/FileInfoPanel\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { ToastContainer } from \"../components/Toast\";\nimport { SearchBar } from \"../components/SearchBar\";\nimport { MoveDialog } from \"../components/MoveDialog\";\nimport { CopyDialog } from \"../components/CopyDialog\";\nimport { ConfirmDialog } from \"../components/ConfirmDialog\";\nimport { UploadQueue } from \"../components/UploadQueue\";\nimport type { FileItem, FolderItem, UploadItem } from \"../types\";\nimport type { FilesEventName } from \"../utils/events\";\nimport { isQuotaExhaustedError } from \"../utils/quotaUtils\";\nimport {\n nativeImpact,\n nativeNotify,\n nativeOpenUrl,\n} from \"../../utils/nativeBridge\";\nimport { emitFilesEvent } from \"../utils/events\";\nimport { tWithFallback } from \"../utils/i18n\";\nimport { generateThumbnail } from \"../utils\";\n\ninterface ShareDialogResult {\n publicUrl: string;\n token: string;\n}\n\ninterface ConfirmDialogState {\n title: string;\n description: string;\n confirmLabel: string;\n variant?: \"danger\" | \"default\";\n onConfirm: () => Promise<void> | void;\n loading?: boolean;\n}\n\n/**\n * BrowserPage - Main file browser with toolbar and view modes\n */\nexport function BrowserPage() {\n const { t } = useI18n();\n const { folderId } = useParams<{ folderId: string }>();\n const navigate = useNavigate();\n const filesContext = useFilesContext();\n const { workspaceId } = filesContext;\n const {\n viewMode,\n setViewMode,\n breadcrumbs,\n selectedFiles,\n selectedFolders,\n clearSelection,\n } = useFilesStore();\n\n // Tab state\n const [activeTab, setActiveTab] = useState<TabView>(\"all\");\n\n const enabledTabs = useMemo<TabView[]>(() => {\n return [\"all\", \"recent\", \"starred\"];\n }, []);\n\n // If the active tab gets disabled at runtime (flag flipped, user opt-out),\n // fall back to \"all\" instead of leaving the user on a blank screen.\n useEffect(() => {\n if (!enabledTabs.includes(activeTab)) {\n setActiveTab(\"all\");\n }\n }, [enabledTabs, activeTab]);\n\n const pageSize = 100;\n\n // Search state\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [searchFilters, setSearchFilters] = useState<SearchFilters>();\n const isSearching = searchQuery.trim().length >= 2;\n\n // Info panel state\n const [infoPanel, setInfoPanel] = useState<{\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n } | null>(null);\n\n // Preview state\n const [previewFile, setPreviewFile] = useState<FileItem | null>(null);\n\n // Toast notifications\n const toast = useToast();\n\n // Fetch data based on active tab. Each view owns one composed page query so\n // files, folders, and folder context travel in a single GraphQL operation.\n const browsePageQuery = useBrowsePage({\n folderId: folderId || undefined,\n pageSize,\n skip: activeTab !== \"all\" || isSearching,\n });\n const recentFilesQuery = useRecentFiles({\n skip: activeTab !== \"recent\" || isSearching,\n });\n const starredItemsQuery = useStarredItems({\n skip: activeTab !== \"starred\" || isSearching,\n });\n const binItemsQuery = useBinItems({\n skip: activeTab !== \"bin\" || isSearching,\n });\n\n const searchResults = useSearch(searchQuery, isSearching, searchFilters);\n\n // Update breadcrumbs when folder path data changes\n useEffect(() => {\n if (\n folderId &&\n browsePageQuery.data?.folderPath &&\n browsePageQuery.data?.currentFolder\n ) {\n // Combine parent folders with current folder\n const parentFolders = browsePageQuery.data.folderPath.folders || [];\n const currentFolder = browsePageQuery.data.currentFolder;\n const breadcrumbPath = [\n ...parentFolders.map((f: { id: string; name: string }) => ({\n id: f.id,\n name: f.name,\n })),\n { id: currentFolder.id, name: currentFolder.name },\n ];\n useFilesStore.getState().setBreadcrumbs(breadcrumbPath);\n } else {\n useFilesStore.getState().setBreadcrumbs([]);\n }\n }, [folderId, browsePageQuery.data]);\n\n // Determine which data to display based on search state\n let files: FileItem[] = [];\n let folders: FolderItem[] = [];\n let loading = false;\n let error: Error | null = null;\n let preserveSortOrder = false; // For Recent/Bin tabs - skip re-sorting\n\n // If searching, use search results\n if (isSearching && searchResults.data) {\n files = searchResults.data.files || [];\n folders = searchResults.data.folders || [];\n loading = searchResults.isLoading;\n error = searchResults.error as Error | null;\n } else {\n // Show data based on active tab\n switch (activeTab) {\n case \"all\":\n files = (browsePageQuery.data?.filesList?.files || []) as FileItem[];\n folders = (browsePageQuery.data?.foldersList?.folders ||\n []) as FolderItem[];\n loading = browsePageQuery.loading;\n error = (browsePageQuery.error as Error) || null;\n preserveSortOrder = false;\n break;\n case \"recent\":\n files = recentFilesQuery.files || [];\n folders = recentFilesQuery.folders || [];\n loading = recentFilesQuery.isLoading;\n error = (recentFilesQuery.error as Error) || null;\n preserveSortOrder = true; // Recent tab already sorted by backend\n break;\n case \"starred\":\n files = starredItemsQuery.files;\n folders = starredItemsQuery.folders;\n loading = starredItemsQuery.isLoading;\n error = (starredItemsQuery.error as Error) || null;\n preserveSortOrder = true;\n break;\n case \"bin\":\n files = binItemsQuery.files;\n folders = binItemsQuery.folders;\n loading = binItemsQuery.isLoading;\n error = (binItemsQuery.error as Error) || null;\n preserveSortOrder = true; // Bin tab already sorted by backend\n break;\n }\n }\n\n const totalItemsInCurrentView =\n activeTab === \"all\"\n ? (browsePageQuery.data?.filesList?.total ?? files.length) +\n (browsePageQuery.data?.foldersList?.total ?? folders.length)\n : null;\n\n const totalSelected = selectedFiles.size + selectedFolders.size;\n const [showNewFolderDialog, setShowNewFolderDialog] = useState(false);\n const [showFolderQuotaExhausted, setShowFolderQuotaExhausted] =\n useState(false);\n const [showRenameDialog, setShowRenameDialog] = useState(false);\n const [showShareDialog, setShowShareDialog] = useState(false);\n const [showMoveDialog, setShowMoveDialog] = useState(false);\n const [showCopyDialog, setShowCopyDialog] = useState(false);\n const [shareTarget, setShareTarget] = useState<FileItem | FolderItem | null>(\n null,\n );\n const [moveTarget, setMoveTarget] = useState<{\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n } | null>(null);\n const [copyTarget, setCopyTarget] = useState<{\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n } | null>(null);\n const [renameTarget, setRenameTarget] = useState<{\n id: string;\n name: string;\n type: \"file\" | \"folder\";\n } | null>(null);\n const [newName, setNewName] = useState(\"\");\n const [newFolderName, setNewFolderName] = useState(\"\");\n const [uploading, setUploading] = useState(false);\n const [uploadQueue, setUploadQueue] = useState<UploadItem[]>([]);\n const [isUploadPanelOpen, setIsUploadPanelOpen] = useState(false);\n const [confirmDialog, setConfirmDialog] = useState<ConfirmDialogState | null>(\n null,\n );\n\n const emitEvent = (\n name: FilesEventName,\n payload: Record<string, unknown>,\n ) => {\n emitFilesEvent(filesContext, name, payload);\n };\n\n const runConfirmedAction = async () => {\n if (!confirmDialog || confirmDialog.loading) return;\n\n const action = confirmDialog.onConfirm;\n setConfirmDialog({ ...confirmDialog, loading: true });\n try {\n await action();\n setConfirmDialog(null);\n } catch (error) {\n emitEvent(\"files.api.failed\", {\n action: \"confirmDialog\",\n message:\n error instanceof Error ? error.message : \"Confirmed action failed\",\n });\n setConfirmDialog((current) =>\n current ? { ...current, loading: false } : current,\n );\n }\n };\n\n // Mutations\n const createFolderMutation = useCreateFolder();\n const uploadFileMutation = useUploadFile();\n const deleteFileMutation = useDeleteFile();\n const deleteFolderMutation = useDeleteFolder();\n const restoreFileMutation = useRestoreFile();\n const restoreFolderMutation = useRestoreFolder();\n const permanentlyDeleteFileMutation = usePermanentlyDeleteFile();\n const permanentlyDeleteFolderMutation = usePermanentlyDeleteFolder();\n const toggleStarMutation = useToggleStar();\n const renameFileMutation = useRenameFile();\n const renameFolderMutation = useRenameFolder();\n const createShareMutation = useCreateShare();\n const createFolderShareMutation = useCreateFolderShare();\n const copyFileMutation = useCopyFile();\n const moveFileMutation = useMoveFile();\n const moveFolderMutation = useMoveFolder();\n const bulkDeleteMutation = useBulkDelete();\n\n // Action handlers\n const handleUploadClick = () => {\n const input = document.createElement(\"input\");\n input.type = \"file\";\n input.multiple = true;\n input.onchange = async (e) => {\n const files = (e.target as HTMLInputElement).files;\n if (files && files.length > 0) {\n const newItems: UploadItem[] = await Promise.all(\n Array.from(files).map(async (file, index) => {\n const thumbnailUrl = await generateThumbnail(file);\n return {\n id: `${Date.now()}-${index}-${file.name}`,\n file,\n status: \"pending\" as const,\n progress: 0,\n folderId: folderId || undefined,\n thumbnailUrl: thumbnailUrl ?? undefined,\n };\n }),\n );\n setUploadQueue((prev) => [...prev, ...newItems]);\n setIsUploadPanelOpen(true);\n setUploading(true);\n\n for (const item of newItems) {\n await processUpload(item);\n }\n setUploading(false);\n }\n };\n input.click();\n };\n\n const processUpload = async (item: UploadItem) => {\n const updateItem = (updates: Partial<UploadItem>) => {\n setUploadQueue((prev) =>\n prev.map((i) => (i.id === item.id ? { ...i, ...updates } : i)),\n );\n };\n\n updateItem({ status: \"uploading\" });\n\n try {\n const uploadedFile = await uploadFileMutation.mutateAsync({\n file: item.file,\n folderId: item.folderId,\n onProgress: (progress) => {\n updateItem({ progress });\n },\n });\n updateItem({ status: \"completed\", progress: 100 });\n emitEvent(\"files.file.uploaded\", {\n fileId: uploadedFile.id,\n fileName: uploadedFile.name,\n folderId: item.folderId,\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error\n ? error.message\n : tWithFallback(t, \"files.upload.errors.failed\", \"Upload failed\");\n if (errorMessage === \"Upload paused\") {\n updateItem({ status: \"paused\" });\n } else if (errorMessage === \"QUOTA_EXHAUSTED\") {\n updateItem({\n status: \"failed\",\n error: tWithFallback(\n t,\n \"files.upload.errors.quotaExceeded\",\n \"Storage quota exceeded\",\n ),\n });\n toast.error(\n tWithFallback(\n t,\n \"files.upload.errors.quotaExceeded\",\n \"Storage quota exceeded. Please upgrade your plan or delete files.\",\n ),\n );\n } else {\n updateItem({ status: \"failed\", error: errorMessage });\n emitEvent(\"files.api.failed\", {\n action: \"uploadFile\",\n fileName: item.file.name,\n message: errorMessage,\n });\n }\n }\n };\n\n const handlePauseUpload = (id: string) => {\n uploadFileMutation.pause();\n setUploadQueue((prev) =>\n prev.map((i) => (i.id === id ? { ...i, status: \"paused\" as const } : i)),\n );\n };\n\n const handleResumeUpload = (id: string) => {\n const item = uploadQueue.find((i) => i.id === id);\n if (item) {\n processUpload(item);\n }\n };\n\n const handleRetryUpload = (id: string) => {\n const item = uploadQueue.find((i) => i.id === id);\n if (item) {\n setUploadQueue((prev) =>\n prev.map((i) =>\n i.id === id\n ? {\n ...i,\n status: \"pending\" as const,\n progress: 0,\n error: undefined,\n }\n : i,\n ),\n );\n processUpload(item);\n }\n };\n\n const handleCancelUpload = (id: string) => {\n setUploadQueue((prev) => {\n const remaining = prev.filter((i) => i.id !== id);\n if (remaining.length === 0) {\n setIsUploadPanelOpen(false);\n setUploading(false);\n }\n return remaining;\n });\n };\n\n // Folder upload handler - uploads entire folder with structure\n const handleFolderUploadClick = () => {\n if (!workspaceId) {\n toast.error(\n tWithFallback(\n t,\n \"files.workspace.errors.notSelected\",\n \"Workspace not selected\",\n ),\n );\n return;\n }\n\n const input = document.createElement(\"input\");\n input.type = \"file\";\n input.webkitdirectory = true;\n input.onchange = async (e) => {\n const files = (e.target as HTMLInputElement).files;\n if (files && files.length > 0) {\n const filesByFolder = new Map<string, File[]>();\n for (const file of Array.from(files)) {\n const relativePath = file.webkitRelativePath || file.name;\n const pathParts = relativePath.split(\"/\");\n const folderPath = pathParts.slice(0, -1).join(\"/\");\n\n if (!filesByFolder.has(folderPath)) {\n filesByFolder.set(folderPath, []);\n }\n filesByFolder.get(folderPath)!.push(file);\n }\n\n const folderIdMap = new Map<string, string>();\n const sortedPaths = Array.from(filesByFolder.keys()).sort();\n\n for (const folderPath of sortedPaths) {\n if (!folderPath) continue;\n\n const pathParts = folderPath.split(\"/\");\n let currentPath = \"\";\n let parentId = folderId || undefined;\n\n for (const part of pathParts) {\n currentPath = currentPath ? `${currentPath}/${part}` : part;\n\n if (!folderIdMap.has(currentPath)) {\n try {\n const { data: createdFolder } =\n await createFolderMutation.mutateAsync({\n name: part,\n parentFolderId: parentId,\n });\n if (createdFolder?.id) {\n folderIdMap.set(currentPath, createdFolder.id);\n parentId = createdFolder.id;\n }\n } catch {\n // Continue best-effort\n }\n } else {\n parentId = folderIdMap.get(currentPath);\n }\n }\n }\n\n const newItems: UploadItem[] = [];\n let index = 0;\n for (const [folderPath, folderFiles] of filesByFolder) {\n const targetFolderId = folderPath\n ? folderIdMap.get(folderPath)\n : folderId || undefined;\n\n for (const file of folderFiles) {\n const thumbnailUrl = await generateThumbnail(file);\n newItems.push({\n id: `${Date.now()}-${index++}-${file.name}`,\n file,\n status: \"pending\",\n progress: 0,\n folderId: targetFolderId,\n thumbnailUrl: thumbnailUrl ?? undefined,\n });\n }\n }\n\n setUploadQueue((prev) => [...prev, ...newItems]);\n setIsUploadPanelOpen(true);\n setUploading(true);\n\n for (const item of newItems) {\n await processUpload(item);\n }\n setUploading(false);\n\n toast.success(\n tWithFallback(\n t,\n \"files.upload.folder.success\",\n \"Uploaded {{count}} file{{plural}} from folder\",\n { count: newItems.length, plural: newItems.length > 1 ? \"s\" : \"\" },\n ),\n );\n }\n };\n input.click();\n };\n\n const handleNewFolderClick = () => {\n setShowNewFolderDialog(true);\n };\n\n const handleCreateFolder = async () => {\n if (newFolderName.trim() && workspaceId) {\n const { data: createdFolder, error } =\n await createFolderMutation.mutateAsync({\n name: newFolderName,\n parentFolderId: folderId,\n });\n\n if (error) {\n if (isQuotaExhaustedError(error)) {\n setShowNewFolderDialog(false);\n setNewFolderName(\"\");\n setShowFolderQuotaExhausted(true);\n } else {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.folder.errors.createFailed\",\n \"Folder creation failed\",\n ),\n );\n emitEvent(\"files.api.failed\", {\n action: \"createFolder\",\n message:\n error instanceof Error ? error.message : \"Folder creation failed\",\n });\n }\n return;\n }\n\n if (createdFolder) {\n setNewFolderName(\"\");\n setShowNewFolderDialog(false);\n emitEvent(\"files.folder.created\", {\n folderName: newFolderName,\n parentFolderId: folderId,\n });\n }\n }\n };\n\n // File action handlers\n const handleFilePreview = (file: FileItem) => {\n setPreviewFile(file);\n };\n\n const handleFileShare = (file: FileItem) => {\n setShareTarget(file);\n setShowShareDialog(true);\n };\n\n const handleFolderShare = (folder: FolderItem) => {\n setShareTarget(folder);\n setShowShareDialog(true);\n };\n\n const handleCreateShare = async (\n input: ShareDialogInput,\n ): Promise<ShareDialogResult> => {\n if (!input.fileId && !input.folderId) {\n throw new Error(\n tWithFallback(\n t,\n \"files.share.errors.targetRequired\",\n \"Share requires a file id or folder id\",\n ),\n );\n }\n\n const shareType = input.invitedEmail ? \"EMAIL_INVITE\" : \"PUBLIC_LINK\";\n let token = \"\";\n\n if (input.fileId) {\n // File share\n const shareInput: CreateShareInput = {\n fileId: input.fileId,\n expiresAt: input.expiresAt,\n maxDownloads: input.maxDownloads,\n password: input.password,\n invitedEmail: input.invitedEmail,\n shareType,\n accessLevel: \"DOWNLOAD\" as const,\n };\n const result = await createShareMutation.mutateAsync(shareInput);\n token = result?.token ?? \"\";\n emitEvent(\"files.share.created\", {\n entityType: \"file\",\n fileId: input.fileId,\n shareType,\n });\n } else if (input.folderId) {\n // Folder share\n const shareInput: CreateFolderShareInput = {\n folderId: input.folderId,\n expiresAt: input.expiresAt,\n maxDownloads: input.maxDownloads,\n password: input.password,\n invitedEmail: input.invitedEmail,\n shareType,\n accessLevel: \"DOWNLOAD\" as const,\n };\n const result = await createFolderShareMutation.mutateAsync(shareInput);\n token = result?.createFolderShare?.token ?? \"\";\n emitEvent(\"files.share.created\", {\n entityType: \"folder\",\n folderId: input.folderId,\n shareType,\n });\n }\n\n return {\n publicUrl: token ? `${window.location.origin}/files/share/${token}` : \"\",\n token,\n };\n };\n\n const handleFileDelete = async (file: FileItem) => {\n nativeImpact(\"medium\");\n setConfirmDialog({\n title: tWithFallback(t, \"files.confirm.deleteFile.title\", \"Delete file\"),\n description: tWithFallback(\n t,\n \"files.confirm.deleteFile.description\",\n 'Move \"{{name}}\" to the bin?',\n { name: file.name },\n ),\n confirmLabel: tWithFallback(t, \"files.common.actions.delete\", \"Delete\"),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n await deleteFileMutation.mutateAsync({ id: file.id });\n nativeNotify(\"success\");\n toast.success(\n tWithFallback(\n t,\n \"files.file.delete.success\",\n '\"{{name}}\" moved to bin',\n { name: file.name },\n ),\n );\n emitEvent(\"files.file.deleted\", {\n fileId: file.id,\n fileName: file.name,\n permanent: false,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.file.errors.deleteFailed\",\n 'Failed to delete \"{{name}}\"',\n { name: file.name },\n ),\n );\n nativeNotify(\"error\");\n emitEvent(\"files.api.failed\", {\n action: \"deleteFile\",\n fileId: file.id,\n message:\n error instanceof Error ? error.message : \"Failed to delete file\",\n });\n }\n },\n });\n };\n\n const handleFileRestore = async (file: FileItem) => {\n try {\n await restoreFileMutation.mutateAsync({ id: file.id });\n toast.success(\n tWithFallback(t, \"files.file.restore.success\", '\"{{name}}\" restored', {\n name: file.name,\n }),\n );\n emitEvent(\"files.file.restored\", {\n fileId: file.id,\n fileName: file.name,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.file.errors.restoreFailed\",\n \"Failed to restore file\",\n ),\n );\n }\n };\n\n const handleFilePermanentDelete = async (file: FileItem) => {\n nativeImpact(\"heavy\");\n setConfirmDialog({\n title: tWithFallback(\n t,\n \"files.confirm.permanentDeleteFile.title\",\n \"Permanently delete file\",\n ),\n description: tWithFallback(\n t,\n \"files.confirm.permanentDeleteFile.description\",\n 'Permanently delete \"{{name}}\"? This cannot be undone.',\n { name: file.name },\n ),\n confirmLabel: tWithFallback(\n t,\n \"files.common.actions.deletePermanently\",\n \"Delete permanently\",\n ),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n await permanentlyDeleteFileMutation.mutateAsync({ id: file.id });\n toast.success(\n tWithFallback(\n t,\n \"files.file.permanentDelete.success\",\n '\"{{name}}\" deleted permanently',\n { name: file.name },\n ),\n );\n emitEvent(\"files.file.deleted\", {\n fileId: file.id,\n fileName: file.name,\n permanent: true,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.file.errors.permanentDeleteFailed\",\n \"Failed to permanently delete file\",\n ),\n );\n }\n },\n });\n };\n\n const handleFileFavorite = async (file: FileItem) => {\n try {\n await toggleStarMutation.mutateAsync({ id: file.id, type: \"file\" });\n emitEvent(\"files.file.starred\", {\n fileId: file.id,\n fileName: file.name,\n starred: !file.starred,\n });\n } catch {\n toast.error(\n tWithFallback(\n t,\n \"files.file.errors.starFailed\",\n \"Failed to update starred state\",\n ),\n );\n emitEvent(\"files.api.failed\", {\n action: \"toggleFileStar\",\n fileId: file.id,\n });\n }\n };\n\n const handleFileRename = (file: FileItem) => {\n setRenameTarget({ id: file.id, name: file.name, type: \"file\" });\n setNewName(file.name);\n setShowRenameDialog(true);\n };\n\n const handleFileDownload = async (file: FileItem) => {\n try {\n const downloadUrl = file.downloadUrl || file.url;\n\n if (!downloadUrl) {\n throw new Error(\n tWithFallback(\n t,\n \"files.file.errors.downloadUrlUnavailable\",\n \"Download URL is unavailable\",\n ),\n );\n }\n\n const a = document.createElement(\"a\");\n a.style.display = \"none\";\n a.href = downloadUrl;\n a.download = file.name;\n a.rel = \"noopener noreferrer\";\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n\n toast.success(\n tWithFallback(t, \"files.file.download.success\", \"Downloaded {{name}}\", {\n name: file.name,\n }),\n );\n emitEvent(\"files.file.downloaded\", {\n fileId: file.id,\n fileName: file.name,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.file.errors.downloadFailed\",\n \"Failed to download file\",\n ),\n );\n }\n };\n\n const handleFileCopy = (file: FileItem) => {\n setCopyTarget({ item: file, type: \"file\" });\n setShowCopyDialog(true);\n };\n\n const handleFileMove = (file: FileItem) => {\n setMoveTarget({ item: file, type: \"file\" });\n setShowMoveDialog(true);\n };\n\n const handleFileInfoClick = (file: FileItem) => {\n setInfoPanel({ item: file, type: \"file\" });\n };\n\n // Folder action handlers\n const handleFolderOpen = (folder: FolderItem) => {\n // Navigate to folder by updating URL\n navigate(`/files/browse/${folder.id}`);\n };\n\n const handleFolderDelete = async (folder: FolderItem) => {\n nativeImpact(\"medium\");\n setConfirmDialog({\n title: tWithFallback(\n t,\n \"files.confirm.deleteFolder.title\",\n \"Delete folder\",\n ),\n description: tWithFallback(\n t,\n \"files.confirm.deleteFolder.description\",\n 'Move folder \"{{name}}\" and all its contents to the bin?',\n { name: folder.name },\n ),\n confirmLabel: tWithFallback(t, \"files.common.actions.delete\", \"Delete\"),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n await deleteFolderMutation.mutateAsync({\n id: folder.id,\n recursive: true,\n });\n toast.success(\n tWithFallback(\n t,\n \"files.folder.delete.success\",\n '\"{{name}}\" moved to bin',\n { name: folder.name },\n ),\n );\n emitEvent(\"files.folder.deleted\", {\n folderId: folder.id,\n folderName: folder.name,\n permanent: false,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.folder.errors.deleteFailed\",\n \"Failed to delete folder\",\n ),\n );\n }\n },\n });\n };\n\n const handleFolderRestore = async (folder: FolderItem) => {\n try {\n await restoreFolderMutation.mutateAsync({ id: folder.id });\n toast.success(\n tWithFallback(\n t,\n \"files.folder.restore.success\",\n '\"{{name}}\" restored',\n { name: folder.name },\n ),\n );\n emitEvent(\"files.folder.restored\", {\n folderId: folder.id,\n folderName: folder.name,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.folder.errors.restoreFailed\",\n \"Failed to restore folder\",\n ),\n );\n }\n };\n\n const handleFolderPermanentDelete = async (folder: FolderItem) => {\n setConfirmDialog({\n title: tWithFallback(\n t,\n \"files.confirm.permanentDeleteFolder.title\",\n \"Permanently delete folder\",\n ),\n description: tWithFallback(\n t,\n \"files.confirm.permanentDeleteFolder.description\",\n 'Permanently delete folder \"{{name}}\" and its contents? This cannot be undone.',\n { name: folder.name },\n ),\n confirmLabel: tWithFallback(\n t,\n \"files.common.actions.deletePermanently\",\n \"Delete permanently\",\n ),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n await permanentlyDeleteFolderMutation.mutateAsync({ id: folder.id });\n toast.success(\n tWithFallback(\n t,\n \"files.folder.permanentDelete.success\",\n '\"{{name}}\" deleted permanently',\n { name: folder.name },\n ),\n );\n emitEvent(\"files.folder.deleted\", {\n folderId: folder.id,\n folderName: folder.name,\n permanent: true,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.folder.errors.permanentDeleteFailed\",\n \"Failed to permanently delete folder\",\n ),\n );\n }\n },\n });\n };\n\n const handleFolderRename = (folder: FolderItem) => {\n setRenameTarget({ id: folder.id, name: folder.name, type: \"folder\" });\n setNewName(folder.name);\n setShowRenameDialog(true);\n };\n\n const handleFolderMove = (folder: FolderItem) => {\n setMoveTarget({ item: folder, type: \"folder\" });\n setShowMoveDialog(true);\n };\n\n const handleFolderFavorite = async (folder: FolderItem) => {\n try {\n await toggleStarMutation.mutateAsync({ id: folder.id, type: \"folder\" });\n emitEvent(\"files.folder.starred\", {\n folderId: folder.id,\n folderName: folder.name,\n starred: !folder.starred,\n });\n } catch {\n toast.error(\n tWithFallback(\n t,\n \"files.folder.errors.starFailed\",\n \"Failed to update starred state\",\n ),\n );\n emitEvent(\"files.api.failed\", {\n action: \"toggleFolderStar\",\n folderId: folder.id,\n });\n }\n };\n\n const handleFolderInfoClick = (folder: FolderItem) => {\n setInfoPanel({ item: folder, type: \"folder\" });\n };\n\n // Move and Copy handlers\n const handleMoveSubmit = async (destinationFolderId: string | null) => {\n if (!moveTarget) return;\n\n try {\n if (moveTarget.type === \"file\") {\n await moveFileMutation.mutateAsync({\n fileId: moveTarget.item.id,\n targetFolderId: destinationFolderId || null,\n });\n toast.success(\n tWithFallback(t, \"files.file.move.success\", '\"{{name}}\" moved', {\n name: moveTarget.item.name,\n }),\n );\n emitEvent(\"files.file.moved\", {\n fileId: moveTarget.item.id,\n fileName: moveTarget.item.name,\n destinationFolderId,\n });\n } else {\n await moveFolderMutation.mutateAsync({\n folderId: moveTarget.item.id,\n targetParentFolderId: destinationFolderId,\n });\n toast.success(\n tWithFallback(t, \"files.folder.move.success\", '\"{{name}}\" moved', {\n name: moveTarget.item.name,\n }),\n );\n emitEvent(\"files.folder.moved\", {\n folderId: moveTarget.item.id,\n folderName: moveTarget.item.name,\n destinationFolderId,\n });\n }\n setShowMoveDialog(false);\n setMoveTarget(null);\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.item.errors.moveFailed\",\n 'Failed to move \"{{name}}\"',\n {\n name: moveTarget.item.name,\n },\n ),\n );\n emitEvent(\"files.api.failed\", {\n action: moveTarget.type === \"file\" ? \"moveFile\" : \"moveFolder\",\n itemId: moveTarget.item.id,\n itemType: moveTarget.type,\n message: error instanceof Error ? error.message : undefined,\n });\n }\n };\n\n const handleCopySubmit = async (\n destinationFolderId: string | null,\n newName?: string,\n ) => {\n if (!copyTarget) return;\n\n try {\n if (copyTarget.type !== \"file\") {\n throw new Error(\n tWithFallback(\n t,\n \"files.folder.errors.copyUnsupported\",\n \"Folder copy is not supported\",\n ),\n );\n }\n\n await copyFileMutation.mutateAsync({\n id: copyTarget.item.id,\n newName: newName || `Copy of ${copyTarget.item.name}`,\n targetFolderId: destinationFolderId || undefined,\n });\n toast.success(\n tWithFallback(t, \"files.file.copy.success\", '\"{{name}}\" copied', {\n name: copyTarget.item.name,\n }),\n );\n emitEvent(\"files.file.copied\", {\n fileId: copyTarget.item.id,\n fileName: copyTarget.item.name,\n destinationFolderId,\n });\n\n setShowCopyDialog(false);\n setCopyTarget(null);\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.file.errors.copyFailed\",\n 'Failed to copy \"{{name}}\"',\n {\n name: copyTarget.item.name,\n },\n ),\n );\n emitEvent(\"files.api.failed\", {\n action: \"copyFile\",\n fileId: copyTarget.item.id,\n message: error instanceof Error ? error.message : undefined,\n });\n }\n };\n\n const handleRenameSubmit = async () => {\n if (!renameTarget || !newName.trim()) return;\n\n try {\n const previousName = renameTarget.name;\n const nextName = newName.trim();\n\n if (renameTarget.type === \"file\") {\n await renameFileMutation.mutateAsync({\n fileId: renameTarget.id,\n newName: nextName,\n });\n toast.success(\n tWithFallback(t, \"files.file.rename.success\", 'Renamed \"{{name}}\"', {\n name: nextName,\n }),\n );\n emitEvent(\"files.file.renamed\", {\n fileId: renameTarget.id,\n previousName,\n name: nextName,\n });\n } else {\n await renameFolderMutation.mutateAsync({\n folderId: renameTarget.id,\n newName: nextName,\n });\n toast.success(\n tWithFallback(\n t,\n \"files.folder.rename.success\",\n 'Renamed \"{{name}}\"',\n {\n name: nextName,\n },\n ),\n );\n emitEvent(\"files.folder.renamed\", {\n folderId: renameTarget.id,\n previousName,\n name: nextName,\n });\n }\n setShowRenameDialog(false);\n setRenameTarget(null);\n setNewName(\"\");\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.item.errors.renameFailed\",\n \"Failed to rename {{type}}\",\n {\n type: renameTarget.type,\n },\n ),\n );\n emitEvent(\"files.api.failed\", {\n action: renameTarget.type === \"file\" ? \"renameFile\" : \"renameFolder\",\n itemId: renameTarget.id,\n itemType: renameTarget.type,\n message: error instanceof Error ? error.message : undefined,\n });\n }\n };\n\n const handleSearch = (query: string, filters?: SearchFilters) => {\n setSearchQuery(query);\n setSearchFilters(filters);\n };\n\n useKeyboardNavigation({\n files,\n folders,\n onFilePreview: handleFilePreview,\n onFileDelete: handleFileDelete,\n onFolderOpen: handleFolderOpen,\n onFolderDelete: handleFolderDelete,\n activeTab,\n });\n\n // Guard: if the host shell hasn't pushed workspace context yet, render a\n // clear loading state rather than firing queries with an undefined workspace\n // (which used to manifest as a silent blank screen).\n // NOTE: We explicitly check for undefined (not yet provided) vs empty string\n // (explicitly no workspace selected) to show appropriate messaging.\n if (workspaceId === undefined) {\n return (\n <div className=\"flex flex-col items-center justify-center min-h-[60vh] gap-3 text-center px-6\">\n <Loader2 className=\"size-8 animate-spin text-text-tertiary\" />\n <p className=\"text-sm text-text-secondary max-w-md\">\n {tWithFallback(\n t,\n \"files.browser.workspace.waiting\",\n \"Waiting for workspace context. If this persists, the app shell may not have provided a workspaceId to the Files module. Try reloading the page or switching workspaces.\",\n )}\n </p>\n </div>\n );\n }\n\n // Empty string means host shell provided context but no workspace is selected\n if (workspaceId === \"\") {\n return (\n <div className=\"flex flex-col items-center justify-center min-h-[60vh] gap-3 text-center px-6\">\n <FolderX className=\"size-8 text-text-tertiary\" />\n <p className=\"text-sm text-text-secondary max-w-md\">\n {tWithFallback(\n t,\n \"files.browser.workspace.notSelected\",\n \"No workspace selected. Please select a workspace to view files.\",\n )}\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"min-h-screen bg-bg-surface\">\n {/* Google Drive-style Header with Breadcrumb Navigation */}\n <div className=\"bg-bg-surface border-b border-border-default px-4 py-3 sm:px-6 sm:py-4\">\n <div className=\"flex items-center gap-2 sm:gap-4\">\n <div className=\"flex items-center gap-1 sm:gap-2 text-sm overflow-x-auto\">\n <button\n type=\"button\"\n onClick={() => navigate(\"/files/browse\")}\n className=\"flex items-center gap-1 text-text-primary hover:bg-action-ghost-bg-hover px-2 py-1 rounded transition-colors duration-200 whitespace-nowrap\"\n title={tWithFallback(\n t,\n \"files.browser.actions.goToRoot\",\n \"Go to root\",\n )}\n >\n <Home className=\"size-4\" />\n <span className=\"hidden sm:inline\">\n {tWithFallback(t, \"files.browser.rootLabel\", \"My Drive\")}\n </span>\n </button>\n {breadcrumbs.map((crumb, index) => (\n <div key={crumb.id} className=\"flex items-center gap-1 sm:gap-2\">\n <span className=\"text-text-tertiary\">/</span>\n <button\n type=\"button\"\n onClick={() => navigate(`/files/browse/${crumb.id}`)}\n className={`hover:bg-action-ghost-bg-hover px-2 py-1 rounded transition-colors duration-200 whitespace-nowrap ${\n index === breadcrumbs.length - 1\n ? \"text-text-primary font-medium\"\n : \"text-text-secondary\"\n }`}\n title={`Go to ${crumb.name}`}\n >\n {crumb.name}\n </button>\n </div>\n ))}\n </div>\n </div>\n </div>\n\n {/* Navigation Tabs */}\n <TabBar\n activeTab={activeTab}\n onTabChange={setActiveTab}\n tabs={enabledTabs}\n />\n\n {/* Google Drive-style Toolbar */}\n <div className=\"bg-bg-surface border-b border-border-default px-4 py-2 sm:px-6 sm:py-3\">\n <div className=\"flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 sm:gap-inline-gap\">\n {/* Left side - Search */}\n <div className=\"w-full sm:flex-1 min-w-0 order-2 sm:order-1\">\n <div className=\"relative w-full max-w-2xl\">\n <SearchBar\n onSearch={handleSearch}\n placeholder={tWithFallback(\n t,\n \"files.search.input.placeholder\",\n \"Search files and folders...\",\n )}\n initialQuery={searchQuery}\n showFilters={true}\n />\n </div>\n </div>\n\n {/* Right side - Actions */}\n <div className=\"flex items-center gap-2 order-1 sm:order-2 w-full sm:w-auto justify-between sm:justify-end\">\n {/* Select All button */}\n {!isSearching && (files.length > 0 || folders.length > 0) && (\n <button\n type=\"button\"\n onClick={() => {\n const allFileIds = files.map((f) => f.id);\n const allFolderIds = folders.map((f) => f.id);\n useFilesStore.getState().selectAllFiles(allFileIds);\n allFolderIds.forEach((id) =>\n useFilesStore.getState().selectFolder(id),\n );\n }}\n className=\"flex items-center gap-2 px-3 py-2 text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-lg hover:bg-action-ghost-bg-hover hover:border-border-default transition-all duration-200\"\n >\n {tWithFallback(\n t,\n \"files.browser.actions.selectAll\",\n \"Select All\",\n )}\n </button>\n )}\n\n {/* Only show New Folder and Upload buttons in \"All Files\" tab */}\n {!isSearching && (\n <>\n <button\n type=\"button\"\n onClick={handleNewFolderClick}\n className=\"flex items-center gap-1 sm:gap-2 px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-lg hover:bg-action-ghost-bg-hover hover:border-border-default transition-all duration-200 shadow-sm\"\n >\n <FolderPlus className=\"size-4\" />\n <span className=\"hidden sm:inline\">\n {tWithFallback(\n t,\n \"files.browser.actions.newFolder\",\n \"New Folder\",\n )}\n </span>\n </button>\n\n <button\n type=\"button\"\n onClick={handleUploadClick}\n disabled={uploading}\n className=\"flex items-center gap-1 sm:gap-2 px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-lg hover:bg-action-ghost-bg-hover hover:border-border-default transition-all duration-200 shadow-sm disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {uploading ? (\n <>\n <Loader2 className=\"size-4 animate-spin\" />\n <span className=\"hidden sm:inline\">\n {tWithFallback(\n t,\n \"files.browser.upload.uploading\",\n \"Uploading...\",\n )}\n </span>\n </>\n ) : (\n <>\n <Upload className=\"size-4\" />\n <span className=\"hidden sm:inline\">\n {tWithFallback(\n t,\n \"files.browser.actions.uploadFiles\",\n \"Upload Files\",\n )}\n </span>\n </>\n )}\n </button>\n\n <button\n type=\"button\"\n onClick={handleFolderUploadClick}\n disabled={uploading}\n className=\"hidden sm:flex items-center gap-2 px-4 py-2.5 text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-lg hover:bg-action-ghost-bg-hover hover:border-border-default transition-all duration-200 shadow-sm disabled:opacity-50 disabled:cursor-not-allowed\"\n title={tWithFallback(\n t,\n \"files.browser.actions.uploadFolderTitle\",\n \"Upload entire folder with structure\",\n )}\n >\n <FolderUp className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.browser.actions.uploadFolder\",\n \"Upload Folder\",\n )}\n </button>\n\n {/* Export button removed per user request */}\n </>\n )}\n\n {/* View mode toggle */}\n <div className=\"flex items-center border border-border-default rounded-lg overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setViewMode(\"grid\")}\n className={`p-2 transition-colors duration-200 ${\n viewMode === \"grid\"\n ? \"bg-bg-accent text-text-link\"\n : \"text-text-secondary hover:bg-action-ghost-bg-hover\"\n }`}\n aria-label={tWithFallback(\n t,\n \"files.browser.view.grid\",\n \"Grid view\",\n )}\n >\n <Grid3x3 className=\"size-5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setViewMode(\"list\")}\n className={`p-2 transition-colors duration-200 ${\n viewMode === \"list\"\n ? \"bg-bg-accent text-text-link\"\n : \"text-text-secondary hover:bg-action-ghost-bg-hover\"\n }`}\n aria-label={tWithFallback(\n t,\n \"files.browser.view.list\",\n \"List view\",\n )}\n >\n <List className=\"size-5\" />\n </button>\n </div>\n </div>\n </div>\n\n {/* Search results indicator */}\n {isSearching && (\n <div className=\"mt-3 flex items-center justify-between p-3 bg-status-success-bg-subtle rounded-lg border border-status-success-border transition-all duration-200\">\n <span className=\"text-sm font-medium text-status-success-text\">\n {tWithFallback(\n t,\n \"files.browser.search.showingResults\",\n 'Showing search results for \"{{query}}\"',\n { query: searchQuery },\n )}\n {searchResults.data &&\n ` (${(searchResults.data.files?.length || 0) + (searchResults.data.folders?.length || 0)} items)`}\n </span>\n <button\n type=\"button\"\n onClick={() => setSearchQuery(\"\")}\n className=\"flex items-center gap-2 text-status-success-text hover:text-status-success-text/80 text-sm font-medium transition-colors duration-200\"\n >\n <X className=\"size-4\" />\n {tWithFallback(t, \"files.browser.search.clear\", \"Clear search\")}\n </button>\n </div>\n )}\n\n {/* Selection info with bulk actions */}\n {totalSelected > 0 && (\n <div className=\"mt-3 flex items-center justify-between p-3 bg-bg-accent rounded-lg border border-action-primary-border transition-all duration-200\">\n <div className=\"flex items-center gap-4\">\n <span className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(\n t,\n \"files.browser.selection.selectedCount\",\n \"{{count}} item{{suffix}} selected\",\n {\n count: totalSelected,\n suffix: totalSelected > 1 ? \"s\" : \"\",\n },\n )}\n </span>\n\n {/* Bulk action buttons */}\n <div className=\"flex items-center gap-2\">\n {activeTab === \"bin\" ? (\n <>\n <button\n type=\"button\"\n onClick={async () => {\n try {\n await Promise.all([\n ...Array.from(selectedFiles).map((fileId) =>\n restoreFileMutation.mutateAsync({ id: fileId }),\n ),\n ...Array.from(selectedFolders).map((folderId) =>\n restoreFolderMutation.mutateAsync({\n id: folderId,\n }),\n ),\n ]);\n\n clearSelection();\n toast.success(\n `${totalSelected} item${totalSelected > 1 ? \"s\" : \"\"} restored`,\n );\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : \"Failed to restore some items\",\n );\n }\n }}\n className=\"flex items-center gap-1.5 rounded-lg border border-status-success-border bg-bg-surface px-3 py-1.5 text-sm font-medium text-status-success-text transition-colors duration-200 hover:bg-status-success-bg-subtle\"\n >\n {tWithFallback(\n t,\n \"files.browser.selection.actions.restore\",\n \"Restore\",\n )}\n </button>\n\n <button\n type=\"button\"\n onClick={async () => {\n setConfirmDialog({\n title: tWithFallback(\n t,\n \"files.confirm.bulkPermanentDelete.title\",\n \"Permanently delete selected items\",\n ),\n description: tWithFallback(\n t,\n \"files.confirm.bulkPermanentDelete.description\",\n \"Permanently delete {{count}} selected item{{plural}}? This cannot be undone.\",\n {\n count: totalSelected,\n plural: totalSelected > 1 ? \"s\" : \"\",\n },\n ),\n confirmLabel: tWithFallback(\n t,\n \"files.common.actions.deletePermanently\",\n \"Delete permanently\",\n ),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n await Promise.all([\n ...Array.from(selectedFiles).map((fileId) =>\n permanentlyDeleteFileMutation.mutateAsync({\n id: fileId,\n }),\n ),\n ...Array.from(selectedFolders).map((folderId) =>\n permanentlyDeleteFolderMutation.mutateAsync({\n id: folderId,\n }),\n ),\n ]);\n\n clearSelection();\n toast.success(\n tWithFallback(\n t,\n \"files.bulk.permanentDelete.success\",\n \"{{count}} item{{plural}} deleted permanently\",\n {\n count: totalSelected,\n plural: totalSelected > 1 ? \"s\" : \"\",\n },\n ),\n );\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.bulk.errors.permanentDeleteFailed\",\n \"Failed to permanently delete some items\",\n ),\n );\n }\n },\n });\n }}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-status-error-text bg-bg-surface border border-status-error-border rounded-lg hover:bg-status-error-bg-subtle transition-colors duration-200\"\n >\n <Trash2 className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.browser.selection.actions.deletePermanently\",\n \"Delete permanently\",\n )}\n </button>\n </>\n ) : (\n <button\n type=\"button\"\n onClick={async () => {\n setConfirmDialog({\n title: tWithFallback(\n t,\n \"files.confirm.bulkDelete.title\",\n \"Delete selected items\",\n ),\n description: tWithFallback(\n t,\n \"files.confirm.bulkDelete.description\",\n \"Move {{count}} selected item{{plural}} to the bin?\",\n {\n count: totalSelected,\n plural: totalSelected > 1 ? \"s\" : \"\",\n },\n ),\n confirmLabel: tWithFallback(\n t,\n \"files.common.actions.delete\",\n \"Delete\",\n ),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n const fileIds = Array.from(selectedFiles);\n const folderIds = Array.from(selectedFolders);\n\n if (fileIds.length > 0) {\n await bulkDeleteMutation.mutateAsync(fileIds);\n }\n\n await Promise.all(\n folderIds.map((folderId) =>\n deleteFolderMutation.mutateAsync({\n id: folderId,\n recursive: true,\n }),\n ),\n );\n\n clearSelection();\n toast.success(\n tWithFallback(\n t,\n \"files.bulk.delete.success\",\n \"{{count}} item{{plural}} moved to bin\",\n {\n count: totalSelected,\n plural: totalSelected > 1 ? \"s\" : \"\",\n },\n ),\n );\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.bulk.errors.deleteFailed\",\n \"Failed to delete some items\",\n ),\n );\n }\n },\n });\n }}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-status-error-text bg-bg-surface border border-status-error-border rounded-lg hover:bg-status-error-bg-subtle transition-colors duration-200\"\n >\n <Trash2 className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.browser.selection.actions.delete\",\n \"Delete\",\n )}\n </button>\n )}\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={clearSelection}\n className=\"flex items-center gap-2 text-text-link hover:text-action-primary-bg-hover text-sm font-medium transition-colors duration-200\"\n >\n <X className=\"size-4\" />\n {tWithFallback(t, \"files.common.actions.clear\", \"Clear\")}\n </button>\n </div>\n )}\n </div>\n\n {/* File Browser */}\n <div className=\"px-2 sm:px-4 md:px-6 py-3 sm:py-4\">\n <FileBrowser\n files={files}\n folders={folders}\n loading={loading}\n error={error}\n preserveSortOrder={preserveSortOrder}\n onFilePreview={handleFilePreview}\n onFileShare={activeTab === \"bin\" ? undefined : handleFileShare}\n onFileDelete={\n activeTab === \"bin\" ? handleFilePermanentDelete : handleFileDelete\n }\n onFileRestore={activeTab === \"bin\" ? handleFileRestore : undefined}\n onFileFavorite={activeTab === \"bin\" ? undefined : handleFileFavorite}\n onFileRename={activeTab === \"bin\" ? undefined : handleFileRename}\n onFileDownload={handleFileDownload}\n onFileCopy={activeTab === \"bin\" ? undefined : handleFileCopy}\n onFileMove={activeTab === \"bin\" ? undefined : handleFileMove}\n onFileInfo={handleFileInfoClick}\n onFolderOpen={handleFolderOpen}\n onFolderShare={activeTab === \"bin\" ? undefined : handleFolderShare}\n onFolderDelete={\n activeTab === \"bin\"\n ? handleFolderPermanentDelete\n : handleFolderDelete\n }\n onFolderRestore={\n activeTab === \"bin\" ? handleFolderRestore : undefined\n }\n onFolderRename={activeTab === \"bin\" ? undefined : handleFolderRename}\n onFolderFavorite={\n activeTab === \"bin\" ? undefined : handleFolderFavorite\n }\n onFolderMove={activeTab === \"bin\" ? undefined : handleFolderMove}\n onFolderInfo={handleFolderInfoClick}\n />\n\n {/* Results Summary */}\n {!loading && (files.length > 0 || folders.length > 0) && (\n <div className=\"mt-4 px-2 text-sm text-text-secondary\">\n {tWithFallback(\n t,\n \"files.browser.results.showingItems\",\n \"Showing {{count}} items\",\n { count: files.length + folders.length },\n )}\n {!isSearching &&\n activeTab === \"all\" &&\n totalItemsInCurrentView !== null &&\n ` ${tWithFallback(\n t,\n \"files.browser.results.ofItems\",\n \"of {{count}} items\",\n { count: totalItemsInCurrentView },\n )}`}\n </div>\n )}\n </div>\n\n {/* New Folder Dialog */}\n {showNewFolderDialog && (\n <div\n className=\"fixed inset-0 backdrop-blur-sm flex items-center justify-center z-[100] animate-in fade-in duration-200\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"files-new-folder-title\"\n >\n <div className=\"bg-bg-surface rounded-lg shadow-xl p-6 w-full max-w-xs mx-4 animate-in zoom-in-95 duration-200\">\n <h2\n id=\"files-new-folder-title\"\n className=\"text-base font-semibold text-text-primary mb-4\"\n >\n {tWithFallback(\n t,\n \"files.browser.newFolderDialog.title\",\n \"New folder\",\n )}\n </h2>\n <input\n type=\"text\"\n value={newFolderName}\n onChange={(e) => setNewFolderName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleCreateFolder();\n if (e.key === \"Escape\") {\n setShowNewFolderDialog(false);\n setNewFolderName(\"\");\n }\n }}\n aria-label={tWithFallback(\n t,\n \"files.browser.newFolderDialog.title\",\n \"New folder\",\n )}\n placeholder={tWithFallback(\n t,\n \"files.browser.newFolderDialog.placeholder\",\n \"Folder name\",\n )}\n className=\"w-full px-4 py-3 border-2 border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200\"\n />\n <div className=\"flex justify-end gap-2 mt-6\">\n <button\n type=\"button\"\n onClick={() => {\n setShowNewFolderDialog(false);\n setNewFolderName(\"\");\n }}\n className=\"px-6 py-2.5 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n >\n {tWithFallback(t, \"files.common.actions.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={handleCreateFolder}\n disabled={\n !newFolderName.trim() || createFolderMutation.isPending\n }\n className=\"px-6 py-2.5 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover disabled:bg-bg-muted disabled:text-text-tertiary disabled:cursor-not-allowed transition-colors duration-200 flex items-center gap-2\"\n >\n {createFolderMutation.isPending && (\n <Loader2 className=\"size-4 animate-spin\" />\n )}\n {createFolderMutation.isPending\n ? tWithFallback(\n t,\n \"files.browser.newFolderDialog.actions.creating\",\n \"Creating...\",\n )\n : tWithFallback(t, \"files.common.actions.create\", \"Create\")}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Rename Dialog */}\n {showRenameDialog && renameTarget && (\n <div\n className=\"fixed inset-0 backdrop-blur-sm flex items-center justify-center z-[100] animate-in fade-in duration-200\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"files-rename-title\"\n >\n <div className=\"bg-bg-surface rounded-lg shadow-xl p-6 w-full max-w-xs mx-4 animate-in zoom-in-95 duration-200\">\n <h2\n id=\"files-rename-title\"\n className=\"text-base font-semibold text-text-primary mb-4\"\n >\n {tWithFallback(\n t,\n \"files.browser.renameDialog.title\",\n \"Rename {{type}}\",\n { type: renameTarget.type },\n )}\n </h2>\n <input\n type=\"text\"\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleRenameSubmit();\n if (e.key === \"Escape\") {\n setShowRenameDialog(false);\n setRenameTarget(null);\n setNewName(\"\");\n }\n }}\n aria-label={tWithFallback(\n t,\n \"files.browser.renameDialog.title\",\n \"Rename\",\n )}\n placeholder={tWithFallback(\n t,\n \"files.browser.renameDialog.placeholder\",\n \"New name\",\n )}\n className=\"w-full px-4 py-3 border-2 border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200\"\n />\n <div className=\"flex justify-end gap-2 mt-6\">\n <button\n type=\"button\"\n onClick={() => {\n setShowRenameDialog(false);\n setRenameTarget(null);\n setNewName(\"\");\n }}\n className=\"px-6 py-2.5 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n >\n {tWithFallback(t, \"files.common.actions.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={handleRenameSubmit}\n disabled={\n !newName.trim() ||\n newName.trim() === renameTarget.name ||\n renameFileMutation.isPending ||\n renameFolderMutation.isPending\n }\n className=\"px-6 py-2.5 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover disabled:bg-bg-muted disabled:text-text-tertiary disabled:cursor-not-allowed transition-colors duration-200 flex items-center gap-2\"\n >\n {(renameFileMutation.isPending ||\n renameFolderMutation.isPending) && (\n <Loader2 className=\"size-4 animate-spin\" />\n )}\n {renameFileMutation.isPending || renameFolderMutation.isPending\n ? tWithFallback(\n t,\n \"files.browser.renameDialog.actions.renaming\",\n \"Renaming...\",\n )\n : tWithFallback(t, \"files.common.actions.rename\", \"Rename\")}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Share Dialog */}\n {showShareDialog && shareTarget && (\n <ShareDialog\n item={shareTarget}\n itemType={\"mimeType\" in shareTarget ? \"file\" : \"folder\"}\n onClose={() => {\n setShowShareDialog(false);\n setShareTarget(null);\n }}\n onCreateShare={handleCreateShare}\n isLoading={createShareMutation.isPending}\n />\n )}\n\n {confirmDialog && (\n <ConfirmDialog\n title={confirmDialog.title}\n description={confirmDialog.description}\n confirmLabel={confirmDialog.confirmLabel}\n cancelLabel={tWithFallback(\n t,\n \"files.common.actions.cancel\",\n \"Cancel\",\n )}\n variant={confirmDialog.variant}\n loading={confirmDialog.loading}\n onConfirm={runConfirmedAction}\n onCancel={() => {\n if (!confirmDialog.loading) {\n setConfirmDialog(null);\n }\n }}\n />\n )}\n\n {/* Folder Quota Exhausted Dialog */}\n {showFolderQuotaExhausted && (\n <ConfirmDialog\n title={tWithFallback(\n t,\n \"files.folder.quota.title\",\n \"Folder Limit Reached\",\n )}\n description={tWithFallback(\n t,\n \"files.folder.quota.description\",\n \"You've reached the folder limit for your plan. Upgrade your plan or purchase an add-on to create more folders.\",\n )}\n confirmLabel={tWithFallback(\n t,\n \"files.folder.quota.upgrade\",\n \"View Billing\",\n )}\n cancelLabel={tWithFallback(\n t,\n \"files.common.actions.dismiss\",\n \"Dismiss\",\n )}\n onConfirm={() => {\n setShowFolderQuotaExhausted(false);\n navigate(\"/billing\");\n }}\n onCancel={() => setShowFolderQuotaExhausted(false)}\n />\n )}\n\n {/* Move Dialog */}\n {showMoveDialog && moveTarget && (\n <MoveDialog\n item={moveTarget.item}\n type={moveTarget.type}\n onClose={() => {\n setShowMoveDialog(false);\n setMoveTarget(null);\n }}\n onMove={handleMoveSubmit}\n isLoading={moveFileMutation.isPending || moveFolderMutation.isPending}\n />\n )}\n\n {/* Copy Dialog */}\n {showCopyDialog && copyTarget && (\n <CopyDialog\n item={copyTarget.item}\n type={copyTarget.type}\n onClose={() => {\n setShowCopyDialog(false);\n setCopyTarget(null);\n }}\n onCopy={handleCopySubmit}\n isLoading={copyFileMutation.isPending}\n />\n )}\n\n {/* File Preview Modal */}\n {previewFile && (\n <FilePreviewModal\n file={previewFile}\n onClose={() => setPreviewFile(null)}\n onDownload={() => {\n const url = previewFile.downloadUrl || previewFile.url;\n void nativeOpenUrl(url);\n }}\n onShare={\n activeTab === \"bin\"\n ? undefined\n : () => {\n setShareTarget(previewFile);\n setShowShareDialog(true);\n }\n }\n onStar={\n activeTab === \"bin\"\n ? undefined\n : () => handleFileFavorite(previewFile)\n }\n onDelete={() =>\n activeTab === \"bin\"\n ? handleFilePermanentDelete(previewFile)\n : handleFileDelete(previewFile)\n }\n />\n )}\n\n {/* File Info Panel */}\n {infoPanel && (\n <FileInfoPanel\n item={infoPanel.item}\n type={infoPanel.type}\n onClose={() => setInfoPanel(null)}\n />\n )}\n\n {/* Upload Progress Indicator */}\n {/* Upload Queue */}\n <UploadQueue\n items={uploadQueue}\n isOpen={isUploadPanelOpen}\n onClose={() => setIsUploadPanelOpen(false)}\n onPause={handlePauseUpload}\n onResume={handleResumeUpload}\n onRetry={handleRetryUpload}\n onCancel={handleCancelUpload}\n />\n\n {/* Toast Notifications */}\n <ToastContainer toasts={toast.toasts} onClose={toast.removeToast} />\n\n {/* Empty State */}\n {!loading && files.length === 0 && folders.length === 0 && (\n <div className=\"px-6 py-12\">\n {isSearching ? (\n <div className=\"text-center animate-in fade-in duration-300\">\n <div className=\"inline-flex items-center justify-center size-16 bg-bg-muted rounded-full mb-4\">\n <Search className=\"size-8 text-text-tertiary\" />\n </div>\n <h3 className=\"text-lg font-medium text-text-primary mb-2\">\n {tWithFallback(\n t,\n \"files.browser.empty.search.title\",\n \"No results found\",\n )}\n </h3>\n <p className=\"text-sm text-text-secondary mb-4\">\n {tWithFallback(\n t,\n \"files.browser.empty.search.description\",\n \"Try adjusting your search query or filters\",\n )}\n </p>\n <button\n type=\"button\"\n onClick={() => {\n setSearchQuery(\"\");\n setSearchFilters(undefined);\n }}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover transition-colors duration-200\"\n >\n {tWithFallback(t, \"files.browser.search.clear\", \"Clear search\")}\n </button>\n </div>\n ) : (\n <EmptyState\n type={activeTab}\n onUpload={activeTab === \"all\" ? handleUploadClick : undefined}\n onNewFolder={\n activeTab === \"all\" ? handleNewFolderClick : undefined\n }\n />\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"BrowserPage.js","names":[],"sources":["../../../src/files/pages/BrowserPage.tsx"],"sourcesContent":["import { useState, useEffect, useMemo } from \"react\";\nimport { useParams, useNavigate } from \"react-router-dom\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { useKeyboardNavigation } from \"../hooks/useKeyboardNavigation\";\nimport {\n Upload,\n FolderPlus,\n FolderUp,\n Grid3x3,\n List,\n Search,\n X,\n Loader2,\n Trash2,\n Home,\n FileDown,\n FolderX,\n} from \"lucide-react\";\nimport { useFilesContext } from \"../providers/FilesProvider\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { useBrowsePage } from \"../hooks/useBrowsePage\";\nimport { useRecentFiles } from \"../hooks/useRecentFiles\";\nimport { useStarredItems } from \"../hooks/useStarredItems\";\nimport { useBinItems } from \"../hooks/useBinItems\";\nimport { useCreateFolder } from \"../hooks/useCreateFolder\";\nimport { useUploadFile } from \"../hooks/useUploadFile\";\nimport { useDeleteFile } from \"../hooks/useDeleteFile\";\nimport { useDeleteFolder } from \"../hooks/useDeleteFolder\";\nimport { useRestoreFile } from \"../hooks/useRestoreFile\";\nimport { useRestoreFolder } from \"../hooks/useRestoreFolder\";\nimport { usePermanentlyDeleteFile } from \"../hooks/usePermanentlyDeleteFile\";\nimport { usePermanentlyDeleteFolder } from \"../hooks/usePermanentlyDeleteFolder\";\nimport { useToggleStar } from \"../hooks/useToggleStar\";\nimport { useRenameFile } from \"../hooks/useRenameFile\";\nimport { useRenameFolder } from \"../hooks/useRenameFolder\";\nimport { type CreateShareInput, useCreateShare } from \"../hooks/useCreateShare\";\nimport {\n type CreateFolderShareInput,\n useCreateFolderShare,\n} from \"../hooks/useCreateFolderShare\";\nimport { useCopyFile } from \"../hooks/useCopyFile\";\nimport { useMoveFile } from \"../hooks/useMoveFile\";\nimport { useMoveFolder } from \"../hooks/useMoveFolder\";\nimport { useBulkDelete } from \"../hooks/useBatchOperations\";\nimport { type SearchFilters, useSearch } from \"../hooks/useSearch\";\nimport { useToast } from \"../hooks/useToast\";\nimport { FileBrowser } from \"../components/FileBrowser\";\nimport { TabBar, type TabView } from \"../components/TabBar\";\nimport { ShareDialog, type ShareDialogInput } from \"../components/ShareDialog\";\nimport { FilePreviewModal } from \"../components/FilePreviewModal\";\nimport { FileInfoPanel } from \"../components/FileInfoPanel\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { ToastContainer } from \"../components/Toast\";\nimport { SearchBar } from \"../components/SearchBar\";\nimport { MoveDialog } from \"../components/MoveDialog\";\nimport { CopyDialog } from \"../components/CopyDialog\";\nimport { ConfirmDialog } from \"../components/ConfirmDialog\";\nimport { UploadQueue } from \"../components/UploadQueue\";\nimport type { FileItem, FolderItem, UploadItem } from \"../types\";\nimport type { FilesEventName } from \"../utils/events\";\nimport { isQuotaExhaustedError } from \"../utils/quotaUtils\";\nimport {\n nativeImpact,\n nativeNotify,\n nativeOpenUrl,\n} from \"../../utils/nativeBridge\";\nimport { emitFilesEvent } from \"../utils/events\";\nimport { tWithFallback } from \"../utils/i18n\";\nimport { generateThumbnail } from \"../utils\";\n\ninterface ShareDialogResult {\n publicUrl: string;\n token: string;\n}\n\ninterface ConfirmDialogState {\n title: string;\n description: string;\n confirmLabel: string;\n variant?: \"danger\" | \"default\";\n onConfirm: () => Promise<void> | void;\n loading?: boolean;\n}\n\n/**\n * BrowserPage - Main file browser with toolbar and view modes\n */\nexport function BrowserPage() {\n const { t } = useI18n();\n const { folderId } = useParams<{ folderId: string }>();\n const navigate = useNavigate();\n const filesContext = useFilesContext();\n const { workspaceId } = filesContext;\n const {\n viewMode,\n setViewMode,\n breadcrumbs,\n selectedFiles,\n selectedFolders,\n clearSelection,\n } = useFilesStore();\n\n // Tab state\n const [activeTab, setActiveTab] = useState<TabView>(\"all\");\n\n const enabledTabs = useMemo<TabView[]>(() => {\n return [\"all\", \"recent\", \"starred\"];\n }, []);\n\n // If the active tab gets disabled at runtime (flag flipped, user opt-out),\n // fall back to \"all\" instead of leaving the user on a blank screen.\n useEffect(() => {\n if (!enabledTabs.includes(activeTab)) {\n setActiveTab(\"all\");\n }\n }, [enabledTabs, activeTab]);\n\n const pageSize = 100;\n\n // Search state\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [searchFilters, setSearchFilters] = useState<SearchFilters>();\n const isSearching = searchQuery.trim().length >= 2;\n\n // Info panel state\n const [infoPanel, setInfoPanel] = useState<{\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n } | null>(null);\n\n // Preview state\n const [previewFile, setPreviewFile] = useState<FileItem | null>(null);\n\n // Toast notifications\n const toast = useToast();\n\n // Fetch data based on active tab. Each view owns one composed page query so\n // files, folders, and folder context travel in a single GraphQL operation.\n const browsePageQuery = useBrowsePage({\n folderId: folderId || undefined,\n pageSize,\n skip: activeTab !== \"all\" || isSearching,\n });\n const recentFilesQuery = useRecentFiles({\n skip: activeTab !== \"recent\" || isSearching,\n });\n const starredItemsQuery = useStarredItems({\n skip: activeTab !== \"starred\" || isSearching,\n });\n const binItemsQuery = useBinItems({\n skip: activeTab !== \"bin\" || isSearching,\n });\n\n const searchResults = useSearch(searchQuery, isSearching, searchFilters);\n\n // Update breadcrumbs when folder path data changes\n useEffect(() => {\n if (\n folderId &&\n browsePageQuery.data?.folderPath &&\n browsePageQuery.data?.currentFolder\n ) {\n // Combine parent folders with current folder\n const parentFolders = browsePageQuery.data.folderPath.folders || [];\n const currentFolder = browsePageQuery.data.currentFolder;\n const breadcrumbPath = [\n ...parentFolders.map((f: { id: string; name: string }) => ({\n id: f.id,\n name: f.name,\n })),\n { id: currentFolder.id, name: currentFolder.name },\n ];\n useFilesStore.getState().setBreadcrumbs(breadcrumbPath);\n } else {\n useFilesStore.getState().setBreadcrumbs([]);\n }\n }, [folderId, browsePageQuery.data]);\n\n // Determine which data to display based on search state\n let files: FileItem[] = [];\n let folders: FolderItem[] = [];\n let loading = false;\n let error: Error | null = null;\n let preserveSortOrder = false; // For Recent/Bin tabs - skip re-sorting\n\n // If searching, use search results\n if (isSearching && searchResults.data) {\n files = searchResults.data.files || [];\n folders = searchResults.data.folders || [];\n loading = searchResults.isLoading;\n error = searchResults.error as Error | null;\n } else {\n // Show data based on active tab\n switch (activeTab) {\n case \"all\":\n files = (browsePageQuery.data?.filesList?.files || []) as FileItem[];\n folders = (browsePageQuery.data?.foldersList?.folders ||\n []) as FolderItem[];\n loading = browsePageQuery.loading;\n error = (browsePageQuery.error as Error) || null;\n preserveSortOrder = false;\n break;\n case \"recent\":\n files = recentFilesQuery.files || [];\n folders = recentFilesQuery.folders || [];\n loading = recentFilesQuery.isLoading;\n error = (recentFilesQuery.error as Error) || null;\n preserveSortOrder = true; // Recent tab already sorted by backend\n break;\n case \"starred\":\n files = starredItemsQuery.files;\n folders = starredItemsQuery.folders;\n loading = starredItemsQuery.isLoading;\n error = (starredItemsQuery.error as Error) || null;\n preserveSortOrder = true;\n break;\n case \"bin\":\n files = binItemsQuery.files;\n folders = binItemsQuery.folders;\n loading = binItemsQuery.isLoading;\n error = (binItemsQuery.error as Error) || null;\n preserveSortOrder = true; // Bin tab already sorted by backend\n break;\n }\n }\n\n const totalItemsInCurrentView =\n activeTab === \"all\"\n ? (browsePageQuery.data?.filesList?.total ?? files.length) +\n (browsePageQuery.data?.foldersList?.total ?? folders.length)\n : null;\n\n const totalSelected = selectedFiles.size + selectedFolders.size;\n const [showNewFolderDialog, setShowNewFolderDialog] = useState(false);\n const [showFolderQuotaExhausted, setShowFolderQuotaExhausted] =\n useState(false);\n const [showRenameDialog, setShowRenameDialog] = useState(false);\n const [showShareDialog, setShowShareDialog] = useState(false);\n const [showMoveDialog, setShowMoveDialog] = useState(false);\n const [showCopyDialog, setShowCopyDialog] = useState(false);\n const [shareTarget, setShareTarget] = useState<FileItem | FolderItem | null>(\n null,\n );\n const [moveTarget, setMoveTarget] = useState<{\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n } | null>(null);\n const [copyTarget, setCopyTarget] = useState<{\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n } | null>(null);\n const [renameTarget, setRenameTarget] = useState<{\n id: string;\n name: string;\n type: \"file\" | \"folder\";\n } | null>(null);\n const [newName, setNewName] = useState(\"\");\n const [newFolderName, setNewFolderName] = useState(\"\");\n const [uploading, setUploading] = useState(false);\n const [uploadQueue, setUploadQueue] = useState<UploadItem[]>([]);\n const [isUploadPanelOpen, setIsUploadPanelOpen] = useState(false);\n const [confirmDialog, setConfirmDialog] = useState<ConfirmDialogState | null>(\n null,\n );\n\n const emitEvent = (\n name: FilesEventName,\n payload: Record<string, unknown>,\n ) => {\n emitFilesEvent(filesContext, name, payload);\n };\n\n const runConfirmedAction = async () => {\n if (!confirmDialog || confirmDialog.loading) return;\n\n const action = confirmDialog.onConfirm;\n setConfirmDialog({ ...confirmDialog, loading: true });\n try {\n await action();\n setConfirmDialog(null);\n } catch (error) {\n emitEvent(\"files.api.failed\", {\n action: \"confirmDialog\",\n message:\n error instanceof Error ? error.message : \"Confirmed action failed\",\n });\n setConfirmDialog((current) =>\n current ? { ...current, loading: false } : current,\n );\n }\n };\n\n // Mutations\n const createFolderMutation = useCreateFolder();\n const uploadFileMutation = useUploadFile();\n const deleteFileMutation = useDeleteFile();\n const deleteFolderMutation = useDeleteFolder();\n const restoreFileMutation = useRestoreFile();\n const restoreFolderMutation = useRestoreFolder();\n const permanentlyDeleteFileMutation = usePermanentlyDeleteFile();\n const permanentlyDeleteFolderMutation = usePermanentlyDeleteFolder();\n const toggleStarMutation = useToggleStar();\n const renameFileMutation = useRenameFile();\n const renameFolderMutation = useRenameFolder();\n const createShareMutation = useCreateShare();\n const createFolderShareMutation = useCreateFolderShare();\n const copyFileMutation = useCopyFile();\n const moveFileMutation = useMoveFile();\n const moveFolderMutation = useMoveFolder();\n const bulkDeleteMutation = useBulkDelete();\n\n // Action handlers\n const handleUploadClick = () => {\n const input = document.createElement(\"input\");\n input.type = \"file\";\n input.multiple = true;\n input.onchange = async (e) => {\n const files = (e.target as HTMLInputElement).files;\n if (files && files.length > 0) {\n const newItems: UploadItem[] = await Promise.all(\n Array.from(files).map(async (file, index) => {\n const thumbnailUrl = await generateThumbnail(file);\n return {\n id: `${Date.now()}-${index}-${file.name}`,\n file,\n status: \"pending\" as const,\n progress: 0,\n folderId: folderId || undefined,\n thumbnailUrl: thumbnailUrl ?? undefined,\n };\n }),\n );\n setUploadQueue((prev) => [...prev, ...newItems]);\n setIsUploadPanelOpen(true);\n setUploading(true);\n\n for (const item of newItems) {\n await processUpload(item);\n }\n setUploading(false);\n }\n };\n input.click();\n };\n\n const processUpload = async (item: UploadItem) => {\n const updateItem = (updates: Partial<UploadItem>) => {\n setUploadQueue((prev) =>\n prev.map((i) => (i.id === item.id ? { ...i, ...updates } : i)),\n );\n };\n\n updateItem({ status: \"uploading\" });\n\n try {\n const uploadedFile = await uploadFileMutation.mutateAsync({\n file: item.file,\n folderId: item.folderId,\n onProgress: (progress) => {\n updateItem({ progress });\n },\n });\n updateItem({ status: \"completed\", progress: 100 });\n emitEvent(\"files.file.uploaded\", {\n fileId: uploadedFile.id,\n fileName: uploadedFile.name,\n folderId: item.folderId,\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error\n ? error.message\n : tWithFallback(t, \"files.upload.errors.failed\", \"Upload failed\");\n if (errorMessage === \"Upload paused\") {\n updateItem({ status: \"paused\" });\n } else if (errorMessage === \"QUOTA_EXHAUSTED\") {\n updateItem({\n status: \"failed\",\n error: tWithFallback(\n t,\n \"files.upload.errors.quotaExceeded\",\n \"Storage quota exceeded\",\n ),\n });\n toast.error(\n tWithFallback(\n t,\n \"files.upload.errors.quotaExceeded\",\n \"Storage quota exceeded. Please upgrade your plan or delete files.\",\n ),\n );\n } else {\n updateItem({ status: \"failed\", error: errorMessage });\n emitEvent(\"files.api.failed\", {\n action: \"uploadFile\",\n fileName: item.file.name,\n message: errorMessage,\n });\n }\n }\n };\n\n const handlePauseUpload = (id: string) => {\n uploadFileMutation.pause();\n setUploadQueue((prev) =>\n prev.map((i) => (i.id === id ? { ...i, status: \"paused\" as const } : i)),\n );\n };\n\n const handleResumeUpload = (id: string) => {\n const item = uploadQueue.find((i) => i.id === id);\n if (item) {\n processUpload(item);\n }\n };\n\n const handleRetryUpload = (id: string) => {\n const item = uploadQueue.find((i) => i.id === id);\n if (item) {\n setUploadQueue((prev) =>\n prev.map((i) =>\n i.id === id\n ? {\n ...i,\n status: \"pending\" as const,\n progress: 0,\n error: undefined,\n }\n : i,\n ),\n );\n processUpload(item);\n }\n };\n\n const handleCancelUpload = (id: string) => {\n setUploadQueue((prev) => {\n const remaining = prev.filter((i) => i.id !== id);\n if (remaining.length === 0) {\n setIsUploadPanelOpen(false);\n setUploading(false);\n }\n return remaining;\n });\n };\n\n // Folder upload handler - uploads entire folder with structure\n const handleFolderUploadClick = () => {\n if (!workspaceId) {\n toast.error(\n tWithFallback(\n t,\n \"files.workspace.errors.notSelected\",\n \"Workspace not selected\",\n ),\n );\n return;\n }\n\n const input = document.createElement(\"input\");\n input.type = \"file\";\n input.webkitdirectory = true;\n input.onchange = async (e) => {\n const files = (e.target as HTMLInputElement).files;\n if (files && files.length > 0) {\n const filesByFolder = new Map<string, File[]>();\n for (const file of Array.from(files)) {\n const relativePath = file.webkitRelativePath || file.name;\n const pathParts = relativePath.split(\"/\");\n const folderPath = pathParts.slice(0, -1).join(\"/\");\n\n if (!filesByFolder.has(folderPath)) {\n filesByFolder.set(folderPath, []);\n }\n filesByFolder.get(folderPath)!.push(file);\n }\n\n const folderIdMap = new Map<string, string>();\n const sortedPaths = Array.from(filesByFolder.keys()).sort();\n\n for (const folderPath of sortedPaths) {\n if (!folderPath) continue;\n\n const pathParts = folderPath.split(\"/\");\n let currentPath = \"\";\n let parentId = folderId || undefined;\n\n for (const part of pathParts) {\n currentPath = currentPath ? `${currentPath}/${part}` : part;\n\n if (!folderIdMap.has(currentPath)) {\n try {\n const { data: createdFolder } =\n await createFolderMutation.mutateAsync({\n name: part,\n parentFolderId: parentId,\n });\n if (createdFolder?.id) {\n folderIdMap.set(currentPath, createdFolder.id);\n parentId = createdFolder.id;\n }\n } catch {\n // Continue best-effort\n }\n } else {\n parentId = folderIdMap.get(currentPath);\n }\n }\n }\n\n const newItems: UploadItem[] = [];\n let index = 0;\n for (const [folderPath, folderFiles] of filesByFolder) {\n const targetFolderId = folderPath\n ? folderIdMap.get(folderPath)\n : folderId || undefined;\n\n for (const file of folderFiles) {\n const thumbnailUrl = await generateThumbnail(file);\n newItems.push({\n id: `${Date.now()}-${index++}-${file.name}`,\n file,\n status: \"pending\",\n progress: 0,\n folderId: targetFolderId,\n thumbnailUrl: thumbnailUrl ?? undefined,\n });\n }\n }\n\n setUploadQueue((prev) => [...prev, ...newItems]);\n setIsUploadPanelOpen(true);\n setUploading(true);\n\n for (const item of newItems) {\n await processUpload(item);\n }\n setUploading(false);\n\n toast.success(\n tWithFallback(\n t,\n \"files.upload.folder.success\",\n \"Uploaded {{count}} file{{plural}} from folder\",\n { count: newItems.length, plural: newItems.length > 1 ? \"s\" : \"\" },\n ),\n );\n }\n };\n input.click();\n };\n\n const handleNewFolderClick = () => {\n setShowNewFolderDialog(true);\n };\n\n const handleCreateFolder = async () => {\n if (newFolderName.trim() && workspaceId) {\n const { data: createdFolder, error } =\n await createFolderMutation.mutateAsync({\n name: newFolderName,\n parentFolderId: folderId,\n });\n\n if (error) {\n if (isQuotaExhaustedError(error)) {\n setShowNewFolderDialog(false);\n setNewFolderName(\"\");\n setShowFolderQuotaExhausted(true);\n } else {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.folder.errors.createFailed\",\n \"Folder creation failed\",\n ),\n );\n emitEvent(\"files.api.failed\", {\n action: \"createFolder\",\n message:\n error instanceof Error ? error.message : \"Folder creation failed\",\n });\n }\n return;\n }\n\n if (createdFolder) {\n setNewFolderName(\"\");\n setShowNewFolderDialog(false);\n emitEvent(\"files.folder.created\", {\n folderName: newFolderName,\n parentFolderId: folderId,\n });\n }\n }\n };\n\n // File action handlers\n const handleFilePreview = (file: FileItem) => {\n setPreviewFile(file);\n };\n\n const handleFileShare = (file: FileItem) => {\n setShareTarget(file);\n setShowShareDialog(true);\n };\n\n const handleFolderShare = (folder: FolderItem) => {\n setShareTarget(folder);\n setShowShareDialog(true);\n };\n\n const handleCreateShare = async (\n input: ShareDialogInput,\n ): Promise<ShareDialogResult> => {\n if (!input.fileId && !input.folderId) {\n throw new Error(\n tWithFallback(\n t,\n \"files.share.errors.targetRequired\",\n \"Share requires a file id or folder id\",\n ),\n );\n }\n\n const shareType = input.invitedEmail ? \"EMAIL_INVITE\" : \"PUBLIC_LINK\";\n let token = \"\";\n\n if (input.fileId) {\n // File share\n const shareInput: CreateShareInput = {\n fileId: input.fileId,\n expiresAt: input.expiresAt,\n maxDownloads: input.maxDownloads,\n password: input.password,\n invitedEmail: input.invitedEmail,\n shareType,\n accessLevel: \"DOWNLOAD\" as const,\n };\n const result = await createShareMutation.mutateAsync(shareInput);\n token = result?.token ?? \"\";\n emitEvent(\"files.share.created\", {\n entityType: \"file\",\n fileId: input.fileId,\n shareType,\n });\n } else if (input.folderId) {\n // Folder share\n const shareInput: CreateFolderShareInput = {\n folderId: input.folderId,\n expiresAt: input.expiresAt,\n maxDownloads: input.maxDownloads,\n password: input.password,\n invitedEmail: input.invitedEmail,\n shareType,\n accessLevel: \"DOWNLOAD\" as const,\n };\n const result = await createFolderShareMutation.mutateAsync(shareInput);\n token = result?.createFolderShare?.token ?? \"\";\n emitEvent(\"files.share.created\", {\n entityType: \"folder\",\n folderId: input.folderId,\n shareType,\n });\n }\n\n return {\n publicUrl: token ? `${window.location.origin}/files/share/${token}` : \"\",\n token,\n };\n };\n\n const handleFileDelete = async (file: FileItem) => {\n nativeImpact(\"medium\");\n setConfirmDialog({\n title: tWithFallback(t, \"files.confirm.deleteFile.title\", \"Delete file\"),\n description: tWithFallback(\n t,\n \"files.confirm.deleteFile.description\",\n 'Move \"{{name}}\" to the bin?',\n { name: file.name },\n ),\n confirmLabel: tWithFallback(t, \"files.common.actions.delete\", \"Delete\"),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n await deleteFileMutation.mutateAsync({ id: file.id });\n nativeNotify(\"success\");\n toast.success(\n tWithFallback(\n t,\n \"files.file.delete.success\",\n '\"{{name}}\" moved to bin',\n { name: file.name },\n ),\n );\n emitEvent(\"files.file.deleted\", {\n fileId: file.id,\n fileName: file.name,\n permanent: false,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.file.errors.deleteFailed\",\n 'Failed to delete \"{{name}}\"',\n { name: file.name },\n ),\n );\n nativeNotify(\"error\");\n emitEvent(\"files.api.failed\", {\n action: \"deleteFile\",\n fileId: file.id,\n message:\n error instanceof Error ? error.message : \"Failed to delete file\",\n });\n }\n },\n });\n };\n\n const handleFileRestore = async (file: FileItem) => {\n try {\n await restoreFileMutation.mutateAsync({ id: file.id });\n toast.success(\n tWithFallback(t, \"files.file.restore.success\", '\"{{name}}\" restored', {\n name: file.name,\n }),\n );\n emitEvent(\"files.file.restored\", {\n fileId: file.id,\n fileName: file.name,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.file.errors.restoreFailed\",\n \"Failed to restore file\",\n ),\n );\n }\n };\n\n const handleFilePermanentDelete = async (file: FileItem) => {\n nativeImpact(\"heavy\");\n setConfirmDialog({\n title: tWithFallback(\n t,\n \"files.confirm.permanentDeleteFile.title\",\n \"Permanently delete file\",\n ),\n description: tWithFallback(\n t,\n \"files.confirm.permanentDeleteFile.description\",\n 'Permanently delete \"{{name}}\"? This cannot be undone.',\n { name: file.name },\n ),\n confirmLabel: tWithFallback(\n t,\n \"files.common.actions.deletePermanently\",\n \"Delete permanently\",\n ),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n await permanentlyDeleteFileMutation.mutateAsync({ id: file.id });\n toast.success(\n tWithFallback(\n t,\n \"files.file.permanentDelete.success\",\n '\"{{name}}\" deleted permanently',\n { name: file.name },\n ),\n );\n emitEvent(\"files.file.deleted\", {\n fileId: file.id,\n fileName: file.name,\n permanent: true,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.file.errors.permanentDeleteFailed\",\n \"Failed to permanently delete file\",\n ),\n );\n }\n },\n });\n };\n\n const handleFileFavorite = async (file: FileItem) => {\n try {\n await toggleStarMutation.mutateAsync({ id: file.id, type: \"file\" });\n emitEvent(\"files.file.starred\", {\n fileId: file.id,\n fileName: file.name,\n starred: !file.starred,\n });\n } catch {\n toast.error(\n tWithFallback(\n t,\n \"files.file.errors.starFailed\",\n \"Failed to update starred state\",\n ),\n );\n emitEvent(\"files.api.failed\", {\n action: \"toggleFileStar\",\n fileId: file.id,\n });\n }\n };\n\n const handleFileRename = (file: FileItem) => {\n setRenameTarget({ id: file.id, name: file.name, type: \"file\" });\n setNewName(file.name);\n setShowRenameDialog(true);\n };\n\n const handleFileDownload = async (file: FileItem) => {\n try {\n const downloadUrl = file.downloadUrl || file.url;\n\n if (!downloadUrl) {\n throw new Error(\n tWithFallback(\n t,\n \"files.file.errors.downloadUrlUnavailable\",\n \"Download URL is unavailable\",\n ),\n );\n }\n\n const a = document.createElement(\"a\");\n a.style.display = \"none\";\n a.href = downloadUrl;\n a.download = file.name;\n a.rel = \"noopener noreferrer\";\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n\n toast.success(\n tWithFallback(t, \"files.file.download.success\", \"Downloaded {{name}}\", {\n name: file.name,\n }),\n );\n emitEvent(\"files.file.downloaded\", {\n fileId: file.id,\n fileName: file.name,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.file.errors.downloadFailed\",\n \"Failed to download file\",\n ),\n );\n }\n };\n\n const handleFileCopy = (file: FileItem) => {\n setCopyTarget({ item: file, type: \"file\" });\n setShowCopyDialog(true);\n };\n\n const handleFileMove = (file: FileItem) => {\n setMoveTarget({ item: file, type: \"file\" });\n setShowMoveDialog(true);\n };\n\n const handleFileInfoClick = (file: FileItem) => {\n setInfoPanel({ item: file, type: \"file\" });\n };\n\n // Folder action handlers\n const handleFolderOpen = (folder: FolderItem) => {\n // Navigate to folder by updating URL\n navigate(`/files/browse/${folder.id}`);\n };\n\n const handleFolderDelete = async (folder: FolderItem) => {\n nativeImpact(\"medium\");\n setConfirmDialog({\n title: tWithFallback(\n t,\n \"files.confirm.deleteFolder.title\",\n \"Delete folder\",\n ),\n description: tWithFallback(\n t,\n \"files.confirm.deleteFolder.description\",\n 'Move folder \"{{name}}\" and all its contents to the bin?',\n { name: folder.name },\n ),\n confirmLabel: tWithFallback(t, \"files.common.actions.delete\", \"Delete\"),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n await deleteFolderMutation.mutateAsync({\n id: folder.id,\n recursive: true,\n });\n toast.success(\n tWithFallback(\n t,\n \"files.folder.delete.success\",\n '\"{{name}}\" moved to bin',\n { name: folder.name },\n ),\n );\n emitEvent(\"files.folder.deleted\", {\n folderId: folder.id,\n folderName: folder.name,\n permanent: false,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.folder.errors.deleteFailed\",\n \"Failed to delete folder\",\n ),\n );\n }\n },\n });\n };\n\n const handleFolderRestore = async (folder: FolderItem) => {\n try {\n await restoreFolderMutation.mutateAsync({ id: folder.id });\n toast.success(\n tWithFallback(\n t,\n \"files.folder.restore.success\",\n '\"{{name}}\" restored',\n { name: folder.name },\n ),\n );\n emitEvent(\"files.folder.restored\", {\n folderId: folder.id,\n folderName: folder.name,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.folder.errors.restoreFailed\",\n \"Failed to restore folder\",\n ),\n );\n }\n };\n\n const handleFolderPermanentDelete = async (folder: FolderItem) => {\n setConfirmDialog({\n title: tWithFallback(\n t,\n \"files.confirm.permanentDeleteFolder.title\",\n \"Permanently delete folder\",\n ),\n description: tWithFallback(\n t,\n \"files.confirm.permanentDeleteFolder.description\",\n 'Permanently delete folder \"{{name}}\" and its contents? This cannot be undone.',\n { name: folder.name },\n ),\n confirmLabel: tWithFallback(\n t,\n \"files.common.actions.deletePermanently\",\n \"Delete permanently\",\n ),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n await permanentlyDeleteFolderMutation.mutateAsync({ id: folder.id });\n toast.success(\n tWithFallback(\n t,\n \"files.folder.permanentDelete.success\",\n '\"{{name}}\" deleted permanently',\n { name: folder.name },\n ),\n );\n emitEvent(\"files.folder.deleted\", {\n folderId: folder.id,\n folderName: folder.name,\n permanent: true,\n });\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.folder.errors.permanentDeleteFailed\",\n \"Failed to permanently delete folder\",\n ),\n );\n }\n },\n });\n };\n\n const handleFolderRename = (folder: FolderItem) => {\n setRenameTarget({ id: folder.id, name: folder.name, type: \"folder\" });\n setNewName(folder.name);\n setShowRenameDialog(true);\n };\n\n const handleFolderMove = (folder: FolderItem) => {\n setMoveTarget({ item: folder, type: \"folder\" });\n setShowMoveDialog(true);\n };\n\n const handleFolderFavorite = async (folder: FolderItem) => {\n try {\n await toggleStarMutation.mutateAsync({ id: folder.id, type: \"folder\" });\n emitEvent(\"files.folder.starred\", {\n folderId: folder.id,\n folderName: folder.name,\n starred: !folder.starred,\n });\n } catch {\n toast.error(\n tWithFallback(\n t,\n \"files.folder.errors.starFailed\",\n \"Failed to update starred state\",\n ),\n );\n emitEvent(\"files.api.failed\", {\n action: \"toggleFolderStar\",\n folderId: folder.id,\n });\n }\n };\n\n const handleFolderInfoClick = (folder: FolderItem) => {\n setInfoPanel({ item: folder, type: \"folder\" });\n };\n\n // Move and Copy handlers\n const handleMoveSubmit = async (destinationFolderId: string | null) => {\n if (!moveTarget) return;\n\n try {\n if (moveTarget.type === \"file\") {\n await moveFileMutation.mutateAsync({\n fileId: moveTarget.item.id,\n targetFolderId: destinationFolderId || null,\n });\n toast.success(\n tWithFallback(t, \"files.file.move.success\", '\"{{name}}\" moved', {\n name: moveTarget.item.name,\n }),\n );\n emitEvent(\"files.file.moved\", {\n fileId: moveTarget.item.id,\n fileName: moveTarget.item.name,\n destinationFolderId,\n });\n } else {\n await moveFolderMutation.mutateAsync({\n folderId: moveTarget.item.id,\n targetParentFolderId: destinationFolderId,\n });\n toast.success(\n tWithFallback(t, \"files.folder.move.success\", '\"{{name}}\" moved', {\n name: moveTarget.item.name,\n }),\n );\n emitEvent(\"files.folder.moved\", {\n folderId: moveTarget.item.id,\n folderName: moveTarget.item.name,\n destinationFolderId,\n });\n }\n setShowMoveDialog(false);\n setMoveTarget(null);\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.item.errors.moveFailed\",\n 'Failed to move \"{{name}}\"',\n {\n name: moveTarget.item.name,\n },\n ),\n );\n emitEvent(\"files.api.failed\", {\n action: moveTarget.type === \"file\" ? \"moveFile\" : \"moveFolder\",\n itemId: moveTarget.item.id,\n itemType: moveTarget.type,\n message: error instanceof Error ? error.message : undefined,\n });\n }\n };\n\n const handleCopySubmit = async (\n destinationFolderId: string | null,\n newName?: string,\n ) => {\n if (!copyTarget) return;\n\n try {\n if (copyTarget.type !== \"file\") {\n throw new Error(\n tWithFallback(\n t,\n \"files.folder.errors.copyUnsupported\",\n \"Folder copy is not supported\",\n ),\n );\n }\n\n await copyFileMutation.mutateAsync({\n id: copyTarget.item.id,\n newName: newName || `Copy of ${copyTarget.item.name}`,\n targetFolderId: destinationFolderId || undefined,\n });\n toast.success(\n tWithFallback(t, \"files.file.copy.success\", '\"{{name}}\" copied', {\n name: copyTarget.item.name,\n }),\n );\n emitEvent(\"files.file.copied\", {\n fileId: copyTarget.item.id,\n fileName: copyTarget.item.name,\n destinationFolderId,\n });\n\n setShowCopyDialog(false);\n setCopyTarget(null);\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.file.errors.copyFailed\",\n 'Failed to copy \"{{name}}\"',\n {\n name: copyTarget.item.name,\n },\n ),\n );\n emitEvent(\"files.api.failed\", {\n action: \"copyFile\",\n fileId: copyTarget.item.id,\n message: error instanceof Error ? error.message : undefined,\n });\n }\n };\n\n const handleRenameSubmit = async () => {\n if (!renameTarget || !newName.trim()) return;\n\n try {\n const previousName = renameTarget.name;\n const nextName = newName.trim();\n\n if (renameTarget.type === \"file\") {\n await renameFileMutation.mutateAsync({\n fileId: renameTarget.id,\n newName: nextName,\n });\n toast.success(\n tWithFallback(t, \"files.file.rename.success\", 'Renamed \"{{name}}\"', {\n name: nextName,\n }),\n );\n emitEvent(\"files.file.renamed\", {\n fileId: renameTarget.id,\n previousName,\n name: nextName,\n });\n } else {\n await renameFolderMutation.mutateAsync({\n folderId: renameTarget.id,\n newName: nextName,\n });\n toast.success(\n tWithFallback(\n t,\n \"files.folder.rename.success\",\n 'Renamed \"{{name}}\"',\n {\n name: nextName,\n },\n ),\n );\n emitEvent(\"files.folder.renamed\", {\n folderId: renameTarget.id,\n previousName,\n name: nextName,\n });\n }\n setShowRenameDialog(false);\n setRenameTarget(null);\n setNewName(\"\");\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.item.errors.renameFailed\",\n \"Failed to rename {{type}}\",\n {\n type: renameTarget.type,\n },\n ),\n );\n emitEvent(\"files.api.failed\", {\n action: renameTarget.type === \"file\" ? \"renameFile\" : \"renameFolder\",\n itemId: renameTarget.id,\n itemType: renameTarget.type,\n message: error instanceof Error ? error.message : undefined,\n });\n }\n };\n\n const handleSearch = (query: string, filters?: SearchFilters) => {\n setSearchQuery(query);\n setSearchFilters(filters);\n };\n\n useKeyboardNavigation({\n files,\n folders,\n onFilePreview: handleFilePreview,\n onFileDelete: handleFileDelete,\n onFolderOpen: handleFolderOpen,\n onFolderDelete: handleFolderDelete,\n activeTab,\n });\n\n // Guard: if the host shell hasn't pushed workspace context yet, render a\n // clear loading state rather than firing queries with an undefined workspace\n // (which used to manifest as a silent blank screen).\n // NOTE: We explicitly check for undefined (not yet provided) vs empty string\n // (explicitly no workspace selected) to show appropriate messaging.\n if (workspaceId === undefined) {\n return (\n <div className=\"flex flex-col items-center justify-center min-h-[60vh] gap-3 text-center px-6\">\n <Loader2 className=\"size-8 animate-spin text-text-tertiary\" />\n <p className=\"text-sm text-text-secondary max-w-md\">\n {tWithFallback(\n t,\n \"files.browser.workspace.waiting\",\n \"Waiting for workspace context. If this persists, the app shell may not have provided a workspaceId to the Files module. Try reloading the page or switching workspaces.\",\n )}\n </p>\n </div>\n );\n }\n\n // Empty string means host shell provided context but no workspace is selected\n if (workspaceId === \"\") {\n return (\n <div className=\"flex flex-col items-center justify-center min-h-[60vh] gap-3 text-center px-6\">\n <FolderX className=\"size-8 text-text-tertiary\" />\n <p className=\"text-sm text-text-secondary max-w-md\">\n {tWithFallback(\n t,\n \"files.browser.workspace.notSelected\",\n \"No workspace selected. Please select a workspace to view files.\",\n )}\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"min-h-screen bg-bg-surface\">\n {/* Google Drive-style Header with Breadcrumb Navigation */}\n <div\n className=\"bg-bg-surface border-b border-border-default px-4 py-3 sm:px-6 sm:py-4\"\n data-tour=\"files-breadcrumb-nav\"\n >\n <div className=\"flex items-center gap-2 sm:gap-4\">\n <div className=\"flex items-center gap-1 sm:gap-2 text-sm overflow-x-auto\">\n <button\n type=\"button\"\n onClick={() => navigate(\"/files/browse\")}\n className=\"flex items-center gap-1 text-text-primary hover:bg-action-ghost-bg-hover px-2 py-1 rounded transition-colors duration-200 whitespace-nowrap\"\n title={tWithFallback(\n t,\n \"files.browser.actions.goToRoot\",\n \"Go to root\",\n )}\n >\n <Home className=\"size-4\" />\n <span className=\"hidden sm:inline\">\n {tWithFallback(t, \"files.browser.rootLabel\", \"My Drive\")}\n </span>\n </button>\n {breadcrumbs.map((crumb, index) => (\n <div key={crumb.id} className=\"flex items-center gap-1 sm:gap-2\">\n <span className=\"text-text-tertiary\">/</span>\n <button\n type=\"button\"\n onClick={() => navigate(`/files/browse/${crumb.id}`)}\n className={`hover:bg-action-ghost-bg-hover px-2 py-1 rounded transition-colors duration-200 whitespace-nowrap ${\n index === breadcrumbs.length - 1\n ? \"text-text-primary font-medium\"\n : \"text-text-secondary\"\n }`}\n title={`Go to ${crumb.name}`}\n >\n {crumb.name}\n </button>\n </div>\n ))}\n </div>\n </div>\n </div>\n\n {/* Navigation Tabs */}\n <div data-tour=\"files-tab-bar\">\n <TabBar\n activeTab={activeTab}\n onTabChange={setActiveTab}\n tabs={enabledTabs}\n />\n </div>\n\n {/* Google Drive-style Toolbar */}\n <div className=\"bg-bg-surface border-b border-border-default px-4 py-2 sm:px-6 sm:py-3\">\n <div className=\"flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 sm:gap-inline-gap\">\n {/* Left side - Search */}\n <div\n className=\"w-full sm:flex-1 min-w-0 order-2 sm:order-1\"\n data-tour=\"files-search-bar\"\n >\n <div className=\"relative w-full max-w-2xl\">\n <SearchBar\n onSearch={handleSearch}\n placeholder={tWithFallback(\n t,\n \"files.search.input.placeholder\",\n \"Search files and folders...\",\n )}\n initialQuery={searchQuery}\n showFilters={true}\n />\n </div>\n </div>\n\n {/* Right side - Actions */}\n <div className=\"flex items-center gap-2 order-1 sm:order-2 w-full sm:w-auto justify-between sm:justify-end\">\n {/* Select All button */}\n {!isSearching && (files.length > 0 || folders.length > 0) && (\n <button\n type=\"button\"\n onClick={() => {\n const allFileIds = files.map((f) => f.id);\n const allFolderIds = folders.map((f) => f.id);\n useFilesStore.getState().selectAllFiles(allFileIds);\n allFolderIds.forEach((id) =>\n useFilesStore.getState().selectFolder(id),\n );\n }}\n className=\"flex items-center gap-2 px-3 py-2 text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-lg hover:bg-action-ghost-bg-hover hover:border-border-default transition-all duration-200\"\n >\n {tWithFallback(\n t,\n \"files.browser.actions.selectAll\",\n \"Select All\",\n )}\n </button>\n )}\n\n {/* Only show New Folder and Upload buttons in \"All Files\" tab */}\n {!isSearching && (\n <>\n <button\n type=\"button\"\n onClick={handleNewFolderClick}\n className=\"flex items-center gap-1 sm:gap-2 px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-lg hover:bg-action-ghost-bg-hover hover:border-border-default transition-all duration-200 shadow-sm\"\n data-tour=\"files-new-folder-button\"\n >\n <FolderPlus className=\"size-4\" />\n <span className=\"hidden sm:inline\">\n {tWithFallback(\n t,\n \"files.browser.actions.newFolder\",\n \"New Folder\",\n )}\n </span>\n </button>\n\n <button\n type=\"button\"\n onClick={handleUploadClick}\n disabled={uploading}\n className=\"flex items-center gap-1 sm:gap-2 px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-lg hover:bg-action-ghost-bg-hover hover:border-border-default transition-all duration-200 shadow-sm disabled:opacity-50 disabled:cursor-not-allowed\"\n data-tour=\"files-upload-files-button\"\n >\n {uploading ? (\n <>\n <Loader2 className=\"size-4 animate-spin\" />\n <span className=\"hidden sm:inline\">\n {tWithFallback(\n t,\n \"files.browser.upload.uploading\",\n \"Uploading...\",\n )}\n </span>\n </>\n ) : (\n <>\n <Upload className=\"size-4\" />\n <span className=\"hidden sm:inline\">\n {tWithFallback(\n t,\n \"files.browser.actions.uploadFiles\",\n \"Upload Files\",\n )}\n </span>\n </>\n )}\n </button>\n\n <button\n type=\"button\"\n onClick={handleFolderUploadClick}\n disabled={uploading}\n className=\"hidden sm:flex items-center gap-2 px-4 py-2.5 text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-lg hover:bg-action-ghost-bg-hover hover:border-border-default transition-all duration-200 shadow-sm disabled:opacity-50 disabled:cursor-not-allowed\"\n title={tWithFallback(\n t,\n \"files.browser.actions.uploadFolderTitle\",\n \"Upload entire folder with structure\",\n )}\n >\n <FolderUp className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.browser.actions.uploadFolder\",\n \"Upload Folder\",\n )}\n </button>\n\n {/* Export button removed per user request */}\n </>\n )}\n\n {/* View mode toggle */}\n <div\n className=\"flex items-center border border-border-default rounded-lg overflow-hidden\"\n data-tour=\"files-view-mode-toggle\"\n >\n <button\n type=\"button\"\n onClick={() => setViewMode(\"grid\")}\n className={`p-2 transition-colors duration-200 ${\n viewMode === \"grid\"\n ? \"bg-bg-accent text-text-link\"\n : \"text-text-secondary hover:bg-action-ghost-bg-hover\"\n }`}\n aria-label={tWithFallback(\n t,\n \"files.browser.view.grid\",\n \"Grid view\",\n )}\n >\n <Grid3x3 className=\"size-5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setViewMode(\"list\")}\n className={`p-2 transition-colors duration-200 ${\n viewMode === \"list\"\n ? \"bg-bg-accent text-text-link\"\n : \"text-text-secondary hover:bg-action-ghost-bg-hover\"\n }`}\n aria-label={tWithFallback(\n t,\n \"files.browser.view.list\",\n \"List view\",\n )}\n >\n <List className=\"size-5\" />\n </button>\n </div>\n </div>\n </div>\n\n {/* Search results indicator */}\n {isSearching && (\n <div className=\"mt-3 flex items-center justify-between p-3 bg-status-success-bg-subtle rounded-lg border border-status-success-border transition-all duration-200\">\n <span className=\"text-sm font-medium text-status-success-text\">\n {tWithFallback(\n t,\n \"files.browser.search.showingResults\",\n 'Showing search results for \"{{query}}\"',\n { query: searchQuery },\n )}\n {searchResults.data &&\n ` (${(searchResults.data.files?.length || 0) + (searchResults.data.folders?.length || 0)} items)`}\n </span>\n <button\n type=\"button\"\n onClick={() => setSearchQuery(\"\")}\n className=\"flex items-center gap-2 text-status-success-text hover:text-status-success-text/80 text-sm font-medium transition-colors duration-200\"\n >\n <X className=\"size-4\" />\n {tWithFallback(t, \"files.browser.search.clear\", \"Clear search\")}\n </button>\n </div>\n )}\n\n {/* Selection info with bulk actions */}\n {totalSelected > 0 && (\n <div className=\"mt-3 flex items-center justify-between p-3 bg-bg-accent rounded-lg border border-action-primary-border transition-all duration-200\">\n <div className=\"flex items-center gap-4\">\n <span className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(\n t,\n \"files.browser.selection.selectedCount\",\n \"{{count}} item{{suffix}} selected\",\n {\n count: totalSelected,\n suffix: totalSelected > 1 ? \"s\" : \"\",\n },\n )}\n </span>\n\n {/* Bulk action buttons */}\n <div className=\"flex items-center gap-2\">\n {activeTab === \"bin\" ? (\n <>\n <button\n type=\"button\"\n onClick={async () => {\n try {\n await Promise.all([\n ...Array.from(selectedFiles).map((fileId) =>\n restoreFileMutation.mutateAsync({ id: fileId }),\n ),\n ...Array.from(selectedFolders).map((folderId) =>\n restoreFolderMutation.mutateAsync({\n id: folderId,\n }),\n ),\n ]);\n\n clearSelection();\n toast.success(\n `${totalSelected} item${totalSelected > 1 ? \"s\" : \"\"} restored`,\n );\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : \"Failed to restore some items\",\n );\n }\n }}\n className=\"flex items-center gap-1.5 rounded-lg border border-status-success-border bg-bg-surface px-3 py-1.5 text-sm font-medium text-status-success-text transition-colors duration-200 hover:bg-status-success-bg-subtle\"\n >\n {tWithFallback(\n t,\n \"files.browser.selection.actions.restore\",\n \"Restore\",\n )}\n </button>\n\n <button\n type=\"button\"\n onClick={async () => {\n setConfirmDialog({\n title: tWithFallback(\n t,\n \"files.confirm.bulkPermanentDelete.title\",\n \"Permanently delete selected items\",\n ),\n description: tWithFallback(\n t,\n \"files.confirm.bulkPermanentDelete.description\",\n \"Permanently delete {{count}} selected item{{plural}}? This cannot be undone.\",\n {\n count: totalSelected,\n plural: totalSelected > 1 ? \"s\" : \"\",\n },\n ),\n confirmLabel: tWithFallback(\n t,\n \"files.common.actions.deletePermanently\",\n \"Delete permanently\",\n ),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n await Promise.all([\n ...Array.from(selectedFiles).map((fileId) =>\n permanentlyDeleteFileMutation.mutateAsync({\n id: fileId,\n }),\n ),\n ...Array.from(selectedFolders).map((folderId) =>\n permanentlyDeleteFolderMutation.mutateAsync({\n id: folderId,\n }),\n ),\n ]);\n\n clearSelection();\n toast.success(\n tWithFallback(\n t,\n \"files.bulk.permanentDelete.success\",\n \"{{count}} item{{plural}} deleted permanently\",\n {\n count: totalSelected,\n plural: totalSelected > 1 ? \"s\" : \"\",\n },\n ),\n );\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.bulk.errors.permanentDeleteFailed\",\n \"Failed to permanently delete some items\",\n ),\n );\n }\n },\n });\n }}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-status-error-text bg-bg-surface border border-status-error-border rounded-lg hover:bg-status-error-bg-subtle transition-colors duration-200\"\n >\n <Trash2 className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.browser.selection.actions.deletePermanently\",\n \"Delete permanently\",\n )}\n </button>\n </>\n ) : (\n <button\n type=\"button\"\n onClick={async () => {\n setConfirmDialog({\n title: tWithFallback(\n t,\n \"files.confirm.bulkDelete.title\",\n \"Delete selected items\",\n ),\n description: tWithFallback(\n t,\n \"files.confirm.bulkDelete.description\",\n \"Move {{count}} selected item{{plural}} to the bin?\",\n {\n count: totalSelected,\n plural: totalSelected > 1 ? \"s\" : \"\",\n },\n ),\n confirmLabel: tWithFallback(\n t,\n \"files.common.actions.delete\",\n \"Delete\",\n ),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n const fileIds = Array.from(selectedFiles);\n const folderIds = Array.from(selectedFolders);\n\n if (fileIds.length > 0) {\n await bulkDeleteMutation.mutateAsync(fileIds);\n }\n\n await Promise.all(\n folderIds.map((folderId) =>\n deleteFolderMutation.mutateAsync({\n id: folderId,\n recursive: true,\n }),\n ),\n );\n\n clearSelection();\n toast.success(\n tWithFallback(\n t,\n \"files.bulk.delete.success\",\n \"{{count}} item{{plural}} moved to bin\",\n {\n count: totalSelected,\n plural: totalSelected > 1 ? \"s\" : \"\",\n },\n ),\n );\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.bulk.errors.deleteFailed\",\n \"Failed to delete some items\",\n ),\n );\n }\n },\n });\n }}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-status-error-text bg-bg-surface border border-status-error-border rounded-lg hover:bg-status-error-bg-subtle transition-colors duration-200\"\n >\n <Trash2 className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.browser.selection.actions.delete\",\n \"Delete\",\n )}\n </button>\n )}\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={clearSelection}\n className=\"flex items-center gap-2 text-text-link hover:text-action-primary-bg-hover text-sm font-medium transition-colors duration-200\"\n >\n <X className=\"size-4\" />\n {tWithFallback(t, \"files.common.actions.clear\", \"Clear\")}\n </button>\n </div>\n )}\n </div>\n\n {/* File Browser */}\n <div\n className=\"px-2 sm:px-4 md:px-6 py-3 sm:py-4\"\n data-tour=\"files-browser-grid\"\n >\n <FileBrowser\n files={files}\n folders={folders}\n loading={loading}\n error={error}\n preserveSortOrder={preserveSortOrder}\n onFilePreview={handleFilePreview}\n onFileShare={activeTab === \"bin\" ? undefined : handleFileShare}\n onFileDelete={\n activeTab === \"bin\" ? handleFilePermanentDelete : handleFileDelete\n }\n onFileRestore={activeTab === \"bin\" ? handleFileRestore : undefined}\n onFileFavorite={activeTab === \"bin\" ? undefined : handleFileFavorite}\n onFileRename={activeTab === \"bin\" ? undefined : handleFileRename}\n onFileDownload={handleFileDownload}\n onFileCopy={activeTab === \"bin\" ? undefined : handleFileCopy}\n onFileMove={activeTab === \"bin\" ? undefined : handleFileMove}\n onFileInfo={handleFileInfoClick}\n onFolderOpen={handleFolderOpen}\n onFolderShare={activeTab === \"bin\" ? undefined : handleFolderShare}\n onFolderDelete={\n activeTab === \"bin\"\n ? handleFolderPermanentDelete\n : handleFolderDelete\n }\n onFolderRestore={\n activeTab === \"bin\" ? handleFolderRestore : undefined\n }\n onFolderRename={activeTab === \"bin\" ? undefined : handleFolderRename}\n onFolderFavorite={\n activeTab === \"bin\" ? undefined : handleFolderFavorite\n }\n onFolderMove={activeTab === \"bin\" ? undefined : handleFolderMove}\n onFolderInfo={handleFolderInfoClick}\n />\n\n {/* Results Summary */}\n {!loading && (files.length > 0 || folders.length > 0) && (\n <div className=\"mt-4 px-2 text-sm text-text-secondary\">\n {tWithFallback(\n t,\n \"files.browser.results.showingItems\",\n \"Showing {{count}} items\",\n { count: files.length + folders.length },\n )}\n {!isSearching &&\n activeTab === \"all\" &&\n totalItemsInCurrentView !== null &&\n ` ${tWithFallback(\n t,\n \"files.browser.results.ofItems\",\n \"of {{count}} items\",\n { count: totalItemsInCurrentView },\n )}`}\n </div>\n )}\n </div>\n\n {/* New Folder Dialog */}\n {showNewFolderDialog && (\n <div\n className=\"fixed inset-0 backdrop-blur-sm flex items-center justify-center z-[100] animate-in fade-in duration-200\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"files-new-folder-title\"\n >\n <div className=\"bg-bg-surface rounded-lg shadow-xl p-6 w-full max-w-xs mx-4 animate-in zoom-in-95 duration-200\">\n <h2\n id=\"files-new-folder-title\"\n className=\"text-base font-semibold text-text-primary mb-4\"\n >\n {tWithFallback(\n t,\n \"files.browser.newFolderDialog.title\",\n \"New folder\",\n )}\n </h2>\n <input\n type=\"text\"\n value={newFolderName}\n onChange={(e) => setNewFolderName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleCreateFolder();\n if (e.key === \"Escape\") {\n setShowNewFolderDialog(false);\n setNewFolderName(\"\");\n }\n }}\n aria-label={tWithFallback(\n t,\n \"files.browser.newFolderDialog.title\",\n \"New folder\",\n )}\n placeholder={tWithFallback(\n t,\n \"files.browser.newFolderDialog.placeholder\",\n \"Folder name\",\n )}\n className=\"w-full px-4 py-3 border-2 border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200\"\n />\n <div className=\"flex justify-end gap-2 mt-6\">\n <button\n type=\"button\"\n onClick={() => {\n setShowNewFolderDialog(false);\n setNewFolderName(\"\");\n }}\n className=\"px-6 py-2.5 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n >\n {tWithFallback(t, \"files.common.actions.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={handleCreateFolder}\n disabled={\n !newFolderName.trim() || createFolderMutation.isPending\n }\n className=\"px-6 py-2.5 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover disabled:bg-bg-muted disabled:text-text-tertiary disabled:cursor-not-allowed transition-colors duration-200 flex items-center gap-2\"\n >\n {createFolderMutation.isPending && (\n <Loader2 className=\"size-4 animate-spin\" />\n )}\n {createFolderMutation.isPending\n ? tWithFallback(\n t,\n \"files.browser.newFolderDialog.actions.creating\",\n \"Creating...\",\n )\n : tWithFallback(t, \"files.common.actions.create\", \"Create\")}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Rename Dialog */}\n {showRenameDialog && renameTarget && (\n <div\n className=\"fixed inset-0 backdrop-blur-sm flex items-center justify-center z-[100] animate-in fade-in duration-200\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"files-rename-title\"\n >\n <div className=\"bg-bg-surface rounded-lg shadow-xl p-6 w-full max-w-xs mx-4 animate-in zoom-in-95 duration-200\">\n <h2\n id=\"files-rename-title\"\n className=\"text-base font-semibold text-text-primary mb-4\"\n >\n {tWithFallback(\n t,\n \"files.browser.renameDialog.title\",\n \"Rename {{type}}\",\n { type: renameTarget.type },\n )}\n </h2>\n <input\n type=\"text\"\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleRenameSubmit();\n if (e.key === \"Escape\") {\n setShowRenameDialog(false);\n setRenameTarget(null);\n setNewName(\"\");\n }\n }}\n aria-label={tWithFallback(\n t,\n \"files.browser.renameDialog.title\",\n \"Rename\",\n )}\n placeholder={tWithFallback(\n t,\n \"files.browser.renameDialog.placeholder\",\n \"New name\",\n )}\n className=\"w-full px-4 py-3 border-2 border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200\"\n />\n <div className=\"flex justify-end gap-2 mt-6\">\n <button\n type=\"button\"\n onClick={() => {\n setShowRenameDialog(false);\n setRenameTarget(null);\n setNewName(\"\");\n }}\n className=\"px-6 py-2.5 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n >\n {tWithFallback(t, \"files.common.actions.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={handleRenameSubmit}\n disabled={\n !newName.trim() ||\n newName.trim() === renameTarget.name ||\n renameFileMutation.isPending ||\n renameFolderMutation.isPending\n }\n className=\"px-6 py-2.5 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover disabled:bg-bg-muted disabled:text-text-tertiary disabled:cursor-not-allowed transition-colors duration-200 flex items-center gap-2\"\n >\n {(renameFileMutation.isPending ||\n renameFolderMutation.isPending) && (\n <Loader2 className=\"size-4 animate-spin\" />\n )}\n {renameFileMutation.isPending || renameFolderMutation.isPending\n ? tWithFallback(\n t,\n \"files.browser.renameDialog.actions.renaming\",\n \"Renaming...\",\n )\n : tWithFallback(t, \"files.common.actions.rename\", \"Rename\")}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Share Dialog */}\n {showShareDialog && shareTarget && (\n <ShareDialog\n item={shareTarget}\n itemType={\"mimeType\" in shareTarget ? \"file\" : \"folder\"}\n onClose={() => {\n setShowShareDialog(false);\n setShareTarget(null);\n }}\n onCreateShare={handleCreateShare}\n isLoading={createShareMutation.isPending}\n />\n )}\n\n {confirmDialog && (\n <ConfirmDialog\n title={confirmDialog.title}\n description={confirmDialog.description}\n confirmLabel={confirmDialog.confirmLabel}\n cancelLabel={tWithFallback(\n t,\n \"files.common.actions.cancel\",\n \"Cancel\",\n )}\n variant={confirmDialog.variant}\n loading={confirmDialog.loading}\n onConfirm={runConfirmedAction}\n onCancel={() => {\n if (!confirmDialog.loading) {\n setConfirmDialog(null);\n }\n }}\n />\n )}\n\n {/* Folder Quota Exhausted Dialog */}\n {showFolderQuotaExhausted && (\n <ConfirmDialog\n title={tWithFallback(\n t,\n \"files.folder.quota.title\",\n \"Folder Limit Reached\",\n )}\n description={tWithFallback(\n t,\n \"files.folder.quota.description\",\n \"You've reached the folder limit for your plan. Upgrade your plan or purchase an add-on to create more folders.\",\n )}\n confirmLabel={tWithFallback(\n t,\n \"files.folder.quota.upgrade\",\n \"View Billing\",\n )}\n cancelLabel={tWithFallback(\n t,\n \"files.common.actions.dismiss\",\n \"Dismiss\",\n )}\n onConfirm={() => {\n setShowFolderQuotaExhausted(false);\n navigate(\"/billing\");\n }}\n onCancel={() => setShowFolderQuotaExhausted(false)}\n />\n )}\n\n {/* Move Dialog */}\n {showMoveDialog && moveTarget && (\n <MoveDialog\n item={moveTarget.item}\n type={moveTarget.type}\n onClose={() => {\n setShowMoveDialog(false);\n setMoveTarget(null);\n }}\n onMove={handleMoveSubmit}\n isLoading={moveFileMutation.isPending || moveFolderMutation.isPending}\n />\n )}\n\n {/* Copy Dialog */}\n {showCopyDialog && copyTarget && (\n <CopyDialog\n item={copyTarget.item}\n type={copyTarget.type}\n onClose={() => {\n setShowCopyDialog(false);\n setCopyTarget(null);\n }}\n onCopy={handleCopySubmit}\n isLoading={copyFileMutation.isPending}\n />\n )}\n\n {/* File Preview Modal */}\n {previewFile && (\n <FilePreviewModal\n file={previewFile}\n onClose={() => setPreviewFile(null)}\n onDownload={() => {\n const url = previewFile.downloadUrl || previewFile.url;\n void nativeOpenUrl(url);\n }}\n onShare={\n activeTab === \"bin\"\n ? undefined\n : () => {\n setShareTarget(previewFile);\n setShowShareDialog(true);\n }\n }\n onStar={\n activeTab === \"bin\"\n ? undefined\n : () => handleFileFavorite(previewFile)\n }\n onDelete={() =>\n activeTab === \"bin\"\n ? handleFilePermanentDelete(previewFile)\n : handleFileDelete(previewFile)\n }\n />\n )}\n\n {/* File Info Panel */}\n {infoPanel && (\n <FileInfoPanel\n item={infoPanel.item}\n type={infoPanel.type}\n onClose={() => setInfoPanel(null)}\n />\n )}\n\n {/* Upload Progress Indicator */}\n {/* Upload Queue */}\n <UploadQueue\n items={uploadQueue}\n isOpen={isUploadPanelOpen}\n onClose={() => setIsUploadPanelOpen(false)}\n onPause={handlePauseUpload}\n onResume={handleResumeUpload}\n onRetry={handleRetryUpload}\n onCancel={handleCancelUpload}\n />\n\n {/* Toast Notifications */}\n <ToastContainer toasts={toast.toasts} onClose={toast.removeToast} />\n\n {/* Empty State */}\n {!loading && files.length === 0 && folders.length === 0 && (\n <div className=\"px-6 py-12\">\n {isSearching ? (\n <div className=\"text-center animate-in fade-in duration-300\">\n <div className=\"inline-flex items-center justify-center size-16 bg-bg-muted rounded-full mb-4\">\n <Search className=\"size-8 text-text-tertiary\" />\n </div>\n <h3 className=\"text-lg font-medium text-text-primary mb-2\">\n {tWithFallback(\n t,\n \"files.browser.empty.search.title\",\n \"No results found\",\n )}\n </h3>\n <p className=\"text-sm text-text-secondary mb-4\">\n {tWithFallback(\n t,\n \"files.browser.empty.search.description\",\n \"Try adjusting your search query or filters\",\n )}\n </p>\n <button\n type=\"button\"\n onClick={() => {\n setSearchQuery(\"\");\n setSearchFilters(undefined);\n }}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover transition-colors duration-200\"\n >\n {tWithFallback(t, \"files.browser.search.clear\", \"Clear search\")}\n </button>\n </div>\n ) : (\n <EmptyState\n type={activeTab}\n onUpload={activeTab === \"all\" ? handleUploadClick : undefined}\n onNewFolder={\n activeTab === \"all\" ? handleNewFolderClick : undefined\n }\n />\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-files",
3
- "version": "2026.528.2",
3
+ "version": "2026.530.1",
4
4
  "description": "Burdenoff Files Microfrontend - Standalone file management module",
5
5
  "type": "module",
6
6
  "imports": {