@dtducas/wh-forge-viewer 1.0.8-beta → 1.0.9-beta0

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/README.md CHANGED
@@ -1,331 +1,415 @@
1
1
  # wh-forge-viewer
2
2
 
3
- A professional Autodesk Forge Viewer component for React with advanced PDF support, intelligent navigation, and production-ready architecture.
3
+ A professional Autodesk Forge Viewer component for React with advanced PDF support, comprehensive markup tools, and real-time collaboration capabilities.
4
4
 
5
5
  ## Features
6
6
 
7
- ### Core Features
8
- - ✅ **Custom Toolbar** - Pre-configured toolbar with Pan, Document Browser, Download, and Pagination controls
9
- - **Enhanced PDF Support** - Optimized for viewing PDF documents with intelligent page navigation
10
- - **Smart Document Browser** - Auto-opens with adaptive panel sizing (single/multi-page)
11
- - **3D/2D Models** - Full support for Autodesk Forge 3D and 2D models (DWF, DWFX)
12
- - **React Integration** - Easy-to-use React component with hooks support
13
-
14
- ### Advanced Navigation
15
- - 🚀 **No-Refresh Navigation** - Document Browser panel doesn't refresh when using pagination buttons
16
- - 🚀 **Smart Thumbnail Selection** - Auto-select and scroll to current thumbnail
17
- - 🚀 **Persistent State** - State survives extension unload/reload cycles
18
- - 🚀 **Synchronized Button States** - Document Browser button always reflects actual panel state
19
- - 🚀 **Smooth Scrolling** - Auto-scroll thumbnails to center in viewport
20
-
21
- ### Architecture & Quality
22
- - 🏗️ **SOLID Architecture** - Manager pattern with clear separation of concerns
23
- - 🏗️ **Type Safety** - Full TypeScript type definitions included
24
- - 🏗️ **Dependency Injection** - Clean, testable, and maintainable code
25
- - 🏗️ **Self-Healing Toolbar** - Automatic recovery mechanism ensures UI persistence
26
- - 🏗️ **Production Ready** - Clean code, no debug logs, optimized performance
7
+ ### Core Viewer
8
+
9
+ - **Custom Toolbar** - Pan, Document Browser, Download, and Pagination controls
10
+ - **Enhanced PDF Support** - Optimized for viewing PDF documents with intelligent page navigation
11
+ - **Smart Document Browser** - Auto-opens with adaptive panel sizing
12
+ - **3D/2D Models** - Full support for DWF, DWFX formats
13
+ - **React Integration** - Easy-to-use React component with hooks support
14
+
15
+ ### Markup Tools
16
+
17
+ - **12 Markup Tools** - Arrow, Rectangle, Circle, Cloud, Text, Freehand, Line, Polyline, Polycloud, Callout, Image/Stamp
18
+ - **SelectTool with Multi-Select** - Drag rectangle to select multiple markups
19
+ - **Property Panel** - Excalidraw-inspired UI for editing markup properties
20
+ - **Undo/Redo** - Full undo/redo support for all operations
21
+ - **Custom Stamps** - Insert images as stamps with drag-drop support
22
+
23
+ ### Collaboration
24
+
25
+ - **Real-Time Sync** - Subscribe to markup changes for WebSocket broadcasting
26
+ - **User Presence** - Track and display remote user cursors
27
+ - **Persistence API** - Save/load markups with JSON or SVG formats
28
+ - **Page Change Events** - Handle markup data during page navigation
29
+
30
+ ### Architecture
31
+
32
+ - **SOLID Principles** - Manager pattern with clear separation of concerns
33
+ - **Type Safety** - Full TypeScript definitions included
34
+ - **Event-Driven** - Decoupled communication via EventBus
35
+ - **Extensible** - Factory pattern for adding custom tools
27
36
 
28
37
  ## Installation
29
38
 
30
39
  ```bash
31
- npm install wh-forge-viewer
40
+ npm install @dtducas/wh-forge-viewer
32
41
  ```
33
42
 
34
- ## Usage
43
+ ## Quick Start
35
44
 
