@abidibo/react-cam-roi 0.14.2 → 0.14.4

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.cjs.js CHANGED
@@ -122,9 +122,13 @@ var formatString = function (str, placeholders) {
122
122
  });
123
123
  return str;
124
124
  };
125
- var abs2Perc = function (value, ref) { return Math.round((value / ref) * 100 * 100) / 100; };
126
- var perc2Abs = function (value, ref) { return Math.round((ref * value * 100) / 100) / 100; };
127
- var defaultTo = function (dft) { return function (value) { return value !== null && value !== void 0 ? value : dft; }; };
125
+ var abs2Perc = function (value, ref) { return Math.round((value / ref) * 100 * 10000) / 10000; };
126
+ var perc2Abs = function (value, ref) { return Math.round((ref / 100) * value * 10000) / 10000; };
127
+ var defaultTo = function (dft) {
128
+ return function (value) {
129
+ return value !== null && value !== void 0 ? value : dft;
130
+ };
131
+ };
128
132
  var compose = function () {
129
133
  var fns = [];
130
134
  for (var _i = 0; _i < arguments.length; _i++) {
@@ -204,7 +208,7 @@ var NumberField = function (_a) {
204
208
  var onChange = _a.onChange, value = _a.value, label = _a.label, required = _a.required, helperText = _a.helperText, error = _a.error;
205
209
  var _b = React.useContext(UiContext), themeMode = _b.themeMode, Typography = _b.Typography;
206
210
  var handleChange = function (e) {
207
- onChange(parseFloat(e.target.value));
211
+ onChange(e.target.value === '' ? null : parseFloat(e.target.value));
208
212
  };
209
213
  return (jsxRuntime.jsxs("div", { className: css('number-field-wrapper', styles$9, themeMode), children: [jsxRuntime.jsx("label", { className: "".concat(css('number-field-label', styles$9, themeMode), " ").concat(error ? css('number-field-label-error', styles$9, null) : ''), children: jsxRuntime.jsxs(Typography, { children: [label, required && ' *'] }) }), jsxRuntime.jsx("input", { type: 'number', className: "".concat(css('number-field', styles$9, themeMode), " ").concat(error ? css('number-field-error', styles$9, null) : ''), onChange: handleChange, value: value !== null && value !== void 0 ? value : '' }), helperText && (jsxRuntime.jsx(Typography, { component: 'div', className: "".concat(css('number-field-helper-text', styles$9, themeMode), " ").concat(error ? css('number-field-helper-text-error', styles$9, null) : ''), children: helperText }))] }));
210
214
  };
@@ -284,11 +288,14 @@ var canDrawShape = function (configuration, shapeType, shapes, notify, message)
284
288
  }
285
289
  return false;
286
290
  };
