@pie-element/hotspot 4.7.18-next.85 → 4.8.1-beta.587

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 (95) hide show
  1. package/CHANGELOG.md +485 -0
  2. package/configure/CHANGELOG.md +425 -0
  3. package/configure/lib/button.js.map +1 -1
  4. package/configure/lib/defaults.js +24 -2
  5. package/configure/lib/defaults.js.map +1 -1
  6. package/configure/lib/hotspot-container.js +44 -23
  7. package/configure/lib/hotspot-container.js.map +1 -1
  8. package/configure/lib/hotspot-drawable.js +11 -5
  9. package/configure/lib/hotspot-drawable.js.map +1 -1
  10. package/configure/lib/hotspot-palette.js +1 -1
  11. package/configure/lib/hotspot-palette.js.map +1 -1
  12. package/configure/lib/hotspot-polygon.js +1 -1
  13. package/configure/lib/hotspot-polygon.js.map +1 -1
  14. package/configure/lib/hotspot-rectangle.js +1 -1
  15. package/configure/lib/hotspot-rectangle.js.map +1 -1
  16. package/configure/lib/index.js +17 -3
  17. package/configure/lib/index.js.map +1 -1
  18. package/configure/lib/root.js +133 -27
  19. package/configure/lib/root.js.map +1 -1
  20. package/configure/lib/upload-control.js.map +1 -1
  21. package/configure/lib/utils.js +18 -4
  22. package/configure/lib/utils.js.map +1 -1
  23. package/configure/package.json +4 -4
  24. package/configure/src/__tests__/__snapshots__/hotspot-container.test.js.snap +2 -1
  25. package/configure/src/__tests__/__snapshots__/root.test.js.snap +56 -4
  26. package/configure/src/__tests__/hotspot-container.test.js +98 -71
  27. package/configure/src/__tests__/hotspot-drawable.test.js +48 -49
  28. package/configure/src/__tests__/index.test.js +28 -51
  29. package/configure/src/__tests__/root.test.js +162 -82
  30. package/configure/src/__tests__/utils.test.js +112 -98
  31. package/configure/src/button.jsx +4 -4
  32. package/configure/src/defaults.js +36 -18
  33. package/configure/src/hotspot-container.jsx +107 -97
  34. package/configure/src/hotspot-drawable.jsx +59 -53
  35. package/configure/src/hotspot-palette.jsx +12 -25
  36. package/configure/src/hotspot-polygon.jsx +20 -22
  37. package/configure/src/hotspot-rectangle.jsx +5 -15
  38. package/configure/src/index.js +32 -18
  39. package/configure/src/root.jsx +120 -51
  40. package/configure/src/upload-control.jsx +9 -20
  41. package/configure/src/utils.js +51 -22
  42. package/controller/CHANGELOG.md +72 -0
  43. package/controller/lib/defaults.js +2 -2
  44. package/controller/lib/defaults.js.map +1 -1
  45. package/controller/lib/index.js +57 -9
  46. package/controller/lib/index.js.map +1 -1
  47. package/controller/lib/utils.js.map +1 -1
  48. package/controller/package.json +2 -2
  49. package/controller/src/__tests__/index.test.js +99 -55
  50. package/controller/src/defaults.js +5 -9
  51. package/controller/src/index.js +58 -34
  52. package/controller/src/utils.js +9 -6
  53. package/docs/config-schema.json +217 -0
  54. package/docs/config-schema.json.md +169 -0
  55. package/docs/demo/config.js +2 -2
  56. package/docs/demo/generate.js +54 -35
  57. package/docs/demo/session.js +2 -2
  58. package/docs/pie-schema.json +59 -0
  59. package/docs/pie-schema.json.md +47 -0
  60. package/lib/hotspot/container.js +44 -7
  61. package/lib/hotspot/container.js.map +1 -1
  62. package/lib/hotspot/icons.js.map +1 -1
  63. package/lib/hotspot/image.js +35 -8
  64. package/lib/hotspot/image.js.map +1 -1
  65. package/lib/hotspot/index.js +72 -18
  66. package/lib/hotspot/index.js.map +1 -1
  67. package/lib/hotspot/polygon.js +51 -32
  68. package/lib/hotspot/polygon.js.map +1 -1
  69. package/lib/hotspot/rectangle.js +51 -32
  70. package/lib/hotspot/rectangle.js.map +1 -1
  71. package/lib/index.js +4 -1
  72. package/lib/index.js.map +1 -1
  73. package/lib/session-updater.js.map +1 -1
  74. package/package.json +7 -4
  75. package/src/__tests__/__snapshots__/{container-test.jsx.snap → container.test.jsx.snap} +8 -0
  76. package/src/__tests__/__snapshots__/image.test.jsx.snap +43 -0
  77. package/src/__tests__/__snapshots__/{polygon-test.jsx.snap → polygon.test.jsx.snap} +11 -0
  78. package/src/__tests__/__snapshots__/{rectangle-test.jsx.snap → rectangle.test.jsx.snap} +11 -0
  79. package/src/__tests__/container.test.jsx +214 -0
  80. package/src/__tests__/{image-test.jsx → image.test.jsx} +10 -2
  81. package/src/__tests__/polygon.test.jsx +235 -0
  82. package/src/__tests__/rectangle.test.jsx +237 -0
  83. package/src/__tests__/{session-updater-test.jsx → session-updater.test.jsx} +22 -31
  84. package/src/hotspot/container.jsx +60 -23
  85. package/src/hotspot/icons.js +4 -2
  86. package/src/hotspot/image.jsx +26 -13
  87. package/src/hotspot/index.jsx +73 -33
  88. package/src/hotspot/polygon.jsx +51 -40
  89. package/src/hotspot/rectangle.jsx +51 -40
  90. package/src/index.js +10 -18
  91. package/src/session-updater.js +1 -1
  92. package/src/__tests__/__snapshots__/image-test.jsx.snap +0 -21
  93. package/src/__tests__/container-test.jsx +0 -143
  94. package/src/__tests__/polygon-test.jsx +0 -76
  95. package/src/__tests__/rectangle-test.jsx +0 -77
