@abidibo/react-cam-roi 0.0.7 → 0.0.10

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.
Files changed (72) hide show
  1. package/README.md +588 -29
  2. package/dist/Components/BoolField/BoolField.module.css +60 -0
  3. package/dist/Components/BoolField/index.d.ts +5 -0
  4. package/dist/Components/BoolField/index.js +13 -0
  5. package/dist/Components/Button/Button.module.css +27 -0
  6. package/dist/Components/Button/index.d.ts +8 -0
  7. package/dist/Components/Button/index.js +15 -0
  8. package/dist/Components/EnumField/EnumField.module.css +61 -0
  9. package/dist/Components/EnumField/index.d.ts +10 -0
  10. package/dist/Components/EnumField/index.js +16 -0
  11. package/dist/Components/IconButton/IconButton.module.css +8 -3
  12. package/dist/Components/IconButton/index.d.ts +1 -0
  13. package/dist/Components/IconButton/index.js +3 -3
  14. package/dist/Components/Modal/Modal.module.css +92 -0
  15. package/dist/Components/Modal/index.d.ts +10 -0
  16. package/dist/Components/Modal/index.js +16 -0
  17. package/dist/Components/NumberField/NumberField.module.css +60 -0
  18. package/dist/Components/NumberField/index.d.ts +3 -0
  19. package/dist/Components/NumberField/index.js +13 -0
  20. package/dist/Components/RoiEditor/Canvas.d.ts +2 -0
  21. package/dist/Components/RoiEditor/Canvas.js +21 -11
  22. package/dist/Components/RoiEditor/Hooks.d.ts +16 -4
  23. package/dist/Components/RoiEditor/Hooks.js +148 -21
  24. package/dist/Components/RoiEditor/ParameterField.d.ts +9 -0
  25. package/dist/Components/RoiEditor/ParameterField.js +27 -0
  26. package/dist/Components/RoiEditor/ParametersModalForm/ParametersModalForm.module.css +5 -0
  27. package/dist/Components/RoiEditor/ParametersModalForm/index.d.ts +10 -0
  28. package/dist/Components/RoiEditor/ParametersModalForm/index.js +31 -0
  29. package/dist/Components/RoiEditor/Polygon.d.ts +3 -2
  30. package/dist/Components/RoiEditor/Polygon.js +18 -0
  31. package/dist/Components/RoiEditor/Polyline.d.ts +12 -1
  32. package/dist/Components/RoiEditor/Polyline.js +18 -0
  33. package/dist/Components/RoiEditor/Rectangle.d.ts +17 -1
  34. package/dist/Components/RoiEditor/Rectangle.js +23 -1
  35. package/dist/Components/RoiEditor/ShapesList.d.ts +2 -0
  36. package/dist/Components/RoiEditor/ShapesList.js +47 -0
  37. package/dist/Components/RoiEditor/ShapesList.module.css +36 -0
  38. package/dist/Components/RoiEditor/Toolbar.js +20 -6
  39. package/dist/Components/RoiEditor/Toolbar.module.css +40 -0
  40. package/dist/Components/RoiEditor/Types.d.ts +97 -1
  41. package/dist/Components/RoiEditor/Types.js +15 -1
  42. package/dist/Components/RoiEditor/Utils.d.ts +22 -0
  43. package/dist/Components/RoiEditor/Utils.js +143 -0
  44. package/dist/Components/RoiEditor/index.d.ts +4 -0
  45. package/dist/Components/RoiEditor/index.js +44 -7
  46. package/dist/Components/TextField/TextField.module.css +61 -0
  47. package/dist/Components/TextField/index.d.ts +6 -0
  48. package/dist/Components/TextField/index.js +13 -0
  49. package/dist/Components/Typography/index.d.ts +4 -0
  50. package/dist/Components/Typography/index.js +3 -2
  51. package/dist/Icons/AnnotateIcon.d.ts +6 -0
  52. package/dist/Icons/AnnotateIcon.js +5 -0
  53. package/dist/Icons/CloseIcon.d.ts +6 -0
  54. package/dist/Icons/CloseIcon.js +5 -0
  55. package/dist/Icons/CopyIcon.d.ts +6 -0
  56. package/dist/Icons/CopyIcon.js +5 -0
  57. package/dist/Icons/SaveIcon.d.ts +6 -0
  58. package/dist/Icons/SaveIcon.js +5 -0
  59. package/dist/Providers/EditorProvider.d.ts +12 -2
  60. package/dist/Providers/EditorProvider.js +16 -2
  61. package/dist/Providers/UiProvider.d.ts +44 -2
  62. package/dist/Providers/UiProvider.js +55 -2
  63. package/dist/Types.d.ts +10 -0
  64. package/dist/Types.js +1 -0
  65. package/dist/Utils/index.d.ts +1 -1
  66. package/dist/Utils/index.js +1 -1
  67. package/dist/index.d.ts +2 -1
  68. package/dist/index.js +2 -1
  69. package/package.json +13 -4
  70. package/dist/Components/RoiEditor/Metadata.d.ts +0 -2
  71. package/dist/Components/RoiEditor/Metadata.js +0 -31
  72. package/dist/Components/RoiEditor/Metadata.module.css +0 -34
