@abidibo/react-cam-roi 0.3.0 → 0.5.0

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/index.esm.js CHANGED
@@ -317,6 +317,17 @@ var fabricShapeToOutputShape = function (shape, type, imageSize) {
317
317
  height: abs2Perc(shape.height, imageSize.height),
318
318
  color: shape.stroke,
319
319
  };
320
+ case "point" /* ToolEnum.Point */:
321
+ return {
322
+ angle: shape.angle,
323
+ scaleX: shape.scaleX,
324
+ scaleY: shape.scaleY,
325
+ skewX: shape.skewX,
326
+ skewY: shape.skewY,
327
+ top: abs2Perc(shape.top, imageSize.height),
328
+ left: abs2Perc(shape.left, imageSize.width),
329
+ color: shape.stroke,
330
+ };
320
331
  case "polygon" /* ToolEnum.Polygon */:
321
332
  case "polyline" /* ToolEnum.Polyline */:
322
333
  return {
@@ -384,6 +395,11 @@ var fabricShapeToOutputCoords = function (shape, type, imageSize) {
384
395
  });
385
396
  })
386
397
  };
398
+ case "point" /* ToolEnum.Point */:
399
+ return {
400
+ x: abs2Perc(shape.left, imageSize.width),
401
+ y: abs2Perc(shape.top, imageSize.height),
402
+ };
387
403
  case "polygon" /* ToolEnum.Polygon */:
388
404
  case "polyline" /* ToolEnum.Polyline */:
