lost-sia 3.1.1 → 3.1.2

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 G,jsx as d}from"react/jsx-runtime";import E from"../../models/AnnotationTool.js";import{getDefaultColor as L}from"../../utils/color.js";import H from"./tools/Point.js";import J from"./tools/Line.js";import K from"./atoms/AnnoBar.js";import Q from"../../models/CanvasAction.js";import X from"./tools/BBox.js";import Y from"./tools/Polygon.js";import{useState as h,useRef as x,useEffect as I}from"react";import e from"../../models/AnnotationMode.js";import Z from"../../utils/TimeUtils.js";const lo=({scaledAnnotation:r,annotationSettings:m,possibleLabels:T,svgScale:i,svgTranslation:l,pageToStageOffset:f,strokeWidth:B,nodeRadius:P,isSelected:c,isDisabled:V=!1,onFinishAnnoCreate:w,onLabelIconClicked:W,onAction:k=(n,a)=>{},onAnnoChanged:A=n=>{},onAnnotationModeChange:F=n=>{},onNotification:O=n=>{}})=>{const[n,a]=h(r.coordinates),[t,M]=h(r.mode),[j,C]=h(!1),R=x(void 0),[_,U]=h();I(()=>{R.current=_},[_]);const N=x(n);I(()=>{N.current=n},[n]);const b=()=>{M(e.VIEW);const o={...r,coordinates:N.current};w(o)},q=o=>T.find(s=>s.id===o),y=(()=>{if(!r.labelIds||r.labelIds.length==0)return L();const o=q(r.labelIds[0]);return o?.color===void 0||o.color===null?L():o.color})(),u={stroke:y,fill:y,strokeWidth:B/i,r:P/i},D=o=>{a(o);let s=o;[e.ADD,e.MOVE].includes(t)&&(s=o.slice(0,-1)),A({...r,coordinates:s})},p=o=>{[e.ADD,e.CREATE,e.MOVE].includes(t)||(M(e.MOVE),U(performance.now())),a(o)},g=()=>{M(e.VIEW);const o=Z.getRoundedDuration(R.current,performance.now()),s=Number.isNaN(r.annoTime)||r.annoTime===null?o:r.annoTime+o;A({...r,coordinates:N.current,annoTime:s})};I(()=>{F(t)},[t]),I(()=>{t===e.CREATE||t===e.ADD||a(r.coordinates)},[r]);const z=()=>{switch(r.type){case E.Point:return d(H,{isSelected:c,annotationSettings:m,coordinates:n[0],pageToStageOffset:f,svgScale:i,svgTranslation:l,style:u,onMoving:o=>p([o]),onMoved:g,onIsDraggingStateChanged:C});case E.Line:return d(J,{annotationSettings:m,coordinates:n,isSelected:c,pageToStageOffset:f,annotationMode:t,svgScale:i,svgTranslation:l,style:u,onAddNode:D,onDeleteNode:D,onMoving:p,onMoved:g,onIsDraggingStateChanged:C,onFinishAnnoCreate:b});case E.BBox:return d(X,{annotationMode:t,annotationSettings:m,startCoords:n[0],endCoords:n[1],isSelected:c,pageToStageOffset:f,style:u,svgScale:i,svgTranslation:l,onDeleteNode:()=>{console.log("TODO")},onIsDraggingStateChanged:C,onFinishAnnoCreate:b,onMoving:p,onMoved:g});case E.Polygon:return d(Y,{annotationSettings:m,coordinates:n,isSelected:c,isDisabled:V,pageToStageOffset:f,annotationMode:t,svgScale:i,svgTranslation:l,style:u,onAddNode:D,onDeleteNode:D,onMoving:p,onMoved:g,onNotification:O,onIsDraggingStateChanged:C,onFinishAnnoCreate:b})}};return G("g",{onClick:o=>{o.stopPropagation(),k(r,Q.ANNO_SELECTED)},children:[!j&&t!==e.CREATE&&d(K,{annotationCoordinates:n,canLabel:m.canLabel,labels:T,color:y,isSelected:c,selectedLabelIds:r.labelIds,style:u,svgScale:i,onLabelIconClicked:W}),z()]})};export{lo as default};
1
+ import{jsxs as G,jsx as d}from"react/jsx-runtime";import g from"../../models/AnnotationTool.js";import{getDefaultColor as L}from"../../utils/color.js";import H from"./tools/Point.js";import J from"./tools/Line.js";import K from"./atoms/AnnoBar.js";import Q from"../../models/CanvasAction.js";import X from"./tools/BBox.js";import Y from"./tools/Polygon.js";import{useState as h,useRef as V,useEffect as I}from"react";import e from"../../models/AnnotationMode.js";import Z from"../../utils/TimeUtils.js";const fo=({scaledAnnotation:r,annotationSettings:u,possibleLabels:T,svgScale:i,svgTranslation:f,pageToStageOffset:l,strokeWidth:x,nodeRadius:B,isSelected:s,isDisabled:P=!1,onFinishAnnoCreate:W,onLabelIconClicked:w,onAction:k=(n,a)=>{},onAnnoChanged:A=n=>{},onAnnotationModeChange:F=n=>{},onNotification:O=n=>{}})=>{const[n,a]=h(r.coordinates),[t,M]=h(s?r.mode:e.VIEW),[j,C]=h(!1),R=V(void 0),[_,U]=h();I(()=>{R.current=_},[_]);const N=V(n);I(()=>{N.current=n},[n]);const b=()=>{M(e.VIEW);const o={...r,coordinates:N.current};W(o)},q=o=>T.find(m=>m.id===o),y=(()=>{if(!r.labelIds||r.labelIds.length==0)return L();const o=q(r.labelIds[0]);return o?.color===void 0||o.color===null?L():o.color})(),c={stroke:y,fill:y,strokeWidth:x/i,r:B/i},D=o=>{a(o);let m=o;[e.ADD,e.MOVE].includes(t)&&(m=o.slice(0,-1)),A({...r,coordinates:m})},p=o=>{[e.ADD,e.CREATE,e.MOVE].includes(t)||(M(e.MOVE),U(performance.now())),a(o)},E=()=>{M(e.VIEW);const o=Z.getRoundedDuration(R.current,performance.now()),m=Number.isNaN(r.annoTime)||r.annoTime===null?o:r.annoTime+o;A({...r,coordinates:N.current,annoTime:m})};I(()=>{F(t)},[t]),I(()=>{t===e.CREATE||t===e.ADD||a(r.coordinates)},[r]);const z=()=>{switch(r.type){case g.Point:return d(H,{isSelected:s,annotationSettings:u,coordinates:n[0],pageToStageOffset:l,svgScale:i,svgTranslation:f,style:c,onMoving:o=>p([o]),onMoved:E,onIsDraggingStateChanged:C});case g.Line:return d(J,{annotationSettings:u,coordinates:n,isSelected:s,pageToStageOffset:l,annotationMode:t,svgScale:i,svgTranslation:f,style:c,onAddNode:D,onDeleteNode:D,onMoving:p,onMoved:E,onIsDraggingStateChanged:C,onFinishAnnoCreate:b});case g.BBox:return d(X,{annotationMode:t,annotationSettings:u,startCoords:n[0],endCoords:n[1],isSelected:s,pageToStageOffset:l,style:c,svgScale:i,svgTranslation:f,onDeleteNode:()=>{console.log("TODO")},onIsDraggingStateChanged:C,onFinishAnnoCreate:b,onMoving:p,onMoved:E});case g.Polygon:return d(Y,{annotationSettings:u,coordinates:n,isSelected:s,isDisabled:P,pageToStageOffset:l,annotationMode:t,svgScale:i,svgTranslation:f,style:c,onAddNode:D,onDeleteNode:D,onMoving:p,onMoved:E,onNotification:O,onIsDraggingStateChanged:C,onFinishAnnoCreate:b})}};return G("g",{onClick:o=>{o.stopPropagation(),k(r,Q.ANNO_SELECTED)},children:[!j&&t!==e.CREATE&&d(K,{annotationCoordinates:n,canLabel:u.canLabel,labels:T,color:y,isSelected:s,selectedLabelIds:r.labelIds,style:c,svgScale:i,onLabelIconClicked:w}),z()]})};export{fo as default};
@@ -1 +1 @@
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};
1
+ import{jsxs as B,jsx as E,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}),[m,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,m);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=>m.x<=0||m.y<=0||u.x<=0||u.y<=0?[]:v.map(n=>({...n,coordinates:A.convertPercentagedCoordinatesToStage(n.coordinates,u,m)})))(),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,m),_.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))},me=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 E(qe,{});const t=[i.CREATE,i.ADD,i.MOVE].includes(g),n=W.map(o=>{const r=o.internalId===s?.internalId;return t&&!r?E("g",{},`annotationComponent_${o.internalId}`):E(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:me,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 E("g",{children:n})},Je=()=>E("circle",{cx:m.x/2,cy:m.y/2,r:"100%",style:{opacity:0},onContextMenu:e=>e.preventDefault(),onClick:()=>{b(!1)}}),Ee={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:[E("div",{style:{position:"absolute",left:j?.x??0,top:j?.y??0,display:j?.y===void 0?"none":"inherit",zIndex:J?7e3:-1},children:E(ot,{defaultLabelId:q,isVisible:J,selectedLabelsIds:s?.labelIds,possibleLabels:te,isMultilabel:K.canHaveMultipleLabels,onLabelSelect:e=>{if(setTimeout(()=>b(!1),0),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};me(o)}})}),F&&B("div",{style:{position:"absolute",left:Ee.x,top:Ee.y,transform:"translate(-50%, -50%)",textAlign:"center",color:"white"},children:[E(rt,{icon:st,size:"5x",style:{marginBottom:15}}),E("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:[E("image",{onContextMenu:e=>e.preventDefault(),href:ee,ref:p,width:m.x>0?m.x:void 0,height:m.y>0?m.y:void 0}),je()]}),J&&Je(),F&&E("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.d.ts CHANGED
@@ -18,9 +18,9 @@ type SiaProps = {
18
18
  possibleLabels: Label[];
19
19
  uiConfig?: UiConfig;
20
20
  onAnnoCreated?: (createdAnno: Annotation, allAnnos: Annotation[]) => void;
21
- onAnnoCreationFinished?: (createdAnno: Annotation, allAnnos: Annotation[]) => void;
22
- onAnnoChanged?: (changedAnno: Annotation, allAnnos: Annotation[]) => void;
23
- onAnnoDeleted?: (deletedAnno: Annotation, allAnnos: Annotation[]) => void;
21
+ onAnnoCreationFinished?: (createdAnno: Annotation) => void;
22
+ onAnnoChanged?: (changedAnno: Annotation) => void;
23
+ onAnnoDeleted?: (deletedAnno: Annotation, allAnnos?: Annotation[]) => void;
24
24
  onImageLabelsChanged?: (selectedImageIds: number[]) => void;
25
25
  onIsImageJunk?: (isJunk: boolean) => void;
26
26
  onNotification?: (notification: SIANotification) => void;
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(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};
1
+ import{jsx as u,jsxs as V}from"react/jsx-runtime";import{useRef as Tn,useState as a,useEffect as I}from"react";import{CSpinner as K}from"@coreui/react";import Cn from"./Canvas/Canvas.js";import _n from"./models/AnnotationTool.js";import pn from"./Toolbar/Toolbar.js";import Hn from"./models/AnnotationMode.js";import O from"./models/AnnotationStatus.js";const jn=({additionalButtons:Q,allowedTools:S,polygonOperationResult:T={annotationsToDelete:[],polygonsToCreate:[]},annotationSettings:b,uiConfig:k,defaultAnnotationTool:X,defaultLabelId:Y,image:A,isLoading:D=!1,isPolygonSelectionMode:E=!1,initialAnnotations:y=void 0,initialImageLabelIds:C=void 0,initialIsImageJunk:Z=!1,possibleLabels:F,onAnnoCreated:$=(l,p)=>{},onAnnoCreationFinished:nn=l=>{},onAnnoChanged:tn=l=>{},onAnnoDeleted:_=(l,p)=>{},onImageLabelsChanged:en=()=>{},onIsImageJunk:on=()=>{},onNotification:sn=l=>{},onSelectAnnotation:an=l=>{},onTimeTravel:rn=l=>{}})=>{const p=Tn(null),[N,J]=a(),[c,r]=a([]),[j,dn]=a(),[d,H]=a(),[h,B]=a([]),[ln,cn]=a(),[m,g]=a(),[L,R]=a(X??_n.Point),v=n=>{const t=[...n],e=[...h];d!==void 0&&e.splice(d+1),e.push(t),H(void 0),B(e)},[fn,P]=a(C),[U,W]=a(),[w,un]=a(!1),[q,z]=a([]),G=n=>{const t=c.findIndex(o=>o.internalId===n),e=[...c],s=e.splice(t,1)[0];r(e),g(void 0),v(e),_(s,e)},In=()=>{m!==void 0&&G(m.internalId)},mn=()=>{let n=0;const t=y.map(e=>({...e,internalId:n++,mode:Hn.VIEW,selectedNode:1,status:e.status,annoTime:e.annoTime??0}));z([...new Array(n).keys()]),r(t),v(t)},An=()=>{let n=0;for(;q.includes(n);)n++;const t=[...q];return t.push(n),z(t),n},hn=n=>{const t=[...c],e=t.findIndex(i=>i.internalId===m?.internalId);if(e===-1)return;const s=t.splice(e,1)[0];_(s,t);const o=[...t];o.push(n),r(o),g(n)},M=n=>{W(n),on(n)},gn=n=>{const t=d??h.length-1,e=t==h.length-1,s=t==0;if(e&&!n||s&&n)return;const o=t+(n?-1:1);H(o)},yn=n=>{const t=[],e=[],s=[];for(const o of n){const i=c.find(f=>f.internalId===o.internalId);i?JSON.stringify(i)!==JSON.stringify(o)&&s.push(o):t.push(o)}for(const o of c)n.find(f=>f.internalId===o.internalId)||e.push(o);return{addedAnnotations:t,removedAnnotations:e,changedAnnotations:s}};I(()=>{if(d==null||d<0||d>h.length-1)return;const t=[...h[d]];r(t);const e=yn(t);rn(e)},[d]),I(()=>{A===void 0&&(r([]),g(void 0),B([]),H(void 0))},[A]),I(()=>{W(Z),!(A!==void 0||y===void 0||y.length===0)&&mn()},[y]),I(()=>{P(C)},[C]),I(()=>{const t={...{canCreate:!0,canEdit:!0,canHaveMultipleLabels:!1,canLabel:!0,minimalArea:250},...b};dn(t)},[b]),I(()=>{const t={...{nodeRadius:4,strokeWidth:4,imageCentered:!1},...k};cn(t)},[k]),I(()=>{const n={bbox:!0,point:!0,line:!0,junk:!0,polygon:!0};if(S===void 0)return J(n);J(S)},[S]);const vn={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?u("div",{className:"d-flex justify-content-center",children:u(K,{color:"primary",style:{width:"5rem",height:"5rem"}})}):V("div",{style:{...w?vn:{},flex:"1 1 auto",minHeight:0,display:"flex",flexDirection:"column"},children:[u("div",{ref:p,style:{marginBottom:10},children:u(pn,{annotationSettings:j,allowedTools:N,additionalButtons:Q,isDisabled:D,isFullscreen:w,isImageJunk:U,imageLabelIds:fn,possibleLabels:F,selectedTool:L,onImageLabelsChanged:n=>{P(n),en(n)},onSetIsFullscreen:un,onSetIsImageJunk:M,onSetSelectedTool:R,onShouldDeleteSelectedAnnotation:In})}),V("div",{style:xn,children:[D&&u("div",{className:"d-flex justify-content-center",children:u(K,{color:"primary",style:{width:"5rem",height:"5rem",marginTop:200}})}),A&&c&&u(Cn,{annotations:c,annotationSettings:j,defaultLabelId:Y,image:A,isFullscreen:w,isImageJunk:U,isPolygonSelectionMode:E,selectedAnnotation:m,selectedAnnoTool:L,polygonOperationResult:T,possibleLabels:F,uiConfig:ln,onAnnoCreated:n=>{r(t=>{const e=[...t,n];return $(n,e),e}),g(n)},onAnnoChanged:n=>{r(t=>{const e=t.findIndex(o=>o.internalId===n.internalId);if(e===-1)return t;const s=[...t];return s[e]=n,n.status!==O.CREATING&&v(s),s}),tn(n)},onAnnoCreationFinished:(n,t)=>{const e={...n,status:O.CREATED},s=E&&T?.annotationsToDelete!==void 0?[...T.annotationsToDelete,...m!==void 0?[m]:[]]:[];r(o=>{const i=[...o];for(const f of s){const x=i.findIndex(Sn=>Sn.internalId===f.internalId);x!==-1&&i.splice(x,1)}if(t)i.push(e);else{const f=o.findIndex(x=>x.internalId===e.internalId);i[f]=e}return v(i),i});for(const o of s)_(o);nn(e)},onAnnoEditing:hn,onSetIsImageJunk:M,onNotification:sn,onRequestNewAnnoId:An,onSelectAnnotation:n=>{g(n),an(n)},onSetSelectedTool:R,onShouldDeleteAnno:G,onTraverseAnnotationHistory:gn})]})]})};export{jn as default};
@@ -19,9 +19,9 @@ declare const meta: {
19
19
  possibleLabels: import('..').Label[];
20
20
  uiConfig?: import('..').UiConfig;
21
21
  onAnnoCreated?: (createdAnno: import('../models').Annotation, allAnnos: import('../models').Annotation[]) => void;
22
- onAnnoCreationFinished?: (createdAnno: import('../models').Annotation, allAnnos: import('../models').Annotation[]) => void;
23
- onAnnoChanged?: (changedAnno: import('../models').Annotation, allAnnos: import('../models').Annotation[]) => void;
24
- onAnnoDeleted?: (deletedAnno: import('../models').Annotation, allAnnos: import('../models').Annotation[]) => void;
22
+ onAnnoCreationFinished?: (createdAnno: import('../models').Annotation) => void;
23
+ onAnnoChanged?: (changedAnno: import('../models').Annotation) => void;
24
+ onAnnoDeleted?: (deletedAnno: import('../models').Annotation, allAnnos?: import('../models').Annotation[]) => void;
25
25
  onImageLabelsChanged?: (selectedImageIds: number[]) => void;
26
26
  onIsImageJunk?: (isJunk: boolean) => void;
27
27
  onNotification?: (notification: import('..').SIANotification) => void;
@@ -19,9 +19,9 @@ declare const meta: {
19
19
  possibleLabels: Label[];
20
20
  uiConfig?: import('..').UiConfig;
21
21
  onAnnoCreated?: (createdAnno: import('../models').Annotation, allAnnos: import('../models').Annotation[]) => void;
22
- onAnnoCreationFinished?: (createdAnno: import('../models').Annotation, allAnnos: import('../models').Annotation[]) => void;
23
- onAnnoChanged?: (changedAnno: import('../models').Annotation, allAnnos: import('../models').Annotation[]) => void;
24
- onAnnoDeleted?: (deletedAnno: import('../models').Annotation, allAnnos: import('../models').Annotation[]) => void;
22
+ onAnnoCreationFinished?: (createdAnno: import('../models').Annotation) => void;
23
+ onAnnoChanged?: (changedAnno: import('../models').Annotation) => void;
24
+ onAnnoDeleted?: (deletedAnno: import('../models').Annotation, allAnnos?: import('../models').Annotation[]) => void;
25
25
  onImageLabelsChanged?: (selectedImageIds: number[]) => void;
26
26
  onIsImageJunk?: (isJunk: boolean) => void;
27
27
  onNotification?: (notification: import('..').SIANotification) => void;
@@ -50,9 +50,9 @@ declare const meta: {
50
50
  possibleLabels: Label[];
51
51
  uiConfig?: import('..').UiConfig;
52
52
  onAnnoCreated?: (createdAnno: import('../models').Annotation, allAnnos: import('../models').Annotation[]) => void;
53
- onAnnoCreationFinished?: (createdAnno: import('../models').Annotation, allAnnos: import('../models').Annotation[]) => void;
54
- onAnnoChanged?: (changedAnno: import('../models').Annotation, allAnnos: import('../models').Annotation[]) => void;
55
- onAnnoDeleted?: (deletedAnno: import('../models').Annotation, allAnnos: import('../models').Annotation[]) => void;
53
+ onAnnoCreationFinished?: (createdAnno: import('../models').Annotation) => void;
54
+ onAnnoChanged?: (changedAnno: import('../models').Annotation) => void;
55
+ onAnnoDeleted?: (deletedAnno: import('../models').Annotation, allAnnos?: import('../models').Annotation[]) => void;
56
56
  onImageLabelsChanged?: (selectedImageIds: number[]) => void;
57
57
  onIsImageJunk?: (isJunk: boolean) => void;
58
58
  onNotification?: (notification: import('..').SIANotification) => void;
@@ -19,9 +19,9 @@ declare const meta: {
19
19
  possibleLabels: import('../..').Label[];
20
20
  uiConfig?: UiConfig;
21
21
  onAnnoCreated?: (createdAnno: import('../../models').Annotation, allAnnos: import('../../models').Annotation[]) => void;
22
- onAnnoCreationFinished?: (createdAnno: import('../../models').Annotation, allAnnos: import('../../models').Annotation[]) => void;
23
- onAnnoChanged?: (changedAnno: import('../../models').Annotation, allAnnos: import('../../models').Annotation[]) => void;
24
- onAnnoDeleted?: (deletedAnno: import('../../models').Annotation, allAnnos: import('../../models').Annotation[]) => void;
22
+ onAnnoCreationFinished?: (createdAnno: import('../../models').Annotation) => void;
23
+ onAnnoChanged?: (changedAnno: import('../../models').Annotation) => void;
24
+ onAnnoDeleted?: (deletedAnno: import('../../models').Annotation, allAnnos?: import('../../models').Annotation[]) => void;
25
25
  onImageLabelsChanged?: (selectedImageIds: number[]) => void;
26
26
  onIsImageJunk?: (isJunk: boolean) => void;
27
27
  onNotification?: (notification: import('../..').SIANotification) => void;
@@ -50,9 +50,9 @@ declare const meta: {
50
50
  possibleLabels: import('../..').Label[];
51
51
  uiConfig?: UiConfig;
52
52
  onAnnoCreated?: (createdAnno: import('../../models').Annotation, allAnnos: import('../../models').Annotation[]) => void;
53
- onAnnoCreationFinished?: (createdAnno: import('../../models').Annotation, allAnnos: import('../../models').Annotation[]) => void;
54
- onAnnoChanged?: (changedAnno: import('../../models').Annotation, allAnnos: import('../../models').Annotation[]) => void;
55
- onAnnoDeleted?: (deletedAnno: import('../../models').Annotation, allAnnos: import('../../models').Annotation[]) => void;
53
+ onAnnoCreationFinished?: (createdAnno: import('../../models').Annotation) => void;
54
+ onAnnoChanged?: (changedAnno: import('../../models').Annotation) => void;
55
+ onAnnoDeleted?: (deletedAnno: import('../../models').Annotation, allAnnos?: import('../../models').Annotation[]) => void;
56
56
  onImageLabelsChanged?: (selectedImageIds: number[]) => void;
57
57
  onIsImageJunk?: (isJunk: boolean) => void;
58
58
  onNotification?: (notification: import('../..').SIANotification) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lost-sia",
3
- "version": "3.1.1",
3
+ "version": "3.1.2",
4
4
  "description": "Single Image Annotation Tool",
5
5
  "license": "MIT",
6
6
  "repository": "l3p-cv/lost-sia",
@@ -52,7 +52,7 @@ const AnnotationComponent = ({
52
52
  const [coordinates, setCoordinates] = useState<Point[]>(scaledAnnotation.coordinates)
53
53
 
54
54
  const [annotationMode, setAnnotationMode] = useState<AnnotationMode>(
55
- scaledAnnotation.mode,
55
+ isSelected ? scaledAnnotation.mode : AnnotationMode.VIEW,
56
56
  )
57
57
  const [isDragging, setIsDragging] = useState<boolean>(false)
58
58
 
@@ -916,8 +916,10 @@ const Canvas = ({
916
916
  possibleLabels={possibleLabels}
917
917
  isMultilabel={annotationSettings.canHaveMultipleLabels}
918
918
  onLabelSelect={(selectedLabelIds: number[]) => {
919
- // close the input popup
920
- setIsLabelInputVisible(false)
919
+ // close the input popup after the current event finishes,
920
+ // so the invisible selection circle stays in place long enough
921
+ // to block the label-click from falling through to SVG annotations
922
+ setTimeout(() => setIsLabelInputVisible(false), 0)
921
923
 
922
924
  // inform parent which label was chosen
923
925
  if (selectedLabelIds.length > 0) {
package/src/Sia.tsx CHANGED
@@ -33,9 +33,9 @@ type SiaProps = {
33
33
  possibleLabels: Label[]
34
34
  uiConfig?: UiConfig
35
35
  onAnnoCreated?: (createdAnno: Annotation, allAnnos: Annotation[]) => void
36
- onAnnoCreationFinished?: (createdAnno: Annotation, allAnnos: Annotation[]) => void
37
- onAnnoChanged?: (changedAnno: Annotation, allAnnos: Annotation[]) => void
38
- onAnnoDeleted?: (deletedAnno: Annotation, allAnnos: Annotation[]) => void
36
+ onAnnoCreationFinished?: (createdAnno: Annotation) => void
37
+ onAnnoChanged?: (changedAnno: Annotation) => void
38
+ onAnnoDeleted?: (deletedAnno: Annotation, allAnnos?: Annotation[]) => void
39
39
  onImageLabelsChanged?: (selectedImageIds: number[]) => void
40
40
  onIsImageJunk?: (isJunk: boolean) => void
41
41
  onNotification?: (notification: SIANotification) => void
@@ -62,8 +62,8 @@ const Sia = ({
62
62
  initialIsImageJunk = false,
63
63
  possibleLabels,
64
64
  onAnnoCreated = (_, __) => {},
65
- onAnnoCreationFinished = (_, __) => {},
66
- onAnnoChanged = (_, __) => {},
65
+ onAnnoCreationFinished = (_) => {},
66
+ onAnnoChanged = (_) => {},
67
67
  onAnnoDeleted = (_, __) => {},
68
68
  onImageLabelsChanged = () => {},
69
69
  onIsImageJunk = () => {},
@@ -498,83 +498,91 @@ const Sia = ({
498
498
  possibleLabels={possibleLabels}
499
499
  uiConfig={uiConfig}
500
500
  onAnnoCreated={(annotation: Annotation) => {
501
- const _annotations: Annotation[] = [...annotations]
502
- _annotations.push(annotation)
503
- setAnnotations(_annotations)
501
+ setAnnotations((prev) => {
502
+ const _annotations = [...prev, annotation]
503
+ onAnnoCreated(annotation, _annotations)
504
+ return _annotations
505
+ })
504
506
  setSelectedAnnotation(annotation)
505
- onAnnoCreated(annotation, _annotations)
506
507
  // dont update history here - we dont have a finished anno at this point
507
508
  }}
508
509
  onAnnoChanged={(changedAnno: Annotation) => {
509
- // update annotation list
510
- const annoListIndex: number = annotations.findIndex(
511
- (anno) => anno.internalId === changedAnno.internalId,
512
- )
510
+ setAnnotations((prev) => {
511
+ // update annotation list
512
+ const annoListIndex: number = prev.findIndex(
513
+ (anno) => anno.internalId === changedAnno.internalId,
514
+ )
513
515
 
514
- // only fire event if item found
515
- if (annoListIndex === -1) return
516
+ // only fire event if item found
517
+ if (annoListIndex === -1) return prev
516
518
 
517
- const _annotations: Annotation[] = [...annotations]
518
- _annotations[annoListIndex] = changedAnno
519
- setAnnotations(_annotations)
519
+ const _annotations: Annotation[] = [...prev]
520
+ _annotations[annoListIndex] = changedAnno
520
521
 
521
- // only update history for full/finished annotations
522
- if (changedAnno.status !== AnnotationStatus.CREATING) {
523
- updateAnnotationHistory(_annotations)
524
- }
522
+ // only update history for full/finished annotations
523
+ if (changedAnno.status !== AnnotationStatus.CREATING) {
524
+ updateAnnotationHistory(_annotations)
525
+ }
526
+
527
+ return _annotations
528
+ })
525
529
 
526
530
  // inform the outside world about our change
527
- onAnnoChanged(changedAnno, _annotations)
531
+ // (kept outside the updater — side effects must not run inside setState)
532
+ onAnnoChanged(changedAnno)
528
533
  }}
529
534
  onAnnoCreationFinished={(
530
535
  changedAnno: Annotation,
531
536
  hasAnnoJustBeenCreated: boolean,
532
537
  ) => {
533
- // update annotation list
534
- const _annotations: Annotation[] = [...annotations]
535
-
536
- // remove the previous annotations we used to do the operation with
537
- if (isPolygonSelectionMode) {
538
- if (polygonOperationResult?.annotationsToDelete !== undefined) {
539
- // we also want to remove the current selected annotation
540
- polygonOperationResult.annotationsToDelete.push(selectedAnnotation)
541
-
542
- for (const annotation of polygonOperationResult.annotationsToDelete) {
543
- // polygonOperationResult.annotationsToDelete.forEach((annotation) => {
544
- // remove annotations "the official way" (inform the server what we did)
545
- deleteAnnotationByInternalId(annotation.internalId)
546
-
547
- // since we are updating the annotations list after all the deletions again, their disappearance wouldn't be noticed
548
- // therefore also manually remove the annotations here
549
-
550
- // get index of selected annotation
551
- const annoListIndex: number = _annotations.findIndex(
552
- (anno) => anno.internalId === annotation.internalId,
553
- )
554
-
555
- // remove annotation from object
556
- _annotations.splice(annoListIndex, 1)
557
- }
558
- }
559
- }
560
- // mark annotation as fully created before storing it
561
- changedAnno.status = AnnotationStatus.CREATED
562
-
563
- // are we just marking an existing annotation as finished or did we created it in the same frame
564
- if (hasAnnoJustBeenCreated) _annotations.push(changedAnno)
565
- else {
566
- // all other annotation types
567
- const annoListIndex: number = annotations.findIndex(
568
- (anno) => anno.internalId === changedAnno.internalId,
569
- )
570
- _annotations[annoListIndex] = changedAnno
538
+ const finishedAnno: Annotation = {
539
+ ...changedAnno,
540
+ status: AnnotationStatus.CREATED, // copy and mark annotation as fully created
571
541
  }
572
542
 
573
- setAnnotations(_annotations)
574
- updateAnnotationHistory(_annotations)
543
+ // Collect annotations to delete before entering the updater.
544
+ // build a fresh array so we never mutate the prop from SiaWrapper.
545
+ const annosToDelete: Annotation[] =
546
+ isPolygonSelectionMode &&
547
+ polygonOperationResult?.annotationsToDelete !== undefined
548
+ ? [
549
+ ...polygonOperationResult.annotationsToDelete,
550
+ ...(selectedAnnotation !== undefined ? [selectedAnnotation] : []),
551
+ ]
552
+ : []
553
+
554
+ setAnnotations((prev) => {
555
+ // update annotation list
556
+ const _annotations: Annotation[] = [...prev]
557
+
558
+ // remove the source annotations that were consumed by the polygon operation
559
+ for (const annotation of annosToDelete) {
560
+ const annoListIndex: number = _annotations.findIndex(
561
+ (anno) => anno.internalId === annotation.internalId,
562
+ )
563
+ if (annoListIndex !== -1) _annotations.splice(annoListIndex, 1)
564
+ }
565
+
566
+ if (hasAnnoJustBeenCreated) _annotations.push(finishedAnno)
567
+ else {
568
+ const annoListIndex: number = prev.findIndex(
569
+ (anno) => anno.internalId === finishedAnno.internalId,
570
+ )
571
+ _annotations[annoListIndex] = finishedAnno
572
+ }
573
+
574
+ updateAnnotationHistory(_annotations)
575
+
576
+ return _annotations
577
+ })
578
+
579
+ // Notify the server about the deletions (outside of the updater/setState!!!)
580
+ for (const annotation of annosToDelete) {
581
+ onAnnoDeleted(annotation)
582
+ }
575
583
 
576
- // inform the outer world about our changes
577
- onAnnoCreationFinished(changedAnno, _annotations)
584
+ // inform the outer world about the new annotation (also outside of the updater/setState!!!)
585
+ onAnnoCreationFinished(finishedAnno)
578
586
  }}
579
587
  onAnnoEditing={handleAnnoEditing}
580
588
  onSetIsImageJunk={handleImageJunk}
@@ -36,10 +36,10 @@ const DemoWrapper = ({
36
36
  onAnnoCreated={(anno: Annotation, _: Annotation[]) => {
37
37
  console.log('CREATED', anno)
38
38
  }}
39
- onAnnoCreationFinished={(anno: Annotation, _: Annotation[]) => {
39
+ onAnnoCreationFinished={(anno: Annotation) => {
40
40
  console.log('FINISHED CREATION', anno)
41
41
  }}
42
- onAnnoChanged={(anno: Annotation, _: Annotation[]) => {
42
+ onAnnoChanged={(anno: Annotation) => {
43
43
  console.log('CHANGED', anno)
44
44
  }}
45
45
  onAnnoDeleted={(anno: Annotation, annos: Annotation[]) => {