@gjermundgaraba/pixel-paper 0.1.1 → 0.2.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/README.md +11 -1
- package/THIRD_PARTY_NOTICES.md +25 -0
- package/dist/board/board.d.ts +12 -12
- package/dist/copy-button/copy-button.d.ts +4 -4
- package/dist/index.d.ts +44 -43
- package/dist/index.js +2 -1
- package/dist/inline-input/inline-input.d.ts +6 -6
- package/dist/markdown-editor/element.d.ts +4 -0
- package/dist/markdown-editor/element.js +128 -0
- package/dist/markdown-editor/engine.js +94 -0
- package/dist/markdown-editor/index.d.ts +5 -0
- package/dist/markdown-editor/index.js +6 -0
- package/dist/markdown-editor/link-policy.js +18 -0
- package/dist/markdown-editor/live/live.js +438 -0
- package/dist/markdown-editor/live/theme.js +117 -0
- package/dist/markdown-editor/markdown-editor.d.ts +11 -0
- package/dist/markdown-editor/markdown-editor.js +22 -0
- package/dist/markdown-editor/reconcile.js +24 -0
- package/dist/menu/menu.d.ts +4 -4
- package/dist/sortable/sortable.d.ts +12 -12
- package/dist/toast/toast.d.ts +8 -8
- package/package.json +16 -2
- package/src/pixel-paper.css +46 -0
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import { brandViewResult as __foldkitBrandViewResult } from 'foldkit/brand'
|
|
2
|
+
import { safeHref, safeImageSource } from "../link-policy.js";
|
|
3
|
+
import { liveMarkdownTheme } from "./theme.js";
|
|
4
|
+
import { syntaxTree } from "@codemirror/language";
|
|
5
|
+
import { Prec, RangeSetBuilder, StateEffect, StateField } from "@codemirror/state";
|
|
6
|
+
import { Decoration, EditorView, ViewPlugin, WidgetType, keymap } from "@codemirror/view";
|
|
7
|
+
// src/markdown-editor/live/live.ts
|
|
8
|
+
const UNKNOWN_HEIGHT = -1;
|
|
9
|
+
const TABLE_ROW_HEIGHT = 32;
|
|
10
|
+
const IMAGE_ESTIMATED_HEIGHT = 240;
|
|
11
|
+
const TABLE_HINT = "Click to edit the table";
|
|
12
|
+
var DrawnWidget = class extends WidgetType {
|
|
13
|
+
drawing;
|
|
14
|
+
constructor(drawing) {
|
|
15
|
+
super();
|
|
16
|
+
this.drawing = drawing;
|
|
17
|
+
}
|
|
18
|
+
eq(other) {
|
|
19
|
+
return __foldkitBrandViewResult((other.drawing.key === this.drawing.key), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#eq");
|
|
20
|
+
}
|
|
21
|
+
toDOM(view) {
|
|
22
|
+
return __foldkitBrandViewResult((this.drawing.draw(view)), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#toDOM");
|
|
23
|
+
}
|
|
24
|
+
get estimatedHeight() {
|
|
25
|
+
return __foldkitBrandViewResult((this.drawing.estimatedHeight), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#estimatedHeight");
|
|
26
|
+
}
|
|
27
|
+
ignoreEvent() {
|
|
28
|
+
return __foldkitBrandViewResult((this.drawing.takesOwnEvents), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#ignoreEvent");
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const spanOf = (className, text) => {
|
|
32
|
+
const span = document.createElement("span");
|
|
33
|
+
span.className = className;
|
|
34
|
+
span.textContent = text;
|
|
35
|
+
return __foldkitBrandViewResult((span), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#spanOf");
|
|
36
|
+
};
|
|
37
|
+
const checkboxWidget = (isChecked) => __foldkitBrandViewResult((new DrawnWidget({
|
|
38
|
+
key: `checkbox:${isChecked}`,
|
|
39
|
+
draw: () => {
|
|
40
|
+
const box = document.createElement("input");
|
|
41
|
+
box.type = "checkbox";
|
|
42
|
+
box.checked = isChecked;
|
|
43
|
+
box.className = "lmd-check";
|
|
44
|
+
box.tabIndex = -1;
|
|
45
|
+
return __foldkitBrandViewResult((box), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#draw");
|
|
46
|
+
},
|
|
47
|
+
estimatedHeight: UNKNOWN_HEIGHT,
|
|
48
|
+
takesOwnEvents: false
|
|
49
|
+
})), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#checkboxWidget");
|
|
50
|
+
const bulletWidget = new DrawnWidget({
|
|
51
|
+
key: "bullet",
|
|
52
|
+
draw: () => __foldkitBrandViewResult((spanOf("lmd-bullet", "•")), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#draw~2"),
|
|
53
|
+
estimatedHeight: UNKNOWN_HEIGHT,
|
|
54
|
+
takesOwnEvents: true
|
|
55
|
+
});
|
|
56
|
+
const imageWidget = (source, alt) => __foldkitBrandViewResult((new DrawnWidget({
|
|
57
|
+
key: `image:${source}\n${alt}`,
|
|
58
|
+
draw: () => {
|
|
59
|
+
const box = spanOf("lmd-img-box", "");
|
|
60
|
+
const safeSource = safeImageSource(source, document.baseURI);
|
|
61
|
+
if (safeSource === void 0) {
|
|
62
|
+
box.append(spanOf("lmd-img-note", alt === "" ? "Image not shown" : alt));
|
|
63
|
+
return __foldkitBrandViewResult((box), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#draw~3");
|
|
64
|
+
}
|
|
65
|
+
const image = document.createElement("img");
|
|
66
|
+
image.className = "lmd-img";
|
|
67
|
+
image.alt = alt;
|
|
68
|
+
image.referrerPolicy = "no-referrer";
|
|
69
|
+
image.addEventListener("error", () => {
|
|
70
|
+
image.replaceWith(spanOf("lmd-img-note", alt === "" ? "Image not found" : `Image not found: ${alt}`));
|
|
71
|
+
}, { once: true });
|
|
72
|
+
image.src = safeSource;
|
|
73
|
+
box.append(image);
|
|
74
|
+
return __foldkitBrandViewResult((box), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#draw~3");
|
|
75
|
+
},
|
|
76
|
+
estimatedHeight: IMAGE_ESTIMATED_HEIGHT,
|
|
77
|
+
takesOwnEvents: false
|
|
78
|
+
})), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#imageWidget");
|
|
79
|
+
const isList = (node) => __foldkitBrandViewResult((node?.name === "BulletList" || node?.name === "OrderedList"), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#isList");
|
|
80
|
+
const hide = Decoration.replace({});
|
|
81
|
+
const mark = (className) => __foldkitBrandViewResult((Decoration.mark({ class: className })), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#mark");
|
|
82
|
+
const line = (className) => __foldkitBrandViewResult((Decoration.line({ class: className })), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#line");
|
|
83
|
+
const INLINE = /* @__PURE__ */ new Map([
|
|
84
|
+
["Emphasis", "lmd-em"],
|
|
85
|
+
["StrongEmphasis", "lmd-strong"],
|
|
86
|
+
["Strikethrough", "lmd-strike"],
|
|
87
|
+
["InlineCode", "lmd-code"],
|
|
88
|
+
["Link", "lmd-link"]
|
|
89
|
+
]);
|
|
90
|
+
const HIDDEN_MARKS = /* @__PURE__ */ new Set([
|
|
91
|
+
"EmphasisMark",
|
|
92
|
+
"StrikethroughMark",
|
|
93
|
+
"LinkMark",
|
|
94
|
+
"URL"
|
|
95
|
+
]);
|
|
96
|
+
const ATX_HEADING = /^ATXHeading(?<level>\d)$/u;
|
|
97
|
+
const ANGLE_BRACKETED = /^<(?<destination>.*)>$/su;
|
|
98
|
+
const EMAIL = /^[^\s:@]+@[^\s:@]+$/u;
|
|
99
|
+
const URL_OWNERS = /* @__PURE__ */ new Set([
|
|
100
|
+
"Link",
|
|
101
|
+
"Image",
|
|
102
|
+
"LinkReference"
|
|
103
|
+
]);
|
|
104
|
+
const isPlainBrackets = (node) => __foldkitBrandViewResult(((node.name === "Link" || node.name === "Image") && node.getChild("URL") === null), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#isPlainBrackets");
|
|
105
|
+
const isBareUrl = (node) => __foldkitBrandViewResult((node.name === "URL" && !URL_OWNERS.has(node.parent?.name ?? "")), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#isBareUrl");
|
|
106
|
+
/** The live layer's decorations over the visible ranges, as a ViewPlugin may provide them. */
|
|
107
|
+
const liveDecorations = (state, visibleRanges, isFocused) => {
|
|
108
|
+
const { ranges } = state.selection;
|
|
109
|
+
const touched = (from, to) => __foldkitBrandViewResult((isFocused && ranges.some((range) => __foldkitBrandViewResult((range.from <= to && range.to >= from), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#anonymous~2"))), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#touched");
|
|
110
|
+
const activeLine = (position) => {
|
|
111
|
+
const { from, to } = state.doc.lineAt(position);
|
|
112
|
+
return __foldkitBrandViewResult((touched(from, to)), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#activeLine");
|
|
113
|
+
};
|
|
114
|
+
const placed = [];
|
|
115
|
+
const add = (from, to, decoration) => {
|
|
116
|
+
placed.push({
|
|
117
|
+
from,
|
|
118
|
+
to,
|
|
119
|
+
decoration,
|
|
120
|
+
isReplace: decoration === hide
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
const replace = (from, to, widget) => {
|
|
124
|
+
placed.push({
|
|
125
|
+
from,
|
|
126
|
+
to,
|
|
127
|
+
decoration: Decoration.replace({ widget }),
|
|
128
|
+
isReplace: true
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
const addLine = (position, decoration) => {
|
|
132
|
+
placed.push({
|
|
133
|
+
from: position,
|
|
134
|
+
to: position,
|
|
135
|
+
decoration,
|
|
136
|
+
isReplace: false
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
const addLines = (from, to, className) => {
|
|
140
|
+
for (let position = from; position <= to;) {
|
|
141
|
+
const { from: start, to: end } = state.doc.lineAt(position);
|
|
142
|
+
addLine(start, line(className));
|
|
143
|
+
position = end + 1;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
const hideWithFollowingSpace = (from, to) => {
|
|
147
|
+
add(from, state.sliceDoc(to, to + 1) === " " ? to + 1 : to, hide);
|
|
148
|
+
};
|
|
149
|
+
for (const { from, to } of visibleRanges) syntaxTree(state).iterate({
|
|
150
|
+
from,
|
|
151
|
+
to,
|
|
152
|
+
enter: (node) => {
|
|
153
|
+
const { name } = node;
|
|
154
|
+
const { parent } = node.node;
|
|
155
|
+
const level = ATX_HEADING.exec(name)?.groups?.["level"];
|
|
156
|
+
if (level !== void 0) {
|
|
157
|
+
addLine(state.doc.lineAt(node.from).from, line(`lmd-h lmd-h${level}`));
|
|
158
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
159
|
+
}
|
|
160
|
+
if (name === "HeaderMark" && parent?.name.startsWith("ATXHeading") === true) {
|
|
161
|
+
if (!activeLine(node.from)) hideWithFollowingSpace(node.from, node.to);
|
|
162
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
163
|
+
}
|
|
164
|
+
if (name === "LinkReference") return __foldkitBrandViewResult((false), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
165
|
+
if (isPlainBrackets(node.node)) return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
166
|
+
if (name === "LinkMark" && parent !== null && isPlainBrackets(parent)) return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
167
|
+
if (name === "Escape") {
|
|
168
|
+
if (!touched(node.from, node.to)) add(node.from, node.from + 1, hide);
|
|
169
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
170
|
+
}
|
|
171
|
+
if (name === "Image") {
|
|
172
|
+
const url = node.node.getChild("URL");
|
|
173
|
+
if (url !== null && !touched(node.from, node.to)) {
|
|
174
|
+
const alt = state.sliceDoc(node.from + 2, Math.max(node.from + 2, url.from - 2));
|
|
175
|
+
replace(node.from, node.to, imageWidget(state.sliceDoc(url.from, url.to).replace(ANGLE_BRACKETED, "$<destination>"), alt));
|
|
176
|
+
}
|
|
177
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
178
|
+
}
|
|
179
|
+
const inlineClass = INLINE.get(name);
|
|
180
|
+
if (inlineClass !== void 0) {
|
|
181
|
+
add(node.from, node.to, mark(inlineClass));
|
|
182
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
183
|
+
}
|
|
184
|
+
if (isBareUrl(node.node)) {
|
|
185
|
+
add(node.from, node.to, mark("lmd-link"));
|
|
186
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
187
|
+
}
|
|
188
|
+
if (parent !== null && (HIDDEN_MARKS.has(name) || name === "CodeMark" && parent.name === "InlineCode")) {
|
|
189
|
+
if (!touched(parent.from, parent.to)) add(node.from, node.to, hide);
|
|
190
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
191
|
+
}
|
|
192
|
+
if (name === "FencedCode" || name === "CodeBlock") {
|
|
193
|
+
addLines(node.from, node.to, "lmd-codeblock");
|
|
194
|
+
return __foldkitBrandViewResult((false), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
195
|
+
}
|
|
196
|
+
if (name === "Blockquote") {
|
|
197
|
+
addLines(node.from, node.to, "lmd-quote");
|
|
198
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
199
|
+
}
|
|
200
|
+
if (name === "QuoteMark") {
|
|
201
|
+
if (!activeLine(node.from)) hideWithFollowingSpace(node.from, node.to);
|
|
202
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
203
|
+
}
|
|
204
|
+
if (name === "HorizontalRule") {
|
|
205
|
+
if (!activeLine(node.from)) {
|
|
206
|
+
addLine(state.doc.lineAt(node.from).from, line("lmd-hr"));
|
|
207
|
+
add(node.from, node.to, hide);
|
|
208
|
+
}
|
|
209
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
210
|
+
}
|
|
211
|
+
if (name === "Table") {
|
|
212
|
+
addLines(node.from, node.to, "lmd-table");
|
|
213
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
214
|
+
}
|
|
215
|
+
if (name === "ListMark" && parent !== null && isList(parent.parent)) {
|
|
216
|
+
if (activeLine(node.from)) return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
217
|
+
if (parent.getChild("Task") !== null) hideWithFollowingSpace(node.from, node.to);
|
|
218
|
+
else if (parent.parent?.name === "BulletList") replace(node.from, node.to, bulletWidget);
|
|
219
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
220
|
+
}
|
|
221
|
+
if (name === "TaskMarker" && !touched(node.from, node.to)) {
|
|
222
|
+
const isChecked = /x/iu.test(state.sliceDoc(node.from, node.to));
|
|
223
|
+
replace(node.from, node.to, checkboxWidget(isChecked));
|
|
224
|
+
if (isChecked && parent !== null) add(node.to, parent.to, mark("lmd-done"));
|
|
225
|
+
}
|
|
226
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter");
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
placed.sort((left, right) => __foldkitBrandViewResult((left.from - right.from || left.decoration.startSide - right.decoration.startSide), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#anonymous~3"));
|
|
230
|
+
const staysOnItsLine = (from, to) => __foldkitBrandViewResult((to <= state.doc.lineAt(from).to), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#staysOnItsLine");
|
|
231
|
+
const builder = new RangeSetBuilder();
|
|
232
|
+
let lastReplaceEnd = -1;
|
|
233
|
+
for (const { from, to, decoration, isReplace } of placed) {
|
|
234
|
+
const isRangeReplace = from !== to && isReplace;
|
|
235
|
+
if (!isRangeReplace || from >= lastReplaceEnd && staysOnItsLine(from, to)) {
|
|
236
|
+
builder.add(from, to, decoration);
|
|
237
|
+
if (isRangeReplace) lastReplaceEnd = to;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return __foldkitBrandViewResult((builder.finish()), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#liveDecorations");
|
|
241
|
+
};
|
|
242
|
+
const DELIMITER_ROW = /^\s*\|?[\s:|-]+\|?\s*$/u;
|
|
243
|
+
const tableCells = (row) => __foldkitBrandViewResult((row.trim().replaceAll(/^\||\|$/gu, "").split(/(?<!\\)\|/u).map((cell) => __foldkitBrandViewResult((cell.trim().replaceAll(String.raw`\|`, "|")), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#anonymous~4"))), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#tableCells");
|
|
244
|
+
const tableOf = (source) => {
|
|
245
|
+
const table = document.createElement("table");
|
|
246
|
+
const head = table.createTHead();
|
|
247
|
+
const body = table.createTBody();
|
|
248
|
+
const rows = source.split("\n").filter((row) => __foldkitBrandViewResult((row.trim() !== ""), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#anonymous~5"));
|
|
249
|
+
table.className = "lmd-table-view";
|
|
250
|
+
for (const [index, row] of rows.entries()) if (index !== 1 || !DELIMITER_ROW.test(row)) {
|
|
251
|
+
const tableRow = document.createElement("tr");
|
|
252
|
+
for (const text of tableCells(row)) {
|
|
253
|
+
const cell = document.createElement(index === 0 ? "th" : "td");
|
|
254
|
+
cell.textContent = text;
|
|
255
|
+
tableRow.append(cell);
|
|
256
|
+
}
|
|
257
|
+
(index === 0 ? head : body).append(tableRow);
|
|
258
|
+
}
|
|
259
|
+
return __foldkitBrandViewResult((table), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#tableOf");
|
|
260
|
+
};
|
|
261
|
+
const tableWidget = (text) => __foldkitBrandViewResult((new DrawnWidget({
|
|
262
|
+
key: `table:${text}`,
|
|
263
|
+
draw: (view) => {
|
|
264
|
+
const dom = document.createElement("div");
|
|
265
|
+
dom.className = "lmd-table-widget";
|
|
266
|
+
dom.title = TABLE_HINT;
|
|
267
|
+
dom.append(tableOf(text));
|
|
268
|
+
dom.addEventListener("mousedown", (event) => {
|
|
269
|
+
event.preventDefault();
|
|
270
|
+
const row = event.target instanceof Element ? event.target.closest("tr") : null;
|
|
271
|
+
const rows = [...dom.querySelectorAll("tr")];
|
|
272
|
+
const rowIndex = row === null ? -1 : rows.indexOf(row);
|
|
273
|
+
const sourceOffset = rowIndex <= 0 ? 0 : rowIndex + 1;
|
|
274
|
+
const first = view.state.doc.lineAt(view.posAtDOM(dom));
|
|
275
|
+
const target = view.state.doc.line(Math.min(first.number + sourceOffset, view.state.doc.lines));
|
|
276
|
+
view.dispatch({ selection: { anchor: Math.min(target.from + 2, target.to) } });
|
|
277
|
+
view.focus();
|
|
278
|
+
});
|
|
279
|
+
return __foldkitBrandViewResult((dom), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#draw~4");
|
|
280
|
+
},
|
|
281
|
+
estimatedHeight: TABLE_ROW_HEIGHT * text.split("\n").length,
|
|
282
|
+
takesOwnEvents: true
|
|
283
|
+
})), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#tableWidget");
|
|
284
|
+
const lastValueOf = (transaction, type, held) => {
|
|
285
|
+
const last = transaction.effects.findLast((effect) => __foldkitBrandViewResult((effect.is(type)), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#anonymous~7"));
|
|
286
|
+
return __foldkitBrandViewResult((last === void 0 ? held : last.value), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#lastValueOf");
|
|
287
|
+
};
|
|
288
|
+
const setFocus = StateEffect.define();
|
|
289
|
+
const setPointerDown = StateEffect.define();
|
|
290
|
+
const pointerDownField = StateField.define({
|
|
291
|
+
create: () => __foldkitBrandViewResult((false), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#create"),
|
|
292
|
+
update: (isDown, transaction) => __foldkitBrandViewResult((lastValueOf(transaction, setPointerDown, isDown)), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#update")
|
|
293
|
+
});
|
|
294
|
+
const POINTER_RELEASE_EVENTS = [
|
|
295
|
+
"mouseup",
|
|
296
|
+
"dragend",
|
|
297
|
+
"contextmenu"
|
|
298
|
+
];
|
|
299
|
+
const holdRevealUntilPointerRelease = (view) => {
|
|
300
|
+
const { ownerDocument } = view.dom;
|
|
301
|
+
const release = () => {
|
|
302
|
+
for (const name of POINTER_RELEASE_EVENTS) ownerDocument.removeEventListener(name, release);
|
|
303
|
+
setTimeout(() => {
|
|
304
|
+
view.dispatch({ effects: setPointerDown.of(false) });
|
|
305
|
+
}, 0);
|
|
306
|
+
};
|
|
307
|
+
view.dispatch({ effects: setPointerDown.of(true) });
|
|
308
|
+
for (const name of POINTER_RELEASE_EVENTS) ownerDocument.addEventListener(name, release);
|
|
309
|
+
};
|
|
310
|
+
const buildTables = (state, isFocused) => {
|
|
311
|
+
const builder = new RangeSetBuilder();
|
|
312
|
+
syntaxTree(state).iterate({ enter: (node) => {
|
|
313
|
+
if (node.name !== "Table") return __foldkitBrandViewResult((node.name === "Document" || node.name.endsWith("List") || node.name === "ListItem" || node.name === "Blockquote"), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter~2");
|
|
314
|
+
const { from } = state.doc.lineAt(node.from);
|
|
315
|
+
const { to } = state.doc.lineAt(node.to);
|
|
316
|
+
const isInside = state.selection.ranges.some((range) => __foldkitBrandViewResult((range.from <= to && range.to >= from), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#anonymous~9"));
|
|
317
|
+
if (from === node.from && !(isFocused && isInside)) builder.add(from, to, Decoration.replace({
|
|
318
|
+
widget: tableWidget(state.sliceDoc(from, to)),
|
|
319
|
+
block: true
|
|
320
|
+
}));
|
|
321
|
+
return __foldkitBrandViewResult((false), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#enter~2");
|
|
322
|
+
} });
|
|
323
|
+
return __foldkitBrandViewResult((builder.finish()), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#buildTables");
|
|
324
|
+
};
|
|
325
|
+
const tablesField = StateField.define({
|
|
326
|
+
create: (state) => (__foldkitBrandViewResult(({
|
|
327
|
+
isFocused: false,
|
|
328
|
+
decorations: buildTables(state, false)
|
|
329
|
+
}), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#create~2")),
|
|
330
|
+
update: (value, transaction) => {
|
|
331
|
+
const isFocused = lastValueOf(transaction, setFocus, value.isFocused);
|
|
332
|
+
const wasDown = transaction.startState.field(pointerDownField);
|
|
333
|
+
const isDown = transaction.state.field(pointerDownField);
|
|
334
|
+
if (isDown && !transaction.docChanged) return __foldkitBrandViewResult(({
|
|
335
|
+
isFocused,
|
|
336
|
+
decorations: value.decorations
|
|
337
|
+
}), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#update~2");
|
|
338
|
+
return __foldkitBrandViewResult((isFocused === value.isFocused && wasDown === isDown && !transaction.docChanged && transaction.selection === void 0 && syntaxTree(transaction.startState) === syntaxTree(transaction.state) ? value : {
|
|
339
|
+
isFocused,
|
|
340
|
+
decorations: buildTables(transaction.state, isFocused)
|
|
341
|
+
}), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#update~2");
|
|
342
|
+
},
|
|
343
|
+
provide: (field) => __foldkitBrandViewResult((EditorView.decorations.from(field, (value) => __foldkitBrandViewResult((value.decorations), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#anonymous~10"))), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#provide")
|
|
344
|
+
});
|
|
345
|
+
const linkHref = (state, node) => {
|
|
346
|
+
const url = node.name === "Link" ? node.getChild("URL") : node;
|
|
347
|
+
if (url === null) return;
|
|
348
|
+
const href = state.sliceDoc(url.from, url.to).replace(ANGLE_BRACKETED, "$<destination>");
|
|
349
|
+
if (/^www\./iu.test(href)) return __foldkitBrandViewResult((`https://${href}`), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#linkHref");
|
|
350
|
+
return __foldkitBrandViewResult((node.name === "URL" && EMAIL.test(href) ? `mailto:${href}` : href), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#linkHref");
|
|
351
|
+
};
|
|
352
|
+
const isLinkNode = (node) => __foldkitBrandViewResult((node.name === "Link" && !isPlainBrackets(node) || isBareUrl(node)), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#isLinkNode");
|
|
353
|
+
const toggleCheckbox = (view, box) => {
|
|
354
|
+
const position = view.posAtDOM(box);
|
|
355
|
+
const text = view.state.sliceDoc(position, position + 3);
|
|
356
|
+
if (!/^\[[ xX]\]$/u.test(text)) return __foldkitBrandViewResult((false), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#toggleCheckbox");
|
|
357
|
+
view.dispatch({ changes: {
|
|
358
|
+
from: position + 1,
|
|
359
|
+
to: position + 2,
|
|
360
|
+
insert: text.charAt(1) === " " ? "x" : " "
|
|
361
|
+
} });
|
|
362
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#toggleCheckbox");
|
|
363
|
+
};
|
|
364
|
+
const linkAt = (state, position, side) => {
|
|
365
|
+
for (let node = syntaxTree(state).resolveInner(position, side); node !== null; node = node.parent) if (isLinkNode(node)) return __foldkitBrandViewResult((linkHref(state, node)), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#linkAt");
|
|
366
|
+
};
|
|
367
|
+
const openLink = (url) => {
|
|
368
|
+
const href = safeHref(url, document.baseURI);
|
|
369
|
+
if (href !== void 0) window.open(href, "_blank", "noopener,noreferrer");
|
|
370
|
+
};
|
|
371
|
+
const openLinkAtCaret = (view) => {
|
|
372
|
+
const { head } = view.state.selection.main;
|
|
373
|
+
const url = linkAt(view.state, head, 1) ?? linkAt(view.state, head, -1);
|
|
374
|
+
if (url === void 0) return __foldkitBrandViewResult((false), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#openLinkAtCaret");
|
|
375
|
+
openLink(url);
|
|
376
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#openLinkAtCaret");
|
|
377
|
+
};
|
|
378
|
+
/** Markdown drawn over its own text, as in Obsidian's Live Preview: the document stays
|
|
379
|
+
* Markdown, and its marks show only around the selection. Redrawing a reveal moves text, so
|
|
380
|
+
* nothing redraws under an IME's composition or a pressed mouse button. */
|
|
381
|
+
const liveMarkdown = () => {
|
|
382
|
+
const preview = ViewPlugin.fromClass(class {
|
|
383
|
+
decorations;
|
|
384
|
+
isStale = false;
|
|
385
|
+
constructor(view) {
|
|
386
|
+
this.decorations = liveDecorations(view.state, view.visibleRanges, view.hasFocus);
|
|
387
|
+
}
|
|
388
|
+
update(update) {
|
|
389
|
+
if (update.view.composing || update.state.field(pointerDownField) && !update.docChanged) {
|
|
390
|
+
this.decorations = this.decorations.map(update.changes);
|
|
391
|
+
this.isStale = true;
|
|
392
|
+
} else if (this.isStale || update.docChanged || update.selectionSet || update.focusChanged || update.viewportChanged || syntaxTree(update.startState) !== syntaxTree(update.state)) {
|
|
393
|
+
this.decorations = liveDecorations(update.state, update.view.visibleRanges, update.view.hasFocus);
|
|
394
|
+
this.isStale = false;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}, {
|
|
398
|
+
decorations: (plugin) => __foldkitBrandViewResult((plugin.decorations), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#decorations"),
|
|
399
|
+
eventObservers: { compositionend: (_, view) => {
|
|
400
|
+
setTimeout(() => {
|
|
401
|
+
view.dispatch({});
|
|
402
|
+
}, 0);
|
|
403
|
+
} },
|
|
404
|
+
eventHandlers: { mousedown: (event, view) => {
|
|
405
|
+
const box = event.target instanceof HTMLInputElement && event.target.classList.contains("lmd-check") ? event.target : void 0;
|
|
406
|
+
if (box !== void 0 && (event.button !== 0 || toggleCheckbox(view, box))) {
|
|
407
|
+
event.preventDefault();
|
|
408
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#mousedown");
|
|
409
|
+
}
|
|
410
|
+
if (event.metaKey || event.ctrlKey) {
|
|
411
|
+
const position = view.posAtCoords({
|
|
412
|
+
x: event.clientX,
|
|
413
|
+
y: event.clientY
|
|
414
|
+
});
|
|
415
|
+
const url = position === null ? void 0 : linkAt(view.state, position, 1);
|
|
416
|
+
if (url !== void 0) {
|
|
417
|
+
openLink(url);
|
|
418
|
+
event.preventDefault();
|
|
419
|
+
return __foldkitBrandViewResult((true), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#mousedown");
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (event.button === 0) holdRevealUntilPointerRelease(view);
|
|
423
|
+
return __foldkitBrandViewResult((false), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#mousedown");
|
|
424
|
+
} }
|
|
425
|
+
});
|
|
426
|
+
return __foldkitBrandViewResult(([
|
|
427
|
+
pointerDownField,
|
|
428
|
+
preview,
|
|
429
|
+
tablesField,
|
|
430
|
+
Prec.high(keymap.of([{
|
|
431
|
+
key: "Mod-Enter",
|
|
432
|
+
run: openLinkAtCaret
|
|
433
|
+
}])),
|
|
434
|
+
EditorView.focusChangeEffect.of((_, isFocusing) => __foldkitBrandViewResult((setFocus.of(isFocusing)), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#anonymous~12")),
|
|
435
|
+
liveMarkdownTheme
|
|
436
|
+
]), "@gjermundgaraba/pixel-paper/markdown-editor/live/live.js#liveMarkdown");
|
|
437
|
+
};
|
|
438
|
+
export { liveDecorations, liveMarkdown };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { EditorView } from "@codemirror/view";
|
|
2
|
+
// src/markdown-editor/live/theme.ts
|
|
3
|
+
const PIXEL_LABEL = {
|
|
4
|
+
fontFamily: "var(--font-px)",
|
|
5
|
+
fontWeight: "400",
|
|
6
|
+
textTransform: "uppercase",
|
|
7
|
+
letterSpacing: "var(--tracking-label)"
|
|
8
|
+
};
|
|
9
|
+
const CODE = {
|
|
10
|
+
fontFamily: "var(--font-code)",
|
|
11
|
+
fontSize: "var(--type-control)"
|
|
12
|
+
};
|
|
13
|
+
/** The live layer's look, in `tokens.css` values alone, so paper and plum both hold. */
|
|
14
|
+
const liveMarkdownTheme = EditorView.baseTheme({
|
|
15
|
+
"&": {
|
|
16
|
+
color: "var(--ink)",
|
|
17
|
+
background: "var(--paper)"
|
|
18
|
+
},
|
|
19
|
+
"&.cm-focused": { outline: "none" },
|
|
20
|
+
".cm-scroller": {
|
|
21
|
+
fontFamily: "var(--font-body)",
|
|
22
|
+
fontSize: "var(--type-body)",
|
|
23
|
+
lineHeight: "1.5",
|
|
24
|
+
overflow: "auto"
|
|
25
|
+
},
|
|
26
|
+
".cm-content": {
|
|
27
|
+
padding: "2px 0",
|
|
28
|
+
caretColor: "var(--ink)"
|
|
29
|
+
},
|
|
30
|
+
".cm-content ::selection": {
|
|
31
|
+
background: "var(--ink)",
|
|
32
|
+
color: "var(--paper)"
|
|
33
|
+
},
|
|
34
|
+
".cm-cursor": { borderLeftColor: "var(--ink)" },
|
|
35
|
+
".cm-line": { padding: "0" },
|
|
36
|
+
".lmd-h": {
|
|
37
|
+
fontWeight: "var(--read-weight)",
|
|
38
|
+
lineHeight: "1.3"
|
|
39
|
+
},
|
|
40
|
+
".lmd-h1, .lmd-h2": { fontSize: "var(--read-h2)" },
|
|
41
|
+
".lmd-h3": { fontSize: "var(--read-h3)" },
|
|
42
|
+
".lmd-h4": {
|
|
43
|
+
...PIXEL_LABEL,
|
|
44
|
+
fontSize: "var(--type-control)"
|
|
45
|
+
},
|
|
46
|
+
".lmd-h5": { fontSize: "var(--type-body)" },
|
|
47
|
+
".lmd-h6": {
|
|
48
|
+
...PIXEL_LABEL,
|
|
49
|
+
fontSize: "var(--type-label)",
|
|
50
|
+
color: "var(--muted)"
|
|
51
|
+
},
|
|
52
|
+
".lmd-strong": { fontWeight: "var(--read-weight)" },
|
|
53
|
+
".lmd-em": { fontStyle: "italic" },
|
|
54
|
+
".lmd-strike, .lmd-done": {
|
|
55
|
+
textDecoration: "line-through",
|
|
56
|
+
color: "var(--muted)"
|
|
57
|
+
},
|
|
58
|
+
".lmd-code": {
|
|
59
|
+
...CODE,
|
|
60
|
+
background: "var(--head)",
|
|
61
|
+
padding: "1px 5px"
|
|
62
|
+
},
|
|
63
|
+
".lmd-link": {
|
|
64
|
+
color: "var(--ink)",
|
|
65
|
+
textDecoration: "underline",
|
|
66
|
+
textDecorationThickness: "var(--hair)",
|
|
67
|
+
textUnderlineOffset: "3px"
|
|
68
|
+
},
|
|
69
|
+
".lmd-codeblock": {
|
|
70
|
+
...CODE,
|
|
71
|
+
background: "var(--head)",
|
|
72
|
+
padding: "0 var(--space-s) !important"
|
|
73
|
+
},
|
|
74
|
+
".lmd-table": CODE,
|
|
75
|
+
".lmd-quote": {
|
|
76
|
+
borderLeft: "var(--hair) solid var(--ink)",
|
|
77
|
+
paddingLeft: "var(--space-m) !important",
|
|
78
|
+
color: "var(--muted)"
|
|
79
|
+
},
|
|
80
|
+
".lmd-hr": {
|
|
81
|
+
height: "0.8em",
|
|
82
|
+
background: "linear-gradient(var(--rule), var(--rule)) center / 100% var(--hair) no-repeat"
|
|
83
|
+
},
|
|
84
|
+
".lmd-bullet": {
|
|
85
|
+
color: "var(--muted)",
|
|
86
|
+
display: "inline-block",
|
|
87
|
+
minWidth: "0.7em"
|
|
88
|
+
},
|
|
89
|
+
".lmd-check": {
|
|
90
|
+
width: "auto",
|
|
91
|
+
margin: "0 var(--space-s) 0 0",
|
|
92
|
+
verticalAlign: "-2px",
|
|
93
|
+
cursor: "pointer",
|
|
94
|
+
accentColor: "var(--ink)"
|
|
95
|
+
},
|
|
96
|
+
".lmd-img": {
|
|
97
|
+
display: "block",
|
|
98
|
+
maxWidth: "100%",
|
|
99
|
+
maxHeight: "480px",
|
|
100
|
+
margin: "var(--space-s) 0"
|
|
101
|
+
},
|
|
102
|
+
".lmd-img-note": {
|
|
103
|
+
color: "var(--muted)",
|
|
104
|
+
fontStyle: "italic"
|
|
105
|
+
},
|
|
106
|
+
".lmd-table-widget": {
|
|
107
|
+
cursor: "text",
|
|
108
|
+
padding: "2px 0"
|
|
109
|
+
},
|
|
110
|
+
".lmd-table-view": { borderCollapse: "collapse" },
|
|
111
|
+
".lmd-table-view th, .lmd-table-view td": {
|
|
112
|
+
border: "var(--hair) solid var(--rule)",
|
|
113
|
+
padding: "3px var(--space-s)",
|
|
114
|
+
textAlign: "left"
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
export { liveMarkdownTheme };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ViewConfig as ViewConfig$1 } from "../textarea-field/textarea-field.js";
|
|
2
|
+
import { Schema } from "effect";
|
|
3
|
+
import { Html, HtmlBuilder } from "foldkit/html";
|
|
4
|
+
/** Configuration for rendering a Markdown editor with `view`. */
|
|
5
|
+
export type ViewConfig<Message> = Pick<ViewConfig$1<Message>, "id" | "label" | "value" | "onInput" | "help" | "error" | "rows">;
|
|
6
|
+
/** A labelled Markdown field, edited in place: its marks show only around the caret, and the
|
|
7
|
+
* text it hands back is the Markdown string as typed, except that the first edit turns CRLF
|
|
8
|
+
* line endings into LF. Without `defineMarkdownEditorElement` it is a plain `TextareaField`,
|
|
9
|
+
* which is also what tests see, and so is a field whose editor fails to mount. With it, the
|
|
10
|
+
* element takes the textarea's place and drives `onInput` itself. */
|
|
11
|
+
export declare const view: <Message>(config: ViewConfig<Message>, h: HtmlBuilder<Message>) => Html;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { brandViewResult as __foldkitBrandViewResult } from 'foldkit/brand'
|
|
2
|
+
import { view as view$1 } from "../textarea-field/textarea-field.js";
|
|
3
|
+
import { Schema } from "effect";
|
|
4
|
+
import { define } from "foldkit/customElement";
|
|
5
|
+
// src/markdown-editor/markdown-editor.ts
|
|
6
|
+
/** The binding to `<pp-markdown-editor>`. The property is `source`, not `value`, because
|
|
7
|
+
* Foldkit's props module skips a `value` write when the element's `value` already matches. */
|
|
8
|
+
const spec = define({
|
|
9
|
+
tag: "pp-markdown-editor",
|
|
10
|
+
properties: { source: Schema.String },
|
|
11
|
+
events: { "value-change": Schema.Struct({ value: Schema.String }) }
|
|
12
|
+
});
|
|
13
|
+
/** A labelled Markdown field, edited in place: its marks show only around the caret, and the
|
|
14
|
+
* text it hands back is the Markdown string as typed, except that the first edit turns CRLF
|
|
15
|
+
* line endings into LF. Without `defineMarkdownEditorElement` it is a plain `TextareaField`,
|
|
16
|
+
* which is also what tests see, and so is a field whose editor fails to mount. With it, the
|
|
17
|
+
* element takes the textarea's place and drives `onInput` itself. */
|
|
18
|
+
const view = (config, h) => {
|
|
19
|
+
const host = spec.withMessage(h);
|
|
20
|
+
return __foldkitBrandViewResult((host([host.Source(config.value), host.OnValueChange(({ value }) => __foldkitBrandViewResult((config.onInput(value)), "@gjermundgaraba/pixel-paper/markdown-editor/markdown-editor.js#anonymous"))], [view$1(config, h)])), "@gjermundgaraba/pixel-paper/markdown-editor/markdown-editor.js#view");
|
|
21
|
+
};
|
|
22
|
+
export { spec, view };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { brandViewResult as __foldkitBrandViewResult } from 'foldkit/brand'
|
|
2
|
+
// src/markdown-editor/reconcile.ts
|
|
3
|
+
/** CodeMirror's document keeps LF, so a stored CRLF text compares equal to it only after this. */
|
|
4
|
+
const withLfLineEndings = (text) => __foldkitBrandViewResult((text.replaceAll(/\r\n?/gu, "\n")), "@gjermundgaraba/pixel-paper/markdown-editor/reconcile.js#withLfLineEndings");
|
|
5
|
+
/** Remembers a document sent up, so its echo cannot be taken for an outside change. */
|
|
6
|
+
const afterEmission = (pending, doc) => __foldkitBrandViewResult(([...pending, doc]), "@gjermundgaraba/pixel-paper/markdown-editor/reconcile.js#afterEmission");
|
|
7
|
+
/** Sorts a `source` write into an echo of this editor's own typing, which must not rewind a
|
|
8
|
+
* document that has moved on, or an outside change. A render may skip echoes, so a match
|
|
9
|
+
* also retires everything older. Text loss here would be silent, with no history behind it. */
|
|
10
|
+
const afterSource = (pending, source, doc) => {
|
|
11
|
+
const echoIndex = pending.indexOf(source);
|
|
12
|
+
if (echoIndex !== -1) return __foldkitBrandViewResult(({
|
|
13
|
+
pending: pending.slice(echoIndex + 1),
|
|
14
|
+
isExternal: false
|
|
15
|
+
}), "@gjermundgaraba/pixel-paper/markdown-editor/reconcile.js#afterSource");
|
|
16
|
+
return __foldkitBrandViewResult((withLfLineEndings(source) === doc ? {
|
|
17
|
+
pending,
|
|
18
|
+
isExternal: false
|
|
19
|
+
} : {
|
|
20
|
+
pending: [],
|
|
21
|
+
isExternal: true
|
|
22
|
+
}), "@gjermundgaraba/pixel-paper/markdown-editor/reconcile.js#afterSource");
|
|
23
|
+
};
|
|
24
|
+
export { afterEmission, afterSource, withLfLineEndings };
|
package/dist/menu/menu.d.ts
CHANGED
|
@@ -68,13 +68,13 @@ export declare const update: (model: Model, message: Message) => Readonly<{
|
|
|
68
68
|
readonly edge: "First" | "Last";
|
|
69
69
|
};
|
|
70
70
|
commands?: Update.Commands<{
|
|
71
|
+
readonly _tag: "CompletedFocus";
|
|
72
|
+
} | {
|
|
71
73
|
readonly _tag: "ClickedToggle";
|
|
72
74
|
} | {
|
|
73
75
|
readonly _tag: "PressedEscape";
|
|
74
76
|
} | {
|
|
75
77
|
readonly _tag: "CompletedFocusEdge";
|
|
76
|
-
} | {
|
|
77
|
-
readonly _tag: "CompletedFocus";
|
|
78
78
|
} | {
|
|
79
79
|
readonly _tag: "CompletedPlaceSlip";
|
|
80
80
|
} | {
|
|
@@ -163,13 +163,13 @@ export declare const view: import("foldkit/submodel").View<{
|
|
|
163
163
|
readonly isOpen: boolean;
|
|
164
164
|
readonly edge: "First" | "Last";
|
|
165
165
|
}, {
|
|
166
|
+
readonly _tag: "CompletedFocus";
|
|
167
|
+
} | {
|
|
166
168
|
readonly _tag: "ClickedToggle";
|
|
167
169
|
} | {
|
|
168
170
|
readonly _tag: "PressedEscape";
|
|
169
171
|
} | {
|
|
170
172
|
readonly _tag: "CompletedFocusEdge";
|
|
171
|
-
} | {
|
|
172
|
-
readonly _tag: "CompletedFocus";
|
|
173
173
|
} | {
|
|
174
174
|
readonly _tag: "CompletedPlaceSlip";
|
|
175
175
|
} | {
|