modern-text 1.9.0 → 1.9.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.
@@ -1,6 +1,6 @@
1
1
  import { diffChars } from 'diff';
2
2
  import { isCRLF, textContentToString, normalizeCRLF, normalizeTextContent, property } from 'modern-idoc';
3
- import { T as Text } from '../shared/modern-text.y0a7DPYV.mjs';
3
+ import { T as Text } from '../shared/modern-text.B2pcGP3X.mjs';
4
4
  import 'modern-path2d';
5
5
  import 'modern-font';
6
6
 
@@ -49,51 +49,147 @@ function parseHTML(html) {
49
49
  }
50
50
  const SUPPORTS_POINTER_EVENTS = "PointerEvent" in globalThis;
51
51
  class TextEditor extends HTMLElement {
52
- prevSelection = [0, 0];
53
- composition = false;
52
+ _prevSelection = [0, 0];
53
+ _composition = false;
54
+ get composition() {
55
+ return this._composition;
56
+ }
57
+ static _defined = false;
54
58
  static register() {
55
- customElements.define("text-editor", this);
59
+ if (!this._defined) {
60
+ this._defined = true;
61
+ customElements.define("text-editor", this);
62
+ }
56
63
  }
57
64
  _text = new Text();
58
65
  get text() {
59
66
  return this._text;
60
67
  }
61
- set text(value) {
62
- this._text = value;
63
- this._text.on("update", () => this._update());
64
- this.setTextInput(this.getPlaintext());
65
- this.text.update();
66
- this._update();
68
+ set text(newText) {
69
+ if (newText) {
70
+ this._text?.off("update", this._update);
71
+ newText.on("update", this._update);
72
+ this._text = newText;
73
+ this._setTextInput(this.getPlaintext());
74
+ this.text.update();
75
+ this._update();
76
+ }
67
77
  }
68
78
  _oldText = "";
69
- $container;
70
- $selection;
71
- $textarea;
72
- $cursor;
73
- onUpdateProperty(key, _newValue, _oldValue, _declaration) {
79
+ _container;
80
+ _selection;
81
+ _textarea;
82
+ _cursor;
83
+ constructor() {
84
+ super();
85
+ const shadowRoot = this.attachShadow({ mode: "open" });
86
+ shadowRoot.appendChild(
87
+ parseHTML(`
88
+ <style>
89
+ :host {
90
+ position: absolute;
91
+ width: 0;
92
+ height: 0;
93
+ }
94
+
95
+ .container {
96
+ position: absolute;
97
+ }
98
+
99
+ textarea {
100
+ position: absolute;
101
+ opacity: 0;
102
+ caret-color: transparent;
103
+ left: 0;
104
+ top: 0;
105
+ width: 100%;
106
+ height: 100%;
107
+ padding: 0;
108
+ border: 0;
109
+ white-space: pre;
110
+ resize: none;
111
+ }
112
+
113
+ .selection {
114
+ position: absolute;
115
+ left: 0;
116
+ top: 0;
117
+ pointer-events: none;
118
+ }
119
+
120
+ .selection > * {
121
+ position: absolute;
122
+ left: 0;
123
+ top: 0;
124
+ background: rgba(var(--color, 0, 0, 0), 0.4);
125
+ }
126
+
127
+ .cursor {
128
+ position: absolute;
129
+ left: 0;
130
+ top: 0;
131
+ pointer-events: none;
132
+ }
133
+
134
+ .cursor.blink {
135
+ animation: cursor-blink 1s steps(2, start) infinite;
136
+ }
137
+
138
+ @keyframes cursor-blink {
139
+ 100% {
140
+ visibility: hidden;
141
+ }
142
+ }
143
+ </style>
144
+
145
+ <div class="container">
146
+ <textarea></textarea>
147
+ <div class="selection"></div>
148
+ <div class="cursor blink"></div>
149
+ </div>
150
+ `)
151
+ );
152
+ this._container = shadowRoot.querySelector(".container");
153
+ this._selection = shadowRoot.querySelector(".selection");
154
+ this._textarea = shadowRoot.querySelector("textarea");
155
+ this._cursor = shadowRoot.querySelector(".cursor");
156
+ this._bindEventListeners();
157
+ this._update = this._update.bind(this);
158
+ }
159
+ connectedCallback() {
160
+ this._emit("init");
161
+ }
162
+ set(text) {
163
+ this.text = text;
164
+ }
165
+ onUpdateProperty(key, _newValue, _oldValue) {
74
166
  switch (key) {
75
167
  case "selection":
76
- this.selectionMinMax = {
168
+ this._selectionMinMax = {
77
169
  min: Math.min(...this.selection),
78
170
  max: Math.max(...this.selection)
79
171
  };
80
172
  break;
81
- case "selectionMinMax":
173
+ case "_selectionMinMax":
82
174
  case "chars":
83
- this.updateSelectedChars();
84
- this.updateCursorPosition();
175
+ this._updateSelectedChars();
176
+ this._updateCursorPosition();
85
177
  break;
86
- case "showCursor":
87
- case "cursorPosition":
88
- this.renderCursor();
178
+ case "_showCursor":
179
+ case "_cursorPosition":
180
+ this._renderCursor();
89
181
  break;
90
- case "selectedChars":
91
- this.renderCursor();
92
- this.renderSelectRange();
182
+ case "_selectedChars":
183
+ this._renderCursor();
184
+ this._renderSelectRange();
185
+ break;
186
+ case "left":
187
+ case "top":
188
+ this._update();
93
189
  break;
94
190
  }
95
191
  }
96
- updateChars() {
192
+ _updateChars() {
97
193
  const paragraphs = [];
98
194
  this.text.paragraphs.forEach((p, paragraphIndex) => {
99
195
  p.fragments.forEach((f, fragmentIndex) => {
@@ -163,21 +259,21 @@ class TextEditor extends HTMLElement {
163
259
  if (chars[chars.length - 1]) {
164
260
  chars[chars.length - 1].isLast = true;
165
261
  }
166
- this.chars = chars;
262
+ this._chars = chars;
167
263
  }
168
- updateSelectedChars() {
169
- this.selectedChars = this.chars.filter((_char, index) => {
170
- return index >= this.selectionMinMax.min && index < this.selectionMinMax.max;
264
+ _updateSelectedChars() {
265
+ this._selectedChars = this._chars.filter((_char, index) => {
266
+ return index >= this._selectionMinMax.min && index < this._selectionMinMax.max;
171
267
  });
172
- this.emit("selected", [
173
- this.chars[this.selectionMinMax.min],
174
- this.chars[this.selectionMinMax.max]
268
+ this._emit("selected", [
269
+ this._chars[this._selectionMinMax.min],
270
+ this._chars[this._selectionMinMax.max]
175
271
  ]);
176
272
  }
177
- updateCursorPosition() {
273
+ _updateCursorPosition() {
178
274
  let left = 0;
179
275
  let top = 0;
180
- const char = this.chars[this.selectionMinMax.min];
276
+ const char = this._chars[this._selectionMinMax.min];
181
277
  if (char?.isLastSelected) {
182
278
  if (this.text.isVertical) {
183
279
  top += char?.height ?? 0;
@@ -187,7 +283,7 @@ class TextEditor extends HTMLElement {
187
283
  }
188
284
  left += char?.left ?? 0;
189
285
  top += char?.top ?? 0;
190
- this.cursorPosition = {
286
+ this._cursorPosition = {
191
287
  color: char?.color,
192
288
  left,
193
289
  top,
@@ -195,88 +291,14 @@ class TextEditor extends HTMLElement {
195
291
  width: char?.width ?? 0
196
292
  };
197
293
  }
198
- constructor() {
199
- super();
200
- const shadowRoot = this.attachShadow({ mode: "open" });
201
- shadowRoot.appendChild(
202
- parseHTML(`
203
- <style>
204
- :host {
205
- position: absolute;
206
- width: 0;
207
- height: 0;
208
- }
209
-
210
- .container {
211
- position: absolute;
212
- }
213
-
214
- textarea {
215
- position: absolute;
216
- opacity: 0;
217
- caret-color: transparent;
218
- left: 0;
219
- top: 0;
220
- width: 100%;
221
- height: 100%;
222
- padding: 0;
223
- border: 0;
224
- white-space: pre;
225
- }
226
-
227
- .selection {
228
- position: absolute;
229
- left: 0;
230
- top: 0;
231
- pointer-events: none;
232
- }
233
-
234
- .selection > * {
235
- position: absolute;
236
- left: 0;
237
- top: 0;
238
- background: rgba(var(--color, 0, 0, 0), 0.4);
239
- }
240
-
241
- .cursor {
242
- position: absolute;
243
- left: 0;
244
- top: 0;
245
- pointer-events: none;
246
- }
247
-
248
- .cursor.blink {
249
- animation: cursor-blink 1s steps(2, start) infinite;
250
- }
251
-
252
- @keyframes cursor-blink {
253
- 100% {
254
- display: none;
255
- }
256
- }
257
- </style>
258
-
259
- <div class="container">
260
- <textarea autofocus></textarea>
261
- <div class="selection"></div>
262
- <div class="cursor blink"></div>
263
- </div>
264
- `)
265
- );
266
- this.$container = shadowRoot.querySelector(".container");
267
- this.$selection = shadowRoot.querySelector(".selection");
268
- this.$textarea = shadowRoot.querySelector("textarea");
269
- this.$cursor = shadowRoot.querySelector(".cursor");
270
- this.bindEventListeners();
271
- }
272
294
  getPlaintext() {
273
295
  return textContentToString(
274
- this.getNewContent(
296
+ this._getNewContent(
275
297
  this.text.content
276
298
  )
277
299
  );
278
300
  }
279
- getNewContent(content, newString = textContentToString(content), oldString = newString) {
301
+ _getNewContent(content, newString = textContentToString(content), oldString = newString) {
280
302
  newString = normalizeCRLF(newString);
281
303
  newString = newString.replace(emojiRE, (emoji) => {
282
304
  if (Array.from(emoji).length > 1) {
@@ -344,41 +366,41 @@ class TextEditor extends HTMLElement {
344
366
  });
345
367
  return newContents;
346
368
  }
347
- setTextInput(newText) {
348
- this.$textarea.value = newText;
369
+ _setTextInput(newText) {
370
+ this._textarea.value = newText;
349
371
  this._oldText = newText;
350
372
  }
351
- onInput() {
352
- const newText = this.$textarea.value;
353
- this.text.content = this.getNewContent(
373
+ _onInput() {
374
+ const newText = this._textarea.value;
375
+ this.text.content = this._getNewContent(
354
376
  this.text.content,
355
377
  newText,
356
378
  this._oldText
357
379
  );
358
380
  this._oldText = newText;
359
381
  this.text.update();
360
- this.emit("update");
382
+ this._emit("update");
361
383
  }
362
384
  _timer;
363
- onKeydown(e) {
385
+ _onKeydown(e) {
364
386
  e.stopPropagation();
365
387
  switch (e.key) {
366
388
  case "Escape":
367
- return this.$textarea.blur();
389
+ return this._textarea.blur();
368
390
  }
369
- this.updateSelectionByDom();
370
- setTimeout(() => this.updateSelectionByDom(), 0);
371
- setTimeout(() => this.updateSelectionByDom(), 100);
391
+ this._updateSelectionByDom();
392
+ setTimeout(() => this._updateSelectionByDom(), 0);
393
+ setTimeout(() => this._updateSelectionByDom(), 100);
372
394
  }
373
- onFocus() {
374
- this.showCursor = true;
395
+ _onFocus() {
396
+ this._showCursor = true;
375
397
  }
376
- onBlur() {
377
- this.showCursor = false;
398
+ _onBlur() {
399
+ this._showCursor = false;
378
400
  }
379
- findNearest(options) {
401
+ _findNearest(options) {
380
402
  const { x, y, xWeight = 1, yWeight = 1 } = options;
381
- const char = this.chars.reduce(
403
+ const char = this._chars.reduce(
382
404
  (prev, current, index) => {
383
405
  const diff = Math.abs(current.left + current.width / 2 - x) * xWeight + Math.abs(current.top + current.height / 2 - y) * yWeight;
384
406
  if (diff < prev.diff) {
@@ -405,120 +427,133 @@ class TextEditor extends HTMLElement {
405
427
  }
406
428
  return -1;
407
429
  }
408
- updateSelectionByDom() {
409
- if (this.composition) {
410
- this.selection = this.prevSelection;
430
+ _updateSelectionByDom() {
431
+ if (this._composition) {
432
+ this.selection = this._prevSelection;
411
433
  } else {
412
434
  let count = 0;
413
435
  const _selection = [];
414
- this.chars.forEach((char, index) => {
415
- if (count <= this.$textarea.selectionStart) {
436
+ this._chars.forEach((char, index) => {
437
+ if (count <= this._textarea.selectionStart) {
416
438
  _selection[0] = index;
417
- } else if (count <= this.$textarea.selectionEnd) {
439
+ } else if (count <= this._textarea.selectionEnd) {
418
440
  _selection[1] = index;
419
441
  }
420
442
  count += char.content.length;
421
443
  });
422
444
  const oldSelection = this.selection;
423
445
  this.selection = _selection;
424
- this.prevSelection = oldSelection;
446
+ this._prevSelection = oldSelection;
425
447
  }
426
448
  }
427
- updateDomSelection() {
449
+ _updateDomSelection() {
428
450
  let start = 0;
429
451
  let end = 0;
430
- this.chars.forEach((char, index) => {
431
- if (index < this.selectionMinMax.min) {
452
+ this._chars.forEach((char, index) => {
453
+ if (index < this._selectionMinMax.min) {
432
454
  start += char.content.length;
433
455
  end = start;
434
- } else if (index < this.selectionMinMax.max) {
456
+ } else if (index < this._selectionMinMax.max) {
435
457
  end += char.content.length;
436
458
  }
437
459
  });
438
- this.$textarea.selectionStart = start;
439
- this.$textarea.selectionEnd = end;
460
+ this._textarea.selectionStart = start;
461
+ this._textarea.selectionEnd = end;
440
462
  }
441
463
  _update() {
442
- this.updateChars();
464
+ this._updateChars();
443
465
  const host = this.shadowRoot.host;
466
+ host.style.left = `${this.left}px`;
467
+ host.style.top = `${this.top}px`;
444
468
  host.style.width = `${this.text.boundingBox.width}px`;
445
469
  host.style.height = `${this.text.boundingBox.height}px`;
446
- this.$container.style.left = `${this.text.glyphBox.left}px`;
447
- this.$container.style.top = `${this.text.glyphBox.top}px`;
448
- this.$container.style.width = `${this.text.glyphBox.width}px`;
449
- this.$container.style.height = `${this.text.glyphBox.height}px`;
450
- this.$textarea.style.fontSize = `${this.text.computedStyle.fontSize}px`;
451
- this.$textarea.style.writingMode = this.text.computedStyle.writingMode;
452
- this.renderSelectRange();
453
- this.renderCursor();
454
- }
455
- bindEventListeners() {
456
- this.$textarea.addEventListener("compositionstart", () => this.composition = true);
457
- this.$textarea.addEventListener("compositionend", () => this.composition = false);
458
- this.$textarea.addEventListener("keydown", this.onKeydown.bind(this));
459
- this.$textarea.addEventListener("input", this.onInput.bind(this));
460
- this.$textarea.addEventListener("focus", this.onFocus.bind(this));
461
- this.$textarea.addEventListener("blur", this.onBlur.bind(this));
470
+ this._container.style.left = `${this.text.glyphBox.left}px`;
471
+ this._container.style.top = `${this.text.glyphBox.top}px`;
472
+ this._container.style.width = `${this.text.glyphBox.width}px`;
473
+ this._container.style.height = `${this.text.glyphBox.height}px`;
474
+ this._textarea.style.fontSize = `${this.text.computedStyle.fontSize}px`;
475
+ this._textarea.style.writingMode = this.text.computedStyle.writingMode;
476
+ this._renderSelectRange();
477
+ this._renderCursor();
478
+ }
479
+ _bindEventListeners() {
480
+ this._textarea.addEventListener("compositionstart", () => this._composition = true);
481
+ this._textarea.addEventListener("compositionend", () => this._composition = false);
482
+ this._textarea.addEventListener("keydown", this._onKeydown.bind(this));
483
+ this._textarea.addEventListener("input", this._onInput.bind(this));
484
+ this._textarea.addEventListener("focus", this._onFocus.bind(this));
485
+ this._textarea.addEventListener("blur", this._onBlur.bind(this));
462
486
  if (SUPPORTS_POINTER_EVENTS) {
463
- this.$textarea.addEventListener("pointerdown", this.start.bind(this));
487
+ this._textarea.addEventListener("pointerdown", this.pointerdown.bind(this));
464
488
  } else {
465
- this.$textarea.addEventListener("mousedown", this.start.bind(this));
489
+ this._textarea.addEventListener("mousedown", this.pointerdown.bind(this));
466
490
  }
467
491
  ["keyup", "mouseup", "input", "paste", "cut"].forEach((key) => {
468
- this.$textarea.addEventListener(key, () => {
469
- this.updateSelectionByDom();
492
+ this._textarea.addEventListener(key, () => {
493
+ this._updateSelectionByDom();
470
494
  });
471
495
  });
472
496
  }
473
- start(e) {
497
+ pointerdown(e) {
498
+ if (e && e.button !== 0) {
499
+ e.preventDefault();
500
+ e.stopPropagation();
501
+ return false;
502
+ }
474
503
  const host = this.shadowRoot.host;
475
504
  const rect = host.getBoundingClientRect();
476
505
  const originalWidth = host.offsetWidth;
477
506
  const originalHeight = host.offsetHeight;
478
507
  const scaleX = rect.width / originalWidth;
479
508
  const scaleY = rect.height / originalHeight;
480
- const offsetX = (e.clientX - rect.left) / scaleX;
481
- const offsetY = (e.clientY - rect.top) / scaleY;
482
- if (!(offsetX > this.text.glyphBox.left && offsetX < this.text.glyphBox.left + this.text.glyphBox.width && offsetY > this.text.glyphBox.top && offsetY < this.text.glyphBox.top + this.text.glyphBox.height)) {
483
- return false;
509
+ let offsetX = 0;
510
+ let offsetY = 0;
511
+ if (e) {
512
+ offsetX = (e.clientX - rect.left) / scaleX;
513
+ offsetY = (e.clientY - rect.top) / scaleY;
514
+ if (!(offsetX > this.text.glyphBox.left && offsetX < this.text.glyphBox.left + this.text.glyphBox.width && offsetY > this.text.glyphBox.top && offsetY < this.text.glyphBox.top + this.text.glyphBox.height)) {
515
+ return false;
516
+ }
517
+ e.preventDefault();
518
+ e.stopPropagation();
484
519
  }
485
- e.preventDefault();
486
- e.stopPropagation();
487
- const index = this.findNearest({ x: offsetX, y: offsetY });
520
+ const index = this._findNearest({ x: offsetX, y: offsetY });
488
521
  this.selection = [index, index];
489
- this.updateDomSelection();
490
- const onMove = (e2) => {
491
- const offsetX2 = (e2.clientX - rect.left) / scaleX;
492
- const offsetY2 = (e2.clientY - rect.top) / scaleY;
493
- this.selection = [
494
- this.selection[0],
495
- this.findNearest({ x: offsetX2, y: offsetY2 })
496
- ];
497
- this.updateDomSelection();
498
- };
499
- const onUp = () => {
522
+ this._updateDomSelection();
523
+ if (e && !["mouseup", "pointerup"].includes(e.type)) {
524
+ const onMove = (e2) => {
525
+ const offsetX2 = (e2.clientX - rect.left) / scaleX;
526
+ const offsetY2 = (e2.clientY - rect.top) / scaleY;
527
+ this.selection = [
528
+ this.selection[0],
529
+ this._findNearest({ x: offsetX2, y: offsetY2 })
530
+ ];
531
+ this._updateDomSelection();
532
+ };
533
+ const onUp = () => {
534
+ if (SUPPORTS_POINTER_EVENTS) {
535
+ document.removeEventListener("pointermove", onMove);
536
+ document.removeEventListener("pointerup", onUp);
537
+ } else {
538
+ document.removeEventListener("mousemove", onMove);
539
+ document.removeEventListener("mouseup", onUp);
540
+ }
541
+ };
500
542
  if (SUPPORTS_POINTER_EVENTS) {
501
- document.removeEventListener("pointermove", onMove);
502
- document.removeEventListener("pointerup", onUp);
543
+ document.addEventListener("pointermove", onMove);
544
+ document.addEventListener("pointerup", onUp);
503
545
  } else {
504
- document.removeEventListener("mousemove", onMove);
505
- document.removeEventListener("mouseup", onUp);
546
+ document.addEventListener("mousemove", onMove);
547
+ document.addEventListener("mouseup", onUp);
506
548
  }
507
- };
508
- if (SUPPORTS_POINTER_EVENTS) {
509
- document.addEventListener("pointermove", onMove);
510
- document.addEventListener("pointerup", onUp);
511
- } else {
512
- document.addEventListener("mousemove", onMove);
513
- document.addEventListener("mouseup", onUp);
514
549
  }
515
- this.$textarea.focus();
550
+ this._textarea.focus();
516
551
  return true;
517
552
  }
518
553
  attributeChangedCallback(name, _oldValue, newValue) {
519
554
  this[name] = newValue;
520
555
  }
521
- emit(type, detail) {
556
+ _emit(type, detail) {
522
557
  return this.dispatchEvent(
523
558
  new CustomEvent(type, {
524
559
  bubbles: true,
@@ -528,11 +563,11 @@ class TextEditor extends HTMLElement {
528
563
  })
529
564
  );
530
565
  }
531
- renderSelectRange() {
532
- if (this.selection[0] !== this.prevSelection[0] || this.selection[1] !== this.prevSelection[1]) {
566
+ _renderSelectRange() {
567
+ if (this.selection[0] !== this._prevSelection[0] || this.selection[1] !== this._prevSelection[1]) {
533
568
  const isVertical = this.text.isVertical;
534
569
  const boxesGroupsMap = {};
535
- this.selectedChars.forEach((char) => {
570
+ this._selectedChars.forEach((char) => {
536
571
  if (char.isLastSelected) {
537
572
  return;
538
573
  }
@@ -548,18 +583,19 @@ class TextEditor extends HTMLElement {
548
583
  });
549
584
  });
550
585
  const boxesGroups = Object.values(boxesGroupsMap);
551
- const sourceLen = this.$selection.children.length;
586
+ const sourceLen = this._selection.children.length;
552
587
  const targetLen = boxesGroups.length;
553
588
  const len = Math.max(sourceLen, targetLen);
589
+ const deleted = [];
554
590
  for (let i = 0; i < len; i++) {
555
- let element = this.$selection.children.item(i);
591
+ let element = this._selection.children.item(i);
556
592
  const boxes = boxesGroups[i];
557
593
  if (!boxes) {
558
- element?.remove();
594
+ deleted.push(element);
559
595
  continue;
560
596
  } else if (!element) {
561
597
  element = document.createElement("div");
562
- this.$selection.append(element);
598
+ this._selection.append(element);
563
599
  }
564
600
  const min = {
565
601
  x: Math.min(...boxes.map((v) => v.x)),
@@ -573,46 +609,51 @@ class TextEditor extends HTMLElement {
573
609
  element.style.height = `${max.y - min.y}px`;
574
610
  element.style.transform = `translate(${min.x}px, ${min.y}px)`;
575
611
  }
612
+ deleted.forEach((el) => el?.remove());
576
613
  }
577
614
  }
578
- renderCursor() {
579
- if (this.showCursor && this.cursorPosition && (this.selection[0] !== this.prevSelection[0] || this.selection[1] !== this.prevSelection[1])) {
580
- if (this.selectedChars.length === 0) {
581
- this.$cursor.style.visibility = "visible";
582
- const cursorPosition = this.cursorPosition;
583
- this.$cursor.style.backgroundColor = cursorPosition.color ?? "rgba(var(--color)";
584
- this.$cursor.style.left = `${cursorPosition.left - this.text.glyphBox.left}px`;
585
- this.$cursor.style.top = `${cursorPosition.top - this.text.glyphBox.top}px`;
586
- this.$cursor.style.height = this.text.isVertical ? "1px" : `${cursorPosition.height}px`;
587
- this.$cursor.style.width = this.text.isVertical ? `${cursorPosition.width}px` : "1px";
588
- } else {
589
- this.$cursor.style.visibility = "hidden";
590
- }
591
- this.$cursor.classList.remove("blink");
592
- if (this._timer) {
593
- clearTimeout(this._timer);
594
- }
595
- this._timer = setTimeout(() => this.$cursor.classList.add("blink"), 500);
615
+ _renderCursor() {
616
+ if (this._showCursor && this._cursorPosition && this._selectedChars.length === 0) {
617
+ const _cursorPosition = this._cursorPosition;
618
+ this._cursor.style.display = "block";
619
+ this._cursor.style.backgroundColor = _cursorPosition.color ?? "rgba(var(--color))";
620
+ this._cursor.style.left = `${_cursorPosition.left - this.text.glyphBox.left}px`;
621
+ this._cursor.style.top = `${_cursorPosition.top - this.text.glyphBox.top}px`;
622
+ this._cursor.style.height = this.text.isVertical ? "1px" : `${_cursorPosition.height}px`;
623
+ this._cursor.style.width = this.text.isVertical ? `${_cursorPosition.width}px` : "1px";
624
+ } else {
625
+ this._cursor.style.display = "none";
626
+ }
627
+ this._cursor.classList.remove("blink");
628
+ if (this._timer) {
629
+ clearTimeout(this._timer);
596
630
  }
631
+ this._timer = setTimeout(() => this._cursor.classList.add("blink"), 500);
597
632
  }
598
633
  }
634
+ __decorateClass([
635
+ property({ fallback: 0 })
636
+ ], TextEditor.prototype, "left");
637
+ __decorateClass([
638
+ property({ fallback: 0 })
639
+ ], TextEditor.prototype, "top");
599
640
  __decorateClass([
600
641
  property({ fallback: () => [0, 0] })
601
642
  ], TextEditor.prototype, "selection");
602
643
  __decorateClass([
603
- property({ fallback: () => ({ min: 0, max: 0 }) })
604
- ], TextEditor.prototype, "selectionMinMax");
644
+ property({ internal: true, fallback: () => ({ min: 0, max: 0 }) })
645
+ ], TextEditor.prototype, "_selectionMinMax");
605
646
  __decorateClass([
606
- property({ fallback: () => [] })
607
- ], TextEditor.prototype, "chars");
647
+ property({ internal: true, fallback: () => [] })
648
+ ], TextEditor.prototype, "_chars");
608
649
  __decorateClass([
609
- property({ fallback: () => [] })
610
- ], TextEditor.prototype, "selectedChars");
650
+ property({ internal: true, fallback: () => [] })
651
+ ], TextEditor.prototype, "_selectedChars");
611
652
  __decorateClass([
612
- property()
613
- ], TextEditor.prototype, "cursorPosition");
653
+ property({ internal: true })
654
+ ], TextEditor.prototype, "_cursorPosition");
614
655
  __decorateClass([
615
- property({ fallback: false })
616
- ], TextEditor.prototype, "showCursor");
656
+ property({ internal: true, fallback: false })
657
+ ], TextEditor.prototype, "_showCursor");
617
658
 
618
659
  export { TextEditor };