@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,504 @@
|
|
|
1
|
+
# FileBrowser Adapter System
|
|
2
|
+
|
|
3
|
+
This directory contains example adapters demonstrating how to integrate external systems with the FileBrowser's dual-panel coordination system.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The FileBrowser adapter system provides a standardized way to:
|
|
8
|
+
- Extend FileBrowser functionality with domain-specific features
|
|
9
|
+
- Maintain selection and navigation coordination between external systems and FileBrowser panels
|
|
10
|
+
- Implement reactive patterns using MobX for seamless state synchronization
|
|
11
|
+
- Handle complex multi-panel interactions and state management
|
|
12
|
+
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
### Coordination Pattern
|
|
16
|
+
|
|
17
|
+
The core coordination pattern follows these principles:
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// 1. Listen to FileBrowser state changes via MobX reactions
|
|
21
|
+
const selectionDisposer = reaction(
|
|
22
|
+
() => ({
|
|
23
|
+
selectedItems: Array.from(fileBrowserModel.selectionManager.selectedItems.keys()),
|
|
24
|
+
focusedItem: fileBrowserModel.selectionManager.focusedItem
|
|
25
|
+
}),
|
|
26
|
+
({ focusedItem }) => {
|
|
27
|
+
// React to selection changes
|
|
28
|
+
this.handleSelectionChange(focusedItem);
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// 2. Update external system state based on FileBrowser changes
|
|
33
|
+
private async handleSelectionChange(item: FileBrowserItem | null) {
|
|
34
|
+
if (!item) return;
|
|
35
|
+
|
|
36
|
+
// Update external system
|
|
37
|
+
await this.updateExternalSystem(item);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 3. Coordinate back to FileBrowser when external system changes
|
|
41
|
+
public selectFromExternalSystem(externalItem: any) {
|
|
42
|
+
// Convert external item to FileBrowser item
|
|
43
|
+
const fileBrowserItem = this.convertToFileBrowserItem(externalItem);
|
|
44
|
+
|
|
45
|
+
// Use coordination methods
|
|
46
|
+
this.fileBrowserModel.selectionManager.selectItem(fileBrowserItem.id);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Key Coordination Points
|
|
51
|
+
|
|
52
|
+
1. **Selection Coordination**: Synchronize selection between FileBrowser and external systems
|
|
53
|
+
2. **Navigation Coordination**: Coordinate navigation events across panels
|
|
54
|
+
3. **State Management**: Maintain consistent state between systems
|
|
55
|
+
4. **Error Handling**: Provide graceful error handling with proper user feedback
|
|
56
|
+
|
|
57
|
+
## Example Adapters
|
|
58
|
+
|
|
59
|
+
### DocumentViewerAdapter
|
|
60
|
+
|
|
61
|
+
Demonstrates integration with a document viewing system:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { DocumentViewerAdapter } from './DocumentViewerAdapter';
|
|
65
|
+
|
|
66
|
+
// Initialize adapter
|
|
67
|
+
const documentViewer = new DocumentViewerAdapter(fileBrowserModel, {
|
|
68
|
+
supportedFileTypes: ['.pdf', '.doc', '.docx', '.txt', '.md'],
|
|
69
|
+
previewEnabled: true,
|
|
70
|
+
maxFileSize: 50 * 1024 * 1024, // 50MB
|
|
71
|
+
enableCoordination: true
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Document will automatically load when files are selected in FileBrowser
|
|
75
|
+
// Navigation will automatically clear stale document state
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Key Features:**
|
|
79
|
+
- Automatic document loading on file selection
|
|
80
|
+
- Preview generation and caching
|
|
81
|
+
- File type validation and size constraints
|
|
82
|
+
- Navigation-aware state management
|
|
83
|
+
- Bidirectional coordination with FileBrowser
|
|
84
|
+
|
|
85
|
+
### GitBrowserAdapter
|
|
86
|
+
|
|
87
|
+
Demonstrates integration with Git repository functionality:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { GitBrowserAdapter } from './GitBrowserAdapter';
|
|
91
|
+
|
|
92
|
+
// Initialize adapter
|
|
93
|
+
const gitBrowser = new GitBrowserAdapter(fileBrowserModel, {
|
|
94
|
+
repositoryPath: '/path/to/repo',
|
|
95
|
+
autoFetch: false,
|
|
96
|
+
statusRefreshInterval: 5000,
|
|
97
|
+
enableCoordination: true
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Load repository
|
|
101
|
+
await gitBrowser.loadRepository('/path/to/repo');
|
|
102
|
+
|
|
103
|
+
// Git status will automatically update based on FileBrowser navigation
|
|
104
|
+
// Branch switching will coordinate with FileBrowser content updates
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Key Features:**
|
|
108
|
+
- Git repository integration
|
|
109
|
+
- Branch and commit coordination
|
|
110
|
+
- File status overlay
|
|
111
|
+
- Left panel mode integration
|
|
112
|
+
- Automatic status refresh
|
|
113
|
+
|
|
114
|
+
## Creating Custom Adapters
|
|
115
|
+
|
|
116
|
+
### Step 1: Define Your Adapter Interface
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
export interface MyAdapterOptions {
|
|
120
|
+
// Configuration options
|
|
121
|
+
enableCoordination?: boolean;
|
|
122
|
+
// ... other options
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export class MyAdapter {
|
|
126
|
+
private fileBrowserModel: FileBrowserModel;
|
|
127
|
+
private options: Required<MyAdapterOptions>;
|
|
128
|
+
private disposers: Array<() => void> = [];
|
|
129
|
+
|
|
130
|
+
constructor(fileBrowserModel: FileBrowserModel, options: MyAdapterOptions = {}) {
|
|
131
|
+
this.fileBrowserModel = fileBrowserModel;
|
|
132
|
+
this.options = {
|
|
133
|
+
enableCoordination: true,
|
|
134
|
+
...options
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
makeAutoObservable(this);
|
|
138
|
+
|
|
139
|
+
if (this.options.enableCoordination) {
|
|
140
|
+
this.setupCoordination();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Step 2: Setup Coordination Reactions
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
private setupCoordination() {
|
|
150
|
+
// Listen for selection changes
|
|
151
|
+
const selectionDisposer = reaction(
|
|
152
|
+
() => ({
|
|
153
|
+
focusedItem: this.fileBrowserModel.selectionManager.focusedItem
|
|
154
|
+
}),
|
|
155
|
+
({ focusedItem }) => {
|
|
156
|
+
this.handleSelectionChange(focusedItem);
|
|
157
|
+
},
|
|
158
|
+
{ fireImmediately: true }
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
// Listen for navigation changes
|
|
162
|
+
const navigationDisposer = reaction(
|
|
163
|
+
() => this.fileBrowserModel.navigationManager.currentPath,
|
|
164
|
+
(currentPath) => {
|
|
165
|
+
this.handleNavigationChange(currentPath || '/');
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
this.disposers.push(selectionDisposer, navigationDisposer);
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Step 3: Implement Coordination Handlers
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
private async handleSelectionChange(item: FileBrowserItem | null) {
|
|
177
|
+
if (!item) {
|
|
178
|
+
this.clearExternalState();
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Update external system based on selection
|
|
183
|
+
try {
|
|
184
|
+
await this.updateExternalSystem(item);
|
|
185
|
+
this.logInfo(`Updated external system for: ${item.name}`);
|
|
186
|
+
} catch (error) {
|
|
187
|
+
this.logError('Failed to update external system', error);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private async handleNavigationChange(currentPath: string) {
|
|
192
|
+
// React to navigation changes
|
|
193
|
+
await this.refreshExternalSystemForPath(currentPath);
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Step 4: Provide Public APIs
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
// Public methods for external control
|
|
201
|
+
public async loadItem(item: FileBrowserItem): Promise<void> {
|
|
202
|
+
// Use coordination to load item
|
|
203
|
+
this.fileBrowserModel.selectionManager.selectItem(item.id);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
public navigateToItem(item: FileBrowserItem): void {
|
|
207
|
+
// Use navigation coordination
|
|
208
|
+
const directoryPath = this.getDirectoryPath(item.path);
|
|
209
|
+
this.fileBrowserModel.navigationManager.navigateToWithCoordination(
|
|
210
|
+
directoryPath,
|
|
211
|
+
'breadcrumb'
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Step 5: Implement Cleanup
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
dispose(): void {
|
|
220
|
+
// Clean up all reactions
|
|
221
|
+
this.disposers.forEach(dispose => dispose());
|
|
222
|
+
this.disposers = [];
|
|
223
|
+
|
|
224
|
+
// Clean up external resources
|
|
225
|
+
this.cleanupExternalSystem();
|
|
226
|
+
|
|
227
|
+
this.logInfo('Adapter disposed');
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Best Practices
|
|
232
|
+
|
|
233
|
+
### 1. Reactive State Management
|
|
234
|
+
|
|
235
|
+
- Use MobX `reaction` for listening to FileBrowser state changes
|
|
236
|
+
- Use `makeAutoObservable` for adapter state
|
|
237
|
+
- Avoid direct state mutations, use actions instead
|
|
238
|
+
|
|
239
|
+
### 2. Error Handling
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
private async handleCoordinatedOperation(operation: () => Promise<void>) {
|
|
243
|
+
try {
|
|
244
|
+
await operation();
|
|
245
|
+
} catch (error) {
|
|
246
|
+
this.setError(`Operation failed: ${error}`);
|
|
247
|
+
// Optionally notify user through FileBrowser error system
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### 3. Performance Optimization
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
// Use caching for expensive operations
|
|
256
|
+
private cache = new Map<string, any>();
|
|
257
|
+
|
|
258
|
+
private async getExpensiveData(key: string): Promise<any> {
|
|
259
|
+
if (this.cache.has(key)) {
|
|
260
|
+
return this.cache.get(key);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const data = await this.computeExpensiveData(key);
|
|
264
|
+
this.cache.set(key, data);
|
|
265
|
+
return data;
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### 4. Logging and Debugging
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
private logInfo(message: string, data?: any): void {
|
|
273
|
+
this.fileBrowserModel.logger?.info(`[MyAdapter] ${message}`, data);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
private logError(message: string, error: any): void {
|
|
277
|
+
this.fileBrowserModel.logger?.error(`[MyAdapter] ${message}`, error);
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### 5. Configuration Management
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
// Provide sensible defaults
|
|
285
|
+
private readonly defaultOptions: Required<MyAdapterOptions> = {
|
|
286
|
+
enableCoordination: true,
|
|
287
|
+
cacheSize: 100,
|
|
288
|
+
refreshInterval: 5000
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
constructor(fileBrowserModel: FileBrowserModel, options: MyAdapterOptions = {}) {
|
|
292
|
+
this.options = { ...this.defaultOptions, ...options };
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Migration Guide
|
|
297
|
+
|
|
298
|
+
### From Single-Panel to Dual-Panel
|
|
299
|
+
|
|
300
|
+
If you have existing FileBrowser integrations that need to be migrated to the dual-panel coordination system:
|
|
301
|
+
|
|
302
|
+
#### 1. Update Event Handling
|
|
303
|
+
|
|
304
|
+
**Before (single-panel):**
|
|
305
|
+
```typescript
|
|
306
|
+
// Direct event handling
|
|
307
|
+
onItemClick(item: FileBrowserItem) {
|
|
308
|
+
this.externalSystem.loadItem(item);
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**After (dual-panel coordination):**
|
|
313
|
+
```typescript
|
|
314
|
+
// Coordination-based handling
|
|
315
|
+
private setupCoordination() {
|
|
316
|
+
reaction(
|
|
317
|
+
() => this.fileBrowserModel.selectionManager.focusedItem,
|
|
318
|
+
(item) => {
|
|
319
|
+
if (item) {
|
|
320
|
+
this.externalSystem.loadItem(item);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
#### 2. Update Navigation Handling
|
|
328
|
+
|
|
329
|
+
**Before:**
|
|
330
|
+
```typescript
|
|
331
|
+
// Direct navigation
|
|
332
|
+
onNavigate(path: string) {
|
|
333
|
+
this.externalSystem.updatePath(path);
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**After:**
|
|
338
|
+
```typescript
|
|
339
|
+
// Coordination-based navigation
|
|
340
|
+
private setupCoordination() {
|
|
341
|
+
reaction(
|
|
342
|
+
() => this.fileBrowserModel.navigationManager.currentPath,
|
|
343
|
+
(path) => {
|
|
344
|
+
if (path) {
|
|
345
|
+
this.externalSystem.updatePath(path);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
#### 3. Update State Management
|
|
353
|
+
|
|
354
|
+
**Before:**
|
|
355
|
+
```typescript
|
|
356
|
+
// Manual state tracking
|
|
357
|
+
private selectedItem: FileBrowserItem | null = null;
|
|
358
|
+
|
|
359
|
+
setSelectedItem(item: FileBrowserItem) {
|
|
360
|
+
this.selectedItem = item;
|
|
361
|
+
this.updateUI();
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
**After:**
|
|
366
|
+
```typescript
|
|
367
|
+
// MobX reactive state
|
|
368
|
+
@observable
|
|
369
|
+
selectedItem: FileBrowserItem | null = null;
|
|
370
|
+
|
|
371
|
+
// Automatic updates via reactions
|
|
372
|
+
private setupCoordination() {
|
|
373
|
+
reaction(
|
|
374
|
+
() => this.fileBrowserModel.selectionManager.focusedItem,
|
|
375
|
+
(item) => {
|
|
376
|
+
this.selectedItem = item;
|
|
377
|
+
// UI updates automatically via MobX
|
|
378
|
+
}
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## Performance Considerations
|
|
384
|
+
|
|
385
|
+
### Large Datasets
|
|
386
|
+
|
|
387
|
+
When working with large datasets:
|
|
388
|
+
|
|
389
|
+
1. **Implement Virtualization**: Only load/render visible items
|
|
390
|
+
2. **Use Pagination**: Break large datasets into manageable chunks
|
|
391
|
+
3. **Cache Strategically**: Cache frequently accessed data with appropriate TTL
|
|
392
|
+
4. **Debounce Updates**: Avoid excessive updates during rapid changes
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
// Example: Debounced status updates
|
|
396
|
+
private debouncedStatusUpdate = debounce(async () => {
|
|
397
|
+
await this.refreshStatus();
|
|
398
|
+
}, 500);
|
|
399
|
+
|
|
400
|
+
private handleNavigationChange(path: string) {
|
|
401
|
+
this.debouncedStatusUpdate();
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Memory Management
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
// Clean up resources properly
|
|
409
|
+
dispose(): void {
|
|
410
|
+
// Dispose reactions
|
|
411
|
+
this.disposers.forEach(dispose => dispose());
|
|
412
|
+
|
|
413
|
+
// Clear caches
|
|
414
|
+
this.cache.clear();
|
|
415
|
+
|
|
416
|
+
// Cancel pending operations
|
|
417
|
+
this.cancelPendingOperations();
|
|
418
|
+
|
|
419
|
+
// Clear timers
|
|
420
|
+
if (this.refreshTimer) {
|
|
421
|
+
clearInterval(this.refreshTimer);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
## Testing
|
|
427
|
+
|
|
428
|
+
### Unit Testing Adapters
|
|
429
|
+
|
|
430
|
+
```typescript
|
|
431
|
+
import { DocumentViewerAdapter } from './DocumentViewerAdapter';
|
|
432
|
+
|
|
433
|
+
describe('DocumentViewerAdapter', () => {
|
|
434
|
+
let adapter: DocumentViewerAdapter;
|
|
435
|
+
let mockFileBrowserModel: jest.Mocked<FileBrowserModel>;
|
|
436
|
+
|
|
437
|
+
beforeEach(() => {
|
|
438
|
+
mockFileBrowserModel = createMockFileBrowserModel();
|
|
439
|
+
adapter = new DocumentViewerAdapter(mockFileBrowserModel);
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
afterEach(() => {
|
|
443
|
+
adapter.dispose();
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
it('should load document when file is selected', async () => {
|
|
447
|
+
const testFile = createTestFile('test.pdf');
|
|
448
|
+
|
|
449
|
+
// Simulate selection change
|
|
450
|
+
mockFileBrowserModel.selectionManager.focusedItem = testFile;
|
|
451
|
+
|
|
452
|
+
// Wait for coordination
|
|
453
|
+
await waitForReaction();
|
|
454
|
+
|
|
455
|
+
expect(adapter.currentDocument).toBeTruthy();
|
|
456
|
+
expect(adapter.currentDocument?.fileName).toBe('test.pdf');
|
|
457
|
+
});
|
|
458
|
+
});
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Integration Testing
|
|
462
|
+
|
|
463
|
+
```typescript
|
|
464
|
+
describe('Adapter Coordination', () => {
|
|
465
|
+
it('should maintain coordination between adapters', async () => {
|
|
466
|
+
const documentAdapter = new DocumentViewerAdapter(fileBrowserModel);
|
|
467
|
+
const gitAdapter = new GitBrowserAdapter(fileBrowserModel);
|
|
468
|
+
|
|
469
|
+
// Select a file
|
|
470
|
+
fileBrowserModel.selectionManager.selectItem('file1');
|
|
471
|
+
|
|
472
|
+
// Both adapters should react
|
|
473
|
+
await waitForReactions();
|
|
474
|
+
|
|
475
|
+
expect(documentAdapter.currentDocument).toBeTruthy();
|
|
476
|
+
expect(gitAdapter.getFileStatus('file1')).toBeTruthy();
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
## Troubleshooting
|
|
482
|
+
|
|
483
|
+
### Common Issues
|
|
484
|
+
|
|
485
|
+
1. **Infinite Loops**: Use coordination flags to prevent circular updates
|
|
486
|
+
2. **Memory Leaks**: Always dispose reactions and clear caches
|
|
487
|
+
3. **Performance Issues**: Implement debouncing and caching
|
|
488
|
+
4. **Type Errors**: Ensure proper TypeScript interfaces for coordination
|
|
489
|
+
|
|
490
|
+
### Debugging Tips
|
|
491
|
+
|
|
492
|
+
```typescript
|
|
493
|
+
// Enable detailed logging
|
|
494
|
+
private logInfo(message: string, data?: any): void {
|
|
495
|
+
if (process.env.NODE_ENV === 'development') {
|
|
496
|
+
console.log(`[${this.constructor.name}] ${message}`, data);
|
|
497
|
+
}
|
|
498
|
+
this.fileBrowserModel.logger?.info(`[${this.constructor.name}] ${message}`, data);
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
## Examples
|
|
503
|
+
|
|
504
|
+
See the `/examples` directory for complete working examples of various adapter patterns and integration scenarios.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Adapter implementations
|
|
2
|
+
export { DocumentViewerAdapter } from './DocumentViewerAdapter';
|
|
3
|
+
export type {
|
|
4
|
+
DocumentViewerOptions,
|
|
5
|
+
DocumentInfo
|
|
6
|
+
} from './DocumentViewerAdapter';
|
|
7
|
+
|
|
8
|
+
export { GitBrowserAdapter } from './GitBrowserAdapter';
|
|
9
|
+
export type {
|
|
10
|
+
GitBrowserOptions,
|
|
11
|
+
GitFileStatus,
|
|
12
|
+
GitCommit,
|
|
13
|
+
GitBranch,
|
|
14
|
+
GitRepositoryInfo
|
|
15
|
+
} from './GitBrowserAdapter';
|
|
16
|
+
|
|
17
|
+
// Base adapter patterns and utilities
|
|
18
|
+
export type { AdapterBase, AdapterOptions, AdapterStats, AdapterDisposer } from './types';
|
|
19
|
+
export { BaseAdapter } from './types';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Re-export core FileBrowser types for adapter development
|
|
23
|
+
*/
|
|
24
|
+
export type { FileBrowserItem } from '../types/FileBrowserTypes';
|
|
25
|
+
export type { FileBrowserModel } from '../models/FileBrowserModel';
|
|
26
|
+
export type { SelectionManagerModel } from '../models/SelectionManagerModel';
|
|
27
|
+
export type { NavigationManagerModel } from '../models/NavigationManagerModel';
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { FileBrowserModel } from '../models/FileBrowserModel';
|
|
2
|
+
import { FileBrowserItem } from '../types/FileBrowserTypes';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Base adapter options that all adapters should support
|
|
6
|
+
*/
|
|
7
|
+
export interface AdapterOptions {
|
|
8
|
+
enableCoordination?: boolean;
|
|
9
|
+
enableLogging?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Base adapter interface that all adapters should implement
|
|
14
|
+
*/
|
|
15
|
+
export interface AdapterBase {
|
|
16
|
+
// Core adapter lifecycle
|
|
17
|
+
dispose(): void;
|
|
18
|
+
|
|
19
|
+
// Coordination methods
|
|
20
|
+
handleSelectionChange(item: FileBrowserItem | null): void | Promise<void>;
|
|
21
|
+
handleNavigationChange(path: string): void | Promise<void>;
|
|
22
|
+
|
|
23
|
+
// Status methods
|
|
24
|
+
readonly isLoading: boolean;
|
|
25
|
+
readonly error: string | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Common coordination patterns for adapters
|
|
30
|
+
*/
|
|
31
|
+
export abstract class BaseAdapter implements AdapterBase {
|
|
32
|
+
protected fileBrowserModel: FileBrowserModel;
|
|
33
|
+
protected disposers: Array<() => void> = [];
|
|
34
|
+
|
|
35
|
+
abstract isLoading: boolean;
|
|
36
|
+
abstract error: string | null;
|
|
37
|
+
|
|
38
|
+
constructor(fileBrowserModel: FileBrowserModel) {
|
|
39
|
+
this.fileBrowserModel = fileBrowserModel;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
abstract handleSelectionChange(item: FileBrowserItem | null): void | Promise<void>;
|
|
43
|
+
abstract handleNavigationChange(path: string): void | Promise<void>;
|
|
44
|
+
|
|
45
|
+
protected logInfo(message: string, data?: any): void {
|
|
46
|
+
this.fileBrowserModel.logger?.info(`[${this.constructor.name}] ${message}`, data);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
protected logError(message: string, error: any): void {
|
|
50
|
+
this.fileBrowserModel.logger?.error(`[${this.constructor.name}] ${message}`, error);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
dispose(): void {
|
|
54
|
+
this.disposers.forEach(dispose => dispose());
|
|
55
|
+
this.disposers = [];
|
|
56
|
+
this.logInfo('Adapter disposed');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Utility types for adapter development
|
|
62
|
+
*/
|
|
63
|
+
export type AdapterDisposer = () => void;
|
|
64
|
+
|
|
65
|
+
export interface AdapterStats {
|
|
66
|
+
isLoaded: boolean;
|
|
67
|
+
hasError: boolean;
|
|
68
|
+
cacheSize?: number;
|
|
69
|
+
[key: string]: any;
|
|
70
|
+
}
|