36
- ```jsx
37
- import { ViewerForgePDF } from 'wh-forge-viewer';
45
+ ### Basic Viewer
38
46
 
39
- function MyApp() {
40
- const [viewer, setViewer] = useState(null);
47
+ ```jsx
48
+ import { ViewerForgePDF } from '@dtducas/wh-forge-viewer';
41
49
 
50
+ function App() {
42
51
  return (
43
52
  <ViewerForgePDF
44
53
  filePath='https://example.com/document.pdf'
45
54
  fileExt='pdf'
46
- setViewer={setViewer}
55
+ onViewerReady={(viewer) => console.log('Ready:', viewer)}
47
56
  />
48
57
  );
49
58
  }
50
59
  ```
51
60
 
52
- ## Props
61
+ ### With Markup Tools
53
62
 
54
- | Prop | Type | Required | Description |
55
- | ----------- | -------- | -------- | ------------------------------------- |
56
- | `filePath` | string | Yes | URL to the document to load |
57
- | `fileExt` | string | Yes | File extension (pdf, dwf, dwfx, etc.) |
58
- | `setViewer` | function | No | Callback to receive viewer instance |
63
+ ```jsx
64
+ import {
65
+ ViewerForgePDF,
66
+ DrawingManager,
67
+ MarkupToolbar,
68
+ PropertyPanel,
69
+ EventBus,
70
+ } from '@dtducas/wh-forge-viewer';
71
+
72
+ function MarkupViewer() {
73
+ const [viewer, setViewer] = useState(null);
74
+ const [drawingManager, setDrawingManager] = useState(null);
75
+ const [activeTool, setActiveTool] = useState(null);
76
+ const [propertyConfig, setPropertyConfig] = useState(null);
77
+ const [propertyValues, setPropertyValues] = useState({});
59
78
 
60
- ## Custom Toolbar
79
+ const eventBus = EventBus.getInstance();
61
80
 
62
- The viewer includes a production-ready custom toolbar with two control groups:
81
+ useEffect(() => {
82
+ if (!viewer) return;
63
83
 
64
- ### Tools Group
84
+ const manager = new DrawingManager(viewer, eventBus, {
85
+ autoEnterEditMode: true,
86
+ defaultTool: 'arrow',
87
+ });
65
88
 
66
- - **Pan Tool** - Enable pan navigation mode
67
- - Auto-activates on viewer load
68
- - Synced with Forge Viewer navigation state
69
-
70
- - **Document Browser** - Toggle document tree/thumbnail view
71
- - Auto-opens for all documents (single/multi-page)
72
- - Positioned on right side with custom styling
73
- - Default tab: Thumbnails view
74
- - Adaptive panel height based on content
75
- - State persists across page navigation
76
-
77
- - **Download** - Download the current document
78
- - One-click file download
79
- - Preserves original filename
89
+ setDrawingManager(manager);
80
90
 
81
- ### Pagination Group
91
+ return () => manager.destroy();
92
+ }, [viewer]);
82
93
 
83
- - **Previous Page** - Navigate to previous page
84
- - **Page Counter** - Display "current / total" pages (e.g., "3 / 9")
85
- - **Next Page** ▶ - Navigate to next page
94
+ const handleToolChange = (tool) => {
95
+ drawingManager?.setActiveTool(tool);
96
+ setActiveTool(tool);
97
+ setPropertyConfig(drawingManager?.getCurrentToolPropertyConfig());
98
+ setPropertyValues(drawingManager?.getCurrentToolPropertyValues() || {});
99
+ };
86
100
 
87
- **Smart Navigation:**
88
- - When Document Browser is open: Uses internal API to prevent panel refresh
89
- - When Document Browser is closed: Uses standard navigation with panel restore
90
- - Thumbnail selection and scroll automatically sync with current page
101
+ return (
102
+ <div style={{ position: 'relative', width: '100%', height: '100vh' }}>
103
+ <ViewerForgePDF
104
+ filePath='/document.pdf'
105
+ fileExt='pdf'
106
+ onViewerReady={setViewer}
107
+ />
108
+
109
+ {drawingManager && (
110
+ <>
111
+ <MarkupToolbar
112
+ activeTool={activeTool}
113
+ onToolChange={handleToolChange}
114
+ onUndo={() => drawingManager.undo()}
115
+ onRedo={() => drawingManager.redo()}
116
+ />
117
+
118
+ <PropertyPanel
119
+ config={propertyConfig}
120
+ values={propertyValues}
121
+ onChange={(key, value) => {
122
+ drawingManager.handlePropertyChange(key, value);
123
+ setPropertyValues(drawingManager.getCurrentToolPropertyValues());
124
+ }}
125
+ />
126
+ </>
127
+ )}
128
+ </div>
129
+ );
130
+ }
131
+ ```
91
132
 
92
- ## Requirements
133
+ ### Real-Time Collaboration
93
134
 
94
- ### Peer Dependencies
95
- - React ^17.0.0 || ^18.0.0
96
- - Ant Design ^5.0.0
135
+ ```jsx
136
+ import {
137
+ DrawingManager,
138
+ EventBus,
139
+ CursorOverlay,
140
+ } from '@dtducas/wh-forge-viewer';
97
141
 