@@ -1,5 +1,6 @@
1
1
  import React, { Component } from 'react';
2
2
  import PropTypes from 'prop-types';
3
+ import classNames from 'classnames';
3
4
  import { withStyles } from '@material-ui/core/styles/index';
4
5
  import Help from '@material-ui/icons/Help';
5
6
 
@@ -10,6 +11,7 @@ import { getAllShapes, groupShapes } from './utils';
10
11
 
11
12
  const isImage = (file) => {
12
13
  const imageType = /image.*/;
14
+
13
15
  return file.type.match(imageType);
14
16
  };
15
17
 
@@ -19,7 +21,7 @@ export class Container extends Component {
19
21
  return {
20
22
  ...prevState,
21
23
  shapes: getAllShapes(nextProps.shapes),
22
- }
24
+ };
23
25
  }
24
26
 
25
27
  constructor(props) {
@@ -28,16 +30,18 @@ export class Container extends Component {
28
30
  this.state = {
29
31
  dragEnabled: true,
30
32
  // always transform shapes map into shapes array at this level
31
- shapes: getAllShapes(props.shapes)
32
- }
33
+ shapes: getAllShapes(props.shapes),
34
+ };
33
35
  }
34
36
 
35
37
  handleFileRead = (file) => {
36
- const { onImageUpload } = this.props;
37
- const reader = new FileReader();
38
+ if (file instanceof Blob) {
39
+ const { onImageUpload } = this.props;
40
+ const reader = new FileReader();
38
41
 
39
- reader.onloadend = () => onImageUpload(reader.result);
40
- reader.readAsDataURL(file)
42
+ reader.onloadend = () => onImageUpload(reader.result);
43
+ reader.readAsDataURL(file);
44
+ }
41
45
  };
42
46
 