@@ -1,3 +1,15 @@
1
+ .toolbar-info {
2
+ padding: .5rem;
3
+ }
4
+ .toolbar-info-light {
5
+ background-color: #ddd;;
6
+ color: #000;
7
+ }
8
+ .toolbar-info-dark {
9
+ background-color: #222;
10
+ color: #fff;
11
+ }
12
+
1
13
  .toolbar {
2
14
  align-items: center;
3
15
  display: flex;
@@ -11,3 +23,31 @@
11
23
  .toolbar-dark {
12
24
  background-color: #333;
13
25
  }
26
+
27
+ .toolbar-helper {
28
+ padding: .5rem;
29
+ }
30
+
31
+ .toolbar-helper-light {
32
+ background-color: #f7f7f7;;
33
+ color: #000;
34
+ }
35
+
36
+ .toolbar-helper-dark {
37
+ background-color: #222;
38
+ color: #fff;
39
+ }
40
+
41
+ .toolbar-spacer {
42
+ height: 20px;
43
+ margin: 0 .5rem;
44
+ width: 1px;
45
+ }
46
+
47
+ .toolbar-spacer-light {
48
+ background-color: #ccc;
49
+ }
50
+
51
+ .toolbar-spacer-dark {
52
+ background-color: #555;
53
+ }
@@ -3,7 +3,7 @@ export declare const enum ToolEnum {
3
3
  Pointer = "pointer",
4
4
  Polyline = "polyline",
5
5
  Polygon = "polygon",
6
- Rectangle = "rectangle"
6
+ Rectangle = "rect"
7
7
  }
8
8
  export type ShapeType = ToolEnum.Polyline | ToolEnum.Polygon | ToolEnum.Rectangle;
9
9
  export type Shape = (fabric.Rect | fabric.Polygon | fabric.Polyline) & {
@@ -17,3 +17,99 @@ export type FabricEvent = fabric.TPointerEventInfo<fabric.TPointerEvent>;
17
17
  export type FabricSelectionEvent = Partial<fabric.TEvent> & {
18
18
  selected: fabric.Object[];
19
19
  };
20
+ export type IAddShape = (id: string, type: ShapeType, shape: Shape) => void;
21
+ export declare enum DataTypeEnum {
22
+ Integer = "int",
23
+ Float = "float",
24
+ String = "string",
25
+ Boolean = "bool"
26
+ }
27
+ export declare enum OperatorEnum {
28
+ Lt = "lt",
29
+ Lte = "lte",
30
+ Gt = "gt",
31
+ Gte = "gte",
32
+ Eq = "eq"
33
+ }
34
+ export type ConfigurationParameter = {
35
+ codename: string;
36
+ label: string;
37
+ description: string;
38
+ unit: string;
39
+ type: DataTypeEnum;
40
+ options: {
41
+ value: number | string;
42
+ label: string;
43
+ }[];
44
+ multiple?: boolean;
45
+ required: boolean;
46
+ value: number | string | boolean | string[] | number[] | null;
47
+ };
48
+ export type RoiConfiguration = {
49
+ role: string;
50
+ type: Omit<ShapeType, 'pointer'>;
51
+ multiplicity: {
52
+ operator: OperatorEnum;
53
+ threshold: number;
54
+ };
55
+ parameters: ConfigurationParameter[];
56
+ };
57
+ export type Configuration = {
58
+ parameters: ConfigurationParameter[];
59
+ rois: RoiConfiguration[];
60
+ options?: {
61
+ hideForbiddenTools?: boolean;
62
+ description?: string;
63
+ };
64
+ };
65
+ export interface INotify {
66
+ info: (message: string) => void;
67
+ warn: (message: string) => void;
68
+ error: (message: string) => void;
69
+ success: (message: string) => void;
70
+ }
71
+ export type Metadata = {
72
+ parameters: OutputParameter[];
73
+ rois: {
74
+ id: string;
75
+ parameters: OutputParameter[];
76
+ }[];
77
+ };
78
+ export type OutputShapeRect = {
79
+ top: number;
80
+ left: number;
81
+ width: number;
82
+ height: number;
83
+ color: string;
84
+ };
85
+ export type OutputShapePolyline = {
86
+ points: {
87
+ x: number;
88
+ y: number;
89
+ }[];
90
+ top: number;
91
+ left: number;
92
+ color: string;
93
+ };
94
+ export type OutputShapePolygon = {
95
+ points: {
96
+ x: number;
97
+ y: number;
98
+ }[];
99
+ top: number;
100
+ left: number;
101
+ color: string;
102
+ };
103
+ export interface OutputParameter {
104
+ codename: string;
105
+ value: number | string | boolean | string[] | number[] | null;
106
+ }
107
+ export interface OutputRoi {
108
+ parameters: OutputParameter[];
109
+ type: ShapeType;
110
+ shape: OutputShapeRect | OutputShapePolyline | OutputShapePolygon;
111
+ }
112
+ export interface Output {
113
+ parameters: OutputParameter[];
114
+ rois: OutputRoi[];
115
+ }
@@ -1 +1,15 @@
1
- export {};
1
+ export var DataTypeEnum;
2
+ (function (DataTypeEnum) {
3
+ DataTypeEnum["Integer"] = "int";
4
+ DataTypeEnum["Float"] = "float";
5
+ DataTypeEnum["String"] = "string";
6
+ DataTypeEnum["Boolean"] = "bool";
7
+ })(DataTypeEnum || (DataTypeEnum = {}));
8
+ export var OperatorEnum;
9
+ (function (OperatorEnum) {
10
+ OperatorEnum["Lt"] = "lt";
11
+ OperatorEnum["Lte"] = "lte";
12
+ OperatorEnum["Gt"] = "gt";
13
+ OperatorEnum["Gte"] = "gte";
14
+ OperatorEnum["Eq"] = "eq";
15
+ })(OperatorEnum || (OperatorEnum = {}));
@@ -0,0 +1,22 @@
1
+ import { Configuration, ConfigurationParameter, INotify, Metadata, Shape, Shapes, ShapeType, ToolEnum } from './Types';
2
+ export declare const notify: INotify;
3
+ export declare const enableRois: (configuration: Configuration) => boolean;
4
+ export declare const enableMainMetadata: (configuration: Configuration) => boolean;
5
+ export declare const canDrawShape: (configuration: Configuration, shapeType: Omit<ToolEnum, ToolEnum.Pointer>, shapes: Shapes, notify: INotify, message: string) => boolean;
6
+ export declare const validateParametersForm: (parameters: ConfigurationParameter[], fields: Record<string, unknown>, setErrors: (errors: Record<string, string>) => void) => boolean;
7
+ export declare const validate: (configuration: Configuration, shapes: Shapes, metadata: Metadata, strings: Record<string, string>) => [boolean, string[]];
8
+ export declare const fabricShapeToOutputShape: (shape: Shape, type: ShapeType) => {
9
+ top: number;
10
+ left: number;
11
+ width: number;
12
+ height: number;
13
+ color: string;
14
+ points?: undefined;
15
+ } | {
16
+ points: any;
17
+ top: number;
18
+ left: number;
19
+ color: string;
20
+ width?: undefined;
21
+ height?: undefined;
22
+ };
@@ -0,0 +1,143 @@
1
+ import { OperatorEnum } from './Types';
2
+ export const notify = {
3
+ info: (message) => alert(`Info: ${message}`),
4
+ warn: (message) => alert(`Warning: ${message}`),
5
+ error: (message) => alert(`Error: ${message}`),
6
+ success: (message) => alert(`Success: ${message}`),
7
+ };
8
+ export const enableRois = (configuration) => {
9
+ return configuration.rois.length > 0;
10
+ };
11
+ export const enableMainMetadata = (configuration) => {
12
+ return configuration.parameters.length > 0;
13
+ };
14
+ export const canDrawShape = (configuration, shapeType, shapes, notify, message) => {
15
+ const rule = configuration.rois.find((roi) => roi.type === shapeType);
16
+ // no rule
17
+ if (!rule || !rule.multiplicity || Object.keys(rule.multiplicity).length === 0) {
18
+ return true;
19
+ }
20
+ const currentShapeCount = Object.values(shapes).filter((s) => s.type === shapeType).length;
21
+ let res = true;
22
+ switch (rule.multiplicity.operator) {
23
+ case OperatorEnum.Eq:
24
+ case OperatorEnum.Lte:
25
+ res = currentShapeCount + 1 <= rule.multiplicity.threshold;
26
+ break;
27
+ case OperatorEnum.Lt:
28
+ res = currentShapeCount + 1 < rule.multiplicity.threshold;
29
+ break;
30
+ default:
31
+ return true;
32
+ }
33
+ if (!res && notify) {
34
+ notify.warn(message);
35
+ }
36
+ return res;
37
+ };
38
+ export const validateParametersForm = (parameters, fields, setErrors) => {
39
+ const err = {};
40
+ parameters.forEach((p) => {
41
+ if (p.required && isEmpty(fields[p.codename])) {
42
+ err[p.codename] = 'requiredField';
43
+ }
44
+ });
45
+ if (Object.keys(err).length > 0) {
46
+ setErrors(err);
47
+ return false;
48
+ }
49
+ return true;
50
+ };
51
+ const isEmpty = (v) => {
52
+ if (typeof v === 'string') {
53
+ return v.length === 0;
54
+ }
55
+ if (Array.isArray(v)) {
56
+ return v.length === 0;
57
+ }
58
+ return v === null || v === undefined;
59
+ };
60
+ export const validate = (configuration, shapes, metadata, strings) => {
61
+ const errors = [];
62
+ // check main parameters
63
+ if (configuration.parameters.length) {
64
+ if (metadata.parameters.find((p) => { var _a; return ((_a = configuration.parameters.find((p2) => p2.codename === p.codename)) === null || _a === void 0 ? void 0 : _a.required) && isEmpty(p.value); })) {
65
+ errors.push(strings.missingRequiredValuesInMainParameters);
66
+ }
67
+ }
68
+ // check rois number
69
+ configuration.rois.forEach((roi) => {
70
+ // check multiplicity
71
+ if (roi.multiplicity) {
72
+ switch (roi.multiplicity.operator) {
73
+ case OperatorEnum.Eq:
74
+ if (Object.values(shapes).filter((s) => s.type === roi.type).length !== roi.multiplicity.threshold) {
75
+ errors.push(strings.shapesOfTypeShouldBeEqualToThreshold
76
+ .replace('{type}', String(roi.type))
77
+ .replace('{threshold}', roi.multiplicity.threshold.toString()));
78
+ }
79
+ break;
80
+ case OperatorEnum.Lt:
81
+ if (Object.values(shapes).filter((s) => s.type === roi.type).length >= roi.multiplicity.threshold) {
82
+ errors.push(strings.shapesOfTypeShouldBeLessThanThreshold
83
+ .replace('{type}', String(roi.type))
84
+ .replace('{threshold}', roi.multiplicity.threshold.toString()));
85
+ }
86
+ break;
87
+ case OperatorEnum.Lte:
88
+ if (Object.values(shapes).filter((s) => s.type === roi.type).length > roi.multiplicity.threshold) {
89
+ errors.push(strings.shapesOfTypeShouldBeLessThanOrEqualToThreshold
90
+ .replace('{type}', String(roi.type))
91
+ .replace('{threshold}', roi.multiplicity.threshold.toString()));
92
+ }
93
+ break;
94
+ case OperatorEnum.Gt:
95
+ if (Object.values(shapes).filter((s) => s.type === roi.type).length <= roi.multiplicity.threshold) {
96
+ errors.push(strings.shapesOfTypeShouldBeGreaterThanThreshold
97
+ .replace('{type}', String(roi.type))
98
+ .replace('{threshold}', roi.multiplicity.threshold.toString()));
99
+ }
100
+ break;
101
+ case OperatorEnum.Gte:
102
+ if (Object.values(shapes).filter((s) => s.type === roi.type).length < roi.multiplicity.threshold) {
103
+ errors.push(strings.shapesOfTypeShouldBeGreaterThanOrEqualToThreshold
104
+ .replace('{type}', String(roi.type))
105
+ .replace('{threshold}', roi.multiplicity.threshold.toString()));
106
+ }
107
+ }
108
+ }
109
+ });
110
+ // check rois metadata
111
+ Object.keys(shapes).forEach(shapeId => {
112
+ var _a, _b;
113
+ const type = shapes[shapeId].type;
114
+ const confParameters = (_b = (_a = configuration.rois.find((r) => r.type === type)) === null || _a === void 0 ? void 0 : _a.parameters) !== null && _b !== void 0 ? _b : [];
115
+ confParameters.forEach((p) => {
116
+ var _a, _b;
117
+ if (p.required && isEmpty((_b = (_a = metadata.rois.find((r) => r.id === shapeId)) === null || _a === void 0 ? void 0 : _a.parameters.find((p) => p.codename === p.codename)) === null || _b === void 0 ? void 0 : _b.value)) {
118
+ errors.push(strings.missingRequiredValuesInShapeParameters.replace('{id}', shapeId));
119
+ }
120
+ });
121
+ });
122
+ return [errors.length === 0, errors];
123
+ };
124
+ export const fabricShapeToOutputShape = (shape, type) => {
125
+ switch (type) {
126
+ case "rect" /* ToolEnum.Rectangle */:
127
+ return {
128
+ top: shape.top,
129
+ left: shape.left,
130
+ width: shape.width,
131
+ height: shape.height,
132
+ color: shape.stroke
133
+ };
134
+ case "polygon" /* ToolEnum.Polygon */:
135
+ case "polyline" /* ToolEnum.Polyline */:
136
+ return {
137
+ points: shape.get('points'),
138
+ top: shape.top,
139
+ left: shape.left,
140
+ color: shape.stroke
141
+ };
142
+ }
143
+ };
@@ -1,5 +1,9 @@
1
+ import { Configuration, Output } from './Types';
1
2
  export type RoiEditorProps = {
2
3
  imageUrl: string;
4
+ configuration: Configuration;
5
+ onSubmit: (data: Output) => void;
6
+ initialData?: Output;
3
7
  };
4
8
  declare const RoiEditor: React.FC<RoiEditorProps>;
5
9
  export default RoiEditor;
@@ -6,32 +6,69 @@ import { css, log } from '../../Utils';
6
6
  import { Loader } from '../Loader';
7
7
  import Canvas from './Canvas';
8
8
  import { useCanvasSize } from './Hooks';
9
- import Metadata from './Metadata';
10
9
  import styles from './RoiEditor.module.css';
10
+ import ShapesList from './ShapesList';
11
11
  import Toolbar from './Toolbar';
12
- // https://medium.com/@na.mazaheri/dynamically-drawing-shapes-on-canvas-with-fabric-js-in-react-js-8b9c42791903
12
+ import { fabricShapeToOutputShape, validate } from './Utils';
13
13
  // https://github.com/n-mazaheri/image-editor
14
- const RoiEditor = ({ imageUrl }) => {
15
- const { themeMode, enableLogs, pickerColors } = useContext(UiContext);
14
+ const RoiEditor = ({ imageUrl, configuration, onSubmit, initialData }) => {
15
+ var _a, _b, _c;
16
+ const { themeMode, enableLogs, pickerColors, strings, notify } = useContext(UiContext);
16
17
  const { imageSize, canvasSize, wrapperRef, isReady } = useCanvasSize(imageUrl);
17
18
  const [activeTool, setActiveTool] = useState("pointer" /* ToolEnum.Pointer */);
18
19
  const [activeColor, setActiveColor] = useState(pickerColors[0]);
20
+ const [metadata, setMetadata] = useState({
21
+ parameters: [
22
+ ...((_a = configuration.parameters.map((p) => {
23
+ const initial = initialData === null || initialData === void 0 ? void 0 : initialData.parameters.find((p) => p.codename === p.codename);
24
+ return {
25
+ codename: p.codename,
26
+ value: initial ? initial.value : p.value,
27
+ };
28
+ })) !== null && _a !== void 0 ? _a : []),
29
+ ],
30
+ rois: [],
31
+ });
19
32
  const [shapes, setShapes] = useState({});
20
33
  const addShape = useCallback((id, type, shape) => setShapes(Object.assign(Object.assign({}, shapes), { [id]: { type, shape } })), [shapes]);
34
+ const addShapes = useCallback((s) => setShapes(Object.assign(Object.assign({}, shapes), s.reduce((r, s) => (Object.assign(Object.assign({}, r), { [s.id]: s })), {}))), [shapes]);
21
35
  const removeShape = useCallback((id) => {
22
36
  const newShapes = Object.assign({}, shapes);
23
37
  delete newShapes[id];
24
38
  setShapes(newShapes);
25
- }, [shapes]);
39
+ setMetadata(Object.assign(Object.assign({}, metadata), { rois: metadata.rois.filter((r) => r.id !== id) }));
40
+ }, [shapes, metadata]);
41
+ const handleSubmit = useCallback(() => {
42
+ var _a, _b;
43
+ const [isValid, errors] = validate(configuration, shapes, metadata, strings);
44
+ if (isValid) {
45
+ onSubmit({
46
+ parameters: (_b = (_a = metadata.parameters) === null || _a === void 0 ? void 0 : _a.map((p) => ({ codename: p.codename, value: p.value }))) !== null && _b !== void 0 ? _b : [],
47
+ rois: Object.keys(shapes).map((shapeId) => {
48
+ var _a, _b, _c;
49
+ return ({
50
+ parameters: (_c = (_b = (_a = metadata.rois
51
+ .find((r) => r.id === shapeId)) === null || _a === void 0 ? void 0 : _a.parameters) === null || _b === void 0 ? void 0 : _b.map((p) => ({ codename: p.codename, value: p.value }))) !== null && _c !== void 0 ? _c : [],
52
+ type: shapes[shapeId].type,
53
+ shape: fabricShapeToOutputShape(shapes[shapeId].shape, shapes[shapeId].shape.type),
54
+ });
55
+ }),
56
+ });
57
+ }
58
+ else {
59
+ notify.error(strings.invalidSubmission + '\n' + errors.map((e) => `- ${e}`).join('\n'));
60
+ }
61
+ }, [onSubmit, configuration, shapes, metadata, strings, notify]);
26
62
  log('info', enableLogs, 'react-cam-roi', 'active tool', activeTool);
27
63
  log('info', enableLogs, 'react-cam-roi', 'canvas size', canvasSize);
64
+ log('info', enableLogs, 'react-cam-roi', 'metadata', metadata);
28
65
  if (!isReady) {
29
66
  return _jsx(Loader, {});
30
67
  }
31
- return (_jsx(EditorProvider, { activeTool: activeTool, setActiveTool: setActiveTool, activeColor: activeColor, setActiveColor: setActiveColor, shapes: shapes, addShape: addShape, removeShape: removeShape, children: _jsxs("div", { style: { maxWidth: '100%', width: `${imageSize.width}px` }, ref: wrapperRef, children: [_jsx(Toolbar, {}), _jsx("div", { className: css('canvasWrapper', styles, themeMode), style: {
68
+ return (_jsx(EditorProvider, { hideForbiddenTools: (_c = (_b = configuration.options) === null || _b === void 0 ? void 0 : _b.hideForbiddenTools) !== null && _c !== void 0 ? _c : false, activeTool: activeTool, setActiveTool: setActiveTool, activeColor: activeColor, setActiveColor: setActiveColor, shapes: shapes, addShape: addShape, addShapes: addShapes, removeShape: removeShape, configuration: configuration, metadata: metadata, setMetadata: setMetadata, onSubmit: handleSubmit, children: _jsxs("div", { style: { maxWidth: '100%', width: `${imageSize.width}px` }, ref: wrapperRef, children: [_jsx(Toolbar, {}), _jsx("div", { className: css('canvasWrapper', styles, themeMode), style: {
32
69
  width: `${canvasSize.width}px`,
33
70
  height: `${canvasSize.height}px`,
34
71
  backgroundImage: `url(${imageUrl})`,
35
- }, children: _jsx(Canvas, { canvasSize: canvasSize }) }), _jsx(Metadata, {})] }) }));
72
+ }, children: _jsx(Canvas, { canvasSize: canvasSize, initialData: initialData }) }), _jsx(ShapesList, {})] }) }));
36
73
  };
37
74
  export default RoiEditor;
@@ -0,0 +1,61 @@
1
+ /*
2
+ .text-field-wrapper {
3
+ margin-bottom: 2rem;
4
+ }
5
+ .text-field-wrapper-light {
6
+ }
7
+ .text-field-wrapper-dark {
8
+ }
9
+ */
10
+
11
+ .text-field {
12
+ border-radius: 0.25rem;
13
+ box-sizing: border-box;
14
+ padding: 0.5rem;
15
+ width: 100%;
16
+ }
17
+ .text-field:focus-visible {
18
+ outline: none;
19
+ border: 1px solid #1976d2;
20
+ }
21
+ .text-field-light {
22
+ background-color: #fff;
23
+ color: #333;
24
+ border: 1px solid #ccc;
25
+ }
26
+ .text-field-dark {
27
+ background-color: #333;
28
+ border: 1px solid #666;
29
+ color: #fff;
30
+ }
31
+ .text-field-error {
32
+ border: 1px solid #d32f2f;
33
+ }
34
+ .text-field-label {
35
+ font-weight: bold;
36
+ display: block;
37
+ margin: 0 0 1rem 0;
38
+ }
39
+ /*
40
+ .text-fiel-label-light {
41
+ }
42
+ .text-field-label-dark {
43
+ }
44
+ */
45
+ .text-field-label-error {
46
+ color: #d32f2f;
47
+ }
48
+ .text-field-helper-text {
49
+ font-style: italic;
50
+ font-size: 0.9rem;
51
+ margin-top: 0.5rem;
52
+ }
53
+ /*
54
+ .text-field-helper-text-light {
55
+ }
56
+ .text-field-helper-text-dark {
57
+ }
58
+ */
59
+ .text-field-helper-text-error {
60
+ color: #d32f2f;
61
+ }
@@ -0,0 +1,6 @@
1
+ import { FieldProps } from '../../Types';
2
+ export interface TextFieldProps extends FieldProps<string> {
3
+ type?: 'text' | 'email' | 'password';
4
+ }
5
+ declare const TextField: React.FC<TextFieldProps>;
6
+ export default TextField;
@@ -0,0 +1,13 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useContext } from 'react';
3
+ import { UiContext } from '../../Providers/UiProvider';
4
+ import { css } from '../../Utils';
5
+ import styles from './TextField.module.css';
6
+ const TextField = ({ onChange, type = 'text', value, label, helperText, error, required = false, readOnly = false, disabled = false, }) => {
7
+ const { themeMode, Typography } = useContext(UiContext);
8
+ const handleChange = (e) => {
9
+ onChange(e.target.value);
10
+ };
11
+ return (_jsxs("div", { className: css('text-field-wrapper', styles, themeMode), children: [_jsx("label", { className: `${css('text-field-label', styles, themeMode)} ${error ? css('text-field-label-error', styles, null) : ''}`, children: _jsxs(Typography, { children: [label, required && ' *'] }) }), _jsx("input", { type: type, className: `${css('text-field', styles, themeMode)} ${error ? css('text-field-error', styles, null) : ''}`, onChange: handleChange, value: value, readOnly: readOnly, disabled: disabled }), helperText && (_jsx(Typography, { component: 'div', className: `${css('text-field-helper-text', styles, themeMode)} ${error ? css('text-field-helper-text-error', styles, null) : ''}`, children: helperText }))] }));
12
+ };
13
+ export default TextField;
@@ -1,5 +1,9 @@
1
1
  export type TypographyProps = {
2
2
  children?: React.ReactNode;
3
+ className?: string;
4
+ variant?: any;
5
+ component?: any;
6
+ style?: React.CSSProperties;
3
7
  };
