@dxos/react-ui-editor 0.4.8-main.6d7437e → 0.4.8-main.7d8f6a4
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/lib/browser/index.mjs +457 -276
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +2 -2
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +2 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +11 -5
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +4 -2
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts +1 -0
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +1 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +7 -4
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/image.d.ts +6 -0
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -1
- package/dist/types/src/extensions/modes.d.ts +1 -0
- package/dist/types/src/extensions/modes.d.ts.map +1 -1
- package/dist/types/src/extensions/state.d.ts +20 -0
- package/dist/types/src/extensions/state.d.ts.map +1 -0
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useDocAccessor.d.ts +4 -2
- package/dist/types/src/hooks/useDocAccessor.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.stories.d.ts +1 -0
- package/dist/types/src/hooks/useTextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +1 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/package.json +25 -27
- package/src/components/TextEditor/TextEditor.stories.tsx +16 -4
- package/src/components/TextEditor/TextEditor.tsx +13 -12
- package/src/components/Toolbar/Toolbar.stories.tsx +23 -24
- package/src/components/Toolbar/Toolbar.tsx +101 -35
- package/src/extensions/automerge/automerge.ts +4 -4
- package/src/extensions/comments.ts +2 -2
- package/src/extensions/factories.ts +0 -3
- package/src/extensions/index.ts +1 -0
- package/src/extensions/markdown/decorate.ts +1 -1
- package/src/extensions/markdown/formatting.test.ts +13 -13
- package/src/extensions/markdown/formatting.ts +95 -87
- package/src/extensions/markdown/image.ts +6 -0
- package/src/extensions/modes.ts +3 -1
- package/src/extensions/state.ts +90 -0
- package/src/hooks/useActionHandler.ts +5 -1
- package/src/hooks/useDocAccessor.ts +8 -2
- package/src/hooks/useTextEditor.stories.tsx +3 -3
- package/src/hooks/useTextEditor.ts +3 -0
- package/src/translations.ts +1 -0
|
@@ -15,6 +15,7 @@ var translations_default = [
|
|
|
15
15
|
"blockquote label": "Block quote",
|
|
16
16
|
"codeblock label": "Code block",
|
|
17
17
|
"comment label": "Create comment",
|
|
18
|
+
"image label": "Insert image",
|
|
18
19
|
"heading label": "Heading level",
|
|
19
20
|
"table label": "Create table"
|
|
20
21
|
}
|
|
@@ -23,18 +24,18 @@ var translations_default = [
|
|
|
23
24
|
];
|
|
24
25
|
|
|
25
26
|
// packages/ui/react-ui-editor/src/index.ts
|
|
26
|
-
import { keymap as
|
|
27
|
+
import { keymap as keymap10 } from "@codemirror/view";
|
|
27
28
|
import { tags as tags2 } from "@lezer/highlight";
|
|
28
29
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
29
30
|
import { Doc, YText, YXmlFragment } from "@dxos/text-model";
|
|
30
31
|
|
|
31
32
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
32
33
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
33
|
-
import { EditorView as
|
|
34
|
+
import { EditorView as EditorView17 } from "@codemirror/view";
|
|
34
35
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
35
36
|
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2 } from "react";
|
|
36
37
|
import { log as log9 } from "@dxos/log";
|
|
37
|
-
import { isNotFalsy as
|
|
38
|
+
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
38
39
|
|
|
39
40
|
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
|
40
41
|
import { StateField } from "@codemirror/state";
|
|
@@ -56,8 +57,8 @@ var Cursor = class _Cursor {
|
|
|
56
57
|
});
|
|
57
58
|
}
|
|
58
59
|
static {
|
|
59
|
-
this.getCursorFromRange = (
|
|
60
|
-
const cursorConverter2 =
|
|
60
|
+
this.getCursorFromRange = (state2, range) => {
|
|
61
|
+
const cursorConverter2 = state2.facet(_Cursor.converter);
|
|
61
62
|
const from = cursorConverter2.toCursor(range.from);
|
|
62
63
|
const to = cursorConverter2.toCursor(range.to, -1);
|
|
63
64
|
return [
|
|
@@ -67,8 +68,8 @@ var Cursor = class _Cursor {
|
|
|
67
68
|
};
|
|
68
69
|
}
|
|
69
70
|
static {
|
|
70
|
-
this.getRangeFromCursor = (
|
|
71
|
-
const cursorConverter2 =
|
|
71
|
+
this.getRangeFromCursor = (state2, cursor) => {
|
|
72
|
+
const cursorConverter2 = state2.facet(_Cursor.converter);
|
|
72
73
|
const parts = cursor.split(":");
|
|
73
74
|
const from = cursorConverter2.fromCursor(parts[0]);
|
|
74
75
|
const to = cursorConverter2.fromCursor(parts[1]);
|
|
@@ -85,15 +86,15 @@ var annotationMark = Decoration.mark({
|
|
|
85
86
|
class: "cm-annotation"
|
|
86
87
|
});
|
|
87
88
|
var annotations = (options = {}) => {
|
|
88
|
-
const match = (
|
|
89
|
+
const match = (state2) => {
|
|
89
90
|
const annotations2 = [];
|
|
90
|
-
const text =
|
|
91
|
+
const text = state2.doc.toString();
|
|
91
92
|
if (options.match) {
|
|
92
93
|
const matches = text.matchAll(options.match);
|
|
93
94
|
for (const match2 of matches) {
|
|
94
95
|
const from = match2.index;
|
|
95
96
|
const to = from + match2[0].length;
|
|
96
|
-
const cursor = Cursor.getCursorFromRange(
|
|
97
|
+
const cursor = Cursor.getCursorFromRange(state2, {
|
|
97
98
|
from,
|
|
98
99
|
to
|
|
99
100
|
});
|
|
@@ -105,8 +106,8 @@ var annotations = (options = {}) => {
|
|
|
105
106
|
return annotations2;
|
|
106
107
|
};
|
|
107
108
|
const annotationsState = StateField.define({
|
|
108
|
-
create: (
|
|
109
|
-
return match(
|
|
109
|
+
create: (state2) => {
|
|
110
|
+
return match(state2);
|
|
110
111
|
},
|
|
111
112
|
update: (value, tr) => {
|
|
112
113
|
if (!tr.changes.empty) {
|
|
@@ -119,10 +120,10 @@ var annotations = (options = {}) => {
|
|
|
119
120
|
annotationsState,
|
|
120
121
|
EditorView.decorations.compute([
|
|
121
122
|
annotationsState
|
|
122
|
-
], (
|
|
123
|
-
const annotations2 =
|
|
123
|
+
], (state2) => {
|
|
124
|
+
const annotations2 = state2.field(annotationsState);
|
|
124
125
|
const decorations = annotations2.map((annotation2) => {
|
|
125
|
-
const range = Cursor.getRangeFromCursor(
|
|
126
|
+
const range = Cursor.getRangeFromCursor(state2, annotation2.cursor);
|
|
126
127
|
return range && annotationMark.range(range.from, range.to);
|
|
127
128
|
}).filter(isNotFalsy);
|
|
128
129
|
return Decoration.set(decorations);
|
|
@@ -239,8 +240,8 @@ var cursorConverter = ({ handle, path }) => ({
|
|
|
239
240
|
|
|
240
241
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
241
242
|
import { Annotation, StateEffect } from "@codemirror/state";
|
|
242
|
-
var getPath = (
|
|
243
|
-
var getLastHeads = (
|
|
243
|
+
var getPath = (state2, field) => state2.field(field).path;
|
|
244
|
+
var getLastHeads = (state2, field) => state2.field(field).lastHeads;
|
|
244
245
|
var updateHeadsEffect = StateEffect.define({});
|
|
245
246
|
var updateHeads = (newHeads) => updateHeadsEffect.of({
|
|
246
247
|
newHeads
|
|
@@ -255,8 +256,8 @@ import { next as A3 } from "@dxos/automerge/automerge";
|
|
|
255
256
|
|
|
256
257
|
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
|
257
258
|
import { next as A2 } from "@dxos/automerge/automerge";
|
|
258
|
-
var updateAutomerge = (field, handle, transactions,
|
|
259
|
-
const { lastHeads, path } =
|
|
259
|
+
var updateAutomerge = (field, handle, transactions, state2) => {
|
|
260
|
+
const { lastHeads, path } = state2.field(field);
|
|
260
261
|
let hasChanges = false;
|
|
261
262
|
for (const tr of transactions) {
|
|
262
263
|
tr.changes.iterChanges(() => {
|
|
@@ -303,7 +304,7 @@ var updateCodeMirror = (view, selection, target, patches) => {
|
|
|
303
304
|
annotations: reconcileAnnotation.of(false)
|
|
304
305
|
});
|
|
305
306
|
};
|
|
306
|
-
var handlePatch = (patch, target,
|
|
307
|
+
var handlePatch = (patch, target, state2) => {
|
|
307
308
|
if (patch.action === "insert") {
|
|
308
309
|
return handleInsert(target, patch);
|
|
309
310
|
} else if (patch.action === "splice") {
|
|
@@ -311,7 +312,7 @@ var handlePatch = (patch, target, state) => {
|
|
|
311
312
|
} else if (patch.action === "del") {
|
|
312
313
|
return handleDel(target, patch);
|
|
313
314
|
} else if (patch.action === "put") {
|
|
314
|
-
return handlePut(target, patch,
|
|
315
|
+
return handlePut(target, patch, state2);
|
|
315
316
|
} else {
|
|
316
317
|
return null;
|
|
317
318
|
}
|
|
@@ -355,7 +356,7 @@ var handleDel = (target, patch) => {
|
|
|
355
356
|
}
|
|
356
357
|
];
|
|
357
358
|
};
|
|
358
|
-
var handlePut = (target, patch,
|
|
359
|
+
var handlePut = (target, patch, state2) => {
|
|
359
360
|
const index = charPath(target, [
|
|
360
361
|
...patch.path,
|
|
361
362
|
0
|
|
@@ -363,7 +364,7 @@ var handlePut = (target, patch, state) => {
|
|
|
363
364
|
if (index == null) {
|
|
364
365
|
return [];
|
|
365
366
|
}
|
|
366
|
-
const length =
|
|
367
|
+
const length = state2.doc.length;
|
|
367
368
|
if (typeof patch.value !== "string") {
|
|
368
369
|
return [];
|
|
369
370
|
}
|
|
@@ -474,13 +475,13 @@ var automerge = (accessor) => {
|
|
|
474
475
|
ViewPlugin.fromClass(class {
|
|
475
476
|
constructor(_view) {
|
|
476
477
|
this._view = _view;
|
|
477
|
-
|
|
478
|
+
this._handleChange = () => {
|
|
479
|
+
syncer.reconcile(this._view, false);
|
|
480
|
+
};
|
|
481
|
+
accessor.handle.addListener("change", this._handleChange);
|
|
478
482
|
}
|
|
479
483
|
destroy() {
|
|
480
|
-
accessor.handle.removeListener("change", this._handleChange
|
|
481
|
-
}
|
|
482
|
-
_handleChange() {
|
|
483
|
-
syncer.reconcile(this._view, false);
|
|
484
|
+
accessor.handle.removeListener("change", this._handleChange);
|
|
484
485
|
}
|
|
485
486
|
}),
|
|
486
487
|
// Reconcile local updates.
|
|
@@ -561,9 +562,9 @@ var RemoteSelectionsDecorator = class {
|
|
|
561
562
|
_updateRemoteSelections(update2) {
|
|
562
563
|
const decorations = [];
|
|
563
564
|
const awarenessStates = this._provider.getRemoteStates();
|
|
564
|
-
for (const
|
|
565
|
-
const anchor =
|
|
566
|
-
const head =
|
|
565
|
+
for (const state2 of awarenessStates) {
|
|
566
|
+
const anchor = state2.position?.anchor ? this._cursorConverter.fromCursor(state2.position.anchor) : null;
|
|
567
|
+
const head = state2.position?.head ? this._cursorConverter.fromCursor(state2.position.head) : null;
|
|
567
568
|
if (anchor == null || head == null) {
|
|
568
569
|
continue;
|
|
569
570
|
}
|
|
@@ -571,8 +572,8 @@ var RemoteSelectionsDecorator = class {
|
|
|
571
572
|
const end = Math.min(Math.max(anchor, head), update2.view.state.doc.length);
|
|
572
573
|
const startLine = update2.view.state.doc.lineAt(start);
|
|
573
574
|
const endLine = update2.view.state.doc.lineAt(end);
|
|
574
|
-
const color =
|
|
575
|
-
const lightColor =
|
|
575
|
+
const color = state2.info.color ?? "#30bced";
|
|
576
|
+
const lightColor = state2.info.lightColor ?? color + "33";
|
|
576
577
|
if (startLine.number === endLine.number) {
|
|
577
578
|
decorations.push({
|
|
578
579
|
from: start,
|
|
@@ -625,7 +626,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
625
626
|
value: Decoration2.widget({
|
|
626
627
|
side: head - anchor > 0 ? -1 : 1,
|
|
627
628
|
block: false,
|
|
628
|
-
widget: new RemoteCaretWidget(
|
|
629
|
+
widget: new RemoteCaretWidget(state2.info.displayName ?? "Anonymous", color)
|
|
629
630
|
})
|
|
630
631
|
});
|
|
631
632
|
}
|
|
@@ -1156,7 +1157,7 @@ var commandConfig = Facet3.define({
|
|
|
1156
1157
|
});
|
|
1157
1158
|
var commandState = StateField3.define({
|
|
1158
1159
|
create: () => ({}),
|
|
1159
|
-
update: (
|
|
1160
|
+
update: (state2, tr) => {
|
|
1160
1161
|
for (const effect of tr.effects) {
|
|
1161
1162
|
if (effect.is(closeEffect)) {
|
|
1162
1163
|
return {};
|
|
@@ -1207,7 +1208,7 @@ var commandState = StateField3.define({
|
|
|
1207
1208
|
};
|
|
1208
1209
|
}
|
|
1209
1210
|
}
|
|
1210
|
-
return
|
|
1211
|
+
return state2;
|
|
1211
1212
|
},
|
|
1212
1213
|
provide: (field) => [
|
|
1213
1214
|
showTooltip.from(field, (value) => value.tooltip ?? null)
|
|
@@ -1453,8 +1454,8 @@ var setComments = StateEffect3.define();
|
|
|
1453
1454
|
var setSelection = StateEffect3.define();
|
|
1454
1455
|
var setCommentState = StateEffect3.define();
|
|
1455
1456
|
var commentsState = StateField4.define({
|
|
1456
|
-
create: (
|
|
1457
|
-
id:
|
|
1457
|
+
create: (state2) => ({
|
|
1458
|
+
id: state2.facet(documentId),
|
|
1458
1459
|
comments: [],
|
|
1459
1460
|
selection: {}
|
|
1460
1461
|
}),
|
|
@@ -1526,8 +1527,8 @@ var commentCurrentMark = Decoration4.mark({
|
|
|
1526
1527
|
});
|
|
1527
1528
|
var commentsDecorations = EditorView7.decorations.compute([
|
|
1528
1529
|
commentsState
|
|
1529
|
-
], (
|
|
1530
|
-
const { selection: { current }, comments: comments2 } =
|
|
1530
|
+
], (state2) => {
|
|
1531
|
+
const { selection: { current }, comments: comments2 } = state2.field(commentsState);
|
|
1531
1532
|
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1532
1533
|
const range = comment.range;
|
|
1533
1534
|
if (!range || range.from === range.to) {
|
|
@@ -1691,7 +1692,7 @@ var optionsFacet = Facet4.define({
|
|
|
1691
1692
|
});
|
|
1692
1693
|
var comments = (options = {}) => {
|
|
1693
1694
|
const { key: shortcut = "meta-'" } = options;
|
|
1694
|
-
const handleSelect = debounce((
|
|
1695
|
+
const handleSelect = debounce((state2) => options.onSelect?.(state2), 200);
|
|
1695
1696
|
return [
|
|
1696
1697
|
optionsFacet.of(options),
|
|
1697
1698
|
documentId.of(options.id),
|
|
@@ -1740,9 +1741,9 @@ var comments = (options = {}) => {
|
|
|
1740
1741
|
//
|
|
1741
1742
|
// Track deleted ranges and update ranges for decorations.
|
|
1742
1743
|
//
|
|
1743
|
-
EditorView7.updateListener.of(({ view, state, changes }) => {
|
|
1744
|
+
EditorView7.updateListener.of(({ view, state: state2, changes }) => {
|
|
1744
1745
|
let mod = false;
|
|
1745
|
-
const { comments: comments2, ...value } =
|
|
1746
|
+
const { comments: comments2, ...value } = state2.field(commentsState);
|
|
1746
1747
|
changes.iterChanges((from, to, from2, to2) => {
|
|
1747
1748
|
comments2.forEach(({ comment, range }) => {
|
|
1748
1749
|
if (from2 === to2) {
|
|
@@ -1772,10 +1773,10 @@ var comments = (options = {}) => {
|
|
|
1772
1773
|
//
|
|
1773
1774
|
// Track selection/proximity.
|
|
1774
1775
|
//
|
|
1775
|
-
EditorView7.updateListener.of(({ view, state }) => {
|
|
1776
|
+
EditorView7.updateListener.of(({ view, state: state2 }) => {
|
|
1776
1777
|
let min = Infinity;
|
|
1777
|
-
const { selection: { current, closest }, comments: comments2 } =
|
|
1778
|
-
const { head } =
|
|
1778
|
+
const { selection: { current, closest }, comments: comments2 } = state2.field(commentsState);
|
|
1779
|
+
const { head } = state2.selection.main;
|
|
1779
1780
|
const selection = {};
|
|
1780
1781
|
comments2.forEach(({ comment, range }) => {
|
|
1781
1782
|
if (head >= range.from && head <= range.to) {
|
|
@@ -1796,7 +1797,7 @@ var comments = (options = {}) => {
|
|
|
1796
1797
|
});
|
|
1797
1798
|
handleSelect({
|
|
1798
1799
|
selection,
|
|
1799
|
-
id:
|
|
1800
|
+
id: state2.facet(documentId),
|
|
1800
1801
|
comments: comments2.map(({ comment, range }) => ({
|
|
1801
1802
|
comment,
|
|
1802
1803
|
range,
|
|
@@ -1831,14 +1832,14 @@ var focusComment = (view, id, center = true) => {
|
|
|
1831
1832
|
});
|
|
1832
1833
|
}
|
|
1833
1834
|
};
|
|
1834
|
-
var useComments = (view, id, comments2
|
|
1835
|
+
var useComments = (view, id, comments2) => {
|
|
1835
1836
|
useEffect(() => {
|
|
1836
1837
|
if (view) {
|
|
1837
1838
|
if (id === view.state.facet(documentId)) {
|
|
1838
1839
|
view.dispatch({
|
|
1839
1840
|
effects: setComments.of({
|
|
1840
1841
|
id,
|
|
1841
|
-
comments: comments2
|
|
1842
|
+
comments: comments2 ?? []
|
|
1842
1843
|
})
|
|
1843
1844
|
});
|
|
1844
1845
|
}
|
|
@@ -1864,11 +1865,11 @@ var cursorLineMargin = (options = {
|
|
|
1864
1865
|
if (!lines || lines <= 0) {
|
|
1865
1866
|
return [];
|
|
1866
1867
|
}
|
|
1867
|
-
return EditorView8.updateListener.of(({ transactions, state, selectionSet, startState, view }) => {
|
|
1868
|
+
return EditorView8.updateListener.of(({ transactions, state: state2, selectionSet, startState, view }) => {
|
|
1868
1869
|
if (transactions.length < 1 || transactions.some((tr) => tr.isUserEvent(annotation))) {
|
|
1869
1870
|
return;
|
|
1870
1871
|
}
|
|
1871
|
-
const s =
|
|
1872
|
+
const s = state2;
|
|
1872
1873
|
const { main } = s.selection;
|
|
1873
1874
|
const rect = view.dom.getBoundingClientRect();
|
|
1874
1875
|
const viewportTop = rect.top - view.documentTop;
|
|
@@ -2233,9 +2234,6 @@ var createBasicExtensions = (_props) => {
|
|
|
2233
2234
|
var defaultSlots = {
|
|
2234
2235
|
editor: {
|
|
2235
2236
|
className: "w-full bs-full"
|
|
2236
|
-
},
|
|
2237
|
-
content: {
|
|
2238
|
-
className: "!p-2"
|
|
2239
2237
|
}
|
|
2240
2238
|
};
|
|
2241
2239
|
var createThemeExtensions = ({ theme, themeMode, slots: _slots } = {}) => {
|
|
@@ -2563,7 +2561,7 @@ var CheckboxWidget = class extends WidgetType3 {
|
|
|
2563
2561
|
}
|
|
2564
2562
|
toDOM(view) {
|
|
2565
2563
|
const input = document.createElement("input");
|
|
2566
|
-
input.className = "cm-task-checkbox";
|
|
2564
|
+
input.className = "cm-task-checkbox ch-checkbox ch-focus-ring -mbs-0.5";
|
|
2567
2565
|
input.type = "checkbox";
|
|
2568
2566
|
input.checked = this._checked;
|
|
2569
2567
|
if (view.state.readOnly) {
|
|
@@ -2609,8 +2607,8 @@ var checkedTask = Decoration5.replace({
|
|
|
2609
2607
|
var uncheckedTask = Decoration5.replace({
|
|
2610
2608
|
widget: new CheckboxWidget(false)
|
|
2611
2609
|
});
|
|
2612
|
-
var editingRange = (
|
|
2613
|
-
const { readOnly, selection: { main: { head } } } =
|
|
2610
|
+
var editingRange = (state2, range, focus) => {
|
|
2611
|
+
const { readOnly, selection: { main: { head } } } = state2;
|
|
2614
2612
|
return focus && !readOnly && head >= range.from && head <= range.to;
|
|
2615
2613
|
};
|
|
2616
2614
|
var MarksByParent = /* @__PURE__ */ new Set([
|
|
@@ -2623,14 +2621,14 @@ var MarksByParent = /* @__PURE__ */ new Set([
|
|
|
2623
2621
|
var buildDecorations = (view, options, focus) => {
|
|
2624
2622
|
const deco = new RangeSetBuilder2();
|
|
2625
2623
|
const atomicDeco = new RangeSetBuilder2();
|
|
2626
|
-
const { state } = view;
|
|
2624
|
+
const { state: state2 } = view;
|
|
2627
2625
|
for (const { from, to } of view.visibleRanges) {
|
|
2628
|
-
syntaxTree(
|
|
2626
|
+
syntaxTree(state2).iterate({
|
|
2629
2627
|
from,
|
|
2630
2628
|
to,
|
|
2631
2629
|
enter: (node) => {
|
|
2632
2630
|
if (node.name === "FencedCode") {
|
|
2633
|
-
const editing = editingRange(
|
|
2631
|
+
const editing = editingRange(state2, node, focus);
|
|
2634
2632
|
for (const block of view.viewportLineBlocks) {
|
|
2635
2633
|
if (block.to < node.from) {
|
|
2636
2634
|
continue;
|
|
@@ -2639,7 +2637,7 @@ var buildDecorations = (view, options, focus) => {
|
|
|
2639
2637
|
break;
|
|
2640
2638
|
}
|
|
2641
2639
|
const first = block.from <= node.from;
|
|
2642
|
-
const last = block.to >= node.to && /^(\s>)*```$/.test(
|
|
2640
|
+
const last = block.to >= node.to && /^(\s>)*```$/.test(state2.doc.sliceString(block.from, block.to));
|
|
2643
2641
|
deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
|
|
2644
2642
|
if (!editing && (first || last)) {
|
|
2645
2643
|
atomicDeco.add(block.from, block.to, hide);
|
|
@@ -2649,9 +2647,9 @@ var buildDecorations = (view, options, focus) => {
|
|
|
2649
2647
|
} else if (node.name === "Link") {
|
|
2650
2648
|
const marks = node.node.getChildren("LinkMark");
|
|
2651
2649
|
const urlNode = node.node.getChild("URL");
|
|
2652
|
-
const editing = editingRange(
|
|
2650
|
+
const editing = editingRange(state2, node, focus);
|
|
2653
2651
|
if (urlNode && marks.length >= 2) {
|
|
2654
|
-
const url =
|
|
2652
|
+
const url = state2.sliceDoc(urlNode.from, urlNode.to);
|
|
2655
2653
|
if (!editing) {
|
|
2656
2654
|
atomicDeco.add(node.from, marks[0].to, hide);
|
|
2657
2655
|
}
|
|
@@ -2672,24 +2670,24 @@ var buildDecorations = (view, options, focus) => {
|
|
|
2672
2670
|
}
|
|
2673
2671
|
} else if (node.name === "HeaderMark") {
|
|
2674
2672
|
const parent = node.node.parent;
|
|
2675
|
-
if (/^ATX/.test(parent.name) && !editingRange(
|
|
2676
|
-
const next =
|
|
2673
|
+
if (/^ATX/.test(parent.name) && !editingRange(state2, state2.doc.lineAt(node.from), focus)) {
|
|
2674
|
+
const next = state2.doc.sliceString(node.to, node.to + 1);
|
|
2677
2675
|
atomicDeco.add(node.from, node.to + (next === " " ? 1 : 0), hide);
|
|
2678
2676
|
}
|
|
2679
2677
|
} else if (node.name === "HorizontalRule") {
|
|
2680
|
-
if (!editingRange(
|
|
2678
|
+
if (!editingRange(state2, node, focus)) {
|
|
2681
2679
|
deco.add(node.from, node.to, horizontalRule);
|
|
2682
2680
|
}
|
|
2683
2681
|
} else if (node.name === "TaskMarker") {
|
|
2684
|
-
if (!editingRange(
|
|
2685
|
-
const checked =
|
|
2682
|
+
if (!editingRange(state2, node, focus)) {
|
|
2683
|
+
const checked = state2.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2686
2684
|
atomicDeco.add(node.from - 2, node.from - 1, Decoration5.mark({
|
|
2687
2685
|
class: "cm-task"
|
|
2688
2686
|
}));
|
|
2689
2687
|
atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
|
|
2690
2688
|
}
|
|
2691
2689
|
} else if (MarksByParent.has(node.name)) {
|
|
2692
|
-
if (!editingRange(
|
|
2690
|
+
if (!editingRange(state2, node.node.parent, focus)) {
|
|
2693
2691
|
atomicDeco.add(node.from, node.to, hide);
|
|
2694
2692
|
}
|
|
2695
2693
|
}
|
|
@@ -2799,8 +2797,8 @@ import { snippet } from "@codemirror/autocomplete";
|
|
|
2799
2797
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
2800
2798
|
import { EditorSelection } from "@codemirror/state";
|
|
2801
2799
|
import { EditorView as EditorView13, keymap as keymap6 } from "@codemirror/view";
|
|
2802
|
-
import {
|
|
2803
|
-
var
|
|
2800
|
+
import { useMemo, useState } from "react";
|
|
2801
|
+
var formattingEquals = (a, b) => a.blockType === b.blockType && a.strong === b.strong && a.emphasis === b.emphasis && a.strikethrough === b.strikethrough && a.code === b.code && a.link === b.link && a.listStyle === b.listStyle && a.blockQuote === b.blockQuote;
|
|
2804
2802
|
var Inline;
|
|
2805
2803
|
(function(Inline2) {
|
|
2806
2804
|
Inline2[Inline2["Strong"] = 0] = "Strong";
|
|
@@ -2814,13 +2812,13 @@ var List;
|
|
|
2814
2812
|
List2[List2["Bullet"] = 1] = "Bullet";
|
|
2815
2813
|
List2[List2["Task"] = 2] = "Task";
|
|
2816
2814
|
})(List || (List = {}));
|
|
2817
|
-
var setHeading = (level) => ({ state, dispatch }) => {
|
|
2818
|
-
const { selection: { ranges }, doc } =
|
|
2815
|
+
var setHeading = (level) => ({ state: state2, dispatch }) => {
|
|
2816
|
+
const { selection: { ranges }, doc } = state2;
|
|
2819
2817
|
const changes = [];
|
|
2820
2818
|
let prevBlock = -1;
|
|
2821
2819
|
for (const range of ranges) {
|
|
2822
2820
|
let sawBlock = false;
|
|
2823
|
-
syntaxTree2(
|
|
2821
|
+
syntaxTree2(state2).iterate({
|
|
2824
2822
|
from: range.from,
|
|
2825
2823
|
to: range.to,
|
|
2826
2824
|
enter: (node) => {
|
|
@@ -2873,7 +2871,7 @@ var setHeading = (level) => ({ state, dispatch }) => {
|
|
|
2873
2871
|
}
|
|
2874
2872
|
});
|
|
2875
2873
|
let line;
|
|
2876
|
-
if (!sawBlock && range.empty && level > 0 && !/\S/.test((line =
|
|
2874
|
+
if (!sawBlock && range.empty && level > 0 && !/\S/.test((line = state2.doc.lineAt(range.from)).text)) {
|
|
2877
2875
|
changes.push({
|
|
2878
2876
|
from: line.from,
|
|
2879
2877
|
to: line.to,
|
|
@@ -2884,23 +2882,23 @@ var setHeading = (level) => ({ state, dispatch }) => {
|
|
|
2884
2882
|
if (!changes.length) {
|
|
2885
2883
|
return false;
|
|
2886
2884
|
}
|
|
2887
|
-
const changeSet =
|
|
2888
|
-
dispatch(
|
|
2885
|
+
const changeSet = state2.changes(changes);
|
|
2886
|
+
dispatch(state2.update({
|
|
2889
2887
|
changes: changeSet,
|
|
2890
|
-
selection:
|
|
2888
|
+
selection: state2.selection.map(changeSet, 1),
|
|
2891
2889
|
userEvent: "format.setHeading",
|
|
2892
2890
|
scrollIntoView: true
|
|
2893
2891
|
}));
|
|
2894
2892
|
return true;
|
|
2895
2893
|
};
|
|
2896
|
-
var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
2894
|
+
var setStyle = (type, enable) => ({ state: state2, dispatch }) => {
|
|
2897
2895
|
const marker = inlineMarkerText(type);
|
|
2898
|
-
const changes =
|
|
2896
|
+
const changes = state2.changeByRange((range) => {
|
|
2899
2897
|
if (!enable && range.empty) {
|
|
2900
|
-
const after =
|
|
2898
|
+
const after = state2.doc.sliceString(range.head, range.head + 6);
|
|
2901
2899
|
const found = after.indexOf(marker);
|
|
2902
2900
|
if (found >= 0 && /^[*~`]*$/.test(after.slice(0, found))) {
|
|
2903
|
-
const before =
|
|
2901
|
+
const before = state2.doc.sliceString(range.head - 6, range.head);
|
|
2904
2902
|
if (before.slice(before.length - found - marker.length, before.length - found) === marker && [
|
|
2905
2903
|
...before.slice(before.length - found)
|
|
2906
2904
|
].reverse().join("") === after.slice(0, found)) {
|
|
@@ -2927,14 +2925,14 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2927
2925
|
let startCovered = false;
|
|
2928
2926
|
let endCovered = false;
|
|
2929
2927
|
let { from, to } = range;
|
|
2930
|
-
syntaxTree2(
|
|
2928
|
+
syntaxTree2(state2).iterate({
|
|
2931
2929
|
from,
|
|
2932
2930
|
to,
|
|
2933
2931
|
enter: (node) => {
|
|
2934
2932
|
const { name } = node;
|
|
2935
2933
|
if (Object.hasOwn(Textblocks, name) && Textblocks[name] !== "codeblock") {
|
|
2936
2934
|
blockStart = blockContentStart(node);
|
|
2937
|
-
blockEnd = blockContentEnd(node,
|
|
2935
|
+
blockEnd = blockContentEnd(node, state2.doc);
|
|
2938
2936
|
startCovered = endCovered = false;
|
|
2939
2937
|
} else if (name === "Link" || name === "Image" && enable) {
|
|
2940
2938
|
if (from < node.from && to > node.from && to <= node.to) {
|
|
@@ -2979,7 +2977,7 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2979
2977
|
});
|
|
2980
2978
|
if (markType !== type && closeStart >= to) {
|
|
2981
2979
|
changesAtEnd.push({
|
|
2982
|
-
from: skipSpaces(Math.min(to, blockEnd),
|
|
2980
|
+
from: skipSpaces(Math.min(to, blockEnd), state2.doc, 1, blockEnd),
|
|
2983
2981
|
insert: inlineMarkerText(markType)
|
|
2984
2982
|
});
|
|
2985
2983
|
}
|
|
@@ -2991,7 +2989,7 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2991
2989
|
});
|
|
2992
2990
|
if (markType !== type && openEnd <= from) {
|
|
2993
2991
|
changes2.push({
|
|
2994
|
-
from: skipSpaces(Math.max(from, blockStart),
|
|
2992
|
+
from: skipSpaces(Math.max(from, blockStart), state2.doc, -1, blockStart),
|
|
2995
2993
|
insert: inlineMarkerText(markType)
|
|
2996
2994
|
});
|
|
2997
2995
|
}
|
|
@@ -3021,7 +3019,7 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
3021
3019
|
changes2.push(startCovered);
|
|
3022
3020
|
} else if (startCovered) {
|
|
3023
3021
|
changes2.push({
|
|
3024
|
-
from: skipSpaces(rangeStart,
|
|
3022
|
+
from: skipSpaces(rangeStart, state2.doc, -1, blockStart),
|
|
3025
3023
|
insert: marker
|
|
3026
3024
|
});
|
|
3027
3025
|
}
|
|
@@ -3029,7 +3027,7 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
3029
3027
|
changes2.push(endCovered);
|
|
3030
3028
|
} else if (endCovered) {
|
|
3031
3029
|
changes2.push({
|
|
3032
|
-
from: skipSpaces(rangeEnd,
|
|
3030
|
+
from: skipSpaces(rangeEnd, state2.doc, 1, blockEnd),
|
|
3033
3031
|
insert: marker
|
|
3034
3032
|
});
|
|
3035
3033
|
}
|
|
@@ -3037,7 +3035,7 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
3037
3035
|
}
|
|
3038
3036
|
}
|
|
3039
3037
|
});
|
|
3040
|
-
if (blockStart < 0 && range.empty && enable && !/\S/.test(
|
|
3038
|
+
if (blockStart < 0 && range.empty && enable && !/\S/.test(state2.doc.lineAt(range.from).text)) {
|
|
3041
3039
|
return {
|
|
3042
3040
|
changes: {
|
|
3043
3041
|
from: range.head,
|
|
@@ -3046,13 +3044,13 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
3046
3044
|
range: EditorSelection.cursor(range.head + marker.length)
|
|
3047
3045
|
};
|
|
3048
3046
|
}
|
|
3049
|
-
const changeSet =
|
|
3047
|
+
const changeSet = state2.changes(changes2.concat(changesAtEnd));
|
|
3050
3048
|
return {
|
|
3051
3049
|
changes: changeSet,
|
|
3052
3050
|
range: range.empty && !changeSet.empty ? EditorSelection.cursor(range.head + marker.length) : EditorSelection.range(changeSet.mapPos(range.from, 1), changeSet.mapPos(range.to, -1))
|
|
3053
3051
|
};
|
|
3054
3052
|
});
|
|
3055
|
-
dispatch(
|
|
3053
|
+
dispatch(state2.update(changes, {
|
|
3056
3054
|
userEvent: enable ? "format.style.add" : "format.style.remove",
|
|
3057
3055
|
scrollIntoView: true
|
|
3058
3056
|
}));
|
|
@@ -3126,8 +3124,8 @@ var insertTable = (view) => {
|
|
|
3126
3124
|
const { from } = doc.line(number);
|
|
3127
3125
|
snippets.table(view, null, from, from);
|
|
3128
3126
|
};
|
|
3129
|
-
var removeLinkInner = (from, to, changes,
|
|
3130
|
-
syntaxTree2(
|
|
3127
|
+
var removeLinkInner = (from, to, changes, state2) => {
|
|
3128
|
+
syntaxTree2(state2).iterate({
|
|
3131
3129
|
from,
|
|
3132
3130
|
to,
|
|
3133
3131
|
enter: (node) => {
|
|
@@ -3141,8 +3139,8 @@ var removeLinkInner = (from, to, changes, state) => {
|
|
|
3141
3139
|
});
|
|
3142
3140
|
} else if (name === "LinkTitle" || name === "URL") {
|
|
3143
3141
|
changes.push({
|
|
3144
|
-
from: skipSpaces(node2.from,
|
|
3145
|
-
to: skipSpaces(node2.to,
|
|
3142
|
+
from: skipSpaces(node2.from, state2.doc, -1),
|
|
3143
|
+
to: skipSpaces(node2.to, state2.doc, 1)
|
|
3146
3144
|
});
|
|
3147
3145
|
}
|
|
3148
3146
|
});
|
|
@@ -3151,32 +3149,32 @@ var removeLinkInner = (from, to, changes, state) => {
|
|
|
3151
3149
|
}
|
|
3152
3150
|
});
|
|
3153
3151
|
};
|
|
3154
|
-
var removeLink = ({ state, dispatch }) => {
|
|
3152
|
+
var removeLink = ({ state: state2, dispatch }) => {
|
|
3155
3153
|
const changes = [];
|
|
3156
|
-
for (const { from, to } of
|
|
3157
|
-
removeLinkInner(from, to, changes,
|
|
3154
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
3155
|
+
removeLinkInner(from, to, changes, state2);
|
|
3158
3156
|
}
|
|
3159
3157
|
if (!changes) {
|
|
3160
3158
|
return false;
|
|
3161
3159
|
}
|
|
3162
|
-
dispatch(
|
|
3160
|
+
dispatch(state2.update({
|
|
3163
3161
|
changes,
|
|
3164
3162
|
userEvent: "format.link.remove",
|
|
3165
3163
|
scrollIntoView: true
|
|
3166
3164
|
}));
|
|
3167
3165
|
return true;
|
|
3168
3166
|
};
|
|
3169
|
-
var addLink = ({ state, dispatch }) => {
|
|
3170
|
-
const changes =
|
|
3167
|
+
var addLink = ({ url, image: image2 } = {}) => ({ state: state2, dispatch }) => {
|
|
3168
|
+
const changes = state2.changeByRange((range) => {
|
|
3171
3169
|
let { from, to } = range;
|
|
3172
3170
|
const cutStyles = [];
|
|
3173
3171
|
let okay = null;
|
|
3174
|
-
syntaxTree2(
|
|
3172
|
+
syntaxTree2(state2).iterate({
|
|
3175
3173
|
from,
|
|
3176
3174
|
to,
|
|
3177
3175
|
enter: (node) => {
|
|
3178
3176
|
if (Object.hasOwn(Textblocks, node.name)) {
|
|
3179
|
-
okay = Textblocks[node.name] !== "codeblock" && from >= blockContentStart(node) && to <= blockContentEnd(node,
|
|
3177
|
+
okay = Textblocks[node.name] !== "codeblock" && from >= blockContentStart(node) && to <= blockContentEnd(node, state2.doc);
|
|
3180
3178
|
} else if (Object.hasOwn(InlineMarker, node.name)) {
|
|
3181
3179
|
const sNode = node.node;
|
|
3182
3180
|
if (node.from < from && node.to <= to) {
|
|
@@ -3196,7 +3194,7 @@ var addLink = ({ state, dispatch }) => {
|
|
|
3196
3194
|
}
|
|
3197
3195
|
});
|
|
3198
3196
|
if (okay === null) {
|
|
3199
|
-
const line =
|
|
3197
|
+
const line = state2.doc.lineAt(from);
|
|
3200
3198
|
okay = to <= line.to && !/\S/.test(line.text.slice(from - line.from));
|
|
3201
3199
|
}
|
|
3202
3200
|
if (!okay) {
|
|
@@ -3206,26 +3204,26 @@ var addLink = ({ state, dispatch }) => {
|
|
|
3206
3204
|
}
|
|
3207
3205
|
const changes2 = [];
|
|
3208
3206
|
const changesAfter = [];
|
|
3209
|
-
removeLinkInner(from, to, changesAfter,
|
|
3207
|
+
removeLinkInner(from, to, changesAfter, state2);
|
|
3210
3208
|
let cursorOffset = 1;
|
|
3211
3209
|
for (const style of cutStyles) {
|
|
3212
3210
|
const type = InlineMarker[style.name];
|
|
3213
3211
|
const mark2 = inlineMarkerText(type);
|
|
3214
3212
|
if (style.from < from) {
|
|
3215
3213
|
changes2.push({
|
|
3216
|
-
from: skipSpaces(from,
|
|
3214
|
+
from: skipSpaces(from, state2.doc, -1),
|
|
3217
3215
|
insert: mark2
|
|
3218
3216
|
});
|
|
3219
3217
|
changesAfter.push({
|
|
3220
|
-
from: skipSpaces(from,
|
|
3218
|
+
from: skipSpaces(from, state2.doc, 1, to),
|
|
3221
3219
|
insert: mark2
|
|
3222
3220
|
});
|
|
3223
3221
|
} else {
|
|
3224
3222
|
changes2.push({
|
|
3225
|
-
from: skipSpaces(to,
|
|
3223
|
+
from: skipSpaces(to, state2.doc, -1, from),
|
|
3226
3224
|
insert: mark2
|
|
3227
3225
|
});
|
|
3228
|
-
const after = skipSpaces(to,
|
|
3226
|
+
const after = skipSpaces(to, state2.doc, 1);
|
|
3229
3227
|
if (after === to) {
|
|
3230
3228
|
cursorOffset += mark2.length;
|
|
3231
3229
|
}
|
|
@@ -3237,34 +3235,34 @@ var addLink = ({ state, dispatch }) => {
|
|
|
3237
3235
|
}
|
|
3238
3236
|
changes2.push({
|
|
3239
3237
|
from,
|
|
3240
|
-
insert: "["
|
|
3238
|
+
insert: image2 ? "`
|
|
3244
3242
|
});
|
|
3245
|
-
const changeSet =
|
|
3243
|
+
const changeSet = state2.changes(changes2.concat(changesAfter));
|
|
3246
3244
|
return {
|
|
3247
3245
|
changes: changeSet,
|
|
3248
|
-
range: EditorSelection.cursor(changeSet.mapPos(to, 1) - cursorOffset)
|
|
3246
|
+
range: EditorSelection.cursor(changeSet.mapPos(to, 1) - cursorOffset - (url ? url.length + 2 : 0))
|
|
3249
3247
|
};
|
|
3250
3248
|
});
|
|
3251
3249
|
if (changes.changes.empty) {
|
|
3252
3250
|
return false;
|
|
3253
3251
|
}
|
|
3254
|
-
dispatch(
|
|
3252
|
+
dispatch(state2.update(changes, {
|
|
3255
3253
|
userEvent: "format.link.add",
|
|
3256
3254
|
scrollIntoView: true
|
|
3257
3255
|
}));
|
|
3258
3256
|
return true;
|
|
3259
3257
|
};
|
|
3260
|
-
var addList = (type) => ({ state, dispatch }) => {
|
|
3258
|
+
var addList = (type) => ({ state: state2, dispatch }) => {
|
|
3261
3259
|
let lastBlock = -1;
|
|
3262
3260
|
let counter = 1;
|
|
3263
3261
|
let first = true;
|
|
3264
3262
|
let parentColumn = null;
|
|
3265
3263
|
const blocks = [];
|
|
3266
|
-
for (const { from, to } of
|
|
3267
|
-
syntaxTree2(
|
|
3264
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
3265
|
+
syntaxTree2(state2).iterate({
|
|
3268
3266
|
from,
|
|
3269
3267
|
to,
|
|
3270
3268
|
enter: (node) => {
|
|
@@ -3276,7 +3274,7 @@ var addList = (type) => ({ state, dispatch }) => {
|
|
|
3276
3274
|
}
|
|
3277
3275
|
if (before?.name === (type === 0 ? "OrderedList" : "BulletList")) {
|
|
3278
3276
|
const item = before.lastChild;
|
|
3279
|
-
const itemLine =
|
|
3277
|
+
const itemLine = state2.doc.lineAt(item.from);
|
|
3280
3278
|
const itemText = itemLine.text.slice(item.from - itemLine.from);
|
|
3281
3279
|
parentColumn = item.from - itemLine.from + /^\s*/.exec(itemText)[0].length;
|
|
3282
3280
|
if (type === 0) {
|
|
@@ -3311,10 +3309,10 @@ var addList = (type) => ({ state, dispatch }) => {
|
|
|
3311
3309
|
});
|
|
3312
3310
|
}
|
|
3313
3311
|
if (!blocks.length) {
|
|
3314
|
-
const { from, to } =
|
|
3312
|
+
const { from, to } = state2.doc.lineAt(state2.selection.main.anchor);
|
|
3315
3313
|
if (from === to) {
|
|
3316
3314
|
const insert = type === 1 ? "- " : type === 0 ? "1. " : "- [ ] ";
|
|
3317
|
-
dispatch(
|
|
3315
|
+
dispatch(state2.update({
|
|
3318
3316
|
changes: [
|
|
3319
3317
|
{
|
|
3320
3318
|
from,
|
|
@@ -3335,11 +3333,11 @@ var addList = (type) => ({ state, dispatch }) => {
|
|
|
3335
3333
|
for (let i = 0; i < blocks.length; i++) {
|
|
3336
3334
|
const { node, counter: counter2, parentColumn: parentColumn2 } = blocks[i];
|
|
3337
3335
|
const nodeFrom = node.name === "CodeBlock" ? node.from - 4 : node.from;
|
|
3338
|
-
let padding = nodeFrom > 0 && !/\s/.test(
|
|
3336
|
+
let padding = nodeFrom > 0 && !/\s/.test(state2.doc.sliceString(nodeFrom - 1, nodeFrom)) ? 1 : 0;
|
|
3339
3337
|
if (type === 0) {
|
|
3340
3338
|
padding += String(counter2).length;
|
|
3341
3339
|
}
|
|
3342
|
-
let line =
|
|
3340
|
+
let line = state2.doc.lineAt(nodeFrom);
|
|
3343
3341
|
const column = nodeFrom - line.from;
|
|
3344
3342
|
if (parentColumn2 !== null && parentColumn2 > column) {
|
|
3345
3343
|
padding = Math.max(padding, parentColumn2 - column);
|
|
@@ -3364,7 +3362,7 @@ var addList = (type) => ({ state, dispatch }) => {
|
|
|
3364
3362
|
insert: mark2
|
|
3365
3363
|
});
|
|
3366
3364
|
while (line.to < node.to) {
|
|
3367
|
-
line =
|
|
3365
|
+
line = state2.doc.lineAt(line.to + 1);
|
|
3368
3366
|
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
3369
3367
|
changes.push({
|
|
3370
3368
|
from: line.from + Math.min(open, column),
|
|
@@ -3379,25 +3377,25 @@ var addList = (type) => ({ state, dispatch }) => {
|
|
|
3379
3377
|
next = next.nextSibling;
|
|
3380
3378
|
}
|
|
3381
3379
|
if (next?.name === "OrderedList") {
|
|
3382
|
-
renumberListItems(next.firstChild, last.counter + 1, changes,
|
|
3380
|
+
renumberListItems(next.firstChild, last.counter + 1, changes, state2.doc);
|
|
3383
3381
|
}
|
|
3384
3382
|
}
|
|
3385
|
-
const changeSet =
|
|
3386
|
-
dispatch(
|
|
3383
|
+
const changeSet = state2.changes(changes);
|
|
3384
|
+
dispatch(state2.update({
|
|
3387
3385
|
changes: changeSet,
|
|
3388
|
-
selection:
|
|
3386
|
+
selection: state2.selection.map(changeSet, 1),
|
|
3389
3387
|
userEvent: "format.list.add",
|
|
3390
3388
|
scrollIntoView: true
|
|
3391
3389
|
}));
|
|
3392
3390
|
return true;
|
|
3393
3391
|
};
|
|
3394
|
-
var removeList = (type) => ({ state, dispatch }) => {
|
|
3392
|
+
var removeList = (type) => ({ state: state2, dispatch }) => {
|
|
3395
3393
|
let lastBlock = -1;
|
|
3396
3394
|
const changes = [];
|
|
3397
3395
|
const stack = [];
|
|
3398
3396
|
const targetNodeType = type === 0 ? "OrderedList" : type === 1 ? "BulletList" : "TaskList";
|
|
3399
|
-
for (const { from, to } of
|
|
3400
|
-
syntaxTree2(
|
|
3397
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
3398
|
+
syntaxTree2(state2).iterate({
|
|
3401
3399
|
from,
|
|
3402
3400
|
to,
|
|
3403
3401
|
enter: (node) => {
|
|
@@ -3414,7 +3412,7 @@ var removeList = (type) => ({ state, dispatch }) => {
|
|
|
3414
3412
|
stack.pop();
|
|
3415
3413
|
} else if (name === "ListItem" && stack[stack.length - 1] === targetNodeType && node.from !== lastBlock) {
|
|
3416
3414
|
lastBlock = node.from;
|
|
3417
|
-
let line =
|
|
3415
|
+
let line = state2.doc.lineAt(node.from);
|
|
3418
3416
|
const mark2 = /^\s*(\d+[.)] |[-*+] (\[[ x]\] )?)/.exec(line.text.slice(node.from - line.from));
|
|
3419
3417
|
if (!mark2) {
|
|
3420
3418
|
return false;
|
|
@@ -3425,7 +3423,7 @@ var removeList = (type) => ({ state, dispatch }) => {
|
|
|
3425
3423
|
to: node.from + mark2[0].length
|
|
3426
3424
|
});
|
|
3427
3425
|
while (line.to < node.to) {
|
|
3428
|
-
line =
|
|
3426
|
+
line = state2.doc.lineAt(line.to + 1);
|
|
3429
3427
|
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
3430
3428
|
if (open > column) {
|
|
3431
3429
|
changes.push({
|
|
@@ -3435,7 +3433,7 @@ var removeList = (type) => ({ state, dispatch }) => {
|
|
|
3435
3433
|
}
|
|
3436
3434
|
}
|
|
3437
3435
|
if (node.to >= to) {
|
|
3438
|
-
renumberListItems(node.node.nextSibling, 1, changes,
|
|
3436
|
+
renumberListItems(node.node.nextSibling, 1, changes, state2.doc);
|
|
3439
3437
|
}
|
|
3440
3438
|
return false;
|
|
3441
3439
|
}
|
|
@@ -3445,7 +3443,7 @@ var removeList = (type) => ({ state, dispatch }) => {
|
|
|
3445
3443
|
if (!changes.length) {
|
|
3446
3444
|
return false;
|
|
3447
3445
|
}
|
|
3448
|
-
dispatch(
|
|
3446
|
+
dispatch(state2.update({
|
|
3449
3447
|
changes,
|
|
3450
3448
|
userEvent: "format.list.remove",
|
|
3451
3449
|
scrollIntoView: true
|
|
@@ -3475,12 +3473,12 @@ var renumberListItems = (item, counter, changes, doc) => {
|
|
|
3475
3473
|
}
|
|
3476
3474
|
}
|
|
3477
3475
|
};
|
|
3478
|
-
var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
3476
|
+
var setBlockquote = (enable) => ({ state: state2, dispatch }) => {
|
|
3479
3477
|
const lines = [];
|
|
3480
3478
|
let lastBlock = -1;
|
|
3481
|
-
for (const { from, to } of
|
|
3479
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
3482
3480
|
const sawBlock = false;
|
|
3483
|
-
syntaxTree2(
|
|
3481
|
+
syntaxTree2(state2).iterate({
|
|
3484
3482
|
from,
|
|
3485
3483
|
to,
|
|
3486
3484
|
enter: (node) => {
|
|
@@ -3489,9 +3487,9 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
3489
3487
|
return false;
|
|
3490
3488
|
}
|
|
3491
3489
|
lastBlock = node.from;
|
|
3492
|
-
let line2 =
|
|
3490
|
+
let line2 = state2.doc.lineAt(node.from);
|
|
3493
3491
|
if (line2.number > 1) {
|
|
3494
|
-
const prevLine =
|
|
3492
|
+
const prevLine = state2.doc.line(line2.number - 1);
|
|
3495
3493
|
if (/^[>\s]*$/.test(prevLine.text)) {
|
|
3496
3494
|
if (!enable || lines.length && lines[lines.length - 1].number === prevLine.number - 1) {
|
|
3497
3495
|
lines.push(prevLine);
|
|
@@ -3503,10 +3501,10 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
3503
3501
|
if (line2.to >= node.to) {
|
|
3504
3502
|
break;
|
|
3505
3503
|
}
|
|
3506
|
-
line2 =
|
|
3504
|
+
line2 = state2.doc.line(line2.number + 1);
|
|
3507
3505
|
}
|
|
3508
|
-
if (!enable && line2.number <
|
|
3509
|
-
const nextLine =
|
|
3506
|
+
if (!enable && line2.number < state2.doc.lines) {
|
|
3507
|
+
const nextLine = state2.doc.line(line2.number + 1);
|
|
3510
3508
|
if (/^[>\s]*$/.test(nextLine.text)) {
|
|
3511
3509
|
lines.push(nextLine);
|
|
3512
3510
|
}
|
|
@@ -3516,7 +3514,7 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
3516
3514
|
}
|
|
3517
3515
|
});
|
|
3518
3516
|
let line;
|
|
3519
|
-
if (!sawBlock && enable && from === to && !/\S/.test((line =
|
|
3517
|
+
if (!sawBlock && enable && from === to && !/\S/.test((line = state2.doc.lineAt(from)).text)) {
|
|
3520
3518
|
lines.push(line);
|
|
3521
3519
|
}
|
|
3522
3520
|
}
|
|
@@ -3540,10 +3538,10 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
3540
3538
|
if (!changes.length) {
|
|
3541
3539
|
return false;
|
|
3542
3540
|
}
|
|
3543
|
-
const changeSet =
|
|
3544
|
-
dispatch(
|
|
3541
|
+
const changeSet = state2.changes(changes);
|
|
3542
|
+
dispatch(state2.update({
|
|
3545
3543
|
changes: changeSet,
|
|
3546
|
-
selection:
|
|
3544
|
+
selection: state2.selection.map(changeSet, 1),
|
|
3547
3545
|
userEvent: enable ? "format.blockquote.add" : "format.blockquote.remove",
|
|
3548
3546
|
scrollIntoView: true
|
|
3549
3547
|
}));
|
|
@@ -3555,11 +3553,11 @@ var toggleBlockquote = (target) => {
|
|
|
3555
3553
|
return (getFormatting(target.state).blockQuote ? removeBlockquote : addBlockquote)(target);
|
|
3556
3554
|
};
|
|
3557
3555
|
var addCodeblock = (target) => {
|
|
3558
|
-
const { state, dispatch } = target;
|
|
3559
|
-
const { selection } =
|
|
3556
|
+
const { state: state2, dispatch } = target;
|
|
3557
|
+
const { selection } = state2;
|
|
3560
3558
|
if (selection.ranges.length === 1 && selection.main.empty) {
|
|
3561
3559
|
const { head } = selection.main;
|
|
3562
|
-
const line =
|
|
3560
|
+
const line = state2.doc.lineAt(head);
|
|
3563
3561
|
if (!/\S/.test(line.text) && head === line.from) {
|
|
3564
3562
|
snippets.codeblock(target, null, line.from, line.to);
|
|
3565
3563
|
return true;
|
|
@@ -3569,7 +3567,7 @@ var addCodeblock = (target) => {
|
|
|
3569
3567
|
for (const { from, to } of selection.ranges) {
|
|
3570
3568
|
let blockFrom = from;
|
|
3571
3569
|
let blockTo = to;
|
|
3572
|
-
syntaxTree2(
|
|
3570
|
+
syntaxTree2(state2).iterate({
|
|
3573
3571
|
from,
|
|
3574
3572
|
to,
|
|
3575
3573
|
enter: (node) => {
|
|
@@ -3578,8 +3576,8 @@ var addCodeblock = (target) => {
|
|
|
3578
3576
|
blockFrom = node.from;
|
|
3579
3577
|
blockTo = node.to;
|
|
3580
3578
|
} else {
|
|
3581
|
-
blockFrom = Math.min(blockFrom,
|
|
3582
|
-
blockTo = Math.max(blockTo,
|
|
3579
|
+
blockFrom = Math.min(blockFrom, state2.doc.lineAt(node.from).from);
|
|
3580
|
+
blockTo = Math.max(blockTo, state2.doc.lineAt(node.to).to);
|
|
3583
3581
|
}
|
|
3584
3582
|
}
|
|
3585
3583
|
}
|
|
@@ -3597,7 +3595,7 @@ var addCodeblock = (target) => {
|
|
|
3597
3595
|
return false;
|
|
3598
3596
|
}
|
|
3599
3597
|
const changes = ranges.map(({ from, to }) => {
|
|
3600
|
-
const column = from -
|
|
3598
|
+
const column = from - state2.doc.lineAt(from).from;
|
|
3601
3599
|
return [
|
|
3602
3600
|
{
|
|
3603
3601
|
from,
|
|
@@ -3609,30 +3607,30 @@ var addCodeblock = (target) => {
|
|
|
3609
3607
|
}
|
|
3610
3608
|
];
|
|
3611
3609
|
});
|
|
3612
|
-
dispatch(
|
|
3610
|
+
dispatch(state2.update({
|
|
3613
3611
|
changes,
|
|
3614
3612
|
userEvent: "format.codeblock.add",
|
|
3615
3613
|
scrollIntoView: true
|
|
3616
3614
|
}));
|
|
3617
3615
|
return true;
|
|
3618
3616
|
};
|
|
3619
|
-
var removeCodeblock = ({ state, dispatch }) => {
|
|
3617
|
+
var removeCodeblock = ({ state: state2, dispatch }) => {
|
|
3620
3618
|
const changes = [];
|
|
3621
3619
|
let lastBlock = -1;
|
|
3622
|
-
for (const { from, to } of
|
|
3623
|
-
syntaxTree2(
|
|
3620
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
3621
|
+
syntaxTree2(state2).iterate({
|
|
3624
3622
|
from,
|
|
3625
3623
|
to,
|
|
3626
3624
|
enter: (node) => {
|
|
3627
3625
|
if (Textblocks[node.name] === "codeblock" && lastBlock !== node.from) {
|
|
3628
3626
|
lastBlock = node.from;
|
|
3629
|
-
const firstLine =
|
|
3627
|
+
const firstLine = state2.doc.lineAt(node.from);
|
|
3630
3628
|
if (node.name === "FencedCode") {
|
|
3631
3629
|
changes.push({
|
|
3632
3630
|
from: node.from,
|
|
3633
3631
|
to: firstLine.to + 1 + node.from - firstLine.from
|
|
3634
3632
|
});
|
|
3635
|
-
const lastLine =
|
|
3633
|
+
const lastLine = state2.doc.lineAt(node.to);
|
|
3636
3634
|
if (/^([\s>]|[-*+] |\d+[).])*`+$/.test(lastLine.text)) {
|
|
3637
3635
|
changes.push({
|
|
3638
3636
|
from: lastLine.from - (lastLine.number === firstLine.number + 1 ? 0 : 1),
|
|
@@ -3641,7 +3639,7 @@ var removeCodeblock = ({ state, dispatch }) => {
|
|
|
3641
3639
|
}
|
|
3642
3640
|
} else {
|
|
3643
3641
|
const column = node.from - firstLine.from;
|
|
3644
|
-
for (let line = firstLine; ; line =
|
|
3642
|
+
for (let line = firstLine; ; line = state2.doc.line(line.number + 1)) {
|
|
3645
3643
|
changes.push({
|
|
3646
3644
|
from: line.from + column - 4,
|
|
3647
3645
|
to: line.from + column
|
|
@@ -3658,7 +3656,7 @@ var removeCodeblock = ({ state, dispatch }) => {
|
|
|
3658
3656
|
if (!changes.length) {
|
|
3659
3657
|
return false;
|
|
3660
3658
|
}
|
|
3661
|
-
dispatch(
|
|
3659
|
+
dispatch(state2.update({
|
|
3662
3660
|
changes,
|
|
3663
3661
|
userEvent: "format.codeblock.remove",
|
|
3664
3662
|
scrollIntoView: true
|
|
@@ -3717,7 +3715,7 @@ var Textblocks = {
|
|
|
3717
3715
|
TableCell: "tablecell",
|
|
3718
3716
|
Task: "paragraph"
|
|
3719
3717
|
};
|
|
3720
|
-
var getFormatting = (
|
|
3718
|
+
var getFormatting = (state2) => {
|
|
3721
3719
|
let blockType = null;
|
|
3722
3720
|
const inline = [
|
|
3723
3721
|
null,
|
|
@@ -3743,7 +3741,7 @@ var getFormatting = (state) => {
|
|
|
3743
3741
|
continue;
|
|
3744
3742
|
} else if (currentBlock.active[i]) {
|
|
3745
3743
|
inline[i] = true;
|
|
3746
|
-
} else if (/\S/.test(
|
|
3744
|
+
} else if (/\S/.test(state2.doc.sliceString(currentBlock.pos, upto))) {
|
|
3747
3745
|
inline[i] = false;
|
|
3748
3746
|
}
|
|
3749
3747
|
}
|
|
@@ -3754,12 +3752,12 @@ var getFormatting = (state) => {
|
|
|
3754
3752
|
currentBlock.pos = Math.min(upto, currentBlock.end);
|
|
3755
3753
|
}
|
|
3756
3754
|
};
|
|
3757
|
-
const { selection } =
|
|
3755
|
+
const { selection } = state2;
|
|
3758
3756
|
for (const range of selection.ranges) {
|
|
3759
3757
|
if (range.empty && inline.some((v) => v === null)) {
|
|
3760
3758
|
const contextSize = Math.min(range.head, 6);
|
|
3761
|
-
const contextBefore =
|
|
3762
|
-
let contextAfter =
|
|
3759
|
+
const contextBefore = state2.doc.sliceString(range.head - contextSize, range.head);
|
|
3760
|
+
let contextAfter = state2.doc.sliceString(range.head, range.head + contextSize);
|
|
3763
3761
|
for (let i = 0; i < contextSize; i++) {
|
|
3764
3762
|
const ch = contextAfter[i];
|
|
3765
3763
|
if (ch !== contextBefore[contextBefore.length - 1 - i] || !/[~`*]/.test(ch)) {
|
|
@@ -3778,7 +3776,7 @@ var getFormatting = (state) => {
|
|
|
3778
3776
|
}
|
|
3779
3777
|
}
|
|
3780
3778
|
}
|
|
3781
|
-
syntaxTree2(
|
|
3779
|
+
syntaxTree2(state2).iterate({
|
|
3782
3780
|
from: range.from,
|
|
3783
3781
|
to: range.to,
|
|
3784
3782
|
enter: (node) => {
|
|
@@ -3852,7 +3850,7 @@ var getFormatting = (state) => {
|
|
|
3852
3850
|
}
|
|
3853
3851
|
});
|
|
3854
3852
|
}
|
|
3855
|
-
const { from, to } =
|
|
3853
|
+
const { from, to } = state2.doc.lineAt(selection.main.anchor);
|
|
3856
3854
|
const blankLine = from === to;
|
|
3857
3855
|
return {
|
|
3858
3856
|
blankLine,
|
|
@@ -3867,17 +3865,22 @@ var getFormatting = (state) => {
|
|
|
3867
3865
|
};
|
|
3868
3866
|
};
|
|
3869
3867
|
var useFormattingState = () => {
|
|
3870
|
-
const [
|
|
3868
|
+
const [state2, setState] = useState();
|
|
3871
3869
|
const observer = useMemo(() => EditorView13.updateListener.of((update2) => {
|
|
3872
3870
|
if (update2.docChanged || update2.selectionSet) {
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3871
|
+
setState((prevState) => {
|
|
3872
|
+
const newState = getFormatting(update2.state);
|
|
3873
|
+
if (!prevState || !formattingEquals(prevState, newState)) {
|
|
3874
|
+
return newState;
|
|
3875
|
+
}
|
|
3876
|
+
return prevState;
|
|
3877
|
+
});
|
|
3877
3878
|
}
|
|
3878
|
-
}), [
|
|
3879
|
+
}), [
|
|
3880
|
+
setState
|
|
3881
|
+
]);
|
|
3879
3882
|
return [
|
|
3880
|
-
|
|
3883
|
+
state2,
|
|
3881
3884
|
observer
|
|
3882
3885
|
];
|
|
3883
3886
|
};
|
|
@@ -3888,8 +3891,8 @@ import { StateField as StateField5 } from "@codemirror/state";
|
|
|
3888
3891
|
import { Decoration as Decoration6, EditorView as EditorView14, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
3889
3892
|
var image = (options = {}) => {
|
|
3890
3893
|
return StateField5.define({
|
|
3891
|
-
create: (
|
|
3892
|
-
return Decoration6.set(buildDecorations2(0,
|
|
3894
|
+
create: (state2) => {
|
|
3895
|
+
return Decoration6.set(buildDecorations2(0, state2.doc.length, state2));
|
|
3893
3896
|
},
|
|
3894
3897
|
update: (value, tr) => {
|
|
3895
3898
|
if (!tr.docChanged && !tr.selection) {
|
|
@@ -3923,16 +3926,16 @@ var preloadImage = (url) => {
|
|
|
3923
3926
|
preloaded.add(url);
|
|
3924
3927
|
}
|
|
3925
3928
|
};
|
|
3926
|
-
var buildDecorations2 = (from, to,
|
|
3929
|
+
var buildDecorations2 = (from, to, state2) => {
|
|
3927
3930
|
const decorations = [];
|
|
3928
|
-
const cursor =
|
|
3929
|
-
syntaxTree3(
|
|
3931
|
+
const cursor = state2.selection.main.head;
|
|
3932
|
+
syntaxTree3(state2).iterate({
|
|
3930
3933
|
enter: (node) => {
|
|
3931
3934
|
if (node.name === "Image") {
|
|
3932
3935
|
const urlNode = node.node.getChild("URL");
|
|
3933
3936
|
if (urlNode) {
|
|
3934
|
-
const hide2 =
|
|
3935
|
-
const url =
|
|
3937
|
+
const hide2 = state2.readOnly || cursor < node.from || cursor > node.to;
|
|
3938
|
+
const url = state2.sliceDoc(urlNode.from, urlNode.to);
|
|
3936
3939
|
preloadImage(url);
|
|
3937
3940
|
decorations.push(Decoration6.replace({
|
|
3938
3941
|
block: true,
|
|
@@ -3962,6 +3965,8 @@ var ImageWidget = class extends WidgetType4 {
|
|
|
3962
3965
|
return img;
|
|
3963
3966
|
}
|
|
3964
3967
|
};
|
|
3968
|
+
var imageUpload = (options = {}) => {
|
|
3969
|
+
};
|
|
3965
3970
|
|
|
3966
3971
|
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
3967
3972
|
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
@@ -4003,21 +4008,21 @@ import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField6 } from "
|
|
|
4003
4008
|
import { Decoration as Decoration7, EditorView as EditorView15, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
4004
4009
|
var table = (options = {}) => {
|
|
4005
4010
|
return StateField6.define({
|
|
4006
|
-
create: (
|
|
4011
|
+
create: (state2) => update(state2, options),
|
|
4007
4012
|
update: (_, tr) => update(tr.state, options),
|
|
4008
4013
|
provide: (field) => EditorView15.decorations.from(field)
|
|
4009
4014
|
});
|
|
4010
4015
|
};
|
|
4011
|
-
var update = (
|
|
4016
|
+
var update = (state2, options) => {
|
|
4012
4017
|
const builder = new RangeSetBuilder3();
|
|
4013
|
-
const cursor =
|
|
4018
|
+
const cursor = state2.selection.main.head;
|
|
4014
4019
|
const tables = [];
|
|
4015
4020
|
const getTable = () => tables[tables.length - 1];
|
|
4016
4021
|
const getRow = () => {
|
|
4017
4022
|
const table2 = getTable();
|
|
4018
4023
|
return table2.rows?.[table2.rows.length - 1];
|
|
4019
4024
|
};
|
|
4020
|
-
syntaxTree5(
|
|
4025
|
+
syntaxTree5(state2).iterate({
|
|
4021
4026
|
enter: (node) => {
|
|
4022
4027
|
switch (node.name) {
|
|
4023
4028
|
case "Table": {
|
|
@@ -4038,9 +4043,9 @@ var update = (state, options) => {
|
|
|
4038
4043
|
case "TableCell": {
|
|
4039
4044
|
const row = getRow();
|
|
4040
4045
|
if (row) {
|
|
4041
|
-
row.push(
|
|
4046
|
+
row.push(state2.sliceDoc(node.from, node.to));
|
|
4042
4047
|
} else {
|
|
4043
|
-
getTable().header?.push(
|
|
4048
|
+
getTable().header?.push(state2.sliceDoc(node.from, node.to));
|
|
4044
4049
|
}
|
|
4045
4050
|
break;
|
|
4046
4051
|
}
|
|
@@ -4048,7 +4053,7 @@ var update = (state, options) => {
|
|
|
4048
4053
|
}
|
|
4049
4054
|
});
|
|
4050
4055
|
tables.forEach((table2) => {
|
|
4051
|
-
const hide2 =
|
|
4056
|
+
const hide2 = state2.readOnly || cursor < table2.from || cursor > table2.to;
|
|
4052
4057
|
if (hide2) {
|
|
4053
4058
|
builder.add(table2.from, table2.to, Decoration7.replace({
|
|
4054
4059
|
widget: new TableWidget(table2)
|
|
@@ -4139,6 +4144,7 @@ var mention = ({ onSearch }) => {
|
|
|
4139
4144
|
import { Facet as Facet6 } from "@codemirror/state";
|
|
4140
4145
|
import { keymap as keymap7 } from "@codemirror/view";
|
|
4141
4146
|
import { vim } from "@replit/codemirror-vim";
|
|
4147
|
+
var focusEvent = "focus.container";
|
|
4142
4148
|
var editorMode = Facet6.define({
|
|
4143
4149
|
combine: (modes) => modes[0] ?? {}
|
|
4144
4150
|
});
|
|
@@ -4155,7 +4161,7 @@ var EditorModes = {
|
|
|
4155
4161
|
key: "Alt-Escape",
|
|
4156
4162
|
run: (view) => {
|
|
4157
4163
|
view.dispatch({
|
|
4158
|
-
userEvent:
|
|
4164
|
+
userEvent: focusEvent
|
|
4159
4165
|
});
|
|
4160
4166
|
return true;
|
|
4161
4167
|
}
|
|
@@ -4164,8 +4170,95 @@ var EditorModes = {
|
|
|
4164
4170
|
]
|
|
4165
4171
|
};
|
|
4166
4172
|
|
|
4173
|
+
// packages/ui/react-ui-editor/src/extensions/state.ts
|
|
4174
|
+
import { Transaction as Transaction2 } from "@codemirror/state";
|
|
4175
|
+
import { EditorView as EditorView16, keymap as keymap8 } from "@codemirror/view";
|
|
4176
|
+
import { debounce as debounce2 } from "@dxos/async";
|
|
4177
|
+
import { invariant as invariant4 } from "@dxos/invariant";
|
|
4178
|
+
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
4179
|
+
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/state.ts";
|
|
4180
|
+
var scrollAnnotation = "dxos.org/cm/scrolling";
|
|
4181
|
+
var keyPrefix = "dxos.org/react-ui-editor/state";
|
|
4182
|
+
var localStorageStateStoreAdapter = {
|
|
4183
|
+
setState: (id, state2) => {
|
|
4184
|
+
invariant4(id, void 0, {
|
|
4185
|
+
F: __dxlog_file11,
|
|
4186
|
+
L: 35,
|
|
4187
|
+
S: void 0,
|
|
4188
|
+
A: [
|
|
4189
|
+
"id",
|
|
4190
|
+
""
|
|
4191
|
+
]
|
|
4192
|
+
});
|
|
4193
|
+
localStorage.setItem(`${keyPrefix}/${id}`, JSON.stringify(state2));
|
|
4194
|
+
},
|
|
4195
|
+
getState: (id) => {
|
|
4196
|
+
invariant4(id, void 0, {
|
|
4197
|
+
F: __dxlog_file11,
|
|
4198
|
+
L: 39,
|
|
4199
|
+
S: void 0,
|
|
4200
|
+
A: [
|
|
4201
|
+
"id",
|
|
4202
|
+
""
|
|
4203
|
+
]
|
|
4204
|
+
});
|
|
4205
|
+
const state2 = localStorage.getItem(`${keyPrefix}/${id}`);
|
|
4206
|
+
return state2 ? JSON.parse(state2) : void 0;
|
|
4207
|
+
}
|
|
4208
|
+
};
|
|
4209
|
+
var state = ({ getState, setState } = {}) => {
|
|
4210
|
+
const setStateDebounced = debounce2(setState, 1e3);
|
|
4211
|
+
return [
|
|
4212
|
+
// TODO(burdon): Track scrolling (currently only updates when cursor moves).
|
|
4213
|
+
EditorView16.updateListener.of(({ view, changes, transactions }) => {
|
|
4214
|
+
const id = view.state.facet(documentId2);
|
|
4215
|
+
if (!id || transactions.some((tr) => tr.isUserEvent(scrollAnnotation))) {
|
|
4216
|
+
return;
|
|
4217
|
+
}
|
|
4218
|
+
if (setState) {
|
|
4219
|
+
const { top } = view.dom.getBoundingClientRect();
|
|
4220
|
+
const pos = view.posAtCoords({
|
|
4221
|
+
x: 0,
|
|
4222
|
+
y: top
|
|
4223
|
+
});
|
|
4224
|
+
if (pos !== null) {
|
|
4225
|
+
const { anchor, head } = view.state.selection.main;
|
|
4226
|
+
setStateDebounced(id, {
|
|
4227
|
+
scrollTo: {
|
|
4228
|
+
from: pos,
|
|
4229
|
+
yMargin: 0
|
|
4230
|
+
},
|
|
4231
|
+
selection: {
|
|
4232
|
+
anchor,
|
|
4233
|
+
head
|
|
4234
|
+
}
|
|
4235
|
+
});
|
|
4236
|
+
}
|
|
4237
|
+
}
|
|
4238
|
+
}),
|
|
4239
|
+
getState && keymap8.of([
|
|
4240
|
+
{
|
|
4241
|
+
key: "ctrl-r",
|
|
4242
|
+
run: (view) => {
|
|
4243
|
+
const state2 = getState(view.state.facet(documentId2));
|
|
4244
|
+
if (state2) {
|
|
4245
|
+
view.dispatch({
|
|
4246
|
+
effects: EditorView16.scrollIntoView(state2.scrollTo.from, {
|
|
4247
|
+
yMargin: 0
|
|
4248
|
+
}),
|
|
4249
|
+
selection: state2.selection,
|
|
4250
|
+
annotations: Transaction2.userEvent.of(scrollAnnotation)
|
|
4251
|
+
});
|
|
4252
|
+
}
|
|
4253
|
+
return true;
|
|
4254
|
+
}
|
|
4255
|
+
}
|
|
4256
|
+
])
|
|
4257
|
+
].filter(isNotFalsy3);
|
|
4258
|
+
};
|
|
4259
|
+
|
|
4167
4260
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
4168
|
-
import { keymap as
|
|
4261
|
+
import { keymap as keymap9 } from "@codemirror/view";
|
|
4169
4262
|
var defaultItems = [
|
|
4170
4263
|
"hello world!",
|
|
4171
4264
|
"this is a test.",
|
|
@@ -4175,7 +4268,7 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
4175
4268
|
let t;
|
|
4176
4269
|
let idx = 0;
|
|
4177
4270
|
return [
|
|
4178
|
-
|
|
4271
|
+
keymap9.of([
|
|
4179
4272
|
{
|
|
4180
4273
|
// Reset.
|
|
4181
4274
|
key: "alt-meta-'",
|
|
@@ -4222,9 +4315,11 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
4222
4315
|
};
|
|
4223
4316
|
|
|
4224
4317
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
4225
|
-
var
|
|
4318
|
+
var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
4226
4319
|
var instanceCount = 0;
|
|
4227
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, className, autoFocus, scrollTo =
|
|
4320
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, className, autoFocus, scrollTo = EditorView17.scrollIntoView(0, {
|
|
4321
|
+
yMargin: 0
|
|
4322
|
+
}), moveToEndOfLine, debug, dataTestId }, forwardedRef) => {
|
|
4228
4323
|
const [instanceId] = useState2(() => `text-editor-${++instanceCount}`);
|
|
4229
4324
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
4230
4325
|
tabBehavior: "limited"
|
|
@@ -4243,42 +4338,42 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4243
4338
|
autoFocus
|
|
4244
4339
|
]);
|
|
4245
4340
|
useEffect2(() => {
|
|
4246
|
-
log9("
|
|
4341
|
+
log9("create", {
|
|
4247
4342
|
id,
|
|
4248
4343
|
instanceId
|
|
4249
4344
|
}, {
|
|
4250
|
-
F:
|
|
4345
|
+
F: __dxlog_file12,
|
|
4251
4346
|
L: 88,
|
|
4252
4347
|
S: void 0,
|
|
4253
4348
|
C: (f, a) => f(...a)
|
|
4254
4349
|
});
|
|
4255
|
-
const
|
|
4350
|
+
const state2 = EditorState2.create({
|
|
4256
4351
|
doc,
|
|
4257
4352
|
selection,
|
|
4258
4353
|
extensions: [
|
|
4259
4354
|
id && documentId2.of(id),
|
|
4260
4355
|
// TODO(burdon): NOTE: Doesn't catch errors in keymap functions.
|
|
4261
|
-
|
|
4356
|
+
EditorView17.exceptionSink.of((err) => {
|
|
4262
4357
|
log9.catch(err, void 0, {
|
|
4263
|
-
F:
|
|
4358
|
+
F: __dxlog_file12,
|
|
4264
4359
|
L: 101,
|
|
4265
4360
|
S: void 0,
|
|
4266
4361
|
C: (f, a) => f(...a)
|
|
4267
4362
|
});
|
|
4268
4363
|
}),
|
|
4269
4364
|
// Focus.
|
|
4270
|
-
|
|
4365
|
+
EditorView17.updateListener.of((update2) => {
|
|
4271
4366
|
update2.transactions.forEach((transaction) => {
|
|
4272
|
-
if (transaction.isUserEvent(
|
|
4367
|
+
if (transaction.isUserEvent(focusEvent)) {
|
|
4273
4368
|
rootRef.current?.focus();
|
|
4274
4369
|
}
|
|
4275
4370
|
});
|
|
4276
4371
|
}),
|
|
4277
4372
|
extensions
|
|
4278
|
-
].filter(
|
|
4373
|
+
].filter(isNotFalsy4)
|
|
4279
4374
|
});
|
|
4280
|
-
const view2 = new
|
|
4281
|
-
state,
|
|
4375
|
+
const view2 = new EditorView17({
|
|
4376
|
+
state: state2,
|
|
4282
4377
|
parent: rootRef.current,
|
|
4283
4378
|
scrollTo,
|
|
4284
4379
|
// NOTE: Uncomment to debug/monitor all transactions.
|
|
@@ -4290,21 +4385,29 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4290
4385
|
view3.update(trs);
|
|
4291
4386
|
}
|
|
4292
4387
|
});
|
|
4293
|
-
|
|
4294
|
-
if (moveToEndOfLine) {
|
|
4388
|
+
if (moveToEndOfLine && !(scrollTo || selection)) {
|
|
4295
4389
|
const { to } = view2.state.doc.lineAt(0);
|
|
4296
|
-
view2
|
|
4390
|
+
view2.dispatch({
|
|
4297
4391
|
selection: {
|
|
4298
4392
|
anchor: to
|
|
4299
4393
|
}
|
|
4300
4394
|
});
|
|
4301
4395
|
}
|
|
4302
|
-
if (
|
|
4396
|
+
if (state2.facet(editorMode).noTabster) {
|
|
4303
4397
|
rootRef.current?.removeAttribute("data-tabster");
|
|
4304
4398
|
}
|
|
4399
|
+
setView(view2);
|
|
4305
4400
|
return () => {
|
|
4401
|
+
log9("destroy", {
|
|
4402
|
+
id,
|
|
4403
|
+
instanceId
|
|
4404
|
+
}, {
|
|
4405
|
+
F: __dxlog_file12,
|
|
4406
|
+
L: 150,
|
|
4407
|
+
S: void 0,
|
|
4408
|
+
C: (f, a) => f(...a)
|
|
4409
|
+
});
|
|
4306
4410
|
view2?.destroy();
|
|
4307
|
-
setView(null);
|
|
4308
4411
|
};
|
|
4309
4412
|
}, [
|
|
4310
4413
|
doc,
|
|
@@ -4334,9 +4437,10 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4334
4437
|
});
|
|
4335
4438
|
|
|
4336
4439
|
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
|
4337
|
-
import { ChatText, Code, CodeBlock, Link, ListBullets, ListChecks, ListNumbers, Paragraph, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic
|
|
4440
|
+
import { ChatText, Code, CodeBlock, Image, Link, ListBullets, ListChecks, ListNumbers, Paragraph, Quotes, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic } from "@phosphor-icons/react";
|
|
4338
4441
|
import { createContext } from "@radix-ui/react-context";
|
|
4339
|
-
import React2, { useRef as useRef2, useState as useState3 } from "react";
|
|
4442
|
+
import React2, { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
4443
|
+
import { useDropzone } from "react-dropzone";
|
|
4340
4444
|
import { DensityProvider, ElevationProvider, Select, Toolbar as NaturalToolbar, Tooltip, useTranslation } from "@dxos/react-ui";
|
|
4341
4445
|
import { getSize } from "@dxos/react-ui-theme";
|
|
4342
4446
|
var tooltipProps = {
|
|
@@ -4353,10 +4457,10 @@ var HeadingIcons = {
|
|
|
4353
4457
|
"6": TextHSix
|
|
4354
4458
|
};
|
|
4355
4459
|
var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
|
|
4356
|
-
var ToolbarRoot = ({ children, onAction, classNames, state }) => {
|
|
4460
|
+
var ToolbarRoot = ({ children, onAction, classNames, state: state2 }) => {
|
|
4357
4461
|
return /* @__PURE__ */ React2.createElement(ToolbarContextProvider, {
|
|
4358
4462
|
onAction,
|
|
4359
|
-
state
|
|
4463
|
+
state: state2
|
|
4360
4464
|
}, /* @__PURE__ */ React2.createElement(DensityProvider, {
|
|
4361
4465
|
density: "fine"
|
|
4362
4466
|
}, /* @__PURE__ */ React2.createElement(ElevationProvider, {
|
|
@@ -4370,7 +4474,7 @@ var ToolbarRoot = ({ children, onAction, classNames, state }) => {
|
|
|
4370
4474
|
};
|
|
4371
4475
|
var buttonStyles = "min-bs-0 p-2";
|
|
4372
4476
|
var iconStyles = getSize(5);
|
|
4373
|
-
var
|
|
4477
|
+
var ToolbarToggleButton = ({ Icon, children, ...props }) => {
|
|
4374
4478
|
return /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
|
|
4375
4479
|
asChild: true
|
|
4376
4480
|
}, /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroupItem, {
|
|
@@ -4383,14 +4487,27 @@ var ToolbarButton = ({ Icon, children, ...props }) => {
|
|
|
4383
4487
|
className: "sr-only"
|
|
4384
4488
|
}, children))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
|
|
4385
4489
|
};
|
|
4490
|
+
var ToolbarButton = ({ Icon, children, ...props }) => {
|
|
4491
|
+
return /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
|
|
4492
|
+
asChild: true
|
|
4493
|
+
}, /* @__PURE__ */ React2.createElement(NaturalToolbar.Button, {
|
|
4494
|
+
variant: "ghost",
|
|
4495
|
+
...props,
|
|
4496
|
+
classNames: buttonStyles
|
|
4497
|
+
}, /* @__PURE__ */ React2.createElement(Icon, {
|
|
4498
|
+
className: iconStyles
|
|
4499
|
+
}), /* @__PURE__ */ React2.createElement("span", {
|
|
4500
|
+
className: "sr-only"
|
|
4501
|
+
}, children))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
|
|
4502
|
+
};
|
|
4386
4503
|
var ToolbarSeparator = () => /* @__PURE__ */ React2.createElement("div", {
|
|
4387
4504
|
role: "separator",
|
|
4388
4505
|
className: "grow"
|
|
4389
4506
|
});
|
|
4390
4507
|
var MarkdownHeading = () => {
|
|
4391
4508
|
const { t } = useTranslation(translationKey);
|
|
4392
|
-
const { onAction, state } = useToolbarContext("MarkdownFormatting");
|
|
4393
|
-
const blockType =
|
|
4509
|
+
const { onAction, state: state2 } = useToolbarContext("MarkdownFormatting");
|
|
4510
|
+
const blockType = state2 ? state2.blockType : "paragraph";
|
|
4394
4511
|
const header = blockType && /heading(\d)/.exec(blockType);
|
|
4395
4512
|
const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : void 0;
|
|
4396
4513
|
const HeadingIcon = HeadingIcons[value ?? "0"];
|
|
@@ -4464,43 +4581,43 @@ var markdownStyles = [
|
|
|
4464
4581
|
{
|
|
4465
4582
|
type: "strong",
|
|
4466
4583
|
Icon: TextB,
|
|
4467
|
-
getState: (
|
|
4584
|
+
getState: (state2) => state2.strong
|
|
4468
4585
|
},
|
|
4469
4586
|
{
|
|
4470
4587
|
type: "emphasis",
|
|
4471
4588
|
Icon: TextItalic,
|
|
4472
|
-
getState: (
|
|
4589
|
+
getState: (state2) => state2.emphasis
|
|
4473
4590
|
},
|
|
4474
4591
|
{
|
|
4475
4592
|
type: "strikethrough",
|
|
4476
4593
|
Icon: TextStrikethrough,
|
|
4477
|
-
getState: (
|
|
4594
|
+
getState: (state2) => state2.strikethrough
|
|
4478
4595
|
},
|
|
4479
4596
|
{
|
|
4480
4597
|
type: "code",
|
|
4481
4598
|
Icon: Code,
|
|
4482
|
-
getState: (
|
|
4599
|
+
getState: (state2) => state2.code
|
|
4483
4600
|
},
|
|
4484
4601
|
{
|
|
4485
4602
|
type: "link",
|
|
4486
4603
|
Icon: Link,
|
|
4487
|
-
getState: (
|
|
4604
|
+
getState: (state2) => state2.link
|
|
4488
4605
|
}
|
|
4489
4606
|
];
|
|
4490
4607
|
var MarkdownStyles = () => {
|
|
4491
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
|
4608
|
+
const { onAction, state: state2 } = useToolbarContext("MarkdownStyles");
|
|
4492
4609
|
const { t } = useTranslation(translationKey);
|
|
4493
4610
|
return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
|
|
4494
4611
|
type: "multiple",
|
|
4495
|
-
value: markdownStyles.filter(({ getState }) =>
|
|
4496
|
-
}, markdownStyles.map(({ type, getState, Icon }) => /* @__PURE__ */ React2.createElement(
|
|
4612
|
+
value: markdownStyles.filter(({ getState }) => state2 && getState(state2)).map(({ type }) => type)
|
|
4613
|
+
}, markdownStyles.map(({ type, getState, Icon }) => /* @__PURE__ */ React2.createElement(ToolbarToggleButton, {
|
|
4497
4614
|
key: type,
|
|
4498
4615
|
value: type,
|
|
4499
4616
|
Icon,
|
|
4500
|
-
disabled:
|
|
4501
|
-
onClick:
|
|
4617
|
+
disabled: state2?.blockType === "codeblock",
|
|
4618
|
+
onClick: state2 ? () => onAction?.({
|
|
4502
4619
|
type,
|
|
4503
|
-
data: !getState(
|
|
4620
|
+
data: !getState(state2)
|
|
4504
4621
|
}) : void 0
|
|
4505
4622
|
}, t(`${type} label`))));
|
|
4506
4623
|
};
|
|
@@ -4508,32 +4625,32 @@ var markdownLists = [
|
|
|
4508
4625
|
{
|
|
4509
4626
|
type: "list-bullet",
|
|
4510
4627
|
Icon: ListBullets,
|
|
4511
|
-
getState: (
|
|
4628
|
+
getState: (state2) => state2.listStyle === "bullet"
|
|
4512
4629
|
},
|
|
4513
4630
|
{
|
|
4514
4631
|
type: "list-ordered",
|
|
4515
4632
|
Icon: ListNumbers,
|
|
4516
|
-
getState: (
|
|
4633
|
+
getState: (state2) => state2.listStyle === "ordered"
|
|
4517
4634
|
},
|
|
4518
4635
|
{
|
|
4519
4636
|
type: "list-task",
|
|
4520
4637
|
Icon: ListChecks,
|
|
4521
|
-
getState: (
|
|
4638
|
+
getState: (state2) => state2.listStyle === "task"
|
|
4522
4639
|
}
|
|
4523
4640
|
];
|
|
4524
4641
|
var MarkdownLists = () => {
|
|
4525
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
|
4642
|
+
const { onAction, state: state2 } = useToolbarContext("MarkdownStyles");
|
|
4526
4643
|
const { t } = useTranslation(translationKey);
|
|
4527
4644
|
return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
|
|
4528
4645
|
type: "single",
|
|
4529
|
-
value:
|
|
4530
|
-
}, markdownLists.map(({ type, getState, Icon }) => /* @__PURE__ */ React2.createElement(
|
|
4646
|
+
value: state2?.listStyle ? `list-${state2.listStyle}` : ""
|
|
4647
|
+
}, markdownLists.map(({ type, getState, Icon }) => /* @__PURE__ */ React2.createElement(ToolbarToggleButton, {
|
|
4531
4648
|
key: type,
|
|
4532
4649
|
value: type,
|
|
4533
4650
|
Icon,
|
|
4534
|
-
onClick:
|
|
4651
|
+
onClick: state2 ? () => onAction?.({
|
|
4535
4652
|
type,
|
|
4536
|
-
data: !getState(
|
|
4653
|
+
data: !getState(state2)
|
|
4537
4654
|
}) : void 0
|
|
4538
4655
|
}, t(`${type} label`))));
|
|
4539
4656
|
};
|
|
@@ -4541,63 +4658,101 @@ var markdownBlocks = [
|
|
|
4541
4658
|
{
|
|
4542
4659
|
type: "blockquote",
|
|
4543
4660
|
Icon: Quotes,
|
|
4544
|
-
getState: (
|
|
4661
|
+
getState: (state2) => state2.blockQuote
|
|
4545
4662
|
},
|
|
4546
4663
|
{
|
|
4547
4664
|
type: "codeblock",
|
|
4548
4665
|
Icon: CodeBlock,
|
|
4549
|
-
getState: (
|
|
4666
|
+
getState: (state2) => state2.blockType === "codeblock"
|
|
4550
4667
|
},
|
|
4551
4668
|
{
|
|
4552
4669
|
type: "table",
|
|
4553
4670
|
Icon: Table2,
|
|
4554
|
-
getState: (
|
|
4555
|
-
disabled: (
|
|
4671
|
+
getState: (state2) => state2.blockType === "tablecell",
|
|
4672
|
+
disabled: (state2) => !state2.blankLine
|
|
4556
4673
|
}
|
|
4557
4674
|
];
|
|
4558
4675
|
var MarkdownBlocks = () => {
|
|
4559
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
|
4676
|
+
const { onAction, state: state2 } = useToolbarContext("MarkdownStyles");
|
|
4560
4677
|
const { t } = useTranslation(translationKey);
|
|
4561
|
-
const value = markdownBlocks.find(({ getState }) =>
|
|
4678
|
+
const value = markdownBlocks.find(({ getState }) => state2 && getState(state2));
|
|
4562
4679
|
return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
|
|
4563
4680
|
type: "single",
|
|
4564
4681
|
value: value?.type ?? ""
|
|
4565
|
-
}, markdownBlocks.map(({ type, disabled, getState, Icon }) => /* @__PURE__ */ React2.createElement(
|
|
4682
|
+
}, markdownBlocks.map(({ type, disabled, getState, Icon }) => /* @__PURE__ */ React2.createElement(ToolbarToggleButton, {
|
|
4566
4683
|
key: type,
|
|
4567
4684
|
value: type,
|
|
4568
4685
|
Icon,
|
|
4569
|
-
disabled: !
|
|
4570
|
-
onClick:
|
|
4686
|
+
disabled: !state2 || disabled?.(state2),
|
|
4687
|
+
onClick: state2 ? () => onAction?.({
|
|
4571
4688
|
type,
|
|
4572
|
-
data: !getState(
|
|
4689
|
+
data: !getState(state2)
|
|
4573
4690
|
}) : void 0
|
|
4574
4691
|
}, t(`${type} label`))));
|
|
4575
4692
|
};
|
|
4576
4693
|
var MarkdownStandard = () => /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(MarkdownHeading, null), /* @__PURE__ */ React2.createElement(MarkdownStyles, null), /* @__PURE__ */ React2.createElement(MarkdownLists, null), /* @__PURE__ */ React2.createElement(MarkdownBlocks, null));
|
|
4577
|
-
var
|
|
4694
|
+
var MarkdownCustom = ({ onUpload } = {}) => {
|
|
4578
4695
|
const { onAction } = useToolbarContext("MarkdownStyles");
|
|
4579
4696
|
const { t } = useTranslation(translationKey);
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4697
|
+
const { acceptedFiles, getInputProps, open } = useDropzone({
|
|
4698
|
+
multiple: false,
|
|
4699
|
+
noDrag: true,
|
|
4700
|
+
accept: {
|
|
4701
|
+
"image/*": [
|
|
4702
|
+
".jpg",
|
|
4703
|
+
".jpeg",
|
|
4704
|
+
".png",
|
|
4705
|
+
".gif"
|
|
4706
|
+
]
|
|
4707
|
+
}
|
|
4708
|
+
});
|
|
4709
|
+
useEffect3(() => {
|
|
4710
|
+
if (onUpload && acceptedFiles.length) {
|
|
4711
|
+
setTimeout(async () => {
|
|
4712
|
+
const f = acceptedFiles[0];
|
|
4713
|
+
const file = new File([
|
|
4714
|
+
f
|
|
4715
|
+
], f.name, {
|
|
4716
|
+
type: f.type,
|
|
4717
|
+
lastModified: f.lastModified
|
|
4718
|
+
});
|
|
4719
|
+
const { url } = await onUpload(file);
|
|
4720
|
+
if (url) {
|
|
4721
|
+
onAction?.({
|
|
4722
|
+
type: "image",
|
|
4723
|
+
data: url
|
|
4724
|
+
});
|
|
4725
|
+
}
|
|
4726
|
+
});
|
|
4727
|
+
}
|
|
4728
|
+
}, [
|
|
4729
|
+
acceptedFiles
|
|
4730
|
+
]);
|
|
4731
|
+
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("input", getInputProps()), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4732
|
+
value: "image",
|
|
4733
|
+
Icon: Image,
|
|
4734
|
+
onClick: () => open()
|
|
4735
|
+
}, t("image label")));
|
|
4736
|
+
};
|
|
4737
|
+
var MarkdownActions = () => {
|
|
4738
|
+
const { onAction } = useToolbarContext("MarkdownStyles");
|
|
4739
|
+
const { t } = useTranslation(translationKey);
|
|
4740
|
+
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4741
|
+
value: "comment",
|
|
4742
|
+
Icon: ChatText,
|
|
4584
4743
|
"data-testid": "editor.toolbar.comment",
|
|
4585
4744
|
onClick: () => onAction?.({
|
|
4586
4745
|
type: "comment"
|
|
4587
|
-
})
|
|
4588
|
-
|
|
4589
|
-
}, /* @__PURE__ */ React2.createElement(ChatText, {
|
|
4590
|
-
className: iconStyles
|
|
4591
|
-
}), /* @__PURE__ */ React2.createElement("span", {
|
|
4592
|
-
className: "sr-only"
|
|
4593
|
-
}, t("comment label")))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, t("comment label"), /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
|
|
4746
|
+
})
|
|
4747
|
+
}, t("comment label")));
|
|
4594
4748
|
};
|
|
4595
4749
|
var Toolbar = {
|
|
4596
4750
|
Root: ToolbarRoot,
|
|
4597
|
-
Button:
|
|
4751
|
+
Button: ToolbarToggleButton,
|
|
4598
4752
|
Separator: ToolbarSeparator,
|
|
4599
4753
|
Markdown: MarkdownStandard,
|
|
4600
|
-
|
|
4754
|
+
Custom: MarkdownCustom,
|
|
4755
|
+
Actions: MarkdownActions
|
|
4601
4756
|
};
|
|
4602
4757
|
|
|
4603
4758
|
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
@@ -4634,7 +4789,13 @@ var useActionHandler = (view) => {
|
|
|
4634
4789
|
insertTable(view);
|
|
4635
4790
|
break;
|
|
4636
4791
|
case "link":
|
|
4637
|
-
(action.data === false ? removeLink : addLink)(view);
|
|
4792
|
+
(action.data === false ? removeLink : addLink())(view);
|
|
4793
|
+
break;
|
|
4794
|
+
case "image":
|
|
4795
|
+
addLink({
|
|
4796
|
+
url: action.data,
|
|
4797
|
+
image: true
|
|
4798
|
+
})(view);
|
|
4638
4799
|
break;
|
|
4639
4800
|
case "comment":
|
|
4640
4801
|
createComment(view);
|
|
@@ -4663,43 +4824,51 @@ var useDocAccessor = (text) => {
|
|
|
4663
4824
|
|
|
4664
4825
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4665
4826
|
import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
|
|
4666
|
-
import { EditorView as
|
|
4667
|
-
import { useEffect as
|
|
4827
|
+
import { EditorView as EditorView18 } from "@codemirror/view";
|
|
4828
|
+
import { useEffect as useEffect4, useMemo as useMemo3, useRef as useRef3, useState as useState4 } from "react";
|
|
4668
4829
|
import { log as log10 } from "@dxos/log";
|
|
4669
|
-
import { isNotFalsy as
|
|
4670
|
-
var
|
|
4830
|
+
import { isNotFalsy as isNotFalsy5 } from "@dxos/util";
|
|
4831
|
+
var __dxlog_file13 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
4671
4832
|
var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
4672
4833
|
let { id, doc, selection, extensions, autoFocus, scrollTo, debug } = useMemo3(cb, deps ?? []);
|
|
4673
4834
|
const onUpdate = useRef3();
|
|
4674
4835
|
const [view, setView] = useState4();
|
|
4675
4836
|
const parentRef = useRef3(null);
|
|
4676
|
-
|
|
4837
|
+
useEffect4(() => {
|
|
4677
4838
|
let view2;
|
|
4678
4839
|
if (parentRef.current) {
|
|
4679
|
-
|
|
4840
|
+
log10("create", {
|
|
4841
|
+
id
|
|
4842
|
+
}, {
|
|
4843
|
+
F: __dxlog_file13,
|
|
4844
|
+
L: 36,
|
|
4845
|
+
S: void 0,
|
|
4846
|
+
C: (f, a) => f(...a)
|
|
4847
|
+
});
|
|
4848
|
+
const state2 = EditorState3.create({
|
|
4680
4849
|
doc,
|
|
4681
4850
|
selection,
|
|
4682
4851
|
extensions: [
|
|
4683
4852
|
id && documentId2.of(id),
|
|
4684
4853
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4685
|
-
|
|
4854
|
+
EditorView18.exceptionSink.of((err) => {
|
|
4686
4855
|
log10.catch(err, void 0, {
|
|
4687
|
-
F:
|
|
4688
|
-
L:
|
|
4856
|
+
F: __dxlog_file13,
|
|
4857
|
+
L: 46,
|
|
4689
4858
|
S: void 0,
|
|
4690
4859
|
C: (f, a) => f(...a)
|
|
4691
4860
|
});
|
|
4692
4861
|
}),
|
|
4693
4862
|
extensions,
|
|
4694
|
-
|
|
4863
|
+
EditorView18.updateListener.of(() => {
|
|
4695
4864
|
onUpdate.current?.();
|
|
4696
4865
|
})
|
|
4697
|
-
].filter(
|
|
4866
|
+
].filter(isNotFalsy5)
|
|
4698
4867
|
});
|
|
4699
|
-
view2 = new
|
|
4868
|
+
view2 = new EditorView18({
|
|
4700
4869
|
parent: parentRef.current,
|
|
4701
4870
|
scrollTo,
|
|
4702
|
-
state,
|
|
4871
|
+
state: state2,
|
|
4703
4872
|
// NOTE: Uncomment to debug/monitor all transactions.
|
|
4704
4873
|
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
4705
4874
|
dispatchTransactions: (trs, view3) => {
|
|
@@ -4712,10 +4881,18 @@ var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
|
4712
4881
|
setView(view2);
|
|
4713
4882
|
}
|
|
4714
4883
|
return () => {
|
|
4884
|
+
log10("destroy", {
|
|
4885
|
+
id
|
|
4886
|
+
}, {
|
|
4887
|
+
F: __dxlog_file13,
|
|
4888
|
+
L: 74,
|
|
4889
|
+
S: void 0,
|
|
4890
|
+
C: (f, a) => f(...a)
|
|
4891
|
+
});
|
|
4715
4892
|
view2?.destroy();
|
|
4716
4893
|
};
|
|
4717
4894
|
}, deps);
|
|
4718
|
-
|
|
4895
|
+
useEffect4(() => {
|
|
4719
4896
|
if (view) {
|
|
4720
4897
|
if (!selection && !view.state.selection.main.anchor) {
|
|
4721
4898
|
selection = EditorSelection2.single(view.state.doc.line(1).to);
|
|
@@ -4774,7 +4951,6 @@ export {
|
|
|
4774
4951
|
callbackWrapper,
|
|
4775
4952
|
command,
|
|
4776
4953
|
comments,
|
|
4777
|
-
compareFormatting,
|
|
4778
4954
|
createBasicExtensions,
|
|
4779
4955
|
createComment,
|
|
4780
4956
|
createDataExtensions,
|
|
@@ -4791,14 +4967,18 @@ export {
|
|
|
4791
4967
|
editorMode,
|
|
4792
4968
|
editorWithToolbarLayout,
|
|
4793
4969
|
focusComment,
|
|
4970
|
+
focusEvent,
|
|
4971
|
+
formattingEquals,
|
|
4794
4972
|
formattingKeymap,
|
|
4795
4973
|
getFormatting,
|
|
4796
4974
|
getToken,
|
|
4797
4975
|
image,
|
|
4976
|
+
imageUpload,
|
|
4798
4977
|
insertTable,
|
|
4799
|
-
|
|
4978
|
+
keymap10 as keymap,
|
|
4800
4979
|
linkTooltip,
|
|
4801
4980
|
listener,
|
|
4981
|
+
localStorageStateStoreAdapter,
|
|
4802
4982
|
logChanges,
|
|
4803
4983
|
markdownHighlightStyle,
|
|
4804
4984
|
markdownTags,
|
|
@@ -4814,6 +4994,7 @@ export {
|
|
|
4814
4994
|
setHeading,
|
|
4815
4995
|
setSelection,
|
|
4816
4996
|
setStyle,
|
|
4997
|
+
state,
|
|
4817
4998
|
table,
|
|
4818
4999
|
tags2 as tags,
|
|
4819
5000
|
toggleBlockquote,
|