@visns-studio/visns-components 4.10.47 → 5.0.0

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 (41) hide show
  1. package/package.json +28 -30
  2. package/src/components/cms/Field.jsx +39 -63
  3. package/src/components/crm/Breadcrumb.jsx +2 -18
  4. package/src/components/crm/DataGrid.jsx +23 -379
  5. package/src/components/crm/Field.jsx +16 -215
  6. package/src/components/crm/Form.jsx +81 -79
  7. package/src/components/crm/MultiSelect.jsx +25 -71
  8. package/src/components/crm/Navigation.jsx +7 -11
  9. package/src/components/crm/QrCode.jsx +8 -12
  10. package/src/components/crm/QuickAction.jsx +1 -0
  11. package/src/components/crm/generic/GenericAuth.jsx +2 -6
  12. package/src/components/crm/generic/GenericDashboard.jsx +30 -340
  13. package/src/components/crm/generic/GenericDetail.jsx +37 -80
  14. package/src/components/crm/generic/GenericDynamic.jsx +76 -94
  15. package/src/components/crm/generic/GenericFormBuilder.jsx +19 -79
  16. package/src/components/crm/generic/GenericIndex.jsx +1 -2
  17. package/src/components/crm/generic/styles/GenericDetail.module.scss +0 -51
  18. package/src/components/crm/generic/styles/GenericFormBuilder.module.scss +0 -5
  19. package/src/components/crm/styles/DataGrid.module.scss +25 -0
  20. package/src/components/crm/styles/Field.module.scss +0 -210
  21. package/src/components/crm/styles/Form.module.scss +0 -78
  22. package/src/components/crm/styles/Navigation.module.scss +4 -10
  23. package/src/components/crm/styles/QrCode.module.scss +0 -18
  24. package/src/index.js +0 -8
  25. package/src/components/crm/generic/styles/GenericDashboard.module.scss +0 -325
  26. package/src/components/crm/sketch/SketchField.jsx +0 -395
  27. package/src/components/crm/sketch/arrow.jsx +0 -108
  28. package/src/components/crm/sketch/circle.jsx +0 -75
  29. package/src/components/crm/sketch/default-tool.jsx +0 -16
  30. package/src/components/crm/sketch/fabrictool.jsx +0 -22
  31. package/src/components/crm/sketch/history.jsx +0 -144
  32. package/src/components/crm/sketch/json/config.json +0 -14
  33. package/src/components/crm/sketch/line.jsx +0 -64
  34. package/src/components/crm/sketch/pan.jsx +0 -48
  35. package/src/components/crm/sketch/pencil.jsx +0 -36
  36. package/src/components/crm/sketch/rectangle-label-object.jsx +0 -69
  37. package/src/components/crm/sketch/rectangle-label.jsx +0 -93
  38. package/src/components/crm/sketch/rectangle.jsx +0 -76
  39. package/src/components/crm/sketch/select.jsx +0 -16
  40. package/src/components/crm/sketch/tools.jsx +0 -11
  41. package/src/components/crm/sketch/utils.jsx +0 -67
