@codemirror/view 6.7.0 → 6.7.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 6.7.1 (2022-12-12)
2
+
3
+ ### Bug fixes
4
+
5
+ Make the editor properly scroll when moving the pointer out of it during drag selection.
6
+
7
+ Fix a regression where clicking below the content element in an editor with its own height didn't focus the editor.
8
+
1
9
  ## 6.7.0 (2022-12-07)
2
10
 
3
11
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -191,6 +191,26 @@ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
191
191
  }
192
192
  }
193
193
  }
194
+ function scrollableParent(dom) {
195
+ let doc = dom.ownerDocument;
196
+ for (let cur = dom.parentNode; cur;) {
197
+ if (cur == doc.body) {
198
+ break;
199
+ }
200
+ else if (cur.nodeType == 1) {
201
+ if (cur.scrollHeight > cur.clientHeight || cur.scrollWidth > cur.clientWidth)
202
+ return cur;
203
+ cur = cur.assignedSlot || cur.parentNode;
204
+ }
205
+ else if (cur.nodeType == 11) {
206
+ cur = cur.host;
207
+ }
208
+ else {
209
+ break;
210
+ }
211
+ }
212
+ return null;
213
+ }
194
214
  class DOMSelectionState {
195
215
  constructor() {
196
216
  this.anchorNode = null;
@@ -3391,22 +3411,30 @@ class InputState {
3391
3411
  this.compositionFirstChange = null;
3392
3412
  this.compositionEndedAt = 0;
3393
3413
  this.mouseSelection = null;
3414
+ let handleEvent = (handler, event) => {
3415
+ if (this.ignoreDuringComposition(event))
3416
+ return;
3417
+ if (event.type == "keydown" && this.keydown(view, event))
3418
+ return;
3419
+ if (this.mustFlushObserver(event))
3420
+ view.observer.forceFlush();
3421
+ if (this.runCustomHandlers(event.type, view, event))
3422
+ event.preventDefault();
3423
+ else
3424
+ handler(view, event);
3425
+ };
3394
3426
  for (let type in handlers) {
3395
3427
  let handler = handlers[type];
3396
- view.contentDOM.addEventListener(type, (event) => {
3397
- if (!eventBelongsToEditor(view, event) || this.ignoreDuringComposition(event))
3398
- return;
3399
- if (type == "keydown" && this.keydown(view, event))
3400
- return;
3401
- if (this.mustFlushObserver(event))
3402
- view.observer.forceFlush();
3403
- if (this.runCustomHandlers(type, view, event))
3404
- event.preventDefault();
3405
- else
3406
- handler(view, event);
3428
+ view.contentDOM.addEventListener(type, event => {
3429
+ if (eventBelongsToEditor(view, event))
3430
+ handleEvent(handler, event);
3407
3431
  }, handlerOptions[type]);
3408
3432
  this.registeredEvents.push(type);
3409
3433
  }
3434
+ view.scrollDOM.addEventListener("mousedown", (event) => {
3435
+ if (event.target == view.scrollDOM)
3436
+ handleEvent(handlers.mousedown, event);
3437
+ });
3410
3438
  if (browser.chrome && browser.chrome_version == 102) { // FIXME remove at some point
3411
3439
  // On Chrome 102, viewport updates somehow stop wheel-based
3412
3440
  // scrolling. Turning off pointer events during the scroll seems
@@ -3563,12 +3591,18 @@ const PendingKeys = [
3563
3591
  const EmacsyPendingKeys = "dthko";
3564
3592
  // Key codes for modifier keys
3565
3593
  const modifierCodes = [16, 17, 18, 20, 91, 92, 224, 225];
3594
+ function dragScrollSpeed(dist) {
3595
+ return dist * 0.7 + 8;
3596
+ }
3566
3597
  class MouseSelection {
3567
3598
  constructor(view, startEvent, style, mustSelect) {
3568
3599
  this.view = view;
3569
3600
  this.style = style;
3570
3601
  this.mustSelect = mustSelect;
3602
+ this.scrollSpeed = { x: 0, y: 0 };
3603
+ this.scrolling = -1;
3571
3604
  this.lastEvent = startEvent;
3605
+ this.scrollParent = scrollableParent(view.contentDOM);
3572
3606
  let doc = view.contentDOM.ownerDocument;
3573
3607
  doc.addEventListener("mousemove", this.move = this.move.bind(this));
3574
3608
  doc.addEventListener("mouseup", this.up = this.up.bind(this));
@@ -3584,11 +3618,24 @@ class MouseSelection {
3584
3618
  }
3585
3619
  }
3586
3620
  move(event) {
3621
+ var _a;
3587
3622
  if (event.buttons == 0)
3588
3623
  return this.destroy();
3589
3624
  if (this.dragging !== false)
3590
3625
  return;
3591
3626
  this.select(this.lastEvent = event);
3627
+ let sx = 0, sy = 0;
3628
+ let rect = ((_a = this.scrollParent) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect())
3629
+ || { left: 0, top: 0, right: this.view.win.innerWidth, bottom: this.view.win.innerHeight };
3630
+ if (event.clientX <= rect.left)
3631
+ sx = -dragScrollSpeed(rect.left - event.clientX);
3632
+ else if (event.clientX >= rect.right)
3633
+ sx = dragScrollSpeed(event.clientX - rect.right);
3634
+ if (event.clientY <= rect.top)
3635
+ sy = -dragScrollSpeed(rect.top - event.clientY);
3636
+ else if (event.clientY >= rect.bottom)
3637
+ sy = dragScrollSpeed(event.clientY - rect.bottom);
3638
+ this.setScrollSpeed(sx, sy);
3592
3639
  }
3593
3640
  up(event) {
3594
3641
  if (this.dragging == null)
@@ -3598,19 +3645,41 @@ class MouseSelection {
3598
3645
  this.destroy();
3599
3646
  }
3600
3647
  destroy() {
3648
+ this.setScrollSpeed(0, 0);
3601
3649
  let doc = this.view.contentDOM.ownerDocument;
3602
3650
  doc.removeEventListener("mousemove", this.move);
3603
3651
  doc.removeEventListener("mouseup", this.up);
3604
3652
  this.view.inputState.mouseSelection = null;
3605
3653
  }
3654
+ setScrollSpeed(sx, sy) {
3655
+ this.scrollSpeed = { x: sx, y: sy };
3656
+ if (sx || sy) {
3657
+ if (this.scrolling < 0)
3658
+ this.scrolling = setInterval(() => this.scroll(), 50);
3659
+ }
3660
+ else if (this.scrolling > -1) {
3661
+ clearInterval(this.scrolling);
3662
+ this.scrolling = -1;
3663
+ }
3664
+ }
3665
+ scroll() {
3666
+ if (this.scrollParent) {
3667
+ this.scrollParent.scrollLeft += this.scrollSpeed.x;
3668
+ this.scrollParent.scrollTop += this.scrollSpeed.y;
3669
+ }
3670
+ else {
3671
+ this.view.win.scrollBy(this.scrollSpeed.x, this.scrollSpeed.y);
3672
+ }
3673
+ if (this.dragging === false)
3674
+ this.select(this.lastEvent);
3675
+ }
3606
3676
  select(event) {
3607
3677
  let selection = this.style.get(event, this.extend, this.multiple);
3608
3678
  if (this.mustSelect || !selection.eq(this.view.state.selection) ||
3609
3679
  selection.main.assoc != this.view.state.selection.main.assoc)
3610
3680
  this.view.dispatch({
3611
3681
  selection,
3612
- userEvent: "select.pointer",
3613
- scrollIntoView: true
3682
+ userEvent: "select.pointer"
3614
3683
  });
3615
3684
  this.mustSelect = false;
3616
3685
  }
@@ -3801,23 +3870,15 @@ function getClickType(event) {
3801
3870
  function basicMouseSelection(view, event) {
3802
3871
  let start = queryPos(view, event), type = getClickType(event);
3803
3872
  let startSel = view.state.selection;
3804
- let last = start, lastEvent = event;
3805
3873
  return {
3806
3874
  update(update) {
3807
3875
  if (update.docChanged) {
3808
3876
  start.pos = update.changes.mapPos(start.pos);
3809
3877
  startSel = startSel.map(update.changes);
3810
- lastEvent = null;
3811
3878
  }
3812
3879
  },
3813
3880
  get(event, extend, multiple) {
3814
- let cur;
3815
- if (lastEvent && event.clientX == lastEvent.clientX && event.clientY == lastEvent.clientY)
3816
- cur = last;
3817
- else {
3818
- cur = last = queryPos(view, event);
3819
- lastEvent = event;
3820
- }
3881
+ let cur = queryPos(view, event);
3821
3882
  let range = rangeForClick(view, cur.pos, cur.bias, type);
3822
3883
  if (start.pos != cur.pos && !extend) {
3823
3884
  let startRange = rangeForClick(view, start.pos, start.bias, type);
package/dist/index.js CHANGED
@@ -187,6 +187,26 @@ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
187
187
  }
188
188
  }
189
189
  }
190
+ function scrollableParent(dom) {
191
+ let doc = dom.ownerDocument;
192
+ for (let cur = dom.parentNode; cur;) {
193
+ if (cur == doc.body) {
194
+ break;
195
+ }
196
+ else if (cur.nodeType == 1) {
197
+ if (cur.scrollHeight > cur.clientHeight || cur.scrollWidth > cur.clientWidth)
198
+ return cur;
199
+ cur = cur.assignedSlot || cur.parentNode;
200
+ }
201
+ else if (cur.nodeType == 11) {
202
+ cur = cur.host;
203
+ }
204
+ else {
205
+ break;
206
+ }
207
+ }
208
+ return null;
209
+ }
190
210
  class DOMSelectionState {
191
211
  constructor() {
192
212
  this.anchorNode = null;
@@ -3385,22 +3405,30 @@ class InputState {
3385
3405
  this.compositionFirstChange = null;
3386
3406
  this.compositionEndedAt = 0;
3387
3407
  this.mouseSelection = null;
3408
+ let handleEvent = (handler, event) => {
3409
+ if (this.ignoreDuringComposition(event))
3410
+ return;
3411
+ if (event.type == "keydown" && this.keydown(view, event))
3412
+ return;
3413
+ if (this.mustFlushObserver(event))
3414
+ view.observer.forceFlush();
3415
+ if (this.runCustomHandlers(event.type, view, event))
3416
+ event.preventDefault();
3417
+ else
3418
+ handler(view, event);
3419
+ };
3388
3420
  for (let type in handlers) {
3389
3421
  let handler = handlers[type];
3390
- view.contentDOM.addEventListener(type, (event) => {
3391
- if (!eventBelongsToEditor(view, event) || this.ignoreDuringComposition(event))
3392
- return;
3393
- if (type == "keydown" && this.keydown(view, event))
3394
- return;
3395
- if (this.mustFlushObserver(event))
3396
- view.observer.forceFlush();
3397
- if (this.runCustomHandlers(type, view, event))
3398
- event.preventDefault();
3399
- else
3400
- handler(view, event);
3422
+ view.contentDOM.addEventListener(type, event => {
3423
+ if (eventBelongsToEditor(view, event))
3424
+ handleEvent(handler, event);
3401
3425
  }, handlerOptions[type]);
3402
3426
  this.registeredEvents.push(type);
3403
3427
  }
3428
+ view.scrollDOM.addEventListener("mousedown", (event) => {
3429
+ if (event.target == view.scrollDOM)
3430
+ handleEvent(handlers.mousedown, event);
3431
+ });
3404
3432
  if (browser.chrome && browser.chrome_version == 102) { // FIXME remove at some point
3405
3433
  // On Chrome 102, viewport updates somehow stop wheel-based
3406
3434
  // scrolling. Turning off pointer events during the scroll seems
@@ -3557,12 +3585,18 @@ const PendingKeys = [
3557
3585
  const EmacsyPendingKeys = "dthko";
3558
3586
  // Key codes for modifier keys
3559
3587
  const modifierCodes = [16, 17, 18, 20, 91, 92, 224, 225];
3588
+ function dragScrollSpeed(dist) {
3589
+ return dist * 0.7 + 8;
3590
+ }
3560
3591
  class MouseSelection {
3561
3592
  constructor(view, startEvent, style, mustSelect) {
3562
3593
  this.view = view;
3563
3594
  this.style = style;
3564
3595
  this.mustSelect = mustSelect;
3596
+ this.scrollSpeed = { x: 0, y: 0 };
3597
+ this.scrolling = -1;
3565
3598
  this.lastEvent = startEvent;
3599
+ this.scrollParent = scrollableParent(view.contentDOM);
3566
3600
  let doc = view.contentDOM.ownerDocument;
3567
3601
  doc.addEventListener("mousemove", this.move = this.move.bind(this));
3568
3602
  doc.addEventListener("mouseup", this.up = this.up.bind(this));
@@ -3578,11 +3612,24 @@ class MouseSelection {
3578
3612
  }
3579
3613
  }
3580
3614
  move(event) {
3615
+ var _a;
3581
3616
  if (event.buttons == 0)
3582
3617
  return this.destroy();
3583
3618
  if (this.dragging !== false)
3584
3619
  return;
3585
3620
  this.select(this.lastEvent = event);
3621
+ let sx = 0, sy = 0;
3622
+ let rect = ((_a = this.scrollParent) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect())
3623
+ || { left: 0, top: 0, right: this.view.win.innerWidth, bottom: this.view.win.innerHeight };
3624
+ if (event.clientX <= rect.left)
3625
+ sx = -dragScrollSpeed(rect.left - event.clientX);
3626
+ else if (event.clientX >= rect.right)
3627
+ sx = dragScrollSpeed(event.clientX - rect.right);
3628
+ if (event.clientY <= rect.top)
3629
+ sy = -dragScrollSpeed(rect.top - event.clientY);
3630
+ else if (event.clientY >= rect.bottom)
3631
+ sy = dragScrollSpeed(event.clientY - rect.bottom);
3632
+ this.setScrollSpeed(sx, sy);
3586
3633
  }
3587
3634
  up(event) {
3588
3635
  if (this.dragging == null)
@@ -3592,19 +3639,41 @@ class MouseSelection {
3592
3639
  this.destroy();
3593
3640
  }
3594
3641
  destroy() {
3642
+ this.setScrollSpeed(0, 0);
3595
3643
  let doc = this.view.contentDOM.ownerDocument;
3596
3644
  doc.removeEventListener("mousemove", this.move);
3597
3645
  doc.removeEventListener("mouseup", this.up);
3598
3646
  this.view.inputState.mouseSelection = null;
3599
3647
  }
3648
+ setScrollSpeed(sx, sy) {
3649
+ this.scrollSpeed = { x: sx, y: sy };
3650
+ if (sx || sy) {
3651
+ if (this.scrolling < 0)
3652
+ this.scrolling = setInterval(() => this.scroll(), 50);
3653
+ }
3654
+ else if (this.scrolling > -1) {
3655
+ clearInterval(this.scrolling);
3656
+ this.scrolling = -1;
3657
+ }
3658
+ }
3659
+ scroll() {
3660
+ if (this.scrollParent) {
3661
+ this.scrollParent.scrollLeft += this.scrollSpeed.x;
3662
+ this.scrollParent.scrollTop += this.scrollSpeed.y;
3663
+ }
3664
+ else {
3665
+ this.view.win.scrollBy(this.scrollSpeed.x, this.scrollSpeed.y);
3666
+ }
3667
+ if (this.dragging === false)
3668
+ this.select(this.lastEvent);
3669
+ }
3600
3670
  select(event) {
3601
3671
  let selection = this.style.get(event, this.extend, this.multiple);
3602
3672
  if (this.mustSelect || !selection.eq(this.view.state.selection) ||
3603
3673
  selection.main.assoc != this.view.state.selection.main.assoc)
3604
3674
  this.view.dispatch({
3605
3675
  selection,
3606
- userEvent: "select.pointer",
3607
- scrollIntoView: true
3676
+ userEvent: "select.pointer"
3608
3677
  });
3609
3678
  this.mustSelect = false;
3610
3679
  }
@@ -3795,23 +3864,15 @@ function getClickType(event) {
3795
3864
  function basicMouseSelection(view, event) {
3796
3865
  let start = queryPos(view, event), type = getClickType(event);
3797
3866
  let startSel = view.state.selection;
3798
- let last = start, lastEvent = event;
3799
3867
  return {
3800
3868
  update(update) {
3801
3869
  if (update.docChanged) {
3802
3870
  start.pos = update.changes.mapPos(start.pos);
3803
3871
  startSel = startSel.map(update.changes);
3804
- lastEvent = null;
3805
3872
  }
3806
3873
  },
3807
3874
  get(event, extend, multiple) {
3808
- let cur;
3809
- if (lastEvent && event.clientX == lastEvent.clientX && event.clientY == lastEvent.clientY)
3810
- cur = last;
3811
- else {
3812
- cur = last = queryPos(view, event);
3813
- lastEvent = event;
3814
- }
3875
+ let cur = queryPos(view, event);
3815
3876
  let range = rangeForClick(view, cur.pos, cur.bias, type);
3816
3877
  if (start.pos != cur.pos && !extend) {
3817
3878
  let startRange = rangeForClick(view, start.pos, start.bias, type);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "6.7.0",
3
+ "version": "6.7.1",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",