lost-sia 3.1.3 → 3.2.0-alpha0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/Canvas/Canvas.js +1 -1
  2. package/dist/SiaViewer.d.ts +19 -0
  3. package/dist/SiaViewer.js +1 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +1 -1
  6. package/dist/stories/Canvas/Canvas.stories.d.ts +3 -3
  7. package/dist/stories/Canvas/CanvasWithOffset.stories.d.ts +6 -6
  8. package/dist/stories/SIA/SiaViewer.stories.d.ts +52 -0
  9. package/package.json +3 -4
  10. package/src/Canvas/Canvas.tsx +5 -1
  11. package/src/SiaViewer.tsx +125 -0
  12. package/src/Toolbar/ToolbarItems/ImageToolItems/ImageLabelInput.tsx +1 -2
  13. package/src/index.ts +1 -1
  14. package/src/stories/SIA/SiaViewer.stories.tsx +105 -0
  15. package/src/stories/exampleData/exampleExternalAnnotations.ts +22 -22
  16. package/dist/assets/brand-icons-Cu_C0hZ4.svg +0 -1008
  17. package/dist/assets/brand-icons-F3SPCeH1.woff +0 -0
  18. package/dist/assets/brand-icons-XL9sxUpA.woff2 +0 -0
  19. package/dist/assets/brand-icons-sqJ2Pg7a.eot +0 -0
  20. package/dist/assets/brand-icons-ubhWoxly.ttf +0 -0
  21. package/dist/assets/flags-DOLqOU7Y.png +0 -0
  22. package/dist/assets/icons-BOCtAERH.woff +0 -0
  23. package/dist/assets/icons-CHzK1VD9.eot +0 -0
  24. package/dist/assets/icons-D29ZQHHw.ttf +0 -0
  25. package/dist/assets/icons-Du6TOHnR.woff2 +0 -0
  26. package/dist/assets/icons-RwhydX30.svg +0 -1518
  27. package/dist/assets/node_modules/semantic-ui-css/semantic.min-09YPtVE6.css +0 -1
  28. package/dist/assets/outline-icons-BfdLr8tr.svg +0 -366
  29. package/dist/assets/outline-icons-DD8jm0uy.ttf +0 -0
  30. package/dist/assets/outline-icons-DInHoiqI.woff2 +0 -0
  31. package/dist/assets/outline-icons-LX8adJ4n.eot +0 -0
  32. package/dist/assets/outline-icons-aQ88nltS.woff +0 -0
  33. package/src/AnnoExampleViewer.jsx +0 -69
  34. package/src/InfoBoxes/AnnoDetails.jsx +0 -165
  35. package/src/InfoBoxes/AnnoStats.jsx +0 -106
  36. package/src/InfoBoxes/InfoBox.jsx +0 -76
  37. package/src/InfoBoxes/InfoBoxArea.jsx +0 -152
  38. package/src/InfoBoxes/LabelInfo.jsx +0 -107
  39. package/src/SIASettingButton.jsx +0 -126