@@ -1,325 +0,0 @@
1
- body {
2
- min-height: 100vh;
3
- background: var(--bg);
4
- }
5
-
6
- .grid {
7
- display: flex;
8
- flex-direction: column;
9
- gap: 2rem;
10
- padding: 2rem;
11
- }
12
-
13
- .filterContainer {
14
- background: #ffffff; // White background for contrast
15
- border: 1px solid #dadce0; // Subtle border for separation
16
- border-radius: 8px; // Rounded corners
17
- padding: 1.5rem;
18
- margin-bottom: 1.5rem; // Spacing below the filter section
19
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); // Subtle shadow for depth
20
- }
21
-
22
- .filterHeader {
23
- text-align: left;
24
- margin-bottom: 1rem;
25
-
26
- h3 {
27
- font-size: 1.25rem;
28
- font-weight: 600;
29
- color: #333;
30
- margin: 0;
31
- }
32
- }
33
-
34
- .filterFields {
35
- display: flex;
36
- flex-wrap: wrap;
37
- gap: 1rem; // Gap between fields
38
- align-items: flex-end; // Align fields vertically
39
- }
40
-
41
- .filterField {
42
- flex: 1; // Ensures equal spacing for each field
43
- display: flex;
44
- flex-direction: column;
45
- min-width: 200px; // Sets a minimum width for smaller screens
46
-
47
- label {
48
- font-size: 0.875rem;
49
- font-weight: 600;
50
- margin-bottom: 0.5rem;
51
- color: #555;
52
- }
53
-
54
- input,
55
- select {
56
- border: 1px solid #dadce0;
57
- border-radius: 5px;
58
- padding: 0.5rem 0.75rem;
59
- font-size: 0.875rem;
60
- color: #333;
61
- outline: none;
62
- background-color: #f9f9f9;
63
- width: 100%; // Ensures full width within the container
64
- height: 51px;
65
-
66
- &:focus {
67
- border-color: #007bff;
68
- box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25); // Focus effect
69
- }
70
- }
71
- }
72
-
73
- .filterActions {
74
- display: flex;
75
- gap: 0.75rem; // Gap between buttons
76
-
77
- .btn {
78
- padding: 0.5rem 1rem;
79
- border-radius: 5px;
80
- font-size: 0.875rem;
81
- font-weight: 600;
82
- text-transform: uppercase;
83
- cursor: pointer;
84
- transition: background-color 0.2s;
85
- height: 51px;
86
-
87
- &.btn-primary {
88
- background-color: #007bff;
89
- color: #fff;
90
- border: none;
91
-
92
- &:hover {
93
- background-color: #0056b3;
94
- }
95
- }
96
-
97
- &.btn-secondary {
98
- background-color: #f8f9fa;
99
- color: #333;
100
- border: 1px solid #ccc;
101
-
102
- &:hover {
103
- background-color: #e2e6ea;
104
- }
105
- }
106
- }
107
- }
108
-
109
- .widgetTitle {
110
- width: 100%;
111
- height: auto;
112
- padding: 0 0 1em 0;
113
- margin-bottom: 1em;
114
- border-bottom: 1px dashed #dadce0;
115
-
116
- h2 {
117
- font-size: 1.375em;
118
- font-weight: 700;
119
- margin: 0;
120
- padding: 0;
121
- line-height: 1;
122
- text-transform: capitalize;
123
- text-align: left;
124
- }
125
- }
126
-
127
- .dashList {
128
- width: 100%;
129
- display: flex;
130
- flex-wrap: wrap;
131
- list-style: none;
132
- padding: 0;
133
- margin: 0;
134
-
135
- li {
136
- width: 100%;
137
- padding: 0;
138
- margin: 0;
139
-
140
- &:first-child {
141
- button {
142
- border-top-left-radius: var(--br);
143
- border-top-right-radius: var(--br);
144
- }
145
- }
146
-
147
- &:last-child {
148
- margin-bottom: 0;
149
-
150
- button {
151
- border-bottom-left-radius: var(--br);
152
- border-bottom-right-radius: var(--br);
153
- border-bottom: 1px solid #dadce0;
154
- }
155
- }
156
-
157
- a {
158
- text-decoration: none;
159
- }
160
-
161
- button {
162
- width: 100%;
163
- display: block;
164
- background: white;
165
- border: 1px solid #dadce0;
166
- border-bottom: none;
167
- outline: none;
168
- padding: 0.5rem 1rem;
169
- color: var(--paragraph-color);
170
- text-align: left;
171
- transition: all 0.25s cubic-bezier(0.25, 0.8, 0.25, 1);
172
- letter-spacing: 0.018em;
173
-
174
- &:hover {
175
- background: rgba(var(--secondary-color), 0.05);
176
- transition: all 0.25s cubic-bezier(0.25, 0.8, 0.25, 1);
177
- }
178
-
179
- strong {
180
- color: var(--paragraph-color);
181
- }
182
-
183
- span {
184
- color: rgba(var(--secondary-color-rgb), 1.1);
185
- float: right;
186
- }
187
- }
188
- }
189
- }
190
-
191
- .grid__row {
192
- width: 100%;
193
- display: flex;
194
- align-items: flex-start;
195
- flex-wrap: nowrap;
196
- height: auto;
197
- gap: 1rem;
198
- }
199
-
200
- .grid__dashfull {
201
- width: 100%;
202
- background: var(--item-color);
203
- border-radius: var(--br);
204
- border: 1px solid rgba(var(--item-color-rgb), 1.15);
205
- box-sizing: border-box;
206
- padding: 20px;
207
- margin: 8px 0;
208
- box-shadow: 0 4px 0 rgba(var(--primary-color-rgb), 0.05);
209
- }
210
-
211
- .tableContainer {
212
- margin-top: 20px;
213
- border: 1px solid #dadce0;
214
- border-radius: 8px;
215
- overflow: hidden;
216
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
217
- }
218
-
219
- .tableContainer table {
220
- width: 100%;
221
- border-collapse: collapse;
222
- text-align: left;
223
- background-color: #ffffff;
224
- }
225
-
226
- .tableContainer th {
227
- background-color: #f6f8fa;
228
- color: #333;
229
- font-weight: bold;
230
- padding: 12px 15px;
231
- border-bottom: 1px solid #dadce0;
232
- text-transform: capitalize;
233
- font-size: 14px;
234
- }
235
-
236
- .tableContainer td {
237
- padding: 10px 15px;
238
- border-bottom: 1px solid #eaeaea;
239
- font-size: 13px;
240
- color: #555;
241
- text-align: center;
242
- }
243
-
244
- .tableContainer tbody tr:hover {
245
- background-color: #f9f9f9;
246
- }
247
-
248
- .tableContainer tbody tr:nth-child(even) {
249
- background-color: #f7f7f7;
250
- }
251
-
252
- .tableContainer th:first-child,
253
- .tableContainer td:first-child {
254
- text-align: left;
255
- font-weight: bold;
256
- padding-left: 20px;
257
- }
258
-
259
- .tableContainer td:last-child {
260
- border-right: none;
261
- }
262
-
263
- .tableContainer th:last-child {
264
- border-right: none;
265
- }
266
-
267
- .dashwidget {
268
- background: var(--primary-color) !important;
269
- border-top: 1px solid transparent !important;
270
- border-left: 1px solid transparent !important;
271
- border-right: 1px solid transparent !important;
272
- border-bottom: 4px solid rgba(var(--primary-color-rgb), 0.9) !important;
273
-
274
- h2 {
275
- color: var(--highlight-color) !important;
276
- }
277
-
278
- .widgetTitle {
279
- border-bottom: 1px dashed rgba(#dadce0, 0.15);
280
- }
281
- }
282
-
283
- .grid__contentlist {
284
- li {
285
- position: relative;
286
-
287
- &:hover {
288
- .edititem {
289
- opacity: 1;
290
- transition: opacity 0.15s cubic-bezier(0.25, 0.8, 0.25, 1);
291
- }
292
- }
293
-
294
- .edititem {
295
- position: absolute;
296
- right: 0;
297
- text-decoration: none;
298
- opacity: 0;
299
- transition: opacity 0.15s cubic-bezier(0.25, 0.8, 0.25, 1);
300
- }
301
- }
302
- }
303
-
304
- .react-datepicker__month-select,
305
- .react-datepicker__year-select {
306
- padding: 0.5em 0.85em;
307
- }
308
-
309
- .react-confirm-alert-overlay {
310
- z-index: 999 !important;
311
- }
312
-
313
- .polActions {
314
- position: fixed;
315
- bottom: 15px;
316
- right: 20px;
317
- width: auto;
318
-
319
- button {
320
- display: block;
321
- float: left;
322
- padding: 0.35em 1em;
323
- margin: 0 0.15em;
324
- }
325
- }
@@ -1,395 +0,0 @@
1
- import React, { PureComponent } from 'react';
2
- import PropTypes from 'prop-types';
3
- import History from './history';
4
- import Select from './select';
5
- import Pencil from './pencil';
6
- import Line from './line';
7
- import Arrow from './arrow';
8
- import Rectangle from './rectangle';
9
- import Circle from './circle';
10
- import Pan from './pan';
11
- import Tool from './tools';
12
- import RectangleLabel from './rectangle-label';
13
- import DefaultTool from './default-tool';
14
- import * as fabric from 'fabric'; // v6
15
- import { toast } from 'react-toastify'; // Import toast
16
-
17
- // Debounce function
18
- function debounce(func, delay) {
19
- let timeout;
20
- return (...args) => {
21
- clearTimeout(timeout);
22
- timeout = setTimeout(() => func.apply(this, args), delay);
23
- };
24
- }
25
-
26
- class SketchField extends PureComponent {
27
- static propTypes = {
28
- lineColor: PropTypes.string,
29
- lineWidth: PropTypes.number,
30
- lineRadius: PropTypes.number,
31
- fillColor: PropTypes.string,
32
- backgroundColor: PropTypes.string,
33
- backgroundImage: PropTypes.string,
34
- opacity: PropTypes.number,
35
- undoSteps: PropTypes.number,
36
- tool: PropTypes.string,
37
- imageFormat: PropTypes.string,
38
- value: PropTypes.object,
39
- forceValue: PropTypes.bool,
40
- widthCorrection: PropTypes.number,
41
- heightCorrection: PropTypes.number,
42
- onChange: PropTypes.func,
43
- defaultValue: PropTypes.object,
44
- width: PropTypes.number,
45
- height: PropTypes.number,
46
- onObjectAdded: PropTypes.func,
47
- onObjectModified: PropTypes.func,
48
- onObjectRemoved: PropTypes.func,
49
- className: PropTypes.string,
50
- style: PropTypes.object,
51
- };
52
-
53
- static defaultProps = {
54
- lineColor: 'black',
55
- lineWidth: 10,
56
- lineRadius: 10,
57
- fillColor: 'transparent',
58
- backgroundColor: 'transparent',
59
- opacity: 1.0,
60
- undoSteps: 25,
61
- tool: null,
62
- widthCorrection: 0,
63
- heightCorrection: 0,
64
- forceValue: false,
65
- onObjectAdded: () => null,
66
- onObjectModified: () => null,
67
- onObjectRemoved: () => null,
68
- };
69
-
70
- _initTools = (fabricCanvas) => {
71
- this._tools = {
72
- [Tool.Select]: new Select(fabricCanvas),
73
- [Tool.Pencil]: new Pencil(fabricCanvas),
74
- [Tool.Line]: new Line(fabricCanvas),
75
- [Tool.Arrow]: new Arrow(fabricCanvas),
76
- [Tool.Rectangle]: new Rectangle(fabricCanvas),
77
- [Tool.RectangleLabel]: new RectangleLabel(fabricCanvas),
78
- [Tool.Circle]: new Circle(fabricCanvas),
79
- [Tool.Pan]: new Pan(fabricCanvas),
80
- [Tool.DefaultTool]: new DefaultTool(fabricCanvas),
81
- };
82
- };
83
-
84
- setBackgroundImage = async (imageUrl) => {
85
- try {
86
- const img = await fabric.Image.fromURL(imageUrl, {
87
- crossOrigin: 'anonymous', // Enable CORS
88
- });
89
-
90
- const imgWidth = img.width;
91
- const imgHeight = img.height;
92
-
93
- // Get the aspect ratio of the image
94
- const aspectRatio = imgWidth / imgHeight;
95
-
96
- // Calculate the new canvas dimensions based on aspect ratio
97
- const { width, height } = this.props; // Default width and height
98
-
99
- let newWidth, newHeight;
100
- if (aspectRatio > 1) {
101
- // Landscape orientation: Set width to max and adjust height
102
- newWidth = width;
103
- newHeight = width / aspectRatio;
104
- } else {
105
- // Portrait orientation: Set height to max and adjust width
106
- newHeight = height;
107
- newWidth = height * aspectRatio;
108
- }
109
-
110
- // Set the new canvas dimensions
111
- this._fc.setWidth(newWidth);
112
- this._fc.setHeight(newHeight);
113
-
114
- // Scale the image to fit the canvas dimensions
115
- img.scaleToWidth(newWidth);
116
- img.scaleToHeight(newHeight);
117
-
118
- // Center the image both horizontally and vertically
119
- img.set({
120
- left: (newWidth - img.getScaledWidth()) / 2,
121
- top: (newHeight - img.getScaledHeight()) / 2,
122
- selectable: false,
123
- evented: false,
124
- });
125
-
126
- // Set the image as the background directly
127
- this._fc.backgroundImage = img;
128
-
129
- // Render the canvas to apply changes
130
- this._fc.requestRenderAll();
131
- } catch (error) {
132
- console.error('Failed to load background image:', error);
133
- }
134
- };
135
-
136
- saveCanvasState = () => {
137
- // Return the current state of the canvas as JSON
138
- const state = this._fc.toJSON();
139
- const backgroundImage = this._fc.backgroundImage
140
- ? {
141
- src: this._fc.backgroundImage._element.src,
142
- left: this._fc.backgroundImage.left,
143
- top: this._fc.backgroundImage.top,
144
- scaleX: this._fc.backgroundImage.scaleX,
145
- scaleY: this._fc.backgroundImage.scaleY,
146
- }
147
- : null;
148
-
149
- return {
150
- state,
151
- backgroundImage,
152
- };
153
- };
154
-
155
- exportCanvasImage = async (format = 'png') => {
156
- // Ensure all images are loaded with CORS
157
- const imageObjects = this._fc.getObjects('image');
158
- for (const imgObj of imageObjects) {
159
- if (imgObj.crossOrigin !== 'anonymous') {
160
- // Set crossOrigin for images that are not set
161
- imgObj.set({ crossOrigin: 'anonymous' });
162
- }
163
- }
164
-
165
- // Get the Base64 representation of the canvas image
166
- const dataURL = this._fc.toDataURL({
167
- format: format,
168
- quality: 0.8,
169
- });
170
-
171
- // Return the Base64 string
172
- return dataURL; // This returns a promise
173
- };
174
-
175
- clearCanvas = () => {
176
- // Clear all objects from the canvas while keeping the background image
177
- const backgroundImage = this._fc.backgroundImage;
178
- this._fc.clear();
179
-
180
- // Restore the background image after clearing
181
- if (backgroundImage) {
182
- this._fc.backgroundImage = backgroundImage;
183
- }
184
- this._fc.renderAll(); // Re-render to show the background image
185
- };
186
-
187
- _resize = (e) => {
188
- const { widthCorrection, heightCorrection } = this.props;
189
- const canvas = this._fc;
190
-
191
- const { offsetWidth, clientHeight } = this._container;
192
- const wfactor = (offsetWidth - widthCorrection) / canvas.width;
193
- const hfactor = (clientHeight - heightCorrection) / canvas.height;
194
-
195
- canvas.setWidth(offsetWidth - widthCorrection);
196
- canvas.setHeight(clientHeight - heightCorrection);
197
-
198
- canvas.getObjects().forEach((obj) => {
199
- obj.scaleX *= wfactor;
200
- obj.scaleY *= hfactor;
201
- obj.left *= wfactor;
202
- obj.top *= hfactor;
203
- obj.setCoords();
204
- });
205
-
206
- this.setState({ parentWidth: offsetWidth });
207
- canvas.requestRenderAll();
208
- };
209
-
210
- _backgroundColor = (color) => {
211
- if (this._fc && color) {
212
- this._fc.backgroundColor = color;
213
- this._fc.requestRenderAll();
214
- }
215
- };
216
-
217
- undo = () => {
218
- if (this._history && this._history.canUndo()) {
219
- const previousState = this._history.undo();
220
- if (previousState) {
221
- // Restore the previous state
222
- this.fromJSON(previousState.state);
223
- // Reapply the background image after undoing
224
- if (previousState.backgroundImage) {
225
- this.setBackgroundImage(previousState.backgroundImage.src);
226
- }
227
- } else {
228
- this._fc.clear(); // If no previous state, clear the canvas
229
-
230
- this.setBackgroundImage(this.props.backgroundImage);
231
- }
232
- this._fc.renderAll(); // Re-render canvas
233
- this.props.onChange && this.props.onChange();
234
- }
235
- };
236
-
237
- redo = () => {
238
- if (this._history && this._history.canRedo()) {
239
- const nextState = this._history.redo();
240
- if (nextState) {
241
- this.fromJSON(nextState.state);
242
- // Reapply the background image after redoing
243
- if (nextState.backgroundImage) {
244
- this.setBackgroundImage(nextState.backgroundImage.src);
245
- }
246
- this._fc.renderAll(); // Re-render canvas
247
- this.props.onChange && this.props.onChange();
248
- }
249
- }
250
- };
251
-
252
- fromJSON = (json) => {
253
- if (!json) return;
254
- this._fc.loadFromJSON(json, () => {
255
- this._fc.requestRenderAll();
256
- this.props.onChange && this.props.onChange();
257
- });
258
- };
259
-
260
- componentDidMount = () => {
261
- const {
262
- tool,
263
- undoSteps,
264
- backgroundColor,
265
- width = 800,
266
- height = 600,
267
- backgroundImage,
268
- defaultValue,
269
- } = this.props;
270
-
271
- this._fc = new fabric.Canvas(this._canvas);
272
- this._fc.setWidth(width);
273
- this._fc.setHeight(height);
274
-
275
- this._initTools(this._fc);
276
- this._backgroundColor(backgroundColor);
277
-
278
- const selectedTool = this._tools[tool];
279
- if (selectedTool) {
280
- selectedTool.configureCanvas(this.props);
281
- selectedTool.attachListeners();
282
- }
283
- this._selectedTool = selectedTool;
284
-
285
- window.addEventListener('resize', this._resize, false);
286
-
287
- this._history = new History(undoSteps);
288
-
289
- this._fc.on('object:added', this._captureState);
290
- this._fc.on('object:modified', this._captureState);
291
- this._fc.on('object:removed', this._captureState);
292
-
293
- this.setState({ canvasReady: true }, () => {
294
- // Load the defaultValue to set the initial state of the canvas
295
- if (defaultValue) {
296
- // Show loading toast
297
- setTimeout(() => {
298
- this.fromJSON(defaultValue);
299
- }, 1000);
300
- } else {
301
- if (backgroundImage) {
302
- this.setBackgroundImage(backgroundImage);
303
- }
304
- }
305
- });
306
-
307
- // Load the defaultValue to set the initial state of the canvas
308
- if (defaultValue) {
309
- // Show loading toast
310
- const toastId = toast.loading('Loading Canvas...');
311
- setTimeout(() => {
312
- this.fromJSON(defaultValue);
313
- // Update toast after loading is done
314
- toast.update(toastId, {
315
- render: 'Saved Canvas loaded!',
316
- type: 'success',
317
- isLoading: false,
318
- autoClose: 2000,
319
- });
320
- }, 1000);
321
- } else {
322
- if (backgroundImage) {
323
- this.setBackgroundImage(backgroundImage);
324
- }
325
- }
326
- };
327
-
328
- _captureState = debounce(() => {
329
- if (this._history && this._fc) {
330
- const state = this._fc.toJSON();
331
- const backgroundImage = this._fc.backgroundImage
332
- ? {
333
- src: this._fc.backgroundImage._element.src,
334
- left: this._fc.backgroundImage.left,
335
- top: this._fc.backgroundImage.top,
336
- scaleX: this._fc.backgroundImage.scaleX,
337
- scaleY: this._fc.backgroundImage.scaleY,
338
- }
339
- : null;
340
-
341
- this._history.keep({
342
- state,
343
- backgroundImage,
344
- });
345
- }
346
- }, 300);
347
-
348
- componentWillUnmount = () => {
349
- window.removeEventListener('resize', this._resize);
350
- };
351
-
352
- componentDidUpdate = (prevProps) => {
353
- if (this.props.tool !== prevProps.tool) {
354
- if (this._selectedTool) {
355
- this._selectedTool.detachListeners();
356
- }
357
-
358
- this._selectedTool = this._tools[this.props.tool];
359
- this._selectedTool.configureCanvas(this.props);
360
- this._selectedTool.attachListeners();
361
- }
362
-
363
- if (this.props.backgroundColor !== prevProps.backgroundColor) {
364
- this._backgroundColor(this.props.backgroundColor);
365
- }
366
-
367
- if (this.props.defaultValue !== prevProps.defaultValue) {
368
- this.fromJSON(this.props.defaultValue);
369
- } else {
370
- if (this.props.backgroundImage !== prevProps.backgroundImage) {
371
- this.setBackgroundImage(this.props.backgroundImage);
372
- }
373
- }
374
- };
375
-
376
- render() {
377
- const { className, style, width = 800, height = 600 } = this.props;
378
- const canvasDivStyle = { ...style, width, height };
379
-
380
- return (
381
- <div
382
- className={className}
383
- ref={(c) => (this._container = c)}
384
- style={canvasDivStyle}
385
- >
386
- <canvas ref={(c) => (this._canvas = c)}>
387
- Sorry, Canvas HTML5 element is not supported by your
388
- browser.
389
- </canvas>
390
- </div>
391
- );
392
- }
393
- }
394
-
395
- export default SketchField;