@operato/image-marker 8.0.0-alpha.10 → 8.0.0-alpha.18
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.
- package/CHANGELOG.md +18 -0
- package/dist/src/ox-image-marker.d.ts +7 -0
- package/dist/src/ox-image-marker.js +221 -127
- package/dist/src/ox-image-marker.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/ox-image-marker.ts +250 -133
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [8.0.0-alpha.18](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.17...v8.0.0-alpha.18) (2024-10-04)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### :bug: Bug Fix
|
|
10
|
+
|
|
11
|
+
* ox-image-marker ([ae56c0a](https://github.com/hatiolab/operato/commit/ae56c0a28af20d029e907181af0babe63526cae5))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## [8.0.0-alpha.17](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.16...v8.0.0-alpha.17) (2024-10-04)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### :bug: Bug Fix
|
|
19
|
+
|
|
20
|
+
* ox-image-marker ([7393507](https://github.com/hatiolab/operato/commit/73935070ba969772cdf6e8c1eff90b0379f535b1))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
6
24
|
## [8.0.0-alpha.10](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.9...v8.0.0-alpha.10) (2024-09-18)
|
|
7
25
|
|
|
8
26
|
|
|
@@ -12,6 +12,10 @@ export declare class OxImageMarker extends BaseImageMarker {
|
|
|
12
12
|
private startY;
|
|
13
13
|
private offsetX;
|
|
14
14
|
private offsetY;
|
|
15
|
+
connectedCallback(): void;
|
|
16
|
+
disconnectedCallback(): void;
|
|
17
|
+
private handleKeyDown;
|
|
18
|
+
private deleteSelectedShape;
|
|
15
19
|
render(): import("lit-html").TemplateResult<1>;
|
|
16
20
|
protected onSvgMouseDown(event: MouseEvent): void;
|
|
17
21
|
private startShapeDragging;
|
|
@@ -30,4 +34,7 @@ export declare class OxImageMarker extends BaseImageMarker {
|
|
|
30
34
|
private onHandleMouseMove;
|
|
31
35
|
private onHandleMouseUp;
|
|
32
36
|
private onTextDoubleClick;
|
|
37
|
+
private showTextInput;
|
|
38
|
+
private adjustInputWidth;
|
|
39
|
+
private measureTextWidth;
|
|
33
40
|
}
|
|
@@ -15,53 +15,119 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
15
15
|
this.startY = 0;
|
|
16
16
|
this.offsetX = 0;
|
|
17
17
|
this.offsetY = 0;
|
|
18
|
-
|
|
18
|
+
this.handleKeyDown = (event) => {
|
|
19
|
+
if ((event.key === 'Delete' || event.key === 'Backspace') && this.selectedShape) {
|
|
20
|
+
this.deleteSelectedShape();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
19
23
|
this.onMouseMove = (event) => {
|
|
20
|
-
if (!this.drawing
|
|
24
|
+
if (!this.drawing)
|
|
21
25
|
return;
|
|
22
26
|
const { x, y } = this.getSvgPoint(event);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
27
|
+
const minDistance = 5;
|
|
28
|
+
const distance = Math.sqrt(Math.pow(x - this.startX, 2) + Math.pow(y - this.startY, 2));
|
|
29
|
+
if (!this.selectedShape && distance >= minDistance) {
|
|
30
|
+
let newShape;
|
|
31
|
+
switch (this.currentShapeType) {
|
|
32
|
+
case 'rectangle':
|
|
33
|
+
newShape = {
|
|
34
|
+
id: Date.now().toString(),
|
|
35
|
+
type: 'rectangle',
|
|
36
|
+
x: this.startX,
|
|
37
|
+
y: this.startY,
|
|
38
|
+
width: 0,
|
|
39
|
+
height: 0
|
|
40
|
+
};
|
|
41
|
+
break;
|
|
42
|
+
case 'circle':
|
|
43
|
+
newShape = {
|
|
44
|
+
id: Date.now().toString(),
|
|
45
|
+
type: 'circle',
|
|
46
|
+
cx: this.startX,
|
|
47
|
+
cy: this.startY,
|
|
48
|
+
r: 0
|
|
49
|
+
};
|
|
50
|
+
break;
|
|
51
|
+
case 'triangle':
|
|
52
|
+
newShape = {
|
|
53
|
+
id: Date.now().toString(),
|
|
54
|
+
type: 'triangle',
|
|
55
|
+
x1: this.startX,
|
|
56
|
+
y1: this.startY,
|
|
57
|
+
width: 0,
|
|
58
|
+
height: 0,
|
|
59
|
+
points: `${this.startX},${this.startY} ${this.startX},${this.startY} ${this.startX},${this.startY}`
|
|
60
|
+
};
|
|
61
|
+
break;
|
|
62
|
+
case 'line':
|
|
63
|
+
newShape = {
|
|
64
|
+
id: Date.now().toString(),
|
|
65
|
+
type: 'line',
|
|
66
|
+
x1: this.startX,
|
|
67
|
+
y1: this.startY,
|
|
68
|
+
width: 0,
|
|
69
|
+
height: 0
|
|
70
|
+
};
|
|
71
|
+
break;
|
|
72
|
+
case 'arrow':
|
|
73
|
+
newShape = {
|
|
74
|
+
id: Date.now().toString(),
|
|
75
|
+
type: 'arrow',
|
|
76
|
+
x1: this.startX,
|
|
77
|
+
y1: this.startY,
|
|
78
|
+
width: 0,
|
|
79
|
+
height: 0
|
|
80
|
+
};
|
|
81
|
+
break;
|
|
82
|
+
default:
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
this.selectedShape = newShape;
|
|
86
|
+
this.shapes = [...this.shapes, newShape];
|
|
87
|
+
}
|
|
88
|
+
if (this.selectedShape) {
|
|
89
|
+
switch (this.selectedShape.type) {
|
|
90
|
+
case 'rectangle':
|
|
91
|
+
this.selectedShape.x = Math.min(x, this.startX);
|
|
92
|
+
this.selectedShape.y = Math.min(y, this.startY);
|
|
93
|
+
this.selectedShape.width = Math.abs(x - this.startX);
|
|
94
|
+
this.selectedShape.height = Math.abs(y - this.startY);
|
|
95
|
+
break;
|
|
96
|
+
case 'circle':
|
|
97
|
+
const dx = x - this.selectedShape.cx;
|
|
98
|
+
const dy = y - this.selectedShape.cy;
|
|
99
|
+
this.selectedShape.r = Math.sqrt(dx * dx + dy * dy);
|
|
100
|
+
break;
|
|
101
|
+
case 'triangle':
|
|
102
|
+
const x2 = x;
|
|
103
|
+
const y2 = y;
|
|
104
|
+
const x3 = this.startX - (x - this.startX);
|
|
105
|
+
const y3 = y;
|
|
106
|
+
this.selectedShape.points = `${this.startX},${this.startY} ${x2},${y2} ${x3},${y3}`;
|
|
107
|
+
break;
|
|
108
|
+
case 'line':
|
|
109
|
+
case 'arrow':
|
|
110
|
+
this.selectedShape.x2 = x;
|
|
111
|
+
this.selectedShape.y2 = y;
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
this.requestUpdate();
|
|
47
115
|
}
|
|
48
|
-
this.requestUpdate();
|
|
49
116
|
};
|
|
50
|
-
// 마우스 업 이벤트 핸들러 (도형 그리기 종료)
|
|
51
117
|
this.onMouseUp = () => {
|
|
52
118
|
this.drawing = false;
|
|
53
119
|
const svg = this.svg;
|
|
54
120
|
svg.removeEventListener('mousemove', this.onMouseMove);
|
|
55
121
|
svg.removeEventListener('mouseup', this.onMouseUp);
|
|
56
|
-
this.selectedShape
|
|
122
|
+
if (this.selectedShape) {
|
|
123
|
+
this.selectedShape.selected = true;
|
|
124
|
+
}
|
|
57
125
|
this.requestUpdate();
|
|
58
126
|
};
|
|
59
127
|
this.onShapeMouseMove = (event) => {
|
|
60
|
-
if (!this.selectedShape)
|
|
128
|
+
if (!this.selectedShape)
|
|
61
129
|
return;
|
|
62
|
-
}
|
|
63
130
|
const { x, y } = this.getSvgPoint(event);
|
|
64
|
-
// 마우스 이동에 따라 도형의 위치 업데이트
|
|
65
131
|
switch (this.selectedShape.type) {
|
|
66
132
|
case 'text':
|
|
67
133
|
case 'rectangle':
|
|
@@ -91,7 +157,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
91
157
|
this.selectedShape.y2 = this.selectedShape.y2 + deltaY;
|
|
92
158
|
break;
|
|
93
159
|
}
|
|
94
|
-
this.requestUpdate();
|
|
160
|
+
this.requestUpdate();
|
|
95
161
|
};
|
|
96
162
|
this.onShapeMouseUp = () => {
|
|
97
163
|
const svg = this.svg;
|
|
@@ -179,6 +245,23 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
179
245
|
}
|
|
180
246
|
`
|
|
181
247
|
]; }
|
|
248
|
+
connectedCallback() {
|
|
249
|
+
super.connectedCallback();
|
|
250
|
+
// 키다운 이벤트 리스너 추가
|
|
251
|
+
window.addEventListener('keydown', this.handleKeyDown);
|
|
252
|
+
}
|
|
253
|
+
disconnectedCallback() {
|
|
254
|
+
super.disconnectedCallback();
|
|
255
|
+
// 키다운 이벤트 리스너 제거
|
|
256
|
+
window.removeEventListener('keydown', this.handleKeyDown);
|
|
257
|
+
}
|
|
258
|
+
deleteSelectedShape() {
|
|
259
|
+
if (this.selectedShape) {
|
|
260
|
+
this.shapes = this.shapes.filter(s => s.id !== this.selectedShape.id);
|
|
261
|
+
this.selectedShape = null;
|
|
262
|
+
this.requestUpdate();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
182
265
|
render() {
|
|
183
266
|
return html `
|
|
184
267
|
<div class="container">
|
|
@@ -200,12 +283,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
200
283
|
const { mode, shapeType } = e.detail;
|
|
201
284
|
this.setMode(mode, shapeType);
|
|
202
285
|
}}
|
|
203
|
-
@clicked-delete=${() =>
|
|
204
|
-
if (this.selectedShape) {
|
|
205
|
-
this.shapes = this.shapes.filter(s => s.id !== this.selectedShape.id);
|
|
206
|
-
this.requestUpdate();
|
|
207
|
-
}
|
|
208
|
-
}}
|
|
286
|
+
@clicked-delete=${() => this.deleteSelectedShape()}
|
|
209
287
|
@clicked-save=${() => {
|
|
210
288
|
this.dispatchEvent(new CustomEvent('shapes-changed', {
|
|
211
289
|
detail: this.shapes,
|
|
@@ -249,82 +327,27 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
249
327
|
}
|
|
250
328
|
}
|
|
251
329
|
startDrawing(event) {
|
|
252
|
-
this.drawing = true;
|
|
253
330
|
const { x, y } = this.getSvgPoint(event);
|
|
254
|
-
this.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
newShape = {
|
|
269
|
-
id: Date.now().toString(),
|
|
270
|
-
type: 'rectangle',
|
|
271
|
-
x: this.startX,
|
|
272
|
-
y: this.startY,
|
|
273
|
-
width: 0,
|
|
274
|
-
height: 0
|
|
275
|
-
};
|
|
276
|
-
break;
|
|
277
|
-
case 'circle':
|
|
278
|
-
newShape = {
|
|
279
|
-
id: Date.now().toString(),
|
|
280
|
-
type: 'circle',
|
|
281
|
-
cx: this.startX,
|
|
282
|
-
cy: this.startY,
|
|
283
|
-
r: 0
|
|
284
|
-
};
|
|
285
|
-
break;
|
|
286
|
-
case 'triangle':
|
|
287
|
-
newShape = {
|
|
288
|
-
id: Date.now().toString(),
|
|
289
|
-
type: 'triangle',
|
|
290
|
-
x1: this.startX,
|
|
291
|
-
y1: this.startY,
|
|
292
|
-
width: 0,
|
|
293
|
-
height: 0,
|
|
294
|
-
points: `${this.startX},${this.startY} ${this.startX},${this.startY} ${this.startX},${this.startY}`
|
|
295
|
-
};
|
|
296
|
-
break;
|
|
297
|
-
case 'line':
|
|
298
|
-
newShape = {
|
|
299
|
-
id: Date.now().toString(),
|
|
300
|
-
type: 'line',
|
|
301
|
-
x1: this.startX,
|
|
302
|
-
y1: this.startY,
|
|
303
|
-
width: 0,
|
|
304
|
-
height: 0
|
|
305
|
-
};
|
|
306
|
-
break;
|
|
307
|
-
case 'arrow':
|
|
308
|
-
newShape = {
|
|
309
|
-
id: Date.now().toString(),
|
|
310
|
-
type: 'arrow',
|
|
311
|
-
x1: this.startX,
|
|
312
|
-
y1: this.startY,
|
|
313
|
-
width: 0,
|
|
314
|
-
height: 0
|
|
315
|
-
};
|
|
316
|
-
break;
|
|
317
|
-
default:
|
|
318
|
-
return;
|
|
331
|
+
if (this.currentShapeType === 'text') {
|
|
332
|
+
const textElement = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
|
333
|
+
textElement.setAttribute('x', x.toString());
|
|
334
|
+
textElement.setAttribute('y', y.toString());
|
|
335
|
+
textElement.textContent = 'ABC';
|
|
336
|
+
this.svg.appendChild(textElement);
|
|
337
|
+
requestAnimationFrame(() => {
|
|
338
|
+
this.showTextInput(textElement, null, { x, y });
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
this.startX = x;
|
|
343
|
+
this.startY = y;
|
|
344
|
+
this.drawing = true;
|
|
319
345
|
}
|
|
320
|
-
this.selectedShape = newShape;
|
|
321
|
-
this.shapes = [...this.shapes, newShape];
|
|
322
346
|
}
|
|
323
347
|
setMode(mode, shapeType) {
|
|
324
348
|
this.currentMode = mode;
|
|
325
349
|
this.currentShapeType = shapeType;
|
|
326
350
|
}
|
|
327
|
-
// SVG 좌표계로 마우스 좌표 변환
|
|
328
351
|
getSvgPoint(event) {
|
|
329
352
|
const svg = this.svg;
|
|
330
353
|
const point = svg.createSVGPoint();
|
|
@@ -333,23 +356,21 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
333
356
|
const ctm = svg.getScreenCTM().inverse();
|
|
334
357
|
return point.matrixTransform(ctm);
|
|
335
358
|
}
|
|
336
|
-
// 도형 렌더링 함수
|
|
337
359
|
renderShape(shape) {
|
|
338
360
|
const commonAttrs = {
|
|
339
361
|
stroke: shape.selected ? 'blue' : 'red',
|
|
340
|
-
'stroke-width':
|
|
362
|
+
'stroke-width': 1,
|
|
341
363
|
fill: 'transparent',
|
|
342
364
|
cursor: 'pointer'
|
|
343
365
|
};
|
|
344
366
|
switch (shape.type) {
|
|
345
367
|
case 'text':
|
|
346
368
|
return svg `
|
|
347
|
-
|
|
348
369
|
<text
|
|
349
370
|
x="${shape.x}"
|
|
350
371
|
y="${shape.y}"
|
|
351
372
|
fill="${commonAttrs.stroke}"
|
|
352
|
-
style="cursor: ${commonAttrs.cursor}; font-size: 16px;
|
|
373
|
+
style="cursor: ${commonAttrs.cursor}; font-size: 16px;"
|
|
353
374
|
@mousedown="${(e) => this.onShapeMouseDown(e, shape)}"
|
|
354
375
|
@dblclick="${(e) => this.onTextDoubleClick(e, shape)}"
|
|
355
376
|
>${shape.text}</text>
|
|
@@ -440,7 +461,6 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
440
461
|
selected: s.id === shape.id
|
|
441
462
|
}));
|
|
442
463
|
this.selectedShape = this.shapes.find(s => s.id == shape.id);
|
|
443
|
-
// 마우스 클릭 좌표와 도형의 현재 좌표 차이 계산
|
|
444
464
|
const { x, y } = this.getSvgPoint(event);
|
|
445
465
|
switch (shape.type) {
|
|
446
466
|
case 'text':
|
|
@@ -461,15 +481,13 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
461
481
|
this.offsetY = y - shape.y1;
|
|
462
482
|
break;
|
|
463
483
|
}
|
|
464
|
-
// 드래그 이벤트 리스너 추가
|
|
465
484
|
const svg = this.svg;
|
|
466
485
|
svg.addEventListener('mousemove', this.onShapeMouseMove);
|
|
467
486
|
svg.addEventListener('mouseup', this.onShapeMouseUp);
|
|
468
487
|
}
|
|
469
488
|
getScale() {
|
|
470
|
-
if (!this.svg)
|
|
489
|
+
if (!this.svg)
|
|
471
490
|
return 1;
|
|
472
|
-
}
|
|
473
491
|
const [vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
|
|
474
492
|
const scaleX = vbWidth / this.svg.clientWidth;
|
|
475
493
|
const scaleY = vbHeight / this.svg.clientHeight;
|
|
@@ -539,33 +557,109 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
539
557
|
}
|
|
540
558
|
onTextDoubleClick(event, shape) {
|
|
541
559
|
event.stopPropagation();
|
|
542
|
-
|
|
560
|
+
const textElement = event.target;
|
|
561
|
+
this.showTextInput(textElement, shape);
|
|
562
|
+
}
|
|
563
|
+
showTextInput(textElement, shape = null, options) {
|
|
564
|
+
const input = document.createElement('input');
|
|
543
565
|
input.style.position = 'absolute';
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
566
|
+
const ctm = textElement.getScreenCTM() || { a: 1, e: 0, d: 1, f: 0 };
|
|
567
|
+
const bbox = textElement.getBBox();
|
|
568
|
+
const screenX = bbox.x * ctm.a + ctm.e;
|
|
569
|
+
const screenY = bbox.y * ctm.d + ctm.f;
|
|
570
|
+
input.style.left = `${screenX}px`;
|
|
571
|
+
input.style.top = `${screenY}px`;
|
|
572
|
+
const computedStyle = window.getComputedStyle(textElement);
|
|
573
|
+
const fontSize = parseFloat(computedStyle.fontSize) * ctm.a;
|
|
574
|
+
const fontFamily = computedStyle.fontFamily;
|
|
575
|
+
const fontWeight = computedStyle.fontWeight;
|
|
576
|
+
const textColor = computedStyle.fill || computedStyle.color;
|
|
577
|
+
const lineHeight = parseFloat(computedStyle.lineHeight) * ctm.d;
|
|
578
|
+
input.style.fontSize = `${fontSize}px`;
|
|
579
|
+
input.style.fontFamily = fontFamily;
|
|
580
|
+
input.style.fontWeight = fontWeight;
|
|
581
|
+
input.style.color = textColor;
|
|
582
|
+
input.style.lineHeight = `${lineHeight}px`;
|
|
583
|
+
input.style.padding = '0';
|
|
584
|
+
input.style.margin = '0';
|
|
585
|
+
input.style.border = 'none';
|
|
586
|
+
input.style.outline = 'none';
|
|
587
|
+
input.style.background = 'transparent';
|
|
588
|
+
if (shape) {
|
|
589
|
+
input.value = shape.text || '';
|
|
590
|
+
}
|
|
591
|
+
textElement.style.visibility = 'hidden';
|
|
547
592
|
document.body.appendChild(input);
|
|
548
|
-
|
|
593
|
+
this.adjustInputWidth(input);
|
|
594
|
+
requestAnimationFrame(() => input.focus());
|
|
595
|
+
input.addEventListener('input', () => {
|
|
596
|
+
this.adjustInputWidth(input);
|
|
597
|
+
});
|
|
549
598
|
input.addEventListener('keydown', e => {
|
|
550
599
|
if (e.key === 'Enter') {
|
|
551
|
-
|
|
600
|
+
const textValue = input.value.trim();
|
|
601
|
+
if (textValue) {
|
|
602
|
+
if (shape) {
|
|
603
|
+
shape.text = textValue;
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
const newShape = {
|
|
607
|
+
id: Date.now().toString(),
|
|
608
|
+
type: 'text',
|
|
609
|
+
x: options.x,
|
|
610
|
+
y: options.y,
|
|
611
|
+
text: textValue
|
|
612
|
+
};
|
|
613
|
+
this.shapes = [...this.shapes, newShape];
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
else if (shape) {
|
|
617
|
+
this.shapes = this.shapes.filter(s => s.id !== shape.id);
|
|
618
|
+
}
|
|
552
619
|
document.body.removeChild(input);
|
|
553
|
-
|
|
620
|
+
if (!shape) {
|
|
621
|
+
this.svg.removeChild(textElement);
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
textElement.style.visibility = 'visible';
|
|
625
|
+
}
|
|
554
626
|
this.requestUpdate();
|
|
555
627
|
}
|
|
556
628
|
else if (e.key === 'Escape') {
|
|
557
629
|
document.body.removeChild(input);
|
|
558
|
-
|
|
559
|
-
|
|
630
|
+
if (!shape) {
|
|
631
|
+
this.svg.removeChild(textElement);
|
|
632
|
+
}
|
|
633
|
+
else {
|
|
634
|
+
textElement.style.visibility = 'visible';
|
|
635
|
+
}
|
|
560
636
|
}
|
|
561
637
|
});
|
|
562
638
|
input.addEventListener('blur', () => {
|
|
563
639
|
requestAnimationFrame(() => {
|
|
564
|
-
|
|
565
|
-
|
|
640
|
+
if (!shape) {
|
|
641
|
+
this.svg.removeChild(textElement);
|
|
642
|
+
}
|
|
643
|
+
else {
|
|
644
|
+
textElement.style.visibility = 'visible';
|
|
645
|
+
}
|
|
646
|
+
if (input.parentElement) {
|
|
647
|
+
document.body.removeChild(input);
|
|
648
|
+
}
|
|
566
649
|
});
|
|
567
650
|
});
|
|
568
651
|
}
|
|
652
|
+
adjustInputWidth(input) {
|
|
653
|
+
const minWidth = 50;
|
|
654
|
+
const textWidth = this.measureTextWidth(input.value || input.placeholder, input);
|
|
655
|
+
input.style.width = `${Math.max(textWidth + 10, minWidth)}px`;
|
|
656
|
+
}
|
|
657
|
+
measureTextWidth(text, input) {
|
|
658
|
+
const canvas = document.createElement('canvas');
|
|
659
|
+
const context = canvas.getContext('2d');
|
|
660
|
+
context.font = window.getComputedStyle(input).font;
|
|
661
|
+
return context.measureText(text).width;
|
|
662
|
+
}
|
|
569
663
|
};
|
|
570
664
|
__decorate([
|
|
571
665
|
state()
|