@@ -1 +1 @@
1
- import{jsxs as K,jsx as p,Fragment as qe}from"react/jsx-runtime";import{useState as g,useRef as Z,useEffect as v}from"react";import O from"../models/AnnotationTool.js";import r from"../models/EditorModes.js";import et from"../utils/KeyMapper.js";import a from"../models/KeyAction.js";import xe from"../Annotation/logic/Annotation.js";import tt from"../models/CanvasAction.js";import nt from"../Annotation/ui/AnnotationComponent.js";import Ce from"../utils/mouse.js";import _ from"../models/AnnotationMode.js";import ot from"./LabelInput.js";import{FontAwesomeIcon as st}from"@fortawesome/react-fontawesome";import{faBan as rt}from"@fortawesome/free-solid-svg-icons";import w from"../models/AnnotationStatus.js";import A from"../utils/transform.js";import it from"../models/NotificationType.js";import at from"../utils/TimeUtils.js";import he from"../utils/windowViewport.js";const Dt=({annotations:h=[],annotationSettings:F,defaultLabelId:q,image:X,isFullscreen:ve=!1,isImageJunk:U=!1,isPolygonSelectionMode:Y=!1,polygonOperationResult:z={annotationsToDelete:[],polygonsToCreate:[]},possibleLabels:ee,preventScrolling:te=!0,selectedAnnotation:i,selectedAnnoTool:N,toolbarHeight:G=0,uiConfig:R,onAnnoCreated:Ie,onAnnoCreationFinished:ne,onAnnoChanged:oe,onAnnoEditing:Te=c=>{},onNotification:se=c=>{},onRequestNewAnnoId:V,onSelectAnnotation:I,onSetIsImageJunk:Me,onSetSelectedTool:Oe=c=>{},onShouldDeleteAnno:re,onTraverseAnnotationHistory:ie})=>{const[c,y]=g(r.VIEW),[we,be]=g(),[ae,De]=g(q),[P,Se]=g({x:-1,y:-1}),[ce,le]=g(0),k={x:P.x,y:P.y},[u,de]=g({x:-1,y:-1}),[d,H]=g({x:-1,y:-1}),[m,fe]=g({x:-1,y:-1}),[f,L]=g(1),[l,b]=g({x:0,y:0}),$={x:l.x+ce,y:l.y},[j,W]=g(),[J,D]=g(!1),ue=Z(null),x=Z(null),T=Z(null),C=((e,t)=>{if(e.x===0||e.y===0||t.x===0||t.y===0)return 0;const n=t.x/e.x,o=t.y/e.y;return Math.min(n,o)})(u,d),_e=()=>{if(T?.current===null)return{x:0,y:0};const e=u.x*C;if(R.imageCentered&&d.x>e){const E=(d.x-e)/2;le(E)}else le(0);const{top:t,left:n}=x.current.getBoundingClientRect(),o={x:n+window.scrollX,y:t+window.scrollY};Se(o)},Ne=new et(e=>Be(e)),Re=e=>{y(r.CREATE);const t=A.convertStageCoordinatesToPercentaged([e],C,u);N===O.BBox&&t.push(t[0]);const n=V(),o=new xe(n,N,t);if(be(performance.now()),ae!==void 0&&(o.labelIds=[ae]),Ie(o),N===O.Point){const s={...o,coordinates:[e],annoTime:0};Q(s)}},Ve=()=>{if(i&&![O.Line,O.Polygon].includes(i.type))return;const e=h.find(n=>n.internalId===i?.internalId);if(e===void 0)return;y(r.CREATE),Oe(e.type);const t={...e,mode:_.CREATE,status:w.CREATING,internalId:V(),selectedNode:e.coordinates.length-1};Te(t)},Pe=()=>{const e=i?i.internalId:0,t=h.find(n=>n.internalId>e);if(t)return I(t);if(h.length>0)return I(h[0])},ke=()=>{const e=i?i.internalId:0,t=[...h];t.sort((o,s)=>s.internalId-o.internalId);const n=t.find(o=>o.internalId<e);if(n)return I(n);if(h.length>0)return I(h.at(-1))},Le=()=>{if(i){const e=JSON.stringify(i);localStorage.setItem("lostAnnotationClipboard",e);const t={title:"Success",message:"Annotation copied",type:it.SUCCESS};se(t)}},We=()=>{const e=localStorage.getItem("lostAnnotationClipboard");if(e==null)return;const t=JSON.parse(e);t.internalId=V(),t.externalId="",ne(t,!0),I(t)},Ee=e=>{const t=A.getMostLeftPoints(e),n=A.getTopPoint(t)[0];return A.convertStageToPage(n,k,f,l)},Be=e=>{switch(e){case a.EDIT_LABEL:if(i){const t=A.convertPercentagedCoordinatesToStage(i.coordinates,u,m);W(Ee(t)),D(!0)}break;case a.DELETE_ANNO:i&&re(i.internalId);break;case a.DELETE_ANNO_IN_CREATION:c===r.CREATE&&(re(i.internalId),y(r.VIEW));break;case a.ENTER_ANNO_ADD_MODE:console.log("KeyAction TODO: ENTER_ANNO_ADD_MODE");break;case a.LEAVE_ANNO_ADD_MODE:console.log("KeyAction TODO: LEAVE_ANNO_ADD_MODE");break;case a.UNDO:ie(!0);break;case a.REDO:ie(!1);break;case a.TRAVERSE_ANNOS:Pe();break;case a.TRAVERSE_ANNOS_BACKWARDS:ke();break;case a.CAM_MOVE_LEFT:S(20*f,0);break;case a.CAM_MOVE_RIGHT:S(-20*f,0);break;case a.CAM_MOVE_UP:S(0,20*f);break;case a.CAM_MOVE_DOWN:S(0,-20*f);break;case a.CAM_MOVE_STOP:console.log("KeyAction TODO: CAM_MOVE_STOP");break;case a.COPY_ANNOTATION:Le();break;case a.PASTE_ANNOTATION:We();break;case a.RECREATE_ANNO:console.log("KeyAction TODO: RECREATE_ANNO"),Ve();break;case a.TOGGLE_IMAGE_JUNK:if(c===r.ADD||c===r.CREATE)return;Me(!U);break;default:console.log("Unknown KeyAction",e);break}},S=(e,t)=>{let n=l.x+e/f,o=l.y+t/f;const s=d.x*.45,E=d.x*.55,M=d.y*.45,Qe=d.y*.55,Ze={x:0,y:0},ye=he.getViewportCoordinates(l,d,f,Ze),Ae=he.getViewportCoordinates(l,d,f,d);ye.vX>=s?n=l.x-5:Ae.vX<=E?n=l.x+5:ye.vY>=M?o=l.y-5:Ae.vY<=Qe&&(o=l.y+5),b({x:n,y:o})},B=(e=>m.x<=0||m.y<=0||u.x<=0||u.y<=0?[]:h.map(n=>({...n,coordinates:A.convertPercentagedCoordinatesToStage(n.coordinates,u,m)})))(),Ke=()=>{if(y(r.VIEW),fe({x:-1,y:-1}),T.current!==null){const{width:e,height:t}=T.current.getBoundingClientRect();de({x:e,y:t})}L(1),b({x:0,y:0}),W(void 0),D(!1)};v(()=>{ue.current?.focus()},[]),v(()=>{const e=t=>{t.button===1&&c===r.CAMERA_MOVE&&y(r.VIEW)};return window.addEventListener("mouseup",e),()=>window.removeEventListener("mouseup",e)},[c]),v(()=>{if(x?.current!==void 0){Ke();const{width:e,height:t}=x.current.getBoundingClientRect(),n=t-G;H({x:e,y:n});const o=new ResizeObserver(()=>{const{width:s,height:E}=x.current.getBoundingClientRect(),M=E-G;H({x:s,y:M})});return o.observe(x.current),()=>o.disconnect()}},[X,ve]),v(()=>{_e()},[d,u,R]),v(()=>{if(x.current===null)return;const{width:e,height:t}=x.current.getBoundingClientRect(),n=t-G;H({x:e,y:n})},[x]),v(()=>{if(T.current===null)return;const{width:e,height:t}=T.current.getBoundingClientRect();de({x:e,y:t})},[X,d]),v(()=>{if(C===0)return;const e={x:u.x*C,y:u.y*C};fe(e)},[C,u]),v(()=>{Y&&z.polygonsToCreate!==void 0&&z.polygonsToCreate.forEach(e=>{const t=V(),n=new xe(t,e.type,A.convertPercentagedCoordinatesToStage(e.coordinates,u,m),_.VIEW,w.CREATED);e.labelIds!==void 0&&(n.labelIds=e.labelIds),Q(n)})},[z]);const Q=e=>{y(r.VIEW);const t={...e,mode:_.VIEW};if(e.type!==O.Point){const s=at.getRoundedDuration(we,performance.now());t.annoTime=s}const n=A.convertStageCoordinatesToPercentaged(e.coordinates,C,u);t.coordinates=n,oe(t);const o=N===O.Point||Y;ne(t,o)},Fe=e=>{Ne.keyDown(e.key,e.shiftKey,e.ctrlKey)&&e.preventDefault()},Xe=e=>{e.preventDefault()},Ue=e=>{if(e.button!==0){if(e.button===1){if(c===r.CREATE||c===r.ADD){e.preventDefault();return}y(r.CAMERA_MOVE)}else if(e.button===2){if(!F.canCreate||c===r.ADD||c===r.CREATE)return;const t=Ce.getAntiScaledMouseStagePosition(e,k,f,l),n={x:t.x-ce,y:t.y};Re(n)}}},Ye=()=>{te&&(document.body.style.overflow="hidden")},ze=e=>{e.button===1&&c===r.CAMERA_MOVE&&y(r.VIEW)},ge=(e,t)=>{c===r.CAMERA_MOVE&&S(e,t)},Ge=()=>{te&&(document.body.style.overflow="")},He=e=>{const o=(e.deltaY<0?1:-1)>0?f*1.25:f/1.25,s=Ce.getAntiScaledMouseStagePosition(e,k,f,l),E=f/o,M={x:E*(s.x+l.x)-s.x,y:E*(s.y+l.y)-s.y};o<1?(L(1),(l.x!=0||l.y!=0)&&b({x:0,y:0})):o>200?(L(200),b(M)):(L(o),b(M))},$e=(e,t)=>{if(t!==tt.ANNO_SELECTED){console.log("Unknown Canvas Action:",t);return}const n={...e,coordinates:A.convertStageCoordinatesToPercentaged([...e.coordinates],C,u)};I(n),W(Ee(e.coordinates))},me=e=>{const t=A.convertStageCoordinatesToPercentaged(e.coordinates,C,u),n={...e,coordinates:t};n.status===w.LOADED&&(n.status=w.CHANGED),oe(n)},je=()=>{if(c===r.CAMERA_MOVE)return p(qe,{});const t=[r.CREATE,r.ADD,r.MOVE].includes(c),n=B.map(o=>{const s=o.internalId===i?.internalId;return t&&!s?p("g",{},`annotationComponent_${o.internalId}`):p(nt,{scaledAnnotation:o,annotationSettings:F,possibleLabels:ee,svgScale:f,svgTranslation:$,pageToStageOffset:k,nodeRadius:R.nodeRadius,strokeWidth:R.strokeWidth,isSelected:s,isDisabled:Y&&s,onFinishAnnoCreate:Q,onLabelIconClicked:()=>D(!0),onAction:$e,onAnnoChanged:me,onAnnotationModeChange:E=>{E===_.MOVE&&y(r.MOVE),c===r.MOVE&&E===_.VIEW&&y(r.VIEW)},onNotification:se},`annotationComponent_${o.internalId}`)});if(i){const o=B.find(E=>E.internalId===i?.internalId),s=B.indexOf(o);n.push(n.splice(s,1)[0])}return p("g",{children:n})},Je=()=>p("circle",{cx:m.x/2,cy:m.y/2,r:"100%",style:{opacity:0},onContextMenu:e=>e.preventDefault(),onClick:()=>{D(!1)}}),pe={x:P.x+d.x/2,y:P.y+d.y/2};return K("div",{ref:x,style:{flex:"1 1 auto",minHeight:0,display:"flex",flexDirection:"column"},children:[p("div",{style:{position:"absolute",left:j?.x??0,top:j?.y??0,display:j?.y===void 0?"none":"inherit",zIndex:J?7e3:-1},children:p(ot,{defaultLabelId:q,isVisible:J,selectedLabelsIds:i?.labelIds,possibleLabels:ee,isMultilabel:F.canHaveMultipleLabels,onLabelSelect:e=>{if(setTimeout(()=>D(!1),0),e.length>0){const s=e.filter(E=>!i.labelIds.includes(E));s.length>0&&De(s[0])}const t=B.find(s=>s.internalId===i.internalId);if(!t)return;const n=t.status===w.LOADED?w.CHANGED:t.status,o={...i,coordinates:t.coordinates,labelIds:[...e],status:n};me(o)}})}),U&&K("div",{style:{position:"absolute",left:pe.x,top:pe.y,transform:"translate(-50%, -50%)",textAlign:"center",color:"white"},children:[p(st,{icon:rt,size:"5x",style:{marginBottom:15}}),p("h2",{children:"Marked as Junk"})]}),K("svg",{ref:ue,style:{flex:"1 1 auto",minHeight:0},onKeyDown:Fe,onKeyUp:Xe,onMouseMove:e=>ge(e.movementX,e.movementY),tabIndex:0,onMouseDown:e=>Ue(e),children:[K("g",{transform:`scale(${f}) translate(${$.x}, ${$.y})`,onMouseOver:Ye,onMouseLeave:Ge,onMouseUp:ze,onWheel:He,onMouseMove:e=>ge(e.movementX,e.movementY),onClick:()=>{I(void 0)},children:[p("image",{onContextMenu:e=>e.preventDefault(),href:X,ref:T,width:m.x>0?m.x:void 0,height:m.y>0?m.y:void 0}),je()]}),J&&Je(),U&&p("rect",{x:"0",y:"0",width:d.x,height:d.y,style:{opacity:.8},onContextMenu:e=>e.preventDefault(),onClick:()=>{W(void 0)}})]})]})};export{Dt as default};
1
+ import{jsxs as F,jsx as p,Fragment as qe}from"react/jsx-runtime";import{useState as g,useRef as Z,useEffect as v}from"react";import O from"../models/AnnotationTool.js";import r from"../models/EditorModes.js";import et from"../utils/KeyMapper.js";import a from"../models/KeyAction.js";import xe from"../Annotation/logic/Annotation.js";import tt from"../models/CanvasAction.js";import nt from"../Annotation/ui/AnnotationComponent.js";import Ce from"../utils/mouse.js";import N from"../models/AnnotationMode.js";import ot from"./LabelInput.js";import{FontAwesomeIcon as st}from"@fortawesome/react-fontawesome";import{faBan as rt}from"@fortawesome/free-solid-svg-icons";import b from"../models/AnnotationStatus.js";import A from"../utils/transform.js";import it from"../models/NotificationType.js";import at from"../utils/TimeUtils.js";import he from"../utils/windowViewport.js";const Dt=({annotations:h=[],annotationSettings:w,defaultLabelId:q,image:X,isFullscreen:ve=!1,isImageJunk:U=!1,isPolygonSelectionMode:Y=!1,polygonOperationResult:z={annotationsToDelete:[],polygonsToCreate:[]},possibleLabels:ee,preventScrolling:te=!0,selectedAnnotation:i,selectedAnnoTool:R,toolbarHeight:G=0,uiConfig:V,onAnnoCreated:Ie,onAnnoCreationFinished:ne,onAnnoChanged:oe,onAnnoEditing:Te=c=>{},onNotification:se=c=>{},onRequestNewAnnoId:P,onSelectAnnotation:I,onSetIsImageJunk:Me,onSetSelectedTool:Oe=c=>{},onShouldDeleteAnno:re,onTraverseAnnotationHistory:ie})=>{const[c,y]=g(r.VIEW),[be,we]=g(),[ae,De]=g(q),[k,Se]=g({x:-1,y:-1}),[ce,le]=g(0),L={x:k.x,y:k.y},[u,de]=g({x:-1,y:-1}),[d,H]=g({x:-1,y:-1}),[m,fe]=g({x:-1,y:-1}),[f,W]=g(1),[l,D]=g({x:0,y:0}),$={x:l.x+ce,y:l.y},[j,B]=g(),[J,S]=g(!1),ue=Z(null),x=Z(null),T=Z(null),C=((e,t)=>{if(e.x===0||e.y===0||t.x===0||t.y===0)return 0;const n=t.x/e.x,o=t.y/e.y;return Math.min(n,o)})(u,d),_e=()=>{if(T?.current===null)return{x:0,y:0};const e=u.x*C;if(V.imageCentered&&d.x>e){const E=(d.x-e)/2;le(E)}else le(0);const{top:t,left:n}=x.current.getBoundingClientRect(),o={x:n+window.scrollX,y:t+window.scrollY};Se(o)},Ne=new et(e=>Be(e)),Re=e=>{y(r.CREATE);const t=A.convertStageCoordinatesToPercentaged([e],C,u);R===O.BBox&&t.push(t[0]);const n=P(),o=new xe(n,R,t);if(we(performance.now()),ae!==void 0&&(o.labelIds=[ae]),Ie(o),R===O.Point){const s={...o,coordinates:[e],annoTime:0};Q(s)}},Ve=()=>{if(i&&![O.Line,O.Polygon].includes(i.type))return;const e=h.find(n=>n.internalId===i?.internalId);if(e===void 0)return;y(r.CREATE),Oe(e.type);const t={...e,mode:N.CREATE,status:b.CREATING,internalId:P(),selectedNode:e.coordinates.length-1};Te(t)},Pe=()=>{const e=i?i.internalId:0,t=h.find(n=>n.internalId>e);if(t)return I(t);if(h.length>0)return I(h[0])},ke=()=>{const e=i?i.internalId:0,t=[...h];t.sort((o,s)=>s.internalId-o.internalId);const n=t.find(o=>o.internalId<e);if(n)return I(n);if(h.length>0)return I(h.at(-1))},Le=()=>{if(i){const e=JSON.stringify(i);localStorage.setItem("lostAnnotationClipboard",e);const t={title:"Success",message:"Annotation copied",type:it.SUCCESS};se(t)}},We=()=>{const e=localStorage.getItem("lostAnnotationClipboard");if(e==null)return;const t=JSON.parse(e);t.internalId=P(),t.externalId="",ne(t,!0),I(t)},Ee=e=>{const t=A.getMostLeftPoints(e),n=A.getTopPoint(t)[0];return A.convertStageToPage(n,L,f,l)},Be=e=>{switch(e){case a.EDIT_LABEL:if(i){const t=A.convertPercentagedCoordinatesToStage(i.coordinates,u,m);B(Ee(t)),S(!0)}break;case a.DELETE_ANNO:i&&re(i.internalId);break;case a.DELETE_ANNO_IN_CREATION:c===r.CREATE&&(re(i.internalId),y(r.VIEW));break;case a.ENTER_ANNO_ADD_MODE:console.log("KeyAction TODO: ENTER_ANNO_ADD_MODE");break;case a.LEAVE_ANNO_ADD_MODE:console.log("KeyAction TODO: LEAVE_ANNO_ADD_MODE");break;case a.UNDO:ie(!0);break;case a.REDO:ie(!1);break;case a.TRAVERSE_ANNOS:Pe();break;case a.TRAVERSE_ANNOS_BACKWARDS:ke();break;case a.CAM_MOVE_LEFT:_(20*f,0);break;case a.CAM_MOVE_RIGHT:_(-20*f,0);break;case a.CAM_MOVE_UP:_(0,20*f);break;case a.CAM_MOVE_DOWN:_(0,-20*f);break;case a.CAM_MOVE_STOP:console.log("KeyAction TODO: CAM_MOVE_STOP");break;case a.COPY_ANNOTATION:Le();break;case a.PASTE_ANNOTATION:We();break;case a.RECREATE_ANNO:console.log("KeyAction TODO: RECREATE_ANNO"),Ve();break;case a.TOGGLE_IMAGE_JUNK:if(c===r.ADD||c===r.CREATE)return;Me(!U);break;default:console.log("Unknown KeyAction",e);break}},_=(e,t)=>{let n=l.x+e/f,o=l.y+t/f;const s=d.x*.45,E=d.x*.55,M=d.y*.45,Qe=d.y*.55,Ze={x:0,y:0},ye=he.getViewportCoordinates(l,d,f,Ze),Ae=he.getViewportCoordinates(l,d,f,d);ye.vX>=s?n=l.x-5:Ae.vX<=E?n=l.x+5:ye.vY>=M?o=l.y-5:Ae.vY<=Qe&&(o=l.y+5),D({x:n,y:o})},K=(e=>m.x<=0||m.y<=0||u.x<=0||u.y<=0?[]:h.map(n=>({...n,coordinates:A.convertPercentagedCoordinatesToStage(n.coordinates,u,m)})))(),Ke=()=>{if(y(r.VIEW),fe({x:-1,y:-1}),T.current!==null){const{width:e,height:t}=T.current.getBoundingClientRect();de({x:e,y:t})}W(1),D({x:0,y:0}),B(void 0),S(!1)};v(()=>{ue.current?.focus()},[]),v(()=>{const e=t=>{t.button===1&&c===r.CAMERA_MOVE&&y(r.VIEW)};return window.addEventListener("mouseup",e),()=>window.removeEventListener("mouseup",e)},[c]),v(()=>{if(x?.current!==void 0){Ke();const{width:e,height:t}=x.current.getBoundingClientRect(),n=t-G;H({x:e,y:n});const o=new ResizeObserver(()=>{const{width:s,height:E}=x.current.getBoundingClientRect(),M=E-G;H({x:s,y:M})});return o.observe(x.current),()=>o.disconnect()}},[X,ve]),v(()=>{_e()},[d,u,V]),v(()=>{if(x.current===null)return;const{width:e,height:t}=x.current.getBoundingClientRect(),n=t-G;H({x:e,y:n})},[x]),v(()=>{if(T.current===null)return;const{width:e,height:t}=T.current.getBoundingClientRect();de({x:e,y:t})},[X,d]),v(()=>{if(C===0)return;const e={x:u.x*C,y:u.y*C};fe(e)},[C,u]),v(()=>{Y&&z.polygonsToCreate!==void 0&&z.polygonsToCreate.forEach(e=>{const t=P(),n=new xe(t,e.type,A.convertPercentagedCoordinatesToStage(e.coordinates,u,m),N.VIEW,b.CREATED);e.labelIds!==void 0&&(n.labelIds=e.labelIds),Q(n)})},[z]);const Q=e=>{y(r.VIEW);const t={...e,mode:N.VIEW};if(e.type!==O.Point){const s=at.getRoundedDuration(be,performance.now());t.annoTime=s}const n=A.convertStageCoordinatesToPercentaged(e.coordinates,C,u);t.coordinates=n,oe(t);const o=R===O.Point||Y;ne(t,o)},Fe=e=>{Ne.keyDown(e.key,e.shiftKey,e.ctrlKey)&&e.preventDefault()},Xe=e=>{e.preventDefault()},Ue=e=>{if(e.button!==0){if(e.button===1){if(c===r.CREATE||c===r.ADD){e.preventDefault();return}y(r.CAMERA_MOVE)}else if(e.button===2){if(!w.canCreate||c===r.ADD||c===r.CREATE)return;const t=Ce.getAntiScaledMouseStagePosition(e,L,f,l),n={x:t.x-ce,y:t.y};Re(n)}}},Ye=()=>{te&&(document.body.style.overflow="hidden")},ze=e=>{e.button===1&&c===r.CAMERA_MOVE&&y(r.VIEW)},ge=(e,t)=>{c===r.CAMERA_MOVE&&_(e,t)},Ge=()=>{te&&(document.body.style.overflow="")},He=e=>{const o=(e.deltaY<0?1:-1)>0?f*1.25:f/1.25,s=Ce.getAntiScaledMouseStagePosition(e,L,f,l),E=f/o,M={x:E*(s.x+l.x)-s.x,y:E*(s.y+l.y)-s.y};o<1?(W(1),(l.x!=0||l.y!=0)&&D({x:0,y:0})):o>200?(W(200),D(M)):(W(o),D(M))},$e=(e,t)=>{if(t!==tt.ANNO_SELECTED){console.log("Unknown Canvas Action:",t);return}const n={...e,coordinates:A.convertStageCoordinatesToPercentaged([...e.coordinates],C,u)};I(n),w.canLabel&&B(Ee(e.coordinates))},me=e=>{const t=A.convertStageCoordinatesToPercentaged(e.coordinates,C,u),n={...e,coordinates:t};n.status===b.LOADED&&(n.status=b.CHANGED),oe(n)},je=()=>{if(c===r.CAMERA_MOVE)return p(qe,{});const t=[r.CREATE,r.ADD,r.MOVE].includes(c),n=K.map(o=>{const s=o.internalId===i?.internalId;return t&&!s?p("g",{},`annotationComponent_${o.internalId}`):p(nt,{scaledAnnotation:o,annotationSettings:w,possibleLabels:ee,svgScale:f,svgTranslation:$,pageToStageOffset:L,nodeRadius:V.nodeRadius,strokeWidth:V.strokeWidth,isSelected:s,isDisabled:Y&&s,onFinishAnnoCreate:Q,onLabelIconClicked:()=>S(!0),onAction:$e,onAnnoChanged:me,onAnnotationModeChange:E=>{E===N.MOVE&&y(r.MOVE),c===r.MOVE&&E===N.VIEW&&y(r.VIEW)},onNotification:se},`annotationComponent_${o.internalId}`)});if(i){const o=K.find(E=>E.internalId===i?.internalId),s=K.indexOf(o);n.push(n.splice(s,1)[0])}return p("g",{children:n})},Je=()=>p("circle",{cx:m.x/2,cy:m.y/2,r:"100%",style:{opacity:0},onContextMenu:e=>e.preventDefault(),onClick:()=>{S(!1)}}),pe={x:k.x+d.x/2,y:k.y+d.y/2};return F("div",{ref:x,style:{flex:"1 1 auto",minHeight:0,display:"flex",flexDirection:"column"},children:[w.canLabel&&p("div",{style:{position:"absolute",left:j?.x??0,top:j?.y??0,display:j?.y===void 0?"none":"inherit",zIndex:J?7e3:-1},children:p(ot,{defaultLabelId:q,isVisible:J,selectedLabelsIds:i?.labelIds,possibleLabels:ee,isMultilabel:w.canHaveMultipleLabels,onLabelSelect:e=>{if(setTimeout(()=>S(!1),0),e.length>0){const s=e.filter(E=>!i.labelIds.includes(E));s.length>0&&De(s[0])}const t=K.find(s=>s.internalId===i.internalId);if(!t)return;const n=t.status===b.LOADED?b.CHANGED:t.status,o={...i,coordinates:t.coordinates,labelIds:[...e],status:n};me(o)}})}),U&&F("div",{style:{position:"absolute",left:pe.x,top:pe.y,transform:"translate(-50%, -50%)",textAlign:"center",color:"white"},children:[p(st,{icon:rt,size:"5x",style:{marginBottom:15}}),p("h2",{children:"Marked as Junk"})]}),F("svg",{ref:ue,style:{flex:"1 1 auto",minHeight:0},onKeyDown:Fe,onKeyUp:Xe,onMouseMove:e=>ge(e.movementX,e.movementY),tabIndex:0,onMouseDown:e=>Ue(e),children:[F("g",{transform:`scale(${f}) translate(${$.x}, ${$.y})`,onMouseOver:Ye,onMouseLeave:Ge,onMouseUp:ze,onWheel:He,onMouseMove:e=>ge(e.movementX,e.movementY),onClick:()=>{I(void 0)},children:[p("image",{onContextMenu:e=>e.preventDefault(),href:X,ref:T,width:m.x>0?m.x:void 0,height:m.y>0?m.y:void 0}),je()]}),J&&Je(),U&&p("rect",{x:"0",y:"0",width:d.x,height:d.y,style:{opacity:.8},onContextMenu:e=>e.preventDefault(),onClick:()=>{B(void 0)}})]})]})};export{Dt as default};
@@ -0,0 +1,19 @@
1
+ import { default as Annotation } from './Annotation/logic/Annotation';
2
+ import { ExternalAnnotation, Label, UiConfig } from './types';
3
+ type SiaViewerProps = {
4
+ image: string;
5
+ annotations?: ExternalAnnotation[];
6
+ possibleLabels: Label[];
7
+ isJunk?: boolean;
8
+ uiConfig?: Partial<UiConfig>;
9
+ enableZoom?: boolean;
10
+ canSelect?: boolean;
11
+ onSelectAnnotation?: (annotation?: Annotation) => void;
12
+ };
13
+ /**
14
+ * View-only SIA component. Renders image + annotations without a toolbar and
15
+ * blocks all mutations (create / edit / delete / label). Zoom and selection
16
+ * can be toggled via props.
17
+ */
18
+ declare const SiaViewer: ({ image, annotations: propAnnotations, possibleLabels, isJunk, uiConfig: propUiConfig, enableZoom, canSelect, onSelectAnnotation, }: SiaViewerProps) => import("react/jsx-runtime").JSX.Element;
19
+ export default SiaViewer;
@@ -0,0 +1 @@
1
+ import{jsx as r}from"react/jsx-runtime";import{useState as s,useEffect as c}from"react";import p from"./Canvas/Canvas.js";import N from"./models/AnnotationMode.js";import h from"./models/AnnotationTool.js";const E={canCreate:!1,canEdit:!1,canLabel:!1,canHaveMultipleLabels:!1},f={nodeRadius:4,strokeWidth:4,imageCentered:!1},y={flex:"1 1 auto",minHeight:0,display:"flex",flexDirection:"column"},H=({image:n,annotations:e,possibleLabels:u,isJunk:m=!1,uiConfig:a,enableZoom:A=!0,canSelect:l=!0,onSelectAnnotation:I=()=>{}})=>{const[S,d]=s([]),[T,t]=s(),[C,g]=s(f);return c(()=>{if(n===void 0||e===void 0){d([]),t(void 0);return}let o=0;const v=e.map(i=>({...i,internalId:o++,mode:N.VIEW,selectedNode:1,status:i.status,annoTime:i.annoTime??0}));d(v),t(void 0)},[e,n]),c(()=>{g({...f,...a})},[a]),r("div",{style:y,onWheelCapture:o=>{A||o.stopPropagation()},children:r(p,{annotations:S,annotationSettings:E,image:n,isImageJunk:m,isPolygonSelectionMode:!1,possibleLabels:u,selectedAnnotation:l?T:void 0,selectedAnnoTool:h.Point,uiConfig:C,onAnnoCreated:()=>{},onAnnoChanged:()=>{},onAnnoCreationFinished:()=>{},onAnnoEditing:()=>{},onNotification:()=>{},onRequestNewAnnoId:()=>0,onSelectAnnotation:l?o=>{t(o),I(o)}:()=>{},onSetIsImageJunk:()=>{},onSetSelectedTool:()=>{},onShouldDeleteAnno:()=>{},onTraverseAnnotationHistory:()=>{}})})};export{H as default};
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './types';
2
2
  export { default as IconButton } from './IconButton';
