@nerd-bible/wordgard 0.5.3-beta6 → 0.5.3-beta7

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 (2) hide show
  1. package/dist/editor.js +68 -35
  2. package/package.json +1 -1
package/dist/editor.js CHANGED
@@ -62,7 +62,7 @@ function separateChange(changes, fromB, toB) {
62
62
  let lenI = 0, dLen = 0;
63
63
  for (let posB = 0, done = false, i = 0; i < changes.length;) {
64
64
  let len = changes[i++], ins = changes[i++], endB = posB + (ins < 0 ? len : ins);
65
- if (fromB > endB || toB < posB) {
65
+ if (fromB >= endB || toB <= posB) {
66
66
  result.push(len, ins);
67
67
  }
68
68
  else {
@@ -1529,6 +1529,8 @@ class DocTile extends CompositeTile {
1529
1529
  changes = separated;
1530
1530
  }
1531
1531
  let builder = new ContentUpdate(state, this, wg, new DecoIterator(state, decoSet), wrapper);
1532
+ if (composition?.target && Tile.get(composition.target))
1533
+ builder.reused.set(Tile.get(composition.target), 2);
1532
1534
  for (let i = 0, posB = 0, startCovered = false; i < changes.length;) {
1533
1535
  let len = changes[i++], ins = changes[i++];
1534
1536
  if (composition && posB == composition.fromB && ins >= 0) {
@@ -3631,6 +3633,7 @@ class InputState {
3631
3633
  mouseSelection = null;
3632
3634
  draggedContent = null;
3633
3635
  notifiedFocused;
3636
+ suppressEvents = false;
3634
3637
  pendingInputEvent = null;
3635
3638
  domDoc;
3636
3639
  _domMapping;
@@ -3646,6 +3649,8 @@ class InputState {
3646
3649
  this._domMapping = ChangeSet.empty(this.domDoc.length);
3647
3650
  }
3648
3651
  handleEvent(event) {
3652
+ if (this.suppressEvents)
3653
+ return;
3649
3654
  if (!eventBelongsToEditor(this.wg, event) || this.ignoreDuringComposition(event))
3650
3655
  return;
3651
3656
  if (event.type == "keydown" && this.keydown(event))
@@ -3797,8 +3802,11 @@ class InputState {
3797
3802
  });
3798
3803
  }
3799
3804
  else if (type == "insertCompositionText") {
3800
- let compositionStart = !wg.inputState.composing.changes;
3801
- wg.inputState.composing.changes++;
3805
+ let compositionStart = true;
3806
+ if (wg.inputState.composing) {
3807
+ compositionStart = !wg.inputState.composing.changes;
3808
+ wg.inputState.composing.changes++;
3809
+ }
3802
3810
  let sel = wg.observer.selectionRange;
3803
3811
  if (!sel.focusNode)
3804
3812
  return false;
@@ -3856,6 +3864,57 @@ class InputState {
3856
3864
  return !tileBefore ? before : !tileAfter ? after : prev == after ? after : before;
3857
3865
  }
3858
3866
  }
3867
+ getCompositionInfo(wg) {
3868
+ let wrap = this.wrappingComposition;
3869
+ if (wrap) {
3870
+ let sel = wg.state.selection.head;
3871
+ return {
3872
+ fromB: sel, toB: sel,
3873
+ text: "",
3874
+ target: null,
3875
+ wrapCursor: wrap
3876
+ };
3877
+ }
3878
+ let comp = this.composing;
3879
+ if (!comp || !(comp.target = this.findComposition(comp.target)))
3880
+ return null;
3881
+ let value = comp.target.nodeValue;
3882
+ let fromB = this.posAtDOM(comp.target, 0, 1), toB = fromB + value.length;
3883
+ let disrupted = false;
3884
+ this.domMapping.iterChanges((fA, tA, fB, tB) => {
3885
+ if (fB < toB && tB > fromB)
3886
+ disrupted = true;
3887
+ });
3888
+ return disrupted ? null : { fromB, toB, text: value, target: comp.target };
3889
+ }
3890
+ clearComposition() {
3891
+ let comp = this.composing;
3892
+ this.composing = null;
3893
+ this.compositionEndedAt = Date.now();
3894
+ if (!comp.target)
3895
+ return false;
3896
+ let pos = this.posAtDOM(comp.target, 0, 1);
3897
+ this.wg.observer.addDirtyRange(pos, pos + comp.target.nodeValue.length);
3898
+ return true;
3899
+ }
3900
+ abortComposition() {
3901
+ if (!this.composing || !this.wg.hasFocus)
3902
+ return;
3903
+ this.clearComposition();
3904
+ this.wg.win.setTimeout(() => {
3905
+ this.suppressEvents = true;
3906
+ try {
3907
+ getSelection(this.wg.root)?.collapse(document.body, 0);
3908
+ let dummy = this.wg.win.document.body.appendChild(document.createElement("input"));
3909
+ dummy.focus();
3910
+ dummy.remove();
3911
+ this.wg.focus();
3912
+ }
3913
+ finally {
3914
+ this.suppressEvents = false;
3915
+ }
3916
+ }, 0);
3917
+ }
3859
3918
  recordTouch(e) {
3860
3919
  this.lastTouchTime = Date.now();
3861
3920
  this.lastTouchEvent = e;
@@ -4118,37 +4177,9 @@ function updateForFocusChange(wg) {
4118
4177
  }
4119
4178
  }, 10);
4120
4179
  }
4121
- function getCompositionInfo(wg) {
4122
- let wrap = wg.inputState.wrappingComposition;
4123
- if (wrap) {
4124
- let sel = wg.state.selection.head;
4125
- return {
4126
- fromB: sel, toB: sel,
4127
- text: "",
4128
- target: null,
4129
- wrapCursor: wrap
4130
- };
4131
- }
4132
- let comp = wg.inputState.composing;
4133
- if (!comp || !(comp.target = wg.inputState.findComposition(comp.target)))
4134
- return null;
4135
- let value = comp.target.nodeValue;
4136
- let pos = wg.inputState.posAtDOM(comp.target, 0);
4137
- return {
4138
- fromB: pos, toB: pos + value.length,
4139
- text: value,
4140
- target: comp.target
4141
- };
4142
- }
4143
4180
  function compositionEnd(wg) {
4144
- let comp = wg.inputState.composing;
4145
- wg.inputState.composing = null;
4146
- wg.inputState.compositionEndedAt = Date.now();
4147
- if (comp && comp.target) {
4148
- let pos = wg.inputState.posAtDOM(comp.target, 0);
4149
- wg.observer.addDirtyRange(pos, pos + comp.target.nodeValue.length);
4181
+ if (wg.inputState.composing && wg.inputState.clearComposition())
4150
4182
  wg.flush();
4151
- }
4152
4183
  }
4153
4184
  function compositionUpdate(wg, event) {
4154
4185
  if (!wg.inputState.composing) {
@@ -4789,8 +4820,8 @@ class Wordgard {
4789
4820
  this.lastFlush = Date.now();
4790
4821
  try {
4791
4822
  let domChanges = this.observer.takeDirty();
4792
- this.viewState.flush();
4793
4823
  this.observer.ignore(() => this.runUpdate(update, domChanges));
4824
+ this.viewState.flush();
4794
4825
  domChanges = null;
4795
4826
  for (let i = 0;; i++) {
4796
4827
  if (i > 5) {
@@ -4856,7 +4887,9 @@ class Wordgard {
4856
4887
  scrollRectIntoView(this.scrollDOM, targetRect, assoc, target.spec.x, target.spec.y, Math.max(Math.min(target.spec.xMargin, offsetWidth), -offsetWidth), Math.max(Math.min(target.spec.yMargin, offsetHeight), -offsetHeight), this.state.textLTR);
4857
4888
  }
4858
4889
  runUpdate(update, domChanges) {
4859
- let composition = this.composing ? getCompositionInfo(this) : null;
4890
+ let composition = this.composing ? this.inputState.getCompositionInfo(this) : null;
4891
+ if (this.composing && !composition)
4892
+ this.inputState.abortComposition();
4860
4893
  let changes = domChanges ? addUpdated(update.changes.sections, domChanges) : update.changes.sections;
4861
4894
  let prevDocTile = this.docTile;
4862
4895
  if (!update.empty) {
@@ -5035,7 +5068,7 @@ class Wordgard {
5035
5068
  if (this.connected)
5036
5069
  this.observer.ignore(() => {
5037
5070
  this.contentDOM.focus({ preventScroll: true });
5038
- if (this.willFlush && this.flushing == 0)
5071
+ if (this.willFlush && this.flushing == 0 && this.viewState.pending.some(tr => tr.docChanged))
5039
5072
  this.flush();
5040
5073
  setDOMSelection(this);
5041
5074
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nerd-bible/wordgard",
3
- "version": "0.5.3-beta6",
3
+ "version": "0.5.3-beta7",
4
4
  "description": "Semantic rich text editor system",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",