lost-sia 3.1.0 → 3.1.1-alpha3

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.
@@ -1 +1 @@
1
- import{jsxs as L,jsx as m,Fragment as Ze}from"react/jsx-runtime";import{useState as y,useRef as Z,useEffect as I}from"react";import M from"../models/AnnotationTool.js";import i from"../models/EditorModes.js";import qe from"../utils/KeyMapper.js";import c from"../models/KeyAction.js";import Ae from"../Annotation/logic/Annotation.js";import et from"../models/CanvasAction.js";import tt from"../Annotation/ui/AnnotationComponent.js";import he from"../utils/mouse.js";import _ from"../models/AnnotationMode.js";import nt from"./LabelInput.js";import{FontAwesomeIcon as ot}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 st from"../models/NotificationType.js";import it from"../utils/TimeUtils.js";import xe from"../utils/windowViewport.js";const bt=({annotations:v=[],annotationSettings:W,defaultLabelId:q,image:ee,isFullscreen:Ce=!1,isImageJunk:B=!1,isPolygonSelectionMode:K=!1,polygonOperationResult:F={annotationsToDelete:[],polygonsToCreate:[]},possibleLabels:te,preventScrolling:ne=!0,selectedAnnotation:s,selectedAnnoTool:N,toolbarHeight:X=0,uiConfig:z,onAnnoCreated:ve,onAnnoCreationFinished:oe,onAnnoChanged:re,onAnnoEditing:Te=g=>{},onNotification:se=g=>{},onRequestNewAnnoId:R,onSelectAnnotation:T,onSetIsImageJunk:Ie,onSetSelectedTool:Oe=g=>{},onShouldDeleteAnno:ie,onTraverseAnnotationHistory:ae})=>{const[g,h]=y(i.VIEW),[Me,we]=y(),[ce,be]=y(q),[V,Se]=y({x:-1,y:-1}),[le,de]=y(0),k={x:V.x,y:V.y},[u,U]=y({x:-1,y:-1}),[d,Y]=y({x:-1,y:-1}),[E,fe]=y({x:-1,y:-1}),[l,P]=y(1),[a,b]=y({x:0,y:0}),G={x:a.x+le,y:a.y},[H,$]=y(),[j,S]=y(!1),ue=Z(null),x=Z(null),p=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),De=()=>{if(p?.current===null)return{x:0,y:0};const e=u.x*C;if(z.imageCentered&&d.x>e){const f=(d.x-e)/2;de(f)}else de(0);const{top:t,left:n}=x.current.getBoundingClientRect(),o={x:n+window.scrollX,y:t+window.scrollY};Se(o)},_e=new qe(e=>We(e)),Ne=e=>{h(i.CREATE);const t=A.convertStageCoordinatesToPercentaged([e],C,u);N===M.BBox&&t.push(t[0]);const n=R(),o=new Ae(n,N,t);if(we(performance.now()),ce!==void 0&&(o.labelIds=[ce]),ve(o),N===M.Point){const r={...o,coordinates:[e],annoTime:0};Q(r)}},Re=()=>{if(s&&![M.Line,M.Polygon].includes(s.type))return;const e=v.find(n=>n.internalId===s?.internalId);if(e===void 0)return;h(i.CREATE),Oe(e.type);const t={...e,mode:_.CREATE,status:w.CREATING,internalId:R(),selectedNode:e.coordinates.length-1};Te(t)},Ve=()=>{const e=s?s.internalId:0,t=v.find(n=>n.internalId>e);if(t)return T(t);if(v.length>0)return T(v[0])},ke=()=>{const e=s?s.internalId:0,t=[...v];t.sort((o,r)=>r.internalId-o.internalId);const n=t.find(o=>o.internalId<e);if(n)return T(n);if(v.length>0)return T(v.at(-1))},Pe=()=>{if(s){const e=JSON.stringify(s);localStorage.setItem("lostAnnotationClipboard",e);const t={title:"Success",message:"Annotation copied",type:st.SUCCESS};se(t)}},Le=()=>{const e=localStorage.getItem("lostAnnotationClipboard");if(e==null)return;const t=JSON.parse(e);t.internalId=R(),t.externalId="",oe(t,!0),T(t)},We=e=>{switch(e){case c.EDIT_LABEL:s&&S(!0);break;case c.DELETE_ANNO:s&&ie(s.internalId);break;case c.DELETE_ANNO_IN_CREATION:g===i.CREATE&&(ie(s.internalId),h(i.VIEW));break;case c.ENTER_ANNO_ADD_MODE:console.log("KeyAction TODO: ENTER_ANNO_ADD_MODE");break;case c.LEAVE_ANNO_ADD_MODE:console.log("KeyAction TODO: LEAVE_ANNO_ADD_MODE");break;case c.UNDO:ae(!0);break;case c.REDO:ae(!1);break;case c.TRAVERSE_ANNOS:Ve();break;case c.TRAVERSE_ANNOS_BACKWARDS:ke();break;case c.CAM_MOVE_LEFT:D(20*l,0);break;case c.CAM_MOVE_RIGHT:D(-20*l,0);break;case c.CAM_MOVE_UP:D(0,20*l);break;case c.CAM_MOVE_DOWN:D(0,-20*l);break;case c.CAM_MOVE_STOP:console.log("KeyAction TODO: CAM_MOVE_STOP");break;case c.COPY_ANNOTATION:Pe();break;case c.PASTE_ANNOTATION:Le();break;case c.RECREATE_ANNO:console.log("KeyAction TODO: RECREATE_ANNO"),Re();break;case c.TOGGLE_IMAGE_JUNK:if(g===i.ADD||g===i.CREATE)return;Ie(!B);break;default:console.log("Unknown KeyAction",e);break}},D=(e,t)=>{let n=a.x+e/l,o=a.y+t/l;const r=d.x*.45,f=d.x*.55,O=d.y*.45,Je=d.y*.55,Qe={x:0,y:0},me=xe.getViewportCoordinates(a,d,l,Qe),pe=xe.getViewportCoordinates(a,d,l,d);me.vX>=r?n=a.x-5:pe.vX<=f?n=a.x+5:me.vY>=O?o=a.y-5:pe.vY<=Je&&(o=a.y+5),b({x:n,y:o})},J=(e=>E.x<=0||E.y<=0||u.x<=0||u.y<=0?[]:v.map(n=>({...n,coordinates:A.convertPercentagedCoordinatesToStage(n.coordinates,u,E)})))(),Be=()=>{if(h(i.VIEW),fe({x:-1,y:-1}),p.current!==null){const{width:e,height:t}=p.current.getBoundingClientRect();U({x:e,y:t})}P(1),b({x:0,y:0}),$(void 0),S(!1)};I(()=>{ue.current?.focus()},[]),I(()=>{if(x?.current!==void 0){const{width:e,height:t}=x.current.getBoundingClientRect(),n=t-X;Y({x:e,y:n});const o=new ResizeObserver(()=>{const{width:r,height:f}=x.current.getBoundingClientRect(),O=f-X;Y({x:r,y:O})});return o.observe(x.current),()=>o.disconnect()}Be()},[ee,Ce]),I(()=>{De()},[p,a,d]),I(()=>{if(x.current===null)return;const{width:e,height:t}=x.current.getBoundingClientRect(),n=t-X;Y({x:e,y:n})},[x]),I(()=>{if(p.current===null)return;const{width:e,height:t}=p.current.getBoundingClientRect();U({x:e,y:t});const n=new ResizeObserver(()=>{const{width:o,height:r}=p.current.getBoundingClientRect();U({x:o,y:r})});return n.observe(p.current),()=>n.disconnect()},[p]),I(()=>{if(C===0)return;const e={x:u.x*C,y:u.y*C};fe(e)},[C,u]),I(()=>{K&&F.polygonsToCreate!==void 0&&F.polygonsToCreate.forEach(e=>{const t=R(),n=new Ae(t,e.type,A.convertPercentagedCoordinatesToStage(e.coordinates,u,E),_.VIEW,w.CREATED);Q(n)})},[F]);const Q=e=>{h(i.VIEW);const t={...e,mode:_.VIEW};if(e.type!==M.Point){const r=it.getRoundedDuration(Me,performance.now());t.annoTime=r}const n=A.convertStageCoordinatesToPercentaged(e.coordinates,C,u);t.coordinates=n,re(t);const o=N===M.Point||K;oe(t,o)},Ke=e=>{_e.keyDown(e.key,e.shiftKey,e.ctrlKey)&&e.preventDefault()},Fe=e=>{e.preventDefault()},Xe=e=>{if(e.button!==0){if(e.button===1)h(i.CAMERA_MOVE);else if(e.button===2){if(!W.canCreate||g===i.ADD||g===i.CREATE)return;const t=he.getAntiScaledMouseStagePosition(e,k,l,a),n={x:t.x-le,y:t.y};Ne(n)}}},ze=()=>{ne&&(document.body.style.overflow="hidden")},Ue=e=>{e.button===1&&h(i.VIEW)},ge=(e,t)=>{g===i.CAMERA_MOVE&&D(e,t)},Ye=()=>{ne&&(document.body.style.overflow="")},Ge=e=>{const o=(e.deltaY<0?1:-1)>0?l*1.25:l/1.25,r=he.getAntiScaledMouseStagePosition(e,k,l,a),f=l/o,O={x:f*(r.x+a.x)-r.x,y:f*(r.y+a.y)-r.y};o<1?(P(1),(a.x!=0||a.y!=0)&&b({x:0,y:0})):o>200?(P(200),b(O)):(P(o),b(O))},He=(e,t)=>{if(t!==et.ANNO_SELECTED){console.log("Unknown Canvas Action:",t);return}const n={...e,coordinates:A.convertStageCoordinatesToPercentaged([...e.coordinates],C,u)};T(n);const o=A.getMostLeftPoints(e.coordinates),r=A.getTopPoint(o)[0],f=A.convertStageToPage(r,k,l,a);$(f)},ye=e=>{const t=A.convertStageCoordinatesToPercentaged(e.coordinates,C,u),n={...e,coordinates:t};n.status===w.LOADED&&(n.status=w.CHANGED),re(n)},$e=()=>{if(g===i.CAMERA_MOVE)return m(Ze,{});const t=[i.CREATE,i.ADD,i.MOVE].includes(g),n=J.map(o=>{const r=o.internalId===s?.internalId;return t&&!r?m("g",{},`annotationComponent_${o.internalId}`):m(tt,{scaledAnnotation:o,annotationSettings:W,possibleLabels:te,svgScale:l,svgTranslation:G,pageToStageOffset:k,nodeRadius:z.nodeRadius,strokeWidth:z.strokeWidth,isSelected:r,isDisabled:K&&r,onFinishAnnoCreate:Q,onLabelIconClicked:()=>S(!0),onAction:He,onAnnoChanged:ye,onAnnotationModeChange:f=>{f===_.MOVE&&h(i.MOVE),g===i.MOVE&&f===_.VIEW&&h(i.VIEW)},onNotification:se},`annotationComponent_${o.internalId}`)});if(s){const o=J.find(f=>f.internalId===s?.internalId),r=J.indexOf(o);n.push(n.splice(r,1)[0])}return m("g",{children:n})},je=()=>m("circle",{cx:E.x/2,cy:E.y/2,r:"100%",style:{opacity:0},onContextMenu:e=>e.preventDefault(),onClick:()=>{S(!1)}}),Ee={x:V.x+d.x/2,y:V.y+d.y/2};return L("div",{ref:x,style:{flex:"1 1 auto",minHeight:0,display:"flex",flexDirection:"column"},children:[m("div",{style:{position:"absolute",left:H?.x??0,top:H?.y??0,display:H?.y===void 0?"none":"inherit",zIndex:j?7e3:-1},children:m(nt,{defaultLabelId:q,isVisible:j,selectedLabelsIds:s?.labelIds,possibleLabels:te,isMultilabel:W.canHaveMultipleLabels,onLabelSelect:e=>{if(S(!1),e.length>0){const o=e.filter(r=>!s.labelIds.includes(r));o.length>0&&be(o[0])}const t=s.status===w.LOADED?w.CHANGED:s.status,n={...s,coordinates:A.convertPercentagedCoordinatesToStage(s.coordinates,u,E),labelIds:[...e],status:t};ye(n)}})}),B&&L("div",{style:{position:"absolute",left:Ee.x,top:Ee.y,transform:"translate(-50%, -50%)",textAlign:"center",color:"white"},children:[m(ot,{icon:rt,size:"5x",style:{marginBottom:15}}),m("h2",{children:"Marked as Junk"})]}),L("svg",{ref:ue,style:{flex:"1 1 auto",minHeight:0},onKeyDown:Ke,onKeyUp:Fe,onMouseMove:e=>ge(e.movementX,e.movementY),tabIndex:0,onMouseDown:e=>Xe(e),children:[L("g",{transform:`scale(${l}) translate(${G.x}, ${G.y})`,onMouseOver:ze,onMouseLeave:Ye,onMouseUp:Ue,onWheel:Ge,onMouseMove:e=>ge(e.movementX,e.movementY),onClick:()=>{T(void 0)},children:[m("image",{onContextMenu:e=>e.preventDefault(),href:ee,ref:p,width:E.x>0?E.x:void 0,height:E.y>0?E.y:void 0}),$e()]}),j&&je(),B&&m("rect",{x:"0",y:"0",width:d.x,height:d.y,style:{opacity:.8},onContextMenu:e=>e.preventDefault(),onClick:()=>{$(void 0)}})]})]})};export{bt as default};
1
+ import{jsxs as B,jsx as m,Fragment as qe}from"react/jsx-runtime";import{useState as y,useRef as Z,useEffect as I}from"react";import M from"../models/AnnotationTool.js";import i from"../models/EditorModes.js";import et from"../utils/KeyMapper.js";import c from"../models/KeyAction.js";import he from"../Annotation/logic/Annotation.js";import tt from"../models/CanvasAction.js";import nt from"../Annotation/ui/AnnotationComponent.js";import xe from"../utils/mouse.js";import _ from"../models/AnnotationMode.js";import ot from"./LabelInput.js";import{FontAwesomeIcon as rt}from"@fortawesome/react-fontawesome";import{faBan as st}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 Ce from"../utils/windowViewport.js";const bt=({annotations:v=[],annotationSettings:K,defaultLabelId:q,image:ee,isFullscreen:ve=!1,isImageJunk:F=!1,isPolygonSelectionMode:X=!1,polygonOperationResult:z={annotationsToDelete:[],polygonsToCreate:[]},possibleLabels:te,preventScrolling:ne=!0,selectedAnnotation:s,selectedAnnoTool:N,toolbarHeight:U=0,uiConfig:Y,onAnnoCreated:Te,onAnnoCreationFinished:oe,onAnnoChanged:re,onAnnoEditing:Ie=g=>{},onNotification:se=g=>{},onRequestNewAnnoId:R,onSelectAnnotation:T,onSetIsImageJunk:Oe,onSetSelectedTool:Me=g=>{},onShouldDeleteAnno:ie,onTraverseAnnotationHistory:ae})=>{const[g,h]=y(i.VIEW),[we,Se]=y(),[ce,be]=y(q),[P,De]=y({x:-1,y:-1}),[le,de]=y(0),V={x:P.x,y:P.y},[u,G]=y({x:-1,y:-1}),[d,H]=y({x:-1,y:-1}),[E,fe]=y({x:-1,y:-1}),[l,k]=y(1),[a,S]=y({x:0,y:0}),$={x:a.x+le,y:a.y},[j,L]=y(),[J,b]=y(!1),ue=Z(null),x=Z(null),p=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(p?.current===null)return{x:0,y:0};const e=u.x*C;if(Y.imageCentered&&d.x>e){const f=(d.x-e)/2;de(f)}else de(0);const{top:t,left:n}=x.current.getBoundingClientRect(),o={x:n+window.scrollX,y:t+window.scrollY};De(o)},Ne=new et(e=>Be(e)),Re=e=>{h(i.CREATE);const t=A.convertStageCoordinatesToPercentaged([e],C,u);N===M.BBox&&t.push(t[0]);const n=R(),o=new he(n,N,t);if(Se(performance.now()),ce!==void 0&&(o.labelIds=[ce]),Te(o),N===M.Point){const r={...o,coordinates:[e],annoTime:0};Q(r)}},Pe=()=>{if(s&&![M.Line,M.Polygon].includes(s.type))return;const e=v.find(n=>n.internalId===s?.internalId);if(e===void 0)return;h(i.CREATE),Me(e.type);const t={...e,mode:_.CREATE,status:w.CREATING,internalId:R(),selectedNode:e.coordinates.length-1};Ie(t)},Ve=()=>{const e=s?s.internalId:0,t=v.find(n=>n.internalId>e);if(t)return T(t);if(v.length>0)return T(v[0])},ke=()=>{const e=s?s.internalId:0,t=[...v];t.sort((o,r)=>r.internalId-o.internalId);const n=t.find(o=>o.internalId<e);if(n)return T(n);if(v.length>0)return T(v.at(-1))},Le=()=>{if(s){const e=JSON.stringify(s);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=R(),t.externalId="",oe(t,!0),T(t)},ge=e=>{const t=A.getMostLeftPoints(e),n=A.getTopPoint(t)[0];return A.convertStageToPage(n,V,l,a)},Be=e=>{switch(e){case c.EDIT_LABEL:if(s){const t=A.convertPercentagedCoordinatesToStage(s.coordinates,u,E);L(ge(t)),b(!0)}break;case c.DELETE_ANNO:s&&ie(s.internalId);break;case c.DELETE_ANNO_IN_CREATION:g===i.CREATE&&(ie(s.internalId),h(i.VIEW));break;case c.ENTER_ANNO_ADD_MODE:console.log("KeyAction TODO: ENTER_ANNO_ADD_MODE");break;case c.LEAVE_ANNO_ADD_MODE:console.log("KeyAction TODO: LEAVE_ANNO_ADD_MODE");break;case c.UNDO:ae(!0);break;case c.REDO:ae(!1);break;case c.TRAVERSE_ANNOS:Ve();break;case c.TRAVERSE_ANNOS_BACKWARDS:ke();break;case c.CAM_MOVE_LEFT:D(20*l,0);break;case c.CAM_MOVE_RIGHT:D(-20*l,0);break;case c.CAM_MOVE_UP:D(0,20*l);break;case c.CAM_MOVE_DOWN:D(0,-20*l);break;case c.CAM_MOVE_STOP:console.log("KeyAction TODO: CAM_MOVE_STOP");break;case c.COPY_ANNOTATION:Le();break;case c.PASTE_ANNOTATION:We();break;case c.RECREATE_ANNO:console.log("KeyAction TODO: RECREATE_ANNO"),Pe();break;case c.TOGGLE_IMAGE_JUNK:if(g===i.ADD||g===i.CREATE)return;Oe(!F);break;default:console.log("Unknown KeyAction",e);break}},D=(e,t)=>{let n=a.x+e/l,o=a.y+t/l;const r=d.x*.45,f=d.x*.55,O=d.y*.45,Qe=d.y*.55,Ze={x:0,y:0},pe=Ce.getViewportCoordinates(a,d,l,Ze),Ae=Ce.getViewportCoordinates(a,d,l,d);pe.vX>=r?n=a.x-5:Ae.vX<=f?n=a.x+5:pe.vY>=O?o=a.y-5:Ae.vY<=Qe&&(o=a.y+5),S({x:n,y:o})},W=(e=>E.x<=0||E.y<=0||u.x<=0||u.y<=0?[]:v.map(n=>({...n,coordinates:A.convertPercentagedCoordinatesToStage(n.coordinates,u,E)})))(),Ke=()=>{if(h(i.VIEW),fe({x:-1,y:-1}),p.current!==null){const{width:e,height:t}=p.current.getBoundingClientRect();G({x:e,y:t})}k(1),S({x:0,y:0}),L(void 0),b(!1)};I(()=>{ue.current?.focus()},[]),I(()=>{if(x?.current!==void 0){const{width:e,height:t}=x.current.getBoundingClientRect(),n=t-U;H({x:e,y:n});const o=new ResizeObserver(()=>{const{width:r,height:f}=x.current.getBoundingClientRect(),O=f-U;H({x:r,y:O})});return o.observe(x.current),()=>o.disconnect()}Ke()},[ee,ve]),I(()=>{_e()},[p,a,d]),I(()=>{if(x.current===null)return;const{width:e,height:t}=x.current.getBoundingClientRect(),n=t-U;H({x:e,y:n})},[x]),I(()=>{if(p.current===null)return;const{width:e,height:t}=p.current.getBoundingClientRect();G({x:e,y:t});const n=new ResizeObserver(()=>{const{width:o,height:r}=p.current.getBoundingClientRect();G({x:o,y:r})});return n.observe(p.current),()=>n.disconnect()},[p]),I(()=>{if(C===0)return;const e={x:u.x*C,y:u.y*C};fe(e)},[C,u]),I(()=>{X&&z.polygonsToCreate!==void 0&&z.polygonsToCreate.forEach(e=>{const t=R(),n=new he(t,e.type,A.convertPercentagedCoordinatesToStage(e.coordinates,u,E),_.VIEW,w.CREATED);Q(n)})},[z]);const Q=e=>{h(i.VIEW);const t={...e,mode:_.VIEW};if(e.type!==M.Point){const r=at.getRoundedDuration(we,performance.now());t.annoTime=r}const n=A.convertStageCoordinatesToPercentaged(e.coordinates,C,u);t.coordinates=n,re(t);const o=N===M.Point||X;oe(t,o)},Fe=e=>{Ne.keyDown(e.key,e.shiftKey,e.ctrlKey)&&e.preventDefault()},Xe=e=>{e.preventDefault()},ze=e=>{if(e.button!==0){if(e.button===1)h(i.CAMERA_MOVE);else if(e.button===2){if(!K.canCreate||g===i.ADD||g===i.CREATE)return;const t=xe.getAntiScaledMouseStagePosition(e,V,l,a),n={x:t.x-le,y:t.y};Re(n)}}},Ue=()=>{ne&&(document.body.style.overflow="hidden")},Ye=e=>{e.button===1&&h(i.VIEW)},ye=(e,t)=>{g===i.CAMERA_MOVE&&D(e,t)},Ge=()=>{ne&&(document.body.style.overflow="")},He=e=>{const o=(e.deltaY<0?1:-1)>0?l*1.25:l/1.25,r=xe.getAntiScaledMouseStagePosition(e,V,l,a),f=l/o,O={x:f*(r.x+a.x)-r.x,y:f*(r.y+a.y)-r.y};o<1?(k(1),(a.x!=0||a.y!=0)&&S({x:0,y:0})):o>200?(k(200),S(O)):(k(o),S(O))},$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)};T(n),L(ge(e.coordinates))},Ee=e=>{const t=A.convertStageCoordinatesToPercentaged(e.coordinates,C,u),n={...e,coordinates:t};n.status===w.LOADED&&(n.status=w.CHANGED),re(n)},je=()=>{if(g===i.CAMERA_MOVE)return m(qe,{});const t=[i.CREATE,i.ADD,i.MOVE].includes(g),n=W.map(o=>{const r=o.internalId===s?.internalId;return t&&!r?m("g",{},`annotationComponent_${o.internalId}`):m(nt,{scaledAnnotation:o,annotationSettings:K,possibleLabels:te,svgScale:l,svgTranslation:$,pageToStageOffset:V,nodeRadius:Y.nodeRadius,strokeWidth:Y.strokeWidth,isSelected:r,isDisabled:X&&r,onFinishAnnoCreate:Q,onLabelIconClicked:()=>b(!0),onAction:$e,onAnnoChanged:Ee,onAnnotationModeChange:f=>{f===_.MOVE&&h(i.MOVE),g===i.MOVE&&f===_.VIEW&&h(i.VIEW)},onNotification:se},`annotationComponent_${o.internalId}`)});if(s){const o=W.find(f=>f.internalId===s?.internalId),r=W.indexOf(o);n.push(n.splice(r,1)[0])}return m("g",{children:n})},Je=()=>m("circle",{cx:E.x/2,cy:E.y/2,r:"100%",style:{opacity:0},onContextMenu:e=>e.preventDefault(),onClick:()=>{b(!1)}}),me={x:P.x+d.x/2,y:P.y+d.y/2};return B("div",{ref:x,style:{flex:"1 1 auto",minHeight:0,display:"flex",flexDirection:"column"},children:[m("div",{style:{position:"absolute",left:j?.x??0,top:j?.y??0,display:j?.y===void 0?"none":"inherit",zIndex:J?7e3:-1},children:m(ot,{defaultLabelId:q,isVisible:J,selectedLabelsIds:s?.labelIds,possibleLabels:te,isMultilabel:K.canHaveMultipleLabels,onLabelSelect:e=>{if(b(!1),e.length>0){const r=e.filter(f=>!s.labelIds.includes(f));r.length>0&&be(r[0])}const t=W.find(r=>r.internalId===s.internalId);if(!t)return;const n=t.status===w.LOADED?w.CHANGED:t.status,o={...s,coordinates:t.coordinates,labelIds:[...e],status:n};Ee(o)}})}),F&&B("div",{style:{position:"absolute",left:me.x,top:me.y,transform:"translate(-50%, -50%)",textAlign:"center",color:"white"},children:[m(rt,{icon:st,size:"5x",style:{marginBottom:15}}),m("h2",{children:"Marked as Junk"})]}),B("svg",{ref:ue,style:{flex:"1 1 auto",minHeight:0},onKeyDown:Fe,onKeyUp:Xe,onMouseMove:e=>ye(e.movementX,e.movementY),tabIndex:0,onMouseDown:e=>ze(e),children:[B("g",{transform:`scale(${l}) translate(${$.x}, ${$.y})`,onMouseOver:Ue,onMouseLeave:Ge,onMouseUp:Ye,onWheel:He,onMouseMove:e=>ye(e.movementX,e.movementY),onClick:()=>{T(void 0)},children:[m("image",{onContextMenu:e=>e.preventDefault(),href:ee,ref:p,width:E.x>0?E.x:void 0,height:E.y>0?E.y:void 0}),je()]}),J&&Je(),F&&m("rect",{x:"0",y:"0",width:d.x,height:d.y,style:{opacity:.8},onContextMenu:e=>e.preventDefault(),onClick:()=>{L(void 0)}})]})]})};export{bt as default};
package/dist/Sia.js CHANGED
@@ -1 +1 @@
1
- import{jsx as f,jsxs as M}from"react/jsx-runtime";import{useRef as gn,useState as a,useEffect as u}from"react";import{CSpinner as V}from"@coreui/react";import Sn from"./Canvas/Canvas.js";import _n from"./models/AnnotationTool.js";import Tn from"./Toolbar/Toolbar.js";import Cn from"./models/AnnotationMode.js";import K from"./models/AnnotationStatus.js";const Nn=({additionalButtons:Q,allowedTools:S,polygonOperationResult:y={annotationsToDelete:[],polygonsToCreate:[]},annotationSettings:w,uiConfig:D,defaultAnnotationTool:X,defaultLabelId:Y,image:I,isLoading:b=!1,isPolygonSelectionMode:k=!1,initialAnnotations:x=void 0,initialImageLabelIds:_=void 0,initialIsImageJunk:Z=!1,possibleLabels:E,onAnnoCreated:$=(l,m)=>{},onAnnoCreationFinished:O=(l,m)=>{},onAnnoChanged:nn=(l,m)=>{},onAnnoDeleted:F=(l,m)=>{},onImageLabelsChanged:tn=()=>{},onIsImageJunk:en=()=>{},onNotification:on=l=>{},onSelectAnnotation:sn=l=>{},onTimeTravel:an=l=>{}})=>{const m=gn(null),[N,J]=a(),[i,r]=a([]),[j,rn]=a(),[d,T]=a(),[A,B]=a([]),[dn,ln]=a(),[h,v]=a(),[L,P]=a(X??_n.Point),g=n=>{const t=[...n],e=[...A];d!==void 0&&e.splice(d+1),e.push(t),T(void 0),B(e)},[cn,R]=a(_),[U,W]=a(),[C,fn]=a(!1),[q,z]=a([]),p=n=>{const t=i.findIndex(o=>o.internalId===n),e=[...i],s=e.splice(t,1)[0];r(e),v(void 0),g(e),F(s,e)},un=()=>{h!==void 0&&p(h.internalId)},In=()=>{let n=0;const t=x.map(e=>({...e,internalId:n++,mode:Cn.VIEW,selectedNode:1,status:e.status,annoTime:e.annoTime??0}));z([...new Array(n).keys()]),r(t),g(t)},mn=()=>{let n=0;for(;q.includes(n);)n++;const t=[...q];return t.push(n),z(t),n},An=n=>{const t=[...i],e=t.findIndex(c=>c.internalId===h?.internalId);if(e===-1)return;const s=t.splice(e,1)[0];F(s,t);const o=[...t];o.push(n),r(o),v(n)},G=n=>{W(n),en(n)},hn=n=>{const t=d??A.length-1,e=t==A.length-1,s=t==0;if(e&&!n||s&&n)return;const o=t+(n?-1:1);T(o)},vn=n=>{const t=[],e=[],s=[];for(const o of n){const c=i.find(H=>H.internalId===o.internalId);c?JSON.stringify(c)!==JSON.stringify(o)&&s.push(o):t.push(o)}for(const o of i)n.find(H=>H.internalId===o.internalId)||e.push(o);return{addedAnnotations:t,removedAnnotations:e,changedAnnotations:s}};u(()=>{if(d==null||d<0||d>A.length-1)return;const t=[...A[d]];r(t);const e=vn(t);an(e)},[d]),u(()=>{I===void 0&&(r([]),v(void 0),B([]),T(void 0))},[I]),u(()=>{W(Z),!(I!==void 0||x===void 0||x.length===0)&&In()},[x]),u(()=>{R(_)},[_]),u(()=>{const t={...{canCreate:!0,canEdit:!0,canHaveMultipleLabels:!1,canLabel:!0,minimalArea:250},...w};rn(t)},[w]),u(()=>{const t={...{nodeRadius:4,strokeWidth:4,imageCentered:!1},...D};ln(t)},[D]),u(()=>{const n={bbox:!0,point:!0,line:!0,junk:!0,polygon:!0};if(S===void 0)return J(n);J(S)},[S]);const yn={position:"fixed",top:0,left:0,zIndex:6e3,backgroundColor:"#ffff",width:"100%",height:"100%",padding:15},xn={flex:"1 1 auto",minHeight:0,display:"flex",flexDirection:"column"};return N===void 0?f("div",{className:"d-flex justify-content-center",children:f(V,{color:"primary",style:{width:"5rem",height:"5rem"}})}):M("div",{style:{...C?yn:{},flex:"1 1 auto",minHeight:0,display:"flex",flexDirection:"column"},children:[f("div",{ref:m,style:{marginBottom:10},children:f(Tn,{annotationSettings:j,allowedTools:N,additionalButtons:Q,isDisabled:b,isFullscreen:C,isImageJunk:U,imageLabelIds:cn,possibleLabels:E,selectedTool:L,onImageLabelsChanged:n=>{R(n),tn(n)},onSetIsFullscreen:fn,onSetIsImageJunk:G,onSetSelectedTool:P,onShouldDeleteSelectedAnnotation:un})}),M("div",{style:xn,children:[b&&f("div",{className:"d-flex justify-content-center",children:f(V,{color:"primary",style:{width:"5rem",height:"5rem",marginTop:200}})}),I&&i&&f(Sn,{annotations:i,annotationSettings:j,defaultLabelId:Y,image:I,isFullscreen:C,isImageJunk:U,isPolygonSelectionMode:k,selectedAnnotation:h,selectedAnnoTool:L,polygonOperationResult:y,possibleLabels:E,uiConfig:dn,onAnnoCreated:n=>{const t=[...i];t.push(n),r(t),v(n),$(n,t)},onAnnoChanged:n=>{const t=i.findIndex(s=>s.internalId===n.internalId);if(t===-1)return;const e=[...i];e[t]=n,r(e),n.status!==K.CREATING&&g(e),nn(n,e)},onAnnoCreationFinished:(n,t)=>{const e=[...i];if(k&&y?.annotationsToDelete!==void 0){y.annotationsToDelete.push(h);for(const s of y.annotationsToDelete){p(s.internalId);const o=e.findIndex(c=>c.internalId===s.internalId);e.splice(o,1)}}if(t)e.push(n);else{const s=i.findIndex(o=>o.internalId===n.internalId);e[s]=n}r(e),g(e),n.status=K.CREATED,O(n,e)},onAnnoEditing:An,onSetIsImageJunk:G,onNotification:on,onRequestNewAnnoId:mn,onSelectAnnotation:n=>{v(n),sn(n)},onSetSelectedTool:P,onShouldDeleteAnno:p,onTraverseAnnotationHistory:hn})]})]})};export{Nn as default};
1
+ import{jsx as f,jsxs as M}from"react/jsx-runtime";import{useRef as gn,useState as a,useEffect as u}from"react";import{CSpinner as V}from"@coreui/react";import Sn from"./Canvas/Canvas.js";import _n from"./models/AnnotationTool.js";import Tn from"./Toolbar/Toolbar.js";import Cn from"./models/AnnotationMode.js";import K from"./models/AnnotationStatus.js";const Nn=({additionalButtons:Q,allowedTools:S,polygonOperationResult:y={annotationsToDelete:[],polygonsToCreate:[]},annotationSettings:w,uiConfig:D,defaultAnnotationTool:X,defaultLabelId:Y,image:I,isLoading:b=!1,isPolygonSelectionMode:k=!1,initialAnnotations:x=void 0,initialImageLabelIds:_=void 0,initialIsImageJunk:Z=!1,possibleLabels:E,onAnnoCreated:$=(l,m)=>{},onAnnoCreationFinished:O=(l,m)=>{},onAnnoChanged:nn=(l,m)=>{},onAnnoDeleted:F=(l,m)=>{},onImageLabelsChanged:tn=()=>{},onIsImageJunk:en=()=>{},onNotification:on=l=>{},onSelectAnnotation:sn=l=>{},onTimeTravel:an=l=>{}})=>{const m=gn(null),[N,J]=a(),[i,r]=a([]),[j,rn]=a(),[d,T]=a(),[A,B]=a([]),[dn,ln]=a(),[h,v]=a(),[L,P]=a(X??_n.Point),g=n=>{const t=[...n],e=[...A];d!==void 0&&e.splice(d+1),e.push(t),T(void 0),B(e)},[cn,R]=a(_),[U,W]=a(),[C,fn]=a(!1),[q,z]=a([]),p=n=>{const t=i.findIndex(o=>o.internalId===n),e=[...i],s=e.splice(t,1)[0];r(e),v(void 0),g(e),F(s,e)},un=()=>{h!==void 0&&p(h.internalId)},In=()=>{let n=0;const t=x.map(e=>({...e,internalId:n++,mode:Cn.VIEW,selectedNode:1,status:e.status,annoTime:e.annoTime??0}));z([...new Array(n).keys()]),r(t),g(t)},mn=()=>{let n=0;for(;q.includes(n);)n++;const t=[...q];return t.push(n),z(t),n},An=n=>{const t=[...i],e=t.findIndex(c=>c.internalId===h?.internalId);if(e===-1)return;const s=t.splice(e,1)[0];F(s,t);const o=[...t];o.push(n),r(o),v(n)},G=n=>{W(n),en(n)},hn=n=>{const t=d??A.length-1,e=t==A.length-1,s=t==0;if(e&&!n||s&&n)return;const o=t+(n?-1:1);T(o)},vn=n=>{const t=[],e=[],s=[];for(const o of n){const c=i.find(H=>H.internalId===o.internalId);c?JSON.stringify(c)!==JSON.stringify(o)&&s.push(o):t.push(o)}for(const o of i)n.find(H=>H.internalId===o.internalId)||e.push(o);return{addedAnnotations:t,removedAnnotations:e,changedAnnotations:s}};u(()=>{if(d==null||d<0||d>A.length-1)return;const t=[...A[d]];r(t);const e=vn(t);an(e)},[d]),u(()=>{I===void 0&&(r([]),v(void 0),B([]),T(void 0))},[I]),u(()=>{W(Z),!(I!==void 0||x===void 0||x.length===0)&&In()},[x]),u(()=>{R(_)},[_]),u(()=>{const t={...{canCreate:!0,canEdit:!0,canHaveMultipleLabels:!1,canLabel:!0,minimalArea:250},...w};rn(t)},[w]),u(()=>{const t={...{nodeRadius:4,strokeWidth:4,imageCentered:!1},...D};ln(t)},[D]),u(()=>{const n={bbox:!0,point:!0,line:!0,junk:!0,polygon:!0};if(S===void 0)return J(n);J(S)},[S]);const yn={position:"fixed",top:0,left:0,zIndex:6e3,backgroundColor:"#ffff",width:"100%",height:"100%",padding:15},xn={flex:"1 1 auto",minHeight:0,display:"flex",flexDirection:"column"};return N===void 0?f("div",{className:"d-flex justify-content-center",children:f(V,{color:"primary",style:{width:"5rem",height:"5rem"}})}):M("div",{style:{...C?yn:{},flex:"1 1 auto",minHeight:0,display:"flex",flexDirection:"column"},children:[f("div",{ref:m,style:{marginBottom:10},children:f(Tn,{annotationSettings:j,allowedTools:N,additionalButtons:Q,isDisabled:b,isFullscreen:C,isImageJunk:U,imageLabelIds:cn,possibleLabels:E,selectedTool:L,onImageLabelsChanged:n=>{R(n),tn(n)},onSetIsFullscreen:fn,onSetIsImageJunk:G,onSetSelectedTool:P,onShouldDeleteSelectedAnnotation:un})}),M("div",{style:xn,children:[b&&f("div",{className:"d-flex justify-content-center",children:f(V,{color:"primary",style:{width:"5rem",height:"5rem",marginTop:200}})}),I&&i&&f(Sn,{annotations:i,annotationSettings:j,defaultLabelId:Y,image:I,isFullscreen:C,isImageJunk:U,isPolygonSelectionMode:k,selectedAnnotation:h,selectedAnnoTool:L,polygonOperationResult:y,possibleLabels:E,uiConfig:dn,onAnnoCreated:n=>{const t=[...i];t.push(n),r(t),v(n),$(n,t)},onAnnoChanged:n=>{const t=i.findIndex(s=>s.internalId===n.internalId);if(t===-1)return;const e=[...i];e[t]=n,r(e),n.status!==K.CREATING&&g(e),nn(n,e)},onAnnoCreationFinished:(n,t)=>{const e=[...i];if(k&&y?.annotationsToDelete!==void 0){y.annotationsToDelete.push(h);for(const s of y.annotationsToDelete){p(s.internalId);const o=e.findIndex(c=>c.internalId===s.internalId);e.splice(o,1)}}if(n.status=K.CREATED,t)e.push(n);else{const s=i.findIndex(o=>o.internalId===n.internalId);e[s]=n}r(e),g(e),O(n,e)},onAnnoEditing:An,onSetIsImageJunk:G,onNotification:on,onRequestNewAnnoId:mn,onSelectAnnotation:n=>{v(n),sn(n)},onSetSelectedTool:P,onShouldDeleteAnno:p,onTraverseAnnotationHistory:hn})]})]})};export{Nn as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lost-sia",
3
- "version": "3.1.0",
3
+ "version": "3.1.1-alpha3",
4
4
  "description": "Single Image Annotation Tool",
5
5
  "license": "MIT",
6
6
  "repository": "l3p-cv/lost-sia",
@@ -337,10 +337,28 @@ const Canvas = ({
337
337
  onSelectAnnotation(annotationToPaste)
338
338
  }
339
339
 
340
+ /** Returns the page-space position of an annotation's top-left corner.
341
+ * @param stageCoords - annotation coordinates already in stage (pixel) space
342
+ */
343
+ const getAnnoTopLeftPagePosition = (stageCoords: Point[]): Point => {
344
+ const leftPoints: Point[] = transform.getMostLeftPoints(stageCoords)
345
+ const topLeftPoint: Point = transform.getTopPoint(leftPoints)[0]
346
+ return transform.convertStageToPage(topLeftPoint, pageToStageOffset, svgScale, svgTranslation)
347
+ }
348
+
340
349
  const handleKeyAction = (keyAction: KeyAction) => {
341
350
  switch (keyAction) {
342
351
  case KeyAction.EDIT_LABEL:
343
- if (selectedAnnotation) setIsLabelInputVisible(true)
352
+ if (selectedAnnotation) {
353
+ // selectedAnnotation coordinates are in the percentaged system — convert to stage first
354
+ const stageCoords = transform.convertPercentagedCoordinatesToStage(
355
+ selectedAnnotation.coordinates,
356
+ imgSize,
357
+ stageSize,
358
+ )
359
+ setLabelInputPosition(getAnnoTopLeftPagePosition(stageCoords))
360
+ setIsLabelInputVisible(true)
361
+ }
344
362
  break
345
363
  case KeyAction.DELETE_ANNO:
346
364
  if (selectedAnnotation) onShouldDeleteAnno(selectedAnnotation.internalId)
@@ -743,16 +761,7 @@ const Canvas = ({
743
761
  onSelectAnnotation(percentagedAnnotation)
744
762
 
745
763
  // get top left point of annotation
746
- const leftPoints: Point[] = transform.getMostLeftPoints(annotation.coordinates)
747
- const topLeftPoint: Point = transform.getTopPoint(leftPoints)[0]
748
- const pageTopLeftPoint: Point = transform.convertStageToPage(
749
- topLeftPoint,
750
- pageToStageOffset,
751
- svgScale,
752
- svgTranslation,
753
- )
754
-
755
- setLabelInputPosition(pageTopLeftPoint)
764
+ setLabelInputPosition(getAnnoTopLeftPagePosition(annotation.coordinates))
756
765
  }
757
766
 
758
767
  const handleOnAnnoChanged = (annotation: Annotation) => {
@@ -921,22 +930,21 @@ const Canvas = ({
921
930
  }
922
931
  }
923
932
 
933
+ // Look up the current annotation from scaledAnnotations
934
+ const currentScaled = scaledAnnotations.find(
935
+ (a) => a.internalId === selectedAnnotation.internalId,
936
+ )
937
+ if (!currentScaled) return
938
+
924
939
  // change the status to CHANGED when the annotation was loaded (initialAnnotations)
925
940
  const newAnnotationStatus: AnnotationStatus =
926
- selectedAnnotation.status === AnnotationStatus.LOADED
941
+ currentScaled.status === AnnotationStatus.LOADED
927
942
  ? AnnotationStatus.CHANGED
928
- : selectedAnnotation.status
943
+ : currentScaled.status
929
944
 
930
- // selectedAnnotation comes from SIA and is therefore in the percentaged system
931
- // convert it first
932
- // also update the new labels
933
945
  const updatedAnno: Annotation = {
934
946
  ...selectedAnnotation,
935
- coordinates: transform.convertPercentagedCoordinatesToStage(
936
- selectedAnnotation.coordinates,
937
- imgSize,
938
- stageSize,
939
- ),
947
+ coordinates: currentScaled.coordinates,
940
948
  labelIds: [...selectedLabelIds],
941
949
  status: newAnnotationStatus,
942
950
  }
package/src/Sia.tsx CHANGED
@@ -557,6 +557,8 @@ const Sia = ({
557
557
  }
558
558
  }
559
559
  }
560
+ // mark annotation as fully created before storing it
561
+ changedAnno.status = AnnotationStatus.CREATED
560
562
 
561
563
  // are we just marking an existing annotation as finished or did we created it in the same frame
562
564
  if (hasAnnoJustBeenCreated) _annotations.push(changedAnno)
@@ -571,9 +573,6 @@ const Sia = ({
571
573
  setAnnotations(_annotations)
572
574
  updateAnnotationHistory(_annotations)
573
575
 
574
- // mark annotation as fully created
575
- changedAnno.status = AnnotationStatus.CREATED
576
-
577
576
  // inform the outer world about our changes
578
577
  onAnnoCreationFinished(changedAnno, _annotations)
579
578
  }}