@progressive-development/pd-content 1.1.0 → 1.1.2

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.
Files changed (53) hide show
  1. package/dist/node_modules/.pnpm/@codemirror_autocomplete@6.20.1/node_modules/@codemirror/autocomplete/dist/index.js +550 -0
  2. package/dist/node_modules/.pnpm/@codemirror_lang-css@6.3.1/node_modules/@codemirror/lang-css/dist/index.js +264 -0
  3. package/dist/node_modules/.pnpm/@codemirror_lang-html@6.4.11/node_modules/@codemirror/lang-html/dist/index.js +661 -0
  4. package/dist/node_modules/.pnpm/@codemirror_lang-java@6.0.2/node_modules/@codemirror/lang-java/dist/index.js +44 -0
  5. package/dist/node_modules/.pnpm/@codemirror_lang-javascript@6.2.5/node_modules/@codemirror/lang-javascript/dist/index.js +346 -0
  6. package/dist/node_modules/.pnpm/@codemirror_lang-json@6.0.2/node_modules/@codemirror/lang-json/dist/index.js +32 -0
  7. package/dist/node_modules/.pnpm/@codemirror_lang-markdown@6.5.0/node_modules/@codemirror/lang-markdown/dist/index.js +492 -0
  8. package/dist/node_modules/.pnpm/@codemirror_lang-python@6.2.1/node_modules/@codemirror/lang-python/dist/index.js +308 -0
  9. package/dist/node_modules/.pnpm/@codemirror_language@6.12.3/node_modules/@codemirror/language/dist/index.js +1572 -0
  10. package/dist/node_modules/.pnpm/@codemirror_state@6.6.0/node_modules/@codemirror/state/dist/index.js +3881 -0
  11. package/dist/node_modules/.pnpm/@codemirror_view@6.40.0/node_modules/@codemirror/view/dist/index.js +9657 -0
  12. package/dist/node_modules/.pnpm/@lezer_common@1.5.1/node_modules/@lezer/common/dist/index.js +2196 -0
  13. package/dist/node_modules/.pnpm/@lezer_css@1.3.3/node_modules/@lezer/css/dist/index.js +147 -0
  14. package/dist/node_modules/.pnpm/@lezer_highlight@1.2.3/node_modules/@lezer/highlight/dist/index.js +898 -0
  15. package/dist/node_modules/.pnpm/@lezer_html@1.3.13/node_modules/@lezer/html/dist/index.js +349 -0
  16. package/dist/node_modules/.pnpm/@lezer_java@1.1.3/node_modules/@lezer/java/dist/index.js +67 -0
  17. package/dist/node_modules/.pnpm/@lezer_javascript@1.5.4/node_modules/@lezer/javascript/dist/index.js +192 -0
  18. package/dist/node_modules/.pnpm/@lezer_json@1.0.3/node_modules/@lezer/json/dist/index.js +37 -0
  19. package/dist/node_modules/.pnpm/@lezer_lr@1.4.8/node_modules/@lezer/lr/dist/index.js +1884 -0
  20. package/dist/node_modules/.pnpm/@lezer_markdown@1.6.3/node_modules/@lezer/markdown/dist/index.js +2335 -0
  21. package/dist/node_modules/.pnpm/@lezer_python@1.1.18/node_modules/@lezer/python/dist/index.js +326 -0
  22. package/dist/node_modules/.pnpm/@marijn_find-cluster-break@1.0.2/node_modules/@marijn/find-cluster-break/src/index.js +82 -0
  23. package/dist/node_modules/.pnpm/style-mod@4.1.3/node_modules/style-mod/src/style-mod.js +174 -0
  24. package/dist/node_modules/.pnpm/w3c-keyname@2.2.8/node_modules/w3c-keyname/index.js +121 -0
  25. package/dist/pd-badge-order/PdBadgeItem.d.ts +11 -0
  26. package/dist/pd-badge-order/PdBadgeItem.d.ts.map +1 -1
  27. package/dist/pd-badge-order/PdBadgeItem.js +162 -10
  28. package/dist/pd-badge-order/PdBadgeOrder.d.ts +56 -17
  29. package/dist/pd-badge-order/PdBadgeOrder.d.ts.map +1 -1
  30. package/dist/pd-badge-order/PdBadgeOrder.js +308 -153
  31. package/dist/pd-badge-order/types.js +3 -1
  32. package/dist/pd-code-snippet/PdCodeSnippet.d.ts +29 -0
  33. package/dist/pd-code-snippet/PdCodeSnippet.d.ts.map +1 -1
  34. package/dist/pd-code-snippet/PdCodeSnippet.js +117 -67
  35. package/dist/pd-code-snippet/codemirror-setup.d.ts +10 -0
  36. package/dist/pd-code-snippet/codemirror-setup.d.ts.map +1 -0
  37. package/dist/pd-code-snippet/codemirror-setup.js +101 -0
  38. package/dist/pd-more-info/PdMoreInfo.d.ts +48 -4
  39. package/dist/pd-more-info/PdMoreInfo.d.ts.map +1 -1
  40. package/dist/pd-more-info/PdMoreInfo.js +132 -17
  41. package/dist/pd-notice-box/PdNoticeBox.js +1 -1
  42. package/dist/pd-panel-viewer/PdPanel.d.ts +3 -0
  43. package/dist/pd-panel-viewer/PdPanel.d.ts.map +1 -1
  44. package/dist/pd-panel-viewer/PdPanel.js +8 -1
  45. package/dist/pd-panel-viewer/PdPanelViewer.d.ts +1 -0
  46. package/dist/pd-panel-viewer/PdPanelViewer.d.ts.map +1 -1
  47. package/dist/pd-panel-viewer/PdPanelViewer.js +44 -28
  48. package/dist/pd-timeline/PdTimeline.d.ts +2 -0
  49. package/dist/pd-timeline/PdTimeline.d.ts.map +1 -1
  50. package/dist/pd-timeline/PdTimeline.js +50 -19
  51. package/dist/types.d.ts +1 -0
  52. package/dist/types.d.ts.map +1 -1
  53. package/package.json +16 -6