98
- ### Browser Support
99
- - Modern browsers with ES6+ support
100
- - Chrome 90+, Firefox 88+, Safari 14+, Edge 90+
142
+ function CollaborativeViewer({ socket }) {
143
+ const [drawingManager, setDrawingManager] = useState(null);
144
+ const [remoteCursors, setRemoteCursors] = useState(new Map());
101
145
 
102
- ### Autodesk Forge Viewer
103
- - Uses v7.108.0 (loaded from CDN)
104
- - Pinned version for production stability
146
+ useEffect(() => {
147
+ if (!drawingManager) return;
148
+
149
+ // Subscribe to local markup changes
150
+ const unsubscribe = drawingManager.onMarkupChange((delta) => {
151
+ socket.emit('markup:delta', delta);
152
+ });
153
+
154
+ // Subscribe to local cursor movement
155
+ const unsubCursor = drawingManager.onLocalCursorMove((position) => {
156
+ socket.emit('cursor:move', { userId: currentUser.id, position });
157
+ });
158
+
159
+ // Handle remote changes
160
+ socket.on('markup:delta', (delta) => {
161
+ drawingManager.applyDelta(delta);
162
+ });
163
+
164
+ // Handle remote cursors
165
+ socket.on('cursor:move', (cursor) => {
166
+ drawingManager.updateUserCursor(cursor);
167
+ setRemoteCursors(new Map(drawingManager.getRemoteCursors()));
168
+ });
169
+
170
+ return () => {
171
+ unsubscribe();
172
+ unsubCursor();
173
+ };
174
+ }, [drawingManager, socket]);
105
175
 
106
- ## Important Notes
176
+ return (
177
+ <>
178
+ {/* ... viewer components ... */}
179
+ <CursorOverlay cursors={remoteCursors} />
180
+ </>
181
+ );
182
+ }
183
+ ```
107
184
 
108
- ### Viewer Versioning
185
+ ### Persistence
109
186
 
110
- This package uses a **specific version** of Autodesk Forge Viewer (v7.108.0) loaded from CDN, instead of wildcards (7.*), to ensure production stability and avoid unexpected breaking changes.
187
+ ```javascript
188
+ // Save to localStorage
189
+ const data = drawingManager.getMarkupData();
190
+ localStorage.setItem('markups', JSON.stringify(data));
111
191
 
112
- **Why pinned version?**
113
- - Predictable behavior in production
114
- - No surprise updates from Autodesk
115
- - ✅ Tested and verified functionality
116
- - ✅ Easy to upgrade when ready
192
+ // Load from localStorage
193
+ const saved = JSON.parse(localStorage.getItem('markups'));
194
+ await drawingManager.loadMarkupData(saved, { mode: 'replace' });
117
195
 
118
- 📖 See [docs/VERSIONING.md](docs/VERSIONING.md) for version update guide.
196
+ // Save to database (JSON format)
197
+ const jsonData = drawingManager.getMarkupDataAsJson('page-guid-123');
198
+ await db.collection('markups').doc('page-guid-123').set(jsonData);
119
199
 
