@dxos/react-ui-editor 0.4.7-main.85d9ee7 → 0.4.7-main.b1ae49b
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 +563 -522
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +3 -0
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +0 -9
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/index.d.ts +0 -2
- package/dist/types/src/components/TextEditor/index.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/{components/TextEditor → extensions/automerge}/automerge.stories.d.ts +4 -2
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -0
- package/dist/types/src/extensions/command/command.d.ts.map +1 -1
- package/dist/types/src/extensions/command/hint.d.ts.map +1 -1
- package/dist/types/src/extensions/command/state.d.ts +1 -1
- package/dist/types/src/extensions/command/state.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/cursor-line-margin.d.ts.map +1 -1
- package/dist/types/src/extensions/dnd.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +0 -1
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/listener.d.ts +1 -1
- package/dist/types/src/extensions/listener.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +2 -2
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts +3 -0
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
- package/dist/types/src/extensions/mention.d.ts.map +1 -1
- package/dist/types/src/hooks/defs.d.ts +5 -11
- package/dist/types/src/hooks/defs.d.ts.map +1 -1
- package/dist/types/src/hooks/useEditorView.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.d.ts +20 -5
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/{components/TextEditor/hooks.stories.d.ts → hooks/useTextEditor.stories.d.ts} +1 -3
- package/dist/types/src/hooks/useTextEditor.stories.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/package.json +30 -30
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +25 -6
- package/src/components/TextEditor/TextEditor.stories.tsx +0 -15
- package/src/components/TextEditor/TextEditor.tsx +11 -6
- package/src/components/TextEditor/index.ts +0 -3
- package/src/components/Toolbar/Toolbar.stories.tsx +2 -1
- package/src/{components/TextEditor → extensions/automerge}/automerge.stories.tsx +32 -37
- package/src/extensions/command/command.ts +4 -7
- package/src/extensions/command/hint.ts +1 -0
- package/src/extensions/command/state.ts +2 -2
- package/src/extensions/comments.ts +2 -1
- package/src/extensions/cursor-line-margin.ts +5 -2
- package/src/extensions/dnd.ts +3 -1
- package/src/extensions/index.ts +0 -1
- package/src/extensions/listener.ts +3 -3
- package/src/extensions/markdown/bundle.ts +4 -14
- package/src/extensions/markdown/decorate.ts +21 -14
- package/src/extensions/mention.ts +3 -1
- package/src/hooks/defs.ts +6 -20
- package/src/hooks/useActionHandler.ts +11 -11
- package/src/hooks/useEditorView.ts +0 -1
- package/src/{components/TextEditor/hooks.stories.tsx → hooks/useTextEditor.stories.tsx} +8 -8
- package/src/hooks/useTextEditor.ts +69 -14
- package/src/hooks/useTextModel.ts +11 -16
- package/src/index.ts +2 -0
- package/src/themes/default.ts +1 -0
- package/src/util.ts +1 -1
- package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/basic.d.ts +0 -9
- package/dist/types/src/extensions/basic.d.ts.map +0 -1
- package/src/extensions/basic.ts +0 -41
|
@@ -24,19 +24,18 @@ var translations_default = [
|
|
|
24
24
|
|
|
25
25
|
// packages/ui/react-ui-editor/src/index.ts
|
|
26
26
|
import { keymap as keymap9 } from "@codemirror/view";
|
|
27
|
+
import { tags as tags2 } from "@lezer/highlight";
|
|
27
28
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
28
29
|
import { Doc, YText, YXmlFragment } from "@dxos/text-model";
|
|
29
30
|
|
|
30
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/index.ts
|
|
31
|
-
import { tags as tags2 } from "@lezer/highlight";
|
|
32
|
-
|
|
33
31
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
34
|
-
import { EditorState as
|
|
35
|
-
import { EditorView as EditorView17, scrollPastEnd } from "@codemirror/view";
|
|
32
|
+
import { EditorState as EditorState3 } from "@codemirror/state";
|
|
33
|
+
import { EditorView as EditorView17, scrollPastEnd as scrollPastEnd2 } from "@codemirror/view";
|
|
36
34
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
37
|
-
import
|
|
38
|
-
import React, { forwardRef, useCallback, useEffect as
|
|
39
|
-
import {
|
|
35
|
+
import defaultsDeep3 from "lodash.defaultsdeep";
|
|
36
|
+
import React, { forwardRef, useCallback, useEffect as useEffect3, useImperativeHandle, useRef as useRef3, useState as useState5, useMemo as useMemo3 } from "react";
|
|
37
|
+
import { DocAccessor } from "@dxos/echo-schema";
|
|
38
|
+
import { log as log9 } from "@dxos/log";
|
|
40
39
|
import { useThemeContext } from "@dxos/react-ui";
|
|
41
40
|
import { focusRing } from "@dxos/react-ui-theme";
|
|
42
41
|
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
@@ -733,28 +732,8 @@ var styles2 = EditorView3.baseTheme({
|
|
|
733
732
|
}
|
|
734
733
|
});
|
|
735
734
|
|
|
736
|
-
// packages/ui/react-ui-editor/src/extensions/basic.ts
|
|
737
|
-
import { closeBrackets } from "@codemirror/autocomplete";
|
|
738
|
-
import { history } from "@codemirror/commands";
|
|
739
|
-
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
740
|
-
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
741
|
-
import { drawSelection, EditorView as EditorView4, highlightActiveLine, placeholder } from "@codemirror/view";
|
|
742
|
-
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
|
743
|
-
var createBasicBundle = ({ themeMode, placeholder: _placeholder, lineWrapping = true, bracketMatching: _bracketMatching = true } = {}) => [
|
|
744
|
-
lineWrapping && EditorView4.lineWrapping,
|
|
745
|
-
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
746
|
-
_bracketMatching && bracketMatching(),
|
|
747
|
-
closeBrackets(),
|
|
748
|
-
drawSelection(),
|
|
749
|
-
highlightActiveLine(),
|
|
750
|
-
history(),
|
|
751
|
-
_placeholder && placeholder(_placeholder),
|
|
752
|
-
// https://github.com/codemirror/theme-one-dark
|
|
753
|
-
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
754
|
-
].filter(isNotFalsy2);
|
|
755
|
-
|
|
756
735
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
757
|
-
import { EditorView as
|
|
736
|
+
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
758
737
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
759
738
|
import { invariant } from "@dxos/invariant";
|
|
760
739
|
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
@@ -802,7 +781,7 @@ var blast = (options = defaultOptions) => {
|
|
|
802
781
|
};
|
|
803
782
|
return [
|
|
804
783
|
// Cursor moved.
|
|
805
|
-
|
|
784
|
+
EditorView4.updateListener.of((update2) => {
|
|
806
785
|
if (blaster?.node !== update2.view.scrollDOM) {
|
|
807
786
|
if (blaster) {
|
|
808
787
|
blaster.destroy();
|
|
@@ -1064,11 +1043,11 @@ var random = (min, max) => {
|
|
|
1064
1043
|
};
|
|
1065
1044
|
|
|
1066
1045
|
// packages/ui/react-ui-editor/src/extensions/command/command.ts
|
|
1067
|
-
import { EditorView as
|
|
1046
|
+
import { EditorView as EditorView6, keymap as keymap3 } from "@codemirror/view";
|
|
1068
1047
|
|
|
1069
1048
|
// packages/ui/react-ui-editor/src/extensions/command/hint.ts
|
|
1070
1049
|
import { RangeSetBuilder } from "@codemirror/state";
|
|
1071
|
-
import { Decoration as Decoration3, EditorView as
|
|
1050
|
+
import { Decoration as Decoration3, EditorView as EditorView5, ViewPlugin as ViewPlugin3, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1072
1051
|
|
|
1073
1052
|
// packages/ui/react-ui-editor/src/extensions/command/state.ts
|
|
1074
1053
|
import { Facet as Facet3, StateEffect as StateEffect2, StateField as StateField3 } from "@codemirror/state";
|
|
@@ -1162,7 +1141,7 @@ var closeCommand = (view) => {
|
|
|
1162
1141
|
}
|
|
1163
1142
|
return false;
|
|
1164
1143
|
};
|
|
1165
|
-
var
|
|
1144
|
+
var commandKeyBindings = [
|
|
1166
1145
|
{
|
|
1167
1146
|
key: "/",
|
|
1168
1147
|
run: openCommand
|
|
@@ -1263,31 +1242,31 @@ var hintViewPlugin = ({ onHint }) => ViewPlugin3.fromClass(class {
|
|
|
1263
1242
|
}
|
|
1264
1243
|
}, {
|
|
1265
1244
|
provide: (plugin) => [
|
|
1266
|
-
|
|
1245
|
+
EditorView5.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration3.none)
|
|
1267
1246
|
]
|
|
1268
1247
|
});
|
|
1269
1248
|
|
|
1270
1249
|
// packages/ui/react-ui-editor/src/extensions/command/command.ts
|
|
1271
1250
|
var command = (options) => {
|
|
1272
1251
|
return [
|
|
1252
|
+
commandConfig.of(options),
|
|
1273
1253
|
commandState,
|
|
1274
|
-
keymap3.of(
|
|
1254
|
+
keymap3.of(commandKeyBindings),
|
|
1275
1255
|
hintViewPlugin(options),
|
|
1276
|
-
|
|
1277
|
-
EditorView7.focusChangeEffect.of((_, focusing) => {
|
|
1256
|
+
EditorView6.focusChangeEffect.of((_, focusing) => {
|
|
1278
1257
|
return focusing ? closeEffect.of(null) : null;
|
|
1279
|
-
})
|
|
1280
|
-
commandConfig.of(options)
|
|
1258
|
+
})
|
|
1281
1259
|
];
|
|
1282
1260
|
};
|
|
1283
1261
|
|
|
1284
1262
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1285
1263
|
import { invertedEffects } from "@codemirror/commands";
|
|
1286
1264
|
import { Facet as Facet4, StateEffect as StateEffect3, StateField as StateField4 } from "@codemirror/state";
|
|
1287
|
-
import { hoverTooltip, keymap as keymap4, Decoration as Decoration4, EditorView as
|
|
1265
|
+
import { hoverTooltip, keymap as keymap4, Decoration as Decoration4, EditorView as EditorView7 } from "@codemirror/view";
|
|
1288
1266
|
import sortBy from "lodash.sortby";
|
|
1289
1267
|
import { useEffect } from "react";
|
|
1290
1268
|
import { debounce } from "@dxos/async";
|
|
1269
|
+
import { log as log3 } from "@dxos/log";
|
|
1291
1270
|
import { nonNullable } from "@dxos/util";
|
|
1292
1271
|
|
|
1293
1272
|
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
@@ -1355,11 +1334,19 @@ var logChanges = (trs) => {
|
|
|
1355
1334
|
return changes2;
|
|
1356
1335
|
}).filter(Boolean);
|
|
1357
1336
|
if (changes.length) {
|
|
1358
|
-
|
|
1337
|
+
log2.info("changes", {
|
|
1338
|
+
changes
|
|
1339
|
+
}, {
|
|
1340
|
+
F: __dxlog_file3,
|
|
1341
|
+
L: 39,
|
|
1342
|
+
S: void 0,
|
|
1343
|
+
C: (f, a) => f(...a)
|
|
1344
|
+
});
|
|
1359
1345
|
}
|
|
1360
1346
|
};
|
|
1361
1347
|
|
|
1362
1348
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1349
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1363
1350
|
var documentId = Facet4.define({
|
|
1364
1351
|
combine: (values) => values[0]
|
|
1365
1352
|
});
|
|
@@ -1404,7 +1391,7 @@ var commentsState = StateField4.define({
|
|
|
1404
1391
|
return value;
|
|
1405
1392
|
}
|
|
1406
1393
|
});
|
|
1407
|
-
var styles3 =
|
|
1394
|
+
var styles3 = EditorView7.baseTheme({
|
|
1408
1395
|
"&light .cm-comment, &light .cm-comment-current": {
|
|
1409
1396
|
mixBlendMode: "darken"
|
|
1410
1397
|
},
|
|
@@ -1438,14 +1425,19 @@ var commentCurrentMark = Decoration4.mark({
|
|
|
1438
1425
|
"data-testid": "cm-comment"
|
|
1439
1426
|
}
|
|
1440
1427
|
});
|
|
1441
|
-
var commentsDecorations =
|
|
1428
|
+
var commentsDecorations = EditorView7.decorations.compute([
|
|
1442
1429
|
commentsState
|
|
1443
1430
|
], (state) => {
|
|
1444
1431
|
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
1445
1432
|
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1446
1433
|
const range = comment.range;
|
|
1447
1434
|
if (!range || range.from === range.to) {
|
|
1448
|
-
|
|
1435
|
+
log3.warn("Invalid range:", range, {
|
|
1436
|
+
F: __dxlog_file4,
|
|
1437
|
+
L: 132,
|
|
1438
|
+
S: void 0,
|
|
1439
|
+
C: (f, a) => f(...a)
|
|
1440
|
+
});
|
|
1449
1441
|
return void 0;
|
|
1450
1442
|
}
|
|
1451
1443
|
if (comment.comment.id === current) {
|
|
@@ -1476,7 +1468,7 @@ var trackPastedComments = (onUpdate) => {
|
|
|
1476
1468
|
}
|
|
1477
1469
|
};
|
|
1478
1470
|
return [
|
|
1479
|
-
|
|
1471
|
+
EditorView7.domEventHandlers({
|
|
1480
1472
|
cut: handleTrack,
|
|
1481
1473
|
copy: handleTrack
|
|
1482
1474
|
}),
|
|
@@ -1498,7 +1490,7 @@ var trackPastedComments = (onUpdate) => {
|
|
|
1498
1490
|
return effects;
|
|
1499
1491
|
}),
|
|
1500
1492
|
// Handle paste or the undo of comment deletion.
|
|
1501
|
-
|
|
1493
|
+
EditorView7.updateListener.of((update2) => {
|
|
1502
1494
|
const restore = [];
|
|
1503
1495
|
for (let i = 0; i < update2.transactions.length; i++) {
|
|
1504
1496
|
const tr = update2.transactions[i];
|
|
@@ -1649,7 +1641,7 @@ var comments = (options = {}) => {
|
|
|
1649
1641
|
//
|
|
1650
1642
|
// Track deleted ranges and update ranges for decorations.
|
|
1651
1643
|
//
|
|
1652
|
-
|
|
1644
|
+
EditorView7.updateListener.of(({ view, state, changes }) => {
|
|
1653
1645
|
let mod = false;
|
|
1654
1646
|
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1655
1647
|
changes.iterChanges((from, to, from2, to2) => {
|
|
@@ -1681,7 +1673,7 @@ var comments = (options = {}) => {
|
|
|
1681
1673
|
//
|
|
1682
1674
|
// Track selection/proximity.
|
|
1683
1675
|
//
|
|
1684
|
-
|
|
1676
|
+
EditorView7.updateListener.of(({ view, state }) => {
|
|
1685
1677
|
let min = Infinity;
|
|
1686
1678
|
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
1687
1679
|
const { head } = state.selection.main;
|
|
@@ -1730,7 +1722,7 @@ var focusComment = (view, id, center = true) => {
|
|
|
1730
1722
|
},
|
|
1731
1723
|
effects: [
|
|
1732
1724
|
//
|
|
1733
|
-
|
|
1725
|
+
EditorView7.scrollIntoView(range.from, center ? {
|
|
1734
1726
|
y: "center"
|
|
1735
1727
|
} : void 0),
|
|
1736
1728
|
setSelection.of({
|
|
@@ -1759,13 +1751,15 @@ var useComments = (view, id, comments2 = []) => {
|
|
|
1759
1751
|
|
|
1760
1752
|
// packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts
|
|
1761
1753
|
import { Facet as Facet5, Transaction } from "@codemirror/state";
|
|
1762
|
-
import { EditorView as
|
|
1754
|
+
import { EditorView as EditorView8 } from "@codemirror/view";
|
|
1755
|
+
import { log as log4 } from "@dxos/log";
|
|
1756
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts";
|
|
1763
1757
|
var cursorLineMarginFacet = Facet5.define({
|
|
1764
1758
|
combine: (input) => input[0] ?? 3
|
|
1765
1759
|
});
|
|
1766
1760
|
var annotation = "cursorLineMargin";
|
|
1767
1761
|
var lineAtPos = (s, pos) => s.doc.lineAt(pos).number;
|
|
1768
|
-
var cursorLineMargin =
|
|
1762
|
+
var cursorLineMargin = EditorView8.updateListener.of(({ transactions, state, selectionSet, startState, view }) => {
|
|
1769
1763
|
if (transactions.length < 1 || transactions.some((tr) => tr.isUserEvent(annotation))) {
|
|
1770
1764
|
return;
|
|
1771
1765
|
}
|
|
@@ -1783,7 +1777,12 @@ var cursorLineMargin = EditorView9.updateListener.of(({ transactions, state, sel
|
|
|
1783
1777
|
const needsScrollTop = false;
|
|
1784
1778
|
const needsScrollBot = mainLine >= visBotLine - cursorLineMargin2;
|
|
1785
1779
|
if (needsScrollTop && needsScrollBot) {
|
|
1786
|
-
|
|
1780
|
+
log4.warn("is cursorScrollMargin too large for the editor size?", void 0, {
|
|
1781
|
+
F: __dxlog_file5,
|
|
1782
|
+
L: 66,
|
|
1783
|
+
S: void 0,
|
|
1784
|
+
C: (f, a) => f(...a)
|
|
1785
|
+
});
|
|
1787
1786
|
return;
|
|
1788
1787
|
}
|
|
1789
1788
|
if (!needsScrollTop && !needsScrollBot) {
|
|
@@ -1801,7 +1800,7 @@ var cursorLineMargin = EditorView9.updateListener.of(({ transactions, state, sel
|
|
|
1801
1800
|
}
|
|
1802
1801
|
view.dispatch({
|
|
1803
1802
|
annotations: Transaction.userEvent.of(annotation),
|
|
1804
|
-
effects:
|
|
1803
|
+
effects: EditorView8.scrollIntoView(s.selection.main.head, {
|
|
1805
1804
|
y: needsScrollTop ? "start" : "end",
|
|
1806
1805
|
yMargin: view.defaultLineHeight * cursorLineMargin2
|
|
1807
1806
|
})
|
|
@@ -1809,40 +1808,49 @@ var cursorLineMargin = EditorView9.updateListener.of(({ transactions, state, sel
|
|
|
1809
1808
|
});
|
|
1810
1809
|
|
|
1811
1810
|
// packages/ui/react-ui-editor/src/extensions/dnd.ts
|
|
1812
|
-
import { EditorView as
|
|
1811
|
+
import { EditorView as EditorView9 } from "@codemirror/view";
|
|
1812
|
+
import { log as log5 } from "@dxos/log";
|
|
1813
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/dnd.ts";
|
|
1813
1814
|
var dnd = () => {
|
|
1814
|
-
return
|
|
1815
|
+
return EditorView9.domEventHandlers({
|
|
1815
1816
|
drop: (event, view) => {
|
|
1816
|
-
|
|
1817
|
+
log5.info("domEventHandlersDrop", {
|
|
1818
|
+
event
|
|
1819
|
+
}, {
|
|
1820
|
+
F: __dxlog_file6,
|
|
1821
|
+
L: 14,
|
|
1822
|
+
S: void 0,
|
|
1823
|
+
C: (f, a) => f(...a)
|
|
1824
|
+
});
|
|
1817
1825
|
}
|
|
1818
1826
|
});
|
|
1819
1827
|
};
|
|
1820
1828
|
|
|
1821
1829
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1822
|
-
import { EditorView as
|
|
1830
|
+
import { EditorView as EditorView10 } from "@codemirror/view";
|
|
1823
1831
|
var listener = ({ onFocus, onChange }) => {
|
|
1824
1832
|
const extensions = [];
|
|
1825
|
-
onFocus && extensions.push(
|
|
1826
|
-
onFocus(
|
|
1833
|
+
onFocus && extensions.push(EditorView10.focusChangeEffect.of((_, focusing) => {
|
|
1834
|
+
onFocus(focusing);
|
|
1827
1835
|
return null;
|
|
1828
1836
|
}));
|
|
1829
|
-
onChange && extensions.push(
|
|
1837
|
+
onChange && extensions.push(EditorView10.updateListener.of((update2) => {
|
|
1830
1838
|
onChange(update2.state.doc.toString());
|
|
1831
1839
|
}));
|
|
1832
1840
|
return extensions;
|
|
1833
1841
|
};
|
|
1834
1842
|
|
|
1835
1843
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1836
|
-
import { closeBrackets
|
|
1837
|
-
import { history
|
|
1844
|
+
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1845
|
+
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1838
1846
|
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1839
|
-
import { bracketMatching
|
|
1847
|
+
import { bracketMatching, defaultHighlightStyle, indentOnInput, syntaxHighlighting } from "@codemirror/language";
|
|
1840
1848
|
import { languages } from "@codemirror/language-data";
|
|
1841
1849
|
import { searchKeymap } from "@codemirror/search";
|
|
1842
1850
|
import { EditorState } from "@codemirror/state";
|
|
1843
|
-
import { oneDarkHighlightStyle
|
|
1844
|
-
import {
|
|
1845
|
-
import { isNotFalsy as
|
|
1851
|
+
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
1852
|
+
import { EditorView as EditorView11, drawSelection, dropCursor, keymap as keymap5, placeholder } from "@codemirror/view";
|
|
1853
|
+
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
|
1846
1854
|
|
|
1847
1855
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1848
1856
|
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
@@ -2035,19 +2043,17 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
2035
2043
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
2036
2044
|
var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => {
|
|
2037
2045
|
return [
|
|
2038
|
-
|
|
2046
|
+
// TODO(burdon): Reconcile with createBasicExtensions.
|
|
2047
|
+
lineWrapping && EditorView11.lineWrapping,
|
|
2039
2048
|
EditorState.allowMultipleSelections.of(true),
|
|
2040
2049
|
EditorState.tabSize.of(2),
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
closeBrackets2(),
|
|
2044
|
-
crosshairCursor(),
|
|
2050
|
+
bracketMatching(),
|
|
2051
|
+
closeBrackets(),
|
|
2045
2052
|
dropCursor(),
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
history2(),
|
|
2053
|
+
drawSelection(),
|
|
2054
|
+
history(),
|
|
2049
2055
|
indentOnInput(),
|
|
2050
|
-
_placeholder &&
|
|
2056
|
+
_placeholder && placeholder(_placeholder),
|
|
2051
2057
|
// Main extension.
|
|
2052
2058
|
// https://github.com/codemirror/lang-markdown
|
|
2053
2059
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -2067,9 +2073,9 @@ var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrap
|
|
|
2067
2073
|
]
|
|
2068
2074
|
}),
|
|
2069
2075
|
// https://github.com/codemirror/theme-one-dark
|
|
2070
|
-
themeMode === "dark" ?
|
|
2076
|
+
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle),
|
|
2071
2077
|
// Custom styles.
|
|
2072
|
-
|
|
2078
|
+
syntaxHighlighting(markdownHighlightStyle()),
|
|
2073
2079
|
keymap5.of([
|
|
2074
2080
|
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
2075
2081
|
indentWithTab,
|
|
@@ -2082,13 +2088,13 @@ var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrap
|
|
|
2082
2088
|
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2083
2089
|
...standardKeymap
|
|
2084
2090
|
])
|
|
2085
|
-
].filter(
|
|
2091
|
+
].filter(isNotFalsy2);
|
|
2086
2092
|
};
|
|
2087
2093
|
|
|
2088
2094
|
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
|
2089
2095
|
import { syntaxTree } from "@codemirror/language";
|
|
2090
2096
|
import { RangeSetBuilder as RangeSetBuilder2, StateEffect as StateEffect4 } from "@codemirror/state";
|
|
2091
|
-
import { EditorView as
|
|
2097
|
+
import { EditorView as EditorView12, Decoration as Decoration5, WidgetType as WidgetType3, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
2092
2098
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
2093
2099
|
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
2094
2100
|
toDOM() {
|
|
@@ -2170,7 +2176,7 @@ var uncheckedTask = Decoration5.replace({
|
|
|
2170
2176
|
});
|
|
2171
2177
|
var editingRange = (state, range, focus) => {
|
|
2172
2178
|
const { readOnly, selection: { main: { head } } } = state;
|
|
2173
|
-
return focus && !readOnly && head >= range.from && head
|
|
2179
|
+
return focus && !readOnly && head >= range.from && head <= range.to;
|
|
2174
2180
|
};
|
|
2175
2181
|
var MarksByParent = /* @__PURE__ */ new Set([
|
|
2176
2182
|
"CodeMark",
|
|
@@ -2198,7 +2204,7 @@ var buildDecorations = (view, options, focus) => {
|
|
|
2198
2204
|
break;
|
|
2199
2205
|
}
|
|
2200
2206
|
const first = block.from <= node.from;
|
|
2201
|
-
const last = block.to >= node.to;
|
|
2207
|
+
const last = block.to >= node.to && /^(\s>)*```$/.test(state.doc.sliceString(block.from, block.to));
|
|
2202
2208
|
deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
|
|
2203
2209
|
if (!editing && (first || last)) {
|
|
2204
2210
|
atomicDeco.add(block.from, block.to, hide);
|
|
@@ -2265,45 +2271,46 @@ var decorateMarkdown = (options = {}) => {
|
|
|
2265
2271
|
return [
|
|
2266
2272
|
ViewPlugin4.fromClass(class {
|
|
2267
2273
|
constructor(view) {
|
|
2268
|
-
this.pendingUpdate = -1;
|
|
2269
2274
|
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(view, options, view.hasFocus));
|
|
2270
2275
|
}
|
|
2271
2276
|
update(update2) {
|
|
2272
|
-
if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((e) => e.is(forceUpdate)))) {
|
|
2277
|
+
if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((e) => e.is(forceUpdate))) || update2.selectionSet && !options.selectionChangeDelay) {
|
|
2273
2278
|
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(update2.view, options, update2.view.hasFocus));
|
|
2274
2279
|
this.clearUpdate();
|
|
2275
2280
|
} else if (update2.selectionSet) {
|
|
2276
2281
|
this.scheduleUpdate(update2.view);
|
|
2277
2282
|
}
|
|
2278
2283
|
}
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
window.clearTimeout(this.pendingUpdate);
|
|
2282
|
-
this.pendingUpdate = -1;
|
|
2283
|
-
}
|
|
2284
|
-
}
|
|
2284
|
+
// TODO(burdon): BUG: If the cursor is at the end of a link at the end of a line,
|
|
2285
|
+
// the cursor will float in space or be in the wrong position after the decoration is applied.
|
|
2285
2286
|
scheduleUpdate(view) {
|
|
2286
2287
|
this.clearUpdate();
|
|
2287
|
-
this.pendingUpdate =
|
|
2288
|
+
this.pendingUpdate = setTimeout(() => {
|
|
2288
2289
|
view.dispatch({
|
|
2289
2290
|
effects: forceUpdate.of(null)
|
|
2290
2291
|
});
|
|
2291
|
-
}, options.selectionChangeDelay
|
|
2292
|
+
}, options.selectionChangeDelay);
|
|
2293
|
+
}
|
|
2294
|
+
clearUpdate() {
|
|
2295
|
+
if (this.pendingUpdate) {
|
|
2296
|
+
clearTimeout(this.pendingUpdate);
|
|
2297
|
+
this.pendingUpdate = void 0;
|
|
2298
|
+
}
|
|
2292
2299
|
}
|
|
2293
2300
|
destroy() {
|
|
2294
2301
|
this.clearUpdate();
|
|
2295
2302
|
}
|
|
2296
2303
|
}, {
|
|
2297
2304
|
provide: (plugin) => [
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2305
|
+
EditorView12.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
|
|
2306
|
+
EditorView12.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
|
|
2307
|
+
EditorView12.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration5.none)
|
|
2301
2308
|
]
|
|
2302
2309
|
}),
|
|
2303
2310
|
formattingStyles
|
|
2304
2311
|
];
|
|
2305
2312
|
};
|
|
2306
|
-
var formattingStyles =
|
|
2313
|
+
var formattingStyles = EditorView12.baseTheme({
|
|
2307
2314
|
"& .cm-code": {
|
|
2308
2315
|
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
2309
2316
|
},
|
|
@@ -2356,7 +2363,7 @@ var formattingStyles = EditorView13.baseTheme({
|
|
|
2356
2363
|
import { snippet } from "@codemirror/autocomplete";
|
|
2357
2364
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
2358
2365
|
import { EditorSelection } from "@codemirror/state";
|
|
2359
|
-
import { EditorView as
|
|
2366
|
+
import { EditorView as EditorView13, keymap as keymap6 } from "@codemirror/view";
|
|
2360
2367
|
import { useState, useMemo } from "react";
|
|
2361
2368
|
var compareFormatting = (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;
|
|
2362
2369
|
var Inline;
|
|
@@ -3426,7 +3433,7 @@ var getFormatting = (state) => {
|
|
|
3426
3433
|
};
|
|
3427
3434
|
var useFormattingState = () => {
|
|
3428
3435
|
const [state, setState] = useState(null);
|
|
3429
|
-
const observer = useMemo(() =>
|
|
3436
|
+
const observer = useMemo(() => EditorView13.updateListener.of((update2) => {
|
|
3430
3437
|
if (update2.docChanged || update2.selectionSet) {
|
|
3431
3438
|
const newState = getFormatting(update2.state);
|
|
3432
3439
|
if (!state || !compareFormatting(state, newState)) {
|
|
@@ -3443,7 +3450,7 @@ var useFormattingState = () => {
|
|
|
3443
3450
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
3444
3451
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
3445
3452
|
import { StateField as StateField5 } from "@codemirror/state";
|
|
3446
|
-
import { Decoration as Decoration6, EditorView as
|
|
3453
|
+
import { Decoration as Decoration6, EditorView as EditorView14, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
3447
3454
|
var image = (options = {}) => {
|
|
3448
3455
|
return StateField5.define({
|
|
3449
3456
|
create: (state) => {
|
|
@@ -3470,7 +3477,7 @@ var image = (options = {}) => {
|
|
|
3470
3477
|
add: buildDecorations2(from, to, tr.state)
|
|
3471
3478
|
});
|
|
3472
3479
|
},
|
|
3473
|
-
provide: (field) =>
|
|
3480
|
+
provide: (field) => EditorView14.decorations.from(field)
|
|
3474
3481
|
});
|
|
3475
3482
|
};
|
|
3476
3483
|
var preloaded = /* @__PURE__ */ new Set();
|
|
@@ -3558,12 +3565,12 @@ var linkTooltip = (render) => hoverTooltip2((view, pos, side) => {
|
|
|
3558
3565
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
3559
3566
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
3560
3567
|
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField6 } from "@codemirror/state";
|
|
3561
|
-
import { Decoration as Decoration7, EditorView as
|
|
3568
|
+
import { Decoration as Decoration7, EditorView as EditorView15, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
3562
3569
|
var table = (options = {}) => {
|
|
3563
3570
|
return StateField6.define({
|
|
3564
3571
|
create: (state) => update(state, options),
|
|
3565
3572
|
update: (_, tr) => update(tr.state, options),
|
|
3566
|
-
provide: (field) =>
|
|
3573
|
+
provide: (field) => EditorView15.decorations.from(field)
|
|
3567
3574
|
});
|
|
3568
3575
|
};
|
|
3569
3576
|
var update = (state, options) => {
|
|
@@ -3655,6 +3662,8 @@ var TableWidget = class extends WidgetType5 {
|
|
|
3655
3662
|
|
|
3656
3663
|
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
3657
3664
|
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
3665
|
+
import { log as log6 } from "@dxos/log";
|
|
3666
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/mention.ts";
|
|
3658
3667
|
var mention = ({ onSearch }) => {
|
|
3659
3668
|
return autocompletion2({
|
|
3660
3669
|
// TODO(burdon): Not working.
|
|
@@ -3666,7 +3675,14 @@ var mention = ({ onSearch }) => {
|
|
|
3666
3675
|
icons: false,
|
|
3667
3676
|
override: [
|
|
3668
3677
|
(context) => {
|
|
3669
|
-
|
|
3678
|
+
log6.info("completion context", {
|
|
3679
|
+
context
|
|
3680
|
+
}, {
|
|
3681
|
+
F: __dxlog_file7,
|
|
3682
|
+
L: 26,
|
|
3683
|
+
S: void 0,
|
|
3684
|
+
C: (f, a) => f(...a)
|
|
3685
|
+
});
|
|
3670
3686
|
const match = context.matchBefore(/@(\w+)?/);
|
|
3671
3687
|
if (!match || match.from === match.to && !context.explicit) {
|
|
3672
3688
|
return null;
|
|
@@ -3773,6 +3789,189 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
3773
3789
|
];
|
|
3774
3790
|
};
|
|
3775
3791
|
|
|
3792
|
+
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
3793
|
+
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
3794
|
+
import { Context as Context2 } from "@dxos/context";
|
|
3795
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
3796
|
+
import { log as log7 } from "@dxos/log";
|
|
3797
|
+
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
3798
|
+
var DEBOUNCE_INTERVAL = 100;
|
|
3799
|
+
var SpaceAwarenessProvider = class {
|
|
3800
|
+
constructor(params) {
|
|
3801
|
+
this._remoteStates = /* @__PURE__ */ new Map();
|
|
3802
|
+
this.remoteStateChange = new Event2();
|
|
3803
|
+
this._space = params.space;
|
|
3804
|
+
this._channel = params.channel;
|
|
3805
|
+
this._peerId = params.peerId;
|
|
3806
|
+
this._info = params.info;
|
|
3807
|
+
}
|
|
3808
|
+
open() {
|
|
3809
|
+
this._ctx = new Context2();
|
|
3810
|
+
this._postTask = new DeferredTask(this._ctx, async () => {
|
|
3811
|
+
if (this._localState) {
|
|
3812
|
+
await this._space.postMessage(this._channel, {
|
|
3813
|
+
kind: "post",
|
|
3814
|
+
state: this._localState
|
|
3815
|
+
});
|
|
3816
|
+
await sleep(DEBOUNCE_INTERVAL);
|
|
3817
|
+
}
|
|
3818
|
+
});
|
|
3819
|
+
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
3820
|
+
switch (message.payload.kind) {
|
|
3821
|
+
case "query": {
|
|
3822
|
+
this._handleQueryMessage();
|
|
3823
|
+
break;
|
|
3824
|
+
}
|
|
3825
|
+
case "post": {
|
|
3826
|
+
this._handlePostMessage(message.payload);
|
|
3827
|
+
break;
|
|
3828
|
+
}
|
|
3829
|
+
}
|
|
3830
|
+
}));
|
|
3831
|
+
void this._space.postMessage(this._channel, {
|
|
3832
|
+
kind: "query"
|
|
3833
|
+
}).catch((err) => {
|
|
3834
|
+
log7.debug("failed to query awareness", {
|
|
3835
|
+
err
|
|
3836
|
+
}, {
|
|
3837
|
+
F: __dxlog_file8,
|
|
3838
|
+
L: 89,
|
|
3839
|
+
S: this,
|
|
3840
|
+
C: (f, a) => f(...a)
|
|
3841
|
+
});
|
|
3842
|
+
});
|
|
3843
|
+
}
|
|
3844
|
+
close() {
|
|
3845
|
+
void this._ctx?.dispose();
|
|
3846
|
+
this._ctx = void 0;
|
|
3847
|
+
this._postTask = void 0;
|
|
3848
|
+
}
|
|
3849
|
+
getRemoteStates() {
|
|
3850
|
+
return Array.from(this._remoteStates.values());
|
|
3851
|
+
}
|
|
3852
|
+
update(position) {
|
|
3853
|
+
invariant2(this._postTask, void 0, {
|
|
3854
|
+
F: __dxlog_file8,
|
|
3855
|
+
L: 104,
|
|
3856
|
+
S: this,
|
|
3857
|
+
A: [
|
|
3858
|
+
"this._postTask",
|
|
3859
|
+
""
|
|
3860
|
+
]
|
|
3861
|
+
});
|
|
3862
|
+
this._localState = {
|
|
3863
|
+
peerId: this._peerId,
|
|
3864
|
+
position,
|
|
3865
|
+
info: this._info
|
|
3866
|
+
};
|
|
3867
|
+
this._postTask.schedule();
|
|
3868
|
+
}
|
|
3869
|
+
_handleQueryMessage() {
|
|
3870
|
+
invariant2(this._postTask, void 0, {
|
|
3871
|
+
F: __dxlog_file8,
|
|
3872
|
+
L: 115,
|
|
3873
|
+
S: this,
|
|
3874
|
+
A: [
|
|
3875
|
+
"this._postTask",
|
|
3876
|
+
""
|
|
3877
|
+
]
|
|
3878
|
+
});
|
|
3879
|
+
this._postTask.schedule();
|
|
3880
|
+
}
|
|
3881
|
+
_handlePostMessage(message) {
|
|
3882
|
+
invariant2(message.kind === "post", void 0, {
|
|
3883
|
+
F: __dxlog_file8,
|
|
3884
|
+
L: 120,
|
|
3885
|
+
S: this,
|
|
3886
|
+
A: [
|
|
3887
|
+
"message.kind === 'post'",
|
|
3888
|
+
""
|
|
3889
|
+
]
|
|
3890
|
+
});
|
|
3891
|
+
this._remoteStates.set(message.state.peerId, message.state);
|
|
3892
|
+
this.remoteStateChange.emit();
|
|
3893
|
+
}
|
|
3894
|
+
};
|
|
3895
|
+
|
|
3896
|
+
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
3897
|
+
var useActionHandler = (view) => {
|
|
3898
|
+
return (action) => {
|
|
3899
|
+
if (!view) {
|
|
3900
|
+
return;
|
|
3901
|
+
}
|
|
3902
|
+
let inlineType, listType;
|
|
3903
|
+
switch (action.type) {
|
|
3904
|
+
case "heading":
|
|
3905
|
+
setHeading(parseInt(action.data))(view);
|
|
3906
|
+
break;
|
|
3907
|
+
case "strong":
|
|
3908
|
+
case "emphasis":
|
|
3909
|
+
case "strikethrough":
|
|
3910
|
+
case "code":
|
|
3911
|
+
inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
|
3912
|
+
(typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
|
|
3913
|
+
break;
|
|
3914
|
+
case "list-ordered":
|
|
3915
|
+
case "list-bullet":
|
|
3916
|
+
case "list-task":
|
|
3917
|
+
listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
|
|
3918
|
+
(action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
|
|
3919
|
+
break;
|
|
3920
|
+
case "blockquote":
|
|
3921
|
+
(action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
|
|
3922
|
+
break;
|
|
3923
|
+
case "codeblock":
|
|
3924
|
+
(action.data === false ? removeCodeblock : addCodeblock)(view);
|
|
3925
|
+
break;
|
|
3926
|
+
case "table":
|
|
3927
|
+
insertTable(view);
|
|
3928
|
+
break;
|
|
3929
|
+
case "link":
|
|
3930
|
+
(action.data === false ? removeLink : addLink)(view);
|
|
3931
|
+
break;
|
|
3932
|
+
case "comment":
|
|
3933
|
+
createComment(view);
|
|
3934
|
+
break;
|
|
3935
|
+
}
|
|
3936
|
+
setTimeout(() => {
|
|
3937
|
+
if (!view.hasFocus) {
|
|
3938
|
+
view.focus();
|
|
3939
|
+
}
|
|
3940
|
+
});
|
|
3941
|
+
};
|
|
3942
|
+
};
|
|
3943
|
+
|
|
3944
|
+
// packages/ui/react-ui-editor/src/hooks/useEditorView.ts
|
|
3945
|
+
import { useRef, useState as useState2 } from "react";
|
|
3946
|
+
var useEditorView = (id) => {
|
|
3947
|
+
const editorRef = useRef(null);
|
|
3948
|
+
const [prev, setPrev] = useState2([
|
|
3949
|
+
null,
|
|
3950
|
+
""
|
|
3951
|
+
]);
|
|
3952
|
+
if (prev[0] !== editorRef.current) {
|
|
3953
|
+
setPrev([
|
|
3954
|
+
editorRef.current,
|
|
3955
|
+
id
|
|
3956
|
+
]);
|
|
3957
|
+
}
|
|
3958
|
+
return [
|
|
3959
|
+
editorRef,
|
|
3960
|
+
prev[1] !== id
|
|
3961
|
+
];
|
|
3962
|
+
};
|
|
3963
|
+
|
|
3964
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
3965
|
+
import { closeBrackets as closeBrackets2 } from "@codemirror/autocomplete";
|
|
3966
|
+
import { history as history2 } from "@codemirror/commands";
|
|
3967
|
+
import { bracketMatching as bracketMatching2 } from "@codemirror/language";
|
|
3968
|
+
import { EditorSelection as EditorSelection2, EditorState as EditorState2 } from "@codemirror/state";
|
|
3969
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor as dropCursor2, EditorView as EditorView16, highlightActiveLine, lineNumbers, placeholder as placeholder2, scrollPastEnd } from "@codemirror/view";
|
|
3970
|
+
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
3971
|
+
import { useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
|
|
3972
|
+
import { log as log8 } from "@dxos/log";
|
|
3973
|
+
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
3974
|
+
|
|
3776
3975
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
3777
3976
|
import get4 from "lodash.get";
|
|
3778
3977
|
var defaultTheme = {
|
|
@@ -3894,7 +4093,8 @@ var defaultTheme = {
|
|
|
3894
4093
|
// tooltip
|
|
3895
4094
|
//
|
|
3896
4095
|
".cm-tooltip": {
|
|
3897
|
-
border: "none"
|
|
4096
|
+
border: "none",
|
|
4097
|
+
background: "unset"
|
|
3898
4098
|
},
|
|
3899
4099
|
".cm-tooltip-below": {},
|
|
3900
4100
|
//
|
|
@@ -4023,39 +4223,258 @@ var codeTheme = {
|
|
|
4023
4223
|
}
|
|
4024
4224
|
};
|
|
4025
4225
|
|
|
4026
|
-
// packages/ui/react-ui-editor/src/
|
|
4027
|
-
var
|
|
4028
|
-
var
|
|
4029
|
-
const
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
const { themeMode } = useThemeContext();
|
|
4033
|
-
const rootRef = useRef(null);
|
|
4034
|
-
const [view, setView] = useState2(null);
|
|
4035
|
-
useImperativeHandle(forwardedRef, () => view, [
|
|
4036
|
-
view
|
|
4037
|
-
]);
|
|
4226
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4227
|
+
var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
4228
|
+
var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}, deps = []) => {
|
|
4229
|
+
const onUpdate = useRef2();
|
|
4230
|
+
const [view, setView] = useState3();
|
|
4231
|
+
const parentRef = useRef2(null);
|
|
4038
4232
|
useEffect2(() => {
|
|
4039
|
-
|
|
4040
|
-
|
|
4233
|
+
let view2;
|
|
4234
|
+
if (parentRef.current) {
|
|
4235
|
+
const state = EditorState2.create({
|
|
4236
|
+
doc,
|
|
4237
|
+
selection,
|
|
4238
|
+
extensions: [
|
|
4239
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4240
|
+
EditorView16.exceptionSink.of((err) => {
|
|
4241
|
+
log8.catch(err, void 0, {
|
|
4242
|
+
F: __dxlog_file9,
|
|
4243
|
+
L: 70,
|
|
4244
|
+
S: void 0,
|
|
4245
|
+
C: (f, a) => f(...a)
|
|
4246
|
+
});
|
|
4247
|
+
}),
|
|
4248
|
+
extensions,
|
|
4249
|
+
EditorView16.updateListener.of(() => {
|
|
4250
|
+
onUpdate.current?.();
|
|
4251
|
+
})
|
|
4252
|
+
].filter(isNotFalsy3)
|
|
4253
|
+
});
|
|
4254
|
+
view2 = new EditorView16({
|
|
4255
|
+
parent: parentRef.current,
|
|
4256
|
+
scrollTo,
|
|
4257
|
+
state,
|
|
4258
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
4259
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
4260
|
+
dispatchTransactions: (trs, view3) => {
|
|
4261
|
+
if (debug) {
|
|
4262
|
+
logChanges(trs);
|
|
4263
|
+
}
|
|
4264
|
+
view3.update(trs);
|
|
4265
|
+
}
|
|
4266
|
+
});
|
|
4267
|
+
setView(view2);
|
|
4041
4268
|
}
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4269
|
+
return () => {
|
|
4270
|
+
view2?.destroy();
|
|
4271
|
+
};
|
|
4272
|
+
}, deps);
|
|
4046
4273
|
useEffect2(() => {
|
|
4274
|
+
if (view) {
|
|
4275
|
+
if (!selection && !view.state.selection.main.anchor) {
|
|
4276
|
+
selection = EditorSelection2.single(view.state.doc.line(1).to);
|
|
4277
|
+
}
|
|
4278
|
+
if (selection || scrollTo) {
|
|
4279
|
+
onUpdate.current = () => {
|
|
4280
|
+
onUpdate.current = void 0;
|
|
4281
|
+
view.dispatch({
|
|
4282
|
+
selection,
|
|
4283
|
+
effects: scrollTo && [
|
|
4284
|
+
scrollTo
|
|
4285
|
+
],
|
|
4286
|
+
scrollIntoView: !scrollTo
|
|
4287
|
+
});
|
|
4288
|
+
};
|
|
4289
|
+
}
|
|
4290
|
+
if (autoFocus) {
|
|
4291
|
+
view.focus();
|
|
4292
|
+
}
|
|
4293
|
+
}
|
|
4294
|
+
}, [
|
|
4295
|
+
view,
|
|
4296
|
+
autoFocus,
|
|
4297
|
+
selection,
|
|
4298
|
+
scrollTo
|
|
4299
|
+
]);
|
|
4300
|
+
return {
|
|
4301
|
+
parentRef,
|
|
4302
|
+
view
|
|
4303
|
+
};
|
|
4304
|
+
};
|
|
4305
|
+
var defaults = {
|
|
4306
|
+
bracketMatching: true,
|
|
4307
|
+
closeBrackets: true,
|
|
4308
|
+
drawSelection: true,
|
|
4309
|
+
editable: true,
|
|
4310
|
+
history: true,
|
|
4311
|
+
lineWrapping: true
|
|
4312
|
+
};
|
|
4313
|
+
var createBasicExtensions = (_props) => {
|
|
4314
|
+
const props = defaultsDeep2({}, _props, defaults);
|
|
4315
|
+
return [
|
|
4316
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4317
|
+
EditorView16.exceptionSink.of((err) => {
|
|
4318
|
+
log8.catch(err, void 0, {
|
|
4319
|
+
F: __dxlog_file9,
|
|
4320
|
+
L: 167,
|
|
4321
|
+
S: void 0,
|
|
4322
|
+
C: (f, a) => f(...a)
|
|
4323
|
+
});
|
|
4324
|
+
}),
|
|
4325
|
+
props.allowMultipleSelections && EditorState2.allowMultipleSelections.of(true),
|
|
4326
|
+
props.bracketMatching && bracketMatching2(),
|
|
4327
|
+
props.closeBrackets && closeBrackets2(),
|
|
4328
|
+
props.crosshairCursor && crosshairCursor(),
|
|
4329
|
+
props.dropCursor && dropCursor2(),
|
|
4330
|
+
props.drawSelection && drawSelection2(),
|
|
4331
|
+
props.highlightActiveLine && highlightActiveLine(),
|
|
4332
|
+
props.history && history2(),
|
|
4333
|
+
props.lineNumbers && lineNumbers(),
|
|
4334
|
+
props.lineWrapping && EditorView16.lineWrapping,
|
|
4335
|
+
props.placeholder && placeholder2(props.placeholder),
|
|
4336
|
+
props.readonly && [
|
|
4337
|
+
EditorState2.readOnly.of(true),
|
|
4338
|
+
EditorView16.editable.of(false)
|
|
4339
|
+
],
|
|
4340
|
+
props.scrollPastEnd && scrollPastEnd(),
|
|
4341
|
+
props.tabSize && EditorState2.tabSize.of(props.tabSize)
|
|
4342
|
+
].filter(isNotFalsy3);
|
|
4343
|
+
};
|
|
4344
|
+
var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
4345
|
+
return [
|
|
4346
|
+
EditorView16.baseTheme(defaultTheme),
|
|
4347
|
+
EditorView16.darkTheme.of(themeMode === "dark"),
|
|
4348
|
+
theme && EditorView16.theme(theme),
|
|
4349
|
+
slots?.editor?.className && EditorView16.editorAttributes.of({
|
|
4350
|
+
class: slots.editor.className
|
|
4351
|
+
}),
|
|
4352
|
+
slots?.content?.className && EditorView16.contentAttributes.of({
|
|
4353
|
+
class: slots.content.className
|
|
4354
|
+
})
|
|
4355
|
+
].filter(isNotFalsy3);
|
|
4356
|
+
};
|
|
4357
|
+
|
|
4358
|
+
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
4359
|
+
import get5 from "lodash.get";
|
|
4360
|
+
import { useState as useState4, useMemo as useMemo2 } from "react";
|
|
4361
|
+
import { generateName } from "@dxos/display-name";
|
|
4362
|
+
import { getRawDoc } from "@dxos/echo-schema";
|
|
4363
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
4364
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
4365
|
+
import { hueTokens } from "@dxos/react-ui-theme";
|
|
4366
|
+
import { hexToHue } from "@dxos/util";
|
|
4367
|
+
var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
4368
|
+
var useTextExtensions = ({ id, text, space, identity }) => {
|
|
4369
|
+
const extensions = [
|
|
4370
|
+
automerge(text)
|
|
4371
|
+
];
|
|
4372
|
+
const peerId = identity?.identityKey.toHex();
|
|
4373
|
+
const { cursorLightValue, cursorDarkValue } = hueTokens[identity?.profile?.data?.hue ?? hexToHue(peerId ?? "0")];
|
|
4374
|
+
if (space && identity) {
|
|
4375
|
+
const awarenessProvider2 = new SpaceAwarenessProvider({
|
|
4376
|
+
space,
|
|
4377
|
+
channel: `awareness.${id}`,
|
|
4378
|
+
peerId: identity.identityKey.toHex(),
|
|
4379
|
+
info: {
|
|
4380
|
+
displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
|
|
4381
|
+
color: cursorDarkValue,
|
|
4382
|
+
lightColor: cursorLightValue
|
|
4383
|
+
}
|
|
4384
|
+
});
|
|
4385
|
+
extensions.push(awareness(awarenessProvider2));
|
|
4386
|
+
}
|
|
4387
|
+
return extensions;
|
|
4388
|
+
};
|
|
4389
|
+
var useTextModel = (props) => useMemo2(() => createModel(props), Object.values(props));
|
|
4390
|
+
var useInMemoryTextModel = ({ id, defaultContent }) => {
|
|
4391
|
+
const [content, setContent] = useState4(defaultContent ?? "");
|
|
4392
|
+
return {
|
|
4393
|
+
id,
|
|
4394
|
+
content,
|
|
4395
|
+
text: () => content,
|
|
4396
|
+
setContent
|
|
4397
|
+
};
|
|
4398
|
+
};
|
|
4399
|
+
var createModel = ({ space, identity, text }) => {
|
|
4400
|
+
if (!text) {
|
|
4401
|
+
return void 0;
|
|
4402
|
+
}
|
|
4403
|
+
invariant3(isAutomergeObject(text), void 0, {
|
|
4404
|
+
F: __dxlog_file10,
|
|
4405
|
+
L: 89,
|
|
4406
|
+
S: void 0,
|
|
4407
|
+
A: [
|
|
4408
|
+
"isAutomergeObject(text)",
|
|
4409
|
+
""
|
|
4410
|
+
]
|
|
4411
|
+
});
|
|
4412
|
+
const obj = text;
|
|
4413
|
+
const doc = getRawDoc(obj, [
|
|
4414
|
+
obj.field
|
|
4415
|
+
]);
|
|
4416
|
+
const peerId = identity?.identityKey.toHex();
|
|
4417
|
+
const { cursorLightValue, cursorDarkValue } = hueTokens[identity?.profile?.data?.hue ?? hexToHue(peerId ?? "0")];
|
|
4418
|
+
const awarenessProvider2 = space && new SpaceAwarenessProvider({
|
|
4419
|
+
space,
|
|
4420
|
+
channel: `automerge.awareness.${obj.id}`,
|
|
4421
|
+
info: {
|
|
4422
|
+
displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
|
|
4423
|
+
color: cursorLightValue,
|
|
4424
|
+
lightColor: cursorDarkValue
|
|
4425
|
+
},
|
|
4426
|
+
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
4427
|
+
});
|
|
4428
|
+
const extensions = [
|
|
4429
|
+
automerge({
|
|
4430
|
+
handle: doc.handle,
|
|
4431
|
+
path: doc.path
|
|
4432
|
+
})
|
|
4433
|
+
];
|
|
4434
|
+
if (awarenessProvider2) {
|
|
4435
|
+
extensions.push(awareness(awarenessProvider2));
|
|
4436
|
+
}
|
|
4437
|
+
return {
|
|
4438
|
+
id: obj.id,
|
|
4439
|
+
content: doc,
|
|
4440
|
+
text: () => get5(doc.handle.docSync(), doc.path),
|
|
4441
|
+
extension: extensions
|
|
4442
|
+
};
|
|
4443
|
+
};
|
|
4444
|
+
|
|
4445
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
4446
|
+
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
4447
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo = EditorView17.scrollIntoView(0), moveToEndOfLine, selection, theme, slots = defaultSlots, extensions = [], scrollPastEnd: _scrollPastEnd, debug }, forwardedRef) => {
|
|
4448
|
+
const tabsterDOMAttribute = useFocusableGroup({
|
|
4449
|
+
tabBehavior: "limited"
|
|
4450
|
+
});
|
|
4451
|
+
const { themeMode } = useThemeContext();
|
|
4452
|
+
const rootRef = useRef3(null);
|
|
4453
|
+
const [view, setView] = useState5(null);
|
|
4454
|
+
useImperativeHandle(forwardedRef, () => view, [
|
|
4455
|
+
view
|
|
4456
|
+
]);
|
|
4457
|
+
useEffect3(() => {
|
|
4458
|
+
if (autoFocus) {
|
|
4459
|
+
view?.focus();
|
|
4460
|
+
}
|
|
4461
|
+
}, [
|
|
4462
|
+
view,
|
|
4463
|
+
autoFocus
|
|
4464
|
+
]);
|
|
4465
|
+
useEffect3(() => {
|
|
4047
4466
|
if (!model || !rootRef.current) {
|
|
4048
4467
|
return;
|
|
4049
4468
|
}
|
|
4050
|
-
const state =
|
|
4051
|
-
doc: model.
|
|
4469
|
+
const state = EditorState3.create({
|
|
4470
|
+
doc: typeof model.content === "string" ? model.content : DocAccessor.getValue(model.content),
|
|
4052
4471
|
selection,
|
|
4053
4472
|
extensions: [
|
|
4054
4473
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4055
4474
|
EditorView17.exceptionSink.of((err) => {
|
|
4056
|
-
|
|
4057
|
-
F:
|
|
4058
|
-
L:
|
|
4475
|
+
log9.catch(err, void 0, {
|
|
4476
|
+
F: __dxlog_file11,
|
|
4477
|
+
L: 123,
|
|
4059
4478
|
S: void 0,
|
|
4060
4479
|
C: (f, a) => f(...a)
|
|
4061
4480
|
});
|
|
@@ -4072,7 +4491,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
4072
4491
|
class: slots.content.className
|
|
4073
4492
|
}),
|
|
4074
4493
|
// NOTE: Assumes default line height.
|
|
4075
|
-
_scrollPastEnd &&
|
|
4494
|
+
_scrollPastEnd && scrollPastEnd2(),
|
|
4076
4495
|
// Focus.
|
|
4077
4496
|
EditorView17.updateListener.of((update2) => {
|
|
4078
4497
|
update2.transactions.forEach((transaction) => {
|
|
@@ -4083,7 +4502,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
4083
4502
|
}),
|
|
4084
4503
|
// State.
|
|
4085
4504
|
EditorView17.editable.of(!readonly),
|
|
4086
|
-
|
|
4505
|
+
EditorState3.readOnly.of(!!readonly),
|
|
4087
4506
|
// Storage and replication.
|
|
4088
4507
|
// NOTE: This must come before user extensions.
|
|
4089
4508
|
model.extension,
|
|
@@ -4148,14 +4567,16 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
4148
4567
|
...tabsterDOMAttribute
|
|
4149
4568
|
});
|
|
4150
4569
|
});
|
|
4151
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping, theme = textTheme, slots, extensions: _extensions, ...props }, forwardedRef) => {
|
|
4570
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping = true, theme = textTheme, slots, extensions: _extensions, ...props }, forwardedRef) => {
|
|
4152
4571
|
const { themeMode } = useThemeContext();
|
|
4153
|
-
const updatedSlots =
|
|
4154
|
-
const extensions =
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
placeholder: placeholder3
|
|
4158
|
-
|
|
4572
|
+
const updatedSlots = defaultsDeep3({}, slots, defaultTextSlots);
|
|
4573
|
+
const extensions = useMemo3(() => [
|
|
4574
|
+
createBasicExtensions({
|
|
4575
|
+
lineWrapping,
|
|
4576
|
+
placeholder: placeholder3
|
|
4577
|
+
}),
|
|
4578
|
+
createThemeExtensions({
|
|
4579
|
+
themeMode
|
|
4159
4580
|
}),
|
|
4160
4581
|
..._extensions ?? []
|
|
4161
4582
|
], [
|
|
@@ -4175,8 +4596,8 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
|
|
|
4175
4596
|
});
|
|
4176
4597
|
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions: _extensions, ...props }, forwardedRef) => {
|
|
4177
4598
|
const { themeMode } = useThemeContext();
|
|
4178
|
-
const updatedSlots =
|
|
4179
|
-
const extensions =
|
|
4599
|
+
const updatedSlots = defaultsDeep3({}, slots, defaultMarkdownSlots);
|
|
4600
|
+
const extensions = useMemo3(() => [
|
|
4180
4601
|
createMarkdownExtensions({
|
|
4181
4602
|
themeMode,
|
|
4182
4603
|
placeholder: placeholder3
|
|
@@ -4214,7 +4635,7 @@ var defaultMarkdownSlots = {
|
|
|
4214
4635
|
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
|
4215
4636
|
import { ChatText, Code, CodeBlock, Link, ListBullets, ListChecks, ListNumbers, Paragraph, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic, Quotes } from "@phosphor-icons/react";
|
|
4216
4637
|
import { createContext } from "@radix-ui/react-context";
|
|
4217
|
-
import React2, { useRef as
|
|
4638
|
+
import React2, { useRef as useRef4, useState as useState6 } from "react";
|
|
4218
4639
|
import { DensityProvider, ElevationProvider, Select, Toolbar as NaturalToolbar, Tooltip, useTranslation } from "@dxos/react-ui";
|
|
4219
4640
|
import { getSize } from "@dxos/react-ui-theme";
|
|
4220
4641
|
var tooltipProps = {
|
|
@@ -4272,9 +4693,9 @@ var MarkdownHeading = () => {
|
|
|
4272
4693
|
const header = blockType && /heading(\d)/.exec(blockType);
|
|
4273
4694
|
const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : void 0;
|
|
4274
4695
|
const HeadingIcon = HeadingIcons[value ?? "0"];
|
|
4275
|
-
const suppressNextTooltip =
|
|
4276
|
-
const [tooltipOpen, setTooltipOpen] =
|
|
4277
|
-
const [selectOpen, setSelectOpen] =
|
|
4696
|
+
const suppressNextTooltip = useRef4(false);
|
|
4697
|
+
const [tooltipOpen, setTooltipOpen] = useState6(false);
|
|
4698
|
+
const [selectOpen, setSelectOpen] = useState6(false);
|
|
4278
4699
|
return /* @__PURE__ */ React2.createElement(Tooltip.Root, {
|
|
4279
4700
|
open: tooltipOpen,
|
|
4280
4701
|
onOpenChange: (nextOpen) => {
|
|
@@ -4477,384 +4898,6 @@ var Toolbar = {
|
|
|
4477
4898
|
Markdown: MarkdownStandard,
|
|
4478
4899
|
Extended: MarkdownExtended
|
|
4479
4900
|
};
|
|
4480
|
-
|
|
4481
|
-
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
4482
|
-
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
4483
|
-
import { Context as Context2 } from "@dxos/context";
|
|
4484
|
-
import { invariant as invariant2 } from "@dxos/invariant";
|
|
4485
|
-
import { log as log4 } from "@dxos/log";
|
|
4486
|
-
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
4487
|
-
var DEBOUNCE_INTERVAL = 100;
|
|
4488
|
-
var SpaceAwarenessProvider = class {
|
|
4489
|
-
constructor(params) {
|
|
4490
|
-
this._remoteStates = /* @__PURE__ */ new Map();
|
|
4491
|
-
this.remoteStateChange = new Event2();
|
|
4492
|
-
this._space = params.space;
|
|
4493
|
-
this._channel = params.channel;
|
|
4494
|
-
this._peerId = params.peerId;
|
|
4495
|
-
this._info = params.info;
|
|
4496
|
-
}
|
|
4497
|
-
open() {
|
|
4498
|
-
this._ctx = new Context2();
|
|
4499
|
-
this._postTask = new DeferredTask(this._ctx, async () => {
|
|
4500
|
-
if (this._localState) {
|
|
4501
|
-
await this._space.postMessage(this._channel, {
|
|
4502
|
-
kind: "post",
|
|
4503
|
-
state: this._localState
|
|
4504
|
-
});
|
|
4505
|
-
await sleep(DEBOUNCE_INTERVAL);
|
|
4506
|
-
}
|
|
4507
|
-
});
|
|
4508
|
-
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
4509
|
-
switch (message.payload.kind) {
|
|
4510
|
-
case "query": {
|
|
4511
|
-
this._handleQueryMessage();
|
|
4512
|
-
break;
|
|
4513
|
-
}
|
|
4514
|
-
case "post": {
|
|
4515
|
-
this._handlePostMessage(message.payload);
|
|
4516
|
-
break;
|
|
4517
|
-
}
|
|
4518
|
-
}
|
|
4519
|
-
}));
|
|
4520
|
-
void this._space.postMessage(this._channel, {
|
|
4521
|
-
kind: "query"
|
|
4522
|
-
}).catch((err) => {
|
|
4523
|
-
log4.debug("failed to query awareness", {
|
|
4524
|
-
err
|
|
4525
|
-
}, {
|
|
4526
|
-
F: __dxlog_file5,
|
|
4527
|
-
L: 89,
|
|
4528
|
-
S: this,
|
|
4529
|
-
C: (f, a) => f(...a)
|
|
4530
|
-
});
|
|
4531
|
-
});
|
|
4532
|
-
}
|
|
4533
|
-
close() {
|
|
4534
|
-
void this._ctx?.dispose();
|
|
4535
|
-
this._ctx = void 0;
|
|
4536
|
-
this._postTask = void 0;
|
|
4537
|
-
}
|
|
4538
|
-
getRemoteStates() {
|
|
4539
|
-
return Array.from(this._remoteStates.values());
|
|
4540
|
-
}
|
|
4541
|
-
update(position) {
|
|
4542
|
-
invariant2(this._postTask, void 0, {
|
|
4543
|
-
F: __dxlog_file5,
|
|
4544
|
-
L: 104,
|
|
4545
|
-
S: this,
|
|
4546
|
-
A: [
|
|
4547
|
-
"this._postTask",
|
|
4548
|
-
""
|
|
4549
|
-
]
|
|
4550
|
-
});
|
|
4551
|
-
this._localState = {
|
|
4552
|
-
peerId: this._peerId,
|
|
4553
|
-
position,
|
|
4554
|
-
info: this._info
|
|
4555
|
-
};
|
|
4556
|
-
this._postTask.schedule();
|
|
4557
|
-
}
|
|
4558
|
-
_handleQueryMessage() {
|
|
4559
|
-
invariant2(this._postTask, void 0, {
|
|
4560
|
-
F: __dxlog_file5,
|
|
4561
|
-
L: 115,
|
|
4562
|
-
S: this,
|
|
4563
|
-
A: [
|
|
4564
|
-
"this._postTask",
|
|
4565
|
-
""
|
|
4566
|
-
]
|
|
4567
|
-
});
|
|
4568
|
-
this._postTask.schedule();
|
|
4569
|
-
}
|
|
4570
|
-
_handlePostMessage(message) {
|
|
4571
|
-
invariant2(message.kind === "post", void 0, {
|
|
4572
|
-
F: __dxlog_file5,
|
|
4573
|
-
L: 120,
|
|
4574
|
-
S: this,
|
|
4575
|
-
A: [
|
|
4576
|
-
"message.kind === 'post'",
|
|
4577
|
-
""
|
|
4578
|
-
]
|
|
4579
|
-
});
|
|
4580
|
-
this._remoteStates.set(message.state.peerId, message.state);
|
|
4581
|
-
this.remoteStateChange.emit();
|
|
4582
|
-
}
|
|
4583
|
-
};
|
|
4584
|
-
|
|
4585
|
-
// packages/ui/react-ui-editor/src/hooks/defs.ts
|
|
4586
|
-
import { StateField as StateField7 } from "@codemirror/state";
|
|
4587
|
-
var modelState = StateField7.define({
|
|
4588
|
-
create: () => void 0,
|
|
4589
|
-
update: (model) => model
|
|
4590
|
-
});
|
|
4591
|
-
|
|
4592
|
-
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
4593
|
-
var useActionHandler = (view) => {
|
|
4594
|
-
return (action) => {
|
|
4595
|
-
if (!view) {
|
|
4596
|
-
return;
|
|
4597
|
-
}
|
|
4598
|
-
let inlineType, listType;
|
|
4599
|
-
switch (action.type) {
|
|
4600
|
-
case "heading":
|
|
4601
|
-
setHeading(parseInt(action.data))(view);
|
|
4602
|
-
break;
|
|
4603
|
-
case "strong":
|
|
4604
|
-
case "emphasis":
|
|
4605
|
-
case "strikethrough":
|
|
4606
|
-
case "code":
|
|
4607
|
-
inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
|
4608
|
-
(typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
|
|
4609
|
-
break;
|
|
4610
|
-
case "list-ordered":
|
|
4611
|
-
case "list-bullet":
|
|
4612
|
-
case "list-task":
|
|
4613
|
-
listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
|
|
4614
|
-
(action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
|
|
4615
|
-
break;
|
|
4616
|
-
case "blockquote":
|
|
4617
|
-
(action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
|
|
4618
|
-
break;
|
|
4619
|
-
case "codeblock":
|
|
4620
|
-
(action.data === false ? removeCodeblock : addCodeblock)(view);
|
|
4621
|
-
break;
|
|
4622
|
-
case "table":
|
|
4623
|
-
insertTable(view);
|
|
4624
|
-
break;
|
|
4625
|
-
case "link":
|
|
4626
|
-
(action.data === false ? removeLink : addLink)(view);
|
|
4627
|
-
break;
|
|
4628
|
-
case "comment":
|
|
4629
|
-
createComment(view);
|
|
4630
|
-
break;
|
|
4631
|
-
}
|
|
4632
|
-
setTimeout(() => {
|
|
4633
|
-
if (!view.hasFocus) {
|
|
4634
|
-
view.focus();
|
|
4635
|
-
}
|
|
4636
|
-
});
|
|
4637
|
-
};
|
|
4638
|
-
};
|
|
4639
|
-
|
|
4640
|
-
// packages/ui/react-ui-editor/src/hooks/useEditorView.ts
|
|
4641
|
-
import { useRef as useRef3, useState as useState4 } from "react";
|
|
4642
|
-
var useEditorView = (id) => {
|
|
4643
|
-
const editorRef = useRef3(null);
|
|
4644
|
-
const [prev, setPrev] = useState4([
|
|
4645
|
-
null,
|
|
4646
|
-
""
|
|
4647
|
-
]);
|
|
4648
|
-
if (prev[0] !== editorRef.current) {
|
|
4649
|
-
setPrev([
|
|
4650
|
-
editorRef.current,
|
|
4651
|
-
id
|
|
4652
|
-
]);
|
|
4653
|
-
}
|
|
4654
|
-
return [
|
|
4655
|
-
editorRef,
|
|
4656
|
-
prev[1] !== id
|
|
4657
|
-
];
|
|
4658
|
-
};
|
|
4659
|
-
|
|
4660
|
-
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4661
|
-
import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
|
|
4662
|
-
import { EditorView as EditorView18 } from "@codemirror/view";
|
|
4663
|
-
import { useEffect as useEffect3, useRef as useRef4, useState as useState5 } from "react";
|
|
4664
|
-
import { log as log5 } from "@dxos/log";
|
|
4665
|
-
import { isNotFalsy as isNotFalsy5 } from "@dxos/util";
|
|
4666
|
-
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
4667
|
-
var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}, deps) => {
|
|
4668
|
-
const onUpdate = useRef4();
|
|
4669
|
-
const [view, setView] = useState5();
|
|
4670
|
-
const parentRef = useRef4(null);
|
|
4671
|
-
useEffect3(() => {
|
|
4672
|
-
let view2;
|
|
4673
|
-
if (parentRef.current) {
|
|
4674
|
-
const state = EditorState3.create({
|
|
4675
|
-
doc,
|
|
4676
|
-
selection,
|
|
4677
|
-
extensions: [
|
|
4678
|
-
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4679
|
-
EditorView18.exceptionSink.of((err) => {
|
|
4680
|
-
log5.catch(err, void 0, {
|
|
4681
|
-
F: __dxlog_file6,
|
|
4682
|
-
L: 57,
|
|
4683
|
-
S: void 0,
|
|
4684
|
-
C: (f, a) => f(...a)
|
|
4685
|
-
});
|
|
4686
|
-
}),
|
|
4687
|
-
extensions,
|
|
4688
|
-
EditorView18.updateListener.of(() => {
|
|
4689
|
-
onUpdate.current?.();
|
|
4690
|
-
})
|
|
4691
|
-
].filter(isNotFalsy5)
|
|
4692
|
-
});
|
|
4693
|
-
view2 = new EditorView18({
|
|
4694
|
-
parent: parentRef.current,
|
|
4695
|
-
scrollTo,
|
|
4696
|
-
state,
|
|
4697
|
-
// NOTE: Uncomment to debug/monitor all transactions.
|
|
4698
|
-
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
4699
|
-
dispatchTransactions: (trs, view3) => {
|
|
4700
|
-
if (debug) {
|
|
4701
|
-
logChanges(trs);
|
|
4702
|
-
}
|
|
4703
|
-
view3.update(trs);
|
|
4704
|
-
}
|
|
4705
|
-
});
|
|
4706
|
-
setView(view2);
|
|
4707
|
-
}
|
|
4708
|
-
return () => {
|
|
4709
|
-
view2?.destroy();
|
|
4710
|
-
};
|
|
4711
|
-
}, deps);
|
|
4712
|
-
useEffect3(() => {
|
|
4713
|
-
if (view) {
|
|
4714
|
-
if (!selection && !view.state.selection.main.anchor) {
|
|
4715
|
-
selection = EditorSelection2.single(view.state.doc.line(1).to);
|
|
4716
|
-
}
|
|
4717
|
-
if (selection || scrollTo) {
|
|
4718
|
-
onUpdate.current = () => {
|
|
4719
|
-
onUpdate.current = void 0;
|
|
4720
|
-
view.dispatch({
|
|
4721
|
-
selection,
|
|
4722
|
-
effects: scrollTo && [
|
|
4723
|
-
scrollTo
|
|
4724
|
-
],
|
|
4725
|
-
scrollIntoView: !scrollTo
|
|
4726
|
-
});
|
|
4727
|
-
};
|
|
4728
|
-
}
|
|
4729
|
-
if (autoFocus) {
|
|
4730
|
-
view.focus();
|
|
4731
|
-
}
|
|
4732
|
-
}
|
|
4733
|
-
}, [
|
|
4734
|
-
view,
|
|
4735
|
-
autoFocus,
|
|
4736
|
-
selection,
|
|
4737
|
-
scrollTo
|
|
4738
|
-
]);
|
|
4739
|
-
return {
|
|
4740
|
-
parentRef,
|
|
4741
|
-
view
|
|
4742
|
-
};
|
|
4743
|
-
};
|
|
4744
|
-
var createDataExtensions = ({ readonly = false } = {}) => {
|
|
4745
|
-
return [
|
|
4746
|
-
//
|
|
4747
|
-
EditorState3.readOnly.of(readonly),
|
|
4748
|
-
EditorView18.editable.of(!readonly)
|
|
4749
|
-
];
|
|
4750
|
-
};
|
|
4751
|
-
var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
4752
|
-
return [
|
|
4753
|
-
//
|
|
4754
|
-
EditorView18.baseTheme(defaultTheme),
|
|
4755
|
-
theme && EditorView18.theme(theme),
|
|
4756
|
-
EditorView18.darkTheme.of(themeMode === "dark"),
|
|
4757
|
-
EditorView18.editorAttributes.of({
|
|
4758
|
-
class: slots?.editor?.className ?? ""
|
|
4759
|
-
}),
|
|
4760
|
-
EditorView18.contentAttributes.of({
|
|
4761
|
-
class: slots?.content?.className ?? ""
|
|
4762
|
-
})
|
|
4763
|
-
].filter(isNotFalsy5);
|
|
4764
|
-
};
|
|
4765
|
-
|
|
4766
|
-
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
4767
|
-
import get5 from "lodash.get";
|
|
4768
|
-
import { useState as useState6, useMemo as useMemo3 } from "react";
|
|
4769
|
-
import { generateName } from "@dxos/display-name";
|
|
4770
|
-
import { getRawDoc } from "@dxos/echo-schema";
|
|
4771
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
4772
|
-
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
4773
|
-
import { hueTokens } from "@dxos/react-ui-theme";
|
|
4774
|
-
import { hexToHue } from "@dxos/util";
|
|
4775
|
-
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
4776
|
-
var useTextExtensions = ({ id, text, space, identity }) => {
|
|
4777
|
-
const extensions = [
|
|
4778
|
-
automerge(text)
|
|
4779
|
-
];
|
|
4780
|
-
const peerId = identity?.identityKey.toHex();
|
|
4781
|
-
const { cursorLightValue, cursorDarkValue } = hueTokens[hexToHue(peerId ?? "0")];
|
|
4782
|
-
if (space && identity) {
|
|
4783
|
-
const awarenessProvider2 = new SpaceAwarenessProvider({
|
|
4784
|
-
space,
|
|
4785
|
-
channel: `awareness.${id}`,
|
|
4786
|
-
peerId: identity.identityKey.toHex(),
|
|
4787
|
-
info: {
|
|
4788
|
-
displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
|
|
4789
|
-
color: cursorDarkValue,
|
|
4790
|
-
lightColor: cursorLightValue
|
|
4791
|
-
}
|
|
4792
|
-
});
|
|
4793
|
-
extensions.push(awareness(awarenessProvider2));
|
|
4794
|
-
}
|
|
4795
|
-
return extensions;
|
|
4796
|
-
};
|
|
4797
|
-
var useTextModel = (props) => useMemo3(() => createModel(props), Object.values(props));
|
|
4798
|
-
var useInMemoryTextModel = ({ id, defaultContent }) => {
|
|
4799
|
-
const [content, setContent] = useState6(defaultContent ?? "");
|
|
4800
|
-
return {
|
|
4801
|
-
id,
|
|
4802
|
-
content,
|
|
4803
|
-
setContent,
|
|
4804
|
-
text: () => content
|
|
4805
|
-
};
|
|
4806
|
-
};
|
|
4807
|
-
var createModel = ({ space, identity, text }) => {
|
|
4808
|
-
if (!text) {
|
|
4809
|
-
return void 0;
|
|
4810
|
-
}
|
|
4811
|
-
invariant3(isAutomergeObject(text), void 0, {
|
|
4812
|
-
F: __dxlog_file7,
|
|
4813
|
-
L: 87,
|
|
4814
|
-
S: void 0,
|
|
4815
|
-
A: [
|
|
4816
|
-
"isAutomergeObject(text)",
|
|
4817
|
-
""
|
|
4818
|
-
]
|
|
4819
|
-
});
|
|
4820
|
-
const obj = text;
|
|
4821
|
-
const doc = getRawDoc(obj, [
|
|
4822
|
-
obj.field
|
|
4823
|
-
]);
|
|
4824
|
-
const peerId = identity?.identityKey.toHex();
|
|
4825
|
-
const { cursorLightValue, cursorDarkValue } = hueTokens[hexToHue(peerId ?? "0")];
|
|
4826
|
-
const awarenessProvider2 = space && new SpaceAwarenessProvider({
|
|
4827
|
-
space,
|
|
4828
|
-
channel: `automerge.awareness.${obj.id}`,
|
|
4829
|
-
info: {
|
|
4830
|
-
displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
|
|
4831
|
-
color: cursorLightValue,
|
|
4832
|
-
lightColor: cursorDarkValue
|
|
4833
|
-
},
|
|
4834
|
-
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
4835
|
-
});
|
|
4836
|
-
const extensions = [
|
|
4837
|
-
modelState.init(() => model),
|
|
4838
|
-
automerge({
|
|
4839
|
-
handle: doc.handle,
|
|
4840
|
-
path: doc.path
|
|
4841
|
-
})
|
|
4842
|
-
];
|
|
4843
|
-
if (awarenessProvider2) {
|
|
4844
|
-
extensions.push(awareness(awarenessProvider2));
|
|
4845
|
-
}
|
|
4846
|
-
const model = {
|
|
4847
|
-
id: obj.id,
|
|
4848
|
-
content: doc,
|
|
4849
|
-
text: () => get5(doc.handle.docSync(), doc.path),
|
|
4850
|
-
extension: extensions,
|
|
4851
|
-
peer: identity ? {
|
|
4852
|
-
id: identity.identityKey.toHex(),
|
|
4853
|
-
name: identity.profile?.displayName
|
|
4854
|
-
} : void 0
|
|
4855
|
-
};
|
|
4856
|
-
return model;
|
|
4857
|
-
};
|
|
4858
4901
|
export {
|
|
4859
4902
|
BaseTextEditor,
|
|
4860
4903
|
Cursor,
|
|
@@ -4886,9 +4929,8 @@ export {
|
|
|
4886
4929
|
command,
|
|
4887
4930
|
comments,
|
|
4888
4931
|
compareFormatting,
|
|
4889
|
-
|
|
4932
|
+
createBasicExtensions,
|
|
4890
4933
|
createComment,
|
|
4891
|
-
createDataExtensions,
|
|
4892
4934
|
createMarkdownExtensions,
|
|
4893
4935
|
createThemeExtensions,
|
|
4894
4936
|
cursorLineMargin,
|
|
@@ -4919,7 +4961,6 @@ export {
|
|
|
4919
4961
|
markdownTagsExtensions,
|
|
4920
4962
|
markdownTheme,
|
|
4921
4963
|
mention,
|
|
4922
|
-
modelState,
|
|
4923
4964
|
outliner,
|
|
4924
4965
|
removeBlockquote,
|
|
4925
4966
|
removeCodeblock,
|