@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,946 @@
1
+ import { makeAutoObservable } from 'mobx';
2
+ import type { TreeProvider, TreeSelectionInfo } from './TreeProvider';
3
+ import type { TreeNodeData, TreeLoadResult, TreeLoadOptions, TreeTableColumn, TreeTableSort, TreeTableExportOptions, TreeSelectionTheme } from '../types/TreeTypes';
4
+ import type { TreeContextMenuItem } from '../types/TreeTypes';
5
+ import { DEFAULT_SELECTION_THEME } from '../utils/SelectionTheme';
6
+ import React from 'react';
7
+ import {
8
+ FileText, ImageIcon as Image, Settings, BookOpen, TestTube, Package,
9
+ Palette, Globe, Zap, Music, Archive, GitBranch, Database, Key,
10
+ Code, Braces, Play, Component
11
+ } from 'lucide-react';
12
+
13
+ export class TestTreeProvider implements TreeProvider {
14
+ // Provider metadata (required)
15
+ readonly id = 'test-tree-provider';
16
+ readonly name = 'Test Tree Provider';
17
+ readonly version = '1.0.0';
18
+
19
+ // Configuration (required)
20
+ isMultiSelectEnabled = true;
21
+ readonly isDragDropEnabled = false;
22
+ readonly isVirtualizationEnabled = false;
23
+ readonly isTableViewEnabled = true;
24
+ useCheckboxSelection = false;
25
+ readonly allowPartialSelection = true;
26
+ readonly config = {};
27
+
28
+ // Observable selection theme
29
+ selectionTheme: TreeSelectionTheme = {
30
+ ...DEFAULT_SELECTION_THEME,
31
+ colorScheme: 'primary',
32
+ intensity: 'prominent',
33
+ focusStyle: 'ring',
34
+ animated: true,
35
+ persistSelection: true
36
+ };
37
+
38
+ // Test provider specific settings
39
+ slowLoading = false;
40
+ simulateErrors = false;
41
+ maxDepth = 3;
42
+ nodesPerLevel = 5;
43
+ loadingDelay = 300;
44
+
45
+ // Callbacks (optional)
46
+ onSelectionChange?: (selectionInfo: TreeSelectionInfo) => void;
47
+ onNodeExpansion?: (node: TreeNodeData, isExpanded: boolean) => void;
48
+ onNodeFocus?: (node: TreeNodeData | null) => void;
49
+
50
+ constructor() {
51
+ makeAutoObservable(this, {
52
+ id: false,
53
+ name: false,
54
+ version: false,
55
+ isDragDropEnabled: false,
56
+ isVirtualizationEnabled: false,
57
+ isTableViewEnabled: false,
58
+ config: false,
59
+ // Make isMultiSelectEnabled and useCheckboxSelection observable
60
+ // isMultiSelectEnabled: true (default - observable)
61
+ // useCheckboxSelection: true (default - observable)
62
+ });
63
+ }
64
+
65
+ /**
66
+ * Update selection theme reactively
67
+ */
68
+ updateSelectionTheme = (theme: Partial<TreeSelectionTheme>) => {
69
+ this.selectionTheme = { ...this.selectionTheme, ...theme };
70
+ };
71
+
72
+ /**
73
+ * Update multi-select setting
74
+ */
75
+ setMultiSelectEnabled = (enabled: boolean) => {
76
+ this.isMultiSelectEnabled = enabled;
77
+ };
78
+
79
+ /**
80
+ * Update checkbox selection setting
81
+ */
82
+ setCheckboxSelection = (enabled: boolean) => {
83
+ this.useCheckboxSelection = enabled;
84
+ };
85
+
86
+ /**
87
+ * Get selection theme configuration
88
+ */
89
+ getSelectionTheme(): TreeSelectionTheme {
90
+ return this.selectionTheme;
91
+ }
92
+
93
+ /**
94
+ * Load tree nodes
95
+ */
96
+ async loadNodes(options?: TreeLoadOptions): Promise<TreeLoadResult> {
97
+ await this.simulateDelay();
98
+
99
+ if (this.simulateErrors && Math.random() < 0.3) {
100
+ throw new Error('Simulated loading error - try again!');
101
+ }
102
+
103
+ const nodes = this.generateMockNodes('', 0);
104
+
105
+ return {
106
+ nodes,
107
+ hasMore: false,
108
+ totalCount: nodes.length
109
+ };
110
+ }
111
+
112
+ /**
113
+ * Load child nodes for a given parent
114
+ */
115
+ async loadChildren(node: TreeNodeData, options?: TreeLoadOptions): Promise<TreeLoadResult> {
116
+ await this.simulateDelay();
117
+
118
+ if (this.simulateErrors && Math.random() < 0.3) {
119
+ throw new Error('Simulated loading error - try again!');
120
+ }
121
+
122
+ // Generate children for the given node
123
+ const pathParts = node.path.split('/').filter(Boolean);
124
+ const depth = pathParts.length;
125
+
126
+ // Only generate children if we haven't exceeded max depth
127
+ if (depth >= this.maxDepth) {
128
+ return {
129
+ nodes: [],
130
+ hasMore: false,
131
+ totalCount: 0
132
+ };
133
+ }
134
+
135
+ const children = this.generateMockNodes(node.path, depth);
136
+
137
+ return {
138
+ nodes: children,
139
+ hasMore: false,
140
+ totalCount: children.length
141
+ };
142
+ }
143
+
144
+ /**
145
+ * Refresh tree data
146
+ */
147
+ async refresh(path?: string): Promise<TreeLoadResult> {
148
+ return path ? this.loadChildren({ path } as TreeNodeData) : this.loadNodes();
149
+ }
150
+
151
+ canExpand(node: TreeNodeData): boolean {
152
+ return node.type === 'directory' && (node.hasChildren ?? true);
153
+ }
154
+
155
+ canSelect(node: TreeNodeData): boolean {
156
+ return !node.disabled;
157
+ }
158
+
159
+ // Context menu support
160
+ getNodeContextMenu(node: TreeNodeData): TreeContextMenuItem[] {
161
+ // Enhanced context menus based on node type and file extension
162
+ const baseItems: TreeContextMenuItem[] = [];
163
+
164
+ if (node.type === 'directory') {
165
+ // Folder-specific menus
166
+ if (node.name.includes('components')) {
167
+ // React Components folder
168
+ return [
169
+ { id: 'open', label: 'Open Folder' },
170
+ { id: 'separator-1', label: '', type: 'separator' },
171
+ { id: 'new-component', label: 'New React Component' },
172
+ { id: 'new-hook', label: 'New Custom Hook' },
173
+ { id: 'new-story', label: 'New Storybook Story' },
174
+ { id: 'separator-2', label: '', type: 'separator' },
175
+ { id: 'run-tests', label: 'Run Component Tests' },
176
+ { id: 'build-docs', label: 'Generate Docs' },
177
+ { id: 'separator-3', label: '', type: 'separator' },
178
+ { id: 'rename', label: 'Rename Folder' },
179
+ { id: 'delete', label: 'Delete Folder' }
180
+ ];
181
+ } else if (node.name.includes('config')) {
182
+ // Configuration folder
183
+ return [
184
+ { id: 'open', label: 'Open Config Folder' },
185
+ { id: 'separator-1', label: '', type: 'separator' },
186
+ { id: 'new-env', label: 'New Environment File' },
187
+ { id: 'new-config', label: 'New Config File' },
188
+ { id: 'validate-config', label: 'Validate Configuration' },
189
+ { id: 'separator-2', label: '', type: 'separator' },
190
+ { id: 'backup-config', label: 'Backup Configuration' },
191
+ { id: 'restore-config', label: 'Restore from Backup' },
192
+ { id: 'separator-3', label: '', type: 'separator' },
193
+ { id: 'rename', label: 'Rename Folder' },
194
+ { id: 'delete', label: 'Delete Folder' }
195
+ ];
196
+ } else {
197
+ // General folder menu
198
+ return [
199
+ { id: 'open', label: 'Open Folder' },
200
+ { id: 'separator-1', label: '', type: 'separator' },
201
+ { id: 'new-file', label: 'New File' },
202
+ { id: 'new-folder', label: 'New Folder' },
203
+ { id: 'separator-2', label: '', type: 'separator' },
204
+ { id: 'import-files', label: 'Import Files' },
205
+ { id: 'export-folder', label: 'Export Folder' },
206
+ { id: 'separator-3', label: '', type: 'separator' },
207
+ { id: 'rename', label: 'Rename Folder' },
208
+ { id: 'delete', label: 'Delete Folder' },
209
+ { id: 'separator-4', label: '', type: 'separator' },
210
+ { id: 'copy', label: 'Copy Folder' },
211
+ { id: 'cut', label: 'Cut Folder' }
212
+ ];
213
+ }
214
+ }
215
+
216
+ // File-specific menus based on extension
217
+ const fileName = node.name;
218
+ const fileExt = fileName.split('.').pop()?.toLowerCase() || '';
219
+
220
+ switch (fileExt) {
221
+ case 'js':
222
+ case 'jsx':
223
+ // JavaScript/React files
224
+ return [
225
+ { id: 'open', label: 'Open in Editor' },
226
+ { id: 'open-preview', label: 'Open in Preview' },
227
+ { id: 'separator-1', label: '', type: 'separator' },
228
+ { id: 'run-file', label: 'Run JavaScript' },
229
+ { id: 'debug-file', label: 'Debug in Browser' },
230
+ { id: 'format-code', label: 'Format with Prettier' },
231
+ { id: 'separator-2', label: '', type: 'separator' },
232
+ { id: 'create-test', label: 'Create Test File' },
233
+ { id: 'run-tests', label: 'Run Tests' },
234
+ { id: 'separator-3', label: '', type: 'separator' },
235
+ { id: 'rename', label: 'Rename File' },
236
+ { id: 'duplicate', label: 'Duplicate File' },
237
+ { id: 'delete', label: 'Delete File' }
238
+ ];
239
+
240
+ case 'ts':
241
+ case 'tsx':
242
+ // TypeScript files
243
+ return [
244
+ { id: 'open', label: 'Open in Editor' },
245
+ { id: 'open-preview', label: 'Open in Preview' },
246
+ { id: 'separator-1', label: '', type: 'separator' },
247
+ { id: 'compile-ts', label: 'Compile TypeScript' },
248
+ { id: 'type-check', label: 'Run Type Check' },
249
+ { id: 'generate-types', label: 'Generate Type Definitions' },
250
+ { id: 'separator-2', label: '', type: 'separator' },
251
+ { id: 'create-test', label: 'Create Test File' },
252
+ { id: 'run-tests', label: 'Run Tests' },
253
+ { id: 'separator-3', label: '', type: 'separator' },
254
+ { id: 'rename', label: 'Rename File' },
255
+ { id: 'duplicate', label: 'Duplicate File' },
256
+ { id: 'delete', label: 'Delete File' }
257
+ ];
258
+
259
+ case 'css':
260
+ case 'scss':
261
+ case 'sass':
262
+ case 'less':
263
+ // Stylesheet files
264
+ return [
265
+ { id: 'open', label: 'Open in Editor' },
266
+ { id: 'open-preview', label: 'Live Preview' },
267
+ { id: 'separator-1', label: '', type: 'separator' },
268
+ { id: 'compile-css', label: 'Compile Stylesheet' },
269
+ { id: 'optimize-css', label: 'Optimize CSS' },
270
+ { id: 'validate-css', label: 'Validate CSS' },
271
+ { id: 'separator-2', label: '', type: 'separator' },
272
+ { id: 'extract-vars', label: 'Extract CSS Variables' },
273
+ { id: 'generate-rtl', label: 'Generate RTL Version' },
274
+ { id: 'separator-3', label: '', type: 'separator' },
275
+ { id: 'rename', label: 'Rename File' },
276
+ { id: 'duplicate', label: 'Duplicate File' },
277
+ { id: 'delete', label: 'Delete File' }
278
+ ];
279
+
280
+ case 'md':
281
+ case 'mdx':
282
+ // Markdown files
283
+ return [
284
+ { id: 'open', label: 'Open in Editor' },
285
+ { id: 'open-preview', label: 'Preview Markdown' },
286
+ { id: 'separator-1', label: '', type: 'separator' },
287
+ { id: 'export-html', label: 'Export to HTML' },
288
+ { id: 'export-pdf', label: 'Export to PDF' },
289
+ { id: 'check-links', label: 'Check Links' },
290
+ { id: 'separator-2', label: '', type: 'separator' },
291
+ { id: 'toc-generate', label: 'Generate Table of Contents' },
292
+ { id: 'word-count', label: 'Word Count & Stats' },
293
+ { id: 'separator-3', label: '', type: 'separator' },
294
+ { id: 'rename', label: 'Rename File' },
295
+ { id: 'duplicate', label: 'Duplicate File' },
296
+ { id: 'delete', label: 'Delete File' }
297
+ ];
298
+
299
+ case 'json':
300
+ // JSON configuration files
301
+ return [
302
+ { id: 'open', label: 'Open in Editor' },
303
+ { id: 'open-viewer', label: 'Open JSON Viewer' },
304
+ { id: 'separator-1', label: '', type: 'separator' },
305
+ { id: 'validate-json', label: 'Validate JSON' },
306
+ { id: 'format-json', label: 'Format JSON' },
307
+ { id: 'minify-json', label: 'Minify JSON' },
308
+ { id: 'separator-2', label: '', type: 'separator' },
309
+ { id: 'compare-json', label: 'Compare with...' },
310
+ { id: 'schema-validate', label: 'Validate Against Schema' },
311
+ { id: 'separator-3', label: '', type: 'separator' },
312
+ { id: 'rename', label: 'Rename File' },
313
+ { id: 'duplicate', label: 'Duplicate File' },
314
+ { id: 'delete', label: 'Delete File' }
315
+ ];
316
+
317
+ case 'jpg':
318
+ case 'jpeg':
319
+ case 'png':
320
+ case 'gif':
321
+ case 'svg':
322
+ case 'webp':
323
+ // Image files
324
+ return [
325
+ { id: 'open', label: 'Open Image' },
326
+ { id: 'open-editor', label: 'Edit in Image Editor' },
327
+ { id: 'separator-1', label: '', type: 'separator' },
328
+ { id: 'resize-image', label: 'Resize Image' },
329
+ { id: 'compress-image', label: 'Compress Image' },
330
+ { id: 'convert-format', label: 'Convert Format' },
331
+ { id: 'separator-2', label: '', type: 'separator' },
332
+ { id: 'image-info', label: 'Image Properties' },
333
+ { id: 'copy-url', label: 'Copy Image URL' },
334
+ { id: 'separator-3', label: '', type: 'separator' },
335
+ { id: 'rename', label: 'Rename File' },
336
+ { id: 'duplicate', label: 'Duplicate File' },
337
+ { id: 'delete', label: 'Delete File' }
338
+ ];
339
+
340
+ default:
341
+ // Generic file menu
342
+ return [
343
+ { id: 'open', label: 'Open File' },
344
+ { id: 'open-with', label: 'Open With...' },
345
+ { id: 'separator-1', label: '', type: 'separator' },
346
+ { id: 'properties', label: 'File Properties' },
347
+ { id: 'permissions', label: 'Change Permissions' },
348
+ { id: 'separator-2', label: '', type: 'separator' },
349
+ { id: 'rename', label: 'Rename File' },
350
+ { id: 'duplicate', label: 'Duplicate File' },
351
+ { id: 'delete', label: 'Delete File' },
352
+ { id: 'separator-3', label: '', type: 'separator' },
353
+ { id: 'copy', label: 'Copy File' },
354
+ { id: 'cut', label: 'Cut File' }
355
+ ];
356
+ }
357
+ }
358
+
359
+ getMultiNodeContextMenu(nodes: TreeNodeData[]): TreeContextMenuItem[] {
360
+ // Enhanced multi-selection menus
361
+ const hasFiles = nodes.some(n => n.type === 'file');
362
+ const hasFolders = nodes.some(n => n.type === 'directory');
363
+ const allSameType = hasFiles && !hasFolders || hasFolders && !hasFiles;
364
+
365
+ if (allSameType && hasFiles) {
366
+ // All files selected
367
+ return [
368
+ { id: 'open-all', label: `Open ${nodes.length} Files` },
369
+ { id: 'separator-1', label: '', type: 'separator' },
370
+ { id: 'compress-files', label: `Create Archive (${nodes.length} files)` },
371
+ { id: 'copy-paths', label: 'Copy File Paths' },
372
+ { id: 'separator-2', label: '', type: 'separator' },
373
+ { id: 'copy-all', label: `Copy ${nodes.length} Files` },
374
+ { id: 'cut-all', label: `Cut ${nodes.length} Files` },
375
+ { id: 'delete-all', label: `Delete ${nodes.length} Files` }
376
+ ];
377
+ } else if (allSameType && hasFolders) {
378
+ // All folders selected
379
+ return [
380
+ { id: 'open-all', label: `Open ${nodes.length} Folders` },
381
+ { id: 'separator-1', label: '', type: 'separator' },
382
+ { id: 'merge-folders', label: 'Merge Folders' },
383
+ { id: 'compare-folders', label: 'Compare Folders' },
384
+ { id: 'separator-2', label: '', type: 'separator' },
385
+ { id: 'copy-all', label: `Copy ${nodes.length} Folders` },
386
+ { id: 'cut-all', label: `Cut ${nodes.length} Folders` },
387
+ { id: 'delete-all', label: `Delete ${nodes.length} Folders` }
388
+ ];
389
+ } else {
390
+ // Mixed selection (files and folders)
391
+ return [
392
+ { id: 'open-all', label: `Open ${nodes.length} Items` },
393
+ { id: 'separator-1', label: '', type: 'separator' },
394
+ { id: 'compress-all', label: `Create Archive (${nodes.length} items)` },
395
+ { id: 'copy-info', label: 'Copy Selection Info' },
396
+ { id: 'separator-2', label: '', type: 'separator' },
397
+ { id: 'copy-all', label: `Copy ${nodes.length} Items` },
398
+ { id: 'cut-all', label: `Cut ${nodes.length} Items` },
399
+ { id: 'delete-all', label: `Delete ${nodes.length} Items` }
400
+ ];
401
+ }
402
+ }
403
+
404
+ onContextMenuAction(menuItemId: string, nodes: TreeNodeData[]): void {
405
+ const nodeNames = nodes.map(n => n.name).join(', ');
406
+ console.log(`🎯 Context menu action: ${menuItemId} on nodes: ${nodeNames}`);
407
+
408
+ // Enhanced action handling with more detailed logging
409
+ switch (menuItemId) {
410
+ // File operations
411
+ case 'open':
412
+ case 'open-all':
413
+ console.log(`📂 Opening: ${nodeNames}`);
414
+ alert(`Opening: ${nodeNames}`);
415
+ break;
416
+ case 'open-preview':
417
+ console.log(`👁️ Opening preview for: ${nodeNames}`);
418
+ alert(`Preview mode for: ${nodeNames}`);
419
+ break;
420
+ case 'open-editor':
421
+ console.log(`✏️ Opening in editor: ${nodeNames}`);
422
+ alert(`Editor opened for: ${nodeNames}`);
423
+ break;
424
+
425
+ // Development operations
426
+ case 'run-file':
427
+ case 'run-tests':
428
+ console.log(`▶️ Running: ${nodeNames}`);
429
+ alert(`Executing: ${nodeNames}`);
430
+ break;
431
+ case 'debug-file':
432
+ console.log(`🐛 Debugging: ${nodeNames}`);
433
+ alert(`Debug session started for: ${nodeNames}`);
434
+ break;
435
+ case 'compile-ts':
436
+ case 'compile-css':
437
+ console.log(`🔨 Compiling: ${nodeNames}`);
438
+ alert(`Compilation started for: ${nodeNames}`);
439
+ break;
440
+ case 'format-code':
441
+ case 'format-json':
442
+ console.log(`🎨 Formatting: ${nodeNames}`);
443
+ alert(`Code formatted: ${nodeNames}`);
444
+ break;
445
+ case 'type-check':
446
+ console.log(`🔍 Type checking: ${nodeNames}`);
447
+ alert(`Type check completed for: ${nodeNames}`);
448
+ break;
449
+
450
+ // Creation operations
451
+ case 'new-file':
452
+ case 'new-folder':
453
+ case 'new-component':
454
+ case 'new-hook':
455
+ case 'new-story':
456
+ console.log(`➕ Creating new ${menuItemId.replace('new-', '')} in: ${nodeNames}`);
457
+ alert(`Creating new ${menuItemId.replace('new-', '')} in: ${nodeNames}`);
458
+ break;
459
+
460
+ // Export/Import operations
461
+ case 'export-html':
462
+ case 'export-pdf':
463
+ console.log(`📤 Exporting ${menuItemId.replace('export-', '')}: ${nodeNames}`);
464
+ alert(`Exporting ${menuItemId.replace('export-', '').toUpperCase()}: ${nodeNames}`);
465
+ break;
466
+ case 'import-files':
467
+ console.log(`📥 Importing files to: ${nodeNames}`);
468
+ alert(`Import dialog opened for: ${nodeNames}`);
469
+ break;
470
+
471
+ // File management
472
+ case 'rename':
473
+ console.log(`✏️ Renaming: ${nodeNames}`);
474
+ alert(`Rename dialog for: ${nodeNames}`);
475
+ break;
476
+ case 'duplicate':
477
+ console.log(`📋 Duplicating: ${nodeNames}`);
478
+ alert(`Duplicated: ${nodeNames}`);
479
+ break;
480
+ case 'delete':
481
+ case 'delete-all':
482
+ console.log(`🗑️ Deleting: ${nodeNames}`);
483
+ alert(`Deleted: ${nodeNames}`);
484
+ break;
485
+ case 'copy':
486
+ case 'copy-all':
487
+ console.log(`📋 Copying: ${nodeNames}`);
488
+ alert(`Copied to clipboard: ${nodeNames}`);
489
+ break;
490
+ case 'cut':
491
+ case 'cut-all':
492
+ console.log(`✂️ Cutting: ${nodeNames}`);
493
+ alert(`Cut to clipboard: ${nodeNames}`);
494
+ break;
495
+
496
+ // Specialized operations
497
+ case 'validate-json':
498
+ case 'validate-css':
499
+ case 'validate-config':
500
+ console.log(`✅ Validating: ${nodeNames}`);
501
+ alert(`Validation passed for: ${nodeNames}`);
502
+ break;
503
+ case 'compress-image':
504
+ case 'compress-files':
505
+ case 'compress-all':
506
+ console.log(`🗜️ Compressing: ${nodeNames}`);
507
+ alert(`Compression completed for: ${nodeNames}`);
508
+ break;
509
+ case 'image-info':
510
+ case 'properties':
511
+ console.log(`ℹ️ Showing properties for: ${nodeNames}`);
512
+ alert(`Properties: ${nodeNames}\nSize: 1.2MB\nType: ${nodes[0]?.type || 'unknown'}\nModified: ${nodes[0]?.lastModified?.toLocaleDateString() || 'unknown'}`);
513
+ break;
514
+
515
+ default:
516
+ console.log(`❓ Unknown action: ${menuItemId}`);
517
+ alert(`Action executed: ${menuItemId} on ${nodeNames}`);
518
+ }
519
+ }
520
+
521
+ // Table view configuration
522
+ getTableColumns(): TreeTableColumn[] {
523
+ return [
524
+ {
525
+ id: 'name',
526
+ label: 'Name',
527
+ dataKey: 'name',
528
+ width: '300px',
529
+ sortable: true,
530
+ filterable: true,
531
+ isTreeColumn: true,
532
+ align: 'left'
533
+ },
534
+ {
535
+ id: 'type',
536
+ label: 'Type',
537
+ dataKey: 'type',
538
+ width: '100px',
539
+ sortable: true,
540
+ filterable: true,
541
+ align: 'left',
542
+ formatValue: (value: string) => value === 'directory' ? 'Folder' : 'File'
543
+ },
544
+ {
545
+ id: 'size',
546
+ label: 'Size',
547
+ dataKey: 'size',
548
+ width: '100px',
549
+ sortable: true,
550
+ align: 'right',
551
+ formatValue: (value: number, node: TreeNodeData) => {
552
+ if (node.type === 'directory') return '-';
553
+ if (!value) return '-';
554
+
555
+ if (value < 1024) return `${value} B`;
556
+ if (value < 1024 * 1024) return `${(value / 1024).toFixed(1)} KB`;
557
+ if (value < 1024 * 1024 * 1024) return `${(value / (1024 * 1024)).toFixed(1)} MB`;
558
+ return `${(value / (1024 * 1024 * 1024)).toFixed(1)} GB`;
559
+ }
560
+ },
561
+ {
562
+ id: 'lastModified',
563
+ label: 'Modified',
564
+ dataKey: 'lastModified',
565
+ width: '150px',
566
+ sortable: true,
567
+ align: 'left',
568
+ formatValue: (value: Date) => {
569
+ if (!value) return '-';
570
+ return value.toLocaleDateString();
571
+ }
572
+ },
573
+ {
574
+ id: 'path',
575
+ label: 'Path',
576
+ dataKey: 'path',
577
+ width: '200px',
578
+ sortable: true,
579
+ filterable: true,
580
+ align: 'left'
581
+ }
582
+ ];
583
+ }
584
+
585
+ getDefaultTableSort(): TreeTableSort {
586
+ return {
587
+ columnId: 'name',
588
+ direction: 'asc'
589
+ };
590
+ }
591
+
592
+ onTableSort(sort: TreeTableSort | null): void {
593
+ console.log('Table sort changed:', sort);
594
+ }
595
+
596
+ async onTableExport(options: TreeTableExportOptions): Promise<string | void> {
597
+ console.log('Table export requested:', options);
598
+ alert(`Export to ${options.format.toUpperCase()} format requested`);
599
+ }
600
+
601
+ private async simulateDelay(): Promise<void> {
602
+ const delay = this.slowLoading ? 1000 : this.loadingDelay;
603
+ await new Promise(resolve => setTimeout(resolve, delay));
604
+ }
605
+
606
+ private generateMockNodes(parentPath: string, depth: number): TreeNodeData[] {
607
+ if (depth >= this.maxDepth) {
608
+ return [];
609
+ }
610
+
611
+ const nodes: TreeNodeData[] = [];
612
+
613
+ // Enhanced file types with better variety for icon demo
614
+ const fileTypes = [
615
+ // Web Development
616
+ 'js', 'jsx', 'ts', 'tsx', 'html', 'css', 'scss', 'sass', 'less',
617
+ // Documentation & Content
618
+ 'md', 'mdx', 'txt', 'pdf',
619
+ // Data & Config
620
+ 'json', 'yml', 'yaml', 'xml', 'env', 'config',
621
+ // Images
622
+ 'jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'ico',
623
+ // Media
624
+ 'mp4', 'mp3', 'wav', 'avi',
625
+ // Archives & Executables
626
+ 'zip', 'tar', 'gz', 'exe', 'app', 'dmg',
627
+ // Development
628
+ 'py', 'php', 'java', 'cpp', 'c', 'go', 'rs', 'rb'
629
+ ];
630
+
631
+ // Enhanced folder names with special types for icon demo
632
+ const folderTypes = [
633
+ // Development Folders
634
+ { name: 'components', type: 'react' },
635
+ { name: 'hooks', type: 'react' },
636
+ { name: 'pages', type: 'react' },
637
+ { name: 'utils', type: 'code' },
638
+ { name: 'lib', type: 'code' },
639
+ { name: 'src', type: 'source' },
640
+ // Config & Build
641
+ { name: 'config', type: 'config' },
642
+ { name: 'build', type: 'build' },
643
+ { name: 'dist', type: 'build' },
644
+ { name: '.github', type: 'git' },
645
+ { name: '.vscode', type: 'vscode' },
646
+ // Assets & Media
647
+ { name: 'assets', type: 'assets' },
648
+ { name: 'images', type: 'images' },
649
+ { name: 'media', type: 'media' },
650
+ { name: 'public', type: 'public' },
651
+ // Documentation & Tests
652
+ { name: 'docs', type: 'docs' },
653
+ { name: 'tests', type: 'test' },
654
+ { name: '__tests__', type: 'test' },
655
+ // Node.js specific
656
+ { name: 'node_modules', type: 'node_modules' }
657
+ ];
658
+
659
+ for (let i = 0; i < this.nodesPerLevel; i++) {
660
+ const nodeId = `${parentPath || 'root'}-${depth}-${i}`.replace(/[^a-zA-Z0-9-_]/g, '-');
661
+
662
+ const shouldBeFolder = depth < this.maxDepth - 1 && (i < this.nodesPerLevel / 2 || Math.random() < 0.4);
663
+
664
+ if (shouldBeFolder) {
665
+ const folderType = folderTypes[i % folderTypes.length] || { name: `folder-${i}`, type: 'default' };
666
+ const folderPath = parentPath ? `${parentPath}/${folderType.name}` : `/${folderType.name}`;
667
+
668
+ nodes.push({
669
+ id: nodeId,
670
+ name: folderType.name,
671
+ path: folderPath,
672
+ type: 'directory',
673
+ hasChildren: depth < this.maxDepth - 1,
674
+ lastModified: new Date(Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000),
675
+ // Add metadata for enhanced demo
676
+ metadata: {
677
+ folderType: folderType.type,
678
+ description: this.getFolderDescription(folderType.type)
679
+ }
680
+ });
681
+ } else {
682
+ const fileType = fileTypes[i % fileTypes.length] || 'txt';
683
+ const fileName = this.generateFileName(fileType, i);
684
+ const filePath = parentPath ? `${parentPath}/${fileName}` : `/${fileName}`;
685
+
686
+ nodes.push({
687
+ id: nodeId,
688
+ name: fileName,
689
+ path: filePath,
690
+ type: 'file',
691
+ hasChildren: false,
692
+ size: Math.floor(Math.random() * 1000000) + 1024,
693
+ lastModified: new Date(Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000),
694
+ // Add metadata for enhanced demo
695
+ metadata: {
696
+ fileType: fileType,
697
+ category: this.getFileCategory(fileType),
698
+ description: this.getFileDescription(fileType)
699
+ }
700
+ });
701
+ }
702
+ }
703
+
704
+ return nodes;
705
+ }
706
+
707
+ private generateFileName(fileType: string, index: number): string {
708
+ const fileNames: Record<string, string[]> = {
709
+ 'js': ['utils', 'helpers', 'config', 'index', 'main'],
710
+ 'jsx': ['App', 'Component', 'Button', 'Modal', 'Form'],
711
+ 'ts': ['types', 'interfaces', 'utils', 'service', 'api'],
712
+ 'tsx': ['HomePage', 'UserCard', 'Navigation', 'Layout', 'Dashboard'],
713
+ 'css': ['styles', 'main', 'theme', 'reset', 'variables'],
714
+ 'scss': ['app', 'components', 'layout', 'mixins', 'variables'],
715
+ 'md': ['README', 'CHANGELOG', 'CONTRIBUTING', 'DOCS', 'API'],
716
+ 'json': ['package', 'tsconfig', 'config', 'settings', 'data'],
717
+ 'yml': ['docker-compose', 'config', 'ci', 'deployment', 'settings'],
718
+ 'py': ['main', 'utils', 'models', 'views', 'tests'],
719
+ 'jpg': ['hero-image', 'profile', 'banner', 'thumbnail', 'cover'],
720
+ 'png': ['logo', 'icon', 'screenshot', 'diagram', 'chart']
721
+ };
722
+
723
+ const names = fileNames[fileType] || ['file'];
724
+ const baseName = names[index % names.length];
725
+
726
+ return `${baseName}.${fileType}`;
727
+ }
728
+
729
+
730
+ private getFolderDescription(folderType: string): string {
731
+ const descriptions: Record<string, string> = {
732
+ 'react': 'React components and hooks',
733
+ 'source': 'Source code files',
734
+ 'code': 'Utility functions and libraries',
735
+ 'config': 'Configuration files',
736
+ 'build': 'Build output and artifacts',
737
+ 'git': 'Git workflow configurations',
738
+ 'vscode': 'VS Code editor settings',
739
+ 'assets': 'Project assets and resources',
740
+ 'images': 'Image files and graphics',
741
+ 'media': 'Media files (video, audio)',
742
+ 'public': 'Public static files',
743
+ 'docs': 'Documentation files',
744
+ 'test': 'Test files and specs',
745
+ 'node_modules': 'Node.js dependencies',
746
+ 'default': 'General folder'
747
+ };
748
+
749
+ return descriptions[folderType] || 'General folder';
750
+ }
751
+
752
+
753
+ private getFileCategory(fileType: string): string {
754
+ const categories: Record<string, string> = {
755
+ // Web Development
756
+ 'js': 'JavaScript', 'jsx': 'React', 'ts': 'TypeScript', 'tsx': 'React TypeScript',
757
+ 'css': 'Stylesheet', 'scss': 'Sass', 'sass': 'Sass', 'less': 'Less',
758
+ 'html': 'Markup', 'xml': 'Markup', 'svg': 'Vector Graphics',
759
+
760
+ // Documentation
761
+ 'md': 'Markdown', 'txt': 'Text', 'pdf': 'Document',
762
+
763
+ // Configuration
764
+ 'json': 'Data', 'yml': 'Config', 'yaml': 'Config', 'env': 'Environment',
765
+
766
+ // Media
767
+ 'jpg': 'Image', 'png': 'Image', 'gif': 'Image',
768
+ 'mp3': 'Audio', 'mp4': 'Video',
769
+
770
+ // Programming
771
+ 'py': 'Python', 'php': 'PHP', 'java': 'Java', 'cpp': 'C++', 'go': 'Go',
772
+
773
+ // Archives
774
+ 'zip': 'Archive', 'tar': 'Archive',
775
+
776
+ // Default
777
+ 'default': 'File'
778
+ };
779
+
780
+ return categories[fileType] || categories['default'] || 'File';
781
+ }
782
+
783
+ private getFileDescription(fileType: string): string {
784
+ const descriptions: Record<string, string> = {
785
+ 'js': 'JavaScript source file',
786
+ 'jsx': 'React component file',
787
+ 'ts': 'TypeScript source file',
788
+ 'tsx': 'React TypeScript component',
789
+ 'css': 'Cascading Style Sheet',
790
+ 'scss': 'Sass stylesheet',
791
+ 'html': 'HTML markup file',
792
+ 'md': 'Markdown documentation',
793
+ 'json': 'JSON data file',
794
+ 'py': 'Python script',
795
+ 'jpg': 'JPEG image file',
796
+ 'png': 'PNG image file',
797
+ 'mp3': 'MP3 audio file',
798
+ 'zip': 'Compressed archive'
799
+ };
800
+
801
+ return descriptions[fileType] || `${fileType.toUpperCase()} file`;
802
+ }
803
+
804
+ /**
805
+ * Get custom icon for a node based on file type and category
806
+ */
807
+ getNodeIcon(node: TreeNodeData): string | React.ComponentType<any> {
808
+ // If it's a directory/folder, use special folder icons
809
+ if (node.type === 'directory') {
810
+ // Special folder icons based on name
811
+ if (node.name.includes('components')) {
812
+ return Component; // React component folder
813
+ }
814
+ if (node.name.includes('assets') || node.name.includes('images')) {
815
+ return Image;
816
+ }
817
+ if (node.name.includes('config') || node.name.includes('settings')) {
818
+ return Settings;
819
+ }
820
+ if (node.name.includes('docs') || node.name.includes('documentation')) {
821
+ return BookOpen;
822
+ }
823
+ if (node.name.includes('test') || node.name.includes('__tests__')) {
824
+ return TestTube;
825
+ }
826
+ if (node.name.includes('lib') || node.name.includes('library')) {
827
+ return Package;
828
+ }
829
+
830
+ // Default folder icons (already handled by TreeNodeList)
831
+ return 'folder';
832
+ }
833
+
834
+ // File icons based on extension
835
+ const extension = node.name.split('.').pop() || '';
836
+
837
+ switch (extension.toLowerCase()) {
838
+ // Web Development
839
+ case 'js':
840
+ case 'jsx':
841
+ return FileText; // JavaScript icon
842
+
843
+ case 'ts':
844
+ case 'tsx':
845
+ return Code; // TypeScript icon
846
+
847
+ case 'html':
848
+ case 'htm':
849
+ return Globe; // HTML icon
850
+
851
+ case 'css':
852
+ case 'scss':
853
+ case 'sass':
854
+ case 'less':
855
+ return Palette; // Stylesheet icon
856
+
857
+ // Documentation
858
+ case 'md':
859
+ case 'mdx':
860
+ return FileText; // Markdown icon
861
+
862
+ case 'txt':
863
+ return FileText;
864
+
865
+ case 'pdf':
866
+ return FileText;
867
+
868
+ // Data & Configuration
869
+ case 'json':
870
+ return Braces; // JSON icon
871
+
872
+ case 'yml':
873
+ case 'yaml':
874
+ return Settings; // YAML icon
875
+
876
+ case 'xml':
877
+ return Code; // XML icon
878
+
879
+ case 'env':
880
+ return Key; // Environment file icon
881
+
882
+ case 'config':
883
+ return Settings; // Config file icon
884
+
885
+ // Images
886
+ case 'jpg':
887
+ case 'jpeg':
888
+ case 'png':
889
+ case 'gif':
890
+ case 'webp':
891
+ case 'bmp':
892
+ case 'tiff':
893
+ case 'ico':
894
+ return Image; // Image icon
895
+
896
+ case 'svg':
897
+ return Zap; // SVG icon (special since it's vector)
898
+
899
+ // Media
900
+ case 'mp4':
901
+ case 'avi':
902
+ case 'mov':
903
+ case 'mkv':
904
+ return Play; // Video icon
905
+
906
+ case 'mp3':
907
+ case 'wav':
908
+ case 'flac':
909
+ case 'ogg':
910
+ return Music; // Audio icon
911
+
912
+ // Archives
913
+ case 'zip':
914
+ case 'tar':
915
+ case 'gz':
916
+ case '7z':
917
+ case 'rar':
918
+ return Archive; // Archive icon
919
+
920
+ // Executables
921
+ case 'exe':
922
+ case 'app':
923
+ case 'deb':
924
+ case 'dmg':
925
+ return Zap; // Executable icon
926
+
927
+ // Development Tools
928
+ case 'git':
929
+ case 'gitignore':
930
+ return GitBranch; // Git icon
931
+
932
+ case 'dockerfile':
933
+ return Package; // Docker icon
934
+
935
+ case 'sql':
936
+ return Database; // Database icon
937
+
938
+ case 'log':
939
+ return FileText; // Log file icon
940
+
941
+ // Default file icon (handled by TreeNodeList)
942
+ default:
943
+ return 'file'; // Use default File icon
944
+ }
945
+ }
946
+ }