@visns-studio/visns-components 4.10.48 → 5.0.1-8.1

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 (61) hide show
  1. package/package.json +29 -29
  2. package/src/components/cms/Field.jsx +39 -63
  3. package/src/components/crm/AsyncSelect.jsx +121 -15
  4. package/src/components/crm/Breadcrumb.jsx +2 -18
  5. package/src/components/crm/DataGrid.jsx +51 -424
  6. package/src/components/crm/Field.jsx +185 -358
  7. package/src/components/crm/Form.jsx +104 -92
  8. package/src/components/crm/MultiSelect.jsx +66 -45
  9. package/src/components/crm/Navigation.jsx +9 -92
  10. package/src/components/crm/QuickAction.jsx +1 -0
  11. package/src/components/crm/auth/Login.jsx +9 -1
  12. package/src/components/crm/auth/Profile.jsx +4 -2
  13. package/src/components/crm/auth/styles/Login.module.scss +52 -82
  14. package/src/components/crm/auth/styles/Profile.module.scss +150 -44
  15. package/src/components/crm/auth/styles/Reset.module.scss +55 -37
  16. package/src/components/crm/auth/styles/Verify.module.scss +55 -76
  17. package/src/components/crm/generic/GenericAuth.jsx +12 -5
  18. package/src/components/crm/generic/GenericDashboard.jsx +30 -340
  19. package/src/components/crm/generic/GenericDetail.jsx +534 -86
  20. package/src/components/crm/generic/GenericDynamic.jsx +76 -94
  21. package/src/components/crm/generic/GenericEditableTable.jsx +407 -0
  22. package/src/components/crm/generic/GenericFormBuilder.jsx +19 -79
  23. package/src/components/crm/generic/GenericIndex.jsx +1 -2
  24. package/src/components/crm/generic/styles/AuditLog.module.scss +4 -37
  25. package/src/components/crm/generic/styles/AuditLogs.module.scss +0 -51
  26. package/src/components/crm/generic/styles/GenericDetail.module.scss +263 -244
  27. package/src/components/crm/generic/styles/GenericDynamic.module.scss +100 -198
  28. package/src/components/crm/generic/styles/GenericEditableTable.module.scss +178 -0
  29. package/src/components/crm/generic/styles/GenericFormBuilder.module.scss +63 -101
  30. package/src/components/crm/generic/styles/GenericIndex.module.scss +46 -66
  31. package/src/components/crm/generic/styles/GenericMain.module.scss +7 -7
  32. package/src/components/crm/generic/styles/GenericSort.module.scss +0 -36
  33. package/src/components/crm/generic/styles/NotificationList.module.scss +1 -32
  34. package/src/components/crm/styles/Autocomplete.module.scss +12 -20
  35. package/src/components/crm/styles/DataGrid.module.scss +28 -86
  36. package/src/components/crm/styles/Field.module.scss +72 -252
  37. package/src/components/crm/styles/Form.module.scss +141 -450
  38. package/src/components/crm/styles/Navigation.module.scss +356 -507
  39. package/src/components/crm/styles/Notification.module.scss +1 -0
  40. package/src/components/crm/styles/QrCode.module.scss +4 -18
  41. package/src/components/crm/styles/SwitchAccount.module.scss +0 -1
  42. package/src/components/crm/styles/TableFilter.module.scss +2 -1
  43. package/src/components/styles/global.css +164 -34
  44. package/src/index.js +0 -8
  45. package/src/components/crm/generic/styles/GenericDashboard.module.scss +0 -325
  46. package/src/components/crm/sketch/SketchField.jsx +0 -395
  47. package/src/components/crm/sketch/arrow.jsx +0 -108
  48. package/src/components/crm/sketch/circle.jsx +0 -75
  49. package/src/components/crm/sketch/default-tool.jsx +0 -16
  50. package/src/components/crm/sketch/fabrictool.jsx +0 -22
  51. package/src/components/crm/sketch/history.jsx +0 -144
  52. package/src/components/crm/sketch/json/config.json +0 -14
  53. package/src/components/crm/sketch/line.jsx +0 -64
  54. package/src/components/crm/sketch/pan.jsx +0 -48
  55. package/src/components/crm/sketch/pencil.jsx +0 -36
  56. package/src/components/crm/sketch/rectangle-label-object.jsx +0 -69
  57. package/src/components/crm/sketch/rectangle-label.jsx +0 -93
  58. package/src/components/crm/sketch/rectangle.jsx +0 -76
  59. package/src/components/crm/sketch/select.jsx +0 -16
  60. package/src/components/crm/sketch/tools.jsx +0 -11
  61. package/src/components/crm/sketch/utils.jsx +0 -67