4
8
  declare const Typography: React.FC<TypographyProps>;
5
9
  export default Typography;
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- const Typography = ({ children }) => {
3
- return _jsx("span", { children: children });
2
+ const Typography = ({ children, style = {}, className = '', component = 'span' }) => {
3
+ const Tag = component;
4
+ return _jsx(Tag, { className: className, style: style, children: children });
4
5
  };
5
6
  export default Typography;
@@ -0,0 +1,6 @@
1
+ type AnnotateIconProps = {
2
+ color?: string;
3
+ style?: React.CSSProperties;
4
+ };
5
+ declare const AnnotateIcon: React.FC<AnnotateIconProps>;
6
+ export default AnnotateIcon;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ const AnnotateIcon = ({ color = 'black', style = {} }) => {
3
+ return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", style: style, children: _jsx("path", { fill: color, d: "M280-280h84l240-238-86-86-238 238v86Zm352-266 42-44q6-6 6-14t-6-14l-56-56q-6-6-14-6t-14 6l-44 42 86 86ZM200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h168q13-36 43.5-58t68.5-22q38 0 68.5 22t43.5 58h168q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm280-590q13 0 21.5-8.5T510-820q0-13-8.5-21.5T480-850q-13 0-21.5 8.5T450-820q0 13 8.5 21.5T480-790ZM200-200v-560 560Z" }) }));
4
+ };
5
+ export default AnnotateIcon;
@@ -0,0 +1,6 @@
1
+ type CloseIconProps = {
2
+ color?: string;
3
+ style?: React.CSSProperties;
4
+ };
5
+ declare const CloseIcon: React.FC<CloseIconProps>;
6
+ export default CloseIcon;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ const CloseIcon = ({ color = 'black', style = {} }) => {
3
+ return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", style: style, children: _jsx("path", { fill: color, d: "m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z" }) }));
4
+ };
5
+ export default CloseIcon;
@@ -0,0 +1,6 @@
1
+ type CopyIconProps = {
2
+ color?: string;
3
+ style?: React.CSSProperties;
4
+ };
5
+ declare const CopyIcon: React.FC<CopyIconProps>;
6
+ export default CopyIcon;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ const CopyIcon = ({ color = 'black', style = {} }) => {
3
+ return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", width: "24px", viewBox: "0 -960 960 960", style: style, children: _jsx("path", { fill: color, d: "M360-240q-33 0-56.5-23.5T280-320v-480q0-33 23.5-56.5T360-880h360q33 0 56.5 23.5T800-800v480q0 33-23.5 56.5T720-240H360Zm0-80h360v-480H360v480ZM200-80q-33 0-56.5-23.5T120-160v-560h80v560h440v80H200Zm160-240v-480 480Z" }) }));
4
+ };
5
+ export default CopyIcon;
@@ -0,0 +1,6 @@
1
+ type SaveIconProps = {
2
+ color?: string;
3
+ style?: React.CSSProperties;
4
+ };
5
+ declare const SaveIcon: React.FC<SaveIconProps>;
6
+ export default SaveIcon;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ const SaveIcon = ({ color = 'black', style = {} }) => {
3
+ return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", style: style, children: _jsx("path", { fill: color, d: "M840-680v480q0 33-23.5 56.5T760-120H200q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h480l160 160Zm-80 34L646-760H200v560h560v-446ZM480-240q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35ZM240-560h360v-160H240v160Zm-40-86v446-560 114Z" }) }));
4
+ };
5
+ export default SaveIcon;
@@ -1,15 +1,25 @@
1
1
  import { PropsWithChildren } from 'react';
2
- import { Shape, Shapes, ShapeType, ToolEnum } from '../Components/RoiEditor/Types';
2
+ import { Configuration, Metadata, Shape, Shapes, ShapeType, ToolEnum } from '../Components/RoiEditor/Types';
3
3
  type EditorContextType = {
4
+ hideForbiddenTools: boolean;
4
5
  activeTool: ToolEnum;
5
6
  setActiveTool: (tool: ToolEnum) => void;
6
7
  activeColor: string;
7
8
  setActiveColor: (color: string) => void;
8
9
  shapes: Shapes;
9
10
  addShape: (id: string, type: ShapeType, shape: Shape) => void;
11
+ addShapes: (shapes: {
12
+ id: string;
13
+ type: ShapeType;
14
+ shape: Shape;
15
+ }[]) => void;
10
16
  removeShape: (id: string) => void;
17
+ configuration: Configuration;
18
+ metadata: Metadata;
19
+ setMetadata: (data: Metadata) => void;
20
+ onSubmit: () => void;
11
21
  };
12
22
  export declare const EditorContext: import("react").Context<EditorContextType | undefined>;
13
23
  export declare function useEditorContext(): EditorContextType;
14
- declare const EditorProvider: ({ children, activeTool, setActiveTool, activeColor, setActiveColor, shapes, addShape, removeShape, }: PropsWithChildren<EditorContextType>) => import("react/jsx-runtime").JSX.Element;
24
+ declare const EditorProvider: ({ children, hideForbiddenTools, activeTool, setActiveTool, activeColor, setActiveColor, shapes, addShape, addShapes, removeShape, configuration, metadata, setMetadata, onSubmit, }: PropsWithChildren<EditorContextType>) => import("react/jsx-runtime").JSX.Element;
15
25
  export default EditorProvider;
@@ -8,7 +8,21 @@ export function useEditorContext() {
8
8
  }
9
9
  return context;
10
10
  }
11
- const EditorProvider = ({ children, activeTool, setActiveTool, activeColor, setActiveColor, shapes, addShape, removeShape, }) => {
12
- return (_jsx(EditorContext.Provider, { value: { activeTool, setActiveTool, activeColor, setActiveColor, shapes, addShape, removeShape }, children: children }));
11
+ const EditorProvider = ({ children, hideForbiddenTools, activeTool, setActiveTool, activeColor, setActiveColor, shapes, addShape, addShapes, removeShape, configuration, metadata, setMetadata, onSubmit, }) => {
12
+ return (_jsx(EditorContext.Provider, { value: {
13
+ hideForbiddenTools,
14
+ activeTool,
15
+ setActiveTool,
16
+ activeColor,
17
+ setActiveColor,
18
+ shapes,
19
+ addShape,
20
+ addShapes,
21
+ removeShape,
22
+ configuration,
23
+ metadata,
24
+ setMetadata,
25
+ onSubmit,
26
+ }, children: children }));
13
27
  };
14
28
  export default EditorProvider;