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