3
3
  export { default as Sia } from './Sia';
4
+ export { default as SiaViewer } from './SiaViewer';
4
5
  export { default as transform } from './utils/transform';
5
6
  export { default as TagLabel } from './Toolbar/ToolbarItems/ImageToolItems/TagLabel';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- /* empty css *//* empty css */import{default as e}from"./IconButton.js";import{default as m}from"./Sia.js";import{default as l}from"./utils/transform.js";import{default as u}from"./Toolbar/ToolbarItems/ImageToolItems/TagLabel.js";export{e as IconButton,m as Sia,u as TagLabel,l as transform};
1
+ /* empty css */import{default as t}from"./IconButton.js";import{default as f}from"./Sia.js";import{default as l}from"./SiaViewer.js";import{default as s}from"./utils/transform.js";import{default as d}from"./Toolbar/ToolbarItems/ImageToolItems/TagLabel.js";export{t as IconButton,f as Sia,l as SiaViewer,d as TagLabel,s as transform};
@@ -2,9 +2,9 @@ import { StoryObj } from '@storybook/react';
2
2
  import { default as AnnotationTool } from '../../models/AnnotationTool';
3
3
  import { AnnotationSettings, UiConfig } from '../../types';
4
4
  export declare const ActionsData: {
5
- onAnnoEvent: any;
6
- onKeyDown: any;
7
- onKeyUp: any;
5
+ onAnnoEvent: import('@vitest/spy').Mock<(...args: any[]) => any>;
6
+ onKeyDown: import('@vitest/spy').Mock<(...args: any[]) => any>;
7
+ onKeyUp: import('@vitest/spy').Mock<(...args: any[]) => any>;
8
8
  };
