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.
- package/dist/Annotation/ui/AnnotationComponent.js +1 -1
- package/dist/Canvas/Canvas.js +1 -1
- package/dist/Sia.d.ts +3 -3
- package/dist/Sia.js +1 -1
- package/dist/stories/AnnotationTools.stories.d.ts +3 -3
- package/dist/stories/MinimalSia.stories.d.ts +6 -6
- package/dist/stories/SIA/SIA.stories.d.ts +6 -6
- package/package.json +1 -1
- package/src/Annotation/ui/AnnotationComponent.tsx +1 -1
- package/src/Canvas/Canvas.tsx +4 -2
- package/src/Sia.tsx +73 -65
- package/src/stories/SIA/DemoWrapper.tsx +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsxs as G,jsx as d}from"react/jsx-runtime";import
|
|
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};
|
package/dist/Canvas/Canvas.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsxs as B,jsx as
|
|
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
|
|
22
|
-
onAnnoChanged?: (changedAnno: Annotation
|
|
23
|
-
onAnnoDeleted?: (deletedAnno: Annotation, allAnnos
|
|
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
|
|
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
|
|
23
|
-
onAnnoChanged?: (changedAnno: import('../models').Annotation
|
|
24
|
-
onAnnoDeleted?: (deletedAnno: import('../models').Annotation, allAnnos
|
|
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
|
|
23
|
-
onAnnoChanged?: (changedAnno: import('../models').Annotation
|
|
24
|
-
onAnnoDeleted?: (deletedAnno: import('../models').Annotation, allAnnos
|
|
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
|
|
54
|
-
onAnnoChanged?: (changedAnno: import('../models').Annotation
|
|
55
|
-
onAnnoDeleted?: (deletedAnno: import('../models').Annotation, allAnnos
|
|
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
|
|
23
|
-
onAnnoChanged?: (changedAnno: import('../../models').Annotation
|
|
24
|
-
onAnnoDeleted?: (deletedAnno: import('../../models').Annotation, allAnnos
|
|
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
|
|
54
|
-
onAnnoChanged?: (changedAnno: import('../../models').Annotation
|
|
55
|
-
onAnnoDeleted?: (deletedAnno: import('../../models').Annotation, allAnnos
|
|
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
|
@@ -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
|
|
package/src/Canvas/Canvas.tsx
CHANGED
|
@@ -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
|
-
|
|
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
|
|
37
|
-
onAnnoChanged?: (changedAnno: Annotation
|
|
38
|
-
onAnnoDeleted?: (deletedAnno: Annotation, allAnnos
|
|
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
|
-
|
|
502
|
-
|
|
503
|
-
|
|
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
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
510
|
+
setAnnotations((prev) => {
|
|
511
|
+
// update annotation list
|
|
512
|
+
const annoListIndex: number = prev.findIndex(
|
|
513
|
+
(anno) => anno.internalId === changedAnno.internalId,
|
|
514
|
+
)
|
|
513
515
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
+
// only fire event if item found
|
|
517
|
+
if (annoListIndex === -1) return prev
|
|
516
518
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
setAnnotations(_annotations)
|
|
519
|
+
const _annotations: Annotation[] = [...prev]
|
|
520
|
+
_annotations[annoListIndex] = changedAnno
|
|
520
521
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
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
|
-
|
|
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
|
-
|
|
534
|
-
|
|
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
|
-
|
|
574
|
-
|
|
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
|
|
577
|
-
onAnnoCreationFinished(
|
|
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
|
|
39
|
+
onAnnoCreationFinished={(anno: Annotation) => {
|
|
40
40
|
console.log('FINISHED CREATION', anno)
|
|
41
41
|
}}
|
|
42
|
-
onAnnoChanged={(anno: Annotation
|
|
42
|
+
onAnnoChanged={(anno: Annotation) => {
|
|
43
43
|
console.log('CHANGED', anno)
|
|
44
44
|
}}
|
|
45
45
|
onAnnoDeleted={(anno: Annotation, annos: Annotation[]) => {
|