@abidibo/react-cam-roi 0.0.8 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +335 -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 +3 -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 +11 -2
- package/dist/Providers/EditorProvider.js +16 -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,112 @@
|
|
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
|
+
// the url of the image we want to annotate
|
55
|
+
imageUrl: string
|
56
|
+
configuration: Configuration
|
57
|
+
onSubmit: (data: Output) => void
|
58
|
+
initialData?: Output
|
59
|
+
}
|
60
|
+
|
61
|
+
export const enum ToolEnum {
|
62
|
+
Pointer = 'pointer',
|
63
|
+
Polyline = 'polyline',
|
64
|
+
Polygon = 'polygon',
|
65
|
+
Rectangle = 'rect',
|
66
|
+
}
|
67
|
+
|
68
|
+
export type ShapeType = ToolEnum.Polyline | ToolEnum.Polygon | ToolEnum.Rectangle
|
69
|
+
|
70
|
+
export type OutputShapeRect = {
|
71
|
+
top: number
|
72
|
+
left: number
|
73
|
+
width: number
|
74
|
+
height: number
|
75
|
+
color: string
|
76
|
+
}
|
77
|
+
|
78
|
+
export type OutputShapePolyline = {
|
79
|
+
points: { x: number; y: number }[]
|
80
|
+
top: number
|
81
|
+
left: number
|
82
|
+
color: string
|
83
|
+
}
|
84
|
+
|
85
|
+
export type OutputShapePolygon = {
|
86
|
+
points: { x: number; y: number }[]
|
87
|
+
top: number
|
88
|
+
left: number
|
89
|
+
color: string
|
90
|
+
}
|
91
|
+
|
92
|
+
|
93
|
+
export interface OutputParameter {
|
94
|
+
codename: string
|
95
|
+
value: number | string | boolean | string[] | number[] | null
|
96
|
+
}
|
97
|
+
|
98
|
+
export interface OutputRoi {
|
99
|
+
parameters: OutputParameter[]
|
100
|
+
type: ShapeType
|
101
|
+
shape: OutputShapeRect | OutputShapePolyline | OutputShapePolygon
|
102
|
+
}
|
103
|
+
export interface Output {
|
104
|
+
parameters: OutputParameter[]
|
105
|
+
rois: OutputRoi[]
|
106
|
+
}
|
107
|
+
```
|
108
|
+
|
109
|
+
Take a look at the `UiProvider` allowed props (below) to see all the customization options.
|
110
|
+
|
46
111
|
## Configuration
|
47
112
|
|
48
113
|
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 +117,7 @@ The configuration prop defines which kind and how many ROIs can be drawn, along
|
|
52
117
|
// import { Types } from '@abidibo/react-cam-roi'
|
53
118
|
// const { ToolEnum, ShapeType, DataTypeEnum, OperatorEnum, ConfigurationParameter, RoiConfiguration, Configuration } = Types
|
54
119
|
|
120
|
+
// The drawable shapes plus the Pointer tool
|
55
121
|
export const enum ToolEnum {
|
56
122
|
Pointer = 'pointer',
|
57
123
|
Polyline = 'polyline',
|
@@ -59,8 +125,10 @@ export const enum ToolEnum {
|
|
59
125
|
Rectangle = 'rect',
|
60
126
|
}
|
61
127
|
|
128
|
+
// Allowed shape types
|
62
129
|
export type ShapeType = ToolEnum.Polyline | ToolEnum.Polygon | ToolEnum.Rectangle
|
63
130
|
|
131
|
+
// Data types allowed for metadata values
|
64
132
|
export enum DataTypeEnum {
|
65
133
|
Integer = 'int',
|
66
134
|
Float = 'float',
|
@@ -68,6 +136,7 @@ export enum DataTypeEnum {
|
|
68
136
|
Boolean = 'bool',
|
69
137
|
}
|
70
138
|
|
139
|
+
// Operators allowed for multiplicity (control how many shapes should/can be drawn)
|
71
140
|
export enum OperatorEnum {
|
72
141
|
Lt = 'lt',
|
73
142
|
Lte = 'lte',
|
@@ -76,32 +145,41 @@ export enum OperatorEnum {
|
|
76
145
|
Eq = 'eq',
|
77
146
|
}
|
78
147
|
|
148
|
+
// Definition of a metadata parameter
|
79
149
|
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
|
-
|
150
|
+
codename: string // unique
|
151
|
+
label: string // label of the parameter
|
152
|
+
description: string // helper text
|
153
|
+
unit: string // postponed to the label
|
154
|
+
type: DataTypeEnum // value type
|
155
|
+
options: { value: number | string | boolean; label: string }[] // if filled the component will be a dropdown
|
156
|
+
multiple?: boolean // for multiple selection
|
157
|
+
required: boolean // required parameter
|
158
|
+
value: number | string | boolean | string[] | number[] | null // default value
|
88
159
|
}
|
89
160
|
|
161
|
+
// Configuration of ROIs
|
90
162
|
export type RoiConfiguration = {
|
91
|
-
role: string
|
92
|
-
type: Omit<ShapeType, 'pointer'>
|
93
|
-
multiplicity: {
|
163
|
+
role: string // for our use case
|
164
|
+
type: Omit<ShapeType, 'pointer'> // shape type
|
165
|
+
multiplicity: { // how many ROIs of this type can be drawn
|
94
166
|
operator: OperatorEnum
|
95
167
|
threshold: number
|
96
168
|
}
|
97
|
-
parameters: ConfigurationParameter[]
|
169
|
+
parameters: ConfigurationParameter[] // ROIs parameters for this shape type
|
98
170
|
}
|
99
171
|
|
172
|
+
// Whole configuration
|
100
173
|
export type Configuration = {
|
101
174
|
parameters: ConfigurationParameter[]
|
102
175
|
rois: RoiConfiguration[]
|
176
|
+
options: {
|
177
|
+
hideForbiddenTools?: boolean // hide tools controllers for shapes that cannot be drawn
|
178
|
+
description?: string // optional initial text shown in the editor
|
179
|
+
}
|
103
180
|
}
|
104
181
|
|
182
|
+
// Example
|
105
183
|
export const configuration: Configuration = {
|
106
184
|
parameters: [
|
107
185
|
{
|
@@ -148,21 +226,25 @@ export const configuration: Configuration = {
|
|
148
226
|
],
|
149
227
|
},
|
150
228
|
],
|
229
|
+
options?: {
|
230
|
+
hideForbiddenTools?: boolean,
|
231
|
+
description?: string,
|
232
|
+
}
|
151
233
|
}
|
152
234
|
```
|
153
235
|
|
154
|
-
## Customization
|
236
|
+
## UiProvider and Customization
|
155
237
|
|
156
238
|
You can customize many aspects of this library by using the `UiProvider`.
|
157
239
|
|
158
|
-
- You can customize both the styles and the components
|
240
|
+
- 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
241
|
- You can override them by using the `UiProvider`. But you can also use the default ones and just add your styling.
|
160
242
|
- 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
243
|
- 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.
|
244
|
+
- You can define custom strings used here and there (some strings require one or more placeholders).
|
163
245
|
- You can enable logs in the console by setting the `enableLogs` option to `true`.
|
164
246
|
|
165
|
-
```tsx
|
247
|
+
``` tsx
|
166
248
|
import IconButton from '@mui/material/IconButton'
|
167
249
|
import { UiProvider, RoiEditor } from 'react-cam-roi'
|
168
250
|
|
@@ -182,22 +264,34 @@ Props and types are defined later in this document.
|
|
182
264
|
```ts
|
183
265
|
type UiContextType = {
|
184
266
|
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
|
-
|
267
|
+
enableLogs: boolean // enable console logs
|
268
|
+
themeMode: 'light' | 'dark' // themeMode for internal components
|
269
|
+
primaryColor: string // primary color for internal components
|
270
|
+
Typography: React.FC<TypographyProps> // component used to surround text
|
271
|
+
Modal: React.FC<ModalProps> // modal dialog component (it displays metadata forms)
|
272
|
+
IconButton: React.FC<IconButtonProps> // wrapper for icon buttons
|
273
|
+
DeleteIcon: React.FC<DeleteIconProps> // delete icon
|
274
|
+
SelectIcon: React.FC<SelectIconProps> // select icon
|
275
|
+
CopyIcon: typeof CopyIcon // copy icon (clone a shape)
|
276
|
+
AnnotateIcon: typeof AnnotateIcon // annotate icon (open metadata form)
|
277
|
+
CloseIcon: typeof CloseIcon // close icon
|
278
|
+
SaveIcon: typeof SaveIcon // save icon
|
279
|
+
TextField: typeof TextField // field used for text input
|
280
|
+
NumberField: typeof NumberField // field used for number input
|
281
|
+
BoolField: typeof BoolField // field used for boolean input
|
282
|
+
EnumField: typeof EnumField // field used for enum input (options filled in parameter definition)
|
283
|
+
Button: typeof Button // button
|
284
|
+
notify: INotify // function used to display notifications
|
285
|
+
strings: { // strings used here and there
|
286
|
+
cancel: string
|
196
287
|
cannotDrawMorePolygons: string
|
197
288
|
cannotDrawMorePolylines: string
|
198
289
|
cannotDrawMoreRectangles: string
|
199
290
|
id: string
|
291
|
+
invalidSubmission: string
|
200
292
|
mainParametersMetadata: string
|
293
|
+
missingRequiredValuesInMainParameters: string
|
294
|
+
missingRequiredValuesInShapeParameters: string // with {id} placeholder
|
201
295
|
polygon: string
|
202
296
|
polygonHelpText: string
|
203
297
|
polyline: string
|
@@ -206,6 +300,13 @@ type UiContextType = {
|
|
206
300
|
rectHelpText: string
|
207
301
|
pointer: string
|
208
302
|
pointerHelpText: string
|
303
|
+
requiredField: string
|
304
|
+
save: string
|
305
|
+
shapesOfTypeShouldBeEqualToThreshold: string // with {type} and {threshold} placeholders
|
306
|
+
shapesOfTypeShouldBeGreaterThanThreshold: string // with {type} and {threshold} placeholders
|
307
|
+
shapesOfTypeShouldBeGreaterThanOrEqualToThreshold: string // with {type} and {threshold} placeholders
|
308
|
+
shapesOfTypeShouldBeLessThanThreshold: string // with {type} and {threshold} placeholders
|
309
|
+
shapesOfTypeShouldBeLessThanOrEqualToThreshold: string // with {type} and {threshold} placeholders
|
209
310
|
type: string
|
210
311
|
}
|
211
312
|
}
|
@@ -239,7 +340,7 @@ type ModalProps = {
|
|
239
340
|
title: string
|
240
341
|
onClose: () => void
|
241
342
|
isOpen: boolean
|
242
|
-
|
343
|
+
maxWidth: 'xs' | 'sm' | 'md' | 'lg'
|
243
344
|
}
|
244
345
|
```
|
245
346
|
|
@@ -257,6 +358,9 @@ type ModalProps = {
|
|
257
358
|
- `react-cam-roi-modal-title`
|
258
359
|
- `react-cam-roi-modal-title-light`
|
259
360
|
- `react-cam-roi-modal-title-dark`
|
361
|
+
- `react-cam-roi-modal-footer`
|
362
|
+
- `react-cam-roi-modal-footer-light`
|
363
|
+
- `react-cam-roi-modal-footer-dark`
|
260
364
|
|
261
365
|
#### Typography
|
262
366
|
|
@@ -268,6 +372,7 @@ type TypographyProps = {
|
|
268
372
|
variant?: any // compatible with mui
|
269
373
|
component?: any // compatible with mui
|
270
374
|
className?: string
|
375
|
+
style?: React.CSSProperties
|
271
376
|
}
|
272
377
|
```
|
273
378
|
|
@@ -278,10 +383,18 @@ type TypographyProps = {
|
|
278
383
|
```ts
|
279
384
|
type IconButtonProps = {
|
280
385
|
children?: React.ReactNode
|
386
|
+
disabled?: boolean
|
281
387
|
onClick?: (event: React.MouseEvent) => void
|
282
388
|
}
|
283
389
|
```
|
284
390
|
|
391
|
+
##### Classes
|
392
|
+
|
393
|
+
- `react-cam-roi-icon-button`
|
394
|
+
- `react-cam-roi-icon-button-light`
|
395
|
+
- `react-cam-roi-icon-button-dark`
|
396
|
+
- `react-cam-roi-icon-button-disabled`
|
397
|
+
|
285
398
|
#### DeleteIcon
|
286
399
|
|
287
400
|
##### Interface
|
@@ -330,11 +443,186 @@ type CopyIconProps = {
|
|
330
443
|
|
331
444
|
##### Interface
|
332
445
|
|
333
|
-
|
446
|
+
```ts
|
334
447
|
type AnnotateIconProps = {
|
335
448
|
color?: string
|
336
449
|
style?: React.CSSProperties
|
337
450
|
}
|
451
|
+
```
|
452
|
+
#### SaveIcon
|
453
|
+
|
454
|
+
##### Interface
|
455
|
+
|
456
|
+
```ts
|
457
|
+
type SaveIconProps = {
|
458
|
+
color?: string
|
459
|
+
style?: React.CSSProperties
|
460
|
+
}
|
461
|
+
```
|
462
|
+
|
463
|
+
#### TextField
|
464
|
+
|
465
|
+
##### Interface
|
466
|
+
|
467
|
+
```ts
|
468
|
+
type TextFieldProps = {
|
469
|
+
type?: 'text' | 'email' | 'password'
|
470
|
+
onChange: (value: string) => void
|
471
|
+
value: string
|
472
|
+
label: string
|
473
|
+
helperText?: string
|
474
|
+
error?: boolean
|
475
|
+
required?: boolean
|
476
|
+
readOnly?: boolean
|
477
|
+
disabled?: boolean
|
478
|
+
}
|
479
|
+
```
|
480
|
+
|
481
|
+
##### Classes
|
482
|
+
|
483
|
+
|
484
|
+
- `react-cam-roi-text-field-wrapper`
|
485
|
+
- `react-cam-roi-text-field-wrapper-light`
|
486
|
+
- `react-cam-roi-text-field-wrapper-dark`
|
487
|
+
- `react-cam-roi-text-field`
|
488
|
+
- `react-cam-roi-text-field--light`
|
489
|
+
- `react-cam-roi-text-field--dark`
|
490
|
+
- `react-cam-roi-text-field--error`
|
491
|
+
- `react-cam-roi-text-field-label`
|
492
|
+
- `react-cam-roi-text-field-label-light`
|
493
|
+
- `react-cam-roi-text-field-label-dark`
|
494
|
+
- `react-cam-roi-text-field-label-error`
|
495
|
+
- `react-cam-roi-text-field-helper-text`
|
496
|
+
- `react-cam-roi-text-field-helper-text-light`
|
497
|
+
- `react-cam-roi-text-field-helper-text-dark`
|
498
|
+
- `react-cam-roi-text-field-helper-text-error`
|
499
|
+
|
500
|
+
#### NumberField
|
501
|
+
|
502
|
+
##### Interface
|
503
|
+
|
504
|
+
```ts
|
505
|
+
type NumberFieldProps = {
|
506
|
+
onChange: (value: number) => void
|
507
|
+
value: number
|
508
|
+
label: string
|
509
|
+
helperText?: string
|
510
|
+
error?: boolean
|
511
|
+
required?: boolean
|
512
|
+
readOnly?: boolean
|
513
|
+
disabled?: boolean
|
514
|
+
}
|
515
|
+
```
|
516
|
+
|
517
|
+
##### Classes
|
518
|
+
|
519
|
+
- `react-cam-roi-number-field-wrapper`
|
520
|
+
- `react-cam-roi-number-field-wrapper-light`
|
521
|
+
- `react-cam-roi-number-field-wrapper-dark`
|
522
|
+
- `react-cam-roi-number-field`
|
523
|
+
- `react-cam-roi-number-field--light`
|
524
|
+
- `react-cam-roi-number-field--dark`
|
525
|
+
- `react-cam-roi-number-field--error`
|
526
|
+
- `react-cam-roi-number-field-label`
|
527
|
+
- `react-cam-roi-number-field-label-light`
|
528
|
+
- `react-cam-roi-number-field-label-dark`
|
529
|
+
- `react-cam-roi-number-field-label-error`
|
530
|
+
- `react-cam-roi-number-field-helper-text`
|
531
|
+
- `react-cam-roi-number-field-helper-text-light`
|
532
|
+
- `react-cam-roi-number-field-helper-text-dark`
|
533
|
+
- `react-cam-roi-number-field-helper-text-error`
|
534
|
+
|
535
|
+
#### BoolField
|
536
|
+
|
537
|
+
##### Interface
|
538
|
+
|
539
|
+
```ts
|
540
|
+
type BoolFieldProps = {
|
541
|
+
onChange: (value: boolean) => void
|
542
|
+
value: boolean
|
543
|
+
label: string
|
544
|
+
helperText?: string
|
545
|
+
error?: boolean
|
546
|
+
required?: boolean
|
547
|
+
readOnly?: boolean
|
548
|
+
disabled?: boolean
|
549
|
+
}
|
550
|
+
```
|
551
|
+
|
552
|
+
##### Classes
|
553
|
+
|
554
|
+
- `react-cam-roi-bool-field-wrapper`
|
555
|
+
- `react-cam-roi-bool-field-wrapper-light`
|
556
|
+
- `react-cam-roi-bool-field-wrapper-dark`
|
557
|
+
- `react-cam-roi-bool-field`
|
558
|
+
- `react-cam-roi-bool-field--light`
|
559
|
+
- `react-cam-roi-bool-field--dark`
|
560
|
+
- `react-cam-roi-bool-field--error`
|
561
|
+
- `react-cam-roi-bool-field-label`
|
562
|
+
- `react-cam-roi-bool-field-label-light`
|
563
|
+
- `react-cam-roi-bool-field-label-dark`
|
564
|
+
- `react-cam-roi-bool-field-label-error`
|
565
|
+
- `react-cam-roi-bool-field-helper-text`
|
566
|
+
- `react-cam-roi-bool-field-helper-text-light`
|
567
|
+
- `react-cam-roi-bool-field-helper-text-dark`
|
568
|
+
- `react-cam-roi-bool-field-helper-text-error`
|
569
|
+
|
570
|
+
#### EnumField
|
571
|
+
|
572
|
+
##### Interface
|
573
|
+
|
574
|
+
```ts
|
575
|
+
type EnumFieldProps = {
|
576
|
+
onChange: (value: string | number | (string | number)[]) => void
|
577
|
+
value: string | number | (string | number)[]
|
578
|
+
label: string
|
579
|
+
helperText?: string
|
580
|
+
error?: boolean
|
581
|
+
required?: boolean
|
582
|
+
multiple?: boolean
|
583
|
+
disabled?: boolean
|
584
|
+
}
|
585
|
+
```
|
586
|
+
|
587
|
+
##### Classes
|
588
|
+
|
589
|
+
- `react-cam-roi-enum-field-wrapper`
|
590
|
+
- `react-cam-roi-enum-field-wrapper-light`
|
591
|
+
- `react-cam-roi-enum-field-wrapper-dark`
|
592
|
+
- `react-cam-roi-enum-field`
|
593
|
+
- `react-cam-roi-enum-field--light`
|
594
|
+
- `react-cam-roi-enum-field--dark`
|
595
|
+
- `react-cam-roi-enum-field--error`
|
596
|
+
- `react-cam-roi-enum-field-label`
|
597
|
+
- `react-cam-roi-enum-field-label-light`
|
598
|
+
- `react-cam-roi-enum-field-label-dark`
|
599
|
+
- `react-cam-roi-enum-field-label-error`
|
600
|
+
- `react-cam-roi-enum-field-helper-text`
|
601
|
+
- `react-cam-roi-enum-field-helper-text-light`
|
602
|
+
- `react-cam-roi-enum-field-helper-text-dark`
|
603
|
+
- `react-cam-roi-enum-field-helper-text-error`
|
604
|
+
|
605
|
+
|
606
|
+
#### Button
|
607
|
+
|
608
|
+
##### Interface
|
609
|
+
|
610
|
+
```ts
|
611
|
+
type ButtonProps = {
|
612
|
+
onClick: (event: React.MouseEvent) => void
|
613
|
+
primary?: boolean
|
614
|
+
disabled?: boolean
|
615
|
+
}
|
616
|
+
```
|
617
|
+
|
618
|
+
##### Classes
|
619
|
+
|
620
|
+
- `react-cam-roi-button`
|
621
|
+
- `react-cam-roi-button-light`
|
622
|
+
- `react-cam-roi-button-dark`
|
623
|
+
- `react-cam-roi-button-disabled`
|
624
|
+
- `react-cam-roi-button-disabled-light`
|
625
|
+
- `react-cam-roi-button-disabled-dark`
|
338
626
|
|
339
627
|
### Functions
|
340
628
|
|
@@ -345,7 +633,7 @@ type INotify = { // compatible with toast (react-toastify)
|
|
345
633
|
error: (message: string) => void
|
346
634
|
success: (message: string) => void
|
347
635
|
}
|
348
|
-
|
636
|
+
```
|
349
637
|
|
350
638
|
### Styles
|
351
639
|
|
@@ -359,6 +647,10 @@ There are components that cannot be overridden. But still you can use classes to
|
|
359
647
|
|
360
648
|
#### Toolbar
|
361
649
|
|
650
|
+
- `react-cam-roi-toolbar-info`
|
651
|
+
- `react-cam-roi-toolbar-info-light`
|
652
|
+
- `react-cam-roi-toolbar-info-dark`
|
653
|
+
|
362
654
|
- `react-cam-roi-toolbar`
|
363
655
|
- `react-cam-roi-toolbar-light`
|
364
656
|
- `react-cam-roi-toolbar-dark`
|
@@ -389,6 +681,10 @@ There are components that cannot be overridden. But still you can use classes to
|
|
389
681
|
- `react-cam-roi-colorpicker-button-active-light`
|
390
682
|
- `react-cam-roi-colorpicker-button-active-dark`
|
391
683
|
|
684
|
+
#### Form
|
685
|
+
|
686
|
+
- `react-cam-roi-form`
|
687
|
+
|
392
688
|
## Development
|
393
689
|
|
394
690
|
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;
|