389
405
  return {
@@ -513,6 +529,7 @@ var DefaultUiContext = {
513
529
  notify: notify,
514
530
  strings: {
515
531
  cancel: 'Cancel',
532
+ cannotDrawMorePoints: 'You cannot draw more points',
516
533
  cannotDrawMorePolygons: 'You cannot draw more polygons',
517
534
  cannotDrawMorePolylines: 'You cannot draw more polylines',
518
535
  cannotDrawMoreRectangles: 'You cannot draw more rectangles',
@@ -522,6 +539,8 @@ var DefaultUiContext = {
522
539
  missingRequiredValuesInMainParameters: 'Missing required values in main parameters',
523
540
  missingRequiredValuesInShapeParameters: 'Missing required values in shape {id} parameters',
524
541
  name: 'Name',
542
+ point: 'Point',
543
+ pointHelpText: 'click to draw the point',
525
544
  polygon: 'Polygon',
526
545
  polygonHelpText: 'click to draw all the polygon points, double click on the last point to close the polygon',
527
546
  polyline: 'Polyline',
@@ -934,6 +953,52 @@ var copyRectangle = function (editorId, canvas, rectangle) {
934
953
  return copy;
935
954
  };
936
955
 
956
+ var handleMouseDownPoint = function (event, editorId, canvas, activeColor, setOriginX, setOriginY) {
957
+ var pointer = canvas.getScenePoint(event.e);
958
+ setOriginX(pointer.x);
959
+ setOriginY(pointer.y);
960
+ var id = v4();
961
+ var newCircle = new Gn({
962
+ left: pointer.x,
963
+ top: pointer.y,
964
+ originX: 'center',
965
+ originY: 'center',
966
+ radius: 6,
967
+ fill: activeColor,
968
+ stroke: activeColor,
969
+ strokeWidth: 2,
970
+ strokeUniform: true,
971
+ selectable: false,
972
+ hasControls: false,
973
+ hoverCursor: 'default',
974
+ id: id,
975
+ });
976
+ canvas.add(newCircle);
977
+ Dispatcher.emit("canvas:".concat(editorId, ":shapeAdded"), { id: id, type: "point" /* ToolEnum.Point */, shape: newCircle });
978
+ canvas.defaultCursor = 'default';
979
+ };
980
+ var copyPoint = function (editorId, canvas, point) {
981
+ var id = v4();
982
+ var copy = new Gn({
983
+ left: point.left + 10,
984
+ top: point.top + 10,
985
+ originX: 'center',
986
+ originY: 'center',
987
+ radius: 6,
988
+ fill: point.fill,
989
+ stroke: point.stroke,
990
+ strokeWidth: point.strokeWidth,
991
+ strokeUniform: true,
992
+ selectable: false,
993
+ hasControls: false,
994
+ hoverCursor: 'default',
995
+ id: id,
996
+ });
997
+ canvas.add(copy);
998
+ Dispatcher.emit("canvas:".concat(editorId, ":shapeAdded"), { id: id, type: "point" /* ToolEnum.Point */, shape: copy });
999
+ return copy;
1000
+ };
1001
+
937
1002
  var useImageSize = function (imageUrl) {
938
1003
  var _a = useState({ width: 0, height: 0 }), imageSize = _a[0], setImageSize = _a[1];
939
1004
  useEffect(function () {
@@ -979,11 +1044,34 @@ var initCanvasData = function (canvasRef, imageSize, addShapes, metadata, setMet
979
1044
  var m_1 = [];
980
1045
  var s_1 = [];
981
1046
  initialData.rois.forEach(function (r) {
982
- var _a, _b, _c;
1047
+ var _a, _b, _c, _d;
983
1048
  log('info', enableLogs !== null && enableLogs !== void 0 ? enableLogs : false, 'Loading initial shape', r);
984
1049
  var id = r.id;
985
1050
  var shape;
986
1051
  switch (r.type) {
1052
+ case "point" /* ToolEnum.Point */:
1053
+ shape = new Gn({
1054
+ angle: r.shape.angle || 0,
1055
+ scaleX: r.shape.scaleX || 1,
1056
+ scaleY: r.shape.scaleY || 1,
1057
+ skewX: r.shape.skewX || 0,
1058
+ skewY: r.shape.skewY || 0,
1059
+ left: perc2Abs(r.shape.left, imageSize.width),
1060
+ top: perc2Abs(r.shape.top, imageSize.height),
1061
+ originX: 'center',
1062
+ originY: 'center',
1063
+ radius: 6,
1064
+ fill: r.shape.color,
1065
+ stroke: r.shape.color,
1066
+ strokeWidth: 2,
1067
+ strokeUniform: true,
1068
+ selectable: false,
1069
+ hasControls: false,
1070
+ hoverCursor: 'default',
1071
+ id: id,
1072
+ });
1073
+ (_a = canvasRef.current) === null || _a === void 0 ? void 0 : _a.add(shape);
1074
+ break;
987
1075
  case "rect" /* ToolEnum.Rectangle */:
988
1076
  shape = new fr({
989
1077
  angle: r.shape.angle || 0,
@@ -1006,7 +1094,7 @@ var initCanvasData = function (canvasRef, imageSize, addShapes, metadata, setMet
1006
1094
  hoverCursor: 'default',
1007
1095
  id: id,
1008
1096
  });
1009
- (_a = canvasRef.current) === null || _a === void 0 ? void 0 : _a.add(shape);
1097
+ (_b = canvasRef.current) === null || _b === void 0 ? void 0 : _b.add(shape);
1010
1098
  break;
1011
1099
  case "polygon" /* ToolEnum.Polygon */:
1012
1100
  shape = new oo(r.shape.points.map(function (_a) {
@@ -1033,7 +1121,7 @@ var initCanvasData = function (canvasRef, imageSize, addShapes, metadata, setMet
1033
1121
  // @ts-expect-error id is not included in types but the property is added and it works
1034
1122
  id: id,
1035
1123
  });
1036
- (_b = canvasRef.current) === null || _b === void 0 ? void 0 : _b.add(shape);
1124
+ (_c = canvasRef.current) === null || _c === void 0 ? void 0 : _c.add(shape);
1037
1125
  break;
1038
1126
  case "polyline" /* ToolEnum.Polyline */:
1039
1127
  shape = new no(r.shape.points.map(function (_a) {
@@ -1059,7 +1147,7 @@ var initCanvasData = function (canvasRef, imageSize, addShapes, metadata, setMet
1059
1147
  hoverCursor: 'default',
1060
1148
  id: id,
1061
1149
  });
1062
- (_c = canvasRef.current) === null || _c === void 0 ? void 0 : _c.add(shape);
1150
+ (_d = canvasRef.current) === null || _d === void 0 ? void 0 : _d.add(shape);
1063
1151
  break;
1064
1152
  }
1065
1153
  m_1.push({ id: id, parameters: r.parameters, name: r.name, role: r.role });
@@ -1084,7 +1172,7 @@ var useTool = function (canvas) {
1084
1172
  var _a;
1085
1173
  Dispatcher.emit("canvas:".concat(editorId, ":shapeSelected"), (_a = event.selected) !== null && _a !== void 0 ? _a : null);
1086
1174
  }, [editorId]);
1087
- var handleRefreshShapes = useCallback(function () { return setShapes(__assign({}, shapes)); }, [shapes]);
1175
+ var handleRefreshShapes = useCallback(function () { return setShapes(__assign({}, shapes)); }, [shapes]); // eslint-disable-line
1088
1176
  // Handler for selection cleared event to reset selected shapes state
1089
1177
  var handleSelectionCleared = useCallback(function () {
1090
1178
  Dispatcher.emit("canvas:".concat(editorId, ":shapeSelected"), null);
@@ -1111,6 +1199,11 @@ var useTool = function (canvas) {
1111
1199
  }
1112
1200
  var handleMouseDown = function (event) {
1113
1201
  switch (activeTool) {
1202
+ case "point" /* ToolEnum.Point */:
1203
+ if (!canDrawShape(configuration, "point" /* ToolEnum.Point */, shapes, notify, strings.cannotDrawMorePoints))
1204
+ return;
1205
+ handleMouseDownPoint(event, editorId, canvas, activeColor, setOriginX, setOriginY);
1206
+ break;
1114
1207
  case "rect" /* ToolEnum.Rectangle */:
1115
1208
  if (!canDrawShape(configuration, "rect" /* ToolEnum.Rectangle */, shapes, notify, strings.cannotDrawMoreRectangles))
1116
1209
  return;
@@ -1211,6 +1304,13 @@ var useDispatcherEvents = function (canvas) {
1211
1304
  var obj = canvas === null || canvas === void 0 ? void 0 : canvas.getObjects().find(function (s) { return s.id === id; });
1212
1305
  var copy;
1213
1306
  switch (obj === null || obj === void 0 ? void 0 : obj.type) {
1307
+ case 'circle': // a ToolEnum.Point is drawed like a circle with fixed radius
1308
+ if (!canDrawShape(configuration, "point" /* ToolEnum.Point */, shapes, notify, strings.cannotDrawMorePoints))
1309
+ return;
1310
+ copy = copyPoint(editorId, canvas, obj);
1311
+ // @ts-expect-error id exists but his stupid ts does not know
1312
+ Dispatcher.emit("canvas:".concat(editorId, ":selectShape"), copy.id);
1313
+ break;
1214
1314
  case "polygon" /* ToolEnum.Polygon */:
1215
1315
  if (!canDrawShape(configuration, "polygon" /* ToolEnum.Polygon */, shapes, notify, strings.cannotDrawMorePolygons))
1216
1316
  return;
@@ -1344,27 +1444,18 @@ var Header = function () {
1344
1444
 
1345
1445
  var styles$5 = {"canvas-wrapper":"RoiEditor-module_canvas-wrapper__q0gQg"};
1346
1446
 
1347
- var isAllowed = function (role, multiplicity, metadata) {
1348
- switch (multiplicity.operator) {
1349
- case OperatorEnum.Eq:
1350
- case OperatorEnum.Lte:
1351
- return metadata.rois.filter(function (m) { return m.role === role; }).length < multiplicity.threshold;
1352
- case OperatorEnum.Lt:
1353
- return metadata.rois.filter(function (m) { return m.role === role; }).length < multiplicity.threshold - 1;
1354
- default:
1355
- return true;
1356
- }
1357
- };
1358
1447
  var RoleField = function (_a) {
1359
1448
  var onChange = _a.onChange, value = _a.value, required = _a.required, shapeType = _a.shapeType, props = __rest(_a, ["onChange", "value", "required", "shapeType"]);
1360
1449
  var _b = useContext(UiContext), strings = _b.strings, EnumField = _b.EnumField;
1361
- var _c = useEditorContext(), configuration = _c.configuration, metadata = _c.metadata;
1450
+ var configuration = useEditorContext().configuration /*, metadata*/;
1362
1451
  var options = [];
1363
1452
  var rois = configuration.rois || [];
1364
1453
  rois
1365
1454
  .filter(function (r) { return r.type === shapeType; })
1366
1455
  .forEach(function (r) {
1367
- if (!options.includes(r.role) && (!r.multiplicity || isAllowed(r.role, r.multiplicity, metadata))) {
1456
+ // the following causes problems with initial data when all shapes are drawn, no roles appear in the edit dropdown
1457
+ // if (!options.includes(r.role) && (!r.multiplicity || isAllowed(r.role, r.multiplicity!, metadata))) {
1458
+ if (!options.includes(r.role)) {
1368
1459
  options.push(r.role);
1369
1460
  }
1370
1461
  });
@@ -1546,6 +1637,11 @@ var ColorPicker = function (_a) {
1546
1637
 
1547
1638
  var styles$1 = {"toolbar":"Toolbar-module_toolbar__ywNcv","toolbar-light":"Toolbar-module_toolbar-light__aJtaH","toolbar-dark":"Toolbar-module_toolbar-dark__9iO4U","toolbar-helper":"Toolbar-module_toolbar-helper__DBw3v","toolbar-helper-light":"Toolbar-module_toolbar-helper-light__Z4PLG","toolbar-helper-dark":"Toolbar-module_toolbar-helper-dark__AEXUy","toolbar-spacer":"Toolbar-module_toolbar-spacer__qPxmN","toolbar-spacer-light":"Toolbar-module_toolbar-spacer-light__2CNYP","toolbar-spacer-dark":"Toolbar-module_toolbar-spacer-dark__cW0Rj"};
1548
1639
 
1640
+ var PointIcon = function (_a) {
1641
+ var _b = _a.color, color = _b === void 0 ? 'black' : _b, _c = _a.style, style = _c === void 0 ? { height: '32px' } : _c;
1642
+ return (jsxs("svg", { style: style, width: "25", height: "25", viewBox: "0 0 25 25", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("circle", { cx: "9.5", cy: "15.5", r: "4.5", fill: color }), jsx("path", { d: "M19.5 0 L21.5 0 L21.5 3.5 L25 3.5 L25 5.5 L21.5 5.5 L21.5 9 L19.5 9 L19.5 5.5 L16 5.5 L16 3.5 L19.5 3.5 Z", stroke: color, "stroke-width": ".6", fill: color })] }));
1643
+ };
1644
+
1549
1645
  var Toolbar = function () {
1550
1646
  var _a;
1551
1647
  var _b = useContext(UiContext), IconButton = _b.IconButton, themeMode = _b.themeMode, primaryColor = _b.primaryColor, Typography = _b.Typography, strings = _b.strings;
@@ -1553,12 +1649,14 @@ var Toolbar = function () {
1553
1649
  var iconColor = function (tool) { return (tool === activeTool ? primaryColor : themeMode === 'light' ? 'black' : 'white'); };
1554
1650
  var setTool = function (tool) { return function () { return setActiveTool(tool); }; };
1555
1651
  var hideForbiddenTools = (_a = configuration.options) === null || _a === void 0 ? void 0 : _a.hideForbiddenTools;
1652
+ var pointEnabled = configuration.rois.find(function (r) { return r.type === "point" /* ToolEnum.Point */; }) &&
1653
+ canDrawShape(configuration, "point" /* ToolEnum.Point */, shapes);
1556
1654
  var polylineEnabled = configuration.rois.find(function (r) { return r.type === "polyline" /* ToolEnum.Polyline */; }) &&
1557
1655
  canDrawShape(configuration, "polyline" /* ToolEnum.Polyline */, shapes);
1558
1656
  var polygonEnabled = configuration.rois.find(function (r) { return r.type === "polygon" /* ToolEnum.Polygon */; }) && canDrawShape(configuration, "polygon" /* ToolEnum.Polygon */, shapes);
1559
1657
  var rectangleEnabled = configuration.rois.find(function (r) { return r.type === "rect" /* ToolEnum.Rectangle */; }) &&
1560
1658
  canDrawShape(configuration, "rect" /* ToolEnum.Rectangle */, shapes);
1561
- return (jsxs(Fragment, { children: [jsx("div", { className: css('toolbar', styles$1, themeMode), children: enableRois(configuration) && (jsxs(Fragment, { children: [jsx(IconButton, { onClick: setTool("pointer" /* ToolEnum.Pointer */), children: jsx(PointerIcon, { color: iconColor("pointer" /* ToolEnum.Pointer */) }) }), (!hideForbiddenTools || polylineEnabled) && (jsx(IconButton, { onClick: setTool("polyline" /* ToolEnum.Polyline */), disabled: !polylineEnabled, children: jsx(PolylineIcon, { color: iconColor("polyline" /* ToolEnum.Polyline */) }) })), (!hideForbiddenTools || polygonEnabled) && (jsx(IconButton, { onClick: setTool("polygon" /* ToolEnum.Polygon */), disabled: !polygonEnabled, children: jsx(PolygonIcon, { color: iconColor("polygon" /* ToolEnum.Polygon */) }) })), (!hideForbiddenTools || rectangleEnabled) && (jsx(IconButton, { onClick: setTool("rect" /* ToolEnum.Rectangle */), disabled: !rectangleEnabled, children: jsx(RectangleIcon, { color: iconColor("rect" /* ToolEnum.Rectangle */) }) })), jsx(ColorPicker, { style: { marginLeft: 'auto', marginRight: '.5rem' } })] })) }), enableRois(configuration) && (jsx("div", { className: css('toolbar-helper', styles$1, themeMode), children: jsxs(Typography, { children: [strings[activeTool], ": ", strings["".concat(activeTool, "HelpText")]] }) }))] }));
1659
+ return (jsxs(Fragment, { children: [jsx("div", { className: css('toolbar', styles$1, themeMode), children: enableRois(configuration) && (jsxs(Fragment, { children: [jsx(IconButton, { onClick: setTool("pointer" /* ToolEnum.Pointer */), children: jsx(PointerIcon, { color: iconColor("pointer" /* ToolEnum.Pointer */) }) }), (!hideForbiddenTools || pointEnabled) && (jsx(IconButton, { onClick: setTool("point" /* ToolEnum.Point */), disabled: !pointEnabled, children: jsx(PointIcon, { color: iconColor("point" /* ToolEnum.Point */) }) })), (!hideForbiddenTools || polylineEnabled) && (jsx(IconButton, { onClick: setTool("polyline" /* ToolEnum.Polyline */), disabled: !polylineEnabled, children: jsx(PolylineIcon, { color: iconColor("polyline" /* ToolEnum.Polyline */) }) })), (!hideForbiddenTools || polygonEnabled) && (jsx(IconButton, { onClick: setTool("polygon" /* ToolEnum.Polygon */), disabled: !polygonEnabled, children: jsx(PolygonIcon, { color: iconColor("polygon" /* ToolEnum.Polygon */) }) })), (!hideForbiddenTools || rectangleEnabled) && (jsx(IconButton, { onClick: setTool("rect" /* ToolEnum.Rectangle */), disabled: !rectangleEnabled, children: jsx(RectangleIcon, { color: iconColor("rect" /* ToolEnum.Rectangle */) }) })), jsx(ColorPicker, { style: { marginLeft: 'auto', marginRight: '.5rem' } })] })) }), enableRois(configuration) && (jsx("div", { className: css('toolbar-helper', styles$1, themeMode), children: jsxs(Typography, { children: [strings[activeTool], ": ", strings["".concat(activeTool, "HelpText")]] }) }))] }));
1562
1660
  };
1563
1661
 
1564
1662
  var styles = {"top-bar":"TopBar-module_top-bar__9oCUR","main-parameters-view":"TopBar-module_main-parameters-view__f-0SX","main-parameters-view-light":"TopBar-module_main-parameters-view-light__o-dbi","main-parameters-view-dark":"TopBar-module_main-parameters-view-dark__FnEnj","main-parameters-button":"TopBar-module_main-parameters-button__9JX--"};
@@ -1571,12 +1669,9 @@ var TopBar = function () {
1571
1669
  var iconColor = themeMode === 'light' ? 'black' : 'white';
1572
1670
  var handleSubmitMetadata = function (data) {
1573
1671
  setMetadata(__assign(__assign({}, metadata), { parameters: data }));
1574
- console.log('SAVE', {
1575
- parameters: data,
1576
- }); // eslint-disable-line
1577
1672
  setForm({ isOpen: false });
1578
1673
  };
1579
- return (jsxs(Fragment, { children: [jsxs("div", { className: css('top-bar', styles, themeMode), children: [enableMainMetadata(configuration) && !((_a = configuration.options) === null || _a === void 0 ? void 0 : _a.viewMainParameters) && (jsxs(Button, { onClick: function () { return setForm({ isOpen: true }); }, children: [jsx(AnnotateIcon, { color: iconColor }), " ", strings.mainParametersMetadata] })), jsxs(Button, { primary: true, onClick: onSubmit, children: [jsx(SaveIcon, { color: primaryFgColor }), " ", strings.save] }), form.isOpen && (jsx(ParametersModalForm, { parameters: configuration.parameters, data: metadata.parameters, title: strings.mainParametersMetadata, onClose: function () { return setForm({ isOpen: false }); }, onSubmit: handleSubmitMetadata }))] }), ((_b = configuration.options) === null || _b === void 0 ? void 0 : _b.viewMainParameters) && (jsxs("div", { className: css('main-parameters-view', styles, themeMode), children: [jsx("div", { className: css('main-parameters-button', styles, themeMode), children: jsxs(Button, { onClick: function () { return setForm({ isOpen: true }); }, children: [jsx(AnnotateIcon, { color: iconColor }), " ", strings.mainParametersMetadata] }) }), jsx(ParametersModalForm, { parameters: configuration.parameters, data: metadata.parameters, title: strings.mainParametersMetadata, onClose: function () { return setForm({ isOpen: false }); }, onSubmit: handleSubmitMetadata, readOnly: true, noModal: true })] }))] }));
1674
+ return (jsxs(Fragment, { children: [jsxs("div", { className: css('top-bar', styles, themeMode), children: [enableMainMetadata(configuration) && !((_a = configuration.options) === null || _a === void 0 ? void 0 : _a.viewMainParameters) && (jsxs(Button, { onClick: function () { return setForm({ isOpen: true }); }, children: [jsx(AnnotateIcon, { color: iconColor }), " ", strings.mainParametersMetadata] })), jsxs(Button, { primary: true, onClick: onSubmit, children: [jsx(SaveIcon, { color: primaryFgColor }), " ", strings.save] }), form.isOpen && (jsx(ParametersModalForm, { parameters: configuration.parameters, data: metadata.parameters, title: strings.mainParametersMetadata, onClose: function () { return setForm({ isOpen: false }); }, onSubmit: handleSubmitMetadata }))] }), enableMainMetadata(configuration) && ((_b = configuration.options) === null || _b === void 0 ? void 0 : _b.viewMainParameters) && (jsxs("div", { className: css('main-parameters-view', styles, themeMode), children: [jsx("div", { className: css('main-parameters-button', styles, themeMode), children: jsxs(Button, { onClick: function () { return setForm({ isOpen: true }); }, children: [jsx(AnnotateIcon, { color: iconColor }), " ", strings.mainParametersMetadata] }) }), jsx(ParametersModalForm, { parameters: configuration.parameters, data: metadata.parameters, title: strings.mainParametersMetadata, onClose: function () { return setForm({ isOpen: false }); }, onSubmit: handleSubmitMetadata, readOnly: true, noModal: true })] }))] }));
1580
1675
  };
1581
1676
 
1582
1677
  // https://github.com/n-mazaheri/image-editor
@@ -1633,7 +1728,7 @@ var RoiEditor = function (_a) {
1633
1728
  role: (_g = (_f = metadata.rois.find(function (r) { return r.id === shapeId; })) === null || _f === void 0 ? void 0 : _f.role) !== null && _g !== void 0 ? _g : '',
1634
1729
  type: shapes[shapeId].type,
1635
1730
  id: shapeId,
1636
- shape: fabricShapeToOutputShape(shapes[shapeId].shape, shapes[shapeId].shape.type, imageSize),
1731
+ shape: fabricShapeToOutputShape(shapes[shapeId].shape, shapes[shapeId].type, imageSize),
1637
1732
  coords: fabricShapeToOutputCoords(shapes[shapeId].shape, shapes[shapeId].shape.type, imageSize),
1638
1733
  });
1639
1734
  }),