@@ -0,0 +1,550 @@
1
+ import { Transaction, Text, StateEffect, Annotation, EditorSelection, StateField, Prec, MapMode, Facet, RangeValue } from '../../../../../@codemirror_state@6.6.0/node_modules/@codemirror/state/dist/index.js';
2
+ import { Decoration, EditorView, keymap, WidgetType } from '../../../../../@codemirror_view@6.40.0/node_modules/@codemirror/view/dist/index.js';
3
+ import { syntaxTree, indentUnit } from '../../../../../@codemirror_language@6.12.3/node_modules/@codemirror/language/dist/index.js';
4
+
5
+ /**
6
+ An instance of this is passed to completion source functions.
7
+ */
8
+ class CompletionContext {
9
+ /**
10
+ Create a new completion context. (Mostly useful for testing
11
+ completion sources—in the editor, the extension will create
12
+ these for you.)
13
+ */
14
+ constructor(
15
+ /**
16
+ The editor state that the completion happens in.
17
+ */
18
+ state,
19
+ /**
20
+ The position at which the completion is happening.
21
+ */
22
+ pos,
23
+ /**
24
+ Indicates whether completion was activated explicitly, or
25
+ implicitly by typing. The usual way to respond to this is to
26
+ only return completions when either there is part of a
27
+ completable entity before the cursor, or `explicit` is true.
28
+ */
29
+ explicit,
30
+ /**
31
+ The editor view. May be undefined if the context was created
32
+ in a situation where there is no such view available, such as
33
+ in synchronous updates via
34
+ [`CompletionResult.update`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.update)
35
+ or when called by test code.
36
+ */
37
+ view) {
38
+ this.state = state;
39
+ this.pos = pos;
40
+ this.explicit = explicit;
41
+ this.view = view;
42
+ /**
43
+ @internal
44
+ */
45
+ this.abortListeners = [];
46
+ /**
47
+ @internal
48
+ */
49
+ this.abortOnDocChange = false;
50
+ }
51
+ /**
52
+ Get the extent, content, and (if there is a token) type of the
53
+ token before `this.pos`.
54
+ */
55
+ tokenBefore(types) {
56
+ let token = syntaxTree(this.state).resolveInner(this.pos, -1);
57
+ while (token && types.indexOf(token.name) < 0)
58
+ token = token.parent;
59
+ return token ? { from: token.from, to: this.pos,
60
+ text: this.state.sliceDoc(token.from, this.pos),
61
+ type: token.type } : null;
62
+ }
63
+ /**
64
+ Get the match of the given expression directly before the
65
+ cursor.
66
+ */
67
+ matchBefore(expr) {
68
+ let line = this.state.doc.lineAt(this.pos);
69
+ let start = Math.max(line.from, this.pos - 250);
70
+ let str = line.text.slice(start - line.from, this.pos - line.from);
71
+ let found = str.search(ensureAnchor(expr));
72
+ return found < 0 ? null : { from: start + found, to: this.pos, text: str.slice(found) };
73
+ }
74
+ /**
75
+ Yields true when the query has been aborted. Can be useful in
76
+ asynchronous queries to avoid doing work that will be ignored.
77
+ */
78
+ get aborted() { return this.abortListeners == null; }
79
+ /**
80
+ Allows you to register abort handlers, which will be called when
81
+ the query is
82
+ [aborted](https://codemirror.net/6/docs/ref/#autocomplete.CompletionContext.aborted).
83
+
84
+ By default, running queries will not be aborted for regular
85
+ typing or backspacing, on the assumption that they are likely to
86
+ return a result with a
87
+ [`validFor`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.validFor) field that
88
+ allows the result to be used after all. Passing `onDocChange:
89
+ true` will cause this query to be aborted for any document
90
+ change.
91
+ */
92
+ addEventListener(type, listener, options) {
93
+ if (type == "abort" && this.abortListeners) {
94
+ this.abortListeners.push(listener);
95
+ if (options && options.onDocChange)
96
+ this.abortOnDocChange = true;
97
+ }
98
+ }
99
+ }
100
+ function toSet(chars) {
101
+ let flat = Object.keys(chars).join("");
102
+ let words = /\w/.test(flat);
103
+ if (words)
104
+ flat = flat.replace(/\w/g, "");
105
+ return `[${words ? "\\w" : ""}${flat.replace(/[^\w\s]/g, "\\$&")}]`;
106
+ }
107
+ function prefixMatch(options) {
108
+ let first = Object.create(null), rest = Object.create(null);
109
+ for (let { label } of options) {
110
+ first[label[0]] = true;
111
+ for (let i = 1; i < label.length; i++)
112
+ rest[label[i]] = true;
113
+ }
114
+ let source = toSet(first) + toSet(rest) + "*$";
115
+ return [new RegExp("^" + source), new RegExp(source)];
116
+ }
117
+ /**
118
+ Given a a fixed array of options, return an autocompleter that
119
+ completes them.
120
+ */
121
+ function completeFromList(list) {
122
+ let options = list.map(o => typeof o == "string" ? { label: o } : o);
123
+ let [validFor, match] = options.every(o => /^\w+$/.test(o.label)) ? [/\w*$/, /\w+$/] : prefixMatch(options);
124
+ return (context) => {
125
+ let token = context.matchBefore(match);
126
+ return token || context.explicit ? { from: token ? token.from : context.pos, options, validFor } : null;
127
+ };
128
+ }
129
+ /**
130
+ Wrap the given completion source so that it will not fire when the
131
+ cursor is in a syntax node with one of the given names.
132
+ */
133
+ function ifNotIn(nodes, source) {
134
+ return (context) => {
135
+ for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent) {
136
+ if (nodes.indexOf(pos.name) > -1)
137
+ return null;
138
+ if (pos.type.isTop)
139
+ break;
140
+ }
141
+ return source(context);
142
+ };
143
+ }
144
+ // Make sure the given regexp has a $ at its end and, if `start` is
145
+ // true, a ^ at its start.
146
+ function ensureAnchor(expr, start) {
147
+ var _a;
148
+ let { source } = expr;
149
+ let addEnd = source[source.length - 1] != "$";
150
+ if (!addEnd)
151
+ return expr;
152
+ return new RegExp(`${""}(?:${source})${addEnd ? "$" : ""}`, (_a = expr.flags) !== null && _a !== void 0 ? _a : (expr.ignoreCase ? "i" : ""));
153
+ }
154
+ /**
155
+ This annotation is added to transactions that are produced by
156
+ picking a completion.
157
+ */
158
+ const pickedCompletion = /*@__PURE__*/Annotation.define();
159
+
160
+ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
161
+ ".cm-tooltip.cm-tooltip-autocomplete": {
162
+ "& > ul": {
163
+ fontFamily: "monospace",
164
+ whiteSpace: "nowrap",
165
+ overflow: "hidden auto",
166
+ maxWidth_fallback: "700px",
167
+ maxWidth: "min(700px, 95vw)",
168
+ minWidth: "250px",
169
+ maxHeight: "10em",
170
+ height: "100%",
171
+ listStyle: "none",
172
+ margin: 0,
173
+ padding: 0,
174
+ "& > li, & > completion-section": {
175
+ padding: "1px 3px",
176
+ lineHeight: 1.2
177
+ },
178
+ "& > li": {
179
+ overflowX: "hidden",
180
+ textOverflow: "ellipsis",
181
+ cursor: "pointer"
182
+ },
183
+ "& > completion-section": {
184
+ display: "list-item",
185
+ borderBottom: "1px solid silver",
186
+ paddingLeft: "0.5em",
187
+ opacity: 0.7
188
+ }
189
+ }
190
+ },
191
+ "&light .cm-tooltip-autocomplete ul li[aria-selected]": {
192
+ background: "#17c",
193
+ color: "white",
194
+ },
195
+ "&light .cm-tooltip-autocomplete-disabled ul li[aria-selected]": {
196
+ background: "#777",
197
+ },
198
+ "&dark .cm-tooltip-autocomplete ul li[aria-selected]": {
199
+ background: "#347",
200
+ color: "white",
201
+ },
202
+ "&dark .cm-tooltip-autocomplete-disabled ul li[aria-selected]": {
203
+ background: "#444",
204
+ },
205
+ ".cm-completionListIncompleteTop:before, .cm-completionListIncompleteBottom:after": {
206
+ content: '"···"',
207
+ opacity: 0.5,
208
+ display: "block",
209
+ textAlign: "center"
210
+ },
211
+ ".cm-tooltip.cm-completionInfo": {
212
+ position: "absolute",
213
+ padding: "3px 9px",
214
+ width: "max-content",
215
+ maxWidth: `${400 /* Info.Width */}px`,
216
+ boxSizing: "border-box",
217
+ whiteSpace: "pre-line"
218
+ },
219
+ ".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
220
+ ".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
221
+ ".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Info.Margin */}px` },
222
+ ".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Info.Margin */}px` },
223
+ "&light .cm-snippetField": { backgroundColor: "#00000022" },
224
+ "&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
225
+ ".cm-snippetFieldPosition": {
226
+ verticalAlign: "text-top",
227
+ width: 0,
228
+ height: "1.15em",
229
+ display: "inline-block",
230
+ margin: "0 -0.7px -.7em",
231
+ borderLeft: "1.4px dotted #888"
232
+ },
233
+ ".cm-completionMatchedText": {
234
+ textDecoration: "underline"
235
+ },
236
+ ".cm-completionDetail": {
237
+ marginLeft: "0.5em",
238
+ fontStyle: "italic"
239
+ },
240
+ ".cm-completionIcon": {
241
+ fontSize: "90%",
242
+ width: ".8em",
243
+ display: "inline-block",
244
+ textAlign: "center",
245
+ paddingRight: ".6em",
246
+ opacity: "0.6",
247
+ boxSizing: "content-box"
248
+ },
249
+ ".cm-completionIcon-function, .cm-completionIcon-method": {
250
+ "&:after": { content: "'ƒ'" }
251
+ },
252
+ ".cm-completionIcon-class": {
253
+ "&:after": { content: "'○'" }
254
+ },
255
+ ".cm-completionIcon-interface": {
256
+ "&:after": { content: "'◌'" }
257
+ },
258
+ ".cm-completionIcon-variable": {
259
+ "&:after": { content: "'𝑥'" }
260
+ },
261
+ ".cm-completionIcon-constant": {
262
+ "&:after": { content: "'𝐶'" }
263
+ },
264
+ ".cm-completionIcon-type": {
265
+ "&:after": { content: "'𝑡'" }
266
+ },
267
+ ".cm-completionIcon-enum": {
268
+ "&:after": { content: "'∪'" }
269
+ },
270
+ ".cm-completionIcon-property": {
271
+ "&:after": { content: "'□'" }
272
+ },
273
+ ".cm-completionIcon-keyword": {
274
+ "&:after": { content: "'🔑\uFE0E'" } // Disable emoji rendering
275
+ },
276
+ ".cm-completionIcon-namespace": {
277
+ "&:after": { content: "'▢'" }
278
+ },
279
+ ".cm-completionIcon-text": {
280
+ "&:after": { content: "'abc'", fontSize: "50%", verticalAlign: "middle" }
281
+ }
282
+ });
283
+
284
+ class FieldPos {
285
+ constructor(field, line, from, to) {
286
+ this.field = field;
287
+ this.line = line;
288
+ this.from = from;
289
+ this.to = to;
290
+ }
291
+ }
292
+ class FieldRange {
293
+ constructor(field, from, to) {
294
+ this.field = field;
295
+ this.from = from;
296
+ this.to = to;
297
+ }
298
+ map(changes) {
299
+ let from = changes.mapPos(this.from, -1, MapMode.TrackDel);
300
+ let to = changes.mapPos(this.to, 1, MapMode.TrackDel);
301
+ return from == null || to == null ? null : new FieldRange(this.field, from, to);
302
+ }
303
+ }
304
+ class Snippet {
305
+ constructor(lines, fieldPositions) {
306
+ this.lines = lines;
307
+ this.fieldPositions = fieldPositions;
308
+ }
309
+ instantiate(state, pos) {
310
+ let text = [], lineStart = [pos];
311
+ let lineObj = state.doc.lineAt(pos), baseIndent = /^\s*/.exec(lineObj.text)[0];
312
+ for (let line of this.lines) {
313
+ if (text.length) {
314
+ let indent = baseIndent, tabs = /^\t*/.exec(line)[0].length;
315
+ for (let i = 0; i < tabs; i++)
316
+ indent += state.facet(indentUnit);
317
+ lineStart.push(pos + indent.length - tabs);
318
+ line = indent + line.slice(tabs);
319
+ }
320
+ text.push(line);
321
+ pos += line.length + 1;
322
+ }
323
+ let ranges = this.fieldPositions.map(pos => new FieldRange(pos.field, lineStart[pos.line] + pos.from, lineStart[pos.line] + pos.to));
324
+ return { text, ranges };
325
+ }
326
+ static parse(template) {
327
+ let fields = [];
328
+ let lines = [], positions = [], m;
329
+ for (let line of template.split(/\r\n?|\n/)) {
330
+ while (m = /[#$]\{(?:(\d+)(?::([^{}]*))?|((?:\\[{}]|[^{}])*))\}/.exec(line)) {
331
+ let seq = m[1] ? +m[1] : null, rawName = m[2] || m[3] || "", found = -1;
332
+ let name = rawName.replace(/\\[{}]/g, m => m[1]);
333
+ for (let i = 0; i < fields.length; i++) {
334
+ if (seq != null ? fields[i].seq == seq : name ? fields[i].name == name : false)
335
+ found = i;
336
+ }
337
+ if (found < 0) {
338
+ let i = 0;
339
+ while (i < fields.length && (seq == null || (fields[i].seq != null && fields[i].seq < seq)))
340
+ i++;
341
+ fields.splice(i, 0, { seq, name });
342
+ found = i;
343
+ for (let pos of positions)
344
+ if (pos.field >= found)
345
+ pos.field++;
346
+ }
347
+ for (let pos of positions)
348
+ if (pos.line == lines.length && pos.from > m.index) {
349
+ let snip = m[2] ? 3 + (m[1] || "").length : 2;
350
+ pos.from -= snip;
351
+ pos.to -= snip;
352
+ }
353
+ positions.push(new FieldPos(found, lines.length, m.index, m.index + name.length));
354
+ line = line.slice(0, m.index) + rawName + line.slice(m.index + m[0].length);
355
+ }
356
+ line = line.replace(/\\([{}])/g, (_, brace, index) => {
357
+ for (let pos of positions)
358
+ if (pos.line == lines.length && pos.from > index) {
359
+ pos.from--;
360
+ pos.to--;
361
+ }
362
+ return brace;
363
+ });
364
+ lines.push(line);
365
+ }
366
+ return new Snippet(lines, positions);
367
+ }
368
+ }
369
+ let fieldMarker = /*@__PURE__*/Decoration.widget({ widget: /*@__PURE__*/new class extends WidgetType {
370
+ toDOM() {
371
+ let span = document.createElement("span");
372
+ span.className = "cm-snippetFieldPosition";
373
+ return span;
374
+ }
375
+ ignoreEvent() { return false; }
376
+ } });
377
+ let fieldRange = /*@__PURE__*/Decoration.mark({ class: "cm-snippetField" });
378
+ class ActiveSnippet {
379
+ constructor(ranges, active) {
380
+ this.ranges = ranges;
381
+ this.active = active;
382
+ this.deco = Decoration.set(ranges.map(r => (r.from == r.to ? fieldMarker : fieldRange).range(r.from, r.to)), true);
383
+ }
384
+ map(changes) {
385
+ let ranges = [];
386
+ for (let r of this.ranges) {
387
+ let mapped = r.map(changes);
388
+ if (!mapped)
389
+ return null;
390
+ ranges.push(mapped);
391
+ }
392
+ return new ActiveSnippet(ranges, this.active);
393
+ }
394
+ selectionInsideField(sel) {
395
+ return sel.ranges.every(range => this.ranges.some(r => r.field == this.active && r.from <= range.from && r.to >= range.to));
396
+ }
397
+ }
398
+ const setActive = /*@__PURE__*/StateEffect.define({
399
+ map(value, changes) { return value && value.map(changes); }
400
+ });
401
+ const moveToField = /*@__PURE__*/StateEffect.define();
402
+ const snippetState = /*@__PURE__*/StateField.define({
403
+ create() { return null; },
404
+ update(value, tr) {
405
+ for (let effect of tr.effects) {
406
+ if (effect.is(setActive))
407
+ return effect.value;
408
+ if (effect.is(moveToField) && value)
409
+ return new ActiveSnippet(value.ranges, effect.value);
410
+ }
411
+ if (value && tr.docChanged)
412
+ value = value.map(tr.changes);
413
+ if (value && tr.selection && !value.selectionInsideField(tr.selection))
414
+ value = null;
415
+ return value;
416
+ },
417
+ provide: f => EditorView.decorations.from(f, val => val ? val.deco : Decoration.none)
418
+ });
419
+ function fieldSelection(ranges, field) {
420
+ return EditorSelection.create(ranges.filter(r => r.field == field).map(r => EditorSelection.range(r.from, r.to)));
421
+ }
422
+ /**
423
+ Convert a snippet template to a function that can
424
+ [apply](https://codemirror.net/6/docs/ref/#autocomplete.Completion.apply) it. Snippets are written
425
+ using syntax like this:
426
+
427
+ "for (let ${index} = 0; ${index} < ${end}; ${index}++) {\n\t${}\n}"
428
+
429
+ Each `${}` placeholder (you may also use `#{}`) indicates a field
430
+ that the user can fill in. Its name, if any, will be the default
431
+ content for the field.
432
+
433
+ When the snippet is activated by calling the returned function,
434
+ the code is inserted at the given position. Newlines in the
435
+ template are indented by the indentation of the start line, plus
436
+ one [indent unit](https://codemirror.net/6/docs/ref/#language.indentUnit) per tab character after
437
+ the newline.
438
+
439
+ On activation, (all instances of) the first field are selected.
440
+ The user can move between fields with Tab and Shift-Tab as long as
441
+ the fields are active. Moving to the last field or moving the
442
+ cursor out of the current field deactivates the fields.
443
+
444
+ The order of fields defaults to textual order, but you can add
445
+ numbers to placeholders (`${1}` or `${1:defaultText}`) to provide
446
+ a custom order.
447
+
448
+ To include a literal `{` or `}` in your template, put a backslash
449
+ in front of it. This will be removed and the brace will not be
450
+ interpreted as indicating a placeholder.
451
+ */
452
+ function snippet(template) {
453
+ let snippet = Snippet.parse(template);
454
+ return (editor, completion, from, to) => {
455
+ let { text, ranges } = snippet.instantiate(editor.state, from);
456
+ let { main } = editor.state.selection;
457
+ let spec = {
458
+ changes: { from, to: to == main.from ? main.to : to, insert: Text.of(text) },
459
+ scrollIntoView: true,
460
+ annotations: completion ? [pickedCompletion.of(completion), Transaction.userEvent.of("input.complete")] : undefined
461
+ };
462
+ if (ranges.length)
463
+ spec.selection = fieldSelection(ranges, 0);
464
+ if (ranges.some(r => r.field > 0)) {
465
+ let active = new ActiveSnippet(ranges, 0);
466
+ let effects = spec.effects = [setActive.of(active)];
467
+ if (editor.state.field(snippetState, false) === undefined)
468
+ effects.push(StateEffect.appendConfig.of([snippetState, addSnippetKeymap, snippetPointerHandler, baseTheme]));
469
+ }
470
+ editor.dispatch(editor.state.update(spec));
471
+ };
472
+ }
473
+ function moveField(dir) {
474
+ return ({ state, dispatch }) => {
475
+ let active = state.field(snippetState, false);
476
+ if (!active || dir < 0 && active.active == 0)
477
+ return false;
478
+ let next = active.active + dir, last = dir > 0 && !active.ranges.some(r => r.field == next + dir);
479
+ dispatch(state.update({
480
+ selection: fieldSelection(active.ranges, next),
481
+ effects: setActive.of(last ? null : new ActiveSnippet(active.ranges, next)),
482
+ scrollIntoView: true
483
+ }));
484
+ return true;
485
+ };
486
+ }
487
+ /**
488
+ A command that clears the active snippet, if any.
489
+ */
490
+ const clearSnippet = ({ state, dispatch }) => {
491
+ let active = state.field(snippetState, false);
492
+ if (!active)
493
+ return false;
494
+ dispatch(state.update({ effects: setActive.of(null) }));
495
+ return true;
496
+ };
497
+ /**
498
+ Move to the next snippet field, if available.
499
+ */
500
+ const nextSnippetField = /*@__PURE__*/moveField(1);
501
+ /**
502
+ Move to the previous snippet field, if available.
503
+ */
504
+ const prevSnippetField = /*@__PURE__*/moveField(-1);
505
+ const defaultSnippetKeymap = [
506
+ { key: "Tab", run: nextSnippetField, shift: prevSnippetField },
507
+ { key: "Escape", run: clearSnippet }
508
+ ];
509
+ /**
510
+ A facet that can be used to configure the key bindings used by
511
+ snippets. The default binds Tab to
512
+ [`nextSnippetField`](https://codemirror.net/6/docs/ref/#autocomplete.nextSnippetField), Shift-Tab to
513
+ [`prevSnippetField`](https://codemirror.net/6/docs/ref/#autocomplete.prevSnippetField), and Escape
514
+ to [`clearSnippet`](https://codemirror.net/6/docs/ref/#autocomplete.clearSnippet).
515
+ */
516
+ const snippetKeymap = /*@__PURE__*/Facet.define({
517
+ combine(maps) { return maps.length ? maps[0] : defaultSnippetKeymap; }
518
+ });
519
+ const addSnippetKeymap = /*@__PURE__*/Prec.highest(/*@__PURE__*/keymap.compute([snippetKeymap], state => state.facet(snippetKeymap)));
520
+ /**
521
+ Create a completion from a snippet. Returns an object with the
522
+ properties from `completion`, plus an `apply` function that
523
+ applies the snippet.
524
+ */
525
+ function snippetCompletion(template, completion) {
526
+ return { ...completion, apply: snippet(template) };
527
+ }
528
+ const snippetPointerHandler = /*@__PURE__*/EditorView.domEventHandlers({
529
+ mousedown(event, view) {
530
+ let active = view.state.field(snippetState, false), pos;
531
+ if (!active || (pos = view.posAtCoords({ x: event.clientX, y: event.clientY })) == null)
532
+ return false;
533
+ let match = active.ranges.find(r => r.from <= pos && r.to >= pos);
534
+ if (!match || match.field == active.active)
535
+ return false;
536
+ view.dispatch({
537
+ selection: fieldSelection(active.ranges, match.field),
538
+ effects: setActive.of(active.ranges.some(r => r.field > match.field)
539
+ ? new ActiveSnippet(active.ranges, match.field) : null),
540
+ scrollIntoView: true
541
+ });
542
+ return true;
543
+ }
544
+ });
545
+ const closedBracket = /*@__PURE__*/new class extends RangeValue {
546
+ };
547
+ closedBracket.startSide = 1;
548
+ closedBracket.endSide = -1;
549
+
550
+ export { CompletionContext, clearSnippet, completeFromList, ifNotIn, nextSnippetField, pickedCompletion, prevSnippetField, snippet, snippetCompletion, snippetKeymap };