43
47
  handleUploadImage = (e) => {
@@ -47,8 +51,17 @@ export class Container extends Component {
47
51
  };
48
52
 
49
53
  enableDropzone = () => this.setState({ dropzoneActive: true });
54
+
50
55
  disableDropzone = () => this.setState({ dropzoneActive: false });
51
56
 
57
+ handleOnPaste = (e) => {
58
+ const { files } = e.clipboardData;
59
+
60
+ if (files && isImage(files[0])) {
61
+ this.handleFileRead(files[0]);
62
+ }
63
+ };
64
+
52
65
  handleOnDrop = (e) => {
53
66
  e.preventDefault();
54
67
 
@@ -63,6 +76,7 @@ export class Container extends Component {
63
76
  } else if (isImage(files[0])) {
64
77
  this.handleFileRead(files[0]);
65
78
  }
79
+
66
80
  this.disableDropzone();
67
81
  };
68
82
 
@@ -82,13 +96,13 @@ export class Container extends Component {
82
96
  this.disableDropzone();
83
97
  };
84
98
 
85
- onUpdateShapes = newShapes => {
99
+ onUpdateShapes = (newShapes) => {
86
100
  const { onUpdateShapes } = this.props;
87
101
 
88
102
  this.setState(
89
103
  { shapes: newShapes },
90
104
  // always transform shapes array back into shapes map when saving changes
91
- () => onUpdateShapes(groupShapes(newShapes))
105
+ () => onUpdateShapes(groupShapes(newShapes)),
92
106
  );
93
107
  };
94
108
 
@@ -97,7 +111,7 @@ export class Container extends Component {
97
111
 
98
112
  if (shapes && shapes.length) {
99
113
  // sort by index value
100
- let newShapes = shapes.sort((a, b) => (parseInt(a.index) - parseInt(b.index)));
114
+ let newShapes = shapes.sort((a, b) => parseInt(a.index) - parseInt(b.index));
101
115
 
102
116
  newShapes = newShapes ? newShapes.slice(0, newShapes.length - 1) : [];
103
117
 
@@ -108,7 +122,9 @@ export class Container extends Component {
108
122
  handleClearAll = () => this.onUpdateShapes([]);
109
123
 
110
124
  handleEnableDrag = () => this.setState({ dragEnabled: true });
125
+
111
126
  handleDisableDrag = () => this.setState({ dragEnabled: false });
127
+
112
128
  handleInputClick = () => this.input.click();
113
129
 
114
130
  toggleTooltip = () => this.setState({ showTooltip: !this.state.showTooltip });
@@ -117,30 +133,34 @@ export class Container extends Component {
117
133
  const {
118
134
  classes,
119
135
  dimensions,
136
+ hasErrors,
120
137
  hotspotColor,
121
138
  imageUrl,
122
139
  multipleCorrect,
123
140
  onUpdateImageDimension,
124
141
  outlineColor,
125
142
  strokeWidth,
126
- preserveAspectRatioEnabled
143
+ preserveAspectRatioEnabled,
127
144
  } = this.props;
128
- const {
129
- dropzoneActive,
130
- dragEnabled,
131
- showTooltip
132
- } = this.state;
145
+ const { dropzoneActive, dragEnabled, showTooltip } = this.state;
133
146
  const { shapes } = this.state;
134
147
 
135
148
  return (
136
149
  <div className={classes.base}>
137
- <div className={`${classes.box} ${dropzoneActive ? classes.boxActive : ''}`}
138
- {...dragEnabled ? {
139
- onDragExit: this.handleOnDragExit,
140
- onDragLeave: this.handleOnDragExit,
141
- onDragOver: this.handleOnDragOver,
142
- onDrop: this.handleOnDrop
143
- } : {}}
150
+ <div
151
+ className={classNames(classes.box, {
152
+ [classes.boxError]: hasErrors && !dropzoneActive,
153
+ [classes.boxActive]: dropzoneActive,
154
+ })}
155
+ {...(dragEnabled
156
+ ? {
157
+ onDragExit: this.handleOnDragExit,
158
+ onDragLeave: this.handleOnDragExit,
159
+ onDragOver: this.handleOnDragOver,
160
+ onDrop: this.handleOnDrop,
161
+ onPaste: this.handleOnPaste,
162
+ }
163
+ : {})}
144
164
  >
145
165
  <div className={classes.toolbar}>
146
166
  {imageUrl && (
@@ -155,54 +175,46 @@ export class Container extends Component {
155
175
  }}
156
176
  />
157
177
  )}
158
- <Button
159
- disabled={!(shapes && shapes.length)}
160
- onClick={this.handleUndo}
161
- label="Undo"
162
- />
163
- <Button
164
- disabled={!(shapes && shapes.length)}
165
- onClick={this.handleClearAll}
166
- label="Clear all"
167
- />
178
+
179
+ <Button disabled={!(shapes && shapes.length)} onClick={this.handleUndo} label="Undo" />
180
+ <Button disabled={!(shapes && shapes.length)} onClick={this.handleClearAll} label="Clear all" />
168
181
  </div>
169
182
 
170
183
  <div
171
- ref={ref => {
184
+ ref={(ref) => {
172
185
  this.imageSection = ref;
173
186
  }}
174
- className={classes.drawableHeight}>
175
- {imageUrl
176
- ? (
177
- <Drawable
178
- dimensions={dimensions}
179
- disableDrag={this.handleDisableDrag}
180
- enableDrag={this.handleEnableDrag}
181
- imageUrl={imageUrl}
182
- hotspotColor={hotspotColor}
183
- multipleCorrect={multipleCorrect}
184
- onUpdateImageDimension={onUpdateImageDimension}
185
- onUpdateShapes={this.onUpdateShapes}
186
- outlineColor={outlineColor}
187
- shapes={shapes}
188
- strokeWidth={strokeWidth}
189
- preserveAspectRatioEnabled={preserveAspectRatioEnabled}
187
+ className={classes.drawableHeight}
188
+ >
189
+ {imageUrl ? (
190
+ <Drawable
191
+ dimensions={dimensions}
192
+ disableDrag={this.handleDisableDrag}
193
+ enableDrag={this.handleEnableDrag}
194
+ imageUrl={imageUrl}
195
+ hotspotColor={hotspotColor}
196
+ multipleCorrect={multipleCorrect}
197
+ onUpdateImageDimension={onUpdateImageDimension}
198
+ onUpdateShapes={this.onUpdateShapes}
199
+ outlineColor={outlineColor}
200
+ shapes={shapes}
201
+ strokeWidth={strokeWidth}
202
+ preserveAspectRatioEnabled={preserveAspectRatioEnabled}
203
+ />
204
+ ) : (
205
+ <div className={classNames(classes.drawableHeight, classes.centered)}>
206
+ <label>Drag and drop or upload image from computer</label>
207
+ <br />
208
+ <UploadControl
209
+ label="Upload Image"
210
+ onInputClick={this.handleInputClick}
211
+ onUploadImage={this.handleUploadImage}
212
+ setRef={(ref) => {
213
+ this.input = ref;
214
+ }}
190
215
  />
191
- )
192
- : (
193
- <div className={`${classes.drawableHeight} ${classes.centered}`}>
194
- <label>Drag and drop or upload image from computer</label>
195
- <br/>
196
- <UploadControl
197
- label="Upload Image"
198
- onInputClick={this.handleInputClick}
199
- onUploadImage={this.handleUploadImage}
200
- setRef={(ref) => {
201
- this.input = ref;
202
- }}
203
- />
204
- </div>
205
- )}
216
+ </div>
217
+ )}
206
218
  </div>
207
219
 
208
220
  {imageUrl && (
@@ -210,60 +222,58 @@ export class Container extends Component {
210
222
  {showTooltip && (
211
223
  <div className={classes.tooltipContent}>
212
224
  <label>
213
- Click and drag to create a hotspot. Click the hotspot to mark correct. Click
214
- again to unmark.
225
+ Click and drag to create a hotspot. Click the hotspot to mark correct. Click again to unmark.
215
226
  </label>
216
- <div className={classes.tooltipArrow}/>
227
+ <div className={classes.tooltipArrow} />
217
228
  </div>
218
229
  )}
219
- <Help
220
- className={classes.icon}
221
- onMouseOut={this.toggleTooltip}
222
- onMouseOver={this.toggleTooltip}
223
- />
230
+
231
+ <Help className={classes.icon} onMouseOut={this.toggleTooltip} onMouseOver={this.toggleTooltip} />
224
232
  </div>
225
233
  )}
226
234
  </div>
227
235
  </div>
228
-
229
236
  );
230
237
  }
231
238
  }
232
239
 
233
- const styles = theme => ({
240
+ const styles = (theme) => ({
234
241
  base: {
235
- marginTop: theme.spacing.unit * 2
242
+ marginTop: theme.spacing.unit * 2,
236
243
  },
237
244
  box: {
238
245
  border: '1px solid #E0E1E6',
239
- borderRadius: '5px'
246
+ borderRadius: '5px',
240
247
  },
241
248
  boxActive: {
242
- border: '1px solid #0032C2'
249
+ border: '1px solid #0032C2',
250
+ },
251
+ boxError: {
252
+ border: '1px solid red',
243
253
  },
244
254
  centered: {
245
255
  alignItems: 'center',
246
256
  display: 'flex',
247
257
  flexDirection: 'column',
248
- justifyContent: 'center'
258
+ justifyContent: 'center',
249
259
  },
250
260
  drawableHeight: {
251
261
  minHeight: 350,
252
- paddingBottom: '40px',
253
- paddingRight: '40px',
262
+ paddingBottom: theme.spacing.unit * 5,
263
+ paddingRight: theme.spacing.unit * 5,
254
264
  },
255
265
  icon: {
256
266
  '&:hover': {
257
267
  color: '#333131',
258
- cursor: 'help'
268
+ cursor: 'help',
259
269
  },
260
- color: '#C1C1C1'
270
+ color: '#C1C1C1',
261
271
  },
262
272
  replaceButton: {
263
273
  marginLeft: 0,
264
274
  },
265
275
  replaceSection: {
266
- marginRight: 'auto'
276
+ marginRight: 'auto',
267
277
  },
268
278
  toolbar: {
269
279
  backgroundColor: '#ECEDF1',
@@ -272,25 +282,25 @@ const styles = theme => ({
272
282
  borderTopRightRadius: '5px',
273
283
  display: 'flex',
274
284
  justifyContent: 'flex-end',
275
- padding: '12px 8px'
285
+ padding: theme.spacing.unit,
276
286
  },
277
287
  tooltip: {
278
288
  position: 'relative',
279
289
  textAlign: 'right',
280
- padding: '5px 9px'
290
+ padding: theme.spacing.unit,
281
291
  },
282
292
  tooltipContent: {
283
293
  background: '#333131',
284
294
  borderRadius: '4px',
285
295
  color: '#FFFFFF',
286
- fontSize: '14px',
296
+ fontSize: theme.typography.fontSize,
287
297
  lineHeight: '18px',
288
- marginTop: '-70px',
289
- padding: '7px 16px',
298
+ marginTop: '-60px',
299
+ padding: theme.spacing.unit,
290
300
  position: 'absolute',
291
301
  right: '5px',
292
302
  textAlign: 'left',
293
- width: '300px'
303
+ width: '300px',
294
304
  },
295
305
  tooltipArrow: {
296
306
  width: 0,
@@ -299,10 +309,10 @@ const styles = theme => ({
299
309
  borderRight: '10px solid transparent',
300
310
  borderTop: '10px solid #333131',
301
311
  marginBottom: -10,
302
- marginTop: '2px',
312
+ marginTop: '4px',
303
313
  position: 'absolute',
304
- right: '5px'
305
- }
314
+ right: '5px',
315
+ },
306
316
  });
307
317
 
308
318
  Container.propTypes = {
@@ -317,14 +327,14 @@ Container.propTypes = {
317
327
  outlineColor: PropTypes.string.isRequired,
318
328
  shapes: PropTypes.shape({
319
329
  rectangles: PropTypes.array,
320
- polygons: PropTypes.array
330
+ polygons: PropTypes.array,
321
331
  }).isRequired,
322
332
  strokeWidth: PropTypes.number,
323
- preserveAspectRatioEnabled: PropTypes.bool
333
+ preserveAspectRatioEnabled: PropTypes.bool,
324
334
  };
335
+
325
336
  Container.defaultProps = {
326
- strokeWidth: 5
337
+ strokeWidth: 5,
327
338
  };
328
339
 
329
-
330
340
  export default withStyles(styles)(Container);
@@ -9,6 +9,8 @@ import Rectangle from './hotspot-rectangle';
9
9
  import Polygon from './hotspot-polygon';
10
10
  import { updateImageDimensions, getUpdatedShapes } from './utils';
11
11
 
12
+ const IMAGE_MAX_WIDTH = 800;
13
+
12
14
  export class Drawable extends React.Component {
13
15
  static getDerivedStateFromProps(nextProps, prevState) {
14
16
  let dimensions = nextProps.dimensions;
@@ -20,7 +22,7 @@ export class Drawable extends React.Component {
20
22
  return {
21
23
  ...prevState,
22
24
  dimensions: dimensions,
23
- }
25
+ };
24
26
  }
25
27
 
26
28
  constructor(props) {
@@ -34,7 +36,7 @@ export class Drawable extends React.Component {
34
36
  height: 0,
35
37
  width: 0,
36
38
  },
37
- }
39
+ };
38
40
  }
39
41
 
40
42
  /// start of handling HotSpots section
@@ -43,7 +45,7 @@ export class Drawable extends React.Component {
43
45
  const { onUpdateShapes, shapes } = this.props;
44
46
  // Add a new rectangle at the mouse position with 0 width and height
45
47
  const newShapes = shapes.slice();
46
- const value = max(newShapes.map(c => parseInt(c.id)).filter(id => !isNaN(id))) || 0;
48
+ const value = max(newShapes.map((c) => parseInt(c.id)).filter((id) => !isNaN(id))) || 0;
47
49
 
48
50
  newShapes.push({
49
51
  id: `${value + 1}`,
@@ -52,7 +54,7 @@ export class Drawable extends React.Component {
52
54
  x: e.evt.layerX,
53
55
  y: e.evt.layerY,
54
56
  group: 'rectangles',
55
- index: shapes.length
57
+ index: shapes.length,
56
58
  });
57
59
 
58
60
  this.setState({ isDrawing: true, isDrawingShapeId: `${value + 1}` });
@@ -84,7 +86,7 @@ export class Drawable extends React.Component {
84
86
  const mouseX = e.evt.layerX;
85
87
  const mouseY = e.evt.layerY;
86
88
 
87
- const currShapeIndex = shapes.findIndex(shape => shape.id === isDrawingShapeId);
89
+ const currShapeIndex = shapes.findIndex((shape) => shape.id === isDrawingShapeId);
88
90
  const currShape = shapes[currShapeIndex];
89
91
 
90
92
  if (currShape) {
@@ -98,7 +100,7 @@ export class Drawable extends React.Component {
98
100
  height: newHeight,
99
101
  width: newWidth,
100
102
  x: currShape.x,
101
- y: currShape.y
103
+ y: currShape.y,
102
104
  };
103
105
 
104
106
  // On mouse move don't trigger any event. Put the shapes on this state instead.
@@ -109,12 +111,12 @@ export class Drawable extends React.Component {
109
111
 
110
112
  handleOnDragEnd = (id, updatedProps) => {
111
113
  const { shapes, onUpdateShapes } = this.props;
112
- const newShapes = shapes.map(shape => {
114
+ const newShapes = shapes.map((shape) => {
113
115
  if (shape.id === id) {
114
116
  return {
115
117
  ...shape,
116
- ...updatedProps
117
- }
118
+ ...updatedProps,
119
+ };
118
120
  }
119
121
  return shape;
120
122
  });
@@ -129,17 +131,17 @@ export class Drawable extends React.Component {
129
131
  let newShapes = [];
130
132
 
131
133
  if (multipleCorrect) {
132
- newShapes = shapes.map(shape => {
134
+ newShapes = shapes.map((shape) => {
133
135
  if (shape.id === id) {
134
136
  shape.correct = !shape.correct;
135
137
  }
136
138
  return shape;
137
- })
139
+ });
138
140
  } else {
139
- newShapes = shapes.map(shape => {
141
+ newShapes = shapes.map((shape) => {
140
142
  shape.correct = shape.id === id;
141
143
  return shape;
142
- })
144
+ });
143
145
  }
144
146
 
145
147
  onUpdateShapes(cloneDeep(newShapes));
@@ -153,15 +155,20 @@ export class Drawable extends React.Component {
153
155
  const elementStyle = getComputedStyle(target);
154
156
  const newHeight = parseFloat(elementStyle.height);
155
157
  const newWidth = parseFloat(elementStyle.width);
158
+ const aspectWidth = newWidth / IMAGE_MAX_WIDTH;
156
159
 
157
- const dimensions = {
158
- height: newHeight,
159
- width: newWidth
160
- };
160
+ const dimensions =
161
+ newWidth > IMAGE_MAX_WIDTH
162
+ ? {
163
+ height: newHeight / aspectWidth,
164
+ width: IMAGE_MAX_WIDTH,
165
+ }
166
+ : {
167
+ height: newHeight,
168
+ width: newWidth,
169
+ };
161
170
 
162
- this.setState(
163
- { dimensions },
164
- () => onUpdateImageDimension(dimensions));
171
+ this.setState({ dimensions }, () => onUpdateImageDimension(dimensions));
165
172
 
166
173
  resizeHandle.addEventListener('mousedown', this.initialiseResize, false);
167
174
  };
@@ -176,47 +183,43 @@ export class Drawable extends React.Component {
176
183
  let drawable = true;
177
184
 
178
185
  // Do not allow resizing over the hotspots
179
- shapes && shapes.forEach(shape => {
180
- const right = shape.x + shape.width + 5;
181
- const bottom = shape.y + shape.height + 5;
182
- if (x <= right || y <= bottom) {
183
- drawable = false
184
- }
185
- });
186
+ shapes &&
187
+ shapes.forEach((shape) => {
188
+ const right = shape.x + shape.width + 5;
189
+ const bottom = shape.y + shape.height + 5;
190
+ if (x <= right || y <= bottom) {
191
+ drawable = false;
192
+ }
193
+ });
186
194
  return drawable;
187
195
  }
188
196
 
189
197
  startResizing = (e) => {
190
198
  const bounds = e.target.getBoundingClientRect();
191
199
  const box = this.image;
192
- const {
193
- disableDrag,
194
- preserveAspectRatioEnabled,
195
- dimensions,
196
- shapes
197
- } = this.props;
200
+ const { disableDrag, preserveAspectRatioEnabled, dimensions, shapes } = this.props;
198
201
 
199
202
  // todo previously we had state.dimensions, is it needed?
200
203
  const { width, height } = updateImageDimensions(
201
204
  dimensions,
202
205
  {
203
206
  width: e.clientX - bounds.left,
204
- height: e.clientY - bounds.top
207
+ height: e.clientY - bounds.top,
205
208
  },
206
- preserveAspectRatioEnabled
209
+ preserveAspectRatioEnabled,
207
210
  );
208
211
 
209
212
  const resizeValid = this.checkIfResizeValid(width, height);
210
213
  const hasMinimumWidth = width > 150 && height > 150;
211
214
 
212
- if (resizeValid && hasMinimumWidth) {
215
+ if (resizeValid && hasMinimumWidth && box) {
213
216
  box.style.width = `${width}px`;
214
217
  box.style.height = `${height}px`;
215
218
 
216
219
  this.setState({
217
220
  resizing: true,
218
221
  dimensions: { height: height, width: width },
219
- stateShapes: getUpdatedShapes(dimensions, { width, height }, shapes)
222
+ stateShapes: getUpdatedShapes(dimensions, { width, height }, shapes),
220
223
  });
221
224
  }
222
225
 
@@ -250,12 +253,12 @@ export class Drawable extends React.Component {
250
253
  hotspotColor,
251
254
  outlineColor,
252
255
  shapes,
253
- strokeWidth
256
+ strokeWidth,
254
257
  } = this.props;
255
258
  const {
256
259
  stateShapes,
257
260
  isDrawing,
258
- dimensions: { height: heightFromState, width: widthFromState }
261
+ dimensions: { height: heightFromState, width: widthFromState },
259
262
  } = this.state;
260
263
  const shapesToUse = stateShapes || shapes;
261
264
 
@@ -266,15 +269,18 @@ export class Drawable extends React.Component {
266
269
  <img
267
270
  className={classes.image}
268
271
  onLoad={this.handleOnImageLoad}
269
- ref={ref => {
272
+ ref={(ref) => {
270
273
  this.image = ref;
271
274
  }}
272
275
  src={imageUrl}
273
- {...height && width ? { style: { height, width } } : {}}
276
+ {...(height && width ? { style: { height, width } } : {})}
277
+ />
278
+ <div
279
+ ref={(ref) => {
280
+ this.resize = ref;
281
+ }}
282
+ className={classes.resize}
274
283
  />
275
- <div ref={ref => {
276
- this.resize = ref;
277
- }} className={classes.resize}/>
278
284
  </div>
279
285
  )}
280
286
 
@@ -282,9 +288,9 @@ export class Drawable extends React.Component {
282
288
  className={classes.stage}
283
289
  height={heightFromState || height}
284
290
  width={widthFromState || width}
285
- onMouseDown={this.handleOnMouseDown }
286
- onMouseUp={this.handleOnMouseUp }
287
- onMouseMove={this.handleMouseMove }
291
+ onMouseDown={this.handleOnMouseDown}
292
+ onMouseUp={this.handleOnMouseUp}
293
+ onMouseMove={this.handleMouseMove}
288
294
  >
289
295
  <Layer>
290
296
  {shapesToUse.map((shape, index) => {
@@ -318,7 +324,7 @@ export class Drawable extends React.Component {
318
324
 
319
325
  const styles = () => ({
320
326
  base: {
321
- position: 'relative'
327
+ position: 'relative',
322
328
  },
323
329
  image: {
324
330
  alignItems: 'center',
@@ -327,7 +333,7 @@ const styles = () => ({
327
333
  },
328
334
  imageContainer: {
329
335
  position: 'relative',
330
- width: 'fit-content'
336
+ width: 'fit-content',
331
337
  },
332
338
  resize: {
333
339
  borderBottom: '1px solid #727272',
@@ -337,13 +343,13 @@ const styles = () => ({
337
343
  height: '10px',
338
344
  position: 'absolute',
339
345
  right: '-10px',
340
- width: '10px'
346
+ width: '10px',
341
347
  },
342
348
  stage: {
343
349
  left: 0,
344
350
  top: 0,
345
- position: 'absolute'
346
- }
351
+ position: 'absolute',
352
+ },
347
353
  });
348
354
 
349
355
  Drawable.propTypes = {
@@ -359,7 +365,7 @@ Drawable.propTypes = {
359
365
  outlineColor: PropTypes.string.isRequired,
360
366
  shapes: PropTypes.array.isRequired,
361
367
  strokeWidth: PropTypes.number,
362
- preserveAspectRatioEnabled: PropTypes.bool
368
+ preserveAspectRatioEnabled: PropTypes.bool,
363
369
  };
364
370
 
365
371
  export default withStyles(styles)(Drawable);