@pie-lib/graphing 4.0.15 → 4.0.17

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.
@@ -16,7 +16,15 @@ export class Point extends React.Component {
16
16
 
17
17
  constructor(props) {
18
18
  super(props);
19
- this.state = {};
19
+ // which label is being edited, null if none - a point only has the one
20
+ this.state = { editingLabel: null };
21
+ }
22
+
23
+ componentDidUpdate(prevProps) {
24
+ // leaving label mode closes any label that is still being edited
25
+ if (prevProps.labelModeEnabled && !this.props.labelModeEnabled && this.state.editingLabel !== null) {
26
+ this.setState({ editingLabel: null });
27
+ }
20
28
  }
21
29
 
22
30
  move = (p) => {
@@ -59,6 +67,12 @@ export class Point extends React.Component {
59
67
  });
60
68
  };
61
69
 
70
+ stopEditingLabel = () => {
71
+ if (this.state.editingLabel !== null) {
72
+ this.setState({ editingLabel: null });
73
+ }
74
+ };
75
+
62
76
  clickPoint = () => {
63
77
  const { labelModeEnabled, onChange, onClick, mark } = this.props;
64
78
 
@@ -73,17 +87,14 @@ export class Point extends React.Component {
73
87
 
74
88
  onChange(mark, { label: '', ...mark });
75
89
 
76
- // MarkLabel is only rendered after the parent re-renders with the new label prop,
77
- // so we defer focus until after that render cycle completes.
78
- setTimeout(() => {
79
- if (this.input) {
80
- this.input.focus();
81
- }
82
- }, 0);
90
+ // MarkLabel focuses itself once it is rendered - it also holds on to the focus if the model
91
+ // that comes back from the host (api save) remounts the input.
92
+ this.setState({ editingLabel: 'label' });
83
93
  };
84
94
 
85
95
  render() {
86
96
  const { coordinatesOnHover, graphProps, labelNode, labelModeEnabled } = this.props;
97
+ const { editingLabel } = this.state;
87
98
  const mark = this.state.mark ? this.state.mark : this.props.mark;
88
99
 
89
100
  return (
@@ -111,9 +122,11 @@ export class Point extends React.Component {
111
122
  ReactDOM.createPortal(
112
123
  <MarkLabel
113
124
  inputRef={(r) => (this.input = r)}
125
+ autoFocus={editingLabel === 'label'}
114
126
  disabled={!labelModeEnabled}
115
127
  mark={mark}
116
128
  graphProps={graphProps}
129
+ onBlur={this.stopEditingLabel}
117
130
  onChange={this.labelChange}
118
131
  />,
119
132
  labelNode,
@@ -90,6 +90,16 @@ export class RawBaseComponent extends React.Component {
90
90
  points: [],
91
91
  };
92
92
 
93
+ // index of the point whose label is edited (points.length for the polygon label), null if none
94
+ state = { editingLabel: null };
95
+
96
+ componentDidUpdate(prevProps) {
97
+ // leaving label mode closes any label that is still being edited
98
+ if (prevProps.labelModeEnabled && !this.props.labelModeEnabled && this.state.editingLabel !== null) {
99
+ this.setState({ editingLabel: null });
100
+ }
101
+ }
102
+
93
103
  dragPoint = (index, from, to) => {
94
104
  log('[dragPoint] from, to:', from, to);
95
105
  const { onChange, points } = this.props;
@@ -162,6 +172,12 @@ export class RawBaseComponent extends React.Component {
162
172
  onChangeProps(update);
163
173
  };
164
174
 
175
+ stopEditingLabel = () => {
176
+ if (this.state.editingLabel !== null) {
177
+ this.setState({ editingLabel: null });
178
+ }
179
+ };
180
+
165
181
  clickPoint = (point, index, data) => {
166
182
  const {
167
183
  closed,
@@ -194,12 +210,9 @@ export class RawBaseComponent extends React.Component {
194
210
  onSetMiddleLabel(strippedMiddle, strippedPoints);
195
211
  }
196
212
 
197
- // defer the focus() call with setTimeout to allow the re-render to complete first.
198
- setTimeout(() => {
199
- if (this.input[index]) {
200
- this.input[index].focus();
201
- }
202
- }, 0);
213
+ // MarkLabel focuses itself once it is rendered - it also holds on to the focus if the model
214
+ // that comes back from the host (api save) remounts the input.
215
+ this.setState({ editingLabel: index });
203
216
 
204
217
  return;
205
218
  }
@@ -230,6 +243,7 @@ export class RawBaseComponent extends React.Component {
230
243
  labelNode,
231
244
  labelModeEnabled,
232
245
  } = this.props;
246
+ const { editingLabel } = this.state;
233
247
  const lines = buildLines(points, closed);
234
248
  const common = { onDragStart, onDragStop, graphProps, disabled, correctness };
235
249
  const polygonLabelIndex = (points && points.length) || 0;
@@ -239,9 +253,11 @@ export class RawBaseComponent extends React.Component {
239
253
  polygonLabelNode = ReactDOM.createPortal(
240
254
  <MarkLabel
241
255
  inputRef={(r) => (this.input[polygonLabelIndex] = r)}
256
+ autoFocus={editingLabel === polygonLabelIndex}
242
257
  disabled={disabled || !labelModeEnabled}
243
258
  mark={middle}
244
259
  graphProps={graphProps}
260
+ onBlur={this.stopEditingLabel}
245
261
  onChange={(label) => onChangeLabelProps({ ...middle, label })}
246
262
  />,
247
263
  labelNode,
@@ -291,9 +307,11 @@ export class RawBaseComponent extends React.Component {
291
307
  ? ReactDOM.createPortal(
292
308
  <MarkLabel
293
309
  inputRef={(r) => (this.input[index] = r)}
310
+ autoFocus={editingLabel === index}
294
311
  disabled={disabled || !labelModeEnabled}
295
312
  mark={p}
296
313
  graphProps={graphProps}
314
+ onBlur={this.stopEditingLabel}
297
315
  onChange={(label) => this.labelChange({ ...p, label }, index)}
298
316
  />,
299
317
  labelNode,
@@ -234,6 +234,16 @@ export const lineBase = (Comp, opts) => {
234
234
  labelNode: PropTypes.object,
235
235
  };
236
236
 
237
+ // which of from/to/middle has its label edited, null if none
238
+ state = { editingLabel: null };
239
+
240
+ componentDidUpdate(prevProps) {
241
+ // leaving label mode closes any label that is still being edited
242
+ if (prevProps.labelModeEnabled && !this.props.labelModeEnabled && this.state.editingLabel !== null) {
243
+ this.setState({ editingLabel: null });
244
+ }
245
+ }
246
+
237
247
  onChangePoint = (point) => {
238
248
  const { middle, onChange } = this.props;
239
249
  const { from, to } = point;
@@ -303,6 +313,12 @@ export const lineBase = (Comp, opts) => {
303
313
  changeMarkProps({ [type]: update });
304
314
  };
305
315
 
316
+ stopEditingLabel = () => {
317
+ if (this.state.editingLabel !== null) {
318
+ this.setState({ editingLabel: null });
319
+ }
320
+ };
321
+
306
322
  clickPoint = (point, type, data) => {
307
323
  const { changeMarkProps, disabled, from, to, middle, labelModeEnabled, limitLabeling, onClick } = this.props;
308
324
 
@@ -331,9 +347,9 @@ export const lineBase = (Comp, opts) => {
331
347
  [type]: { label: '', ...point },
332
348
  });
333
349
 
334
- if (this.input[type]) {
335
- this.input[type].focus();
336
- }
350
+ // MarkLabel focuses itself once it is rendered - it also holds on to the focus if the model
351
+ // that comes back from the host (api save) remounts the input.
352
+ this.setState({ editingLabel: type });
337
353
  };
338
354
 
339
355
  // IMPORTANT, do not remove
@@ -354,6 +370,7 @@ export const lineBase = (Comp, opts) => {
354
370
  labelNode,
355
371
  labelModeEnabled,
356
372
  } = this.props;
373
+ const { editingLabel } = this.state;
357
374
  const common = { graphProps, onDragStart, onDragStop, disabled, correctness, onClick };
358
375
  const angle = to ? trig.toDegrees(trig.angle(from, to)) : 0;
359
376
 
@@ -366,9 +383,11 @@ export const lineBase = (Comp, opts) => {
366
383
  fromLabelNode = ReactDOM.createPortal(
367
384
  <MarkLabel
368
385
  inputRef={(r) => (this.input.from = r)}
386
+ autoFocus={editingLabel === 'from'}
369
387
  disabled={!labelModeEnabled}
370
388
  mark={from}
371
389
  graphProps={graphProps}
390
+ onBlur={this.stopEditingLabel}
372
391
  onChange={(label) => this.labelChange({ ...from, label }, 'from')}
373
392
  />,
374
393
  labelNode,
@@ -379,9 +398,11 @@ export const lineBase = (Comp, opts) => {
379
398
  toLabelNode = ReactDOM.createPortal(
380
399
  <MarkLabel
381
400
  inputRef={(r) => (this.input.to = r)}
401
+ autoFocus={editingLabel === 'to'}
382
402
  disabled={!labelModeEnabled}
383
403
  mark={to}
384
404
  graphProps={graphProps}
405
+ onBlur={this.stopEditingLabel}
385
406
  onChange={(label) => this.labelChange({ ...to, label }, 'to')}
386
407
  />,
387
408
  labelNode,
@@ -392,9 +413,11 @@ export const lineBase = (Comp, opts) => {
392
413
  lineLabelNode = ReactDOM.createPortal(
393
414
  <MarkLabel
394
415
  inputRef={(r) => (this.input.middle = r)}
416
+ autoFocus={editingLabel === 'middle'}
395
417
  disabled={!labelModeEnabled}
396
418
  mark={middle}
397
419
  graphProps={graphProps}
420
+ onBlur={this.stopEditingLabel}
398
421
  onChange={(label) => this.labelChange({ ...middle, label }, 'middle')}
399
422
  />,
400
423
  labelNode,