287
- var validateParametersForm = function (parameters, fields, setErrors, strings) {
291
+ var validateParametersForm = function (parameters, fields, setErrors, resetErrors) {
292
+ resetErrors();
288
293
  var err = {};
289
294
  parameters.forEach(function (p) {
290
- if (p.required && isEmpty(fields[p.codename])) {
291
- err[p.codename] = strings.requiredField;
295
+ if (p.required &&
296
+ (isEmpty(fields[p.codename]) ||
297
+ isNil(fields[p.codename]))) {
298
+ err[p.codename] = 'requiredField';
292
299
  }
293
300
  });
294
301
  if (Object.keys(err).length > 0) {
@@ -306,6 +313,9 @@ var isEmpty = function (v) {
306
313
  }
307
314
  return v === null || v === undefined;
308
315
  };
316
+ var isNil = function (v) {
317
+ return v === null || v === undefined;
318
+ };
309
319
  var validate$1 = function (configuration, presetName, shapes, metadata, strings) {
310
320
  var errors = [];
311
321
  // check presetName
@@ -367,9 +377,9 @@ var validate$1 = function (configuration, presetName, shapes, metadata, strings)
367
377
  });
368
378
  // check rois metadata
369
379
  Object.keys(shapes).forEach(function (shapeId) {
370
- var _a, _b;
371
- var type = shapes[shapeId].type;
372
- var confParameters = (_b = (_a = configuration.rois.find(function (r) { return r.type === type; })) === null || _a === void 0 ? void 0 : _a.parameters) !== null && _b !== void 0 ? _b : [];
380
+ var _a, _b, _c;
381
+ var role = (_a = metadata.rois.find(function (r) { return r.id === shapeId; })) === null || _a === void 0 ? void 0 : _a.role;
382
+ var confParameters = (_c = (_b = configuration.rois.find(function (r) { return r.role === role; })) === null || _b === void 0 ? void 0 : _b.parameters) !== null && _c !== void 0 ? _c : [];
373
383
  confParameters.forEach(function (p) {
374
384
  var _a, _b;
375
385
  if (p.required &&
@@ -380,7 +390,7 @@ var validate$1 = function (configuration, presetName, shapes, metadata, strings)
380
390
  });
381
391
  return [errors.length === 0, errors];
382
392
  };
383
- var fabricShapeToOutputShape = function (shape, type, imageSize) {
393
+ var fabricShapeToOutputShape = function (shape, type, canvasSize) {
384
394
  switch (type) {
385
395
  case "rect" /* ToolEnum.Rectangle */:
386
396
  return {
@@ -389,10 +399,10 @@ var fabricShapeToOutputShape = function (shape, type, imageSize) {
389
399
  scaleY: shape.scaleY,
390
400
  skewX: shape.skewX,
391
401
  skewY: shape.skewY,
392
- top: abs2Perc(shape.top, imageSize.height),
393
- left: abs2Perc(shape.left, imageSize.width),
394
- width: abs2Perc(shape.width, imageSize.width),
395
- height: abs2Perc(shape.height, imageSize.height),
402
+ top: abs2Perc(shape.top, canvasSize.height),
403
+ left: abs2Perc(shape.left, canvasSize.width),
404
+ width: abs2Perc(shape.width, canvasSize.width),
405
+ height: abs2Perc(shape.height, canvasSize.height),
396
406
  color: shape.stroke,
397
407
  };
398
408
  case "point" /* ToolEnum.Point */:
@@ -402,8 +412,8 @@ var fabricShapeToOutputShape = function (shape, type, imageSize) {
402
412
  scaleY: shape.scaleY,
403
413
  skewX: shape.skewX,
404
414
  skewY: shape.skewY,
405
- top: abs2Perc(shape.top, imageSize.height),
406
- left: abs2Perc(shape.left, imageSize.width),
415
+ top: abs2Perc(shape.top, canvasSize.height),
416
+ left: abs2Perc(shape.left, canvasSize.width),
407
417
  color: shape.stroke,
408
418
  };
409
419
  case "polygon" /* ToolEnum.Polygon */:
@@ -412,12 +422,12 @@ var fabricShapeToOutputShape = function (shape, type, imageSize) {
412
422
  points: shape.get('points').map(function (_a) {
413
423
  var x = _a.x, y = _a.y;
414
424
  return ({
415
- x: abs2Perc(x, imageSize.width),
416
- y: abs2Perc(y, imageSize.height),
425
+ x: abs2Perc(x, canvasSize.width),
426
+ y: abs2Perc(y, canvasSize.height),
417
427
  });
418
428
  }),
419
- top: abs2Perc(shape.top, imageSize.height),
420
- left: abs2Perc(shape.left, imageSize.width),
429
+ top: abs2Perc(shape.top, canvasSize.height),
430
+ left: abs2Perc(shape.left, canvasSize.width),
421
431
  color: shape.stroke,
422
432
  angle: shape.angle,
423
433
  scaleX: shape.scaleX,
@@ -463,22 +473,22 @@ function getAbsolutePoints(shape) {
463
473
  return { x: transformedPoint.x, y: transformedPoint.y };
464
474
  });
465
475
  }
466
- var fabricShapeToOutputCoords = function (shape, type, imageSize) {
476
+ var fabricShapeToOutputCoords = function (shape, type, canvasSize) {
467
477
  switch (type) {
468
478
  case "rect" /* ToolEnum.Rectangle */:
469
479
  return {
470
480
  points: getAbsoluteRectData(shape).map(function (_a) {
471
481
  var x = _a.x, y = _a.y;
472
482
  return ({
473
- x: abs2Perc(x, imageSize.width),
474
- y: abs2Perc(y, imageSize.height),
483
+ x: abs2Perc(x, canvasSize.width),
484
+ y: abs2Perc(y, canvasSize.height),
475
485
  });
476
486
  }),
477
487
  };
478
488
  case "point" /* ToolEnum.Point */:
479
489
  return {
480
- x: abs2Perc(shape.left, imageSize.width),
481
- y: abs2Perc(shape.top, imageSize.height),
490
+ x: abs2Perc(shape.left, canvasSize.width),
491
+ y: abs2Perc(shape.top, canvasSize.height),
482
492
  };
483
493
  case "polygon" /* ToolEnum.Polygon */:
484
494
  case "polyline" /* ToolEnum.Polyline */:
@@ -486,8 +496,8 @@ var fabricShapeToOutputCoords = function (shape, type, imageSize) {
486
496
  points: getAbsolutePoints(shape).map(function (_a) {
487
497
  var x = _a.x, y = _a.y;
488
498
  return ({
489
- x: abs2Perc(x, imageSize.width),
490
- y: abs2Perc(y, imageSize.height),
499
+ x: abs2Perc(x, canvasSize.width),
500
+ y: abs2Perc(y, canvasSize.height),
491
501
  });
492
502
  }),
493
503
  };
@@ -641,13 +651,6 @@ var UiProvider = function (_a) {
641
651
  return jsxRuntime.jsx(UiContext.Provider, { value: ctx, children: children });
642
652
  };
643
653
 
644
- var styles$7 = {"loader":"Loader-module_loader__6JyG7","spin":"Loader-module_spin__ZcV1b","loader-light":"Loader-module_loader-light__WlXKM","loader-dark":"Loader-module_loader-dark__mW1w5"};
645
-
646
- var Loader = function () {
647
- var themeMode = React.useContext(UiContext).themeMode;
648
- return jsxRuntime.jsx("div", { className: css('loader', styles$7, themeMode) });
649
- };
650
-
651
654
  /**
652
655
  * Event Dispatcher
653
656
  *
@@ -718,6 +721,13 @@ var Dispatcher = {
718
721
  }
719
722
  };
720
723
 
724
+ var styles$7 = {"loader":"Loader-module_loader__6JyG7","spin":"Loader-module_spin__ZcV1b","loader-light":"Loader-module_loader-light__WlXKM","loader-dark":"Loader-module_loader-dark__mW1w5"};
725
+
726
+ var Loader = function () {
727
+ var themeMode = React.useContext(UiContext).themeMode;
728
+ return jsxRuntime.jsx("div", { className: css('loader', styles$7, themeMode) });
729
+ };
730
+
721
731
  // Unique ID creation requires a high quality random # generator. In the browser we therefore
722
732
  // require the crypto API and do not support built-in fallback to lower quality random number
723
733
  // generators (like Math.random()).
@@ -782,6 +792,52 @@ function v4(options, buf, offset) {
782
792
  return stringify(rnds);
783
793
  }
784
794
 
795
+ var handleMouseDownPoint = function (event, editorId, canvas, activeColor, setOriginX, setOriginY) {
796
+ var pointer = canvas.getScenePoint(event.e);
797
+ setOriginX(pointer.x);
798
+ setOriginY(pointer.y);
799
+ var id = v4();
800
+ var newCircle = new Gn({
801
+ left: pointer.x,
802
+ top: pointer.y,
803
+ originX: 'center',
804
+ originY: 'center',
805
+ radius: 6,
806
+ fill: 'transparent',
807
+ stroke: activeColor,
808
+ strokeWidth: 2,
809
+ strokeUniform: true,
810
+ selectable: false,
811
+ hasControls: false,
812
+ hoverCursor: 'default',
813
+ id: id,
814
+ });
815
+ canvas.add(newCircle);
816
+ Dispatcher.emit("canvas:".concat(editorId, ":shapeAdded"), { id: id, type: "point" /* ToolEnum.Point */, shape: newCircle });
817
+ canvas.defaultCursor = 'default';
818
+ };
819
+ var copyPoint = function (editorId, canvas, point) {
820
+ var id = v4();
821
+ var copy = new Gn({
822
+ left: point.left + 10,
823
+ top: point.top + 10,
824
+ originX: 'center',
825
+ originY: 'center',
826
+ radius: 6,
827
+ fill: 'transparent',
828
+ stroke: point.stroke,
829
+ strokeWidth: point.strokeWidth,
830
+ strokeUniform: true,
831
+ selectable: false,
832
+ hasControls: false,
833
+ hoverCursor: 'default',
834
+ id: id,
835
+ });
836
+ canvas.add(copy);
837
+ Dispatcher.emit("canvas:".concat(editorId, ":shapeAdded"), { id: id, type: "point" /* ToolEnum.Point */, shape: copy });
838
+ return copy;
839
+ };
840
+
785
841
  var addPoint$1 = function (event, canvas, color, points, setPoints, lines, setLines) {
786
842
  var pointer = canvas.getScenePoint(event.e);
787
843
  var newPoint = { x: pointer.x, y: pointer.y };
@@ -1029,52 +1085,6 @@ var copyRectangle = function (editorId, canvas, rectangle) {
1029
1085
  return copy;
1030
1086
  };
1031
1087
 
1032
- var handleMouseDownPoint = function (event, editorId, canvas, activeColor, setOriginX, setOriginY) {
1033
- var pointer = canvas.getScenePoint(event.e);
1034
- setOriginX(pointer.x);
1035
- setOriginY(pointer.y);
1036
- var id = v4();
1037
- var newCircle = new Gn({
1038
- left: pointer.x,
1039
- top: pointer.y,
1040
- originX: 'center',
1041
- originY: 'center',
1042
- radius: 6,
1043
- fill: 'transparent',
1044
- stroke: activeColor,
1045
- strokeWidth: 2,
1046
- strokeUniform: true,
1047
- selectable: false,
1048
- hasControls: false,
1049
- hoverCursor: 'default',
1050
- id: id,
1051
- });
1052
- canvas.add(newCircle);
1053
- Dispatcher.emit("canvas:".concat(editorId, ":shapeAdded"), { id: id, type: "point" /* ToolEnum.Point */, shape: newCircle });
1054
- canvas.defaultCursor = 'default';
1055
- };
1056
- var copyPoint = function (editorId, canvas, point) {
1057
- var id = v4();
1058
- var copy = new Gn({
1059
- left: point.left + 10,
1060
- top: point.top + 10,
1061
- originX: 'center',
1062
- originY: 'center',
1063
- radius: 6,
1064
- fill: 'transparent',
1065
- stroke: point.stroke,
1066
- strokeWidth: point.strokeWidth,
1067
- strokeUniform: true,
1068
- selectable: false,
1069
- hasControls: false,
1070
- hoverCursor: 'default',
1071
- id: id,
1072
- });
1073
- canvas.add(copy);
1074
- Dispatcher.emit("canvas:".concat(editorId, ":shapeAdded"), { id: id, type: "point" /* ToolEnum.Point */, shape: copy });
1075
- return copy;
1076
- };
1077
-
1078
1088
  var useImageSize = function (imageUrl) {
1079
1089
  var _a = React.useState({ width: 0, height: 0 }), imageSize = _a[0], setImageSize = _a[1];
1080
1090
  React.useEffect(function () {
@@ -1114,7 +1124,7 @@ var useCanvasSize = function (imageUrl) {
1114
1124
  }, [imageSize, wrapperRef.current]); // eslint-disable-line
1115
1125
  return { imageSize: imageSize, canvasSize: canvasSize, wrapperRef: wrapperRef, isReady: isReady };
1116
1126
  };
1117
- var initCanvasData = function (canvasRef, imageSize, addShapes, metadata, setMetadata, initialData, enableLogs) {
1127
+ var initCanvasData = function (canvasRef, canvasSize, addShapes, metadata, setMetadata, initialData, enableLogs) {
1118
1128
  log('info', enableLogs !== null && enableLogs !== void 0 ? enableLogs : false, 'Loading initial shapes data', initialData, canvasRef.current);
1119
1129
  if (initialData === null || initialData === void 0 ? void 0 : initialData.rois) {
1120
1130
  var m_1 = [];
@@ -1132,8 +1142,8 @@ var initCanvasData = function (canvasRef, imageSize, addShapes, metadata, setMet
1132
1142
  scaleY: r.shape.scaleY || 1,
1133
1143
  skewX: r.shape.skewX || 0,
1134
1144
  skewY: r.shape.skewY || 0,
1135
- left: perc2Abs(r.shape.left, imageSize.width),
1136
- top: perc2Abs(r.shape.top, imageSize.height),
1145
+ left: perc2Abs(r.shape.left, canvasSize.width),
1146
+ top: perc2Abs(r.shape.top, canvasSize.height),
1137
1147
  originX: 'center',
1138
1148
  originY: 'center',
1139
1149
  radius: 6,
@@ -1155,12 +1165,12 @@ var initCanvasData = function (canvasRef, imageSize, addShapes, metadata, setMet
1155
1165
  scaleY: r.shape.scaleY || 1,
1156
1166
  skewX: r.shape.skewX || 0,
1157
1167
  skewY: r.shape.skewY || 0,
1158
- left: perc2Abs(r.shape.left, imageSize.width),
1159
- top: perc2Abs(r.shape.top, imageSize.height),
1168
+ left: perc2Abs(r.shape.left, canvasSize.width),
1169
+ top: perc2Abs(r.shape.top, canvasSize.height),
1160
1170
  originX: 'left',
1161
1171
  originY: 'top',
1162
- width: perc2Abs(r.shape.width, imageSize.width),
1163
- height: perc2Abs(r.shape.height, imageSize.height),
1172
+ width: perc2Abs(r.shape.width, canvasSize.width),
1173
+ height: perc2Abs(r.shape.height, canvasSize.height),
1164
1174
  fill: 'transparent',
1165
1175
  stroke: r.shape.color,
1166
1176
  strokeWidth: 2,
@@ -1176,8 +1186,8 @@ var initCanvasData = function (canvasRef, imageSize, addShapes, metadata, setMet
1176
1186
  shape = new oo(r.shape.points.map(function (_a) {
1177
1187
  var x = _a.x, y = _a.y;
1178
1188
  return ({
1179
- x: perc2Abs(x, imageSize.width),
1180
- y: perc2Abs(y, imageSize.height),
1189
+ x: perc2Abs(x, canvasSize.width),
1190
+ y: perc2Abs(y, canvasSize.height),
1181
1191
  });
1182
1192
  }), {
1183
1193
  angle: r.shape.angle || 0,
@@ -1185,8 +1195,8 @@ var initCanvasData = function (canvasRef, imageSize, addShapes, metadata, setMet
1185
1195
  scaleY: r.shape.scaleY || 1,
1186
1196
  skewX: r.shape.skewX || 0,
1187
1197
  skewY: r.shape.skewY || 0,
1188
- top: perc2Abs(r.shape.top, imageSize.height),
1189
- left: perc2Abs(r.shape.left, imageSize.width),
1198
+ top: perc2Abs(r.shape.top, canvasSize.height),
1199
+ left: perc2Abs(r.shape.left, canvasSize.width),
1190
1200
  fill: 'transparent',
1191
1201
  stroke: r.shape.color,
1192
1202
  strokeWidth: 2,
@@ -1203,8 +1213,8 @@ var initCanvasData = function (canvasRef, imageSize, addShapes, metadata, setMet
1203
1213
  shape = new no(r.shape.points.map(function (_a) {
1204
1214
  var x = _a.x, y = _a.y;
1205
1215
  return ({
1206
- x: perc2Abs(x, imageSize.width),
1207
- y: perc2Abs(y, imageSize.height),
1216
+ x: perc2Abs(x, canvasSize.width),
1217
+ y: perc2Abs(y, canvasSize.height),
1208
1218
  });
1209
1219
  }), {
1210
1220
  angle: r.shape.angle || 0,
@@ -1212,8 +1222,8 @@ var initCanvasData = function (canvasRef, imageSize, addShapes, metadata, setMet
1212
1222
  scaleY: r.shape.scaleY || 1,
1213
1223
  skewX: r.shape.skewX || 0,
1214
1224
  skewY: r.shape.skewY || 0,
1215
- top: perc2Abs(r.shape.top, imageSize.height),
1216
- left: perc2Abs(r.shape.left, imageSize.width),
1225
+ top: perc2Abs(r.shape.top, canvasSize.height),
1226
+ left: perc2Abs(r.shape.left, canvasSize.width),
1217
1227
  fill: 'transparent',
1218
1228
  stroke: r.shape.color,
1219
1229
  strokeWidth: 2,
@@ -1441,28 +1451,40 @@ var useParametersForm = function (parameters) {
1441
1451
  setFields(__assign(__assign({}, fields), (_a = {}, _a[key] = value, _a)));
1442
1452
  };
1443
1453
  };
1454
+ var resetErrors = function () {
1455
+ setErrors({});
1456
+ };
1457
+ var reset = function () {
1458
+ setFields(parameters.reduce(function (acc, p) {
1459
+ var _a;
1460
+ return (__assign(__assign({}, acc), (_a = {}, _a[p.codename] = p.value, _a)));
1461
+ }, {}));
1462
+ setErrors({});
1463
+ };
1444
1464
  return {
1445
1465
  fields: fields,
1446
1466
  setField: setField,
1447
1467
  setFields: setFields,
1448
1468
  errors: errors,
1449
1469
  setErrors: setErrors,
1470
+ resetErrors: resetErrors,
1471
+ reset: reset,
1450
1472
  };
1451
1473
  };
1452
1474
 
1453
1475
  var Canvas = function (_a) {
1454
- var canvasRef = _a.canvasRef, canvasSize = _a.canvasSize, imageSize = _a.imageSize, initialData = _a.initialData;
1476
+ var canvasRef = _a.canvasRef, canvasSize = _a.canvasSize; _a.imageSize; var initialData = _a.initialData;
1455
1477
  var _b = useEditorContext(), metadata = _b.metadata, setMetadata = _b.setMetadata, addShapes = _b.addShapes, editorId = _b.editorId;
1456
1478
  var enableLogs = React.useContext(UiContext).enableLogs;
1457
- var _c = React.useState(false), initialized = _c[0], setInitialized = _c[1];
1479
+ // const [initialized, setInitialized] = useState(false)
1458
1480
  useTool(canvasRef.current);
1459
1481
  useDispatcherEvents(canvasRef.current);
1460
1482
  React.useEffect(function () {
1461
- if (canvasSize.width !== 0 && canvasSize.height !== 0 && !initialized) {
1483
+ console.log('EFFECT XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
1484
+ if (canvasSize.width !== 0 && canvasSize.height !== 0) {
1462
1485
  canvasRef.current = new xn("react-cam-roi-canvas-".concat(editorId));
1463
1486
  canvasRef.current.setDimensions({ width: canvasSize.width, height: canvasSize.height });
1464
- initCanvasData(canvasRef, imageSize, addShapes, metadata, setMetadata, initialData, enableLogs);
1465
- setInitialized(true);
1487
+ initCanvasData(canvasRef, canvasSize, addShapes, metadata, setMetadata, initialData, enableLogs);
1466
1488
  }
1467
1489
  return function () {
1468
1490
  var _a;
@@ -1534,7 +1556,7 @@ var RoleField = function (_a) {
1534
1556
  }
1535
1557
  });
1536
1558
  React.useEffect(function () {
1537
- if (required) {
1559
+ if (required && !value) {
1538
1560
  onChange(options[0]);
1539
1561
  }
1540
1562
  }, []); // eslint-disable-line react-hooks/exhaustive-deps
@@ -1569,11 +1591,11 @@ var ParameterField = function (_a) {
1569
1591
  var styles$4 = {"form":"ParametersModalForm-module_form__WXebJ","fieldset":"ParametersModalForm-module_fieldset__V-ywT","legend":"ParametersModalForm-module_legend__F6CPv","legend-light":"ParametersModalForm-module_legend-light__X9tWX","legend-dark":"ParametersModalForm-module_legend-dark__isTas"};
1570
1592
 
1571
1593
  var ParametersModalForm = function (_a) {
1572
- var title = _a.title, onClose = _a.onClose, parameters = _a.parameters, data = _a.data, onSubmit = _a.onSubmit, shapeType = _a.shapeType, shapeName = _a.shapeName, shapeRole = _a.shapeRole, noModal = _a.noModal, readOnly = _a.readOnly;
1594
+ var title = _a.title, onClose = _a.onClose, parameters = _a.parameters, rolesParameters = _a.rolesParameters, data = _a.data, onSubmit = _a.onSubmit, shapeType = _a.shapeType, shapeName = _a.shapeName, shapeRole = _a.shapeRole, noModal = _a.noModal, readOnly = _a.readOnly;
1573
1595
  var _b = React.useContext(UiContext), Modal = _b.Modal, TextField = _b.TextField, strings = _b.strings, themeMode = _b.themeMode, Typography = _b.Typography;
1574
1596
  var _c = React.useState(shapeName !== null && shapeName !== void 0 ? shapeName : ''), name = _c[0], setName = _c[1];
1575
1597
  var _d = React.useState(shapeRole !== null && shapeRole !== void 0 ? shapeRole : ''), role = _d[0], setRole = _d[1];
1576
- var _e = useParametersForm(data), fields = _e.fields, setField = _e.setField, errors = _e.errors, setErrors = _e.setErrors;
1598
+ var _e = useParametersForm(data), fields = _e.fields, setField = _e.setField, errors = _e.errors, setErrors = _e.setErrors, resetErrors = _e.resetErrors, reset = _e.reset;
1577
1599
  var readonlyFields = data.reduce(function (acc, p) {
1578
1600
  var _a;
1579
1601
  return (__assign(__assign({}, acc), (_a = {}, _a[p.codename] = p.value, _a)));
@@ -1584,12 +1606,25 @@ var ParametersModalForm = function (_a) {
1584
1606
  handleSubmit();
1585
1607
  }
1586
1608
  }, [fields]);
1609
+ var currentParameters = shapeType
1610
+ ? defaultTo([])(rolesParameters === null || rolesParameters === void 0 ? void 0 : rolesParameters[role])
1611
+ : defaultTo([])(parameters);
1612
+ // add a listener in order for general save to call validate
1613
+ React.useEffect(function () {
1614
+ var validate = function () {
1615
+ validateParametersForm(currentParameters, fields, setErrors, resetErrors);
1616
+ };
1617
+ Dispatcher.register('editor:save', validate);
1618
+ return function () {
1619
+ Dispatcher.unregister('editor:save', validate);
1620
+ };
1621
+ }, [currentParameters, fields, setErrors, resetErrors]);
1587
1622
  var handleSubmit = function () {
1588
1623
  if (shapeType && name === '') {
1589
1624
  setErrors({ name: strings.requiredField });
1590
1625
  }
1591
- else if (!noModal || validateParametersForm(parameters, fields, setErrors, strings)) {
1592
- var data_1 = __spreadArray([], parameters.map(function (p) { return ({ codename: p.codename, value: fields[p.codename] }); }), true);
1626
+ else if (noModal || validateParametersForm(currentParameters, fields, setErrors, resetErrors)) {
1627
+ var data_1 = __spreadArray([], currentParameters.map(function (p) { return ({ codename: p.codename, value: fields[p.codename] }); }), true);
1593
1628
  if (shapeType) {
1594
1629
  onSubmit(data_1, { name: name, role: role });
1595
1630
  }
@@ -1599,7 +1634,7 @@ var ParametersModalForm = function (_a) {
1599
1634
  }
1600
1635
  };
1601
1636
  // group parameters by fieldset
1602
- var groupedParameters = parameters.reduce(function (acc, p) {
1637
+ var groupedParameters = currentParameters.reduce(function (acc, p) {
1603
1638
  if (acc[p.fieldSet || '']) {
1604
1639
  acc[p.fieldSet || ''].push(p);
1605
1640
  }
@@ -1608,7 +1643,7 @@ var ParametersModalForm = function (_a) {
1608
1643
  }
1609
1644
  return acc;
1610
1645
  }, {});
1611
- var form = (jsxRuntime.jsxs("div", { className: css('form', styles$4, null), children: [shapeType && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(TextField, { required: true, label: strings.name, type: "text", value: name, onChange: compose(setName, defaultTo('')), error: !!errors.name, helperText: errors.name, readOnly: readOnly }), jsxRuntime.jsx(RoleField, { required: true, value: role, onChange: compose(setRole, defaultTo('')), error: !!errors.role, helperText: errors.role, shapeType: shapeType, readOnly: readOnly, disabled: readOnly })] })), Object.keys(groupedParameters)
1646
+ var form = (jsxRuntime.jsxs("div", { className: css('form', styles$4, null), children: [shapeType && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(TextField, { required: true, label: strings.name, type: "text", value: name, onChange: compose(setName, defaultTo('')), error: !!errors.name, helperText: errors.name, readOnly: readOnly }), jsxRuntime.jsx(RoleField, { required: true, value: role, onChange: compose(reset, setRole, defaultTo('')), error: !!errors.role, helperText: errors.role, shapeType: shapeType, readOnly: readOnly, disabled: readOnly })] })), Object.keys(groupedParameters)
1612
1647
  .sort()
1613
1648
  .map(function (fieldSet) { return (jsxRuntime.jsxs("div", { className: css('fieldset', styles$4, themeMode), children: [fieldSet && (jsxRuntime.jsx(Typography, { component: "div", className: css('legend', styles$4, themeMode), children: fieldSet })), groupedParameters[fieldSet].map(function (parameter) {
1614
1649
  switch (parameter.type) {
@@ -1616,7 +1651,9 @@ var ParametersModalForm = function (_a) {
1616
1651
  return (jsxRuntime.jsx(ParameterField, { value: String((readOnly ? readonlyFields : fields)[parameter.codename]), onChange: setField(parameter.codename), parameter: parameter, errors: errors, readOnly: readOnly }, parameter.codename));
1617
1652
  case 'int':
1618
1653
  case 'float':
1619
- return (jsxRuntime.jsx(ParameterField, { value: (readOnly ? readonlyFields : fields)[parameter.codename], onChange: setField(parameter.codename), parameter: parameter, errors: errors, readOnly: readOnly }, parameter.codename));
1654
+ return (jsxRuntime.jsx(ParameterField, { value: (readOnly ? readonlyFields : fields)[parameter.codename] === ''
1655
+ ? null
1656
+ : (readOnly ? readonlyFields : fields)[parameter.codename], onChange: setField(parameter.codename), parameter: parameter, errors: errors, readOnly: readOnly }, parameter.codename));
1620
1657
  case 'bool':
1621
1658
  return (jsxRuntime.jsx(ParameterField, { value: (readOnly ? readonlyFields : fields)[parameter.codename], onChange: setField(parameter.codename), parameter: parameter, errors: errors, readOnly: readOnly }, parameter.codename));
1622
1659
  default:
@@ -1629,16 +1666,16 @@ var ParametersModalForm = function (_a) {
1629
1666
  var styles$3 = {"shapes-table":"ShapesList-module_shapes-table__sx5Xp","shapes-table-light":"ShapesList-module_shapes-table-light__TbtKn","shapes-table-dark":"ShapesList-module_shapes-table-dark__siyhV","shapes-row-selected-light":"ShapesList-module_shapes-row-selected-light__-0gaE","shapes-row-selected-dark":"ShapesList-module_shapes-row-selected-dark__bGR3a","shapes-row-even-light":"ShapesList-module_shapes-row-even-light__2eUZX","shapes-row-even-dark":"ShapesList-module_shapes-row-even-dark__eyECv","shapes-row-odd-light":"ShapesList-module_shapes-row-odd-light__vZzPj","shapes-row-odd-dark":"ShapesList-module_shapes-row-odd-dark__TWGAu","shapesTableName":"ShapesList-module_shapesTableName__9Q6i1","shapesTableColor":"ShapesList-module_shapesTableColor__Iyd33"};
1630
1667
 
1631
1668
  var ShapesList = function () {
1632
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
1633
- var _l = React.useContext(UiContext), strings = _l.strings, Typography = _l.Typography, IconButton = _l.IconButton, DeleteIcon = _l.DeleteIcon, AnnotateIcon = _l.AnnotateIcon, CopyIcon = _l.CopyIcon, themeMode = _l.themeMode;
1634
- var _m = useEditorContext(), shapes = _m.shapes, removeShape = _m.removeShape, configuration = _m.configuration, metadata = _m.metadata, setMetadata = _m.setMetadata, addShape = _m.addShape, editorId = _m.editorId;
1635
- var _o = React.useState([]), selected = _o[0], setSelected = _o[1];
1636
- var _p = React.useState({
1669
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1670
+ var _j = React.useContext(UiContext), strings = _j.strings, Typography = _j.Typography, IconButton = _j.IconButton, DeleteIcon = _j.DeleteIcon, AnnotateIcon = _j.AnnotateIcon, CopyIcon = _j.CopyIcon, themeMode = _j.themeMode;
1671
+ var _k = useEditorContext(), shapes = _k.shapes, removeShape = _k.removeShape, configuration = _k.configuration, metadata = _k.metadata, setMetadata = _k.setMetadata, addShape = _k.addShape, editorId = _k.editorId;
1672
+ var _l = React.useState([]), selected = _l[0], setSelected = _l[1];
1673
+ var _m = React.useState({
1637
1674
  isOpen: false,
1638
1675
  shapeId: '',
1639
1676
  type: null,
1640
1677
  shape: null,
1641
- }), form = _p[0], setForm = _p[1];
1678
+ }), form = _m[0], setForm = _m[1];
1642
1679
  // open metadata form immediately after drawing the shape
1643
1680
  React.useEffect(function () {
1644
1681
  var openForm = function (_, _a) {
@@ -1695,7 +1732,12 @@ var ShapesList = function () {
1695
1732
  : idx % 2 === 0
1696
1733
  ? css('shapes-row-even', styles$3, themeMode)
1697
1734
  : css('shapes-row-odd', styles$3, themeMode), children: [jsxRuntime.jsx("td", { children: jsxRuntime.jsxs("div", { className: styles$3.shapesTableName, children: [jsxRuntime.jsx("div", { className: styles$3.shapesTableColor, style: { backgroundColor: shapes[id].shape.stroke } }), jsxRuntime.jsx(Typography, { children: m === null || m === void 0 ? void 0 : m.name })] }) }), jsxRuntime.jsx("td", { children: jsxRuntime.jsx(Typography, { children: (_a = configuration.rois.find(function (r) { return r.role === (m === null || m === void 0 ? void 0 : m.role); })) === null || _a === void 0 ? void 0 : _a.label }) }), jsxRuntime.jsx("td", { children: jsxRuntime.jsx(Typography, { children: strings[shapes[id].type] }) }), jsxRuntime.jsxs("td", { children: [jsxRuntime.jsx(IconButton, { onClick: handleCopyShape(id), children: jsxRuntime.jsx(CopyIcon, { color: iconColor }) }), jsxRuntime.jsx(IconButton, { onClick: handleEditShapeMetadata(id), children: jsxRuntime.jsx(AnnotateIcon, { color: iconColor }) }), jsxRuntime.jsx(IconButton, { onClick: handleRemoveShape(id), children: jsxRuntime.jsx(DeleteIcon, { color: iconColor }) })] })] }, id));
1698
- }) })] }), form.isOpen && (jsxRuntime.jsx(ParametersModalForm, { shapeType: form.type || shapes[form.shapeId].type, shapeName: (_b = (_a = metadata.rois.find(function (roi) { return roi.id === form.shapeId; })) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : '', shapeRole: (_d = (_c = metadata.rois.find(function (roi) { return roi.id === form.shapeId; })) === null || _c === void 0 ? void 0 : _c.role) !== null && _d !== void 0 ? _d : '', shapeId: form.shapeId, parameters: (_f = (_e = configuration.rois.find(function (roi) { return roi.type === (form.type || shapes[form.shapeId].type); })) === null || _e === void 0 ? void 0 : _e.parameters) !== null && _f !== void 0 ? _f : [], data: (_k = (_h = (_g = metadata.rois.find(function (roi) { return roi.id === form.shapeId; })) === null || _g === void 0 ? void 0 : _g.parameters) !== null && _h !== void 0 ? _h : (_j = configuration.rois.find(function (roi) { return roi.type === (form.type || shapes[form.shapeId].type); })) === null || _j === void 0 ? void 0 : _j.parameters) !== null && _k !== void 0 ? _k : [], title: strings.shapeParametersMetadata, onClose: handleCloseMetadataForm, onSubmit: handleSubmitMetadata(form.shapeId) }))] }));
1735
+ }) })] }), form.isOpen && (jsxRuntime.jsx(ParametersModalForm, { shapeType: form.type || shapes[form.shapeId].type, shapeName: (_b = (_a = metadata.rois.find(function (roi) { return roi.id === form.shapeId; })) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : '', shapeRole: (_d = (_c = metadata.rois.find(function (roi) { return roi.id === form.shapeId; })) === null || _c === void 0 ? void 0 : _c.role) !== null && _d !== void 0 ? _d : '', shapeId: form.shapeId, rolesParameters: configuration.rois
1736
+ .filter(function (roi) { return roi.type === (form.type || shapes[form.shapeId].type); })
1737
+ .reduce(function (acc, p) {
1738
+ var _a;
1739
+ return (__assign(__assign({}, acc), (_a = {}, _a[p.role] = p.parameters, _a)));
1740
+ }, {}), data: (_h = (_f = (_e = metadata.rois.find(function (roi) { return roi.id === form.shapeId; })) === null || _e === void 0 ? void 0 : _e.parameters) !== null && _f !== void 0 ? _f : (_g = configuration.rois.find(function (roi) { return roi.type === (form.type || shapes[form.shapeId].type); })) === null || _g === void 0 ? void 0 : _g.parameters) !== null && _h !== void 0 ? _h : [], title: strings.shapeParametersMetadata, onClose: handleCloseMetadataForm, onSubmit: handleSubmitMetadata(form.shapeId) }))] }));
1699
1741
  };
1700
1742
 
1701
1743
  var FullRoiIcon = function (_a) {
@@ -1834,12 +1876,12 @@ var RoiEditor = function (_a) {
1834
1876
  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 : '',
1835
1877
  type: shapes[shapeId].type,
1836
1878
  id: shapeId,
1837
- shape: fabricShapeToOutputShape(shapes[shapeId].shape, shapes[shapeId].type, imageSize),
1838
- coords: fabricShapeToOutputCoords(shapes[shapeId].shape, shapes[shapeId].shape.type, imageSize),
1879
+ shape: fabricShapeToOutputShape(shapes[shapeId].shape, shapes[shapeId].type, canvasSize),
1880
+ coords: fabricShapeToOutputCoords(shapes[shapeId].shape, shapes[shapeId].shape.type, canvasSize),
1839
1881
  });
1840
1882
  }),
1841
1883
  };
1842
- }, [imageSize.width, imageSize.height, canvasRef]);
1884
+ }, [canvasSize.width, canvasSize.height, canvasRef]);
1843
1885
  React.useEffect(function () {
1844
1886
  // do not run on first update
1845
1887
  if (firstUpdate.current < 3) {
@@ -1852,6 +1894,7 @@ var RoiEditor = function (_a) {
1852
1894
  }
1853
1895
  }, [metadata, shapes, onUpdate, prepareOutput]);
1854
1896
  var handleSubmit = React.useCallback(function () {
1897
+ Dispatcher.emit('editor:save');
1855
1898
  var _a = validate$1(configuration, presetName, shapes, metadata, strings), isValid = _a[0], errors = _a[1];
1856
1899
  if (isValid) {
1857
1900
  onSubmit(prepareOutput(metadata, shapes, presetName, presetDescription));
@@ -1867,6 +1910,7 @@ var RoiEditor = function (_a) {
1867
1910
  log('info', enableLogs, 'react-cam-roi', 'canvas size', canvasSize);
1868
1911
  log('info', enableLogs, 'react-cam-roi', 'image size', imageSize);
1869
1912
  log('info', enableLogs, 'react-cam-roi', 'metadata', metadata);
1913
+ log('info', enableLogs, 'react-cam-roi', 'shapes', shapes);
1870
1914
  if (!isReady) {
1871
1915
  return jsxRuntime.jsx(Loader, {});
1872
1916
  }