120
- ### Known Behaviors
200
+ // Load from database
201
+ const doc = await db.collection('markups').doc('page-guid-123').get();
202
+ await drawingManager.loadMarkupDataFromJson(doc.data());
203
+ ```
121
204
 
122
- **Extension Lifecycle:**
123
- - Forge Viewer unloads extensions when navigating between pages
124
- - This package handles this gracefully with GLOBAL_STATE persistence
125
- - All states (viewables, page index, panel state) are preserved
205
+ ### PDF Export with Markup
126
206
 
127
- **Document Browser Panel:**
128
- - Auto-opens for both single and multi-page documents
129
- - Panel height adapts to content (compact for 1 page, scrollable for many)
130
- - Positioned on right side by default
131
- - Uses Thumbnails tab as default view
207
+ ```javascript
208
+ // Export current page with markup as vector overlay
209
+ const result = await drawingManager.exportCurrentPagePDF(filePath, 0);
210
+ if (result.success && result.blob) {
211
+ const url = URL.createObjectURL(result.blob);
212
+ window.open(url); // Preview in new tab
213
+ }
132
214
 
133
- ## Architecture
215
+ // Multi-page export
216
+ const markupsByPage = [
217
+ { pageIndex: 0, svgString: savedPage0Svg },
218
+ { pageIndex: 1, svgString: drawingManager.getMarkupSVG() }, // current page
219
+ ];
220
+ await drawingManager.exportAndDownloadPDF(filePath, markupsByPage, {
221
+ filename: 'annotated-document',
222
+ });
223
+ ```
134
224
 
135
- This package follows **SOLID principles** and uses a production-ready modular architecture:
225
+ ## Components
136
226
 
137
- ### Core Components
227
+ ### ViewerForgePDF
138
228
 
139
- **Managers** (Business Logic)
140
- - `PaginationManager` - Handles page navigation, viewables management, and smart Document Browser API integration
141
- - `ToolbarManager` - Creates and manages custom toolbar buttons and their states
142
- - `DocumentBrowserManager` - Controls Document Browser panel visibility, styling, and state persistence
229
+ Main viewer component.
143
230
 
144
- **Services** (Utilities)
145
- - `EventBus` - Singleton event bus for decoupled communication between managers
146
- - `FileLoader` - Loads PDF/DWF/DWFX files into viewer with viewables extraction
147
- - `DownloadService` - Handles file downloads with proper filename extraction
231
+ | Prop | Type | Required | Description |
232
+ | ------------------ | -------- | -------- | ------------------------------- |
233
+ | `filePath` | string | Yes | URL to the document |
234
+ | `fileExt` | string | Yes | File extension (pdf, dwf, dwfx) |
235
+ | `onViewerReady` | function | No | Callback with viewer instance |
236
+ | `onDocumentLoaded` | function | No | Callback with viewables array |
237
+ | `onError` | function | No | Callback for errors |
148
238
 
149
- **Extension**
150
- - `ToolbarExtension` - Main extension that orchestrates all managers and services
239
+ ### MarkupToolbar
151
240
 
152
- ### Key Features
241
+ Floating toolbar for tool selection.
153
242
 
154
- **Global State Persistence**
155
- - State survives Forge Viewer's extension unload/reload cycles
156
- - Preserves viewables, current page index, and Document Browser state
157
- - Seamless navigation without losing context
243
+ | Prop | Type | Description |
244
+ | -------------- | -------- | --------------------- |
245
+ | `activeTool` | string | Currently active tool |
246
+ | `onToolChange` | function | Tool change callback |
247
+ | `onUndo` | function | Undo callback |
248
+ | `onRedo` | function | Redo callback |
158
249
 
159
- **Smart Navigation**
160
- - Detects if Document Browser panel is open
161
- - Uses `_changeModelFn` API when open (no panel refresh)
162
- - Falls back to `loadDocumentNode` when closed (with state restoration)
163
- - Automatic thumbnail selection and scroll synchronization
250
+ ### PropertyPanel
164
251
 
165
- **Self-Healing Mechanism**
166
- - Polls every 8ms to detect missing toolbar groups
167
- - Automatically recreates toolbar if removed by Forge Viewer
168
- - Syncs button states with actual panel visibility
169
- - Ensures UI consistency at all times
252
+ Side panel for editing properties.
170
253
 
171
- 📖 See [ARCHITECTURE.md](ARCHITECTURE.md) for detailed architecture documentation.
254
+ | Prop | Type | Description |
255
+ | ---------- | ------------------- | ------------------------ |
256
+ | `config` | IToolPropertyConfig | Property configuration |
257
+ | `values` | object | Current property values |
258
+ | `onChange` | function | Property change callback |
259
+ | `onAction` | function | Action button callback |
172
260
 
173
- ## Advanced Usage
261
+ ### CursorOverlay
174
262
 
175
- ### Accessing Viewer Instance
263
+ Overlay for displaying remote cursors.
176
264
 
177
- ```jsx
178
- function MyApp() {
179
- const [viewer, setViewer] = useState(null);
265
+ | Prop | Type | Description |
266
+ | -------------- | ------- | ----------------------------- |
267
+ | `cursors` | Map | Remote user cursors |
268
+ | `viewerBounds` | DOMRect | Viewer bounds for positioning |
180
269
 
181
- useEffect(() => {
182
- if (viewer) {
183
- // Access viewer API
184
- console.log('Viewer loaded:', viewer);
185
-
186
- // Listen to Forge Viewer events
187
- viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, () => {
188
- console.log('Geometry loaded');
189
- });
190
- }
191
- }, [viewer]);
270
+ ## DrawingManager API
192
271
 
