@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,219 @@
1
+ import React, { useState } from 'react';
2
+ import {
3
+ ChevronDown,
4
+ ChevronRight,
5
+ Plus,
6
+ Minus,
7
+ FileText,
8
+ FilePlus2,
9
+ FileX2,
10
+ FileEdit,
11
+ ArrowRightLeft,
12
+ } from 'lucide-react';
13
+ import type { GitDiffEntry } from '@anymux/file-system';
14
+
15
+ // ---- Helpers ----
16
+
17
+ function statusIcon(status: GitDiffEntry['status']) {
18
+ switch (status) {
19
+ case 'added':
20
+ return <FilePlus2 className="h-3.5 w-3.5 text-green-500" />;
21
+ case 'deleted':
22
+ return <FileX2 className="h-3.5 w-3.5 text-red-500" />;
23
+ case 'modified':
24
+ return <FileEdit className="h-3.5 w-3.5 text-yellow-500" />;
25
+ case 'renamed':
26
+ return <ArrowRightLeft className="h-3.5 w-3.5 text-blue-500" />;
27
+ }
28
+ }
29
+
30
+ function statusLabel(status: GitDiffEntry['status']): string {
31
+ switch (status) {
32
+ case 'added': return 'Added';
33
+ case 'deleted': return 'Deleted';
34
+ case 'modified': return 'Modified';
35
+ case 'renamed': return 'Renamed';
36
+ }
37
+ }
38
+
39
+ function statusBadgeClass(status: GitDiffEntry['status']): string {
40
+ switch (status) {
41
+ case 'added':
42
+ return 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400';
43
+ case 'deleted':
44
+ return 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400';
45
+ case 'modified':
46
+ return 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400';
47
+ case 'renamed':
48
+ return 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400';
49
+ }
50
+ }
51
+
52
+ interface PatchLine {
53
+ type: 'context' | 'addition' | 'deletion' | 'header';
54
+ content: string;
55
+ }
56
+
57
+ function parsePatch(patch: string): PatchLine[] {
58
+ const lines = patch.split('\n');
59
+ return lines.map((line) => {
60
+ if (line.startsWith('@@')) {
61
+ return { type: 'header', content: line };
62
+ } else if (line.startsWith('+')) {
63
+ return { type: 'addition', content: line };
64
+ } else if (line.startsWith('-')) {
65
+ return { type: 'deletion', content: line };
66
+ }
67
+ return { type: 'context', content: line };
68
+ });
69
+ }
70
+
71
+ function lineClassName(type: PatchLine['type']): string {
72
+ switch (type) {
73
+ case 'addition':
74
+ return 'bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-300';
75
+ case 'deletion':
76
+ return 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-300';
77
+ case 'header':
78
+ return 'bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 font-medium';
79
+ default:
80
+ return 'text-gray-700 dark:text-gray-300';
81
+ }
82
+ }
83
+
84
+ // ---- Types ----
85
+
86
+ export interface DiffViewerProps {
87
+ entries: GitDiffEntry[];
88
+ className?: string;
89
+ }
90
+
91
+ // ---- File Diff Section ----
92
+
93
+ interface FileDiffSectionProps {
94
+ entry: GitDiffEntry;
95
+ defaultExpanded?: boolean;
96
+ }
97
+
98
+ function FileDiffSection({ entry, defaultExpanded = false }: FileDiffSectionProps) {
99
+ const [expanded, setExpanded] = useState(defaultExpanded);
100
+ const patchLines = entry.patch ? parsePatch(entry.patch) : [];
101
+
102
+ return (
103
+ <div className="border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden">
104
+ {/* File header */}
105
+ <button
106
+ onClick={() => setExpanded(!expanded)}
107
+ className="flex items-center gap-2 w-full px-3 py-2 bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-700/50 transition-colors text-left"
108
+ >
109
+ <span className="flex-shrink-0 text-gray-400">
110
+ {expanded ? (
111
+ <ChevronDown className="h-3.5 w-3.5" />
112
+ ) : (
113
+ <ChevronRight className="h-3.5 w-3.5" />
114
+ )}
115
+ </span>
116
+
117
+ {statusIcon(entry.status)}
118
+
119
+ <span className="text-xs font-mono truncate flex-1">
120
+ {entry.previousPath && entry.status === 'renamed' ? (
121
+ <>
122
+ <span className="text-gray-400">{entry.previousPath}</span>
123
+ <span className="text-gray-500 mx-1">&rarr;</span>
124
+ <span>{entry.path}</span>
125
+ </>
126
+ ) : (
127
+ entry.path
128
+ )}
129
+ </span>
130
+
131
+ <span className={`px-1.5 py-0.5 text-[9px] font-medium rounded flex-shrink-0 ${statusBadgeClass(entry.status)}`}>
132
+ {statusLabel(entry.status)}
133
+ </span>
134
+
135
+ <div className="flex items-center gap-1.5 flex-shrink-0 text-[10px]">
136
+ {entry.additions > 0 && (
137
+ <span className="flex items-center gap-0.5 text-green-600 dark:text-green-400">
138
+ <Plus className="h-2.5 w-2.5" />
139
+ {entry.additions}
140
+ </span>
141
+ )}
142
+ {entry.deletions > 0 && (
143
+ <span className="flex items-center gap-0.5 text-red-600 dark:text-red-400">
144
+ <Minus className="h-2.5 w-2.5" />
145
+ {entry.deletions}
146
+ </span>
147
+ )}
148
+ </div>
149
+ </button>
150
+
151
+ {/* Patch content */}
152
+ {expanded && (
153
+ <div className="overflow-x-auto">
154
+ {patchLines.length > 0 ? (
155
+ <pre className="text-[11px] leading-[1.6] font-mono">
156
+ {patchLines.map((line, i) => (
157
+ <div
158
+ key={i}
159
+ className={`px-3 ${lineClassName(line.type)}`}
160
+ >
161
+ {line.content}
162
+ </div>
163
+ ))}
164
+ </pre>
165
+ ) : (
166
+ <div className="px-3 py-4 text-center text-xs text-gray-400 italic">
167
+ No diff content available
168
+ </div>
169
+ )}
170
+ </div>
171
+ )}
172
+ </div>
173
+ );
174
+ }
175
+
176
+ // ---- DiffViewer Component ----
177
+
178
+ export const DiffViewer: React.FC<DiffViewerProps> = ({ entries, className }) => {
179
+ if (entries.length === 0) {
180
+ return (
181
+ <div className={`flex items-center justify-center py-8 text-xs text-gray-400 ${className ?? ''}`}>
182
+ No changes to display
183
+ </div>
184
+ );
185
+ }
186
+
187
+ const totalAdditions = entries.reduce((sum, e) => sum + e.additions, 0);
188
+ const totalDeletions = entries.reduce((sum, e) => sum + e.deletions, 0);
189
+
190
+ return (
191
+ <div className={`space-y-2 ${className ?? ''}`}>
192
+ {/* Summary bar */}
193
+ <div className="flex items-center gap-3 px-3 py-2 bg-gray-50 dark:bg-gray-800 rounded-lg text-xs text-gray-600 dark:text-gray-300">
194
+ <div className="flex items-center gap-1">
195
+ <FileText className="h-3.5 w-3.5 text-gray-400" />
196
+ <span className="font-medium">{entries.length}</span>
197
+ <span>file{entries.length !== 1 ? 's' : ''} changed</span>
198
+ </div>
199
+ <div className="flex items-center gap-1 text-green-600 dark:text-green-400">
200
+ <Plus className="h-3 w-3" />
201
+ <span>{totalAdditions}</span>
202
+ </div>
203
+ <div className="flex items-center gap-1 text-red-600 dark:text-red-400">
204
+ <Minus className="h-3 w-3" />
205
+ <span>{totalDeletions}</span>
206
+ </div>
207
+ </div>
208
+
209
+ {/* File diffs */}
210
+ {entries.map((entry) => (
211
+ <FileDiffSection
212
+ key={entry.path}
213
+ entry={entry}
214
+ defaultExpanded={entries.length <= 5}
215
+ />
216
+ ))}
217
+ </div>
218
+ );
219
+ };
@@ -0,0 +1,4 @@
1
+ export { CommitList, type CommitListProps } from './CommitList';
2
+ export { CommitGraph, computeGraphLayout, graphWidth, type GraphNode, type GraphConnection } from './CommitGraph';
3
+ export { DiffViewer, type DiffViewerProps } from './DiffViewer';
4
+ export { BranchList, type BranchListProps } from './BranchList';
@@ -0,0 +1,146 @@
1
+ import React from 'react';
2
+ import {
3
+ File, FileText, FileImage, FileVideo, FileAudio, FileCode,
4
+ Folder, FolderOpen, FolderPlus, FilePlus, Archive, FileSpreadsheet, FileType, Settings,
5
+ FileJson, FileTerminal, Database, Globe, Presentation, FileKey,
6
+ Eye, Pencil, Trash2, Copy, Download, Upload, Share2, Scissors,
7
+ Star, Heart, Bookmark, Tag, Info, AlertTriangle, AlertCircle,
8
+ CheckCircle, Plus, Minus, X, Check, ZoomIn, List,
9
+ type LucideIcon
10
+ } from 'lucide-react';
11
+
12
+ // Icon name to Lucide component mapping for resolving string icon identifiers
13
+ export const lucideIconMap: Record<string, LucideIcon> = {
14
+ 'file': File, 'file-text': FileText, 'file-image': FileImage,
15
+ 'file-video': FileVideo, 'file-audio': FileAudio, 'file-code': FileCode,
16
+ 'folder': Folder, 'folder-open': FolderOpen, 'folder-plus': FolderPlus, 'file-plus': FilePlus, 'archive': Archive,
17
+ 'file-spreadsheet': FileSpreadsheet, 'file-type': FileType, 'settings': Settings,
18
+ 'file-json': FileJson, 'file-terminal': FileTerminal,
19
+ 'database': Database, 'globe': Globe, 'presentation': Presentation, 'file-key': FileKey,
20
+ };
21
+
22
+ // Semantic color mapping for icon types
23
+ export const iconColorMap: Record<string, string> = {
24
+ 'folder': 'text-blue-500',
25
+ 'folder-open': 'text-blue-500',
26
+ 'file-image': 'text-emerald-500',
27
+ 'file-video': 'text-orange-500',
28
+ 'file-audio': 'text-violet-500',
29
+ 'file-code': 'text-blue-500',
30
+ 'file-text': 'text-gray-500',
31
+ 'file-type': 'text-gray-500',
32
+ 'file-json': 'text-yellow-500',
33
+ 'file-terminal': 'text-green-500',
34
+ 'file-spreadsheet': 'text-emerald-600',
35
+ 'file-key': 'text-red-500',
36
+ 'archive': 'text-amber-500',
37
+ 'database': 'text-purple-500',
38
+ 'globe': 'text-blue-400',
39
+ 'presentation': 'text-orange-500',
40
+ 'file': 'text-gray-400',
41
+ };
42
+
43
+ // Comprehensive file extension to icon name mapping
44
+ export const fileExtensionIconMap: Record<string, string> = {
45
+ // Images
46
+ 'jpg': 'file-image', 'jpeg': 'file-image', 'png': 'file-image', 'gif': 'file-image',
47
+ 'svg': 'file-image', 'webp': 'file-image', 'bmp': 'file-image', 'ico': 'file-image',
48
+ 'tiff': 'file-image', 'tif': 'file-image', 'avif': 'file-image', 'heic': 'file-image',
49
+ // Video
50
+ 'mp4': 'file-video', 'avi': 'file-video', 'mkv': 'file-video', 'mov': 'file-video',
51
+ 'wmv': 'file-video', 'flv': 'file-video', 'webm': 'file-video', 'm4v': 'file-video',
52
+ // Audio
53
+ 'mp3': 'file-audio', 'wav': 'file-audio', 'flac': 'file-audio', 'aac': 'file-audio',
54
+ 'ogg': 'file-audio', 'wma': 'file-audio', 'm4a': 'file-audio', 'opus': 'file-audio',
55
+ // Documents
56
+ 'txt': 'file-text', 'md': 'file-text', 'mdx': 'file-text', 'rst': 'file-text',
57
+ 'rtf': 'file-text', 'log': 'file-text', 'csv': 'file-text',
58
+ 'pdf': 'file-type', 'doc': 'file-text', 'docx': 'file-text',
59
+ // Spreadsheets
60
+ 'xls': 'file-spreadsheet', 'xlsx': 'file-spreadsheet', 'ods': 'file-spreadsheet',
61
+ // Presentations
62
+ 'ppt': 'presentation', 'pptx': 'presentation', 'odp': 'presentation',
63
+ // Code - JavaScript/TypeScript
64
+ 'js': 'file-code', 'jsx': 'file-code', 'ts': 'file-code', 'tsx': 'file-code',
65
+ 'mjs': 'file-code', 'cjs': 'file-code',
66
+ // Code - Web
67
+ 'html': 'globe', 'htm': 'globe', 'css': 'file-code', 'scss': 'file-code',
68
+ 'sass': 'file-code', 'less': 'file-code', 'vue': 'file-code', 'svelte': 'file-code',
69
+ // Code - Data
70
+ 'json': 'file-json', 'jsonc': 'file-json', 'json5': 'file-json',
71
+ 'xml': 'file-code', 'yaml': 'file-code', 'yml': 'file-code', 'toml': 'file-code',
72
+ // Code - General
73
+ 'py': 'file-code', 'rb': 'file-code', 'java': 'file-code', 'kt': 'file-code',
74
+ 'go': 'file-code', 'rs': 'file-code', 'c': 'file-code', 'cpp': 'file-code',
75
+ 'h': 'file-code', 'hpp': 'file-code', 'cs': 'file-code', 'swift': 'file-code',
76
+ 'php': 'file-code', 'r': 'file-code', 'lua': 'file-code', 'dart': 'file-code',
77
+ 'scala': 'file-code', 'zig': 'file-code', 'ex': 'file-code', 'exs': 'file-code',
78
+ // Shell / Config
79
+ 'sh': 'file-terminal', 'bash': 'file-terminal', 'zsh': 'file-terminal',
80
+ 'fish': 'file-terminal', 'ps1': 'file-terminal', 'bat': 'file-terminal',
81
+ 'cmd': 'file-terminal',
82
+ // Config files
83
+ 'env': 'file-key', 'ini': 'settings', 'conf': 'settings', 'cfg': 'settings',
84
+ 'properties': 'settings',
85
+ // Database
86
+ 'sql': 'database', 'sqlite': 'database', 'db': 'database',
87
+ // Archives
88
+ 'zip': 'archive', 'tar': 'archive', 'gz': 'archive', 'bz2': 'archive',
89
+ 'xz': 'archive', '7z': 'archive', 'rar': 'archive', 'tgz': 'archive',
90
+ // Lock / package files
91
+ 'lock': 'file-key',
92
+ };
93
+
94
+ // Get icon name for a file extension
95
+ export function getIconForExtension(filename: string): string {
96
+ const ext = filename.split('.').pop()?.toLowerCase() || '';
97
+ return fileExtensionIconMap[ext] || 'file';
98
+ }
99
+
100
+ // Get icon name for a file (handles directories too)
101
+ export function getIconForFile(filename: string, isDirectory: boolean): string {
102
+ if (isDirectory) return 'folder';
103
+ return getIconForExtension(filename);
104
+ }
105
+
106
+ // Context menu icon mapping - Lucide icons for menu items
107
+ export const contextMenuIconMap: Record<string, LucideIcon> = {
108
+ 'eye': Eye,
109
+ 'edit': Pencil,
110
+ 'trash': Trash2,
111
+ 'folder-open': FolderOpen,
112
+ 'copy': Copy,
113
+ 'download': Download,
114
+ 'upload': Upload,
115
+ 'share': Share2,
116
+ 'scissors': Scissors,
117
+ 'star': Star,
118
+ 'heart': Heart,
119
+ 'bookmark': Bookmark,
120
+ 'tag': Tag,
121
+ 'settings': Settings,
122
+ 'info': Info,
123
+ 'warning': AlertTriangle,
124
+ 'error': AlertCircle,
125
+ 'success': CheckCircle,
126
+ 'plus': Plus,
127
+ 'minus': Minus,
128
+ 'x': X,
129
+ 'check': Check,
130
+ 'file': File,
131
+ 'folder': Folder,
132
+ 'folder-plus': FolderPlus,
133
+ 'file-plus': FilePlus,
134
+ 'archive': Archive,
135
+ 'zoom-in': ZoomIn,
136
+ 'list': List,
137
+ };
138
+
139
+ // Resolve an icon name to a React element
140
+ export function resolveIcon(name: string, className?: string): React.ReactElement {
141
+ const iconName = name || 'file';
142
+ const MappedIcon = lucideIconMap[iconName] || File;
143
+ const colorClass = iconColorMap[iconName] || 'text-gray-400';
144
+ const finalClassName = className ? `${className} ${colorClass}` : `w-4 h-4 ${colorClass}`;
145
+ return React.createElement(MappedIcon, { className: finalClassName });
146
+ }
@@ -0,0 +1,9 @@
1
+ export {
2
+ lucideIconMap,
3
+ iconColorMap,
4
+ fileExtensionIconMap,
5
+ contextMenuIconMap,
6
+ getIconForExtension,
7
+ getIconForFile,
8
+ resolveIcon,
9
+ } from './iconMap';
package/src/index.ts ADDED
@@ -0,0 +1,13 @@
1
+ export * from './file-browser';
2
+ export * from './tree';
3
+ export * from './list';
4
+ export * from './git';
5
+ export * from './layout';
6
+ export * from './media';
7
+ export * from './calendar';
8
+ export * from './contacts';
9
+ export * from './icons';
10
+
11
+ // Aliases for backwards compatibility with @anymux/fs-ui
12
+ export { Tree as TreeComponent } from './tree';
13
+ export type { TreeProps as TreeComponentProps } from './tree/components/Tree';