9
9
  declare const meta: {
10
10
  title: string;
@@ -2,9 +2,9 @@ import { StoryObj } from '@storybook/react';
2
2
  import { default as AnnotationTool } from '../../models/AnnotationTool';
3
3
  import { UiConfig } from '../../types';
4
4
  export declare const ActionsData: {
5
- onAnnoEvent: any;
6
- onKeyDown: any;
7
- onKeyUp: any;
5
+ onAnnoEvent: import('@vitest/spy').Mock<(...args: any[]) => any>;
6
+ onKeyDown: import('@vitest/spy').Mock<(...args: any[]) => any>;
7
+ onKeyUp: import('@vitest/spy').Mock<(...args: any[]) => any>;
8
8
  };
9
9
  declare const meta: {
10
10
  title: string;
@@ -22,9 +22,9 @@ declare const meta: {
22
22
  tags: string[];
23
23
  excludeStories: RegExp;
24
24
  args: {
25
- onAnnoEvent: any;
26
- onKeyDown: any;
27
- onKeyUp: any;
25
+ onAnnoEvent: import('@vitest/spy').Mock<(...args: any[]) => any>;
26
+ onKeyDown: import('@vitest/spy').Mock<(...args: any[]) => any>;
27
+ onKeyUp: import('@vitest/spy').Mock<(...args: any[]) => any>;
28
28
  };
29
29
  };
30
30
  export default meta;
@@ -0,0 +1,52 @@
1
+ import { StoryObj } from '@storybook/react';
2
+ export declare const ActionsData: {};
3
+ declare const meta: {
4
+ title: string;
5
+ component: ({ image, annotations: propAnnotations, possibleLabels, isJunk, uiConfig: propUiConfig, enableZoom, canSelect, onSelectAnnotation, }: {
6
+ image: string;
7
+ annotations?: import('../..').ExternalAnnotation[];
8
+ possibleLabels: import('../..').Label[];
9
+ isJunk?: boolean;
10
+ uiConfig?: Partial<import('../..').UiConfig>;
11
+ enableZoom?: boolean;
12
+ canSelect?: boolean;
13
+ onSelectAnnotation?: (annotation?: import('../../models').Annotation) => void;
14
+ }) => import("react/jsx-runtime").JSX.Element;
15
+ parameters: {
16
+ layout: string;
17
+ };
18
+ tags: string[];
19
+ excludeStories: RegExp;
20
+ args: {};
21
+ };
22
+ export default meta;
23
+ type Story = StoryObj<typeof meta>;
24
+ /**
25
+ * SiaViewer with point annotations. No toolbar, no editing.
26
+ * Try clicking annotations to select them and scrolling to zoom.
27
+ */
28
+ export declare const WithPointAnnotations: Story;
29
+ /**
30
+ * SiaViewer with bbox annotations.
31
+ */
32
+ export declare const WithBBoxAnnotations: Story;
33
+ /**
34
+ * SiaViewer with line annotations.
35
+ */
36
+ export declare const WithLineAnnotations: Story;
37
+ /**
38
+ * SiaViewer with polygon annotations.
39
+ */
40
+ export declare const WithPolygonAnnotations: Story;
41
+ /**
42
+ * SiaViewer with zoom disabled.
43
+ */
44
+ export declare const ZoomDisabled: Story;
45
+ /**
46
+ * SiaViewer with selection disabled. Annotations cannot be clicked.
47
+ */
48
+ export declare const SelectionDisabled: Story;
49
+ /**
50
+ * SiaViewer marked as junk.
51
+ */
52
+ export declare const Junk: Story;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lost-sia",
3
- "version": "3.1.3",
3
+ "version": "3.2.0-alpha0",
4
4
  "description": "Single Image Annotation Tool",
5
5
  "license": "MIT",
6
6
  "repository": "l3p-cv/lost-sia",
@@ -63,9 +63,7 @@
63
63
  "react": "^19.2.1",
64
64
  "react-dom": "^19.2.1",
65
65
  "react-draggable": "^4.5.0",
66
- "sass": "^1.95.0",
67
- "semantic-ui-css": "2.5.0",
68
- "semantic-ui-react": "^2.0.3"
66
+ "sass": "^1.95.0"
69
67
  },
70
68
  "peerDependencies": {
71
69
  "@coreui/react": "^5.9.1",
@@ -81,6 +79,7 @@
81
79
  "@storybook/addon-links": "^10.1.6",
82
80
  "@storybook/react": "^10.1.6",
83
81
  "@storybook/react-vite": "^10.1.6",
82
+ "@storybook/test": "^8.6.15",
84
83
  "@types/react": "^19.2.7",
85
84
  "@typescript-eslint/eslint-plugin": "^8.46.1",
86
85
  "@typescript-eslint/parser": "^8.46.1",
@@ -780,7 +780,9 @@ const Canvas = ({
780
780
  onSelectAnnotation(percentagedAnnotation)
781
781
 
782
782
  // get top left point of annotation
783
- setLabelInputPosition(getAnnoTopLeftPagePosition(annotation.coordinates))
783
+ if (annotationSettings.canLabel) {
784
+ setLabelInputPosition(getAnnoTopLeftPagePosition(annotation.coordinates))
785
+ }
784
786
  }
785
787
 
786
788
  const handleOnAnnoChanged = (annotation: Annotation) => {
@@ -919,6 +921,7 @@ const Canvas = ({
919
921
  flexDirection: 'column',
920
922
  }}
921
923
  >
924
+ {annotationSettings.canLabel && (
922
925
  <div
923
926
  style={{
924
927
  position: 'absolute',
@@ -973,6 +976,7 @@ const Canvas = ({
973
976
  }}
974
977
  />
975
978
  </div>
979
+ )}
976
980
 
977
981
  {isImageJunk && (
978
982
  <div
@@ -0,0 +1,125 @@
1
+ import { CSSProperties, useEffect, useState, WheelEvent } from 'react'
2
+ import Canvas from './Canvas/Canvas'
3
+ import Annotation from './Annotation/logic/Annotation'
4
+ import AnnotationMode from './models/AnnotationMode'
5
+ import AnnotationTool from './models/AnnotationTool'
6
+ import { AnnotationSettings, ExternalAnnotation, Label, UiConfig } from './types'
7
+
8
+ type SiaViewerProps = {
9
+ image: string
10
+ annotations?: ExternalAnnotation[]
11
+ possibleLabels: Label[]
12
+ isJunk?: boolean
13
+ uiConfig?: Partial<UiConfig>
14
+ enableZoom?: boolean
15
+ canSelect?: boolean
16
+ onSelectAnnotation?: (annotation?: Annotation) => void
17
+ }
18
+
19
+ const VIEW_ANNOTATION_SETTINGS: AnnotationSettings = {
20
+ canCreate: false,
21
+ canEdit: false,
22
+ canLabel: false,
23
+ canHaveMultipleLabels: false,
24
+ }
25
+
26
+ const DEFAULT_UI_CONFIG: UiConfig = {
27
+ nodeRadius: 4,
28
+ strokeWidth: 4,
29
+ imageCentered: false,
30
+ }
31
+
32
+ const containerStyle: CSSProperties = {
33
+ flex: '1 1 auto',
34
+ minHeight: 0,
35
+ display: 'flex',
36
+ flexDirection: 'column',
37
+ }
38
+
39
+ /**
40
+ * View-only SIA component. Renders image + annotations without a toolbar and
41
+ * blocks all mutations (create / edit / delete / label). Zoom and selection
42
+ * can be toggled via props.
43
+ */
44
+ const SiaViewer = ({
45
+ image,
46
+ annotations: propAnnotations,
47
+ possibleLabels,
48
+ isJunk = false,
49
+ uiConfig: propUiConfig,
50
+ enableZoom = true,
51
+ canSelect = true,
52
+ onSelectAnnotation = () => {},
53
+ }: SiaViewerProps) => {
54
+ const [annotations, setAnnotations] = useState<Annotation[]>([])
55
+ const [selectedAnnotation, setSelectedAnnotation] = useState<
56
+ Annotation | undefined
57
+ >()
58
+ const [uiConfig, setUiConfig] = useState<UiConfig>(DEFAULT_UI_CONFIG)
59
+
60
+ // (re)initialize annotations whenever the annotations or image prop changes
61
+ useEffect(() => {
62
+ if (image === undefined || propAnnotations === undefined) {
63
+ setAnnotations([])
64
+ setSelectedAnnotation(undefined)
65
+ return
66
+ }
67
+
68
+ let internalId = 0
69
+ const next: Annotation[] = propAnnotations.map((externalAnno) => ({
70
+ ...externalAnno,
71
+ internalId: internalId++,
72
+ mode: AnnotationMode.VIEW,
73
+ selectedNode: 1,
74
+ status: externalAnno.status,
75
+ annoTime: externalAnno.annoTime ?? 0,
76
+ }))
77
+
78
+ setAnnotations(next)
79
+ setSelectedAnnotation(undefined)
80
+ }, [propAnnotations, image])
81
+
82
+ useEffect(() => {
83
+ setUiConfig({ ...DEFAULT_UI_CONFIG, ...propUiConfig })
84
+ }, [propUiConfig])
85
+
86
+ const stopZoom = (e: WheelEvent) => {
87
+ if (!enableZoom) e.stopPropagation()
88
+ }
89
+
90
+ return (
91
+ <div style={containerStyle} onWheelCapture={stopZoom}>
92
+ <Canvas
93
+ annotations={annotations}
94
+ annotationSettings={VIEW_ANNOTATION_SETTINGS}
95
+ image={image}
96
+ isImageJunk={isJunk}
97
+ isPolygonSelectionMode={false}
98
+ possibleLabels={possibleLabels}
99
+ selectedAnnotation={canSelect ? selectedAnnotation : undefined}
100
+ selectedAnnoTool={AnnotationTool.Point}
101
+ uiConfig={uiConfig}
102
+ onAnnoCreated={() => {}}
103
+ onAnnoChanged={() => {}}
104
+ onAnnoCreationFinished={() => {}}
105
+ onAnnoEditing={() => {}}
106
+ onNotification={() => {}}
107
+ onRequestNewAnnoId={() => 0}
108
+ onSelectAnnotation={
109
+ canSelect
110
+ ? (annotation) => {
111
+ setSelectedAnnotation(annotation)
112
+ onSelectAnnotation(annotation)
113
+ }
114
+ : () => {}
115
+ }
116
+ onSetIsImageJunk={() => {}}
117
+ onSetSelectedTool={() => {}}
118
+ onShouldDeleteAnno={() => {}}
119
+ onTraverseAnnotationHistory={() => {}}
120
+ />
121
+ </div>
122
+ )
123
+ }
124
+
125
+ export default SiaViewer
@@ -11,7 +11,6 @@ import {
11
11
  import { Label } from '../../../types'
12
12
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
13
13
  import { faTag } from '@fortawesome/free-solid-svg-icons'
14
- import { IconProps } from 'semantic-ui-react'
15
14
  import TagLabel from './TagLabel'
16
15
 
17
16
  type ImageLabelInputProps = {
@@ -69,7 +68,7 @@ const ImageLabelInput = ({
69
68
  if (!selectedLabelsIds || selectedLabelsIds.length === 0)
70
69
  return (
71
70
  <div style={{ marginTop: 6 }}>
72
- <FontAwesomeIcon icon={faTag as IconProps} />
71
+ <FontAwesomeIcon icon={faTag} />
73
72
  </div>
74
73
  )
75
74
 
package/src/index.ts CHANGED
@@ -1,4 +1,3 @@
1
- import 'semantic-ui-css/semantic.min.css'
2
1
  import './SIA.scss'
3
2
 
4
3
  // export all type definitions
@@ -6,5 +5,6 @@ export * from './types'
6
5
 
7
6
  export { default as IconButton } from './IconButton'
8
7
  export { default as Sia } from './Sia'
8
+ export { default as SiaViewer } from './SiaViewer'
9
9
  export { default as transform } from './utils/transform'
10
10
  export { default as TagLabel } from './Toolbar/ToolbarItems/ImageToolItems/TagLabel'
@@ -0,0 +1,105 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+
3
+ import SiaViewer from '../../SiaViewer'
4
+
5
+ import exampleImage from '../exampleData/exampleImage'
6
+ import exampleLabels from '../exampleData/exampleLabels'
7
+ import exampleExternalAnnotations from '../exampleData/exampleExternalAnnotations'
8
+
9
+ export const ActionsData = {}
10
+
11
+ const meta = {
12
+ title: 'Components/SiaViewer',
13
+ component: SiaViewer,
14
+ parameters: {
15
+ layout: 'fullscreen',
16
+ },
17
+ tags: ['!autodocs'],
18
+ excludeStories: /.*Data$/,
19
+ args: {
20
+ ...ActionsData,
21
+ },
22
+ } satisfies Meta<typeof SiaViewer>
23
+
24
+ export default meta
25
+ type Story = StoryObj<typeof meta>
26
+
27
+ const defaultArgs = {
28
+ ...ActionsData,
29
+ image: exampleImage,
30
+ possibleLabels: exampleLabels.voc,
31
+ }
32
+
33
+ /**
34
+ * SiaViewer with point annotations. No toolbar, no editing.
35
+ * Try clicking annotations to select them and scrolling to zoom.
36
+ */
37
+ export const WithPointAnnotations: Story = {
38
+ args: {
39
+ ...defaultArgs,
40
+ annotations: exampleExternalAnnotations.point,
41
+ },
42
+ }
43
+
44
+ /**
45
+ * SiaViewer with bbox annotations.
46
+ */
47
+ export const WithBBoxAnnotations: Story = {
48
+ args: {
49
+ ...defaultArgs,
50
+ annotations: exampleExternalAnnotations.bbox,
51
+ },
52
+ }
53
+
54
+ /**
55
+ * SiaViewer with line annotations.
56
+ */
57
+ export const WithLineAnnotations: Story = {
58
+ args: {
59
+ ...defaultArgs,
60
+ annotations: exampleExternalAnnotations.line,
61
+ },
62
+ }
63
+
64
+ /**
65
+ * SiaViewer with polygon annotations.
66
+ */
67
+ export const WithPolygonAnnotations: Story = {
68
+ args: {
69
+ ...defaultArgs,
70
+ annotations: exampleExternalAnnotations.polygon,
71
+ },
72
+ }
73
+
74
+ /**
75
+ * SiaViewer with zoom disabled.
76
+ */
77
+ export const ZoomDisabled: Story = {
78
+ args: {
79
+ ...defaultArgs,
80
+ annotations: exampleExternalAnnotations.polygon,
81
+ enableZoom: false,
82
+ },
83
+ }
84
+
85
+ /**
86
+ * SiaViewer with selection disabled. Annotations cannot be clicked.
87
+ */
88
+ export const SelectionDisabled: Story = {
89
+ args: {
90
+ ...defaultArgs,
91
+ annotations: exampleExternalAnnotations.polygon,
92
+ canSelect: false,
93
+ },
94
+ }
95
+
96
+ /**
97
+ * SiaViewer marked as junk.
98
+ */
99
+ export const Junk: Story = {
100
+ args: {
101
+ ...defaultArgs,
102
+ annotations: exampleExternalAnnotations.polygon,
103
+ isJunk: true,
104
+ },
105
+ }
@@ -37,10 +37,10 @@ const point: ExternalAnnotation[] = [
37
37
  const line: ExternalAnnotation[] = [
38
38
  {
39
39
  coordinates: [
40
- { x: 50, y: 50 },
41
- { x: 200, y: 100 },
42
- { x: 250, y: 100 },
43
- { x: 250, y: 200 },
40
+ { x: 0.05, y: 0.05 },
41
+ { x: 0.2, y: 0.1 },
42
+ { x: 0.25, y: 0.1 },
43
+ { x: 0.25, y: 0.2 },
44
44
  ],
45
45
  labelIds: [5],
46
46
  type: AnnotationTool.Line,
@@ -48,11 +48,11 @@ const line: ExternalAnnotation[] = [
48
48
  },
49
49
  {
50
50
  coordinates: [
51
- { x: 259.883, y: 300.424 },
52
- { x: 350, y: 331.5263919270834 },
53
- { x: 355, y: 320 },
54
- { x: 370, y: 300 },
55
- { x: 270, y: 250 },
51
+ { x: 0.26, y: 0.3 },
52
+ { x: 0.35, y: 0.33 },
53
+ { x: 0.36, y: 0.32 },
54
+ { x: 0.37, y: 0.3 },
55
+ { x: 0.27, y: 0.25 },
56
56
  ],
57
57
  labelIds: [8, 11],
58
58
  type: AnnotationTool.Line,
@@ -63,8 +63,8 @@ const line: ExternalAnnotation[] = [
63
63
  const bbox: ExternalAnnotation[] = [
64
64
  {
65
65
  coordinates: [
66
- { x: 50, y: 50 },
67
- { x: 200, y: 200 },
66
+ { x: 0.05, y: 0.05 },
67
+ { x: 0.2, y: 0.2 },
68
68
  ],
69
69
  labelIds: [5],
70
70
  type: AnnotationTool.BBox,
@@ -72,8 +72,8 @@ const bbox: ExternalAnnotation[] = [
72
72
  },
73
73
  {
74
74
  coordinates: [
75
- { x: 250, y: 100 },
76
- { x: 450, y: 150 },
75
+ { x: 0.25, y: 0.1 },
76
+ { x: 0.45, y: 0.15 },
77
77
  ],
78
78
  labelIds: [8, 11],
79
79
  type: AnnotationTool.BBox,
@@ -84,10 +84,10 @@ const bbox: ExternalAnnotation[] = [
84
84
  const polygon: ExternalAnnotation[] = [
85
85
  {
86
86
  coordinates: [
87
- { x: 50, y: 50 },
88
- { x: 200, y: 100 },
89
- { x: 250, y: 100 },
90
- { x: 250, y: 200 },
87
+ { x: 0.05, y: 0.05 },
88
+ { x: 0.2, y: 0.1 },
89
+ { x: 0.25, y: 0.1 },
90
+ { x: 0.25, y: 0.2 },
91
91
  ],
92
92
  labelIds: [5],
93
93
  status: AnnotationStatus.LOADED,
@@ -95,11 +95,11 @@ const polygon: ExternalAnnotation[] = [
95
95
  },
96
96
  {
97
97
  coordinates: [
98
- { x: 259.883, y: 300.424 },
99
- { x: 350, y: 331.5263919270834 },
100
- { x: 355, y: 320 },
101
- { x: 370, y: 300 },
102
- { x: 270, y: 250 },
98
+ { x: 0.26, y: 0.3 },
99
+ { x: 0.35, y: 0.33 },
100
+ { x: 0.36, y: 0.32 },
101
+ { x: 0.37, y: 0.3 },
102
+ { x: 0.27, y: 0.25 },
103
103
  ],
104
104
  labelIds: [8, 11],
105
105
  status: AnnotationStatus.LOADED,