193
- return (
194
- <ViewerForgePDF
195
- filePath="/path/to/document.pdf"
196
- fileExt="pdf"
197
- setViewer={setViewer}
198
- />
199
- );
200
- }
272
+ ### Edit Mode
273
+
274
+ ```typescript
275
+ await drawingManager.enterEditMode(); // Enter markup mode
276
+ drawingManager.leaveEditMode(); // Exit markup mode
277
+ drawingManager.isEditMode(); // Check if in edit mode
201
278
  ```
202
279
 
203
- ### Event Bus Integration
280
+ ### Tools
204
281
 
205
- The package exposes an EventBus for custom integrations:
282
+ ```typescript
283
+ drawingManager.setActiveTool('arrow'); // Set active tool
284
+ drawingManager.getActiveTool(); // Get current tool
285
+ drawingManager.setStrokeStyle('#e03131', 2, 1.0); // Set stroke
286
+ drawingManager.setFillStyle('#228be6', 0.3); // Set fill
287
+ ```
206
288
 
207
- ```javascript
208
- import { EventBus } from '@dtducas/wh-forge-viewer';
289
+ **Available Tools:**
290
+ `select`, `arrow`, `rectangle`, `ellipse`, `cloud`, `label`, `freehand`, `line`, `polyline`, `polycloud`, `callout`, `image`
209
291
 
210
- const eventBus = EventBus.getInstance();
292
+ ### Markup Operations
211
293
 
212
- // Listen to page changes
213
- eventBus.on('page:changed', (data) => {
214
- console.log('Page changed to:', data.index);
215
- console.log('From Document Browser:', data.fromDocBrowser);
216
- console.log('From Pagination:', data.fromPagination);
217
- });
294
+ ```typescript
295
+ drawingManager.saveMarkups(); // Save current markups
296
+ drawingManager.loadMarkups(data); // Load markups
297
+ drawingManager.clearMarkups(); // Clear all markups
298
+ drawingManager.exportToSVG(); // Export to SVG string
299
+ drawingManager.undo(); // Undo last action
300
+ drawingManager.redo(); // Redo last undone action
301
+ ```
218
302
 
219
- // Listen to Document Browser events
220
- eventBus.on('docBrowser:opened', () => {
221
- console.log('Document Browser opened');
222
- });
303
+ ### Collaborative API
223
304
 
224
- eventBus.on('docBrowser:closed', () => {
225
- console.log('Document Browser closed');
226
- });
227
- ```
305
+ ```typescript
306
+ // Get markup data for persistence
307
+ const data = drawingManager.getMarkupData(viewableGUID);
228
308
 
229
- ## Performance Optimizations
309
+ // Load markup data
310
+ await drawingManager.loadMarkupData(data, { mode: 'replace' });
230
311
 
231
- ### No-Refresh Navigation
232
- When Document Browser panel is open, pagination uses internal Forge Viewer API (`_changeModelFn`) instead of full page reload. This provides:
233
- - Faster page navigation
234
- - ✨ No panel refresh/flicker
235
- - 🎯 Smooth user experience
236
- - 💾 Memory efficient
312
+ // Subscribe to changes
313
+ const unsubscribe = drawingManager.onMarkupChange((delta) => {
314
+ // delta: { type: 'create'|'update'|'delete', markupId, data, timestamp }
315
+ socket.emit('markup:delta', delta);
316
+ });
237
317
 
238
- ### Intelligent State Management
239
- - Global state persists across extension lifecycles
240
- - Minimal re-renders and DOM updates
241
- - Efficient event-driven architecture
242
- - Debounced toolbar healing checks
318
+ // Apply remote changes
319
+ drawingManager.applyDelta(delta);
243
320
 
244
- ### Adaptive UI
245
- - Panel height adjusts based on thumbnail count
246
- - Single page: Compact panel
247
- - Multi-page: Optimized for scrolling (max 80% viewport)
321
+ // Batch apply (for initial load)
322
+ drawingManager.applyBatch(elements, true);
323
+ ```
248
324
 
