@abidibo/react-cam-roi 0.0.7 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
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;