@wallarm-org/design-system 1.30.0 → 1.31.0
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/dist/components/CodeEditor/CodeEditorContent.d.ts +17 -0
- package/dist/components/CodeEditor/CodeEditorContent.js +197 -0
- package/dist/components/CodeEditor/CodeEditorContext.d.ts +17 -0
- package/dist/components/CodeEditor/CodeEditorContext.js +8 -0
- package/dist/components/CodeEditor/CodeEditorRoot.d.ts +77 -0
- package/dist/components/CodeEditor/CodeEditorRoot.js +203 -0
- package/dist/components/CodeEditor/classes.d.ts +21 -0
- package/dist/components/CodeEditor/classes.js +41 -0
- package/dist/components/CodeEditor/engine/SearchPanel.d.ts +13 -0
- package/dist/components/CodeEditor/engine/SearchPanel.js +201 -0
- package/dist/components/CodeEditor/engine/adapterPainter.d.ts +23 -0
- package/dist/components/CodeEditor/engine/adapterPainter.js +110 -0
- package/dist/components/CodeEditor/engine/babelSyntax.d.ts +15 -0
- package/dist/components/CodeEditor/engine/babelSyntax.js +54 -0
- package/dist/components/CodeEditor/engine/completion.d.ts +17 -0
- package/dist/components/CodeEditor/engine/completion.js +129 -0
- package/dist/components/CodeEditor/engine/contentAttributes.d.ts +12 -0
- package/dist/components/CodeEditor/engine/contentAttributes.js +24 -0
- package/dist/components/CodeEditor/engine/diagnostics.d.ts +73 -0
- package/dist/components/CodeEditor/engine/diagnostics.js +327 -0
- package/dist/components/CodeEditor/engine/diff.d.ts +37 -0
- package/dist/components/CodeEditor/engine/diff.js +145 -0
- package/dist/components/CodeEditor/engine/folds.d.ts +25 -0
- package/dist/components/CodeEditor/engine/folds.js +458 -0
- package/dist/components/CodeEditor/engine/gutters.d.ts +22 -0
- package/dist/components/CodeEditor/engine/gutters.js +160 -0
- package/dist/components/CodeEditor/engine/index.d.ts +12 -0
- package/dist/components/CodeEditor/engine/index.js +387 -0
- package/dist/components/CodeEditor/engine/languages/http/index.d.ts +20 -0
- package/dist/components/CodeEditor/engine/languages/http/index.js +69 -0
- package/dist/components/CodeEditor/engine/languages/http/parser.d.ts +2 -0
- package/dist/components/CodeEditor/engine/languages/http/parser.js +31 -0
- package/dist/components/CodeEditor/engine/languages/http/parser.terms.d.ts +1 -0
- package/dist/components/CodeEditor/engine/languages/http/parser.terms.js +2 -0
- package/dist/components/CodeEditor/engine/languages/index.d.ts +8 -0
- package/dist/components/CodeEditor/engine/languages/index.js +41 -0
- package/dist/components/CodeEditor/engine/languages/json.d.ts +8 -0
- package/dist/components/CodeEditor/engine/languages/json.js +11 -0
- package/dist/components/CodeEditor/engine/languages/jsonPointers.d.ts +47 -0
- package/dist/components/CodeEditor/engine/languages/jsonPointers.js +125 -0
- package/dist/components/CodeEditor/engine/languages/yaml.d.ts +4 -0
- package/dist/components/CodeEditor/engine/languages/yaml.js +11 -0
- package/dist/components/CodeEditor/engine/lines.d.ts +22 -0
- package/dist/components/CodeEditor/engine/lines.js +131 -0
- package/dist/components/CodeEditor/engine/luaSyntax.d.ts +14 -0
- package/dist/components/CodeEditor/engine/luaSyntax.js +36 -0
- package/dist/components/CodeEditor/engine/positions.d.ts +19 -0
- package/dist/components/CodeEditor/engine/positions.js +22 -0
- package/dist/components/CodeEditor/engine/schema/complete.d.ts +12 -0
- package/dist/components/CodeEditor/engine/schema/complete.js +211 -0
- package/dist/components/CodeEditor/engine/schema/hover.d.ts +12 -0
- package/dist/components/CodeEditor/engine/schema/hover.js +73 -0
- package/dist/components/CodeEditor/engine/schema/loadSchema.d.ts +19 -0
- package/dist/components/CodeEditor/engine/schema/loadSchema.js +32 -0
- package/dist/components/CodeEditor/engine/schema/validate.d.ts +9 -0
- package/dist/components/CodeEditor/engine/schema/validate.js +67 -0
- package/dist/components/CodeEditor/engine/search.d.ts +13 -0
- package/dist/components/CodeEditor/engine/search.js +84 -0
- package/dist/components/CodeEditor/engine/searchMatches.d.ts +8 -0
- package/dist/components/CodeEditor/engine/searchMatches.js +15 -0
- package/dist/components/CodeEditor/engine/theme.d.ts +8 -0
- package/dist/components/CodeEditor/engine/theme.js +89 -0
- package/dist/components/CodeEditor/engine/types.d.ts +44 -0
- package/dist/components/CodeEditor/engine/types.js +0 -0
- package/dist/components/CodeEditor/hooks/useCodeEditor.d.ts +6 -0
- package/dist/components/CodeEditor/hooks/useCodeEditor.js +3 -0
- package/dist/components/CodeEditor/index.d.ts +6 -0
- package/dist/components/CodeEditor/index.js +5 -0
- package/dist/components/CodeEditor/lib/PortalOutlet.d.ts +11 -0
- package/dist/components/CodeEditor/lib/PortalOutlet.js +11 -0
- package/dist/components/CodeEditor/lib/httpCompletions.d.ts +7 -0
- package/dist/components/CodeEditor/lib/httpCompletions.js +102 -0
- package/dist/components/CodeEditor/lib/httpCompletionsData.d.ts +29 -0
- package/dist/components/CodeEditor/lib/httpCompletionsData.js +650 -0
- package/dist/components/CodeEditor/lib/keyboardHint.d.ts +5 -0
- package/dist/components/CodeEditor/lib/keyboardHint.js +2 -0
- package/dist/components/CodeEditor/lib/loadEngine.d.ts +7 -0
- package/dist/components/CodeEditor/lib/loadEngine.js +9 -0
- package/dist/components/CodeEditor/lib/portalRegistry.d.ts +20 -0
- package/dist/components/CodeEditor/lib/portalRegistry.js +47 -0
- package/dist/components/CodeEditor/lib/splitContentProps.d.ts +12 -0
- package/dist/components/CodeEditor/lib/splitContentProps.js +28 -0
- package/dist/components/CodeEditor/types.d.ts +72 -0
- package/dist/components/CodeEditor/types.js +0 -0
- package/dist/components/CodeSnippet/CodeSnippetCode.js +6 -23
- package/dist/components/CodeSnippet/CodeSnippetCopyButton.js +4 -3
- package/dist/components/CodeSnippet/CodeSnippetFrameContext.d.ts +25 -0
- package/dist/components/CodeSnippet/CodeSnippetFrameContext.js +3 -0
- package/dist/components/CodeSnippet/CodeSnippetFullscreenButton.js +2 -2
- package/dist/components/CodeSnippet/CodeSnippetRoot.d.ts +3 -5
- package/dist/components/CodeSnippet/CodeSnippetRoot.js +56 -50
- package/dist/components/CodeSnippet/CodeSnippetShowMoreButton.js +7 -5
- package/dist/components/CodeSnippet/CodeSnippetWrapButton.js +2 -2
- package/dist/components/CodeSnippet/adapters/highlightjs.js +1 -0
- package/dist/components/CodeSnippet/adapters/prism.js +3 -1
- package/dist/components/CodeSnippet/adapters/shiki.js +1 -0
- package/dist/components/CodeSnippet/adapters/types.d.ts +3 -3
- package/dist/components/CodeSnippet/classes.d.ts +3 -0
- package/dist/components/CodeSnippet/classes.js +14 -0
- package/dist/components/CodeSnippet/hooks/index.d.ts +1 -0
- package/dist/components/CodeSnippet/hooks/index.js +1 -0
- package/dist/components/CodeSnippet/hooks/useCodeSnippetFrame.d.ts +2 -0
- package/dist/components/CodeSnippet/hooks/useCodeSnippetFrame.js +8 -0
- package/dist/components/CodeSnippet/index.d.ts +2 -1
- package/dist/components/CodeSnippet/index.js +1 -1
- package/dist/components/CodeSnippet/internal/CodeSnippetFrame.d.ts +22 -0
- package/dist/components/CodeSnippet/internal/CodeSnippetFrame.js +81 -0
- package/dist/components/CodeSnippet/internal/CodeToken.d.ts +2 -1
- package/dist/components/CodeSnippet/internal/CodeToken.js +1 -1
- package/dist/components/CodeSnippet/internal/FoldSummary.d.ts +11 -0
- package/dist/components/CodeSnippet/internal/FoldSummary.js +27 -0
- package/dist/components/CodeSnippet/internal/FoldToggle.d.ts +2 -0
- package/dist/components/CodeSnippet/internal/FoldToggle.js +2 -1
- package/dist/components/CodeSnippet/internal/index.d.ts +1 -0
- package/dist/components/CodeSnippet/internal/index.js +1 -0
- package/dist/components/CodeSnippet/lib/foldUtils.d.ts +9 -2
- package/dist/components/CodeSnippet/lib/foldUtils.js +2 -2
- package/dist/components/CodeSnippet/lib/showMore.d.ts +7 -0
- package/dist/components/CodeSnippet/lib/showMore.js +7 -0
- package/dist/components/Copyable/Copyable.d.ts +5 -2
- package/dist/components/Copyable/Copyable.js +1 -1
- package/dist/metadata/components.json +1235 -5
- package/package.json +24 -1
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
import { createElement } from "react";
|
|
2
|
+
import { foldService } from "@codemirror/language";
|
|
3
|
+
import { EditorSelection, Facet, Prec, StateEffect, StateField } from "@codemirror/state";
|
|
4
|
+
import { Decoration, EditorView, GutterMarker, ViewPlugin, WidgetType, gutter, keymap } from "@codemirror/view";
|
|
5
|
+
import { FoldSummary } from "../../CodeSnippet/internal/FoldSummary.js";
|
|
6
|
+
import { FoldToggle } from "../../CodeSnippet/internal/FoldToggle.js";
|
|
7
|
+
import { getFoldSummaryLabel, validateFolds } from "../../CodeSnippet/lib/foldUtils.js";
|
|
8
|
+
const FOLDS_DEBOUNCE_MS = 150;
|
|
9
|
+
const foldsConfig = Facet.define({
|
|
10
|
+
combine: (values)=>values[0] ?? null
|
|
11
|
+
});
|
|
12
|
+
const setFoldsEffect = StateEffect.define();
|
|
13
|
+
const setCollapsedEffect = StateEffect.define();
|
|
14
|
+
const portalIds = new WeakMap();
|
|
15
|
+
const releasePortal = (portals, dom)=>{
|
|
16
|
+
const id = portalIds.get(dom);
|
|
17
|
+
if (void 0 === id) return;
|
|
18
|
+
portalIds.delete(dom);
|
|
19
|
+
portals.unregister(id);
|
|
20
|
+
};
|
|
21
|
+
const sameRegion = (a, b)=>a.id === b.id && a.startLine === b.startLine && a.endLine === b.endLine && a.label === b.label && a.toggleProps === b.toggleProps && a.summaryProps === b.summaryProps;
|
|
22
|
+
const regionLineCount = (region)=>region.endLine - region.startLine + 1;
|
|
23
|
+
const regionRange = (state, region, startingLineNumber)=>({
|
|
24
|
+
from: state.doc.line(region.startLine - startingLineNumber + 1).from,
|
|
25
|
+
to: state.doc.line(region.endLine - startingLineNumber + 1).to
|
|
26
|
+
});
|
|
27
|
+
const startingLine = (state)=>state.facet(foldsConfig)?.startingLineNumber ?? 1;
|
|
28
|
+
const computeRaw = (config, state)=>{
|
|
29
|
+
const folds = config?.folds;
|
|
30
|
+
if (void 0 === folds) return [];
|
|
31
|
+
if ('function' == typeof folds) return folds(state.doc.toString(), {
|
|
32
|
+
startingLineNumber: config?.startingLineNumber ?? 1
|
|
33
|
+
});
|
|
34
|
+
return folds;
|
|
35
|
+
};
|
|
36
|
+
const resolve = (raw, state, warn)=>validateFolds(raw, state.doc.lines, startingLine(state), {
|
|
37
|
+
warn
|
|
38
|
+
});
|
|
39
|
+
class FoldSummaryWidget extends WidgetType {
|
|
40
|
+
region;
|
|
41
|
+
portals;
|
|
42
|
+
testId;
|
|
43
|
+
constructor(region, portals, testId){
|
|
44
|
+
super(), this.region = region, this.portals = portals, this.testId = testId;
|
|
45
|
+
}
|
|
46
|
+
eq(other) {
|
|
47
|
+
return sameRegion(this.region, other.region) && this.portals === other.portals && this.testId === other.testId;
|
|
48
|
+
}
|
|
49
|
+
toDOM(view) {
|
|
50
|
+
const host = document.createElement('span');
|
|
51
|
+
host.className = 'cm-ds-fold-summary';
|
|
52
|
+
const { id } = this.region;
|
|
53
|
+
const portalId = this.portals.register(host, createElement(FoldSummary, {
|
|
54
|
+
fold: this.region,
|
|
55
|
+
lineCount: regionLineCount(this.region),
|
|
56
|
+
onToggle: ()=>{
|
|
57
|
+
toggleFoldRegion(view, id);
|
|
58
|
+
},
|
|
59
|
+
testId: void 0 === this.testId ? void 0 : `${this.testId}--fold-summary`
|
|
60
|
+
}));
|
|
61
|
+
portalIds.set(host, portalId);
|
|
62
|
+
return host;
|
|
63
|
+
}
|
|
64
|
+
destroy(dom) {
|
|
65
|
+
releasePortal(this.portals, dom);
|
|
66
|
+
}
|
|
67
|
+
ignoreEvent() {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const buildDecorations = (state, regions, collapsed)=>{
|
|
72
|
+
const config = state.facet(foldsConfig);
|
|
73
|
+
if (!config || 0 === collapsed.size) return Decoration.none;
|
|
74
|
+
const ranges = [];
|
|
75
|
+
for (const region of regions){
|
|
76
|
+
if (!collapsed.has(region.id)) continue;
|
|
77
|
+
const { from, to } = regionRange(state, region, config.startingLineNumber);
|
|
78
|
+
ranges.push(Decoration.replace({
|
|
79
|
+
widget: new FoldSummaryWidget(region, config.portals, config.testId)
|
|
80
|
+
}).range(from, to));
|
|
81
|
+
}
|
|
82
|
+
return Decoration.set(ranges, true);
|
|
83
|
+
};
|
|
84
|
+
const selectionEntersRange = (range, from, to)=>range.head > from && range.head < to || !range.empty && range.from >= from && range.to <= to;
|
|
85
|
+
const mapRegions = (raw, tr, startingLineNumber)=>{
|
|
86
|
+
const oldDoc = tr.startState.doc;
|
|
87
|
+
const newDoc = tr.state.doc;
|
|
88
|
+
const offset = startingLineNumber - 1;
|
|
89
|
+
return raw.map((region)=>{
|
|
90
|
+
const startLine = region.startLine - offset;
|
|
91
|
+
const endLine = region.endLine - offset;
|
|
92
|
+
if (startLine < 1 || endLine > oldDoc.lines || startLine > endLine) return region;
|
|
93
|
+
const from = tr.changes.mapPos(oldDoc.line(startLine).from, 1);
|
|
94
|
+
const to = tr.changes.mapPos(oldDoc.line(endLine).to, -1);
|
|
95
|
+
const nextStart = newDoc.lineAt(Math.min(from, to)).number + offset;
|
|
96
|
+
const nextEnd = newDoc.lineAt(to).number + offset;
|
|
97
|
+
if (nextStart === region.startLine && nextEnd === region.endLine) return region;
|
|
98
|
+
return {
|
|
99
|
+
...region,
|
|
100
|
+
startLine: nextStart,
|
|
101
|
+
endLine: nextEnd
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
const sameSet = (a, b)=>a.size === b.size && [
|
|
106
|
+
...a
|
|
107
|
+
].every((id)=>b.has(id));
|
|
108
|
+
const initialState = (state)=>{
|
|
109
|
+
const raw = computeRaw(state.facet(foldsConfig), state);
|
|
110
|
+
const regions = resolve(raw, state, true);
|
|
111
|
+
const collapsed = new Set(regions.filter((r)=>r.defaultCollapsed).map((r)=>r.id));
|
|
112
|
+
return {
|
|
113
|
+
raw,
|
|
114
|
+
regions,
|
|
115
|
+
collapsed,
|
|
116
|
+
seen: new Set(regions.map((r)=>r.id)),
|
|
117
|
+
decorations: Decoration.none
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
const updateState = (value, tr)=>{
|
|
121
|
+
const { state } = tr;
|
|
122
|
+
let { raw, regions } = value;
|
|
123
|
+
let validated = false;
|
|
124
|
+
if (tr.startState.facet(foldsConfig) !== state.facet(foldsConfig)) {
|
|
125
|
+
raw = computeRaw(state.facet(foldsConfig), state);
|
|
126
|
+
regions = resolve(raw, state, true);
|
|
127
|
+
validated = true;
|
|
128
|
+
}
|
|
129
|
+
for (const effect of tr.effects)if (effect.is(setFoldsEffect)) {
|
|
130
|
+
raw = effect.value;
|
|
131
|
+
regions = resolve(raw, state, true);
|
|
132
|
+
validated = true;
|
|
133
|
+
}
|
|
134
|
+
const isFunction = 'function' == typeof state.facet(foldsConfig)?.folds;
|
|
135
|
+
if (!validated && tr.docChanged) {
|
|
136
|
+
if (isFunction) raw = mapRegions(raw, tr, startingLine(state));
|
|
137
|
+
regions = resolve(raw, state, false);
|
|
138
|
+
}
|
|
139
|
+
const collapsed = new Set(value.collapsed);
|
|
140
|
+
let seen = value.seen;
|
|
141
|
+
if (regions !== value.regions) {
|
|
142
|
+
const nextSeen = new Set(seen);
|
|
143
|
+
for (const region of regions)if (!nextSeen.has(region.id)) {
|
|
144
|
+
nextSeen.add(region.id);
|
|
145
|
+
if (region.defaultCollapsed) collapsed.add(region.id);
|
|
146
|
+
}
|
|
147
|
+
seen = nextSeen;
|
|
148
|
+
}
|
|
149
|
+
for (const effect of tr.effects)if (effect.is(setCollapsedEffect)) if (effect.value.collapsed) collapsed.add(effect.value.id);
|
|
150
|
+
else collapsed.delete(effect.value.id);
|
|
151
|
+
if (validated || !isFunction) {
|
|
152
|
+
const ids = new Set(regions.map((r)=>r.id));
|
|
153
|
+
for (const id of [
|
|
154
|
+
...collapsed
|
|
155
|
+
])if (!ids.has(id)) collapsed.delete(id);
|
|
156
|
+
}
|
|
157
|
+
const userEdit = tr.docChanged && (tr.isUserEvent('input') || tr.isUserEvent('delete'));
|
|
158
|
+
if (collapsed.size > 0 && (tr.selection || userEdit)) {
|
|
159
|
+
const start = startingLine(state);
|
|
160
|
+
for (const region of regions){
|
|
161
|
+
if (!collapsed.has(region.id)) continue;
|
|
162
|
+
const { from, to } = regionRange(state, region, start);
|
|
163
|
+
const selected = void 0 !== tr.selection && state.selection.ranges.some((range)=>selectionEntersRange(range, from, to));
|
|
164
|
+
let edited = false;
|
|
165
|
+
if (userEdit) tr.changes.iterChangedRanges((_fromA, _toA, fromB, toB)=>{
|
|
166
|
+
if (fromB <= to && toB >= from) edited = true;
|
|
167
|
+
});
|
|
168
|
+
if (selected || edited) collapsed.delete(region.id);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const collapsedChanged = !sameSet(collapsed, value.collapsed);
|
|
172
|
+
if (regions === value.regions && !collapsedChanged && !tr.docChanged && seen === value.seen) return value;
|
|
173
|
+
const nextCollapsed = collapsedChanged ? collapsed : value.collapsed;
|
|
174
|
+
return {
|
|
175
|
+
raw,
|
|
176
|
+
regions,
|
|
177
|
+
collapsed: nextCollapsed,
|
|
178
|
+
seen,
|
|
179
|
+
decorations: buildDecorations(state, regions, nextCollapsed)
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
const foldsField = StateField.define({
|
|
183
|
+
create: (state)=>{
|
|
184
|
+
const value = initialState(state);
|
|
185
|
+
return {
|
|
186
|
+
...value,
|
|
187
|
+
decorations: buildDecorations(state, value.regions, value.collapsed)
|
|
188
|
+
};
|
|
189
|
+
},
|
|
190
|
+
update: updateState,
|
|
191
|
+
provide: (field)=>EditorView.decorations.from(field, (value)=>value.decorations)
|
|
192
|
+
});
|
|
193
|
+
const functionFoldsPlugin = ViewPlugin.fromClass(class {
|
|
194
|
+
view;
|
|
195
|
+
timer = null;
|
|
196
|
+
constructor(view){
|
|
197
|
+
this.view = view;
|
|
198
|
+
}
|
|
199
|
+
update(update) {
|
|
200
|
+
if (!update.docChanged) return;
|
|
201
|
+
if ('function' != typeof update.state.facet(foldsConfig)?.folds) return;
|
|
202
|
+
this.clear();
|
|
203
|
+
this.timer = setTimeout(()=>{
|
|
204
|
+
this.timer = null;
|
|
205
|
+
const config = this.view.state.facet(foldsConfig);
|
|
206
|
+
const folds = config?.folds;
|
|
207
|
+
if ('function' != typeof folds) return;
|
|
208
|
+
const raw = folds(this.view.state.doc.toString(), {
|
|
209
|
+
startingLineNumber: config?.startingLineNumber ?? 1
|
|
210
|
+
});
|
|
211
|
+
this.view.dispatch({
|
|
212
|
+
effects: setFoldsEffect.of(raw)
|
|
213
|
+
});
|
|
214
|
+
}, FOLDS_DEBOUNCE_MS);
|
|
215
|
+
}
|
|
216
|
+
clear() {
|
|
217
|
+
if (null !== this.timer) clearTimeout(this.timer);
|
|
218
|
+
this.timer = null;
|
|
219
|
+
}
|
|
220
|
+
destroy() {
|
|
221
|
+
this.clear();
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
const readField = (state)=>state.field(foldsField, false);
|
|
225
|
+
const setCollapsed = (view, targets, collapse)=>{
|
|
226
|
+
const { state } = view;
|
|
227
|
+
if (0 === targets.length) return false;
|
|
228
|
+
const start = startingLine(state);
|
|
229
|
+
const ranges = targets.map((region)=>regionRange(state, region, start));
|
|
230
|
+
const effects = targets.map((region)=>setCollapsedEffect.of({
|
|
231
|
+
id: region.id,
|
|
232
|
+
collapsed: collapse
|
|
233
|
+
}));
|
|
234
|
+
if (1 === targets.length && targets[0]) {
|
|
235
|
+
const label = getFoldSummaryLabel(targets[0], regionLineCount(targets[0]));
|
|
236
|
+
effects.push(EditorView.announce.of(`${collapse ? 'Folded' : 'Unfolded'} ${label}`));
|
|
237
|
+
}
|
|
238
|
+
let selection;
|
|
239
|
+
if (collapse) {
|
|
240
|
+
let moved = false;
|
|
241
|
+
const next = state.selection.ranges.map((range)=>{
|
|
242
|
+
const hit = ranges.find(({ from, to })=>selectionEntersRange(range, from, to));
|
|
243
|
+
if (!hit) return range;
|
|
244
|
+
moved = true;
|
|
245
|
+
return EditorSelection.cursor(hit.from);
|
|
246
|
+
});
|
|
247
|
+
if (moved) selection = EditorSelection.create(next, state.selection.mainIndex);
|
|
248
|
+
}
|
|
249
|
+
view.dispatch(selection ? {
|
|
250
|
+
effects,
|
|
251
|
+
selection
|
|
252
|
+
} : {
|
|
253
|
+
effects
|
|
254
|
+
});
|
|
255
|
+
return true;
|
|
256
|
+
};
|
|
257
|
+
const getCollapsedFoldIds = (state)=>readField(state)?.collapsed ?? new Set();
|
|
258
|
+
const getVisibleRowCount = (state)=>{
|
|
259
|
+
const value = readField(state);
|
|
260
|
+
if (!value) return state.doc.lines;
|
|
261
|
+
let hidden = 0;
|
|
262
|
+
for (const region of value.regions)if (value.collapsed.has(region.id)) hidden += regionLineCount(region) - 1;
|
|
263
|
+
return state.doc.lines - hidden;
|
|
264
|
+
};
|
|
265
|
+
const getCollapsedRanges = (state)=>{
|
|
266
|
+
const value = readField(state);
|
|
267
|
+
if (!value || 0 === value.collapsed.size) return [];
|
|
268
|
+
const start = startingLine(state);
|
|
269
|
+
return value.regions.filter((region)=>value.collapsed.has(region.id)).map((region)=>regionRange(state, region, start));
|
|
270
|
+
};
|
|
271
|
+
const toggleFoldRegion = (view, id)=>{
|
|
272
|
+
const value = readField(view.state);
|
|
273
|
+
const region = value?.regions.find((r)=>r.id === id);
|
|
274
|
+
if (!value || !region) return false;
|
|
275
|
+
return setCollapsed(view, [
|
|
276
|
+
region
|
|
277
|
+
], !value.collapsed.has(id));
|
|
278
|
+
};
|
|
279
|
+
const foldAllRegions = (view)=>{
|
|
280
|
+
const value = readField(view.state);
|
|
281
|
+
if (!value) return false;
|
|
282
|
+
return setCollapsed(view, value.regions.filter((r)=>!value.collapsed.has(r.id)), true);
|
|
283
|
+
};
|
|
284
|
+
const unfoldAllRegions = (view)=>{
|
|
285
|
+
const value = readField(view.state);
|
|
286
|
+
if (!value) return false;
|
|
287
|
+
return setCollapsed(view, value.regions.filter((r)=>value.collapsed.has(r.id)), false);
|
|
288
|
+
};
|
|
289
|
+
const regionAtCursor = (state)=>{
|
|
290
|
+
const value = readField(state);
|
|
291
|
+
if (!value) return;
|
|
292
|
+
const line = state.doc.lineAt(state.selection.main.head).number + startingLine(state) - 1;
|
|
293
|
+
return value.regions.find((r)=>r.startLine <= line && r.endLine >= line);
|
|
294
|
+
};
|
|
295
|
+
const foldRegionAtCursor = (view)=>{
|
|
296
|
+
const region = regionAtCursor(view.state);
|
|
297
|
+
if (!region || getCollapsedFoldIds(view.state).has(region.id)) return false;
|
|
298
|
+
return setCollapsed(view, [
|
|
299
|
+
region
|
|
300
|
+
], true);
|
|
301
|
+
};
|
|
302
|
+
const unfoldRegionAtCursor = (view)=>{
|
|
303
|
+
const region = regionAtCursor(view.state);
|
|
304
|
+
if (!region || !getCollapsedFoldIds(view.state).has(region.id)) return false;
|
|
305
|
+
return setCollapsed(view, [
|
|
306
|
+
region
|
|
307
|
+
], false);
|
|
308
|
+
};
|
|
309
|
+
const foldsKeymap = Prec.high(keymap.of([
|
|
310
|
+
{
|
|
311
|
+
key: 'Ctrl-Shift-[',
|
|
312
|
+
mac: 'Cmd-Alt-[',
|
|
313
|
+
run: foldRegionAtCursor
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
key: 'Ctrl-Shift-]',
|
|
317
|
+
mac: 'Cmd-Alt-]',
|
|
318
|
+
run: unfoldRegionAtCursor
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
key: 'Ctrl-Alt-[',
|
|
322
|
+
run: foldAllRegions
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
key: 'Ctrl-Alt-]',
|
|
326
|
+
run: unfoldAllRegions
|
|
327
|
+
}
|
|
328
|
+
]));
|
|
329
|
+
const regionsFoldService = foldService.of((state, lineStart)=>{
|
|
330
|
+
const value = readField(state);
|
|
331
|
+
if (!value) return null;
|
|
332
|
+
const start = startingLine(state);
|
|
333
|
+
const line = state.doc.lineAt(lineStart).number + start - 1;
|
|
334
|
+
const region = value.regions.find((r)=>r.startLine === line);
|
|
335
|
+
return region ? regionRange(state, region, start) : null;
|
|
336
|
+
});
|
|
337
|
+
const toggleHosts = new WeakMap();
|
|
338
|
+
const toggleHostByDom = new WeakMap();
|
|
339
|
+
const renderToggle = (view, regionId, testId)=>{
|
|
340
|
+
const value = readField(view.state);
|
|
341
|
+
const region = value?.regions.find((r)=>r.id === regionId);
|
|
342
|
+
if (!value || !region) return null;
|
|
343
|
+
return createElement(FoldToggle, {
|
|
344
|
+
fold: region,
|
|
345
|
+
isCollapsed: value.collapsed.has(regionId),
|
|
346
|
+
onToggle: ()=>{
|
|
347
|
+
toggleFoldRegion(view, regionId);
|
|
348
|
+
},
|
|
349
|
+
testId: void 0 === testId ? void 0 : `${testId}--fold-toggle`
|
|
350
|
+
});
|
|
351
|
+
};
|
|
352
|
+
class FoldToggleMarker extends GutterMarker {
|
|
353
|
+
region;
|
|
354
|
+
portals;
|
|
355
|
+
testId;
|
|
356
|
+
constructor(region, portals, testId){
|
|
357
|
+
super(), this.region = region, this.portals = portals, this.testId = testId;
|
|
358
|
+
}
|
|
359
|
+
eq(other) {
|
|
360
|
+
return other instanceof FoldToggleMarker && this.region.id === other.region.id && this.region.startLine === other.region.startLine && this.portals === other.portals && this.testId === other.testId;
|
|
361
|
+
}
|
|
362
|
+
toDOM(view) {
|
|
363
|
+
const host = document.createElement('span');
|
|
364
|
+
host.className = 'cm-ds-fold-toggle';
|
|
365
|
+
const { id } = this.region;
|
|
366
|
+
const portalId = this.portals.register(host, renderToggle(view, id, this.testId));
|
|
367
|
+
portalIds.set(host, portalId);
|
|
368
|
+
const entry = {
|
|
369
|
+
view,
|
|
370
|
+
regionId: id,
|
|
371
|
+
portalId,
|
|
372
|
+
portals: this.portals,
|
|
373
|
+
testId: this.testId
|
|
374
|
+
};
|
|
375
|
+
toggleHostByDom.set(host, entry);
|
|
376
|
+
let hosts = toggleHosts.get(view);
|
|
377
|
+
if (!hosts) {
|
|
378
|
+
hosts = new Set();
|
|
379
|
+
toggleHosts.set(view, hosts);
|
|
380
|
+
}
|
|
381
|
+
hosts.add(entry);
|
|
382
|
+
return host;
|
|
383
|
+
}
|
|
384
|
+
destroy(dom) {
|
|
385
|
+
const entry = toggleHostByDom.get(dom);
|
|
386
|
+
if (entry) {
|
|
387
|
+
toggleHostByDom.delete(dom);
|
|
388
|
+
toggleHosts.get(entry.view)?.delete(entry);
|
|
389
|
+
}
|
|
390
|
+
releasePortal(this.portals, dom);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
const foldToggleUpdater = ViewPlugin.define((view)=>({
|
|
394
|
+
update (update) {
|
|
395
|
+
if (readField(update.startState) === readField(update.state)) return;
|
|
396
|
+
for (const entry of toggleHosts.get(view) ?? []){
|
|
397
|
+
const node = renderToggle(view, entry.regionId, entry.testId);
|
|
398
|
+
if (node) entry.portals.update(entry.portalId, node);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}));
|
|
402
|
+
class FoldSpacerMarker extends GutterMarker {
|
|
403
|
+
eq(other) {
|
|
404
|
+
return other instanceof FoldSpacerMarker;
|
|
405
|
+
}
|
|
406
|
+
toDOM() {
|
|
407
|
+
const spacer = document.createElement('span');
|
|
408
|
+
spacer.className = 'cm-ds-fold-spacer';
|
|
409
|
+
return spacer;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
const foldSpacer = new FoldSpacerMarker();
|
|
413
|
+
const foldGutterTheme = EditorView.theme({
|
|
414
|
+
'.cm-ds-fold-gutter .cm-gutterElement': {
|
|
415
|
+
display: 'flex',
|
|
416
|
+
alignItems: 'center',
|
|
417
|
+
justifyContent: 'center',
|
|
418
|
+
padding: '0 4px'
|
|
419
|
+
},
|
|
420
|
+
'.cm-ds-fold-spacer, .cm-ds-fold-toggle': {
|
|
421
|
+
display: 'flex',
|
|
422
|
+
width: '16px',
|
|
423
|
+
height: '16px'
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
const foldGutter = [
|
|
427
|
+
gutter({
|
|
428
|
+
class: 'cm-ds-fold-gutter',
|
|
429
|
+
renderEmptyElements: true,
|
|
430
|
+
lineMarker: (view, line)=>{
|
|
431
|
+
const { state } = view;
|
|
432
|
+
const value = readField(state);
|
|
433
|
+
const config = state.facet(foldsConfig);
|
|
434
|
+
if (!value || !config) return null;
|
|
435
|
+
const lineNumber = state.doc.lineAt(line.from).number + config.startingLineNumber - 1;
|
|
436
|
+
const region = value.regions.find((r)=>r.startLine === lineNumber);
|
|
437
|
+
if (!region) return null;
|
|
438
|
+
return new FoldToggleMarker(region, config.portals, config.testId);
|
|
439
|
+
},
|
|
440
|
+
lineMarkerChange: (update)=>readField(update.startState) !== readField(update.state),
|
|
441
|
+
initialSpacer: ()=>foldSpacer
|
|
442
|
+
}),
|
|
443
|
+
foldToggleUpdater,
|
|
444
|
+
foldGutterTheme
|
|
445
|
+
];
|
|
446
|
+
const foldsExtension = (config)=>({
|
|
447
|
+
extension: [
|
|
448
|
+
foldsConfig.of({
|
|
449
|
+
...config
|
|
450
|
+
}),
|
|
451
|
+
foldsField,
|
|
452
|
+
functionFoldsPlugin,
|
|
453
|
+
foldsKeymap,
|
|
454
|
+
regionsFoldService
|
|
455
|
+
],
|
|
456
|
+
gutter: void 0 === config.folds || Array.isArray(config.folds) && 0 === config.folds.length ? null : foldGutter
|
|
457
|
+
});
|
|
458
|
+
export { FOLDS_DEBOUNCE_MS, foldAllRegions, foldsExtension, getCollapsedFoldIds, getCollapsedRanges, getVisibleRowCount, toggleFoldRegion, unfoldAllRegions };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Extension } from '@codemirror/state';
|
|
2
|
+
import type { LineConfig } from '../../CodeSnippet/CodeSnippetContext';
|
|
3
|
+
import type { PortalRegistry } from '../lib/portalRegistry';
|
|
4
|
+
export interface GuttersConfig {
|
|
5
|
+
lines: Record<number, LineConfig>;
|
|
6
|
+
startingLineNumber: number;
|
|
7
|
+
lineNumbers: boolean;
|
|
8
|
+
foldGutter: Extension | null;
|
|
9
|
+
portals: PortalRegistry;
|
|
10
|
+
testId: string | undefined;
|
|
11
|
+
/** Diff mode (`original` set): `+` / `-` prefixes and colour sticks from the merge chunks. */
|
|
12
|
+
diff?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** Gutter wrapper classes (`.cm-gutter`), used by tests and the theme below. */
|
|
15
|
+
export declare const STICK_GUTTER_CLASS = "cm-ds-stick";
|
|
16
|
+
export declare const PREFIX_GUTTER_CLASS = "cm-ds-prefix";
|
|
17
|
+
/**
|
|
18
|
+
* Gutters in CodeSnippet order: colour stick (only if any line has `color`, or diff mode) →
|
|
19
|
+
* line numbers (if `lineNumbers`) → fold gutter (if given) → prefix (only if any line has
|
|
20
|
+
* `prefix`, or diff mode). In diff mode the diff marker wins over the line's own stick/prefix.
|
|
21
|
+
*/
|
|
22
|
+
export declare const guttersExtension: (config: GuttersConfig) => Extension;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { RangeSet, StateField } from "@codemirror/state";
|
|
2
|
+
import { EditorView, GutterMarker, gutter, gutterLineClass, lineNumberMarkers, lineNumbers } from "@codemirror/view";
|
|
3
|
+
import { cn } from "../../../utils/cn.js";
|
|
4
|
+
import { LINE_COLOR_STYLES } from "../../CodeSnippet/lib/lineStyles.js";
|
|
5
|
+
import { deletedRowCount, diffChunksChanged, isDiffInsertedLine } from "./diff.js";
|
|
6
|
+
import { lineNumberToDocLine } from "./positions.js";
|
|
7
|
+
const STICK_GUTTER_CLASS = 'cm-ds-stick';
|
|
8
|
+
const PREFIX_GUTTER_CLASS = 'cm-ds-prefix';
|
|
9
|
+
class ClassMarker extends GutterMarker {
|
|
10
|
+
elementClass;
|
|
11
|
+
constructor(elementClass){
|
|
12
|
+
super(), this.elementClass = elementClass;
|
|
13
|
+
}
|
|
14
|
+
eq(other) {
|
|
15
|
+
return other instanceof ClassMarker && other.elementClass === this.elementClass;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const STICK_BASE_CLASS = 'border-l-2 pl-12';
|
|
19
|
+
const transparentStick = new ClassMarker(cn(STICK_BASE_CLASS, 'border-transparent'));
|
|
20
|
+
const colorStickMarkers = new Map();
|
|
21
|
+
const getStickMarker = (color)=>{
|
|
22
|
+
if (!color) return transparentStick;
|
|
23
|
+
let marker = colorStickMarkers.get(color);
|
|
24
|
+
if (!marker) {
|
|
25
|
+
marker = new ClassMarker(cn(STICK_BASE_CLASS, LINE_COLOR_STYLES[color].border));
|
|
26
|
+
colorStickMarkers.set(color, marker);
|
|
27
|
+
}
|
|
28
|
+
return marker;
|
|
29
|
+
};
|
|
30
|
+
const prefixPortalIds = new WeakMap();
|
|
31
|
+
class PrefixMarker extends GutterMarker {
|
|
32
|
+
lineNumber;
|
|
33
|
+
prefix;
|
|
34
|
+
color;
|
|
35
|
+
portals;
|
|
36
|
+
elementClass;
|
|
37
|
+
constructor(lineNumber, prefix, color, portals){
|
|
38
|
+
super(), this.lineNumber = lineNumber, this.prefix = prefix, this.color = color, this.portals = portals;
|
|
39
|
+
this.elementClass = cn('px-8 text-center', color ? LINE_COLOR_STYLES[color].text : void 0);
|
|
40
|
+
}
|
|
41
|
+
eq(other) {
|
|
42
|
+
return other instanceof PrefixMarker && other.lineNumber === this.lineNumber && other.prefix === this.prefix && other.color === this.color && other.portals === this.portals;
|
|
43
|
+
}
|
|
44
|
+
toDOM(view) {
|
|
45
|
+
const host = view.dom.ownerDocument.createElement('span');
|
|
46
|
+
const { prefix } = this;
|
|
47
|
+
if ('string' == typeof prefix || 'number' == typeof prefix || 'bigint' == typeof prefix) host.textContent = String(prefix);
|
|
48
|
+
else if (null != prefix && 'boolean' != typeof prefix) prefixPortalIds.set(host, this.portals.register(host, prefix));
|
|
49
|
+
return host;
|
|
50
|
+
}
|
|
51
|
+
destroy(dom) {
|
|
52
|
+
const id = prefixPortalIds.get(dom);
|
|
53
|
+
if (void 0 !== id) {
|
|
54
|
+
prefixPortalIds.delete(dom);
|
|
55
|
+
this.portals.unregister(id);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
class DeletedRowsMarker extends GutterMarker {
|
|
60
|
+
rows;
|
|
61
|
+
elementClass = cn('px-8 text-center', LINE_COLOR_STYLES.danger.text);
|
|
62
|
+
constructor(rows){
|
|
63
|
+
super(), this.rows = rows;
|
|
64
|
+
}
|
|
65
|
+
eq(other) {
|
|
66
|
+
return other instanceof DeletedRowsMarker && other.rows === this.rows;
|
|
67
|
+
}
|
|
68
|
+
toDOM(view) {
|
|
69
|
+
const doc = view.dom.ownerDocument;
|
|
70
|
+
const host = doc.createElement('span');
|
|
71
|
+
for(let row = 0; row < this.rows; row++){
|
|
72
|
+
const cell = doc.createElement('div');
|
|
73
|
+
cell.textContent = '-';
|
|
74
|
+
host.append(cell);
|
|
75
|
+
}
|
|
76
|
+
return host;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const absoluteLineAt = (state, block, startingLineNumber)=>state.doc.lineAt(block.from).number + startingLineNumber - 1;
|
|
80
|
+
const gutterTheme = EditorView.theme({
|
|
81
|
+
'.cm-lineNumbers': {
|
|
82
|
+
color: 'var(--color-text-secondary)',
|
|
83
|
+
userSelect: 'none'
|
|
84
|
+
},
|
|
85
|
+
'.cm-lineNumbers .cm-gutterElement': {
|
|
86
|
+
padding: '0 8px',
|
|
87
|
+
minWidth: '0',
|
|
88
|
+
textAlign: 'right'
|
|
89
|
+
},
|
|
90
|
+
[`.${PREFIX_GUTTER_CLASS}`]: {
|
|
91
|
+
color: 'var(--color-syntax-no-syntax)',
|
|
92
|
+
userSelect: 'none'
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
const buildGutterClassSets = (state, lines, startingLineNumber)=>{
|
|
96
|
+
const background = [];
|
|
97
|
+
const numberText = [];
|
|
98
|
+
for (const [key, config] of Object.entries(lines)){
|
|
99
|
+
if (!config.color) continue;
|
|
100
|
+
const line = lineNumberToDocLine(state.doc, Number(key), startingLineNumber);
|
|
101
|
+
if (!line) continue;
|
|
102
|
+
const styles = LINE_COLOR_STYLES[config.color];
|
|
103
|
+
background.push(new ClassMarker(styles.bg).range(line.from));
|
|
104
|
+
numberText.push(new ClassMarker(styles.text).range(line.from));
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
background: RangeSet.of(background, true),
|
|
108
|
+
numberText: RangeSet.of(numberText, true)
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
const guttersExtension = (config)=>{
|
|
112
|
+
const { lines, startingLineNumber, portals } = config;
|
|
113
|
+
const diff = true === config.diff;
|
|
114
|
+
const configs = Object.values(lines);
|
|
115
|
+
const hasColors = configs.some((line)=>null != line.color);
|
|
116
|
+
const hasPrefixes = configs.some((line)=>null != line.prefix);
|
|
117
|
+
if (!hasColors && !hasPrefixes && !diff && !config.lineNumbers && !config.foldGutter) return [];
|
|
118
|
+
const extensions = [
|
|
119
|
+
gutterTheme
|
|
120
|
+
];
|
|
121
|
+
if (hasColors || diff) {
|
|
122
|
+
const classSets = StateField.define({
|
|
123
|
+
create: (state)=>buildGutterClassSets(state, lines, startingLineNumber),
|
|
124
|
+
update: (value, tr)=>tr.docChanged ? buildGutterClassSets(tr.state, lines, startingLineNumber) : value,
|
|
125
|
+
provide: (field)=>[
|
|
126
|
+
gutterLineClass.from(field, (sets)=>sets.background),
|
|
127
|
+
lineNumberMarkers.from(field, (sets)=>sets.numberText)
|
|
128
|
+
]
|
|
129
|
+
});
|
|
130
|
+
extensions.push(classSets, gutter({
|
|
131
|
+
class: STICK_GUTTER_CLASS,
|
|
132
|
+
lineMarker: (view, block)=>getStickMarker(diff && isDiffInsertedLine(view.state, block.from) ? 'success' : lines[absoluteLineAt(view.state, block, startingLineNumber)]?.color),
|
|
133
|
+
widgetMarker: (view, _widget, block)=>diff && deletedRowCount(view.state, block) > 0 ? getStickMarker('danger') : null,
|
|
134
|
+
lineMarkerChange: diff ? diffChunksChanged : null,
|
|
135
|
+
initialSpacer: ()=>transparentStick
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
if (config.lineNumbers) extensions.push(lineNumbers({
|
|
139
|
+
formatNumber: (lineNo)=>String(lineNo + startingLineNumber - 1)
|
|
140
|
+
}));
|
|
141
|
+
if (config.foldGutter) extensions.push(config.foldGutter);
|
|
142
|
+
if (hasPrefixes || diff) extensions.push(gutter({
|
|
143
|
+
class: PREFIX_GUTTER_CLASS,
|
|
144
|
+
lineMarker: (view, block)=>{
|
|
145
|
+
const absolute = absoluteLineAt(view.state, block, startingLineNumber);
|
|
146
|
+
if (diff && isDiffInsertedLine(view.state, block.from)) return new PrefixMarker(absolute, '+', 'success', portals);
|
|
147
|
+
const line = lines[absolute];
|
|
148
|
+
if (line?.prefix == null) return null;
|
|
149
|
+
return new PrefixMarker(absolute, line.prefix, line.color, portals);
|
|
150
|
+
},
|
|
151
|
+
widgetMarker: (view, _widget, block)=>{
|
|
152
|
+
if (!diff) return null;
|
|
153
|
+
const rows = deletedRowCount(view.state, block);
|
|
154
|
+
return rows > 0 ? new DeletedRowsMarker(rows) : null;
|
|
155
|
+
},
|
|
156
|
+
lineMarkerChange: diff ? diffChunksChanged : null
|
|
157
|
+
}));
|
|
158
|
+
return extensions;
|
|
159
|
+
};
|
|
160
|
+
export { PREFIX_GUTTER_CLASS, STICK_GUTTER_CLASS, guttersExtension };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type AnnotationType, type ChangeSpec } from '@codemirror/state';
|
|
2
|
+
import type { EditorHandle, EngineCallbacks, EngineOptions } from './types';
|
|
3
|
+
/** Marks transactions that sync the `value` prop into the editor — never echoed to `onChange`. */
|
|
4
|
+
export declare const externalChange: AnnotationType<boolean>;
|
|
5
|
+
/**
|
|
6
|
+
* Smallest single replacement turning `from` into `to` (common prefix/suffix),
|
|
7
|
+
* so an external value sync does not move the cursor. Never splits a UTF-16
|
|
8
|
+
* surrogate pair. `null` when the strings are equal.
|
|
9
|
+
*/
|
|
10
|
+
export declare const minimalChange: (from: string, to: string) => ChangeSpec | null;
|
|
11
|
+
export { searchConfigured } from './search';
|
|
12
|
+
export declare const createEditor: (parent: HTMLElement, initialOptions: EngineOptions, callbacks: EngineCallbacks) => EditorHandle;
|