249
- ## Development
325
+ ### User Presence
250
326
 
251
- ```bash
252
- # Install dependencies
253
- npm install
327
+ ```typescript
328
+ // Broadcast local cursor
329
+ const unsub = drawingManager.onLocalCursorMove((position) => {
330
+ socket.emit('cursor:move', { userId, position });
331
+ });
254
332
 
255
- # Build package
256
- npm run build
333
+ // Update remote cursor
334
+ drawingManager.updateUserCursor({ userId, userName, color, position });
257
335
 
258
- # Watch mode for development
259
- npm run dev
336
+ // Remove cursor when user leaves
337
+ drawingManager.removeUserCursor(userId);
338
+
339
+ // Get all remote cursors
340
+ const cursors = drawingManager.getRemoteCursors();
260
341
  ```
261
342
 
262
- ## Testing
343
+ ## EventBus Events
263
344
 
264
- A complete test app is included in `/test/app`:
345
+ | Event | Payload | Description |
346
+ | -------------------------- | ------------------------ | ---------------------- |
347
+ | `page:changing` | `{ fromIndex, toIndex }` | Before page navigation |
348
+ | `page:changed` | `{ index, viewable }` | After page navigation |
349
+ | `drawing:editModeEntered` | `{}` | Entered markup mode |
350
+ | `drawing:editModeExited` | `{}` | Exited markup mode |
351
+ | `drawing:toolChanged` | `{ tool }` | Tool changed |
352
+ | `drawing:propertiesSynced` | `{ values }` | Properties updated |
265
353
 
266
- ```bash
267
- cd test/app
268
- npm install
269
- npm run dev
354
+ ```javascript
355
+ import { EventBus, EVENT_NAMES } from '@dtducas/wh-forge-viewer';
356
+
357
+ const eventBus = EventBus.getInstance();
358
+
359
+ eventBus.on(EVENT_NAMES.PAGE_CHANGED, ({ index }) => {
360
+ console.log('Now on page:', index);
361
+ });
270
362
  ```
271
363
 
272
- ## Publishing
364
+ ## Custom Toolbar
273
365
 
274
- The package is automatically published to NPM when you push a version tag:
366
+ Built-in toolbar includes:
275
367
 
276
- ```bash
277
- # Update version in package.json
278
- npm version patch # or minor, major
368
+ **Tools Group:**
279
369
 
280
- # Push tag
281
- git push origin v1.0.x
282
- ```
370
+ - Pan Tool - Navigate the document
371
+ - Document Browser - Toggle thumbnail/tree view
372
+ - Download - Download current document
283
373
 
284
- ## Troubleshooting
374
+ **Pagination Group:**
285
375
 
286
- ### Browser Console Warning: "runtime.lastError"
376
+ - Previous/Next Page navigation
377
+ - Current page indicator
287
378
 
288
- **Error:** `Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.`
379
+ **Smart Features:**
289
380
 
290
- **Cause:** This comes from browser extensions (React DevTools, Redux DevTools, etc.) trying to inject into your page.
381
+ - No-refresh navigation when Document Browser is open
382
+ - Self-healing mechanism for toolbar persistence
383
+ - Synchronized button states
291
384
 
