@codemirror/view 6.36.8 → 6.37.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 +14 -0
- package/dist/index.cjs +183 -17
- package/dist/index.d.cts +85 -11
- package/dist/index.d.ts +85 -11
- package/dist/index.js +182 -18
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 6.37.1 (2025-05-30)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Properly add `crelt` as a dependency.
|
|
6
|
+
|
|
7
|
+
## 6.37.0 (2025-05-29)
|
|
8
|
+
|
|
9
|
+
### New features
|
|
10
|
+
|
|
11
|
+
View plugins can now take an argument, in which case they must be instantiated with their `of` method in order to be added to a configuration.
|
|
12
|
+
|
|
13
|
+
The new `showDialog` function makes it easy to show a notification or prompt using a CodeMirror panel.
|
|
14
|
+
|
|
1
15
|
## 6.36.8 (2025-05-12)
|
|
2
16
|
|
|
3
17
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var state = require('@codemirror/state');
|
|
4
4
|
var styleMod = require('style-mod');
|
|
5
5
|
var w3cKeyname = require('w3c-keyname');
|
|
6
|
+
var elt = require('crelt');
|
|
6
7
|
|
|
7
8
|
function getSelection(root) {
|
|
8
9
|
let target;
|
|
@@ -2430,11 +2431,23 @@ function logException(state, exception, context) {
|
|
|
2430
2431
|
}
|
|
2431
2432
|
const editable = state.Facet.define({ combine: values => values.length ? values[0] : true });
|
|
2432
2433
|
let nextPluginID = 0;
|
|
2433
|
-
const viewPlugin = state.Facet.define(
|
|
2434
|
+
const viewPlugin = state.Facet.define({
|
|
2435
|
+
combine(plugins) {
|
|
2436
|
+
return plugins.filter((p, i) => {
|
|
2437
|
+
for (let j = 0; j < i; j++)
|
|
2438
|
+
if (plugins[j].plugin == p.plugin)
|
|
2439
|
+
return false;
|
|
2440
|
+
return true;
|
|
2441
|
+
});
|
|
2442
|
+
}
|
|
2443
|
+
});
|
|
2434
2444
|
/**
|
|
2435
2445
|
View plugins associate stateful values with a view. They can
|
|
2436
2446
|
influence the way the content is drawn, and are notified of things
|
|
2437
|
-
that happen in the view.
|
|
2447
|
+
that happen in the view. They optionally take an argument, in
|
|
2448
|
+
which case you need to call [`of`](https://codemirror.net/6/docs/ref/#view.ViewPlugin.of) to create
|
|
2449
|
+
an extension for the plugin. When the argument type is undefined,
|
|
2450
|
+
you can use the plugin instance as an extension directly.
|
|
2438
2451
|
*/
|
|
2439
2452
|
class ViewPlugin {
|
|
2440
2453
|
constructor(
|
|
@@ -2458,7 +2471,14 @@ class ViewPlugin {
|
|
|
2458
2471
|
this.create = create;
|
|
2459
2472
|
this.domEventHandlers = domEventHandlers;
|
|
2460
2473
|
this.domEventObservers = domEventObservers;
|
|
2461
|
-
this.
|
|
2474
|
+
this.baseExtensions = buildExtensions(this);
|
|
2475
|
+
this.extension = this.baseExtensions.concat(viewPlugin.of({ plugin: this, arg: undefined }));
|
|
2476
|
+
}
|
|
2477
|
+
/**
|
|
2478
|
+
Create an extension for this plugin with the given argument.
|
|
2479
|
+
*/
|
|
2480
|
+
of(arg) {
|
|
2481
|
+
return this.baseExtensions.concat(viewPlugin.of({ plugin: this, arg }));
|
|
2462
2482
|
}
|
|
2463
2483
|
/**
|
|
2464
2484
|
Define a plugin from a constructor function that creates the
|
|
@@ -2467,7 +2487,7 @@ class ViewPlugin {
|
|
|
2467
2487
|
static define(create, spec) {
|
|
2468
2488
|
const { eventHandlers, eventObservers, provide, decorations: deco } = spec || {};
|
|
2469
2489
|
return new ViewPlugin(nextPluginID++, create, eventHandlers, eventObservers, plugin => {
|
|
2470
|
-
let ext = [
|
|
2490
|
+
let ext = [];
|
|
2471
2491
|
if (deco)
|
|
2472
2492
|
ext.push(decorations.of(view => {
|
|
2473
2493
|
let pluginInst = view.plugin(plugin);
|
|
@@ -2483,7 +2503,7 @@ class ViewPlugin {
|
|
|
2483
2503
|
editor view as argument.
|
|
2484
2504
|
*/
|
|
2485
2505
|
static fromClass(cls, spec) {
|
|
2486
|
-
return ViewPlugin.define(view => new cls(view), spec);
|
|
2506
|
+
return ViewPlugin.define((view, arg) => new cls(view, arg), spec);
|
|
2487
2507
|
}
|
|
2488
2508
|
}
|
|
2489
2509
|
class PluginInstance {
|
|
@@ -2491,18 +2511,19 @@ class PluginInstance {
|
|
|
2491
2511
|
this.spec = spec;
|
|
2492
2512
|
// When starting an update, all plugins have this field set to the
|
|
2493
2513
|
// update object, indicating they need to be updated. When finished
|
|
2494
|
-
// updating, it is set to `
|
|
2514
|
+
// updating, it is set to `null`. Retrieving a plugin that needs to
|
|
2495
2515
|
// be updated with `view.plugin` forces an eager update.
|
|
2496
2516
|
this.mustUpdate = null;
|
|
2497
2517
|
// This is null when the plugin is initially created, but
|
|
2498
2518
|
// initialized on the first update.
|
|
2499
2519
|
this.value = null;
|
|
2500
2520
|
}
|
|
2521
|
+
get plugin() { return this.spec && this.spec.plugin; }
|
|
2501
2522
|
update(view) {
|
|
2502
2523
|
if (!this.value) {
|
|
2503
2524
|
if (this.spec) {
|
|
2504
2525
|
try {
|
|
2505
|
-
this.value = this.spec.create(view);
|
|
2526
|
+
this.value = this.spec.plugin.create(view, this.spec.arg);
|
|
2506
2527
|
}
|
|
2507
2528
|
catch (e) {
|
|
2508
2529
|
logException(view.state, e, "CodeMirror plugin crashed");
|
|
@@ -4360,16 +4381,16 @@ function computeHandlers(plugins) {
|
|
|
4360
4381
|
return result[type] || (result[type] = { observers: [], handlers: [] });
|
|
4361
4382
|
}
|
|
4362
4383
|
for (let plugin of plugins) {
|
|
4363
|
-
let spec = plugin.spec;
|
|
4364
|
-
if (
|
|
4365
|
-
for (let type in
|
|
4366
|
-
let f =
|
|
4384
|
+
let spec = plugin.spec, handlers = spec && spec.plugin.domEventHandlers, observers = spec && spec.plugin.domEventObservers;
|
|
4385
|
+
if (handlers)
|
|
4386
|
+
for (let type in handlers) {
|
|
4387
|
+
let f = handlers[type];
|
|
4367
4388
|
if (f)
|
|
4368
4389
|
record(type).handlers.push(bindHandler(plugin.value, f));
|
|
4369
4390
|
}
|
|
4370
|
-
if (
|
|
4371
|
-
for (let type in
|
|
4372
|
-
let f =
|
|
4391
|
+
if (observers)
|
|
4392
|
+
for (let type in observers) {
|
|
4393
|
+
let f = observers[type];
|
|
4373
4394
|
if (f)
|
|
4374
4395
|
record(type).observers.push(bindHandler(plugin.value, f));
|
|
4375
4396
|
}
|
|
@@ -6616,6 +6637,21 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
6616
6637
|
backgroundColor: "#333338",
|
|
6617
6638
|
color: "white"
|
|
6618
6639
|
},
|
|
6640
|
+
".cm-dialog": {
|
|
6641
|
+
padding: "2px 19px 4px 6px",
|
|
6642
|
+
position: "relative",
|
|
6643
|
+
"& label": { fontSize: "80%" },
|
|
6644
|
+
},
|
|
6645
|
+
".cm-dialog-close": {
|
|
6646
|
+
position: "absolute",
|
|
6647
|
+
top: "3px",
|
|
6648
|
+
right: "4px",
|
|
6649
|
+
backgroundColor: "inherit",
|
|
6650
|
+
border: "none",
|
|
6651
|
+
font: "inherit",
|
|
6652
|
+
fontSize: "14px",
|
|
6653
|
+
padding: "0"
|
|
6654
|
+
},
|
|
6619
6655
|
".cm-tab": {
|
|
6620
6656
|
display: "inline-block",
|
|
6621
6657
|
overflow: "hidden",
|
|
@@ -7928,8 +7964,8 @@ class EditorView {
|
|
|
7928
7964
|
*/
|
|
7929
7965
|
plugin(plugin) {
|
|
7930
7966
|
let known = this.pluginMap.get(plugin);
|
|
7931
|
-
if (known === undefined || known && known.
|
|
7932
|
-
this.pluginMap.set(plugin, known = this.plugins.find(p => p.
|
|
7967
|
+
if (known === undefined || known && known.plugin != plugin)
|
|
7968
|
+
this.pluginMap.set(plugin, known = this.plugins.find(p => p.plugin == plugin) || null);
|
|
7933
7969
|
return known && known.update(this).value;
|
|
7934
7970
|
}
|
|
7935
7971
|
/**
|
|
@@ -10644,6 +10680,134 @@ const showPanel = state.Facet.define({
|
|
|
10644
10680
|
enables: panelPlugin
|
|
10645
10681
|
});
|
|
10646
10682
|
|
|
10683
|
+
/**
|
|
10684
|
+
Show a panel above or below the editor to show the user a message
|
|
10685
|
+
or prompt them for input. Returns an effect that can be dispatched
|
|
10686
|
+
to close the dialog, and a promise that resolves when the dialog
|
|
10687
|
+
is closed or a form inside of it is submitted.
|
|
10688
|
+
|
|
10689
|
+
You are encouraged, if your handling of the result of the promise
|
|
10690
|
+
dispatches a transaction, to include the `close` effect in it. If
|
|
10691
|
+
you don't, this function will automatically dispatch a separate
|
|
10692
|
+
transaction right after.
|
|
10693
|
+
*/
|
|
10694
|
+
function showDialog(view, config) {
|
|
10695
|
+
let resolve;
|
|
10696
|
+
let promise = new Promise(r => resolve = r);
|
|
10697
|
+
let panelCtor = (view) => createDialog(view, config, resolve);
|
|
10698
|
+
if (view.state.field(dialogField, false)) {
|
|
10699
|
+
view.dispatch({ effects: openDialogEffect.of(panelCtor) });
|
|
10700
|
+
}
|
|
10701
|
+
else {
|
|
10702
|
+
view.dispatch({ effects: state.StateEffect.appendConfig.of(dialogField.init(() => [panelCtor])) });
|
|
10703
|
+
}
|
|
10704
|
+
let close = closeDialogEffect.of(panelCtor);
|
|
10705
|
+
return { close, result: promise.then(form => {
|
|
10706
|
+
let queue = view.win.queueMicrotask || ((f) => view.win.setTimeout(f, 10));
|
|
10707
|
+
queue(() => {
|
|
10708
|
+
if (view.state.field(dialogField).indexOf(panelCtor) > -1)
|
|
10709
|
+
view.dispatch({ effects: close });
|
|
10710
|
+
});
|
|
10711
|
+
return form;
|
|
10712
|
+
}) };
|
|
10713
|
+
}
|
|
10714
|
+
/**
|
|
10715
|
+
Find the [`Panel`](https://codemirror.net/6/docs/ref/#view.Panel) for an open dialog, using a class
|
|
10716
|
+
name as identifier.
|
|
10717
|
+
*/
|
|
10718
|
+
function getDialog(view, className) {
|
|
10719
|
+
let dialogs = view.state.field(dialogField, false) || [];
|
|
10720
|
+
for (let open of dialogs) {
|
|
10721
|
+
let panel = getPanel(view, open);
|
|
10722
|
+
if (panel && panel.dom.classList.contains(className))
|
|
10723
|
+
return panel;
|
|
10724
|
+
}
|
|
10725
|
+
return null;
|
|
10726
|
+
}
|
|
10727
|
+
const dialogField = state.StateField.define({
|
|
10728
|
+
create() { return []; },
|
|
10729
|
+
update(dialogs, tr) {
|
|
10730
|
+
for (let e of tr.effects) {
|
|
10731
|
+
if (e.is(openDialogEffect))
|
|
10732
|
+
dialogs = [e.value].concat(dialogs);
|
|
10733
|
+
else if (e.is(closeDialogEffect))
|
|
10734
|
+
dialogs = dialogs.filter(d => d != e.value);
|
|
10735
|
+
}
|
|
10736
|
+
return dialogs;
|
|
10737
|
+
},
|
|
10738
|
+
provide: f => showPanel.computeN([f], state => state.field(f))
|
|
10739
|
+
});
|
|
10740
|
+
const openDialogEffect = state.StateEffect.define();
|
|
10741
|
+
const closeDialogEffect = state.StateEffect.define();
|
|
10742
|
+
function createDialog(view, config, result) {
|
|
10743
|
+
let content = config.content ? config.content(view, () => done(null)) : null;
|
|
10744
|
+
if (!content) {
|
|
10745
|
+
content = elt("form");
|
|
10746
|
+
if (config.input) {
|
|
10747
|
+
let input = elt("input", config.input);
|
|
10748
|
+
if (/^(text|password|number|email|tel|url)$/.test(input.type))
|
|
10749
|
+
input.classList.add("cm-textfield");
|
|
10750
|
+
if (!input.name)
|
|
10751
|
+
input.name = "input";
|
|
10752
|
+
content.appendChild(elt("label", (config.label || "") + ": ", input));
|
|
10753
|
+
}
|
|
10754
|
+
else {
|
|
10755
|
+
content.appendChild(document.createTextNode(config.label || ""));
|
|
10756
|
+
}
|
|
10757
|
+
content.appendChild(document.createTextNode(" "));
|
|
10758
|
+
content.appendChild(elt("button", { class: "cm-button", type: "submit" }, config.submitLabel || "OK"));
|
|
10759
|
+
}
|
|
10760
|
+
let forms = content.nodeName == "FORM" ? [content] : content.querySelectorAll("form");
|
|
10761
|
+
for (let i = 0; i < forms.length; i++) {
|
|
10762
|
+
let form = forms[i];
|
|
10763
|
+
form.addEventListener("keydown", (event) => {
|
|
10764
|
+
if (event.keyCode == 27) { // Escape
|
|
10765
|
+
event.preventDefault();
|
|
10766
|
+
done(null);
|
|
10767
|
+
}
|
|
10768
|
+
else if (event.keyCode == 13) { // Enter
|
|
10769
|
+
event.preventDefault();
|
|
10770
|
+
done(form);
|
|
10771
|
+
}
|
|
10772
|
+
});
|
|
10773
|
+
form.addEventListener("submit", (event) => {
|
|
10774
|
+
event.preventDefault();
|
|
10775
|
+
done(form);
|
|
10776
|
+
});
|
|
10777
|
+
}
|
|
10778
|
+
let panel = elt("div", content, elt("button", {
|
|
10779
|
+
onclick: () => done(null),
|
|
10780
|
+
"aria-label": view.state.phrase("close"),
|
|
10781
|
+
class: "cm-dialog-close",
|
|
10782
|
+
type: "button"
|
|
10783
|
+
}, ["×"]));
|
|
10784
|
+
if (config.class)
|
|
10785
|
+
panel.className = config.class;
|
|
10786
|
+
panel.classList.add("cm-dialog");
|
|
10787
|
+
function done(form) {
|
|
10788
|
+
if (panel.contains(panel.ownerDocument.activeElement))
|
|
10789
|
+
view.focus();
|
|
10790
|
+
result(form);
|
|
10791
|
+
}
|
|
10792
|
+
return {
|
|
10793
|
+
dom: panel,
|
|
10794
|
+
top: config.top,
|
|
10795
|
+
mount: () => {
|
|
10796
|
+
if (config.focus) {
|
|
10797
|
+
let focus;
|
|
10798
|
+
if (typeof config.focus == "string")
|
|
10799
|
+
focus = content.querySelector(config.focus);
|
|
10800
|
+
else
|
|
10801
|
+
focus = content.querySelector("input") || content.querySelector("button");
|
|
10802
|
+
if (focus && "select" in focus)
|
|
10803
|
+
focus.select();
|
|
10804
|
+
else if (focus && "focus" in focus)
|
|
10805
|
+
focus.focus();
|
|
10806
|
+
}
|
|
10807
|
+
}
|
|
10808
|
+
};
|
|
10809
|
+
}
|
|
10810
|
+
|
|
10647
10811
|
/**
|
|
10648
10812
|
A gutter marker represents a bit of information attached to a line
|
|
10649
10813
|
in a specific gutter. Your own custom markers have to extend this
|
|
@@ -10702,7 +10866,7 @@ Define an editor gutter. The order in which the gutters appear is
|
|
|
10702
10866
|
determined by their extension priority.
|
|
10703
10867
|
*/
|
|
10704
10868
|
function gutter(config) {
|
|
10705
|
-
return [gutters(), activeGutters.of(
|
|
10869
|
+
return [gutters(), activeGutters.of({ ...defaults, ...config })];
|
|
10706
10870
|
}
|
|
10707
10871
|
const unfixGutters = state.Facet.define({
|
|
10708
10872
|
combine: values => values.some(x => x)
|
|
@@ -11194,6 +11358,7 @@ exports.closeHoverTooltips = closeHoverTooltips;
|
|
|
11194
11358
|
exports.crosshairCursor = crosshairCursor;
|
|
11195
11359
|
exports.drawSelection = drawSelection;
|
|
11196
11360
|
exports.dropCursor = dropCursor;
|
|
11361
|
+
exports.getDialog = getDialog;
|
|
11197
11362
|
exports.getDrawSelectionConfig = getDrawSelectionConfig;
|
|
11198
11363
|
exports.getPanel = getPanel;
|
|
11199
11364
|
exports.getTooltip = getTooltip;
|
|
@@ -11220,6 +11385,7 @@ exports.rectangularSelection = rectangularSelection;
|
|
|
11220
11385
|
exports.repositionTooltips = repositionTooltips;
|
|
11221
11386
|
exports.runScopeHandlers = runScopeHandlers;
|
|
11222
11387
|
exports.scrollPastEnd = scrollPastEnd;
|
|
11388
|
+
exports.showDialog = showDialog;
|
|
11223
11389
|
exports.showPanel = showPanel;
|
|
11224
11390
|
exports.showTooltip = showTooltip;
|
|
11225
11391
|
exports.tooltips = tooltips;
|
package/dist/index.d.cts
CHANGED
|
@@ -438,7 +438,7 @@ interface PluginSpec<V extends PluginValue> {
|
|
|
438
438
|
Specify that the plugin provides additional extensions when
|
|
439
439
|
added to an editor configuration.
|
|
440
440
|
*/
|
|
441
|
-
provide?: (plugin: ViewPlugin<V>) => Extension;
|
|
441
|
+
provide?: (plugin: ViewPlugin<V, any>) => Extension;
|
|
442
442
|
/**
|
|
443
443
|
Allow the plugin to provide decorations. When given, this should
|
|
444
444
|
be a function that take the plugin value and return a
|
|
@@ -451,26 +451,36 @@ interface PluginSpec<V extends PluginValue> {
|
|
|
451
451
|
/**
|
|
452
452
|
View plugins associate stateful values with a view. They can
|
|
453
453
|
influence the way the content is drawn, and are notified of things
|
|
454
|
-
that happen in the view.
|
|
454
|
+
that happen in the view. They optionally take an argument, in
|
|
455
|
+
which case you need to call [`of`](https://codemirror.net/6/docs/ref/#view.ViewPlugin.of) to create
|
|
456
|
+
an extension for the plugin. When the argument type is undefined,
|
|
457
|
+
you can use the plugin instance as an extension directly.
|
|
455
458
|
*/
|
|
456
|
-
declare class ViewPlugin<V extends PluginValue> {
|
|
459
|
+
declare class ViewPlugin<V extends PluginValue, Arg = undefined> {
|
|
457
460
|
/**
|
|
458
|
-
|
|
461
|
+
When `Arg` is undefined, instances of this class act as
|
|
462
|
+
extensions. Otherwise, you have to call `of` to create an
|
|
463
|
+
extension value.
|
|
459
464
|
*/
|
|
460
|
-
extension: Extension;
|
|
465
|
+
extension: Arg extends undefined ? Extension : null;
|
|
466
|
+
private baseExtensions;
|
|
461
467
|
private constructor();
|
|
462
468
|
/**
|
|
469
|
+
Create an extension for this plugin with the given argument.
|
|
470
|
+
*/
|
|
471
|
+
of(arg: Arg): Extension;
|
|
472
|
+
/**
|
|
463
473
|
Define a plugin from a constructor function that creates the
|
|
464
474
|
plugin's value, given an editor view.
|
|
465
475
|
*/
|
|
466
|
-
static define<V extends PluginValue>(create: (view: EditorView) => V, spec?: PluginSpec<V>): ViewPlugin<V>;
|
|
476
|
+
static define<V extends PluginValue, Arg = undefined>(create: (view: EditorView, arg: Arg) => V, spec?: PluginSpec<V>): ViewPlugin<V, Arg>;
|
|
467
477
|
/**
|
|
468
478
|
Create a plugin for a class whose constructor takes a single
|
|
469
479
|
editor view as argument.
|
|
470
480
|
*/
|
|
471
|
-
static fromClass<V extends PluginValue>(cls: {
|
|
472
|
-
new (view: EditorView): V;
|
|
473
|
-
}, spec?: PluginSpec<V>): ViewPlugin<V>;
|
|
481
|
+
static fromClass<V extends PluginValue, Arg = undefined>(cls: {
|
|
482
|
+
new (view: EditorView, arg: Arg): V;
|
|
483
|
+
}, spec?: PluginSpec<V>): ViewPlugin<V, Arg>;
|
|
474
484
|
}
|
|
475
485
|
interface MeasureRequest<T> {
|
|
476
486
|
/**
|
|
@@ -829,7 +839,7 @@ declare class EditorView {
|
|
|
829
839
|
know you registered a given plugin, it is recommended to check
|
|
830
840
|
the return value of this method.
|
|
831
841
|
*/
|
|
832
|
-
plugin<T extends PluginValue>(plugin: ViewPlugin<T>): T | null;
|
|
842
|
+
plugin<T extends PluginValue>(plugin: ViewPlugin<T, any>): T | null;
|
|
833
843
|
/**
|
|
834
844
|
The top position of the document, in screen coordinates. This
|
|
835
845
|
may be negative when the editor is scrolled down. Points
|
|
@@ -2078,6 +2088,70 @@ constructor is no longer provided.) Values of `null` are ignored.
|
|
|
2078
2088
|
*/
|
|
2079
2089
|
declare const showPanel: Facet<PanelConstructor | null, readonly (PanelConstructor | null)[]>;
|
|
2080
2090
|
|
|
2091
|
+
type DialogConfig = {
|
|
2092
|
+
/**
|
|
2093
|
+
A function to render the content of the dialog. The result
|
|
2094
|
+
should contain at least one `<form>` element. Submit handlers a
|
|
2095
|
+
handler for the Escape key will be added to the form.
|
|
2096
|
+
|
|
2097
|
+
If this is not given, the `label`, `input`, and `submitLabel`
|
|
2098
|
+
fields will be used to create a simple form for you.
|
|
2099
|
+
*/
|
|
2100
|
+
content?: (view: EditorView, close: () => void) => HTMLElement;
|
|
2101
|
+
/**
|
|
2102
|
+
When `content` isn't given, this provides the text shown in the
|
|
2103
|
+
dialog.
|
|
2104
|
+
*/
|
|
2105
|
+
label?: string;
|
|
2106
|
+
/**
|
|
2107
|
+
The attributes for an input element shown next to the label. If
|
|
2108
|
+
not given, no input element is added.
|
|
2109
|
+
*/
|
|
2110
|
+
input?: {
|
|
2111
|
+
[attr: string]: string;
|
|
2112
|
+
};
|
|
2113
|
+
/**
|
|
2114
|
+
The label for the button that submits the form. Defaults to
|
|
2115
|
+
`"OK"`.
|
|
2116
|
+
*/
|
|
2117
|
+
submitLabel?: string;
|
|
2118
|
+
/**
|
|
2119
|
+
Extra classes to add to the panel.
|
|
2120
|
+
*/
|
|
2121
|
+
class?: string;
|
|
2122
|
+
/**
|
|
2123
|
+
A query selector to find the field that should be focused when
|
|
2124
|
+
the dialog is opened. When set to true, this picks the first
|
|
2125
|
+
`<input>` or `<button>` element in the form.
|
|
2126
|
+
*/
|
|
2127
|
+
focus?: string | boolean;
|
|
2128
|
+
/**
|
|
2129
|
+
By default, dialogs are shown below the editor. Set this to
|
|
2130
|
+
`true` to have it show up at the top.
|
|
2131
|
+
*/
|
|
2132
|
+
top?: boolean;
|
|
2133
|
+
};
|
|
2134
|
+
/**
|
|
2135
|
+
Show a panel above or below the editor to show the user a message
|
|
2136
|
+
or prompt them for input. Returns an effect that can be dispatched
|
|
2137
|
+
to close the dialog, and a promise that resolves when the dialog
|
|
2138
|
+
is closed or a form inside of it is submitted.
|
|
2139
|
+
|
|
2140
|
+
You are encouraged, if your handling of the result of the promise
|
|
2141
|
+
dispatches a transaction, to include the `close` effect in it. If
|
|
2142
|
+
you don't, this function will automatically dispatch a separate
|
|
2143
|
+
transaction right after.
|
|
2144
|
+
*/
|
|
2145
|
+
declare function showDialog(view: EditorView, config: DialogConfig): {
|
|
2146
|
+
close: StateEffect<unknown>;
|
|
2147
|
+
result: Promise<HTMLFormElement | null>;
|
|
2148
|
+
};
|
|
2149
|
+
/**
|
|
2150
|
+
Find the [`Panel`](https://codemirror.net/6/docs/ref/#view.Panel) for an open dialog, using a class
|
|
2151
|
+
name as identifier.
|
|
2152
|
+
*/
|
|
2153
|
+
declare function getDialog(view: EditorView, className: string): Panel | null;
|
|
2154
|
+
|
|
2081
2155
|
/**
|
|
2082
2156
|
A gutter marker represents a bit of information attached to a line
|
|
2083
2157
|
in a specific gutter. Your own custom markers have to extend this
|
|
@@ -2223,4 +2297,4 @@ trailing whitespace.
|
|
|
2223
2297
|
*/
|
|
2224
2298
|
declare function highlightTrailingWhitespace(): Extension;
|
|
2225
2299
|
|
|
2226
|
-
export { BidiSpan, BlockInfo, BlockType, type Command, type DOMEventHandlers, type DOMEventMap, Decoration, type DecorationSet, Direction, EditorView, type EditorViewConfig, GutterMarker, type HoverTooltipSource, type KeyBinding, type LayerMarker, MatchDecorator, type MouseSelectionStyle, type Panel, type PanelConstructor, type PluginSpec, type PluginValue, type Rect, RectangleMarker, type Tooltip, type TooltipView, ViewPlugin, ViewUpdate, WidgetType, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getDrawSelectionConfig, getPanel, getTooltip, gutter, gutterLineClass, gutterWidgetClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, highlightTrailingWhitespace, highlightWhitespace, hoverTooltip, keymap, layer, lineNumberMarkers, lineNumberWidgetMarker, lineNumbers, logException, panels, placeholder, rectangularSelection, repositionTooltips, runScopeHandlers, scrollPastEnd, showPanel, showTooltip, tooltips };
|
|
2300
|
+
export { BidiSpan, BlockInfo, BlockType, type Command, type DOMEventHandlers, type DOMEventMap, Decoration, type DecorationSet, Direction, EditorView, type EditorViewConfig, GutterMarker, type HoverTooltipSource, type KeyBinding, type LayerMarker, MatchDecorator, type MouseSelectionStyle, type Panel, type PanelConstructor, type PluginSpec, type PluginValue, type Rect, RectangleMarker, type Tooltip, type TooltipView, ViewPlugin, ViewUpdate, WidgetType, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getDialog, getDrawSelectionConfig, getPanel, getTooltip, gutter, gutterLineClass, gutterWidgetClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, highlightTrailingWhitespace, highlightWhitespace, hoverTooltip, keymap, layer, lineNumberMarkers, lineNumberWidgetMarker, lineNumbers, logException, panels, placeholder, rectangularSelection, repositionTooltips, runScopeHandlers, scrollPastEnd, showDialog, showPanel, showTooltip, tooltips };
|
package/dist/index.d.ts
CHANGED
|
@@ -438,7 +438,7 @@ interface PluginSpec<V extends PluginValue> {
|
|
|
438
438
|
Specify that the plugin provides additional extensions when
|
|
439
439
|
added to an editor configuration.
|
|
440
440
|
*/
|
|
441
|
-
provide?: (plugin: ViewPlugin<V>) => Extension;
|
|
441
|
+
provide?: (plugin: ViewPlugin<V, any>) => Extension;
|
|
442
442
|
/**
|
|
443
443
|
Allow the plugin to provide decorations. When given, this should
|
|
444
444
|
be a function that take the plugin value and return a
|
|
@@ -451,26 +451,36 @@ interface PluginSpec<V extends PluginValue> {
|
|
|
451
451
|
/**
|
|
452
452
|
View plugins associate stateful values with a view. They can
|
|
453
453
|
influence the way the content is drawn, and are notified of things
|
|
454
|
-
that happen in the view.
|
|
454
|
+
that happen in the view. They optionally take an argument, in
|
|
455
|
+
which case you need to call [`of`](https://codemirror.net/6/docs/ref/#view.ViewPlugin.of) to create
|
|
456
|
+
an extension for the plugin. When the argument type is undefined,
|
|
457
|
+
you can use the plugin instance as an extension directly.
|
|
455
458
|
*/
|
|
456
|
-
declare class ViewPlugin<V extends PluginValue> {
|
|
459
|
+
declare class ViewPlugin<V extends PluginValue, Arg = undefined> {
|
|
457
460
|
/**
|
|
458
|
-
|
|
461
|
+
When `Arg` is undefined, instances of this class act as
|
|
462
|
+
extensions. Otherwise, you have to call `of` to create an
|
|
463
|
+
extension value.
|
|
459
464
|
*/
|
|
460
|
-
extension: Extension;
|
|
465
|
+
extension: Arg extends undefined ? Extension : null;
|
|
466
|
+
private baseExtensions;
|
|
461
467
|
private constructor();
|
|
462
468
|
/**
|
|
469
|
+
Create an extension for this plugin with the given argument.
|
|
470
|
+
*/
|
|
471
|
+
of(arg: Arg): Extension;
|
|
472
|
+
/**
|
|
463
473
|
Define a plugin from a constructor function that creates the
|
|
464
474
|
plugin's value, given an editor view.
|
|
465
475
|
*/
|
|
466
|
-
static define<V extends PluginValue>(create: (view: EditorView) => V, spec?: PluginSpec<V>): ViewPlugin<V>;
|
|
476
|
+
static define<V extends PluginValue, Arg = undefined>(create: (view: EditorView, arg: Arg) => V, spec?: PluginSpec<V>): ViewPlugin<V, Arg>;
|
|
467
477
|
/**
|
|
468
478
|
Create a plugin for a class whose constructor takes a single
|
|
469
479
|
editor view as argument.
|
|
470
480
|
*/
|
|
471
|
-
static fromClass<V extends PluginValue>(cls: {
|
|
472
|
-
new (view: EditorView): V;
|
|
473
|
-
}, spec?: PluginSpec<V>): ViewPlugin<V>;
|
|
481
|
+
static fromClass<V extends PluginValue, Arg = undefined>(cls: {
|
|
482
|
+
new (view: EditorView, arg: Arg): V;
|
|
483
|
+
}, spec?: PluginSpec<V>): ViewPlugin<V, Arg>;
|
|
474
484
|
}
|
|
475
485
|
interface MeasureRequest<T> {
|
|
476
486
|
/**
|
|
@@ -829,7 +839,7 @@ declare class EditorView {
|
|
|
829
839
|
know you registered a given plugin, it is recommended to check
|
|
830
840
|
the return value of this method.
|
|
831
841
|
*/
|
|
832
|
-
plugin<T extends PluginValue>(plugin: ViewPlugin<T>): T | null;
|
|
842
|
+
plugin<T extends PluginValue>(plugin: ViewPlugin<T, any>): T | null;
|
|
833
843
|
/**
|
|
834
844
|
The top position of the document, in screen coordinates. This
|
|
835
845
|
may be negative when the editor is scrolled down. Points
|
|
@@ -2078,6 +2088,70 @@ constructor is no longer provided.) Values of `null` are ignored.
|
|
|
2078
2088
|
*/
|
|
2079
2089
|
declare const showPanel: Facet<PanelConstructor | null, readonly (PanelConstructor | null)[]>;
|
|
2080
2090
|
|
|
2091
|
+
type DialogConfig = {
|
|
2092
|
+
/**
|
|
2093
|
+
A function to render the content of the dialog. The result
|
|
2094
|
+
should contain at least one `<form>` element. Submit handlers a
|
|
2095
|
+
handler for the Escape key will be added to the form.
|
|
2096
|
+
|
|
2097
|
+
If this is not given, the `label`, `input`, and `submitLabel`
|
|
2098
|
+
fields will be used to create a simple form for you.
|
|
2099
|
+
*/
|
|
2100
|
+
content?: (view: EditorView, close: () => void) => HTMLElement;
|
|
2101
|
+
/**
|
|
2102
|
+
When `content` isn't given, this provides the text shown in the
|
|
2103
|
+
dialog.
|
|
2104
|
+
*/
|
|
2105
|
+
label?: string;
|
|
2106
|
+
/**
|
|
2107
|
+
The attributes for an input element shown next to the label. If
|
|
2108
|
+
not given, no input element is added.
|
|
2109
|
+
*/
|
|
2110
|
+
input?: {
|
|
2111
|
+
[attr: string]: string;
|
|
2112
|
+
};
|
|
2113
|
+
/**
|
|
2114
|
+
The label for the button that submits the form. Defaults to
|
|
2115
|
+
`"OK"`.
|
|
2116
|
+
*/
|
|
2117
|
+
submitLabel?: string;
|
|
2118
|
+
/**
|
|
2119
|
+
Extra classes to add to the panel.
|
|
2120
|
+
*/
|
|
2121
|
+
class?: string;
|
|
2122
|
+
/**
|
|
2123
|
+
A query selector to find the field that should be focused when
|
|
2124
|
+
the dialog is opened. When set to true, this picks the first
|
|
2125
|
+
`<input>` or `<button>` element in the form.
|
|
2126
|
+
*/
|
|
2127
|
+
focus?: string | boolean;
|
|
2128
|
+
/**
|
|
2129
|
+
By default, dialogs are shown below the editor. Set this to
|
|
2130
|
+
`true` to have it show up at the top.
|
|
2131
|
+
*/
|
|
2132
|
+
top?: boolean;
|
|
2133
|
+
};
|
|
2134
|
+
/**
|
|
2135
|
+
Show a panel above or below the editor to show the user a message
|
|
2136
|
+
or prompt them for input. Returns an effect that can be dispatched
|
|
2137
|
+
to close the dialog, and a promise that resolves when the dialog
|
|
2138
|
+
is closed or a form inside of it is submitted.
|
|
2139
|
+
|
|
2140
|
+
You are encouraged, if your handling of the result of the promise
|
|
2141
|
+
dispatches a transaction, to include the `close` effect in it. If
|
|
2142
|
+
you don't, this function will automatically dispatch a separate
|
|
2143
|
+
transaction right after.
|
|
2144
|
+
*/
|
|
2145
|
+
declare function showDialog(view: EditorView, config: DialogConfig): {
|
|
2146
|
+
close: StateEffect<unknown>;
|
|
2147
|
+
result: Promise<HTMLFormElement | null>;
|
|
2148
|
+
};
|
|
2149
|
+
/**
|
|
2150
|
+
Find the [`Panel`](https://codemirror.net/6/docs/ref/#view.Panel) for an open dialog, using a class
|
|
2151
|
+
name as identifier.
|
|
2152
|
+
*/
|
|
2153
|
+
declare function getDialog(view: EditorView, className: string): Panel | null;
|
|
2154
|
+
|
|
2081
2155
|
/**
|
|
2082
2156
|
A gutter marker represents a bit of information attached to a line
|
|
2083
2157
|
in a specific gutter. Your own custom markers have to extend this
|
|
@@ -2223,4 +2297,4 @@ trailing whitespace.
|
|
|
2223
2297
|
*/
|
|
2224
2298
|
declare function highlightTrailingWhitespace(): Extension;
|
|
2225
2299
|
|
|
2226
|
-
export { BidiSpan, BlockInfo, BlockType, type Command, type DOMEventHandlers, type DOMEventMap, Decoration, type DecorationSet, Direction, EditorView, type EditorViewConfig, GutterMarker, type HoverTooltipSource, type KeyBinding, type LayerMarker, MatchDecorator, type MouseSelectionStyle, type Panel, type PanelConstructor, type PluginSpec, type PluginValue, type Rect, RectangleMarker, type Tooltip, type TooltipView, ViewPlugin, ViewUpdate, WidgetType, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getDrawSelectionConfig, getPanel, getTooltip, gutter, gutterLineClass, gutterWidgetClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, highlightTrailingWhitespace, highlightWhitespace, hoverTooltip, keymap, layer, lineNumberMarkers, lineNumberWidgetMarker, lineNumbers, logException, panels, placeholder, rectangularSelection, repositionTooltips, runScopeHandlers, scrollPastEnd, showPanel, showTooltip, tooltips };
|
|
2300
|
+
export { BidiSpan, BlockInfo, BlockType, type Command, type DOMEventHandlers, type DOMEventMap, Decoration, type DecorationSet, Direction, EditorView, type EditorViewConfig, GutterMarker, type HoverTooltipSource, type KeyBinding, type LayerMarker, MatchDecorator, type MouseSelectionStyle, type Panel, type PanelConstructor, type PluginSpec, type PluginValue, type Rect, RectangleMarker, type Tooltip, type TooltipView, ViewPlugin, ViewUpdate, WidgetType, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getDialog, getDrawSelectionConfig, getPanel, getTooltip, gutter, gutterLineClass, gutterWidgetClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, highlightTrailingWhitespace, highlightWhitespace, hoverTooltip, keymap, layer, lineNumberMarkers, lineNumberWidgetMarker, lineNumbers, logException, panels, placeholder, rectangularSelection, repositionTooltips, runScopeHandlers, scrollPastEnd, showDialog, showPanel, showTooltip, tooltips };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Text, RangeSet, MapMode, RangeValue, findClusterBreak, EditorSelection, Facet, StateEffect, ChangeSet, findColumn, CharCategory, EditorState, Annotation, 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
|
+
import elt from 'crelt';
|
|
4
5
|
|
|
5
6
|
function getSelection(root) {
|
|
6
7
|
let target;
|
|
@@ -2426,11 +2427,23 @@ function logException(state, exception, context) {
|
|
|
2426
2427
|
}
|
|
2427
2428
|
const editable = /*@__PURE__*/Facet.define({ combine: values => values.length ? values[0] : true });
|
|
2428
2429
|
let nextPluginID = 0;
|
|
2429
|
-
const viewPlugin = /*@__PURE__*/Facet.define(
|
|
2430
|
+
const viewPlugin = /*@__PURE__*/Facet.define({
|
|
2431
|
+
combine(plugins) {
|
|
2432
|
+
return plugins.filter((p, i) => {
|
|
2433
|
+
for (let j = 0; j < i; j++)
|
|
2434
|
+
if (plugins[j].plugin == p.plugin)
|
|
2435
|
+
return false;
|
|
2436
|
+
return true;
|
|
2437
|
+
});
|
|
2438
|
+
}
|
|
2439
|
+
});
|
|
2430
2440
|
/**
|
|
2431
2441
|
View plugins associate stateful values with a view. They can
|
|
2432
2442
|
influence the way the content is drawn, and are notified of things
|
|
2433
|
-
that happen in the view.
|
|
2443
|
+
that happen in the view. They optionally take an argument, in
|
|
2444
|
+
which case you need to call [`of`](https://codemirror.net/6/docs/ref/#view.ViewPlugin.of) to create
|
|
2445
|
+
an extension for the plugin. When the argument type is undefined,
|
|
2446
|
+
you can use the plugin instance as an extension directly.
|
|
2434
2447
|
*/
|
|
2435
2448
|
class ViewPlugin {
|
|
2436
2449
|
constructor(
|
|
@@ -2454,7 +2467,14 @@ class ViewPlugin {
|
|
|
2454
2467
|
this.create = create;
|
|
2455
2468
|
this.domEventHandlers = domEventHandlers;
|
|
2456
2469
|
this.domEventObservers = domEventObservers;
|
|
2457
|
-
this.
|
|
2470
|
+
this.baseExtensions = buildExtensions(this);
|
|
2471
|
+
this.extension = this.baseExtensions.concat(viewPlugin.of({ plugin: this, arg: undefined }));
|
|
2472
|
+
}
|
|
2473
|
+
/**
|
|
2474
|
+
Create an extension for this plugin with the given argument.
|
|
2475
|
+
*/
|
|
2476
|
+
of(arg) {
|
|
2477
|
+
return this.baseExtensions.concat(viewPlugin.of({ plugin: this, arg }));
|
|
2458
2478
|
}
|
|
2459
2479
|
/**
|
|
2460
2480
|
Define a plugin from a constructor function that creates the
|
|
@@ -2463,7 +2483,7 @@ class ViewPlugin {
|
|
|
2463
2483
|
static define(create, spec) {
|
|
2464
2484
|
const { eventHandlers, eventObservers, provide, decorations: deco } = spec || {};
|
|
2465
2485
|
return new ViewPlugin(nextPluginID++, create, eventHandlers, eventObservers, plugin => {
|
|
2466
|
-
let ext = [
|
|
2486
|
+
let ext = [];
|
|
2467
2487
|
if (deco)
|
|
2468
2488
|
ext.push(decorations.of(view => {
|
|
2469
2489
|
let pluginInst = view.plugin(plugin);
|
|
@@ -2479,7 +2499,7 @@ class ViewPlugin {
|
|
|
2479
2499
|
editor view as argument.
|
|
2480
2500
|
*/
|
|
2481
2501
|
static fromClass(cls, spec) {
|
|
2482
|
-
return ViewPlugin.define(view => new cls(view), spec);
|
|
2502
|
+
return ViewPlugin.define((view, arg) => new cls(view, arg), spec);
|
|
2483
2503
|
}
|
|
2484
2504
|
}
|
|
2485
2505
|
class PluginInstance {
|
|
@@ -2487,18 +2507,19 @@ class PluginInstance {
|
|
|
2487
2507
|
this.spec = spec;
|
|
2488
2508
|
// When starting an update, all plugins have this field set to the
|
|
2489
2509
|
// update object, indicating they need to be updated. When finished
|
|
2490
|
-
// updating, it is set to `
|
|
2510
|
+
// updating, it is set to `null`. Retrieving a plugin that needs to
|
|
2491
2511
|
// be updated with `view.plugin` forces an eager update.
|
|
2492
2512
|
this.mustUpdate = null;
|
|
2493
2513
|
// This is null when the plugin is initially created, but
|
|
2494
2514
|
// initialized on the first update.
|
|
2495
2515
|
this.value = null;
|
|
2496
2516
|
}
|
|
2517
|
+
get plugin() { return this.spec && this.spec.plugin; }
|
|
2497
2518
|
update(view) {
|
|
2498
2519
|
if (!this.value) {
|
|
2499
2520
|
if (this.spec) {
|
|
2500
2521
|
try {
|
|
2501
|
-
this.value = this.spec.create(view);
|
|
2522
|
+
this.value = this.spec.plugin.create(view, this.spec.arg);
|
|
2502
2523
|
}
|
|
2503
2524
|
catch (e) {
|
|
2504
2525
|
logException(view.state, e, "CodeMirror plugin crashed");
|
|
@@ -4356,16 +4377,16 @@ function computeHandlers(plugins) {
|
|
|
4356
4377
|
return result[type] || (result[type] = { observers: [], handlers: [] });
|
|
4357
4378
|
}
|
|
4358
4379
|
for (let plugin of plugins) {
|
|
4359
|
-
let spec = plugin.spec;
|
|
4360
|
-
if (
|
|
4361
|
-
for (let type in
|
|
4362
|
-
let f =
|
|
4380
|
+
let spec = plugin.spec, handlers = spec && spec.plugin.domEventHandlers, observers = spec && spec.plugin.domEventObservers;
|
|
4381
|
+
if (handlers)
|
|
4382
|
+
for (let type in handlers) {
|
|
4383
|
+
let f = handlers[type];
|
|
4363
4384
|
if (f)
|
|
4364
4385
|
record(type).handlers.push(bindHandler(plugin.value, f));
|
|
4365
4386
|
}
|
|
4366
|
-
if (
|
|
4367
|
-
for (let type in
|
|
4368
|
-
let f =
|
|
4387
|
+
if (observers)
|
|
4388
|
+
for (let type in observers) {
|
|
4389
|
+
let f = observers[type];
|
|
4369
4390
|
if (f)
|
|
4370
4391
|
record(type).observers.push(bindHandler(plugin.value, f));
|
|
4371
4392
|
}
|
|
@@ -6611,6 +6632,21 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
6611
6632
|
backgroundColor: "#333338",
|
|
6612
6633
|
color: "white"
|
|
6613
6634
|
},
|
|
6635
|
+
".cm-dialog": {
|
|
6636
|
+
padding: "2px 19px 4px 6px",
|
|
6637
|
+
position: "relative",
|
|
6638
|
+
"& label": { fontSize: "80%" },
|
|
6639
|
+
},
|
|
6640
|
+
".cm-dialog-close": {
|
|
6641
|
+
position: "absolute",
|
|
6642
|
+
top: "3px",
|
|
6643
|
+
right: "4px",
|
|
6644
|
+
backgroundColor: "inherit",
|
|
6645
|
+
border: "none",
|
|
6646
|
+
font: "inherit",
|
|
6647
|
+
fontSize: "14px",
|
|
6648
|
+
padding: "0"
|
|
6649
|
+
},
|
|
6614
6650
|
".cm-tab": {
|
|
6615
6651
|
display: "inline-block",
|
|
6616
6652
|
overflow: "hidden",
|
|
@@ -7923,8 +7959,8 @@ class EditorView {
|
|
|
7923
7959
|
*/
|
|
7924
7960
|
plugin(plugin) {
|
|
7925
7961
|
let known = this.pluginMap.get(plugin);
|
|
7926
|
-
if (known === undefined || known && known.
|
|
7927
|
-
this.pluginMap.set(plugin, known = this.plugins.find(p => p.
|
|
7962
|
+
if (known === undefined || known && known.plugin != plugin)
|
|
7963
|
+
this.pluginMap.set(plugin, known = this.plugins.find(p => p.plugin == plugin) || null);
|
|
7928
7964
|
return known && known.update(this).value;
|
|
7929
7965
|
}
|
|
7930
7966
|
/**
|
|
@@ -10639,6 +10675,134 @@ const showPanel = /*@__PURE__*/Facet.define({
|
|
|
10639
10675
|
enables: panelPlugin
|
|
10640
10676
|
});
|
|
10641
10677
|
|
|
10678
|
+
/**
|
|
10679
|
+
Show a panel above or below the editor to show the user a message
|
|
10680
|
+
or prompt them for input. Returns an effect that can be dispatched
|
|
10681
|
+
to close the dialog, and a promise that resolves when the dialog
|
|
10682
|
+
is closed or a form inside of it is submitted.
|
|
10683
|
+
|
|
10684
|
+
You are encouraged, if your handling of the result of the promise
|
|
10685
|
+
dispatches a transaction, to include the `close` effect in it. If
|
|
10686
|
+
you don't, this function will automatically dispatch a separate
|
|
10687
|
+
transaction right after.
|
|
10688
|
+
*/
|
|
10689
|
+
function showDialog(view, config) {
|
|
10690
|
+
let resolve;
|
|
10691
|
+
let promise = new Promise(r => resolve = r);
|
|
10692
|
+
let panelCtor = (view) => createDialog(view, config, resolve);
|
|
10693
|
+
if (view.state.field(dialogField, false)) {
|
|
10694
|
+
view.dispatch({ effects: openDialogEffect.of(panelCtor) });
|
|
10695
|
+
}
|
|
10696
|
+
else {
|
|
10697
|
+
view.dispatch({ effects: StateEffect.appendConfig.of(dialogField.init(() => [panelCtor])) });
|
|
10698
|
+
}
|
|
10699
|
+
let close = closeDialogEffect.of(panelCtor);
|
|
10700
|
+
return { close, result: promise.then(form => {
|
|
10701
|
+
let queue = view.win.queueMicrotask || ((f) => view.win.setTimeout(f, 10));
|
|
10702
|
+
queue(() => {
|
|
10703
|
+
if (view.state.field(dialogField).indexOf(panelCtor) > -1)
|
|
10704
|
+
view.dispatch({ effects: close });
|
|
10705
|
+
});
|
|
10706
|
+
return form;
|
|
10707
|
+
}) };
|
|
10708
|
+
}
|
|
10709
|
+
/**
|
|
10710
|
+
Find the [`Panel`](https://codemirror.net/6/docs/ref/#view.Panel) for an open dialog, using a class
|
|
10711
|
+
name as identifier.
|
|
10712
|
+
*/
|
|
10713
|
+
function getDialog(view, className) {
|
|
10714
|
+
let dialogs = view.state.field(dialogField, false) || [];
|
|
10715
|
+
for (let open of dialogs) {
|
|
10716
|
+
let panel = getPanel(view, open);
|
|
10717
|
+
if (panel && panel.dom.classList.contains(className))
|
|
10718
|
+
return panel;
|
|
10719
|
+
}
|
|
10720
|
+
return null;
|
|
10721
|
+
}
|
|
10722
|
+
const dialogField = /*@__PURE__*/StateField.define({
|
|
10723
|
+
create() { return []; },
|
|
10724
|
+
update(dialogs, tr) {
|
|
10725
|
+
for (let e of tr.effects) {
|
|
10726
|
+
if (e.is(openDialogEffect))
|
|
10727
|
+
dialogs = [e.value].concat(dialogs);
|
|
10728
|
+
else if (e.is(closeDialogEffect))
|
|
10729
|
+
dialogs = dialogs.filter(d => d != e.value);
|
|
10730
|
+
}
|
|
10731
|
+
return dialogs;
|
|
10732
|
+
},
|
|
10733
|
+
provide: f => showPanel.computeN([f], state => state.field(f))
|
|
10734
|
+
});
|
|
10735
|
+
const openDialogEffect = /*@__PURE__*/StateEffect.define();
|
|
10736
|
+
const closeDialogEffect = /*@__PURE__*/StateEffect.define();
|
|
10737
|
+
function createDialog(view, config, result) {
|
|
10738
|
+
let content = config.content ? config.content(view, () => done(null)) : null;
|
|
10739
|
+
if (!content) {
|
|
10740
|
+
content = elt("form");
|
|
10741
|
+
if (config.input) {
|
|
10742
|
+
let input = elt("input", config.input);
|
|
10743
|
+
if (/^(text|password|number|email|tel|url)$/.test(input.type))
|
|
10744
|
+
input.classList.add("cm-textfield");
|
|
10745
|
+
if (!input.name)
|
|
10746
|
+
input.name = "input";
|
|
10747
|
+
content.appendChild(elt("label", (config.label || "") + ": ", input));
|
|
10748
|
+
}
|
|
10749
|
+
else {
|
|
10750
|
+
content.appendChild(document.createTextNode(config.label || ""));
|
|
10751
|
+
}
|
|
10752
|
+
content.appendChild(document.createTextNode(" "));
|
|
10753
|
+
content.appendChild(elt("button", { class: "cm-button", type: "submit" }, config.submitLabel || "OK"));
|
|
10754
|
+
}
|
|
10755
|
+
let forms = content.nodeName == "FORM" ? [content] : content.querySelectorAll("form");
|
|
10756
|
+
for (let i = 0; i < forms.length; i++) {
|
|
10757
|
+
let form = forms[i];
|
|
10758
|
+
form.addEventListener("keydown", (event) => {
|
|
10759
|
+
if (event.keyCode == 27) { // Escape
|
|
10760
|
+
event.preventDefault();
|
|
10761
|
+
done(null);
|
|
10762
|
+
}
|
|
10763
|
+
else if (event.keyCode == 13) { // Enter
|
|
10764
|
+
event.preventDefault();
|
|
10765
|
+
done(form);
|
|
10766
|
+
}
|
|
10767
|
+
});
|
|
10768
|
+
form.addEventListener("submit", (event) => {
|
|
10769
|
+
event.preventDefault();
|
|
10770
|
+
done(form);
|
|
10771
|
+
});
|
|
10772
|
+
}
|
|
10773
|
+
let panel = elt("div", content, elt("button", {
|
|
10774
|
+
onclick: () => done(null),
|
|
10775
|
+
"aria-label": view.state.phrase("close"),
|
|
10776
|
+
class: "cm-dialog-close",
|
|
10777
|
+
type: "button"
|
|
10778
|
+
}, ["×"]));
|
|
10779
|
+
if (config.class)
|
|
10780
|
+
panel.className = config.class;
|
|
10781
|
+
panel.classList.add("cm-dialog");
|
|
10782
|
+
function done(form) {
|
|
10783
|
+
if (panel.contains(panel.ownerDocument.activeElement))
|
|
10784
|
+
view.focus();
|
|
10785
|
+
result(form);
|
|
10786
|
+
}
|
|
10787
|
+
return {
|
|
10788
|
+
dom: panel,
|
|
10789
|
+
top: config.top,
|
|
10790
|
+
mount: () => {
|
|
10791
|
+
if (config.focus) {
|
|
10792
|
+
let focus;
|
|
10793
|
+
if (typeof config.focus == "string")
|
|
10794
|
+
focus = content.querySelector(config.focus);
|
|
10795
|
+
else
|
|
10796
|
+
focus = content.querySelector("input") || content.querySelector("button");
|
|
10797
|
+
if (focus && "select" in focus)
|
|
10798
|
+
focus.select();
|
|
10799
|
+
else if (focus && "focus" in focus)
|
|
10800
|
+
focus.focus();
|
|
10801
|
+
}
|
|
10802
|
+
}
|
|
10803
|
+
};
|
|
10804
|
+
}
|
|
10805
|
+
|
|
10642
10806
|
/**
|
|
10643
10807
|
A gutter marker represents a bit of information attached to a line
|
|
10644
10808
|
in a specific gutter. Your own custom markers have to extend this
|
|
@@ -10697,7 +10861,7 @@ Define an editor gutter. The order in which the gutters appear is
|
|
|
10697
10861
|
determined by their extension priority.
|
|
10698
10862
|
*/
|
|
10699
10863
|
function gutter(config) {
|
|
10700
|
-
return [gutters(), activeGutters.of(
|
|
10864
|
+
return [gutters(), activeGutters.of({ ...defaults, ...config })];
|
|
10701
10865
|
}
|
|
10702
10866
|
const unfixGutters = /*@__PURE__*/Facet.define({
|
|
10703
10867
|
combine: values => values.some(x => x)
|
|
@@ -11174,4 +11338,4 @@ function highlightTrailingWhitespace() {
|
|
|
11174
11338
|
const __test = { HeightMap, HeightOracle, MeasuredHeights, QueryType, ChangedRange, computeOrder,
|
|
11175
11339
|
moveVisually, clearHeightChangeFlag, getHeightChangeFlag: () => heightChangeFlag };
|
|
11176
11340
|
|
|
11177
|
-
export { BidiSpan, BlockInfo, BlockType, Decoration, Direction, EditorView, GutterMarker, MatchDecorator, RectangleMarker, ViewPlugin, ViewUpdate, WidgetType, __test, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getDrawSelectionConfig, getPanel, getTooltip, gutter, gutterLineClass, gutterWidgetClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, highlightTrailingWhitespace, highlightWhitespace, hoverTooltip, keymap, layer, lineNumberMarkers, lineNumberWidgetMarker, lineNumbers, logException, panels, placeholder, rectangularSelection, repositionTooltips, runScopeHandlers, scrollPastEnd, showPanel, showTooltip, tooltips };
|
|
11341
|
+
export { BidiSpan, BlockInfo, BlockType, Decoration, Direction, EditorView, GutterMarker, MatchDecorator, RectangleMarker, ViewPlugin, ViewUpdate, WidgetType, __test, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getDialog, getDrawSelectionConfig, getPanel, getTooltip, gutter, gutterLineClass, gutterWidgetClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, highlightTrailingWhitespace, highlightWhitespace, hoverTooltip, keymap, layer, lineNumberMarkers, lineNumberWidgetMarker, lineNumbers, logException, panels, placeholder, rectangularSelection, repositionTooltips, runScopeHandlers, scrollPastEnd, showDialog, showPanel, showTooltip, tooltips };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codemirror/view",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.37.1",
|
|
4
4
|
"description": "DOM view component for the CodeMirror code editor",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "cm-runtests",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@codemirror/state": "^6.5.0",
|
|
30
|
+
"crelt": "^1.0.6",
|
|
30
31
|
"style-mod": "^4.1.0",
|
|
31
32
|
"w3c-keyname": "^2.2.4"
|
|
32
33
|
},
|