@anymux/ui-kit 0.1.0

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.
Files changed (244) hide show
  1. package/dist/ExplorerLayout-CSIJd7N4.js +105 -0
  2. package/dist/ExplorerLayout-CSIJd7N4.js.map +1 -0
  3. package/dist/FileBrowserContext-B6jixa2j.js +11 -0
  4. package/dist/FileBrowserContext-B6jixa2j.js.map +1 -0
  5. package/dist/calendar-DSlrbHoj.js +761 -0
  6. package/dist/calendar-DSlrbHoj.js.map +1 -0
  7. package/dist/calendar.d.ts +3 -0
  8. package/dist/calendar.js +3 -0
  9. package/dist/contacts-DQXTZzHc.js +539 -0
  10. package/dist/contacts-DQXTZzHc.js.map +1 -0
  11. package/dist/contacts.d.ts +3 -0
  12. package/dist/contacts.js +3 -0
  13. package/dist/file-browser-m5atC3kF.js +6755 -0
  14. package/dist/file-browser-m5atC3kF.js.map +1 -0
  15. package/dist/file-browser.d.ts +11 -0
  16. package/dist/file-browser.js +9 -0
  17. package/dist/git-B55e6LL-.js +561 -0
  18. package/dist/git-B55e6LL-.js.map +1 -0
  19. package/dist/git.d.ts +2 -0
  20. package/dist/git.js +3 -0
  21. package/dist/iconMap-V4B8P-Uh.js +206 -0
  22. package/dist/iconMap-V4B8P-Uh.js.map +1 -0
  23. package/dist/icons-CIsIOZXR.js +0 -0
  24. package/dist/icons.d.ts +2 -0
  25. package/dist/icons.js +4 -0
  26. package/dist/index-BNmNIWBL.d.ts +71 -0
  27. package/dist/index-BNmNIWBL.d.ts.map +1 -0
  28. package/dist/index-Bryv_GCG.d.ts +1481 -0
  29. package/dist/index-Bryv_GCG.d.ts.map +1 -0
  30. package/dist/index-CuQIjSXs.d.ts +134 -0
  31. package/dist/index-CuQIjSXs.d.ts.map +1 -0
  32. package/dist/index-DSu19mq0.d.ts +153 -0
  33. package/dist/index-DSu19mq0.d.ts.map +1 -0
  34. package/dist/index-DmsyeHFr.d.ts +149 -0
  35. package/dist/index-DmsyeHFr.d.ts.map +1 -0
  36. package/dist/index-DxnJ8FYM.d.ts +17 -0
  37. package/dist/index-DxnJ8FYM.d.ts.map +1 -0
  38. package/dist/index-DzfY1Tok.d.ts +32 -0
  39. package/dist/index-DzfY1Tok.d.ts.map +1 -0
  40. package/dist/index-Ml_SgiKa.d.ts +1847 -0
  41. package/dist/index-Ml_SgiKa.d.ts.map +1 -0
  42. package/dist/index-kHr9udZD.d.ts +1025 -0
  43. package/dist/index-kHr9udZD.d.ts.map +1 -0
  44. package/dist/index.d.ts +11 -0
  45. package/dist/index.js +15 -0
  46. package/dist/layout-Ca_4r8ka.js +89 -0
  47. package/dist/layout-Ca_4r8ka.js.map +1 -0
  48. package/dist/layout.d.ts +2 -0
  49. package/dist/layout.js +5 -0
  50. package/dist/list-CxfT6hix.js +6831 -0
  51. package/dist/list-CxfT6hix.js.map +1 -0
  52. package/dist/list.d.ts +2 -0
  53. package/dist/list.js +5 -0
  54. package/dist/media-DZ292aKK.js +557 -0
  55. package/dist/media-DZ292aKK.js.map +1 -0
  56. package/dist/media.d.ts +3 -0
  57. package/dist/media.js +3 -0
  58. package/dist/tree-Dd9Z0Aso.js +3351 -0
  59. package/dist/tree-Dd9Z0Aso.js.map +1 -0
  60. package/dist/tree.d.ts +2 -0
  61. package/dist/tree.js +6 -0
  62. package/dist/types-common-CB3kRek8.d.ts +26 -0
  63. package/dist/types-common-CB3kRek8.d.ts.map +1 -0
  64. package/dist/utils-B4fdKKsy.js +3 -0
  65. package/package.json +109 -0
  66. package/src/calendar/AgendaView.tsx +37 -0
  67. package/src/calendar/CalendarBrowser.tsx +90 -0
  68. package/src/calendar/CalendarModel.ts +142 -0
  69. package/src/calendar/CalendarSidebar.tsx +81 -0
  70. package/src/calendar/DayView.tsx +76 -0
  71. package/src/calendar/EventCard.tsx +51 -0
  72. package/src/calendar/MockCalendarProvider.ts +98 -0
  73. package/src/calendar/MonthView.tsx +77 -0
  74. package/src/calendar/WeekView.tsx +129 -0
  75. package/src/calendar/index.ts +18 -0
  76. package/src/calendar/types.ts +25 -0
  77. package/src/contacts/ContactAvatar.tsx +35 -0
  78. package/src/contacts/ContactBrowser.tsx +56 -0
  79. package/src/contacts/ContactCard.tsx +37 -0
  80. package/src/contacts/ContactDetail.tsx +63 -0
  81. package/src/contacts/ContactGroupSidebar.tsx +40 -0
  82. package/src/contacts/ContactList.tsx +32 -0
  83. package/src/contacts/ContactListModel.ts +120 -0
  84. package/src/contacts/MockContactProvider.ts +77 -0
  85. package/src/contacts/index.ts +17 -0
  86. package/src/contacts/types.ts +26 -0
  87. package/src/demos/CalendarBrowserDemo.tsx +15 -0
  88. package/src/demos/ContactBrowserDemo.tsx +15 -0
  89. package/src/demos/MediaBrowserDemo.tsx +15 -0
  90. package/src/file-browser/adapters/DocumentViewerAdapter.ts +371 -0
  91. package/src/file-browser/adapters/FileSystemBridge.ts +168 -0
  92. package/src/file-browser/adapters/GitBrowserAdapter.ts +546 -0
  93. package/src/file-browser/adapters/README.md +504 -0
  94. package/src/file-browser/adapters/index.ts +27 -0
  95. package/src/file-browser/adapters/types.ts +70 -0
  96. package/src/file-browser/architecture.md +645 -0
  97. package/src/file-browser/components/CreateItemDialog.tsx +71 -0
  98. package/src/file-browser/components/DeleteConfirmDialog.tsx +58 -0
  99. package/src/file-browser/components/FileBrowser.tsx +473 -0
  100. package/src/file-browser/components/FileBrowserContent.tsx +209 -0
  101. package/src/file-browser/components/FileBrowserHeader.tsx +151 -0
  102. package/src/file-browser/components/FileBrowserToolbar.tsx +145 -0
  103. package/src/file-browser/components/LeftPanel/LeftPanel.tsx +103 -0
  104. package/src/file-browser/components/LeftPanel/LeftPanelTabs.tsx +70 -0
  105. package/src/file-browser/components/LeftPanel/TreeNavigationView.tsx +256 -0
  106. package/src/file-browser/components/PreviewPane.tsx +146 -0
  107. package/src/file-browser/components/RightPanel/FilePreview.tsx +219 -0
  108. package/src/file-browser/components/RightPanel/RightPanel.tsx +186 -0
  109. package/src/file-browser/components/RightPanel/RightPanelToolbar.tsx +113 -0
  110. package/src/file-browser/components/UploadProgress.tsx +123 -0
  111. package/src/file-browser/components/ViewerHost.tsx +208 -0
  112. package/src/file-browser/components/mobile/MobileNavigation.tsx +227 -0
  113. package/src/file-browser/components/navigation/NavigationButtons.tsx +171 -0
  114. package/src/file-browser/components/shared/ErrorBoundary.tsx +116 -0
  115. package/src/file-browser/components/shared/FileBrowserItem.tsx +195 -0
  116. package/src/file-browser/components/shared/FileIcon.tsx +169 -0
  117. package/src/file-browser/components/toolbar/ViewModeToggle.tsx +200 -0
  118. package/src/file-browser/components/views/ListView/ListView.tsx +484 -0
  119. package/src/file-browser/components/views/ThumbnailView/ThumbnailView.tsx +323 -0
  120. package/src/file-browser/components/views/TreeView/TreeNode.tsx +186 -0
  121. package/src/file-browser/components/views/TreeView/TreeNodeList.tsx +191 -0
  122. package/src/file-browser/components/views/TreeView/TreeView.tsx +200 -0
  123. package/src/file-browser/components/views/TreemapView/TreemapView.tsx +339 -0
  124. package/src/file-browser/context/FileBrowserContext.tsx +13 -0
  125. package/src/file-browser/examples/BasicUsage.tsx +20 -0
  126. package/src/file-browser/index.ts +98 -0
  127. package/src/file-browser/models/FileBrowserModel.ts +623 -0
  128. package/src/file-browser/models/LeftPanelManagerModel.ts +105 -0
  129. package/src/file-browser/models/NavigationManagerModel.ts +312 -0
  130. package/src/file-browser/models/ResponsiveLayoutManagerModel.ts +437 -0
  131. package/src/file-browser/models/RightPanelManagerModel.ts +190 -0
  132. package/src/file-browser/models/SelectionManagerModel.ts +252 -0
  133. package/src/file-browser/models/ToolbarManagerModel.ts +144 -0
  134. package/src/file-browser/models/UploadModel.ts +147 -0
  135. package/src/file-browser/models/ViewModeManagerModel.ts +185 -0
  136. package/src/file-browser/models/ViewerHostModel.ts +44 -0
  137. package/src/file-browser/models/ui/ListViewUIModel.ts +265 -0
  138. package/src/file-browser/models/ui/PreviewUIModel.ts +297 -0
  139. package/src/file-browser/models/ui/ThumbnailViewUIModel.ts +254 -0
  140. package/src/file-browser/models/ui/TreeViewUIModel.ts +128 -0
  141. package/src/file-browser/models/ui/TreemapViewUIModel.ts +350 -0
  142. package/src/file-browser/providers/FileSystemListProvider.ts +552 -0
  143. package/src/file-browser/providers/FileSystemProvider.ts +401 -0
  144. package/src/file-browser/providers/FileSystemTreeProvider.ts +231 -0
  145. package/src/file-browser/providers/GitProvider.ts +337 -0
  146. package/src/file-browser/providers/GitRepositoryProvider.ts +376 -0
  147. package/src/file-browser/providers/IFileBrowserProvider.ts +56 -0
  148. package/src/file-browser/providers/MemoryProvider.ts +303 -0
  149. package/src/file-browser/providers/index.ts +4 -0
  150. package/src/file-browser/registry/ViewerRegistry.ts +551 -0
  151. package/src/file-browser/registry/types.ts +144 -0
  152. package/src/file-browser/scripts/performanceBenchmark.ts +553 -0
  153. package/src/file-browser/services/ThumbnailCacheService.ts +128 -0
  154. package/src/file-browser/tasks.md +537 -0
  155. package/src/file-browser/types/FileBrowserTypes.ts +126 -0
  156. package/src/file-browser/types/ProviderTypes.ts +155 -0
  157. package/src/file-browser/types/UITypes.ts +235 -0
  158. package/src/file-browser/types/ViewModeTypes.ts +150 -0
  159. package/src/file-browser/utils/gestures.ts +327 -0
  160. package/src/file-browser/utils/performance.ts +563 -0
  161. package/src/file-browser/viewers/ImageViewer.tsx +163 -0
  162. package/src/file-browser/viewers/ImageViewerModel.ts +79 -0
  163. package/src/file-browser/viewers/TextViewer.tsx +95 -0
  164. package/src/file-browser/viewers/UnsupportedFileViewer.tsx +57 -0
  165. package/src/file-browser/viewers/index.ts +61 -0
  166. package/src/git/BranchList.tsx +128 -0
  167. package/src/git/CommitGraph.tsx +239 -0
  168. package/src/git/CommitList.tsx +258 -0
  169. package/src/git/DiffViewer.tsx +219 -0
  170. package/src/git/index.ts +4 -0
  171. package/src/icons/iconMap.ts +146 -0
  172. package/src/icons/index.ts +9 -0
  173. package/src/index.ts +13 -0
  174. package/src/layout/README.md +307 -0
  175. package/src/layout/components/ExplorerLayout/ExplorerLayout.tsx +178 -0
  176. package/src/layout/examples/SimpleExample.tsx +60 -0
  177. package/src/layout/index.ts +6 -0
  178. package/src/lib/utils.ts +1 -0
  179. package/src/list/README.md +303 -0
  180. package/src/list/architecture.md +807 -0
  181. package/src/list/components/CalculatedGridView.tsx +252 -0
  182. package/src/list/components/DragPreview.tsx +102 -0
  183. package/src/list/components/ListContextMenu.tsx +274 -0
  184. package/src/list/components/ListItem.tsx +761 -0
  185. package/src/list/components/ListItems.tsx +919 -0
  186. package/src/list/components/MasonryView.tsx +241 -0
  187. package/src/list/components/SearchFilter.tsx +44 -0
  188. package/src/list/components/TreemapView.tsx +709 -0
  189. package/src/list/components/ViewSizeControls.tsx +205 -0
  190. package/src/list/components/ViewTypeSelector.tsx +312 -0
  191. package/src/list/components/VirtualizedDetailsView.tsx +231 -0
  192. package/src/list/components/VirtualizedGrid.tsx +164 -0
  193. package/src/list/components/VirtualizedList.tsx +154 -0
  194. package/src/list/components/VirtualizedMasonryView.tsx +344 -0
  195. package/src/list/components/shared/EmptyState.tsx +103 -0
  196. package/src/list/components/shared/ErrorBoundary.tsx +123 -0
  197. package/src/list/components/shared/ErrorDisplay.tsx +100 -0
  198. package/src/list/components/shared/ListLoader.tsx +146 -0
  199. package/src/list/components/shared/LoadingIndicator.tsx +80 -0
  200. package/src/list/index.ts +92 -0
  201. package/src/list/models/ListItemsModel.ts +1301 -0
  202. package/src/list/models/TreemapModel.ts +204 -0
  203. package/src/list/providers/ListItemsProvider.ts +313 -0
  204. package/src/list/providers/TestListProvider.ts +604 -0
  205. package/src/list/tasks.md +937 -0
  206. package/src/list/types/ListTypes.ts +178 -0
  207. package/src/list/utils/BenchmarkLogger.ts +243 -0
  208. package/src/list/utils/DragDropManager.ts +320 -0
  209. package/src/list/utils/GridLayoutCalculator.ts +290 -0
  210. package/src/list/utils/ListAccessibility.ts +367 -0
  211. package/src/list/utils/ListKeyboard.ts +414 -0
  212. package/src/list/utils/MasonryLayoutCalculator.ts +302 -0
  213. package/src/list/utils/MasonryLayoutEngine.ts +401 -0
  214. package/src/list/utils/__tests__/MasonryLayoutEngine.test.ts +157 -0
  215. package/src/list/utils/__tests__/VirtualizedMasonryView.test.tsx +251 -0
  216. package/src/media/AlbumSidebar.tsx +48 -0
  217. package/src/media/MediaBrowser.tsx +92 -0
  218. package/src/media/MediaBrowserModel.ts +138 -0
  219. package/src/media/MediaGrid.tsx +50 -0
  220. package/src/media/MediaList.tsx +49 -0
  221. package/src/media/MediaPreview.tsx +63 -0
  222. package/src/media/MediaTimeline.tsx +38 -0
  223. package/src/media/MockMediaProvider.ts +70 -0
  224. package/src/media/index.ts +18 -0
  225. package/src/media/types.ts +21 -0
  226. package/src/styles/variables.css +60 -0
  227. package/src/tree/DEVELOPMENT_SUMMARY.md +170 -0
  228. package/src/tree/__tests__/TreeModel.test.ts +16 -0
  229. package/src/tree/architecture.md +530 -0
  230. package/src/tree/components/Tree.tsx +283 -0
  231. package/src/tree/components/TreeCheckbox.tsx +147 -0
  232. package/src/tree/components/TreeContextMenu.tsx +139 -0
  233. package/src/tree/components/TreeNodeList.tsx +329 -0
  234. package/src/tree/components/TreeTable.tsx +382 -0
  235. package/src/tree/index.ts +58 -0
  236. package/src/tree/models/TreeModel.ts +839 -0
  237. package/src/tree/providers/SimpleTreeProvider.ts +463 -0
  238. package/src/tree/providers/TestTreeProvider.ts +946 -0
  239. package/src/tree/providers/TreeProvider.ts +308 -0
  240. package/src/tree/tasks.md +2046 -0
  241. package/src/tree/types/TreeTypes.ts +279 -0
  242. package/src/tree/utils/SelectionTheme.ts +150 -0
  243. package/src/tree/utils/logger.ts +203 -0
  244. package/src/types-common.ts +21 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-browser-m5atC3kF.js","names":["fileSystem: IFileSystem","path: string","stats: Stats | null","onProgress?: (progress: ScanProgress) => void","_progress?: ScanProgress","item: FileSystemItem","content: Buffer | string","isDirectory: boolean","oldPath: string","newPath: string","bridge: FileSystemBridge","options: FileSystemTreeProviderOptions","selectionInfo: TreeSelectionInfo","options?: TreeLoadOptions","nodes: TreeNodeData[]","node: TreeNodeData","childNodes: TreeNodeData[]","path?: string","parentNode?: TreeNodeData","expanded: boolean","node: TreeNodeData | null","menuItemId: string","parentPath: string","type: 'file' | 'folder'","path: string","newName: string","targets: Array<{ path: string; isDirectory: boolean }>","name: string","dbPromise: Promise<IDBPDatabase> | null","serviceId: string","path: string","data: ArrayBuffer","mime: string","aspectRatio: number","entry: CachedThumbnail","bridge: FileSystemBridge","options: FileSystemListProviderOptions","selectionInfo: ListSelectionInfo","item: ListItemData","menuItemId: string","items: ListItemData[]","path: string","mimeMap: Record<string, string>","options?: ListLoadOptions","allItems: ListItemData[]","start: number","end: number","viewType: ListViewType","onProgress?: (progress: import('../../list/providers/ListItemsProvider').TreemapScanProgress) => void","fsItems: FileSystemItem[]","listener: ListItemsProviderListener","baseMenu: ListContextMenuItem[]","menu: ListContextMenuItem[]","draggedItems: ListItemData[]","targetItem: ListItemData | null","position: 'before' | 'after' | 'inside'","event: DragEvent","dragDropInfo: ListDragDropInfo","success: boolean","item: FileSystemItem","filename: string","parentPath: string","type: 'file' | 'folder'","newName: string","targets: Array<{ path: string; isDirectory: boolean }>","name: string","config: ViewerConfig","plugin: FileViewerPlugin","filename: string","pattern: string","pluginId: string","file: FileMatchContext","options?: { preferEditable?: boolean }","opts?: { path?: string; mimeType?: string; size?: number }","ctx: FileMatchContext","viewerId: string","id: string","scored: Array<{ plugin: FileViewerPlugin; score: number }>","TextViewer: React.FC<ViewerProps>","scaler: Scaler","filePath: string","img: HTMLImageElement","MIME_MAP: Record<string, string>","buffer: ArrayBuffer","mime: string","content: string | ArrayBuffer","name: string","mimeType?: string","ImageViewer: React.FC<ViewerProps>","UnsupportedFileViewer: React.FC<ViewerProps>","bridge: FileSystemBridge","notify?: (type: 'success' | 'error' | 'warning', message: string) => void","fileList: FileList | File[]","targetDirectory: string","buffer: ArrayBuffer","fileSystem: IFileSystem","path: string","selectedItems: ListItemData[]","type: 'success' | 'error' | 'warning'","message: string","nodes: TreeNodeData[]","name: string","size?: number","viewer: ViewerConfig","content: string | ArrayBuffer | undefined","files: FileList | File[]","itemId: string","currentName: string","source: 'list' | 'tree'","newName: string","targets: Array<{ path: string; isDirectory: boolean; name: string }>","parentPath: string","type: 'file' | 'folder'","DeleteConfirmDialog: React.FC<DeleteConfirmDialogProps>","CreateItemDialog: React.FC<CreateItemDialogProps>","e: React.KeyboardEvent","UploadProgress: React.FC<UploadProgressProps>","dirty: boolean","extras: React.ReactNode","loading: boolean","error: string | null","ViewerLoadingFallback: React.FC<{ name: string }>","ToolbarActionButton: React.FC<{ action: ToolbarAction }>","ViewerHost: React.FC<ViewerHostProps>","e: KeyboardEvent","isDirty: boolean","extras: React.ReactNode","viewerProps: ViewerProps","shortcutKey: string","PreviewPane: React.FC<PreviewPaneProps>","pluginId: string","PreviewHeader: React.FC<{\n name: string;\n size?: number;\n icon?: 'text' | 'image' | 'unknown';\n}>","FileBrowser: React.FC<FileBrowserProps>","e: React.DragEvent","e: KeyboardEvent","path: string","newName: string","lucideIconMap: Record<string, LucideIcon>","item: FileBrowserItem","isExpanded?: boolean","FileIcon: React.FC<FileIconProps>","iconDefinition: IconDefinition | undefined","IconComponent: LucideIcon","FileBrowserItemComponent: React.FC<FileBrowserItemProps>","event: React.MouseEvent","event: React.KeyboardEvent","bytes?: number","date?: Date | string","props: ErrorBoundaryProps","error: Error","errorInfo: React.ErrorInfo","fileSystem: IFileSystem","cacheOptions?: Partial<CacheOptions>","path: string","mode: number | undefined","error: any","operation: string","basePath: string","relativePath: string","item: FileBrowserItem","iconMap: Record<string, string>","action: string","items: FileBrowserItem[]","data: FileBrowserItem[]","oldestPath: string | null","message: string","options: GitRepositoryOptions","path: string","item: FileBrowserItem","items: FileBrowserItem[]","basePath: string","relativePath: string","result: IconDefinition","ext?: string","iconMap: Record<string, string>","statusIndicators: Record<string, string>","action: string","branch: string","path?: string","options: { path?: string; maxCount?: number }","mockFiles: Record<string, GitFileInfo[]>","file: GitFileInfo","message: string","repository: GitRepositoryModel | GitWrapperIntegration","path: string","fileTree: GitFileTreeNode[]","node: GitFileTreeNode","basePath: string","relativePath: string","item: FileBrowserItem","action: string","items: FileBrowserItem[]","owner: SelectionOwner","itemId: string","startItemId: string","endItemId: string","allItems: FileBrowserItem[]","items: FileBrowserItem[]","item: FileBrowserItem | null","item: FileBrowserItem","path: string","owner: NavigationOwner","path: string","currentPath: string","resolvedSegments: string[]","source: 'tree' | 'right' | 'breadcrumb' | 'history'","selectionManager: any","owner: ToolbarOwner","action: ToolbarAction","actionId: string","updates: Partial<ToolbarAction>","action: ContextAction","context: ActionContext","actions: ToolbarAction[]","actions: ContextAction[]","owner: any","path: string","item: FileBrowserItem","nodes: FileBrowserItem[]","newSettings: Partial<TreeViewSettings>","owner: ListViewOwner","column: ColumnDefinition","columnId: string","updates: Partial<ColumnDefinition>","width: number","fromIndex: number","toIndex: number","field: string","direction: 'asc' | 'desc'","newSettings: Partial<ListViewSettings>","name: string","defaultColumns: ColumnDefinition[]","value: number","value: Date","owner: ThumbnailOwner","size: number","spacing: number","ratio: number","columns: number | 'auto'","quality: 'low' | 'medium' | 'high'","itemId: string","loading: boolean","containerWidth: number","newSettings: Partial<ThumbnailViewSettings>","preset: 'compact' | 'balanced' | 'detailed'","owner: TreemapOwner","size: number","depth: number","scheme: 'type' | 'size' | 'date' | 'custom'","padding: number","level: number","nodeId: string","items: FileBrowserItem[]","width: number","height: number","item: FileBrowserItem","extension: string","colorMap: Record<string, string>","nodes: TreemapNode[]","newSettings: Partial<TreemapViewSettings>","preset: 'overview' | 'detailed' | 'interactive'","owner: any","viewModeId: string","definition: ViewModeDefinition","key: keyof FilterCriteria","value: any","field: string","direction: 'asc' | 'desc'","capability: string","FileBrowserHeader: React.FC<FileBrowserHeaderProps>","index: number","context: ActionContext","action: ToolbarAction","FileBrowserContent: React.FC<FileBrowserContentProps>","TreeViewPlaceholder: React.FC<{ model: FileBrowserModel }>","ListViewPlaceholder: React.FC<{ model: FileBrowserModel }>","ThumbnailViewPlaceholder: React.FC<{ model: FileBrowserModel }>","TreeNode: React.FC<TreeNodeProps>","e: React.MouseEvent","e: React.KeyboardEvent","TreeNodeList: React.FC<TreeNodeListProps>","result: TreeNodeFlat[]","items: FileBrowserItem[]","item: FileBrowserItem","e: React.KeyboardEvent","currentIndex: number","TreeView: React.FC<TreeViewProps>","items: FileBrowserItem[]","rootItems: FileBrowserItem[]","item: FileBrowserItem","folderPath: string","e: React.KeyboardEvent","ListViewHeader: React.FC<{\n columns: ColumnDefinition[];\n listModel: ListViewUIModel;\n className?: string;\n}>","column: ColumnDefinition","columnId: string","newWidth: number","MobileListViewRow: React.FC<{\n item: FileBrowserItem;\n isSelected: boolean;\n isFocused: boolean;\n onItemClick?: (item: FileBrowserItem) => void;\n onItemDoubleClick?: (item: FileBrowserItem) => void;\n getItemIcon?: (item: FileBrowserItem) => any;\n index: number;\n}>","size: number","date: Date","ListViewRow: React.FC<{\n item: FileBrowserItem;\n columns: ColumnDefinition[];\n isSelected: boolean;\n isFocused: boolean;\n onItemClick?: (item: FileBrowserItem) => void;\n onItemDoubleClick?: (item: FileBrowserItem) => void;\n getItemIcon?: (item: FileBrowserItem) => any;\n striped?: boolean;\n index: number;\n}>","e: React.KeyboardEvent","ListView: React.FC<ListViewProps>","item: FileBrowserItem","NavigationButton: React.FC<NavigationButtonProps>","NavigationButtons: React.FC<NavigationButtonsProps>","e: KeyboardEvent","VIEW_MODE_OPTIONS: Partial<Record<ViewModeType, ViewModeOption>>","ViewModeToggle: React.FC<ViewModeToggleProps>","mode: ViewModeType","e: React.KeyboardEvent","nextIndex: number","e: KeyboardEvent","modeOption: ViewModeOption","index: number"],"sources":["../src/file-browser/adapters/FileSystemBridge.ts","../src/file-browser/providers/FileSystemTreeProvider.ts","../src/file-browser/services/ThumbnailCacheService.ts","../src/file-browser/providers/FileSystemListProvider.ts","../src/file-browser/registry/ViewerRegistry.ts","../src/file-browser/viewers/TextViewer.tsx","../src/file-browser/viewers/ImageViewerModel.ts","../src/file-browser/viewers/ImageViewer.tsx","../src/file-browser/viewers/UnsupportedFileViewer.tsx","../src/file-browser/viewers/index.ts","../src/file-browser/models/UploadModel.ts","../src/file-browser/models/FileBrowserModel.ts","../src/file-browser/components/DeleteConfirmDialog.tsx","../src/file-browser/components/CreateItemDialog.tsx","../src/file-browser/components/UploadProgress.tsx","../src/file-browser/models/ViewerHostModel.ts","../src/file-browser/components/ViewerHost.tsx","../src/file-browser/components/PreviewPane.tsx","../src/file-browser/components/FileBrowser.tsx","../src/file-browser/components/shared/FileIcon.tsx","../src/file-browser/components/shared/FileBrowserItem.tsx","../src/file-browser/components/shared/ErrorBoundary.tsx","../src/file-browser/providers/FileSystemProvider.ts","../src/file-browser/providers/GitRepositoryProvider.ts","../src/file-browser/providers/GitProvider.ts","../src/file-browser/models/SelectionManagerModel.ts","../src/file-browser/models/NavigationManagerModel.ts","../src/file-browser/models/ToolbarManagerModel.ts","../src/file-browser/models/ui/TreeViewUIModel.ts","../src/file-browser/models/ui/ListViewUIModel.ts","../src/file-browser/models/ui/ThumbnailViewUIModel.ts","../src/file-browser/models/ui/TreemapViewUIModel.ts","../src/file-browser/models/ViewModeManagerModel.ts","../src/file-browser/components/FileBrowserHeader.tsx","../src/file-browser/components/FileBrowserContent.tsx","../src/file-browser/components/views/TreeView/TreeNode.tsx","../src/file-browser/components/views/TreeView/TreeNodeList.tsx","../src/file-browser/components/views/TreeView/TreeView.tsx","../src/file-browser/components/views/ListView/ListView.tsx","../src/file-browser/components/navigation/NavigationButtons.tsx","../src/file-browser/components/toolbar/ViewModeToggle.tsx"],"sourcesContent":["import { makeAutoObservable } from 'mobx';\nimport type { IFileSystem, Dirent, Stats } from '@anymux/file-system';\n\nexport interface ScanProgress {\n directoriesScanned: number;\n filesFound: number;\n totalSize: number;\n}\n\nexport interface FileSystemItem {\n id: string;\n path: string;\n name: string;\n type: 'file' | 'directory';\n size?: number;\n modified?: Date;\n isDirectory: boolean;\n children?: FileSystemItem[];\n}\n\nexport class FileSystemBridge {\n constructor(private fileSystem: IFileSystem) {\n makeAutoObservable(this, {\n fileSystem: false,\n });\n }\n\n // Tree operations (directories only)\n async loadDirectoryTree(path: string): Promise<FileSystemItem[]> {\n const dirents = await this.fileSystem.readdir(path, { withFileTypes: true });\n\n return dirents\n .filter(dirent => dirent.isDirectory())\n .map(dirent => ({\n id: `${path}/${dirent.name}`.replace(/\\/\\//g, '/'),\n path: `${path}/${dirent.name}`.replace(/\\/\\//g, '/'),\n name: dirent.name,\n type: 'directory' as const,\n isDirectory: true\n }));\n }\n\n // List operations (all items)\n async loadDirectoryContents(path: string): Promise<FileSystemItem[]> {\n const dirents = await this.fileSystem.readdir(path, { withFileTypes: true });\n\n const items = await Promise.all(\n dirents.map(async (dirent) => {\n const itemPath = `${path}/${dirent.name}`.replace(/\\/\\//g, '/');\n let stats: Stats | null = null;\n\n try {\n stats = await this.fileSystem.stat(itemPath);\n } catch (err) {\n console.warn(`[FileSystemBridge] stat failed for ${itemPath}:`, err instanceof Error ? err.message : err);\n }\n\n return {\n id: itemPath,\n path: itemPath,\n name: dirent.name,\n type: dirent.isDirectory() ? 'directory' as const : 'file' as const,\n size: stats?.size,\n modified: stats?.mtime,\n isDirectory: dirent.isDirectory()\n };\n })\n );\n\n // Sort: directories first, then files, both alphabetically\n return items.sort((a, b) => {\n if (a.type !== b.type) {\n return a.type === 'directory' ? -1 : 1;\n }\n return a.name.localeCompare(b.name);\n });\n }\n\n // Recursive directory scan for treemap — returns nested FileSystemItem tree\n async loadDirectoryRecursive(\n path: string,\n maxDepth = 3,\n onProgress?: (progress: ScanProgress) => void,\n _progress?: ScanProgress,\n ): Promise<FileSystemItem[]> {\n const progress = _progress ?? { directoriesScanned: 0, filesFound: 0, totalSize: 0 };\n const dirents = await this.fileSystem.readdir(path, { withFileTypes: true });\n\n const items = await Promise.all(\n dirents.map(async (dirent) => {\n const itemPath = `${path}/${dirent.name}`.replace(/\\/\\//g, '/');\n const isDir = dirent.isDirectory();\n let stats: Stats | null = null;\n\n try {\n stats = await this.fileSystem.stat(itemPath);\n } catch {\n // skip stat errors\n }\n\n if (isDir) {\n progress.directoriesScanned++;\n } else {\n progress.filesFound++;\n if (stats?.size) progress.totalSize += stats.size;\n }\n onProgress?.(progress);\n\n const item: FileSystemItem = {\n id: itemPath,\n path: itemPath,\n name: dirent.name,\n type: isDir ? 'directory' : 'file',\n size: stats?.size,\n modified: stats?.mtime,\n isDirectory: isDir,\n };\n\n // Recursively load subdirectories\n if (isDir && maxDepth > 0) {\n try {\n item.children = await this.loadDirectoryRecursive(itemPath, maxDepth - 1, onProgress, progress);\n } catch {\n item.children = [];\n }\n }\n\n return item;\n })\n );\n\n return items;\n }\n\n // File operations\n async readFile(path: string): Promise<Buffer | string> {\n return this.fileSystem.readFile(path);\n }\n\n async writeFile(path: string, content: Buffer | string): Promise<void> {\n return this.fileSystem.writeFile(path, content);\n }\n\n async deleteItem(path: string, isDirectory: boolean): Promise<void> {\n if (isDirectory) {\n return this.fileSystem.rmdir(path, { recursive: true });\n } else {\n return this.fileSystem.unlink(path);\n }\n }\n\n async createDirectory(path: string): Promise<void> {\n await this.fileSystem.mkdir(path, { recursive: true });\n }\n\n async renameItem(oldPath: string, newPath: string): Promise<void> {\n return this.fileSystem.rename(oldPath, newPath);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n await this.fileSystem.access(path);\n return true;\n } catch {\n return false;\n }\n }\n}\n","import { makeAutoObservable } from 'mobx';\nimport type { TreeProvider, TreeSelectionInfo } from '../../tree/providers/TreeProvider';\nimport type { TreeNodeData, TreeLoadOptions, TreeLoadResult, TreeContextMenuItem } from '../../tree/types/TreeTypes';\nimport { FileSystemBridge, type FileSystemItem } from '../adapters/FileSystemBridge';\n\ninterface FileSystemTreeProviderOptions {\n showFilesInTree: boolean;\n onSelectionChange: (path: string) => void;\n onRefresh?: () => Promise<void>;\n onRenameRequest?: (itemId: string, currentName: string, path: string, source: 'list' | 'tree') => void;\n onDeleteRequest?: (targets: Array<{ path: string; isDirectory: boolean; name: string }>) => void;\n onNewItemRequest?: (parentPath: string, type: 'file' | 'folder') => void;\n}\n\nexport class FileSystemTreeProvider implements TreeProvider {\n readonly id = 'filesystem-tree';\n readonly name = 'File System Tree';\n readonly version = '1.0.0';\n\n isMultiSelectEnabled = false;\n readonly isDragDropEnabled = true;\n readonly isVirtualizationEnabled = false;\n readonly useCheckboxSelection = false;\n readonly allowPartialSelection = false;\n readonly isTableViewEnabled = false;\n\n constructor(\n private bridge: FileSystemBridge,\n private options: FileSystemTreeProviderOptions\n ) {\n makeAutoObservable(this, {});\n }\n\n async loadNodes(options?: TreeLoadOptions): Promise<TreeLoadResult> {\n const rootItems = await this.bridge.loadDirectoryTree('/');\n\n const nodes: TreeNodeData[] = rootItems.map(item => ({\n id: item.id,\n name: item.name,\n path: item.path,\n type: 'directory',\n hasChildren: true,\n isExpanded: false,\n metadata: item\n }));\n\n return {\n nodes,\n totalCount: nodes.length\n };\n }\n\n async loadChildren(node: TreeNodeData, options?: TreeLoadOptions): Promise<TreeLoadResult> {\n try {\n const items = await this.bridge.loadDirectoryTree(node.path);\n\n const childNodes: TreeNodeData[] = items.map(item => ({\n id: item.id,\n name: item.name,\n path: item.path,\n type: 'directory',\n hasChildren: true,\n isExpanded: false,\n metadata: item\n }));\n\n return {\n nodes: childNodes,\n totalCount: childNodes.length\n };\n } catch {\n return { nodes: [], totalCount: 0 };\n }\n }\n\n async refresh(path?: string): Promise<TreeLoadResult> {\n return this.loadNodes();\n }\n\n getNodeContextMenu(node: TreeNodeData): TreeContextMenuItem[] {\n return [\n {\n id: 'open',\n label: 'Open',\n icon: 'folder-open',\n type: 'item',\n handler: () => this.options.onSelectionChange(node.path)\n },\n { id: 'separator1', type: 'separator', label: '' },\n {\n id: 'new-folder',\n label: 'New Folder',\n icon: 'folder-plus',\n type: 'item',\n handler: () => this.requestNewItem(node.path, 'folder')\n },\n {\n id: 'new-file',\n label: 'New File',\n icon: 'file-plus',\n type: 'item',\n handler: () => this.requestNewItem(node.path, 'file')\n },\n { id: 'separator2', type: 'separator', label: '' },\n {\n id: 'rename',\n label: 'Rename',\n icon: 'edit',\n type: 'item',\n handler: () => this.requestRename(node)\n },\n {\n id: 'delete',\n label: 'Delete',\n icon: 'trash',\n type: 'item',\n handler: () => this.requestDelete([node])\n }\n ];\n }\n\n getMultiNodeContextMenu(nodes: TreeNodeData[]): TreeContextMenuItem[] {\n return [\n {\n id: 'delete-multiple',\n label: `Delete ${nodes.length} Folders`,\n icon: 'trash',\n type: 'item',\n handler: () => this.requestDelete(nodes)\n }\n ];\n }\n\n getEmptySpaceContextMenu(parentNode?: TreeNodeData): TreeContextMenuItem[] {\n const parentPath = parentNode?.path || '/';\n return [\n {\n id: 'new-folder',\n label: 'New Folder',\n icon: 'folder-plus',\n type: 'item',\n handler: () => this.requestNewItem(parentPath, 'folder')\n },\n {\n id: 'new-file',\n label: 'New File',\n icon: 'file-plus',\n type: 'item',\n handler: () => this.requestNewItem(parentPath, 'file')\n }\n ];\n }\n\n canExpand(node: TreeNodeData): boolean {\n return node.type === 'directory';\n }\n\n canSelect(node: TreeNodeData): boolean {\n return true;\n }\n\n onSelectionChange = (selectionInfo: TreeSelectionInfo) => {\n if (selectionInfo.selectedNodes.length > 0) {\n const selectedNode = selectionInfo.selectedNodes[0];\n if (selectedNode) {\n this.options.onSelectionChange(selectedNode.path);\n }\n }\n };\n\n onNodeExpansion?(node: TreeNodeData, expanded: boolean): void {}\n\n onNodeDoubleClick?(node: TreeNodeData): void {\n this.options.onSelectionChange(node.path);\n }\n\n onNodeFocus?(node: TreeNodeData | null): void {}\n\n onContextMenuAction?(menuItemId: string, nodes: TreeNodeData[]): void {}\n\n private requestRename(node: TreeNodeData) {\n if (this.options.onRenameRequest) {\n const currentName = node.path.split('/').pop() || '';\n this.options.onRenameRequest(node.id, currentName, node.path, 'tree');\n }\n }\n\n private requestDelete(nodes: TreeNodeData[]) {\n if (this.options.onDeleteRequest) {\n const targets = nodes.map(n => ({\n path: n.path,\n isDirectory: true,\n name: n.path.split('/').pop() || ''\n }));\n this.options.onDeleteRequest(targets);\n }\n }\n\n private requestNewItem(parentPath: string, type: 'file' | 'folder') {\n if (this.options.onNewItemRequest) {\n this.options.onNewItemRequest(parentPath, type);\n }\n }\n\n async executeRename(path: string, newName: string): Promise<void> {\n const parentPath = path.split('/').slice(0, -1).join('/') || '/';\n const newPath = `${parentPath}/${newName}`.replace(/\\/\\//g, '/');\n await this.bridge.renameItem(path, newPath);\n await this.options.onRefresh?.();\n }\n\n async executeDelete(targets: Array<{ path: string; isDirectory: boolean }>): Promise<void> {\n await Promise.all(targets.map(t =>\n this.bridge.deleteItem(t.path, t.isDirectory)\n ));\n await this.options.onRefresh?.();\n }\n\n async executeCreate(parentPath: string, name: string, type: 'file' | 'folder'): Promise<void> {\n const newPath = `${parentPath}/${name}`.replace(/\\/\\//g, '/');\n if (type === 'folder') {\n await this.bridge.createDirectory(newPath);\n } else {\n await this.bridge.writeFile(newPath, '');\n }\n await this.options.onRefresh?.();\n }\n\n async initialize?(): Promise<void> {}\n dispose?(): void {}\n}\n","import { openDB, type IDBPDatabase } from 'idb';\n\nconst DB_NAME = 'anymux-thumbnail-cache';\nconst DB_VERSION = 1;\nconst STORE_NAME = 'thumbnails';\n\ninterface CachedThumbnail {\n /** Composite key: serviceId + path */\n key: string;\n /** Raw image data */\n data: ArrayBuffer;\n /** MIME type */\n mime: string;\n /** Aspect ratio (width / height) */\n aspectRatio: number;\n /** Timestamp for cache eviction */\n cachedAt: number;\n}\n\n/** Max age for cached thumbnails (7 days) */\nconst MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;\n/** Max number of cached entries */\nconst MAX_ENTRIES = 2000;\n\nlet dbPromise: Promise<IDBPDatabase> | null = null;\n\nfunction getDB(): Promise<IDBPDatabase> {\n if (!dbPromise) {\n dbPromise = openDB(DB_NAME, DB_VERSION, {\n upgrade(db) {\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n const store = db.createObjectStore(STORE_NAME, { keyPath: 'key' });\n store.createIndex('cachedAt', 'cachedAt');\n }\n },\n });\n }\n return dbPromise;\n}\n\nfunction makeKey(serviceId: string, path: string): string {\n return `${serviceId}:${path}`;\n}\n\nexport const ThumbnailCacheService = {\n async get(serviceId: string, path: string): Promise<{ blobUrl: string; aspectRatio: number } | null> {\n try {\n const db = await getDB();\n const key = makeKey(serviceId, path);\n const entry = await db.get(STORE_NAME, key) as CachedThumbnail | undefined;\n if (!entry) return null;\n\n // Check expiry\n if (Date.now() - entry.cachedAt > MAX_AGE_MS) {\n await db.delete(STORE_NAME, key);\n return null;\n }\n\n const blob = new Blob([entry.data], { type: entry.mime });\n const blobUrl = URL.createObjectURL(blob);\n return { blobUrl, aspectRatio: entry.aspectRatio };\n } catch {\n return null;\n }\n },\n\n async put(serviceId: string, path: string, data: ArrayBuffer, mime: string, aspectRatio: number): Promise<void> {\n try {\n const db = await getDB();\n const entry: CachedThumbnail = {\n key: makeKey(serviceId, path),\n data,\n mime,\n aspectRatio,\n cachedAt: Date.now(),\n };\n await db.put(STORE_NAME, entry);\n } catch {\n // IndexedDB write failed — non-critical\n }\n },\n\n async evictOld(): Promise<void> {\n try {\n const db = await getDB();\n const tx = db.transaction(STORE_NAME, 'readwrite');\n const store = tx.objectStore(STORE_NAME);\n const index = store.index('cachedAt');\n const cutoff = Date.now() - MAX_AGE_MS;\n\n let cursor = await index.openCursor();\n while (cursor) {\n if ((cursor.value as CachedThumbnail).cachedAt < cutoff) {\n await cursor.delete();\n } else {\n break; // index is sorted by cachedAt, so all remaining are newer\n }\n cursor = await cursor.continue();\n }\n\n // Also enforce max entries\n const count = await store.count();\n if (count > MAX_ENTRIES) {\n const toDelete = count - MAX_ENTRIES;\n let deleteCursor = await index.openCursor();\n let deleted = 0;\n while (deleteCursor && deleted < toDelete) {\n await deleteCursor.delete();\n deleted++;\n deleteCursor = await deleteCursor.continue();\n }\n }\n\n await tx.done;\n } catch {\n // Eviction failed — non-critical\n }\n },\n\n async clear(): Promise<void> {\n try {\n const db = await getDB();\n await db.clear(STORE_NAME);\n } catch {\n // Clear failed\n }\n },\n};\n","import { makeAutoObservable, observable, runInAction } from 'mobx';\nimport type {\n ListItemsProvider,\n ListItemsProviderListener\n} from '../../list/providers/ListItemsProvider';\nimport type {\n ListItemData,\n ListLoadOptions,\n ListLoadResult,\n ListViewType,\n ListContextMenuItem,\n ListSelectionInfo,\n VirtualizationConfig,\n ListDragDropInfo\n} from '../../list/types/ListTypes';\nimport { LIST_VIEW_TYPE, GRID_VIEW_TYPE, DETAILS_VIEW_TYPE } from '../../list';\nimport { MASONRY_HORIZONTAL_VIEW_TYPE, MASONRY_VERTICAL_VIEW_TYPE, TREEMAP_VIEW_TYPE } from '../../list/providers/ListItemsProvider';\nimport { FileSystemBridge, type FileSystemItem } from '../adapters/FileSystemBridge';\nimport { getIconForFile } from '../../icons/iconMap';\nimport { ThumbnailCacheService } from '../services/ThumbnailCacheService';\n\ninterface FileSystemListProviderOptions {\n showAllItems: boolean;\n /** Service identifier for IndexedDB thumbnail cache key scoping */\n serviceId?: string;\n onSelectionChange: (items: ListItemData[]) => void;\n onNavigation: (path: string) => void;\n onNavigateUp?: () => void;\n onOpenFile?: (path: string, name: string, size?: number) => void;\n onPreviewFile?: (path: string, name: string, size?: number) => void;\n onRefresh?: () => Promise<void>;\n onRenameRequest?: (itemId: string, currentName: string, path: string, source: 'list' | 'tree') => void;\n onDeleteRequest?: (targets: Array<{ path: string; isDirectory: boolean; name: string }>) => void;\n onNewItemRequest?: (parentPath: string, type: 'file' | 'folder') => void;\n}\n\nexport class FileSystemListProvider implements ListItemsProvider {\n readonly id = 'filesystem-list';\n readonly name = 'File System List';\n readonly supportedViewTypes: ListViewType[] = [\n LIST_VIEW_TYPE,\n GRID_VIEW_TYPE,\n DETAILS_VIEW_TYPE,\n MASONRY_HORIZONTAL_VIEW_TYPE,\n MASONRY_VERTICAL_VIEW_TYPE,\n TREEMAP_VIEW_TYPE\n ];\n readonly isMultiSelectEnabled = true;\n readonly isVirtualizationEnabled = false;\n readonly isDragDropEnabled = true;\n\n currentPath: string = '/';\n private listeners: ListItemsProviderListener[] = [];\n\n // Thumbnail blob URL cache: path → blob URL\n thumbnailCache = observable.map<string, string>();\n // Aspect ratio cache: path → width/height ratio\n aspectRatioCache = observable.map<string, number>();\n // Track in-flight loads to avoid duplicate requests\n private thumbnailLoading = new Set<string>();\n\n constructor(\n private bridge: FileSystemBridge,\n private options: FileSystemListProviderOptions\n ) {\n makeAutoObservable(this, {\n bridge: false,\n options: false,\n listeners: false,\n thumbnailLoading: false,\n });\n // Evict expired IndexedDB thumbnails on startup (non-blocking)\n ThumbnailCacheService.evictOld();\n }\n\n /**\n * Get a cached thumbnail blob URL, or trigger async load if not cached.\n * Returns undefined while loading (MobX will re-render when cache updates).\n */\n getThumbnailBlobUrl(path: string): string | undefined {\n const cached = this.thumbnailCache.get(path);\n if (cached) return cached;\n\n // Start async load if not already loading\n if (!this.thumbnailLoading.has(path)) {\n this.thumbnailLoading.add(path);\n this.loadThumbnail(path);\n }\n return undefined;\n }\n\n private async loadThumbnail(path: string): Promise<void> {\n const serviceId = this.options.serviceId ?? 'default';\n try {\n // Try IndexedDB cache first\n const cached = await ThumbnailCacheService.get(serviceId, path);\n if (cached) {\n runInAction(() => {\n this.thumbnailCache.set(path, cached.blobUrl);\n this.aspectRatioCache.set(path, cached.aspectRatio);\n });\n return;\n }\n\n // Fall back to network load\n const content = await this.bridge.readFile(path);\n const ext = path.split('.').pop()?.toLowerCase() || '';\n const mimeMap: Record<string, string> = {\n jpg: 'image/jpeg', jpeg: 'image/jpeg', png: 'image/png',\n gif: 'image/gif', svg: 'image/svg+xml', webp: 'image/webp'\n };\n const mime = mimeMap[ext] || 'image/png';\n const rawData = typeof content === 'string' ? new TextEncoder().encode(content) : content;\n const blob = new Blob([rawData], { type: mime });\n const url = URL.createObjectURL(blob);\n runInAction(() => {\n this.thumbnailCache.set(path, url);\n });\n // Measure actual image dimensions for masonry aspect ratios\n const img = new Image();\n img.src = url;\n img.onload = () => {\n if (img.naturalWidth > 0 && img.naturalHeight > 0) {\n const aspectRatio = img.naturalWidth / img.naturalHeight;\n runInAction(() => {\n this.aspectRatioCache.set(path, aspectRatio);\n });\n // Persist to IndexedDB for future page loads\n const buffer = rawData instanceof ArrayBuffer ? rawData : (rawData as Uint8Array).buffer;\n ThumbnailCacheService.put(serviceId, path, buffer, mime, aspectRatio);\n }\n };\n } catch (error) {\n console.warn('Failed to load thumbnail:', path, error);\n } finally {\n this.thumbnailLoading.delete(path);\n }\n }\n\n /**\n * Get cached aspect ratio for an image path.\n * Returns undefined if not yet measured.\n */\n getAspectRatio(path: string): number | undefined {\n return this.aspectRatioCache.get(path);\n }\n\n /**\n * Revoke all cached blob URLs (call on path change / unmount)\n */\n clearThumbnailCache(): void {\n for (const url of this.thumbnailCache.values()) {\n URL.revokeObjectURL(url);\n }\n this.thumbnailCache.clear();\n this.aspectRatioCache.clear();\n this.thumbnailLoading.clear();\n }\n\n setPath(path: string) {\n this.currentPath = path;\n this.clearThumbnailCache();\n }\n\n async loadItems(options?: ListLoadOptions): Promise<ListLoadResult> {\n const items = await this.bridge.loadDirectoryContents(this.currentPath);\n\n const allItems: ListItemData[] = items.map(item => ({\n id: item.id,\n name: item.name,\n type: item.type,\n path: item.path,\n size: item.size,\n modified: item.modified,\n isDirectory: item.isDirectory,\n metadata: item,\n thumbnailUrl: this.getThumbnailUrl(item),\n icon: this.getFileIconString(item)\n }));\n\n const totalCount = allItems.length;\n const offset = options?.offset ?? 0;\n const limit = options?.limit ?? totalCount;\n const paginatedItems = allItems.slice(offset, offset + limit);\n\n return {\n items: paginatedItems,\n totalCount,\n hasMore: offset + limit < totalCount\n };\n }\n\n async getItemCount(): Promise<number> {\n const result = await this.loadItems();\n return result.totalCount || 0;\n }\n\n async loadItemRange(start: number, end: number): Promise<ListLoadResult> {\n const result = await this.loadItems();\n const rangeItems = result.items.slice(start, end);\n\n return {\n items: rangeItems,\n totalCount: result.totalCount\n };\n }\n\n async refresh(): Promise<ListLoadResult> {\n const result = await this.loadItems();\n this.listeners.forEach(listener => {\n listener.onItemsCountChanged(result.totalCount || 0);\n });\n return result;\n }\n\n getItemHeight(viewType: ListViewType): number {\n switch (viewType.id) {\n case 'list': return 32;\n case 'grid': return 200;\n case 'details': return 32;\n case 'masonry-horizontal': return 160;\n default: return 40;\n }\n }\n\n getItemWidth(viewType: ListViewType): number {\n switch (viewType.id) {\n case 'grid': return 240;\n case 'masonry-horizontal': return 200;\n default: return 0;\n }\n }\n\n getVirtualizationConfig(): VirtualizationConfig {\n return {\n itemHeight: 40,\n overscan: 5,\n threshold: 50\n };\n }\n\n onSelectionChange = (selectionInfo: ListSelectionInfo) => {\n this.options.onSelectionChange(selectionInfo.selectedItems);\n\n // Trigger preview on single file selection\n if (\n selectionInfo.selectedItems.length === 1 &&\n selectionInfo.selectionType === 'single' &&\n this.options.onPreviewFile\n ) {\n const item = selectionInfo.selectedItems[0]!;\n if (!item.isDirectory) {\n const fsItem = item.metadata as FileSystemItem;\n this.options.onPreviewFile(item.path, fsItem.name, fsItem.size);\n }\n }\n };\n\n onViewTypeChange?(viewType: ListViewType): void {}\n\n async loadTreemapData(onProgress?: (progress: import('../../list/providers/ListItemsProvider').TreemapScanProgress) => void) {\n const items = await this.bridge.loadDirectoryRecursive(this.currentPath, 3, onProgress);\n const convert = (fsItems: FileSystemItem[]): import('../../list/providers/ListItemsProvider').TreemapNodeData[] =>\n fsItems.map(item => ({\n name: item.name,\n path: item.path,\n size: item.size,\n isDirectory: item.isDirectory,\n children: item.children ? convert(item.children) : undefined,\n }));\n return convert(items);\n }\n\n onItemDoubleClick = (item: ListItemData) => {\n if (item.isDirectory) {\n this.options.onNavigation(item.path);\n } else {\n this.openFileWithViewer(item);\n }\n };\n\n addListener(listener: ListItemsProviderListener): void {\n this.listeners.push(listener);\n }\n\n removeListener(listener: ListItemsProviderListener): void {\n const index = this.listeners.indexOf(listener);\n if (index >= 0) {\n this.listeners.splice(index, 1);\n }\n }\n\n getItemIcon(item: ListItemData): string {\n const fsItem = item.metadata as FileSystemItem;\n return this.getFileIconString(fsItem);\n }\n\n getItemContextMenu(item: ListItemData): ListContextMenuItem[] {\n const baseMenu: ListContextMenuItem[] = [\n {\n id: 'open',\n label: item.isDirectory ? 'Open Folder' : 'Open',\n icon: item.isDirectory ? 'folder-open' : 'eye',\n type: 'item'\n }\n ];\n\n if (!item.isDirectory) {\n baseMenu.push(\n { id: 'separator1', type: 'separator', label: '' },\n { id: 'download', label: 'Download', icon: 'download', type: 'item' }\n );\n }\n\n if (item.isDirectory) {\n baseMenu.push(\n { id: 'separator-new', type: 'separator', label: '' },\n { id: 'new-folder', label: 'New Folder', icon: 'folder-plus', type: 'item' },\n { id: 'new-file', label: 'New File', icon: 'file-plus', type: 'item' }\n );\n }\n\n baseMenu.push(\n { id: 'separator2', type: 'separator', label: '' },\n { id: 'copy-path', label: 'Copy Path', icon: 'copy', type: 'item' },\n { id: 'rename', label: 'Rename', icon: 'edit', type: 'item', shortcut: 'F2' },\n { id: 'separator3', type: 'separator', label: '' },\n { id: 'delete', label: 'Delete', icon: 'trash', type: 'item', destructive: true, shortcut: 'Del' }\n );\n\n return baseMenu;\n }\n\n getEmptySpaceContextMenu(): ListContextMenuItem[] {\n return [\n { id: 'new-folder', label: 'New Folder', icon: 'folder-plus', type: 'item' },\n { id: 'new-file', label: 'New File', icon: 'file-plus', type: 'item' }\n ];\n }\n\n getMultiItemContextMenu(items: ListItemData[]): ListContextMenuItem[] {\n const hasFiles = items.some(i => !i.isDirectory);\n const menu: ListContextMenuItem[] = [];\n\n if (hasFiles) {\n menu.push(\n { id: 'download-multiple', label: `Download ${items.filter(i => !i.isDirectory).length} Files`, icon: 'download', type: 'item' }\n );\n }\n\n menu.push(\n { id: 'copy-path', label: 'Copy Paths', icon: 'copy', type: 'item' },\n { id: 'separator-del', type: 'separator', label: '' },\n { id: 'delete-multiple', label: `Delete ${items.length} Items`, icon: 'trash', type: 'item', destructive: true, shortcut: 'Del' }\n );\n\n return menu;\n }\n\n onContextMenuAction = (menuItemId: string, items: ListItemData[]) => {\n if (items.length === 0) {\n switch (menuItemId) {\n case 'new-folder':\n this.requestNewItem(this.currentPath, 'folder');\n break;\n case 'new-file':\n this.requestNewItem(this.currentPath, 'file');\n break;\n }\n return;\n }\n\n const item = items[0];\n if (!item) return;\n\n switch (menuItemId) {\n case 'open':\n this.onItemDoubleClick(item);\n break;\n case 'download':\n this.downloadFile(item.path);\n break;\n case 'download-multiple':\n items.filter(i => !i.isDirectory).forEach(i => this.downloadFile(i.path));\n break;\n case 'copy-path':\n this.copyPaths(items);\n break;\n case 'rename':\n this.requestRename(item);\n break;\n case 'delete':\n this.requestDelete([item]);\n break;\n case 'delete-multiple':\n this.requestDelete(items);\n break;\n case 'new-folder':\n this.requestNewItem(item.isDirectory ? item.path : this.currentPath, 'folder');\n break;\n case 'new-file':\n this.requestNewItem(item.isDirectory ? item.path : this.currentPath, 'file');\n break;\n }\n }\n\n canDragItem?(item: ListItemData): boolean {\n return true;\n }\n\n canDropItems?(draggedItems: ListItemData[], targetItem: ListItemData | null, position: 'before' | 'after' | 'inside'): boolean {\n // Can only drop into directories\n if (!targetItem?.isDirectory) return false;\n if (position !== 'inside') return false;\n // Cannot drop a folder into itself or its own children\n for (const item of draggedItems) {\n if (targetItem.path === item.path) return false;\n if (targetItem.path.startsWith(item.path + '/')) return false;\n }\n return true;\n }\n\n onDragStart?(draggedItems: ListItemData[], event: DragEvent): void {}\n\n onDrop?(dragDropInfo: ListDragDropInfo): void {\n const { draggedItems, targetItem } = dragDropInfo;\n if (!targetItem?.isDirectory) return;\n\n // Move each dragged item into the target directory\n const moves = draggedItems.map(async (item) => {\n const name = item.path.split('/').pop() || '';\n const newPath = `${targetItem.path}/${name}`.replace(/\\/\\//g, '/');\n try {\n await this.bridge.renameItem(item.path, newPath);\n } catch (e) {\n console.error(`Failed to move ${item.path} → ${newPath}:`, e);\n }\n });\n\n Promise.all(moves).then(() => this.options.onRefresh?.());\n }\n\n onDragEnd?(draggedItems: ListItemData[], success: boolean): void {}\n\n resolveThumbnailUrl(item: ListItemData): string | undefined {\n if (item.type === 'file' && this.isImageFile(item.name)) {\n return this.getThumbnailBlobUrl(item.path);\n }\n return undefined;\n }\n\n private getThumbnailUrl(item: FileSystemItem): string | undefined {\n // Return path as marker that this item has a thumbnail.\n // Actual blob URL resolved via resolveThumbnailUrl/thumbnailCache.\n if (item.type === 'file' && this.isImageFile(item.name)) {\n return item.path;\n }\n return undefined;\n }\n\n private getFileIconString(item: FileSystemItem): string {\n return getIconForFile(item.name, item.isDirectory);\n }\n\n private isImageFile(filename: string): boolean {\n const ext = filename.split('.').pop()?.toLowerCase();\n return ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp'].includes(ext || '');\n }\n\n private openFileWithViewer(item: ListItemData): void {\n const fsItem = item.metadata as FileSystemItem;\n if (this.options.onOpenFile) {\n this.options.onOpenFile(item.path, fsItem.name, fsItem.size);\n }\n }\n\n private copyPaths(items: ListItemData[]) {\n const paths = items.map(i => i.path).join('\\n');\n navigator.clipboard.writeText(paths).catch((err) => {\n console.error('Failed to copy paths:', err);\n });\n }\n\n private async downloadFile(path: string) {\n try {\n const content = await this.bridge.readFile(path);\n const filename = path.split('/').pop() || 'download';\n const blob = new Blob(\n [typeof content === 'string' ? content : content],\n { type: 'application/octet-stream' }\n );\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n } catch (error) {\n console.error('Download failed:', error);\n }\n }\n\n private requestRename(item: ListItemData) {\n if (this.options.onRenameRequest) {\n const currentName = item.path.split('/').pop() || '';\n this.options.onRenameRequest(item.id, currentName, item.path, 'list');\n }\n }\n\n private requestDelete(items: ListItemData[]) {\n if (this.options.onDeleteRequest) {\n const targets = items.map(item => ({\n path: item.path,\n isDirectory: Boolean(item.isDirectory),\n name: item.path.split('/').pop() || ''\n }));\n this.options.onDeleteRequest(targets);\n }\n }\n\n private requestNewItem(parentPath: string, type: 'file' | 'folder') {\n if (this.options.onNewItemRequest) {\n this.options.onNewItemRequest(parentPath, type);\n }\n }\n\n async executeRename(path: string, newName: string): Promise<void> {\n const parentPath = path.split('/').slice(0, -1).join('/') || '/';\n const newPath = `${parentPath}/${newName}`.replace(/\\/\\//g, '/');\n await this.bridge.renameItem(path, newPath);\n await this.options.onRefresh?.();\n }\n\n async executeDelete(targets: Array<{ path: string; isDirectory: boolean }>): Promise<void> {\n await Promise.all(targets.map(t =>\n this.bridge.deleteItem(t.path, t.isDirectory)\n ));\n await this.options.onRefresh?.();\n }\n\n async executeCreate(parentPath: string, name: string, type: 'file' | 'folder'): Promise<void> {\n const newPath = `${parentPath}/${name}`.replace(/\\/\\//g, '/');\n if (type === 'folder') {\n await this.bridge.createDirectory(newPath);\n } else {\n await this.bridge.writeFile(newPath, '');\n }\n await this.options.onRefresh?.();\n }\n}\n","import React from 'react';\nimport type {\n FileViewerPlugin,\n FileMatchContext,\n ResolvedViewer,\n} from './types';\n\n// Re-export types from types.ts for convenience\nexport type { FileViewerPlugin, FileMatchContext, ResolvedViewer, ToolbarAction, KeyboardShortcut } from './types';\n\n// ---- Legacy interfaces (kept for backward compatibility) ----\n\nexport interface ViewerConfig {\n id: string;\n name: string;\n description?: string;\n extensions: string[];\n component: React.ComponentType<ViewerProps>;\n priority?: number;\n canEdit?: boolean;\n isDefault?: boolean;\n}\n\nexport interface ViewerProps {\n file: {\n path: string;\n name: string;\n content?: string | ArrayBuffer;\n size?: number;\n mimeType?: string;\n };\n onClose?: () => void;\n onSave?: (content: string | ArrayBuffer) => Promise<void>;\n className?: string;\n readOnly?: boolean;\n /** Callback for viewer to register toolbar controls rendered in parent toolbar */\n onToolbarExtras?: (extras: React.ReactNode) => void;\n\n // ---- NEW: Edit lifecycle ----\n\n /**\n * Called by the plugin when the content becomes dirty (modified).\n * The host uses this to show unsaved-changes indicators and\n * to prompt before closing.\n */\n onDirtyChange?: (isDirty: boolean) => void;\n\n /**\n * Whether to render in compact/preview mode (inside the preview pane)\n * vs full mode (inside the main viewer area).\n * Plugins can adjust their layout based on this.\n */\n mode?: 'preview' | 'full';\n\n /**\n * Content fetcher for streaming/on-demand loading.\n * Plugins that handle large files (PDF, video) can use this\n * instead of receiving the full content upfront.\n */\n fetchContent?: () => Promise<string | ArrayBuffer>;\n\n /**\n * URL for the file if it can be accessed directly (e.g., S3 presigned URL).\n * Useful for media players that need a URL, not a buffer.\n */\n contentUrl?: string;\n}\n\n// ---- Match type bonus constants ----\n\nconst MATCH_BONUS_EXTENSION = 80;\nconst MATCH_BONUS_MIME = 70;\nconst MATCH_BONUS_PATTERN = 60;\n\n// ---- Adapter: wrap legacy ViewerConfig into FileViewerPlugin ----\n\nexport function viewerConfigToPlugin(config: ViewerConfig): FileViewerPlugin {\n const plugin: FileViewerPlugin = {\n id: config.id,\n name: config.name,\n extensions: config.extensions.map(ext => ext.toLowerCase().replace(/^\\./, '')),\n capabilities: {\n canPreview: true,\n canFullscreen: true,\n },\n priority: config.priority ?? 0,\n component: config.component,\n };\n if (config.description !== undefined) plugin.description = config.description;\n if (config.canEdit !== undefined) plugin.capabilities.canEdit = config.canEdit;\n if (config.isDefault !== undefined) plugin.isDefault = config.isDefault;\n return plugin;\n}\n\n// ---- Adapter: convert FileViewerPlugin back to ViewerConfig (for backward-compat getters) ----\n\nfunction pluginToViewerConfig(plugin: FileViewerPlugin): ViewerConfig {\n const config: ViewerConfig = {\n id: plugin.id,\n name: plugin.name,\n extensions: plugin.extensions ?? [],\n component: resolveComponent(plugin),\n priority: plugin.priority ?? 0,\n };\n if (plugin.description !== undefined) config.description = plugin.description;\n if (plugin.capabilities.canEdit !== undefined) config.canEdit = plugin.capabilities.canEdit;\n if (plugin.isDefault !== undefined) config.isDefault = plugin.isDefault;\n return config;\n}\n\n// ---- Lazy component cache ----\n\nconst lazyCache = new Map<string, React.LazyExoticComponent<React.ComponentType<ViewerProps>>>();\n\nfunction resolveComponent(plugin: FileViewerPlugin): React.ComponentType<ViewerProps> {\n if (plugin.component) {\n return plugin.component;\n }\n if (plugin.load) {\n if (!lazyCache.has(plugin.id)) {\n lazyCache.set(plugin.id, React.lazy(plugin.load));\n }\n return lazyCache.get(plugin.id)!;\n }\n throw new Error(`Plugin \"${plugin.id}\" has no component or loader`);\n}\n\n// ---- Simple glob matching for filePatterns ----\n\nfunction matchesGlob(filename: string, pattern: string): boolean {\n // Convert simple glob pattern to regex\n // Supports: * (any chars), ? (single char), and literal strings\n const escaped = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&')\n .replace(/\\*/g, '.*')\n .replace(/\\?/g, '.');\n const regex = new RegExp(`^${escaped}$`, 'i');\n return regex.test(filename);\n}\n\n// ---- ViewerRegistry class ----\n\nexport class ViewerRegistry {\n // ---- Legacy storage (kept for backward compat) ----\n private viewers = new Map<string, ViewerConfig>();\n private extensionMap = new Map<string, ViewerConfig[]>();\n\n // ---- New plugin storage ----\n private plugins = new Map<string, FileViewerPlugin>();\n private extensionIndex = new Map<string, FileViewerPlugin[]>();\n private mimeTypeIndex = new Map<string, FileViewerPlugin[]>();\n private patternPlugins: FileViewerPlugin[] = [];\n\n // ==============================\n // NEW: Plugin API\n // ==============================\n\n /**\n * Register a plugin. Replaces any existing plugin with the same ID.\n */\n registerPlugin(plugin: FileViewerPlugin): void {\n if (!plugin.component && !plugin.load) {\n throw new Error(`Plugin \"${plugin.id}\" must provide either component or load()`);\n }\n\n // Remove existing plugin with same ID (if any)\n this.unregisterPlugin(plugin.id);\n\n this.plugins.set(plugin.id, plugin);\n this.rebuildIndexes();\n\n // Also register in legacy storage for backward compat\n this.syncPluginToLegacy(plugin);\n }\n\n /**\n * Unregister a plugin by ID.\n */\n unregisterPlugin(pluginId: string): void {\n if (!this.plugins.has(pluginId)) return;\n\n this.plugins.delete(pluginId);\n this.rebuildIndexes();\n\n // Also remove from legacy maps\n this.removeLegacy(pluginId);\n\n // Clean lazy cache\n lazyCache.delete(pluginId);\n }\n\n /**\n * Find the best viewer for a given file.\n *\n * Matching order with scoring:\n * 1. Extension match (bonus: 80)\n * 2. MIME type match (bonus: 70)\n * 3. Filename pattern match (bonus: 60)\n * 4. canHandle() callback (bonus: canHandle return value 0-100)\n * 5. Default plugin (isDefault: true, bonus: 0)\n *\n * Final score = matchTypeBonus + plugin.priority + canHandle score (if applicable)\n */\n resolveViewer(\n file: FileMatchContext,\n options?: { preferEditable?: boolean }\n ): ResolvedViewer | null {\n const candidates = this.findCandidates(file);\n\n if (options?.preferEditable) {\n const editable = candidates.filter(c => c.plugin.capabilities.canEdit);\n if (editable.length > 0) return editable[0]!;\n }\n\n return candidates[0] ?? null;\n }\n\n /**\n * Find ALL viewers that can handle a file, sorted by score (descending).\n * Used for \"Open with...\" menu.\n */\n resolveAllViewers(file: FileMatchContext): ResolvedViewer[] {\n return this.findCandidates(file);\n }\n\n /**\n * Get a plugin by ID.\n */\n getPluginById(pluginId: string): FileViewerPlugin | null {\n return this.plugins.get(pluginId) ?? null;\n }\n\n /**\n * Get all registered plugins.\n */\n getAllPlugins(): FileViewerPlugin[] {\n return Array.from(this.plugins.values()).sort((a, b) => a.name.localeCompare(b.name));\n }\n\n /**\n * Build a FileMatchContext from a filename (convenience helper).\n */\n buildFileMatchContext(\n filename: string,\n opts?: { path?: string; mimeType?: string; size?: number }\n ): FileMatchContext {\n const ctx: FileMatchContext = {\n name: filename,\n path: opts?.path ?? filename,\n extension: this.extractExtension(filename),\n };\n if (opts?.mimeType !== undefined) ctx.mimeType = opts.mimeType;\n if (opts?.size !== undefined) ctx.size = opts.size;\n return ctx;\n }\n\n // ==============================\n // LEGACY API (backward compat)\n // ==============================\n\n registerViewer(config: ViewerConfig): void {\n // Register via plugin API, which also syncs to legacy\n this.registerPlugin(viewerConfigToPlugin(config));\n }\n\n unregisterViewer(viewerId: string): void {\n this.unregisterPlugin(viewerId);\n }\n\n getViewer(filename: string, preferEditable = false): ViewerConfig | null {\n const extension = this.extractExtension(filename);\n const viewers = this.extensionMap.get(extension) || [];\n\n if (viewers.length === 0) {\n return this.getDefaultViewer();\n }\n\n let candidates = viewers;\n if (preferEditable) {\n const editableViewers = viewers.filter(v => v.canEdit);\n if (editableViewers.length > 0) {\n candidates = editableViewers;\n }\n }\n\n return candidates[0] || null;\n }\n\n getViewers(filename: string): ViewerConfig[] {\n const extension = this.extractExtension(filename);\n return [...(this.extensionMap.get(extension) || [])];\n }\n\n canHandle(filename: string): boolean {\n const extension = this.extractExtension(filename);\n if (this.extensionMap.has(extension)) return true;\n\n // Also check plugin pattern/canHandle matching\n const ctx = this.buildFileMatchContext(filename);\n for (const plugin of this.patternPlugins) {\n if (plugin.filePatterns) {\n for (const pattern of plugin.filePatterns) {\n if (matchesGlob(filename, pattern)) return true;\n }\n }\n if (plugin.canHandle) {\n if (plugin.canHandle(ctx) > 0) return true;\n }\n }\n\n return false;\n }\n\n getAllViewers(): ViewerConfig[] {\n return Array.from(this.viewers.values()).sort((a, b) => a.name.localeCompare(b.name));\n }\n\n getViewerById(id: string): ViewerConfig | null {\n return this.viewers.get(id) || null;\n }\n\n getFileCategory(filename: string): string {\n const extension = this.extractExtension(filename);\n\n const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'bmp', 'ico'];\n const videoExts = ['mp4', 'avi', 'mov', 'wmv', 'flv', 'webm', 'mkv'];\n const audioExts = ['mp3', 'wav', 'flac', 'aac', 'ogg', 'wma', 'm4a'];\n const codeExts = ['js', 'jsx', 'ts', 'tsx', 'py', 'java', 'cpp', 'c', 'cs', 'php', 'rb', 'go', 'rs', 'swift', 'kt', 'html', 'css', 'scss'];\n const textExts = ['txt', 'md', 'mdx', 'rst', 'rtf'];\n const documentExts = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'];\n const archiveExts = ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'];\n\n if (imageExts.includes(extension)) return 'image';\n if (videoExts.includes(extension)) return 'video';\n if (audioExts.includes(extension)) return 'audio';\n if (codeExts.includes(extension)) return 'code';\n if (textExts.includes(extension)) return 'text';\n if (documentExts.includes(extension)) return 'document';\n if (archiveExts.includes(extension)) return 'archive';\n\n return 'file';\n }\n\n // ==============================\n // INTERNAL\n // ==============================\n\n private extractExtension(filename: string): string {\n const lastDot = filename.lastIndexOf('.');\n if (lastDot === -1 || lastDot === filename.length - 1) {\n return '';\n }\n return filename.slice(lastDot + 1).toLowerCase();\n }\n\n private getDefaultViewer(): ViewerConfig | null {\n for (const viewer of this.viewers.values()) {\n if (viewer.isDefault) {\n return viewer;\n }\n }\n return null;\n }\n\n /**\n * Find all candidate viewers for a file, scored and sorted descending.\n */\n private findCandidates(file: FileMatchContext): ResolvedViewer[] {\n const scored: Array<{ plugin: FileViewerPlugin; score: number }> = [];\n\n // 1. Extension match\n if (file.extension) {\n const byExt = this.extensionIndex.get(file.extension) || [];\n for (const plugin of byExt) {\n let score = MATCH_BONUS_EXTENSION + (plugin.priority ?? 0);\n if (plugin.canHandle) {\n const canHandleScore = plugin.canHandle(file);\n if (canHandleScore <= 0) continue; // canHandle rejected\n score += canHandleScore;\n }\n scored.push({ plugin, score });\n }\n }\n\n // 2. MIME type match\n if (file.mimeType) {\n const byMime = this.mimeTypeIndex.get(file.mimeType) || [];\n for (const plugin of byMime) {\n // Skip if already scored by extension\n if (scored.some(s => s.plugin.id === plugin.id)) continue;\n\n let score = MATCH_BONUS_MIME + (plugin.priority ?? 0);\n if (plugin.canHandle) {\n const canHandleScore = plugin.canHandle(file);\n if (canHandleScore <= 0) continue;\n score += canHandleScore;\n }\n scored.push({ plugin, score });\n }\n }\n\n // 3. Pattern match + canHandle-only plugins\n for (const plugin of this.patternPlugins) {\n // Skip if already scored\n if (scored.some(s => s.plugin.id === plugin.id)) continue;\n\n let matched = false;\n let matchBonus = 0;\n\n // Check filePatterns\n if (plugin.filePatterns) {\n for (const pattern of plugin.filePatterns) {\n if (matchesGlob(file.name, pattern)) {\n matched = true;\n matchBonus = MATCH_BONUS_PATTERN;\n break;\n }\n }\n }\n\n // Check canHandle (for plugins with only canHandle, or in addition to pattern match)\n if (plugin.canHandle) {\n const canHandleScore = plugin.canHandle(file);\n if (canHandleScore > 0) {\n if (!matched) {\n // canHandle-only match: score IS the canHandle return value\n matched = true;\n matchBonus = canHandleScore;\n } else {\n // Pattern + canHandle: add canHandle score\n matchBonus += canHandleScore;\n }\n } else if (!matched) {\n continue;\n }\n }\n\n if (matched) {\n scored.push({ plugin, score: matchBonus + (plugin.priority ?? 0) });\n }\n }\n\n // 4. If nothing matched, try default plugin\n if (scored.length === 0) {\n for (const plugin of this.plugins.values()) {\n if (plugin.isDefault) {\n scored.push({ plugin, score: 0 });\n break;\n }\n }\n }\n\n // Sort by score descending, break ties by priority descending\n scored.sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n return (b.plugin.priority ?? 0) - (a.plugin.priority ?? 0);\n });\n\n // Resolve to ResolvedViewer\n return scored.map(({ plugin, score }) => ({\n plugin,\n Component: resolveComponent(plugin),\n confidence: score,\n }));\n }\n\n /**\n * Rebuild plugin indexes from the plugin map.\n */\n private rebuildIndexes(): void {\n this.extensionIndex.clear();\n this.mimeTypeIndex.clear();\n this.patternPlugins = [];\n\n for (const plugin of this.plugins.values()) {\n // Index by extension\n if (plugin.extensions) {\n for (const ext of plugin.extensions) {\n const normalized = ext.toLowerCase().replace(/^\\./, '');\n const list = this.extensionIndex.get(normalized) || [];\n list.push(plugin);\n this.extensionIndex.set(normalized, list);\n }\n }\n\n // Index by MIME type\n if (plugin.mimeTypes) {\n for (const mime of plugin.mimeTypes) {\n const list = this.mimeTypeIndex.get(mime) || [];\n list.push(plugin);\n this.mimeTypeIndex.set(mime, list);\n }\n }\n\n // Track plugins with patterns or canHandle\n if (plugin.filePatterns || plugin.canHandle) {\n this.patternPlugins.push(plugin);\n }\n }\n }\n\n /**\n * Sync a plugin into the legacy viewers/extensionMap storage.\n */\n private syncPluginToLegacy(plugin: FileViewerPlugin): void {\n const config = pluginToViewerConfig(plugin);\n this.viewers.set(config.id, config);\n\n if (config.extensions) {\n config.extensions.forEach(ext => {\n const normalizedExt = ext.toLowerCase().replace(/^\\./, '');\n const existingViewers = this.extensionMap.get(normalizedExt) || [];\n\n const insertIndex = existingViewers.findIndex(\n v => (v.priority || 0) < (config.priority || 0)\n );\n if (insertIndex === -1) {\n existingViewers.push(config);\n } else {\n existingViewers.splice(insertIndex, 0, config);\n }\n\n this.extensionMap.set(normalizedExt, existingViewers);\n });\n }\n }\n\n /**\n * Remove a plugin from legacy storage.\n */\n private removeLegacy(pluginId: string): void {\n const config = this.viewers.get(pluginId);\n if (!config) return;\n\n this.viewers.delete(pluginId);\n\n config.extensions.forEach(ext => {\n const normalizedExt = ext.toLowerCase().replace(/^\\./, '');\n const viewers = this.extensionMap.get(normalizedExt) || [];\n const filtered = viewers.filter(v => v.id !== pluginId);\n\n if (filtered.length === 0) {\n this.extensionMap.delete(normalizedExt);\n } else {\n this.extensionMap.set(normalizedExt, filtered);\n }\n });\n }\n}\n\nexport const globalViewerRegistry = new ViewerRegistry();\n","import React, { useState, useEffect } from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { FileText } from 'lucide-react';\nimport { cn } from '../../lib/utils';\nimport { ViewerProps } from '../registry/ViewerRegistry';\n\nexport const TextViewer: React.FC<ViewerProps> = observer(({\n file,\n onClose,\n className,\n}) => {\n const [content, setContent] = useState<string>('');\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const loadContent = async () => {\n try {\n setIsLoading(true);\n setError(null);\n\n if (file.content) {\n if (typeof file.content === 'string') {\n setContent(file.content);\n } else {\n const decoder = new TextDecoder('utf-8');\n setContent(decoder.decode(file.content));\n }\n } else {\n setContent(`Sample content for ${file.name}\\n\\nPath: ${file.path}`);\n }\n } catch (err) {\n setError(`Failed to load file: ${err instanceof Error ? err.message : 'Unknown error'}`);\n } finally {\n setIsLoading(false);\n }\n };\n\n loadContent();\n }, [file]);\n\n if (isLoading) {\n return (\n <div className={cn(\"h-full flex flex-col\", className)}>\n <div className=\"flex items-center gap-2 px-4 py-3 border-b bg-muted/30 flex-shrink-0\">\n <FileText className=\"w-4 h-4 text-muted-foreground\" />\n <span className=\"text-sm font-medium\">Loading {file.name}</span>\n </div>\n <div className=\"flex-1 flex items-center justify-center\">\n <span className=\"text-sm text-muted-foreground\">Loading file content...</span>\n </div>\n </div>\n );\n }\n\n if (error) {\n return (\n <div className={cn(\"h-full flex flex-col\", className)}>\n <div className=\"flex items-center gap-2 px-4 py-3 border-b bg-muted/30 flex-shrink-0\">\n <FileText className=\"w-4 h-4 text-destructive\" />\n <span className=\"text-sm font-medium text-destructive\">Error loading {file.name}</span>\n </div>\n <div className=\"flex-1 flex items-center justify-center\">\n <div className=\"text-center\">\n <p className=\"text-sm font-medium text-destructive\">Failed to load file</p>\n <p className=\"text-xs text-muted-foreground mt-1\">{error}</p>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div className={cn(\"h-full flex flex-col\", className)}>\n <div className=\"flex items-center justify-between px-4 py-3 border-b bg-muted/30 flex-shrink-0\">\n <div className=\"flex items-center gap-2\">\n <FileText className=\"w-4 h-4 text-muted-foreground\" />\n <span className=\"text-sm font-medium\">{file.name}</span>\n {file.size != null && (\n <span className=\"text-xs text-muted-foreground\">\n ({(file.size / 1024).toFixed(1)} KB)\n </span>\n )}\n </div>\n </div>\n <div className=\"flex-1 min-h-0 overflow-auto p-4\">\n <pre className=\"font-mono text-sm leading-relaxed whitespace-pre-wrap break-words m-0 p-4 bg-muted/50 rounded-md border\">\n {content}\n </pre>\n </div>\n </div>\n );\n});\n\nTextViewer.displayName = 'TextViewer';\n","import { makeAutoObservable } from 'mobx';\n\ntype Scaler = {\n ref: React.RefObject<HTMLDivElement | null>;\n values: { zoom: number; translateX: number; translateY: number };\n setZoomBounds: (min: number, max: number) => void;\n setContentSize: (width: number, height: number) => void;\n fitToContent: (animate?: boolean) => void;\n zoomBy: (factor: number, animate?: boolean, originX?: number, originY?: number) => void;\n};\n\nexport class ImageViewerModel {\n imageError = false;\n isLoaded = false;\n currentFilePath = '';\n private scaler: Scaler | null = null;\n\n constructor() {\n makeAutoObservable(this, { scaler: false });\n }\n\n setScaler(scaler: Scaler): void {\n this.scaler = scaler;\n }\n\n get zoomPercent(): number {\n return Math.round((this.scaler?.values.zoom ?? 1) * 100);\n }\n\n /** Reset state when navigating to a different file */\n onFileChange(filePath: string): void {\n if (this.currentFilePath !== filePath) {\n this.currentFilePath = filePath;\n this.isLoaded = false;\n this.imageError = false;\n }\n }\n\n handleImageLoad(img: HTMLImageElement): void {\n if (!this.scaler) return;\n this.scaler.setZoomBounds(0.01, 100);\n requestAnimationFrame(() => {\n this.scaler!.setContentSize(img.naturalWidth, img.naturalHeight);\n this.scaler!.fitToContent(false);\n this.isLoaded = true;\n });\n }\n\n handleImageError(): void {\n this.imageError = true;\n this.isLoaded = true;\n }\n\n zoomIn(): void {\n if (!this.scaler) return;\n const el = this.scaler.ref.current;\n if (el) {\n const r = el.getBoundingClientRect();\n this.scaler.zoomBy(1.3, true, r.width / 2, r.height / 2);\n } else {\n this.scaler.zoomBy(1.3, true);\n }\n }\n\n zoomOut(): void {\n if (!this.scaler) return;\n const el = this.scaler.ref.current;\n if (el) {\n const r = el.getBoundingClientRect();\n this.scaler.zoomBy(0.77, true, r.width / 2, r.height / 2);\n } else {\n this.scaler.zoomBy(0.77, true);\n }\n }\n\n resetZoom(): void {\n this.scaler?.fitToContent(true);\n }\n}\n","import React, { useState, useEffect } from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { ImageIcon, ZoomIn, ZoomOut, Maximize } from 'lucide-react';\nimport { useScaler } from '@panscale/react';\nimport { cn } from '../../lib/utils';\nimport { ViewerProps } from '../registry/ViewerRegistry';\nimport { ImageViewerModel } from './ImageViewerModel';\n\nconst MIME_MAP: Record<string, string> = {\n 'png': 'image/png', 'jpg': 'image/jpeg', 'jpeg': 'image/jpeg',\n 'gif': 'image/gif', 'webp': 'image/webp', 'svg': 'image/svg+xml',\n 'bmp': 'image/bmp', 'ico': 'image/x-icon', 'avif': 'image/avif',\n 'tiff': 'image/tiff', 'tif': 'image/tiff',\n};\n\n// Convert ArrayBuffer to base64 data URL — no lifecycle management needed (unlike blob URLs)\nfunction arrayBufferToDataUrl(buffer: ArrayBuffer, mime: string): string {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]!);\n }\n return `data:${mime};base64,${btoa(binary)}`;\n}\n\nfunction getImageUrl(content: string | ArrayBuffer, name: string, mimeType?: string): string | null {\n if (content instanceof ArrayBuffer) {\n const ext = name.split('.').pop()?.toLowerCase() || 'png';\n const mime = MIME_MAP[ext] || mimeType || 'image/png';\n return arrayBufferToDataUrl(content, mime);\n }\n if (typeof content === 'string') {\n if (content.startsWith('data:') || content.startsWith('http')) {\n return content;\n }\n if (name.endsWith('.svg')) {\n return `data:image/svg+xml,${encodeURIComponent(content)}`;\n }\n try {\n const ext = name.split('.').pop()?.toLowerCase() || 'png';\n const mime = MIME_MAP[ext] || mimeType || 'image/png';\n return `data:${mime};base64,${btoa(content)}`;\n } catch {\n return null;\n }\n }\n return null;\n}\n\nexport const ImageViewer: React.FC<ViewerProps> = observer(({\n file,\n onClose,\n onToolbarExtras,\n className,\n}) => {\n const imageUrl = file.content ? getImageUrl(file.content, file.name, file.mimeType) : null;\n const [model] = useState(() => new ImageViewerModel());\n const scaler = useScaler({ zooming: true, bouncing: true });\n\n // Wire scaler into model and handle file changes\n model.setScaler(scaler);\n model.onFileChange(file.path);\n\n const zoomPercent = model.zoomPercent;\n\n // Register zoom controls in parent toolbar\n useEffect(() => {\n if (!onToolbarExtras || !imageUrl || model.imageError) {\n onToolbarExtras?.(null);\n return;\n }\n onToolbarExtras(\n <div className=\"flex items-center gap-0.5\">\n <button\n onClick={() => model.zoomOut()}\n className=\"p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors\"\n title=\"Zoom out\"\n >\n <ZoomOut className=\"w-3.5 h-3.5\" />\n </button>\n <span className=\"text-muted-foreground text-xs min-w-[2.5rem] text-center tabular-nums\">\n {zoomPercent}%\n </span>\n <button\n onClick={() => model.zoomIn()}\n className=\"p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors\"\n title=\"Zoom in\"\n >\n <ZoomIn className=\"w-3.5 h-3.5\" />\n </button>\n <button\n onClick={() => model.resetZoom()}\n className=\"p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors\"\n title=\"Fit to screen\"\n >\n <Maximize className=\"w-3.5 h-3.5\" />\n </button>\n </div>\n );\n }, [onToolbarExtras, imageUrl, model.imageError, zoomPercent, model]);\n\n return (\n <div className={cn(\"h-full flex flex-col\", className)}>\n {/* Pan/zoom image area — full height, no separate toolbar */}\n <div\n className=\"flex-1 min-h-0 relative\"\n style={{ backgroundColor: '#111' }}\n >\n {model.imageError || !imageUrl ? (\n <div className=\"flex flex-col items-center justify-center h-full gap-3 text-white/60\">\n <ImageIcon className=\"w-16 h-16\" />\n <p className=\"text-sm\">{model.imageError ? 'Failed to load image' : 'Preview not available'}</p>\n <p className=\"text-xs text-white/40\">{file.name}</p>\n </div>\n ) : (\n <>\n {!model.isLoaded && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-2 text-white/60 z-10\">\n <div className=\"animate-spin w-6 h-6 border-2 border-white/40 border-t-white rounded-full\" />\n <p className=\"text-sm\">Loading image...</p>\n </div>\n )}\n {/* Panscale scaler container */}\n <div\n ref={scaler.ref}\n style={{\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n position: 'relative',\n touchAction: 'none',\n }}\n >\n <div\n style={{\n transform: `translate(${scaler.values.translateX}px, ${scaler.values.translateY}px) scale(${scaler.values.zoom})`,\n transformOrigin: '0 0',\n willChange: 'transform',\n }}\n >\n <img\n src={imageUrl}\n alt={file.name}\n className=\"select-none\"\n style={{\n display: 'block',\n maxWidth: 'none',\n opacity: model.isLoaded ? 1 : 0,\n }}\n onLoad={(e) => model.handleImageLoad(e.currentTarget)}\n onError={() => model.handleImageError()}\n draggable={false}\n />\n </div>\n </div>\n </>\n )}\n </div>\n </div>\n );\n});\n\nImageViewer.displayName = 'ImageViewer';\n","import React, { useCallback } from 'react';\nimport { FileQuestion, Download } from 'lucide-react';\nimport { Button } from '@anymux/ui/components/button';\nimport { cn } from '../../lib/utils';\nimport type { ViewerProps } from '../registry/ViewerRegistry';\n\nexport const UnsupportedFileViewer: React.FC<ViewerProps> = ({\n file,\n onClose,\n className,\n}) => {\n const extension = file.name.split('.').pop()?.toLowerCase() || '';\n\n const handleDownload = useCallback(() => {\n if (!file.content) return;\n\n const blob = file.content instanceof ArrayBuffer\n ? new Blob([file.content])\n : new Blob([file.content], { type: 'text/plain' });\n\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = file.name;\n a.click();\n URL.revokeObjectURL(url);\n }, [file.content, file.name]);\n\n return (\n <div className={cn(\"h-full flex items-center justify-center bg-muted/10\", className)}>\n <div className=\"flex flex-col items-center gap-4 text-center px-6\">\n <FileQuestion className=\"w-16 h-16 text-muted-foreground/60\" />\n <div>\n <p className=\"text-sm font-medium\">{file.name}</p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Preview not available{extension ? ` for .${extension} files` : ''}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n {file.content && (\n <Button variant=\"outline\" size=\"sm\" onClick={handleDownload}>\n <Download className=\"w-4 h-4 mr-1.5\" />\n Download\n </Button>\n )}\n {onClose && (\n <Button variant=\"ghost\" size=\"sm\" onClick={onClose}>\n Close\n </Button>\n )}\n </div>\n </div>\n </div>\n );\n};\n\nUnsupportedFileViewer.displayName = 'UnsupportedFileViewer';\n","import { globalViewerRegistry } from '../registry/ViewerRegistry';\nimport { TextViewer } from './TextViewer';\nimport { ImageViewer } from './ImageViewer';\n\n// Export viewers\nexport { TextViewer } from './TextViewer';\nexport { ImageViewer } from './ImageViewer';\nexport { UnsupportedFileViewer } from './UnsupportedFileViewer';\nexport { globalViewerRegistry, type ViewerConfig, type ViewerProps } from '../registry/ViewerRegistry';\n\n// Also re-export new plugin types\nexport type { FileViewerPlugin, FileMatchContext, ResolvedViewer, ToolbarAction, KeyboardShortcut } from '../registry/types';\n\n// Register default viewers for common file types using the new plugin API\nexport function registerDefaultViewers() {\n // Text files viewer (built-in, priority 10, default fallback)\n globalViewerRegistry.registerPlugin({\n id: 'text-viewer',\n name: 'Text Viewer',\n description: 'View text files, code, and configuration files',\n extensions: [\n 'txt', 'md', 'mdx', 'rst', 'rtf',\n 'js', 'jsx', 'ts', 'tsx', 'json', 'jsonc',\n 'html', 'htm', 'css', 'scss', 'sass', 'less',\n 'xml', 'svg', 'yaml', 'yml', 'toml',\n 'ini', 'conf', 'config', 'env',\n 'py', 'java', 'cpp', 'c', 'cs', 'php', 'rb', 'go', 'rs',\n 'swift', 'kt', 'scala', 'sh', 'bash', 'zsh', 'fish',\n 'log', 'gitignore', 'dockerignore', 'editorconfig',\n ],\n capabilities: {\n canEdit: false,\n canPreview: true,\n canFullscreen: true,\n },\n component: TextViewer,\n priority: 10,\n isDefault: true,\n });\n\n // Image files viewer (built-in, priority 20)\n globalViewerRegistry.registerPlugin({\n id: 'image-viewer',\n name: 'Image Viewer',\n description: 'View image files including photos and graphics',\n extensions: [\n 'png', 'jpg', 'jpeg', 'gif', 'svg', 'webp',\n 'bmp', 'ico', 'tiff', 'tif', 'avif',\n ],\n capabilities: {\n canEdit: false,\n canPreview: true,\n canFullscreen: true,\n },\n component: ImageViewer,\n priority: 20,\n });\n}\n\n// Auto-register default viewers when module is imported\nregisterDefaultViewers();\n","import { makeAutoObservable, flow, observable } from 'mobx';\nimport type { FileSystemBridge } from '../adapters/FileSystemBridge';\n\nexport interface UploadFileEntry {\n /** Original File object from the browser */\n file: File;\n /** Target path on the file system */\n targetPath: string;\n /** Upload progress 0-100 */\n progress: number;\n /** Status of this individual file */\n status: 'pending' | 'uploading' | 'done' | 'error';\n /** Error message if status is 'error' */\n error?: string;\n}\n\nexport class UploadModel {\n private bridge: FileSystemBridge;\n\n /** Files currently being uploaded or queued */\n files: UploadFileEntry[] = [];\n\n /** Overall upload state */\n isUploading = false;\n\n /** Number of completed uploads in the current batch */\n completedCount = 0;\n\n /** Whether the upload summary toast is visible */\n showSummary = false;\n\n /** Last batch summary */\n lastSummary: { total: number; succeeded: number; failed: number } | null = null;\n\n private notify: (type: 'success' | 'error' | 'warning', message: string) => void;\n\n constructor(bridge: FileSystemBridge, notify?: (type: 'success' | 'error' | 'warning', message: string) => void) {\n this.bridge = bridge;\n this.notify = notify ?? (() => {});\n makeAutoObservable(this, {\n bridge: false,\n notify: false,\n files: observable.shallow,\n });\n }\n\n /** Total number of files in the current batch */\n get totalCount(): number {\n return this.files.length;\n }\n\n /** Overall progress across all files (0-100) */\n get overallProgress(): number {\n if (this.files.length === 0) return 0;\n const total = this.files.reduce((sum, f) => sum + f.progress, 0);\n return Math.round(total / this.files.length);\n }\n\n /** Number of files that failed */\n get failedCount(): number {\n return this.files.filter(f => f.status === 'error').length;\n }\n\n /** Whether there are any active uploads */\n get hasActiveUploads(): boolean {\n return this.isUploading;\n }\n\n /**\n * Upload multiple files to a target directory.\n * Uses MobX flow for proper async tracking.\n */\n uploadFiles = flow(function* (\n this: UploadModel,\n fileList: FileList | File[],\n targetDirectory: string\n ) {\n const files = Array.from(fileList);\n if (files.length === 0) return;\n\n // Build the upload queue\n this.files = files.map(file => ({\n file,\n targetPath: `${targetDirectory}/${file.name}`.replace(/\\/\\//g, '/'),\n progress: 0,\n status: 'pending' as const,\n }));\n this.completedCount = 0;\n this.isUploading = true;\n this.showSummary = false;\n this.lastSummary = null;\n\n let succeeded = 0;\n let failed = 0;\n\n for (let i = 0; i < this.files.length; i++) {\n const entry = this.files[i]!;\n entry.status = 'uploading';\n entry.progress = 0;\n\n try {\n // Read file content as ArrayBuffer\n const buffer: ArrayBuffer = yield entry.file.arrayBuffer();\n entry.progress = 50; // Mark 50% after reading into memory\n\n // Write to the file system\n yield this.bridge.writeFile(entry.targetPath, Buffer.from(buffer));\n\n entry.progress = 100;\n entry.status = 'done';\n succeeded++;\n } catch (err) {\n entry.status = 'error';\n entry.error = err instanceof Error ? err.message : 'Upload failed';\n entry.progress = 0;\n failed++;\n }\n\n this.completedCount = i + 1;\n }\n\n this.isUploading = false;\n this.lastSummary = { total: files.length, succeeded, failed };\n this.showSummary = true;\n\n if (failed === 0) {\n this.notify('success', `Uploaded ${succeeded} file${succeeded > 1 ? 's' : ''}`);\n } else if (succeeded > 0) {\n this.notify('warning', `Uploaded ${succeeded}/${files.length} files (${failed} failed)`);\n } else {\n this.notify('error', `Upload failed: ${failed} file${failed > 1 ? 's' : ''}`);\n }\n });\n\n /** Clear the file list and summary */\n clear(): void {\n this.files = [];\n this.completedCount = 0;\n this.showSummary = false;\n this.lastSummary = null;\n }\n\n /** Dismiss the summary toast */\n dismissSummary(): void {\n this.showSummary = false;\n }\n}\n","import { makeAutoObservable, runInAction } from 'mobx';\nimport { TreeModel } from '../../tree';\nimport { ListItemsModel } from '../../list';\nimport type { IFileSystem } from '@anymux/file-system';\nimport { FileSystemBridge } from '../adapters/FileSystemBridge';\nimport { FileSystemTreeProvider } from '../providers/FileSystemTreeProvider';\nimport { FileSystemListProvider } from '../providers/FileSystemListProvider';\nimport type { ListItemData } from '../../list/types/ListTypes';\nimport type { TreeNodeData } from '../../tree/types/TreeTypes';\nimport { globalViewerRegistry, type ViewerConfig, UnsupportedFileViewer } from '../viewers';\nimport { UploadModel } from './UploadModel';\n\nexport interface OpenFileState {\n path: string;\n name: string;\n content?: string | ArrayBuffer;\n size?: number;\n mimeType?: string;\n viewer: ViewerConfig;\n}\n\nexport interface PreviewFileState {\n path: string;\n name: string;\n content?: string | ArrayBuffer;\n size?: number;\n mimeType?: string;\n viewer: ViewerConfig;\n isLoading: boolean;\n}\n\nexport class FileBrowserModel {\n // File system integration\n fileSystem: IFileSystem;\n fileSystemBridge: FileSystemBridge;\n\n // Component providers\n treeProvider: FileSystemTreeProvider;\n listProvider: FileSystemListProvider;\n\n // Component models\n treeModel: TreeModel;\n listModel: ListItemsModel;\n\n // Upload model\n uploadModel: UploadModel;\n\n // Synchronized state\n currentPath: string = '/';\n selectedPath: string | null = null;\n\n // UI state\n isLoading: boolean = false;\n error: string | null = null;\n\n // Callback for path changes (URL sync)\n onPathChange?: (path: string) => void;\n\n // Notification callbacks (wired by consuming code to toast/notifications)\n onNotify?: (type: 'success' | 'error' | 'warning', message: string) => void;\n /** Structured action callback with undo support */\n onAction?: (action: { type: 'create' | 'rename' | 'delete' | 'upload'; message: string; undo?: () => Promise<void> }) => void;\n\n // Viewer state\n openFile: OpenFileState | null = null;\n isLoadingFile: boolean = false;\n\n // Preview pane state\n previewEnabled: boolean = false;\n previewFile: PreviewFileState | null = null;\n\n // Dialog state for rename/delete/create operations\n renameState: { itemId: string; currentName: string; path: string; source: 'list' | 'tree' } | null = null;\n deleteState: { targets: Array<{ path: string; isDirectory: boolean; name: string }> } | null = null;\n createState: { parentPath: string; type: 'file' | 'folder' } | null = null;\n\n constructor(fileSystem: IFileSystem) {\n makeAutoObservable(this, {\n fileSystem: false,\n fileSystemBridge: false,\n onPathChange: false,\n onNotify: false,\n onAction: false,\n });\n\n this.fileSystem = fileSystem;\n this.fileSystemBridge = new FileSystemBridge(fileSystem);\n\n this.treeProvider = new FileSystemTreeProvider(this.fileSystemBridge, {\n showFilesInTree: false,\n onSelectionChange: this.handleTreeSelection,\n onRefresh: () => this.refresh(),\n onRenameRequest: (itemId, currentName, path, source) => this.requestRename(itemId, currentName, path, source),\n onDeleteRequest: (targets) => this.requestDelete(targets),\n onNewItemRequest: (parentPath, type) => this.requestCreate(parentPath, type)\n });\n\n this.listProvider = new FileSystemListProvider(this.fileSystemBridge, {\n showAllItems: true,\n onSelectionChange: this.handleListSelection,\n onNavigation: this.handleListNavigation,\n onNavigateUp: () => this.navigateUp(),\n onOpenFile: (path, name, size) => this.openFileViewer(path, name, size),\n onPreviewFile: (path, name, size) => this.loadPreviewFile(path, name, size),\n onRefresh: () => this.refresh(),\n onRenameRequest: (itemId, currentName, path, source) => this.requestRename(itemId, currentName, path, source),\n onDeleteRequest: (targets) => this.requestDelete(targets),\n onNewItemRequest: (parentPath, type) => this.requestCreate(parentPath, type)\n });\n\n this.treeModel = new TreeModel(this.treeProvider);\n this.listModel = new ListItemsModel(this.listProvider);\n this.uploadModel = new UploadModel(this.fileSystemBridge, (type, msg) => this.notify(type, msg));\n }\n\n private notify(type: 'success' | 'error' | 'warning', message: string): void {\n this.onNotify?.(type, message);\n }\n\n async setInitialPath(path: string) {\n this.currentPath = path;\n this.selectedPath = path;\n\n this.listProvider.setPath(path);\n\n await Promise.all([\n this.treeModel.loadNodes(),\n this.listModel.loadItems()\n ]);\n\n this.selectPathInTree(path);\n }\n\n handleTreeSelection = async (path: string) => {\n this.selectedPath = path;\n this.currentPath = path;\n this.previewFile = null;\n this.error = null;\n this.openFile = null;\n this.onPathChange?.(path);\n\n this.listProvider.setPath(path);\n this.listModel.clearItems();\n this.listModel.clearSearch();\n this.listModel.totalItemCount = 0;\n await this.listModel.loadItems();\n };\n\n handleListNavigation = async (path: string) => {\n this.currentPath = path;\n this.selectedPath = path;\n this.previewFile = null;\n this.error = null;\n this.openFile = null;\n this.onPathChange?.(path);\n\n this.selectPathInTree(path);\n\n this.listProvider.setPath(path);\n this.listModel.clearItems();\n this.listModel.clearSearch();\n this.listModel.totalItemCount = 0;\n await this.listModel.loadItems();\n };\n\n handleListSelection = (selectedItems: ListItemData[]) => {\n // Optional: auto-navigate on single directory selection\n };\n\n private selectPathInTree(path: string) {\n const node = this.findNodeByPath(path);\n if (node) {\n this.treeModel.selectNode(node);\n }\n }\n\n private findNodeByPath(path: string): TreeNodeData | null {\n const searchNodes = (nodes: TreeNodeData[]): TreeNodeData | null => {\n for (const node of nodes) {\n if (node.path === path) {\n return node;\n }\n if (node.children) {\n const found = searchNodes(node.children);\n if (found) return found;\n }\n }\n return null;\n };\n\n return searchNodes(this.treeModel.nodes);\n }\n\n async navigateUp() {\n const parentPath = this.currentPath.split('/').slice(0, -1).join('/') || '/';\n await this.handleListNavigation(parentPath);\n }\n\n async navigateToPath(path: string) {\n await this.handleListNavigation(path);\n }\n\n async refresh() {\n runInAction(() => {\n this.isLoading = true;\n this.error = null;\n this.treeModel.errors.clear();\n });\n\n try {\n await Promise.all([\n this.treeModel.loadNodes(),\n this.listModel.refresh()\n ]);\n } catch (error) {\n runInAction(() => {\n this.error = error instanceof Error ? error.message : 'Failed to refresh';\n });\n } finally {\n runInAction(() => {\n this.isLoading = false;\n });\n }\n }\n\n async navigateToBreadcrumb(path: string) {\n await this.handleListNavigation(path);\n }\n\n get canNavigateUp(): boolean {\n return this.currentPath !== '/';\n }\n\n get pathSegments(): Array<{ name: string; path: string }> {\n if (this.currentPath === '/') {\n return [{ name: 'Root', path: '/' }];\n }\n\n const segments = this.currentPath.split('/').filter(Boolean);\n return [\n { name: 'Root', path: '/' },\n ...segments.map((segment, index) => ({\n name: segment,\n path: '/' + segments.slice(0, index + 1).join('/')\n }))\n ];\n }\n\n get isTreeLoading(): boolean {\n return this.treeModel.isLoading;\n }\n\n get isListLoading(): boolean {\n return this.listModel.isLoading;\n }\n\n get hasTreeNodes(): boolean {\n return this.treeModel.hasNodes;\n }\n\n get hasListItems(): boolean {\n return this.listModel.items.length > 0;\n }\n\n get hasError(): boolean {\n return this.error !== null;\n }\n\n get hasItems(): boolean {\n return this.hasListItems;\n }\n\n get itemsArray(): ListItemData[] {\n return this.listModel.items;\n }\n\n async refreshItems(): Promise<void> {\n await this.refresh();\n }\n\n clearError(): void {\n this.error = null;\n }\n\n async setCurrentPath(path: string): Promise<void> {\n await this.navigateToPath(path);\n }\n\n // Image extensions that should be read as binary\n private static readonly BINARY_EXTENSIONS = new Set([\n 'png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'ico', 'tiff', 'tif', 'avif',\n 'pdf', 'zip', 'tar', 'gz',\n ]);\n\n private static readonly MIME_TYPES: Record<string, string> = {\n 'txt': 'text/plain', 'md': 'text/markdown', 'json': 'application/json',\n 'js': 'text/javascript', 'ts': 'text/typescript', 'css': 'text/css',\n 'html': 'text/html', 'png': 'image/png', 'jpg': 'image/jpeg',\n 'jpeg': 'image/jpeg', 'gif': 'image/gif', 'svg': 'image/svg+xml',\n 'webp': 'image/webp', 'bmp': 'image/bmp', 'ico': 'image/x-icon',\n 'avif': 'image/avif', 'tiff': 'image/tiff', 'tif': 'image/tiff',\n 'pdf': 'application/pdf',\n };\n\n async openFileViewer(path: string, name: string, size?: number): Promise<void> {\n const extension = name.split('.').pop()?.toLowerCase() || '';\n const isSupported = globalViewerRegistry.canHandle(name);\n const viewer: ViewerConfig = isSupported\n ? globalViewerRegistry.getViewer(name)!\n : { id: 'unsupported', name: 'Unsupported', extensions: [], component: UnsupportedFileViewer };\n\n const isBinary = !isSupported || FileBrowserModel.BINARY_EXTENSIONS.has(extension);\n\n // Show loading state immediately so UI stays responsive\n runInAction(() => {\n this.isLoadingFile = true;\n });\n\n let content: string | ArrayBuffer | undefined;\n try {\n const raw = await this.fileSystemBridge.readFile(path);\n if (typeof raw === 'string') {\n if (isBinary) {\n const bytes = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) {\n bytes[i] = raw.charCodeAt(i) & 0xff;\n }\n content = bytes.buffer as ArrayBuffer;\n } else {\n content = raw;\n }\n } else if (raw instanceof ArrayBuffer) {\n if (isBinary) {\n content = raw;\n } else {\n content = new TextDecoder('utf-8').decode(raw);\n }\n } else if (ArrayBuffer.isView(raw)) {\n if (isBinary) {\n const copy = new Uint8Array(raw.byteLength);\n copy.set(new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength));\n content = copy.buffer as ArrayBuffer;\n } else {\n content = new TextDecoder('utf-8').decode(raw);\n }\n }\n } catch (err) {\n console.warn(`[FileBrowser] Failed to read file ${path}:`, err instanceof Error ? err.message : err);\n }\n\n runInAction(() => {\n this.isLoadingFile = false;\n this.openFile = {\n path,\n name,\n content,\n size,\n mimeType: FileBrowserModel.MIME_TYPES[extension] || 'application/octet-stream',\n viewer,\n };\n });\n }\n\n get viewableFiles(): Array<{ path: string; name: string; size?: number }> {\n return this.listModel.items\n .filter(item => !item.isDirectory && globalViewerRegistry.canHandle(item.name))\n .map(item => ({ path: item.path, name: item.name, size: item.size }));\n }\n\n get currentFileIndex(): number {\n if (!this.openFile) return -1;\n return this.viewableFiles.findIndex(f => f.path === this.openFile!.path);\n }\n\n get canNavigateNext(): boolean {\n return this.currentFileIndex >= 0 && this.currentFileIndex < this.viewableFiles.length - 1;\n }\n\n get canNavigatePrev(): boolean {\n return this.currentFileIndex > 0;\n }\n\n async navigateToNextFile(): Promise<void> {\n const files = this.viewableFiles;\n const idx = this.currentFileIndex;\n if (idx >= 0 && idx < files.length - 1) {\n const next = files[idx + 1]!;\n await this.openFileViewer(next.path, next.name, next.size);\n }\n }\n\n async navigateToPrevFile(): Promise<void> {\n const files = this.viewableFiles;\n const idx = this.currentFileIndex;\n if (idx > 0) {\n const prev = files[idx - 1]!;\n await this.openFileViewer(prev.path, prev.name, prev.size);\n }\n }\n\n closeFileViewer(): void {\n this.openFile = null;\n }\n\n // Preview pane\n togglePreview(): void {\n this.previewEnabled = !this.previewEnabled;\n if (!this.previewEnabled) {\n this.previewFile = null;\n }\n }\n\n async loadPreviewFile(path: string, name: string, size?: number): Promise<void> {\n if (!this.previewEnabled) return;\n\n const extension = name.split('.').pop()?.toLowerCase() || '';\n const isSupported = globalViewerRegistry.canHandle(name);\n const viewer: ViewerConfig = isSupported\n ? globalViewerRegistry.getViewer(name)!\n : { id: 'unsupported', name: 'Unsupported', extensions: [], component: UnsupportedFileViewer };\n\n runInAction(() => {\n this.previewFile = {\n path, name, size,\n mimeType: FileBrowserModel.MIME_TYPES[extension] || 'application/octet-stream',\n viewer, isLoading: true,\n };\n });\n\n const isBinary = !isSupported || FileBrowserModel.BINARY_EXTENSIONS.has(extension);\n let content: string | ArrayBuffer | undefined;\n try {\n const raw = await this.fileSystemBridge.readFile(path);\n if (typeof raw === 'string') {\n if (isBinary) {\n const bytes = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) bytes[i] = raw.charCodeAt(i) & 0xff;\n content = bytes.buffer as ArrayBuffer;\n } else {\n content = raw;\n }\n } else if (raw instanceof ArrayBuffer) {\n content = isBinary ? raw : new TextDecoder('utf-8').decode(raw);\n } else if (ArrayBuffer.isView(raw)) {\n if (isBinary) {\n const copy = new Uint8Array(raw.byteLength);\n copy.set(new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength));\n content = copy.buffer as ArrayBuffer;\n } else {\n content = new TextDecoder('utf-8').decode(raw);\n }\n }\n } catch (err) {\n console.warn(`[FileBrowser] Failed to read preview for ${path}:`, err instanceof Error ? err.message : err);\n }\n\n runInAction(() => {\n if (this.previewFile?.path === path) {\n this.previewFile = {\n path, name, content, size,\n mimeType: FileBrowserModel.MIME_TYPES[extension] || 'application/octet-stream',\n viewer, isLoading: false,\n };\n }\n });\n }\n\n clearPreview(): void {\n this.previewFile = null;\n }\n\n // Upload files\n async uploadFiles(files: FileList | File[]): Promise<void> {\n await this.uploadModel.uploadFiles(files, this.currentPath);\n await this.refresh();\n }\n\n triggerFileUpload(): void {\n const input = document.createElement('input');\n input.type = 'file';\n input.multiple = true;\n input.onchange = () => {\n if (input.files && input.files.length > 0) {\n this.uploadFiles(input.files);\n }\n };\n input.click();\n }\n\n // Rename dialog\n requestRename(itemId: string, currentName: string, path: string, source: 'list' | 'tree' = 'list'): void {\n this.renameState = { itemId, currentName, path, source };\n }\n\n async confirmRename(newName: string): Promise<void> {\n if (!this.renameState) return;\n const { path } = this.renameState;\n runInAction(() => { this.renameState = null; });\n\n for (const [key] of this.treeModel.expandedNodes) {\n if (key === path || key.startsWith(path + '/')) {\n this.treeModel.expandedNodes.delete(key);\n }\n }\n\n const parentPath = path.split('/').slice(0, -1).join('/') || '/';\n const newPath = `${parentPath}/${newName}`.replace(/\\/\\//g, '/');\n\n if (this.currentPath === path) {\n this.currentPath = newPath;\n this.selectedPath = newPath;\n this.listProvider.setPath(newPath);\n } else if (this.currentPath.startsWith(path + '/')) {\n const newCurrentPath = this.currentPath.replace(path, newPath);\n this.currentPath = newCurrentPath;\n this.selectedPath = newCurrentPath;\n this.listProvider.setPath(newCurrentPath);\n }\n\n try {\n const oldName = path.split('/').pop() || '';\n await this.listProvider.executeRename(path, newName);\n const message = `Renamed to \"${newName}\"`;\n if (this.onAction) {\n this.onAction({\n type: 'rename',\n message,\n undo: async () => {\n await this.listProvider.executeRename(newPath, oldName);\n this.refresh();\n },\n });\n } else {\n this.notify('success', message);\n }\n } catch (err) {\n this.notify('error', `Rename failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n cancelRename(): void {\n this.renameState = null;\n }\n\n // Delete dialog\n requestDelete(targets: Array<{ path: string; isDirectory: boolean; name: string }>): void {\n this.deleteState = { targets };\n }\n\n async confirmDelete(): Promise<void> {\n if (!this.deleteState) return;\n const { targets } = this.deleteState;\n runInAction(() => { this.deleteState = null; });\n\n for (const target of targets) {\n if (target.isDirectory) {\n if (this.currentPath === target.path || this.currentPath.startsWith(target.path + '/')) {\n const parentPath = target.path.split('/').slice(0, -1).join('/') || '/';\n this.currentPath = parentPath;\n this.selectedPath = parentPath;\n this.listProvider.setPath(parentPath);\n break;\n }\n for (const [key] of this.treeModel.expandedNodes) {\n if (key === target.path || key.startsWith(target.path + '/')) {\n this.treeModel.expandedNodes.delete(key);\n }\n }\n }\n }\n\n try {\n await this.listProvider.executeDelete(targets);\n const count = targets.length;\n const message = count === 1 ? `Deleted \"${targets[0]!.name}\"` : `Deleted ${count} items`;\n if (this.onAction) {\n this.onAction({ type: 'delete', message });\n } else {\n this.notify('success', message);\n }\n } catch (err) {\n this.notify('error', `Delete failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n cancelDelete(): void {\n this.deleteState = null;\n }\n\n // Create dialog\n requestCreate(parentPath: string, type: 'file' | 'folder'): void {\n this.createState = { parentPath, type };\n }\n\n async confirmCreate(name: string): Promise<void> {\n if (!this.createState) return;\n const { parentPath, type } = this.createState;\n runInAction(() => { this.createState = null; });\n try {\n await this.listProvider.executeCreate(parentPath, name, type);\n const message = `Created ${type} \"${name}\"`;\n if (this.onAction) {\n const itemPath = `${parentPath}/${name}`.replace(/\\/\\//g, '/');\n this.onAction({\n type: 'create',\n message,\n undo: async () => {\n await this.listProvider.executeDelete([{ path: itemPath, isDirectory: type === 'folder', name }]);\n this.refresh();\n },\n });\n } else {\n this.notify('success', message);\n }\n } catch (err) {\n this.notify('error', `Create ${type} failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n cancelCreate(): void {\n this.createState = null;\n }\n}\n","import React from 'react';\nimport {\n AlertDialog,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogCancel,\n} from '@anymux/ui/components/alert-dialog';\nimport { Button } from '@anymux/ui/components/button';\n\ninterface DeleteConfirmDialogProps {\n targets: Array<{ path: string; isDirectory: boolean; name: string }>;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nexport const DeleteConfirmDialog: React.FC<DeleteConfirmDialogProps> = ({\n targets,\n onConfirm,\n onCancel,\n}) => {\n return (\n <AlertDialog open onOpenChange={(open) => { if (!open) onCancel(); }}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n Delete {targets.length === 1 ? `\"${targets[0]?.name}\"` : `${targets.length} items`}?\n </AlertDialogTitle>\n <AlertDialogDescription>\n {targets.length === 1 ? (\n <>This will permanently delete <strong>{targets[0]?.name}</strong>.</>\n ) : (\n <span>\n This will permanently delete the following items:\n <ul className=\"mt-2 list-disc list-inside text-sm\">\n {targets.map((t) => (\n <li key={t.path}>{t.name}</li>\n ))}\n </ul>\n </span>\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <Button\n variant=\"destructive\"\n onClick={onConfirm}\n >\n Delete\n </Button>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n};\n","import React, { useState, useRef, useEffect } from 'react';\nimport {\n AlertDialog,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogCancel,\n} from '@anymux/ui/components/alert-dialog';\nimport { Button } from '@anymux/ui/components/button';\nimport { Input } from '@anymux/ui/components/input';\n\ninterface CreateItemDialogProps {\n type: 'file' | 'folder';\n onConfirm: (name: string) => void;\n onCancel: () => void;\n}\n\nexport const CreateItemDialog: React.FC<CreateItemDialogProps> = ({\n type,\n onConfirm,\n onCancel,\n}) => {\n const [name, setName] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n requestAnimationFrame(() => inputRef.current?.focus());\n }, []);\n\n const handleSubmit = () => {\n const trimmed = name.trim();\n if (trimmed) {\n onConfirm(trimmed);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n return (\n <AlertDialog open onOpenChange={(open) => { if (!open) onCancel(); }}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>New {type === 'folder' ? 'Folder' : 'File'}</AlertDialogTitle>\n <AlertDialogDescription>\n Enter a name for the new {type === 'folder' ? 'folder' : 'file'}.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <Input\n ref={inputRef}\n value={name}\n onChange={(e) => setName(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={type === 'folder' ? 'Folder name' : 'File name'}\n />\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <Button onClick={handleSubmit} disabled={!name.trim()}>\n Create\n </Button>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n};\n","import React from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { X, CheckCircle2, AlertCircle, Upload, FileUp } from 'lucide-react';\nimport { cn } from '../../lib/utils';\nimport { Button } from '@anymux/ui/components/button';\nimport { Progress } from '@anymux/ui/components/progress';\nimport type { UploadModel } from '../models/UploadModel';\n\ninterface UploadProgressProps {\n uploadModel: UploadModel;\n className?: string;\n}\n\n/**\n * Floating upload progress panel.\n * Shows during active uploads and briefly after completion.\n */\nexport const UploadProgress: React.FC<UploadProgressProps> = observer(({\n uploadModel,\n className,\n}) => {\n const { files, isUploading, overallProgress, completedCount, totalCount, showSummary, lastSummary } = uploadModel;\n\n // Nothing to show\n if (!isUploading && !showSummary) return null;\n\n return (\n <div\n className={cn(\n 'absolute bottom-3 right-3 z-40 w-72 rounded-lg border bg-background shadow-lg',\n className\n )}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-3 py-2 border-b bg-muted/30\">\n <div className=\"flex items-center gap-2 text-sm font-medium\">\n <FileUp className=\"w-4 h-4\" />\n {isUploading ? (\n <span>Uploading {completedCount}/{totalCount}</span>\n ) : (\n <span>Upload Complete</span>\n )}\n </div>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-5 w-5\"\n onClick={() => {\n if (!isUploading) {\n uploadModel.clear();\n } else {\n uploadModel.dismissSummary();\n }\n }}\n title=\"Dismiss\"\n >\n <X className=\"w-3 h-3\" />\n </Button>\n </div>\n\n {/* Overall progress bar */}\n {isUploading && (\n <div className=\"px-3 py-2\">\n <Progress value={overallProgress} className=\"h-1.5\" />\n <p className=\"text-xs text-muted-foreground mt-1\">\n {overallProgress}% complete\n </p>\n </div>\n )}\n\n {/* File list (max 4 visible, scrollable) */}\n <div className=\"max-h-32 overflow-y-auto\">\n {files.map((entry, idx) => (\n <div\n key={`${entry.targetPath}-${idx}`}\n className=\"flex items-center gap-2 px-3 py-1.5 text-xs border-t first:border-t-0\"\n >\n {entry.status === 'done' && (\n <CheckCircle2 className=\"w-3.5 h-3.5 text-green-500 flex-shrink-0\" />\n )}\n {entry.status === 'error' && (\n <AlertCircle className=\"w-3.5 h-3.5 text-destructive flex-shrink-0\" />\n )}\n {entry.status === 'uploading' && (\n <Upload className=\"w-3.5 h-3.5 text-primary animate-pulse flex-shrink-0\" />\n )}\n {entry.status === 'pending' && (\n <div className=\"w-3.5 h-3.5 rounded-full border border-muted-foreground/40 flex-shrink-0\" />\n )}\n <span className=\"truncate flex-1\" title={entry.file.name}>\n {entry.file.name}\n </span>\n {entry.status === 'uploading' && (\n <span className=\"text-muted-foreground flex-shrink-0\">{entry.progress}%</span>\n )}\n {entry.status === 'error' && (\n <span className=\"text-destructive flex-shrink-0 truncate max-w-[80px]\" title={entry.error}>\n {entry.error}\n </span>\n )}\n </div>\n ))}\n </div>\n\n {/* Summary footer */}\n {showSummary && lastSummary && !isUploading && (\n <div className=\"px-3 py-2 border-t bg-muted/20 text-xs text-muted-foreground\">\n {lastSummary.failed === 0 ? (\n <span className=\"text-green-600 dark:text-green-400\">\n All {lastSummary.total} file{lastSummary.total !== 1 ? 's' : ''} uploaded successfully\n </span>\n ) : (\n <span>\n {lastSummary.succeeded} succeeded, {lastSummary.failed} failed\n </span>\n )}\n </div>\n )}\n </div>\n );\n});\n\nUploadProgress.displayName = 'UploadProgress';\n","import React from 'react';\nimport { makeAutoObservable } from 'mobx';\n\n/**\n * MobX model for ViewerHost component state.\n * Manages the transient UI state for a specific viewer session:\n * dirty tracking, toolbar extras from the plugin, and loading state.\n */\nexport class ViewerHostModel {\n isDirty = false;\n isLoading = false;\n error: string | null = null;\n toolbarExtras: React.ReactNode = null;\n\n constructor() {\n makeAutoObservable(this, {\n // toolbarExtras is ReactNode, not deeply observable\n toolbarExtras: false,\n });\n }\n\n setDirty(dirty: boolean): void {\n this.isDirty = dirty;\n }\n\n setToolbarExtras(extras: React.ReactNode): void {\n this.toolbarExtras = extras;\n }\n\n setLoading(loading: boolean): void {\n this.isLoading = loading;\n }\n\n setError(error: string | null): void {\n this.error = error;\n }\n\n reset(): void {\n this.isDirty = false;\n this.isLoading = false;\n this.error = null;\n this.toolbarExtras = null;\n }\n}\n","import React, { Suspense, useState, useEffect, useCallback } from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { Loader2 } from 'lucide-react';\nimport { cn } from '../../lib/utils';\nimport type { ViewerProps } from '../registry/ViewerRegistry';\nimport type { ResolvedViewer, KeyboardShortcut, ToolbarAction } from '../registry/types';\nimport { ViewerHostModel } from '../models/ViewerHostModel';\n\nexport interface ViewerHostProps {\n /** The resolved viewer from the registry */\n viewer: ResolvedViewer;\n /** File metadata and content */\n file: ViewerProps['file'];\n /** 'full' for main viewer, 'preview' for inline pane */\n mode: 'full' | 'preview';\n /** Called when the viewer wants to close */\n onClose?: () => void;\n /** Called to save edits */\n onSave?: (content: string | ArrayBuffer) => Promise<void>;\n /** Whether the file is read-only */\n readOnly?: boolean;\n /** Optional URL for direct content access */\n contentUrl?: string;\n /** Optional lazy content fetcher */\n fetchContent?: () => Promise<string | ArrayBuffer>;\n /** Additional toolbar elements from the host (e.g., prev/next nav) */\n hostToolbar?: React.ReactNode;\n className?: string;\n}\n\n/**\n * Loading fallback shown while a lazy-loaded viewer component is being fetched.\n */\nconst ViewerLoadingFallback: React.FC<{ name: string }> = ({ name }) => (\n <div className=\"flex flex-col items-center justify-center h-full gap-2 text-muted-foreground\">\n <Loader2 className=\"w-6 h-6 animate-spin\" />\n <p className=\"text-sm\">Loading {name}...</p>\n </div>\n);\n\n/**\n * Render a single ToolbarAction as a button.\n */\nconst ToolbarActionButton: React.FC<{ action: ToolbarAction }> = ({ action }) => {\n const isEnabled = typeof action.enabled === 'function' ? action.enabled() : action.enabled !== false;\n const Icon = action.icon;\n\n return (\n <button\n onClick={action.onClick}\n disabled={!isEnabled}\n className={cn(\n 'p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors',\n 'disabled:opacity-40 disabled:pointer-events-none'\n )}\n title={action.shortcutLabel ? `${action.label} (${action.shortcutLabel})` : action.label}\n >\n {Icon ? <Icon className=\"w-3.5 h-3.5\" /> : <span className=\"text-xs px-1\">{action.label}</span>}\n </button>\n );\n};\n\n/**\n * ViewerHost: shared viewer surface component.\n *\n * Renders a resolved viewer plugin wrapped in Suspense, with:\n * - Plugin's declarative toolbarActions (left + right positions)\n * - Host toolbar slot (e.g., prev/next navigation)\n * - Dynamic toolbar extras injected by the plugin via onToolbarExtras\n * - Keyboard shortcut bindings from the plugin\n * - Dirty state tracking via onDirtyChange\n *\n * Used by FileBrowser (full viewer mode), PreviewPane, and\n * future ObjectStorageBrowser/GitBrowser integration.\n */\nexport const ViewerHost: React.FC<ViewerHostProps> = observer(({\n viewer,\n file,\n mode,\n onClose,\n onSave,\n readOnly,\n contentUrl,\n fetchContent,\n hostToolbar,\n className,\n}) => {\n const [model] = useState(() => new ViewerHostModel());\n\n // Reset model when viewer or file changes\n useEffect(() => {\n model.reset();\n }, [viewer.plugin.id, file.path, model]);\n\n // Bind keyboard shortcuts from the plugin\n useEffect(() => {\n const shortcuts = viewer.plugin.keyboardShortcuts;\n if (!shortcuts || shortcuts.length === 0) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n for (const shortcut of shortcuts) {\n if (matchShortcut(e, shortcut.key)) {\n e.preventDefault();\n shortcut.handler();\n return;\n }\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [viewer.plugin.keyboardShortcuts]);\n\n // Callback for the plugin to report dirty state\n const handleDirtyChange = useCallback((isDirty: boolean) => {\n model.setDirty(isDirty);\n }, [model]);\n\n // Callback for the plugin to inject toolbar extras\n const handleToolbarExtras = useCallback((extras: React.ReactNode) => {\n model.setToolbarExtras(extras);\n }, [model]);\n\n const { Component, plugin } = viewer;\n\n // Collect toolbar actions from the plugin\n const leftActions = (plugin.toolbarActions ?? []).filter(a => a.position === 'left');\n const rightActions = (plugin.toolbarActions ?? []).filter(a => a.position !== 'left');\n\n const hasToolbar = mode === 'full' && (\n leftActions.length > 0 ||\n rightActions.length > 0 ||\n hostToolbar ||\n model.toolbarExtras\n );\n\n // Build viewer props, only setting optional fields when defined\n // (exactOptionalPropertyTypes forbids assigning undefined to optional props)\n const viewerProps: ViewerProps = {\n file,\n className: 'h-full',\n onToolbarExtras: handleToolbarExtras,\n onDirtyChange: handleDirtyChange,\n mode,\n };\n if (onClose !== undefined) viewerProps.onClose = onClose;\n if (onSave !== undefined) viewerProps.onSave = onSave;\n if (readOnly !== undefined) viewerProps.readOnly = readOnly;\n if (fetchContent !== undefined) viewerProps.fetchContent = fetchContent;\n if (contentUrl !== undefined) viewerProps.contentUrl = contentUrl;\n\n return (\n <div className={cn('h-full flex flex-col', className)}>\n {/* Toolbar (only in full mode, and only if there are items to show) */}\n {hasToolbar && (\n <div className=\"flex items-center justify-between px-2 py-1 border-b bg-muted/20 flex-shrink-0 min-h-[36px]\">\n {/* Left side: plugin left actions */}\n <div className=\"flex items-center gap-0.5\">\n {leftActions.map(action => (\n <ToolbarActionButton key={action.id} action={action} />\n ))}\n </div>\n\n {/* Right side: plugin extras + plugin right actions + host toolbar */}\n <div className=\"flex items-center gap-1\">\n {model.toolbarExtras}\n {rightActions.map(action => (\n <ToolbarActionButton key={action.id} action={action} />\n ))}\n {hostToolbar}\n </div>\n </div>\n )}\n\n {/* Viewer content wrapped in Suspense for lazy-loaded plugins */}\n <div className=\"flex-1 min-h-0\">\n <Suspense fallback={<ViewerLoadingFallback name={plugin.name} />}>\n <Component {...viewerProps} />\n </Suspense>\n </div>\n </div>\n );\n});\n\nViewerHost.displayName = 'ViewerHost';\n\n// ---- Keyboard shortcut matching ----\n\n/**\n * Match a keyboard event against a shortcut key string.\n * Supports modifiers: ctrl, shift, alt, meta\n * Examples: 'ctrl+s', 'escape', 'ctrl+shift+p', 'pagedown'\n */\nfunction matchShortcut(e: KeyboardEvent, shortcutKey: string): boolean {\n const parts = shortcutKey.toLowerCase().split('+');\n const key = parts[parts.length - 1]!;\n const needCtrl = parts.includes('ctrl');\n const needShift = parts.includes('shift');\n const needAlt = parts.includes('alt');\n const needMeta = parts.includes('meta');\n\n if (e.ctrlKey !== needCtrl) return false;\n if (e.shiftKey !== needShift) return false;\n if (e.altKey !== needAlt) return false;\n if (e.metaKey !== needMeta) return false;\n\n return e.key.toLowerCase() === key;\n}\n","import React from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { FileText, ImageIcon, FileQuestion, Loader2, Eye } from 'lucide-react';\nimport { cn } from '../../lib/utils';\nimport type { PreviewFileState } from '../models/FileBrowserModel';\nimport { globalViewerRegistry } from '../registry/ViewerRegistry';\nimport { ViewerHost } from './ViewerHost';\n\nexport interface PreviewPaneProps {\n previewFile: PreviewFileState | null;\n className?: string;\n}\n\n/**\n * File preview pane that delegates to ViewerHost for rendering.\n *\n * Uses the plugin registry to resolve the appropriate viewer for the file,\n * rather than hardcoding viewer IDs. Falls back to a generic unsupported\n * placeholder when no plugin with preview capability is found.\n */\nexport const PreviewPane: React.FC<PreviewPaneProps> = observer(({\n previewFile,\n className,\n}) => {\n // Empty state: no file selected\n if (!previewFile) {\n return (\n <div className={cn(\"h-full flex flex-col items-center justify-center text-muted-foreground bg-muted/5\", className)}>\n <Eye className=\"w-10 h-10 mb-3 opacity-40\" />\n <p className=\"text-sm font-medium\">No file selected</p>\n <p className=\"text-xs mt-1 opacity-60\">Click a file to preview</p>\n </div>\n );\n }\n\n // Loading state\n if (previewFile.isLoading) {\n return (\n <div className={cn(\"h-full flex flex-col\", className)}>\n <PreviewHeader name={previewFile.name} size={previewFile.size} />\n <div className=\"flex-1 flex items-center justify-center\">\n <div className=\"flex flex-col items-center gap-2 text-muted-foreground\">\n <Loader2 className=\"w-6 h-6 animate-spin\" />\n <p className=\"text-sm\">Loading preview...</p>\n </div>\n </div>\n </div>\n );\n }\n\n // Resolve viewer from registry using the new plugin API\n const fileCtx = globalViewerRegistry.buildFileMatchContext(\n previewFile.name,\n {\n path: previewFile.path,\n mimeType: previewFile.mimeType,\n size: previewFile.size,\n }\n );\n const resolved = globalViewerRegistry.resolveViewer(fileCtx);\n\n // Check if the resolved plugin supports preview mode\n const canPreview = resolved?.plugin.capabilities.canPreview !== false;\n\n if (resolved && canPreview) {\n // Delegate rendering to ViewerHost in preview mode\n return (\n <div className={cn(\"h-full flex flex-col\", className)}>\n <PreviewHeader\n name={previewFile.name}\n size={previewFile.size}\n icon={getIconType(resolved.plugin.id)}\n />\n <div className=\"flex-1 min-h-0\">\n <ViewerHost\n viewer={resolved}\n file={{\n path: previewFile.path,\n name: previewFile.name,\n content: previewFile.content,\n size: previewFile.size,\n mimeType: previewFile.mimeType,\n }}\n mode=\"preview\"\n readOnly\n className=\"h-full\"\n />\n </div>\n </div>\n );\n }\n\n // Unsupported file type — no plugin can handle preview\n return (\n <div className={cn(\"h-full flex flex-col\", className)}>\n <PreviewHeader name={previewFile.name} size={previewFile.size} icon=\"unknown\" />\n <div className=\"flex-1 flex items-center justify-center\">\n <div className=\"flex flex-col items-center gap-3 text-center px-4\">\n <FileQuestion className=\"w-12 h-12 text-muted-foreground/50\" />\n <div>\n <p className=\"text-sm font-medium\">{previewFile.name}</p>\n <p className=\"text-xs text-muted-foreground mt-1\">\n Preview not available for this file type\n </p>\n </div>\n </div>\n </div>\n </div>\n );\n});\n\nPreviewPane.displayName = 'PreviewPane';\n\n// --- Helper to determine icon type from plugin ID ---\n\nfunction getIconType(pluginId: string): 'text' | 'image' | 'unknown' {\n if (pluginId.includes('image')) return 'image';\n if (pluginId.includes('text') || pluginId.includes('code') || pluginId.includes('editor')) return 'text';\n return 'unknown';\n}\n\n// --- Sub-components (unchanged from original) ---\n\nconst PreviewHeader: React.FC<{\n name: string;\n size?: number;\n icon?: 'text' | 'image' | 'unknown';\n}> = ({ name, size, icon }) => {\n const IconComponent = icon === 'image' ? ImageIcon : icon === 'text' ? FileText : FileQuestion;\n return (\n <div className=\"flex items-center gap-2 px-3 py-2 border-b bg-muted/20 flex-shrink-0 min-h-[36px]\">\n <IconComponent className=\"w-3.5 h-3.5 text-muted-foreground flex-shrink-0\" />\n <span className=\"text-xs font-medium truncate flex-1\" title={name}>\n {name}\n </span>\n {size != null && (\n <span className=\"text-[10px] text-muted-foreground flex-shrink-0\">\n {size > 1024 * 1024\n ? `${(size / (1024 * 1024)).toFixed(1)} MB`\n : `${(size / 1024).toFixed(1)} KB`\n }\n </span>\n )}\n </div>\n );\n};\n","import React, { useState, useEffect, useCallback, useRef } from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { cn } from '../../lib/utils';\nimport { Badge } from '@anymux/ui/components/badge';\nimport { Button } from '@anymux/ui/components/button';\nimport { PathBreadcrumb } from '@anymux/ui/components/path-breadcrumb';\nimport { ArrowUp, RotateCw, FolderTree, Files, X, ChevronLeft, ChevronRight, Upload, Loader2, PanelRightOpen, PanelRightClose, CheckSquare } from 'lucide-react';\nimport { BrowserError } from '@anymux/ui/components/browser-error';\nimport { Tree } from '../../tree';\nimport { ListItems, ViewTypeSelector, SearchFilter } from '../../list';\nimport { ExplorerLayout } from '../../layout/components/ExplorerLayout/ExplorerLayout';\nimport { FileBrowserModel } from '../models/FileBrowserModel';\nimport type { IFileSystem } from '@anymux/file-system';\nimport { registerDefaultViewers } from '../viewers';\nimport { globalViewerRegistry } from '../registry/ViewerRegistry';\nimport { DeleteConfirmDialog } from './DeleteConfirmDialog';\nimport { CreateItemDialog } from './CreateItemDialog';\nimport { UploadProgress } from './UploadProgress';\nimport { PreviewPane } from './PreviewPane';\nimport { ViewerHost } from './ViewerHost';\nimport { FileBrowserContext } from '../context/FileBrowserContext';\n\nexport interface FileBrowserProps {\n fileSystem: IFileSystem;\n initialPath?: string;\n className?: string;\n showBreadcrumbs?: boolean;\n showNavigation?: boolean;\n onError?: (error: { message: string }) => void;\n onPathChange?: (path: string) => void;\n onNotify?: (type: 'success' | 'error' | 'warning', message: string) => void;\n /** Structured action callback with undo support (preferred over onNotify for success actions) */\n onAction?: (action: { type: 'create' | 'rename' | 'delete' | 'upload'; message: string; undo?: () => Promise<void> }) => void;\n}\n\nexport const FileBrowser: React.FC<FileBrowserProps> = observer(({\n fileSystem,\n initialPath = '/',\n className,\n showBreadcrumbs = true,\n showNavigation = true,\n onError,\n onPathChange,\n onNotify,\n onAction,\n}) => {\n const [model] = useState(() => new FileBrowserModel(fileSystem));\n\n // Propagate errors to parent (e.g., auth errors for reconnect UI)\n useEffect(() => {\n if (model.error && onError) {\n onError({ message: model.error });\n }\n }, [model.error, onError]);\n\n // Wire callbacks into model (called directly from navigation/operation methods)\n model.onPathChange = onPathChange;\n model.onNotify = onNotify;\n model.onAction = onAction;\n\n // Native file drop support (drag files from OS into browser)\n const [isDragOver, setIsDragOver] = useState(false);\n const dragCounterRef = useRef(0);\n\n const handleNativeDragOver = useCallback((e: React.DragEvent) => {\n // Only handle native file drops, not internal DnD\n if (e.dataTransfer.types.includes('Files')) {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n }\n }, []);\n\n const handleNativeDragEnter = useCallback((e: React.DragEvent) => {\n if (e.dataTransfer.types.includes('Files')) {\n e.preventDefault();\n dragCounterRef.current++;\n setIsDragOver(true);\n }\n }, []);\n\n const handleNativeDragLeave = useCallback((e: React.DragEvent) => {\n dragCounterRef.current--;\n if (dragCounterRef.current <= 0) {\n dragCounterRef.current = 0;\n setIsDragOver(false);\n }\n }, []);\n\n const handleNativeDrop = useCallback(async (e: React.DragEvent) => {\n e.preventDefault();\n dragCounterRef.current = 0;\n setIsDragOver(false);\n\n const files = e.dataTransfer.files;\n if (!files || files.length === 0) return;\n\n // Delegate to the upload model for progress tracking\n model.uploadFiles(files);\n }, [model]);\n\n const isInitialMount = useRef(true);\n useEffect(() => {\n // On initial mount, always load. On subsequent renders, only navigate if path changed.\n if (!isInitialMount.current && initialPath === model.currentPath) return;\n isInitialMount.current = false;\n model.setInitialPath(initialPath);\n }, [initialPath, model]);\n\n useEffect(() => {\n registerDefaultViewers();\n }, []);\n\n // Keyboard navigation for viewer (left/right arrows, Escape)\n useEffect(() => {\n if (!model.openFile) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') { model.closeFileViewer(); return; }\n if (e.key === 'ArrowRight') { model.navigateToNextFile(); return; }\n if (e.key === 'ArrowLeft') { model.navigateToPrevFile(); return; }\n };\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [model, model.openFile]);\n\n const handleBreadcrumbClick = (path: string) => {\n model.navigateToPath(path);\n };\n\n // Show loading overlay while file is being read from remote\n if (model.isLoadingFile && !model.openFile) {\n return (\n <div className={cn(\"h-full w-full flex items-center justify-center bg-background\", className)}>\n <div className=\"flex flex-col items-center gap-2 text-muted-foreground\">\n <Loader2 className=\"w-6 h-6 animate-spin\" />\n <p className=\"text-sm\">Loading file...</p>\n </div>\n </div>\n );\n }\n\n // If a file is open, show the inline ACDSee-style viewer via ViewerHost\n if (model.openFile) {\n const files = model.viewableFiles;\n const idx = model.currentFileIndex;\n\n // Resolve viewer from registry using the new plugin API\n const fileCtx = globalViewerRegistry.buildFileMatchContext(\n model.openFile.name,\n {\n path: model.openFile.path,\n mimeType: model.openFile.mimeType,\n size: model.openFile.size,\n }\n );\n const resolvedViewer = globalViewerRegistry.resolveViewer(fileCtx);\n\n // Fallback: use the legacy viewer from openFile state if no plugin match\n const viewer = resolvedViewer ?? {\n plugin: {\n id: model.openFile.viewer.id,\n name: model.openFile.viewer.name,\n capabilities: { canPreview: true, canFullscreen: true },\n component: model.openFile.viewer.component,\n },\n Component: model.openFile.viewer.component,\n confidence: 0,\n };\n\n // Host-level toolbar: close button, file name, prev/next navigation\n const hostToolbar = (\n <>\n {files.length > 1 && (\n <>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => model.navigateToPrevFile()}\n disabled={!model.canNavigatePrev}\n title=\"Previous file (left arrow)\"\n >\n <ChevronLeft className=\"w-4 h-4\" />\n </Button>\n <span className=\"text-xs text-muted-foreground min-w-[4rem] text-center\">\n {idx + 1} / {files.length}\n </span>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => model.navigateToNextFile()}\n disabled={!model.canNavigateNext}\n title=\"Next file (right arrow)\"\n >\n <ChevronRight className=\"w-4 h-4\" />\n </Button>\n </>\n )}\n </>\n );\n\n return (\n <FileBrowserContext.Provider value={{\n renameState: null,\n onRenameCommit: () => {},\n onRenameCancel: () => {},\n }}>\n <div className={cn(\"h-full w-full flex flex-col bg-background\", className)}>\n {/* Host-level toolbar with close/file info */}\n <div className=\"flex items-center justify-between px-2 sm:px-3 py-1.5 sm:py-2 border-b bg-muted/30 flex-shrink-0\">\n <div className=\"flex items-center gap-1 sm:gap-2 min-w-0\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => model.closeFileViewer()} title=\"Back to files (Esc)\" className=\"flex-shrink-0\">\n <X className=\"w-4 h-4 sm:mr-1\" /> <span className=\"hidden sm:inline\">Close</span>\n </Button>\n <span className=\"text-xs sm:text-sm font-medium truncate max-w-[120px] sm:max-w-[300px]\" title={model.openFile.path}>\n {model.openFile.name}\n </span>\n {model.openFile.size != null && (\n <span className=\"text-xs text-muted-foreground hidden sm:inline\">\n ({model.openFile.size > 1024 * 1024\n ? `${(model.openFile.size / (1024 * 1024)).toFixed(1)} MB`\n : `${(model.openFile.size / 1024).toFixed(1)} KB`\n })\n </span>\n )}\n </div>\n </div>\n\n {/* ViewerHost renders the plugin component + its toolbar */}\n <div className=\"flex-1 min-h-0\">\n <ViewerHost\n viewer={viewer}\n file={{\n path: model.openFile.path,\n name: model.openFile.name,\n content: model.openFile.content,\n size: model.openFile.size,\n mimeType: model.openFile.mimeType,\n }}\n mode=\"full\"\n onClose={() => model.closeFileViewer()}\n hostToolbar={hostToolbar}\n className=\"h-full\"\n />\n </div>\n </div>\n </FileBrowserContext.Provider>\n );\n }\n\n // Header content\n const headerContent = (showBreadcrumbs || showNavigation) ? (\n <div className=\"flex items-center justify-between px-2 py-1.5 bg-muted/10\">\n <div className=\"flex items-center gap-2\">\n {showNavigation && (\n <>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => model.navigateUp()}\n disabled={!model.canNavigateUp}\n title=\"Navigate up\"\n >\n <ArrowUp className=\"w-4 h-4\" />\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => model.refresh()}\n disabled={model.isLoading}\n title=\"Refresh\"\n >\n <RotateCw className=\"w-4 h-4\" />\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => model.triggerFileUpload()}\n disabled={model.uploadModel.isUploading}\n title=\"Upload files\"\n >\n <Upload className=\"w-4 h-4\" />\n </Button>\n {model.listModel.isLoading && (\n <Loader2 className=\"w-4 h-4 animate-spin text-muted-foreground\" />\n )}\n </>\n )}\n\n {showBreadcrumbs && (\n <PathBreadcrumb\n path={model.currentPath}\n onNavigate={handleBreadcrumbClick}\n showHome\n editable\n className=\"text-[13px]\"\n />\n )}\n </div>\n </div>\n ) : undefined;\n\n // Sidebar content (Tree Navigation)\n const sidebarContent = (\n <Tree\n provider={model.treeProvider}\n model={model.treeModel}\n className=\"h-full\"\n />\n );\n\n const sidebarToolbar = (\n <h3 className=\"text-sm font-medium flex items-center gap-1.5\"><FolderTree className=\"w-4 h-4 text-muted-foreground\" />Folders</h3>\n );\n\n // Main content (List Items + optional Preview Pane)\n const listContent = model.error ? (\n <BrowserError\n error={model.error}\n context=\"File Browser\"\n onRetry={() => model.refresh()}\n onGoBack={model.canNavigateUp ? () => model.navigateUp() : undefined}\n />\n ) : (\n <ListItems\n model={model.listModel}\n className=\"h-full\"\n />\n );\n\n const previewWidth = model.previewEnabled && model.previewFile ? 360 : 0;\n\n const mainContent = model.previewEnabled ? (\n <div className=\"flex h-full w-full\">\n <div className=\"flex-1 min-w-0 h-full overflow-hidden\">\n {listContent}\n </div>\n <div\n className={cn(\n \"flex-shrink-0 h-full overflow-hidden transition-[width] duration-200 ease-in-out\",\n previewWidth > 0 && \"border-l\"\n )}\n style={{ width: previewWidth }}\n >\n {previewWidth > 0 && (\n <PreviewPane\n previewFile={model.previewFile}\n className=\"h-full\"\n />\n )}\n </div>\n </div>\n ) : listContent;\n\n const mainToolbar = (\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium flex items-center gap-1.5\"><Files className=\"w-4 h-4 text-muted-foreground\" />Contents</h3>\n {model.listModel.totalItemCount > 0 && (\n <Badge variant=\"secondary\" className=\"text-xs\">\n {model.listModel.hasSearchQuery\n ? `${model.listModel.items.length} / ${model.listModel.totalItemCount}`\n : model.listModel.totalItemCount} items\n </Badge>\n )}\n <SearchFilter model={model.listModel} />\n </div>\n <div className=\"flex items-center gap-1\">\n <ViewTypeSelector\n viewTypes={model.listProvider.supportedViewTypes}\n currentViewType={model.listModel.currentViewType}\n onViewTypeChange={(viewType) => model.listModel.setViewType(viewType)}\n />\n <Button\n variant={model.listModel.showCheckboxes ? 'secondary' : 'ghost'}\n size=\"icon\"\n className=\"h-7 w-7\"\n onClick={() => model.listModel.toggleCheckboxes()}\n title={model.listModel.showCheckboxes ? 'Hide checkboxes' : 'Show checkboxes for multi-select'}\n >\n <CheckSquare className=\"h-4 w-4\" />\n </Button>\n <Button\n variant={model.previewEnabled ? 'secondary' : 'ghost'}\n size=\"icon\"\n className=\"h-7 w-7\"\n onClick={() => model.togglePreview()}\n title={model.previewEnabled ? 'Hide preview pane' : 'Show preview pane'}\n >\n {model.previewEnabled ? (\n <PanelRightClose className=\"h-4 w-4\" />\n ) : (\n <PanelRightOpen className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </div>\n );\n\n const contextValue = {\n renameState: model.renameState ? { itemId: model.renameState.itemId, currentName: model.renameState.currentName, source: model.renameState.source } : null,\n onRenameCommit: (newName: string) => model.confirmRename(newName),\n onRenameCancel: () => model.cancelRename(),\n };\n\n return (\n <FileBrowserContext.Provider value={contextValue}>\n <div\n className={cn(\"h-full w-full relative\", className)}\n onDragOver={handleNativeDragOver}\n onDragEnter={handleNativeDragEnter}\n onDragLeave={handleNativeDragLeave}\n onDrop={handleNativeDrop}\n >\n {/* Native file drop overlay */}\n {isDragOver && (\n <div className=\"absolute inset-0 z-50 bg-blue-500/10 border-2 border-dashed border-blue-500 rounded-lg flex items-center justify-center pointer-events-none\">\n <div className=\"flex flex-col items-center gap-2 text-blue-600 dark:text-blue-400\">\n <Upload className=\"w-8 h-8\" />\n <p className=\"text-sm font-medium\">Drop files here to upload</p>\n <p className=\"text-xs text-muted-foreground\">Files will be added to {model.currentPath}</p>\n </div>\n </div>\n )}\n <ExplorerLayout\n sections={{\n header: headerContent,\n sidebar: {\n content: sidebarContent,\n toolbar: sidebarToolbar,\n width: 260\n },\n main: {\n content: mainContent,\n toolbar: mainToolbar\n }\n }}\n />\n\n {/* Delete confirmation dialog */}\n {model.deleteState && (\n <DeleteConfirmDialog\n targets={model.deleteState.targets}\n onConfirm={() => model.confirmDelete()}\n onCancel={() => model.cancelDelete()}\n />\n )}\n\n {/* Create item dialog */}\n {model.createState && (\n <CreateItemDialog\n type={model.createState.type}\n onConfirm={(name) => model.confirmCreate(name)}\n onCancel={() => model.cancelCreate()}\n />\n )}\n\n {/* Upload progress panel */}\n <UploadProgress uploadModel={model.uploadModel} />\n\n {/* Loading overlay */}\n {model.isLoading && !model.hasListItems && (\n <div className=\"absolute inset-0 bg-background/80 flex items-center justify-center z-50\">\n <div className=\"text-center\">\n <div className=\"animate-spin w-6 h-6 border-2 border-primary border-t-transparent rounded-full mx-auto\"></div>\n <p className=\"text-sm text-muted-foreground mt-2\">Loading...</p>\n </div>\n </div>\n )}\n </div>\n </FileBrowserContext.Provider>\n );\n});\n\nFileBrowser.displayName = 'FileBrowser';\n","import React from 'react';\nimport { \n File, \n FileText, \n FileImage, \n FileVideo, \n FileAudio, \n FileCode, \n Folder, \n FolderOpen,\n Archive,\n FileSpreadsheet,\n FileType,\n Settings,\n LucideIcon,\n} from 'lucide-react';\n\n// Map icon names to actual Lucide components\nconst lucideIconMap: Record<string, LucideIcon> = {\n 'file': File,\n 'file-text': FileText,\n 'file-image': FileImage,\n 'file-video': FileVideo,\n 'file-audio': FileAudio,\n 'file-code': FileCode,\n 'folder': Folder,\n 'folder-open': FolderOpen,\n 'archive': Archive,\n 'file-spreadsheet': FileSpreadsheet,\n 'file-type': FileType,\n 'settings': Settings,\n};\nimport { cn } from '../../../lib/utils';\nimport { FileBrowserItem, IconDefinition } from '../../types/FileBrowserTypes';\n\nexport interface FileIconProps {\n item: FileBrowserItem;\n getItemIcon?: (item: FileBrowserItem) => IconDefinition;\n size?: 'sm' | 'md' | 'lg' | 'xl';\n className?: string;\n isExpanded?: boolean; // For folders in tree view\n}\n\nconst sizeClasses = {\n sm: 'w-4 h-4',\n md: 'w-5 h-5',\n lg: 'w-6 h-6',\n xl: 'w-8 h-8',\n};\n\n// Default icon mapping based on file types and extensions\nconst getDefaultIcon = (item: FileBrowserItem, isExpanded?: boolean): LucideIcon => {\n if (item.type === 'directory') {\n return isExpanded ? FolderOpen : Folder;\n }\n\n // Get file extension\n const extension = item.name.split('.').pop()?.toLowerCase();\n \n // Code files\n const codeExtensions = ['js', 'jsx', 'ts', 'tsx', 'py', 'java', 'cpp', 'c', 'cs', 'php', 'rb', 'go', 'rs', 'swift', 'kt', 'scala', 'html', 'css', 'scss', 'sass', 'less', 'vue', 'svelte'];\n if (extension && codeExtensions.includes(extension)) {\n return FileCode;\n }\n\n // Image files\n const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp', 'ico', 'tiff', 'tif'];\n if (extension && imageExtensions.includes(extension)) {\n return FileImage;\n }\n\n // Video files\n const videoExtensions = ['mp4', 'avi', 'mov', 'wmv', 'flv', 'webm', 'mkv', '3gp', 'm4v'];\n if (extension && videoExtensions.includes(extension)) {\n return FileVideo;\n }\n\n // Audio files\n const audioExtensions = ['mp3', 'wav', 'flac', 'aac', 'ogg', 'wma', 'm4a', 'opus'];\n if (extension && audioExtensions.includes(extension)) {\n return FileAudio;\n }\n\n // Archive files\n const archiveExtensions = ['zip', 'rar', '7z', 'tar', 'gz', 'bz2', 'xz', 'tgz'];\n if (extension && archiveExtensions.includes(extension)) {\n return Archive;\n }\n\n // Spreadsheet files\n const spreadsheetExtensions = ['xlsx', 'xls', 'csv', 'ods'];\n if (extension && spreadsheetExtensions.includes(extension)) {\n return FileSpreadsheet;\n }\n\n // Text files\n const textExtensions = ['txt', 'md', 'mdx', 'rst', 'rtf', 'doc', 'docx', 'pdf'];\n if (extension && textExtensions.includes(extension)) {\n return FileText;\n }\n\n // Config files\n const configExtensions = ['json', 'yaml', 'yml', 'toml', 'ini', 'conf', 'config', 'env'];\n if (extension && configExtensions.includes(extension)) {\n return Settings;\n }\n\n // Font files\n const fontExtensions = ['ttf', 'otf', 'woff', 'woff2', 'eot'];\n if (extension && fontExtensions.includes(extension)) {\n return FileType;\n }\n\n // Default fallback\n return File;\n};\n\nconst FileIcon: React.FC<FileIconProps> = ({\n item,\n getItemIcon,\n size = 'md',\n className,\n isExpanded = false,\n}) => {\n // Try to get icon from provider first\n let iconDefinition: IconDefinition | undefined;\n \n try {\n iconDefinition = getItemIcon?.(item);\n } catch (error) {\n console.warn('Error getting icon from provider:', error);\n }\n\n // Determine icon to render\n let IconComponent: LucideIcon;\n let iconColor = '';\n\n if (iconDefinition) {\n // Use provider-defined icon\n if (iconDefinition.type === 'lucide' && iconDefinition.name) {\n // Map icon name to actual Lucide component\n const MappedIcon = lucideIconMap[iconDefinition.name];\n IconComponent = MappedIcon || getDefaultIcon(item, isExpanded);\n } else if (iconDefinition.type === 'custom' && iconDefinition.component) {\n // Custom React component (not implemented in this basic version)\n IconComponent = getDefaultIcon(item, isExpanded);\n } else {\n IconComponent = getDefaultIcon(item, isExpanded);\n }\n \n iconColor = iconDefinition.color || '';\n } else {\n // Use default icon mapping\n IconComponent = getDefaultIcon(item, isExpanded);\n }\n\n return (\n <IconComponent\n className={cn(\n sizeClasses[size],\n iconColor && `text-[${iconColor}]`,\n className\n )}\n aria-hidden=\"true\"\n />\n );\n};\n\nexport default FileIcon; ","import React from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { cn } from '../../../lib/utils';\nimport { FileBrowserItem as FileBrowserItemType } from '../../types/FileBrowserTypes';\nimport FileIcon from './FileIcon';\n\nexport interface FileBrowserItemProps {\n item: FileBrowserItemType;\n isSelected?: boolean;\n isHovered?: boolean;\n showDetails?: boolean;\n showIcon?: boolean;\n showSize?: boolean;\n showDate?: boolean;\n iconSize?: 'sm' | 'md' | 'lg';\n layout?: 'horizontal' | 'vertical';\n onClick?: (item: FileBrowserItemType, event: React.MouseEvent) => void;\n onDoubleClick?: (item: FileBrowserItemType, event: React.MouseEvent) => void;\n onContextMenu?: (item: FileBrowserItemType, event: React.MouseEvent) => void;\n onKeyDown?: (item: FileBrowserItemType, event: React.KeyboardEvent) => void;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n}\n\nconst iconSizeClasses = {\n sm: 'w-4 h-4',\n md: 'w-6 h-6',\n lg: 'w-8 h-8',\n};\n\nconst FileBrowserItemComponent: React.FC<FileBrowserItemProps> = observer(({\n item,\n isSelected = false,\n isHovered = false,\n showDetails = false,\n showIcon = true,\n showSize = false,\n showDate = false,\n iconSize = 'md',\n layout = 'horizontal',\n onClick,\n onDoubleClick,\n onContextMenu,\n onKeyDown,\n className,\n style,\n children,\n}) => {\n const handleClick = (event: React.MouseEvent) => {\n onClick?.(item, event);\n };\n\n const handleDoubleClick = (event: React.MouseEvent) => {\n onDoubleClick?.(item, event);\n };\n\n const handleContextMenu = (event: React.MouseEvent) => {\n event.preventDefault();\n onContextMenu?.(item, event);\n };\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n onClick?.(item, event as any);\n }\n onKeyDown?.(item, event);\n };\n\n const formatFileSize = (bytes?: number): string => {\n if (!bytes || bytes === 0) return '';\n \n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n let size = bytes;\n let unitIndex = 0;\n \n while (size >= 1024 && unitIndex < units.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n \n return `${size.toFixed(unitIndex === 0 ? 0 : 1)} ${units[unitIndex]}`;\n };\n\n const formatDate = (date?: Date | string): string => {\n if (!date) return '';\n \n const dateObj = typeof date === 'string' ? new Date(date) : date;\n return dateObj.toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n };\n\n const isVertical = layout === 'vertical';\n\n return (\n <div\n className={cn(\n 'group relative flex items-center gap-2 p-2 rounded-md cursor-pointer transition-colors',\n 'hover:bg-muted/50 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1',\n isSelected && 'bg-primary/10 border border-primary/20',\n isHovered && !isSelected && 'bg-muted/30',\n isVertical && 'flex-col text-center',\n className\n )}\n style={style}\n onClick={handleClick}\n onDoubleClick={handleDoubleClick}\n onContextMenu={handleContextMenu}\n onKeyDown={handleKeyDown}\n tabIndex={0}\n role=\"button\"\n aria-label={`${item.type === 'directory' ? 'Folder' : 'File'}: ${item.name}`}\n aria-selected={isSelected}\n >\n {/* Icon */}\n {showIcon && (\n <div className={cn('flex-shrink-0', isVertical && 'mb-1')}>\n <FileIcon\n item={item}\n size={iconSize}\n className={iconSizeClasses[iconSize]}\n />\n </div>\n )}\n\n {/* Content */}\n <div className={cn(\n 'flex-1 min-w-0',\n isVertical ? 'text-center' : 'flex items-center justify-between'\n )}>\n {/* Name and details */}\n <div className={cn('min-w-0', !isVertical && 'flex-1')}>\n <div className={cn(\n 'font-medium text-sm truncate',\n item.type === 'directory' && 'text-primary',\n isVertical && 'text-center'\n )} title={item.name}>\n {item.name}\n </div>\n \n {showDetails && (\n <div className={cn(\n 'text-xs text-muted-foreground mt-0.5',\n isVertical && 'text-center'\n )}>\n {item.type === 'directory' ? 'Folder' : 'File'}\n </div>\n )}\n </div>\n\n {/* Size and date */}\n {(showSize || showDate) && !isVertical && (\n <div className=\"flex-shrink-0 text-xs text-muted-foreground ml-2\">\n <div className=\"flex flex-col items-end gap-0.5\">\n {showSize && item.size !== undefined && (\n <span>{formatFileSize(item.size)}</span>\n )}\n {showDate && item.lastModified && (\n <span>{formatDate(item.lastModified)}</span>\n )}\n </div>\n </div>\n )}\n\n {/* Vertical layout size/date */}\n {(showSize || showDate) && isVertical && (\n <div className=\"text-xs text-muted-foreground mt-1 text-center\">\n {showSize && item.size !== undefined && (\n <div>{formatFileSize(item.size)}</div>\n )}\n {showDate && item.lastModified && (\n <div>{formatDate(item.lastModified)}</div>\n )}\n </div>\n )}\n </div>\n\n {/* Custom children */}\n {children}\n\n {/* Selection indicator */}\n {isSelected && (\n <div className=\"absolute inset-0 border-2 border-primary rounded-md pointer-events-none\" />\n )}\n </div>\n );\n});\n\nFileBrowserItemComponent.displayName = 'FileBrowserItem';\n\nexport default FileBrowserItemComponent; ","import React, { Component, ReactNode } from 'react';\nimport { AlertTriangle } from 'lucide-react';\nimport { cn } from '../../../lib/utils';\n\nexport interface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: (error: Error, errorInfo: string, onReset: () => void) => ReactNode;\n onError?: (error: Error, errorInfo: string) => void;\n className?: string;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n errorInfo: string | null;\n}\n\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = {\n hasError: false,\n error: null,\n errorInfo: null,\n };\n }\n\n static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\n return {\n hasError: true,\n error,\n };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n const errorInfoString = errorInfo.componentStack || '';\n \n this.setState({\n errorInfo: errorInfoString,\n });\n\n // Call optional error reporting callback\n this.props.onError?.(error, errorInfoString);\n\n // Log error for debugging\n console.error('FileBrowser Error Boundary caught an error:', error);\n console.error('Error Info:', errorInfo);\n }\n\n handleReset = () => {\n this.setState({\n hasError: false,\n error: null,\n errorInfo: null,\n });\n };\n\n render() {\n if (this.state.hasError) {\n const { fallback, className } = this.props;\n const { error, errorInfo } = this.state;\n\n // Use custom fallback if provided\n if (fallback && error) {\n return fallback(error, errorInfo || '', this.handleReset);\n }\n\n // Default error UI\n return (\n <div\n className={cn(\n 'flex flex-col items-center justify-center p-8 text-center border border-destructive/20 rounded-lg bg-destructive/5',\n className\n )}\n role=\"alert\"\n aria-live=\"assertive\"\n >\n <AlertTriangle \n className=\"w-12 h-12 text-destructive mb-4\" \n aria-hidden=\"true\"\n />\n \n <h2 className=\"text-lg font-semibold text-destructive mb-2\">\n Something went wrong\n </h2>\n \n <p className=\"text-sm text-muted-foreground mb-4 max-w-md\">\n {error?.message || 'An unexpected error occurred while rendering the file browser.'}\n </p>\n \n <div className=\"flex gap-2\">\n <button\n onClick={this.handleReset}\n className=\"px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 transition-colors\"\n >\n Try Again\n </button>\n \n <button\n onClick={() => window.location.reload()}\n className=\"px-4 py-2 bg-secondary text-secondary-foreground rounded-md hover:bg-secondary/90 focus:outline-none focus:ring-2 focus:ring-secondary focus:ring-offset-2 transition-colors\"\n >\n Reload Page\n </button>\n </div>\n \n {/* Error details removed to prevent build issues */}\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n\nexport default ErrorBoundary; ","import { IFileSystem } from '@anymux/file-system';\nimport { IFileBrowserProvider } from './IFileBrowserProvider';\nimport { FileBrowserItem, IconDefinition, PreviewData } from '../types/FileBrowserTypes';\nimport { LeftPanelMode } from '../models/LeftPanelManagerModel';\nimport { ViewModeDefinition } from '../models/RightPanelManagerModel';\n\ninterface CacheEntry {\n data: FileBrowserItem[];\n timestamp: number;\n lastAccessed: number;\n accessCount: number;\n}\n\ninterface CacheOptions {\n maxSize: number;\n ttlMs: number;\n enableLogging: boolean;\n}\n\nexport class FileSystemProvider implements IFileBrowserProvider {\n readonly id = 'filesystem';\n readonly name = 'File System Provider';\n readonly version = '1.0.0';\n\n private fileSystem: IFileSystem;\n private cache = new Map<string, CacheEntry>();\n private cacheOptions: CacheOptions;\n\n constructor(fileSystem: IFileSystem, cacheOptions?: Partial<CacheOptions>) {\n this.fileSystem = fileSystem;\n this.cacheOptions = {\n maxSize: 100,\n ttlMs: 30000, // 30 seconds\n enableLogging: false,\n ...cacheOptions\n };\n }\n\n async loadItems(path: string): Promise<FileBrowserItem[]> {\n try {\n const normalizedPath = this.normalizePath(path);\n \n // Check cache first\n const cached = this.getFromCache(normalizedPath);\n if (cached) {\n this.logCache(`Cache hit for ${normalizedPath}`);\n return cached;\n }\n \n this.logCache(`Cache miss for ${normalizedPath}`);\n const items = await this.fileSystem.readdir(normalizedPath, { withFileTypes: true });\n \n // Load detailed information for each item\n const itemsWithDetails = await Promise.all(\n items.map(async (item) => {\n const itemPath = this.resolvePath(normalizedPath, item.name);\n \n try {\n // Get detailed file information\n const stats = await this.fileSystem.stat(itemPath);\n \n return {\n id: itemPath,\n name: item.name,\n path: itemPath,\n type: item.isDirectory() ? 'directory' as const : 'file' as const,\n hasChildren: item.isDirectory(),\n size: stats.size,\n lastModified: new Date(stats.mtime),\n permissions: this.formatPermissions(stats.mode),\n metadata: {\n created: new Date(stats.birthtime || stats.ctime),\n accessed: new Date(stats.atime),\n isSymlink: stats.isSymbolicLink?.() || false,\n blocks: stats.blocks,\n blksize: stats.blksize,\n dev: stats.dev,\n ino: stats.ino,\n nlink: stats.nlink,\n rdev: stats.rdev,\n uid: stats.uid,\n gid: stats.gid,\n }\n };\n } catch (statError) {\n // If stat fails, return basic info without details\n console.warn(`Failed to get stats for ${itemPath}:`, statError);\n return {\n id: itemPath,\n name: item.name,\n path: itemPath,\n type: item.isDirectory() ? 'directory' as const : 'file' as const,\n hasChildren: item.isDirectory(),\n };\n }\n })\n );\n \n // Store in cache\n this.setInCache(normalizedPath, itemsWithDetails);\n \n return itemsWithDetails;\n } catch (error) {\n // Invalidate cache on error\n this.invalidateCache(this.normalizePath(path));\n \n const enhancedError = this.enhanceError(error, path, 'loadItems');\n console.error('Failed to load items:', enhancedError);\n throw enhancedError;\n }\n }\n\n normalizePath(path: string): string {\n // Normalize path separators and remove duplicate slashes\n if (!path || path === '') return '/';\n \n // Convert backslashes to forward slashes\n let normalized = path.replace(/\\\\/g, '/');\n \n // Remove duplicate slashes\n normalized = normalized.replace(/\\/+/g, '/');\n \n // Remove trailing slash unless it's root\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n \n // Ensure it starts with /\n if (!normalized.startsWith('/')) {\n normalized = '/' + normalized;\n }\n \n return normalized;\n }\n\n private formatPermissions(mode: number | undefined): string {\n if (mode === undefined) return '';\n \n // Extract permission bits (last 9 bits)\n const perms = mode & parseInt('777', 8);\n \n // Convert to rwx format\n const octal = perms.toString(8).padStart(3, '0');\n let result = '';\n \n for (let i = 0; i < 3; i++) {\n const digit = parseInt(octal[i] || '0', 10);\n result += (digit & 4) ? 'r' : '-';\n result += (digit & 2) ? 'w' : '-';\n result += (digit & 1) ? 'x' : '-';\n }\n \n return result;\n }\n\n private enhanceError(error: any, path: string, operation: string): Error {\n const message = error?.message || 'Unknown error';\n const code = error?.code || 'UNKNOWN';\n \n const enhancedError = new Error(\n `${operation} failed for path \"${path}\": ${message}`\n );\n \n // Preserve error properties\n (enhancedError as any).code = code;\n (enhancedError as any).path = path;\n (enhancedError as any).operation = operation;\n (enhancedError as any).originalError = error;\n (enhancedError as any).timestamp = new Date();\n \n return enhancedError;\n }\n\n getParentPath(path: string): string | null {\n const normalized = this.normalizePath(path);\n if (normalized === '/') return null;\n \n const parts = normalized.split('/').filter(Boolean);\n parts.pop();\n \n return parts.length === 0 ? '/' : '/' + parts.join('/');\n }\n\n resolvePath(basePath: string, relativePath: string): string {\n if (relativePath.startsWith('/')) {\n return this.normalizePath(relativePath);\n }\n \n const base = this.normalizePath(basePath);\n const resolved = base === '/' ? `/${relativePath}` : `${base}/${relativePath}`;\n return this.normalizePath(resolved);\n }\n\n getItemIcon(item: FileBrowserItem): IconDefinition {\n if (item.type === 'directory') {\n return {\n type: 'lucide',\n name: 'folder',\n color: '#3b82f6'\n };\n }\n \n // Simple file type detection based on extension\n const ext = item.name.split('.').pop()?.toLowerCase();\n const iconMap: Record<string, string> = {\n 'js': 'file-code',\n 'ts': 'file-code',\n 'jsx': 'file-code',\n 'tsx': 'file-code',\n 'html': 'file-code',\n 'css': 'file-code',\n 'json': 'file-code',\n 'md': 'file-text',\n 'txt': 'file-text',\n 'png': 'image',\n 'jpg': 'image',\n 'jpeg': 'image',\n 'gif': 'image',\n 'svg': 'image',\n 'pdf': 'file-text',\n };\n \n return {\n type: 'lucide',\n name: iconMap[ext || ''] || 'file',\n color: '#6b7280'\n };\n }\n\n getItemDisplayName(item: FileBrowserItem): string {\n return item.name;\n }\n\n async getItemPreview(item: FileBrowserItem): Promise<PreviewData | null> {\n // Basic preview support - this could be extended\n if (item.type === 'file') {\n const ext = item.name.split('.').pop()?.toLowerCase();\n \n if (['png', 'jpg', 'jpeg', 'gif', 'svg'].includes(ext || '')) {\n return {\n type: 'image',\n url: item.path // This would need to be a proper URL in a real implementation\n };\n }\n \n if (['txt', 'md', 'json', 'js', 'ts', 'css', 'html'].includes(ext || '')) {\n try {\n // For text files, we could read and preview content\n return {\n type: 'text',\n content: 'Preview not implemented'\n };\n } catch {\n return null;\n }\n }\n }\n \n return null;\n }\n\n canPerformAction(action: string, items: FileBrowserItem[]): boolean {\n // Basic action support\n const supportedActions = ['delete', 'rename', 'copy', 'move'];\n return supportedActions.includes(action) && items.length > 0;\n }\n\n async performAction(action: string, items: FileBrowserItem[]): Promise<any> {\n // This would implement actual file operations\n // For now, just return success\n console.log(`Performing action ${action} on items:`, items);\n return { success: true, message: `${action} completed` };\n }\n\n async initialize(): Promise<void> {\n // Any initialization needed\n }\n\n dispose(): void {\n // Clear cache\n this.cache.clear();\n }\n\n // Cache management methods\n private getFromCache(path: string): FileBrowserItem[] | null {\n const entry = this.cache.get(path);\n if (!entry) return null;\n\n const now = Date.now();\n \n // Check if expired\n if (now - entry.timestamp > this.cacheOptions.ttlMs) {\n this.cache.delete(path);\n this.logCache(`Cache entry expired for ${path}`);\n return null;\n }\n\n // Update access stats\n entry.lastAccessed = now;\n entry.accessCount++;\n \n return entry.data;\n }\n\n private setInCache(path: string, data: FileBrowserItem[]): void {\n const now = Date.now();\n \n // Evict oldest entries if cache is full\n if (this.cache.size >= this.cacheOptions.maxSize) {\n this.evictLeastRecentlyUsed();\n }\n\n this.cache.set(path, {\n data: [...data], // Clone to prevent mutations\n timestamp: now,\n lastAccessed: now,\n accessCount: 1\n });\n\n this.logCache(`Cached ${data.length} items for ${path}`);\n }\n\n private invalidateCache(path: string): void {\n if (this.cache.has(path)) {\n this.cache.delete(path);\n this.logCache(`Invalidated cache for ${path}`);\n }\n }\n\n private evictLeastRecentlyUsed(): void {\n let oldestPath: string | null = null;\n let oldestAccess = Date.now();\n\n for (const [path, entry] of this.cache.entries()) {\n if (entry.lastAccessed < oldestAccess) {\n oldestAccess = entry.lastAccessed;\n oldestPath = path;\n }\n }\n\n if (oldestPath) {\n this.cache.delete(oldestPath);\n this.logCache(`Evicted LRU cache entry: ${oldestPath}`);\n }\n }\n\n private logCache(message: string): void {\n if (this.cacheOptions.enableLogging) {\n console.log(`[FileSystemProvider Cache] ${message}`);\n }\n }\n\n // Public cache methods for external management\n clearCache(): void {\n this.cache.clear();\n this.logCache('Cache cleared');\n }\n\n getCacheStats(): { size: number; maxSize: number; hitRate?: number } {\n return {\n size: this.cache.size,\n maxSize: this.cacheOptions.maxSize\n };\n }\n\n // Dual-panel support\n getLeftPanelModes(): LeftPanelMode[] {\n return [\n {\n id: 'tree',\n name: 'Tree',\n icon: 'folder-tree',\n component: {} as any, // Will be set by consumer\n isAvailable: () => true\n }\n ];\n }\n\n getRightPanelViewModes(): ViewModeDefinition[] {\n return [\n {\n id: 'list',\n name: 'List',\n icon: 'list',\n applicableFor: (contentType) => contentType === 'folder'\n },\n {\n id: 'thumbnail',\n name: 'Thumbnails',\n icon: 'grid-3x3',\n applicableFor: (contentType) => contentType === 'folder'\n },\n {\n id: 'detail',\n name: 'Details',\n icon: 'info',\n applicableFor: (contentType) => contentType === 'folder'\n }\n ];\n }\n} ","import type { IFileBrowserProvider } from './IFileBrowserProvider';\nimport type { FileBrowserItem, IconDefinition, PreviewData } from '../types/FileBrowserTypes';\nimport type { IFileSystem, IGitRepo } from '@anymux/file-system';\n\ninterface GitRepositoryOptions {\n repositoryPath: string;\n branch?: string;\n enableLogging?: boolean;\n fileSystem?: IFileSystem;\n gitRepo?: IGitRepo;\n}\n\ninterface GitFileInfo {\n path: string;\n type: 'file' | 'directory' | 'symlink';\n size?: number;\n lastModified?: Date;\n sha?: string;\n staged?: boolean;\n modified?: boolean;\n}\n\nexport class GitRepositoryProvider implements IFileBrowserProvider {\n readonly id = 'git-repository';\n readonly name = 'Git Repository Provider';\n readonly version = '1.0.0';\n\n private options: GitRepositoryOptions;\n private fileSystem: IFileSystem | undefined;\n private gitRepo: IGitRepo | undefined;\n\n constructor(options: GitRepositoryOptions) {\n this.options = {\n branch: 'main',\n enableLogging: false,\n ...options\n };\n this.fileSystem = options.fileSystem;\n this.gitRepo = options.gitRepo;\n }\n\n async loadItems(path: string): Promise<FileBrowserItem[]> {\n try {\n const normalizedPath = this.normalizePath(path);\n this.log(`Loading git items for path: ${normalizedPath}`);\n\n // Delegate to real file system if provided\n if (this.fileSystem) {\n return this.loadItemsFromFileSystem(normalizedPath);\n }\n\n // Fallback to mock data\n const mockGitFiles = await this.getMockGitFiles(normalizedPath);\n\n return mockGitFiles.map(file => {\n const item: FileBrowserItem = {\n id: file.path,\n name: this.getFileName(file.path),\n path: file.path,\n type: file.type === 'directory' ? 'directory' as const : 'file' as const,\n hasChildren: file.type === 'directory',\n metadata: {\n sha: file.sha,\n staged: file.staged,\n modified: file.modified,\n gitStatus: this.getGitStatus(file)\n }\n };\n if (file.size != null) item.size = file.size;\n if (file.lastModified != null) item.lastModified = file.lastModified;\n return item;\n });\n } catch (error) {\n this.log(`Error loading git items: ${error}`);\n throw new Error(`Failed to load git repository items: ${error}`);\n }\n }\n\n private async loadItemsFromFileSystem(path: string): Promise<FileBrowserItem[]> {\n if (!this.fileSystem) return [];\n\n const entries = await this.fileSystem.readdir(path);\n const items: FileBrowserItem[] = [];\n\n for (const entry of entries) {\n const entryPath = path === '/' ? `/${entry}` : `${path}/${entry}`;\n try {\n const stat = await this.fileSystem.stat(entryPath);\n const isDir = stat.isDirectory();\n const item: FileBrowserItem = {\n id: entryPath,\n name: String(entry),\n path: entryPath,\n type: isDir ? 'directory' as const : 'file' as const,\n hasChildren: isDir,\n lastModified: stat.mtime,\n };\n if (!isDir) item.size = stat.size;\n items.push(item);\n } catch (err) {\n console.warn(`[GitRepositoryProvider] stat failed for ${entryPath}, skipping:`, err instanceof Error ? err.message : err);\n }\n }\n\n return items;\n }\n\n normalizePath(path: string): string {\n if (!path || path === '') return '/';\n\n let normalized = path.replace(/\\\\/g, '/');\n normalized = normalized.replace(/\\/+/g, '/');\n\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n\n if (!normalized.startsWith('/')) {\n normalized = '/' + normalized;\n }\n\n return normalized;\n }\n\n getParentPath(path: string): string | null {\n const normalized = this.normalizePath(path);\n if (normalized === '/') return null;\n\n const parts = normalized.split('/').filter(Boolean);\n parts.pop();\n\n return parts.length === 0 ? '/' : '/' + parts.join('/');\n }\n\n resolvePath(basePath: string, relativePath: string): string {\n if (relativePath.startsWith('/')) {\n return this.normalizePath(relativePath);\n }\n\n const base = this.normalizePath(basePath);\n const resolved = base === '/' ? `/${relativePath}` : `${base}/${relativePath}`;\n return this.normalizePath(resolved);\n }\n\n getItemIcon(item: FileBrowserItem): IconDefinition {\n const gitStatus = item.metadata?.gitStatus;\n\n if (item.type === 'directory') {\n if (gitStatus === 'modified') {\n return { type: 'lucide', name: 'folder-edit', color: '#f59e0b' };\n }\n if (gitStatus === 'staged') {\n return { type: 'lucide', name: 'folder-check', color: '#10b981' };\n }\n return { type: 'lucide', name: 'folder-git-2', color: '#3b82f6' };\n }\n\n const ext = item.name.split('.').pop()?.toLowerCase();\n const baseIcon = this.getBaseFileIcon(ext);\n\n let color = baseIcon.color;\n if (gitStatus === 'modified') {\n color = '#f59e0b';\n } else if (gitStatus === 'staged') {\n color = '#10b981';\n } else if (gitStatus === 'untracked') {\n color = '#ef4444';\n }\n\n const result: IconDefinition = { type: baseIcon.type };\n if (baseIcon.name) result.name = baseIcon.name;\n if (color) result.color = color;\n return result;\n }\n\n private getBaseFileIcon(ext?: string): IconDefinition {\n const iconMap: Record<string, string> = {\n 'gitignore': 'git-branch',\n 'gitattributes': 'git-branch',\n 'gitmodules': 'git-branch',\n 'js': 'file-code',\n 'ts': 'file-code',\n 'jsx': 'file-code',\n 'tsx': 'file-code',\n 'vue': 'file-code',\n 'html': 'file-code',\n 'css': 'file-code',\n 'scss': 'file-code',\n 'json': 'file-code',\n 'yaml': 'file-code',\n 'yml': 'file-code',\n 'md': 'file-text',\n 'txt': 'file-text',\n 'rst': 'file-text',\n 'png': 'image',\n 'jpg': 'image',\n 'jpeg': 'image',\n 'gif': 'image',\n 'svg': 'image',\n 'webp': 'image',\n 'toml': 'settings',\n 'ini': 'settings',\n 'conf': 'settings',\n 'zip': 'file-archive',\n 'tar': 'file-archive',\n 'gz': 'file-archive',\n 'pdf': 'file-text',\n 'lock': 'lock',\n };\n\n return {\n type: 'lucide',\n name: iconMap[ext || ''] || 'file',\n color: '#6b7280'\n };\n }\n\n getItemDisplayName(item: FileBrowserItem): string {\n const gitStatus = item.metadata?.gitStatus;\n\n const statusIndicators: Record<string, string> = {\n 'modified': ' ●',\n 'staged': ' ✓',\n 'untracked': ' ?',\n 'deleted': ' ✗',\n };\n\n const indicator = gitStatus ? statusIndicators[gitStatus] || '' : '';\n return item.name + indicator;\n }\n\n async getItemPreview(item: FileBrowserItem): Promise<PreviewData | null> {\n if (item.type === 'file') {\n const ext = item.name.split('.').pop()?.toLowerCase();\n\n if (['gitignore', 'gitattributes', 'gitmodules'].includes(ext || '')) {\n return {\n type: 'text',\n content: `Git configuration file: ${item.name}`\n };\n }\n\n if (['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp'].includes(ext || '')) {\n return {\n type: 'image',\n url: `git-blob://${this.options.repositoryPath}/${item.path}`\n };\n }\n\n // Read file content from real file system if available\n if (this.fileSystem && ['txt', 'md', 'json', 'js', 'ts', 'css', 'html', 'yaml', 'yml'].includes(ext || '')) {\n try {\n const content = await this.fileSystem.readFile(item.path, 'utf-8');\n return {\n type: 'text',\n content: typeof content === 'string' ? content.slice(0, 4096) : 'Binary file'\n };\n } catch {\n return { type: 'text', content: 'Unable to read file' };\n }\n }\n }\n\n return null;\n }\n\n canPerformAction(action: string, items: FileBrowserItem[]): boolean {\n const gitActions = ['stage', 'unstage', 'commit', 'revert', 'diff', 'blame'];\n const basicActions = ['view', 'copy'];\n\n const supportedActions = [...gitActions, ...basicActions];\n return supportedActions.includes(action) && items.length > 0;\n }\n\n async performAction(action: string, items: FileBrowserItem[]): Promise<any> {\n this.log(`Performing git action ${action} on items:`, items);\n\n switch (action) {\n case 'stage':\n return { success: true, message: `Staged ${items.length} files` };\n case 'unstage':\n return { success: true, message: `Unstaged ${items.length} files` };\n case 'commit':\n return { success: true, message: 'Commit created' };\n case 'revert':\n return { success: true, message: `Reverted ${items.length} files` };\n case 'diff':\n return { success: true, data: 'Diff content would go here' };\n case 'blame':\n return { success: true, data: 'Blame information would go here' };\n default:\n return { success: true, message: `${action} completed` };\n }\n }\n\n async initialize(): Promise<void> {\n this.log(`Initializing git repository provider for ${this.options.repositoryPath}`);\n }\n\n dispose(): void {\n this.log('Disposing git repository provider');\n }\n\n // Git-specific methods\n async getCurrentBranch(): Promise<string> {\n if (this.gitRepo) {\n const branches = await this.gitRepo.listBranches();\n const defaultBranch = branches.find(b => b.isDefault);\n return defaultBranch?.name || this.options.branch || 'main';\n }\n return this.options.branch || 'main';\n }\n\n async getBranches(): Promise<string[]> {\n if (this.gitRepo) {\n const branches = await this.gitRepo.listBranches();\n return branches.map(b => b.name);\n }\n return ['main', 'develop', 'feature/new-feature'];\n }\n\n async switchBranch(branch: string): Promise<void> {\n this.log(`Switching to branch: ${branch}`);\n this.options.branch = branch;\n }\n\n async getCommitHistory(path?: string, limit = 50): Promise<any[]> {\n if (this.gitRepo) {\n const options: { path?: string; maxCount?: number } = { maxCount: limit };\n if (path != null) options.path = path;\n return this.gitRepo.listCommits(options);\n }\n return [];\n }\n\n // Private helper methods\n private async getMockGitFiles(path: string): Promise<GitFileInfo[]> {\n const mockFiles: Record<string, GitFileInfo[]> = {\n '/': [\n { path: '/src', type: 'directory', lastModified: new Date() },\n { path: '/docs', type: 'directory', lastModified: new Date() },\n { path: '/package.json', type: 'file', size: 1024, lastModified: new Date(), sha: 'abc123', modified: true },\n { path: '/README.md', type: 'file', size: 2048, lastModified: new Date(), sha: 'def456' },\n { path: '/.gitignore', type: 'file', size: 512, lastModified: new Date(), sha: 'ghi789' },\n ],\n '/src': [\n { path: '/src/index.ts', type: 'file', size: 4096, lastModified: new Date(), sha: 'jkl012', staged: true },\n { path: '/src/components', type: 'directory', lastModified: new Date() },\n { path: '/src/utils.ts', type: 'file', size: 1536, lastModified: new Date(), sha: 'mno345', modified: true },\n ],\n '/docs': [\n { path: '/docs/guide.md', type: 'file', size: 8192, lastModified: new Date(), sha: 'pqr678' },\n { path: '/docs/api.md', type: 'file', size: 6144, lastModified: new Date(), sha: 'stu901' },\n ]\n };\n\n return mockFiles[path] || [];\n }\n\n private getFileName(path: string): string {\n const parts = path.split('/');\n return parts[parts.length - 1] || path;\n }\n\n private getGitStatus(file: GitFileInfo): string {\n if (file.staged) return 'staged';\n if (file.modified) return 'modified';\n return 'tracked';\n }\n\n private log(message: string, ...args: any[]): void {\n if (this.options.enableLogging) {\n console.log(`[GitRepositoryProvider] ${message}`, ...args);\n }\n }\n}\n","import { IFileBrowserProvider } from './IFileBrowserProvider';\nimport { FileBrowserItem, IconDefinition, PreviewData } from '../types/FileBrowserTypes';\nimport { LeftPanelMode } from '../models/LeftPanelManagerModel';\nimport { ViewModeDefinition } from '../models/RightPanelManagerModel';\n\n// Import Git Browser types (these would be imported from the actual Git Browser app)\ninterface GitRepositoryModel {\n path: string;\n fileTree: any[];\n isLoadingFiles: boolean;\n getFileContent(path: string): Promise<string>;\n // Add other methods as needed\n}\n\ninterface GitWrapperIntegration {\n path: string;\n fileTree: any[];\n isLoadingFiles: boolean;\n getFileContent(path: string): Promise<string>;\n // Add other methods as needed\n}\n\ninterface GitFileTreeNode {\n name: string;\n path: string;\n type: 'file' | 'directory';\n size?: number;\n children?: GitFileTreeNode[];\n}\n\nexport class GitProvider implements IFileBrowserProvider {\n readonly id = 'git';\n readonly name = 'Git Provider';\n readonly version = '1.0.0';\n\n private repository: GitRepositoryModel | GitWrapperIntegration;\n\n constructor(repository: GitRepositoryModel | GitWrapperIntegration) {\n this.repository = repository;\n }\n\n // Core data operations\n async loadItems(path: string): Promise<FileBrowserItem[]> {\n try {\n const normalizedPath = this.normalizePath(path);\n \n // Wait for file tree to load if it's currently loading\n if (this.repository.isLoadingFiles) {\n // In a real implementation, we'd wait for the loading to complete\n // For now, return empty array\n return [];\n }\n\n const fileTree = this.repository.fileTree;\n if (!fileTree || fileTree.length === 0) {\n return [];\n }\n\n // Find the items for the current path\n const items = this.getItemsForPath(normalizedPath, fileTree);\n \n return items.map(node => this.convertGitNodeToFileBrowserItem(node));\n } catch (error) {\n console.error(`Failed to load Git items from ${path}:`, error);\n throw new Error(`Failed to load Git repository items: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n\n private getItemsForPath(path: string, fileTree: GitFileTreeNode[]): GitFileTreeNode[] {\n if (path === '/' || path === '') {\n return fileTree;\n }\n\n // Navigate to the specified path\n const pathSegments = path.split('/').filter(segment => segment !== '');\n let currentNodes = fileTree;\n\n for (const segment of pathSegments) {\n const node = currentNodes.find(n => n.name === segment && n.type === 'directory');\n if (!node || !node.children) {\n return [];\n }\n currentNodes = node.children;\n }\n\n return currentNodes;\n }\n\n private convertGitNodeToFileBrowserItem(node: GitFileTreeNode): FileBrowserItem {\n return {\n id: node.path,\n name: node.name,\n path: node.path,\n type: node.type === 'directory' ? 'directory' : 'file',\n size: node.size,\n lastModified: new Date(), // Git doesn't provide this directly\n hasChildren: node.type === 'directory' && (node.children?.length || 0) > 0,\n metadata: {\n gitPath: node.path,\n isGitFile: true\n }\n };\n }\n\n // Dual-panel support\n getLeftPanelModes(): LeftPanelMode[] {\n return [\n {\n id: 'tree',\n name: 'Tree',\n icon: 'folder-tree',\n component: {} as any, // Will be set by consumer\n isAvailable: () => true\n },\n {\n id: 'git-graph',\n name: 'Git Graph',\n icon: 'git-branch',\n component: {} as any, // Will be set by consumer\n isAvailable: () => true\n }\n ];\n }\n\n getRightPanelViewModes(): ViewModeDefinition[] {\n return [\n {\n id: 'list',\n name: 'List',\n icon: 'list',\n applicableFor: (contentType) => contentType === 'folder'\n },\n {\n id: 'thumbnail',\n name: 'Thumbnails',\n icon: 'grid-3x3',\n applicableFor: (contentType) => contentType === 'folder'\n },\n {\n id: 'git-history',\n name: 'History',\n icon: 'history',\n applicableFor: (contentType) => contentType === 'file'\n },\n {\n id: 'git-diff',\n name: 'Diff',\n icon: 'git-compare',\n applicableFor: (contentType) => contentType === 'file'\n }\n ];\n }\n\n // Path operations\n normalizePath(path: string): string {\n if (!path || path === '') return '/';\n \n let normalized = path.startsWith('/') ? path : '/' + path;\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n \n return normalized;\n }\n\n getParentPath(path: string): string | null {\n const normalized = this.normalizePath(path);\n if (normalized === '/') return null;\n \n const lastSlashIndex = normalized.lastIndexOf('/');\n if (lastSlashIndex === 0) return '/';\n \n return normalized.substring(0, lastSlashIndex);\n }\n\n resolvePath(basePath: string, relativePath: string): string {\n const normalizedBase = this.normalizePath(basePath);\n \n if (normalizedBase === '/') {\n return '/' + relativePath;\n }\n \n return normalizedBase + '/' + relativePath;\n }\n\n // Item customization\n getItemIcon(item: FileBrowserItem): IconDefinition {\n if (item.type === 'directory') {\n return { type: 'lucide', name: 'folder-git-2', color: '#3b82f6' };\n }\n \n if (item.name) {\n const extension = item.name.split('.').pop()?.toLowerCase();\n switch (extension) {\n case 'js':\n case 'ts':\n case 'mjs':\n case 'cjs':\n return { type: 'lucide', name: 'file-code', color: '#f7df1e' };\n case 'jsx':\n case 'tsx':\n return { type: 'lucide', name: 'component', color: '#61dafb' };\n case 'json':\n return { type: 'lucide', name: 'braces', color: '#f7df1e' };\n case 'md':\n case 'markdown':\n return { type: 'lucide', name: 'file-text', color: '#083fa1' };\n case 'gitignore':\n case 'gitattributes':\n case 'gitmodules':\n return { type: 'lucide', name: 'git-branch', color: '#f05032' };\n case 'html':\n case 'htm':\n return { type: 'lucide', name: 'globe', color: '#e34c26' };\n case 'css':\n case 'scss':\n case 'sass':\n case 'less':\n return { type: 'lucide', name: 'palette', color: '#1572b6' };\n case 'jpg':\n case 'jpeg':\n case 'png':\n case 'gif':\n case 'webp':\n case 'svg':\n return { type: 'lucide', name: 'image', color: '#10b981' };\n default:\n return { type: 'lucide', name: 'file', color: '#6b7280' };\n }\n }\n \n return { type: 'lucide', name: 'file', color: '#6b7280' };\n }\n\n getItemDisplayName(item: FileBrowserItem): string {\n return item.name || 'Unknown';\n }\n\n // File preview capabilities\n canPreviewFile(item: FileBrowserItem): boolean {\n if (item.type !== 'file' || !item.name) return false;\n \n const extension = item.name.split('.').pop()?.toLowerCase();\n const previewableExtensions = [\n 'txt', 'md', 'markdown', 'json', 'js', 'ts', 'jsx', 'tsx', \n 'html', 'htm', 'css', 'scss', 'sass', 'less', 'xml', 'yaml', 'yml',\n 'csv', 'log', 'ini', 'conf', 'config', 'gitignore', 'gitattributes'\n ];\n \n return previewableExtensions.includes(extension || '');\n }\n\n async getFilePreview(item: FileBrowserItem): Promise<PreviewData> {\n if (!this.canPreviewFile(item)) {\n throw new Error(`Cannot preview file: ${item.name}`);\n }\n \n try {\n const content = await this.repository.getFileContent(item.path);\n \n return {\n type: 'text',\n content: content,\n metadata: {\n size: item.size || 0,\n lastModified: item.lastModified || new Date(),\n gitPath: item.path,\n encoding: 'utf8'\n }\n };\n } catch (error) {\n throw new Error(`Failed to read Git file: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n\n async getItemPreview(item: FileBrowserItem): Promise<PreviewData | null> {\n if (item.type !== 'file' || !this.canPreviewFile(item)) return null;\n \n try {\n return await this.getFilePreview(item);\n } catch (error) {\n console.warn(`Failed to preview Git file ${item.name}:`, error);\n return null;\n }\n }\n\n // Optional capabilities\n canPerformAction(action: string, items: FileBrowserItem[]): boolean {\n switch (action) {\n case 'git-checkout':\n case 'git-diff':\n case 'git-history':\n return items.length === 1;\n case 'git-stage':\n case 'git-unstage':\n return items.length > 0;\n default:\n return false;\n }\n }\n\n async performAction(action: string, items: FileBrowserItem[]): Promise<any> {\n // Git-specific actions would be implemented here\n switch (action) {\n case 'git-checkout':\n throw new Error('Git checkout action not implemented yet');\n case 'git-diff':\n throw new Error('Git diff action not implemented yet');\n case 'git-history':\n throw new Error('Git history action not implemented yet');\n case 'git-stage':\n throw new Error('Git stage action not implemented yet');\n case 'git-unstage':\n throw new Error('Git unstage action not implemented yet');\n default:\n throw new Error(`Unknown Git action: ${action}`);\n }\n }\n\n // Lifecycle\n async initialize(): Promise<void> {\n // Validate that the repository is accessible\n try {\n if (!this.repository.path) {\n throw new Error('Repository path is not set');\n }\n } catch (error) {\n throw new Error(`Failed to initialize GitProvider: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n\n dispose(): void {\n // Clean up any resources if needed\n // The Git repository models don't specify a dispose method,\n // so we don't need to do anything here\n }\n} ","import { makeAutoObservable, observable, reaction } from 'mobx';\nimport { FileBrowserItem } from '../types/FileBrowserTypes';\n\ninterface SelectionOwner {\n logger?: { info: (message: string) => void } | null;\n leftPanel?: any; // LeftPanelManagerModel\n rightPanel?: any; // RightPanelManagerModel\n navigationManager?: any; // NavigationManagerModel\n}\n\nexport class SelectionManagerModel {\n // Observable state\n selectedItems = observable.map<string, boolean>();\n lastSelectedIndex = -1;\n \n // Current selected item for coordination\n focusedItem: FileBrowserItem | null = null;\n \n // Coordination state\n isUpdatingFromPanels = false; // Prevent infinite loops\n \n private owner: SelectionOwner;\n private disposers: (() => void)[] = [];\n\n constructor(owner: SelectionOwner) {\n makeAutoObservable(this);\n \n this.owner = owner;\n \n // Set up coordination reactions\n this.setupCoordinationReactions();\n }\n\n // Computed values\n get selectedItemsArray() {\n return Array.from(this.selectedItems.keys()).filter(id => \n this.selectedItems.get(id) === true\n );\n }\n\n get hasSelection() {\n return this.selectedItemsArray.length > 0;\n }\n\n get selectionCount() {\n return this.selectedItemsArray.length;\n }\n\n get isMultipleSelection() {\n return this.selectionCount > 1;\n }\n\n isSelected = (itemId: string): boolean => {\n return this.selectedItems.get(itemId) === true;\n };\n\n // Actions\n selectItem = (itemId: string, multiSelect = false) => {\n this.owner.logger?.info(`selectItem: ${itemId}, multiSelect: ${multiSelect}`);\n \n if (!multiSelect) {\n this.clearSelection();\n }\n \n this.selectedItems.set(itemId, true);\n };\n\n deselectItem = (itemId: string) => {\n this.owner.logger?.info(`deselectItem: ${itemId}`);\n this.selectedItems.set(itemId, false);\n };\n\n toggleSelection = (itemId: string, multiSelect = false) => {\n const isCurrentlySelected = this.isSelected(itemId);\n \n if (isCurrentlySelected) {\n this.deselectItem(itemId);\n } else {\n this.selectItem(itemId, multiSelect);\n }\n };\n\n selectRange = (startItemId: string, endItemId: string, allItems: FileBrowserItem[]) => {\n this.owner.logger?.info(`selectRange: ${startItemId} to ${endItemId}`);\n \n const startIndex = allItems.findIndex(item => item.id === startItemId);\n const endIndex = allItems.findIndex(item => item.id === endItemId);\n \n if (startIndex === -1 || endIndex === -1) return;\n \n const minIndex = Math.min(startIndex, endIndex);\n const maxIndex = Math.max(startIndex, endIndex);\n \n // Clear current selection\n this.clearSelection();\n \n // Select range\n for (let i = minIndex; i <= maxIndex; i++) {\n const item = allItems[i];\n if (item) {\n this.selectedItems.set(item.id, true);\n }\n }\n };\n\n selectAll = (items: FileBrowserItem[]) => {\n this.owner.logger?.info(`selectAll: ${items.length} items`);\n \n items.forEach(item => {\n this.selectedItems.set(item.id, true);\n });\n };\n\n clearSelection = () => {\n this.owner.logger?.info('clearSelection');\n this.selectedItems.clear();\n this.lastSelectedIndex = -1;\n };\n\n invertSelection = (allItems: FileBrowserItem[]) => {\n this.owner.logger?.info(`invertSelection: ${allItems.length} total items`);\n \n allItems.forEach(item => {\n const isSelected = this.isSelected(item.id);\n this.selectedItems.set(item.id, !isSelected);\n });\n };\n\n getSelectedItems = (allItems: FileBrowserItem[]): FileBrowserItem[] => {\n return allItems.filter(item => this.isSelected(item.id));\n };\n\n // Coordination methods\n setFocusedItem = (item: FileBrowserItem | null) => {\n this.focusedItem = item;\n \n if (item && !this.isUpdatingFromPanels) {\n this.coordinateSelection(item);\n }\n \n this.owner.logger?.info(`setFocusedItem: ${item?.name || 'none'}`);\n };\n\n private coordinateSelection = (item: FileBrowserItem) => {\n if (this.isUpdatingFromPanels) return;\n \n this.isUpdatingFromPanels = true;\n \n try {\n // Update right panel based on selection\n if (this.owner.rightPanel) {\n this.owner.rightPanel.setSelectedItem(item);\n }\n \n // Update navigation if item is a directory\n if (item.type === 'directory' && this.owner.navigationManager) {\n this.owner.navigationManager.setCurrentPath(item.path);\n }\n \n this.owner.logger?.info(`Coordinated selection: ${item.name} (${item.type})`);\n \n } finally {\n this.isUpdatingFromPanels = false;\n }\n };\n\n private setupCoordinationReactions = () => {\n // React to selection changes for coordination\n const selectionReaction = reaction(\n () => ({\n selectedIds: this.selectedItemsArray,\n focusedItem: this.focusedItem\n }),\n ({ selectedIds, focusedItem }) => {\n if (this.isUpdatingFromPanels) return;\n \n this.owner.logger?.info(`Selection reaction: ${selectedIds.length} selected, focused: ${focusedItem?.name || 'none'}`);\n \n // Update panel states based on selection\n if (focusedItem) {\n this.coordinateSelection(focusedItem);\n }\n },\n { name: 'SelectionCoordination' }\n );\n \n this.disposers.push(selectionReaction);\n };\n\n // Panel-specific selection methods\n selectFromTreePanel = (item: FileBrowserItem) => {\n this.isUpdatingFromPanels = true;\n \n try {\n this.selectItem(item.id);\n this.setFocusedItem(item);\n \n // Update right panel\n if (this.owner.rightPanel) {\n this.owner.rightPanel.setSelectedItem(item);\n }\n \n this.owner.logger?.info(`Tree panel selection: ${item.name}`);\n \n } finally {\n this.isUpdatingFromPanels = false;\n }\n };\n\n selectFromRightPanel = (item: FileBrowserItem) => {\n this.isUpdatingFromPanels = true;\n \n try {\n this.selectItem(item.id);\n this.setFocusedItem(item);\n \n // TODO: Update tree panel expansion/selection when TreeNavigationView supports it\n this.owner.logger?.info(`Right panel selection: ${item.name}`);\n \n } finally {\n this.isUpdatingFromPanels = false;\n }\n };\n\n // Navigation-triggered selection\n selectFromNavigation = (path: string, allItems: FileBrowserItem[]) => {\n const item = allItems.find(item => item.path === path);\n \n if (item) {\n this.isUpdatingFromPanels = true;\n \n try {\n this.selectItem(item.id);\n this.setFocusedItem(item);\n \n this.owner.logger?.info(`Navigation selection: ${item.name}`);\n \n } finally {\n this.isUpdatingFromPanels = false;\n }\n }\n };\n\n // Cleanup\n dispose = () => {\n this.disposers.forEach(disposer => disposer());\n this.disposers = [];\n this.clearSelection();\n this.focusedItem = null;\n this.owner.logger?.info('SelectionManagerModel disposed');\n };\n} ","import { makeAutoObservable, reaction } from 'mobx';\n\ninterface NavigationOwner {\n logger?: { info: (message: string) => void } | null;\n leftPanel?: any; // LeftPanelManagerModel\n rightPanel?: any; // RightPanelManagerModel\n selectionManager?: any; // SelectionManagerModel\n}\n\nexport class NavigationManagerModel {\n // Observable state\n history: string[] = [];\n historyIndex = -1;\n \n // Coordination state\n isUpdatingFromPanels = false; // Prevent infinite loops\n \n private owner: NavigationOwner;\n private disposers: (() => void)[] = [];\n\n constructor(owner: NavigationOwner) {\n makeAutoObservable(this);\n \n this.owner = owner;\n \n // Set up coordination reactions\n this.setupCoordinationReactions();\n }\n\n // Computed values\n get canGoBack() {\n return this.historyIndex > 0;\n }\n\n get canGoForward() {\n return this.historyIndex < this.history.length - 1;\n }\n\n get currentPath() {\n return this.historyIndex >= 0 ? (this.history[this.historyIndex] ?? '/') : '/';\n }\n\n get previousPath(): string | null {\n if (!this.canGoBack) return null;\n return this.history[this.historyIndex - 1] ?? null;\n }\n\n get nextPath(): string | null {\n if (!this.canGoForward) return null;\n return this.history[this.historyIndex + 1] ?? null;\n }\n\n // Actions\n addToHistory = (path: string) => {\n const normalizedPath = this.normalizePath(path);\n this.owner.logger?.info(`addToHistory: ${normalizedPath}`);\n \n // Don't add if it's the same as current path\n if (normalizedPath === this.currentPath) {\n return;\n }\n \n // Remove any forward history when adding new path\n if (this.canGoForward) {\n this.history = this.history.slice(0, this.historyIndex + 1);\n }\n \n // Add new path\n this.history.push(normalizedPath);\n this.historyIndex = this.history.length - 1;\n \n // Limit history size to prevent memory issues\n const maxHistorySize = 100;\n if (this.history.length > maxHistorySize) {\n this.history = this.history.slice(-maxHistorySize);\n this.historyIndex = this.history.length - 1;\n }\n };\n\n goBack = (): string | null => {\n if (!this.canGoBack) {\n this.owner.logger?.info('goBack: cannot go back');\n return null;\n }\n \n this.historyIndex--;\n const path = this.currentPath;\n this.owner.logger?.info(`goBack: navigating to ${path}`);\n return path;\n };\n\n goForward = (): string | null => {\n if (!this.canGoForward) {\n this.owner.logger?.info('goForward: cannot go forward');\n return null;\n }\n \n this.historyIndex++;\n const path = this.currentPath;\n this.owner.logger?.info(`goForward: navigating to ${path}`);\n return path;\n };\n\n goToParent = (currentPath: string): string | null => {\n const normalizedPath = this.normalizePath(currentPath);\n const parentPath = this.getParentPath(normalizedPath);\n \n if (parentPath && parentPath !== normalizedPath) {\n this.owner.logger?.info(`goToParent: ${normalizedPath} -> ${parentPath}`);\n return parentPath;\n }\n \n this.owner.logger?.info(`goToParent: already at root for ${normalizedPath}`);\n return null;\n };\n\n clearHistory = () => {\n this.owner.logger?.info('clearHistory');\n this.history = [];\n this.historyIndex = -1;\n };\n\n setCurrentPath = (path: string) => {\n this.addToHistory(path);\n };\n\n navigateTo = (path: string) => {\n this.addToHistory(path);\n };\n\n // Path utilities\n normalizePath = (path: string): string => {\n if (!path || path === '') return '/';\n \n // Ensure path starts with /\n let normalized = path.startsWith('/') ? path : '/' + path;\n \n // Remove trailing slash unless it's root\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n \n // Resolve .. and . segments\n const segments = normalized.split('/').filter(segment => segment !== '');\n const resolvedSegments: string[] = [];\n \n for (const segment of segments) {\n if (segment === '..') {\n if (resolvedSegments.length > 0) {\n resolvedSegments.pop();\n }\n } else if (segment !== '.') {\n resolvedSegments.push(segment);\n }\n }\n \n return resolvedSegments.length === 0 ? '/' : '/' + resolvedSegments.join('/');\n };\n\n getParentPath = (path: string): string | null => {\n const normalized = this.normalizePath(path);\n \n if (normalized === '/') {\n return null; // Root has no parent\n }\n \n const lastSlashIndex = normalized.lastIndexOf('/');\n if (lastSlashIndex === 0) {\n return '/'; // Parent is root\n }\n \n return normalized.substring(0, lastSlashIndex);\n };\n\n getPathSegments = (path: string): string[] => {\n const normalized = this.normalizePath(path);\n if (normalized === '/') return [];\n \n return normalized.split('/').filter(segment => segment !== '');\n };\n\n joinPaths = (...paths: string[]): string => {\n const joined = paths.join('/');\n return this.normalizePath(joined);\n };\n\n // Coordination methods\n private setupCoordinationReactions = () => {\n // React to navigation changes for panel coordination\n const navigationReaction = reaction(\n () => this.currentPath,\n (currentPath) => {\n if (this.isUpdatingFromPanels || !currentPath) return;\n \n this.owner.logger?.info(`Navigation reaction: path changed to ${currentPath}`);\n \n // Update panels based on navigation\n this.coordinateNavigation(currentPath);\n },\n { name: 'NavigationCoordination' }\n );\n \n this.disposers.push(navigationReaction);\n };\n\n private coordinateNavigation = (path: string) => {\n if (this.isUpdatingFromPanels) return;\n \n this.isUpdatingFromPanels = true;\n \n try {\n // Update right panel to show the new path content\n if (this.owner.rightPanel) {\n // If navigating to a directory, clear selection and show folder content\n this.owner.rightPanel.setSelectedItem(null);\n }\n \n // Update selection manager to reflect navigation\n if (this.owner.selectionManager) {\n // Find the item for this path and set it as focused\n // This will be implemented when we have access to the items\n this.owner.logger?.info(`Navigation coordination: ${path}`);\n }\n \n } finally {\n this.isUpdatingFromPanels = false;\n }\n };\n\n // Panel-specific navigation methods\n navigateFromTreePanel = (path: string) => {\n this.isUpdatingFromPanels = true;\n \n try {\n this.navigateTo(path);\n \n // Update right panel to show folder content\n if (this.owner.rightPanel) {\n this.owner.rightPanel.setSelectedItem(null);\n }\n \n this.owner.logger?.info(`Tree panel navigation: ${path}`);\n \n } finally {\n this.isUpdatingFromPanels = false;\n }\n };\n\n navigateFromRightPanel = (path: string) => {\n this.isUpdatingFromPanels = true;\n \n try {\n this.navigateTo(path);\n \n // TODO: Update tree panel expansion when TreeNavigationView supports it\n this.owner.logger?.info(`Right panel navigation: ${path}`);\n \n } finally {\n this.isUpdatingFromPanels = false;\n }\n };\n\n // Breadcrumb navigation\n navigateFromBreadcrumb = (path: string) => {\n this.isUpdatingFromPanels = true;\n \n try {\n this.navigateTo(path);\n \n // Update both panels\n if (this.owner.rightPanel) {\n this.owner.rightPanel.setSelectedItem(null);\n }\n \n this.owner.logger?.info(`Breadcrumb navigation: ${path}`);\n \n } finally {\n this.isUpdatingFromPanels = false;\n }\n };\n\n // Enhanced navigation with coordination\n navigateToWithCoordination = (path: string, source: 'tree' | 'right' | 'breadcrumb' | 'history' = 'history') => {\n switch (source) {\n case 'tree':\n this.navigateFromTreePanel(path);\n break;\n case 'right':\n this.navigateFromRightPanel(path);\n break;\n case 'breadcrumb':\n this.navigateFromBreadcrumb(path);\n break;\n default:\n this.navigateTo(path);\n break;\n }\n };\n\n // Set selection manager reference after both managers are created\n setSelectionManager = (selectionManager: any) => {\n (this.owner as any).selectionManager = selectionManager;\n };\n\n // Cleanup\n dispose = () => {\n this.disposers.forEach(disposer => disposer());\n this.disposers = [];\n this.clearHistory();\n this.owner.logger?.info('NavigationManagerModel disposed');\n };\n} ","import { makeAutoObservable, observable } from 'mobx';\nimport { ToolbarAction, ContextAction, ActionContext } from '../types/ProviderTypes';\nimport { FileBrowserItem } from '../types/FileBrowserTypes';\n\ninterface ToolbarOwner {\n logger?: { info: (message: string) => void } | null;\n}\n\nexport class ToolbarManagerModel {\n // Observable state\n toolbarActions = observable.map<string, ToolbarAction>();\n contextActions = observable.map<string, ContextAction>();\n \n private owner: ToolbarOwner;\n\n constructor(owner: ToolbarOwner) {\n makeAutoObservable(this);\n \n this.owner = owner;\n }\n\n // Computed values\n get globalActions() {\n return Array.from(this.toolbarActions.values()).filter(action => \n action.category === 'global'\n );\n }\n\n get selectionActions() {\n return Array.from(this.toolbarActions.values()).filter(action => \n action.category === 'selection'\n );\n }\n\n get allToolbarActions() {\n return Array.from(this.toolbarActions.values());\n }\n\n get allContextActions() {\n return Array.from(this.contextActions.values());\n }\n\n // Actions\n addAction = (action: ToolbarAction) => {\n this.owner.logger?.info(`addAction: ${action.id} (${action.category || 'default'})`);\n this.toolbarActions.set(action.id, action);\n };\n\n removeAction = (actionId: string) => {\n this.owner.logger?.info(`removeAction: ${actionId}`);\n this.toolbarActions.delete(actionId);\n };\n\n updateAction = (actionId: string, updates: Partial<ToolbarAction>) => {\n const existing = this.toolbarActions.get(actionId);\n if (existing) {\n this.owner.logger?.info(`updateAction: ${actionId}`);\n this.toolbarActions.set(actionId, { ...existing, ...updates });\n }\n };\n\n addContextAction = (action: ContextAction) => {\n this.owner.logger?.info(`addContextAction: ${action.id}`);\n this.contextActions.set(action.id, action);\n };\n\n removeContextAction = (actionId: string) => {\n this.owner.logger?.info(`removeContextAction: ${actionId}`);\n this.contextActions.delete(actionId);\n };\n\n // Context-sensitive filtering\n getAvailableActions = (context: ActionContext): ToolbarAction[] => {\n return this.allToolbarActions.filter(action => {\n // Check if action is visible\n if (action.isVisible && !action.isVisible(context)) {\n return false;\n }\n \n // Check if action is enabled\n if (action.isEnabled && !action.isEnabled(context)) {\n return false;\n }\n \n return true;\n });\n };\n\n getContextActionsForItem = (context: ActionContext): ContextAction[] => {\n return this.allContextActions.filter(action => {\n // Check if action is visible\n if (action.isVisible && !action.isVisible(context)) {\n return false;\n }\n \n // Check if action is enabled\n if (action.isEnabled && !action.isEnabled(context)) {\n return false;\n }\n \n return true;\n });\n };\n\n // Action execution helpers\n canExecuteAction = (actionId: string, context: ActionContext): boolean => {\n const action = this.toolbarActions.get(actionId);\n if (!action) return false;\n \n const availableActions = this.getAvailableActions(context);\n return availableActions.some(a => a.id === actionId);\n };\n\n getActionById = (actionId: string): ToolbarAction | undefined => {\n return this.toolbarActions.get(actionId);\n };\n\n getContextActionById = (actionId: string): ContextAction | undefined => {\n return this.contextActions.get(actionId);\n };\n\n // Bulk operations\n setActions = (actions: ToolbarAction[]) => {\n this.owner.logger?.info(`setActions: ${actions.length} actions`);\n this.toolbarActions.clear();\n actions.forEach(action => {\n this.toolbarActions.set(action.id, action);\n });\n };\n\n setContextActions = (actions: ContextAction[]) => {\n this.owner.logger?.info(`setContextActions: ${actions.length} actions`);\n this.contextActions.clear();\n actions.forEach(action => {\n this.contextActions.set(action.id, action);\n });\n };\n\n clearAllActions = () => {\n this.owner.logger?.info('clearAllActions');\n this.toolbarActions.clear();\n this.contextActions.clear();\n };\n} ","import { makeAutoObservable, observable } from 'mobx';\nimport { TreeViewSettings } from '../../types/ViewModeTypes';\nimport { FileBrowserItem } from '../../types/FileBrowserTypes';\n\nexport class TreeViewUIModel {\n // Tree-specific state\n expandedFolders = observable.map<string, boolean>();\n indentSize = 20;\n showConnectors = true;\n expandOnSingleClick = false;\n collapseOnSecondClick = true;\n rememberExpansion = true;\n \n // Settings\n settings: TreeViewSettings = {};\n \n // Owner reference for logging\n private owner: any;\n\n constructor(owner: any) {\n makeAutoObservable(this);\n \n this.owner = owner;\n this.initializeSettings();\n }\n\n get logger() {\n return this.owner.logger;\n }\n\n // Computed values\n get expandedFoldersArray() {\n return Array.from(this.expandedFolders.keys()).filter(key => \n this.expandedFolders.get(key)\n );\n }\n\n // Actions\n expandFolder = (path: string) => {\n this.logger?.info(`expandFolder: ${path}`);\n this.expandedFolders.set(path, true);\n };\n\n collapseFolder = (path: string) => {\n this.logger?.info(`collapseFolder: ${path}`);\n this.expandedFolders.set(path, false);\n };\n\n toggleFolder = (path: string) => {\n const isExpanded = this.isFolderExpanded(path);\n if (isExpanded) {\n this.collapseFolder(path);\n } else {\n this.expandFolder(path);\n }\n };\n\n isFolderExpanded = (path: string): boolean => {\n return this.expandedFolders.get(path) || false;\n };\n\n hasChildren = (item: FileBrowserItem): boolean => {\n return item.type === 'directory' && (Boolean(item.hasChildren) || Boolean(item.children && item.children.length > 0));\n };\n\n sortTreeNodes = (nodes: FileBrowserItem[]): FileBrowserItem[] => {\n return [...nodes].sort((a, b) => {\n // Directories first\n if (a.type === 'directory' && b.type !== 'directory') return -1;\n if (b.type === 'directory' && a.type !== 'directory') return 1;\n \n // Then alphabetical\n return a.name.localeCompare(b.name);\n });\n };\n\n expandAll = () => {\n this.logger?.info('expandAll');\n // This would need access to all items to expand all folders\n // Implementation depends on how we access the parent model's items\n };\n\n collapseAll = () => {\n this.logger?.info('collapseAll');\n this.expandedFolders.clear();\n };\n\n updateSettings = (newSettings: Partial<TreeViewSettings>) => {\n this.logger?.info('updateSettings', newSettings);\n this.settings = { ...this.settings, ...newSettings };\n \n // Apply settings to local properties\n if (newSettings.indentSize !== undefined) {\n this.indentSize = newSettings.indentSize;\n }\n if (newSettings.showConnectors !== undefined) {\n this.showConnectors = newSettings.showConnectors;\n }\n if (newSettings.expandOnSingleClick !== undefined) {\n this.expandOnSingleClick = newSettings.expandOnSingleClick;\n }\n if (newSettings.collapseOnSecondClick !== undefined) {\n this.collapseOnSecondClick = newSettings.collapseOnSecondClick;\n }\n if (newSettings.rememberExpansion !== undefined) {\n this.rememberExpansion = newSettings.rememberExpansion;\n }\n };\n\n // Private methods\n private initializeSettings() {\n this.settings = {\n indentSize: this.indentSize,\n showConnectors: this.showConnectors,\n expandOnSingleClick: this.expandOnSingleClick,\n collapseOnSecondClick: this.collapseOnSecondClick,\n rememberExpansion: this.rememberExpansion,\n defaultSortField: 'name',\n defaultSortDirection: 'asc',\n };\n }\n\n // Cleanup\n dispose() {\n this.logger?.info('TreeViewUIModel disposing');\n this.expandedFolders.clear();\n }\n} ","import { makeAutoObservable, observable } from 'mobx';\nimport { ListViewSettings } from '../../types/ViewModeTypes';\n\nexport interface SortCriteria {\n field: string;\n direction: 'asc' | 'desc';\n}\n\nexport interface ColumnDefinition {\n id: string;\n label: string;\n field: string;\n width: number;\n minWidth: number;\n maxWidth?: number;\n resizable: boolean;\n sortable: boolean;\n visible: boolean;\n align?: 'left' | 'center' | 'right';\n format?: (value: any) => string;\n}\n\ninterface ListViewOwner {\n logger?: { info: (message: string) => void } | null;\n}\n\nexport class ListViewUIModel {\n // Column management\n columns = observable.map<string, ColumnDefinition>();\n columnOrder: string[] = [];\n \n // Sorting state\n currentSort: SortCriteria | null = null;\n \n // Settings\n settings: ListViewSettings = {};\n \n // UI state\n showHeader = true;\n striped = true;\n compact = false;\n hoverable = true;\n \n // Owner reference for logging\n private owner: ListViewOwner;\n\n constructor(owner: ListViewOwner) {\n makeAutoObservable(this);\n \n this.owner = owner;\n this.initializeDefaultColumns();\n }\n\n get logger() {\n return this.owner.logger;\n }\n\n // Computed values\n get visibleColumns() {\n return this.columnOrder\n .map(id => this.columns.get(id))\n .filter(col => col && col.visible) as ColumnDefinition[];\n }\n\n get sortableColumns() {\n return Array.from(this.columns.values()).filter(col => col.sortable);\n }\n\n get allColumns() {\n return Array.from(this.columns.values());\n }\n\n get totalWidth() {\n return this.visibleColumns.reduce((sum, col) => sum + col.width, 0);\n }\n\n // Actions\n addColumn = (column: ColumnDefinition) => {\n this.logger?.info(`addColumn: ${column.id}`);\n this.columns.set(column.id, column);\n if (!this.columnOrder.includes(column.id)) {\n this.columnOrder.push(column.id);\n }\n };\n\n removeColumn = (columnId: string) => {\n this.logger?.info(`removeColumn: ${columnId}`);\n this.columns.delete(columnId);\n this.columnOrder = this.columnOrder.filter(id => id !== columnId);\n };\n\n updateColumn = (columnId: string, updates: Partial<ColumnDefinition>) => {\n const existing = this.columns.get(columnId);\n if (existing) {\n this.logger?.info(`updateColumn: ${columnId}`);\n this.columns.set(columnId, { ...existing, ...updates });\n }\n };\n\n resizeColumn = (columnId: string, width: number) => {\n const column = this.columns.get(columnId);\n if (column && column.resizable) {\n const constrainedWidth = Math.max(\n column.minWidth,\n column.maxWidth ? Math.min(width, column.maxWidth) : width\n );\n this.updateColumn(columnId, { width: constrainedWidth });\n }\n };\n\n reorderColumns = (fromIndex: number, toIndex: number) => {\n this.logger?.info(`reorderColumns: ${fromIndex} -> ${toIndex}`);\n const newOrder = [...this.columnOrder];\n const [moved] = newOrder.splice(fromIndex, 1);\n if (moved) {\n newOrder.splice(toIndex, 0, moved);\n this.columnOrder = newOrder;\n }\n };\n\n showColumn = (columnId: string) => {\n this.updateColumn(columnId, { visible: true });\n };\n\n hideColumn = (columnId: string) => {\n this.updateColumn(columnId, { visible: false });\n };\n\n toggleColumnVisibility = (columnId: string) => {\n const column = this.columns.get(columnId);\n if (column) {\n this.updateColumn(columnId, { visible: !column.visible });\n }\n };\n\n // Sorting\n setSortCriteria = (field: string, direction: 'asc' | 'desc') => {\n this.logger?.info(`setSortCriteria: ${field} ${direction}`);\n this.currentSort = { field, direction };\n };\n\n toggleSort = (field: string) => {\n if (this.currentSort?.field === field) {\n // Toggle direction\n const newDirection = this.currentSort.direction === 'asc' ? 'desc' : 'asc';\n this.setSortCriteria(field, newDirection);\n } else {\n // Set new field with ascending direction\n this.setSortCriteria(field, 'asc');\n }\n };\n\n clearSort = () => {\n this.logger?.info('clearSort');\n this.currentSort = null;\n };\n\n // Settings management\n updateSettings = (newSettings: Partial<ListViewSettings>) => {\n this.logger?.info('updateSettings');\n this.settings = { ...this.settings, ...newSettings };\n };\n\n // Column presets\n resetToDefaults = () => {\n this.logger?.info('resetToDefaults');\n this.columns.clear();\n this.columnOrder = [];\n this.currentSort = null;\n this.initializeDefaultColumns();\n };\n\n saveColumnLayout = (name: string) => {\n this.logger?.info(`saveColumnLayout: ${name}`);\n // This would save the current column configuration\n // Implementation depends on persistence layer\n };\n\n loadColumnLayout = (name: string) => {\n this.logger?.info(`loadColumnLayout: ${name}`);\n // This would load a saved column configuration\n // Implementation depends on persistence layer\n };\n\n // Private methods\n private initializeDefaultColumns() {\n const defaultColumns: ColumnDefinition[] = [\n {\n id: 'name',\n label: 'Name',\n field: 'name',\n width: 200,\n minWidth: 120,\n resizable: true,\n sortable: true,\n visible: true,\n align: 'left',\n },\n {\n id: 'size',\n label: 'Size',\n field: 'size',\n width: 100,\n minWidth: 80,\n resizable: true,\n sortable: true,\n visible: true,\n align: 'right',\n format: (value: number) => {\n if (value == null) return '-';\n const units = ['B', 'KB', 'MB', 'GB'];\n let size = value;\n let unitIndex = 0;\n while (size >= 1024 && unitIndex < units.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n return `${size.toFixed(1)} ${units[unitIndex]}`;\n },\n },\n {\n id: 'lastModified',\n label: 'Modified',\n field: 'lastModified',\n width: 150,\n minWidth: 120,\n resizable: true,\n sortable: true,\n visible: true,\n align: 'left',\n format: (value: Date) => {\n if (!value) return '-';\n return value.toLocaleDateString();\n },\n },\n {\n id: 'type',\n label: 'Type',\n field: 'type',\n width: 80,\n minWidth: 60,\n resizable: true,\n sortable: true,\n visible: false, // Hidden by default\n align: 'left',\n },\n ];\n\n defaultColumns.forEach(col => {\n this.columns.set(col.id, col);\n this.columnOrder.push(col.id);\n });\n\n // Set default sort\n this.currentSort = { field: 'name', direction: 'asc' };\n }\n\n // Cleanup\n dispose() {\n this.logger?.info('ListViewUIModel disposing');\n this.columns.clear();\n this.columnOrder = [];\n this.currentSort = null;\n }\n} ","import { makeAutoObservable } from 'mobx';\nimport { ThumbnailViewSettings } from '../../types/ViewModeTypes';\n\ninterface ThumbnailOwner {\n logger?: { info: (message: string) => void } | null;\n}\n\nexport class ThumbnailViewUIModel {\n // Thumbnail settings\n thumbnailSize = 128;\n gridSpacing = 16;\n aspectRatio = 1;\n showFilenames = true;\n showFileSize = false;\n showDate = false;\n loadThumbnails = true;\n thumbnailQuality: 'low' | 'medium' | 'high' = 'medium';\n \n // Grid layout\n columnsPerRow = 'auto' as number | 'auto';\n \n // Settings\n settings: ThumbnailViewSettings = {};\n \n // Preview loading state\n loadingThumbnails = new Set<string>();\n failedThumbnails = new Set<string>();\n \n // Owner reference for logging\n private owner: ThumbnailOwner;\n\n constructor(owner: ThumbnailOwner) {\n makeAutoObservable(this);\n \n this.owner = owner;\n this.initializeSettings();\n }\n\n get logger() {\n return this.owner.logger;\n }\n\n // Computed values\n get itemWidth() {\n return this.thumbnailSize + this.gridSpacing;\n }\n\n get itemHeight() {\n return this.thumbnailSize / this.aspectRatio + \n (this.showFilenames ? 24 : 0) + \n (this.showFileSize || this.showDate ? 16 : 0) + \n this.gridSpacing;\n }\n\n get isLoadingAnyThumbnails() {\n return this.loadingThumbnails.size > 0;\n }\n\n get thumbnailSizePresets() {\n return [\n { label: 'Small', value: 64 },\n { label: 'Medium', value: 128 },\n { label: 'Large', value: 192 },\n { label: 'Extra Large', value: 256 },\n ];\n }\n\n // Actions\n setThumbnailSize = (size: number) => {\n this.logger?.info(`setThumbnailSize: ${size}`);\n this.thumbnailSize = Math.max(32, Math.min(512, size));\n };\n\n setGridSpacing = (spacing: number) => {\n this.logger?.info(`setGridSpacing: ${spacing}`);\n this.gridSpacing = Math.max(0, Math.min(32, spacing));\n };\n\n setAspectRatio = (ratio: number) => {\n this.logger?.info(`setAspectRatio: ${ratio}`);\n this.aspectRatio = Math.max(0.5, Math.min(2, ratio));\n };\n\n setColumnsPerRow = (columns: number | 'auto') => {\n this.logger?.info(`setColumnsPerRow: ${columns}`);\n this.columnsPerRow = columns;\n };\n\n toggleShowFilenames = () => {\n this.logger?.info(`toggleShowFilenames: ${!this.showFilenames}`);\n this.showFilenames = !this.showFilenames;\n };\n\n toggleShowFileSize = () => {\n this.logger?.info(`toggleShowFileSize: ${!this.showFileSize}`);\n this.showFileSize = !this.showFileSize;\n };\n\n toggleShowDate = () => {\n this.logger?.info(`toggleShowDate: ${!this.showDate}`);\n this.showDate = !this.showDate;\n };\n\n setThumbnailQuality = (quality: 'low' | 'medium' | 'high') => {\n this.logger?.info(`setThumbnailQuality: ${quality}`);\n this.thumbnailQuality = quality;\n };\n\n // Preview loading state management\n setThumbnailLoading = (itemId: string, loading: boolean) => {\n if (loading) {\n this.loadingThumbnails.add(itemId);\n this.failedThumbnails.delete(itemId);\n } else {\n this.loadingThumbnails.delete(itemId);\n }\n };\n\n setThumbnailFailed = (itemId: string) => {\n this.loadingThumbnails.delete(itemId);\n this.failedThumbnails.add(itemId);\n };\n\n setThumbnailSuccess = (itemId: string) => {\n this.loadingThumbnails.delete(itemId);\n this.failedThumbnails.delete(itemId);\n };\n\n isThumbnailLoading = (itemId: string): boolean => {\n return this.loadingThumbnails.has(itemId);\n };\n\n isThumbnailFailed = (itemId: string): boolean => {\n return this.failedThumbnails.has(itemId);\n };\n\n clearThumbnailStates = () => {\n this.logger?.info('clearThumbnailStates');\n this.loadingThumbnails.clear();\n this.failedThumbnails.clear();\n };\n\n // Layout calculation\n calculateGridLayout = (containerWidth: number): { columns: number; itemsPerRow: number } => {\n if (this.columnsPerRow === 'auto') {\n const columns = Math.floor(containerWidth / this.itemWidth);\n return {\n columns: Math.max(1, columns),\n itemsPerRow: Math.max(1, columns),\n };\n } else {\n return {\n columns: this.columnsPerRow,\n itemsPerRow: this.columnsPerRow,\n };\n }\n };\n\n // Settings management\n updateSettings = (newSettings: Partial<ThumbnailViewSettings>) => {\n this.logger?.info('updateSettings');\n this.settings = { ...this.settings, ...newSettings };\n \n // Apply settings to local properties\n if (newSettings.thumbnailSize !== undefined) {\n this.setThumbnailSize(newSettings.thumbnailSize);\n }\n if (newSettings.aspectRatio !== undefined) {\n this.setAspectRatio(newSettings.aspectRatio);\n }\n if (newSettings.showFilenames !== undefined) {\n this.showFilenames = newSettings.showFilenames;\n }\n if (newSettings.showFileSize !== undefined) {\n this.showFileSize = newSettings.showFileSize;\n }\n if (newSettings.showDate !== undefined) {\n this.showDate = newSettings.showDate;\n }\n if (newSettings.gridSpacing !== undefined) {\n this.setGridSpacing(newSettings.gridSpacing);\n }\n if (newSettings.loadThumbnails !== undefined) {\n this.loadThumbnails = newSettings.loadThumbnails;\n }\n if (newSettings.thumbnailQuality !== undefined) {\n this.setThumbnailQuality(newSettings.thumbnailQuality);\n }\n };\n\n // Presets\n applyPreset = (preset: 'compact' | 'balanced' | 'detailed') => {\n this.logger?.info(`applyPreset: ${preset}`);\n \n switch (preset) {\n case 'compact':\n this.setThumbnailSize(64);\n this.setGridSpacing(8);\n this.showFilenames = true;\n this.showFileSize = false;\n this.showDate = false;\n break;\n case 'balanced':\n this.setThumbnailSize(128);\n this.setGridSpacing(16);\n this.showFilenames = true;\n this.showFileSize = true;\n this.showDate = false;\n break;\n case 'detailed':\n this.setThumbnailSize(192);\n this.setGridSpacing(24);\n this.showFilenames = true;\n this.showFileSize = true;\n this.showDate = true;\n break;\n }\n };\n\n resetToDefaults = () => {\n this.logger?.info('resetToDefaults');\n this.thumbnailSize = 128;\n this.gridSpacing = 16;\n this.aspectRatio = 1;\n this.showFilenames = true;\n this.showFileSize = false;\n this.showDate = false;\n this.loadThumbnails = true;\n this.thumbnailQuality = 'medium';\n this.columnsPerRow = 'auto';\n this.clearThumbnailStates();\n this.initializeSettings();\n };\n\n // Private methods\n private initializeSettings() {\n this.settings = {\n thumbnailSize: this.thumbnailSize,\n aspectRatio: this.aspectRatio,\n showFilenames: this.showFilenames,\n showFileSize: this.showFileSize,\n showDate: this.showDate,\n gridSpacing: this.gridSpacing,\n loadThumbnails: this.loadThumbnails,\n thumbnailQuality: this.thumbnailQuality,\n };\n }\n\n // Cleanup\n dispose() {\n this.logger?.info('ThumbnailViewUIModel disposing');\n this.clearThumbnailStates();\n }\n} ","import { makeAutoObservable } from 'mobx';\nimport { TreemapViewSettings } from '../../types/ViewModeTypes';\nimport { FileBrowserItem } from '../../types/FileBrowserTypes';\n\ninterface TreemapOwner {\n logger?: { info: (message: string) => void } | null;\n}\n\nexport interface TreemapNode {\n id: string;\n name: string;\n size: number;\n type: 'file' | 'directory';\n children?: TreemapNode[];\n depth: number;\n x: number;\n y: number;\n width: number;\n height: number;\n color?: string;\n}\n\nexport class TreemapViewUIModel {\n // Treemap settings\n minTileSize = 10;\n maxDepth = 3;\n showLabels = true;\n showSizes = true;\n colorScheme: 'type' | 'size' | 'date' | 'custom' = 'type';\n animationDuration = 300;\n \n // Layout settings\n padding = 2;\n borderWidth = 1;\n aspectRatio = 1.618; // Golden ratio\n \n // Interaction settings\n enableZoom = true;\n enableDrillDown = true;\n showTooltips = true;\n \n // Settings\n settings: TreemapViewSettings = {};\n \n // Current state\n currentRoot: string | null = null;\n zoomLevel = 1;\n \n // Owner reference for logging\n private owner: TreemapOwner;\n\n constructor(owner: TreemapOwner) {\n makeAutoObservable(this);\n \n this.owner = owner;\n this.initializeSettings();\n }\n\n get logger() {\n return this.owner.logger;\n }\n\n // Computed values\n get effectiveMinTileSize() {\n return this.minTileSize * this.zoomLevel;\n }\n\n get colorSchemes() {\n return [\n { id: 'type', label: 'File Type', description: 'Color by file type' },\n { id: 'size', label: 'File Size', description: 'Color by file size' },\n { id: 'depth', label: 'Directory Depth', description: 'Color by directory depth' },\n { id: 'extension', label: 'File Extension', description: 'Color by file extension' },\n ];\n }\n\n // Actions\n setMinTileSize = (size: number) => {\n this.logger?.info(`setMinTileSize: ${size}`);\n this.minTileSize = Math.max(5, Math.min(50, size));\n };\n\n setMaxDepth = (depth: number) => {\n this.logger?.info(`setMaxDepth: ${depth}`);\n this.maxDepth = Math.max(1, Math.min(10, depth));\n };\n\n setColorScheme = (scheme: 'type' | 'size' | 'date' | 'custom') => {\n this.logger?.info(`setColorScheme: ${scheme}`);\n this.colorScheme = scheme;\n };\n\n setPadding = (padding: number) => {\n this.logger?.info(`setPadding: ${padding}`);\n this.padding = Math.max(0, Math.min(10, padding));\n };\n\n setZoomLevel = (level: number) => {\n this.logger?.info(`setZoomLevel: ${level}`);\n this.zoomLevel = Math.max(0.1, Math.min(5, level));\n };\n\n toggleShowLabels = () => {\n this.logger?.info(`toggleShowLabels: ${!this.showLabels}`);\n this.showLabels = !this.showLabels;\n };\n\n toggleShowSizes = () => {\n this.logger?.info(`toggleShowSizes: ${!this.showSizes}`);\n this.showSizes = !this.showSizes;\n };\n\n toggleEnableZoom = () => {\n this.logger?.info(`toggleEnableZoom: ${!this.enableZoom}`);\n this.enableZoom = !this.enableZoom;\n };\n\n toggleEnableDrillDown = () => {\n this.logger?.info(`toggleEnableDrillDown: ${!this.enableDrillDown}`);\n this.enableDrillDown = !this.enableDrillDown;\n };\n\n // Navigation\n drillDown = (nodeId: string) => {\n if (this.enableDrillDown) {\n this.logger?.info(`drillDown: ${nodeId}`);\n this.currentRoot = nodeId;\n }\n };\n\n drillUp = () => {\n if (this.currentRoot) {\n this.logger?.info('drillUp');\n // This would need access to parent hierarchy\n // Implementation depends on how we access the parent model's items\n this.currentRoot = null;\n }\n };\n\n resetView = () => {\n this.logger?.info('resetView');\n this.currentRoot = null;\n this.zoomLevel = 1;\n };\n\n // Treemap calculation helpers\n calculateTreemapLayout = (\n items: FileBrowserItem[], \n width: number, \n height: number\n ): TreemapNode[] => {\n // Convert items to treemap nodes with size calculation\n const nodes = this.itemsToTreemapNodes(items);\n \n // Apply squarified treemap algorithm\n return this.squarify(nodes, width, height);\n };\n\n private itemsToTreemapNodes = (items: FileBrowserItem[]): TreemapNode[] => {\n return items.map(item => ({\n id: item.id,\n name: item.name,\n size: this.calculateItemSize(item),\n type: item.type,\n depth: 0,\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n color: this.getItemColor(item),\n }));\n };\n\n private calculateItemSize = (item: FileBrowserItem): number => {\n // Default size calculation - can be overridden by providers\n if (item.type === 'file') {\n return item.size || 1;\n } else {\n // For directories, use number of children or default size\n return item.children?.length || 10;\n }\n };\n\n private getItemColor = (item: FileBrowserItem): string => {\n switch (this.colorScheme) {\n case 'type':\n return item.type === 'directory' ? '#4A90E2' : '#7ED321';\n case 'size':\n const size = item.size || 0;\n if (size < 1024) return '#50E3C2';\n if (size < 1024 * 1024) return '#F5A623';\n return '#D0021B';\n case 'date':\n // This would need date information from the file\n return '#9013FE';\n case 'custom':\n const ext = item.name.split('.').pop()?.toLowerCase() || '';\n return this.getExtensionColor(ext);\n default:\n return '#4A90E2';\n }\n };\n\n private getExtensionColor = (extension: string): string => {\n const colorMap: Record<string, string> = {\n 'js': '#F7DF1E',\n 'ts': '#3178C6',\n 'html': '#E34F26',\n 'css': '#1572B6',\n 'json': '#000000',\n 'md': '#083FA1',\n 'txt': '#808080',\n 'pdf': '#FF0000',\n 'jpg': '#4CAF50',\n 'png': '#4CAF50',\n 'gif': '#4CAF50',\n };\n return colorMap[extension] || '#9E9E9E';\n };\n\n private squarify = (nodes: TreemapNode[], width: number, height: number): TreemapNode[] => {\n // Simplified squarified treemap algorithm\n // In a real implementation, this would be more sophisticated\n const totalSize = nodes.reduce((sum, node) => sum + node.size, 0);\n \n let x = 0;\n let y = 0;\n let currentRowHeight = 0;\n \n return nodes.map(node => {\n const area = (node.size / totalSize) * width * height;\n const nodeWidth = Math.sqrt(area * this.aspectRatio);\n const nodeHeight = area / nodeWidth;\n \n // Simple row-based layout\n if (x + nodeWidth > width) {\n x = 0;\n y += currentRowHeight;\n currentRowHeight = 0;\n }\n \n const result = {\n ...node,\n x,\n y,\n width: Math.max(this.effectiveMinTileSize, nodeWidth),\n height: Math.max(this.effectiveMinTileSize, nodeHeight),\n };\n \n x += result.width + this.padding;\n currentRowHeight = Math.max(currentRowHeight, result.height + this.padding);\n \n return result;\n });\n };\n\n // Settings management\n updateSettings = (newSettings: Partial<TreemapViewSettings>) => {\n this.logger?.info('updateSettings');\n this.settings = { ...this.settings, ...newSettings };\n \n // Apply settings to local properties\n if (newSettings.colorScheme !== undefined) {\n // Map the TreemapViewSettings colorScheme to our internal colorScheme\n switch (newSettings.colorScheme) {\n case 'size':\n this.setColorScheme('size');\n break;\n case 'type':\n this.setColorScheme('type');\n break;\n case 'date':\n this.setColorScheme('date');\n break;\n case 'custom':\n this.setColorScheme('custom');\n break;\n }\n }\n if (newSettings.showLabels !== undefined) {\n this.showLabels = newSettings.showLabels;\n }\n if (newSettings.paddingInner !== undefined) {\n this.setPadding(newSettings.paddingInner);\n }\n if (newSettings.zoomable !== undefined) {\n this.enableZoom = newSettings.zoomable;\n }\n };\n\n // Presets\n applyPreset = (preset: 'overview' | 'detailed' | 'interactive') => {\n this.logger?.info(`applyPreset: ${preset}`);\n \n switch (preset) {\n case 'overview':\n this.setMaxDepth(2);\n this.setMinTileSize(15);\n this.showLabels = false;\n this.showSizes = false;\n break;\n case 'detailed':\n this.setMaxDepth(4);\n this.setMinTileSize(8);\n this.showLabels = true;\n this.showSizes = true;\n break;\n case 'interactive':\n this.setMaxDepth(3);\n this.setMinTileSize(12);\n this.showLabels = true;\n this.showSizes = false;\n this.enableZoom = true;\n this.enableDrillDown = true;\n break;\n }\n };\n\n resetToDefaults = () => {\n this.logger?.info('resetToDefaults');\n this.minTileSize = 10;\n this.maxDepth = 3;\n this.showLabels = true;\n this.showSizes = true;\n this.colorScheme = 'type';\n this.padding = 2;\n this.enableZoom = true;\n this.enableDrillDown = true;\n this.currentRoot = null;\n this.zoomLevel = 1;\n this.initializeSettings();\n };\n\n // Private methods\n private initializeSettings() {\n this.settings = {\n colorScheme: this.colorScheme,\n showLabels: this.showLabels,\n zoomable: this.enableZoom,\n defaultSortField: 'size',\n defaultSortDirection: 'desc',\n };\n }\n\n // Cleanup\n dispose() {\n this.logger?.info('TreemapViewUIModel disposing');\n this.currentRoot = null;\n }\n} ","import { makeAutoObservable, observable } from 'mobx';\nimport { ViewModeDefinition } from '../types/ViewModeTypes';\nimport { FilterCriteria } from '../types/FileBrowserTypes';\nimport { TreeViewUIModel } from './ui/TreeViewUIModel';\nimport { ListViewUIModel, SortCriteria } from './ui/ListViewUIModel';\nimport { ThumbnailViewUIModel } from './ui/ThumbnailViewUIModel';\nimport { TreemapViewUIModel } from './ui/TreemapViewUIModel';\n\nexport class ViewModeManagerModel {\n // View modes\n availableViewModes = observable.map<string, ViewModeDefinition>();\n currentViewMode = 'tree';\n \n // Filtering and sorting\n currentFilters: FilterCriteria = {};\n currentSortCriteria: SortCriteria | null = null;\n \n // View-specific UI models\n treeViewUI: TreeViewUIModel;\n listViewUI: ListViewUIModel;\n thumbnailViewUI: ThumbnailViewUIModel;\n treemapViewUI: TreemapViewUIModel;\n \n // Owner reference for logging\n private owner: any;\n\n constructor(owner: any) {\n makeAutoObservable(this);\n \n this.owner = owner;\n \n // Initialize view-specific UI models\n this.treeViewUI = new TreeViewUIModel(this);\n this.listViewUI = new ListViewUIModel(this);\n this.thumbnailViewUI = new ThumbnailViewUIModel(this);\n this.treemapViewUI = new TreemapViewUIModel(this);\n \n // Initialize with default view modes\n this.initializeDefaultViewModes();\n }\n\n get logger() {\n return this.owner.logger;\n }\n \n // Computed values\n get currentViewModeDefinition() {\n return this.availableViewModes.get(this.currentViewMode);\n }\n \n get availableViewModesArray() {\n return Array.from(this.availableViewModes.values())\n .sort((a, b) => (a.priority || 0) - (b.priority || 0));\n }\n \n get currentViewUI() {\n switch (this.currentViewMode) {\n case 'tree':\n return this.treeViewUI;\n case 'list':\n return this.listViewUI;\n case 'thumbnail':\n return this.thumbnailViewUI;\n case 'treemap':\n return this.treemapViewUI;\n default:\n return this.treeViewUI;\n }\n }\n \n get hasFilters() {\n return Object.keys(this.currentFilters).length > 0;\n }\n \n get hasSorting() {\n return this.currentSortCriteria !== null;\n }\n\n // Actions\n setCurrentViewMode = (viewModeId: string) => {\n this.logger?.info(`setCurrentViewMode: ${viewModeId}`);\n \n if (this.availableViewModes.has(viewModeId)) {\n this.currentViewMode = viewModeId;\n \n // Apply default sorting for the view mode if none exists\n const viewMode = this.availableViewModes.get(viewModeId);\n if (viewMode?.settings?.defaultSortField && !this.currentSortCriteria) {\n this.setSortCriteria(\n viewMode.settings.defaultSortField,\n viewMode.settings.defaultSortDirection || 'asc'\n );\n }\n } else {\n this.logger?.warn(`Unknown view mode: ${viewModeId}`);\n }\n };\n\n registerViewMode = (definition: ViewModeDefinition) => {\n this.logger?.info(`registerViewMode: ${definition.id}`);\n this.availableViewModes.set(definition.id, definition);\n };\n\n unregisterViewMode = (viewModeId: string) => {\n this.logger?.info(`unregisterViewMode: ${viewModeId}`);\n this.availableViewModes.delete(viewModeId);\n \n // Switch to default if current view mode was removed\n if (this.currentViewMode === viewModeId) {\n const defaultViewMode = this.availableViewModesArray[0];\n if (defaultViewMode) {\n this.setCurrentViewMode(defaultViewMode.id);\n }\n }\n };\n\n setFilter = (key: keyof FilterCriteria, value: any) => {\n this.logger?.info(`setFilter: ${key} = ${value}`);\n \n if (value === undefined || value === null || value === '') {\n // Remove filter if value is empty\n const newFilters = { ...this.currentFilters };\n delete newFilters[key];\n this.currentFilters = newFilters;\n } else {\n this.currentFilters = {\n ...this.currentFilters,\n [key]: value,\n };\n }\n };\n\n clearFilters = () => {\n this.logger?.info('clearFilters');\n this.currentFilters = {};\n };\n\n setSortCriteria = (field: string, direction: 'asc' | 'desc') => {\n this.logger?.info(`setSortCriteria: ${field} ${direction}`);\n this.currentSortCriteria = { field, direction };\n };\n\n clearSort = () => {\n this.logger?.info('clearSort');\n this.currentSortCriteria = null;\n };\n\n toggleSortDirection = () => {\n if (this.currentSortCriteria) {\n this.setSortCriteria(\n this.currentSortCriteria.field,\n this.currentSortCriteria.direction === 'asc' ? 'desc' : 'asc'\n );\n }\n };\n\n // View mode capabilities\n supportsCapability = (capability: string): boolean => {\n const viewMode = this.currentViewModeDefinition;\n if (!viewMode) return false;\n \n return (viewMode.capabilities as any)[capability] === true;\n };\n\n // Private methods\n private initializeDefaultViewModes() {\n // Default view modes will be registered by providers\n // This is just setting up the initial state\n this.logger?.info('initializeDefaultViewModes');\n }\n\n // Cleanup\n dispose() {\n this.logger?.info('ViewModeManagerModel disposing');\n \n // Dispose of UI models\n this.treeViewUI.dispose?.();\n this.listViewUI.dispose?.();\n this.thumbnailViewUI.dispose?.();\n this.treemapViewUI.dispose?.();\n \n // Clear collections\n this.availableViewModes.clear();\n }\n} ","import React from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { ChevronRight, Home } from 'lucide-react';\nimport { cn } from '../../lib/utils';\nimport { FileBrowserModel } from '../models/FileBrowserModel';\nimport { ToolbarManagerModel } from '../models/ToolbarManagerModel';\nimport type { FileBrowserItem } from '../types/FileBrowserTypes';\nimport type { ToolbarAction, ActionContext } from '../types/ProviderTypes';\n\nexport interface FileBrowserHeaderProps {\n model: FileBrowserModel;\n toolbarManager?: ToolbarManagerModel;\n className?: string;\n showBreadcrumb?: boolean;\n showToolbar?: boolean;\n}\n\nconst FileBrowserHeader: React.FC<FileBrowserHeaderProps> = observer(({\n model,\n toolbarManager,\n className,\n showBreadcrumb = true,\n showToolbar = true,\n}) => {\n const currentPath = model.currentPath;\n const pathSegments = currentPath.split('/').filter(Boolean);\n\n const handlePathClick = (index: number) => {\n const newPath = index === -1 ? '/' : '/' + pathSegments.slice(0, index + 1).join('/');\n model.setCurrentPath(newPath);\n };\n\n const renderBreadcrumb = () => {\n if (!showBreadcrumb) return null;\n\n return (\n <div className=\"flex items-center gap-1 min-w-0 flex-1\">\n {/* Root/Home button */}\n <button\n onClick={() => handlePathClick(-1)}\n className={cn(\n 'flex items-center gap-1 px-2 py-1 rounded-md text-sm hover:bg-muted transition-colors',\n currentPath === '/' && 'bg-muted text-muted-foreground'\n )}\n aria-label=\"Navigate to root\"\n >\n <Home className=\"w-4 h-4\" />\n <span className=\"hidden sm:inline\">Root</span>\n </button>\n\n {/* Path segments */}\n {pathSegments.length > 0 && (\n <>\n <ChevronRight className=\"w-4 h-4 text-muted-foreground\" />\n <div className=\"flex items-center gap-1 min-w-0 flex-1\">\n {pathSegments.map((segment, index) => {\n const isLast = index === pathSegments.length - 1;\n\n return (\n <React.Fragment key={index}>\n <button\n onClick={() => handlePathClick(index)}\n className={cn(\n 'px-2 py-1 rounded-md text-sm transition-colors truncate',\n isLast\n ? 'bg-muted text-muted-foreground font-medium'\n : 'hover:bg-muted'\n )}\n title={segment}\n aria-current={isLast ? 'page' : undefined}\n >\n {segment}\n </button>\n\n {!isLast && (\n <ChevronRight className=\"w-4 h-4 text-muted-foreground flex-shrink-0\" />\n )}\n </React.Fragment>\n );\n })}\n </div>\n </>\n )}\n </div>\n );\n };\n\n const renderToolbar = () => {\n if (!showToolbar) return null;\n\n if (!toolbarManager) {\n return (\n <div className=\"flex items-center gap-1\" />\n );\n }\n\n const context: ActionContext = {\n selectedItems: [],\n currentPath: model.currentPath,\n provider: undefined as any,\n viewMode: 'list',\n allItems: model.itemsArray as any as FileBrowserItem[]\n };\n\n const actions = toolbarManager.getAvailableActions(context);\n\n if (actions.length === 0) {\n return <div className=\"flex items-center gap-1\" />;\n }\n\n return (\n <div className=\"flex items-center gap-1\">\n {actions.map((action: ToolbarAction) => (\n <button\n key={action.id}\n onClick={() => action.action(context)}\n disabled={action.isEnabled ? !action.isEnabled(context) : false}\n className={cn(\n 'flex items-center gap-1 px-2 py-1 rounded-md text-sm transition-colors',\n 'hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed',\n action.variant === 'primary' && 'bg-primary text-primary-foreground hover:bg-primary/90',\n action.variant === 'destructive' && 'text-destructive hover:bg-destructive/10'\n )}\n title={action.tooltip || action.label}\n >\n {action.showLabel !== false && (\n <span className=\"hidden sm:inline\">{action.label}</span>\n )}\n </button>\n ))}\n </div>\n );\n };\n\n return (\n <header\n className={cn(\n 'flex items-center justify-between gap-4 p-4 border-b bg-background',\n className\n )}\n role=\"banner\"\n >\n {renderBreadcrumb()}\n {renderToolbar()}\n </header>\n );\n});\n\nFileBrowserHeader.displayName = 'FileBrowserHeader';\n\nexport default FileBrowserHeader;\n","import React from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { AlertCircle, FolderOpen } from 'lucide-react';\nimport { cn } from '../../lib/utils';\nimport { FileBrowserModel } from '../models/FileBrowserModel';\nimport { LoadingSpinner } from '@anymux/ui/components/loading-spinner';\nimport { ErrorBoundary } from './shared/ErrorBoundary';\n\nexport interface FileBrowserContentProps {\n model: FileBrowserModel;\n className?: string;\n currentViewMode?: string;\n}\n\nconst FileBrowserContent: React.FC<FileBrowserContentProps> = observer(({\n model,\n className,\n currentViewMode = 'tree',\n}) => {\n // Loading state\n if (model.isLoading) {\n return (\n <div className={cn('flex items-center justify-center p-8', className)}>\n <LoadingSpinner\n size=\"lg\"\n label=\"Loading files...\"\n />\n </div>\n );\n }\n\n // Error state\n if (model.hasError && model.error) {\n return (\n <div className={cn('p-8', className)}>\n <div \n className=\"flex flex-col items-center justify-center text-center border border-destructive/20 rounded-lg bg-destructive/5 p-8\"\n role=\"alert\"\n aria-live=\"assertive\"\n >\n <AlertCircle className=\"w-12 h-12 text-destructive mb-4\" />\n \n <h3 className=\"text-lg font-semibold text-destructive mb-2\">\n Error Loading Files\n </h3>\n \n <p className=\"text-sm text-muted-foreground mb-4 max-w-md\">\n {model.error}\n </p>\n \n <div className=\"flex gap-2\">\n <button\n onClick={() => model.refreshItems()}\n className=\"px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 transition-colors\"\n >\n Try Again\n </button>\n \n <button\n onClick={() => model.clearError()}\n className=\"px-4 py-2 bg-secondary text-secondary-foreground rounded-md hover:bg-secondary/90 focus:outline-none focus:ring-2 focus:ring-secondary focus:ring-offset-2 transition-colors\"\n >\n Dismiss\n </button>\n </div>\n </div>\n </div>\n );\n }\n\n // Empty state\n if (!model.hasItems) {\n return (\n <div className={cn('flex items-center justify-center p-8', className)}>\n <div className=\"text-center\">\n <FolderOpen className=\"w-16 h-16 text-muted-foreground mx-auto mb-4\" />\n \n <h3 className=\"text-lg font-semibold text-muted-foreground mb-2\">\n No Files Found\n </h3>\n \n <p className=\"text-sm text-muted-foreground max-w-md\">\n This directory is empty or no files match the current filters.\n </p>\n \n <button\n onClick={() => model.refreshItems()}\n className=\"mt-4 px-4 py-2 bg-secondary text-secondary-foreground rounded-md hover:bg-secondary/90 focus:outline-none focus:ring-2 focus:ring-secondary focus:ring-offset-2 transition-colors\"\n >\n Refresh\n </button>\n </div>\n </div>\n );\n }\n\n // Content with view mode switching\n const renderViewMode = () => {\n switch (currentViewMode) {\n case 'tree':\n return <TreeViewPlaceholder model={model} />;\n case 'list':\n return <ListViewPlaceholder model={model} />;\n case 'thumbnail':\n return <ThumbnailViewPlaceholder model={model} />;\n default:\n return <TreeViewPlaceholder model={model} />;\n }\n };\n\n return (\n <ErrorBoundary>\n <div \n className={cn('flex-1 overflow-auto', className)}\n role=\"main\"\n aria-label={`File browser content - ${currentViewMode} view`}\n >\n {renderViewMode()}\n </div>\n </ErrorBoundary>\n );\n});\n\n// Placeholder components for view modes (to be implemented in Phase 4)\nconst TreeViewPlaceholder: React.FC<{ model: FileBrowserModel }> = observer(({ model }) => (\n <div className=\"p-4\">\n <div className=\"text-sm text-muted-foreground mb-4\">\n Tree View Mode - {model.itemsArray.length} items\n </div>\n <div className=\"space-y-1\">\n {model.itemsArray.map((item) => (\n <div \n key={item.id} \n className=\"flex items-center gap-2 p-2 hover:bg-muted rounded-md cursor-pointer\"\n onClick={() => {\n if (item.type === 'directory') {\n model.setCurrentPath(item.path);\n }\n }}\n >\n <span className=\"text-sm\">{item.type === 'directory' ? '📁' : '📄'}</span>\n <span className=\"text-sm\">{item.name}</span>\n </div>\n ))}\n </div>\n </div>\n));\n\nconst ListViewPlaceholder: React.FC<{ model: FileBrowserModel }> = observer(({ model }) => (\n <div className=\"p-4\">\n <div className=\"text-sm text-muted-foreground mb-4\">\n List View Mode - {model.itemsArray.length} items\n </div>\n <div className=\"grid grid-cols-1 gap-1\">\n {model.itemsArray.map((item) => (\n <div \n key={item.id} \n className=\"grid grid-cols-3 gap-4 p-2 hover:bg-muted rounded-md cursor-pointer text-sm\"\n onClick={() => {\n if (item.type === 'directory') {\n model.setCurrentPath(item.path);\n }\n }}\n >\n <span className=\"flex items-center gap-2\">\n <span>{item.type === 'directory' ? '📁' : '📄'}</span>\n {item.name}\n </span>\n <span className=\"text-muted-foreground\">\n {item.size ? `${Math.round(item.size / 1024)}KB` : '-'}\n </span>\n <span className=\"text-muted-foreground\">\n {item.lastModified ? item.lastModified.toLocaleDateString() : '-'}\n </span>\n </div>\n ))}\n </div>\n </div>\n));\n\nconst ThumbnailViewPlaceholder: React.FC<{ model: FileBrowserModel }> = observer(({ model }) => (\n <div className=\"p-4\">\n <div className=\"text-sm text-muted-foreground mb-4\">\n Thumbnail View Mode - {model.itemsArray.length} items\n </div>\n <div className=\"grid grid-cols-4 md:grid-cols-6 lg:grid-cols-8 gap-4\">\n {model.itemsArray.map((item) => (\n <div \n key={item.id} \n className=\"flex flex-col items-center p-2 hover:bg-muted rounded-md cursor-pointer\"\n onClick={() => {\n if (item.type === 'directory') {\n model.setCurrentPath(item.path);\n }\n }}\n >\n <div className=\"w-12 h-12 flex items-center justify-center text-2xl mb-2\">\n {item.type === 'directory' ? '📁' : '📄'}\n </div>\n <span className=\"text-xs text-center line-clamp-2\">{item.name}</span>\n </div>\n ))}\n </div>\n </div>\n));\n\nFileBrowserContent.displayName = 'FileBrowserContent';\n\nexport default FileBrowserContent; ","import React from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { ChevronRight, ChevronDown } from 'lucide-react';\nimport { cn } from '../../../../lib/utils';\nimport { FileBrowserItem } from '../../../types/FileBrowserTypes';\nimport { TreeViewUIModel } from '../../../models/ui/TreeViewUIModel';\nimport FileIcon from '../../shared/FileIcon';\n\nexport interface TreeNodeProps {\n item: FileBrowserItem;\n treeModel: TreeViewUIModel;\n level: number;\n onItemClick?: (item: FileBrowserItem) => void;\n onItemDoubleClick?: (item: FileBrowserItem) => void;\n isSelected?: boolean;\n isFocused?: boolean;\n getItemIcon?: (item: FileBrowserItem) => any;\n}\n\nconst TreeNode: React.FC<TreeNodeProps> = observer(({\n item,\n treeModel,\n level,\n onItemClick,\n onItemDoubleClick,\n isSelected = false,\n isFocused = false,\n getItemIcon,\n}) => {\n const isDirectory = item.type === 'directory';\n const hasChildren = isDirectory && treeModel.hasChildren(item);\n const isExpanded = isDirectory && treeModel.isFolderExpanded(item.path);\n const indentSize = treeModel.indentSize;\n\n const handleExpanderClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (hasChildren) {\n treeModel.toggleFolder(item.path);\n }\n };\n\n const handleItemClick = (e: React.MouseEvent) => {\n e.preventDefault();\n \n // Handle expand on single click if enabled\n if (isDirectory && treeModel.expandOnSingleClick) {\n treeModel.toggleFolder(item.path);\n }\n \n onItemClick?.(item);\n };\n\n const handleItemDoubleClick = (e: React.MouseEvent) => {\n e.preventDefault();\n \n // Handle collapse on second click if enabled\n if (isDirectory && treeModel.collapseOnSecondClick && isExpanded) {\n treeModel.collapseFolder(item.path);\n }\n \n onItemDoubleClick?.(item);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault();\n handleItemClick(e as any);\n break;\n case 'ArrowRight':\n if (isDirectory && !isExpanded && hasChildren) {\n e.preventDefault();\n treeModel.expandFolder(item.path);\n }\n break;\n case 'ArrowLeft':\n if (isDirectory && isExpanded) {\n e.preventDefault();\n treeModel.collapseFolder(item.path);\n }\n break;\n }\n };\n\n return (\n <div\n className={cn(\n 'flex items-center group relative select-none',\n 'hover:bg-muted/50 transition-colors cursor-pointer',\n isSelected && 'bg-primary/10 text-primary',\n isFocused && 'ring-2 ring-primary ring-inset'\n )}\n style={{ paddingLeft: `${level * indentSize}px` }}\n onClick={handleItemClick}\n onDoubleClick={handleItemDoubleClick}\n onKeyDown={handleKeyDown}\n tabIndex={0}\n role=\"treeitem\"\n aria-expanded={isDirectory ? isExpanded : undefined}\n aria-level={level + 1}\n aria-selected={isSelected}\n aria-label={`${item.type === 'directory' ? 'Folder' : 'File'}: ${item.name}`}\n >\n {/* Tree connectors */}\n {treeModel.showConnectors && level > 0 && (\n <div className=\"absolute left-0 top-0 h-full\">\n {/* Vertical line for parent levels */}\n <div \n className=\"absolute bg-border\"\n style={{\n left: `${(level - 1) * indentSize + indentSize / 2 - 0.5}px`,\n top: 0,\n width: '1px',\n height: '100%',\n }}\n />\n {/* Horizontal line to item */}\n <div \n className=\"absolute bg-border\"\n style={{\n left: `${(level - 1) * indentSize + indentSize / 2}px`,\n top: '50%',\n width: `${indentSize / 2}px`,\n height: '1px',\n }}\n />\n </div>\n )}\n\n {/* Expander icon */}\n <div className=\"flex items-center justify-center w-5 h-5 mr-1\">\n {hasChildren && (\n <button\n onClick={handleExpanderClick}\n className={cn(\n 'flex items-center justify-center w-4 h-4 rounded-sm',\n 'hover:bg-muted transition-colors',\n 'focus:outline-none focus:ring-1 focus:ring-primary'\n )}\n tabIndex={-1}\n aria-label={isExpanded ? 'Collapse folder' : 'Expand folder'}\n >\n {isExpanded ? (\n <ChevronDown className=\"w-3 h-3\" />\n ) : (\n <ChevronRight className=\"w-3 h-3\" />\n )}\n </button>\n )}\n </div>\n\n {/* File/folder icon */}\n <div className=\"flex items-center justify-center w-5 h-5 mr-2\">\n <FileIcon\n item={item}\n getItemIcon={getItemIcon}\n size=\"sm\"\n isExpanded={isExpanded}\n />\n </div>\n\n {/* Item name */}\n <span \n className={cn(\n 'flex-1 text-sm truncate',\n item.isLoading && 'opacity-50'\n )}\n title={item.name}\n >\n {item.name}\n </span>\n\n {/* Loading indicator */}\n {item.isLoading && (\n <div className=\"flex items-center justify-center w-4 h-4 ml-2\">\n <div className=\"w-3 h-3 border border-primary border-t-transparent rounded-full animate-spin\" />\n </div>\n )}\n </div>\n );\n});\n\nTreeNode.displayName = 'TreeNode';\n\nexport default TreeNode; ","import React, { useCallback, useMemo } from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { cn } from '../../../../lib/utils';\nimport { FileBrowserItem } from '../../../types/FileBrowserTypes';\nimport { TreeViewUIModel } from '../../../models/ui/TreeViewUIModel';\nimport TreeNode from './TreeNode';\n\nexport interface TreeNodeListProps {\n items: FileBrowserItem[];\n treeModel: TreeViewUIModel;\n onItemClick?: (item: FileBrowserItem) => void;\n onItemDoubleClick?: (item: FileBrowserItem) => void;\n onSelectionChange?: (selectedItems: FileBrowserItem[]) => void;\n selectedItemIds?: Set<string>;\n focusedItemId?: string;\n className?: string;\n getItemIcon?: (item: FileBrowserItem) => any;\n virtualization?: boolean;\n maxHeight?: number;\n}\n\ninterface TreeNodeFlat {\n item: FileBrowserItem;\n level: number;\n key: string;\n}\n\nconst TreeNodeList: React.FC<TreeNodeListProps> = observer(({\n items,\n treeModel,\n onItemClick,\n onItemDoubleClick,\n onSelectionChange,\n selectedItemIds = new Set(),\n focusedItemId,\n className,\n getItemIcon,\n virtualization = false,\n maxHeight = 400,\n}) => {\n // Flatten tree structure for rendering\n const flattenedNodes = useMemo(() => {\n const result: TreeNodeFlat[] = [];\n \n const processItems = (items: FileBrowserItem[], level = 0) => {\n const sortedItems = treeModel.sortTreeNodes(items);\n \n for (const item of sortedItems) {\n result.push({\n item,\n level,\n key: `${item.path}-${level}`,\n });\n \n // Add children if folder is expanded\n if (item.type === 'directory' && \n treeModel.isFolderExpanded(item.path) && \n item.children && \n item.children.length > 0) {\n processItems(item.children, level + 1);\n }\n }\n };\n \n processItems(items);\n return result;\n }, [items, treeModel, treeModel.expandedFoldersArray]);\n\n const handleItemClick = useCallback((item: FileBrowserItem) => {\n onItemClick?.(item);\n }, [onItemClick]);\n\n const handleItemDoubleClick = useCallback((item: FileBrowserItem) => {\n onItemDoubleClick?.(item);\n }, [onItemDoubleClick]);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent, currentIndex: number) => {\n const nodeCount = flattenedNodes.length;\n \n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (currentIndex < nodeCount - 1) {\n const nextNode = flattenedNodes[currentIndex + 1];\n if (nextNode) {\n handleItemClick(nextNode.item);\n }\n }\n break;\n \n case 'ArrowUp':\n e.preventDefault();\n if (currentIndex > 0) {\n const prevNode = flattenedNodes[currentIndex - 1];\n if (prevNode) {\n handleItemClick(prevNode.item);\n }\n }\n break;\n \n case 'Home':\n e.preventDefault();\n if (nodeCount > 0) {\n const firstNode = flattenedNodes[0];\n if (firstNode) {\n handleItemClick(firstNode.item);\n }\n }\n break;\n \n case 'End':\n e.preventDefault();\n if (nodeCount > 0) {\n const lastNode = flattenedNodes[nodeCount - 1];\n if (lastNode) {\n handleItemClick(lastNode.item);\n }\n }\n break;\n }\n }, [flattenedNodes, handleItemClick]);\n\n // Regular rendering (non-virtualized)\n const renderNodes = () => {\n return flattenedNodes.map((node, index) => (\n <TreeNode\n key={node.key}\n item={node.item}\n treeModel={treeModel}\n level={node.level}\n onItemClick={handleItemClick}\n onItemDoubleClick={handleItemDoubleClick}\n isSelected={selectedItemIds.has(node.item.id)}\n isFocused={focusedItemId === node.item.id}\n getItemIcon={getItemIcon}\n />\n ));\n };\n\n // Virtualized rendering for large lists\n const renderVirtualizedNodes = () => {\n // Basic virtualization implementation\n // For production, consider using react-window or react-virtualized\n const itemHeight = 24; // Approximate height per tree node\n const containerHeight = Math.min(maxHeight, flattenedNodes.length * itemHeight);\n const visibleCount = Math.ceil(containerHeight / itemHeight);\n \n // For now, render all items - proper virtualization would require scroll handling\n return (\n <div \n className=\"overflow-auto\"\n style={{ maxHeight: containerHeight }}\n role=\"tree\"\n aria-label=\"File tree\"\n >\n {renderNodes()}\n </div>\n );\n };\n\n if (flattenedNodes.length === 0) {\n return (\n <div className={cn('p-4 text-center text-muted-foreground', className)}>\n <p className=\"text-sm\">No items to display</p>\n </div>\n );\n }\n\n return (\n <div \n className={cn('focus-within:outline-none', className)}\n role=\"tree\"\n aria-label=\"File tree\"\n onKeyDown={(e) => {\n // Find currently focused item index\n const focusedIndex = flattenedNodes.findIndex(node => \n node.item.id === focusedItemId\n );\n if (focusedIndex >= 0) {\n handleKeyDown(e, focusedIndex);\n }\n }}\n >\n {virtualization ? renderVirtualizedNodes() : renderNodes()}\n </div>\n );\n});\n\nTreeNodeList.displayName = 'TreeNodeList';\n\nexport default TreeNodeList; ","import React, { useEffect } from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { cn } from '../../../../lib/utils';\nimport { FileBrowserItem } from '../../../types/FileBrowserTypes';\nimport { TreeViewUIModel } from '../../../models/ui/TreeViewUIModel';\nimport TreeNodeList from './TreeNodeList';\n\nexport interface TreeViewProps {\n items: FileBrowserItem[];\n treeModel: TreeViewUIModel;\n onItemClick?: (item: FileBrowserItem) => void;\n onItemDoubleClick?: (item: FileBrowserItem) => void;\n onItemActivate?: (item: FileBrowserItem) => void;\n onSelectionChange?: (selectedItems: FileBrowserItem[]) => void;\n onPathChange?: (path: string) => void;\n selectedItemIds?: Set<string>;\n focusedItemId?: string;\n className?: string;\n getItemIcon?: (item: FileBrowserItem) => any;\n loadFolder?: (path: string) => Promise<FileBrowserItem[]>;\n virtualization?: boolean;\n maxHeight?: number;\n}\n\nconst TreeView: React.FC<TreeViewProps> = observer(({\n items,\n treeModel,\n onItemClick,\n onItemDoubleClick,\n onItemActivate,\n onSelectionChange,\n onPathChange,\n selectedItemIds = new Set<string>(),\n focusedItemId,\n className,\n getItemIcon,\n loadFolder,\n virtualization = false,\n maxHeight,\n}) => {\n // Build hierarchical tree structure from flat items array\n const buildTreeStructure = (items: FileBrowserItem[]): FileBrowserItem[] => {\n const itemMap = new Map<string, FileBrowserItem>();\n const rootItems: FileBrowserItem[] = [];\n \n // First pass: create map of all items\n items.forEach(item => {\n itemMap.set(item.path, { ...item, children: [] });\n });\n \n // Second pass: build hierarchy\n items.forEach(item => {\n const itemCopy = itemMap.get(item.path);\n if (!itemCopy) return;\n \n // Find parent path\n const pathParts = item.path.split('/').filter(Boolean);\n if (pathParts.length === 1) {\n // Root level item\n rootItems.push(itemCopy);\n } else {\n // Find parent\n const parentPath = '/' + pathParts.slice(0, -1).join('/');\n const parent = itemMap.get(parentPath);\n if (parent && parent.children) {\n parent.children.push(itemCopy);\n } else {\n // Parent not found, treat as root item\n rootItems.push(itemCopy);\n }\n }\n });\n \n return rootItems;\n };\n\n const treeItems = React.useMemo(() => {\n return buildTreeStructure(items);\n }, [items]);\n\n const handleItemClick = (item: FileBrowserItem) => {\n onItemClick?.(item);\n \n // If it's a directory, handle expansion based on settings\n if (item.type === 'directory') {\n if (treeModel.expandOnSingleClick) {\n treeModel.toggleFolder(item.path);\n \n // Load folder contents if needed\n if (!treeModel.isFolderExpanded(item.path) && loadFolder) {\n handleFolderLoad(item.path);\n }\n }\n }\n };\n\n const handleItemDoubleClick = (item: FileBrowserItem) => {\n onItemDoubleClick?.(item);\n onItemActivate?.(item);\n \n // Handle directory navigation or file activation\n if (item.type === 'directory') {\n // Navigate to directory or toggle expansion\n if (treeModel.collapseOnSecondClick && treeModel.isFolderExpanded(item.path)) {\n treeModel.collapseFolder(item.path);\n } else {\n onPathChange?.(item.path);\n }\n } else {\n // File activation\n onItemActivate?.(item);\n }\n };\n\n const handleFolderLoad = async (folderPath: string) => {\n if (!loadFolder) return;\n \n try {\n treeModel.logger?.info(`Loading folder: ${folderPath}`);\n const folderItems = await loadFolder(folderPath);\n \n // Update the item in the tree to include children\n // This would need integration with the parent model\n treeModel.logger?.info(`Loaded ${folderItems.length} items for ${folderPath}`);\n } catch (error) {\n treeModel.logger?.error(`Failed to load folder ${folderPath}:`, error);\n }\n };\n\n // Handle folder expansion when state changes\n useEffect(() => {\n const expandedFolders = treeModel.expandedFoldersArray;\n \n // Load contents for newly expanded folders\n expandedFolders.forEach((folderPath: string) => {\n // Check if folder needs loading (doesn't have children but should)\n const item = items.find(item => item.path === folderPath);\n if (item && \n item.type === 'directory' && \n (!item.children || item.children.length === 0) &&\n item.hasChildren &&\n loadFolder) {\n handleFolderLoad(folderPath);\n }\n });\n }, [items, loadFolder]);\n\n // Keyboard shortcuts\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'a':\n if (e.ctrlKey || e.metaKey) {\n e.preventDefault();\n treeModel.expandAll();\n }\n break;\n case 'c':\n if (e.ctrlKey || e.metaKey) {\n e.preventDefault();\n treeModel.collapseAll();\n }\n break;\n }\n };\n\n if (!treeItems || treeItems.length === 0) {\n return (\n <div className={cn('p-4 text-center text-muted-foreground', className)}>\n <p className=\"text-sm\">No folders or files to display</p>\n </div>\n );\n }\n\n return (\n <div \n className={cn('tree-view h-full overflow-hidden', className)}\n onKeyDown={handleKeyDown}\n role=\"tree\"\n aria-label=\"File tree view\"\n >\n <TreeNodeList\n items={treeItems}\n treeModel={treeModel}\n onItemClick={handleItemClick}\n onItemDoubleClick={handleItemDoubleClick}\n onSelectionChange={onSelectionChange}\n selectedItemIds={selectedItemIds}\n focusedItemId={focusedItemId}\n getItemIcon={getItemIcon}\n virtualization={virtualization}\n maxHeight={maxHeight}\n className=\"h-full\"\n />\n </div>\n );\n});\n\nTreeView.displayName = 'TreeView';\n\nexport default TreeView; ","import React from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { ChevronUp, ChevronDown, MoreVertical } from 'lucide-react';\nimport { cn } from '../../../../lib/utils';\nimport { FileBrowserItem } from '../../../types/FileBrowserTypes';\nimport { ListViewUIModel, ColumnDefinition } from '../../../models/ui/ListViewUIModel';\nimport { ResponsiveLayoutManagerModel } from '../../../models/ResponsiveLayoutManagerModel';\nimport FileIcon from '../../shared/FileIcon';\n\nexport interface ListViewProps {\n items: FileBrowserItem[];\n listModel: ListViewUIModel;\n responsiveManager?: ResponsiveLayoutManagerModel;\n onItemClick?: (item: FileBrowserItem) => void;\n onItemDoubleClick?: (item: FileBrowserItem) => void;\n onItemActivate?: (item: FileBrowserItem) => void;\n onSelectionChange?: (selectedItems: FileBrowserItem[]) => void;\n selectedItemIds?: Set<string>;\n focusedItemId?: string;\n className?: string;\n getItemIcon?: (item: FileBrowserItem) => any;\n}\n\nconst ListViewHeader: React.FC<{\n columns: ColumnDefinition[];\n listModel: ListViewUIModel;\n className?: string;\n}> = observer(({ columns, listModel, className }) => {\n const handleColumnClick = (column: ColumnDefinition) => {\n if (column.sortable) {\n listModel.toggleSort(column.field);\n }\n };\n\n const handleColumnResize = (columnId: string, newWidth: number) => {\n listModel.resizeColumn(columnId, newWidth);\n };\n\n return (\n <div \n className={cn(\n 'flex border-b bg-muted/30 sticky top-0 z-10',\n listModel.showHeader ? 'block' : 'hidden',\n className\n )}\n role=\"row\"\n >\n {columns.map((column) => {\n const isSorted = listModel.currentSort?.field === column.field;\n const sortDirection = isSorted ? listModel.currentSort?.direction : undefined;\n \n return (\n <div\n key={column.id}\n className={cn(\n 'flex items-center gap-2 px-3 py-2 text-sm font-medium border-r border-border last:border-r-0',\n 'select-none transition-colors',\n column.sortable && 'hover:bg-muted/50 cursor-pointer',\n column.align === 'center' && 'justify-center',\n column.align === 'right' && 'justify-end'\n )}\n style={{ \n width: column.width,\n minWidth: column.minWidth,\n maxWidth: column.maxWidth,\n }}\n onClick={() => handleColumnClick(column)}\n role=\"columnheader\"\n aria-sort={\n isSorted \n ? sortDirection === 'asc' ? 'ascending' : 'descending'\n : undefined\n }\n >\n <span className=\"truncate\">{column.label}</span>\n \n {column.sortable && (\n <div className=\"flex flex-col\">\n {isSorted && sortDirection === 'asc' && (\n <ChevronUp className=\"w-3 h-3\" />\n )}\n {isSorted && sortDirection === 'desc' && (\n <ChevronDown className=\"w-3 h-3\" />\n )}\n </div>\n )}\n </div>\n );\n })}\n </div>\n );\n});\n\n// Mobile-optimized row component\nconst MobileListViewRow: React.FC<{\n item: FileBrowserItem;\n isSelected: boolean;\n isFocused: boolean;\n onItemClick?: (item: FileBrowserItem) => void;\n onItemDoubleClick?: (item: FileBrowserItem) => void;\n getItemIcon?: (item: FileBrowserItem) => any;\n index: number;\n}> = observer(({ \n item, \n isSelected, \n isFocused, \n onItemClick, \n onItemDoubleClick, \n getItemIcon,\n index,\n}) => {\n const handleClick = () => {\n onItemClick?.(item);\n };\n\n const handleDoubleClick = () => {\n onItemDoubleClick?.(item);\n };\n\n const formatSize = (size: number): string => {\n if (size === 0) return '0 B';\n const units = ['B', 'KB', 'MB', 'GB'];\n let fileSize = size;\n let unitIndex = 0;\n while (fileSize >= 1024 && unitIndex < units.length - 1) {\n fileSize /= 1024;\n unitIndex++;\n }\n return `${fileSize.toFixed(1)} ${units[unitIndex]}`;\n };\n\n const formatDate = (date: Date): string => {\n return date.toLocaleDateString(undefined, { \n month: 'short', \n day: 'numeric',\n year: date.getFullYear() !== new Date().getFullYear() ? 'numeric' : undefined\n });\n };\n\n return (\n <div\n className={cn(\n // Touch-friendly height (minimum 44px)\n 'flex items-center gap-3 p-4 border-b border-border',\n 'hover:bg-muted/30 active:bg-muted/50 transition-colors cursor-pointer',\n 'focus:outline-none focus:ring-2 focus:ring-primary focus:ring-inset',\n 'min-h-[44px]', // Ensure touch-friendly target size\n isSelected && 'bg-primary/10 text-primary',\n isFocused && 'ring-2 ring-primary ring-inset'\n )}\n onClick={handleClick}\n onDoubleClick={handleDoubleClick}\n tabIndex={0}\n role=\"row\"\n aria-selected={isSelected}\n >\n {/* Icon */}\n <div className=\"flex-shrink-0\">\n <FileIcon\n item={item}\n getItemIcon={getItemIcon}\n size=\"md\"\n />\n </div>\n\n {/* Main content */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center justify-between\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium truncate\" title={item.name}>\n {item.name}\n </p>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground mt-1\">\n <span>{item.type === 'directory' ? 'Folder' : 'File'}</span>\n {item.size !== undefined && item.type !== 'directory' && (\n <>\n <span>•</span>\n <span>{formatSize(item.size)}</span>\n </>\n )}\n {item.lastModified && (\n <>\n <span>•</span>\n <span>{formatDate(item.lastModified)}</span>\n </>\n )}\n </div>\n </div>\n \n {/* Action button */}\n <button\n className={cn(\n 'flex-shrink-0 w-8 h-8 flex items-center justify-center',\n 'rounded-md hover:bg-muted/50 transition-colors',\n 'focus:outline-none focus:ring-2 focus:ring-primary'\n )}\n onClick={(e) => {\n e.stopPropagation();\n // Handle context menu or actions\n }}\n aria-label=\"More actions\"\n >\n <MoreVertical className=\"w-4 h-4\" />\n </button>\n </div>\n </div>\n </div>\n );\n});\n\nconst ListViewRow: React.FC<{\n item: FileBrowserItem;\n columns: ColumnDefinition[];\n isSelected: boolean;\n isFocused: boolean;\n onItemClick?: (item: FileBrowserItem) => void;\n onItemDoubleClick?: (item: FileBrowserItem) => void;\n getItemIcon?: (item: FileBrowserItem) => any;\n striped?: boolean;\n index: number;\n}> = observer(({ \n item, \n columns, \n isSelected, \n isFocused, \n onItemClick, \n onItemDoubleClick, \n getItemIcon,\n striped = false,\n index,\n}) => {\n const handleClick = () => {\n onItemClick?.(item);\n };\n\n const handleDoubleClick = () => {\n onItemDoubleClick?.(item);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault();\n handleClick();\n break;\n }\n };\n\n const getCellValue = (column: ColumnDefinition): string => {\n const value = (item as any)[column.field];\n \n if (column.format && value !== undefined && value !== null) {\n return column.format(value);\n }\n \n // Default formatting for common fields\n switch (column.field) {\n case 'size':\n if (typeof value === 'number') {\n if (value === 0) return '0 B';\n const units = ['B', 'KB', 'MB', 'GB'];\n let size = value;\n let unitIndex = 0;\n while (size >= 1024 && unitIndex < units.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n return `${size.toFixed(1)} ${units[unitIndex]}`;\n }\n return '-';\n case 'lastModified':\n if (value instanceof Date) {\n return value.toLocaleDateString();\n }\n return '-';\n case 'type':\n return item.type === 'directory' ? 'Folder' : 'File';\n default:\n return value?.toString() || '-';\n }\n };\n\n return (\n <div\n className={cn(\n 'flex border-b border-border hover:bg-muted/30 transition-colors cursor-pointer',\n 'focus:outline-none focus:ring-2 focus:ring-primary focus:ring-inset',\n isSelected && 'bg-primary/10 text-primary',\n isFocused && 'ring-2 ring-primary ring-inset',\n striped && index % 2 === 1 && 'bg-muted/20'\n )}\n onClick={handleClick}\n onDoubleClick={handleDoubleClick}\n onKeyDown={handleKeyDown}\n tabIndex={0}\n role=\"row\"\n aria-selected={isSelected}\n >\n {columns.map((column, columnIndex) => (\n <div\n key={column.id}\n className={cn(\n 'flex items-center gap-2 px-3 py-2 text-sm border-r border-border last:border-r-0',\n 'truncate',\n column.align === 'center' && 'justify-center',\n column.align === 'right' && 'justify-end'\n )}\n style={{ \n width: column.width,\n minWidth: column.minWidth,\n maxWidth: column.maxWidth,\n }}\n role=\"cell\"\n >\n {/* Show icon only in first column (usually name) */}\n {columnIndex === 0 && (\n <FileIcon\n item={item}\n getItemIcon={getItemIcon}\n size=\"sm\"\n />\n )}\n \n <span className=\"truncate\" title={getCellValue(column)}>\n {getCellValue(column)}\n </span>\n </div>\n ))}\n </div>\n );\n});\n\nconst ListView: React.FC<ListViewProps> = observer(({\n items,\n listModel,\n responsiveManager,\n onItemClick,\n onItemDoubleClick,\n onItemActivate,\n onSelectionChange,\n selectedItemIds = new Set<string>(),\n focusedItemId,\n className,\n getItemIcon,\n}) => {\n const visibleColumns = listModel.visibleColumns;\n const isMobile = responsiveManager?.isMobile ?? false;\n \n // On mobile, use simplified columns or mobile layout\n const effectiveColumns = isMobile \n ? visibleColumns.filter(col => ['name'].includes(col.field)) // Only show name on mobile\n : visibleColumns;\n\n const handleItemClick = (item: FileBrowserItem) => {\n onItemClick?.(item);\n };\n\n const handleItemDoubleClick = (item: FileBrowserItem) => {\n onItemDoubleClick?.(item);\n onItemActivate?.(item);\n };\n\n const sortedItems = React.useMemo(() => {\n if (!listModel.currentSort) {\n return items;\n }\n\n const { field, direction } = listModel.currentSort;\n \n return [...items].sort((a, b) => {\n const aValue = (a as any)[field];\n const bValue = (b as any)[field];\n \n // Handle null/undefined values\n if (aValue == null && bValue == null) return 0;\n if (aValue == null) return direction === 'asc' ? -1 : 1;\n if (bValue == null) return direction === 'asc' ? 1 : -1;\n \n // Type-specific sorting\n if (typeof aValue === 'string' && typeof bValue === 'string') {\n const result = aValue.localeCompare(bValue);\n return direction === 'asc' ? result : -result;\n }\n \n if (typeof aValue === 'number' && typeof bValue === 'number') {\n const result = aValue - bValue;\n return direction === 'asc' ? result : -result;\n }\n \n if (aValue instanceof Date && bValue instanceof Date) {\n const result = aValue.getTime() - bValue.getTime();\n return direction === 'asc' ? result : -result;\n }\n \n // Fallback to string comparison\n const result = String(aValue).localeCompare(String(bValue));\n return direction === 'asc' ? result : -result;\n });\n }, [items, listModel.currentSort]);\n\n if (items.length === 0) {\n return (\n <div className={cn('p-4 text-center text-muted-foreground', className)}>\n <p className=\"text-sm\">No files to display</p>\n </div>\n );\n }\n\n if (!isMobile && effectiveColumns.length === 0) {\n return (\n <div className={cn('p-4 text-center text-muted-foreground', className)}>\n <p className=\"text-sm\">No columns configured</p>\n <button\n onClick={() => listModel.resetToDefaults()}\n className=\"mt-2 px-3 py-1 bg-primary text-primary-foreground rounded-md text-sm\"\n >\n Reset to Defaults\n </button>\n </div>\n );\n }\n\n // Mobile layout\n if (isMobile) {\n return (\n <div \n className={cn('list-view h-full overflow-hidden flex flex-col', className)}\n role=\"list\"\n aria-label=\"File list view (mobile)\"\n >\n <div className=\"flex-1 overflow-auto\">\n {sortedItems.map((item, index) => (\n <MobileListViewRow\n key={item.id}\n item={item}\n isSelected={selectedItemIds.has(item.id)}\n isFocused={focusedItemId === item.id}\n onItemClick={handleItemClick}\n onItemDoubleClick={handleItemDoubleClick}\n getItemIcon={getItemIcon}\n index={index}\n />\n ))}\n </div>\n </div>\n );\n }\n\n // Desktop layout\n return (\n <div \n className={cn('list-view h-full overflow-hidden flex flex-col', className)}\n role=\"grid\"\n aria-label=\"File list view\"\n >\n <ListViewHeader \n columns={effectiveColumns} \n listModel={listModel}\n />\n \n <div className=\"flex-1 overflow-auto\">\n {sortedItems.map((item, index) => (\n <ListViewRow\n key={item.id}\n item={item}\n columns={effectiveColumns}\n isSelected={selectedItemIds.has(item.id)}\n isFocused={focusedItemId === item.id}\n onItemClick={handleItemClick}\n onItemDoubleClick={handleItemDoubleClick}\n getItemIcon={getItemIcon}\n striped={listModel.striped}\n index={index}\n />\n ))}\n </div>\n </div>\n );\n});\n\nListView.displayName = 'ListView';\n\nexport default ListView; ","import React from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { ArrowLeft, ArrowRight, ArrowUp } from 'lucide-react';\nimport { cn } from '../../../lib/utils';\n\nexport interface NavigationButtonsProps {\n canGoBack?: boolean;\n canGoForward?: boolean;\n canGoUp?: boolean;\n onGoBack?: () => void;\n onGoForward?: () => void;\n onGoUp?: () => void;\n className?: string;\n variant?: 'default' | 'compact';\n showLabels?: boolean;\n disabled?: boolean;\n}\n\ninterface NavigationButtonProps {\n icon: React.ReactNode;\n label: string;\n onClick?: () => void;\n disabled?: boolean;\n shortcut?: string;\n className?: string;\n showLabel?: boolean;\n}\n\nconst NavigationButton: React.FC<NavigationButtonProps> = ({\n icon,\n label,\n onClick,\n disabled = false,\n shortcut,\n className,\n showLabel = false,\n}) => {\n const tooltipText = shortcut ? `${label} (${shortcut})` : label;\n\n return (\n <button\n onClick={onClick}\n disabled={disabled}\n className={cn(\n 'flex items-center gap-2 px-3 py-2 rounded-md text-sm transition-colors',\n 'hover:bg-muted focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2',\n 'disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-transparent',\n className\n )}\n title={tooltipText}\n aria-label={tooltipText}\n >\n {icon}\n {showLabel && <span className=\"hidden sm:inline\">{label}</span>}\n </button>\n );\n};\n\nconst NavigationButtons: React.FC<NavigationButtonsProps> = observer(({\n canGoBack = false,\n canGoForward = false,\n canGoUp = false,\n onGoBack,\n onGoForward,\n onGoUp,\n className,\n variant = 'default',\n showLabels = false,\n disabled = false,\n}) => {\n // Handle keyboard shortcuts\n React.useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n // Only handle shortcuts when not typing in inputs\n if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {\n return;\n }\n\n // Check for Alt key combinations\n if (e.altKey) {\n switch (e.key) {\n case 'ArrowLeft':\n e.preventDefault();\n if (canGoBack && onGoBack) {\n onGoBack();\n }\n break;\n case 'ArrowRight':\n e.preventDefault();\n if (canGoForward && onGoForward) {\n onGoForward();\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n if (canGoUp && onGoUp) {\n onGoUp();\n }\n break;\n }\n }\n\n // Browser-style shortcuts\n if ((e.ctrlKey || e.metaKey) && e.key === '[') {\n e.preventDefault();\n if (canGoBack && onGoBack) {\n onGoBack();\n }\n }\n \n if ((e.ctrlKey || e.metaKey) && e.key === ']') {\n e.preventDefault();\n if (canGoForward && onGoForward) {\n onGoForward();\n }\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [canGoBack, canGoForward, canGoUp, onGoBack, onGoForward, onGoUp]);\n\n const isCompact = variant === 'compact';\n const buttonSize = isCompact ? 'w-8 h-8 p-1' : 'px-3 py-2';\n\n return (\n <div\n className={cn(\n 'flex items-center',\n isCompact ? 'gap-1' : 'gap-2',\n className\n )}\n role=\"toolbar\"\n aria-label=\"Navigation buttons\"\n >\n <NavigationButton\n icon={<ArrowLeft className={isCompact ? 'w-4 h-4' : 'w-4 h-4'} />}\n label=\"Back\"\n onClick={onGoBack}\n disabled={disabled || !canGoBack}\n shortcut=\"Alt+←\"\n className={buttonSize}\n showLabel={showLabels && !isCompact}\n />\n\n <NavigationButton\n icon={<ArrowRight className={isCompact ? 'w-4 h-4' : 'w-4 h-4'} />}\n label=\"Forward\"\n onClick={onGoForward}\n disabled={disabled || !canGoForward}\n shortcut=\"Alt+→\"\n className={buttonSize}\n showLabel={showLabels && !isCompact}\n />\n\n <NavigationButton\n icon={<ArrowUp className={isCompact ? 'w-4 h-4' : 'w-4 h-4'} />}\n label=\"Up\"\n onClick={onGoUp}\n disabled={disabled || !canGoUp}\n shortcut=\"Alt+↑\"\n className={buttonSize}\n showLabel={showLabels && !isCompact}\n />\n </div>\n );\n});\n\nNavigationButtons.displayName = 'NavigationButtons';\n\nexport default NavigationButtons; ","import React from 'react';\nimport { observer } from 'mobx-react-lite';\nimport { List, Grid3X3, FileImage } from 'lucide-react';\nimport { cn } from '../../../lib/utils';\nimport type { ViewModeType } from '../../types/ViewModeTypes';\n\nexport interface ViewModeToggleProps {\n currentMode: ViewModeType;\n availableModes: ViewModeType[];\n onModeChange?: (mode: ViewModeType) => void;\n className?: string;\n variant?: 'tabs' | 'buttons';\n showLabels?: boolean;\n disabled?: boolean;\n}\n\ninterface ViewModeOption {\n mode: ViewModeType;\n icon: React.ReactNode;\n label: string;\n description: string;\n}\n\nconst VIEW_MODE_OPTIONS: Partial<Record<ViewModeType, ViewModeOption>> = {\n tree: {\n mode: 'tree',\n icon: <List className=\"w-4 h-4\" />,\n label: 'Tree',\n description: 'Hierarchical tree view'\n },\n list: {\n mode: 'list',\n icon: <Grid3X3 className=\"w-4 h-4\" />,\n label: 'List',\n description: 'Detailed list view'\n },\n thumbnail: {\n mode: 'thumbnail',\n icon: <FileImage className=\"w-4 h-4\" />,\n label: 'Thumbnails',\n description: 'Thumbnail grid view'\n }\n};\n\nconst ViewModeToggle: React.FC<ViewModeToggleProps> = observer(({\n currentMode,\n availableModes,\n onModeChange,\n className,\n variant = 'tabs',\n showLabels = true,\n disabled = false,\n}) => {\n const handleModeChange = (mode: ViewModeType) => {\n if (!disabled && mode !== currentMode) {\n onModeChange?.(mode);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent, mode: ViewModeType) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleModeChange(mode);\n }\n \n // Arrow key navigation\n if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n e.preventDefault();\n const currentIndex = availableModes.indexOf(currentMode);\n let nextIndex: number;\n \n if (e.key === 'ArrowLeft') {\n nextIndex = currentIndex > 0 ? currentIndex - 1 : availableModes.length - 1;\n } else {\n nextIndex = currentIndex < availableModes.length - 1 ? currentIndex + 1 : 0;\n }\n \n const nextMode = availableModes[nextIndex];\n if (nextMode) {\n handleModeChange(nextMode);\n }\n }\n };\n\n // Keyboard shortcuts\n React.useEffect(() => {\n const handleGlobalKeyDown = (e: KeyboardEvent) => {\n // Only handle shortcuts when not typing in inputs\n if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {\n return;\n }\n\n // Number keys 1-3 for view modes\n if (e.key >= '1' && e.key <= '3') {\n const index = parseInt(e.key) - 1;\n const mode = availableModes[index];\n if (mode && !disabled) {\n e.preventDefault();\n handleModeChange(mode);\n }\n }\n };\n\n window.addEventListener('keydown', handleGlobalKeyDown);\n return () => window.removeEventListener('keydown', handleGlobalKeyDown);\n }, [availableModes, disabled, currentMode, onModeChange]);\n\n if (availableModes.length <= 1) {\n return null;\n }\n\n const renderTabButton = (modeOption: ViewModeOption, index: number) => {\n const isActive = modeOption.mode === currentMode;\n const isDisabled = disabled;\n \n return (\n <button\n key={modeOption.mode}\n onClick={() => handleModeChange(modeOption.mode)}\n onKeyDown={(e) => handleKeyDown(e, modeOption.mode)}\n disabled={isDisabled}\n className={cn(\n 'flex items-center gap-2 px-3 py-2 text-sm font-medium transition-colors',\n 'border-b-2 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2',\n 'disabled:opacity-50 disabled:cursor-not-allowed',\n isActive\n ? 'border-primary text-primary bg-primary/5'\n : 'border-transparent text-muted-foreground hover:text-foreground hover:bg-muted',\n !showLabels && 'px-2'\n )}\n role=\"tab\"\n aria-selected={isActive}\n aria-controls={`view-${modeOption.mode}`}\n title={`${modeOption.description} (${index + 1})`}\n >\n {modeOption.icon}\n {showLabels && <span className=\"hidden sm:inline\">{modeOption.label}</span>}\n </button>\n );\n };\n\n const renderToggleButton = (modeOption: ViewModeOption, index: number) => {\n const isActive = modeOption.mode === currentMode;\n const isDisabled = disabled;\n \n return (\n <button\n key={modeOption.mode}\n onClick={() => handleModeChange(modeOption.mode)}\n onKeyDown={(e) => handleKeyDown(e, modeOption.mode)}\n disabled={isDisabled}\n className={cn(\n 'flex items-center gap-2 px-3 py-2 text-sm font-medium transition-colors',\n 'border border-input focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2',\n 'disabled:opacity-50 disabled:cursor-not-allowed',\n 'first:rounded-l-md last:rounded-r-md first:border-r-0 last:border-l-0',\n isActive\n ? 'bg-primary text-primary-foreground border-primary'\n : 'bg-background hover:bg-muted',\n !showLabels && 'px-2'\n )}\n aria-pressed={isActive}\n title={`${modeOption.description} (${index + 1})`}\n >\n {modeOption.icon}\n {showLabels && <span className=\"hidden sm:inline\">{modeOption.label}</span>}\n </button>\n );\n };\n\n const availableOptions = availableModes\n .map(mode => VIEW_MODE_OPTIONS[mode])\n .filter((option): option is ViewModeOption => option !== undefined);\n\n if (variant === 'tabs') {\n return (\n <div\n className={cn('flex items-center', className)}\n role=\"tablist\"\n aria-label=\"View mode selection\"\n >\n {availableOptions.map(renderTabButton)}\n </div>\n );\n }\n\n return (\n <div\n className={cn('flex items-center', className)}\n role=\"group\"\n aria-label=\"View mode selection\"\n >\n {availableOptions.map(renderToggleButton)}\n </div>\n );\n});\n\nViewModeToggle.displayName = 'ViewModeToggle';\n\nexport default ViewModeToggle; "],"mappings":"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"}