292
- **Solution:** This is safe to ignore. It doesn't affect your application. To remove the warning:
293
- - Disable browser extensions during development, OR
294
- - Add error boundary to catch extension errors
385
+ ## Requirements
295
386
 
296
- ### Document Browser Button Not Syncing
387
+ - React ^17.0.0 || ^18.0.0
388
+ - Ant Design ^5.0.0 (peer dependency)
389
+ - Modern browsers (Chrome 90+, Firefox 88+, Safari 14+, Edge 90+)
297
390
 
298
- If the Document Browser button state doesn't match panel visibility:
299
- 1. Check browser console for errors
300
- 2. Verify Autodesk Forge Viewer version (should be v7.108.0)
301
- 3. Try refreshing the page
302
- 4. The self-healing mechanism should auto-fix within seconds
391
+ ## Development
303
392
 
304
- ### Pagination Display Not Updating
393
+ ```bash
394
+ # Install dependencies
395
+ npm install
396
+
397
+ # Build package
398
+ npm run build
305
399
 
306
- If page numbers don't update after navigation:
307
- 1. Extension includes aggressive update mechanism (10+ retries)
308
- 2. Should auto-correct within 500ms
309
- 3. Check if toolbar group is being removed by other extensions
400
+ # Watch mode
401
+ npm run dev
310
402
 
311
- ## Changelog
403
+ # Test app
404
+ cd test/app && npm install && npm run dev
405
+ ```
312
406
 
313
- ### v1.0.7 (Latest)
314
- - ✨ Smart navigation: Document Browser panel no longer refreshes when using pagination buttons
315
- - ✨ Auto-scroll thumbnails to center selected page
316
- - ✨ Adaptive panel height for single vs multi-page documents
317
- - ✨ Global state persistence across extension reload cycles
318
- - 🐛 Fixed: Document Browser button state sync after thumbnail navigation
319
- - 🐛 Fixed: Thumbnail selection not updating when using pagination buttons
320
- - 🧹 Removed all debug console logs for production
321
- - 📝 Full code cleanup and optimization
407
+ ## Documentation
322
408
 
323
- ### v1.0.5
324
- - Initial public release
325
- - Custom toolbar with Pan, Document Browser, Download buttons
326
- - Pagination controls for multi-page documents
327
- - Self-healing toolbar mechanism
328
- - SOLID architecture refactor
409
+ - [API Reference](docs/API.md) - Complete API documentation
410
+ - [Architecture](ARCHITECTURE.md) - Detailed architecture documentation
411
+ - [Versioning Guide](docs/VERSIONING.md) - Forge Viewer version management
412
+ - [Collaborative API](docs/COLLABORATIVE-API.md) - Real-time collaboration guide
329
413
 
330
414
  ## License
331
415
 
@@ -335,20 +419,15 @@ MIT
335
419
 
336
420
  **Duong Tran Quang**
337
421
 
338
- - Email: <baymax.contact@gmail.com>
422
+ - Email: baymax.contact@gmail.com
339
423
  - GitHub: [@DTDucas](https://github.com/DTDucas)
340
424
  - LinkedIn: [dtducas](https://www.linkedin.com/in/dtducas)
341
425
 
342
- ## Support & Issues
343
-
344
- - 🐛 [Report bugs](https://github.com/DTDucas/wh-forge-viewer/issues)
345
- - 💡 [Request features](https://github.com/DTDucas/wh-forge-viewer/issues)
346
- - 📖 [View documentation](https://github.com/DTDucas/wh-forge-viewer#readme)
347
-
348
- ## Contributing
426
+ ## Support
349
427
 
350
- Contributions are welcome! Please read [ARCHITECTURE.md](ARCHITECTURE.md) before submitting PRs.
428
+ - [Report bugs](https://github.com/DTDucas/wh-forge-viewer/issues)
429
+ - [Request features](https://github.com/DTDucas/wh-forge-viewer/issues)
351
430
 
352
431
  ---
353
432
 
354
- Made with ❤️ by [DTDucas](https://github.com/DTDucas)
433
+ Made with care by [DTDucas](https://github.com/DTDucas)