@codemirror/view 6.21.4 → 6.22.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 +30 -0
- package/dist/index.cjs +127 -32
- package/dist/index.d.cts +35 -2
- package/dist/index.d.ts +35 -2
- package/dist/index.js +128 -33
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
1
|
+
## 6.22.1 (2023-11-27)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Call widget `destroy` methods when the entire editor is destroyed or reset.
|
|
6
|
+
|
|
7
|
+
Work around an issue on Safari on macOS Sonoma that made the native cursor visible even when `drawSelection` is enabled.
|
|
8
|
+
|
|
9
|
+
Fix an issue where, on some browsers, the screenreader announced text ended up in the printed document.
|
|
10
|
+
|
|
11
|
+
Fix a bug where a hover tooltip could stick around even though the pointer was no longer on the editor when it was moved out over the tooltip.
|
|
12
|
+
|
|
13
|
+
Fix an issue where hover tooltips could close when moving the mouse onto them due to mouse position rounding issues.
|
|
14
|
+
|
|
15
|
+
## 6.22.0 (2023-11-03)
|
|
16
|
+
|
|
17
|
+
### Bug fixes
|
|
18
|
+
|
|
19
|
+
Exceptions raised by update listeners are now routed to the configured exception sink, if any.
|
|
20
|
+
|
|
21
|
+
Fix an issue where passing large scroll margins to `scrollIntoView` would cause the measure loop to fail to terminate.
|
|
22
|
+
|
|
23
|
+
Widgets that are draggable (and allow drag events through in their `ignoreEvent` implementation) can now use the editor's built-in drag/drop behavior.
|
|
24
|
+
|
|
25
|
+
### New features
|
|
26
|
+
|
|
27
|
+
The new `scrollTo` option to `EditorView` allows an initial scroll position to be provided.
|
|
28
|
+
|
|
29
|
+
The new `EditorView.scrollSnapshot` method returns an effect that can be used to reset to a previous scroll position.
|
|
30
|
+
|
|
1
31
|
## 6.21.4 (2023-10-24)
|
|
2
32
|
|
|
3
33
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -503,7 +503,7 @@ class ContentView {
|
|
|
503
503
|
this.markDirty();
|
|
504
504
|
for (let i = from; i < to; i++) {
|
|
505
505
|
let child = this.children[i];
|
|
506
|
-
if (child.parent == this)
|
|
506
|
+
if (child.parent == this && children.indexOf(child) < 0)
|
|
507
507
|
child.destroy();
|
|
508
508
|
}
|
|
509
509
|
this.children.splice(from, to - from, ...children);
|
|
@@ -540,6 +540,8 @@ class ContentView {
|
|
|
540
540
|
// number > 0 when after its position.
|
|
541
541
|
getSide() { return 0; }
|
|
542
542
|
destroy() {
|
|
543
|
+
for (let child of this.children)
|
|
544
|
+
child.destroy();
|
|
543
545
|
this.parent = null;
|
|
544
546
|
}
|
|
545
547
|
}
|
|
@@ -1788,15 +1790,28 @@ const nativeSelectionHidden = state.Facet.define({
|
|
|
1788
1790
|
combine: values => values.some(x => x)
|
|
1789
1791
|
});
|
|
1790
1792
|
class ScrollTarget {
|
|
1791
|
-
constructor(range, y = "nearest", x = "nearest", yMargin = 5, xMargin = 5
|
|
1793
|
+
constructor(range, y = "nearest", x = "nearest", yMargin = 5, xMargin = 5,
|
|
1794
|
+
// This data structure is abused to also store precise scroll
|
|
1795
|
+
// snapshots, instead of a `scrollIntoView` request. When this
|
|
1796
|
+
// flag is `true`, `range` points at a position in the reference
|
|
1797
|
+
// line, `yMargin` holds the difference between the top of that
|
|
1798
|
+
// line and the top of the editor, and `xMargin` holds the
|
|
1799
|
+
// editor's `scrollLeft`.
|
|
1800
|
+
isSnapshot = false) {
|
|
1792
1801
|
this.range = range;
|
|
1793
1802
|
this.y = y;
|
|
1794
1803
|
this.x = x;
|
|
1795
1804
|
this.yMargin = yMargin;
|
|
1796
1805
|
this.xMargin = xMargin;
|
|
1806
|
+
this.isSnapshot = isSnapshot;
|
|
1797
1807
|
}
|
|
1798
1808
|
map(changes) {
|
|
1799
|
-
return changes.empty ? this :
|
|
1809
|
+
return changes.empty ? this :
|
|
1810
|
+
new ScrollTarget(this.range.map(changes), this.y, this.x, this.yMargin, this.xMargin, this.isSnapshot);
|
|
1811
|
+
}
|
|
1812
|
+
clip(state$1) {
|
|
1813
|
+
return this.range.to <= state$1.doc.length ? this :
|
|
1814
|
+
new ScrollTarget(state.EditorSelection.cursor(state$1.doc.length), this.y, this.x, this.yMargin, this.xMargin, this.isSnapshot);
|
|
1800
1815
|
}
|
|
1801
1816
|
}
|
|
1802
1817
|
const scrollIntoView = state.StateEffect.define({ map: (t, ch) => t.map(ch) });
|
|
@@ -3090,6 +3105,12 @@ class DocView extends ContentView {
|
|
|
3090
3105
|
];
|
|
3091
3106
|
}
|
|
3092
3107
|
scrollIntoView(target) {
|
|
3108
|
+
if (target.isSnapshot) {
|
|
3109
|
+
let ref = this.view.viewState.lineBlockAt(target.range.head);
|
|
3110
|
+
this.view.scrollDOM.scrollTop = ref.top - target.yMargin;
|
|
3111
|
+
this.view.scrollDOM.scrollLeft = target.xMargin;
|
|
3112
|
+
return;
|
|
3113
|
+
}
|
|
3093
3114
|
let { range } = target;
|
|
3094
3115
|
let rect = this.coordsAt(range.head, range.empty ? range.assoc : range.head > range.anchor ? -1 : 1), other;
|
|
3095
3116
|
if (!rect)
|
|
@@ -3102,7 +3123,8 @@ class DocView extends ContentView {
|
|
|
3102
3123
|
left: rect.left - margins.left, top: rect.top - margins.top,
|
|
3103
3124
|
right: rect.right + margins.right, bottom: rect.bottom + margins.bottom
|
|
3104
3125
|
};
|
|
3105
|
-
|
|
3126
|
+
let { offsetWidth, offsetHeight } = this.view.scrollDOM;
|
|
3127
|
+
scrollRectIntoView(this.view.scrollDOM, targetRect, range.head < range.anchor ? -1 : 1, target.x, target.y, Math.max(Math.min(target.xMargin, offsetWidth), -offsetWidth), Math.max(Math.min(target.yMargin, offsetHeight), -offsetHeight), this.view.textDirection == exports.Direction.LTR);
|
|
3106
3128
|
}
|
|
3107
3129
|
}
|
|
3108
3130
|
function betweenUneditable(pos) {
|
|
@@ -3639,6 +3661,9 @@ class InputState {
|
|
|
3639
3661
|
// the mutation events fire shortly after the compositionend event
|
|
3640
3662
|
this.compositionPendingChange = false;
|
|
3641
3663
|
this.mouseSelection = null;
|
|
3664
|
+
// When a drag from the editor is active, this points at the range
|
|
3665
|
+
// being dragged.
|
|
3666
|
+
this.draggedContent = null;
|
|
3642
3667
|
this.handleEvent = this.handleEvent.bind(this);
|
|
3643
3668
|
this.notifiedFocused = view.hasFocus;
|
|
3644
3669
|
// On Safari adding an input event handler somehow prevents an
|
|
@@ -3755,6 +3780,8 @@ class InputState {
|
|
|
3755
3780
|
update(update) {
|
|
3756
3781
|
if (this.mouseSelection)
|
|
3757
3782
|
this.mouseSelection.update(update);
|
|
3783
|
+
if (this.draggedContent && update.docChanged)
|
|
3784
|
+
this.draggedContent = this.draggedContent.map(update.changes);
|
|
3758
3785
|
if (update.transactions.length)
|
|
3759
3786
|
this.lastKeyCode = this.lastSelectionTime = 0;
|
|
3760
3787
|
}
|
|
@@ -3872,7 +3899,7 @@ class MouseSelection {
|
|
|
3872
3899
|
let doc = this.view.contentDOM.ownerDocument;
|
|
3873
3900
|
doc.removeEventListener("mousemove", this.move);
|
|
3874
3901
|
doc.removeEventListener("mouseup", this.up);
|
|
3875
|
-
this.view.inputState.mouseSelection = null;
|
|
3902
|
+
this.view.inputState.mouseSelection = this.view.inputState.draggedContent = null;
|
|
3876
3903
|
}
|
|
3877
3904
|
setScrollSpeed(sx, sy) {
|
|
3878
3905
|
this.scrollSpeed = { x: sx, y: sy };
|
|
@@ -3930,8 +3957,6 @@ class MouseSelection {
|
|
|
3930
3957
|
this.mustSelect = false;
|
|
3931
3958
|
}
|
|
3932
3959
|
update(update) {
|
|
3933
|
-
if (update.docChanged && this.dragging)
|
|
3934
|
-
this.dragging = this.dragging.map(update.changes);
|
|
3935
3960
|
if (this.style.update(update))
|
|
3936
3961
|
setTimeout(() => this.select(this.lastEvent), 20);
|
|
3937
3962
|
}
|
|
@@ -4159,23 +4184,36 @@ function removeRangeAround(sel, pos) {
|
|
|
4159
4184
|
return null;
|
|
4160
4185
|
}
|
|
4161
4186
|
handlers.dragstart = (view, event) => {
|
|
4162
|
-
let { selection: { main } } = view.state;
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4187
|
+
let { selection: { main: range } } = view.state;
|
|
4188
|
+
if (event.target.draggable) {
|
|
4189
|
+
let cView = view.docView.nearest(event.target);
|
|
4190
|
+
if (cView && cView.isWidget) {
|
|
4191
|
+
let from = cView.posAtStart, to = from + cView.length;
|
|
4192
|
+
if (from >= range.to || to <= range.from)
|
|
4193
|
+
range = state.EditorSelection.range(from, to);
|
|
4194
|
+
}
|
|
4195
|
+
}
|
|
4196
|
+
let { inputState } = view;
|
|
4197
|
+
if (inputState.mouseSelection)
|
|
4198
|
+
inputState.mouseSelection.dragging = true;
|
|
4199
|
+
inputState.draggedContent = range;
|
|
4166
4200
|
if (event.dataTransfer) {
|
|
4167
|
-
event.dataTransfer.setData("Text", view.state.sliceDoc(
|
|
4201
|
+
event.dataTransfer.setData("Text", view.state.sliceDoc(range.from, range.to));
|
|
4168
4202
|
event.dataTransfer.effectAllowed = "copyMove";
|
|
4169
4203
|
}
|
|
4170
4204
|
return false;
|
|
4171
4205
|
};
|
|
4206
|
+
handlers.dragend = view => {
|
|
4207
|
+
view.inputState.draggedContent = null;
|
|
4208
|
+
return false;
|
|
4209
|
+
};
|
|
4172
4210
|
function dropText(view, event, text, direct) {
|
|
4173
4211
|
if (!text)
|
|
4174
4212
|
return;
|
|
4175
4213
|
let dropPos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
|
|
4176
|
-
let {
|
|
4177
|
-
let del = direct &&
|
|
4178
|
-
{ from:
|
|
4214
|
+
let { draggedContent } = view.inputState;
|
|
4215
|
+
let del = direct && draggedContent && dragMovesSelection(view, event)
|
|
4216
|
+
? { from: draggedContent.from, to: draggedContent.to } : null;
|
|
4179
4217
|
let ins = { from: dropPos, insert: text };
|
|
4180
4218
|
let changes = view.state.changes(del ? [del, ins] : ins);
|
|
4181
4219
|
view.focus();
|
|
@@ -4184,6 +4222,7 @@ function dropText(view, event, text, direct) {
|
|
|
4184
4222
|
selection: { anchor: changes.mapPos(dropPos, -1), head: changes.mapPos(dropPos, 1) },
|
|
4185
4223
|
userEvent: del ? "move.drop" : "input.drop"
|
|
4186
4224
|
});
|
|
4225
|
+
view.inputState.draggedContent = null;
|
|
4187
4226
|
}
|
|
4188
4227
|
handlers.drop = (view, event) => {
|
|
4189
4228
|
if (!event.dataTransfer)
|
|
@@ -5844,6 +5883,13 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5844
5883
|
"&.cm-focused > .cm-scroller > .cm-cursorLayer .cm-cursor": {
|
|
5845
5884
|
display: "block"
|
|
5846
5885
|
},
|
|
5886
|
+
".cm-announced": {
|
|
5887
|
+
position: "fixed",
|
|
5888
|
+
top: "-10000px"
|
|
5889
|
+
},
|
|
5890
|
+
"@media print": {
|
|
5891
|
+
".cm-announced": { display: "none" }
|
|
5892
|
+
},
|
|
5847
5893
|
"&light .cm-activeLine": { backgroundColor: "#cceeff44" },
|
|
5848
5894
|
"&dark .cm-activeLine": { backgroundColor: "#99eeff33" },
|
|
5849
5895
|
"&light .cm-specialChar": { color: "red" },
|
|
@@ -6892,7 +6938,7 @@ class EditorView {
|
|
|
6892
6938
|
this.scrollDOM.className = "cm-scroller";
|
|
6893
6939
|
this.scrollDOM.appendChild(this.contentDOM);
|
|
6894
6940
|
this.announceDOM = document.createElement("div");
|
|
6895
|
-
this.announceDOM.
|
|
6941
|
+
this.announceDOM.className = "cm-announced";
|
|
6896
6942
|
this.announceDOM.setAttribute("aria-live", "polite");
|
|
6897
6943
|
this.dom = document.createElement("div");
|
|
6898
6944
|
this.dom.appendChild(this.announceDOM);
|
|
@@ -6904,6 +6950,8 @@ class EditorView {
|
|
|
6904
6950
|
this.dispatch = this.dispatch.bind(this);
|
|
6905
6951
|
this._root = (config.root || getRoot(config.parent) || document);
|
|
6906
6952
|
this.viewState = new ViewState(config.state || state.EditorState.create(config));
|
|
6953
|
+
if (config.scrollTo && config.scrollTo.is(scrollIntoView))
|
|
6954
|
+
this.viewState.scrollTarget = config.scrollTo.value.clip(this.viewState.state);
|
|
6907
6955
|
this.plugins = this.state.facet(viewPlugin).map(spec => new PluginInstance(spec));
|
|
6908
6956
|
for (let plugin of this.plugins)
|
|
6909
6957
|
plugin.update(this);
|
|
@@ -6991,7 +7039,7 @@ class EditorView {
|
|
|
6991
7039
|
}
|
|
6992
7040
|
for (let e of tr.effects)
|
|
6993
7041
|
if (e.is(scrollIntoView))
|
|
6994
|
-
scrollTarget = e.value;
|
|
7042
|
+
scrollTarget = e.value.clip(this.state);
|
|
6995
7043
|
}
|
|
6996
7044
|
this.viewState.update(update, scrollTarget);
|
|
6997
7045
|
this.bidiCache = CachedOrder.update(this.bidiCache, update.changes);
|
|
@@ -7014,8 +7062,14 @@ class EditorView {
|
|
|
7014
7062
|
if (redrawn || attrsChanged || scrollTarget || this.viewState.mustEnforceCursorAssoc || this.viewState.mustMeasureContent)
|
|
7015
7063
|
this.requestMeasure();
|
|
7016
7064
|
if (!update.empty)
|
|
7017
|
-
for (let listener of this.state.facet(updateListener))
|
|
7018
|
-
|
|
7065
|
+
for (let listener of this.state.facet(updateListener)) {
|
|
7066
|
+
try {
|
|
7067
|
+
listener(update);
|
|
7068
|
+
}
|
|
7069
|
+
catch (e) {
|
|
7070
|
+
logException(this.state, e, "update listener");
|
|
7071
|
+
}
|
|
7072
|
+
}
|
|
7019
7073
|
if (dispatchFocus || domChange)
|
|
7020
7074
|
Promise.resolve().then(() => {
|
|
7021
7075
|
if (dispatchFocus && this.state == dispatchFocus.startState)
|
|
@@ -7050,6 +7104,7 @@ class EditorView {
|
|
|
7050
7104
|
this.pluginMap.clear();
|
|
7051
7105
|
for (let plugin of this.plugins)
|
|
7052
7106
|
plugin.update(this);
|
|
7107
|
+
this.docView.destroy();
|
|
7053
7108
|
this.docView = new DocView(this);
|
|
7054
7109
|
this.inputState.ensureHandlers(this.plugins);
|
|
7055
7110
|
this.mountStyles();
|
|
@@ -7582,6 +7637,7 @@ class EditorView {
|
|
|
7582
7637
|
plugin.destroy(this);
|
|
7583
7638
|
this.plugins = [];
|
|
7584
7639
|
this.inputState.destroy();
|
|
7640
|
+
this.docView.destroy();
|
|
7585
7641
|
this.dom.remove();
|
|
7586
7642
|
this.observer.destroy();
|
|
7587
7643
|
if (this.measureScheduled > -1)
|
|
@@ -7597,6 +7653,23 @@ class EditorView {
|
|
|
7597
7653
|
return scrollIntoView.of(new ScrollTarget(typeof pos == "number" ? state.EditorSelection.cursor(pos) : pos, options.y, options.x, options.yMargin, options.xMargin));
|
|
7598
7654
|
}
|
|
7599
7655
|
/**
|
|
7656
|
+
Return an effect that resets the editor to its current (at the
|
|
7657
|
+
time this method was called) scroll position. Note that this
|
|
7658
|
+
only affects the editor's own scrollable element, not parents.
|
|
7659
|
+
See also
|
|
7660
|
+
[`EditorViewConfig.scrollTo`](https://codemirror.net/6/docs/ref/#view.EditorViewConfig.scrollTo).
|
|
7661
|
+
|
|
7662
|
+
The effect should be used with a document identical to the one
|
|
7663
|
+
it was created for. Failing to do so is not an error, but may
|
|
7664
|
+
not scroll to the expected position. You can
|
|
7665
|
+
[map](https://codemirror.net/6/docs/ref/#state.StateEffect.map) the effect to account for changes.
|
|
7666
|
+
*/
|
|
7667
|
+
scrollSnapshot() {
|
|
7668
|
+
let { scrollTop, scrollLeft } = this.scrollDOM;
|
|
7669
|
+
let ref = this.viewState.scrollAnchorAt(scrollTop);
|
|
7670
|
+
return scrollIntoView.of(new ScrollTarget(state.EditorSelection.cursor(ref.from), "start", "start", ref.top - scrollTop, scrollLeft, true));
|
|
7671
|
+
}
|
|
7672
|
+
/**
|
|
7600
7673
|
Returns an extension that can be used to add DOM event handlers.
|
|
7601
7674
|
The value should be an object mapping event names to handler
|
|
7602
7675
|
functions. For any given event, such functions are ordered by
|
|
@@ -8425,8 +8498,10 @@ const themeSpec = {
|
|
|
8425
8498
|
"&::selection": { backgroundColor: "transparent !important" }
|
|
8426
8499
|
}
|
|
8427
8500
|
};
|
|
8428
|
-
if (CanHidePrimary)
|
|
8501
|
+
if (CanHidePrimary) {
|
|
8429
8502
|
themeSpec[".cm-line"].caretColor = "transparent !important";
|
|
8503
|
+
themeSpec[".cm-content"] = { caretColor: "transparent !important" };
|
|
8504
|
+
}
|
|
8430
8505
|
const hideNativeSelection = state.Prec.highest(EditorView.theme(themeSpec));
|
|
8431
8506
|
|
|
8432
8507
|
const setDropCursorPos = state.StateEffect.define({
|
|
@@ -9483,7 +9558,7 @@ const showHoverTooltipHost = showTooltip.compute([showHoverTooltip], state => {
|
|
|
9483
9558
|
return null;
|
|
9484
9559
|
return {
|
|
9485
9560
|
pos: Math.min(...tooltips.map(t => t.pos)),
|
|
9486
|
-
end: Math.max(...tooltips.
|
|
9561
|
+
end: Math.max(...tooltips.map(t => { var _a; return (_a = t.end) !== null && _a !== void 0 ? _a : t.pos; })),
|
|
9487
9562
|
create: HoverTooltipHost.create,
|
|
9488
9563
|
above: tooltips[0].above,
|
|
9489
9564
|
arrow: tooltips.some(t => t.arrow),
|
|
@@ -9563,14 +9638,19 @@ class HoverPlugin {
|
|
|
9563
9638
|
view.dispatch({ effects: this.setHover.of(open) });
|
|
9564
9639
|
}
|
|
9565
9640
|
}
|
|
9641
|
+
get tooltip() {
|
|
9642
|
+
let plugin = this.view.plugin(tooltipPlugin);
|
|
9643
|
+
let index = plugin ? plugin.manager.tooltips.findIndex(t => t.create == HoverTooltipHost.create) : -1;
|
|
9644
|
+
return index > -1 ? plugin.manager.tooltipViews[index] : null;
|
|
9645
|
+
}
|
|
9566
9646
|
mousemove(event) {
|
|
9567
9647
|
var _a;
|
|
9568
9648
|
this.lastMove = { x: event.clientX, y: event.clientY, target: event.target, time: Date.now() };
|
|
9569
9649
|
if (this.hoverTimeout < 0)
|
|
9570
9650
|
this.hoverTimeout = setTimeout(this.checkHover, this.hoverTime);
|
|
9571
|
-
let tooltip = this
|
|
9572
|
-
if (tooltip && !isInTooltip(
|
|
9573
|
-
let { pos } =
|
|
9651
|
+
let { active, tooltip } = this;
|
|
9652
|
+
if (active && tooltip && !isInTooltip(tooltip.dom, event) || this.pending) {
|
|
9653
|
+
let { pos } = active || this.pending, end = (_a = active === null || active === void 0 ? void 0 : active.end) !== null && _a !== void 0 ? _a : pos;
|
|
9574
9654
|
if ((pos == end ? this.view.posAtCoords(this.lastMove) != pos
|
|
9575
9655
|
: !isOverRange(this.view, pos, end, event.clientX, event.clientY))) {
|
|
9576
9656
|
this.view.dispatch({ effects: this.setHover.of(null) });
|
|
@@ -9578,11 +9658,26 @@ class HoverPlugin {
|
|
|
9578
9658
|
}
|
|
9579
9659
|
}
|
|
9580
9660
|
}
|
|
9581
|
-
mouseleave(
|
|
9661
|
+
mouseleave(event) {
|
|
9582
9662
|
clearTimeout(this.hoverTimeout);
|
|
9583
9663
|
this.hoverTimeout = -1;
|
|
9584
|
-
|
|
9585
|
-
|
|
9664
|
+
let { active } = this;
|
|
9665
|
+
if (active) {
|
|
9666
|
+
let { tooltip } = this;
|
|
9667
|
+
let inTooltip = tooltip && tooltip.dom.contains(event.relatedTarget);
|
|
9668
|
+
if (!inTooltip)
|
|
9669
|
+
this.view.dispatch({ effects: this.setHover.of(null) });
|
|
9670
|
+
else
|
|
9671
|
+
this.watchTooltipLeave(tooltip.dom);
|
|
9672
|
+
}
|
|
9673
|
+
}
|
|
9674
|
+
watchTooltipLeave(tooltip) {
|
|
9675
|
+
let watch = (event) => {
|
|
9676
|
+
tooltip.removeEventListener("mouseleave", watch);
|
|
9677
|
+
if (this.active && !this.view.dom.contains(event.relatedTarget))
|
|
9678
|
+
this.view.dispatch({ effects: this.setHover.of(null) });
|
|
9679
|
+
};
|
|
9680
|
+
tooltip.addEventListener("mouseleave", watch);
|
|
9586
9681
|
}
|
|
9587
9682
|
destroy() {
|
|
9588
9683
|
clearTimeout(this.hoverTimeout);
|
|
@@ -9590,11 +9685,11 @@ class HoverPlugin {
|
|
|
9590
9685
|
this.view.dom.removeEventListener("mousemove", this.mousemove);
|
|
9591
9686
|
}
|
|
9592
9687
|
}
|
|
9593
|
-
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9688
|
+
const tooltipMargin = 4;
|
|
9689
|
+
function isInTooltip(tooltip, event) {
|
|
9690
|
+
let rect = tooltip.getBoundingClientRect();
|
|
9691
|
+
return event.clientX >= rect.left - tooltipMargin && event.clientX <= rect.right + tooltipMargin &&
|
|
9692
|
+
event.clientY >= rect.top - tooltipMargin && event.clientY <= rect.bottom + tooltipMargin;
|
|
9598
9693
|
}
|
|
9599
9694
|
function isOverRange(view, from, to, x, y, margin) {
|
|
9600
9695
|
let rect = view.scrollDOM.getBoundingClientRect();
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _codemirror_state from '@codemirror/state';
|
|
2
|
-
import { RangeSet, RangeValue, Range, EditorState, Extension, Transaction, ChangeSet, EditorSelection, EditorStateConfig,
|
|
2
|
+
import { RangeSet, RangeValue, Range, EditorState, Extension, Transaction, ChangeSet, SelectionRange, ChangeDesc, EditorSelection, EditorStateConfig, StateEffect, TransactionSpec, Line, Facet } from '@codemirror/state';
|
|
3
3
|
import { StyleModule, StyleSpec } from 'style-mod';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -361,6 +361,17 @@ apply to the editor, and if it can, perform it as a side effect
|
|
|
361
361
|
transaction) and return `true`.
|
|
362
362
|
*/
|
|
363
363
|
type Command = (target: EditorView) => boolean;
|
|
364
|
+
declare class ScrollTarget {
|
|
365
|
+
readonly range: SelectionRange;
|
|
366
|
+
readonly y: ScrollStrategy;
|
|
367
|
+
readonly x: ScrollStrategy;
|
|
368
|
+
readonly yMargin: number;
|
|
369
|
+
readonly xMargin: number;
|
|
370
|
+
readonly isSnapshot: boolean;
|
|
371
|
+
constructor(range: SelectionRange, y?: ScrollStrategy, x?: ScrollStrategy, yMargin?: number, xMargin?: number, isSnapshot?: boolean);
|
|
372
|
+
map(changes: ChangeDesc): ScrollTarget;
|
|
373
|
+
clip(state: EditorState): ScrollTarget;
|
|
374
|
+
}
|
|
364
375
|
/**
|
|
365
376
|
Log or report an unhandled exception in client code. Should
|
|
366
377
|
probably only be used by extension code that allows client code to
|
|
@@ -633,6 +644,13 @@ interface EditorViewConfig extends EditorStateConfig {
|
|
|
633
644
|
*/
|
|
634
645
|
root?: Document | ShadowRoot;
|
|
635
646
|
/**
|
|
647
|
+
Pass an effect created with
|
|
648
|
+
[`EditorView.scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) or
|
|
649
|
+
[`EditorView.scrollSnapshot`](https://codemirror.net/6/docs/ref/#view.EditorView.scrollSnapshot)
|
|
650
|
+
here to set an initial scroll position.
|
|
651
|
+
*/
|
|
652
|
+
scrollTo?: StateEffect<any>;
|
|
653
|
+
/**
|
|
636
654
|
Override the way transactions are
|
|
637
655
|
[dispatched](https://codemirror.net/6/docs/ref/#view.EditorView.dispatch) for this editor view.
|
|
638
656
|
Your implementation, if provided, should probably call the
|
|
@@ -1032,15 +1050,30 @@ declare class EditorView {
|
|
|
1032
1050
|
/**
|
|
1033
1051
|
Extra vertical distance to add when moving something into
|
|
1034
1052
|
view. Not used with the `"center"` strategy. Defaults to 5.
|
|
1053
|
+
Must be less than the height of the editor.
|
|
1035
1054
|
*/
|
|
1036
1055
|
yMargin?: number;
|
|
1037
1056
|
/**
|
|
1038
1057
|
Extra horizontal distance to add. Not used with the `"center"`
|
|
1039
|
-
strategy. Defaults to 5.
|
|
1058
|
+
strategy. Defaults to 5. Must be less than the width of the
|
|
1059
|
+
editor.
|
|
1040
1060
|
*/
|
|
1041
1061
|
xMargin?: number;
|
|
1042
1062
|
}): StateEffect<unknown>;
|
|
1043
1063
|
/**
|
|
1064
|
+
Return an effect that resets the editor to its current (at the
|
|
1065
|
+
time this method was called) scroll position. Note that this
|
|
1066
|
+
only affects the editor's own scrollable element, not parents.
|
|
1067
|
+
See also
|
|
1068
|
+
[`EditorViewConfig.scrollTo`](https://codemirror.net/6/docs/ref/#view.EditorViewConfig.scrollTo).
|
|
1069
|
+
|
|
1070
|
+
The effect should be used with a document identical to the one
|
|
1071
|
+
it was created for. Failing to do so is not an error, but may
|
|
1072
|
+
not scroll to the expected position. You can
|
|
1073
|
+
[map](https://codemirror.net/6/docs/ref/#state.StateEffect.map) the effect to account for changes.
|
|
1074
|
+
*/
|
|
1075
|
+
scrollSnapshot(): StateEffect<ScrollTarget>;
|
|
1076
|
+
/**
|
|
1044
1077
|
Facet to add a [style
|
|
1045
1078
|
module](https://github.com/marijnh/style-mod#documentation) to
|
|
1046
1079
|
an editor view. The view will ensure that the module is
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _codemirror_state from '@codemirror/state';
|
|
2
|
-
import { RangeSet, RangeValue, Range, EditorState, Extension, Transaction, ChangeSet, EditorSelection, EditorStateConfig,
|
|
2
|
+
import { RangeSet, RangeValue, Range, EditorState, Extension, Transaction, ChangeSet, SelectionRange, ChangeDesc, EditorSelection, EditorStateConfig, StateEffect, TransactionSpec, Line, Facet } from '@codemirror/state';
|
|
3
3
|
import { StyleModule, StyleSpec } from 'style-mod';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -361,6 +361,17 @@ apply to the editor, and if it can, perform it as a side effect
|
|
|
361
361
|
transaction) and return `true`.
|
|
362
362
|
*/
|
|
363
363
|
type Command = (target: EditorView) => boolean;
|
|
364
|
+
declare class ScrollTarget {
|
|
365
|
+
readonly range: SelectionRange;
|
|
366
|
+
readonly y: ScrollStrategy;
|
|
367
|
+
readonly x: ScrollStrategy;
|
|
368
|
+
readonly yMargin: number;
|
|
369
|
+
readonly xMargin: number;
|
|
370
|
+
readonly isSnapshot: boolean;
|
|
371
|
+
constructor(range: SelectionRange, y?: ScrollStrategy, x?: ScrollStrategy, yMargin?: number, xMargin?: number, isSnapshot?: boolean);
|
|
372
|
+
map(changes: ChangeDesc): ScrollTarget;
|
|
373
|
+
clip(state: EditorState): ScrollTarget;
|
|
374
|
+
}
|
|
364
375
|
/**
|
|
365
376
|
Log or report an unhandled exception in client code. Should
|
|
366
377
|
probably only be used by extension code that allows client code to
|
|
@@ -633,6 +644,13 @@ interface EditorViewConfig extends EditorStateConfig {
|
|
|
633
644
|
*/
|
|
634
645
|
root?: Document | ShadowRoot;
|
|
635
646
|
/**
|
|
647
|
+
Pass an effect created with
|
|
648
|
+
[`EditorView.scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) or
|
|
649
|
+
[`EditorView.scrollSnapshot`](https://codemirror.net/6/docs/ref/#view.EditorView.scrollSnapshot)
|
|
650
|
+
here to set an initial scroll position.
|
|
651
|
+
*/
|
|
652
|
+
scrollTo?: StateEffect<any>;
|
|
653
|
+
/**
|
|
636
654
|
Override the way transactions are
|
|
637
655
|
[dispatched](https://codemirror.net/6/docs/ref/#view.EditorView.dispatch) for this editor view.
|
|
638
656
|
Your implementation, if provided, should probably call the
|
|
@@ -1032,15 +1050,30 @@ declare class EditorView {
|
|
|
1032
1050
|
/**
|
|
1033
1051
|
Extra vertical distance to add when moving something into
|
|
1034
1052
|
view. Not used with the `"center"` strategy. Defaults to 5.
|
|
1053
|
+
Must be less than the height of the editor.
|
|
1035
1054
|
*/
|
|
1036
1055
|
yMargin?: number;
|
|
1037
1056
|
/**
|
|
1038
1057
|
Extra horizontal distance to add. Not used with the `"center"`
|
|
1039
|
-
strategy. Defaults to 5.
|
|
1058
|
+
strategy. Defaults to 5. Must be less than the width of the
|
|
1059
|
+
editor.
|
|
1040
1060
|
*/
|
|
1041
1061
|
xMargin?: number;
|
|
1042
1062
|
}): StateEffect<unknown>;
|
|
1043
1063
|
/**
|
|
1064
|
+
Return an effect that resets the editor to its current (at the
|
|
1065
|
+
time this method was called) scroll position. Note that this
|
|
1066
|
+
only affects the editor's own scrollable element, not parents.
|
|
1067
|
+
See also
|
|
1068
|
+
[`EditorViewConfig.scrollTo`](https://codemirror.net/6/docs/ref/#view.EditorViewConfig.scrollTo).
|
|
1069
|
+
|
|
1070
|
+
The effect should be used with a document identical to the one
|
|
1071
|
+
it was created for. Failing to do so is not an error, but may
|
|
1072
|
+
not scroll to the expected position. You can
|
|
1073
|
+
[map](https://codemirror.net/6/docs/ref/#state.StateEffect.map) the effect to account for changes.
|
|
1074
|
+
*/
|
|
1075
|
+
scrollSnapshot(): StateEffect<ScrollTarget>;
|
|
1076
|
+
/**
|
|
1044
1077
|
Facet to add a [style
|
|
1045
1078
|
module](https://github.com/marijnh/style-mod#documentation) to
|
|
1046
1079
|
an editor view. The view will ensure that the module is
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Text, RangeSet, MapMode, RangeValue, Facet, StateEffect, ChangeSet,
|
|
1
|
+
import { Text, RangeSet, MapMode, RangeValue, Facet, StateEffect, ChangeSet, EditorSelection, findClusterBreak, findColumn, CharCategory, Annotation, EditorState, Transaction, Prec, codePointAt, codePointSize, combineConfig, StateField, RangeSetBuilder, countColumn } from '@codemirror/state';
|
|
2
2
|
import { StyleModule } from 'style-mod';
|
|
3
3
|
import { keyName, base, shift } from 'w3c-keyname';
|
|
4
4
|
|
|
@@ -501,7 +501,7 @@ class ContentView {
|
|
|
501
501
|
this.markDirty();
|
|
502
502
|
for (let i = from; i < to; i++) {
|
|
503
503
|
let child = this.children[i];
|
|
504
|
-
if (child.parent == this)
|
|
504
|
+
if (child.parent == this && children.indexOf(child) < 0)
|
|
505
505
|
child.destroy();
|
|
506
506
|
}
|
|
507
507
|
this.children.splice(from, to - from, ...children);
|
|
@@ -538,6 +538,8 @@ class ContentView {
|
|
|
538
538
|
// number > 0 when after its position.
|
|
539
539
|
getSide() { return 0; }
|
|
540
540
|
destroy() {
|
|
541
|
+
for (let child of this.children)
|
|
542
|
+
child.destroy();
|
|
541
543
|
this.parent = null;
|
|
542
544
|
}
|
|
543
545
|
}
|
|
@@ -1785,15 +1787,28 @@ const nativeSelectionHidden = /*@__PURE__*/Facet.define({
|
|
|
1785
1787
|
combine: values => values.some(x => x)
|
|
1786
1788
|
});
|
|
1787
1789
|
class ScrollTarget {
|
|
1788
|
-
constructor(range, y = "nearest", x = "nearest", yMargin = 5, xMargin = 5
|
|
1790
|
+
constructor(range, y = "nearest", x = "nearest", yMargin = 5, xMargin = 5,
|
|
1791
|
+
// This data structure is abused to also store precise scroll
|
|
1792
|
+
// snapshots, instead of a `scrollIntoView` request. When this
|
|
1793
|
+
// flag is `true`, `range` points at a position in the reference
|
|
1794
|
+
// line, `yMargin` holds the difference between the top of that
|
|
1795
|
+
// line and the top of the editor, and `xMargin` holds the
|
|
1796
|
+
// editor's `scrollLeft`.
|
|
1797
|
+
isSnapshot = false) {
|
|
1789
1798
|
this.range = range;
|
|
1790
1799
|
this.y = y;
|
|
1791
1800
|
this.x = x;
|
|
1792
1801
|
this.yMargin = yMargin;
|
|
1793
1802
|
this.xMargin = xMargin;
|
|
1803
|
+
this.isSnapshot = isSnapshot;
|
|
1794
1804
|
}
|
|
1795
1805
|
map(changes) {
|
|
1796
|
-
return changes.empty ? this :
|
|
1806
|
+
return changes.empty ? this :
|
|
1807
|
+
new ScrollTarget(this.range.map(changes), this.y, this.x, this.yMargin, this.xMargin, this.isSnapshot);
|
|
1808
|
+
}
|
|
1809
|
+
clip(state) {
|
|
1810
|
+
return this.range.to <= state.doc.length ? this :
|
|
1811
|
+
new ScrollTarget(EditorSelection.cursor(state.doc.length), this.y, this.x, this.yMargin, this.xMargin, this.isSnapshot);
|
|
1797
1812
|
}
|
|
1798
1813
|
}
|
|
1799
1814
|
const scrollIntoView = /*@__PURE__*/StateEffect.define({ map: (t, ch) => t.map(ch) });
|
|
@@ -3086,6 +3101,12 @@ class DocView extends ContentView {
|
|
|
3086
3101
|
];
|
|
3087
3102
|
}
|
|
3088
3103
|
scrollIntoView(target) {
|
|
3104
|
+
if (target.isSnapshot) {
|
|
3105
|
+
let ref = this.view.viewState.lineBlockAt(target.range.head);
|
|
3106
|
+
this.view.scrollDOM.scrollTop = ref.top - target.yMargin;
|
|
3107
|
+
this.view.scrollDOM.scrollLeft = target.xMargin;
|
|
3108
|
+
return;
|
|
3109
|
+
}
|
|
3089
3110
|
let { range } = target;
|
|
3090
3111
|
let rect = this.coordsAt(range.head, range.empty ? range.assoc : range.head > range.anchor ? -1 : 1), other;
|
|
3091
3112
|
if (!rect)
|
|
@@ -3098,7 +3119,8 @@ class DocView extends ContentView {
|
|
|
3098
3119
|
left: rect.left - margins.left, top: rect.top - margins.top,
|
|
3099
3120
|
right: rect.right + margins.right, bottom: rect.bottom + margins.bottom
|
|
3100
3121
|
};
|
|
3101
|
-
|
|
3122
|
+
let { offsetWidth, offsetHeight } = this.view.scrollDOM;
|
|
3123
|
+
scrollRectIntoView(this.view.scrollDOM, targetRect, range.head < range.anchor ? -1 : 1, target.x, target.y, Math.max(Math.min(target.xMargin, offsetWidth), -offsetWidth), Math.max(Math.min(target.yMargin, offsetHeight), -offsetHeight), this.view.textDirection == Direction.LTR);
|
|
3102
3124
|
}
|
|
3103
3125
|
}
|
|
3104
3126
|
function betweenUneditable(pos) {
|
|
@@ -3635,6 +3657,9 @@ class InputState {
|
|
|
3635
3657
|
// the mutation events fire shortly after the compositionend event
|
|
3636
3658
|
this.compositionPendingChange = false;
|
|
3637
3659
|
this.mouseSelection = null;
|
|
3660
|
+
// When a drag from the editor is active, this points at the range
|
|
3661
|
+
// being dragged.
|
|
3662
|
+
this.draggedContent = null;
|
|
3638
3663
|
this.handleEvent = this.handleEvent.bind(this);
|
|
3639
3664
|
this.notifiedFocused = view.hasFocus;
|
|
3640
3665
|
// On Safari adding an input event handler somehow prevents an
|
|
@@ -3751,6 +3776,8 @@ class InputState {
|
|
|
3751
3776
|
update(update) {
|
|
3752
3777
|
if (this.mouseSelection)
|
|
3753
3778
|
this.mouseSelection.update(update);
|
|
3779
|
+
if (this.draggedContent && update.docChanged)
|
|
3780
|
+
this.draggedContent = this.draggedContent.map(update.changes);
|
|
3754
3781
|
if (update.transactions.length)
|
|
3755
3782
|
this.lastKeyCode = this.lastSelectionTime = 0;
|
|
3756
3783
|
}
|
|
@@ -3868,7 +3895,7 @@ class MouseSelection {
|
|
|
3868
3895
|
let doc = this.view.contentDOM.ownerDocument;
|
|
3869
3896
|
doc.removeEventListener("mousemove", this.move);
|
|
3870
3897
|
doc.removeEventListener("mouseup", this.up);
|
|
3871
|
-
this.view.inputState.mouseSelection = null;
|
|
3898
|
+
this.view.inputState.mouseSelection = this.view.inputState.draggedContent = null;
|
|
3872
3899
|
}
|
|
3873
3900
|
setScrollSpeed(sx, sy) {
|
|
3874
3901
|
this.scrollSpeed = { x: sx, y: sy };
|
|
@@ -3926,8 +3953,6 @@ class MouseSelection {
|
|
|
3926
3953
|
this.mustSelect = false;
|
|
3927
3954
|
}
|
|
3928
3955
|
update(update) {
|
|
3929
|
-
if (update.docChanged && this.dragging)
|
|
3930
|
-
this.dragging = this.dragging.map(update.changes);
|
|
3931
3956
|
if (this.style.update(update))
|
|
3932
3957
|
setTimeout(() => this.select(this.lastEvent), 20);
|
|
3933
3958
|
}
|
|
@@ -4155,23 +4180,36 @@ function removeRangeAround(sel, pos) {
|
|
|
4155
4180
|
return null;
|
|
4156
4181
|
}
|
|
4157
4182
|
handlers.dragstart = (view, event) => {
|
|
4158
|
-
let { selection: { main } } = view.state;
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4183
|
+
let { selection: { main: range } } = view.state;
|
|
4184
|
+
if (event.target.draggable) {
|
|
4185
|
+
let cView = view.docView.nearest(event.target);
|
|
4186
|
+
if (cView && cView.isWidget) {
|
|
4187
|
+
let from = cView.posAtStart, to = from + cView.length;
|
|
4188
|
+
if (from >= range.to || to <= range.from)
|
|
4189
|
+
range = EditorSelection.range(from, to);
|
|
4190
|
+
}
|
|
4191
|
+
}
|
|
4192
|
+
let { inputState } = view;
|
|
4193
|
+
if (inputState.mouseSelection)
|
|
4194
|
+
inputState.mouseSelection.dragging = true;
|
|
4195
|
+
inputState.draggedContent = range;
|
|
4162
4196
|
if (event.dataTransfer) {
|
|
4163
|
-
event.dataTransfer.setData("Text", view.state.sliceDoc(
|
|
4197
|
+
event.dataTransfer.setData("Text", view.state.sliceDoc(range.from, range.to));
|
|
4164
4198
|
event.dataTransfer.effectAllowed = "copyMove";
|
|
4165
4199
|
}
|
|
4166
4200
|
return false;
|
|
4167
4201
|
};
|
|
4202
|
+
handlers.dragend = view => {
|
|
4203
|
+
view.inputState.draggedContent = null;
|
|
4204
|
+
return false;
|
|
4205
|
+
};
|
|
4168
4206
|
function dropText(view, event, text, direct) {
|
|
4169
4207
|
if (!text)
|
|
4170
4208
|
return;
|
|
4171
4209
|
let dropPos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
|
|
4172
|
-
let {
|
|
4173
|
-
let del = direct &&
|
|
4174
|
-
{ from:
|
|
4210
|
+
let { draggedContent } = view.inputState;
|
|
4211
|
+
let del = direct && draggedContent && dragMovesSelection(view, event)
|
|
4212
|
+
? { from: draggedContent.from, to: draggedContent.to } : null;
|
|
4175
4213
|
let ins = { from: dropPos, insert: text };
|
|
4176
4214
|
let changes = view.state.changes(del ? [del, ins] : ins);
|
|
4177
4215
|
view.focus();
|
|
@@ -4180,6 +4218,7 @@ function dropText(view, event, text, direct) {
|
|
|
4180
4218
|
selection: { anchor: changes.mapPos(dropPos, -1), head: changes.mapPos(dropPos, 1) },
|
|
4181
4219
|
userEvent: del ? "move.drop" : "input.drop"
|
|
4182
4220
|
});
|
|
4221
|
+
view.inputState.draggedContent = null;
|
|
4183
4222
|
}
|
|
4184
4223
|
handlers.drop = (view, event) => {
|
|
4185
4224
|
if (!event.dataTransfer)
|
|
@@ -5839,6 +5878,13 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5839
5878
|
"&.cm-focused > .cm-scroller > .cm-cursorLayer .cm-cursor": {
|
|
5840
5879
|
display: "block"
|
|
5841
5880
|
},
|
|
5881
|
+
".cm-announced": {
|
|
5882
|
+
position: "fixed",
|
|
5883
|
+
top: "-10000px"
|
|
5884
|
+
},
|
|
5885
|
+
"@media print": {
|
|
5886
|
+
".cm-announced": { display: "none" }
|
|
5887
|
+
},
|
|
5842
5888
|
"&light .cm-activeLine": { backgroundColor: "#cceeff44" },
|
|
5843
5889
|
"&dark .cm-activeLine": { backgroundColor: "#99eeff33" },
|
|
5844
5890
|
"&light .cm-specialChar": { color: "red" },
|
|
@@ -6887,7 +6933,7 @@ class EditorView {
|
|
|
6887
6933
|
this.scrollDOM.className = "cm-scroller";
|
|
6888
6934
|
this.scrollDOM.appendChild(this.contentDOM);
|
|
6889
6935
|
this.announceDOM = document.createElement("div");
|
|
6890
|
-
this.announceDOM.
|
|
6936
|
+
this.announceDOM.className = "cm-announced";
|
|
6891
6937
|
this.announceDOM.setAttribute("aria-live", "polite");
|
|
6892
6938
|
this.dom = document.createElement("div");
|
|
6893
6939
|
this.dom.appendChild(this.announceDOM);
|
|
@@ -6899,6 +6945,8 @@ class EditorView {
|
|
|
6899
6945
|
this.dispatch = this.dispatch.bind(this);
|
|
6900
6946
|
this._root = (config.root || getRoot(config.parent) || document);
|
|
6901
6947
|
this.viewState = new ViewState(config.state || EditorState.create(config));
|
|
6948
|
+
if (config.scrollTo && config.scrollTo.is(scrollIntoView))
|
|
6949
|
+
this.viewState.scrollTarget = config.scrollTo.value.clip(this.viewState.state);
|
|
6902
6950
|
this.plugins = this.state.facet(viewPlugin).map(spec => new PluginInstance(spec));
|
|
6903
6951
|
for (let plugin of this.plugins)
|
|
6904
6952
|
plugin.update(this);
|
|
@@ -6986,7 +7034,7 @@ class EditorView {
|
|
|
6986
7034
|
}
|
|
6987
7035
|
for (let e of tr.effects)
|
|
6988
7036
|
if (e.is(scrollIntoView))
|
|
6989
|
-
scrollTarget = e.value;
|
|
7037
|
+
scrollTarget = e.value.clip(this.state);
|
|
6990
7038
|
}
|
|
6991
7039
|
this.viewState.update(update, scrollTarget);
|
|
6992
7040
|
this.bidiCache = CachedOrder.update(this.bidiCache, update.changes);
|
|
@@ -7009,8 +7057,14 @@ class EditorView {
|
|
|
7009
7057
|
if (redrawn || attrsChanged || scrollTarget || this.viewState.mustEnforceCursorAssoc || this.viewState.mustMeasureContent)
|
|
7010
7058
|
this.requestMeasure();
|
|
7011
7059
|
if (!update.empty)
|
|
7012
|
-
for (let listener of this.state.facet(updateListener))
|
|
7013
|
-
|
|
7060
|
+
for (let listener of this.state.facet(updateListener)) {
|
|
7061
|
+
try {
|
|
7062
|
+
listener(update);
|
|
7063
|
+
}
|
|
7064
|
+
catch (e) {
|
|
7065
|
+
logException(this.state, e, "update listener");
|
|
7066
|
+
}
|
|
7067
|
+
}
|
|
7014
7068
|
if (dispatchFocus || domChange)
|
|
7015
7069
|
Promise.resolve().then(() => {
|
|
7016
7070
|
if (dispatchFocus && this.state == dispatchFocus.startState)
|
|
@@ -7045,6 +7099,7 @@ class EditorView {
|
|
|
7045
7099
|
this.pluginMap.clear();
|
|
7046
7100
|
for (let plugin of this.plugins)
|
|
7047
7101
|
plugin.update(this);
|
|
7102
|
+
this.docView.destroy();
|
|
7048
7103
|
this.docView = new DocView(this);
|
|
7049
7104
|
this.inputState.ensureHandlers(this.plugins);
|
|
7050
7105
|
this.mountStyles();
|
|
@@ -7577,6 +7632,7 @@ class EditorView {
|
|
|
7577
7632
|
plugin.destroy(this);
|
|
7578
7633
|
this.plugins = [];
|
|
7579
7634
|
this.inputState.destroy();
|
|
7635
|
+
this.docView.destroy();
|
|
7580
7636
|
this.dom.remove();
|
|
7581
7637
|
this.observer.destroy();
|
|
7582
7638
|
if (this.measureScheduled > -1)
|
|
@@ -7592,6 +7648,23 @@ class EditorView {
|
|
|
7592
7648
|
return scrollIntoView.of(new ScrollTarget(typeof pos == "number" ? EditorSelection.cursor(pos) : pos, options.y, options.x, options.yMargin, options.xMargin));
|
|
7593
7649
|
}
|
|
7594
7650
|
/**
|
|
7651
|
+
Return an effect that resets the editor to its current (at the
|
|
7652
|
+
time this method was called) scroll position. Note that this
|
|
7653
|
+
only affects the editor's own scrollable element, not parents.
|
|
7654
|
+
See also
|
|
7655
|
+
[`EditorViewConfig.scrollTo`](https://codemirror.net/6/docs/ref/#view.EditorViewConfig.scrollTo).
|
|
7656
|
+
|
|
7657
|
+
The effect should be used with a document identical to the one
|
|
7658
|
+
it was created for. Failing to do so is not an error, but may
|
|
7659
|
+
not scroll to the expected position. You can
|
|
7660
|
+
[map](https://codemirror.net/6/docs/ref/#state.StateEffect.map) the effect to account for changes.
|
|
7661
|
+
*/
|
|
7662
|
+
scrollSnapshot() {
|
|
7663
|
+
let { scrollTop, scrollLeft } = this.scrollDOM;
|
|
7664
|
+
let ref = this.viewState.scrollAnchorAt(scrollTop);
|
|
7665
|
+
return scrollIntoView.of(new ScrollTarget(EditorSelection.cursor(ref.from), "start", "start", ref.top - scrollTop, scrollLeft, true));
|
|
7666
|
+
}
|
|
7667
|
+
/**
|
|
7595
7668
|
Returns an extension that can be used to add DOM event handlers.
|
|
7596
7669
|
The value should be an object mapping event names to handler
|
|
7597
7670
|
functions. For any given event, such functions are ordered by
|
|
@@ -8420,8 +8493,10 @@ const themeSpec = {
|
|
|
8420
8493
|
"&::selection": { backgroundColor: "transparent !important" }
|
|
8421
8494
|
}
|
|
8422
8495
|
};
|
|
8423
|
-
if (CanHidePrimary)
|
|
8496
|
+
if (CanHidePrimary) {
|
|
8424
8497
|
themeSpec[".cm-line"].caretColor = "transparent !important";
|
|
8498
|
+
themeSpec[".cm-content"] = { caretColor: "transparent !important" };
|
|
8499
|
+
}
|
|
8425
8500
|
const hideNativeSelection = /*@__PURE__*/Prec.highest(/*@__PURE__*/EditorView.theme(themeSpec));
|
|
8426
8501
|
|
|
8427
8502
|
const setDropCursorPos = /*@__PURE__*/StateEffect.define({
|
|
@@ -9478,7 +9553,7 @@ const showHoverTooltipHost = /*@__PURE__*/showTooltip.compute([showHoverTooltip]
|
|
|
9478
9553
|
return null;
|
|
9479
9554
|
return {
|
|
9480
9555
|
pos: Math.min(...tooltips.map(t => t.pos)),
|
|
9481
|
-
end: Math.max(...tooltips.
|
|
9556
|
+
end: Math.max(...tooltips.map(t => { var _a; return (_a = t.end) !== null && _a !== void 0 ? _a : t.pos; })),
|
|
9482
9557
|
create: HoverTooltipHost.create,
|
|
9483
9558
|
above: tooltips[0].above,
|
|
9484
9559
|
arrow: tooltips.some(t => t.arrow),
|
|
@@ -9558,14 +9633,19 @@ class HoverPlugin {
|
|
|
9558
9633
|
view.dispatch({ effects: this.setHover.of(open) });
|
|
9559
9634
|
}
|
|
9560
9635
|
}
|
|
9636
|
+
get tooltip() {
|
|
9637
|
+
let plugin = this.view.plugin(tooltipPlugin);
|
|
9638
|
+
let index = plugin ? plugin.manager.tooltips.findIndex(t => t.create == HoverTooltipHost.create) : -1;
|
|
9639
|
+
return index > -1 ? plugin.manager.tooltipViews[index] : null;
|
|
9640
|
+
}
|
|
9561
9641
|
mousemove(event) {
|
|
9562
9642
|
var _a;
|
|
9563
9643
|
this.lastMove = { x: event.clientX, y: event.clientY, target: event.target, time: Date.now() };
|
|
9564
9644
|
if (this.hoverTimeout < 0)
|
|
9565
9645
|
this.hoverTimeout = setTimeout(this.checkHover, this.hoverTime);
|
|
9566
|
-
let tooltip = this
|
|
9567
|
-
if (tooltip && !isInTooltip(
|
|
9568
|
-
let { pos } =
|
|
9646
|
+
let { active, tooltip } = this;
|
|
9647
|
+
if (active && tooltip && !isInTooltip(tooltip.dom, event) || this.pending) {
|
|
9648
|
+
let { pos } = active || this.pending, end = (_a = active === null || active === void 0 ? void 0 : active.end) !== null && _a !== void 0 ? _a : pos;
|
|
9569
9649
|
if ((pos == end ? this.view.posAtCoords(this.lastMove) != pos
|
|
9570
9650
|
: !isOverRange(this.view, pos, end, event.clientX, event.clientY))) {
|
|
9571
9651
|
this.view.dispatch({ effects: this.setHover.of(null) });
|
|
@@ -9573,11 +9653,26 @@ class HoverPlugin {
|
|
|
9573
9653
|
}
|
|
9574
9654
|
}
|
|
9575
9655
|
}
|
|
9576
|
-
mouseleave(
|
|
9656
|
+
mouseleave(event) {
|
|
9577
9657
|
clearTimeout(this.hoverTimeout);
|
|
9578
9658
|
this.hoverTimeout = -1;
|
|
9579
|
-
|
|
9580
|
-
|
|
9659
|
+
let { active } = this;
|
|
9660
|
+
if (active) {
|
|
9661
|
+
let { tooltip } = this;
|
|
9662
|
+
let inTooltip = tooltip && tooltip.dom.contains(event.relatedTarget);
|
|
9663
|
+
if (!inTooltip)
|
|
9664
|
+
this.view.dispatch({ effects: this.setHover.of(null) });
|
|
9665
|
+
else
|
|
9666
|
+
this.watchTooltipLeave(tooltip.dom);
|
|
9667
|
+
}
|
|
9668
|
+
}
|
|
9669
|
+
watchTooltipLeave(tooltip) {
|
|
9670
|
+
let watch = (event) => {
|
|
9671
|
+
tooltip.removeEventListener("mouseleave", watch);
|
|
9672
|
+
if (this.active && !this.view.dom.contains(event.relatedTarget))
|
|
9673
|
+
this.view.dispatch({ effects: this.setHover.of(null) });
|
|
9674
|
+
};
|
|
9675
|
+
tooltip.addEventListener("mouseleave", watch);
|
|
9581
9676
|
}
|
|
9582
9677
|
destroy() {
|
|
9583
9678
|
clearTimeout(this.hoverTimeout);
|
|
@@ -9585,11 +9680,11 @@ class HoverPlugin {
|
|
|
9585
9680
|
this.view.dom.removeEventListener("mousemove", this.mousemove);
|
|
9586
9681
|
}
|
|
9587
9682
|
}
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
|
|
9683
|
+
const tooltipMargin = 4;
|
|
9684
|
+
function isInTooltip(tooltip, event) {
|
|
9685
|
+
let rect = tooltip.getBoundingClientRect();
|
|
9686
|
+
return event.clientX >= rect.left - tooltipMargin && event.clientX <= rect.right + tooltipMargin &&
|
|
9687
|
+
event.clientY >= rect.top - tooltipMargin && event.clientY <= rect.bottom + tooltipMargin;
|
|
9593
9688
|
}
|
|
9594
9689
|
function isOverRange(view, from, to, x, y, margin) {
|
|
9595
9690
|
let rect = view.scrollDOM.getBoundingClientRect();
|