bdsa-react-components 0.1.20 → 0.1.22
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/CHANGELOG.md +66 -0
- package/CURSOR_INTEGRATION.md +75 -15
- package/dist/components/AnnotationManager/AnnotationManager.d.ts +2 -185
- package/dist/components/AnnotationManager/AnnotationManager.d.ts.map +1 -1
- package/dist/components/AnnotationManager/AnnotationManager.types.d.ts +120 -0
- package/dist/components/AnnotationManager/AnnotationManager.types.d.ts.map +1 -0
- package/dist/components/FolderBrowser/FolderBrowser.d.ts +2 -117
- package/dist/components/FolderBrowser/FolderBrowser.d.ts.map +1 -1
- package/dist/components/FolderBrowser/FolderBrowser.render.d.ts +12 -0
- package/dist/components/FolderBrowser/FolderBrowser.render.d.ts.map +1 -0
- package/dist/components/FolderBrowser/FolderBrowser.types.d.ts +94 -0
- package/dist/components/FolderBrowser/FolderBrowser.types.d.ts.map +1 -0
- package/dist/components/FolderBrowser/FolderBrowser.utils.d.ts +34 -0
- package/dist/components/FolderBrowser/FolderBrowser.utils.d.ts.map +1 -0
- package/dist/components/FolderBrowser/useFolderBrowserDataFetching.d.ts +58 -0
- package/dist/components/FolderBrowser/useFolderBrowserDataFetching.d.ts.map +1 -0
- package/dist/components/FolderThumbnailBrowser/FolderThumbnailBrowser.d.ts +54 -0
- package/dist/components/FolderThumbnailBrowser/FolderThumbnailBrowser.d.ts.map +1 -0
- package/dist/components/SlideViewer/SlideViewer.d.ts +2 -171
- package/dist/components/SlideViewer/SlideViewer.d.ts.map +1 -1
- package/dist/components/SlideViewer/SlideViewer.types.d.ts +175 -0
- package/dist/components/SlideViewer/SlideViewer.types.d.ts.map +1 -0
- package/dist/components/SlideViewer/SlideViewer.utils.d.ts +46 -0
- package/dist/components/SlideViewer/SlideViewer.utils.d.ts.map +1 -0
- package/dist/components/SlideViewer/hooks/index.d.ts +5 -0
- package/dist/components/SlideViewer/hooks/index.d.ts.map +1 -0
- package/dist/components/SlideViewer/hooks/useAnnotationFetching.d.ts +23 -0
- package/dist/components/SlideViewer/hooks/useAnnotationFetching.d.ts.map +1 -0
- package/dist/components/SlideViewer/hooks/useAnnotationOpacity.d.ts +8 -0
- package/dist/components/SlideViewer/hooks/useAnnotationOpacity.d.ts.map +1 -0
- package/dist/components/SlideViewer/hooks/useAnnotationRendering.d.ts +14 -0
- package/dist/components/SlideViewer/hooks/useAnnotationRendering.d.ts.map +1 -0
- package/dist/components/SlideViewer/hooks/useSlideViewerInitialization.d.ts +21 -0
- package/dist/components/SlideViewer/hooks/useSlideViewerInitialization.d.ts.map +1 -0
- package/dist/components/ThumbnailGrid/ThumbnailGrid.d.ts +55 -0
- package/dist/components/ThumbnailGrid/ThumbnailGrid.d.ts.map +1 -0
- package/dist/components/ThumbnailViewer/ThumbnailViewer.d.ts +45 -0
- package/dist/components/ThumbnailViewer/ThumbnailViewer.d.ts.map +1 -0
- package/dist/index.cjs +71 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38955 -37886
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,39 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.1.20] - 2025-11-12
|
|
9
|
+
|
|
10
|
+
### Added - Debug Mode for Clean Console Output 🔇
|
|
11
|
+
|
|
12
|
+
#### Debug Logging System
|
|
13
|
+
- **New `debug` prop** added to all major components:
|
|
14
|
+
- `FolderBrowser` - `debug?: boolean` (default: `false`)
|
|
15
|
+
- `SlideViewer` - `debug?: boolean` (default: `false`)
|
|
16
|
+
- `AnnotationManager` - `debug?: boolean` (default: `false`)
|
|
17
|
+
- **All `console.log()` calls now respect debug flag** - no console spam in production
|
|
18
|
+
- **`console.error()` always logs** - important errors still visible
|
|
19
|
+
- **New utility**: `createDebugLogger(componentName, debug)` for custom debug logging
|
|
20
|
+
- **Exported types**: `DebugLogger` interface for TypeScript support
|
|
21
|
+
|
|
22
|
+
#### Benefits
|
|
23
|
+
- ✅ **Clean console by default** - No more debug log spam in production apps
|
|
24
|
+
- ✅ **Opt-in debugging** - Enable `debug={true}` when troubleshooting
|
|
25
|
+
- ✅ **Backward compatible** - Existing code works unchanged (just cleaner output)
|
|
26
|
+
- ✅ **Prefixed logs** - Easy to identify which component logged what
|
|
27
|
+
|
|
28
|
+
#### Usage
|
|
29
|
+
```typescript
|
|
30
|
+
// Production (no console spam)
|
|
31
|
+
<FolderBrowser apiBaseUrl="..." />
|
|
32
|
+
|
|
33
|
+
// Development/debugging
|
|
34
|
+
<FolderBrowser apiBaseUrl="..." debug={true} />
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
- **Default behavior**: Console logs are now suppressed by default (was always on)
|
|
39
|
+
- This is a **non-breaking change** - existing code works the same, just cleaner
|
|
40
|
+
|
|
8
41
|
## [0.1.19] - 2025-11-10
|
|
9
42
|
|
|
10
43
|
### Added - Major UX Improvements and AI Model Detection 🚀
|
|
@@ -427,3 +460,36 @@ None - all changes are backward compatible.
|
|
|
427
460
|
- Initial project setup
|
|
428
461
|
- Basic project structure
|
|
429
462
|
- Build configuration
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
### Changed
|
|
466
|
+
- Improved SlideViewer component cleanup and error handling
|
|
467
|
+
- Enhanced AnnotationManager state management to prevent infinite loops
|
|
468
|
+
|
|
469
|
+
### Fixed
|
|
470
|
+
- Fixed `_transformBounds` error in consuming applications
|
|
471
|
+
- Fixed race conditions in annotation state updates
|
|
472
|
+
- Fixed loading state not clearing properly in AnnotationManager
|
|
473
|
+
- Fixed annotation rendering issues when toggling visibility
|
|
474
|
+
|
|
475
|
+
## [0.1.11] - 2025-11-04
|
|
476
|
+
|
|
477
|
+
### Added
|
|
478
|
+
- SlideViewer component with OpenSeadragon integration
|
|
479
|
+
- AnnotationManager component for DSA annotations
|
|
480
|
+
- FolderBrowser component for navigating DSA resources
|
|
481
|
+
- Annotation caching system (Memory and IndexedDB)
|
|
482
|
+
- Button and Card components
|
|
483
|
+
|
|
484
|
+
### Changed
|
|
485
|
+
- Initial component library setup
|
|
486
|
+
- Added TypeScript support
|
|
487
|
+
- Configured Vite build system
|
|
488
|
+
- Set up Storybook for component documentation
|
|
489
|
+
|
|
490
|
+
## [0.1.0] - 2025-11-01
|
|
491
|
+
|
|
492
|
+
### Added
|
|
493
|
+
- Initial project setup
|
|
494
|
+
- Basic project structure
|
|
495
|
+
- Build configuration
|
package/CURSOR_INTEGRATION.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# bdsa-react-components - CURSOR Integration Guide
|
|
2
2
|
|
|
3
|
-
**Version:** 0.1.
|
|
3
|
+
**Version:** 0.1.22 | **Generated:** 2025-11-19T15:48:44.677Z
|
|
4
4
|
|
|
5
5
|
> This document provides everything Cursor needs to integrate and use the bdsa-react-components library.
|
|
6
6
|
> Copy this entire document into your project's .cursorrules or docs folder.
|
|
@@ -42,7 +42,7 @@ npm run build
|
|
|
42
42
|
### Import
|
|
43
43
|
|
|
44
44
|
```tsx
|
|
45
|
-
import { AnnotationManager, Button, Card, DsaAuthManager, FolderBrowser, SlideViewer } from 'bdsa-react-components'
|
|
45
|
+
import { AnnotationManager, Button, Card, DsaAuthManager, FolderBrowser, FolderThumbnailBrowser, SlideViewer, ThumbnailGrid, ThumbnailViewer } from 'bdsa-react-components'
|
|
46
46
|
import 'bdsa-react-components/styles.css'
|
|
47
47
|
```
|
|
48
48
|
|
|
@@ -120,6 +120,40 @@ FolderBrowser component
|
|
|
120
120
|
- `GET /collection` - List collections
|
|
121
121
|
- `GET /folder?parentType={type}&parentId={id}` - List folders
|
|
122
122
|
|
|
123
|
+
### FolderThumbnailBrowser
|
|
124
|
+
|
|
125
|
+
Size presets for thumbnails
|
|
126
|
+
|
|
127
|
+
**Example:**
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
<FolderThumbnailBrowser
|
|
131
|
+
apiBaseUrl="http://bdsa.pathology.emory.edu:8080/api/v1"
|
|
132
|
+
folderId="6903df87d26a6d93de19a9b0"
|
|
133
|
+
viewerSize="l"
|
|
134
|
+
itemsPerPage={12}
|
|
135
|
+
showViewerControls={false}
|
|
136
|
+
selectedAnnotationName="Gray White Segmentation"
|
|
137
|
+
annotationOpacity={0.7}
|
|
138
|
+
onAnnotationOpacityChange={(opacity) => console.log(opacity)}
|
|
139
|
+
/>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Features:**
|
|
143
|
+
|
|
144
|
+
- Displays thumbnails using OpenSeadragon (full viewer with zoom/pan)
|
|
145
|
+
- Supports annotation overlays with opacity control
|
|
146
|
+
- Automatic pagination based on container size
|
|
147
|
+
- Size presets: 's' (120px), 'm' (180px), 'l' (240px), 'xl' (320px)
|
|
148
|
+
- Authentication via `apiHeaders` or `fetchFn`
|
|
149
|
+
- Token query parameter support via `tokenQueryParam` prop
|
|
150
|
+
|
|
151
|
+
**API Endpoints:**
|
|
152
|
+
|
|
153
|
+
- `GET /item?folderId={id}` - Fetch items from folder
|
|
154
|
+
- `GET /item/{id}/tiles/dzi.dzi` - DZI descriptor for thumbnail
|
|
155
|
+
- `GET /annotation?itemId={id}` - Fetch annotations for item
|
|
156
|
+
|
|
123
157
|
### SlideViewer
|
|
124
158
|
|
|
125
159
|
A slide viewer component that integrates OpenSeadragon with Paper.js annotations for viewing Digital Slide Archive images with annotation overlays.
|
|
@@ -140,6 +174,42 @@ A slide viewer component that integrates OpenSeadragon with Paper.js annotations
|
|
|
140
174
|
|
|
141
175
|
- `GET /annotation/{id}` - Fetch annotation document by ID
|
|
142
176
|
|
|
177
|
+
### ThumbnailGrid
|
|
178
|
+
|
|
179
|
+
Size presets for thumbnails
|
|
180
|
+
|
|
181
|
+
**Example:**
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
<ThumbnailGrid
|
|
185
|
+
apiBaseUrl="http://bdsa.pathology.emory.edu:8080/api/v1"
|
|
186
|
+
folderId="6903df87d26a6d93de19a9b0"
|
|
187
|
+
thumbnailSize="l"
|
|
188
|
+
itemsPerPage={12}
|
|
189
|
+
tokenQueryParam={true}
|
|
190
|
+
apiHeaders={{ 'Girder-Token': token }}
|
|
191
|
+
onThumbnailClick={(item) => console.log(item)}
|
|
192
|
+
/>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Features:**
|
|
196
|
+
|
|
197
|
+
- Lightweight thumbnail grid (static images, no OpenSeadragon)
|
|
198
|
+
- Faster loading for simple thumbnail browsing
|
|
199
|
+
- Automatic pagination based on container size
|
|
200
|
+
- Size presets: 's' (120px), 'm' (180px), 'l' (240px), 'xl' (320px)
|
|
201
|
+
- Thumbnail URLs include `?width={size}` for optimized loading
|
|
202
|
+
- Authentication via `apiHeaders` with optional `tokenQueryParam`
|
|
203
|
+
|
|
204
|
+
**API Endpoints:**
|
|
205
|
+
|
|
206
|
+
- `GET /item?folderId={id}` - Fetch items from folder
|
|
207
|
+
- `GET /item/{id}/tiles/thumbnail?width={size}&token={token}` - Thumbnail image
|
|
208
|
+
|
|
209
|
+
### ThumbnailViewer
|
|
210
|
+
|
|
211
|
+
Individual thumbnail component that wraps SlideViewer for displaying a single DSA item with optional annotation overlay.
|
|
212
|
+
|
|
143
213
|
## Type Definitions
|
|
144
214
|
|
|
145
215
|
Import types:
|
|
@@ -161,24 +231,14 @@ import type {
|
|
|
161
231
|
Item as FolderBrowserItem,
|
|
162
232
|
Resource,
|
|
163
233
|
DsaAuthManagerProps,
|
|
234
|
+
FolderThumbnailBrowserProps,
|
|
235
|
+
ThumbnailViewerProps,
|
|
236
|
+
ThumbnailGridProps,
|
|
164
237
|
} from 'bdsa-react-components'
|
|
165
238
|
```
|
|
166
239
|
|
|
167
240
|
### Key Types
|
|
168
241
|
|
|
169
|
-
**SlideImageInfo:**
|
|
170
|
-
```typescript
|
|
171
|
-
interface SlideImageInfo {
|
|
172
|
-
imageId?: string | number
|
|
173
|
-
width?: number
|
|
174
|
-
height?: number
|
|
175
|
-
tileWidth?: number
|
|
176
|
-
levels?: number
|
|
177
|
-
baseUrl?: string
|
|
178
|
-
http: //bdsa.pathology.emory.edu:8080/api/v1/item/{itemId
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
242
|
## Authentication
|
|
183
243
|
|
|
184
244
|
Components making API calls (`SlideViewer`, `AnnotationManager`, `FolderBrowser`) support auth via:
|
|
@@ -1,190 +1,7 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
+
import { AnnotationSearchResult, AnnotationManagerProps, AnnotationManagerHandle, AnnotationManagerContext } from './AnnotationManager.types';
|
|
2
3
|
|
|
3
|
-
export
|
|
4
|
-
_id: string;
|
|
5
|
-
_modelType: string;
|
|
6
|
-
_elementCount?: number;
|
|
7
|
-
_detailsCount?: number;
|
|
8
|
-
_version?: number;
|
|
9
|
-
_accessLevel?: number;
|
|
10
|
-
itemId?: string;
|
|
11
|
-
public?: boolean;
|
|
12
|
-
created?: string;
|
|
13
|
-
updated?: string;
|
|
14
|
-
creatorId?: string;
|
|
15
|
-
updatedId?: string;
|
|
16
|
-
groups?: (string | null)[];
|
|
17
|
-
annotation?: {
|
|
18
|
-
name?: string;
|
|
19
|
-
description?: string;
|
|
20
|
-
attributes?: Record<string, unknown>;
|
|
21
|
-
display?: Record<string, unknown>;
|
|
22
|
-
};
|
|
23
|
-
[key: string]: unknown;
|
|
24
|
-
}
|
|
25
|
-
export interface AnnotationManagerProps {
|
|
26
|
-
/** Image/Item ID to search annotations for */
|
|
27
|
-
imageId?: string;
|
|
28
|
-
/** Base URL for DSA API (e.g., http://bdsa.pathology.emory.edu:8080/api/v1) */
|
|
29
|
-
apiBaseUrl?: string;
|
|
30
|
-
/** Maximum number of annotations to fetch per request (default: 50) */
|
|
31
|
-
limit?: number;
|
|
32
|
-
/** Custom fetch function for API requests. Useful for adding authentication headers. */
|
|
33
|
-
fetchFn?: (url: string, options?: RequestInit) => Promise<Response>;
|
|
34
|
-
/** Custom headers to add to all API requests. Merged with fetchFn headers if both are provided. */
|
|
35
|
-
apiHeaders?: HeadersInit;
|
|
36
|
-
/** Callback when annotations are loaded */
|
|
37
|
-
onAnnotationsLoaded?: (annotations: AnnotationSearchResult[]) => void;
|
|
38
|
-
/** Callback when annotation loading fails */
|
|
39
|
-
onError?: (error: Error) => void;
|
|
40
|
-
/** Show debug panel with raw API response (default: false, hidden in production) */
|
|
41
|
-
showDebugPanel?: boolean;
|
|
42
|
-
/** Callback when annotation is loaded/unloaded */
|
|
43
|
-
onAnnotationLoadChange?: (annotationId: string, loaded: boolean) => void;
|
|
44
|
-
/** Callback when annotation visibility is toggled */
|
|
45
|
-
onAnnotationVisibilityChange?: (annotationId: string, visible: boolean) => void;
|
|
46
|
-
/** Callback when annotation opacity changes */
|
|
47
|
-
onAnnotationOpacityChange?: (annotationId: string, opacity: number) => void;
|
|
48
|
-
/** Callback when annotation has finished loading and is ready (called by SlideViewer after rendering) */
|
|
49
|
-
onAnnotationReady?: (annotationId: string) => void;
|
|
50
|
-
/**
|
|
51
|
-
* Callback from SlideViewer that should be called when annotations are ready.
|
|
52
|
-
* This simplifies integration - just pass the same callback function to both
|
|
53
|
-
* AnnotationManager and SlideViewer. AnnotationManager will handle forwarding
|
|
54
|
-
* internally to clear loading states.
|
|
55
|
-
*
|
|
56
|
-
* Use this instead of the render prop pattern for simpler integration.
|
|
57
|
-
*/
|
|
58
|
-
slideViewerOnAnnotationReady?: (annotationId: string | number) => void;
|
|
59
|
-
/**
|
|
60
|
-
* Callback fired whenever the list of loaded annotation IDs changes.
|
|
61
|
-
* This is called when:
|
|
62
|
-
* - User clicks "Load" on an annotation
|
|
63
|
-
* - User clicks "Hide" on an annotation
|
|
64
|
-
* - Annotations are unloaded
|
|
65
|
-
*
|
|
66
|
-
* @param annotationIds - Array of currently loaded annotation IDs
|
|
67
|
-
*/
|
|
68
|
-
onLoadedAnnotationIdsChange?: (annotationIds: string[]) => void;
|
|
69
|
-
/**
|
|
70
|
-
* Callback fired when an individual annotation is loaded.
|
|
71
|
-
* Useful for tracking which specific annotation was just loaded.
|
|
72
|
-
*
|
|
73
|
-
* @param annotationId - The ID of the annotation that was loaded
|
|
74
|
-
* @param annotationData - The full annotation document (optional, for performance)
|
|
75
|
-
*/
|
|
76
|
-
onAnnotationLoad?: (annotationId: string, annotationData?: unknown) => void;
|
|
77
|
-
/**
|
|
78
|
-
* Callback fired when an individual annotation is hidden/unloaded.
|
|
79
|
-
*
|
|
80
|
-
* @param annotationId - The ID of the annotation that was hidden
|
|
81
|
-
*/
|
|
82
|
-
onAnnotationHide?: (annotationId: string) => void;
|
|
83
|
-
/**
|
|
84
|
-
* Callback fired whenever annotation state changes.
|
|
85
|
-
* Provides complete state snapshot - annotation IDs, opacities, visibility, etc.
|
|
86
|
-
* This is the primary way to sync with SlideViewer and eliminates the need for
|
|
87
|
-
* multiple individual callbacks.
|
|
88
|
-
*
|
|
89
|
-
* This callback fires whenever:
|
|
90
|
-
* - An annotation is loaded/unloaded
|
|
91
|
-
* - Annotation opacity changes
|
|
92
|
-
* - Annotation visibility changes
|
|
93
|
-
*
|
|
94
|
-
* @param state - Complete annotation state snapshot
|
|
95
|
-
*/
|
|
96
|
-
onAnnotationStateChange?: (state: {
|
|
97
|
-
/** Array of currently loaded annotation IDs */
|
|
98
|
-
loadedAnnotationIds: string[];
|
|
99
|
-
/** Map of annotation ID -> opacity (0.0 to 1.0) */
|
|
100
|
-
opacities: Map<string, number>;
|
|
101
|
-
/** Map of annotation ID -> visibility (true = visible, false = hidden) */
|
|
102
|
-
visibility: Map<string, boolean>;
|
|
103
|
-
/** Callback function that should be passed to SlideViewer's onAnnotationReady prop.
|
|
104
|
-
* This automatically clears loading states in AnnotationManager when called. */
|
|
105
|
-
onAnnotationReady?: (annotationId: string | number) => void;
|
|
106
|
-
}) => void;
|
|
107
|
-
/**
|
|
108
|
-
* Callback fired whenever any annotation opacity changes.
|
|
109
|
-
* Provides complete map of all opacities - convenience alternative to individual callbacks.
|
|
110
|
-
*
|
|
111
|
-
* This is a convenience callback. For complete state sync, use `onAnnotationStateChange` instead.
|
|
112
|
-
*
|
|
113
|
-
* @param opacities - Map of all annotation ID -> opacity values
|
|
114
|
-
*/
|
|
115
|
-
onAnnotationOpacitiesChange?: (opacities: Map<string, number>) => void;
|
|
116
|
-
/**
|
|
117
|
-
* Callback fired whenever annotation headers change.
|
|
118
|
-
* Provides a map of annotation ID -> header document.
|
|
119
|
-
*
|
|
120
|
-
* This eliminates the need to extract headers from the render prop pattern.
|
|
121
|
-
* Use this to automatically sync annotationHeaders to SlideViewer.
|
|
122
|
-
*
|
|
123
|
-
* @param headers - Map of annotation ID -> annotation header document
|
|
124
|
-
*/
|
|
125
|
-
onAnnotationHeadersChange?: (headers: Map<string | number, AnnotationSearchResult>) => void;
|
|
126
|
-
/** Map of annotation IDs to their loaded state */
|
|
127
|
-
loadedAnnotations?: Set<string>;
|
|
128
|
-
/** Map of annotation IDs to their visibility state */
|
|
129
|
-
visibleAnnotations?: Map<string, boolean>;
|
|
130
|
-
/** Map of annotation IDs to their opacity (0-1) */
|
|
131
|
-
annotationOpacities?: Map<string, number>;
|
|
132
|
-
/** Optional cache instance to check if annotations are cached locally. If not provided, automatically creates an IndexedDBAnnotationCache.
|
|
133
|
-
* Set to `null` to disable caching. If provided, will show a cache indicator icon when annotations are cached. */
|
|
134
|
-
annotationCache?: {
|
|
135
|
-
has(annotationId: string | number, versionHash?: string): Promise<boolean>;
|
|
136
|
-
delete?(annotationId: string | number): Promise<void>;
|
|
137
|
-
} | null;
|
|
138
|
-
/** If true, disables caching entirely (equivalent to annotationCache={null}). Useful for debugging or forcing fresh fetches. */
|
|
139
|
-
disableCache?: boolean;
|
|
140
|
-
/** Show default vertical UI (default: true). Set to false to use custom render prop. */
|
|
141
|
-
showDefaultUI?: boolean;
|
|
142
|
-
className?: string;
|
|
143
|
-
children?: React.ReactNode | ((context: {
|
|
144
|
-
annotations: AnnotationSearchResult[];
|
|
145
|
-
loading: boolean;
|
|
146
|
-
error: Error | null;
|
|
147
|
-
annotationIds: string[];
|
|
148
|
-
loadedAnnotations: Set<string>;
|
|
149
|
-
visibleAnnotations: Map<string, boolean>;
|
|
150
|
-
annotationOpacities: Map<string, number>;
|
|
151
|
-
toggleLoad: (annotationId: string) => void;
|
|
152
|
-
toggleVisibility: (annotationId: string) => void;
|
|
153
|
-
setOpacity: (annotationId: string, opacity: number) => void;
|
|
154
|
-
onAnnotationReady: (annotationId: string | number) => void;
|
|
155
|
-
}) => React.ReactNode);
|
|
156
|
-
/** If true, enables debug logging to console. Default: false */
|
|
157
|
-
debug?: boolean;
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Imperative handle interface for AnnotationManager.
|
|
161
|
-
* Allows parent components to query annotation state programmatically.
|
|
162
|
-
*/
|
|
163
|
-
export interface AnnotationManagerHandle {
|
|
164
|
-
/** Get all available annotations */
|
|
165
|
-
getAnnotations: () => AnnotationSearchResult[];
|
|
166
|
-
/** Get annotation by ID */
|
|
167
|
-
getAnnotation: (id: string) => AnnotationSearchResult | undefined;
|
|
168
|
-
/** Get all loaded annotation IDs */
|
|
169
|
-
getLoadedAnnotationIds: () => string[];
|
|
170
|
-
/** Check if an annotation is loaded */
|
|
171
|
-
isAnnotationLoaded: (id: string) => boolean;
|
|
172
|
-
/** Check if an annotation is visible */
|
|
173
|
-
isAnnotationVisible: (id: string) => boolean;
|
|
174
|
-
/** Get opacity for an annotation (0-1) */
|
|
175
|
-
getAnnotationOpacity: (id: string) => number;
|
|
176
|
-
/** Get loading state for an annotation */
|
|
177
|
-
isAnnotationLoading: (id: string) => boolean;
|
|
178
|
-
/** Get all visible annotation IDs */
|
|
179
|
-
getVisibleAnnotationIds: () => string[];
|
|
180
|
-
/** Get complete annotation state snapshot */
|
|
181
|
-
getAnnotationState: () => {
|
|
182
|
-
loadedAnnotationIds: string[];
|
|
183
|
-
opacities: Map<string, number>;
|
|
184
|
-
visibility: Map<string, boolean>;
|
|
185
|
-
loadingAnnotationIds: string[];
|
|
186
|
-
};
|
|
187
|
-
}
|
|
4
|
+
export type { AnnotationSearchResult, AnnotationManagerProps, AnnotationManagerHandle, AnnotationManagerContext };
|
|
188
5
|
/**
|
|
189
6
|
* AnnotationManager component for managing annotation loading, visibility, and state.
|
|
190
7
|
* This component handles the business logic for annotations while keeping SlideViewer
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnnotationManager.d.ts","sourceRoot":"","sources":["../../../src/components/AnnotationManager/AnnotationManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiF,MAAM,OAAO,CAAA;AAGrG,OAAO,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"AnnotationManager.d.ts","sourceRoot":"","sources":["../../../src/components/AnnotationManager/AnnotationManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiF,MAAM,OAAO,CAAA;AAGrG,OAAO,yBAAyB,CAAA;AAChC,OAAO,KAAK,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAA;AAElJ,YAAY,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,CAAA;AAEjH;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,wGAq2B7B,CAAA"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { IndexedDBAnnotationCache } from '../../cache';
|
|
3
|
+
|
|
4
|
+
export interface AnnotationSearchResult {
|
|
5
|
+
_id: string;
|
|
6
|
+
_modelType: string;
|
|
7
|
+
_elementCount?: number;
|
|
8
|
+
_detailsCount?: number;
|
|
9
|
+
_version?: number;
|
|
10
|
+
_accessLevel?: number;
|
|
11
|
+
itemId?: string;
|
|
12
|
+
public?: boolean;
|
|
13
|
+
created?: string;
|
|
14
|
+
updated?: string;
|
|
15
|
+
creatorId?: string;
|
|
16
|
+
updatedId?: string;
|
|
17
|
+
groups?: (string | null)[];
|
|
18
|
+
annotation?: {
|
|
19
|
+
name?: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
attributes?: Record<string, unknown>;
|
|
22
|
+
display?: Record<string, unknown>;
|
|
23
|
+
};
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
}
|
|
26
|
+
export interface AnnotationManagerProps {
|
|
27
|
+
/** Image/Item ID to search annotations for */
|
|
28
|
+
imageId?: string;
|
|
29
|
+
/** Base URL for DSA API (e.g., http://bdsa.pathology.emory.edu:8080/api/v1) */
|
|
30
|
+
apiBaseUrl?: string;
|
|
31
|
+
/** Maximum number of annotations to fetch per request (default: 50) */
|
|
32
|
+
limit?: number;
|
|
33
|
+
/** Custom fetch function for API requests. Useful for adding authentication headers. */
|
|
34
|
+
fetchFn?: (url: string, options?: RequestInit) => Promise<Response>;
|
|
35
|
+
/** Custom headers to add to all API requests. Merged with fetchFn headers if both are provided. */
|
|
36
|
+
apiHeaders?: HeadersInit;
|
|
37
|
+
/** Callback when annotations are loaded */
|
|
38
|
+
onAnnotationsLoaded?: (annotations: AnnotationSearchResult[]) => void;
|
|
39
|
+
/** Callback when annotation loading fails */
|
|
40
|
+
onError?: (error: Error) => void;
|
|
41
|
+
/** Show debug panel with raw API response (default: false, hidden in production) */
|
|
42
|
+
showDebugPanel?: boolean;
|
|
43
|
+
/** Callback when annotation is loaded/unloaded */
|
|
44
|
+
onAnnotationLoadChange?: (annotationId: string, loaded: boolean) => void;
|
|
45
|
+
/** Callback when annotation visibility is toggled */
|
|
46
|
+
onAnnotationVisibilityChange?: (annotationId: string, visible: boolean) => void;
|
|
47
|
+
/** Callback when annotation opacity changes */
|
|
48
|
+
onAnnotationOpacityChange?: (annotationId: string, opacity: number) => void;
|
|
49
|
+
/** Callback when annotation is ready (fully rendered) */
|
|
50
|
+
onAnnotationReady?: (annotationId: string) => void;
|
|
51
|
+
/** Callback for SlideViewer's onAnnotationReady (internal use) */
|
|
52
|
+
slideViewerOnAnnotationReady?: (annotationId: string | number) => void;
|
|
53
|
+
/** Callback when loaded annotation IDs change */
|
|
54
|
+
onLoadedAnnotationIdsChange?: (annotationIds: string[]) => void;
|
|
55
|
+
/** Callback when annotation is loaded */
|
|
56
|
+
onAnnotationLoad?: (annotationId: string) => void;
|
|
57
|
+
/** Callback when annotation is hidden */
|
|
58
|
+
onAnnotationHide?: (annotationId: string) => void;
|
|
59
|
+
/** Unified callback for annotation state changes */
|
|
60
|
+
onAnnotationStateChange?: (state: {
|
|
61
|
+
loadedAnnotationIds: string[];
|
|
62
|
+
opacities: Map<string, number>;
|
|
63
|
+
visibility: Map<string, boolean>;
|
|
64
|
+
onAnnotationReady?: (id: string | number) => void;
|
|
65
|
+
}) => void;
|
|
66
|
+
/** Callback when annotation opacities change */
|
|
67
|
+
onAnnotationOpacitiesChange?: (opacities: Map<string, number>) => void;
|
|
68
|
+
/** Callback when annotation headers change */
|
|
69
|
+
onAnnotationHeadersChange?: (headers: Map<string | number, AnnotationSearchResult>) => void;
|
|
70
|
+
/** External state: loaded annotation IDs */
|
|
71
|
+
loadedAnnotations?: Set<string>;
|
|
72
|
+
/** External state: visible annotation IDs */
|
|
73
|
+
visibleAnnotations?: Map<string, boolean>;
|
|
74
|
+
/** External state: annotation opacities */
|
|
75
|
+
annotationOpacities?: Map<string, number>;
|
|
76
|
+
/** External annotation cache */
|
|
77
|
+
annotationCache?: IndexedDBAnnotationCache | null;
|
|
78
|
+
/** Disable annotation caching (default: false) */
|
|
79
|
+
disableCache?: boolean;
|
|
80
|
+
/** Show default UI (default: true) */
|
|
81
|
+
showDefaultUI?: boolean;
|
|
82
|
+
/** Custom CSS class name */
|
|
83
|
+
className?: string;
|
|
84
|
+
/** Custom render function (render prop) */
|
|
85
|
+
children?: ((context: AnnotationManagerContext) => React.ReactNode) | React.ReactNode;
|
|
86
|
+
/** If true, enables debug logging to console. Default: false */
|
|
87
|
+
debug?: boolean;
|
|
88
|
+
}
|
|
89
|
+
export interface AnnotationManagerContext {
|
|
90
|
+
annotations: AnnotationSearchResult[];
|
|
91
|
+
loading: boolean;
|
|
92
|
+
error: Error | null;
|
|
93
|
+
annotationIds: string[];
|
|
94
|
+
loadedAnnotations: Set<string>;
|
|
95
|
+
visibleAnnotations: Map<string, boolean>;
|
|
96
|
+
annotationOpacities: Map<string, number>;
|
|
97
|
+
toggleLoad: (annotationId: string) => void;
|
|
98
|
+
toggleVisibility: (annotationId: string) => void;
|
|
99
|
+
setOpacity: (annotationId: string, opacity: number) => void;
|
|
100
|
+
handleAnnotationReady: (id: string | number) => void;
|
|
101
|
+
onAnnotationReady: (id: string | number) => void;
|
|
102
|
+
loadingAnnotations: Set<string>;
|
|
103
|
+
}
|
|
104
|
+
export interface AnnotationManagerHandle {
|
|
105
|
+
getAnnotations: () => AnnotationSearchResult[];
|
|
106
|
+
getAnnotation: (id: string) => AnnotationSearchResult | undefined;
|
|
107
|
+
getLoadedAnnotationIds: () => string[];
|
|
108
|
+
isAnnotationLoaded: (id: string) => boolean;
|
|
109
|
+
isAnnotationVisible: (id: string) => boolean;
|
|
110
|
+
getAnnotationOpacity: (id: string) => number;
|
|
111
|
+
isAnnotationLoading: (id: string) => boolean;
|
|
112
|
+
getVisibleAnnotationIds: () => string[];
|
|
113
|
+
getAnnotationState: () => {
|
|
114
|
+
loadedAnnotationIds: string[];
|
|
115
|
+
opacities: Map<string, number>;
|
|
116
|
+
visibility: Map<string, boolean>;
|
|
117
|
+
loadingAnnotationIds: string[];
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=AnnotationManager.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnnotationManager.types.d.ts","sourceRoot":"","sources":["../../../src/components/AnnotationManager/AnnotationManager.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,122 +1,7 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
+
import { Collection, Folder, Item, Resource, FolderBrowserProps } from './FolderBrowser.types';
|
|
2
3
|
|
|
3
|
-
export
|
|
4
|
-
_id: string;
|
|
5
|
-
name: string;
|
|
6
|
-
description?: string;
|
|
7
|
-
public?: boolean;
|
|
8
|
-
created?: string;
|
|
9
|
-
updated?: string;
|
|
10
|
-
[key: string]: unknown;
|
|
11
|
-
}
|
|
12
|
-
export interface Folder {
|
|
13
|
-
_id: string;
|
|
14
|
-
name: string;
|
|
15
|
-
description?: string;
|
|
16
|
-
public?: boolean;
|
|
17
|
-
created?: string;
|
|
18
|
-
updated?: string;
|
|
19
|
-
parentId?: string;
|
|
20
|
-
parentType?: 'collection' | 'folder';
|
|
21
|
-
[key: string]: unknown;
|
|
22
|
-
}
|
|
23
|
-
export interface Item {
|
|
24
|
-
_id: string;
|
|
25
|
-
name: string;
|
|
26
|
-
description?: string;
|
|
27
|
-
folderId?: string;
|
|
28
|
-
collectionId?: string;
|
|
29
|
-
public?: boolean;
|
|
30
|
-
created?: string;
|
|
31
|
-
updated?: string;
|
|
32
|
-
[key: string]: unknown;
|
|
33
|
-
}
|
|
34
|
-
export type Resource = (Collection | Folder | Item) & {
|
|
35
|
-
type: 'collection' | 'folder' | 'item';
|
|
36
|
-
};
|
|
37
|
-
export interface FolderBrowserProps {
|
|
38
|
-
/** Base URL for DSA API (e.g., http://bdsa.pathology.emory.edu:8080/api/v1) */
|
|
39
|
-
apiBaseUrl?: string;
|
|
40
|
-
/** Custom fetch function for API requests. Useful for adding authentication headers. */
|
|
41
|
-
fetchFn?: (url: string, options?: RequestInit) => Promise<Response>;
|
|
42
|
-
/** Custom headers to add to all API requests. Merged with fetchFn headers if both are provided. */
|
|
43
|
-
apiHeaders?: HeadersInit;
|
|
44
|
-
/** Callback when a resource (collection or folder) is selected */
|
|
45
|
-
onResourceSelect?: (resource: Resource) => void;
|
|
46
|
-
/** Callback when resource selection changes */
|
|
47
|
-
onSelectionChange?: (resource: Resource | null) => void;
|
|
48
|
-
/** Show collections at the root level (default: true, ignored if rootId is provided) */
|
|
49
|
-
showCollections?: boolean;
|
|
50
|
-
/** Root directory ID to start from (if provided, only shows this collection/folder and its children) */
|
|
51
|
-
rootId?: string;
|
|
52
|
-
/** Type of root directory - 'collection' or 'folder' (required if rootId is provided) */
|
|
53
|
-
rootType?: 'collection' | 'folder';
|
|
54
|
-
/** Number of folders to load per page (default: 50, set to 0 to load all) */
|
|
55
|
-
foldersPerPage?: number;
|
|
56
|
-
/** Start at a specific collection ID instead of showing all collections (deprecated: use rootId and rootType) */
|
|
57
|
-
startCollectionId?: string;
|
|
58
|
-
/** Start at a specific folder ID (requires startCollectionId or parentFolderId) (deprecated: use rootId and rootType) */
|
|
59
|
-
startFolderId?: string;
|
|
60
|
-
/** Start at a folder's subfolder (requires parentFolderId) (deprecated: use rootId and rootType) */
|
|
61
|
-
parentFolderId?: string;
|
|
62
|
-
className?: string;
|
|
63
|
-
/** Custom render for collections */
|
|
64
|
-
renderCollection?: (collection: Collection, isExpanded: boolean, onToggle: () => void, itemCount?: number) => React.ReactNode;
|
|
65
|
-
/** Custom render for folders */
|
|
66
|
-
renderFolder?: (folder: Folder, depth: number, isExpanded: boolean, onToggle: () => void, itemCount?: number) => React.ReactNode;
|
|
67
|
-
/** If true, shows items (files) within folders and collections in the tree view. Default: false */
|
|
68
|
-
showItems?: boolean;
|
|
69
|
-
/** If true, fetches items from folders even if showItems is false. Useful for getting item counts or filtering. Default: value of showItems */
|
|
70
|
-
fetchItems?: boolean;
|
|
71
|
-
/** Number of items to load per page when items are fetched (default: 50, set to 0 to load all) */
|
|
72
|
-
itemsPerPage?: number;
|
|
73
|
-
/** Callback when an item is selected (only used when showItems is true) */
|
|
74
|
-
onItemSelect?: (item: Item) => void;
|
|
75
|
-
/** Custom render for items */
|
|
76
|
-
renderItem?: (item: Item, depth: number) => React.ReactNode;
|
|
77
|
-
/**
|
|
78
|
-
* Filter function for items. Called for each item fetched from API.
|
|
79
|
-
* Return true to include the item, false to exclude it.
|
|
80
|
-
* Receives the full Item object, so you can filter by name, extension, metadata, or any other property.
|
|
81
|
-
*
|
|
82
|
-
* ⚠️ IMPORTANT: This function must be stable (wrapped in useCallback) to prevent infinite re-renders.
|
|
83
|
-
*
|
|
84
|
-
* @example
|
|
85
|
-
* // Filter by extension
|
|
86
|
-
* const itemFilter = useCallback((item) => {
|
|
87
|
-
* return item.name.endsWith('.jpg') || item.name.endsWith('.png');
|
|
88
|
-
* }, []);
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* // Filter by metadata
|
|
92
|
-
* const itemFilter = useCallback((item) => {
|
|
93
|
-
* return item.meta?.type === 'model' && item.meta?.status === 'published';
|
|
94
|
-
* }, []);
|
|
95
|
-
*
|
|
96
|
-
* @example
|
|
97
|
-
* // Combine name and metadata filters
|
|
98
|
-
* const itemFilter = useCallback((item) => {
|
|
99
|
-
* const hasValidExtension = item.name.endsWith('.tif') || item.name.endsWith('.svs');
|
|
100
|
-
* const hasLargeImage = item.largeImage != null;
|
|
101
|
-
* return hasValidExtension && hasLargeImage;
|
|
102
|
-
* }, []);
|
|
103
|
-
*/
|
|
104
|
-
itemFilter?: (item: Item) => boolean;
|
|
105
|
-
/** Callback when items are fetched for a folder. Receives folder/collection ID and all fetched items (before filtering). */
|
|
106
|
-
onItemsFetched?: (folderId: string, items: Item[]) => void;
|
|
107
|
-
/** If true, shows item count next to folder/collection names. Default: false */
|
|
108
|
-
showItemCount?: boolean;
|
|
109
|
-
/** If true, persists the selected resource to localStorage and restores it on mount. Default: false */
|
|
110
|
-
persistSelection?: boolean;
|
|
111
|
-
/** Custom key for localStorage persistence. Default: 'bdsa_folder_browser_selection' */
|
|
112
|
-
persistSelectionKey?: string;
|
|
113
|
-
/** If true, persists the expansion state (which folders/collections are expanded) to localStorage and restores it on mount. Default: false */
|
|
114
|
-
persistExpansion?: boolean;
|
|
115
|
-
/** Custom key for localStorage expansion state persistence. Default: 'bdsa_folder_browser_expansion' */
|
|
116
|
-
persistExpansionKey?: string;
|
|
117
|
-
/** If true, enables debug logging to console. Default: false */
|
|
118
|
-
debug?: boolean;
|
|
119
|
-
}
|
|
4
|
+
export type { Collection, Folder, Item, Resource, FolderBrowserProps };
|
|
120
5
|
/**
|
|
121
6
|
* FolderBrowser component for browsing DSA collections and folders.
|
|
122
7
|
*
|