@abidibo/react-cam-roi 0.0.8 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +340 -39
- package/dist/Components/BoolField/BoolField.module.css +60 -0
- package/dist/Components/BoolField/index.d.ts +5 -0
- package/dist/Components/BoolField/index.js +13 -0
- package/dist/Components/Button/Button.module.css +27 -0
- package/dist/Components/Button/index.d.ts +8 -0
- package/dist/Components/Button/index.js +15 -0
- package/dist/Components/EnumField/EnumField.module.css +61 -0
- package/dist/Components/EnumField/index.d.ts +10 -0
- package/dist/Components/EnumField/index.js +16 -0
- package/dist/Components/IconButton/IconButton.module.css +8 -3
- package/dist/Components/IconButton/index.d.ts +1 -0
- package/dist/Components/IconButton/index.js +3 -3
- package/dist/Components/Modal/Modal.module.css +7 -0
- package/dist/Components/Modal/index.d.ts +2 -1
- package/dist/Components/Modal/index.js +3 -3
- package/dist/Components/NumberField/NumberField.module.css +60 -0
- package/dist/Components/NumberField/index.d.ts +3 -0
- package/dist/Components/NumberField/index.js +13 -0
- package/dist/Components/RoiEditor/Canvas.d.ts +2 -0
- package/dist/Components/RoiEditor/Canvas.js +20 -8
- package/dist/Components/RoiEditor/Hooks.d.ts +13 -0
- package/dist/Components/RoiEditor/Hooks.js +84 -5
- package/dist/Components/RoiEditor/ParameterField.d.ts +9 -0
- package/dist/Components/RoiEditor/ParameterField.js +27 -0
- package/dist/Components/RoiEditor/ParametersModalForm/ParametersModalForm.module.css +5 -0
- package/dist/Components/RoiEditor/ParametersModalForm/index.d.ts +10 -0
- package/dist/Components/RoiEditor/ParametersModalForm/index.js +31 -0
- package/dist/Components/RoiEditor/ShapesList.js +19 -6
- package/dist/Components/RoiEditor/Toolbar.js +13 -3
- package/dist/Components/RoiEditor/Toolbar.module.css +13 -1
- package/dist/Components/RoiEditor/Types.d.ts +52 -2
- package/dist/Components/RoiEditor/Utils.d.ts +18 -1
- package/dist/Components/RoiEditor/Utils.js +106 -0
- package/dist/Components/RoiEditor/index.d.ts +4 -1
- package/dist/Components/RoiEditor/index.js +44 -6
- package/dist/Components/TextField/TextField.module.css +61 -0
- package/dist/Components/TextField/index.d.ts +6 -0
- package/dist/Components/TextField/index.js +13 -0
- package/dist/Components/Typography/index.d.ts +1 -0
- package/dist/Components/Typography/index.js +2 -2
- package/dist/Icons/SaveIcon.d.ts +6 -0
- package/dist/Icons/SaveIcon.js +5 -0
- package/dist/Providers/EditorProvider.d.ts +12 -2
- package/dist/Providers/EditorProvider.js +17 -2
- package/dist/Providers/UiProvider.d.ts +24 -1
- package/dist/Providers/UiProvider.js +30 -1
- package/dist/Types.d.ts +10 -0
- package/dist/Types.js +1 -0
- package/dist/Utils/index.d.ts +1 -1
- package/dist/Utils/index.js +1 -1
- package/package.json +7 -2
- package/dist/Components/RoiEditor/ParametersModalForm.d.ts +0 -5
- package/dist/Components/RoiEditor/ParametersModalForm.js +0 -8
package/README.md
CHANGED
@@ -2,47 +2,117 @@
|
|
2
2
|
|
3
3
|
> Still in development!
|
4
4
|
|
5
|
-
This is a react component which lets you draw regions of interest (ROI) over images, manage metadata and import/export everything.
|
6
|
-
|
7
|
-
Metadata are dynamic information that can be attached to the whole image or to each ROI. The ROI that can be drawn, and the metadata are controlled through a configuration object.
|
5
|
+
This is a react component which lets you draw regions of interest (ROI) over images, manage metadata and import/export everything.
|
6
|
+
Metadata are dynamic information that can be attached to the whole image and/or to each ROI. The number of drawable ROIs can also be configured.
|
8
7
|
|
9
8
|
![Screenshot](./react-cam-roi.png)
|
10
9
|
|
11
|
-
It provides one component: `RoiEditor` and one provider: `UiProvider`. The editor lets you draw regions of interest over a given image (url). Each
|
10
|
+
It provides one component: `RoiEditor` and one provider: `UiProvider`. The editor lets you draw regions of interest over a given image (url). Each ROI can have dynamic metadata attached.
|
11
|
+
|
12
12
|
Export and import functionality is also provided.
|
13
13
|
|
14
14
|
Features:
|
15
15
|
|
16
16
|
- Autosizing of the editor: the canvas resizes to the size of the image, but it's also responsive, so if the container width is smaller, then the canvas is resized accordingly keeping the aspect ratio.
|
17
|
+
(the size is adjusted on load, after will remain the same even if changing viewport size)
|
17
18
|
- Draw polylines, polygons and rectangles, change dimensions and rotate them.
|
18
|
-
- Support for
|
19
|
+
- Support for number of drawable ROIs, defining a rule for each type.
|
20
|
+
- Support for dynamic metadata information attached to each shape and the whole image (with validation included).
|
19
21
|
- Import and export shapes and metadata in json format.
|
20
22
|
- Highly customizable: shape colors, custom components and css classes.
|
21
23
|
|
22
24
|
## Installation
|
23
25
|
|
24
|
-
```
|
26
|
+
``` bash
|
25
27
|
npm install @abidibo/react-cam-roi
|
26
28
|
```
|
27
29
|
|
28
30
|
## Usage
|
29
31
|
|
30
32
|
```ts
|
31
|
-
import { RoiEditor, UiProvider } from '@abidibo/react-cam-roi'
|
33
|
+
import { RoiEditor, UiProvider, Types } from '@abidibo/react-cam-roi'
|
32
34
|
import { Typography, IconButton, Delete } from '@mui/material'
|
33
35
|
|
34
36
|
const MyComponent: React.FC = () => {
|
35
37
|
const themMode = 'light'
|
36
|
-
const config = {} //
|
38
|
+
const config = {} // see below
|
39
|
+
|
40
|
+
const handleSubmit = (data: Types.Output) => console.log(data)
|
37
41
|
|
38
42
|
return (
|
39
43
|
<UiProvider themeMode={themeMode} IconButton={IconButton} Typography={Typography} DeleteIcon={() => <Delete />}>
|
40
|
-
<RoiEditor imageUrl={'https://placecats.com/800/600'} configuration={config} />
|
44
|
+
<RoiEditor imageUrl={'https://placecats.com/800/600'} configuration={config} onSubmit={handleSubmit} />
|
41
45
|
</UiProvider>
|
42
46
|
)
|
43
47
|
}
|
44
48
|
```
|
45
49
|
|
50
|
+
The `RoiEditor` props and the `Output` interface used both in import and export:
|
51
|
+
|
52
|
+
``` ts
|
53
|
+
export type RoiEditorProps = {
|
54
|
+
// id of this editor instance, should be unique
|
55
|
+
id: string
|
56
|
+
// the url of the image we want to annotate
|
57
|
+
imageUrl: string
|
58
|
+
// configuration object
|
59
|
+
configuration: Configuration
|
60
|
+
// callback called when exporting data
|
61
|
+
onSubmit: (data: Output) => void
|
62
|
+
// initial imported data
|
63
|
+
initialData?: Output
|
64
|
+
}
|
65
|
+
|
66
|
+
export const enum ToolEnum {
|
67
|
+
Pointer = 'pointer',
|
68
|
+
Polyline = 'polyline',
|
69
|
+
Polygon = 'polygon',
|
70
|
+
Rectangle = 'rect',
|
71
|
+
}
|
72
|
+
|
73
|
+
export type ShapeType = ToolEnum.Polyline | ToolEnum.Polygon | ToolEnum.Rectangle
|
74
|
+
|
75
|
+
export type OutputShapeRect = {
|
76
|
+
top: number
|
77
|
+
left: number
|
78
|
+
width: number
|
79
|
+
height: number
|
80
|
+
color: string
|
81
|
+
}
|
82
|
+
|
83
|
+
export type OutputShapePolyline = {
|
84
|
+
points: { x: number; y: number }[]
|
85
|
+
top: number
|
86
|
+
left: number
|
87
|
+
color: string
|
88
|
+
}
|
89
|
+
|
90
|
+
export type OutputShapePolygon = {
|
91
|
+
points: { x: number; y: number }[]
|
92
|
+
top: number
|
93
|
+
left: number
|
94
|
+
color: string
|
95
|
+
}
|
96
|
+
|
97
|
+
|
98
|
+
export interface OutputParameter {
|
99
|
+
codename: string
|
100
|
+
value: number | string | boolean | string[] | number[] | null
|
101
|
+
}
|
102
|
+
|
103
|
+
export interface OutputRoi {
|
104
|
+
parameters: OutputParameter[]
|
105
|
+
type: ShapeType
|
106
|
+
shape: OutputShapeRect | OutputShapePolyline | OutputShapePolygon
|
107
|
+
}
|
108
|
+
export interface Output {
|
109
|
+
parameters: OutputParameter[]
|
110
|
+
rois: OutputRoi[]
|
111
|
+
}
|
112
|
+
```
|
113
|
+
|
114
|
+
Take a look at the `UiProvider` allowed props (below) to see all the customization options.
|
115
|
+
|
46
116
|
## Configuration
|
47
117
|
|
48
118
|
The configuration prop defines which kind and how many ROIs can be drawn, along with metadata information. Here the types definitions and an example:
|
@@ -52,6 +122,7 @@ The configuration prop defines which kind and how many ROIs can be drawn, along
|
|
52
122
|
// import { Types } from '@abidibo/react-cam-roi'
|
53
123
|
// const { ToolEnum, ShapeType, DataTypeEnum, OperatorEnum, ConfigurationParameter, RoiConfiguration, Configuration } = Types
|
54
124
|
|
125
|
+
// The drawable shapes plus the Pointer tool
|
55
126
|
export const enum ToolEnum {
|
56
127
|
Pointer = 'pointer',
|
57
128
|
Polyline = 'polyline',
|
@@ -59,8 +130,10 @@ export const enum ToolEnum {
|
|
59
130
|
Rectangle = 'rect',
|
60
131
|
}
|
61
132
|
|
133
|
+
// Allowed shape types
|
62
134
|
export type ShapeType = ToolEnum.Polyline | ToolEnum.Polygon | ToolEnum.Rectangle
|
63
135
|
|
136
|
+
// Data types allowed for metadata values
|
64
137
|
export enum DataTypeEnum {
|
65
138
|
Integer = 'int',
|
66
139
|
Float = 'float',
|
@@ -68,6 +141,7 @@ export enum DataTypeEnum {
|
|
68
141
|
Boolean = 'bool',
|
69
142
|
}
|
70
143
|
|
144
|
+
// Operators allowed for multiplicity (control how many shapes should/can be drawn)
|
71
145
|
export enum OperatorEnum {
|
72
146
|
Lt = 'lt',
|
73
147
|
Lte = 'lte',
|
@@ -76,32 +150,41 @@ export enum OperatorEnum {
|
|
76
150
|
Eq = 'eq',
|
77
151
|
}
|
78
152
|
|
153
|
+
// Definition of a metadata parameter
|
79
154
|
export type ConfigurationParameter = {
|
80
|
-
codename: string
|
81
|
-
label: string
|
82
|
-
description: string
|
83
|
-
unit: string
|
84
|
-
type: DataTypeEnum
|
85
|
-
options: { value: number | string | boolean; label: string }[]
|
86
|
-
|
87
|
-
|
155
|
+
codename: string // unique
|
156
|
+
label: string // label of the parameter
|
157
|
+
description: string // helper text
|
158
|
+
unit: string // postponed to the label
|
159
|
+
type: DataTypeEnum // value type
|
160
|
+
options: { value: number | string | boolean; label: string }[] // if filled the component will be a dropdown
|
161
|
+
multiple?: boolean // for multiple selection
|
162
|
+
required: boolean // required parameter
|
163
|
+
value: number | string | boolean | string[] | number[] | null // default value
|
88
164
|
}
|
89
165
|
|
166
|
+
// Configuration of ROIs
|
90
167
|
export type RoiConfiguration = {
|
91
|
-
role: string
|
92
|
-
type: Omit<ShapeType, 'pointer'>
|
93
|
-
multiplicity: {
|
168
|
+
role: string // for our use case
|
169
|
+
type: Omit<ShapeType, 'pointer'> // shape type
|
170
|
+
multiplicity: { // how many ROIs of this type can be drawn
|
94
171
|
operator: OperatorEnum
|
95
172
|
threshold: number
|
96
173
|
}
|
97
|
-
parameters: ConfigurationParameter[]
|
174
|
+
parameters: ConfigurationParameter[] // ROIs parameters for this shape type
|
98
175
|
}
|
99
176
|
|
177
|
+
// Whole configuration
|
100
178
|
export type Configuration = {
|
101
179
|
parameters: ConfigurationParameter[]
|
102
180
|
rois: RoiConfiguration[]
|
181
|
+
options: {
|
182
|
+
hideForbiddenTools?: boolean // hide tools controllers for shapes that cannot be drawn
|
183
|
+
description?: string // optional initial text shown in the editor
|
184
|
+
}
|
103
185
|
}
|
104
186
|
|
187
|
+
// Example
|
105
188
|
export const configuration: Configuration = {
|
106
189
|
parameters: [
|
107
190
|
{
|
@@ -148,21 +231,25 @@ export const configuration: Configuration = {
|
|
148
231
|
],
|
149
232
|
},
|
150
233
|
],
|
234
|
+
options?: {
|
235
|
+
hideForbiddenTools?: boolean,
|
236
|
+
description?: string,
|
237
|
+
}
|
151
238
|
}
|
152
239
|
```
|
153
240
|
|
154
|
-
## Customization
|
241
|
+
## UiProvider and Customization
|
155
242
|
|
156
243
|
You can customize many aspects of this library by using the `UiProvider`.
|
157
244
|
|
158
|
-
- You can customize both the styles and the components
|
245
|
+
- You can customize both the styles and the components used in this library. The library provides default components with an interface almost compatible witu mui components (maybe you'll need to wrap some of them).
|
159
246
|
- You can override them by using the `UiProvider`. But you can also use the default ones and just add your styling.
|
160
247
|
- You can pass a theme mode which is used by the default components to determine the color scheme. It is also used to define custom classes you can use for styling.
|
161
248
|
- You can define a primary color which is used for color or background of active elements.
|
162
|
-
- You can define custom strings used here and there.
|
249
|
+
- You can define custom strings used here and there (some strings require one or more placeholders).
|
163
250
|
- You can enable logs in the console by setting the `enableLogs` option to `true`.
|
164
251
|
|
165
|
-
```tsx
|
252
|
+
``` tsx
|
166
253
|
import IconButton from '@mui/material/IconButton'
|
167
254
|
import { UiProvider, RoiEditor } from 'react-cam-roi'
|
168
255
|
|
@@ -182,22 +269,34 @@ Props and types are defined later in this document.
|
|
182
269
|
```ts
|
183
270
|
type UiContextType = {
|
184
271
|
children?: React.ReactNode
|
185
|
-
enableLogs: boolean
|
186
|
-
themeMode: 'light' | 'dark'
|
187
|
-
primaryColor: string
|
188
|
-
Typography: React.FC<TypographyProps>
|
189
|
-
Modal: React.FC<ModalProps>
|
190
|
-
IconButton: React.FC<IconButtonProps>
|
191
|
-
DeleteIcon: React.FC<DeleteIconProps>
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
272
|
+
enableLogs: boolean // enable console logs
|
273
|
+
themeMode: 'light' | 'dark' // themeMode for internal components
|
274
|
+
primaryColor: string // primary color for internal components
|
275
|
+
Typography: React.FC<TypographyProps> // component used to surround text
|
276
|
+
Modal: React.FC<ModalProps> // modal dialog component (it displays metadata forms)
|
277
|
+
IconButton: React.FC<IconButtonProps> // wrapper for icon buttons
|
278
|
+
DeleteIcon: React.FC<DeleteIconProps> // delete icon
|
279
|
+
SelectIcon: React.FC<SelectIconProps> // select icon
|
280
|
+
CopyIcon: typeof CopyIcon // copy icon (clone a shape)
|
281
|
+
AnnotateIcon: typeof AnnotateIcon // annotate icon (open metadata form)
|
282
|
+
CloseIcon: typeof CloseIcon // close icon
|
283
|
+
SaveIcon: typeof SaveIcon // save icon
|
284
|
+
TextField: typeof TextField // field used for text input
|
285
|
+
NumberField: typeof NumberField // field used for number input
|
286
|
+
BoolField: typeof BoolField // field used for boolean input
|
287
|
+
EnumField: typeof EnumField // field used for enum input (options filled in parameter definition)
|
288
|
+
Button: typeof Button // button
|
289
|
+
notify: INotify // function used to display notifications
|
290
|
+
strings: { // strings used here and there
|
291
|
+
cancel: string
|
196
292
|
cannotDrawMorePolygons: string
|
197
293
|
cannotDrawMorePolylines: string
|
198
294
|
cannotDrawMoreRectangles: string
|
199
295
|
id: string
|
296
|
+
invalidSubmission: string
|
200
297
|
mainParametersMetadata: string
|
298
|
+
missingRequiredValuesInMainParameters: string
|
299
|
+
missingRequiredValuesInShapeParameters: string // with {id} placeholder
|
201
300
|
polygon: string
|
202
301
|
polygonHelpText: string
|
203
302
|
polyline: string
|
@@ -206,6 +305,13 @@ type UiContextType = {
|
|
206
305
|
rectHelpText: string
|
207
306
|
pointer: string
|
208
307
|
pointerHelpText: string
|
308
|
+
requiredField: string
|
309
|
+
save: string
|
310
|
+
shapesOfTypeShouldBeEqualToThreshold: string // with {type} and {threshold} placeholders
|
311
|
+
shapesOfTypeShouldBeGreaterThanThreshold: string // with {type} and {threshold} placeholders
|
312
|
+
shapesOfTypeShouldBeGreaterThanOrEqualToThreshold: string // with {type} and {threshold} placeholders
|
313
|
+
shapesOfTypeShouldBeLessThanThreshold: string // with {type} and {threshold} placeholders
|
314
|
+
shapesOfTypeShouldBeLessThanOrEqualToThreshold: string // with {type} and {threshold} placeholders
|
209
315
|
type: string
|
210
316
|
}
|
211
317
|
}
|
@@ -239,7 +345,7 @@ type ModalProps = {
|
|
239
345
|
title: string
|
240
346
|
onClose: () => void
|
241
347
|
isOpen: boolean
|
242
|
-
|
348
|
+
maxWidth: 'xs' | 'sm' | 'md' | 'lg'
|
243
349
|
}
|
244
350
|
```
|
245
351
|
|
@@ -257,6 +363,9 @@ type ModalProps = {
|
|
257
363
|
- `react-cam-roi-modal-title`
|
258
364
|
- `react-cam-roi-modal-title-light`
|
259
365
|
- `react-cam-roi-modal-title-dark`
|
366
|
+
- `react-cam-roi-modal-footer`
|
367
|
+
- `react-cam-roi-modal-footer-light`
|
368
|
+
- `react-cam-roi-modal-footer-dark`
|
260
369
|
|
261
370
|
#### Typography
|
262
371
|
|
@@ -268,6 +377,7 @@ type TypographyProps = {
|
|
268
377
|
variant?: any // compatible with mui
|
269
378
|
component?: any // compatible with mui
|
270
379
|
className?: string
|
380
|
+
style?: React.CSSProperties
|
271
381
|
}
|
272
382
|
```
|
273
383
|
|
@@ -278,10 +388,18 @@ type TypographyProps = {
|
|
278
388
|
```ts
|
279
389
|
type IconButtonProps = {
|
280
390
|
children?: React.ReactNode
|
391
|
+
disabled?: boolean
|
281
392
|
onClick?: (event: React.MouseEvent) => void
|
282
393
|
}
|
283
394
|
```
|
284
395
|
|
396
|
+
##### Classes
|
397
|
+
|
398
|
+
- `react-cam-roi-icon-button`
|
399
|
+
- `react-cam-roi-icon-button-light`
|
400
|
+
- `react-cam-roi-icon-button-dark`
|
401
|
+
- `react-cam-roi-icon-button-disabled`
|
402
|
+
|
285
403
|
#### DeleteIcon
|
286
404
|
|
287
405
|
##### Interface
|
@@ -330,11 +448,186 @@ type CopyIconProps = {
|
|
330
448
|
|
331
449
|
##### Interface
|
332
450
|
|
333
|
-
|
451
|
+
```ts
|
334
452
|
type AnnotateIconProps = {
|
335
453
|
color?: string
|
336
454
|
style?: React.CSSProperties
|
337
455
|
}
|
456
|
+
```
|
457
|
+
#### SaveIcon
|
458
|
+
|
459
|
+
##### Interface
|
460
|
+
|
461
|
+
```ts
|
462
|
+
type SaveIconProps = {
|
463
|
+
color?: string
|
464
|
+
style?: React.CSSProperties
|
465
|
+
}
|
466
|
+
```
|
467
|
+
|
468
|
+
#### TextField
|
469
|
+
|
470
|
+
##### Interface
|
471
|
+
|
472
|
+
```ts
|
473
|
+
type TextFieldProps = {
|
474
|
+
type?: 'text' | 'email' | 'password'
|
475
|
+
onChange: (value: string) => void
|
476
|
+
value: string
|
477
|
+
label: string
|
478
|
+
helperText?: string
|
479
|
+
error?: boolean
|
480
|
+
required?: boolean
|
481
|
+
readOnly?: boolean
|
482
|
+
disabled?: boolean
|
483
|
+
}
|
484
|
+
```
|
485
|
+
|
486
|
+
##### Classes
|
487
|
+
|
488
|
+
|
489
|
+
- `react-cam-roi-text-field-wrapper`
|
490
|
+
- `react-cam-roi-text-field-wrapper-light`
|
491
|
+
- `react-cam-roi-text-field-wrapper-dark`
|
492
|
+
- `react-cam-roi-text-field`
|
493
|
+
- `react-cam-roi-text-field--light`
|
494
|
+
- `react-cam-roi-text-field--dark`
|
495
|
+
- `react-cam-roi-text-field--error`
|
496
|
+
- `react-cam-roi-text-field-label`
|
497
|
+
- `react-cam-roi-text-field-label-light`
|
498
|
+
- `react-cam-roi-text-field-label-dark`
|
499
|
+
- `react-cam-roi-text-field-label-error`
|
500
|
+
- `react-cam-roi-text-field-helper-text`
|
501
|
+
- `react-cam-roi-text-field-helper-text-light`
|
502
|
+
- `react-cam-roi-text-field-helper-text-dark`
|
503
|
+
- `react-cam-roi-text-field-helper-text-error`
|
504
|
+
|
505
|
+
#### NumberField
|
506
|
+
|
507
|
+
##### Interface
|
508
|
+
|
509
|
+
```ts
|
510
|
+
type NumberFieldProps = {
|
511
|
+
onChange: (value: number) => void
|
512
|
+
value: number
|
513
|
+
label: string
|
514
|
+
helperText?: string
|
515
|
+
error?: boolean
|
516
|
+
required?: boolean
|
517
|
+
readOnly?: boolean
|
518
|
+
disabled?: boolean
|
519
|
+
}
|
520
|
+
```
|
521
|
+
|
522
|
+
##### Classes
|
523
|
+
|
524
|
+
- `react-cam-roi-number-field-wrapper`
|
525
|
+
- `react-cam-roi-number-field-wrapper-light`
|
526
|
+
- `react-cam-roi-number-field-wrapper-dark`
|
527
|
+
- `react-cam-roi-number-field`
|
528
|
+
- `react-cam-roi-number-field--light`
|
529
|
+
- `react-cam-roi-number-field--dark`
|
530
|
+
- `react-cam-roi-number-field--error`
|
531
|
+
- `react-cam-roi-number-field-label`
|
532
|
+
- `react-cam-roi-number-field-label-light`
|
533
|
+
- `react-cam-roi-number-field-label-dark`
|
534
|
+
- `react-cam-roi-number-field-label-error`
|
535
|
+
- `react-cam-roi-number-field-helper-text`
|
536
|
+
- `react-cam-roi-number-field-helper-text-light`
|
537
|
+
- `react-cam-roi-number-field-helper-text-dark`
|
538
|
+
- `react-cam-roi-number-field-helper-text-error`
|
539
|
+
|
540
|
+
#### BoolField
|
541
|
+
|
542
|
+
##### Interface
|
543
|
+
|
544
|
+
```ts
|
545
|
+
type BoolFieldProps = {
|
546
|
+
onChange: (value: boolean) => void
|
547
|
+
value: boolean
|
548
|
+
label: string
|
549
|
+
helperText?: string
|
550
|
+
error?: boolean
|
551
|
+
required?: boolean
|
552
|
+
readOnly?: boolean
|
553
|
+
disabled?: boolean
|
554
|
+
}
|
555
|
+
```
|
556
|
+
|
557
|
+
##### Classes
|
558
|
+
|
559
|
+
- `react-cam-roi-bool-field-wrapper`
|
560
|
+
- `react-cam-roi-bool-field-wrapper-light`
|
561
|
+
- `react-cam-roi-bool-field-wrapper-dark`
|
562
|
+
- `react-cam-roi-bool-field`
|
563
|
+
- `react-cam-roi-bool-field--light`
|
564
|
+
- `react-cam-roi-bool-field--dark`
|
565
|
+
- `react-cam-roi-bool-field--error`
|
566
|
+
- `react-cam-roi-bool-field-label`
|
567
|
+
- `react-cam-roi-bool-field-label-light`
|
568
|
+
- `react-cam-roi-bool-field-label-dark`
|
569
|
+
- `react-cam-roi-bool-field-label-error`
|
570
|
+
- `react-cam-roi-bool-field-helper-text`
|
571
|
+
- `react-cam-roi-bool-field-helper-text-light`
|
572
|
+
- `react-cam-roi-bool-field-helper-text-dark`
|
573
|
+
- `react-cam-roi-bool-field-helper-text-error`
|
574
|
+
|
575
|
+
#### EnumField
|
576
|
+
|
577
|
+
##### Interface
|
578
|
+
|
579
|
+
```ts
|
580
|
+
type EnumFieldProps = {
|
581
|
+
onChange: (value: string | number | (string | number)[]) => void
|
582
|
+
value: string | number | (string | number)[]
|
583
|
+
label: string
|
584
|
+
helperText?: string
|
585
|
+
error?: boolean
|
586
|
+
required?: boolean
|
587
|
+
multiple?: boolean
|
588
|
+
disabled?: boolean
|
589
|
+
}
|
590
|
+
```
|
591
|
+
|
592
|
+
##### Classes
|
593
|
+
|
594
|
+
- `react-cam-roi-enum-field-wrapper`
|
595
|
+
- `react-cam-roi-enum-field-wrapper-light`
|
596
|
+
- `react-cam-roi-enum-field-wrapper-dark`
|
597
|
+
- `react-cam-roi-enum-field`
|
598
|
+
- `react-cam-roi-enum-field--light`
|
599
|
+
- `react-cam-roi-enum-field--dark`
|
600
|
+
- `react-cam-roi-enum-field--error`
|
601
|
+
- `react-cam-roi-enum-field-label`
|
602
|
+
- `react-cam-roi-enum-field-label-light`
|
603
|
+
- `react-cam-roi-enum-field-label-dark`
|
604
|
+
- `react-cam-roi-enum-field-label-error`
|
605
|
+
- `react-cam-roi-enum-field-helper-text`
|
606
|
+
- `react-cam-roi-enum-field-helper-text-light`
|
607
|
+
- `react-cam-roi-enum-field-helper-text-dark`
|
608
|
+
- `react-cam-roi-enum-field-helper-text-error`
|
609
|
+
|
610
|
+
|
611
|
+
#### Button
|
612
|
+
|
613
|
+
##### Interface
|
614
|
+
|
615
|
+
```ts
|
616
|
+
type ButtonProps = {
|
617
|
+
onClick: (event: React.MouseEvent) => void
|
618
|
+
primary?: boolean
|
619
|
+
disabled?: boolean
|
620
|
+
}
|
621
|
+
```
|
622
|
+
|
623
|
+
##### Classes
|
624
|
+
|
625
|
+
- `react-cam-roi-button`
|
626
|
+
- `react-cam-roi-button-light`
|
627
|
+
- `react-cam-roi-button-dark`
|
628
|
+
- `react-cam-roi-button-disabled`
|
629
|
+
- `react-cam-roi-button-disabled-light`
|
630
|
+
- `react-cam-roi-button-disabled-dark`
|
338
631
|
|
339
632
|
### Functions
|
340
633
|
|
@@ -345,7 +638,7 @@ type INotify = { // compatible with toast (react-toastify)
|
|
345
638
|
error: (message: string) => void
|
346
639
|
success: (message: string) => void
|
347
640
|
}
|
348
|
-
|
641
|
+
```
|
349
642
|
|
350
643
|
### Styles
|
351
644
|
|
@@ -359,6 +652,10 @@ There are components that cannot be overridden. But still you can use classes to
|
|
359
652
|
|
360
653
|
#### Toolbar
|
361
654
|
|
655
|
+
- `react-cam-roi-toolbar-info`
|
656
|
+
- `react-cam-roi-toolbar-info-light`
|
657
|
+
- `react-cam-roi-toolbar-info-dark`
|
658
|
+
|
362
659
|
- `react-cam-roi-toolbar`
|
363
660
|
- `react-cam-roi-toolbar-light`
|
364
661
|
- `react-cam-roi-toolbar-dark`
|
@@ -389,6 +686,10 @@ There are components that cannot be overridden. But still you can use classes to
|
|
389
686
|
- `react-cam-roi-colorpicker-button-active-light`
|
390
687
|
- `react-cam-roi-colorpicker-button-active-dark`
|
391
688
|
|
689
|
+
#### Form
|
690
|
+
|
691
|
+
- `react-cam-roi-form`
|
692
|
+
|
392
693
|
## Development
|
393
694
|
|
394
695
|
After cloning the repository and install dependencies (`yarn install`), you can run the following commands:
|
@@ -0,0 +1,60 @@
|
|
1
|
+
/*
|
2
|
+
.bool-field-wrapper {
|
3
|
+
margin-bottom: 2rem;
|
4
|
+
}
|
5
|
+
.bool-field-wrapper-light {
|
6
|
+
}
|
7
|
+
.bool-field-wrapper-dark {
|
8
|
+
}
|
9
|
+
*/
|
10
|
+
|
11
|
+
.bool-field {
|
12
|
+
border-radius: 0.25rem;
|
13
|
+
box-sizing: border-box;
|
14
|
+
padding: 0.5rem;
|
15
|
+
}
|
16
|
+
.bool-field:focus-visible {
|
17
|
+
outline: none;
|
18
|
+
border: 1px solid #1976d2;
|
19
|
+
}
|
20
|
+
.bool-field-light {
|
21
|
+
background-color: #fff;
|
22
|
+
color: #333;
|
23
|
+
border: 1px solid #ccc;
|
24
|
+
}
|
25
|
+
.bool-field-dark {
|
26
|
+
background-color: #333;
|
27
|
+
border: 1px solid #666;
|
28
|
+
color: #fff;
|
29
|
+
}
|
30
|
+
.bool-field-error {
|
31
|
+
border: 1px solid #d32f2f;
|
32
|
+
}
|
33
|
+
.bool-field-label {
|
34
|
+
font-weight: bold;
|
35
|
+
display: block;
|
36
|
+
margin: 0 0 1rem 0;
|
37
|
+
}
|
38
|
+
/*
|
39
|
+
.text-fiel-label-light {
|
40
|
+
}
|
41
|
+
.bool-field-label-dark {
|
42
|
+
}
|
43
|
+
*/
|
44
|
+
.bool-field-label-error {
|
45
|
+
color: #d32f2f;
|
46
|
+
}
|
47
|
+
.bool-field-helper-text {
|
48
|
+
font-style: italic;
|
49
|
+
font-size: 0.9rem;
|
50
|
+
margin-top: 0.5rem;
|
51
|
+
}
|
52
|
+
/*
|
53
|
+
.bool-field-helper-text-light {
|
54
|
+
}
|
55
|
+
.bool-field-helper-text-dark {
|
56
|
+
}
|
57
|
+
*/
|
58
|
+
.bool-field-helper-text-error {
|
59
|
+
color: #d32f2f;
|
60
|
+
}
|
@@ -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 './BoolField.module.css';
|
6
|
+
const BoolField = ({ onChange, value, label, helperText, error, readOnly = false, disabled = false, required = false, }) => {
|
7
|
+
const { themeMode, Typography } = useContext(UiContext);
|
8
|
+
const handleChange = (e) => {
|
9
|
+
onChange(e.target.checked);
|
10
|
+
};
|
11
|
+
return (_jsxs("div", { className: css('bool-field-wrapper', styles, themeMode), children: [_jsx("label", { className: `${css('bool-field-label', styles, themeMode)} ${error ? css('bool-field-label-error', styles, null) : ''}`, children: _jsxs(Typography, { children: [label, required && ' *'] }) }), _jsx("input", { type: 'checkbox', className: `${css('bool-field', styles, themeMode)} ${error ? css('bool-field-error', styles, null) : ''}`, onChange: handleChange, checked: value, readOnly: readOnly, disabled: disabled }), helperText && (_jsx(Typography, { component: 'div', className: `${css('bool-field-helper-text', styles, themeMode)} ${error ? css('bool-field-helper-text-error', styles, null) : ''}`, children: helperText }))] }));
|
12
|
+
};
|
13
|
+
export default BoolField;
|
@@ -0,0 +1,27 @@
|
|
1
|
+
.button {
|
2
|
+
border: none;
|
3
|
+
border-radius: 4px;
|
4
|
+
color: black;
|
5
|
+
padding: .5rem 1rem;
|
6
|
+
text-align: center;
|
7
|
+
text-decoration: none;
|
8
|
+
display: inline-block;
|
9
|
+
font-size: 16px;
|
10
|
+
margin: 4px 2px;
|
11
|
+
cursor: pointer;
|
12
|
+
}
|
13
|
+
|
14
|
+
.button-light {
|
15
|
+
background-color: #d7d7d7;
|
16
|
+
color: black;
|
17
|
+
}
|
18
|
+
|
19
|
+
.button-dark {
|
20
|
+
background-color: #383838;
|
21
|
+
color: white;
|
22
|
+
}
|
23
|
+
|
24
|
+
.button-disabled {
|
25
|
+
cursor: not-allowed;
|
26
|
+
opacity: 0.5;
|
27
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
2
|
+
export type ButtonProps = {
|
3
|
+
onClick: (event: React.MouseEvent) => void;
|
4
|
+
primary?: boolean;
|
5
|
+
disabled?: boolean;
|
6
|
+
};
|
7
|
+
declare const Button: ({ onClick, primary, disabled, children }: PropsWithChildren<ButtonProps>) => import("react/jsx-runtime").JSX.Element;
|
8
|
+
export default Button;
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { 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 './Button.module.css';
|
6
|
+
const Button = ({ onClick, primary, disabled, children }) => {
|
7
|
+
const { themeMode, primaryColor } = useContext(UiContext);
|
8
|
+
const style = {};
|
9
|
+
if (primary) {
|
10
|
+
style.backgroundColor = primaryColor;
|
11
|
+
style.color = 'white';
|
12
|
+
}
|
13
|
+
return (_jsx("button", { className: `${css('button', styles, themeMode)}${disabled ? ` ${css('button-disabled', styles, themeMode)}` : ''}`, style: style, onClick: onClick, disabled: disabled, children: children }));
|
14
|
+
};
|
15
|
+
export default Button;
|