bdsa-react-components 0.1.17 → 0.1.18
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 +25 -0
- package/CURSOR_INTEGRATION.md +1 -1
- package/dist/components/FolderBrowser/FolderBrowser.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +11 -11
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,31 @@ 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.17] - 2025-11-07
|
|
9
|
+
|
|
10
|
+
### Changed - UI Improvements
|
|
11
|
+
- **SlideViewer**: Reduced `min-height` from 400px to 128px for better flexibility in small layouts and embedded use cases
|
|
12
|
+
- **FolderBrowser**: Completely redesigned with compact tree-view pattern
|
|
13
|
+
- Replaced folder emoji icons (📁📂) with CSS triangle indicators (▶/▼) for open/closed state
|
|
14
|
+
- Replaced item emoji icon (📄) with minimal text-based icon for consistency
|
|
15
|
+
- Added hierarchy lines connecting parent/child nodes for better visual structure
|
|
16
|
+
- Optimized indentation: child triangles align with parent text (20px = icon 16px + margin 4px) for cleaner vertical alignment
|
|
17
|
+
- This creates a more compact tree structure where nested items don't progressively shift far to the right
|
|
18
|
+
- Significantly reduced padding and spacing throughout (4px instead of 12px)
|
|
19
|
+
- Smaller font sizes (13px body, 12px/11px for badges)
|
|
20
|
+
- Removed borders around collections and folders for flatter appearance
|
|
21
|
+
- More subtle hover states and selection indicators
|
|
22
|
+
- Cleaner "Load More" button styling
|
|
23
|
+
- Overall space savings: ~60% more compact vertically
|
|
24
|
+
|
|
25
|
+
### Technical Details
|
|
26
|
+
- Updated `SlideViewer.css` with new minimum heights
|
|
27
|
+
- Completely rewrote `FolderBrowser.css` with compact tree-view design
|
|
28
|
+
- Updated `FolderBrowser.tsx` to use CSS-based triangle icons instead of emoji
|
|
29
|
+
- Fixed item rendering to use correct `resource-item` CSS class
|
|
30
|
+
- Used CSS `::before` pseudo-elements for hierarchy lines and triangles
|
|
31
|
+
- All tests still passing (120/120)
|
|
32
|
+
|
|
8
33
|
## [0.1.16] - 2025-11-06
|
|
9
34
|
|
|
10
35
|
### Added
|
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.18 | **Generated:** 2025-11-07T17:41:53.997Z
|
|
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.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FolderBrowser.d.ts","sourceRoot":"","sources":["../../../src/components/FolderBrowser/FolderBrowser.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAA;AACvE,OAAO,qBAAqB,CAAA;AAE5B,MAAM,WAAW,UAAU;IACvB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,MAAM;IACnB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAA;IACpC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,IAAI;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACzB;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,UAAU,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG;IAAE,IAAI,EAAE,YAAY,GAAG,QAAQ,GAAG,MAAM,CAAA;CAAE,CAAA;AAEhG,MAAM,WAAW,kBAAkB;IAC/B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wFAAwF;IACxF,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IACnE,mGAAmG;IACnG,UAAU,CAAC,EAAE,WAAW,CAAA;IACxB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAA;IAC/C,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAA;IACvD,wFAAwF;IACxF,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,wGAAwG;IACxG,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yFAAyF;IACzF,QAAQ,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAA;IAClC,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iHAAiH;IACjH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,yHAAyH;IACzH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,oGAAoG;IACpG,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,KAAK,CAAC,SAAS,CAAA;IACzG,gCAAgC;IAChC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,KAAK,CAAC,SAAS,CAAA;IAC5G,oGAAoG;IACpG,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,qGAAqG;IACrG,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IACnC,8BAA8B;IAC9B,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAA;IAC3D,uGAAuG;IACvG,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,wFAAwF;IACxF,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,8IAA8I;IAC9I,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,wGAAwG;IACxG,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC/B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"FolderBrowser.d.ts","sourceRoot":"","sources":["../../../src/components/FolderBrowser/FolderBrowser.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAA;AACvE,OAAO,qBAAqB,CAAA;AAE5B,MAAM,WAAW,UAAU;IACvB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,MAAM;IACnB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAA;IACpC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,IAAI;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACzB;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,UAAU,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG;IAAE,IAAI,EAAE,YAAY,GAAG,QAAQ,GAAG,MAAM,CAAA;CAAE,CAAA;AAEhG,MAAM,WAAW,kBAAkB;IAC/B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wFAAwF;IACxF,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IACnE,mGAAmG;IACnG,UAAU,CAAC,EAAE,WAAW,CAAA;IACxB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAA;IAC/C,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAA;IACvD,wFAAwF;IACxF,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,wGAAwG;IACxG,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yFAAyF;IACzF,QAAQ,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAA;IAClC,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iHAAiH;IACjH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,yHAAyH;IACzH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,oGAAoG;IACpG,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,KAAK,CAAC,SAAS,CAAA;IACzG,gCAAgC;IAChC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,KAAK,CAAC,SAAS,CAAA;IAC5G,oGAAoG;IACpG,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,qGAAqG;IACrG,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IACnC,8BAA8B;IAC9B,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAA;IAC3D,uGAAuG;IACvG,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,wFAAwF;IACxF,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,8IAA8I;IAC9I,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,wGAAwG;IACxG,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC/B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,2FAklCzB,CAAA"}
|
package/dist/index.cjs
CHANGED
|
@@ -1749,5 +1749,5 @@ input[type=range] {
|
|
|
1749
1749
|
`+Re),q+=`
|
|
1750
1750
|
return module.exports;`;var Ie=jt.agent;if(p&&(Ie.chrome||Ie.firefox&&Ie.versionNumber<40)){var ge=p.createElement("script"),Pe=p.head||p.getElementsByTagName("head")[0];Ie.firefox&&(q=`
|
|
1751
1751
|
`+q),ge.appendChild(p.createTextNode("document.__paperscript__ = function("+oe+") {"+q+`
|
|
1752
|
-
}`)),Pe.appendChild(ge),pe=p.__paperscript__,delete p.__paperscript__,Pe.removeChild(ge)}else pe=Function(oe,q);var Re=pe&&pe.apply(Q,te),je=Re||{};return c.each(K,function(He){var Qe=je[He];Qe&&(H[He]=Qe)}),X&&(je.onResize&&X.setOnResize(je.onResize),X.emit("resize",{size:X.size,delta:new D}),je.onFrame&&X.setOnFrame(je.onFrame),X.requestUpdate()),Re}function z(q){if(/^text\/(?:x-|)paperscript$/.test(q.type)&&A.getAttribute(q,"ignore")!=="true"){var Q=A.getAttribute(q,"canvas"),G=p.getElementById(Q),X=q.src||q.getAttribute("data-src"),H=A.hasAttribute(q,"async"),K="data-paper-scope";if(!G)throw new Error('Unable to find canvas with id "'+Q+'"');var ie=A.get(G.getAttribute(K))||new A().setup(G);return G.setAttribute(K,ie._id),X?lt.request({url:X,async:H,mimeType:"text/plain",onLoad:function(oe){O(oe,ie,X)}}):O(q.innerHTML,ie,q.baseURI),q.setAttribute("data-paper-ignore","true"),ie}}function F(){c.each(p&&p.getElementsByTagName("script"),z)}function ee(q){return q?z(q):F()}return a&&(p.readyState==="complete"?setTimeout(F):Nt.add(a,{load:F})),{compile:N,execute:O,load:ee,parse:u,calculateBinary:T,calculateUnary:R}}).call(this);var jt=new(A.inject(c.exports,{Base:c,Numerical:j,Key:Mi,DomEvent:Nt,DomElement:si,document:p,window:a,Symbol:ct,PlacedSymbol:ni}));return jt.agent.node&&Zr(jt),typeof n=="function"&&n.amd?n("paper",jt):l&&(l.exports=jt),jt}).call(es,typeof self=="object"?self:null)})(as);var Gn=as.exports;const Va=ts(Gn),Ua=ia({__proto__:null,default:Va},[Gn]);function Bs(){if(!window.__paperJsPatchesApplied)try{if(!Ua||!Gn.View||!Gn.View.prototype){console.warn("[bdsa-react-components] Paper.js View not found, cannot apply patches");return}const l=Gn.View.prototype,w=l.getBounds;l.getBounds=function(){if(!this._transformBounds)return null;try{return w.call(this)}catch{return null}};const n=l.getCenter;l.getCenter=function(){if(!this._transformBounds)return null;try{return n.call(this)}catch{return null}};const a=l.setCenter;if(l.setCenter=function(...p){if(this._transformBounds)try{return a.apply(this,p)}catch{}},l._handleMouseEvent){const p=l._handleMouseEvent;l._handleMouseEvent=function(...c){if(this._transformBounds)try{return p.apply(this,c)}catch{}}}console.log("[bdsa-react-components] Applied Paper.js runtime patches"),window.__paperJsPatchesApplied=!0}catch(l){console.warn("[bdsa-react-components] Failed to apply Paper.js patches:",l)}}function Dr(l){if(!l||typeof l!="object")return!1;const w=l;return w.type==="FeatureCollection"&&Array.isArray(w.features)}function Ns(l){if(!l||typeof l!="object")return!1;const w=l;return!!(Array.isArray(w.elements)||w.annotation&&typeof w.annotation=="object"&&Array.isArray(w.annotation.elements))}function Ds(l){const w=l.geometry,n=l.properties||{},a=n.lineColor||n.stroke||"#ff0000",p=n.fillColor||n.fill||"rgba(255,0,0,0.3)",c=n.lineWidth||n["stroke-width"]||1,C=n.group||n.id,A=n.label||n.name;switch(w.type){case"Polygon":{const m=w.coordinates;if(!m||m.length===0)return null;const k=m[0];return!k||k.length<3?null:{type:"polyline",points:k.map(L=>[L[0],L[1]]),closed:!0,lineColor:String(a),fillColor:String(p),lineWidth:Number(c),group:C?String(C):void 0,label:A?String(A):void 0}}case"LineString":{const m=w.coordinates;return!m||m.length<2?null:{type:"polyline",points:m.map(k=>[k[0],k[1]]),closed:!1,lineColor:String(a),fillColor:String(p),lineWidth:Number(c),group:C?String(C):void 0,label:A?String(A):void 0}}case"Point":{const m=w.coordinates;if(!m||m.length<2)return null;const[k,L]=m,j=c*2||2,J=[];for(let D=0;D<8;D++){const fe=D/8*2*Math.PI;J.push([k+j*Math.cos(fe),L+j*Math.sin(fe)])}return{type:"polyline",points:J,closed:!0,lineColor:String(a),fillColor:String(p),lineWidth:Number(c),group:C?String(C):void 0,label:A?String(A):void 0}}case"MultiPolygon":case"MultiLineString":case"MultiPoint":return console.warn(`GeoJSON ${w.type} not yet supported, skipping feature`),null;default:return console.warn(`Unknown GeoJSON geometry type: ${w.type}`),null}}function Fs(l){const w=[];for(const n of l.features){const a=Ds(n);a&&w.push(a)}return w}function zs(l){var n;if(!l||typeof l!="object")return[];if(Dr(l))return console.log("Detected GeoJSON FeatureCollection format, transforming to DSA elements..."),Fs(l);const w=l;return w.elements&&Array.isArray(w.elements)?(console.log("Detected DSA format (root level elements)"),w.elements):(n=w.annotation)!=null&&n.elements&&Array.isArray(w.annotation.elements)?(console.log("Detected DSA format (nested annotation.elements)"),w.annotation.elements):(console.warn("Unknown annotation format, expected GeoJSON FeatureCollection or DSA format. Got:",{type:l.type,hasElements:"elements"in w,hasAnnotation:"annotation"in w,keys:Object.keys(l).slice(0,10)}),[])}function js(l){return!l||typeof l!="object"?"unknown":Dr(l)?"geojson":Ns(l)?"dsa":"unknown"}Bs();function Ga(l){const w={};if(l._id!==void 0&&(w._id=l._id),l._version!==void 0&&(w._version=l._version),l._modelType!==void 0&&(w._modelType=l._modelType),l.updated!==void 0&&(w.updated=l.updated),l.modified!==void 0&&(w.modified=l.modified),l._accessLevel!==void 0&&(w._accessLevel=l._accessLevel),l.annotation&&typeof l.annotation=="object"){const p=l.annotation;p.name!==void 0&&(w.name=p.name)}const n=JSON.stringify(w,Object.keys(w).sort());let a=5381;for(let p=0;p<n.length;p++)a=(a<<5)+a+n.charCodeAt(p),a=a&a;return(a>>>0).toString(16)}function Wa(l,w){if(l)return l;if(w)if(w instanceof Headers){const n=w.get("Authorization")||w.get("Girder-Token");if(n)return n.startsWith("Bearer ")?n.substring(7):n}else if(Array.isArray(w)){for(const[n,a]of w)if(n.toLowerCase()==="authorization"||n.toLowerCase()==="girder-token")return a.startsWith("Bearer ")?a.substring(7):a}else{const n=w,a=n.Authorization||n.authorization||n["Girder-Token"]||n["girder-token"];if(a)return a.startsWith("Bearer ")?a.substring(7):a}}function Sr(l,w){if(!w)return l;const n=l.includes("?")?"&":"?";return`${l}${n}token=${encodeURIComponent(w)}`}function In(l,w){const n=Math.max(0,Math.min(1,w));if(l.startsWith("rgba(")){const a=l.match(/(\d+(?:\.\d+)?)/g);if(a&&a.length>=3){const p=a[0],c=a[1],C=a[2];return`rgba(${p}, ${c}, ${C}, ${n})`}}else if(l.startsWith("rgb(")){const a=l.match(/(\d+(?:\.\d+)?)/g);if(a&&a.length>=3){const p=a[0],c=a[1],C=a[2];return`rgba(${p}, ${c}, ${C}, ${n})`}}else if(l.startsWith("#")){const a=l.replace("#","");let p,c,C;return a.length===3?(p=parseInt(a[0]+a[0],16),c=parseInt(a[1]+a[1],16),C=parseInt(a[2]+a[2],16)):(p=parseInt(a.substring(0,2),16),c=parseInt(a.substring(2,4),16),C=parseInt(a.substring(4,6),16)),`rgba(${p}, ${c}, ${C}, ${n})`}return l}const Vn={documentProperties:[{key:"id",label:"ID",formatter:l=>String(l)},{key:"elementCount",label:"Elements",formatter:l=>String(l)},{key:"totalPoints",label:"Points/Vertices",formatter:l=>String(l)},{key:"types",label:"Types",formatter:l=>Array.isArray(l)&&l.length>0?l.join(", "):"N/A",show:!0},{key:"filteredCount",label:"Filtered",formatter:(l,w)=>w.filteredCount!==void 0&&w.filteredCount>0?`${w.filteredCount} element(s) (${w.filteredPoints||0} points) skipped`:"None",show:!0}],showFetchedSection:!0,showProvidedSection:!0,showTotalSection:!0,headerText:"Annotation Information"},Hs=wt.forwardRef(({imageInfo:l,annotations:w=[],annotationIds:n=[],apiBaseUrl:a,onViewerReady:p,onAnnotationClick:c,defaultAnnotationColor:C="#ff0000",strokeWidth:A=2,osdOptions:m={},className:k="",height:L="600px",width:j="100%",showAnnotationInfo:J=!1,annotationInfoConfig:D,maxPointsPerAnnotation:fe=1e4,maxTotalPoints:le=1e5,fetchFn:$,apiHeaders:Ae,authToken:Xe,tokenQueryParam:Ve=!1,showAnnotationControls:Lt=!1,defaultAnnotationOpacity:vt=1,annotationOpacities:tt,visibleAnnotations:Kt,onAnnotationReady:Te,annotationCache:Jt,disableCache:At=!1,disableVisibilityCheck:ni=!1,annotationHeaders:ct},fi)=>{var o,u;const pt=wt.useRef(null),[ei,gt]=wt.useState(null),[Ut,mi]=wt.useState(null),[Xt,_i]=wt.useState(null),[Vi,ji]=wt.useState([]),[Yt,Li]=wt.useState([]),bt=wt.useRef(null),li=wt.useRef(""),[It,Di]=wt.useState(vt),si=wt.useMemo(()=>At||Jt===null?null:Jt||new Er,[Jt,At]),Nt=wt.useRef(!0);wt.useEffect(()=>(Nt.current=!0,()=>{Nt.current=!1}),[]);const[ui,Hi]=wt.useState(!ni);wt.useEffect(()=>{if(ni){Hi(!0);return}if(!pt.current)return;const f=new IntersectionObserver(v=>{v.forEach(b=>{b.isIntersecting&&b.intersectionRatio>.1?Hi(!0):Hi(!1)})},{threshold:.1,rootMargin:"50px"});return f.observe(pt.current),()=>{pt.current&&f.unobserve(pt.current)}},[ni]),wt.useEffect(()=>{const f=R=>{if(!R)return!1;const N=R instanceof Error?R.message:String(R);if(N&&typeof N=="string"){const O=N.toLowerCase();if(O.includes("_transformbounds")||O.includes("transformbounds")||O.includes("cannot read properties of null")||O.includes("reading '_transformbounds'")||O.includes('reading "_transformbounds"'))return!0}if(R instanceof Error&&R.stack){const O=R.stack.toLowerCase();if(O.includes("_transformbounds")||O.includes("transformbounds")||O.includes("getbounds"))return!0}if(R instanceof ErrorEvent){const O=R.filename||"";if(O.includes("osd-paperjs-annotation")||O.includes("annotation.js")){const z=R.message||String(R);if(z.includes("null")||z.includes("_transformBounds"))return!0}}return!1},v=R=>{const N=R instanceof ErrorEvent&&R.error||R;return f(N)?(R instanceof ErrorEvent&&(R.preventDefault(),R.stopPropagation()),!0):!1},b=R=>{const N=R.reason;return f(N)?(R.preventDefault(),R.stopPropagation(),!0):!1};window.addEventListener("error",v,!0),window.addEventListener("unhandledrejection",b,!0);const T=window.onerror;return window.onerror=(R,N,O,z,F)=>f(F)||f(R)?!0:T?T(R,N,O,z,F):!1,()=>{window.removeEventListener("error",v,!0),window.removeEventListener("unhandledrejection",b,!0),window.onerror=T}},[]);const Fi=wt.useCallback(f=>{if(!f||!f.view)return!1;const v=f.view;return!(v._transformBounds===null||v._transformBounds===void 0||typeof f.view.draw!="function")},[]),Ci=wt.useCallback(f=>{if(Nt.current){if(!Fi(f)){console.warn("Paper.js not fully initialized, skipping draw operation");return}try{f.view&&typeof f.view.draw=="function"&&f.view.draw()}catch(v){v instanceof Error&&v.message.includes("_transformBounds")?console.warn("Paper.js draw operation skipped (component likely unmounting or hidden)"):console.error("Error drawing Paper.js view:",v)}}},[Fi]),Mi=wt.useMemo(()=>Vi.map(f=>`${f.id}:${f.left}:${f.top}:${f.width}:${f.height}`).join("|"),[Vi]),ri=wt.useRef(`osd-viewer-${Math.random().toString(36).substr(2,9)}`),Z=wt.useRef(!1),_e=wt.useRef(""),Ge=wt.useRef(p);wt.useEffect(()=>{Ge.current=p},[p]);const lt=wt.useRef(c);wt.useEffect(()=>{lt.current=c},[c]);const st=wt.useMemo(()=>Wa(Xe,Ae),[Xe,Ae]),Rt=wt.useMemo(()=>{const f=$||fetch;return!Ve||!st?f:(v,b)=>{const T=Sr(v,st);return f(T,b)}},[$,st,Ve]),et=wt.useMemo(()=>{if(l.dziUrl)return Ve&&st?Sr(l.dziUrl,st):l.dziUrl},[l.dziUrl,st,Ve]),$t=wt.useMemo(()=>et||l.dziUrl||`${l.imageId}-${l.baseUrl}`,[et,l.dziUrl,l.imageId,l.baseUrl]),jt=wt.useMemo(()=>{var f;return Array.isArray(w)?JSON.stringify(w.map(v=>({id:v.id,left:v.left,top:v.top,width:v.width,height:v.height}))):w&&typeof w=="object"&&"type"in w&&w.type==="FeatureCollection"?JSON.stringify(((f=w.features)==null?void 0:f.map(v=>({id:v.id})))||[]):"[]"},[w]),t=wt.useMemo(()=>!Array.isArray(w)&&w&&typeof w=="object"&&"type"in w&&w.type==="FeatureCollection"?w.features.map(f=>{var v,b,T,R;if(f.geometry.type==="Polygon"){const N=f.geometry.coordinates[0];if(N.length>=4){const[O,z]=N[0],[F,,,ee]=N[2],q=F-O,Q=ee-z;return{id:f.id||((v=f.properties)==null?void 0:v.id),left:O,top:z,width:q,height:Q,color:((b=f.properties)==null?void 0:b.color)||C,group:(T=f.properties)==null?void 0:T.group,label:(R=f.properties)==null?void 0:R.label,...f.properties}}}return null}).filter(f=>f!==null):Array.isArray(w)?[...w]:[],[jt,C]);wt.useEffect(()=>{if(!pt.current||!ui&&!Z.current||Z.current)return;let f=null,v=null,b=null;const T=setTimeout(()=>{var R,N,O;if(!(!Nt.current||!pt.current)&&ui)try{Z.current=!0,_e.current=$t,pt.current.id=ri.current;const z={id:ri.current,prefixUrl:"https://openseadragon.github.io/openseadragon/images/",maxImageCacheCount:1e3,crossOriginPolicy:"Anonymous",autoHideControls:!1,debugMode:!1,showNavigator:!0,showZoomControl:!0,showHomeControl:!0,showFullPageControl:!0,...Ae?{ajaxHeaders:Ae}:{},...m};if(f=ra(z),v=f.createPaperOverlay(),Nt.current&&mi(v),b=new qr.AnnotationToolkit(f,{overlay:v}),b&&typeof((N=(R=b.overlay)==null?void 0:R.paperScope)==null?void 0:N.view)<"u"){const F=b.overlay.paperScope;if(F&&F.view){const ee=F.view,q=G=>{try{return G!=null&&typeof G._transformBounds<"u"&&G._transformBounds!==null}catch{return!1}},Q=new Proxy(ee,{get:(G,X)=>{var H;if(X==="getBounds"||X==="_transformBounds")return function(...K){var ie,oe;try{return!G||!q(G)?X==="getBounds"?{x:0,y:0,width:0,height:0}:null:X==="getBounds"?((ie=ee.getBounds)==null?void 0:ie.apply(G,K))||{x:0,y:0,width:0,height:0}:G[X]}catch(te){if(te instanceof Error){const pe=((oe=te.message)==null?void 0:oe.toLowerCase())||"";if(pe.includes("_transformbounds")||pe.includes("transformbounds")||pe.includes("cannot read properties of null"))return X==="getBounds"?{x:0,y:0,width:0,height:0}:null}throw te}};try{const K=G[X];return X==="_transformBounds"&&K==null?()=>({x:0,y:0,width:0,height:0}):K}catch(K){if(K instanceof Error){const ie=((H=K.message)==null?void 0:H.toLowerCase())||"";if(ie.includes("_transformbounds")||ie.includes("null"))return X==="_transformBounds"?()=>({x:0,y:0,width:0,height:0}):null}throw K}}});try{F.view=Q}catch{}}}if(Nt.current&&_i(b),!f)return;if(f.addHandler("open-failed",F=>{console.warn("OpenSeadragon: Open failed",F)}),f.addHandler("open",F=>{!Nt.current||!f||(console.log("OpenSeadragon: Image opened",F),gt(f),Ge.current&&Ge.current(f))}),f.world.addHandler("add-item",F=>{if(!Nt.current)return;const ee=F;console.log("Tiled image added:",ee.item),bt.current=ee.item}),et)f.open(et);else{if(!l.imageId||!l.width||!l.height||!l.tileWidth||!l.levels||!l.baseUrl){console.error("SlideViewer: If dziUrl is not provided, all manual fields (imageId, width, height, tileWidth, levels, baseUrl) are required");return}const F={width:l.width,height:l.height,tileSize:l.tileWidth,minLevel:0,maxLevel:l.levels-1,getTileUrl:(ee,q,Q)=>{const G=`${l.baseUrl}/wsi/files/tile/${l.imageId}/${ee}/${q}/${Q}`;return Ve&&st?Sr(G,st):G}};f&&f.addTiledImage({tileSource:F,success:()=>{!Nt.current||!f||(gt(f),Ge.current&&Ge.current(f))}})}}catch(z){if(console.error("Error initializing SlideViewer:",z),Z.current=!1,z instanceof Error&&((O=z.message)!=null&&O.toLowerCase().includes("_transformbounds")))return}},100);return()=>{clearTimeout(T);const R=$t!==_e.current;if(!Nt.current||R){if(R&&(_e.current=$t),b)try{b.destroy()}catch(O){console.warn("Error destroying annotation toolkit:",O)}if(v)try{v.destroy()}catch(O){console.warn("Error destroying paper overlay:",O)}if(f)try{if(typeof f.isDestroyed=="boolean"&&f.isDestroyed)return;f.destroy()}catch(O){console.warn("Error destroying OpenSeadragon viewer:",O)}Nt.current||(Z.current=!1)}}},[$t,m]),wt.useEffect(()=>{if(!Nt.current)return;if(!n||n.length===0||!a){ji(v=>v.length===0?v:[]),Li(v=>v.length===0?v:[]);return}(async()=>{try{console.log(`Fetching ${n.length} annotation(s) from DSA API...`);const v=Rt,b=n.map(async q=>{var oe,te,pe,Se,Ce,Ie;const Q=ct?ct instanceof Map?ct.get(q):ct[String(q)]:void 0,G=Q?Ga(Q):void 0;if(si){try{const ge=await si.get(q,G);if(ge!=null){if(ge&&typeof ge=="object"&&(ge.elements||((oe=ge.annotation)==null?void 0:oe.elements)||((te=ge.annotation)==null?void 0:te.elements)===null||Array.isArray((pe=ge.annotation)==null?void 0:pe.elements)))return console.log(`Cache hit for annotation ${q}${G?` (version hash: ${G})`:""}`,{hasElements:!!(ge!=null&&ge.elements)||!!((Se=ge==null?void 0:ge.annotation)!=null&&Se.elements),elementCount:Array.isArray(ge==null?void 0:ge.elements)?ge.elements.length:Array.isArray((Ce=ge==null?void 0:ge.annotation)==null?void 0:Ce.elements)?ge.annotation.elements.length:0}),ge;console.warn(`Invalid cached data format for annotation ${q}, clearing cache and fetching fresh...`,{type:typeof ge,keys:ge&&typeof ge=="object"?Object.keys(ge):"N/A",hasElements:!!(ge!=null&&ge.elements)||!!((Ie=ge==null?void 0:ge.annotation)!=null&&Ie.elements)}),await si.delete(q).catch(Re=>console.warn("Failed to delete invalid cache entry:",Re))}}catch(ge){console.warn(`Error reading from cache for annotation ${q}, fetching from API:`,ge)}console.log(G?`Cache miss or version mismatch for annotation ${q} (current version hash: ${G}), fetching from API...`:`Cache miss for annotation ${q}, fetching from API...`)}const X=`${a}/annotation/${q}`;console.log(`Fetching annotation ${q} from: ${X}`);const H={};Ae&&(H.headers=Ae);const K=await v(X,H);if(!K.ok)return console.warn(`Failed to fetch annotation ${q}:`,K.statusText,K.status),null;const ie=await K.json();return console.log(`Successfully fetched annotation ${q}:`,ie),si&&ie&&await si.set(q,ie,{versionHash:G}),ie}),T=await Promise.all(b);if(!Nt.current){console.log("Component unmounted during annotation fetch, skipping state update");return}const R=[];let N=0,O=0;const z=T.filter(q=>q!=null).map((q,Q)=>{const G=String(n[Q]),X=new Set,H=[];let K=0,ie=0,oe=0;const te=js(q);console.log(`Annotation ${G} format: ${te}`);const pe=zs(q);for(const Se of pe)if(Se&&typeof Se=="object"){const Ce=Se;if(Ce.type&&X.add(Ce.type),Ce.type==="rectangle"&&Ce.x!==void 0&&Ce.y!==void 0&&Ce.width!==void 0&&Ce.height!==void 0)4>fe?(ie++,oe+=4,console.warn(`Skipping rectangle annotation ${Ce.group||H.length} in document ${G}: has 4 points (exceeds limit of ${fe})`)):(K+=4,H.push({id:Ce.group||H.length,left:Ce.x,top:Ce.y,width:Ce.width,height:Ce.height,color:Ce.lineColor||C,group:Ce.group,label:Ce.label,annotationType:"rectangle",element:Ce,documentId:G}));else if(Ce.type==="polyline"&&Ce.points&&Ce.points.length>=2){const Ie=Ce.points.length;if(Ie>fe)ie++,oe+=Ie,console.warn(`Skipping polyline annotation ${Ce.group||H.length} in document ${G}: has ${Ie} points (exceeds limit of ${fe})`);else{K+=Ie;const ge=Ce.points.map(Mt=>Mt[0]),Pe=Ce.points.map(Mt=>Mt[1]),Re=Math.min(...ge),je=Math.min(...Pe),He=Math.max(...ge),Qe=Math.max(...Pe),_t=He-Re,Ot=Qe-je;H.push({id:Ce.group||H.length,left:Re,top:je,width:_t,height:Ot,color:Ce.lineColor||C,group:Ce.group,label:Ce.label,annotationType:"polyline",points:Ce.points,closed:Ce.closed,fillColor:Ce.fillColor,element:Ce,documentId:G})}}}return R.push({id:G,elementCount:H.length,totalPoints:K,types:Array.from(X),filteredCount:ie>0?ie:void 0,filteredPoints:oe>0?oe:void 0}),N+=ie,O+=oe,H}).flat();let F=z;const ee=z.reduce((q,Q)=>Q.annotationType==="polyline"&&Q.points?q+Q.points.length:q+4,0);if(ee>le){console.warn(`Total points (${ee}) exceeds limit (${le}). Filtering annotations starting from largest ones...`);const q=z.map(G=>({annotation:G,pointCount:G.annotationType==="polyline"&&G.points?G.points.length:4}));q.sort((G,X)=>X.pointCount-G.pointCount);let Q=0;F=[];for(const{annotation:G,pointCount:X}of q)Q+X<=le?(F.push(G),Q+=X):console.warn(`Skipping annotation ${G.id}: adding ${X} points would exceed total limit (${Q+X} > ${le})`);console.warn(`Filtered annotations: ${z.length} → ${F.length} (${z.length-F.length} skipped)`)}if(N>0&&console.warn(`Annotation document(s) ${n.join(", ")}: ${N} annotation(s) filtered due to per-annotation point limits (${O} total points skipped)`),console.log(`Parsed ${F.length} annotation feature(s) from ${n.length} annotation document(s)`),!Nt.current){console.log("Component unmounted after annotation parsing, skipping state update");return}ji(F),Li(R)}catch(v){console.error("Error fetching annotations:",v),Nt.current&&ji([])}})()},[n?JSON.stringify(n):"",a||"",C,fe,le,Rt,si,ct]),wt.useEffect(()=>{if(!ei||!Ut||!Xt)return;const f=Ut.paperScope;if(!f||!f.project)return;const v=bt.current;if(!v||typeof v.addPaperItem!="function")return;const b=[...t,...Vi],T=`${jt}:${Mi}`;if(li.current===T)return;if(li.current=T,console.log(`Rendering ${b.length} total annotation(s)`),b.length===0){try{const O=Xt.getFeatures();if(O&&Array.isArray(O))for(const z of O)try{z.remove()}catch(F){console.warn("Error removing feature:",F)}}catch(O){console.warn("Could not clear existing features:",O)}return}console.log(`About to render ${b.length} annotations, tiledImage:`,v);try{if(v.paperItems&&Array.isArray(v.paperItems)&&v.paperItems.length>0){const O=[...v.paperItems].reverse();for(const z of O)try{z&&typeof z.remove=="function"&&z.remove()}catch{}}try{const O=Xt.getFeatures();if(O&&Array.isArray(O)&&O.length>0){const z=O.filter(F=>F!=null&&typeof F.remove=="function");for(const F of z)try{F.remove()}catch{}}}catch{}}catch(O){console.warn("Error clearing existing annotations:",O)}const R=tt instanceof Map?new Map(Array.from(tt.entries()).map(([O,z])=>[String(O),z])):tt?new Map(Object.entries(tt).map(([O,z])=>[String(O),z])):null,N=new Set;for(const O of b)try{const z=O.documentId,F=z!==void 0?String(z):void 0;console.log(`SlideViewer: Processing annotation feature id=${O.id}, documentId=${z}, lookupId=${F}`);let ee=It;if(R&&F!==void 0){const Q=R.get(F);Q!==void 0&&(ee=Q)}if(console.log(`SlideViewer: Annotation opacity=${ee}, will ${ee<=0?"skip":"render"}`),ee<=0){console.log("SlideViewer: Skipping annotation with opacity 0 (hidden)");continue}let q;if(O.annotationType==="polyline"&&O.points&&Array.isArray(O.points)){const Q=new f.Path,G=O.color||C;Q.strokeColor=In(G,ee),Q.strokeWidth=A;const X=O.fillColor||"rgba(0, 0, 0, 0)";Q.fillColor=In(X,ee),O.points.forEach((H,K)=>{K===0?Q.moveTo(H[0],H[1]):Q.lineTo(H[0],H[1])}),O.closed&&Q.closePath(),q=Q}else{const Q=new f.Rectangle(O.left,O.top,O.width,O.height),G=new f.Path.Rectangle(Q),X=O.color||C;G.strokeColor=In(X,ee),G.strokeWidth=A,G.fillColor=In("rgba(0, 0, 0, 0)",ee),q=G}if(q.data={annotation:O},q.annotationId=O.id,lt.current&&(q.onClick=Q=>{var G;(G=lt.current)==null||G.call(lt,O)}),q.style={rescale:{strokeWidth:A}},v.addPaperItem(q),q&&typeof q=="object")try{qr.AnnotationToolkit.registerFeature(q)}catch(Q){console.warn("Failed to register feature with toolkit:",Q)}F!==void 0?(N.add(F),console.log(`SlideViewer: Added documentId '${F}' to renderedDocumentIds. Set now has:`,Array.from(N))):console.warn(`SlideViewer: Cannot track document ID - lookupId is undefined for annotation id=${O.id}`)}catch(z){console.error(`Error rendering annotation ${O.id}:`,z,O)}Ci(f),console.log(`Finished rendering ${b.length} annotations`),console.log(`SlideViewer: onAnnotationReady is ${Te?"defined":"undefined"}, renderedDocumentIds has ${N.size} items:`,Array.from(N)),Te&&N.size>0?setTimeout(()=>{console.log(`SlideViewer: setTimeout fired, calling onAnnotationReady for ${N.size} document(s)`),N.forEach(O=>{try{console.log(`SlideViewer: Calling onAnnotationReady('${O}')`),Te(O)}catch(z){console.error(`Error calling onAnnotationReady for ${O}:`,z)}})},100):console.warn(`SlideViewer: Not calling onAnnotationReady - callback is ${Te?"":"not "}defined, renderedDocumentIds has ${N.size} items`)},[ei,Ut,Xt,jt,Mi,A,It,tt,Kt,Te]),wt.useEffect(()=>{var v;if(!ei||!Ut||!Xt)return;const f=Ut.paperScope;if(!(!f||!f.project))try{const b=Xt.getFeatures();if(b&&Array.isArray(b)){const T=tt instanceof Map?tt:tt?new Map(Object.entries(tt).map(([N,O])=>[String(N),O])):null;let R=!1;for(const N of b)try{if(N&&typeof N=="object"){const O=N,z=(v=O.data)==null?void 0:v.annotation;if(!z)continue;const F=z.documentId,ee=F!==void 0?String(F):void 0;if(ee===void 0)continue;let q=It;if(T&&ee!==void 0){const H=T.get(ee);H!==void 0&&(q=H)}if(q<=0){try{const H=z.color||C,K=z.fillColor||"rgba(0, 0, 0, 0)";O.strokeColor&&(O.strokeColor=In(H,0),R=!0),O.fillColor&&(O.fillColor=In(K,0),R=!0)}catch{try{O.remove&&(O.remove(),R=!0)}catch(K){console.warn("Could not hide annotation:",K)}}continue}let Q=It;if(T&&ee!==void 0&&T.has(ee)){const H=T.get(ee);H!==void 0&&(Q=H)}const G=z.color||C,X=z.fillColor||"rgba(0, 0, 0, 0)";O.strokeColor&&(O.strokeColor=In(G,Q),R=!0),O.fillColor&&(O.fillColor=In(X,Q),R=!0)}}catch(O){console.warn("Error updating annotation opacity:",O)}R&&Ci(f)}}catch(b){console.warn("Could not update annotation opacity:",b)}},[It,tt,Kt,ei,Ut,Xt,vt,C,Ci]);const r=wt.useMemo(()=>({documentProperties:(D==null?void 0:D.documentProperties)??Vn.documentProperties??[],showFetchedSection:(D==null?void 0:D.showFetchedSection)??Vn.showFetchedSection??!0,showProvidedSection:(D==null?void 0:D.showProvidedSection)??Vn.showProvidedSection??!0,showTotalSection:(D==null?void 0:D.showTotalSection)??Vn.showTotalSection??!0,headerText:(D==null?void 0:D.headerText)??Vn.headerText??"Annotation Information"}),[D]),h={width:typeof j=="number"?`${j}px`:j,height:typeof L=="number"?`${L}px`:L};return Je.jsxs("div",{ref:fi,className:`bdsa-slide-viewer ${k}`,style:h,children:[Je.jsx("div",{ref:pt,className:"bdsa-slide-viewer__container"}),(J||Lt)&&Je.jsxs("div",{className:"bdsa-slide-viewer__sidebar",children:[Lt&&Je.jsxs("div",{className:"bdsa-slide-viewer__controls",children:[Je.jsx("div",{className:"bdsa-slide-viewer__controls-header",children:Je.jsx("strong",{children:"Annotation Controls"})}),Je.jsxs("div",{className:"bdsa-slide-viewer__controls-section",children:[Je.jsxs("div",{className:"bdsa-slide-viewer__controls-label",children:["Opacity: ",Math.round(It*100),"%"]}),Je.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:It,onChange:f=>Di(parseFloat(f.target.value)),className:"bdsa-slide-viewer__opacity-slider"})]})]}),J&&(Array.isArray(w)&&w.length>0||!Array.isArray(w)&&w&&"type"in w&&w.type==="FeatureCollection"&&((o=w.features)==null?void 0:o.length)>0||Yt.length>0||Vi.length>0)&&Je.jsxs("div",{className:"bdsa-slide-viewer__annotation-info",children:[Je.jsx("div",{className:"bdsa-slide-viewer__annotation-info-header",children:Je.jsx("strong",{children:r.headerText})}),r.showFetchedSection&&Yt.length>0&&Je.jsxs("div",{className:"bdsa-slide-viewer__annotation-info-section",children:[Je.jsx("div",{className:"bdsa-slide-viewer__annotation-info-title",children:"Fetched from DSA API:"}),Yt.map(f=>Je.jsx("div",{className:"bdsa-slide-viewer__annotation-info-item",children:r.documentProperties.filter(v=>v.show!==!1).map(v=>{const b=f[v.key],T=v.formatter?v.formatter(b,{...f,totalPoints:f.totalPoints??0}):String(b??"N/A");return Je.jsxs("div",{children:[v.label,": ",T]},v.key)})},f.id))]}),r.showProvidedSection&&(Array.isArray(w)&&w.length>0||!Array.isArray(w)&&w&&w.type==="FeatureCollection")&&Je.jsxs("div",{className:"bdsa-slide-viewer__annotation-info-section",children:[Je.jsx("div",{className:"bdsa-slide-viewer__annotation-info-title",children:"Provided Annotations:"}),Je.jsx("div",{className:"bdsa-slide-viewer__annotation-info-item",children:Array.isArray(w)?Je.jsxs("div",{children:["Count: ",w.length]}):Je.jsxs("div",{children:["GeoJSON FeatureCollection with ",((u=w.features)==null?void 0:u.length)||0," features"]})})]}),r.showTotalSection&&Je.jsxs("div",{className:"bdsa-slide-viewer__annotation-info-section",children:[Je.jsx("div",{className:"bdsa-slide-viewer__annotation-info-title",children:"Total Rendered:"}),Je.jsxs("div",{className:"bdsa-slide-viewer__annotation-info-item",children:[Vi.length+(Array.isArray(w)?w.length:0)," annotation(s)"]})]})]})]})]})});Hs.displayName="SlideViewer";const Vs=wt.forwardRef(({imageId:l,apiBaseUrl:w,limit:n=50,fetchFn:a,apiHeaders:p,onAnnotationsLoaded:c,onError:C,showDebugPanel:A=!1,onAnnotationLoadChange:m,onAnnotationVisibilityChange:k,onAnnotationOpacityChange:L,onAnnotationReady:j,slideViewerOnAnnotationReady:J,onLoadedAnnotationIdsChange:D,onAnnotationLoad:fe,onAnnotationHide:le,onAnnotationStateChange:$,onAnnotationOpacitiesChange:Ae,onAnnotationHeadersChange:Xe,loadedAnnotations:Ve,visibleAnnotations:Lt,annotationOpacities:vt,annotationCache:tt,disableCache:Kt=!1,showDefaultUI:Te=!0,className:Jt="",children:At},ni)=>{const[ct,fi]=wt.useState([]),[pt,ei]=wt.useState(!1),[gt,Ut]=wt.useState(null),[mi,Xt]=wt.useState(null),[_i,Vi]=wt.useState(new Set),[ji,Yt]=wt.useState(new Map),[Li,bt]=wt.useState(new Map),li=wt.useRef(new Map),[It,Di]=wt.useState(null),[si,Nt]=wt.useState(new Set),[ui,Hi]=wt.useState(new Set),Fi=wt.useMemo(()=>Kt||tt===null?null:tt||new Er,[tt,Kt]),Ci=Ve??_i,Mi=Lt??ji,ri=vt??Li,Z=wt.useMemo(()=>Array.from(Ci).sort(),[Ci]);wt.useEffect(()=>{D&&D(Z)},[Z,D]);const _e=wt.useRef(null),Ge=wt.useCallback(()=>{const u=Array.from(Ci).sort(),f=new Map(ri),v=new Map(Mi);if($){const b=_e.current;$({loadedAnnotationIds:u,opacities:f,visibility:v,onAnnotationReady:b||void 0})}Ae&&Ae(f),D&&D(u)},[Ci,ri,Mi,$,Ae,D]),lt=wt.useMemo(()=>Array.from(ri.entries()).sort(([u],[f])=>u.localeCompare(f)),[ri]),st=wt.useMemo(()=>Array.from(Mi.entries()).sort(([u],[f])=>u.localeCompare(f)),[Mi]);wt.useEffect(()=>{Ge()},[Ge,Z,lt,st]);const Rt=wt.useCallback(u=>{const f=String(u);console.log(`[AM] handleAnnotationReadyInternal called for ${f}`),Nt(v=>{const b=v.has(f),T=new Set(v);return T.delete(f),console.log(`[AM] Cleared loading for ${f}. Was loading: ${b}. Still loading:`,Array.from(T)),T}),Fi&&Fi.has(f).then(v=>{v&&Hi(b=>new Set(b).add(f))}).catch(()=>{}),j==null||j(f),J==null||J(f)},[j,J,Fi]);_e.current=Rt,wt.useEffect(()=>{_e.current=Rt,Ge()},[Rt,Ge]);const et=Rt,$t=wt.useCallback(u=>{const f=String(u),v=Ci.has(f);console.log(`[AM] toggleLoad for ${f}. Currently loaded: ${v}`),v?(Ve||Vi(b=>{const T=new Set(b);return T.delete(f),T}),Lt||Yt(b=>{const T=new Map(b);return T.delete(f),T}),vt||bt(b=>{const T=new Map(b);return T.delete(f),T}),m==null||m(f,!1),le==null||le(f),Nt(b=>{const T=new Set(b);return T.delete(f),T})):(console.log(`[AM] Adding ${f} to loading state`),Nt(b=>new Set(b).add(f)),Ve||(console.log(`[AM] toggleLoad: Adding ${f} to internalLoadedAnnotations`),Vi(b=>{const T=new Set(b).add(f);return console.log("[AM] internalLoadedAnnotations now:",Array.from(T)),T})),Lt||Yt(b=>new Map(b).set(f,!0)),vt||bt(b=>new Map(b).set(f,1)),m==null||m(f,!0),fe==null||fe(f))},[Ve,Lt,vt,Ci,m,fe,le,Ge]),jt=wt.useCallback(u=>{const f=ri.get(u)??1;if(f>0){li.current.set(u,f);const b=0;vt||bt(T=>new Map(T).set(u,b)),L==null||L(u,b),Lt||Yt(T=>new Map(T).set(u,!1)),k==null||k(u,!1)}else{const b=li.current.get(u)??1;li.current.delete(u),vt||bt(T=>new Map(T).set(u,b)),L==null||L(u,b),Lt||Yt(T=>new Map(T).set(u,!0)),k==null||k(u,!0)}},[vt,Lt,ri,L,k,Ge]),t=wt.useCallback((u,f)=>{vt||bt(v=>new Map(v).set(u,f)),L==null||L(u,f)},[vt,L,Ge]);wt.useEffect(()=>{if(!l||!w){fi([]),ei(!1),Ut(null),Xt(null);return}(async()=>{ei(!0),Ut(null),Xt(null);try{const f=new URLSearchParams({itemId:l,limit:String(n),offset:"0",sort:"lowerName",sortdir:"1"}),v=`${w}/annotation?${f.toString()}`,b=a||fetch,T={};p&&(T.headers=p),console.log(`AnnotationManager: Fetching annotations from: ${v}`);const R=await b(v,T);if(!R.ok)throw new Error(`Failed to fetch annotations: ${R.status} ${R.statusText}`);const N=await R.json();console.log("AnnotationManager: API response:",N),A&&Xt(JSON.stringify(N,null,2));let O=[];if(Array.isArray(N)?(O=N,console.log(`AnnotationManager: Parsed ${O.length} annotation(s) from array response`)):N&&Array.isArray(N.data)?(O=N.data,console.log(`AnnotationManager: Parsed ${O.length} annotation(s) from paginated response`)):N&&typeof N=="object"?(O=[N],console.log("AnnotationManager: Parsed 1 annotation from single object response")):console.warn("AnnotationManager: Unexpected response format:",typeof N,N),fi(O),console.log(`AnnotationManager: Fetched ${O.length} annotation(s) from API`),O.length>0&&console.log("AnnotationManager: Annotation IDs:",O.map(z=>z._id)),Xe&&O.length>0){const z=new Map;O.forEach(F=>{z.set(String(F._id),F)}),Xe(z)}Fi&&O.length>0?(async()=>{const F=new Set;for(const ee of O){const q=String(ee._id);try{await Fi.has(q)&&F.add(q)}catch{}}Hi(F)})():Hi(new Set),c&&c(O)}catch(f){const v=f instanceof Error?f:new Error(String(f));Ut(v),Xt(null),C&&C(v)}finally{ei(!1)}})()},[l,w,n,a,p,c,C,A,Xe]),wt.useEffect(()=>{if(Xe&&ct.length>0){const u=new Map;ct.forEach(f=>{u.set(String(f._id),f)}),Xe(u)}},[ct,Xe]);const r=wt.useMemo(()=>({annotations:ct,loading:pt,error:gt,annotationIds:ct.map(u=>u._id),loadedAnnotations:Ci,visibleAnnotations:Mi,annotationOpacities:ri,toggleLoad:$t,toggleVisibility:jt,setOpacity:t,handleAnnotationReady:Rt,onAnnotationReady:et,loadingAnnotations:si}),[ct,pt,gt,Ci,Mi,ri,$t,jt,t,Rt,et,si]),h=wt.useRef(null);wt.useImperativeHandle(ni,()=>({getAnnotations:()=>ct,getAnnotation:u=>ct.find(f=>String(f._id)===u),getLoadedAnnotationIds:()=>Array.from(Ci),isAnnotationLoaded:u=>Ci.has(u),isAnnotationVisible:u=>(ri.get(u)??1)>0,getAnnotationOpacity:u=>ri.get(u)??1,isAnnotationLoading:u=>si.has(u),getVisibleAnnotationIds:()=>Array.from(Ci).filter(u=>(ri.get(u)??1)>0),getAnnotationState:()=>({loadedAnnotationIds:Array.from(Ci),opacities:new Map(ri),visibility:new Map(Mi),loadingAnnotationIds:Array.from(si)})}),[ct,Ci,Mi,ri,si]);const o=()=>{if(pt)return Je.jsx("div",{className:"bdsa-annotation-manager__list",children:Je.jsx("div",{className:"bdsa-annotation-manager__empty-state",children:Je.jsx("p",{children:"Loading annotations..."})})});if(gt)return Je.jsx("div",{className:"bdsa-annotation-manager__list",children:Je.jsx("div",{className:"bdsa-annotation-manager__empty-state",style:{color:"#dc3545"},children:Je.jsxs("p",{children:["Error: ",gt.message]})})});if(ct.length===0)return Je.jsx("div",{className:"bdsa-annotation-manager__list",children:Je.jsx("div",{className:"bdsa-annotation-manager__empty-state",children:Je.jsx("p",{children:"No annotations found"})})});const u=Array.from(Ci).length;return Je.jsxs("div",{className:"bdsa-annotation-manager__list",children:[Je.jsxs("div",{className:"bdsa-annotation-manager__list-header",children:[Je.jsxs("h3",{children:["Annotations (",ct.length," total)"]}),Je.jsxs("p",{children:[u," loaded in viewer"]})]}),ct.map(f=>{var z;const v=String(f._id),b=Ci.has(v),T=si.has(v),R=ri.get(v)??1,N=ui.has(v),O=It===v;return Je.jsxs("div",{className:`bdsa-annotation-manager__annotation-card ${b?"bdsa-annotation-manager__annotation-card--loaded":""} ${O?"bdsa-annotation-manager__annotation-card--selected":""}`,onClick:()=>Di(f._id),children:[Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-header",children:[Je.jsx("h4",{className:"bdsa-annotation-manager__annotation-card-title",children:((z=f.annotation)==null?void 0:z.name)||f._id}),Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-meta",children:[f.public===!1&&Je.jsx("span",{className:"bdsa-annotation-manager__annotation-card-badge bdsa-annotation-manager__annotation-card-badge--private",children:"Private"}),f.public===!0&&Je.jsx("span",{className:"bdsa-annotation-manager__annotation-card-badge bdsa-annotation-manager__annotation-card-badge--public",children:"Public"}),N&&Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-cache-indicator-group",children:[Je.jsx("span",{className:"bdsa-annotation-manager__annotation-card-cache-indicator",title:"Cached locally - will load quickly",children:Je.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[Je.jsx("rect",{x:"2",y:"3",width:"20",height:"18",rx:"2"}),Je.jsx("path",{d:"M7 3h10M7 21h10M9 9h6M9 15h6"})]})}),Fi&&typeof Fi.delete=="function"&&Je.jsx("button",{className:"bdsa-annotation-manager__annotation-card-cache-bypass",onClick:async F=>{F.stopPropagation();const ee=String(f._id);try{await Fi.delete(ee),Hi(q=>{const Q=new Set(q);return Q.delete(ee),Q}),Ci.has(ee)&&($t(ee),setTimeout(()=>$t(ee),100))}catch(q){console.warn("Failed to clear cache for annotation:",q)}},title:"Clear cache and refresh this annotation",children:Je.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[Je.jsx("path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"}),Je.jsx("path",{d:"M21 3v5h-5"}),Je.jsx("path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"}),Je.jsx("path",{d:"M3 21v-5h5"})]})})]}),Je.jsx("button",{className:"bdsa-annotation-manager__annotation-card-button bdsa-annotation-manager__annotation-card-button--load bdsa-annotation-manager__annotation-card-button--load-header",onClick:F=>{F.stopPropagation(),$t(String(f._id))},title:b?"Unload annotation":"Load annotation",children:b?Je.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:Je.jsx("line",{x1:"5",y1:"12",x2:"19",y2:"12"})}):Je.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[Je.jsx("line",{x1:"12",y1:"5",x2:"12",y2:"19"}),Je.jsx("line",{x1:"5",y1:"12",x2:"19",y2:"12"})]})})]})]}),Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-details",children:[f._elementCount!==void 0&&Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-detail",children:[Je.jsx("strong",{children:"Elements:"})," ",f._elementCount]}),f._detailsCount!==void 0&&Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-detail",children:[Je.jsx("strong",{children:"Points:"})," ",f._detailsCount.toLocaleString()]})]}),Je.jsx("div",{className:"bdsa-annotation-manager__annotation-card-controls",children:T?Je.jsxs("div",{className:"bdsa-annotation-manager__loading-indicator",children:[Je.jsx("div",{className:"bdsa-annotation-manager__spinner"}),Je.jsx("span",{children:"Loading..."})]}):b?Je.jsxs(Je.Fragment,{children:[Je.jsx("button",{className:"bdsa-annotation-manager__annotation-card-button bdsa-annotation-manager__annotation-card-button--visibility",onClick:F=>{F.stopPropagation(),jt(f._id)},title:R>0?"Hide annotation":"Show annotation",children:Je.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:R>0?Je.jsxs(Je.Fragment,{children:[Je.jsx("path",{d:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"}),Je.jsx("circle",{cx:"12",cy:"12",r:"3"})]}):Je.jsxs(Je.Fragment,{children:[Je.jsx("path",{d:"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"}),Je.jsx("line",{x1:"1",y1:"1",x2:"23",y2:"23"})]})})}),Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-opacity",onClick:F=>F.stopPropagation(),children:[Je.jsxs("label",{className:"bdsa-annotation-manager__annotation-card-opacity-label",children:["Opacity: ",Math.round(R*100),"%"]}),Je.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:R,onChange:F=>t(f._id,parseFloat(F.target.value)),onClick:F=>F.stopPropagation(),onMouseDown:F=>F.stopPropagation(),className:"bdsa-annotation-manager__annotation-card-opacity-slider"})]})]}):null})]},f._id)})]})};return Je.jsxs("div",{ref:h,className:`bdsa-annotation-manager ${Jt}`,children:[Te?Je.jsxs(Je.Fragment,{children:[o(),At&&typeof At=="function"?At(r):At]}):At&&typeof At=="function"?At(r):At,A&&mi&&Je.jsxs("div",{className:"bdsa-annotation-manager__debug-panel",children:[Je.jsx("div",{className:"bdsa-annotation-manager__debug-panel-header",children:Je.jsx("strong",{children:"Raw API Response (Debug)"})}),Je.jsx("pre",{className:"bdsa-annotation-manager__debug-panel-content",children:mi})]})]})});Vs.displayName="AnnotationManager";const Us=wt.forwardRef(({apiBaseUrl:l,fetchFn:w,apiHeaders:n,onResourceSelect:a,onSelectionChange:p,showCollections:c=!0,rootId:C,rootType:A,startCollectionId:m,startFolderId:k,parentFolderId:L,foldersPerPage:j=50,className:J="",renderCollection:D,renderFolder:fe,showItems:le=!0,itemsPerPage:$=50,onItemSelect:Ae,renderItem:Xe,persistSelection:Ve=!1,persistSelectionKey:Lt="bdsa_folder_browser_selection",persistExpansion:vt=!1,persistExpansionKey:tt="bdsa_folder_browser_expansion"},Kt)=>{const[Te,Jt]=wt.useState([]),[At,ni]=wt.useState(null),[ct,fi]=wt.useState(null),[pt,ei]=wt.useState({}),[gt,Ut]=wt.useState({}),[mi,Xt]=wt.useState({}),[_i,Vi]=wt.useState({}),[ji,Yt]=wt.useState(()=>{if(vt)try{const v=localStorage.getItem(`${tt}_collections`);if(v){const b=JSON.parse(v);return new Set(b)}}catch(v){console.warn("Failed to restore expanded collections from localStorage:",v)}return new Set}),[Li,bt]=wt.useState(()=>{if(vt)try{const v=localStorage.getItem(`${tt}_folders`);if(v){const b=JSON.parse(v);return new Set(b)}}catch(v){console.warn("Failed to restore expanded folders from localStorage:",v)}return new Set}),[li,It]=wt.useState(null),[Di,si]=wt.useState(!1),[Nt,ui]=wt.useState({}),[Hi,Fi]=wt.useState({}),[Ci,Mi]=wt.useState(null),ri=wt.useRef(null),Z=wt.useRef(!1),_e=wt.useRef(!1),Ge=wt.useCallback(()=>{const v={};return n&&(v.headers=n),v},[n]);wt.useEffect(()=>{if(Ve&&li)try{const v={resource:li,timestamp:Date.now()};localStorage.setItem(Lt,JSON.stringify(v))}catch(v){console.warn("Failed to save selection to localStorage:",v)}},[li,Ve,Lt]),wt.useEffect(()=>{if(Ve&&!_e.current){_e.current=!0;try{const v=localStorage.getItem(Lt);if(v){const b=JSON.parse(v);b.resource&&b.resource._id&&(It(b.resource),vt||(b.resource.type==="collection"?Yt(new Set([b.resource._id])):b.resource.type==="folder"&&bt(new Set([b.resource._id]))))}}catch(v){console.warn("Failed to restore selection from localStorage:",v)}}},[Ve,Lt,vt]),wt.useEffect(()=>{if(vt&&!(Te.length===0&&!At)&&!Z.current){Z.current=!0;try{const v=localStorage.getItem(`${tt}_collections`),b=localStorage.getItem(`${tt}_folders`);if(v){const T=JSON.parse(v);T.length>0&&(Yt(new Set(T)),T.forEach(R=>{const N=Te.find(O=>O._id===R)||((At==null?void 0:At._id)===R?At:null);N&&st(N)}))}if(b){const T=JSON.parse(b);T.length>0&&bt(new Set(T))}}catch(v){console.warn("Failed to restore expansion state:",v)}}},[vt,tt,Te,At,pt]),wt.useEffect(()=>{vt&&(ji.forEach(v=>{var T;if(!(pt[v]!==void 0||((T=mi[v])==null?void 0:T.loaded))&&!Nt[v]){const R=Te.find(N=>N._id===v)||((At==null?void 0:At._id)===v?At:null);R&&st(R)}}),Li.forEach(v=>{var T;let b=null;for(const R of Object.values(pt))if(b=R.find(N=>N._id===v)||null,b)break;b&&(!(pt[v]!==void 0||(T=mi[v])!=null&&T.loaded)&&!Nt[v]&&Rt(b),le&&!(gt[v]!==void 0)&&!Hi[v]&&et(v,b))}))},[vt,ji,Li,pt,gt,Te,At,le,mi,Nt,Hi]),wt.useEffect(()=>{if(vt)try{const v=Array.from(ji);localStorage.setItem(`${tt}_collections`,JSON.stringify(v))}catch(v){console.warn("Failed to save expanded collections to localStorage:",v)}},[ji,vt,tt]),wt.useEffect(()=>{if(vt)try{const v=Array.from(Li);localStorage.setItem(`${tt}_folders`,JSON.stringify(v))}catch(v){console.warn("Failed to save expanded folders to localStorage:",v)}},[Li,vt,tt]),wt.useEffect(()=>{if(!li||!ri.current)return;const v=setTimeout(()=>{var T;const b=(T=ri.current)==null?void 0:T.querySelector(`[data-resource-id="${li._id}"]`);b&&b.scrollIntoView({behavior:"smooth",block:"center"})},100);return()=>clearTimeout(v)},[li]);const lt=wt.useCallback(async()=>{if(!l){Mi(new Error("API base URL is required"));return}si(!0),Mi(null);try{const v=`${l}/collection`,b=w||fetch,T=Ge(),R=await b(v,T);if(!R.ok)throw new Error(`Failed to fetch collections: ${R.status} ${R.statusText}`);const N=await R.json(),O=Array.isArray(N)?N:N.items||[];Jt(O),m&&O.some(z=>z._id===m)&&(Yt(new Set([m])),await st(O.find(z=>z._id===m)))}catch(v){const b=v instanceof Error?v:new Error("Unknown error loading collections");Mi(b),console.error("Error loading collections:",b)}finally{si(!1)}},[l,w,Ge,m]),st=wt.useCallback(async(v,b=!1)=>{if(!l||!(v!=null&&v._id))return;let T=!1,R=0;if(Xt(N=>{const O=N[v._id];return O!=null&&O.loaded&&!b&&(T=!0),b&&O&&(R=O.offset),N}),!T){ui(N=>({...N,[v._id]:!0}));try{const N=new URLSearchParams({parentType:"collection",parentId:v._id});j>0&&(N.append("limit",String(j)),N.append("offset",String(R)));const O=`${l}/folder?${N.toString()}`,z=w||fetch,F=Ge(),ee=await z(O,F);if(!ee.ok){console.warn(`Failed to fetch folders for collection ${v._id}:`,ee.statusText);return}const q=await ee.json();let Q=[],G=!1;Array.isArray(q)?(Q=q,G=j>0&&q.length===j):(Q=q.items||[],G=j>0&&q.total>R+Q.length),ei(X=>({...X,[v._id]:b?[...X[v._id]||[],...Q]:Q})),Xt(X=>({...X,[v._id]:{offset:j>0?R+Q.length:0,hasMore:j>0?G:!1,loaded:!0}})),!b&&k&&Q.some(X=>X._id===k)&&(bt(X=>new Set(X).add(k)),await Rt(Q.find(X=>X._id===k),!0))}catch(N){console.error(`Error loading folders for collection ${v._id}:`,N)}finally{ui(N=>({...N,[v._id]:!1}))}}},[l,w,Ge,k,j]),Rt=wt.useCallback(async(v,b=!1)=>{if(!l||!(v!=null&&v._id))return;let T=!1,R=0;if(Xt(N=>{const O=N[v._id];return O!=null&&O.loaded&&!b&&(T=!0),b&&O&&(R=O.offset),N}),!T){ui(N=>({...N,[v._id]:!0}));try{const N=new URLSearchParams({parentType:"folder",parentId:v._id});j>0&&(N.append("limit",String(j)),N.append("offset",String(R)));const O=`${l}/folder?${N.toString()}`,z=w||fetch,F=Ge(),ee=await z(O,F);if(!ee.ok){console.warn(`Failed to fetch subfolders for folder ${v._id}:`,ee.statusText);return}const q=await ee.json();let Q=[],G=!1;Array.isArray(q)?(Q=q,G=j>0&&q.length===j):(Q=q.items||[],G=j>0&&q.total>R+Q.length),ei(X=>({...X,[v._id]:b?[...X[v._id]||[],...Q]:Q})),Xt(X=>({...X,[v._id]:{offset:j>0?R+Q.length:0,hasMore:j>0?G:!1,loaded:!0}}))}catch(N){console.error(`Error loading subfolders for folder ${v._id}:`,N)}finally{ui(N=>({...N,[v._id]:!1}))}}},[l,w,Ge,j]),et=wt.useCallback(async(v,b,T=!1)=>{if(!l||!le)return;b&&console.log(`[FolderBrowser] Checking folder ${v} (${b.name}):`,{parentType:b.parentType,parentId:b.parentId,hasItems:!0}),b?b.parentType==="collection"?console.log(`[FolderBrowser] Root folder ${v} (${b.name}) - attempting item fetch (typically empty, but checking anyway)`):b.parentType==="folder"?console.log(`[FolderBrowser] Subfolder ${v} (${b.name}) - fetching items`):console.log(`[FolderBrowser] Folder ${v} (${b.name}) - parentType unknown (${b.parentType}), attempting fetch`):console.log(`[FolderBrowser] Folder object not provided for ${v} - attempting item fetch`);const R=T&&_i[v]?_i[v].offset:0;Fi(N=>({...N,[v]:!0}));try{const N=new URLSearchParams;N.append("folderId",v),$>0&&(N.append("limit",String($)),N.append("offset",String(R)));const O=`${l}/item?${N.toString()}`;console.log(`[FolderBrowser] Fetching items from: ${O}`);const z=w||fetch,F=Ge(),ee=await z(O,F);if(!ee.ok){console.warn(`[FolderBrowser] Failed to fetch items for folder ${v}:`,ee.status,ee.statusText);return}const q=await ee.json();console.log("[FolderBrowser] Received response:",q);let Q=[],G=!1;Array.isArray(q)?(Q=q,G=$>0&&q.length===$):(Q=q.items||[],G=$>0&&q.total>R+Q.length),console.log(`[FolderBrowser] Parsed ${Q.length} items for folder ${v}`),Ut(X=>({...X,[v]:T?[...X[v]||[],...Q]:Q})),$>0&&Vi(X=>({...X,[v]:{offset:R+Q.length,hasMore:G}}))}catch(N){console.error(`[FolderBrowser] Error loading items for folder ${v}:`,N)}finally{Fi(N=>({...N,[v]:!1}))}},[l,w,Ge,le,$,_i]),$t=wt.useCallback(async()=>{if(!(!l||!C||!A)){si(!0),Mi(null);try{let v=A==="collection"?`${l}/collection/${C}`:`${l}/folder/${C}`;const b=w||fetch,T=Ge();let R=await b(v,T),N=null;if(R.ok)N=await R.json();else if(console.warn(`Direct fetch failed for ${A} ${C}, trying list endpoint...`),A==="collection"){const O=`${l}/collection`;if(R=await b(O,T),!R.ok)throw new Error(`Failed to fetch collections: ${R.status} ${R.statusText}`);const z=await R.json();if(N=(Array.isArray(z)?z:z.items||[]).find(ee=>ee._id===C)||null,!N)throw new Error(`Collection with ID ${C} not found`)}else{try{const O=`${l}/folder`;if(R=await b(O,T),R.ok){const z=await R.json();N=(Array.isArray(z)?z:z.items||[]).find(ee=>ee._id===C)||null}}catch{console.warn("Could not list folders directly, will need to search through collections")}if(!N){const O=`${l}/collection`,z=await b(O,T);if(!z.ok)throw new Error(`Failed to fetch collections for folder search: ${z.status}`);const F=await z.json(),ee=Array.isArray(F)?F:F.items||[];for(const q of ee){const Q=`${l}/folder?parentType=collection&parentId=${q._id}`,G=await b(Q,T);if(G.ok){const X=await G.json(),H=Array.isArray(X)?X:X.items||[],K=H.find(oe=>oe._id===C);if(K){N=K;break}const ie=async oe=>{const te=`${l}/folder?parentType=folder&parentId=${oe._id}`,pe=await b(te,T);if(pe.ok){const Se=await pe.json(),Ce=Array.isArray(Se)?Se:Se.items||[],Ie=Ce.find(ge=>ge._id===C);if(Ie)return Ie;for(const ge of Ce){const Pe=await ie(ge);if(Pe)return Pe}}return null};for(const oe of H){const te=await ie(oe);if(te){N=te;break}}if(N)break}}if(!N)throw new Error(`Folder with ID ${C} not found in any collection`)}}if(!N)throw new Error(`${A} with ID ${C} not found`);if(A==="collection"){const O=N;ni(O),Yt(new Set([C])),await st(O)}else{const O=N;fi(O),bt(new Set([C])),await Rt(O)}}catch(v){const b=v instanceof Error?v:new Error(`Unknown error loading ${A}`);Mi(b),console.error(`Error loading root ${A}:`,b)}finally{si(!1)}}},[l,C,A,w,Ge,st,Rt]),jt=wt.useCallback(async v=>{if(ji.has(v._id))Yt(T=>{const R=new Set(T);return R.delete(v._id),R});else{const T=ri.current;let R=null,N=0;if(T){let O=T.parentElement;for(;O&&O!==document.body;){const z=window.getComputedStyle(O),F=z.overflowY||z.overflow;if(F==="auto"||F==="scroll"){R=O,N=O.scrollTop;break}if(O.scrollHeight>O.clientHeight&&O.clientHeight>0){R=O,N=O.scrollTop;break}O=O.parentElement}}if(Yt(O=>new Set(O).add(v._id)),await st(v,!1),R){const O=N;requestAnimationFrame(()=>{requestAnimationFrame(()=>{R&&R.scrollTop!==void 0&&(R.scrollTop=O)})})}}},[ji,st]),t=wt.useCallback(async v=>{if(Li.has(v._id))bt(T=>{const R=new Set(T);return R.delete(v._id),R});else{const T=ri.current;let R=null,N=0;if(T){let O=T.parentElement;for(;O&&O!==document.body;){const z=window.getComputedStyle(O),F=z.overflowY||z.overflow;if(F==="auto"||F==="scroll"){R=O,N=O.scrollTop;break}if(O.scrollHeight>O.clientHeight&&O.clientHeight>0){R=O,N=O.scrollTop;break}O=O.parentElement}}if(bt(O=>new Set(O).add(v._id)),await Rt(v,!1),le?(console.log(`[FolderBrowser] Toggling folder ${v._id} (${v.name}) - showItems=${le}, calling loadItemsForFolder`),await et(v._id,v,!1)):console.log(`[FolderBrowser] Toggling folder ${v._id} (${v.name}) - showItems is FALSE, skipping item load`),R){const O=N;requestAnimationFrame(()=>{requestAnimationFrame(()=>{R&&R.scrollTop!==void 0&&(R.scrollTop=O)})})}}},[Li,Rt,le,et]),r=wt.useCallback((v,b)=>{const T={...v,type:b};It(T),a==null||a(T),p==null||p(T)},[a,p]),h=wt.useCallback(v=>{const b={...v,type:"item"};It(b),Ae==null||Ae(v),p==null||p(b)},[Ae,p]);wt.useEffect(()=>{C&&A&&l?$t():c&&l?lt():c&&!l&&(Mi(new Error("API base URL is required")),si(!1))},[C,A,c,l,lt,$t]);const o=wt.useCallback((v,b)=>{const T=(li==null?void 0:li._id)===v._id&&(li==null?void 0:li.type)==="item";return Xe?Xe(v,b):Je.jsx("div",{className:"bdsa-folder-browser__item",style:{marginLeft:`${b*20}px`},children:Je.jsxs("div",{className:`bdsa-folder-browser__folder-header ${T?"selected":""}`,onClick:()=>h(v),onDoubleClick:()=>h(v),"data-resource-id":v._id,children:[Je.jsx("span",{className:"bdsa-folder-browser__folder-icon",children:"📄"}),Je.jsx("span",{className:"bdsa-folder-browser__folder-name",children:v.name}),Je.jsx("span",{className:"bdsa-folder-browser__folder-type",children:"Item"})]})},v._id)},[li,Xe,h]),u=wt.useCallback((v,b=0)=>{var z,F;const T=Li.has(v._id),R=pt[v._id]||[],N=le?gt[v._id]||[]:[],O=(li==null?void 0:li._id)===v._id&&(li==null?void 0:li.type)==="folder";return fe?fe(v,b,T,()=>t(v)):Je.jsxs("div",{className:"bdsa-folder-browser__folder",style:{marginLeft:`${b*20}px`},children:[Je.jsxs("div",{className:`bdsa-folder-browser__folder-header ${O?"selected":""}`,onClick:()=>t(v),onDoubleClick:()=>r(v,"folder"),"data-resource-id":v._id,children:[Je.jsx("span",{className:`bdsa-folder-browser__folder-icon ${T?"expanded":""}`,children:T?"📂":"📁"}),Je.jsx("span",{className:"bdsa-folder-browser__folder-name",children:v.name}),Je.jsx("span",{className:"bdsa-folder-browser__folder-type",children:"Folder"})]}),T&&Je.jsxs("div",{className:"bdsa-folder-browser__folder-contents",children:[R.map(ee=>u(ee,b+1)),le&&N.map(ee=>o(ee,b+1)),le&&Hi[v._id]&&Je.jsx("div",{className:"bdsa-folder-browser__loading",style:{marginLeft:`${(b+1)*20}px`},children:Je.jsx("span",{children:"Loading items..."})}),j>0&&((z=mi[v._id])==null?void 0:z.hasMore)&&!Nt[v._id]&&Je.jsx("div",{className:"bdsa-folder-browser__load-more",style:{marginLeft:`${(b+1)*20}px`},children:Je.jsx("button",{className:"bdsa-folder-browser__load-more-btn",onClick:()=>Rt(v,!0),disabled:Nt[v._id],children:Nt[v._id]?"Loading...":"Load More Folders"})}),le&&$>0&&((F=_i[v._id])==null?void 0:F.hasMore)&&Je.jsx("div",{className:"bdsa-folder-browser__load-more",style:{marginLeft:`${(b+1)*20}px`},children:Je.jsx("button",{className:"bdsa-folder-browser__load-more-btn",onClick:()=>et(v._id,v,!0),disabled:Hi[v._id],children:Hi[v._id]?"Loading...":"Load More Items"})})]})]},v._id)},[Li,pt,gt,le,li,fe,t,r,j,mi,Nt,Rt,$,_i,Hi,et,o]),f=wt.useCallback(v=>{var N;const b=ji.has(v._id),T=pt[v._id]||[],R=(li==null?void 0:li._id)===v._id&&(li==null?void 0:li.type)==="collection";return D?D(v,b,()=>jt(v)):Je.jsxs("div",{className:"bdsa-folder-browser__collection",children:[Je.jsxs("div",{className:`bdsa-folder-browser__folder-header ${R?"selected":""}`,onClick:()=>jt(v),onDoubleClick:()=>r(v,"collection"),"data-resource-id":v._id,children:[Je.jsx("span",{className:`bdsa-folder-browser__folder-icon ${b?"expanded":""}`,children:b?"📂":"📁"}),Je.jsx("span",{className:"bdsa-folder-browser__folder-name",children:v.name}),Je.jsx("span",{className:"bdsa-folder-browser__folder-type",children:"Collection"})]}),b&&Je.jsxs("div",{className:"bdsa-folder-browser__folder-contents",children:[T.map(O=>u(O,1)),j>0&&((N=mi[v._id])==null?void 0:N.hasMore)&&!Nt[v._id]&&Je.jsx("div",{className:"bdsa-folder-browser__load-more",children:Je.jsx("button",{className:"bdsa-folder-browser__load-more-btn",onClick:()=>st(v,!0),disabled:Nt[v._id],children:Nt[v._id]?"Loading...":"Load More Folders"})})]})]},v._id)},[ji,pt,li,D,jt,r,j,mi,Nt,st,u]);return Je.jsxs("div",{ref:v=>{typeof Kt=="function"?Kt(v):Kt&&"current"in Kt&&(Kt.current=v),ri.current=v},className:`bdsa-folder-browser ${J}`,children:[Di&&Je.jsx("div",{className:"bdsa-folder-browser__loading",children:Je.jsx("span",{children:C&&A?`Loading ${A}...`:"Loading collections..."})}),Ci&&Je.jsxs("div",{className:"bdsa-folder-browser__error",children:[Je.jsx("span",{children:Ci.message}),Je.jsx("button",{onClick:()=>{C&&A?$t():lt()},children:"Retry"})]}),!Di&&!Ci&&Je.jsxs(Je.Fragment,{children:[C&&A==="collection"&&At&&Je.jsx("div",{className:"bdsa-folder-browser__collections",children:f(At)}),C&&A==="folder"&&ct&&Je.jsx("div",{className:"bdsa-folder-browser__collections",children:u(ct,0)}),!C&&c&&Je.jsx("div",{className:"bdsa-folder-browser__collections",children:Te.length===0?Je.jsx("div",{className:"bdsa-folder-browser__empty",children:Je.jsx("span",{children:"No collections found"})}):Te.map(v=>f(v))})]})]})});Us.displayName="FolderBrowser";const un={DSA_CONFIG:"bdsa_dsa_config",GIRDER_TOKEN:"bdsa_girder_token",USER_INFO:"bdsa_user_info",LAST_LOGIN:"bdsa_last_login",TOKEN_EXPIRY:"bdsa_token_expiry"};class qa{constructor(){on(this,"listeners",new Set);on(this,"config");on(this,"token");on(this,"userInfo");on(this,"lastLogin");on(this,"tokenExpiry");on(this,"isAuthenticated");this.config=this.loadConfig(),this.token=this.loadToken(),this.userInfo=this.loadUserInfo(),this.lastLogin=this.loadLastLogin(),this.tokenExpiry=this.loadTokenExpiry(),this.isAuthenticated=this.validateAuthentication()}subscribe(w){return this.listeners.add(w),()=>this.listeners.delete(w)}notify(){this.listeners.forEach(w=>w())}loadConfig(){try{const w=localStorage.getItem(un.DSA_CONFIG);return w?JSON.parse(w):{baseUrl:"",resourceId:"",resourceType:"folder",fetchStrategy:"unlimited",pageSize:100,metadataSyncTargetFolder:""}}catch(w){return console.error("Error loading DSA config:",w),{baseUrl:"",resourceId:"",resourceType:"folder",fetchStrategy:"unlimited",pageSize:100,metadataSyncTargetFolder:""}}}loadToken(){try{return localStorage.getItem(un.GIRDER_TOKEN)||""}catch(w){return console.error("Error loading Girder token:",w),""}}loadUserInfo(){try{const w=localStorage.getItem(un.USER_INFO);return w?JSON.parse(w):null}catch(w){return console.error("Error loading user info:",w),null}}loadLastLogin(){try{const w=localStorage.getItem(un.LAST_LOGIN);return w?new Date(w):null}catch(w){return console.error("Error loading last login:",w),null}}loadTokenExpiry(){try{const w=localStorage.getItem(un.TOKEN_EXPIRY);return w?new Date(w):null}catch(w){return console.error("Error loading token expiry:",w),null}}saveConfig(){try{localStorage.setItem(un.DSA_CONFIG,JSON.stringify(this.config))}catch(w){console.error("Error saving DSA config:",w)}}saveToken(){try{localStorage.setItem(un.GIRDER_TOKEN,this.token)}catch(w){console.error("Error saving Girder token:",w)}}saveUserInfo(){try{this.userInfo&&localStorage.setItem(un.USER_INFO,JSON.stringify(this.userInfo))}catch(w){console.error("Error saving user info:",w)}}saveLastLogin(){try{this.lastLogin&&localStorage.setItem(un.LAST_LOGIN,this.lastLogin.toISOString())}catch(w){console.error("Error saving last login:",w)}}saveTokenExpiry(){try{this.tokenExpiry&&localStorage.setItem(un.TOKEN_EXPIRY,this.tokenExpiry.toISOString())}catch(w){console.error("Error saving token expiry:",w)}}validateAuthentication(){return!this.token||!this.config.baseUrl?!1:this.tokenExpiry&&new Date>this.tokenExpiry?(console.log("Token has expired"),this.logout(),!1):!0}async authenticate(w,n){var a;try{if(!this.config.baseUrl)throw new Error("DSA server URL not configured");const p=btoa(`${w}:${n}`),c=await fetch(`${this.config.baseUrl}/api/v1/user/authentication`,{method:"GET",headers:{Authorization:`Basic ${p}`,"Content-Type":"application/json"}});if(!c.ok){const k=await c.json().catch(()=>({}));throw new Error(k.message||`Authentication failed: ${c.status}`)}const C=await c.json(),A=(a=C==null?void 0:C.authToken)==null?void 0:a.token,m=C==null?void 0:C.user;if(!A)throw new Error("No authentication token received from server");return this.token=A,this.userInfo={id:(m==null?void 0:m._id)||(m==null?void 0:m.id)||"",name:(m==null?void 0:m.login)||(m==null?void 0:m.firstName)||(m==null?void 0:m.email)||"User",email:m==null?void 0:m.email,login:m==null?void 0:m.login},this.lastLogin=new Date,this.tokenExpiry=new Date(Date.now()+30*24*60*60*1e3),this.isAuthenticated=!0,this.saveToken(),this.saveUserInfo(),this.saveLastLogin(),this.saveTokenExpiry(),this.notify(),{success:!0,user:this.userInfo}}catch(p){throw console.error("Authentication failed:",p),this.logout(),p}}logout(){this.token&&this.config.baseUrl&&fetch(`${this.config.baseUrl}/api/v1/user/authentication`,{method:"DELETE",headers:{"Girder-Token":this.token}}).catch(w=>{console.warn("Server logout failed:",w)}),this.token="",this.userInfo=null,this.lastLogin=null,this.tokenExpiry=null,this.isAuthenticated=!1,localStorage.removeItem(un.GIRDER_TOKEN),localStorage.removeItem(un.USER_INFO),localStorage.removeItem(un.LAST_LOGIN),localStorage.removeItem(un.TOKEN_EXPIRY),this.notify()}async validateToken(){if(!this.token||!this.config.baseUrl)return!1;try{return(await fetch(`${this.config.baseUrl}/api/v1/user/me`,{headers:{"Girder-Token":this.token}})).ok?!0:(console.log("Token validation failed, logging out"),this.logout(),!1)}catch(w){return console.error("Token validation error:",w),this.logout(),!1}}updateConfig(w){this.config={...this.config,...w},this.saveConfig(),this.notify()}setServerUrl(w){this.config.baseUrl=w,this.saveConfig(),this.notify()}getAuthHeaders(){return this.isAuthenticated?{"Girder-Token":this.token,"Content-Type":"application/json"}:{}}getApiUrl(w){if(!this.config.baseUrl)throw new Error("DSA server URL not configured");return`${this.config.baseUrl}${w}`}isConfigured(){return!!this.config.baseUrl}isDataReady(){return!!(this.config.baseUrl&&this.config.resourceId&&this.isAuthenticated)}getStatus(){return{isAuthenticated:this.isAuthenticated,isConfigured:this.isConfigured(),hasToken:!!this.token,hasConfig:!!this.config.baseUrl,user:this.userInfo,serverUrl:this.config.baseUrl,resourceId:this.config.resourceId,resourceType:this.config.resourceType,lastLogin:this.lastLogin,tokenExpiry:this.tokenExpiry}}getConfig(){return{...this.config}}getToken(){return this.token}async testConnection(){if(!this.config.baseUrl)throw new Error("DSA server URL not configured");try{const w=await fetch(`${this.config.baseUrl}/api/v1/system/version`,{method:"GET",headers:{"Content-Type":"application/json"}});if(w.ok)return{success:!0,version:await w.json(),message:"Connection successful"};throw new Error(`Server responded with status: ${w.status}`)}catch(w){throw new Error(`Connection failed: ${w.message}`)}}}const hn=new qa;function Gs(){const[l,w]=wt.useState(hn.getStatus());return wt.useEffect(()=>{const j=hn.subscribe(()=>{w(hn.getStatus())});return l.isAuthenticated&&hn.validateToken(),j},[]),{authStatus:l,login:async(j,J)=>{await hn.authenticate(j,J)},logout:()=>{hn.logout()},updateConfig:j=>{hn.updateConfig(j)},validateToken:async()=>await hn.validateToken(),testConnection:async()=>await hn.testConnection(),getAuthHeaders:()=>hn.getAuthHeaders(),getApiUrl:j=>hn.getApiUrl(j),getToken:()=>hn.getToken(),getConfig:()=>hn.getConfig()}}const Za=({onAuthChange:l,allowServerConfig:w=!0,className:n="",compact:a=!1})=>{const{authStatus:p,login:c,logout:C,updateConfig:A}=Gs(),[m,k]=wt.useState(!1),[L,j]=wt.useState({username:"",password:"",serverUrl:""}),[J,D]=wt.useState(!1),[fe,le]=wt.useState("");wt.useEffect(()=>{l&&l(p.isAuthenticated)},[p.isAuthenticated,l]);const $=async vt=>{vt.preventDefault(),D(!0),le("");try{w&&L.serverUrl&&L.serverUrl!==p.serverUrl&&A({baseUrl:L.serverUrl}),await c(L.username,L.password),k(!1),j({username:"",password:"",serverUrl:""})}catch(tt){le(tt.message)}finally{D(!1)}},Ae=()=>{C()},Xe=()=>{j(vt=>({...vt,serverUrl:p.serverUrl||""})),k(!0)},Lt=p.isConfigured?p.isAuthenticated?{text:"Connected",className:"status-connected",icon:"✅"}:{text:"Not Connected",className:"status-not-connected",icon:"🔌"}:{text:"Not Configured",className:"status-not-configured",icon:"⚙️"};return a?Je.jsxs("div",{className:`dsa-auth-manager compact ${n}`,children:[Je.jsxs("div",{className:"dsa-status-compact",children:[Je.jsx("span",{className:`status-indicator ${Lt.className}`,children:Lt.icon}),p.isAuthenticated&&p.user&&Je.jsx("span",{className:"user-name",children:p.user.name})]}),Je.jsx("button",{className:p.isAuthenticated?"logout-button":"login-button",onClick:p.isAuthenticated?Ae:Xe,disabled:!p.isConfigured&&!w,children:p.isAuthenticated?"Logout":"Login"}),m&&Je.jsx(Kr,{show:m,onClose:()=>k(!1),onSubmit:$,loginForm:L,setLoginForm:j,authStatus:p,isLoading:J,error:fe,allowServerConfig:w})]}):Je.jsxs("div",{className:`dsa-auth-manager ${n}`,children:[Je.jsxs("div",{className:"dsa-status",children:[Je.jsx("span",{className:`status-indicator ${Lt.className}`,children:Lt.icon}),Je.jsxs("div",{className:"status-info",children:[Je.jsx("div",{className:"status-text",children:Lt.text}),p.isAuthenticated&&p.user&&Je.jsxs("div",{className:"user-info",children:[p.user.name,p.serverUrl&&Je.jsx("div",{className:"server-url",children:new URL(p.serverUrl).hostname})]})]})]}),Je.jsx("div",{className:"dsa-actions",children:p.isAuthenticated?Je.jsx("button",{className:"logout-button",onClick:Ae,title:"Logout from DSA server",children:"Logout"}):Je.jsx("button",{className:"login-button",onClick:Xe,disabled:!p.isConfigured&&!w,title:!p.isConfigured&&!w?"Configure DSA server first":"Login to DSA server",children:"Login"})}),m&&Je.jsx(Kr,{show:m,onClose:()=>k(!1),onSubmit:$,loginForm:L,setLoginForm:j,authStatus:p,isLoading:J,error:fe,allowServerConfig:w})]})},Kr=({show:l,onClose:w,onSubmit:n,loginForm:a,setLoginForm:p,authStatus:c,isLoading:C,error:A,allowServerConfig:m})=>l?Je.jsx("div",{className:"modal-overlay",onClick:w,children:Je.jsxs("div",{className:"modal-content login-modal",onClick:k=>k.stopPropagation(),children:[Je.jsxs("div",{className:"modal-header",children:[Je.jsx("h2",{children:"Login to DSA Server"}),Je.jsx("button",{className:"close-button",onClick:w,children:"×"})]}),Je.jsxs("form",{onSubmit:n,className:"login-form",children:[m&&Je.jsxs("div",{className:"form-group",children:[Je.jsx("label",{htmlFor:"serverUrl",children:"DSA Server URL *"}),Je.jsx("input",{type:"url",id:"serverUrl",value:a.serverUrl,onChange:k=>p(L=>({...L,serverUrl:k.target.value})),placeholder:"http://bdsa.pathology.emory.edu:8080",required:!0}),Je.jsxs("div",{className:"field-help",children:["The base URL of your Digital Slide Archive server",Je.jsx("br",{}),Je.jsx("small",{children:"💡 Don't include /api/v1 - it will be added automatically"})]})]}),!m&&c.serverUrl&&Je.jsxs("div",{className:"form-group",children:[Je.jsx("label",{children:"Server"}),Je.jsx("div",{className:"server-display",children:c.serverUrl})]}),Je.jsxs("div",{className:"form-group",children:[Je.jsx("label",{htmlFor:"username",children:"Username"}),Je.jsx("input",{type:"text",id:"username",value:a.username,onChange:k=>p(L=>({...L,username:k.target.value})),placeholder:"Enter your DSA username",required:!0})]}),Je.jsxs("div",{className:"form-group",children:[Je.jsx("label",{htmlFor:"password",children:"Password"}),Je.jsx("input",{type:"password",id:"password",value:a.password,onChange:k=>p(L=>({...L,password:k.target.value})),placeholder:"Enter your password",required:!0})]}),A&&Je.jsx("div",{className:"error-message",children:A}),Je.jsxs("div",{className:"modal-actions",children:[Je.jsx("button",{type:"button",className:"cancel-button",onClick:w,disabled:C,children:"Cancel"}),Je.jsx("button",{type:"submit",className:"login-submit-button",disabled:C||!a.username||!a.password,children:C?"Logging in...":"Login"})]})]})]})}):null;function Ws(l){const w=l.largeImage;if(w===!0||w==="true"||typeof w=="object"&&w!==null)return!0;const p=(l.meta||{}).largeImage;return p===!0||p==="true"||typeof p=="object"&&p!==null}function Ya(l){return l.filter(Ws)}exports.AnnotationManager=Vs;exports.Button=Qr;exports.Card=$r;exports.DsaAuthManager=Za;exports.FolderBrowser=Us;exports.IndexedDBAnnotationCache=Er;exports.MemoryAnnotationCache=sa;exports.SlideViewer=Hs;exports.applyPaperJsPatches=Bs;exports.checkIndexedDBQuota=ss;exports.detectAnnotationFormat=js;exports.dsaAuthStore=hn;exports.extractAnnotationElements=zs;exports.filterLargeImages=Ya;exports.formatBytes=Qn;exports.geoJSONFeatureToDSAElement=Ds;exports.geoJSONToDSAElements=Fs;exports.hasLargeImage=Ws;exports.isDSAAnnotation=Ns;exports.isGeoJSONFeatureCollection=Dr;exports.logQuotaInfo=ua;exports.requestPersistentStorage=la;exports.useDsaAuth=Gs;
|
|
1752
|
+
}`)),Pe.appendChild(ge),pe=p.__paperscript__,delete p.__paperscript__,Pe.removeChild(ge)}else pe=Function(oe,q);var Re=pe&&pe.apply(Q,te),je=Re||{};return c.each(K,function(He){var Qe=je[He];Qe&&(H[He]=Qe)}),X&&(je.onResize&&X.setOnResize(je.onResize),X.emit("resize",{size:X.size,delta:new D}),je.onFrame&&X.setOnFrame(je.onFrame),X.requestUpdate()),Re}function z(q){if(/^text\/(?:x-|)paperscript$/.test(q.type)&&A.getAttribute(q,"ignore")!=="true"){var Q=A.getAttribute(q,"canvas"),G=p.getElementById(Q),X=q.src||q.getAttribute("data-src"),H=A.hasAttribute(q,"async"),K="data-paper-scope";if(!G)throw new Error('Unable to find canvas with id "'+Q+'"');var ie=A.get(G.getAttribute(K))||new A().setup(G);return G.setAttribute(K,ie._id),X?lt.request({url:X,async:H,mimeType:"text/plain",onLoad:function(oe){O(oe,ie,X)}}):O(q.innerHTML,ie,q.baseURI),q.setAttribute("data-paper-ignore","true"),ie}}function F(){c.each(p&&p.getElementsByTagName("script"),z)}function ee(q){return q?z(q):F()}return a&&(p.readyState==="complete"?setTimeout(F):Nt.add(a,{load:F})),{compile:N,execute:O,load:ee,parse:u,calculateBinary:T,calculateUnary:R}}).call(this);var jt=new(A.inject(c.exports,{Base:c,Numerical:j,Key:Mi,DomEvent:Nt,DomElement:si,document:p,window:a,Symbol:ct,PlacedSymbol:ni}));return jt.agent.node&&Zr(jt),typeof n=="function"&&n.amd?n("paper",jt):l&&(l.exports=jt),jt}).call(es,typeof self=="object"?self:null)})(as);var Gn=as.exports;const Va=ts(Gn),Ua=ia({__proto__:null,default:Va},[Gn]);function Bs(){if(!window.__paperJsPatchesApplied)try{if(!Ua||!Gn.View||!Gn.View.prototype){console.warn("[bdsa-react-components] Paper.js View not found, cannot apply patches");return}const l=Gn.View.prototype,w=l.getBounds;l.getBounds=function(){if(!this._transformBounds)return null;try{return w.call(this)}catch{return null}};const n=l.getCenter;l.getCenter=function(){if(!this._transformBounds)return null;try{return n.call(this)}catch{return null}};const a=l.setCenter;if(l.setCenter=function(...p){if(this._transformBounds)try{return a.apply(this,p)}catch{}},l._handleMouseEvent){const p=l._handleMouseEvent;l._handleMouseEvent=function(...c){if(this._transformBounds)try{return p.apply(this,c)}catch{}}}console.log("[bdsa-react-components] Applied Paper.js runtime patches"),window.__paperJsPatchesApplied=!0}catch(l){console.warn("[bdsa-react-components] Failed to apply Paper.js patches:",l)}}function Dr(l){if(!l||typeof l!="object")return!1;const w=l;return w.type==="FeatureCollection"&&Array.isArray(w.features)}function Ns(l){if(!l||typeof l!="object")return!1;const w=l;return!!(Array.isArray(w.elements)||w.annotation&&typeof w.annotation=="object"&&Array.isArray(w.annotation.elements))}function Ds(l){const w=l.geometry,n=l.properties||{},a=n.lineColor||n.stroke||"#ff0000",p=n.fillColor||n.fill||"rgba(255,0,0,0.3)",c=n.lineWidth||n["stroke-width"]||1,C=n.group||n.id,A=n.label||n.name;switch(w.type){case"Polygon":{const m=w.coordinates;if(!m||m.length===0)return null;const k=m[0];return!k||k.length<3?null:{type:"polyline",points:k.map(L=>[L[0],L[1]]),closed:!0,lineColor:String(a),fillColor:String(p),lineWidth:Number(c),group:C?String(C):void 0,label:A?String(A):void 0}}case"LineString":{const m=w.coordinates;return!m||m.length<2?null:{type:"polyline",points:m.map(k=>[k[0],k[1]]),closed:!1,lineColor:String(a),fillColor:String(p),lineWidth:Number(c),group:C?String(C):void 0,label:A?String(A):void 0}}case"Point":{const m=w.coordinates;if(!m||m.length<2)return null;const[k,L]=m,j=c*2||2,J=[];for(let D=0;D<8;D++){const fe=D/8*2*Math.PI;J.push([k+j*Math.cos(fe),L+j*Math.sin(fe)])}return{type:"polyline",points:J,closed:!0,lineColor:String(a),fillColor:String(p),lineWidth:Number(c),group:C?String(C):void 0,label:A?String(A):void 0}}case"MultiPolygon":case"MultiLineString":case"MultiPoint":return console.warn(`GeoJSON ${w.type} not yet supported, skipping feature`),null;default:return console.warn(`Unknown GeoJSON geometry type: ${w.type}`),null}}function Fs(l){const w=[];for(const n of l.features){const a=Ds(n);a&&w.push(a)}return w}function zs(l){var n;if(!l||typeof l!="object")return[];if(Dr(l))return console.log("Detected GeoJSON FeatureCollection format, transforming to DSA elements..."),Fs(l);const w=l;return w.elements&&Array.isArray(w.elements)?(console.log("Detected DSA format (root level elements)"),w.elements):(n=w.annotation)!=null&&n.elements&&Array.isArray(w.annotation.elements)?(console.log("Detected DSA format (nested annotation.elements)"),w.annotation.elements):(console.warn("Unknown annotation format, expected GeoJSON FeatureCollection or DSA format. Got:",{type:l.type,hasElements:"elements"in w,hasAnnotation:"annotation"in w,keys:Object.keys(l).slice(0,10)}),[])}function js(l){return!l||typeof l!="object"?"unknown":Dr(l)?"geojson":Ns(l)?"dsa":"unknown"}Bs();function Ga(l){const w={};if(l._id!==void 0&&(w._id=l._id),l._version!==void 0&&(w._version=l._version),l._modelType!==void 0&&(w._modelType=l._modelType),l.updated!==void 0&&(w.updated=l.updated),l.modified!==void 0&&(w.modified=l.modified),l._accessLevel!==void 0&&(w._accessLevel=l._accessLevel),l.annotation&&typeof l.annotation=="object"){const p=l.annotation;p.name!==void 0&&(w.name=p.name)}const n=JSON.stringify(w,Object.keys(w).sort());let a=5381;for(let p=0;p<n.length;p++)a=(a<<5)+a+n.charCodeAt(p),a=a&a;return(a>>>0).toString(16)}function Wa(l,w){if(l)return l;if(w)if(w instanceof Headers){const n=w.get("Authorization")||w.get("Girder-Token");if(n)return n.startsWith("Bearer ")?n.substring(7):n}else if(Array.isArray(w)){for(const[n,a]of w)if(n.toLowerCase()==="authorization"||n.toLowerCase()==="girder-token")return a.startsWith("Bearer ")?a.substring(7):a}else{const n=w,a=n.Authorization||n.authorization||n["Girder-Token"]||n["girder-token"];if(a)return a.startsWith("Bearer ")?a.substring(7):a}}function Sr(l,w){if(!w)return l;const n=l.includes("?")?"&":"?";return`${l}${n}token=${encodeURIComponent(w)}`}function In(l,w){const n=Math.max(0,Math.min(1,w));if(l.startsWith("rgba(")){const a=l.match(/(\d+(?:\.\d+)?)/g);if(a&&a.length>=3){const p=a[0],c=a[1],C=a[2];return`rgba(${p}, ${c}, ${C}, ${n})`}}else if(l.startsWith("rgb(")){const a=l.match(/(\d+(?:\.\d+)?)/g);if(a&&a.length>=3){const p=a[0],c=a[1],C=a[2];return`rgba(${p}, ${c}, ${C}, ${n})`}}else if(l.startsWith("#")){const a=l.replace("#","");let p,c,C;return a.length===3?(p=parseInt(a[0]+a[0],16),c=parseInt(a[1]+a[1],16),C=parseInt(a[2]+a[2],16)):(p=parseInt(a.substring(0,2),16),c=parseInt(a.substring(2,4),16),C=parseInt(a.substring(4,6),16)),`rgba(${p}, ${c}, ${C}, ${n})`}return l}const Vn={documentProperties:[{key:"id",label:"ID",formatter:l=>String(l)},{key:"elementCount",label:"Elements",formatter:l=>String(l)},{key:"totalPoints",label:"Points/Vertices",formatter:l=>String(l)},{key:"types",label:"Types",formatter:l=>Array.isArray(l)&&l.length>0?l.join(", "):"N/A",show:!0},{key:"filteredCount",label:"Filtered",formatter:(l,w)=>w.filteredCount!==void 0&&w.filteredCount>0?`${w.filteredCount} element(s) (${w.filteredPoints||0} points) skipped`:"None",show:!0}],showFetchedSection:!0,showProvidedSection:!0,showTotalSection:!0,headerText:"Annotation Information"},Hs=wt.forwardRef(({imageInfo:l,annotations:w=[],annotationIds:n=[],apiBaseUrl:a,onViewerReady:p,onAnnotationClick:c,defaultAnnotationColor:C="#ff0000",strokeWidth:A=2,osdOptions:m={},className:k="",height:L="600px",width:j="100%",showAnnotationInfo:J=!1,annotationInfoConfig:D,maxPointsPerAnnotation:fe=1e4,maxTotalPoints:le=1e5,fetchFn:$,apiHeaders:Ae,authToken:Xe,tokenQueryParam:Ve=!1,showAnnotationControls:Lt=!1,defaultAnnotationOpacity:vt=1,annotationOpacities:tt,visibleAnnotations:Kt,onAnnotationReady:Te,annotationCache:Jt,disableCache:At=!1,disableVisibilityCheck:ni=!1,annotationHeaders:ct},fi)=>{var o,u;const pt=wt.useRef(null),[ei,gt]=wt.useState(null),[Ut,mi]=wt.useState(null),[Xt,_i]=wt.useState(null),[Vi,ji]=wt.useState([]),[Yt,Li]=wt.useState([]),bt=wt.useRef(null),li=wt.useRef(""),[It,Di]=wt.useState(vt),si=wt.useMemo(()=>At||Jt===null?null:Jt||new Er,[Jt,At]),Nt=wt.useRef(!0);wt.useEffect(()=>(Nt.current=!0,()=>{Nt.current=!1}),[]);const[ui,Hi]=wt.useState(!ni);wt.useEffect(()=>{if(ni){Hi(!0);return}if(!pt.current)return;const f=new IntersectionObserver(v=>{v.forEach(b=>{b.isIntersecting&&b.intersectionRatio>.1?Hi(!0):Hi(!1)})},{threshold:.1,rootMargin:"50px"});return f.observe(pt.current),()=>{pt.current&&f.unobserve(pt.current)}},[ni]),wt.useEffect(()=>{const f=R=>{if(!R)return!1;const N=R instanceof Error?R.message:String(R);if(N&&typeof N=="string"){const O=N.toLowerCase();if(O.includes("_transformbounds")||O.includes("transformbounds")||O.includes("cannot read properties of null")||O.includes("reading '_transformbounds'")||O.includes('reading "_transformbounds"'))return!0}if(R instanceof Error&&R.stack){const O=R.stack.toLowerCase();if(O.includes("_transformbounds")||O.includes("transformbounds")||O.includes("getbounds"))return!0}if(R instanceof ErrorEvent){const O=R.filename||"";if(O.includes("osd-paperjs-annotation")||O.includes("annotation.js")){const z=R.message||String(R);if(z.includes("null")||z.includes("_transformBounds"))return!0}}return!1},v=R=>{const N=R instanceof ErrorEvent&&R.error||R;return f(N)?(R instanceof ErrorEvent&&(R.preventDefault(),R.stopPropagation()),!0):!1},b=R=>{const N=R.reason;return f(N)?(R.preventDefault(),R.stopPropagation(),!0):!1};window.addEventListener("error",v,!0),window.addEventListener("unhandledrejection",b,!0);const T=window.onerror;return window.onerror=(R,N,O,z,F)=>f(F)||f(R)?!0:T?T(R,N,O,z,F):!1,()=>{window.removeEventListener("error",v,!0),window.removeEventListener("unhandledrejection",b,!0),window.onerror=T}},[]);const Fi=wt.useCallback(f=>{if(!f||!f.view)return!1;const v=f.view;return!(v._transformBounds===null||v._transformBounds===void 0||typeof f.view.draw!="function")},[]),Ci=wt.useCallback(f=>{if(Nt.current){if(!Fi(f)){console.warn("Paper.js not fully initialized, skipping draw operation");return}try{f.view&&typeof f.view.draw=="function"&&f.view.draw()}catch(v){v instanceof Error&&v.message.includes("_transformBounds")?console.warn("Paper.js draw operation skipped (component likely unmounting or hidden)"):console.error("Error drawing Paper.js view:",v)}}},[Fi]),Mi=wt.useMemo(()=>Vi.map(f=>`${f.id}:${f.left}:${f.top}:${f.width}:${f.height}`).join("|"),[Vi]),ri=wt.useRef(`osd-viewer-${Math.random().toString(36).substr(2,9)}`),Z=wt.useRef(!1),_e=wt.useRef(""),Ge=wt.useRef(p);wt.useEffect(()=>{Ge.current=p},[p]);const lt=wt.useRef(c);wt.useEffect(()=>{lt.current=c},[c]);const st=wt.useMemo(()=>Wa(Xe,Ae),[Xe,Ae]),Rt=wt.useMemo(()=>{const f=$||fetch;return!Ve||!st?f:(v,b)=>{const T=Sr(v,st);return f(T,b)}},[$,st,Ve]),et=wt.useMemo(()=>{if(l.dziUrl)return Ve&&st?Sr(l.dziUrl,st):l.dziUrl},[l.dziUrl,st,Ve]),$t=wt.useMemo(()=>et||l.dziUrl||`${l.imageId}-${l.baseUrl}`,[et,l.dziUrl,l.imageId,l.baseUrl]),jt=wt.useMemo(()=>{var f;return Array.isArray(w)?JSON.stringify(w.map(v=>({id:v.id,left:v.left,top:v.top,width:v.width,height:v.height}))):w&&typeof w=="object"&&"type"in w&&w.type==="FeatureCollection"?JSON.stringify(((f=w.features)==null?void 0:f.map(v=>({id:v.id})))||[]):"[]"},[w]),t=wt.useMemo(()=>!Array.isArray(w)&&w&&typeof w=="object"&&"type"in w&&w.type==="FeatureCollection"?w.features.map(f=>{var v,b,T,R;if(f.geometry.type==="Polygon"){const N=f.geometry.coordinates[0];if(N.length>=4){const[O,z]=N[0],[F,,,ee]=N[2],q=F-O,Q=ee-z;return{id:f.id||((v=f.properties)==null?void 0:v.id),left:O,top:z,width:q,height:Q,color:((b=f.properties)==null?void 0:b.color)||C,group:(T=f.properties)==null?void 0:T.group,label:(R=f.properties)==null?void 0:R.label,...f.properties}}}return null}).filter(f=>f!==null):Array.isArray(w)?[...w]:[],[jt,C]);wt.useEffect(()=>{if(!pt.current||!ui&&!Z.current||Z.current)return;let f=null,v=null,b=null;const T=setTimeout(()=>{var R,N,O;if(!(!Nt.current||!pt.current)&&ui)try{Z.current=!0,_e.current=$t,pt.current.id=ri.current;const z={id:ri.current,prefixUrl:"https://openseadragon.github.io/openseadragon/images/",maxImageCacheCount:1e3,crossOriginPolicy:"Anonymous",autoHideControls:!1,debugMode:!1,showNavigator:!0,showZoomControl:!0,showHomeControl:!0,showFullPageControl:!0,...Ae?{ajaxHeaders:Ae}:{},...m};if(f=ra(z),v=f.createPaperOverlay(),Nt.current&&mi(v),b=new qr.AnnotationToolkit(f,{overlay:v}),b&&typeof((N=(R=b.overlay)==null?void 0:R.paperScope)==null?void 0:N.view)<"u"){const F=b.overlay.paperScope;if(F&&F.view){const ee=F.view,q=G=>{try{return G!=null&&typeof G._transformBounds<"u"&&G._transformBounds!==null}catch{return!1}},Q=new Proxy(ee,{get:(G,X)=>{var H;if(X==="getBounds"||X==="_transformBounds")return function(...K){var ie,oe;try{return!G||!q(G)?X==="getBounds"?{x:0,y:0,width:0,height:0}:null:X==="getBounds"?((ie=ee.getBounds)==null?void 0:ie.apply(G,K))||{x:0,y:0,width:0,height:0}:G[X]}catch(te){if(te instanceof Error){const pe=((oe=te.message)==null?void 0:oe.toLowerCase())||"";if(pe.includes("_transformbounds")||pe.includes("transformbounds")||pe.includes("cannot read properties of null"))return X==="getBounds"?{x:0,y:0,width:0,height:0}:null}throw te}};try{const K=G[X];return X==="_transformBounds"&&K==null?()=>({x:0,y:0,width:0,height:0}):K}catch(K){if(K instanceof Error){const ie=((H=K.message)==null?void 0:H.toLowerCase())||"";if(ie.includes("_transformbounds")||ie.includes("null"))return X==="_transformBounds"?()=>({x:0,y:0,width:0,height:0}):null}throw K}}});try{F.view=Q}catch{}}}if(Nt.current&&_i(b),!f)return;if(f.addHandler("open-failed",F=>{console.warn("OpenSeadragon: Open failed",F)}),f.addHandler("open",F=>{!Nt.current||!f||(console.log("OpenSeadragon: Image opened",F),gt(f),Ge.current&&Ge.current(f))}),f.world.addHandler("add-item",F=>{if(!Nt.current)return;const ee=F;console.log("Tiled image added:",ee.item),bt.current=ee.item}),et)f.open(et);else{if(!l.imageId||!l.width||!l.height||!l.tileWidth||!l.levels||!l.baseUrl){console.error("SlideViewer: If dziUrl is not provided, all manual fields (imageId, width, height, tileWidth, levels, baseUrl) are required");return}const F={width:l.width,height:l.height,tileSize:l.tileWidth,minLevel:0,maxLevel:l.levels-1,getTileUrl:(ee,q,Q)=>{const G=`${l.baseUrl}/wsi/files/tile/${l.imageId}/${ee}/${q}/${Q}`;return Ve&&st?Sr(G,st):G}};f&&f.addTiledImage({tileSource:F,success:()=>{!Nt.current||!f||(gt(f),Ge.current&&Ge.current(f))}})}}catch(z){if(console.error("Error initializing SlideViewer:",z),Z.current=!1,z instanceof Error&&((O=z.message)!=null&&O.toLowerCase().includes("_transformbounds")))return}},100);return()=>{clearTimeout(T);const R=$t!==_e.current;if(!Nt.current||R){if(R&&(_e.current=$t),b)try{b.destroy()}catch(O){console.warn("Error destroying annotation toolkit:",O)}if(v)try{v.destroy()}catch(O){console.warn("Error destroying paper overlay:",O)}if(f)try{if(typeof f.isDestroyed=="boolean"&&f.isDestroyed)return;f.destroy()}catch(O){console.warn("Error destroying OpenSeadragon viewer:",O)}Nt.current||(Z.current=!1)}}},[$t,m]),wt.useEffect(()=>{if(!Nt.current)return;if(!n||n.length===0||!a){ji(v=>v.length===0?v:[]),Li(v=>v.length===0?v:[]);return}(async()=>{try{console.log(`Fetching ${n.length} annotation(s) from DSA API...`);const v=Rt,b=n.map(async q=>{var oe,te,pe,Se,Ce,Ie;const Q=ct?ct instanceof Map?ct.get(q):ct[String(q)]:void 0,G=Q?Ga(Q):void 0;if(si){try{const ge=await si.get(q,G);if(ge!=null){if(ge&&typeof ge=="object"&&(ge.elements||((oe=ge.annotation)==null?void 0:oe.elements)||((te=ge.annotation)==null?void 0:te.elements)===null||Array.isArray((pe=ge.annotation)==null?void 0:pe.elements)))return console.log(`Cache hit for annotation ${q}${G?` (version hash: ${G})`:""}`,{hasElements:!!(ge!=null&&ge.elements)||!!((Se=ge==null?void 0:ge.annotation)!=null&&Se.elements),elementCount:Array.isArray(ge==null?void 0:ge.elements)?ge.elements.length:Array.isArray((Ce=ge==null?void 0:ge.annotation)==null?void 0:Ce.elements)?ge.annotation.elements.length:0}),ge;console.warn(`Invalid cached data format for annotation ${q}, clearing cache and fetching fresh...`,{type:typeof ge,keys:ge&&typeof ge=="object"?Object.keys(ge):"N/A",hasElements:!!(ge!=null&&ge.elements)||!!((Ie=ge==null?void 0:ge.annotation)!=null&&Ie.elements)}),await si.delete(q).catch(Re=>console.warn("Failed to delete invalid cache entry:",Re))}}catch(ge){console.warn(`Error reading from cache for annotation ${q}, fetching from API:`,ge)}console.log(G?`Cache miss or version mismatch for annotation ${q} (current version hash: ${G}), fetching from API...`:`Cache miss for annotation ${q}, fetching from API...`)}const X=`${a}/annotation/${q}`;console.log(`Fetching annotation ${q} from: ${X}`);const H={};Ae&&(H.headers=Ae);const K=await v(X,H);if(!K.ok)return console.warn(`Failed to fetch annotation ${q}:`,K.statusText,K.status),null;const ie=await K.json();return console.log(`Successfully fetched annotation ${q}:`,ie),si&&ie&&await si.set(q,ie,{versionHash:G}),ie}),T=await Promise.all(b);if(!Nt.current){console.log("Component unmounted during annotation fetch, skipping state update");return}const R=[];let N=0,O=0;const z=T.filter(q=>q!=null).map((q,Q)=>{const G=String(n[Q]),X=new Set,H=[];let K=0,ie=0,oe=0;const te=js(q);console.log(`Annotation ${G} format: ${te}`);const pe=zs(q);for(const Se of pe)if(Se&&typeof Se=="object"){const Ce=Se;if(Ce.type&&X.add(Ce.type),Ce.type==="rectangle"&&Ce.x!==void 0&&Ce.y!==void 0&&Ce.width!==void 0&&Ce.height!==void 0)4>fe?(ie++,oe+=4,console.warn(`Skipping rectangle annotation ${Ce.group||H.length} in document ${G}: has 4 points (exceeds limit of ${fe})`)):(K+=4,H.push({id:Ce.group||H.length,left:Ce.x,top:Ce.y,width:Ce.width,height:Ce.height,color:Ce.lineColor||C,group:Ce.group,label:Ce.label,annotationType:"rectangle",element:Ce,documentId:G}));else if(Ce.type==="polyline"&&Ce.points&&Ce.points.length>=2){const Ie=Ce.points.length;if(Ie>fe)ie++,oe+=Ie,console.warn(`Skipping polyline annotation ${Ce.group||H.length} in document ${G}: has ${Ie} points (exceeds limit of ${fe})`);else{K+=Ie;const ge=Ce.points.map(Mt=>Mt[0]),Pe=Ce.points.map(Mt=>Mt[1]),Re=Math.min(...ge),je=Math.min(...Pe),He=Math.max(...ge),Qe=Math.max(...Pe),_t=He-Re,Ot=Qe-je;H.push({id:Ce.group||H.length,left:Re,top:je,width:_t,height:Ot,color:Ce.lineColor||C,group:Ce.group,label:Ce.label,annotationType:"polyline",points:Ce.points,closed:Ce.closed,fillColor:Ce.fillColor,element:Ce,documentId:G})}}}return R.push({id:G,elementCount:H.length,totalPoints:K,types:Array.from(X),filteredCount:ie>0?ie:void 0,filteredPoints:oe>0?oe:void 0}),N+=ie,O+=oe,H}).flat();let F=z;const ee=z.reduce((q,Q)=>Q.annotationType==="polyline"&&Q.points?q+Q.points.length:q+4,0);if(ee>le){console.warn(`Total points (${ee}) exceeds limit (${le}). Filtering annotations starting from largest ones...`);const q=z.map(G=>({annotation:G,pointCount:G.annotationType==="polyline"&&G.points?G.points.length:4}));q.sort((G,X)=>X.pointCount-G.pointCount);let Q=0;F=[];for(const{annotation:G,pointCount:X}of q)Q+X<=le?(F.push(G),Q+=X):console.warn(`Skipping annotation ${G.id}: adding ${X} points would exceed total limit (${Q+X} > ${le})`);console.warn(`Filtered annotations: ${z.length} → ${F.length} (${z.length-F.length} skipped)`)}if(N>0&&console.warn(`Annotation document(s) ${n.join(", ")}: ${N} annotation(s) filtered due to per-annotation point limits (${O} total points skipped)`),console.log(`Parsed ${F.length} annotation feature(s) from ${n.length} annotation document(s)`),!Nt.current){console.log("Component unmounted after annotation parsing, skipping state update");return}ji(F),Li(R)}catch(v){console.error("Error fetching annotations:",v),Nt.current&&ji([])}})()},[n?JSON.stringify(n):"",a||"",C,fe,le,Rt,si,ct]),wt.useEffect(()=>{if(!ei||!Ut||!Xt)return;const f=Ut.paperScope;if(!f||!f.project)return;const v=bt.current;if(!v||typeof v.addPaperItem!="function")return;const b=[...t,...Vi],T=`${jt}:${Mi}`;if(li.current===T)return;if(li.current=T,console.log(`Rendering ${b.length} total annotation(s)`),b.length===0){try{const O=Xt.getFeatures();if(O&&Array.isArray(O))for(const z of O)try{z.remove()}catch(F){console.warn("Error removing feature:",F)}}catch(O){console.warn("Could not clear existing features:",O)}return}console.log(`About to render ${b.length} annotations, tiledImage:`,v);try{if(v.paperItems&&Array.isArray(v.paperItems)&&v.paperItems.length>0){const O=[...v.paperItems].reverse();for(const z of O)try{z&&typeof z.remove=="function"&&z.remove()}catch{}}try{const O=Xt.getFeatures();if(O&&Array.isArray(O)&&O.length>0){const z=O.filter(F=>F!=null&&typeof F.remove=="function");for(const F of z)try{F.remove()}catch{}}}catch{}}catch(O){console.warn("Error clearing existing annotations:",O)}const R=tt instanceof Map?new Map(Array.from(tt.entries()).map(([O,z])=>[String(O),z])):tt?new Map(Object.entries(tt).map(([O,z])=>[String(O),z])):null,N=new Set;for(const O of b)try{const z=O.documentId,F=z!==void 0?String(z):void 0;console.log(`SlideViewer: Processing annotation feature id=${O.id}, documentId=${z}, lookupId=${F}`);let ee=It;if(R&&F!==void 0){const Q=R.get(F);Q!==void 0&&(ee=Q)}if(console.log(`SlideViewer: Annotation opacity=${ee}, will ${ee<=0?"skip":"render"}`),ee<=0){console.log("SlideViewer: Skipping annotation with opacity 0 (hidden)");continue}let q;if(O.annotationType==="polyline"&&O.points&&Array.isArray(O.points)){const Q=new f.Path,G=O.color||C;Q.strokeColor=In(G,ee),Q.strokeWidth=A;const X=O.fillColor||"rgba(0, 0, 0, 0)";Q.fillColor=In(X,ee),O.points.forEach((H,K)=>{K===0?Q.moveTo(H[0],H[1]):Q.lineTo(H[0],H[1])}),O.closed&&Q.closePath(),q=Q}else{const Q=new f.Rectangle(O.left,O.top,O.width,O.height),G=new f.Path.Rectangle(Q),X=O.color||C;G.strokeColor=In(X,ee),G.strokeWidth=A,G.fillColor=In("rgba(0, 0, 0, 0)",ee),q=G}if(q.data={annotation:O},q.annotationId=O.id,lt.current&&(q.onClick=Q=>{var G;(G=lt.current)==null||G.call(lt,O)}),q.style={rescale:{strokeWidth:A}},v.addPaperItem(q),q&&typeof q=="object")try{qr.AnnotationToolkit.registerFeature(q)}catch(Q){console.warn("Failed to register feature with toolkit:",Q)}F!==void 0?(N.add(F),console.log(`SlideViewer: Added documentId '${F}' to renderedDocumentIds. Set now has:`,Array.from(N))):console.warn(`SlideViewer: Cannot track document ID - lookupId is undefined for annotation id=${O.id}`)}catch(z){console.error(`Error rendering annotation ${O.id}:`,z,O)}Ci(f),console.log(`Finished rendering ${b.length} annotations`),console.log(`SlideViewer: onAnnotationReady is ${Te?"defined":"undefined"}, renderedDocumentIds has ${N.size} items:`,Array.from(N)),Te&&N.size>0?setTimeout(()=>{console.log(`SlideViewer: setTimeout fired, calling onAnnotationReady for ${N.size} document(s)`),N.forEach(O=>{try{console.log(`SlideViewer: Calling onAnnotationReady('${O}')`),Te(O)}catch(z){console.error(`Error calling onAnnotationReady for ${O}:`,z)}})},100):console.warn(`SlideViewer: Not calling onAnnotationReady - callback is ${Te?"":"not "}defined, renderedDocumentIds has ${N.size} items`)},[ei,Ut,Xt,jt,Mi,A,It,tt,Kt,Te]),wt.useEffect(()=>{var v;if(!ei||!Ut||!Xt)return;const f=Ut.paperScope;if(!(!f||!f.project))try{const b=Xt.getFeatures();if(b&&Array.isArray(b)){const T=tt instanceof Map?tt:tt?new Map(Object.entries(tt).map(([N,O])=>[String(N),O])):null;let R=!1;for(const N of b)try{if(N&&typeof N=="object"){const O=N,z=(v=O.data)==null?void 0:v.annotation;if(!z)continue;const F=z.documentId,ee=F!==void 0?String(F):void 0;if(ee===void 0)continue;let q=It;if(T&&ee!==void 0){const H=T.get(ee);H!==void 0&&(q=H)}if(q<=0){try{const H=z.color||C,K=z.fillColor||"rgba(0, 0, 0, 0)";O.strokeColor&&(O.strokeColor=In(H,0),R=!0),O.fillColor&&(O.fillColor=In(K,0),R=!0)}catch{try{O.remove&&(O.remove(),R=!0)}catch(K){console.warn("Could not hide annotation:",K)}}continue}let Q=It;if(T&&ee!==void 0&&T.has(ee)){const H=T.get(ee);H!==void 0&&(Q=H)}const G=z.color||C,X=z.fillColor||"rgba(0, 0, 0, 0)";O.strokeColor&&(O.strokeColor=In(G,Q),R=!0),O.fillColor&&(O.fillColor=In(X,Q),R=!0)}}catch(O){console.warn("Error updating annotation opacity:",O)}R&&Ci(f)}}catch(b){console.warn("Could not update annotation opacity:",b)}},[It,tt,Kt,ei,Ut,Xt,vt,C,Ci]);const r=wt.useMemo(()=>({documentProperties:(D==null?void 0:D.documentProperties)??Vn.documentProperties??[],showFetchedSection:(D==null?void 0:D.showFetchedSection)??Vn.showFetchedSection??!0,showProvidedSection:(D==null?void 0:D.showProvidedSection)??Vn.showProvidedSection??!0,showTotalSection:(D==null?void 0:D.showTotalSection)??Vn.showTotalSection??!0,headerText:(D==null?void 0:D.headerText)??Vn.headerText??"Annotation Information"}),[D]),h={width:typeof j=="number"?`${j}px`:j,height:typeof L=="number"?`${L}px`:L};return Je.jsxs("div",{ref:fi,className:`bdsa-slide-viewer ${k}`,style:h,children:[Je.jsx("div",{ref:pt,className:"bdsa-slide-viewer__container"}),(J||Lt)&&Je.jsxs("div",{className:"bdsa-slide-viewer__sidebar",children:[Lt&&Je.jsxs("div",{className:"bdsa-slide-viewer__controls",children:[Je.jsx("div",{className:"bdsa-slide-viewer__controls-header",children:Je.jsx("strong",{children:"Annotation Controls"})}),Je.jsxs("div",{className:"bdsa-slide-viewer__controls-section",children:[Je.jsxs("div",{className:"bdsa-slide-viewer__controls-label",children:["Opacity: ",Math.round(It*100),"%"]}),Je.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:It,onChange:f=>Di(parseFloat(f.target.value)),className:"bdsa-slide-viewer__opacity-slider"})]})]}),J&&(Array.isArray(w)&&w.length>0||!Array.isArray(w)&&w&&"type"in w&&w.type==="FeatureCollection"&&((o=w.features)==null?void 0:o.length)>0||Yt.length>0||Vi.length>0)&&Je.jsxs("div",{className:"bdsa-slide-viewer__annotation-info",children:[Je.jsx("div",{className:"bdsa-slide-viewer__annotation-info-header",children:Je.jsx("strong",{children:r.headerText})}),r.showFetchedSection&&Yt.length>0&&Je.jsxs("div",{className:"bdsa-slide-viewer__annotation-info-section",children:[Je.jsx("div",{className:"bdsa-slide-viewer__annotation-info-title",children:"Fetched from DSA API:"}),Yt.map(f=>Je.jsx("div",{className:"bdsa-slide-viewer__annotation-info-item",children:r.documentProperties.filter(v=>v.show!==!1).map(v=>{const b=f[v.key],T=v.formatter?v.formatter(b,{...f,totalPoints:f.totalPoints??0}):String(b??"N/A");return Je.jsxs("div",{children:[v.label,": ",T]},v.key)})},f.id))]}),r.showProvidedSection&&(Array.isArray(w)&&w.length>0||!Array.isArray(w)&&w&&w.type==="FeatureCollection")&&Je.jsxs("div",{className:"bdsa-slide-viewer__annotation-info-section",children:[Je.jsx("div",{className:"bdsa-slide-viewer__annotation-info-title",children:"Provided Annotations:"}),Je.jsx("div",{className:"bdsa-slide-viewer__annotation-info-item",children:Array.isArray(w)?Je.jsxs("div",{children:["Count: ",w.length]}):Je.jsxs("div",{children:["GeoJSON FeatureCollection with ",((u=w.features)==null?void 0:u.length)||0," features"]})})]}),r.showTotalSection&&Je.jsxs("div",{className:"bdsa-slide-viewer__annotation-info-section",children:[Je.jsx("div",{className:"bdsa-slide-viewer__annotation-info-title",children:"Total Rendered:"}),Je.jsxs("div",{className:"bdsa-slide-viewer__annotation-info-item",children:[Vi.length+(Array.isArray(w)?w.length:0)," annotation(s)"]})]})]})]})]})});Hs.displayName="SlideViewer";const Vs=wt.forwardRef(({imageId:l,apiBaseUrl:w,limit:n=50,fetchFn:a,apiHeaders:p,onAnnotationsLoaded:c,onError:C,showDebugPanel:A=!1,onAnnotationLoadChange:m,onAnnotationVisibilityChange:k,onAnnotationOpacityChange:L,onAnnotationReady:j,slideViewerOnAnnotationReady:J,onLoadedAnnotationIdsChange:D,onAnnotationLoad:fe,onAnnotationHide:le,onAnnotationStateChange:$,onAnnotationOpacitiesChange:Ae,onAnnotationHeadersChange:Xe,loadedAnnotations:Ve,visibleAnnotations:Lt,annotationOpacities:vt,annotationCache:tt,disableCache:Kt=!1,showDefaultUI:Te=!0,className:Jt="",children:At},ni)=>{const[ct,fi]=wt.useState([]),[pt,ei]=wt.useState(!1),[gt,Ut]=wt.useState(null),[mi,Xt]=wt.useState(null),[_i,Vi]=wt.useState(new Set),[ji,Yt]=wt.useState(new Map),[Li,bt]=wt.useState(new Map),li=wt.useRef(new Map),[It,Di]=wt.useState(null),[si,Nt]=wt.useState(new Set),[ui,Hi]=wt.useState(new Set),Fi=wt.useMemo(()=>Kt||tt===null?null:tt||new Er,[tt,Kt]),Ci=Ve??_i,Mi=Lt??ji,ri=vt??Li,Z=wt.useMemo(()=>Array.from(Ci).sort(),[Ci]);wt.useEffect(()=>{D&&D(Z)},[Z,D]);const _e=wt.useRef(null),Ge=wt.useCallback(()=>{const u=Array.from(Ci).sort(),f=new Map(ri),v=new Map(Mi);if($){const b=_e.current;$({loadedAnnotationIds:u,opacities:f,visibility:v,onAnnotationReady:b||void 0})}Ae&&Ae(f),D&&D(u)},[Ci,ri,Mi,$,Ae,D]),lt=wt.useMemo(()=>Array.from(ri.entries()).sort(([u],[f])=>u.localeCompare(f)),[ri]),st=wt.useMemo(()=>Array.from(Mi.entries()).sort(([u],[f])=>u.localeCompare(f)),[Mi]);wt.useEffect(()=>{Ge()},[Ge,Z,lt,st]);const Rt=wt.useCallback(u=>{const f=String(u);console.log(`[AM] handleAnnotationReadyInternal called for ${f}`),Nt(v=>{const b=v.has(f),T=new Set(v);return T.delete(f),console.log(`[AM] Cleared loading for ${f}. Was loading: ${b}. Still loading:`,Array.from(T)),T}),Fi&&Fi.has(f).then(v=>{v&&Hi(b=>new Set(b).add(f))}).catch(()=>{}),j==null||j(f),J==null||J(f)},[j,J,Fi]);_e.current=Rt,wt.useEffect(()=>{_e.current=Rt,Ge()},[Rt,Ge]);const et=Rt,$t=wt.useCallback(u=>{const f=String(u),v=Ci.has(f);console.log(`[AM] toggleLoad for ${f}. Currently loaded: ${v}`),v?(Ve||Vi(b=>{const T=new Set(b);return T.delete(f),T}),Lt||Yt(b=>{const T=new Map(b);return T.delete(f),T}),vt||bt(b=>{const T=new Map(b);return T.delete(f),T}),m==null||m(f,!1),le==null||le(f),Nt(b=>{const T=new Set(b);return T.delete(f),T})):(console.log(`[AM] Adding ${f} to loading state`),Nt(b=>new Set(b).add(f)),Ve||(console.log(`[AM] toggleLoad: Adding ${f} to internalLoadedAnnotations`),Vi(b=>{const T=new Set(b).add(f);return console.log("[AM] internalLoadedAnnotations now:",Array.from(T)),T})),Lt||Yt(b=>new Map(b).set(f,!0)),vt||bt(b=>new Map(b).set(f,1)),m==null||m(f,!0),fe==null||fe(f))},[Ve,Lt,vt,Ci,m,fe,le,Ge]),jt=wt.useCallback(u=>{const f=ri.get(u)??1;if(f>0){li.current.set(u,f);const b=0;vt||bt(T=>new Map(T).set(u,b)),L==null||L(u,b),Lt||Yt(T=>new Map(T).set(u,!1)),k==null||k(u,!1)}else{const b=li.current.get(u)??1;li.current.delete(u),vt||bt(T=>new Map(T).set(u,b)),L==null||L(u,b),Lt||Yt(T=>new Map(T).set(u,!0)),k==null||k(u,!0)}},[vt,Lt,ri,L,k,Ge]),t=wt.useCallback((u,f)=>{vt||bt(v=>new Map(v).set(u,f)),L==null||L(u,f)},[vt,L,Ge]);wt.useEffect(()=>{if(!l||!w){fi([]),ei(!1),Ut(null),Xt(null);return}(async()=>{ei(!0),Ut(null),Xt(null);try{const f=new URLSearchParams({itemId:l,limit:String(n),offset:"0",sort:"lowerName",sortdir:"1"}),v=`${w}/annotation?${f.toString()}`,b=a||fetch,T={};p&&(T.headers=p),console.log(`AnnotationManager: Fetching annotations from: ${v}`);const R=await b(v,T);if(!R.ok)throw new Error(`Failed to fetch annotations: ${R.status} ${R.statusText}`);const N=await R.json();console.log("AnnotationManager: API response:",N),A&&Xt(JSON.stringify(N,null,2));let O=[];if(Array.isArray(N)?(O=N,console.log(`AnnotationManager: Parsed ${O.length} annotation(s) from array response`)):N&&Array.isArray(N.data)?(O=N.data,console.log(`AnnotationManager: Parsed ${O.length} annotation(s) from paginated response`)):N&&typeof N=="object"?(O=[N],console.log("AnnotationManager: Parsed 1 annotation from single object response")):console.warn("AnnotationManager: Unexpected response format:",typeof N,N),fi(O),console.log(`AnnotationManager: Fetched ${O.length} annotation(s) from API`),O.length>0&&console.log("AnnotationManager: Annotation IDs:",O.map(z=>z._id)),Xe&&O.length>0){const z=new Map;O.forEach(F=>{z.set(String(F._id),F)}),Xe(z)}Fi&&O.length>0?(async()=>{const F=new Set;for(const ee of O){const q=String(ee._id);try{await Fi.has(q)&&F.add(q)}catch{}}Hi(F)})():Hi(new Set),c&&c(O)}catch(f){const v=f instanceof Error?f:new Error(String(f));Ut(v),Xt(null),C&&C(v)}finally{ei(!1)}})()},[l,w,n,a,p,c,C,A,Xe]),wt.useEffect(()=>{if(Xe&&ct.length>0){const u=new Map;ct.forEach(f=>{u.set(String(f._id),f)}),Xe(u)}},[ct,Xe]);const r=wt.useMemo(()=>({annotations:ct,loading:pt,error:gt,annotationIds:ct.map(u=>u._id),loadedAnnotations:Ci,visibleAnnotations:Mi,annotationOpacities:ri,toggleLoad:$t,toggleVisibility:jt,setOpacity:t,handleAnnotationReady:Rt,onAnnotationReady:et,loadingAnnotations:si}),[ct,pt,gt,Ci,Mi,ri,$t,jt,t,Rt,et,si]),h=wt.useRef(null);wt.useImperativeHandle(ni,()=>({getAnnotations:()=>ct,getAnnotation:u=>ct.find(f=>String(f._id)===u),getLoadedAnnotationIds:()=>Array.from(Ci),isAnnotationLoaded:u=>Ci.has(u),isAnnotationVisible:u=>(ri.get(u)??1)>0,getAnnotationOpacity:u=>ri.get(u)??1,isAnnotationLoading:u=>si.has(u),getVisibleAnnotationIds:()=>Array.from(Ci).filter(u=>(ri.get(u)??1)>0),getAnnotationState:()=>({loadedAnnotationIds:Array.from(Ci),opacities:new Map(ri),visibility:new Map(Mi),loadingAnnotationIds:Array.from(si)})}),[ct,Ci,Mi,ri,si]);const o=()=>{if(pt)return Je.jsx("div",{className:"bdsa-annotation-manager__list",children:Je.jsx("div",{className:"bdsa-annotation-manager__empty-state",children:Je.jsx("p",{children:"Loading annotations..."})})});if(gt)return Je.jsx("div",{className:"bdsa-annotation-manager__list",children:Je.jsx("div",{className:"bdsa-annotation-manager__empty-state",style:{color:"#dc3545"},children:Je.jsxs("p",{children:["Error: ",gt.message]})})});if(ct.length===0)return Je.jsx("div",{className:"bdsa-annotation-manager__list",children:Je.jsx("div",{className:"bdsa-annotation-manager__empty-state",children:Je.jsx("p",{children:"No annotations found"})})});const u=Array.from(Ci).length;return Je.jsxs("div",{className:"bdsa-annotation-manager__list",children:[Je.jsxs("div",{className:"bdsa-annotation-manager__list-header",children:[Je.jsxs("h3",{children:["Annotations (",ct.length," total)"]}),Je.jsxs("p",{children:[u," loaded in viewer"]})]}),ct.map(f=>{var z;const v=String(f._id),b=Ci.has(v),T=si.has(v),R=ri.get(v)??1,N=ui.has(v),O=It===v;return Je.jsxs("div",{className:`bdsa-annotation-manager__annotation-card ${b?"bdsa-annotation-manager__annotation-card--loaded":""} ${O?"bdsa-annotation-manager__annotation-card--selected":""}`,onClick:()=>Di(f._id),children:[Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-header",children:[Je.jsx("h4",{className:"bdsa-annotation-manager__annotation-card-title",children:((z=f.annotation)==null?void 0:z.name)||f._id}),Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-meta",children:[f.public===!1&&Je.jsx("span",{className:"bdsa-annotation-manager__annotation-card-badge bdsa-annotation-manager__annotation-card-badge--private",children:"Private"}),f.public===!0&&Je.jsx("span",{className:"bdsa-annotation-manager__annotation-card-badge bdsa-annotation-manager__annotation-card-badge--public",children:"Public"}),N&&Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-cache-indicator-group",children:[Je.jsx("span",{className:"bdsa-annotation-manager__annotation-card-cache-indicator",title:"Cached locally - will load quickly",children:Je.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[Je.jsx("rect",{x:"2",y:"3",width:"20",height:"18",rx:"2"}),Je.jsx("path",{d:"M7 3h10M7 21h10M9 9h6M9 15h6"})]})}),Fi&&typeof Fi.delete=="function"&&Je.jsx("button",{className:"bdsa-annotation-manager__annotation-card-cache-bypass",onClick:async F=>{F.stopPropagation();const ee=String(f._id);try{await Fi.delete(ee),Hi(q=>{const Q=new Set(q);return Q.delete(ee),Q}),Ci.has(ee)&&($t(ee),setTimeout(()=>$t(ee),100))}catch(q){console.warn("Failed to clear cache for annotation:",q)}},title:"Clear cache and refresh this annotation",children:Je.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[Je.jsx("path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"}),Je.jsx("path",{d:"M21 3v5h-5"}),Je.jsx("path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"}),Je.jsx("path",{d:"M3 21v-5h5"})]})})]}),Je.jsx("button",{className:"bdsa-annotation-manager__annotation-card-button bdsa-annotation-manager__annotation-card-button--load bdsa-annotation-manager__annotation-card-button--load-header",onClick:F=>{F.stopPropagation(),$t(String(f._id))},title:b?"Unload annotation":"Load annotation",children:b?Je.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:Je.jsx("line",{x1:"5",y1:"12",x2:"19",y2:"12"})}):Je.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[Je.jsx("line",{x1:"12",y1:"5",x2:"12",y2:"19"}),Je.jsx("line",{x1:"5",y1:"12",x2:"19",y2:"12"})]})})]})]}),Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-details",children:[f._elementCount!==void 0&&Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-detail",children:[Je.jsx("strong",{children:"Elements:"})," ",f._elementCount]}),f._detailsCount!==void 0&&Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-detail",children:[Je.jsx("strong",{children:"Points:"})," ",f._detailsCount.toLocaleString()]})]}),Je.jsx("div",{className:"bdsa-annotation-manager__annotation-card-controls",children:T?Je.jsxs("div",{className:"bdsa-annotation-manager__loading-indicator",children:[Je.jsx("div",{className:"bdsa-annotation-manager__spinner"}),Je.jsx("span",{children:"Loading..."})]}):b?Je.jsxs(Je.Fragment,{children:[Je.jsx("button",{className:"bdsa-annotation-manager__annotation-card-button bdsa-annotation-manager__annotation-card-button--visibility",onClick:F=>{F.stopPropagation(),jt(f._id)},title:R>0?"Hide annotation":"Show annotation",children:Je.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:R>0?Je.jsxs(Je.Fragment,{children:[Je.jsx("path",{d:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"}),Je.jsx("circle",{cx:"12",cy:"12",r:"3"})]}):Je.jsxs(Je.Fragment,{children:[Je.jsx("path",{d:"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"}),Je.jsx("line",{x1:"1",y1:"1",x2:"23",y2:"23"})]})})}),Je.jsxs("div",{className:"bdsa-annotation-manager__annotation-card-opacity",onClick:F=>F.stopPropagation(),children:[Je.jsxs("label",{className:"bdsa-annotation-manager__annotation-card-opacity-label",children:["Opacity: ",Math.round(R*100),"%"]}),Je.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:R,onChange:F=>t(f._id,parseFloat(F.target.value)),onClick:F=>F.stopPropagation(),onMouseDown:F=>F.stopPropagation(),className:"bdsa-annotation-manager__annotation-card-opacity-slider"})]})]}):null})]},f._id)})]})};return Je.jsxs("div",{ref:h,className:`bdsa-annotation-manager ${Jt}`,children:[Te?Je.jsxs(Je.Fragment,{children:[o(),At&&typeof At=="function"?At(r):At]}):At&&typeof At=="function"?At(r):At,A&&mi&&Je.jsxs("div",{className:"bdsa-annotation-manager__debug-panel",children:[Je.jsx("div",{className:"bdsa-annotation-manager__debug-panel-header",children:Je.jsx("strong",{children:"Raw API Response (Debug)"})}),Je.jsx("pre",{className:"bdsa-annotation-manager__debug-panel-content",children:mi})]})]})});Vs.displayName="AnnotationManager";const Us=wt.forwardRef(({apiBaseUrl:l,fetchFn:w,apiHeaders:n,onResourceSelect:a,onSelectionChange:p,showCollections:c=!0,rootId:C,rootType:A,startCollectionId:m,startFolderId:k,parentFolderId:L,foldersPerPage:j=50,className:J="",renderCollection:D,renderFolder:fe,showItems:le=!0,itemsPerPage:$=50,onItemSelect:Ae,renderItem:Xe,persistSelection:Ve=!1,persistSelectionKey:Lt="bdsa_folder_browser_selection",persistExpansion:vt=!1,persistExpansionKey:tt="bdsa_folder_browser_expansion"},Kt)=>{const[Te,Jt]=wt.useState([]),[At,ni]=wt.useState(null),[ct,fi]=wt.useState(null),[pt,ei]=wt.useState({}),[gt,Ut]=wt.useState({}),[mi,Xt]=wt.useState({}),[_i,Vi]=wt.useState({}),[ji,Yt]=wt.useState(()=>{if(vt)try{const v=localStorage.getItem(`${tt}_collections`);if(v){const b=JSON.parse(v);return new Set(b)}}catch(v){console.warn("Failed to restore expanded collections from localStorage:",v)}return new Set}),[Li,bt]=wt.useState(()=>{if(vt)try{const v=localStorage.getItem(`${tt}_folders`);if(v){const b=JSON.parse(v);return new Set(b)}}catch(v){console.warn("Failed to restore expanded folders from localStorage:",v)}return new Set}),[li,It]=wt.useState(null),[Di,si]=wt.useState(!1),[Nt,ui]=wt.useState({}),[Hi,Fi]=wt.useState({}),[Ci,Mi]=wt.useState(null),ri=wt.useRef(null),Z=wt.useRef(!1),_e=wt.useRef(!1),Ge=wt.useCallback(()=>{const v={};return n&&(v.headers=n),v},[n]);wt.useEffect(()=>{if(Ve&&li)try{const v={resource:li,timestamp:Date.now()};localStorage.setItem(Lt,JSON.stringify(v))}catch(v){console.warn("Failed to save selection to localStorage:",v)}},[li,Ve,Lt]),wt.useEffect(()=>{if(Ve&&!_e.current){_e.current=!0;try{const v=localStorage.getItem(Lt);if(v){const b=JSON.parse(v);b.resource&&b.resource._id&&(It(b.resource),vt||(b.resource.type==="collection"?Yt(new Set([b.resource._id])):b.resource.type==="folder"&&bt(new Set([b.resource._id]))))}}catch(v){console.warn("Failed to restore selection from localStorage:",v)}}},[Ve,Lt,vt]),wt.useEffect(()=>{if(vt&&!(Te.length===0&&!At)&&!Z.current){Z.current=!0;try{const v=localStorage.getItem(`${tt}_collections`),b=localStorage.getItem(`${tt}_folders`);if(v){const T=JSON.parse(v);T.length>0&&(Yt(new Set(T)),T.forEach(R=>{const N=Te.find(O=>O._id===R)||((At==null?void 0:At._id)===R?At:null);N&&st(N)}))}if(b){const T=JSON.parse(b);T.length>0&&bt(new Set(T))}}catch(v){console.warn("Failed to restore expansion state:",v)}}},[vt,tt,Te,At,pt]),wt.useEffect(()=>{vt&&(ji.forEach(v=>{var T;if(!(pt[v]!==void 0||((T=mi[v])==null?void 0:T.loaded))&&!Nt[v]){const R=Te.find(N=>N._id===v)||((At==null?void 0:At._id)===v?At:null);R&&st(R)}}),Li.forEach(v=>{var T;let b=null;for(const R of Object.values(pt))if(b=R.find(N=>N._id===v)||null,b)break;b&&(!(pt[v]!==void 0||(T=mi[v])!=null&&T.loaded)&&!Nt[v]&&Rt(b),le&&!(gt[v]!==void 0)&&!Hi[v]&&et(v,b))}))},[vt,ji,Li,pt,gt,Te,At,le,mi,Nt,Hi]),wt.useEffect(()=>{if(vt)try{const v=Array.from(ji);localStorage.setItem(`${tt}_collections`,JSON.stringify(v))}catch(v){console.warn("Failed to save expanded collections to localStorage:",v)}},[ji,vt,tt]),wt.useEffect(()=>{if(vt)try{const v=Array.from(Li);localStorage.setItem(`${tt}_folders`,JSON.stringify(v))}catch(v){console.warn("Failed to save expanded folders to localStorage:",v)}},[Li,vt,tt]),wt.useEffect(()=>{if(!li||!ri.current)return;const v=setTimeout(()=>{var T;const b=(T=ri.current)==null?void 0:T.querySelector(`[data-resource-id="${li._id}"]`);b&&b.scrollIntoView({behavior:"smooth",block:"center"})},100);return()=>clearTimeout(v)},[li]);const lt=wt.useCallback(async()=>{if(!l){Mi(new Error("API base URL is required"));return}si(!0),Mi(null);try{const v=`${l}/collection`,b=w||fetch,T=Ge(),R=await b(v,T);if(!R.ok)throw new Error(`Failed to fetch collections: ${R.status} ${R.statusText}`);const N=await R.json(),O=Array.isArray(N)?N:N.items||[];Jt(O),m&&O.some(z=>z._id===m)&&(Yt(new Set([m])),await st(O.find(z=>z._id===m)))}catch(v){const b=v instanceof Error?v:new Error("Unknown error loading collections");Mi(b),console.error("Error loading collections:",b)}finally{si(!1)}},[l,w,Ge,m]),st=wt.useCallback(async(v,b=!1)=>{if(!l||!(v!=null&&v._id))return;let T=!1,R=0;if(Xt(N=>{const O=N[v._id];return O!=null&&O.loaded&&!b&&(T=!0),b&&O&&(R=O.offset),N}),!T){ui(N=>({...N,[v._id]:!0}));try{const N=new URLSearchParams({parentType:"collection",parentId:v._id});j>0&&(N.append("limit",String(j)),N.append("offset",String(R)));const O=`${l}/folder?${N.toString()}`,z=w||fetch,F=Ge(),ee=await z(O,F);if(!ee.ok){console.warn(`Failed to fetch folders for collection ${v._id}:`,ee.statusText);return}const q=await ee.json();let Q=[],G=!1;Array.isArray(q)?(Q=q,G=j>0&&q.length===j):(Q=q.items||[],G=j>0&&q.total>R+Q.length),ei(X=>({...X,[v._id]:b?[...X[v._id]||[],...Q]:Q})),Xt(X=>({...X,[v._id]:{offset:j>0?R+Q.length:0,hasMore:j>0?G:!1,loaded:!0}})),!b&&k&&Q.some(X=>X._id===k)&&(bt(X=>new Set(X).add(k)),await Rt(Q.find(X=>X._id===k),!0))}catch(N){console.error(`Error loading folders for collection ${v._id}:`,N)}finally{ui(N=>({...N,[v._id]:!1}))}}},[l,w,Ge,k,j]),Rt=wt.useCallback(async(v,b=!1)=>{if(!l||!(v!=null&&v._id))return;let T=!1,R=0;if(Xt(N=>{const O=N[v._id];return O!=null&&O.loaded&&!b&&(T=!0),b&&O&&(R=O.offset),N}),!T){ui(N=>({...N,[v._id]:!0}));try{const N=new URLSearchParams({parentType:"folder",parentId:v._id});j>0&&(N.append("limit",String(j)),N.append("offset",String(R)));const O=`${l}/folder?${N.toString()}`,z=w||fetch,F=Ge(),ee=await z(O,F);if(!ee.ok){console.warn(`Failed to fetch subfolders for folder ${v._id}:`,ee.statusText);return}const q=await ee.json();let Q=[],G=!1;Array.isArray(q)?(Q=q,G=j>0&&q.length===j):(Q=q.items||[],G=j>0&&q.total>R+Q.length),ei(X=>({...X,[v._id]:b?[...X[v._id]||[],...Q]:Q})),Xt(X=>({...X,[v._id]:{offset:j>0?R+Q.length:0,hasMore:j>0?G:!1,loaded:!0}}))}catch(N){console.error(`Error loading subfolders for folder ${v._id}:`,N)}finally{ui(N=>({...N,[v._id]:!1}))}}},[l,w,Ge,j]),et=wt.useCallback(async(v,b,T=!1)=>{if(!l||!le)return;b&&console.log(`[FolderBrowser] Checking folder ${v} (${b.name}):`,{parentType:b.parentType,parentId:b.parentId,hasItems:!0}),b?b.parentType==="collection"?console.log(`[FolderBrowser] Root folder ${v} (${b.name}) - attempting item fetch (typically empty, but checking anyway)`):b.parentType==="folder"?console.log(`[FolderBrowser] Subfolder ${v} (${b.name}) - fetching items`):console.log(`[FolderBrowser] Folder ${v} (${b.name}) - parentType unknown (${b.parentType}), attempting fetch`):console.log(`[FolderBrowser] Folder object not provided for ${v} - attempting item fetch`);const R=T&&_i[v]?_i[v].offset:0;Fi(N=>({...N,[v]:!0}));try{const N=new URLSearchParams;N.append("folderId",v),$>0&&(N.append("limit",String($)),N.append("offset",String(R)));const O=`${l}/item?${N.toString()}`;console.log(`[FolderBrowser] Fetching items from: ${O}`);const z=w||fetch,F=Ge(),ee=await z(O,F);if(!ee.ok){console.warn(`[FolderBrowser] Failed to fetch items for folder ${v}:`,ee.status,ee.statusText);return}const q=await ee.json();console.log("[FolderBrowser] Received response:",q);let Q=[],G=!1;Array.isArray(q)?(Q=q,G=$>0&&q.length===$):(Q=q.items||[],G=$>0&&q.total>R+Q.length),console.log(`[FolderBrowser] Parsed ${Q.length} items for folder ${v}`),Ut(X=>({...X,[v]:T?[...X[v]||[],...Q]:Q})),$>0&&Vi(X=>({...X,[v]:{offset:R+Q.length,hasMore:G}}))}catch(N){console.error(`[FolderBrowser] Error loading items for folder ${v}:`,N)}finally{Fi(N=>({...N,[v]:!1}))}},[l,w,Ge,le,$,_i]),$t=wt.useCallback(async()=>{if(!(!l||!C||!A)){si(!0),Mi(null);try{let v=A==="collection"?`${l}/collection/${C}`:`${l}/folder/${C}`;const b=w||fetch,T=Ge();let R=await b(v,T),N=null;if(R.ok)N=await R.json();else if(console.warn(`Direct fetch failed for ${A} ${C}, trying list endpoint...`),A==="collection"){const O=`${l}/collection`;if(R=await b(O,T),!R.ok)throw new Error(`Failed to fetch collections: ${R.status} ${R.statusText}`);const z=await R.json();if(N=(Array.isArray(z)?z:z.items||[]).find(ee=>ee._id===C)||null,!N)throw new Error(`Collection with ID ${C} not found`)}else{try{const O=`${l}/folder`;if(R=await b(O,T),R.ok){const z=await R.json();N=(Array.isArray(z)?z:z.items||[]).find(ee=>ee._id===C)||null}}catch{console.warn("Could not list folders directly, will need to search through collections")}if(!N){const O=`${l}/collection`,z=await b(O,T);if(!z.ok)throw new Error(`Failed to fetch collections for folder search: ${z.status}`);const F=await z.json(),ee=Array.isArray(F)?F:F.items||[];for(const q of ee){const Q=`${l}/folder?parentType=collection&parentId=${q._id}`,G=await b(Q,T);if(G.ok){const X=await G.json(),H=Array.isArray(X)?X:X.items||[],K=H.find(oe=>oe._id===C);if(K){N=K;break}const ie=async oe=>{const te=`${l}/folder?parentType=folder&parentId=${oe._id}`,pe=await b(te,T);if(pe.ok){const Se=await pe.json(),Ce=Array.isArray(Se)?Se:Se.items||[],Ie=Ce.find(ge=>ge._id===C);if(Ie)return Ie;for(const ge of Ce){const Pe=await ie(ge);if(Pe)return Pe}}return null};for(const oe of H){const te=await ie(oe);if(te){N=te;break}}if(N)break}}if(!N)throw new Error(`Folder with ID ${C} not found in any collection`)}}if(!N)throw new Error(`${A} with ID ${C} not found`);if(A==="collection"){const O=N;ni(O),Yt(new Set([C])),await st(O)}else{const O=N;fi(O),bt(new Set([C])),await Rt(O)}}catch(v){const b=v instanceof Error?v:new Error(`Unknown error loading ${A}`);Mi(b),console.error(`Error loading root ${A}:`,b)}finally{si(!1)}}},[l,C,A,w,Ge,st,Rt]),jt=wt.useCallback(async v=>{if(ji.has(v._id))Yt(T=>{const R=new Set(T);return R.delete(v._id),R});else{const T=ri.current;let R=null,N=0;if(T){let O=T.parentElement;for(;O&&O!==document.body;){const z=window.getComputedStyle(O),F=z.overflowY||z.overflow;if(F==="auto"||F==="scroll"){R=O,N=O.scrollTop;break}if(O.scrollHeight>O.clientHeight&&O.clientHeight>0){R=O,N=O.scrollTop;break}O=O.parentElement}}if(Yt(O=>new Set(O).add(v._id)),await st(v,!1),R){const O=N;requestAnimationFrame(()=>{requestAnimationFrame(()=>{R&&R.scrollTop!==void 0&&(R.scrollTop=O)})})}}},[ji,st]),t=wt.useCallback(async v=>{if(Li.has(v._id))bt(T=>{const R=new Set(T);return R.delete(v._id),R});else{const T=ri.current;let R=null,N=0;if(T){let O=T.parentElement;for(;O&&O!==document.body;){const z=window.getComputedStyle(O),F=z.overflowY||z.overflow;if(F==="auto"||F==="scroll"){R=O,N=O.scrollTop;break}if(O.scrollHeight>O.clientHeight&&O.clientHeight>0){R=O,N=O.scrollTop;break}O=O.parentElement}}if(bt(O=>new Set(O).add(v._id)),await Rt(v,!1),le?(console.log(`[FolderBrowser] Toggling folder ${v._id} (${v.name}) - showItems=${le}, calling loadItemsForFolder`),await et(v._id,v,!1)):console.log(`[FolderBrowser] Toggling folder ${v._id} (${v.name}) - showItems is FALSE, skipping item load`),R){const O=N;requestAnimationFrame(()=>{requestAnimationFrame(()=>{R&&R.scrollTop!==void 0&&(R.scrollTop=O)})})}}},[Li,Rt,le,et]),r=wt.useCallback((v,b)=>{const T={...v,type:b};It(T),a==null||a(T),p==null||p(T)},[a,p]),h=wt.useCallback(v=>{const b={...v,type:"item"};It(b),Ae==null||Ae(v),p==null||p(b)},[Ae,p]);wt.useEffect(()=>{C&&A&&l?$t():c&&l?lt():c&&!l&&(Mi(new Error("API base URL is required")),si(!1))},[C,A,c,l,lt,$t]);const o=wt.useCallback((v,b)=>{const T=(li==null?void 0:li._id)===v._id&&(li==null?void 0:li.type)==="item";return Xe?Xe(v,b):Je.jsx("div",{className:"bdsa-folder-browser__item",children:Je.jsxs("div",{className:`bdsa-folder-browser__resource-item ${T?"selected":""}`,onClick:()=>h(v),onDoubleClick:()=>h(v),"data-resource-id":v._id,children:[Je.jsx("span",{className:"bdsa-folder-browser__resource-icon",children:"📄"}),Je.jsx("span",{className:"bdsa-folder-browser__resource-name",children:v.name}),Je.jsx("span",{className:"bdsa-folder-browser__resource-type",children:"Item"})]})},v._id)},[li,Xe,h]),u=wt.useCallback((v,b=0)=>{var z,F;const T=Li.has(v._id),R=pt[v._id]||[],N=le?gt[v._id]||[]:[],O=(li==null?void 0:li._id)===v._id&&(li==null?void 0:li.type)==="folder";return fe?fe(v,b,T,()=>t(v)):Je.jsxs("div",{className:"bdsa-folder-browser__folder",children:[Je.jsxs("div",{className:`bdsa-folder-browser__folder-header ${O?"selected":""}`,onClick:()=>t(v),onDoubleClick:()=>r(v,"folder"),"data-resource-id":v._id,children:[Je.jsx("span",{className:`bdsa-folder-browser__folder-icon ${T?"expanded":""}`}),Je.jsx("span",{className:"bdsa-folder-browser__folder-name",children:v.name}),Je.jsx("span",{className:"bdsa-folder-browser__folder-type",children:"Folder"})]}),T&&Je.jsxs("div",{className:"bdsa-folder-browser__folder-contents",children:[R.map(ee=>u(ee,b+1)),le&&N.map(ee=>o(ee,b+1)),le&&Hi[v._id]&&Je.jsx("div",{className:"bdsa-folder-browser__loading",children:Je.jsx("span",{children:"Loading items..."})}),j>0&&((z=mi[v._id])==null?void 0:z.hasMore)&&!Nt[v._id]&&Je.jsx("div",{className:"bdsa-folder-browser__load-more",children:Je.jsx("button",{className:"bdsa-folder-browser__load-more-btn",onClick:()=>Rt(v,!0),disabled:Nt[v._id],children:Nt[v._id]?"Loading...":"Load More Folders"})}),le&&$>0&&((F=_i[v._id])==null?void 0:F.hasMore)&&Je.jsx("div",{className:"bdsa-folder-browser__load-more",children:Je.jsx("button",{className:"bdsa-folder-browser__load-more-btn",onClick:()=>et(v._id,v,!0),disabled:Hi[v._id],children:Hi[v._id]?"Loading...":"Load More Items"})})]})]},v._id)},[Li,pt,gt,le,li,fe,t,r,j,mi,Nt,Rt,$,_i,Hi,et,o]),f=wt.useCallback(v=>{var N;const b=ji.has(v._id),T=pt[v._id]||[],R=(li==null?void 0:li._id)===v._id&&(li==null?void 0:li.type)==="collection";return D?D(v,b,()=>jt(v)):Je.jsxs("div",{className:"bdsa-folder-browser__collection",children:[Je.jsxs("div",{className:`bdsa-folder-browser__folder-header ${R?"selected":""}`,onClick:()=>jt(v),onDoubleClick:()=>r(v,"collection"),"data-resource-id":v._id,children:[Je.jsx("span",{className:`bdsa-folder-browser__folder-icon ${b?"expanded":""}`}),Je.jsx("span",{className:"bdsa-folder-browser__folder-name",children:v.name}),Je.jsx("span",{className:"bdsa-folder-browser__folder-type",children:"Collection"})]}),b&&Je.jsxs("div",{className:"bdsa-folder-browser__folder-contents",children:[T.map(O=>u(O,1)),j>0&&((N=mi[v._id])==null?void 0:N.hasMore)&&!Nt[v._id]&&Je.jsx("div",{className:"bdsa-folder-browser__load-more",children:Je.jsx("button",{className:"bdsa-folder-browser__load-more-btn",onClick:()=>st(v,!0),disabled:Nt[v._id],children:Nt[v._id]?"Loading...":"Load More Folders"})})]})]},v._id)},[ji,pt,li,D,jt,r,j,mi,Nt,st,u]);return Je.jsxs("div",{ref:v=>{typeof Kt=="function"?Kt(v):Kt&&"current"in Kt&&(Kt.current=v),ri.current=v},className:`bdsa-folder-browser ${J}`,children:[Di&&Je.jsx("div",{className:"bdsa-folder-browser__loading",children:Je.jsx("span",{children:C&&A?`Loading ${A}...`:"Loading collections..."})}),Ci&&Je.jsxs("div",{className:"bdsa-folder-browser__error",children:[Je.jsx("span",{children:Ci.message}),Je.jsx("button",{onClick:()=>{C&&A?$t():lt()},children:"Retry"})]}),!Di&&!Ci&&Je.jsxs(Je.Fragment,{children:[C&&A==="collection"&&At&&Je.jsx("div",{className:"bdsa-folder-browser__collections",children:f(At)}),C&&A==="folder"&&ct&&Je.jsx("div",{className:"bdsa-folder-browser__collections",children:u(ct,0)}),!C&&c&&Je.jsx("div",{className:"bdsa-folder-browser__collections",children:Te.length===0?Je.jsx("div",{className:"bdsa-folder-browser__empty",children:Je.jsx("span",{children:"No collections found"})}):Te.map(v=>f(v))})]})]})});Us.displayName="FolderBrowser";const un={DSA_CONFIG:"bdsa_dsa_config",GIRDER_TOKEN:"bdsa_girder_token",USER_INFO:"bdsa_user_info",LAST_LOGIN:"bdsa_last_login",TOKEN_EXPIRY:"bdsa_token_expiry"};class qa{constructor(){on(this,"listeners",new Set);on(this,"config");on(this,"token");on(this,"userInfo");on(this,"lastLogin");on(this,"tokenExpiry");on(this,"isAuthenticated");this.config=this.loadConfig(),this.token=this.loadToken(),this.userInfo=this.loadUserInfo(),this.lastLogin=this.loadLastLogin(),this.tokenExpiry=this.loadTokenExpiry(),this.isAuthenticated=this.validateAuthentication()}subscribe(w){return this.listeners.add(w),()=>this.listeners.delete(w)}notify(){this.listeners.forEach(w=>w())}loadConfig(){try{const w=localStorage.getItem(un.DSA_CONFIG);return w?JSON.parse(w):{baseUrl:"",resourceId:"",resourceType:"folder",fetchStrategy:"unlimited",pageSize:100,metadataSyncTargetFolder:""}}catch(w){return console.error("Error loading DSA config:",w),{baseUrl:"",resourceId:"",resourceType:"folder",fetchStrategy:"unlimited",pageSize:100,metadataSyncTargetFolder:""}}}loadToken(){try{return localStorage.getItem(un.GIRDER_TOKEN)||""}catch(w){return console.error("Error loading Girder token:",w),""}}loadUserInfo(){try{const w=localStorage.getItem(un.USER_INFO);return w?JSON.parse(w):null}catch(w){return console.error("Error loading user info:",w),null}}loadLastLogin(){try{const w=localStorage.getItem(un.LAST_LOGIN);return w?new Date(w):null}catch(w){return console.error("Error loading last login:",w),null}}loadTokenExpiry(){try{const w=localStorage.getItem(un.TOKEN_EXPIRY);return w?new Date(w):null}catch(w){return console.error("Error loading token expiry:",w),null}}saveConfig(){try{localStorage.setItem(un.DSA_CONFIG,JSON.stringify(this.config))}catch(w){console.error("Error saving DSA config:",w)}}saveToken(){try{localStorage.setItem(un.GIRDER_TOKEN,this.token)}catch(w){console.error("Error saving Girder token:",w)}}saveUserInfo(){try{this.userInfo&&localStorage.setItem(un.USER_INFO,JSON.stringify(this.userInfo))}catch(w){console.error("Error saving user info:",w)}}saveLastLogin(){try{this.lastLogin&&localStorage.setItem(un.LAST_LOGIN,this.lastLogin.toISOString())}catch(w){console.error("Error saving last login:",w)}}saveTokenExpiry(){try{this.tokenExpiry&&localStorage.setItem(un.TOKEN_EXPIRY,this.tokenExpiry.toISOString())}catch(w){console.error("Error saving token expiry:",w)}}validateAuthentication(){return!this.token||!this.config.baseUrl?!1:this.tokenExpiry&&new Date>this.tokenExpiry?(console.log("Token has expired"),this.logout(),!1):!0}async authenticate(w,n){var a;try{if(!this.config.baseUrl)throw new Error("DSA server URL not configured");const p=btoa(`${w}:${n}`),c=await fetch(`${this.config.baseUrl}/api/v1/user/authentication`,{method:"GET",headers:{Authorization:`Basic ${p}`,"Content-Type":"application/json"}});if(!c.ok){const k=await c.json().catch(()=>({}));throw new Error(k.message||`Authentication failed: ${c.status}`)}const C=await c.json(),A=(a=C==null?void 0:C.authToken)==null?void 0:a.token,m=C==null?void 0:C.user;if(!A)throw new Error("No authentication token received from server");return this.token=A,this.userInfo={id:(m==null?void 0:m._id)||(m==null?void 0:m.id)||"",name:(m==null?void 0:m.login)||(m==null?void 0:m.firstName)||(m==null?void 0:m.email)||"User",email:m==null?void 0:m.email,login:m==null?void 0:m.login},this.lastLogin=new Date,this.tokenExpiry=new Date(Date.now()+30*24*60*60*1e3),this.isAuthenticated=!0,this.saveToken(),this.saveUserInfo(),this.saveLastLogin(),this.saveTokenExpiry(),this.notify(),{success:!0,user:this.userInfo}}catch(p){throw console.error("Authentication failed:",p),this.logout(),p}}logout(){this.token&&this.config.baseUrl&&fetch(`${this.config.baseUrl}/api/v1/user/authentication`,{method:"DELETE",headers:{"Girder-Token":this.token}}).catch(w=>{console.warn("Server logout failed:",w)}),this.token="",this.userInfo=null,this.lastLogin=null,this.tokenExpiry=null,this.isAuthenticated=!1,localStorage.removeItem(un.GIRDER_TOKEN),localStorage.removeItem(un.USER_INFO),localStorage.removeItem(un.LAST_LOGIN),localStorage.removeItem(un.TOKEN_EXPIRY),this.notify()}async validateToken(){if(!this.token||!this.config.baseUrl)return!1;try{return(await fetch(`${this.config.baseUrl}/api/v1/user/me`,{headers:{"Girder-Token":this.token}})).ok?!0:(console.log("Token validation failed, logging out"),this.logout(),!1)}catch(w){return console.error("Token validation error:",w),this.logout(),!1}}updateConfig(w){this.config={...this.config,...w},this.saveConfig(),this.notify()}setServerUrl(w){this.config.baseUrl=w,this.saveConfig(),this.notify()}getAuthHeaders(){return this.isAuthenticated?{"Girder-Token":this.token,"Content-Type":"application/json"}:{}}getApiUrl(w){if(!this.config.baseUrl)throw new Error("DSA server URL not configured");return`${this.config.baseUrl}${w}`}isConfigured(){return!!this.config.baseUrl}isDataReady(){return!!(this.config.baseUrl&&this.config.resourceId&&this.isAuthenticated)}getStatus(){return{isAuthenticated:this.isAuthenticated,isConfigured:this.isConfigured(),hasToken:!!this.token,hasConfig:!!this.config.baseUrl,user:this.userInfo,serverUrl:this.config.baseUrl,resourceId:this.config.resourceId,resourceType:this.config.resourceType,lastLogin:this.lastLogin,tokenExpiry:this.tokenExpiry}}getConfig(){return{...this.config}}getToken(){return this.token}async testConnection(){if(!this.config.baseUrl)throw new Error("DSA server URL not configured");try{const w=await fetch(`${this.config.baseUrl}/api/v1/system/version`,{method:"GET",headers:{"Content-Type":"application/json"}});if(w.ok)return{success:!0,version:await w.json(),message:"Connection successful"};throw new Error(`Server responded with status: ${w.status}`)}catch(w){throw new Error(`Connection failed: ${w.message}`)}}}const hn=new qa;function Gs(){const[l,w]=wt.useState(hn.getStatus());return wt.useEffect(()=>{const j=hn.subscribe(()=>{w(hn.getStatus())});return l.isAuthenticated&&hn.validateToken(),j},[]),{authStatus:l,login:async(j,J)=>{await hn.authenticate(j,J)},logout:()=>{hn.logout()},updateConfig:j=>{hn.updateConfig(j)},validateToken:async()=>await hn.validateToken(),testConnection:async()=>await hn.testConnection(),getAuthHeaders:()=>hn.getAuthHeaders(),getApiUrl:j=>hn.getApiUrl(j),getToken:()=>hn.getToken(),getConfig:()=>hn.getConfig()}}const Za=({onAuthChange:l,allowServerConfig:w=!0,className:n="",compact:a=!1})=>{const{authStatus:p,login:c,logout:C,updateConfig:A}=Gs(),[m,k]=wt.useState(!1),[L,j]=wt.useState({username:"",password:"",serverUrl:""}),[J,D]=wt.useState(!1),[fe,le]=wt.useState("");wt.useEffect(()=>{l&&l(p.isAuthenticated)},[p.isAuthenticated,l]);const $=async vt=>{vt.preventDefault(),D(!0),le("");try{w&&L.serverUrl&&L.serverUrl!==p.serverUrl&&A({baseUrl:L.serverUrl}),await c(L.username,L.password),k(!1),j({username:"",password:"",serverUrl:""})}catch(tt){le(tt.message)}finally{D(!1)}},Ae=()=>{C()},Xe=()=>{j(vt=>({...vt,serverUrl:p.serverUrl||""})),k(!0)},Lt=p.isConfigured?p.isAuthenticated?{text:"Connected",className:"status-connected",icon:"✅"}:{text:"Not Connected",className:"status-not-connected",icon:"🔌"}:{text:"Not Configured",className:"status-not-configured",icon:"⚙️"};return a?Je.jsxs("div",{className:`dsa-auth-manager compact ${n}`,children:[Je.jsxs("div",{className:"dsa-status-compact",children:[Je.jsx("span",{className:`status-indicator ${Lt.className}`,children:Lt.icon}),p.isAuthenticated&&p.user&&Je.jsx("span",{className:"user-name",children:p.user.name})]}),Je.jsx("button",{className:p.isAuthenticated?"logout-button":"login-button",onClick:p.isAuthenticated?Ae:Xe,disabled:!p.isConfigured&&!w,children:p.isAuthenticated?"Logout":"Login"}),m&&Je.jsx(Kr,{show:m,onClose:()=>k(!1),onSubmit:$,loginForm:L,setLoginForm:j,authStatus:p,isLoading:J,error:fe,allowServerConfig:w})]}):Je.jsxs("div",{className:`dsa-auth-manager ${n}`,children:[Je.jsxs("div",{className:"dsa-status",children:[Je.jsx("span",{className:`status-indicator ${Lt.className}`,children:Lt.icon}),Je.jsxs("div",{className:"status-info",children:[Je.jsx("div",{className:"status-text",children:Lt.text}),p.isAuthenticated&&p.user&&Je.jsxs("div",{className:"user-info",children:[p.user.name,p.serverUrl&&Je.jsx("div",{className:"server-url",children:new URL(p.serverUrl).hostname})]})]})]}),Je.jsx("div",{className:"dsa-actions",children:p.isAuthenticated?Je.jsx("button",{className:"logout-button",onClick:Ae,title:"Logout from DSA server",children:"Logout"}):Je.jsx("button",{className:"login-button",onClick:Xe,disabled:!p.isConfigured&&!w,title:!p.isConfigured&&!w?"Configure DSA server first":"Login to DSA server",children:"Login"})}),m&&Je.jsx(Kr,{show:m,onClose:()=>k(!1),onSubmit:$,loginForm:L,setLoginForm:j,authStatus:p,isLoading:J,error:fe,allowServerConfig:w})]})},Kr=({show:l,onClose:w,onSubmit:n,loginForm:a,setLoginForm:p,authStatus:c,isLoading:C,error:A,allowServerConfig:m})=>l?Je.jsx("div",{className:"modal-overlay",onClick:w,children:Je.jsxs("div",{className:"modal-content login-modal",onClick:k=>k.stopPropagation(),children:[Je.jsxs("div",{className:"modal-header",children:[Je.jsx("h2",{children:"Login to DSA Server"}),Je.jsx("button",{className:"close-button",onClick:w,children:"×"})]}),Je.jsxs("form",{onSubmit:n,className:"login-form",children:[m&&Je.jsxs("div",{className:"form-group",children:[Je.jsx("label",{htmlFor:"serverUrl",children:"DSA Server URL *"}),Je.jsx("input",{type:"url",id:"serverUrl",value:a.serverUrl,onChange:k=>p(L=>({...L,serverUrl:k.target.value})),placeholder:"http://bdsa.pathology.emory.edu:8080",required:!0}),Je.jsxs("div",{className:"field-help",children:["The base URL of your Digital Slide Archive server",Je.jsx("br",{}),Je.jsx("small",{children:"💡 Don't include /api/v1 - it will be added automatically"})]})]}),!m&&c.serverUrl&&Je.jsxs("div",{className:"form-group",children:[Je.jsx("label",{children:"Server"}),Je.jsx("div",{className:"server-display",children:c.serverUrl})]}),Je.jsxs("div",{className:"form-group",children:[Je.jsx("label",{htmlFor:"username",children:"Username"}),Je.jsx("input",{type:"text",id:"username",value:a.username,onChange:k=>p(L=>({...L,username:k.target.value})),placeholder:"Enter your DSA username",required:!0})]}),Je.jsxs("div",{className:"form-group",children:[Je.jsx("label",{htmlFor:"password",children:"Password"}),Je.jsx("input",{type:"password",id:"password",value:a.password,onChange:k=>p(L=>({...L,password:k.target.value})),placeholder:"Enter your password",required:!0})]}),A&&Je.jsx("div",{className:"error-message",children:A}),Je.jsxs("div",{className:"modal-actions",children:[Je.jsx("button",{type:"button",className:"cancel-button",onClick:w,disabled:C,children:"Cancel"}),Je.jsx("button",{type:"submit",className:"login-submit-button",disabled:C||!a.username||!a.password,children:C?"Logging in...":"Login"})]})]})]})}):null;function Ws(l){const w=l.largeImage;if(w===!0||w==="true"||typeof w=="object"&&w!==null)return!0;const p=(l.meta||{}).largeImage;return p===!0||p==="true"||typeof p=="object"&&p!==null}function Ya(l){return l.filter(Ws)}exports.AnnotationManager=Vs;exports.Button=Qr;exports.Card=$r;exports.DsaAuthManager=Za;exports.FolderBrowser=Us;exports.IndexedDBAnnotationCache=Er;exports.MemoryAnnotationCache=sa;exports.SlideViewer=Hs;exports.applyPaperJsPatches=Bs;exports.checkIndexedDBQuota=ss;exports.detectAnnotationFormat=js;exports.dsaAuthStore=hn;exports.extractAnnotationElements=zs;exports.filterLargeImages=Ya;exports.formatBytes=Qn;exports.geoJSONFeatureToDSAElement=Ds;exports.geoJSONToDSAElements=Fs;exports.hasLargeImage=Ws;exports.isDSAAnnotation=Ns;exports.isGeoJSONFeatureCollection=Dr;exports.logQuotaInfo=ua;exports.requestPersistentStorage=la;exports.useDsaAuth=Gs;
|
|
1753
1753
|
//# sourceMappingURL=index.cjs.map
|