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.
Files changed (46) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/CURSOR_INTEGRATION.md +75 -15
  3. package/dist/components/AnnotationManager/AnnotationManager.d.ts +2 -185
  4. package/dist/components/AnnotationManager/AnnotationManager.d.ts.map +1 -1
  5. package/dist/components/AnnotationManager/AnnotationManager.types.d.ts +120 -0
  6. package/dist/components/AnnotationManager/AnnotationManager.types.d.ts.map +1 -0
  7. package/dist/components/FolderBrowser/FolderBrowser.d.ts +2 -117
  8. package/dist/components/FolderBrowser/FolderBrowser.d.ts.map +1 -1
  9. package/dist/components/FolderBrowser/FolderBrowser.render.d.ts +12 -0
  10. package/dist/components/FolderBrowser/FolderBrowser.render.d.ts.map +1 -0
  11. package/dist/components/FolderBrowser/FolderBrowser.types.d.ts +94 -0
  12. package/dist/components/FolderBrowser/FolderBrowser.types.d.ts.map +1 -0
  13. package/dist/components/FolderBrowser/FolderBrowser.utils.d.ts +34 -0
  14. package/dist/components/FolderBrowser/FolderBrowser.utils.d.ts.map +1 -0
  15. package/dist/components/FolderBrowser/useFolderBrowserDataFetching.d.ts +58 -0
  16. package/dist/components/FolderBrowser/useFolderBrowserDataFetching.d.ts.map +1 -0
  17. package/dist/components/FolderThumbnailBrowser/FolderThumbnailBrowser.d.ts +54 -0
  18. package/dist/components/FolderThumbnailBrowser/FolderThumbnailBrowser.d.ts.map +1 -0
  19. package/dist/components/SlideViewer/SlideViewer.d.ts +2 -171
  20. package/dist/components/SlideViewer/SlideViewer.d.ts.map +1 -1
  21. package/dist/components/SlideViewer/SlideViewer.types.d.ts +175 -0
  22. package/dist/components/SlideViewer/SlideViewer.types.d.ts.map +1 -0
  23. package/dist/components/SlideViewer/SlideViewer.utils.d.ts +46 -0
  24. package/dist/components/SlideViewer/SlideViewer.utils.d.ts.map +1 -0
  25. package/dist/components/SlideViewer/hooks/index.d.ts +5 -0
  26. package/dist/components/SlideViewer/hooks/index.d.ts.map +1 -0
  27. package/dist/components/SlideViewer/hooks/useAnnotationFetching.d.ts +23 -0
  28. package/dist/components/SlideViewer/hooks/useAnnotationFetching.d.ts.map +1 -0
  29. package/dist/components/SlideViewer/hooks/useAnnotationOpacity.d.ts +8 -0
  30. package/dist/components/SlideViewer/hooks/useAnnotationOpacity.d.ts.map +1 -0
  31. package/dist/components/SlideViewer/hooks/useAnnotationRendering.d.ts +14 -0
  32. package/dist/components/SlideViewer/hooks/useAnnotationRendering.d.ts.map +1 -0
  33. package/dist/components/SlideViewer/hooks/useSlideViewerInitialization.d.ts +21 -0
  34. package/dist/components/SlideViewer/hooks/useSlideViewerInitialization.d.ts.map +1 -0
  35. package/dist/components/ThumbnailGrid/ThumbnailGrid.d.ts +55 -0
  36. package/dist/components/ThumbnailGrid/ThumbnailGrid.d.ts.map +1 -0
  37. package/dist/components/ThumbnailViewer/ThumbnailViewer.d.ts +45 -0
  38. package/dist/components/ThumbnailViewer/ThumbnailViewer.d.ts.map +1 -0
  39. package/dist/index.cjs +71 -71
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.ts +6 -0
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +38955 -37886
  44. package/dist/index.js.map +1 -1
  45. package/dist/style.css +1 -1
  46. 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
@@ -1,6 +1,6 @@
1
1
  # bdsa-react-components - CURSOR Integration Guide
2
2
 
3
- **Version:** 0.1.20 | **Generated:** 2025-11-12T21:56:05.713Z
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 interface AnnotationSearchResult {
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":"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"}
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 interface Collection {
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
  *