@codemirror/view 0.19.32 → 0.19.33
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 +16 -0
- package/dist/index.cjs +108 -62
- package/dist/index.d.ts +37 -1
- package/dist/index.js +108 -62
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## 0.19.33 (2021-12-16)
|
|
2
|
+
|
|
3
|
+
### Breaking changes
|
|
4
|
+
|
|
5
|
+
`EditorView.scrollTo` and `EditorView.centerOn` are deprecated in favor of `EditorView.scrollIntoView`, and will be removed in the next breaking release.
|
|
6
|
+
|
|
7
|
+
### Bug fixes
|
|
8
|
+
|
|
9
|
+
Fix an issue that could cause the editor to unnecessarily interfere with composition (especially visible on macOS Chrome).
|
|
10
|
+
|
|
11
|
+
A composition started with multiple lines selected will no longer be interruptd by the editor.
|
|
12
|
+
|
|
13
|
+
### New features
|
|
14
|
+
|
|
15
|
+
The new `EditorView.scrollIntoView` function allows you to do more fine-grained scrolling.
|
|
16
|
+
|
|
1
17
|
## 0.19.32 (2021-12-15)
|
|
2
18
|
|
|
3
19
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -101,8 +101,7 @@ function windowRect(win) {
|
|
|
101
101
|
return { left: 0, right: win.innerWidth,
|
|
102
102
|
top: 0, bottom: win.innerHeight };
|
|
103
103
|
}
|
|
104
|
-
|
|
105
|
-
function scrollRectIntoView(dom, rect, side, center) {
|
|
104
|
+
function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
106
105
|
let doc = dom.ownerDocument, win = doc.defaultView;
|
|
107
106
|
for (let cur = dom; cur;) {
|
|
108
107
|
if (cur.nodeType == 1) { // Element
|
|
@@ -121,38 +120,42 @@ function scrollRectIntoView(dom, rect, side, center) {
|
|
|
121
120
|
top: rect.top, bottom: rect.top + cur.clientHeight };
|
|
122
121
|
}
|
|
123
122
|
let moveX = 0, moveY = 0;
|
|
124
|
-
if (
|
|
123
|
+
if (y == "nearest") {
|
|
124
|
+
if (rect.top < bounding.top) {
|
|
125
|
+
moveY = -(bounding.top - rect.top + yMargin);
|
|
126
|
+
if (side > 0 && rect.bottom > bounding.bottom + moveY)
|
|
127
|
+
moveY = rect.bottom - bounding.bottom + moveY + yMargin;
|
|
128
|
+
}
|
|
129
|
+
else if (rect.bottom > bounding.bottom) {
|
|
130
|
+
moveY = rect.bottom - bounding.bottom + yMargin;
|
|
131
|
+
if (side < 0 && (rect.top - moveY) < bounding.top)
|
|
132
|
+
moveY = -(bounding.top + moveY - rect.top + yMargin);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
125
136
|
let rectHeight = rect.bottom - rect.top, boundingHeight = bounding.bottom - bounding.top;
|
|
126
|
-
let targetTop
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
else if (side < 0)
|
|
130
|
-
targetTop = rect.top - ScrollSpace;
|
|
131
|
-
else
|
|
132
|
-
targetTop = rect.bottom + ScrollSpace - boundingHeight;
|
|
137
|
+
let targetTop = y == "center" && rectHeight <= boundingHeight ? rect.top + rectHeight / 2 - boundingHeight / 2 :
|
|
138
|
+
y == "start" || y == "center" && side < 0 ? rect.top - yMargin :
|
|
139
|
+
rect.bottom - boundingHeight + yMargin;
|
|
133
140
|
moveY = targetTop - bounding.top;
|
|
134
|
-
if (Math.abs(moveY) <= 1)
|
|
135
|
-
moveY = 0;
|
|
136
|
-
}
|
|
137
|
-
else if (rect.top < bounding.top) {
|
|
138
|
-
moveY = -(bounding.top - rect.top + ScrollSpace);
|
|
139
|
-
if (side > 0 && rect.bottom > bounding.bottom + moveY)
|
|
140
|
-
moveY = rect.bottom - bounding.bottom + moveY + ScrollSpace;
|
|
141
141
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
142
|
+
if (x == "nearest") {
|
|
143
|
+
if (rect.left < bounding.left) {
|
|
144
|
+
moveX = -(bounding.left - rect.left + xMargin);
|
|
145
|
+
if (side > 0 && rect.right > bounding.right + moveX)
|
|
146
|
+
moveX = rect.right - bounding.right + moveX + xMargin;
|
|
147
|
+
}
|
|
148
|
+
else if (rect.right > bounding.right) {
|
|
149
|
+
moveX = rect.right - bounding.right + xMargin;
|
|
150
|
+
if (side < 0 && rect.left < bounding.left + moveX)
|
|
151
|
+
moveX = -(bounding.left + moveX - rect.left + xMargin);
|
|
152
|
+
}
|
|
151
153
|
}
|
|
152
|
-
else
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
else {
|
|
155
|
+
let targetLeft = x == "center" ? rect.left + (rect.right - rect.left) / 2 - (bounding.right - bounding.left) / 2 :
|
|
156
|
+
(x == "start") == ltr ? rect.left - xMargin :
|
|
157
|
+
rect.right - (bounding.right - bounding.left) + xMargin;
|
|
158
|
+
moveX = targetLeft - bounding.left;
|
|
156
159
|
}
|
|
157
160
|
if (moveX || moveY) {
|
|
158
161
|
if (top) {
|
|
@@ -176,7 +179,7 @@ function scrollRectIntoView(dom, rect, side, center) {
|
|
|
176
179
|
if (top)
|
|
177
180
|
break;
|
|
178
181
|
cur = cur.assignedSlot || cur.parentNode;
|
|
179
|
-
|
|
182
|
+
x = y = "nearest";
|
|
180
183
|
}
|
|
181
184
|
else if (cur.nodeType == 11) { // A shadow root
|
|
182
185
|
cur = cur.host;
|
|
@@ -263,6 +266,10 @@ function getRoot(node) {
|
|
|
263
266
|
}
|
|
264
267
|
return null;
|
|
265
268
|
}
|
|
269
|
+
function clearAttributes(node) {
|
|
270
|
+
while (node.attributes.length)
|
|
271
|
+
node.removeAttributeNode(node.attributes[0]);
|
|
272
|
+
}
|
|
266
273
|
|
|
267
274
|
class DOMPos {
|
|
268
275
|
constructor(node, offset, precise = true) {
|
|
@@ -309,14 +316,16 @@ class ContentView {
|
|
|
309
316
|
// given position.
|
|
310
317
|
coordsAt(_pos, _side) { return null; }
|
|
311
318
|
sync(track) {
|
|
312
|
-
var _a;
|
|
313
319
|
if (this.dirty & 2 /* Node */) {
|
|
314
320
|
let parent = this.dom;
|
|
315
321
|
let pos = parent.firstChild;
|
|
316
322
|
for (let child of this.children) {
|
|
317
323
|
if (child.dirty) {
|
|
318
|
-
if (!child.dom && pos
|
|
319
|
-
|
|
324
|
+
if (!child.dom && pos) {
|
|
325
|
+
let contentView = ContentView.get(pos);
|
|
326
|
+
if (!contentView || !contentView.parent && contentView.constructor == child.constructor)
|
|
327
|
+
child.reuseDOM(pos);
|
|
328
|
+
}
|
|
320
329
|
child.sync(track);
|
|
321
330
|
child.dirty = 0 /* Not */;
|
|
322
331
|
}
|
|
@@ -344,7 +353,7 @@ class ContentView {
|
|
|
344
353
|
}
|
|
345
354
|
}
|
|
346
355
|
}
|
|
347
|
-
reuseDOM(_dom) {
|
|
356
|
+
reuseDOM(_dom) { }
|
|
348
357
|
localPosFromDOM(node, offset) {
|
|
349
358
|
let after;
|
|
350
359
|
if (node == this.dom) {
|
|
@@ -643,10 +652,8 @@ class TextView extends ContentView {
|
|
|
643
652
|
}
|
|
644
653
|
}
|
|
645
654
|
reuseDOM(dom) {
|
|
646
|
-
if (dom.nodeType
|
|
647
|
-
|
|
648
|
-
this.createDOM(dom);
|
|
649
|
-
return true;
|
|
655
|
+
if (dom.nodeType == 3)
|
|
656
|
+
this.createDOM(dom);
|
|
650
657
|
}
|
|
651
658
|
merge(from, to, source) {
|
|
652
659
|
if (source && (!(source instanceof TextView) || this.length - (to - from) + source.length > MaxJoinLen))
|
|
@@ -681,18 +688,26 @@ class MarkView extends ContentView {
|
|
|
681
688
|
for (let ch of children)
|
|
682
689
|
ch.setParent(this);
|
|
683
690
|
}
|
|
684
|
-
|
|
685
|
-
|
|
691
|
+
setAttrs(dom) {
|
|
692
|
+
clearAttributes(dom);
|
|
686
693
|
if (this.mark.class)
|
|
687
694
|
dom.className = this.mark.class;
|
|
688
695
|
if (this.mark.attrs)
|
|
689
696
|
for (let name in this.mark.attrs)
|
|
690
697
|
dom.setAttribute(name, this.mark.attrs[name]);
|
|
691
|
-
|
|
698
|
+
return dom;
|
|
699
|
+
}
|
|
700
|
+
reuseDOM(node) {
|
|
701
|
+
if (node.nodeName == this.mark.tagName.toUpperCase()) {
|
|
702
|
+
this.setDOM(node);
|
|
703
|
+
this.dirty |= 4 /* Attrs */ | 2 /* Node */;
|
|
704
|
+
}
|
|
692
705
|
}
|
|
693
706
|
sync(track) {
|
|
694
|
-
if (!this.dom
|
|
695
|
-
this.
|
|
707
|
+
if (!this.dom)
|
|
708
|
+
this.setDOM(this.setAttrs(document.createElement(this.mark.tagName)));
|
|
709
|
+
else if (this.dirty & 4 /* Attrs */)
|
|
710
|
+
this.setAttrs(this.dom);
|
|
696
711
|
super.sync(track);
|
|
697
712
|
}
|
|
698
713
|
merge(from, to, source, _hasStart, openStart, openEnd) {
|
|
@@ -836,8 +851,7 @@ class WidgetView extends ContentView {
|
|
|
836
851
|
}
|
|
837
852
|
class CompositionView extends WidgetView {
|
|
838
853
|
domAtPos(pos) { return new DOMPos(this.widget.text, pos); }
|
|
839
|
-
sync() {
|
|
840
|
-
this.setDOM(this.widget.toDOM()); }
|
|
854
|
+
sync() { this.setDOM(this.widget.toDOM()); }
|
|
841
855
|
localPosFromDOM(node, offset) {
|
|
842
856
|
return !offset ? 0 : node.nodeType == 3 ? Math.min(offset, this.length) : this.length;
|
|
843
857
|
}
|
|
@@ -1302,13 +1316,23 @@ class LineView extends ContentView {
|
|
|
1302
1316
|
domAtPos(pos) {
|
|
1303
1317
|
return inlineDOMAtPos(this.dom, this.children, pos);
|
|
1304
1318
|
}
|
|
1319
|
+
reuseDOM(node) {
|
|
1320
|
+
if (node.nodeName == "DIV") {
|
|
1321
|
+
this.setDOM(node);
|
|
1322
|
+
this.dirty |= 4 /* Attrs */ | 2 /* Node */;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1305
1325
|
sync(track) {
|
|
1306
1326
|
var _a;
|
|
1307
|
-
if (!this.dom
|
|
1327
|
+
if (!this.dom) {
|
|
1308
1328
|
this.setDOM(document.createElement("div"));
|
|
1309
1329
|
this.dom.className = "cm-line";
|
|
1310
1330
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
1311
1331
|
}
|
|
1332
|
+
else if (this.dirty & 4 /* Attrs */) {
|
|
1333
|
+
clearAttributes(this.dom);
|
|
1334
|
+
this.prevAttrs = this.attrs ? null : undefined;
|
|
1335
|
+
}
|
|
1312
1336
|
if (this.prevAttrs !== undefined) {
|
|
1313
1337
|
updateAttrs(this.dom, this.prevAttrs, this.attrs);
|
|
1314
1338
|
this.dom.classList.add("cm-line");
|
|
@@ -1580,12 +1604,27 @@ const mouseSelectionStyle = state.Facet.define();
|
|
|
1580
1604
|
const exceptionSink = state.Facet.define();
|
|
1581
1605
|
const updateListener = state.Facet.define();
|
|
1582
1606
|
const inputHandler = state.Facet.define();
|
|
1607
|
+
// FIXME remove
|
|
1583
1608
|
const scrollTo = state.StateEffect.define({
|
|
1584
1609
|
map: (range, changes) => range.map(changes)
|
|
1585
1610
|
});
|
|
1611
|
+
// FIXME remove
|
|
1586
1612
|
const centerOn = state.StateEffect.define({
|
|
1587
1613
|
map: (range, changes) => range.map(changes)
|
|
1588
1614
|
});
|
|
1615
|
+
class ScrollTarget {
|
|
1616
|
+
constructor(range, y = "nearest", x = "nearest", yMargin = 5, xMargin = 5) {
|
|
1617
|
+
this.range = range;
|
|
1618
|
+
this.y = y;
|
|
1619
|
+
this.x = x;
|
|
1620
|
+
this.yMargin = yMargin;
|
|
1621
|
+
this.xMargin = xMargin;
|
|
1622
|
+
}
|
|
1623
|
+
map(changes) {
|
|
1624
|
+
return changes.empty ? this : new ScrollTarget(this.range.map(changes), this.y, this.x, this.yMargin, this.xMargin);
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
const scrollIntoView = state.StateEffect.define({ map: (t, ch) => t.map(ch) });
|
|
1589
1628
|
/**
|
|
1590
1629
|
Log or report an unhandled exception in client code. Should
|
|
1591
1630
|
probably only be used by extension code that allows client code to
|
|
@@ -2664,7 +2703,8 @@ class DocView extends ContentView {
|
|
|
2664
2703
|
this.view.viewState.lineGapDeco
|
|
2665
2704
|
];
|
|
2666
2705
|
}
|
|
2667
|
-
scrollIntoView(
|
|
2706
|
+
scrollIntoView(target) {
|
|
2707
|
+
let { range } = target;
|
|
2668
2708
|
let rect = this.coordsAt(range.head, range.empty ? range.assoc : range.head > range.anchor ? -1 : 1), other;
|
|
2669
2709
|
if (!rect)
|
|
2670
2710
|
return;
|
|
@@ -2684,10 +2724,11 @@ class DocView extends ContentView {
|
|
|
2684
2724
|
if (bottom != null)
|
|
2685
2725
|
mBottom = Math.max(mBottom, bottom);
|
|
2686
2726
|
}
|
|
2687
|
-
|
|
2727
|
+
let targetRect = {
|
|
2688
2728
|
left: rect.left - mLeft, top: rect.top - mTop,
|
|
2689
2729
|
right: rect.right + mRight, bottom: rect.bottom + mBottom
|
|
2690
|
-
}
|
|
2730
|
+
};
|
|
2731
|
+
scrollRectIntoView(this.view.scrollDOM, targetRect, range.head < range.anchor ? -1 : 1, target.x, target.y, target.xMargin, target.yMargin, this.view.textDirection == exports.Direction.LTR);
|
|
2691
2732
|
}
|
|
2692
2733
|
}
|
|
2693
2734
|
function betweenUneditable(pos) {
|
|
@@ -4521,15 +4562,6 @@ class LineGapWidget extends WidgetType {
|
|
|
4521
4562
|
}
|
|
4522
4563
|
get estimatedHeight() { return this.vertical ? this.size : -1; }
|
|
4523
4564
|
}
|
|
4524
|
-
class ScrollTarget {
|
|
4525
|
-
constructor(range, center = false) {
|
|
4526
|
-
this.range = range;
|
|
4527
|
-
this.center = center;
|
|
4528
|
-
}
|
|
4529
|
-
map(changes) {
|
|
4530
|
-
return changes.empty ? this : new ScrollTarget(this.range.map(changes), this.center);
|
|
4531
|
-
}
|
|
4532
|
-
}
|
|
4533
4565
|
class ViewState {
|
|
4534
4566
|
constructor(state) {
|
|
4535
4567
|
this.state = state;
|
|
@@ -4710,9 +4742,9 @@ class ViewState {
|
|
|
4710
4742
|
let { head } = scrollTarget.range, viewHeight = this.editorHeight;
|
|
4711
4743
|
if (head < viewport.from || head > viewport.to) {
|
|
4712
4744
|
let block = map.lineAt(head, QueryType.ByPos, doc, 0, 0), topPos;
|
|
4713
|
-
if (scrollTarget.center)
|
|
4745
|
+
if (scrollTarget.y == "center")
|
|
4714
4746
|
topPos = (block.top + block.bottom) / 2 - viewHeight / 2;
|
|
4715
|
-
else if (head < viewport.from)
|
|
4747
|
+
else if (scrollTarget.y == "start" || head < viewport.from)
|
|
4716
4748
|
topPos = block.top;
|
|
4717
4749
|
else
|
|
4718
4750
|
topPos = block.bottom - viewHeight;
|
|
@@ -5818,7 +5850,9 @@ class EditorView {
|
|
|
5818
5850
|
if (e.is(scrollTo))
|
|
5819
5851
|
scrollTarget = new ScrollTarget(e.value);
|
|
5820
5852
|
else if (e.is(centerOn))
|
|
5821
|
-
scrollTarget = new ScrollTarget(e.value,
|
|
5853
|
+
scrollTarget = new ScrollTarget(e.value, "center");
|
|
5854
|
+
else if (e.is(scrollIntoView))
|
|
5855
|
+
scrollTarget = e.value;
|
|
5822
5856
|
}
|
|
5823
5857
|
}
|
|
5824
5858
|
this.viewState.update(update, scrollTarget);
|
|
@@ -6386,6 +6420,14 @@ class EditorView {
|
|
|
6386
6420
|
this.destroyed = true;
|
|
6387
6421
|
}
|
|
6388
6422
|
/**
|
|
6423
|
+
Returns an effect that can be
|
|
6424
|
+
[added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a transaction to
|
|
6425
|
+
cause it to scroll the given position or range into view.
|
|
6426
|
+
*/
|
|
6427
|
+
static scrollIntoView(pos, options = {}) {
|
|
6428
|
+
return scrollIntoView.of(new ScrollTarget(typeof pos == "number" ? state.EditorSelection.cursor(pos) : pos, options.y, options.x, options.yMargin, options.xMargin));
|
|
6429
|
+
}
|
|
6430
|
+
/**
|
|
6389
6431
|
Facet that can be used to add DOM event handlers. The value
|
|
6390
6432
|
should be an object mapping event names to handler functions. The
|
|
6391
6433
|
first such function to return true will be assumed to have handled
|
|
@@ -6439,11 +6481,15 @@ class EditorView {
|
|
|
6439
6481
|
/**
|
|
6440
6482
|
Effect that can be [added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a
|
|
6441
6483
|
transaction to make it scroll the given range into view.
|
|
6484
|
+
|
|
6485
|
+
*Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
|
|
6442
6486
|
*/
|
|
6443
6487
|
EditorView.scrollTo = scrollTo;
|
|
6444
6488
|
/**
|
|
6445
6489
|
Effect that makes the editor scroll the given range to the
|
|
6446
6490
|
center of the visible view.
|
|
6491
|
+
|
|
6492
|
+
*Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
|
|
6447
6493
|
*/
|
|
6448
6494
|
EditorView.centerOn = centerOn;
|
|
6449
6495
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as _codemirror_rangeset from '@codemirror/rangeset';
|
|
|
2
2
|
import { RangeSet, RangeValue, Range } from '@codemirror/rangeset';
|
|
3
3
|
export { Range } from '@codemirror/rangeset';
|
|
4
4
|
import * as _codemirror_state from '@codemirror/state';
|
|
5
|
-
import { EditorState, Extension, Transaction, ChangeSet, EditorSelection, TransactionSpec, SelectionRange, Facet } from '@codemirror/state';
|
|
5
|
+
import { EditorState, Extension, Transaction, ChangeSet, EditorSelection, TransactionSpec, SelectionRange, StateEffect, Facet } from '@codemirror/state';
|
|
6
6
|
import { Line } from '@codemirror/text';
|
|
7
7
|
import { StyleModule, StyleSpec } from 'style-mod';
|
|
8
8
|
|
|
@@ -264,6 +264,7 @@ interface Rect {
|
|
|
264
264
|
readonly top: number;
|
|
265
265
|
readonly bottom: number;
|
|
266
266
|
}
|
|
267
|
+
declare type ScrollStrategy = "nearest" | "start" | "end" | "center";
|
|
267
268
|
|
|
268
269
|
/**
|
|
269
270
|
Command functions are used in key bindings and other types of user
|
|
@@ -1006,14 +1007,49 @@ declare class EditorView {
|
|
|
1006
1007
|
/**
|
|
1007
1008
|
Effect that can be [added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a
|
|
1008
1009
|
transaction to make it scroll the given range into view.
|
|
1010
|
+
|
|
1011
|
+
*Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
|
|
1009
1012
|
*/
|
|
1010
1013
|
static scrollTo: _codemirror_state.StateEffectType<SelectionRange>;
|
|
1011
1014
|
/**
|
|
1012
1015
|
Effect that makes the editor scroll the given range to the
|
|
1013
1016
|
center of the visible view.
|
|
1017
|
+
|
|
1018
|
+
*Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
|
|
1014
1019
|
*/
|
|
1015
1020
|
static centerOn: _codemirror_state.StateEffectType<SelectionRange>;
|
|
1016
1021
|
/**
|
|
1022
|
+
Returns an effect that can be
|
|
1023
|
+
[added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a transaction to
|
|
1024
|
+
cause it to scroll the given position or range into view.
|
|
1025
|
+
*/
|
|
1026
|
+
static scrollIntoView(pos: number | SelectionRange, options?: {
|
|
1027
|
+
/**
|
|
1028
|
+
By default (`"nearest"`) the position will be vertically
|
|
1029
|
+
scrolled only the minimal amount required to move the given
|
|
1030
|
+
position into view. You can set this to `"start"` to move it
|
|
1031
|
+
to the top of the view, `"end"` to move it to the bottom, or
|
|
1032
|
+
`"center"` to move it to the center.
|
|
1033
|
+
*/
|
|
1034
|
+
y?: ScrollStrategy;
|
|
1035
|
+
/**
|
|
1036
|
+
Effect similar to
|
|
1037
|
+
[`y`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView^options.y), but for the
|
|
1038
|
+
horizontal scroll position.
|
|
1039
|
+
*/
|
|
1040
|
+
x?: ScrollStrategy;
|
|
1041
|
+
/**
|
|
1042
|
+
Extra vertical distance to add when moving something into
|
|
1043
|
+
view. Not used with the `"center"` strategy. Defaults to 5.
|
|
1044
|
+
*/
|
|
1045
|
+
yMargin?: number;
|
|
1046
|
+
/**
|
|
1047
|
+
Extra horizontal distance to add. Not used with the `"center"`
|
|
1048
|
+
strategy. Defaults to 5.
|
|
1049
|
+
*/
|
|
1050
|
+
xMargin?: number;
|
|
1051
|
+
}): StateEffect<unknown>;
|
|
1052
|
+
/**
|
|
1017
1053
|
Facet to add a [style
|
|
1018
1054
|
module](https://github.com/marijnh/style-mod#documentation) to
|
|
1019
1055
|
an editor view. The view will ensure that the module is
|
package/dist/index.js
CHANGED
|
@@ -98,8 +98,7 @@ function windowRect(win) {
|
|
|
98
98
|
return { left: 0, right: win.innerWidth,
|
|
99
99
|
top: 0, bottom: win.innerHeight };
|
|
100
100
|
}
|
|
101
|
-
|
|
102
|
-
function scrollRectIntoView(dom, rect, side, center) {
|
|
101
|
+
function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
103
102
|
let doc = dom.ownerDocument, win = doc.defaultView;
|
|
104
103
|
for (let cur = dom; cur;) {
|
|
105
104
|
if (cur.nodeType == 1) { // Element
|
|
@@ -118,38 +117,42 @@ function scrollRectIntoView(dom, rect, side, center) {
|
|
|
118
117
|
top: rect.top, bottom: rect.top + cur.clientHeight };
|
|
119
118
|
}
|
|
120
119
|
let moveX = 0, moveY = 0;
|
|
121
|
-
if (
|
|
120
|
+
if (y == "nearest") {
|
|
121
|
+
if (rect.top < bounding.top) {
|
|
122
|
+
moveY = -(bounding.top - rect.top + yMargin);
|
|
123
|
+
if (side > 0 && rect.bottom > bounding.bottom + moveY)
|
|
124
|
+
moveY = rect.bottom - bounding.bottom + moveY + yMargin;
|
|
125
|
+
}
|
|
126
|
+
else if (rect.bottom > bounding.bottom) {
|
|
127
|
+
moveY = rect.bottom - bounding.bottom + yMargin;
|
|
128
|
+
if (side < 0 && (rect.top - moveY) < bounding.top)
|
|
129
|
+
moveY = -(bounding.top + moveY - rect.top + yMargin);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
122
133
|
let rectHeight = rect.bottom - rect.top, boundingHeight = bounding.bottom - bounding.top;
|
|
123
|
-
let targetTop
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
else if (side < 0)
|
|
127
|
-
targetTop = rect.top - ScrollSpace;
|
|
128
|
-
else
|
|
129
|
-
targetTop = rect.bottom + ScrollSpace - boundingHeight;
|
|
134
|
+
let targetTop = y == "center" && rectHeight <= boundingHeight ? rect.top + rectHeight / 2 - boundingHeight / 2 :
|
|
135
|
+
y == "start" || y == "center" && side < 0 ? rect.top - yMargin :
|
|
136
|
+
rect.bottom - boundingHeight + yMargin;
|
|
130
137
|
moveY = targetTop - bounding.top;
|
|
131
|
-
if (Math.abs(moveY) <= 1)
|
|
132
|
-
moveY = 0;
|
|
133
|
-
}
|
|
134
|
-
else if (rect.top < bounding.top) {
|
|
135
|
-
moveY = -(bounding.top - rect.top + ScrollSpace);
|
|
136
|
-
if (side > 0 && rect.bottom > bounding.bottom + moveY)
|
|
137
|
-
moveY = rect.bottom - bounding.bottom + moveY + ScrollSpace;
|
|
138
138
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
139
|
+
if (x == "nearest") {
|
|
140
|
+
if (rect.left < bounding.left) {
|
|
141
|
+
moveX = -(bounding.left - rect.left + xMargin);
|
|
142
|
+
if (side > 0 && rect.right > bounding.right + moveX)
|
|
143
|
+
moveX = rect.right - bounding.right + moveX + xMargin;
|
|
144
|
+
}
|
|
145
|
+
else if (rect.right > bounding.right) {
|
|
146
|
+
moveX = rect.right - bounding.right + xMargin;
|
|
147
|
+
if (side < 0 && rect.left < bounding.left + moveX)
|
|
148
|
+
moveX = -(bounding.left + moveX - rect.left + xMargin);
|
|
149
|
+
}
|
|
148
150
|
}
|
|
149
|
-
else
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
151
|
+
else {
|
|
152
|
+
let targetLeft = x == "center" ? rect.left + (rect.right - rect.left) / 2 - (bounding.right - bounding.left) / 2 :
|
|
153
|
+
(x == "start") == ltr ? rect.left - xMargin :
|
|
154
|
+
rect.right - (bounding.right - bounding.left) + xMargin;
|
|
155
|
+
moveX = targetLeft - bounding.left;
|
|
153
156
|
}
|
|
154
157
|
if (moveX || moveY) {
|
|
155
158
|
if (top) {
|
|
@@ -173,7 +176,7 @@ function scrollRectIntoView(dom, rect, side, center) {
|
|
|
173
176
|
if (top)
|
|
174
177
|
break;
|
|
175
178
|
cur = cur.assignedSlot || cur.parentNode;
|
|
176
|
-
|
|
179
|
+
x = y = "nearest";
|
|
177
180
|
}
|
|
178
181
|
else if (cur.nodeType == 11) { // A shadow root
|
|
179
182
|
cur = cur.host;
|
|
@@ -260,6 +263,10 @@ function getRoot(node) {
|
|
|
260
263
|
}
|
|
261
264
|
return null;
|
|
262
265
|
}
|
|
266
|
+
function clearAttributes(node) {
|
|
267
|
+
while (node.attributes.length)
|
|
268
|
+
node.removeAttributeNode(node.attributes[0]);
|
|
269
|
+
}
|
|
263
270
|
|
|
264
271
|
class DOMPos {
|
|
265
272
|
constructor(node, offset, precise = true) {
|
|
@@ -306,14 +313,16 @@ class ContentView {
|
|
|
306
313
|
// given position.
|
|
307
314
|
coordsAt(_pos, _side) { return null; }
|
|
308
315
|
sync(track) {
|
|
309
|
-
var _a;
|
|
310
316
|
if (this.dirty & 2 /* Node */) {
|
|
311
317
|
let parent = this.dom;
|
|
312
318
|
let pos = parent.firstChild;
|
|
313
319
|
for (let child of this.children) {
|
|
314
320
|
if (child.dirty) {
|
|
315
|
-
if (!child.dom && pos
|
|
316
|
-
|
|
321
|
+
if (!child.dom && pos) {
|
|
322
|
+
let contentView = ContentView.get(pos);
|
|
323
|
+
if (!contentView || !contentView.parent && contentView.constructor == child.constructor)
|
|
324
|
+
child.reuseDOM(pos);
|
|
325
|
+
}
|
|
317
326
|
child.sync(track);
|
|
318
327
|
child.dirty = 0 /* Not */;
|
|
319
328
|
}
|
|
@@ -341,7 +350,7 @@ class ContentView {
|
|
|
341
350
|
}
|
|
342
351
|
}
|
|
343
352
|
}
|
|
344
|
-
reuseDOM(_dom) {
|
|
353
|
+
reuseDOM(_dom) { }
|
|
345
354
|
localPosFromDOM(node, offset) {
|
|
346
355
|
let after;
|
|
347
356
|
if (node == this.dom) {
|
|
@@ -640,10 +649,8 @@ class TextView extends ContentView {
|
|
|
640
649
|
}
|
|
641
650
|
}
|
|
642
651
|
reuseDOM(dom) {
|
|
643
|
-
if (dom.nodeType
|
|
644
|
-
|
|
645
|
-
this.createDOM(dom);
|
|
646
|
-
return true;
|
|
652
|
+
if (dom.nodeType == 3)
|
|
653
|
+
this.createDOM(dom);
|
|
647
654
|
}
|
|
648
655
|
merge(from, to, source) {
|
|
649
656
|
if (source && (!(source instanceof TextView) || this.length - (to - from) + source.length > MaxJoinLen))
|
|
@@ -678,18 +685,26 @@ class MarkView extends ContentView {
|
|
|
678
685
|
for (let ch of children)
|
|
679
686
|
ch.setParent(this);
|
|
680
687
|
}
|
|
681
|
-
|
|
682
|
-
|
|
688
|
+
setAttrs(dom) {
|
|
689
|
+
clearAttributes(dom);
|
|
683
690
|
if (this.mark.class)
|
|
684
691
|
dom.className = this.mark.class;
|
|
685
692
|
if (this.mark.attrs)
|
|
686
693
|
for (let name in this.mark.attrs)
|
|
687
694
|
dom.setAttribute(name, this.mark.attrs[name]);
|
|
688
|
-
|
|
695
|
+
return dom;
|
|
696
|
+
}
|
|
697
|
+
reuseDOM(node) {
|
|
698
|
+
if (node.nodeName == this.mark.tagName.toUpperCase()) {
|
|
699
|
+
this.setDOM(node);
|
|
700
|
+
this.dirty |= 4 /* Attrs */ | 2 /* Node */;
|
|
701
|
+
}
|
|
689
702
|
}
|
|
690
703
|
sync(track) {
|
|
691
|
-
if (!this.dom
|
|
692
|
-
this.
|
|
704
|
+
if (!this.dom)
|
|
705
|
+
this.setDOM(this.setAttrs(document.createElement(this.mark.tagName)));
|
|
706
|
+
else if (this.dirty & 4 /* Attrs */)
|
|
707
|
+
this.setAttrs(this.dom);
|
|
693
708
|
super.sync(track);
|
|
694
709
|
}
|
|
695
710
|
merge(from, to, source, _hasStart, openStart, openEnd) {
|
|
@@ -833,8 +848,7 @@ class WidgetView extends ContentView {
|
|
|
833
848
|
}
|
|
834
849
|
class CompositionView extends WidgetView {
|
|
835
850
|
domAtPos(pos) { return new DOMPos(this.widget.text, pos); }
|
|
836
|
-
sync() {
|
|
837
|
-
this.setDOM(this.widget.toDOM()); }
|
|
851
|
+
sync() { this.setDOM(this.widget.toDOM()); }
|
|
838
852
|
localPosFromDOM(node, offset) {
|
|
839
853
|
return !offset ? 0 : node.nodeType == 3 ? Math.min(offset, this.length) : this.length;
|
|
840
854
|
}
|
|
@@ -1298,13 +1312,23 @@ class LineView extends ContentView {
|
|
|
1298
1312
|
domAtPos(pos) {
|
|
1299
1313
|
return inlineDOMAtPos(this.dom, this.children, pos);
|
|
1300
1314
|
}
|
|
1315
|
+
reuseDOM(node) {
|
|
1316
|
+
if (node.nodeName == "DIV") {
|
|
1317
|
+
this.setDOM(node);
|
|
1318
|
+
this.dirty |= 4 /* Attrs */ | 2 /* Node */;
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1301
1321
|
sync(track) {
|
|
1302
1322
|
var _a;
|
|
1303
|
-
if (!this.dom
|
|
1323
|
+
if (!this.dom) {
|
|
1304
1324
|
this.setDOM(document.createElement("div"));
|
|
1305
1325
|
this.dom.className = "cm-line";
|
|
1306
1326
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
1307
1327
|
}
|
|
1328
|
+
else if (this.dirty & 4 /* Attrs */) {
|
|
1329
|
+
clearAttributes(this.dom);
|
|
1330
|
+
this.prevAttrs = this.attrs ? null : undefined;
|
|
1331
|
+
}
|
|
1308
1332
|
if (this.prevAttrs !== undefined) {
|
|
1309
1333
|
updateAttrs(this.dom, this.prevAttrs, this.attrs);
|
|
1310
1334
|
this.dom.classList.add("cm-line");
|
|
@@ -1576,12 +1600,27 @@ const mouseSelectionStyle = /*@__PURE__*/Facet.define();
|
|
|
1576
1600
|
const exceptionSink = /*@__PURE__*/Facet.define();
|
|
1577
1601
|
const updateListener = /*@__PURE__*/Facet.define();
|
|
1578
1602
|
const inputHandler = /*@__PURE__*/Facet.define();
|
|
1603
|
+
// FIXME remove
|
|
1579
1604
|
const scrollTo = /*@__PURE__*/StateEffect.define({
|
|
1580
1605
|
map: (range, changes) => range.map(changes)
|
|
1581
1606
|
});
|
|
1607
|
+
// FIXME remove
|
|
1582
1608
|
const centerOn = /*@__PURE__*/StateEffect.define({
|
|
1583
1609
|
map: (range, changes) => range.map(changes)
|
|
1584
1610
|
});
|
|
1611
|
+
class ScrollTarget {
|
|
1612
|
+
constructor(range, y = "nearest", x = "nearest", yMargin = 5, xMargin = 5) {
|
|
1613
|
+
this.range = range;
|
|
1614
|
+
this.y = y;
|
|
1615
|
+
this.x = x;
|
|
1616
|
+
this.yMargin = yMargin;
|
|
1617
|
+
this.xMargin = xMargin;
|
|
1618
|
+
}
|
|
1619
|
+
map(changes) {
|
|
1620
|
+
return changes.empty ? this : new ScrollTarget(this.range.map(changes), this.y, this.x, this.yMargin, this.xMargin);
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
const scrollIntoView = /*@__PURE__*/StateEffect.define({ map: (t, ch) => t.map(ch) });
|
|
1585
1624
|
/**
|
|
1586
1625
|
Log or report an unhandled exception in client code. Should
|
|
1587
1626
|
probably only be used by extension code that allows client code to
|
|
@@ -2659,7 +2698,8 @@ class DocView extends ContentView {
|
|
|
2659
2698
|
this.view.viewState.lineGapDeco
|
|
2660
2699
|
];
|
|
2661
2700
|
}
|
|
2662
|
-
scrollIntoView(
|
|
2701
|
+
scrollIntoView(target) {
|
|
2702
|
+
let { range } = target;
|
|
2663
2703
|
let rect = this.coordsAt(range.head, range.empty ? range.assoc : range.head > range.anchor ? -1 : 1), other;
|
|
2664
2704
|
if (!rect)
|
|
2665
2705
|
return;
|
|
@@ -2679,10 +2719,11 @@ class DocView extends ContentView {
|
|
|
2679
2719
|
if (bottom != null)
|
|
2680
2720
|
mBottom = Math.max(mBottom, bottom);
|
|
2681
2721
|
}
|
|
2682
|
-
|
|
2722
|
+
let targetRect = {
|
|
2683
2723
|
left: rect.left - mLeft, top: rect.top - mTop,
|
|
2684
2724
|
right: rect.right + mRight, bottom: rect.bottom + mBottom
|
|
2685
|
-
}
|
|
2725
|
+
};
|
|
2726
|
+
scrollRectIntoView(this.view.scrollDOM, targetRect, range.head < range.anchor ? -1 : 1, target.x, target.y, target.xMargin, target.yMargin, this.view.textDirection == Direction.LTR);
|
|
2686
2727
|
}
|
|
2687
2728
|
}
|
|
2688
2729
|
function betweenUneditable(pos) {
|
|
@@ -4515,15 +4556,6 @@ class LineGapWidget extends WidgetType {
|
|
|
4515
4556
|
}
|
|
4516
4557
|
get estimatedHeight() { return this.vertical ? this.size : -1; }
|
|
4517
4558
|
}
|
|
4518
|
-
class ScrollTarget {
|
|
4519
|
-
constructor(range, center = false) {
|
|
4520
|
-
this.range = range;
|
|
4521
|
-
this.center = center;
|
|
4522
|
-
}
|
|
4523
|
-
map(changes) {
|
|
4524
|
-
return changes.empty ? this : new ScrollTarget(this.range.map(changes), this.center);
|
|
4525
|
-
}
|
|
4526
|
-
}
|
|
4527
4559
|
class ViewState {
|
|
4528
4560
|
constructor(state) {
|
|
4529
4561
|
this.state = state;
|
|
@@ -4704,9 +4736,9 @@ class ViewState {
|
|
|
4704
4736
|
let { head } = scrollTarget.range, viewHeight = this.editorHeight;
|
|
4705
4737
|
if (head < viewport.from || head > viewport.to) {
|
|
4706
4738
|
let block = map.lineAt(head, QueryType.ByPos, doc, 0, 0), topPos;
|
|
4707
|
-
if (scrollTarget.center)
|
|
4739
|
+
if (scrollTarget.y == "center")
|
|
4708
4740
|
topPos = (block.top + block.bottom) / 2 - viewHeight / 2;
|
|
4709
|
-
else if (head < viewport.from)
|
|
4741
|
+
else if (scrollTarget.y == "start" || head < viewport.from)
|
|
4710
4742
|
topPos = block.top;
|
|
4711
4743
|
else
|
|
4712
4744
|
topPos = block.bottom - viewHeight;
|
|
@@ -5812,7 +5844,9 @@ class EditorView {
|
|
|
5812
5844
|
if (e.is(scrollTo))
|
|
5813
5845
|
scrollTarget = new ScrollTarget(e.value);
|
|
5814
5846
|
else if (e.is(centerOn))
|
|
5815
|
-
scrollTarget = new ScrollTarget(e.value,
|
|
5847
|
+
scrollTarget = new ScrollTarget(e.value, "center");
|
|
5848
|
+
else if (e.is(scrollIntoView))
|
|
5849
|
+
scrollTarget = e.value;
|
|
5816
5850
|
}
|
|
5817
5851
|
}
|
|
5818
5852
|
this.viewState.update(update, scrollTarget);
|
|
@@ -6380,6 +6414,14 @@ class EditorView {
|
|
|
6380
6414
|
this.destroyed = true;
|
|
6381
6415
|
}
|
|
6382
6416
|
/**
|
|
6417
|
+
Returns an effect that can be
|
|
6418
|
+
[added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a transaction to
|
|
6419
|
+
cause it to scroll the given position or range into view.
|
|
6420
|
+
*/
|
|
6421
|
+
static scrollIntoView(pos, options = {}) {
|
|
6422
|
+
return scrollIntoView.of(new ScrollTarget(typeof pos == "number" ? EditorSelection.cursor(pos) : pos, options.y, options.x, options.yMargin, options.xMargin));
|
|
6423
|
+
}
|
|
6424
|
+
/**
|
|
6383
6425
|
Facet that can be used to add DOM event handlers. The value
|
|
6384
6426
|
should be an object mapping event names to handler functions. The
|
|
6385
6427
|
first such function to return true will be assumed to have handled
|
|
@@ -6433,11 +6475,15 @@ class EditorView {
|
|
|
6433
6475
|
/**
|
|
6434
6476
|
Effect that can be [added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a
|
|
6435
6477
|
transaction to make it scroll the given range into view.
|
|
6478
|
+
|
|
6479
|
+
*Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
|
|
6436
6480
|
*/
|
|
6437
6481
|
EditorView.scrollTo = scrollTo;
|
|
6438
6482
|
/**
|
|
6439
6483
|
Effect that makes the editor scroll the given range to the
|
|
6440
6484
|
center of the visible view.
|
|
6485
|
+
|
|
6486
|
+
*Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
|
|
6441
6487
|
*/
|
|
6442
6488
|
EditorView.centerOn = centerOn;
|
|
6443
6489
|
/**
|