@@ -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;
@@ -1,108 +0,0 @@
1
- import FabricCanvasTool from './fabrictool';
2
- import {
3
- Line as FabricLine,
4
- Triangle as FabricTriangle,
5
- Group as FabricGroup,
6
- } from 'fabric'; // Import specific classes
7
-
8
- class Arrow extends FabricCanvasTool {
9
- configureCanvas(props) {
10
- const canvas = this._canvas;
11
-
12
- // Disable selection and set up drawing mode
13
- canvas.isDrawingMode = false;
14
- canvas.selection = false;
15
- canvas.forEachObject((o) => {
16
- o.selectable = false;
17
- o.evented = false;
18
- });
19
-
20
- // Set arrow line properties
21
- this._width = props.lineWidth || 1;
22
- this._color = props.lineColor || 'black';
23
- }
24
-
25
- doMouseDown(o) {
26
- this.isDown = true;
27
- const canvas = this._canvas;
28
-
29
- // Get initial mouse pointer position
30
- const pointer = canvas.getPointer(o.e);
31
- const points = [pointer.x, pointer.y, pointer.x, pointer.y];
32
-
33
- // Create the main line of the arrow
34
- this.line = new FabricLine(points, {
35
- strokeWidth: this._width,
36
- fill: this._color,
37
- stroke: this._color,
38
- originX: 'center',
39
- originY: 'center',
40
- selectable: false,
41
- evented: false,
42
- });
43
-
44
- // Create the arrowhead as a triangle
45
- this.head = new FabricTriangle({
46
- fill: this._color,
47
- left: pointer.x,
48
- top: pointer.y,
49
- originX: 'center',
50
- originY: 'center',
51
- height: 3 * this._width,
52
- width: 3 * this._width,
53
- selectable: false,
54
- evented: false,
55
- angle: 90,
56
- });
57
-
58
- // Add both line and head to the canvas
59
- canvas.add(this.line);
60
- canvas.add(this.head);
61
- }
62
-
63
- doMouseMove(o) {
64
- if (!this.isDown) return;
65
- const canvas = this._canvas;
66
- const pointer = canvas.getPointer(o.e);
67
-
68
- // Update the line endpoint as mouse moves
69
- this.line.set({ x2: pointer.x, y2: pointer.y });
70
- this.line.setCoords();
71
-
72
- // Calculate angle for the arrowhead to point along the line
73
- const xDelta = pointer.x - this.line.x1;
74
- const yDelta = pointer.y - this.line.y1;
75
- this.head.set({
76
- left: pointer.x,
77
- top: pointer.y,
78
- angle: 90 + (Math.atan2(yDelta, xDelta) * 180) / Math.PI,
79
- });
80
-
81
- // Render changes
82
- canvas.requestRenderAll();
83
- }
84
-
85
- doMouseUp() {
86
- this.isDown = false;
87
- const canvas = this._canvas;
88
-
89
- // Remove separate line and head and group them into an arrow
90
- canvas.remove(this.line);
91
- canvas.remove(this.head);
92
-
93
- const arrow = new FabricGroup([this.line, this.head], {
94
- selectable: true,
95
- evented: true,
96
- });
97
-
98
- // Add the grouped arrow back to the canvas
99
- canvas.add(arrow);
100
- canvas.requestRenderAll();
101
- }
102
-
103
- doMouseOut() {
104
- this.isDown = false;
105
- }
106
- }
107
-
108
- export default Arrow;
@@ -1,75 +0,0 @@
1
- import FabricCanvasTool from './fabrictool';
2
- import { Circle as FabricCircle } from 'fabric';
3
-
4
- class Circle extends FabricCanvasTool {
5
- constructor(canvas) {
6
- super(canvas);
7
- // Define event handlers as arrow functions for consistent references
8
- this.doMouseDown = (o) => this._doMouseDown(o);
9
- this.doMouseMove = (o) => this._doMouseMove(o);
10
- this.doMouseUp = () => this._doMouseUp();
11
- }
12
-
13
- configureCanvas(props) {
14
- const canvas = this._canvas;
15
- canvas.isDrawingMode = false; // Disable drawing mode for custom drawing
16
- canvas.selection = false;
17
- this._width = props.lineWidth || 2;
18
- this._color = props.lineColor || 'black';
19
- this._fill = props.fillColor || 'transparent';
20
- }
21
-
22
- attachListeners() {
23
- this._canvas.on('mouse:down', this.doMouseDown);
24
- this._canvas.on('mouse:move', this.doMouseMove);
25
- this._canvas.on('mouse:up', this.doMouseUp);
26
- }
27
-
28
- detachListeners() {
29
- this._canvas.off('mouse:down', this.doMouseDown);
30
- this._canvas.off('mouse:move', this.doMouseMove);
31
- this._canvas.off('mouse:up', this.doMouseUp);
32
- }
33
-
34
- _doMouseDown(o) {
35
- const canvas = this._canvas;
36
- this.isDown = true;
37
- const pointer = canvas.getPointer(o.e);
38
- this.startX = pointer.x;
39
- this.startY = pointer.y;
40
-
41
- this.circle = new FabricCircle({
42
- left: this.startX,
43
- top: this.startY,
44
- originX: 'center',
45
- originY: 'center',
46
- strokeWidth: this._width,
47
- stroke: this._color,
48
- fill: this._fill,
49
- radius: 1, // Start with a minimal radius, updated on `doMouseMove`
50
- selectable: false,
51
- evented: false,
52
- });
53
- canvas.add(this.circle);
54
- }
55
-
56
- _doMouseMove(o) {
57
- if (!this.isDown) return;
58
- const canvas = this._canvas;
59
- const pointer = canvas.getPointer(o.e);
60
- const radius = Math.sqrt(
61
- Math.pow(pointer.x - this.startX, 2) +
62
- Math.pow(pointer.y - this.startY, 2)
63
- );
64
-
65
- this.circle.set({ radius });
66
- this.circle.setCoords();
67
- canvas.renderAll();
68
- }
69
-
70
- _doMouseUp() {
71
- this.isDown = false;
72
- }
73
- }
74
-
75
- export default Circle;
@@ -1,16 +0,0 @@
1
- /*eslint no-unused-vars: 0*/
2
-
3
- import FabricCanvasTool from './fabrictool';
4
-
5
- class DefaultTool extends FabricCanvasTool {
6
- configureCanvas(props) {
7
- let canvas = this._canvas;
8
- canvas.isDrawingMode = canvas.selection = false;
9
- canvas.forEachObject((o) => (o.selectable = o.evented = false));
10
- canvas.discardActiveObject();
11
- canvas.defaultCursor = 'pointer';
12
- canvas.renderAll();
13
- }
14
- }
15
-
16
- export default DefaultTool;
@@ -1,22 +0,0 @@
1
- /* eslint no-unused-vars: 0 */
2
-
3
- /**
4
- * "Abstract" like base class for a Canvas tool
5
- */
6
- class FabricCanvasTool {
7
- constructor(canvas) {
8
- this._canvas = canvas;
9
- }
10
-
11
- configureCanvas(props) {}
12
-
13
- doMouseUp(event) {}
14
-
15
- doMouseDown(event) {}
16
-
17
- doMouseMove(event) {}
18
-
19
- doMouseOut(event) {}
20
- }
21
-
22
- export default FabricCanvasTool;