@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.
- package/dist/ExplorerLayout-CSIJd7N4.js +105 -0
- package/dist/ExplorerLayout-CSIJd7N4.js.map +1 -0
- package/dist/FileBrowserContext-B6jixa2j.js +11 -0
- package/dist/FileBrowserContext-B6jixa2j.js.map +1 -0
- package/dist/calendar-DSlrbHoj.js +761 -0
- package/dist/calendar-DSlrbHoj.js.map +1 -0
- package/dist/calendar.d.ts +3 -0
- package/dist/calendar.js +3 -0
- package/dist/contacts-DQXTZzHc.js +539 -0
- package/dist/contacts-DQXTZzHc.js.map +1 -0
- package/dist/contacts.d.ts +3 -0
- package/dist/contacts.js +3 -0
- package/dist/file-browser-m5atC3kF.js +6755 -0
- package/dist/file-browser-m5atC3kF.js.map +1 -0
- package/dist/file-browser.d.ts +11 -0
- package/dist/file-browser.js +9 -0
- package/dist/git-B55e6LL-.js +561 -0
- package/dist/git-B55e6LL-.js.map +1 -0
- package/dist/git.d.ts +2 -0
- package/dist/git.js +3 -0
- package/dist/iconMap-V4B8P-Uh.js +206 -0
- package/dist/iconMap-V4B8P-Uh.js.map +1 -0
- package/dist/icons-CIsIOZXR.js +0 -0
- package/dist/icons.d.ts +2 -0
- package/dist/icons.js +4 -0
- package/dist/index-BNmNIWBL.d.ts +71 -0
- package/dist/index-BNmNIWBL.d.ts.map +1 -0
- package/dist/index-Bryv_GCG.d.ts +1481 -0
- package/dist/index-Bryv_GCG.d.ts.map +1 -0
- package/dist/index-CuQIjSXs.d.ts +134 -0
- package/dist/index-CuQIjSXs.d.ts.map +1 -0
- package/dist/index-DSu19mq0.d.ts +153 -0
- package/dist/index-DSu19mq0.d.ts.map +1 -0
- package/dist/index-DmsyeHFr.d.ts +149 -0
- package/dist/index-DmsyeHFr.d.ts.map +1 -0
- package/dist/index-DxnJ8FYM.d.ts +17 -0
- package/dist/index-DxnJ8FYM.d.ts.map +1 -0
- package/dist/index-DzfY1Tok.d.ts +32 -0
- package/dist/index-DzfY1Tok.d.ts.map +1 -0
- package/dist/index-Ml_SgiKa.d.ts +1847 -0
- package/dist/index-Ml_SgiKa.d.ts.map +1 -0
- package/dist/index-kHr9udZD.d.ts +1025 -0
- package/dist/index-kHr9udZD.d.ts.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +15 -0
- package/dist/layout-Ca_4r8ka.js +89 -0
- package/dist/layout-Ca_4r8ka.js.map +1 -0
- package/dist/layout.d.ts +2 -0
- package/dist/layout.js +5 -0
- package/dist/list-CxfT6hix.js +6831 -0
- package/dist/list-CxfT6hix.js.map +1 -0
- package/dist/list.d.ts +2 -0
- package/dist/list.js +5 -0
- package/dist/media-DZ292aKK.js +557 -0
- package/dist/media-DZ292aKK.js.map +1 -0
- package/dist/media.d.ts +3 -0
- package/dist/media.js +3 -0
- package/dist/tree-Dd9Z0Aso.js +3351 -0
- package/dist/tree-Dd9Z0Aso.js.map +1 -0
- package/dist/tree.d.ts +2 -0
- package/dist/tree.js +6 -0
- package/dist/types-common-CB3kRek8.d.ts +26 -0
- package/dist/types-common-CB3kRek8.d.ts.map +1 -0
- package/dist/utils-B4fdKKsy.js +3 -0
- package/package.json +109 -0
- package/src/calendar/AgendaView.tsx +37 -0
- package/src/calendar/CalendarBrowser.tsx +90 -0
- package/src/calendar/CalendarModel.ts +142 -0
- package/src/calendar/CalendarSidebar.tsx +81 -0
- package/src/calendar/DayView.tsx +76 -0
- package/src/calendar/EventCard.tsx +51 -0
- package/src/calendar/MockCalendarProvider.ts +98 -0
- package/src/calendar/MonthView.tsx +77 -0
- package/src/calendar/WeekView.tsx +129 -0
- package/src/calendar/index.ts +18 -0
- package/src/calendar/types.ts +25 -0
- package/src/contacts/ContactAvatar.tsx +35 -0
- package/src/contacts/ContactBrowser.tsx +56 -0
- package/src/contacts/ContactCard.tsx +37 -0
- package/src/contacts/ContactDetail.tsx +63 -0
- package/src/contacts/ContactGroupSidebar.tsx +40 -0
- package/src/contacts/ContactList.tsx +32 -0
- package/src/contacts/ContactListModel.ts +120 -0
- package/src/contacts/MockContactProvider.ts +77 -0
- package/src/contacts/index.ts +17 -0
- package/src/contacts/types.ts +26 -0
- package/src/demos/CalendarBrowserDemo.tsx +15 -0
- package/src/demos/ContactBrowserDemo.tsx +15 -0
- package/src/demos/MediaBrowserDemo.tsx +15 -0
- package/src/file-browser/adapters/DocumentViewerAdapter.ts +371 -0
- package/src/file-browser/adapters/FileSystemBridge.ts +168 -0
- package/src/file-browser/adapters/GitBrowserAdapter.ts +546 -0
- package/src/file-browser/adapters/README.md +504 -0
- package/src/file-browser/adapters/index.ts +27 -0
- package/src/file-browser/adapters/types.ts +70 -0
- package/src/file-browser/architecture.md +645 -0
- package/src/file-browser/components/CreateItemDialog.tsx +71 -0
- package/src/file-browser/components/DeleteConfirmDialog.tsx +58 -0
- package/src/file-browser/components/FileBrowser.tsx +473 -0
- package/src/file-browser/components/FileBrowserContent.tsx +209 -0
- package/src/file-browser/components/FileBrowserHeader.tsx +151 -0
- package/src/file-browser/components/FileBrowserToolbar.tsx +145 -0
- package/src/file-browser/components/LeftPanel/LeftPanel.tsx +103 -0
- package/src/file-browser/components/LeftPanel/LeftPanelTabs.tsx +70 -0
- package/src/file-browser/components/LeftPanel/TreeNavigationView.tsx +256 -0
- package/src/file-browser/components/PreviewPane.tsx +146 -0
- package/src/file-browser/components/RightPanel/FilePreview.tsx +219 -0
- package/src/file-browser/components/RightPanel/RightPanel.tsx +186 -0
- package/src/file-browser/components/RightPanel/RightPanelToolbar.tsx +113 -0
- package/src/file-browser/components/UploadProgress.tsx +123 -0
- package/src/file-browser/components/ViewerHost.tsx +208 -0
- package/src/file-browser/components/mobile/MobileNavigation.tsx +227 -0
- package/src/file-browser/components/navigation/NavigationButtons.tsx +171 -0
- package/src/file-browser/components/shared/ErrorBoundary.tsx +116 -0
- package/src/file-browser/components/shared/FileBrowserItem.tsx +195 -0
- package/src/file-browser/components/shared/FileIcon.tsx +169 -0
- package/src/file-browser/components/toolbar/ViewModeToggle.tsx +200 -0
- package/src/file-browser/components/views/ListView/ListView.tsx +484 -0
- package/src/file-browser/components/views/ThumbnailView/ThumbnailView.tsx +323 -0
- package/src/file-browser/components/views/TreeView/TreeNode.tsx +186 -0
- package/src/file-browser/components/views/TreeView/TreeNodeList.tsx +191 -0
- package/src/file-browser/components/views/TreeView/TreeView.tsx +200 -0
- package/src/file-browser/components/views/TreemapView/TreemapView.tsx +339 -0
- package/src/file-browser/context/FileBrowserContext.tsx +13 -0
- package/src/file-browser/examples/BasicUsage.tsx +20 -0
- package/src/file-browser/index.ts +98 -0
- package/src/file-browser/models/FileBrowserModel.ts +623 -0
- package/src/file-browser/models/LeftPanelManagerModel.ts +105 -0
- package/src/file-browser/models/NavigationManagerModel.ts +312 -0
- package/src/file-browser/models/ResponsiveLayoutManagerModel.ts +437 -0
- package/src/file-browser/models/RightPanelManagerModel.ts +190 -0
- package/src/file-browser/models/SelectionManagerModel.ts +252 -0
- package/src/file-browser/models/ToolbarManagerModel.ts +144 -0
- package/src/file-browser/models/UploadModel.ts +147 -0
- package/src/file-browser/models/ViewModeManagerModel.ts +185 -0
- package/src/file-browser/models/ViewerHostModel.ts +44 -0
- package/src/file-browser/models/ui/ListViewUIModel.ts +265 -0
- package/src/file-browser/models/ui/PreviewUIModel.ts +297 -0
- package/src/file-browser/models/ui/ThumbnailViewUIModel.ts +254 -0
- package/src/file-browser/models/ui/TreeViewUIModel.ts +128 -0
- package/src/file-browser/models/ui/TreemapViewUIModel.ts +350 -0
- package/src/file-browser/providers/FileSystemListProvider.ts +552 -0
- package/src/file-browser/providers/FileSystemProvider.ts +401 -0
- package/src/file-browser/providers/FileSystemTreeProvider.ts +231 -0
- package/src/file-browser/providers/GitProvider.ts +337 -0
- package/src/file-browser/providers/GitRepositoryProvider.ts +376 -0
- package/src/file-browser/providers/IFileBrowserProvider.ts +56 -0
- package/src/file-browser/providers/MemoryProvider.ts +303 -0
- package/src/file-browser/providers/index.ts +4 -0
- package/src/file-browser/registry/ViewerRegistry.ts +551 -0
- package/src/file-browser/registry/types.ts +144 -0
- package/src/file-browser/scripts/performanceBenchmark.ts +553 -0
- package/src/file-browser/services/ThumbnailCacheService.ts +128 -0
- package/src/file-browser/tasks.md +537 -0
- package/src/file-browser/types/FileBrowserTypes.ts +126 -0
- package/src/file-browser/types/ProviderTypes.ts +155 -0
- package/src/file-browser/types/UITypes.ts +235 -0
- package/src/file-browser/types/ViewModeTypes.ts +150 -0
- package/src/file-browser/utils/gestures.ts +327 -0
- package/src/file-browser/utils/performance.ts +563 -0
- package/src/file-browser/viewers/ImageViewer.tsx +163 -0
- package/src/file-browser/viewers/ImageViewerModel.ts +79 -0
- package/src/file-browser/viewers/TextViewer.tsx +95 -0
- package/src/file-browser/viewers/UnsupportedFileViewer.tsx +57 -0
- package/src/file-browser/viewers/index.ts +61 -0
- package/src/git/BranchList.tsx +128 -0
- package/src/git/CommitGraph.tsx +239 -0
- package/src/git/CommitList.tsx +258 -0
- package/src/git/DiffViewer.tsx +219 -0
- package/src/git/index.ts +4 -0
- package/src/icons/iconMap.ts +146 -0
- package/src/icons/index.ts +9 -0
- package/src/index.ts +13 -0
- package/src/layout/README.md +307 -0
- package/src/layout/components/ExplorerLayout/ExplorerLayout.tsx +178 -0
- package/src/layout/examples/SimpleExample.tsx +60 -0
- package/src/layout/index.ts +6 -0
- package/src/lib/utils.ts +1 -0
- package/src/list/README.md +303 -0
- package/src/list/architecture.md +807 -0
- package/src/list/components/CalculatedGridView.tsx +252 -0
- package/src/list/components/DragPreview.tsx +102 -0
- package/src/list/components/ListContextMenu.tsx +274 -0
- package/src/list/components/ListItem.tsx +761 -0
- package/src/list/components/ListItems.tsx +919 -0
- package/src/list/components/MasonryView.tsx +241 -0
- package/src/list/components/SearchFilter.tsx +44 -0
- package/src/list/components/TreemapView.tsx +709 -0
- package/src/list/components/ViewSizeControls.tsx +205 -0
- package/src/list/components/ViewTypeSelector.tsx +312 -0
- package/src/list/components/VirtualizedDetailsView.tsx +231 -0
- package/src/list/components/VirtualizedGrid.tsx +164 -0
- package/src/list/components/VirtualizedList.tsx +154 -0
- package/src/list/components/VirtualizedMasonryView.tsx +344 -0
- package/src/list/components/shared/EmptyState.tsx +103 -0
- package/src/list/components/shared/ErrorBoundary.tsx +123 -0
- package/src/list/components/shared/ErrorDisplay.tsx +100 -0
- package/src/list/components/shared/ListLoader.tsx +146 -0
- package/src/list/components/shared/LoadingIndicator.tsx +80 -0
- package/src/list/index.ts +92 -0
- package/src/list/models/ListItemsModel.ts +1301 -0
- package/src/list/models/TreemapModel.ts +204 -0
- package/src/list/providers/ListItemsProvider.ts +313 -0
- package/src/list/providers/TestListProvider.ts +604 -0
- package/src/list/tasks.md +937 -0
- package/src/list/types/ListTypes.ts +178 -0
- package/src/list/utils/BenchmarkLogger.ts +243 -0
- package/src/list/utils/DragDropManager.ts +320 -0
- package/src/list/utils/GridLayoutCalculator.ts +290 -0
- package/src/list/utils/ListAccessibility.ts +367 -0
- package/src/list/utils/ListKeyboard.ts +414 -0
- package/src/list/utils/MasonryLayoutCalculator.ts +302 -0
- package/src/list/utils/MasonryLayoutEngine.ts +401 -0
- package/src/list/utils/__tests__/MasonryLayoutEngine.test.ts +157 -0
- package/src/list/utils/__tests__/VirtualizedMasonryView.test.tsx +251 -0
- package/src/media/AlbumSidebar.tsx +48 -0
- package/src/media/MediaBrowser.tsx +92 -0
- package/src/media/MediaBrowserModel.ts +138 -0
- package/src/media/MediaGrid.tsx +50 -0
- package/src/media/MediaList.tsx +49 -0
- package/src/media/MediaPreview.tsx +63 -0
- package/src/media/MediaTimeline.tsx +38 -0
- package/src/media/MockMediaProvider.ts +70 -0
- package/src/media/index.ts +18 -0
- package/src/media/types.ts +21 -0
- package/src/styles/variables.css +60 -0
- package/src/tree/DEVELOPMENT_SUMMARY.md +170 -0
- package/src/tree/__tests__/TreeModel.test.ts +16 -0
- package/src/tree/architecture.md +530 -0
- package/src/tree/components/Tree.tsx +283 -0
- package/src/tree/components/TreeCheckbox.tsx +147 -0
- package/src/tree/components/TreeContextMenu.tsx +139 -0
- package/src/tree/components/TreeNodeList.tsx +329 -0
- package/src/tree/components/TreeTable.tsx +382 -0
- package/src/tree/index.ts +58 -0
- package/src/tree/models/TreeModel.ts +839 -0
- package/src/tree/providers/SimpleTreeProvider.ts +463 -0
- package/src/tree/providers/TestTreeProvider.ts +946 -0
- package/src/tree/providers/TreeProvider.ts +308 -0
- package/src/tree/tasks.md +2046 -0
- package/src/tree/types/TreeTypes.ts +279 -0
- package/src/tree/utils/SelectionTheme.ts +150 -0
- package/src/tree/utils/logger.ts +203 -0
- package/src/types-common.ts +21 -0
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ListItemsProvider,
|
|
3
|
+
ListItemsProviderListener,
|
|
4
|
+
LIST_VIEW_TYPE,
|
|
5
|
+
GRID_VIEW_TYPE,
|
|
6
|
+
DETAILS_VIEW_TYPE,
|
|
7
|
+
MASONRY_HORIZONTAL_VIEW_TYPE,
|
|
8
|
+
MASONRY_VERTICAL_VIEW_TYPE,
|
|
9
|
+
type ListViewType
|
|
10
|
+
} from './ListItemsProvider';
|
|
11
|
+
import type {
|
|
12
|
+
ListItemData,
|
|
13
|
+
ListLoadOptions,
|
|
14
|
+
ListLoadResult,
|
|
15
|
+
ListSelectionInfo,
|
|
16
|
+
ListContextMenuItem,
|
|
17
|
+
ListDragDropInfo,
|
|
18
|
+
VirtualizationConfig
|
|
19
|
+
} from '../types/ListTypes';
|
|
20
|
+
import React from 'react';
|
|
21
|
+
import {
|
|
22
|
+
FileText, Image, Video, Music, Folder, Archive,
|
|
23
|
+
File, Settings, Code, Database, Globe, Palette,
|
|
24
|
+
Package, BookOpen, TestTube, GitBranch, Key,
|
|
25
|
+
Braces, Play, Zap, Component
|
|
26
|
+
} from 'lucide-react';
|
|
27
|
+
import { makeAutoObservable } from 'mobx';
|
|
28
|
+
|
|
29
|
+
// AICODE-NOTE: Simple test provider for development and testing with mock data
|
|
30
|
+
export class TestListProvider implements ListItemsProvider {
|
|
31
|
+
// =====================
|
|
32
|
+
// Basic Configuration
|
|
33
|
+
// =====================
|
|
34
|
+
|
|
35
|
+
readonly id = 'test-list-provider';
|
|
36
|
+
readonly name = 'Test List Provider';
|
|
37
|
+
readonly isMultiSelectEnabled = true;
|
|
38
|
+
readonly isVirtualizationEnabled = true;
|
|
39
|
+
readonly isDragDropEnabled = true;
|
|
40
|
+
|
|
41
|
+
readonly supportedViewTypes: ListViewType[] = [
|
|
42
|
+
LIST_VIEW_TYPE,
|
|
43
|
+
GRID_VIEW_TYPE,
|
|
44
|
+
DETAILS_VIEW_TYPE,
|
|
45
|
+
MASONRY_HORIZONTAL_VIEW_TYPE,
|
|
46
|
+
MASONRY_VERTICAL_VIEW_TYPE
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
// AICODE-NOTE: Mock data for testing - different types of items
|
|
50
|
+
private items: ListItemData[] = [];
|
|
51
|
+
private listener?: ListItemsProviderListener;
|
|
52
|
+
|
|
53
|
+
constructor() {
|
|
54
|
+
makeAutoObservable(this, {});
|
|
55
|
+
// AICODE-NOTE: Generate large dataset with 10,000 items for performance testing
|
|
56
|
+
this.generateLargeDataset();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// =====================
|
|
60
|
+
// Mock Data Generation
|
|
61
|
+
// =====================
|
|
62
|
+
|
|
63
|
+
private generateLargeDataset(): void {
|
|
64
|
+
// AICODE-NOTE: Generate 10,000 items with varied dimensions and images
|
|
65
|
+
const start = performance.now();
|
|
66
|
+
const fileTypes = [
|
|
67
|
+
{ ext: 'jpg', icon: '🖼️', type: 'Image' },
|
|
68
|
+
{ ext: 'png', icon: '🖼️', type: 'Image' },
|
|
69
|
+
{ ext: 'pdf', icon: '📄', type: 'Document' },
|
|
70
|
+
{ ext: 'doc', icon: '📝', type: 'Document' },
|
|
71
|
+
{ ext: 'mp4', icon: '🎬', type: 'Video' },
|
|
72
|
+
{ ext: 'mp3', icon: '🎵', type: 'Audio' },
|
|
73
|
+
{ ext: 'zip', icon: '📦', type: 'Archive' },
|
|
74
|
+
{ ext: 'txt', icon: '📄', type: 'Text' },
|
|
75
|
+
{ ext: 'js', icon: '⚡', type: 'Code' },
|
|
76
|
+
{ ext: 'css', icon: '🎨', type: 'Style' }
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
const adjectives = ['Amazing', 'Beautiful', 'Creative', 'Dynamic', 'Elegant', 'Fantastic', 'Gorgeous', 'Incredible', 'Lovely', 'Magnificent'];
|
|
80
|
+
const nouns = ['Photo', 'Document', 'Project', 'Design', 'Artwork', 'Report', 'Presentation', 'Video', 'Music', 'Archive'];
|
|
81
|
+
|
|
82
|
+
for (let i = 0; i < 10000; i++) {
|
|
83
|
+
const fileType = fileTypes[i % fileTypes.length]!;
|
|
84
|
+
const adjective = adjectives[i % adjectives.length]!;
|
|
85
|
+
const noun = nouns[Math.floor(i / adjectives.length) % nouns.length]!;
|
|
86
|
+
|
|
87
|
+
// Generate variable dimensions for realistic masonry layout
|
|
88
|
+
const baseWidth = 200 + (i % 5) * 40; // 200-360px width
|
|
89
|
+
const aspectRatios = [1, 1.2, 1.5, 0.8, 0.6, 1.8]; // Various aspect ratios
|
|
90
|
+
const aspectRatio = aspectRatios[i % aspectRatios.length]!;
|
|
91
|
+
const height = Math.round(baseWidth / aspectRatio);
|
|
92
|
+
|
|
93
|
+
// Generate image URL for visual items
|
|
94
|
+
const isImageType = fileType.type === 'Image' || (i % 3 === 0); // Show images for image types and every 3rd item
|
|
95
|
+
const thumbnailUrl = isImageType
|
|
96
|
+
? `https://picsum.photos/${baseWidth}/${height}?random=${i}`
|
|
97
|
+
: undefined;
|
|
98
|
+
|
|
99
|
+
const item: ListItemData = {
|
|
100
|
+
id: `item-${i}`,
|
|
101
|
+
name: `${adjective} ${noun} ${i + 1}.${fileType.ext}`,
|
|
102
|
+
type: fileType.type,
|
|
103
|
+
icon: fileType.icon,
|
|
104
|
+
size: Math.floor(Math.random() * 10000000) + 1000, // 1KB to 10MB
|
|
105
|
+
modified: new Date(Date.now() - Math.random() * 365 * 24 * 60 * 60 * 1000), // Random date within last year
|
|
106
|
+
thumbnailUrl,
|
|
107
|
+
aspectRatio,
|
|
108
|
+
getDimensions: () => ({ width: baseWidth, height })
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
this.items.push(item);
|
|
112
|
+
}
|
|
113
|
+
console.log('Generated 10,000 items in', performance.now() - start, 'ms');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private getIconForType(type: string): string {
|
|
117
|
+
const iconMap: Record<string, string> = {
|
|
118
|
+
document: 'file-text',
|
|
119
|
+
image: 'image',
|
|
120
|
+
video: 'video',
|
|
121
|
+
audio: 'music',
|
|
122
|
+
folder: 'folder',
|
|
123
|
+
archive: 'archive'
|
|
124
|
+
};
|
|
125
|
+
return iconMap[type] || 'file';
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Get custom icon for an item based on file type and extension
|
|
130
|
+
*/
|
|
131
|
+
getItemIcon(item: ListItemData): string | React.ComponentType<any> {
|
|
132
|
+
// If it's a folder, use folder icon
|
|
133
|
+
if (item.type === 'folder') {
|
|
134
|
+
return Folder;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Get file extension
|
|
138
|
+
const extension = item.name.split('.').pop()?.toLowerCase() || '';
|
|
139
|
+
|
|
140
|
+
// Return appropriate icon based on extension
|
|
141
|
+
switch (extension) {
|
|
142
|
+
// Web Development
|
|
143
|
+
case 'js':
|
|
144
|
+
case 'jsx':
|
|
145
|
+
return Code; // JavaScript icon
|
|
146
|
+
|
|
147
|
+
case 'ts':
|
|
148
|
+
case 'tsx':
|
|
149
|
+
return FileText; // TypeScript icon
|
|
150
|
+
|
|
151
|
+
case 'html':
|
|
152
|
+
case 'htm':
|
|
153
|
+
return Globe; // HTML icon
|
|
154
|
+
|
|
155
|
+
case 'css':
|
|
156
|
+
case 'scss':
|
|
157
|
+
case 'sass':
|
|
158
|
+
case 'less':
|
|
159
|
+
return Palette; // Stylesheet icon
|
|
160
|
+
|
|
161
|
+
// Documentation
|
|
162
|
+
case 'md':
|
|
163
|
+
case 'mdx':
|
|
164
|
+
return BookOpen; // Markdown icon
|
|
165
|
+
|
|
166
|
+
case 'txt':
|
|
167
|
+
return FileText;
|
|
168
|
+
|
|
169
|
+
case 'pdf':
|
|
170
|
+
return FileText;
|
|
171
|
+
|
|
172
|
+
// Data & Configuration
|
|
173
|
+
case 'json':
|
|
174
|
+
return Braces; // JSON icon
|
|
175
|
+
|
|
176
|
+
case 'yml':
|
|
177
|
+
case 'yaml':
|
|
178
|
+
return Settings; // YAML icon
|
|
179
|
+
|
|
180
|
+
case 'xml':
|
|
181
|
+
return Code; // XML icon
|
|
182
|
+
|
|
183
|
+
case 'env':
|
|
184
|
+
return Key; // Environment file icon
|
|
185
|
+
|
|
186
|
+
case 'config':
|
|
187
|
+
return Settings; // Config file icon
|
|
188
|
+
|
|
189
|
+
// Images
|
|
190
|
+
case 'jpg':
|
|
191
|
+
case 'jpeg':
|
|
192
|
+
case 'png':
|
|
193
|
+
case 'gif':
|
|
194
|
+
case 'webp':
|
|
195
|
+
case 'bmp':
|
|
196
|
+
case 'tiff':
|
|
197
|
+
case 'ico':
|
|
198
|
+
return Image; // Image icon
|
|
199
|
+
|
|
200
|
+
case 'svg':
|
|
201
|
+
return Zap; // SVG icon (special since it's vector)
|
|
202
|
+
|
|
203
|
+
// Media
|
|
204
|
+
case 'mp4':
|
|
205
|
+
case 'avi':
|
|
206
|
+
case 'mov':
|
|
207
|
+
case 'mkv':
|
|
208
|
+
return Play; // Video icon
|
|
209
|
+
|
|
210
|
+
case 'mp3':
|
|
211
|
+
case 'wav':
|
|
212
|
+
case 'flac':
|
|
213
|
+
case 'ogg':
|
|
214
|
+
return Music; // Audio icon
|
|
215
|
+
|
|
216
|
+
// Archives
|
|
217
|
+
case 'zip':
|
|
218
|
+
case 'tar':
|
|
219
|
+
case 'gz':
|
|
220
|
+
case '7z':
|
|
221
|
+
case 'rar':
|
|
222
|
+
return Archive; // Archive icon
|
|
223
|
+
|
|
224
|
+
// Executables
|
|
225
|
+
case 'exe':
|
|
226
|
+
case 'app':
|
|
227
|
+
case 'deb':
|
|
228
|
+
case 'dmg':
|
|
229
|
+
return Zap; // Executable icon
|
|
230
|
+
|
|
231
|
+
// Development Tools
|
|
232
|
+
case 'git':
|
|
233
|
+
case 'gitignore':
|
|
234
|
+
return GitBranch;
|
|
235
|
+
|
|
236
|
+
case 'dockerfile':
|
|
237
|
+
return Package; // Docker icon
|
|
238
|
+
|
|
239
|
+
case 'sql':
|
|
240
|
+
return Database; // Database icon
|
|
241
|
+
|
|
242
|
+
case 'log':
|
|
243
|
+
return FileText; // Log file icon
|
|
244
|
+
|
|
245
|
+
// Default file icon
|
|
246
|
+
default:
|
|
247
|
+
return File; // Use default File icon
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// =====================
|
|
252
|
+
// Data Loading Methods
|
|
253
|
+
// =====================
|
|
254
|
+
|
|
255
|
+
async loadItems(options?: ListLoadOptions): Promise<ListLoadResult> {
|
|
256
|
+
// AICODE-NOTE: Simulate async loading with small delay
|
|
257
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
258
|
+
|
|
259
|
+
let items = [...this.items];
|
|
260
|
+
|
|
261
|
+
// Apply search filter
|
|
262
|
+
if (options?.searchQuery) {
|
|
263
|
+
const query = options.searchQuery.toLowerCase();
|
|
264
|
+
items = items.filter(item =>
|
|
265
|
+
item.name.toLowerCase().includes(query) ||
|
|
266
|
+
item.type?.toLowerCase().includes(query)
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Apply sorting
|
|
271
|
+
if (options?.sortBy) {
|
|
272
|
+
const sortField = options.sortBy;
|
|
273
|
+
items.sort((a, b) => {
|
|
274
|
+
const aVal = a[sortField];
|
|
275
|
+
const bVal = b[sortField];
|
|
276
|
+
|
|
277
|
+
if (aVal === undefined) return 1;
|
|
278
|
+
if (bVal === undefined) return -1;
|
|
279
|
+
|
|
280
|
+
let comparison = 0;
|
|
281
|
+
if (aVal < bVal) comparison = -1;
|
|
282
|
+
if (aVal > bVal) comparison = 1;
|
|
283
|
+
|
|
284
|
+
return options.sortDirection === 'desc' ? -comparison : comparison;
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Apply pagination
|
|
289
|
+
const limit = options?.limit || items.length;
|
|
290
|
+
const offset = options?.offset || 0;
|
|
291
|
+
const paginatedItems = items.slice(offset, offset + limit);
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
items: paginatedItems,
|
|
295
|
+
totalCount: items.length,
|
|
296
|
+
hasMore: offset + limit < items.length
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
async getItemCount(): Promise<number> {
|
|
301
|
+
return this.items.length;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
async loadItemRange(start: number, end: number): Promise<ListLoadResult> {
|
|
305
|
+
// AICODE-NOTE: Simulate async range loading with delay
|
|
306
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
307
|
+
|
|
308
|
+
const items: ListItemData[] = [];
|
|
309
|
+
|
|
310
|
+
// AICODE-NOTE: Generate items on demand for the requested range
|
|
311
|
+
for (let i = start; i < end && i < this.items.length; i++) {
|
|
312
|
+
// AICODE-NOTE: Check if item already exists in cache
|
|
313
|
+
const existingItem = i < this.items.length ? this.items[i] : null;
|
|
314
|
+
if (existingItem) {
|
|
315
|
+
items.push(existingItem);
|
|
316
|
+
} else {
|
|
317
|
+
// AICODE-NOTE: Item should already exist from generateLargeDataset
|
|
318
|
+
// If we reach here, something is wrong with the data generation
|
|
319
|
+
console.warn(`Item at index ${i} not found in pre-generated dataset`);
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return {
|
|
325
|
+
items,
|
|
326
|
+
totalCount: this.items.length,
|
|
327
|
+
hasMore: end < this.items.length
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
async refresh(): Promise<ListLoadResult> {
|
|
332
|
+
// AICODE-NOTE: For testing, just return all items
|
|
333
|
+
return this.loadItems();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// =====================
|
|
337
|
+
// View Configuration
|
|
338
|
+
// =====================
|
|
339
|
+
|
|
340
|
+
getItemHeight(viewType: ListViewType): number {
|
|
341
|
+
// AICODE-NOTE: Different heights for different view types
|
|
342
|
+
switch (viewType.id) {
|
|
343
|
+
case 'list': return 40;
|
|
344
|
+
case 'grid': return 120;
|
|
345
|
+
case 'details': return 32;
|
|
346
|
+
default: return 40;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
getItemWidth(viewType: ListViewType): number {
|
|
351
|
+
// AICODE-NOTE: Fixed widths for grid layouts
|
|
352
|
+
switch (viewType.id) {
|
|
353
|
+
case 'grid': return 200;
|
|
354
|
+
default: return 200;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
getVirtualizationConfig(): VirtualizationConfig {
|
|
359
|
+
return {
|
|
360
|
+
itemHeight: 40,
|
|
361
|
+
overscan: 5,
|
|
362
|
+
threshold: 50,
|
|
363
|
+
rangeSize: 20
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// =====================
|
|
368
|
+
// Event Callbacks
|
|
369
|
+
// =====================
|
|
370
|
+
|
|
371
|
+
onSelectionChange(selectionInfo: ListSelectionInfo): void {
|
|
372
|
+
// AICODE-NOTE: Log selection changes for debugging
|
|
373
|
+
console.log('Selection changed:', {
|
|
374
|
+
selectedCount: selectionInfo.selectedItems.length,
|
|
375
|
+
selectionType: selectionInfo.selectionType,
|
|
376
|
+
trigger: selectionInfo.trigger
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
onViewTypeChange(viewType: ListViewType): void {
|
|
381
|
+
console.log('View type changed to:', viewType.name);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
onItemDoubleClick(item: ListItemData): void {
|
|
385
|
+
console.log('Item double-clicked:', item.name);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// =====================
|
|
389
|
+
// Context Menu Support
|
|
390
|
+
// =====================
|
|
391
|
+
|
|
392
|
+
getItemContextMenu(item: ListItemData): ListContextMenuItem[] {
|
|
393
|
+
// AICODE-NOTE: Basic context menu for testing
|
|
394
|
+
const baseMenu: ListContextMenuItem[] = [
|
|
395
|
+
{ id: 'open', label: 'Open', icon: 'eye' },
|
|
396
|
+
{ id: 'rename', label: 'Rename', icon: 'edit' },
|
|
397
|
+
{ id: 'separator', label: '', type: 'separator' },
|
|
398
|
+
{ id: 'delete', label: 'Delete', icon: 'trash', destructive: true }
|
|
399
|
+
];
|
|
400
|
+
|
|
401
|
+
// Add type-specific items
|
|
402
|
+
if (item.type === 'folder') {
|
|
403
|
+
baseMenu.unshift({ id: 'open-folder', label: 'Open Folder', icon: 'folder-open' });
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return baseMenu;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
getMultiItemContextMenu(items: ListItemData[]): ListContextMenuItem[] {
|
|
410
|
+
// AICODE-NOTE: Context menu for multiple selected items
|
|
411
|
+
const multiMenu: ListContextMenuItem[] = [
|
|
412
|
+
{
|
|
413
|
+
id: 'delete-multiple',
|
|
414
|
+
label: `Delete ${items.length} items`,
|
|
415
|
+
icon: 'trash',
|
|
416
|
+
destructive: true,
|
|
417
|
+
shortcut: 'Del'
|
|
418
|
+
},
|
|
419
|
+
{ id: 'separator', label: '', type: 'separator' },
|
|
420
|
+
{
|
|
421
|
+
id: 'copy-multiple',
|
|
422
|
+
label: `Copy ${items.length} items`,
|
|
423
|
+
icon: 'copy',
|
|
424
|
+
shortcut: 'Ctrl+C'
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
id: 'cut-multiple',
|
|
428
|
+
label: `Cut ${items.length} items`,
|
|
429
|
+
icon: 'scissors',
|
|
430
|
+
shortcut: 'Ctrl+X'
|
|
431
|
+
}
|
|
432
|
+
];
|
|
433
|
+
|
|
434
|
+
// AICODE-NOTE: Add archive option if multiple files selected
|
|
435
|
+
const hasFiles = items.some(item => item.type !== 'folder');
|
|
436
|
+
if (hasFiles) {
|
|
437
|
+
multiMenu.push(
|
|
438
|
+
{ id: 'separator2', label: '', type: 'separator' },
|
|
439
|
+
{
|
|
440
|
+
id: 'archive-multiple',
|
|
441
|
+
label: `Archive ${items.length} items`,
|
|
442
|
+
icon: 'archive',
|
|
443
|
+
tooltip: 'Create a zip archive of selected items'
|
|
444
|
+
}
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return multiMenu;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
onContextMenuAction(menuItemId: string, items: ListItemData[]): void {
|
|
452
|
+
console.log(`Context menu action '${menuItemId}' on items:`, items.map(i => i.name));
|
|
453
|
+
|
|
454
|
+
switch (menuItemId) {
|
|
455
|
+
case 'delete':
|
|
456
|
+
case 'delete-multiple':
|
|
457
|
+
// AICODE-NOTE: For testing, just log - real provider would delete items
|
|
458
|
+
console.log('Would delete items:', items.map(i => i.name));
|
|
459
|
+
break;
|
|
460
|
+
case 'rename':
|
|
461
|
+
console.log('Would rename item:', items[0]?.name);
|
|
462
|
+
break;
|
|
463
|
+
case 'copy-multiple':
|
|
464
|
+
console.log('Would copy items to clipboard:', items.map(i => i.name));
|
|
465
|
+
break;
|
|
466
|
+
case 'cut-multiple':
|
|
467
|
+
console.log('Would cut items to clipboard:', items.map(i => i.name));
|
|
468
|
+
break;
|
|
469
|
+
case 'archive-multiple':
|
|
470
|
+
console.log('Would create archive of items:', items.map(i => i.name));
|
|
471
|
+
break;
|
|
472
|
+
case 'open':
|
|
473
|
+
case 'open-folder':
|
|
474
|
+
console.log('Would open item:', items[0]?.name);
|
|
475
|
+
break;
|
|
476
|
+
default:
|
|
477
|
+
console.log('Unhandled menu action:', menuItemId);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// =====================
|
|
482
|
+
// Drag and Drop Support
|
|
483
|
+
// =====================
|
|
484
|
+
|
|
485
|
+
canDragItem(item: ListItemData): boolean {
|
|
486
|
+
// AICODE-NOTE: For testing, allow dragging all items except system files
|
|
487
|
+
return !item.name.startsWith('.');
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
canDropItems(draggedItems: ListItemData[], targetItem: ListItemData | null, position: 'before' | 'after' | 'inside'): boolean {
|
|
491
|
+
// AICODE-NOTE: For testing, allow most drops with some restrictions
|
|
492
|
+
|
|
493
|
+
// Can't drop on itself
|
|
494
|
+
if (targetItem && draggedItems.some(item => item.id === targetItem.id)) {
|
|
495
|
+
return false;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Can only drop inside folders
|
|
499
|
+
if (position === 'inside' && targetItem?.type !== 'folder') {
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
return true;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
onDragStart(draggedItems: ListItemData[], event: DragEvent): void {
|
|
507
|
+
console.log('Drag started with items:', draggedItems.map(i => i.name));
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
onDrop(dragDropInfo: ListDragDropInfo): void {
|
|
511
|
+
const { draggedItems, targetItem, position } = dragDropInfo;
|
|
512
|
+
|
|
513
|
+
console.log('Drop operation:', {
|
|
514
|
+
draggedItems: draggedItems.map((i: ListItemData) => i.name),
|
|
515
|
+
targetItem: targetItem?.name || 'empty space',
|
|
516
|
+
position
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
// AICODE-NOTE: For testing, simulate reordering by logging
|
|
520
|
+
if (position === 'before' || position === 'after') {
|
|
521
|
+
console.log(`Would reorder items ${position} ${targetItem?.name}`);
|
|
522
|
+
} else if (position === 'inside' && targetItem?.type === 'folder') {
|
|
523
|
+
console.log(`Would move items into folder: ${targetItem.name}`);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
onDragEnd(draggedItems: ListItemData[], success: boolean): void {
|
|
528
|
+
console.log('Drag ended:', {
|
|
529
|
+
items: draggedItems.map(i => i.name),
|
|
530
|
+
success
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// =====================
|
|
535
|
+
// Legacy Listener Support
|
|
536
|
+
// =====================
|
|
537
|
+
|
|
538
|
+
addListener(listener: ListItemsProviderListener): void {
|
|
539
|
+
this.listener = listener;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
removeListener(listener: ListItemsProviderListener): void {
|
|
543
|
+
this.listener = undefined;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// =====================
|
|
547
|
+
// Helper Methods for Testing
|
|
548
|
+
// =====================
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Add a new mock item (useful for testing dynamic updates)
|
|
552
|
+
*/
|
|
553
|
+
addMockItem(item: Partial<ListItemData>): void {
|
|
554
|
+
const { id, name, ...rest } = item;
|
|
555
|
+
const newItem: ListItemData = {
|
|
556
|
+
id: id || `item-${Date.now()}`,
|
|
557
|
+
name: name || 'New Item',
|
|
558
|
+
type: 'document',
|
|
559
|
+
modified: new Date(),
|
|
560
|
+
icon: 'file',
|
|
561
|
+
...rest
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
this.items.push(newItem);
|
|
565
|
+
|
|
566
|
+
// Notify listeners
|
|
567
|
+
this.listener?.onItemsCountChanged(this.items.length);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Remove an item by ID (useful for testing dynamic updates)
|
|
572
|
+
*/
|
|
573
|
+
removeMockItem(itemId: string): void {
|
|
574
|
+
const index = this.items.findIndex(item => item.id === itemId);
|
|
575
|
+
if (index >= 0) {
|
|
576
|
+
this.items.splice(index, 1);
|
|
577
|
+
|
|
578
|
+
// Notify listeners
|
|
579
|
+
this.listener?.onItemsCountChanged(this.items.length);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* Update an existing item (useful for testing dynamic updates)
|
|
585
|
+
*/
|
|
586
|
+
updateMockItem(itemId: string, updates: Partial<ListItemData>): void {
|
|
587
|
+
const index = this.items.findIndex(item => item.id === itemId);
|
|
588
|
+
if (index >= 0) {
|
|
589
|
+
const currentItem = this.items[index]!;
|
|
590
|
+
const { id, name, ...rest } = updates;
|
|
591
|
+
|
|
592
|
+
this.items[index] = {
|
|
593
|
+
...currentItem,
|
|
594
|
+
...rest,
|
|
595
|
+
// Ensure required fields are never undefined
|
|
596
|
+
id: id || currentItem.id,
|
|
597
|
+
name: name || currentItem.name
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
// Notify listeners
|
|
601
|
+
this.listener?.onItemChanged(index);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|