@dxos/react-ui-editor 0.3.11-main.2e39ec4 → 0.3.11-main.2f1331c
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 +1854 -1391
- 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 +16 -14
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +20 -17
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +6 -6
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts +26 -0
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/hooks.stories.d.ts +23 -0
- package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +25 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +23 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/index.d.ts +2 -0
- package/dist/types/src/components/Toolbar/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.spec.d.ts +2 -0
- package/dist/types/src/extensions/automerge/automerge.spec.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/automerge.test.d.ts +2 -0
- package/dist/types/src/extensions/automerge/automerge.test.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +9 -11
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts +8 -12
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +2 -2
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/awareness.d.ts +2 -2
- package/dist/types/src/extensions/awareness.d.ts.map +1 -1
- package/dist/types/src/extensions/basic.d.ts +4 -5
- package/dist/types/src/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +37 -20
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/{util → extensions}/cursor.d.ts +10 -2
- package/dist/types/src/extensions/cursor.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +2 -8
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +3 -6
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/code.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts +13 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/heading.d.ts +6 -0
- package/dist/types/src/extensions/markdown/heading.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/hr.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts +8 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/tasklist.d.ts.map +1 -0
- package/dist/types/src/extensions/mention.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner.d.ts +4 -0
- package/dist/types/src/extensions/outliner.d.ts.map +1 -0
- package/dist/types/src/hooks/awareness-provider.d.ts +7 -4
- package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -1
- package/dist/types/src/hooks/defs.d.ts +25 -0
- package/dist/types/src/hooks/defs.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +4 -2
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useActionHandler.d.ts +4 -0
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -0
- package/dist/types/src/hooks/useEditorView.d.ts +17 -0
- package/dist/types/src/hooks/useEditorView.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextEditor.d.ts +39 -0
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextModel.d.ts +2 -32
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/markdown.d.ts +2 -2
- package/dist/types/src/styles/markdown.d.ts.map +1 -1
- package/dist/types/src/styles/tokens.d.ts +1 -0
- package/dist/types/src/styles/tokens.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +7 -0
- package/dist/types/src/util.d.ts.map +1 -0
- package/package.json +48 -37
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +84 -91
- package/src/components/TextEditor/TextEditor.stories.tsx +12 -46
- package/src/components/TextEditor/TextEditor.tsx +136 -95
- package/src/components/TextEditor/automerge.stories.tsx +1 -2
- package/src/components/TextEditor/comments.stories.tsx +357 -0
- package/src/components/TextEditor/hooks.stories.tsx +106 -0
- package/src/components/Toolbar/Toolbar.stories.tsx +90 -0
- package/src/components/Toolbar/Toolbar.tsx +166 -0
- package/src/components/Toolbar/index.ts +5 -0
- package/src/components/index.ts +1 -0
- package/src/extensions/autocomplete.ts +23 -19
- package/src/extensions/automerge/automerge.spec.tsx +76 -0
- package/src/extensions/automerge/automerge.test.ts +13 -0
- package/src/extensions/automerge/automerge.ts +55 -46
- package/src/extensions/automerge/cursor.ts +5 -4
- package/src/extensions/automerge/defs.ts +13 -34
- package/src/extensions/automerge/semaphore.ts +33 -32
- package/src/extensions/automerge/update-automerge.ts +14 -8
- package/src/extensions/automerge/update-codemirror.ts +5 -5
- package/src/extensions/awareness.ts +43 -49
- package/src/extensions/basic.ts +17 -10
- package/src/extensions/comments.ts +323 -268
- package/src/extensions/cursor.ts +50 -0
- package/src/extensions/index.ts +2 -8
- package/src/extensions/markdown/bundle.ts +23 -28
- package/src/extensions/markdown/code.ts +150 -0
- package/src/extensions/markdown/formatting.ts +188 -0
- package/src/extensions/markdown/heading.ts +59 -0
- package/src/extensions/markdown/highlight.ts +11 -26
- package/src/extensions/markdown/hr.ts +71 -0
- package/src/extensions/markdown/image.ts +87 -0
- package/src/extensions/markdown/index.ts +8 -0
- package/src/extensions/{link.ts → markdown/link.ts} +87 -86
- package/src/extensions/{table.ts → markdown/table.ts} +10 -4
- package/src/extensions/markdown/tasklist.ts +110 -0
- package/src/extensions/mention.ts +9 -2
- package/src/extensions/outliner.ts +12 -0
- package/src/hooks/awareness-provider.ts +24 -20
- package/src/hooks/defs.ts +42 -0
- package/src/hooks/index.ts +5 -2
- package/src/hooks/useActionHandler.ts +62 -0
- package/src/hooks/useEditorView.ts +29 -0
- package/src/hooks/useTextEditor.ts +153 -0
- package/src/hooks/useTextModel.ts +50 -59
- package/src/index.ts +3 -0
- package/src/styles/markdown.ts +9 -12
- package/src/styles/tokens.ts +3 -0
- package/src/themes/default.ts +53 -80
- package/src/util.ts +41 -0
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts +0 -12
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts +0 -12
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/code.d.ts.map +0 -1
- package/dist/types/src/extensions/hr.d.ts.map +0 -1
- package/dist/types/src/extensions/image.d.ts.map +0 -1
- package/dist/types/src/extensions/link.d.ts.map +0 -1
- package/dist/types/src/extensions/mermaid.d.ts +0 -3
- package/dist/types/src/extensions/mermaid.d.ts.map +0 -1
- package/dist/types/src/extensions/table.d.ts.map +0 -1
- package/dist/types/src/extensions/tasklist.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/cursor.d.ts +0 -4
- package/dist/types/src/extensions/yjs/cursor.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/index.d.ts +0 -2
- package/dist/types/src/extensions/yjs/index.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.d.ts +0 -4
- package/dist/types/src/extensions/yjs/yjs.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.test.d.ts +0 -2
- package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge.d.ts +0 -3
- package/dist/types/src/hooks/automerge.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs.d.ts +0 -27
- package/dist/types/src/hooks/yjs.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -3
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/proto/gen/schema.d.ts +0 -15
- package/dist/types/src/testing/proto/gen/schema.d.ts.map +0 -1
- package/dist/types/src/testing/proto/index.d.ts +0 -2
- package/dist/types/src/testing/proto/index.d.ts.map +0 -1
- package/dist/types/src/testing/replicator.d.ts +0 -45
- package/dist/types/src/testing/replicator.d.ts.map +0 -1
- package/dist/types/src/util/cursor.d.ts.map +0 -1
- package/dist/types/src/util/index.d.ts +0 -3
- package/dist/types/src/util/index.d.ts.map +0 -1
- package/dist/types/src/util/util.d.ts +0 -5
- package/dist/types/src/util/util.d.ts.map +0 -1
- package/src/components/TextEditor/codemirror.stories.ts +0 -115
- package/src/components/TextEditor/yjs.stories.tsx +0 -56
- package/src/extensions/code.ts +0 -99
- package/src/extensions/hr.ts +0 -74
- package/src/extensions/image.ts +0 -69
- package/src/extensions/mermaid.ts +0 -11
- package/src/extensions/tasklist.ts +0 -121
- package/src/extensions/yjs/cursor.ts +0 -21
- package/src/extensions/yjs/index.ts +0 -5
- package/src/extensions/yjs/yjs.test.ts +0 -35
- package/src/extensions/yjs/yjs.ts +0 -16
- package/src/hooks/automerge.ts +0 -52
- package/src/hooks/yjs.ts +0 -178
- package/src/testing/index.ts +0 -6
- package/src/testing/proto/gen/schema.ts +0 -49
- package/src/testing/proto/index.ts +0 -5
- package/src/testing/proto/schema.proto +0 -15
- package/src/testing/replicator.ts +0 -184
- package/src/util/cursor.ts +0 -29
- package/src/util/index.ts +0 -6
- package/src/util/util.ts +0 -18
- /package/dist/types/src/extensions/{code.d.ts → markdown/code.d.ts} +0 -0
- /package/dist/types/src/extensions/{hr.d.ts → markdown/hr.d.ts} +0 -0
- /package/dist/types/src/extensions/{image.d.ts → markdown/image.d.ts} +0 -0
- /package/dist/types/src/extensions/{link.d.ts → markdown/link.d.ts} +0 -0
- /package/dist/types/src/extensions/{table.d.ts → markdown/table.d.ts} +0 -0
- /package/dist/types/src/extensions/{tasklist.d.ts → markdown/tasklist.d.ts} +0 -0
|
@@ -8,55 +8,59 @@ import { tags as tags2 } from "@lezer/highlight";
|
|
|
8
8
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
9
9
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
10
10
|
import { EditorView as EditorView13 } from "@codemirror/view";
|
|
11
|
-
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
12
11
|
import { vim } from "@replit/codemirror-vim";
|
|
13
12
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
14
|
-
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
|
|
15
|
-
import {
|
|
13
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState } from "react";
|
|
14
|
+
import { log as log2 } from "@dxos/log";
|
|
16
15
|
import { useThemeContext } from "@dxos/react-ui";
|
|
17
|
-
import {
|
|
16
|
+
import { attentionSurface, mx as mx3 } from "@dxos/react-ui-theme";
|
|
17
|
+
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
18
18
|
|
|
19
19
|
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
|
20
20
|
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
|
21
|
+
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
21
22
|
import { keymap } from "@codemirror/view";
|
|
22
23
|
var autocomplete = ({ onSearch }) => {
|
|
23
24
|
return [
|
|
24
25
|
// https://codemirror.net/docs/ref/#view.keymap
|
|
25
26
|
// https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
|
|
27
|
+
// TODO(burdon): Set custom keymap.
|
|
26
28
|
keymap.of(completionKeymap),
|
|
27
29
|
// https://codemirror.net/examples/autocompletion
|
|
28
30
|
// https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
|
29
31
|
autocompletion({
|
|
30
|
-
|
|
32
|
+
activateOnTyping: true,
|
|
33
|
+
// closeOnBlur: false,
|
|
31
34
|
// defaultKeymap: false,
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
from: match.from,
|
|
44
|
-
options: onSearch(match.text.toLowerCase())
|
|
45
|
-
};
|
|
35
|
+
// TODO(burdon): Styles/fragments.
|
|
36
|
+
tooltipClass: () => "shadow rounded"
|
|
37
|
+
}),
|
|
38
|
+
// TODO(burdon): Option to create new page?
|
|
39
|
+
// TODO(burdon): Optional decoration via addToOptions
|
|
40
|
+
markdownLanguage.data.of({
|
|
41
|
+
autocomplete: (context) => {
|
|
42
|
+
const match = context.matchBefore(/\w*/);
|
|
43
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
44
|
+
return null;
|
|
46
45
|
}
|
|
47
|
-
|
|
46
|
+
return {
|
|
47
|
+
from: match.from,
|
|
48
|
+
options: onSearch(match.text.toLowerCase())
|
|
49
|
+
};
|
|
50
|
+
}
|
|
48
51
|
})
|
|
49
52
|
];
|
|
50
53
|
};
|
|
51
54
|
|
|
52
55
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
53
|
-
import {
|
|
54
|
-
import {
|
|
55
|
-
import {
|
|
56
|
+
import { invertedEffects } from "@codemirror/commands";
|
|
57
|
+
import { StateField } from "@codemirror/state";
|
|
58
|
+
import { EditorView, ViewPlugin } from "@codemirror/view";
|
|
59
|
+
import { next as A4 } from "@dxos/automerge/automerge";
|
|
56
60
|
|
|
57
61
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
|
58
62
|
import get from "lodash.get";
|
|
59
|
-
import { next as
|
|
63
|
+
import { next as A } from "@dxos/automerge/automerge";
|
|
60
64
|
var cursorConverter = (handle, path) => ({
|
|
61
65
|
// TODO(burdon): Handle assoc to associate with a previous character.
|
|
62
66
|
toCursor: (pos) => {
|
|
@@ -68,7 +72,7 @@ var cursorConverter = (handle, path) => ({
|
|
|
68
72
|
if (typeof value === "string" && value.length <= pos) {
|
|
69
73
|
return "end";
|
|
70
74
|
}
|
|
71
|
-
return
|
|
75
|
+
return A.getCursor(doc, path.slice(), pos);
|
|
72
76
|
},
|
|
73
77
|
fromCursor: (cursor) => {
|
|
74
78
|
if (cursor === "") {
|
|
@@ -86,26 +90,28 @@ var cursorConverter = (handle, path) => ({
|
|
|
86
90
|
return 0;
|
|
87
91
|
}
|
|
88
92
|
}
|
|
89
|
-
return
|
|
93
|
+
return A.getCursorPosition(doc, path.slice(), cursor);
|
|
90
94
|
}
|
|
91
95
|
});
|
|
92
96
|
|
|
93
97
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
94
98
|
import { Annotation, StateEffect } from "@codemirror/state";
|
|
95
|
-
var
|
|
96
|
-
var
|
|
99
|
+
var getPath = (state, field) => state.field(field).path;
|
|
100
|
+
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
101
|
+
var updateHeadsEffect = StateEffect.define({});
|
|
102
|
+
var updateHeads = (newHeads) => updateHeadsEffect.of({
|
|
97
103
|
newHeads
|
|
98
104
|
});
|
|
99
|
-
var
|
|
100
|
-
var
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
var reconcileAnnotation = Annotation.define();
|
|
106
|
+
var isReconcile = (tr) => {
|
|
107
|
+
return !!tr.annotation(reconcileAnnotation);
|
|
108
|
+
};
|
|
103
109
|
|
|
104
110
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
105
|
-
import { next as
|
|
111
|
+
import { next as A3 } from "@dxos/automerge/automerge";
|
|
106
112
|
|
|
107
113
|
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
|
108
|
-
import { next as
|
|
114
|
+
import { next as A2 } from "@dxos/automerge/automerge";
|
|
109
115
|
var updateAutomerge = (field, handle, transactions, state) => {
|
|
110
116
|
const { lastHeads, path } = state.field(field);
|
|
111
117
|
let hasChanges = false;
|
|
@@ -118,11 +124,19 @@ var updateAutomerge = (field, handle, transactions, state) => {
|
|
|
118
124
|
return void 0;
|
|
119
125
|
}
|
|
120
126
|
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
|
127
|
+
const invertedTransactions = [];
|
|
121
128
|
for (const tr of transactions) {
|
|
122
|
-
tr.changes.iterChanges((fromA, toA, _fromB, _toB,
|
|
123
|
-
|
|
129
|
+
tr.changes.iterChanges((fromA, toA, _fromB, _toB, insert) => {
|
|
130
|
+
invertedTransactions.push({
|
|
131
|
+
from: fromA,
|
|
132
|
+
del: toA - fromA,
|
|
133
|
+
insert
|
|
134
|
+
});
|
|
124
135
|
});
|
|
125
136
|
}
|
|
137
|
+
invertedTransactions.reverse().forEach(({ from, del, insert }) => {
|
|
138
|
+
A2.splice(doc, path.slice(), from, del, insert.toString());
|
|
139
|
+
});
|
|
126
140
|
});
|
|
127
141
|
return newHeads ?? void 0;
|
|
128
142
|
};
|
|
@@ -137,13 +151,13 @@ var updateCodeMirror = (view, selection, target, patches) => {
|
|
|
137
151
|
selection = selection.map(changeSet, 1);
|
|
138
152
|
view.dispatch({
|
|
139
153
|
changes: changeSet,
|
|
140
|
-
annotations:
|
|
154
|
+
annotations: reconcileAnnotation.of(false)
|
|
141
155
|
});
|
|
142
156
|
}
|
|
143
157
|
}
|
|
144
158
|
view.dispatch({
|
|
145
159
|
selection,
|
|
146
|
-
annotations:
|
|
160
|
+
annotations: reconcileAnnotation.of(false)
|
|
147
161
|
});
|
|
148
162
|
};
|
|
149
163
|
var handlePatch = (patch, target, state) => {
|
|
@@ -164,7 +178,7 @@ var handleInsert = (target, patch) => {
|
|
|
164
178
|
if (index == null) {
|
|
165
179
|
return [];
|
|
166
180
|
}
|
|
167
|
-
const text = patch.values.map((
|
|
181
|
+
const text = patch.values.map((value) => value ? value.toString() : "").join("");
|
|
168
182
|
return [
|
|
169
183
|
{
|
|
170
184
|
from: index,
|
|
@@ -236,89 +250,100 @@ var charPath = (textPath, candidatePath) => {
|
|
|
236
250
|
|
|
237
251
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
238
252
|
var PatchSemaphore = class {
|
|
239
|
-
|
|
240
|
-
|
|
253
|
+
// prettier-ignore
|
|
254
|
+
constructor(_handle, _state) {
|
|
255
|
+
this._handle = _handle;
|
|
256
|
+
this._state = _state;
|
|
241
257
|
this._inReconcile = false;
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
258
|
+
}
|
|
259
|
+
reconcile(view) {
|
|
260
|
+
if (!this._inReconcile) {
|
|
247
261
|
this._inReconcile = true;
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
let newHeads = updateAutomerge(this._field, handle, transactions, view.state);
|
|
262
|
-
if (newHeads === null || newHeads === void 0) {
|
|
263
|
-
newHeads = automerge2.getHeads(handle.docSync());
|
|
264
|
-
}
|
|
265
|
-
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(handle.docSync(), oldHeads, newHeads);
|
|
266
|
-
updateCodeMirror(view, selection, path, diff);
|
|
262
|
+
this.doReconcile(view);
|
|
263
|
+
this._inReconcile = false;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
doReconcile(view) {
|
|
267
|
+
const path = getPath(view.state, this._state);
|
|
268
|
+
const oldHeads = getLastHeads(view.state, this._state);
|
|
269
|
+
let selection = view.state.selection;
|
|
270
|
+
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcile(tx));
|
|
271
|
+
const toInvert = transactions.slice().reverse();
|
|
272
|
+
for (const tr of toInvert) {
|
|
273
|
+
const inverted = tr.changes.invert(tr.startState.doc);
|
|
274
|
+
selection = selection.map(inverted);
|
|
267
275
|
view.dispatch({
|
|
268
|
-
|
|
269
|
-
annotations:
|
|
276
|
+
changes: inverted,
|
|
277
|
+
annotations: reconcileAnnotation.of(true)
|
|
270
278
|
});
|
|
271
|
-
|
|
272
|
-
|
|
279
|
+
}
|
|
280
|
+
let newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
|
|
281
|
+
if (newHeads === null || newHeads === void 0) {
|
|
282
|
+
newHeads = A3.getHeads(this._handle.docSync());
|
|
283
|
+
}
|
|
284
|
+
const diff = A3.equals(oldHeads, newHeads) ? [] : A3.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
285
|
+
updateCodeMirror(view, selection, path, diff);
|
|
286
|
+
view.dispatch({
|
|
287
|
+
effects: updateHeads(newHeads),
|
|
288
|
+
annotations: reconcileAnnotation.of(false)
|
|
289
|
+
});
|
|
273
290
|
}
|
|
274
291
|
};
|
|
275
292
|
|
|
276
|
-
// packages/ui/react-ui-editor/src/
|
|
293
|
+
// packages/ui/react-ui-editor/src/extensions/cursor.ts
|
|
277
294
|
import { Facet } from "@codemirror/state";
|
|
278
|
-
var
|
|
295
|
+
var defaultCursorConverter = {
|
|
279
296
|
toCursor: (position) => position.toString(),
|
|
280
297
|
fromCursor: (cursor) => parseInt(cursor)
|
|
281
298
|
};
|
|
282
|
-
var
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
// packages/ui/react-ui-editor/src/util/util.ts
|
|
287
|
-
import { log } from "@dxos/log";
|
|
288
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/util.ts";
|
|
289
|
-
var callbackWrapper = (fn) => (...args) => {
|
|
290
|
-
try {
|
|
291
|
-
return fn(...args);
|
|
292
|
-
} catch (error) {
|
|
293
|
-
log.catch(error, void 0, {
|
|
294
|
-
F: __dxlog_file,
|
|
295
|
-
L: 16,
|
|
296
|
-
S: void 0,
|
|
297
|
-
C: (f, a) => f(...a)
|
|
299
|
+
var Cursor = class _Cursor {
|
|
300
|
+
static {
|
|
301
|
+
this.converter = Facet.define({
|
|
302
|
+
combine: (providers) => providers[0] ?? defaultCursorConverter
|
|
298
303
|
});
|
|
299
304
|
}
|
|
305
|
+
static {
|
|
306
|
+
this.getCursorFromRange = (state, range) => {
|
|
307
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
308
|
+
const from = cursorConverter2.toCursor(range.from);
|
|
309
|
+
const to = cursorConverter2.toCursor(range.to, -1);
|
|
310
|
+
return [
|
|
311
|
+
from,
|
|
312
|
+
to
|
|
313
|
+
].join(":");
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
static {
|
|
317
|
+
this.getRangeFromCursor = (state, cursor) => {
|
|
318
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
319
|
+
const parts = cursor.split(":");
|
|
320
|
+
const from = cursorConverter2.fromCursor(parts[0]);
|
|
321
|
+
const to = cursorConverter2.fromCursor(parts[1]);
|
|
322
|
+
return from !== void 0 && to !== void 0 ? {
|
|
323
|
+
from,
|
|
324
|
+
to
|
|
325
|
+
} : void 0;
|
|
326
|
+
};
|
|
327
|
+
}
|
|
300
328
|
};
|
|
301
329
|
|
|
302
330
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
303
|
-
var
|
|
304
|
-
|
|
305
|
-
});
|
|
306
|
-
var automerge3 = ({ handle, path }) => {
|
|
307
|
-
const stateField = StateField.define({
|
|
331
|
+
var automerge = ({ handle, path }) => {
|
|
332
|
+
const syncState = StateField.define({
|
|
308
333
|
create: () => ({
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
334
|
+
path: path.slice(),
|
|
335
|
+
lastHeads: A4.getHeads(handle.docSync()),
|
|
336
|
+
unreconciledTransactions: []
|
|
312
337
|
}),
|
|
313
338
|
update: (value, tr) => {
|
|
314
339
|
const result = {
|
|
340
|
+
path: path.slice(),
|
|
315
341
|
lastHeads: value.lastHeads,
|
|
316
|
-
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
317
|
-
path: path.slice()
|
|
342
|
+
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
318
343
|
};
|
|
319
344
|
let clearUnreconciled = false;
|
|
320
345
|
for (const effect of tr.effects) {
|
|
321
|
-
if (effect.is(
|
|
346
|
+
if (effect.is(updateHeadsEffect)) {
|
|
322
347
|
result.lastHeads = effect.value.newHeads;
|
|
323
348
|
clearUnreconciled = true;
|
|
324
349
|
}
|
|
@@ -326,46 +351,53 @@ var automerge3 = ({ handle, path }) => {
|
|
|
326
351
|
if (clearUnreconciled) {
|
|
327
352
|
result.unreconciledTransactions = [];
|
|
328
353
|
} else {
|
|
329
|
-
if (!
|
|
354
|
+
if (!isReconcile(tr)) {
|
|
330
355
|
result.unreconciledTransactions.push(tr);
|
|
331
356
|
}
|
|
332
357
|
}
|
|
333
358
|
return result;
|
|
334
359
|
}
|
|
335
360
|
});
|
|
336
|
-
const semaphore = new PatchSemaphore(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
361
|
+
const semaphore = new PatchSemaphore(handle, syncState);
|
|
362
|
+
return [
|
|
363
|
+
Cursor.converter.of(cursorConverter(handle, path)),
|
|
364
|
+
syncState,
|
|
365
|
+
// Reconcile external updates.
|
|
366
|
+
ViewPlugin.fromClass(class {
|
|
367
|
+
constructor(_view) {
|
|
368
|
+
this._view = _view;
|
|
369
|
+
handle.addListener("change", this._handleChange.bind(this));
|
|
370
|
+
}
|
|
371
|
+
destroy() {
|
|
372
|
+
handle.removeListener("change", this._handleChange.bind(this));
|
|
373
|
+
}
|
|
374
|
+
_handleChange() {
|
|
375
|
+
semaphore.reconcile(this._view);
|
|
376
|
+
}
|
|
377
|
+
}),
|
|
378
|
+
// Reconcile local updates.
|
|
379
|
+
EditorView.updateListener.of(({ view, changes }) => {
|
|
380
|
+
if (!changes.empty) {
|
|
381
|
+
semaphore.reconcile(view);
|
|
382
|
+
}
|
|
383
|
+
}),
|
|
384
|
+
// TODO(burdon): Record undo transactions.
|
|
385
|
+
// See https://github.com/yjs/y-codemirror.next/tree/main
|
|
386
|
+
// https://codemirror.net/examples/inverted-effect
|
|
387
|
+
invertedEffects.of((tr) => {
|
|
388
|
+
const effects = [];
|
|
389
|
+
if (!tr.changes.empty) {
|
|
390
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => {
|
|
349
391
|
});
|
|
350
392
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
});
|
|
356
|
-
return {
|
|
357
|
-
extension: [
|
|
358
|
-
CursorConverter.of(cursorConverter(handle, path)),
|
|
359
|
-
semaphoreFacet.of(semaphore),
|
|
360
|
-
stateField,
|
|
361
|
-
viewPlugin
|
|
362
|
-
]
|
|
363
|
-
};
|
|
393
|
+
return effects;
|
|
394
|
+
})
|
|
395
|
+
];
|
|
364
396
|
};
|
|
365
397
|
|
|
366
398
|
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
367
|
-
import { Annotation as Annotation2, Facet as
|
|
368
|
-
import { Decoration, EditorView, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
399
|
+
import { Annotation as Annotation2, Facet as Facet2, RangeSet } from "@codemirror/state";
|
|
400
|
+
import { Decoration, EditorView as EditorView2, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
369
401
|
import { Event } from "@dxos/async";
|
|
370
402
|
import { Context } from "@dxos/context";
|
|
371
403
|
var dummyProvider = {
|
|
@@ -374,17 +406,17 @@ var dummyProvider = {
|
|
|
374
406
|
},
|
|
375
407
|
close: () => {
|
|
376
408
|
},
|
|
409
|
+
getRemoteStates: () => [],
|
|
377
410
|
update: () => {
|
|
378
|
-
}
|
|
379
|
-
getRemoteStates: () => []
|
|
411
|
+
}
|
|
380
412
|
};
|
|
381
|
-
var
|
|
413
|
+
var awarenessProvider = Facet2.define({
|
|
382
414
|
combine: (providers) => providers[0] ?? dummyProvider
|
|
383
415
|
});
|
|
384
416
|
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
385
417
|
var awareness = (provider = dummyProvider) => {
|
|
386
418
|
return [
|
|
387
|
-
|
|
419
|
+
awarenessProvider.of(provider),
|
|
388
420
|
ViewPlugin2.fromClass(RemoteSelectionsDecorator, {
|
|
389
421
|
decorations: (value) => value.decorations
|
|
390
422
|
}),
|
|
@@ -397,8 +429,8 @@ var RemoteSelectionsDecorator = class {
|
|
|
397
429
|
this._ctx = new Context();
|
|
398
430
|
this._lastAnchor = void 0;
|
|
399
431
|
this._lastHead = void 0;
|
|
400
|
-
this._cursorConverter = view.state.facet(
|
|
401
|
-
this._provider = view.state.facet(
|
|
432
|
+
this._cursorConverter = view.state.facet(Cursor.converter);
|
|
433
|
+
this._provider = view.state.facet(awarenessProvider);
|
|
402
434
|
this._provider.open();
|
|
403
435
|
this._provider.remoteStateChange.on(this._ctx, () => {
|
|
404
436
|
view.dispatch({
|
|
@@ -412,13 +444,13 @@ var RemoteSelectionsDecorator = class {
|
|
|
412
444
|
void this._ctx.dispose();
|
|
413
445
|
this._provider.close();
|
|
414
446
|
}
|
|
415
|
-
update(
|
|
416
|
-
this._updateLocalSelection(
|
|
417
|
-
this._updateRemoteSelections(
|
|
447
|
+
update(update2) {
|
|
448
|
+
this._updateLocalSelection(update2);
|
|
449
|
+
this._updateRemoteSelections(update2);
|
|
418
450
|
}
|
|
419
|
-
_updateLocalSelection(
|
|
420
|
-
const hasFocus =
|
|
421
|
-
const { anchor = void 0, head = void 0 } = hasFocus ?
|
|
451
|
+
_updateLocalSelection(update2) {
|
|
452
|
+
const hasFocus = update2.view.hasFocus && update2.view.dom.ownerDocument.hasFocus();
|
|
453
|
+
const { anchor = void 0, head = void 0 } = hasFocus ? update2.state.selection.main : {};
|
|
422
454
|
if (this._lastAnchor === anchor && this._lastHead === head) {
|
|
423
455
|
return;
|
|
424
456
|
}
|
|
@@ -429,7 +461,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
429
461
|
head: this._cursorConverter.toCursor(head)
|
|
430
462
|
} : void 0);
|
|
431
463
|
}
|
|
432
|
-
_updateRemoteSelections(
|
|
464
|
+
_updateRemoteSelections(update2) {
|
|
433
465
|
const decorations = [];
|
|
434
466
|
const awarenessStates = this._provider.getRemoteStates();
|
|
435
467
|
for (const state of awarenessStates) {
|
|
@@ -438,10 +470,10 @@ var RemoteSelectionsDecorator = class {
|
|
|
438
470
|
if (anchor == null || head == null) {
|
|
439
471
|
continue;
|
|
440
472
|
}
|
|
441
|
-
const start = Math.min(Math.min(anchor, head),
|
|
442
|
-
const end = Math.min(Math.max(anchor, head),
|
|
443
|
-
const startLine =
|
|
444
|
-
const endLine =
|
|
473
|
+
const start = Math.min(Math.min(anchor, head), update2.view.state.doc.length);
|
|
474
|
+
const end = Math.min(Math.max(anchor, head), update2.view.state.doc.length);
|
|
475
|
+
const startLine = update2.view.state.doc.lineAt(start);
|
|
476
|
+
const endLine = update2.view.state.doc.lineAt(end);
|
|
445
477
|
const color = state.info.color ?? "#30bced";
|
|
446
478
|
const lightColor = state.info.lightColor ?? color + "33";
|
|
447
479
|
if (startLine.number === endLine.number) {
|
|
@@ -452,7 +484,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
452
484
|
attributes: {
|
|
453
485
|
style: `background-color: ${lightColor}`
|
|
454
486
|
},
|
|
455
|
-
class: "cm-
|
|
487
|
+
class: "cm-collab-selection"
|
|
456
488
|
})
|
|
457
489
|
});
|
|
458
490
|
} else {
|
|
@@ -463,7 +495,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
463
495
|
attributes: {
|
|
464
496
|
style: `background-color: ${color}`
|
|
465
497
|
},
|
|
466
|
-
class: "cm-
|
|
498
|
+
class: "cm-collab-selection"
|
|
467
499
|
})
|
|
468
500
|
});
|
|
469
501
|
decorations.push({
|
|
@@ -473,18 +505,18 @@ var RemoteSelectionsDecorator = class {
|
|
|
473
505
|
attributes: {
|
|
474
506
|
style: `background-color: ${color}`
|
|
475
507
|
},
|
|
476
|
-
class: "cm-
|
|
508
|
+
class: "cm-collab-selection"
|
|
477
509
|
})
|
|
478
510
|
});
|
|
479
511
|
for (let i = startLine.number + 1; i < endLine.number; i++) {
|
|
480
|
-
const linePos =
|
|
512
|
+
const linePos = update2.view.state.doc.line(i).from;
|
|
481
513
|
decorations.push({
|
|
482
514
|
from: linePos,
|
|
483
515
|
to: linePos,
|
|
484
516
|
value: Decoration.line({
|
|
485
517
|
attributes: {
|
|
486
518
|
style: `background-color: ${color}`,
|
|
487
|
-
class: "cm-
|
|
519
|
+
class: "cm-collab-selectionLine"
|
|
488
520
|
}
|
|
489
521
|
})
|
|
490
522
|
});
|
|
@@ -504,23 +536,21 @@ var RemoteSelectionsDecorator = class {
|
|
|
504
536
|
}
|
|
505
537
|
};
|
|
506
538
|
var RemoteCaretWidget = class extends WidgetType {
|
|
507
|
-
constructor(
|
|
539
|
+
constructor(_name, _color) {
|
|
508
540
|
super();
|
|
509
|
-
this.
|
|
510
|
-
this.
|
|
511
|
-
this.name = name;
|
|
512
|
-
this.color = color;
|
|
541
|
+
this._name = _name;
|
|
542
|
+
this._color = _color;
|
|
513
543
|
}
|
|
514
544
|
toDOM() {
|
|
515
545
|
const span = document.createElement("span");
|
|
516
|
-
span.className = "cm-
|
|
517
|
-
span.style.backgroundColor = this.
|
|
518
|
-
span.style.borderColor = this.
|
|
546
|
+
span.className = "cm-collab-selectionCaret";
|
|
547
|
+
span.style.backgroundColor = this._color;
|
|
548
|
+
span.style.borderColor = this._color;
|
|
519
549
|
const dot = document.createElement("div");
|
|
520
|
-
dot.className = "cm-
|
|
550
|
+
dot.className = "cm-collab-selectionCaretDot";
|
|
521
551
|
const info = document.createElement("div");
|
|
522
|
-
info.className = "cm-
|
|
523
|
-
info.innerText = this.
|
|
552
|
+
info.className = "cm-collab-selectionInfo";
|
|
553
|
+
info.innerText = this._name;
|
|
524
554
|
span.appendChild(document.createTextNode("\u2060"));
|
|
525
555
|
span.appendChild(dot);
|
|
526
556
|
span.appendChild(document.createTextNode("\u2060"));
|
|
@@ -528,15 +558,12 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
528
558
|
span.appendChild(document.createTextNode("\u2060"));
|
|
529
559
|
return span;
|
|
530
560
|
}
|
|
531
|
-
eq(widget) {
|
|
532
|
-
return widget.color === this.color;
|
|
533
|
-
}
|
|
534
|
-
compare(widget) {
|
|
535
|
-
return widget.color === this.color;
|
|
536
|
-
}
|
|
537
561
|
updateDOM() {
|
|
538
562
|
return false;
|
|
539
563
|
}
|
|
564
|
+
eq(widget) {
|
|
565
|
+
return widget._color === this._color;
|
|
566
|
+
}
|
|
540
567
|
get estimatedHeight() {
|
|
541
568
|
return -1;
|
|
542
569
|
}
|
|
@@ -544,58 +571,60 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
544
571
|
return true;
|
|
545
572
|
}
|
|
546
573
|
};
|
|
547
|
-
var styles =
|
|
548
|
-
".cm-
|
|
549
|
-
".cm-
|
|
574
|
+
var styles = EditorView2.baseTheme({
|
|
575
|
+
".cm-collab-selection": {},
|
|
576
|
+
".cm-collab-selectionLine": {
|
|
550
577
|
padding: 0,
|
|
551
578
|
margin: "0px 2px 0px 4px"
|
|
552
579
|
},
|
|
553
|
-
".cm-
|
|
580
|
+
".cm-collab-selectionCaret": {
|
|
554
581
|
position: "relative",
|
|
555
582
|
borderLeft: "1px solid black",
|
|
556
583
|
borderRight: "1px solid black",
|
|
557
584
|
marginLeft: "-1px",
|
|
558
585
|
marginRight: "-1px",
|
|
559
586
|
boxSizing: "border-box",
|
|
560
|
-
display: "inline"
|
|
587
|
+
display: "inline",
|
|
588
|
+
cursor: "pointer"
|
|
561
589
|
},
|
|
562
|
-
".cm-
|
|
590
|
+
".cm-collab-selectionCaretDot": {
|
|
563
591
|
borderRadius: "50%",
|
|
564
592
|
position: "absolute",
|
|
565
|
-
width: ".
|
|
566
|
-
height: ".
|
|
567
|
-
top: "-.
|
|
568
|
-
left: "-.
|
|
593
|
+
width: ".5em",
|
|
594
|
+
height: ".5em",
|
|
595
|
+
top: "-.25em",
|
|
596
|
+
left: "-.25em",
|
|
569
597
|
backgroundColor: "inherit",
|
|
570
598
|
transition: "transform .3s ease-in-out",
|
|
571
599
|
boxSizing: "border-box"
|
|
572
600
|
},
|
|
573
|
-
".cm-
|
|
574
|
-
|
|
575
|
-
|
|
601
|
+
".cm-collab-selectionCaret:hover > .cm-collab-selectionCaretDot": {
|
|
602
|
+
transform: "scale(0)",
|
|
603
|
+
transformOrigin: "center"
|
|
576
604
|
},
|
|
577
|
-
".cm-
|
|
605
|
+
".cm-collab-selectionInfo": {
|
|
578
606
|
position: "absolute",
|
|
579
|
-
|
|
580
|
-
|
|
607
|
+
transform: "translate(-50%, 0)",
|
|
608
|
+
top: "-20px",
|
|
609
|
+
left: 0,
|
|
581
610
|
fontSize: ".75em",
|
|
582
|
-
fontFamily: "serif",
|
|
611
|
+
fontFamily: "sans-serif",
|
|
583
612
|
fontStyle: "normal",
|
|
584
613
|
fontWeight: "normal",
|
|
585
614
|
lineHeight: "normal",
|
|
586
615
|
userSelect: "none",
|
|
587
616
|
color: "white",
|
|
588
|
-
|
|
589
|
-
paddingRight: "2px",
|
|
617
|
+
padding: "2px",
|
|
590
618
|
zIndex: 101,
|
|
591
619
|
transition: "opacity .3s ease-in-out",
|
|
592
620
|
backgroundColor: "inherit",
|
|
593
|
-
|
|
621
|
+
borderRadius: "2px",
|
|
622
|
+
// These should be separate.
|
|
594
623
|
opacity: 0,
|
|
595
624
|
transitionDelay: "0s",
|
|
596
625
|
whiteSpace: "nowrap"
|
|
597
626
|
},
|
|
598
|
-
".cm-
|
|
627
|
+
".cm-collab-selectionCaret:hover > .cm-collab-selectionInfo": {
|
|
599
628
|
opacity: 1,
|
|
600
629
|
transitionDelay: "0s"
|
|
601
630
|
}
|
|
@@ -603,26 +632,29 @@ var styles = EditorView.baseTheme({
|
|
|
603
632
|
|
|
604
633
|
// packages/ui/react-ui-editor/src/extensions/basic.ts
|
|
605
634
|
import { closeBrackets } from "@codemirror/autocomplete";
|
|
635
|
+
import { history } from "@codemirror/commands";
|
|
606
636
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
607
637
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
608
|
-
import { drawSelection, EditorView as
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
638
|
+
import { drawSelection, EditorView as EditorView3, highlightActiveLine, placeholder } from "@codemirror/view";
|
|
639
|
+
import { isNotFalsy } from "@dxos/util";
|
|
640
|
+
var createBasicBundle = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => [
|
|
641
|
+
lineWrapping && EditorView3.lineWrapping,
|
|
612
642
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
613
643
|
bracketMatching(),
|
|
614
644
|
closeBrackets(),
|
|
615
645
|
drawSelection(),
|
|
646
|
+
highlightActiveLine(),
|
|
647
|
+
history(),
|
|
616
648
|
_placeholder && placeholder(_placeholder),
|
|
617
|
-
//
|
|
649
|
+
// https://github.com/codemirror/theme-one-dark
|
|
618
650
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
619
|
-
].filter(
|
|
651
|
+
].filter(isNotFalsy);
|
|
620
652
|
|
|
621
653
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
622
|
-
import { EditorView as
|
|
654
|
+
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
623
655
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
624
656
|
import { invariant } from "@dxos/invariant";
|
|
625
|
-
var
|
|
657
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
626
658
|
var defaultOptions = {
|
|
627
659
|
effect: 2,
|
|
628
660
|
maxParticles: 200,
|
|
@@ -655,10 +687,10 @@ var blast = (options = defaultOptions) => {
|
|
|
655
687
|
const getPoint = (view, pos) => {
|
|
656
688
|
const { left: x = 0, top: y = 0 } = view.coordsForChar(pos) ?? {};
|
|
657
689
|
const element = document.elementFromPoint(x, y);
|
|
658
|
-
const { offsetLeft: left = 0, offsetTop:
|
|
690
|
+
const { offsetLeft: left = 0, offsetTop: top2 = 0 } = view.scrollDOM.parentElement ?? {};
|
|
659
691
|
const point = {
|
|
660
692
|
x: x - left,
|
|
661
|
-
y: y -
|
|
693
|
+
y: y - top2
|
|
662
694
|
};
|
|
663
695
|
return {
|
|
664
696
|
element,
|
|
@@ -667,12 +699,12 @@ var blast = (options = defaultOptions) => {
|
|
|
667
699
|
};
|
|
668
700
|
return [
|
|
669
701
|
// Cursor moved.
|
|
670
|
-
|
|
671
|
-
if (blaster?.node !==
|
|
702
|
+
EditorView4.updateListener.of((update2) => {
|
|
703
|
+
if (blaster?.node !== update2.view.scrollDOM) {
|
|
672
704
|
if (blaster) {
|
|
673
705
|
blaster.destroy();
|
|
674
706
|
}
|
|
675
|
-
blaster = new Blaster(
|
|
707
|
+
blaster = new Blaster(update2.view.scrollDOM, defaultsDeep({
|
|
676
708
|
particleGravity: 0.2,
|
|
677
709
|
particleShrinkRate: 0.995,
|
|
678
710
|
color: () => [
|
|
@@ -686,10 +718,10 @@ var blast = (options = defaultOptions) => {
|
|
|
686
718
|
} else {
|
|
687
719
|
blaster.resize();
|
|
688
720
|
}
|
|
689
|
-
const current =
|
|
721
|
+
const current = update2.state.selection.main.head;
|
|
690
722
|
if (current !== last) {
|
|
691
723
|
last = current;
|
|
692
|
-
const { element, point } = getPoint(
|
|
724
|
+
const { element, point } = getPoint(update2.view, current - 1);
|
|
693
725
|
if (element && point) {
|
|
694
726
|
blaster.spawn({
|
|
695
727
|
element,
|
|
@@ -749,7 +781,7 @@ var Blaster = class {
|
|
|
749
781
|
}
|
|
750
782
|
initialize() {
|
|
751
783
|
invariant(!this._canvas && !this._ctx, void 0, {
|
|
752
|
-
F:
|
|
784
|
+
F: __dxlog_file,
|
|
753
785
|
L: 138,
|
|
754
786
|
S: this,
|
|
755
787
|
A: [
|
|
@@ -786,7 +818,7 @@ var Blaster = class {
|
|
|
786
818
|
}
|
|
787
819
|
start() {
|
|
788
820
|
invariant(this._canvas && this._ctx, void 0, {
|
|
789
|
-
F:
|
|
821
|
+
F: __dxlog_file,
|
|
790
822
|
L: 177,
|
|
791
823
|
S: this,
|
|
792
824
|
A: [
|
|
@@ -928,10 +960,14 @@ var random = (min, max) => {
|
|
|
928
960
|
return min + ~~(Math.random() * (max - min + 1));
|
|
929
961
|
};
|
|
930
962
|
|
|
931
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
932
|
-
import {
|
|
933
|
-
import
|
|
934
|
-
import {
|
|
963
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
964
|
+
import { invertedEffects as invertedEffects2 } from "@codemirror/commands";
|
|
965
|
+
import { Facet as Facet3, StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
966
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration2, EditorView as EditorView5 } from "@codemirror/view";
|
|
967
|
+
import sortBy from "lodash.sortby";
|
|
968
|
+
import { useEffect } from "react";
|
|
969
|
+
import { debounce } from "@dxos/async";
|
|
970
|
+
import { nonNullable } from "@dxos/util";
|
|
935
971
|
|
|
936
972
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
937
973
|
import * as random2 from "lib0/random";
|
|
@@ -974,34 +1010,15 @@ var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
|
974
1010
|
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
975
1011
|
import { mx } from "@dxos/react-ui-theme";
|
|
976
1012
|
var headings = {
|
|
977
|
-
1:
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
987
|
-
"-ml-[7px]"
|
|
988
|
-
],
|
|
989
|
-
4: [
|
|
990
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
991
|
-
"-ml-[6px]"
|
|
992
|
-
],
|
|
993
|
-
5: [
|
|
994
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
995
|
-
"-ml-[5px]"
|
|
996
|
-
],
|
|
997
|
-
6: [
|
|
998
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline",
|
|
999
|
-
"-ml-[4px]"
|
|
1000
|
-
]
|
|
1001
|
-
};
|
|
1002
|
-
var heading = (level, readonly) => {
|
|
1003
|
-
const [style, offset] = headings[level];
|
|
1004
|
-
return mx(style, readonly && offset);
|
|
1013
|
+
1: "mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
|
|
1014
|
+
2: "mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
|
|
1015
|
+
3: "mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
1016
|
+
4: "mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
1017
|
+
5: "mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
1018
|
+
6: "mbs-4 mbe-2 font-medium text-inherit no-underline"
|
|
1019
|
+
};
|
|
1020
|
+
var heading = (level) => {
|
|
1021
|
+
return headings[level];
|
|
1005
1022
|
};
|
|
1006
1023
|
var light = "text-neutral-200 dark:text-neutral-800";
|
|
1007
1024
|
var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
|
|
@@ -1014,158 +1031,114 @@ var inlineUrl = mx(code, "px-1");
|
|
|
1014
1031
|
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
1015
1032
|
|
|
1016
1033
|
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
1034
|
+
import get2 from "lodash.get";
|
|
1017
1035
|
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
1018
1036
|
var tokens = tailwindConfig({}).theme;
|
|
1037
|
+
var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue);
|
|
1019
1038
|
|
|
1020
|
-
// packages/ui/react-ui-editor/src/
|
|
1021
|
-
|
|
1022
|
-
var
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
display: "block",
|
|
1034
|
-
paddingInline: "4px !important"
|
|
1035
|
-
},
|
|
1036
|
-
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
1037
|
-
paddingTop: "4px !important",
|
|
1038
|
-
borderTopLeftRadius: "4px",
|
|
1039
|
-
borderTopRightRadius: "4px"
|
|
1040
|
-
},
|
|
1041
|
-
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
1042
|
-
paddingBottom: "4px !important",
|
|
1043
|
-
borderBottomLeftRadius: "4px",
|
|
1044
|
-
borderBottomRightRadius: "4px"
|
|
1039
|
+
// packages/ui/react-ui-editor/src/util.ts
|
|
1040
|
+
import { log } from "@dxos/log";
|
|
1041
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1042
|
+
var callbackWrapper = (fn) => (...args) => {
|
|
1043
|
+
try {
|
|
1044
|
+
return fn(...args);
|
|
1045
|
+
} catch (err) {
|
|
1046
|
+
log.catch(err, void 0, {
|
|
1047
|
+
F: __dxlog_file2,
|
|
1048
|
+
L: 18,
|
|
1049
|
+
S: void 0,
|
|
1050
|
+
C: (f, a) => f(...a)
|
|
1051
|
+
});
|
|
1045
1052
|
}
|
|
1046
|
-
});
|
|
1047
|
-
var getLineRange = (lines, from, to) => {
|
|
1048
|
-
const start = lines.findIndex((line) => line.from >= from);
|
|
1049
|
-
const end = lines.findIndex((line) => line.to >= to);
|
|
1050
|
-
return [
|
|
1051
|
-
start,
|
|
1052
|
-
end
|
|
1053
|
-
];
|
|
1054
1053
|
};
|
|
1055
|
-
var
|
|
1056
|
-
const
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
const text = view.state.doc.sliceString(0);
|
|
1060
|
-
const matches = text.matchAll(CODE_REGEX);
|
|
1061
|
-
const blocks = view.viewportLineBlocks;
|
|
1062
|
-
for (const match of matches) {
|
|
1063
|
-
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1064
|
-
for (let i = range[0]; i <= range[1]; i++) {
|
|
1065
|
-
const block = blocks[i];
|
|
1066
|
-
decorations.push(Decoration2.line({
|
|
1067
|
-
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1068
|
-
}).range(block.from));
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1054
|
+
var logChanges = (trs) => {
|
|
1055
|
+
const changes = trs.flatMap((tr) => {
|
|
1056
|
+
if (tr.changes.empty) {
|
|
1057
|
+
return void 0;
|
|
1071
1058
|
}
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
decorations: (value) => value.decorations
|
|
1086
|
-
}),
|
|
1087
|
-
styles2
|
|
1088
|
-
];
|
|
1059
|
+
const changes2 = [];
|
|
1060
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
|
1061
|
+
fromA,
|
|
1062
|
+
toA,
|
|
1063
|
+
fromB,
|
|
1064
|
+
toB,
|
|
1065
|
+
inserted: inserted.toString()
|
|
1066
|
+
})));
|
|
1067
|
+
return changes2;
|
|
1068
|
+
}).filter(Boolean);
|
|
1069
|
+
if (changes.length) {
|
|
1070
|
+
console.log("changes", changes);
|
|
1071
|
+
}
|
|
1089
1072
|
};
|
|
1090
1073
|
|
|
1091
1074
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1092
|
-
|
|
1093
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5, MatchDecorator, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1094
|
-
import get3 from "lodash.get";
|
|
1095
|
-
import sortBy from "lodash.sortby";
|
|
1096
|
-
import { debounce } from "@dxos/async";
|
|
1097
|
-
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1098
|
-
import { log as log2 } from "@dxos/log";
|
|
1099
|
-
import { nonNullable } from "@dxos/util";
|
|
1100
|
-
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1101
|
-
var styles3 = EditorView5.baseTheme({
|
|
1102
|
-
"& .cm-bookmark": {
|
|
1103
|
-
cursor: "pointer",
|
|
1104
|
-
margin: "4px",
|
|
1105
|
-
padding: "4px",
|
|
1106
|
-
backgroundColor: "yellow"
|
|
1107
|
-
},
|
|
1108
|
-
"& .cm-bookmark-selected": {
|
|
1109
|
-
backgroundColor: "orange"
|
|
1110
|
-
},
|
|
1075
|
+
var styles2 = EditorView5.baseTheme({
|
|
1111
1076
|
"& .cm-comment": {
|
|
1112
|
-
backgroundColor:
|
|
1077
|
+
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1113
1078
|
},
|
|
1114
|
-
"& .cm-comment-
|
|
1115
|
-
backgroundColor:
|
|
1079
|
+
"& .cm-comment-current": {
|
|
1080
|
+
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1116
1081
|
}
|
|
1117
1082
|
});
|
|
1118
|
-
var
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
const range = view.state.field(commentsStateField).ranges.find((range2) => range2.id === thread);
|
|
1128
|
-
if (!range) {
|
|
1083
|
+
var commentMark = Decoration2.mark({
|
|
1084
|
+
class: "cm-comment"
|
|
1085
|
+
});
|
|
1086
|
+
var commentCurrentMark = Decoration2.mark({
|
|
1087
|
+
class: "cm-comment-current"
|
|
1088
|
+
});
|
|
1089
|
+
var focusComment = (view, id, center = true) => {
|
|
1090
|
+
const comment = view.state.field(commentsState).comments.find((range2) => range2.comment.id === id);
|
|
1091
|
+
if (!comment?.comment.cursor) {
|
|
1129
1092
|
return;
|
|
1130
1093
|
}
|
|
1131
|
-
view.
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1094
|
+
const range = Cursor.getRangeFromCursor(view.state, comment.comment.cursor);
|
|
1095
|
+
if (range) {
|
|
1096
|
+
view.dispatch({
|
|
1097
|
+
selection: {
|
|
1098
|
+
anchor: range.from
|
|
1099
|
+
},
|
|
1100
|
+
effects: [
|
|
1101
|
+
//
|
|
1102
|
+
EditorView5.scrollIntoView(range.from, center ? {
|
|
1103
|
+
y: "center"
|
|
1104
|
+
} : void 0),
|
|
1105
|
+
setSelection.of({
|
|
1106
|
+
current: id
|
|
1107
|
+
})
|
|
1108
|
+
]
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1140
1111
|
};
|
|
1141
|
-
var
|
|
1112
|
+
var setComments = StateEffect2.define();
|
|
1142
1113
|
var setSelection = StateEffect2.define();
|
|
1143
1114
|
var setCommentState = StateEffect2.define();
|
|
1144
|
-
var
|
|
1115
|
+
var commentsState = StateField2.define({
|
|
1145
1116
|
create: () => ({
|
|
1146
|
-
|
|
1117
|
+
comments: [],
|
|
1118
|
+
selection: {}
|
|
1147
1119
|
}),
|
|
1148
1120
|
update: (value, tr) => {
|
|
1149
|
-
const cursorConverter3 = tr.state.facet(CursorConverter);
|
|
1150
1121
|
for (const effect of tr.effects) {
|
|
1151
1122
|
if (effect.is(setSelection)) {
|
|
1152
1123
|
return {
|
|
1153
1124
|
...value,
|
|
1154
|
-
|
|
1125
|
+
selection: effect.value
|
|
1155
1126
|
};
|
|
1156
1127
|
}
|
|
1157
|
-
if (effect.is(
|
|
1158
|
-
const
|
|
1159
|
-
|
|
1160
|
-
|
|
1128
|
+
if (effect.is(setComments)) {
|
|
1129
|
+
const comments2 = effect.value.map((comment) => {
|
|
1130
|
+
if (!comment.cursor) {
|
|
1131
|
+
return void 0;
|
|
1132
|
+
}
|
|
1133
|
+
const range = Cursor.getRangeFromCursor(tr.state, comment.cursor);
|
|
1161
1134
|
return range && {
|
|
1162
|
-
|
|
1163
|
-
|
|
1135
|
+
comment,
|
|
1136
|
+
range
|
|
1164
1137
|
};
|
|
1165
1138
|
}).filter(nonNullable);
|
|
1166
1139
|
return {
|
|
1167
1140
|
...value,
|
|
1168
|
-
|
|
1141
|
+
comments: comments2
|
|
1169
1142
|
};
|
|
1170
1143
|
}
|
|
1171
1144
|
if (effect.is(setCommentState)) {
|
|
@@ -1175,143 +1148,174 @@ var commentsStateField = StateField2.define({
|
|
|
1175
1148
|
return value;
|
|
1176
1149
|
}
|
|
1177
1150
|
});
|
|
1178
|
-
var
|
|
1179
|
-
|
|
1151
|
+
var commentsDecorations = EditorView5.decorations.compute([
|
|
1152
|
+
commentsState
|
|
1180
1153
|
], (state) => {
|
|
1181
|
-
const {
|
|
1182
|
-
const decorations = sortBy(
|
|
1183
|
-
|
|
1154
|
+
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
1155
|
+
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1156
|
+
const range = comment.range;
|
|
1157
|
+
if (!range || range.from === range.to) {
|
|
1158
|
+
console.warn("Invalid range:", range);
|
|
1184
1159
|
return void 0;
|
|
1185
1160
|
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
to: selection.to
|
|
1189
|
-
};
|
|
1190
|
-
if (selection.id === active) {
|
|
1191
|
-
return marks.highlightActive.range(range.from, range.to);
|
|
1161
|
+
if (comment.comment.id === current) {
|
|
1162
|
+
return commentCurrentMark.range(range.from, range.to);
|
|
1192
1163
|
} else {
|
|
1193
|
-
return
|
|
1164
|
+
return commentMark.range(range.from, range.to);
|
|
1194
1165
|
}
|
|
1195
|
-
}).filter(nonNullable)
|
|
1196
|
-
return
|
|
1166
|
+
}).filter(nonNullable);
|
|
1167
|
+
return Decoration2.set(decorations);
|
|
1197
1168
|
});
|
|
1198
|
-
var
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
return this._anchor === other._anchor && this._id === other._id;
|
|
1216
|
-
}
|
|
1217
|
-
toDOM() {
|
|
1218
|
-
const span = document.createElement("span");
|
|
1219
|
-
span.className = "cm-bookmark";
|
|
1220
|
-
span.textContent = "\u203B";
|
|
1221
|
-
if (this._handleClick) {
|
|
1222
|
-
span.onclick = () => this._handleClick();
|
|
1223
|
-
}
|
|
1224
|
-
return span;
|
|
1225
|
-
}
|
|
1226
|
-
};
|
|
1227
|
-
var comments = (options = {}) => {
|
|
1228
|
-
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1229
|
-
const createCommentThread = (view) => {
|
|
1230
|
-
const cursorConverter3 = view.state.facet(CursorConverter);
|
|
1231
|
-
invariant2(options.onCreate, void 0, {
|
|
1232
|
-
F: __dxlog_file3,
|
|
1233
|
-
L: 225,
|
|
1234
|
-
S: void 0,
|
|
1235
|
-
A: [
|
|
1236
|
-
"options.onCreate",
|
|
1237
|
-
""
|
|
1238
|
-
]
|
|
1239
|
-
});
|
|
1240
|
-
const { head, from, to } = view.state.selection.main;
|
|
1241
|
-
if (from === to) {
|
|
1242
|
-
return false;
|
|
1169
|
+
var trackPastedComments = (onUpdate) => {
|
|
1170
|
+
let tracked = null;
|
|
1171
|
+
const handleTrack = (event, view) => {
|
|
1172
|
+
const comments2 = view.state.field(commentsState);
|
|
1173
|
+
const { main } = view.state.selection;
|
|
1174
|
+
const selectedRanges = comments2.comments.filter(({ range }) => range.from >= main.from && range.to <= main.to && range.from < range.to);
|
|
1175
|
+
if (!selectedRanges.length) {
|
|
1176
|
+
tracked = null;
|
|
1177
|
+
} else {
|
|
1178
|
+
tracked = {
|
|
1179
|
+
text: view.state.doc.slice(main.from, main.to),
|
|
1180
|
+
comments: selectedRanges.map(({ comment, range }) => ({
|
|
1181
|
+
id: comment.id,
|
|
1182
|
+
from: range.from - main.from,
|
|
1183
|
+
to: range.to - main.from
|
|
1184
|
+
}))
|
|
1185
|
+
};
|
|
1243
1186
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1187
|
+
};
|
|
1188
|
+
return [
|
|
1189
|
+
EditorView5.domEventHandlers({
|
|
1190
|
+
cut: handleTrack,
|
|
1191
|
+
copy: handleTrack
|
|
1192
|
+
}),
|
|
1193
|
+
// Track deleted comments.
|
|
1194
|
+
invertedEffects2.of((tr) => {
|
|
1195
|
+
const { comments: comments2 } = tr.startState.field(commentsState);
|
|
1196
|
+
const effects = [];
|
|
1197
|
+
tr.changes.iterChangedRanges((fromA, toA) => {
|
|
1198
|
+
for (const { comment: { id }, range: { from, to } } of comments2) {
|
|
1199
|
+
if (from < to && from >= fromA && to <= toA) {
|
|
1200
|
+
effects.push(restoreCommentEffect.of({
|
|
1201
|
+
id,
|
|
1202
|
+
from,
|
|
1203
|
+
to
|
|
1204
|
+
}));
|
|
1257
1205
|
}
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1206
|
+
}
|
|
1207
|
+
});
|
|
1208
|
+
return effects;
|
|
1209
|
+
}),
|
|
1210
|
+
// Handle paste or the undo of comment deletion.
|
|
1211
|
+
EditorView5.updateListener.of((update2) => {
|
|
1212
|
+
const restore = [];
|
|
1213
|
+
for (let i = 0; i < update2.transactions.length; i++) {
|
|
1214
|
+
const tr = update2.transactions[i];
|
|
1215
|
+
for (let j = 0; j < restore.length; j++) {
|
|
1216
|
+
restore[j] = mapTrackedComment(restore[j], tr.changes);
|
|
1217
|
+
}
|
|
1218
|
+
for (const effect of tr.effects) {
|
|
1219
|
+
if (effect.is(restoreCommentEffect)) {
|
|
1220
|
+
restore.push(effect.value);
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
if (tracked) {
|
|
1225
|
+
const paste = update2.transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1226
|
+
if (paste) {
|
|
1227
|
+
let found = -1;
|
|
1228
|
+
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1229
|
+
if (text.eq(tracked.text)) {
|
|
1230
|
+
for (let i = update2.transactions.indexOf(paste) + 1; i < update2.transactions.length; i++) {
|
|
1231
|
+
fromB = update2.transactions[i].changes.mapPos(fromB);
|
|
1232
|
+
}
|
|
1233
|
+
found = fromB;
|
|
1268
1234
|
}
|
|
1269
1235
|
});
|
|
1236
|
+
if (found > -1) {
|
|
1237
|
+
for (const moved of tracked.comments) {
|
|
1238
|
+
restore.push({
|
|
1239
|
+
id: moved.id,
|
|
1240
|
+
from: found + moved.from,
|
|
1241
|
+
to: found + moved.to
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
tracked = null;
|
|
1270
1246
|
}
|
|
1271
|
-
return true;
|
|
1272
1247
|
}
|
|
1273
|
-
|
|
1248
|
+
for (const comment of restore) {
|
|
1249
|
+
const { comments: comments2 } = update2.startState.field(commentsState);
|
|
1250
|
+
const exists = comments2.some((c) => c.comment.id === comment.id && c.range.from < c.range.to);
|
|
1251
|
+
if (!exists) {
|
|
1252
|
+
const cursor = Cursor.getCursorFromRange(update2.state, comment);
|
|
1253
|
+
onUpdate(comment.id, cursor);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
})
|
|
1257
|
+
];
|
|
1258
|
+
};
|
|
1259
|
+
var mapTrackedComment = (comment, changes) => ({
|
|
1260
|
+
id: comment.id,
|
|
1261
|
+
from: changes.mapPos(comment.from, 1),
|
|
1262
|
+
to: changes.mapPos(comment.to, 1)
|
|
1263
|
+
});
|
|
1264
|
+
var restoreCommentEffect = StateEffect2.define({
|
|
1265
|
+
map: mapTrackedComment
|
|
1266
|
+
});
|
|
1267
|
+
var optionsFacet = Facet3.define({
|
|
1268
|
+
combine: (providers) => providers[0]
|
|
1269
|
+
});
|
|
1270
|
+
var createComment = (view) => {
|
|
1271
|
+
const options = view.state.facet(optionsFacet);
|
|
1272
|
+
const { from, to } = view.state.selection.main;
|
|
1273
|
+
if (from === to) {
|
|
1274
1274
|
return false;
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1275
|
+
}
|
|
1276
|
+
if (to === view.state.doc.length) {
|
|
1277
|
+
view.dispatch({
|
|
1278
|
+
changes: {
|
|
1279
|
+
from: to,
|
|
1280
|
+
insert: "\n"
|
|
1281
|
+
}
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
1285
|
+
from,
|
|
1286
|
+
to
|
|
1287
|
+
});
|
|
1288
|
+
if (cursor) {
|
|
1289
|
+
const id = options.onCreate?.(cursor, view.coordsAtPos(from));
|
|
1290
|
+
if (id) {
|
|
1291
|
+
view.dispatch({
|
|
1292
|
+
effects: setSelection.of({
|
|
1293
|
+
current: id
|
|
1294
|
+
}),
|
|
1295
|
+
selection: {
|
|
1296
|
+
anchor: to
|
|
1288
1297
|
}
|
|
1289
1298
|
});
|
|
1299
|
+
return true;
|
|
1290
1300
|
}
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
}, {
|
|
1298
|
-
decorations: (instance) => instance.bookmarks,
|
|
1299
|
-
provide: (plugin) => EditorView5.atomicRanges.of((view) => {
|
|
1300
|
-
return view.plugin(plugin)?.bookmarks || Decoration3.none;
|
|
1301
|
-
})
|
|
1302
|
-
});
|
|
1301
|
+
}
|
|
1302
|
+
return false;
|
|
1303
|
+
};
|
|
1304
|
+
var comments = (options = {}) => {
|
|
1305
|
+
const { key: shortcut = "meta-'" } = options;
|
|
1306
|
+
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1303
1307
|
return [
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
+
optionsFacet.of(options),
|
|
1309
|
+
commentsState,
|
|
1310
|
+
commentsDecorations,
|
|
1311
|
+
styles2,
|
|
1308
1312
|
//
|
|
1309
1313
|
// Keymap.
|
|
1310
1314
|
//
|
|
1311
1315
|
options.onCreate ? keymap3.of([
|
|
1312
1316
|
{
|
|
1313
|
-
key:
|
|
1314
|
-
run: callbackWrapper(
|
|
1317
|
+
key: shortcut,
|
|
1318
|
+
run: callbackWrapper(createComment)
|
|
1315
1319
|
}
|
|
1316
1320
|
]) : [],
|
|
1317
1321
|
//
|
|
@@ -1327,7 +1331,7 @@ var comments = (options = {}) => {
|
|
|
1327
1331
|
above: true,
|
|
1328
1332
|
create: () => {
|
|
1329
1333
|
const el = document.createElement("div");
|
|
1330
|
-
options.onHover
|
|
1334
|
+
options.onHover(el, shortcut);
|
|
1331
1335
|
return {
|
|
1332
1336
|
dom: el,
|
|
1333
1337
|
offset: {
|
|
@@ -1340,372 +1344,128 @@ var comments = (options = {}) => {
|
|
|
1340
1344
|
}
|
|
1341
1345
|
return null;
|
|
1342
1346
|
}, {
|
|
1343
|
-
|
|
1347
|
+
// TODO(burdon): Hide on change triggered immediately?
|
|
1348
|
+
// hideOnChange: true,
|
|
1344
1349
|
hoverTime: 1e3
|
|
1345
1350
|
}) : [],
|
|
1346
1351
|
//
|
|
1347
|
-
//
|
|
1348
|
-
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1352
|
+
// Track deleted ranges and update ranges for decorations.
|
|
1349
1353
|
//
|
|
1350
1354
|
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1351
|
-
|
|
1352
|
-
{
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
if (
|
|
1358
|
-
|
|
1359
|
-
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1360
|
-
log2.info("deleted comment", {
|
|
1361
|
-
thread: range.id
|
|
1362
|
-
}, {
|
|
1363
|
-
F: __dxlog_file3,
|
|
1364
|
-
L: 359,
|
|
1365
|
-
S: void 0,
|
|
1366
|
-
C: (f, a) => f(...a)
|
|
1367
|
-
});
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1370
|
-
if (from <= range.to) {
|
|
1371
|
-
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1372
|
-
Object.assign(range, newRange);
|
|
1373
|
-
mod = true;
|
|
1355
|
+
let mod = false;
|
|
1356
|
+
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1357
|
+
changes.iterChanges((from, to, from2, to2) => {
|
|
1358
|
+
comments2.forEach(({ comment, range }) => {
|
|
1359
|
+
if (from2 === to2) {
|
|
1360
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1361
|
+
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1362
|
+
options.onDelete?.(comment.id);
|
|
1374
1363
|
}
|
|
1375
|
-
}
|
|
1364
|
+
}
|
|
1365
|
+
if (from <= range.to) {
|
|
1366
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1367
|
+
Object.assign(range, newRange);
|
|
1368
|
+
mod = true;
|
|
1369
|
+
}
|
|
1370
|
+
});
|
|
1371
|
+
});
|
|
1372
|
+
if (mod) {
|
|
1373
|
+
view.dispatch({
|
|
1374
|
+
effects: setCommentState.of({
|
|
1375
|
+
comments: comments2,
|
|
1376
|
+
...value
|
|
1377
|
+
})
|
|
1376
1378
|
});
|
|
1377
|
-
if (mod) {
|
|
1378
|
-
view.dispatch({
|
|
1379
|
-
effects: setCommentState.of({
|
|
1380
|
-
active,
|
|
1381
|
-
ranges
|
|
1382
|
-
})
|
|
1383
|
-
});
|
|
1384
|
-
}
|
|
1385
1379
|
}
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1380
|
+
}),
|
|
1381
|
+
//
|
|
1382
|
+
// Track selection/proximity.
|
|
1383
|
+
//
|
|
1384
|
+
EditorView5.updateListener.of(({ view, state }) => {
|
|
1385
|
+
let min = Infinity;
|
|
1386
|
+
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
1387
|
+
const { head } = state.selection.main;
|
|
1388
|
+
const selection = {};
|
|
1389
|
+
comments2.forEach(({ comment, range }) => {
|
|
1390
|
+
if (head >= range.from && head <= range.to) {
|
|
1391
|
+
selection.current = comment.id;
|
|
1392
|
+
selection.closest = void 0;
|
|
1393
|
+
}
|
|
1394
|
+
if (!selection.current) {
|
|
1395
|
+
const d = Math.min(Math.abs(head - range.from), Math.abs(head - range.to));
|
|
1399
1396
|
if (d < min) {
|
|
1400
|
-
|
|
1397
|
+
selection.closest = comment.id;
|
|
1401
1398
|
min = d;
|
|
1402
1399
|
}
|
|
1403
|
-
});
|
|
1404
|
-
if (selected.active !== active || selected.closest !== closest) {
|
|
1405
|
-
view.dispatch({
|
|
1406
|
-
effects: setSelection.of(selected)
|
|
1407
|
-
});
|
|
1408
|
-
handleSelect({
|
|
1409
|
-
...selected,
|
|
1410
|
-
ranges: ranges.map((range) => ({
|
|
1411
|
-
...range,
|
|
1412
|
-
location: view.coordsAtPos(range.from)
|
|
1413
|
-
}))
|
|
1414
|
-
});
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
})
|
|
1418
|
-
];
|
|
1419
|
-
};
|
|
1420
|
-
var getCursorFromRange = (cursorConverter3, range) => {
|
|
1421
|
-
const from = cursorConverter3.toCursor(range.from);
|
|
1422
|
-
const to = cursorConverter3.toCursor(range.to, -1);
|
|
1423
|
-
return [
|
|
1424
|
-
from,
|
|
1425
|
-
to
|
|
1426
|
-
].join(":");
|
|
1427
|
-
};
|
|
1428
|
-
var getRangeFromCursor = (cursorConverter3, cursor) => {
|
|
1429
|
-
const parts = cursor.split(":");
|
|
1430
|
-
const from = cursorConverter3.fromCursor(parts[0]);
|
|
1431
|
-
const to = cursorConverter3.fromCursor(parts[1]);
|
|
1432
|
-
return from && to ? {
|
|
1433
|
-
from,
|
|
1434
|
-
to
|
|
1435
|
-
} : void 0;
|
|
1436
|
-
};
|
|
1437
|
-
|
|
1438
|
-
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1439
|
-
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin5, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1440
|
-
import get4 from "lodash.get";
|
|
1441
|
-
var styles4 = EditorView6.baseTheme({
|
|
1442
|
-
"& .cm-hr": {
|
|
1443
|
-
// TODO(burdon): ???
|
|
1444
|
-
// Note that block-level decorations should not have vertical margins,
|
|
1445
|
-
borderBottom: `1px solid ${get4(tokens, "extend.colors.neutral.200")}`
|
|
1446
|
-
}
|
|
1447
|
-
});
|
|
1448
|
-
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
1449
|
-
constructor(_pos) {
|
|
1450
|
-
super();
|
|
1451
|
-
this._pos = _pos;
|
|
1452
|
-
}
|
|
1453
|
-
eq(other) {
|
|
1454
|
-
return this._pos === other._pos;
|
|
1455
|
-
}
|
|
1456
|
-
toDOM(view) {
|
|
1457
|
-
const el = document.createElement("div");
|
|
1458
|
-
el.className = "cm-hr";
|
|
1459
|
-
return el;
|
|
1460
|
-
}
|
|
1461
|
-
};
|
|
1462
|
-
var placeholderMatcher = new MatchDecorator2({
|
|
1463
|
-
regexp: /^---$/g,
|
|
1464
|
-
decoration: (match, view, pos) => Decoration4.replace({
|
|
1465
|
-
widget: new HorizontalRuleWidget(pos)
|
|
1466
|
-
})
|
|
1467
|
-
});
|
|
1468
|
-
var hr = () => [
|
|
1469
|
-
styles4,
|
|
1470
|
-
ViewPlugin5.fromClass(class {
|
|
1471
|
-
constructor(view) {
|
|
1472
|
-
this.rules = placeholderMatcher.createDeco(view);
|
|
1473
|
-
}
|
|
1474
|
-
update(update4) {
|
|
1475
|
-
this.rules = placeholderMatcher.updateDeco(update4, this.rules);
|
|
1476
|
-
}
|
|
1477
|
-
}, {
|
|
1478
|
-
decorations: (instance) => instance.rules,
|
|
1479
|
-
// TODO(burdon): Is this really atomic (cursor can move into ---).
|
|
1480
|
-
provide: (plugin) => EditorView6.atomicRanges.of((view) => {
|
|
1481
|
-
return view.plugin(plugin)?.rules || Decoration4.none;
|
|
1482
|
-
})
|
|
1483
|
-
})
|
|
1484
|
-
];
|
|
1485
|
-
|
|
1486
|
-
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1487
|
-
import { syntaxTree } from "@codemirror/language";
|
|
1488
|
-
import { RangeSetBuilder, StateField as StateField3 } from "@codemirror/state";
|
|
1489
|
-
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1490
|
-
var image = (options = {}) => {
|
|
1491
|
-
return StateField3.define({
|
|
1492
|
-
create: (state) => update(state, options),
|
|
1493
|
-
update: (_, tr) => update(tr.state, options),
|
|
1494
|
-
provide: (field) => EditorView7.decorations.from(field)
|
|
1495
|
-
});
|
|
1496
|
-
};
|
|
1497
|
-
var update = (state, options) => {
|
|
1498
|
-
const builder = new RangeSetBuilder();
|
|
1499
|
-
const cursor = state.selection.main.head;
|
|
1500
|
-
syntaxTree(state).iterate({
|
|
1501
|
-
enter: (node) => {
|
|
1502
|
-
if (node.name === "Image") {
|
|
1503
|
-
const urlNode = node.node.getChild("URL");
|
|
1504
|
-
if (urlNode) {
|
|
1505
|
-
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1506
|
-
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1507
|
-
builder.add(hide ? node.from : node.to, node.to, Decoration5.replace({
|
|
1508
|
-
block: true,
|
|
1509
|
-
widget: new ImageWidget(url)
|
|
1510
|
-
}));
|
|
1511
|
-
}
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
});
|
|
1515
|
-
return builder.finish();
|
|
1516
|
-
};
|
|
1517
|
-
var ImageWidget = class extends WidgetType4 {
|
|
1518
|
-
constructor(_url) {
|
|
1519
|
-
super();
|
|
1520
|
-
this._url = _url;
|
|
1521
|
-
}
|
|
1522
|
-
// TODO(burdon): Does this need to be unique for each position?
|
|
1523
|
-
eq(other) {
|
|
1524
|
-
return this._url === other._url;
|
|
1525
|
-
}
|
|
1526
|
-
toDOM(view) {
|
|
1527
|
-
const img = document.createElement("img");
|
|
1528
|
-
img.setAttribute("src", this._url);
|
|
1529
|
-
img.setAttribute("class", "cm-image");
|
|
1530
|
-
return img;
|
|
1531
|
-
}
|
|
1532
|
-
};
|
|
1533
|
-
|
|
1534
|
-
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1535
|
-
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1536
|
-
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField4 } from "@codemirror/state";
|
|
1537
|
-
import { Decoration as Decoration6, EditorView as EditorView8, WidgetType as WidgetType5, hoverTooltip as hoverTooltip2 } from "@codemirror/view";
|
|
1538
|
-
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1539
|
-
var markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
|
|
1540
|
-
var link = (options = {}) => {
|
|
1541
|
-
const extensions = [
|
|
1542
|
-
StateField4.define({
|
|
1543
|
-
create: (state) => update2(state, options),
|
|
1544
|
-
update: (_, tr) => update2(tr.state, options),
|
|
1545
|
-
provide: (field) => EditorView8.decorations.from(field)
|
|
1546
|
-
})
|
|
1547
|
-
];
|
|
1548
|
-
if (options.onHover) {
|
|
1549
|
-
extensions.push(
|
|
1550
|
-
// https://codemirror.net/examples/tooltip
|
|
1551
|
-
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1552
|
-
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1553
|
-
hoverTooltip2((view, pos) => {
|
|
1554
|
-
const { from, text } = view.state.doc.lineAt(pos);
|
|
1555
|
-
const p = pos - from;
|
|
1556
|
-
let idx = 0;
|
|
1557
|
-
let match;
|
|
1558
|
-
do {
|
|
1559
|
-
match = text.substring(idx).match(markdownLinkRegexp);
|
|
1560
|
-
if (!match) {
|
|
1561
|
-
match = void 0;
|
|
1562
|
-
break;
|
|
1563
|
-
}
|
|
1564
|
-
idx = text.indexOf(match[0]);
|
|
1565
|
-
if (p >= idx && p < idx + match[0].length) {
|
|
1566
|
-
break;
|
|
1567
|
-
}
|
|
1568
|
-
idx += match[0].length;
|
|
1569
|
-
} while (true);
|
|
1570
|
-
if (!match) {
|
|
1571
|
-
return null;
|
|
1572
1400
|
}
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
pos: idx + from,
|
|
1576
|
-
end: idx + from + match[0].length,
|
|
1577
|
-
above: true,
|
|
1578
|
-
create: () => {
|
|
1579
|
-
const el = document.createElement("div");
|
|
1580
|
-
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1581
|
-
options.onHover(el, url);
|
|
1582
|
-
return {
|
|
1583
|
-
dom: el,
|
|
1584
|
-
offset: {
|
|
1585
|
-
x: 0,
|
|
1586
|
-
y: 4
|
|
1587
|
-
}
|
|
1588
|
-
};
|
|
1589
|
-
}
|
|
1590
|
-
};
|
|
1591
|
-
})
|
|
1592
|
-
);
|
|
1593
|
-
}
|
|
1594
|
-
return extensions;
|
|
1595
|
-
};
|
|
1596
|
-
var LinkButton = class extends WidgetType5 {
|
|
1597
|
-
constructor(_pos, _url, _onAttach) {
|
|
1598
|
-
super();
|
|
1599
|
-
this._pos = _pos;
|
|
1600
|
-
this._url = _url;
|
|
1601
|
-
this._onAttach = _onAttach;
|
|
1602
|
-
}
|
|
1603
|
-
eq(other) {
|
|
1604
|
-
return this._pos === other._pos && this._url === other._url;
|
|
1605
|
-
}
|
|
1606
|
-
toDOM(view) {
|
|
1607
|
-
const el = document.createElement("span");
|
|
1608
|
-
this._onAttach(el, this._url);
|
|
1609
|
-
return el;
|
|
1610
|
-
}
|
|
1611
|
-
};
|
|
1612
|
-
var LinkText = class extends WidgetType5 {
|
|
1613
|
-
constructor(_text, _url) {
|
|
1614
|
-
super();
|
|
1615
|
-
this._text = _text;
|
|
1616
|
-
this._url = _url;
|
|
1617
|
-
}
|
|
1618
|
-
eq(other) {
|
|
1619
|
-
return this._url === other._url;
|
|
1620
|
-
}
|
|
1621
|
-
toDOM(view) {
|
|
1622
|
-
const link2 = document.createElement("a");
|
|
1623
|
-
link2.setAttribute("class", "cm-link");
|
|
1624
|
-
link2.textContent = this._text;
|
|
1625
|
-
if (this._url) {
|
|
1626
|
-
link2.setAttribute("rel", "noreferrer");
|
|
1627
|
-
link2.setAttribute("target", "_blank");
|
|
1628
|
-
link2.href = this._url;
|
|
1629
|
-
} else {
|
|
1630
|
-
link2.onclick = () => {
|
|
1401
|
+
});
|
|
1402
|
+
if (selection.current !== current || selection.closest !== closest) {
|
|
1631
1403
|
view.dispatch({
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1404
|
+
effects: setSelection.of(selection)
|
|
1405
|
+
});
|
|
1406
|
+
handleSelect({
|
|
1407
|
+
selection,
|
|
1408
|
+
comments: comments2.map(({ comment, range }) => ({
|
|
1409
|
+
comment,
|
|
1410
|
+
range,
|
|
1411
|
+
location: view.coordsAtPos(range.from)
|
|
1412
|
+
}))
|
|
1635
1413
|
});
|
|
1636
|
-
};
|
|
1637
|
-
}
|
|
1638
|
-
return link2;
|
|
1639
|
-
}
|
|
1640
|
-
};
|
|
1641
|
-
var update2 = (state, options) => {
|
|
1642
|
-
const builder = new RangeSetBuilder2();
|
|
1643
|
-
const cursor = state.selection.main.head;
|
|
1644
|
-
syntaxTree2(state).iterate({
|
|
1645
|
-
enter: (node) => {
|
|
1646
|
-
if (node.name === "Link") {
|
|
1647
|
-
const marks2 = node.node.getChildren("LinkMark");
|
|
1648
|
-
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
1649
|
-
const urlNode = node.node.getChild("URL");
|
|
1650
|
-
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
1651
|
-
if (!url) {
|
|
1652
|
-
return false;
|
|
1653
|
-
}
|
|
1654
|
-
if (state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1655
|
-
builder.add(node.from, node.to, Decoration6.replace({
|
|
1656
|
-
widget: new LinkText(text, options.link ? url : void 0)
|
|
1657
|
-
}));
|
|
1658
|
-
}
|
|
1659
|
-
if (options.onRender) {
|
|
1660
|
-
builder.add(node.to, node.to, Decoration6.replace({
|
|
1661
|
-
widget: new LinkButton(node.from, url, options.onRender)
|
|
1662
|
-
}));
|
|
1663
|
-
}
|
|
1664
|
-
return false;
|
|
1665
1414
|
}
|
|
1415
|
+
}),
|
|
1416
|
+
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
1417
|
+
];
|
|
1418
|
+
};
|
|
1419
|
+
var useComments = (view, comments2 = []) => {
|
|
1420
|
+
useEffect(() => {
|
|
1421
|
+
if (view) {
|
|
1422
|
+
view.dispatch({
|
|
1423
|
+
effects: setComments.of(comments2)
|
|
1424
|
+
});
|
|
1666
1425
|
}
|
|
1667
|
-
}
|
|
1668
|
-
|
|
1426
|
+
}, [
|
|
1427
|
+
view,
|
|
1428
|
+
comments2
|
|
1429
|
+
]);
|
|
1669
1430
|
};
|
|
1670
1431
|
|
|
1671
1432
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1672
|
-
import { EditorView as
|
|
1433
|
+
import { EditorView as EditorView6 } from "@codemirror/view";
|
|
1673
1434
|
var listener = ({ onFocus, onChange }) => {
|
|
1674
1435
|
const extensions = [];
|
|
1675
|
-
onFocus && extensions.push(
|
|
1436
|
+
onFocus && extensions.push(EditorView6.focusChangeEffect.of((_, focused) => {
|
|
1676
1437
|
onFocus(focused);
|
|
1677
1438
|
return null;
|
|
1678
1439
|
}));
|
|
1679
|
-
onChange && extensions.push(
|
|
1680
|
-
onChange(
|
|
1440
|
+
onChange && extensions.push(EditorView6.updateListener.of((update2) => {
|
|
1441
|
+
onChange(update2.state.doc.toString());
|
|
1681
1442
|
}));
|
|
1682
1443
|
return extensions;
|
|
1683
1444
|
};
|
|
1684
1445
|
|
|
1685
1446
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1686
1447
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1687
|
-
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1688
|
-
import { markdownLanguage as
|
|
1448
|
+
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1449
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1689
1450
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1690
1451
|
import { languages } from "@codemirror/language-data";
|
|
1691
1452
|
import { searchKeymap } from "@codemirror/search";
|
|
1692
1453
|
import { EditorState } from "@codemirror/state";
|
|
1693
1454
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1694
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1455
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView7, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1456
|
+
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
|
1695
1457
|
|
|
1696
1458
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1697
|
-
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
1459
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1698
1460
|
import { HighlightStyle } from "@codemirror/language";
|
|
1699
1461
|
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1700
1462
|
import { Table } from "@lezer/markdown";
|
|
1701
|
-
import get5 from "lodash.get";
|
|
1702
1463
|
var markdownTags = {
|
|
1703
1464
|
Blockquote: Tag.define(),
|
|
1704
1465
|
CodeMark: Tag.define(),
|
|
1705
1466
|
CodeText: Tag.define(),
|
|
1706
1467
|
EmphasisMark: Tag.define(),
|
|
1707
1468
|
HeaderMark: Tag.define(),
|
|
1708
|
-
// HorizontalRule: Tag.define(),
|
|
1709
1469
|
InlineCode: Tag.define(),
|
|
1710
1470
|
LinkLabel: Tag.define(),
|
|
1711
1471
|
LinkReference: Tag.define(),
|
|
@@ -1790,7 +1550,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1790
1550
|
markdownTags.QuoteMark,
|
|
1791
1551
|
markdownTags.EmphasisMark
|
|
1792
1552
|
],
|
|
1793
|
-
class:
|
|
1553
|
+
class: mark
|
|
1794
1554
|
},
|
|
1795
1555
|
// E.g., code block language (after ```).
|
|
1796
1556
|
{
|
|
@@ -1798,7 +1558,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1798
1558
|
tags.function(tags.variableName),
|
|
1799
1559
|
tags.labelName
|
|
1800
1560
|
],
|
|
1801
|
-
class:
|
|
1561
|
+
class: codeMark
|
|
1802
1562
|
},
|
|
1803
1563
|
{
|
|
1804
1564
|
tag: [
|
|
@@ -1809,27 +1569,27 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1809
1569
|
// Headings.
|
|
1810
1570
|
{
|
|
1811
1571
|
tag: tags.heading1,
|
|
1812
|
-
class: heading(1
|
|
1572
|
+
class: heading(1)
|
|
1813
1573
|
},
|
|
1814
1574
|
{
|
|
1815
1575
|
tag: tags.heading2,
|
|
1816
|
-
class: heading(2
|
|
1576
|
+
class: heading(2)
|
|
1817
1577
|
},
|
|
1818
1578
|
{
|
|
1819
1579
|
tag: tags.heading3,
|
|
1820
|
-
class: heading(3
|
|
1580
|
+
class: heading(3)
|
|
1821
1581
|
},
|
|
1822
1582
|
{
|
|
1823
1583
|
tag: tags.heading4,
|
|
1824
|
-
class: heading(4
|
|
1584
|
+
class: heading(4)
|
|
1825
1585
|
},
|
|
1826
1586
|
{
|
|
1827
1587
|
tag: tags.heading5,
|
|
1828
|
-
class: heading(5
|
|
1588
|
+
class: heading(5)
|
|
1829
1589
|
},
|
|
1830
1590
|
{
|
|
1831
1591
|
tag: tags.heading6,
|
|
1832
|
-
class: heading(6
|
|
1592
|
+
class: heading(6)
|
|
1833
1593
|
},
|
|
1834
1594
|
// Emphasis.
|
|
1835
1595
|
{
|
|
@@ -1855,7 +1615,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1855
1615
|
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
1856
1616
|
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
1857
1617
|
// the code, but all other CSS properties will be inherited.
|
|
1858
|
-
// IMPORTANT: Therefore, the fenced code block will use the base editor font.
|
|
1618
|
+
// IMPORTANT: Therefore, the fenced code block will use the base editor font unless changed by an extension.
|
|
1859
1619
|
{
|
|
1860
1620
|
tag: [
|
|
1861
1621
|
markdownTags.CodeText,
|
|
@@ -1869,12 +1629,6 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1869
1629
|
],
|
|
1870
1630
|
class: blockquote
|
|
1871
1631
|
},
|
|
1872
|
-
// TODO(burdon): Replace with extension.
|
|
1873
|
-
// {
|
|
1874
|
-
// tag: [markdownTags.HorizontalRule],
|
|
1875
|
-
// class: mx(horizontalRule, readonly && '-indent-[100rem]'),
|
|
1876
|
-
// },
|
|
1877
|
-
// TODO(burdon): Only if being edited.
|
|
1878
1632
|
{
|
|
1879
1633
|
tag: [
|
|
1880
1634
|
markdownTags.TableCell
|
|
@@ -1882,27 +1636,27 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1882
1636
|
class: "font-mono"
|
|
1883
1637
|
}
|
|
1884
1638
|
], {
|
|
1885
|
-
scope:
|
|
1639
|
+
scope: markdownLanguage2,
|
|
1886
1640
|
all: {
|
|
1887
|
-
fontFamily:
|
|
1641
|
+
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
1888
1642
|
}
|
|
1889
1643
|
});
|
|
1890
1644
|
};
|
|
1891
1645
|
|
|
1892
1646
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1893
|
-
var
|
|
1647
|
+
var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => {
|
|
1894
1648
|
return [
|
|
1649
|
+
lineWrapping && EditorView7.lineWrapping,
|
|
1895
1650
|
EditorState.allowMultipleSelections.of(true),
|
|
1896
1651
|
EditorState.tabSize.of(2),
|
|
1897
|
-
|
|
1898
|
-
customKeymap(),
|
|
1652
|
+
// https://github.com/codemirror/basic-setup
|
|
1899
1653
|
bracketMatching2(),
|
|
1900
1654
|
closeBrackets2(),
|
|
1901
1655
|
crosshairCursor(),
|
|
1902
1656
|
dropCursor(),
|
|
1903
1657
|
drawSelection2(),
|
|
1904
|
-
|
|
1905
|
-
|
|
1658
|
+
highlightActiveLine2(),
|
|
1659
|
+
history2(),
|
|
1906
1660
|
indentOnInput(),
|
|
1907
1661
|
_placeholder && placeholder2(_placeholder),
|
|
1908
1662
|
// Main extension.
|
|
@@ -1914,7 +1668,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1914
1668
|
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
1915
1669
|
// https://github.github.com/gfm
|
|
1916
1670
|
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
1917
|
-
base:
|
|
1671
|
+
base: markdownLanguage3,
|
|
1918
1672
|
// Languages for syntax highlighting fenced code blocks.
|
|
1919
1673
|
codeLanguages: languages,
|
|
1920
1674
|
// Parser extensions.
|
|
@@ -1926,81 +1680,620 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1926
1680
|
// https://github.com/codemirror/theme-one-dark
|
|
1927
1681
|
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
1928
1682
|
// Custom styles.
|
|
1929
|
-
syntaxHighlighting2(markdownHighlightStyle(
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
]);
|
|
1944
|
-
|
|
1945
|
-
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
1946
|
-
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
1947
|
-
var mention = ({ onSearch }) => {
|
|
1948
|
-
return autocompletion2({
|
|
1949
|
-
closeOnBlur: false,
|
|
1950
|
-
override: [
|
|
1951
|
-
(context) => {
|
|
1952
|
-
const match = context.matchBefore(/@(\w+)?/);
|
|
1953
|
-
if (!match || match.from === match.to && !context.explicit) {
|
|
1954
|
-
return null;
|
|
1955
|
-
}
|
|
1956
|
-
console.log(match);
|
|
1957
|
-
return {
|
|
1958
|
-
from: match.from,
|
|
1959
|
-
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
1960
|
-
label: `@${value}`
|
|
1961
|
-
}))
|
|
1962
|
-
};
|
|
1963
|
-
}
|
|
1964
|
-
]
|
|
1965
|
-
});
|
|
1683
|
+
syntaxHighlighting2(markdownHighlightStyle()),
|
|
1684
|
+
keymap4.of([
|
|
1685
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
1686
|
+
indentWithTab,
|
|
1687
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
1688
|
+
...closeBracketsKeymap,
|
|
1689
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
1690
|
+
...historyKeymap,
|
|
1691
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
1692
|
+
...searchKeymap,
|
|
1693
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
1694
|
+
...standardKeymap
|
|
1695
|
+
])
|
|
1696
|
+
].filter(isNotFalsy2);
|
|
1966
1697
|
};
|
|
1967
1698
|
|
|
1968
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1969
|
-
|
|
1970
|
-
|
|
1699
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/code.ts
|
|
1700
|
+
import { syntaxTree } from "@codemirror/language";
|
|
1701
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1702
|
+
import { ViewPlugin as ViewPlugin3, EditorView as EditorView8, Decoration as Decoration3, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1703
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1704
|
+
var styles3 = EditorView8.baseTheme({
|
|
1705
|
+
"& .cm-code": {
|
|
1706
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1707
|
+
},
|
|
1708
|
+
"& .cm-codeblock": {
|
|
1709
|
+
width: "100%",
|
|
1710
|
+
paddingInline: "1rem !important",
|
|
1711
|
+
position: "relative",
|
|
1712
|
+
"&::after": {
|
|
1713
|
+
content: '""',
|
|
1714
|
+
position: "absolute",
|
|
1715
|
+
inset: 0
|
|
1716
|
+
}
|
|
1717
|
+
},
|
|
1718
|
+
"&light .cm-codeblock": {
|
|
1719
|
+
"&::after": {
|
|
1720
|
+
background: getToken("extend.semanticColors.input.light"),
|
|
1721
|
+
mixBlendMode: "darken"
|
|
1722
|
+
}
|
|
1723
|
+
},
|
|
1724
|
+
"&dark .cm-codeblock": {
|
|
1725
|
+
"&::after": {
|
|
1726
|
+
background: getToken("extend.semanticColors.input.dark"),
|
|
1727
|
+
mixBlendMode: "lighten"
|
|
1728
|
+
}
|
|
1729
|
+
},
|
|
1730
|
+
"& .cm-codeblock-first": {
|
|
1731
|
+
display: "inline-block",
|
|
1732
|
+
"&::after": {
|
|
1733
|
+
borderTopLeftRadius: ".5rem",
|
|
1734
|
+
borderTopRightRadius: ".5rem"
|
|
1735
|
+
}
|
|
1736
|
+
},
|
|
1737
|
+
"& .cm-codeblock-last": {
|
|
1738
|
+
display: "inline-block",
|
|
1739
|
+
"&::after": {
|
|
1740
|
+
borderBottomLeftRadius: ".5rem",
|
|
1741
|
+
borderBottomRightRadius: ".5rem"
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
});
|
|
1745
|
+
var getLineRange = (lines, from, to) => {
|
|
1746
|
+
const start = lines.findIndex((line) => line.from >= from);
|
|
1747
|
+
const end = lines.findIndex((line) => line.to >= to);
|
|
1748
|
+
return [
|
|
1749
|
+
start,
|
|
1750
|
+
end
|
|
1751
|
+
];
|
|
1971
1752
|
};
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
}
|
|
1753
|
+
var LineWidget = class extends WidgetType2 {
|
|
1754
|
+
constructor(_className) {
|
|
1755
|
+
super();
|
|
1756
|
+
this._className = _className;
|
|
1757
|
+
}
|
|
1758
|
+
toDOM() {
|
|
1759
|
+
const el = document.createElement("span");
|
|
1760
|
+
el.innerHTML = " ";
|
|
1761
|
+
el.className = mx2("cm-code cm-codeblock", this._className);
|
|
1762
|
+
return el;
|
|
1763
|
+
}
|
|
1983
1764
|
};
|
|
1984
|
-
var
|
|
1985
|
-
|
|
1765
|
+
var top = new LineWidget("cm-codeblock-first");
|
|
1766
|
+
var bottom = new LineWidget("cm-codeblock-last");
|
|
1767
|
+
var buildDecorations = (view) => {
|
|
1768
|
+
const builder = new RangeSetBuilder();
|
|
1769
|
+
const { state } = view;
|
|
1770
|
+
const blocks = view.viewportLineBlocks;
|
|
1986
1771
|
const cursor = state.selection.main.head;
|
|
1987
|
-
const
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
1772
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1773
|
+
syntaxTree(state).iterate({
|
|
1774
|
+
enter: (node) => {
|
|
1775
|
+
if (node.name === "FencedCode") {
|
|
1776
|
+
const edit = !view.state.readOnly && cursor >= node.from && cursor <= node.to;
|
|
1777
|
+
const range = getLineRange(blocks, node.from, node.to);
|
|
1778
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1779
|
+
const block = blocks[i];
|
|
1780
|
+
if (!edit && (i === range[0] || i === range[1])) {
|
|
1781
|
+
builder.add(block.from, block.to, Decoration3.replace({
|
|
1782
|
+
widget: i === range[0] ? top : bottom
|
|
1783
|
+
}));
|
|
1784
|
+
} else {
|
|
1785
|
+
builder.add(block.from, block.from, Decoration3.line({
|
|
1786
|
+
class: mx2("cm-code cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1787
|
+
}));
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
2002
1790
|
}
|
|
2003
|
-
|
|
1791
|
+
},
|
|
1792
|
+
from,
|
|
1793
|
+
to
|
|
1794
|
+
});
|
|
1795
|
+
}
|
|
1796
|
+
return builder.finish();
|
|
1797
|
+
};
|
|
1798
|
+
var code2 = () => {
|
|
1799
|
+
return [
|
|
1800
|
+
ViewPlugin3.fromClass(class {
|
|
1801
|
+
constructor(view) {
|
|
1802
|
+
this.decorations = buildDecorations(view);
|
|
1803
|
+
}
|
|
1804
|
+
update(update2) {
|
|
1805
|
+
this.decorations = buildDecorations(update2.view);
|
|
1806
|
+
}
|
|
1807
|
+
}, {
|
|
1808
|
+
decorations: (value) => value.decorations
|
|
1809
|
+
}),
|
|
1810
|
+
styles3
|
|
1811
|
+
];
|
|
1812
|
+
};
|
|
1813
|
+
|
|
1814
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
1815
|
+
import { snippet } from "@codemirror/autocomplete";
|
|
1816
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1817
|
+
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1818
|
+
import { Decoration as Decoration4, keymap as keymap5, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1819
|
+
var setHeading = (level) => (view) => {
|
|
1820
|
+
const { selection: { ranges }, doc } = view.state;
|
|
1821
|
+
const changes = [];
|
|
1822
|
+
for (const range of ranges) {
|
|
1823
|
+
const { number } = doc.lineAt(range.anchor);
|
|
1824
|
+
const { from, to } = doc.line(number);
|
|
1825
|
+
const line = doc.sliceString(from, to);
|
|
1826
|
+
const [_, marks, spaces] = line.match(/(#+)(\s+)/) ?? [];
|
|
1827
|
+
const current = marks?.length ?? 0;
|
|
1828
|
+
if (level !== current) {
|
|
1829
|
+
changes.push({
|
|
1830
|
+
from,
|
|
1831
|
+
to: from + current + (spaces?.length ?? 0),
|
|
1832
|
+
insert: "#".repeat(level) + (level > 0 ? " " : "")
|
|
1833
|
+
});
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
if (changes.length) {
|
|
1837
|
+
view.dispatch({
|
|
1838
|
+
changes
|
|
1839
|
+
});
|
|
1840
|
+
}
|
|
1841
|
+
return true;
|
|
1842
|
+
};
|
|
1843
|
+
var toggleStyle = (mark2) => (view) => {
|
|
1844
|
+
const { ranges } = view.state.selection;
|
|
1845
|
+
for (const range of ranges) {
|
|
1846
|
+
if (range.from === range.to) {
|
|
1847
|
+
return false;
|
|
1848
|
+
}
|
|
1849
|
+
view.dispatch({
|
|
1850
|
+
changes: [
|
|
1851
|
+
{
|
|
1852
|
+
from: range.from,
|
|
1853
|
+
insert: mark2
|
|
1854
|
+
},
|
|
1855
|
+
{
|
|
1856
|
+
from: range.to,
|
|
1857
|
+
insert: mark2
|
|
1858
|
+
}
|
|
1859
|
+
]
|
|
1860
|
+
});
|
|
1861
|
+
}
|
|
1862
|
+
return true;
|
|
1863
|
+
};
|
|
1864
|
+
var snippets = {
|
|
1865
|
+
codeblock: snippet([
|
|
1866
|
+
"```#{lang}",
|
|
1867
|
+
" #{}",
|
|
1868
|
+
"```"
|
|
1869
|
+
].join("\n")),
|
|
1870
|
+
table: snippet([
|
|
1871
|
+
"| #{col1} | #{col2} |",
|
|
1872
|
+
"| ---- | ---- |",
|
|
1873
|
+
"| #{val1} | #{val2} |",
|
|
1874
|
+
"| #{val3} | #{val4} |"
|
|
1875
|
+
].join("\n"))
|
|
1876
|
+
};
|
|
1877
|
+
var insertCodeblock = (view) => {
|
|
1878
|
+
const { selection: { main }, doc } = view.state;
|
|
1879
|
+
const { number } = doc.lineAt(main.anchor);
|
|
1880
|
+
const { from } = doc.line(number);
|
|
1881
|
+
snippets.codeblock(view, null, from, from);
|
|
1882
|
+
};
|
|
1883
|
+
var insertTable = (view) => {
|
|
1884
|
+
const { selection: { main }, doc } = view.state;
|
|
1885
|
+
const { number } = doc.lineAt(main.anchor);
|
|
1886
|
+
const { from } = doc.line(number);
|
|
1887
|
+
snippets.table(view, null, from, from);
|
|
1888
|
+
};
|
|
1889
|
+
var toggleBold = toggleStyle("**");
|
|
1890
|
+
var toggleItalic = toggleStyle("_");
|
|
1891
|
+
var toggleStrikethrough = toggleStyle("~~");
|
|
1892
|
+
var toggleList = (view) => {
|
|
1893
|
+
};
|
|
1894
|
+
var formatting = (options = {}) => {
|
|
1895
|
+
return [
|
|
1896
|
+
keymap5.of([
|
|
1897
|
+
{
|
|
1898
|
+
key: "meta-b",
|
|
1899
|
+
run: toggleBold
|
|
1900
|
+
}
|
|
1901
|
+
]),
|
|
1902
|
+
styling()
|
|
1903
|
+
];
|
|
1904
|
+
};
|
|
1905
|
+
var styling = () => {
|
|
1906
|
+
const buildDecorations7 = (view) => {
|
|
1907
|
+
const builder = new RangeSetBuilder2();
|
|
1908
|
+
const { state } = view;
|
|
1909
|
+
const cursor = state.selection.main.head;
|
|
1910
|
+
const replace = (node, marks) => {
|
|
1911
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
1912
|
+
for (const mark2 of marks) {
|
|
1913
|
+
builder.add(mark2.from, mark2.to, Decoration4.replace({}));
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
};
|
|
1917
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1918
|
+
syntaxTree2(state).iterate({
|
|
1919
|
+
enter: (node) => {
|
|
1920
|
+
switch (node.name) {
|
|
1921
|
+
case "Emphasis":
|
|
1922
|
+
case "StrongEmphasis": {
|
|
1923
|
+
const marks = node.node.getChildren("EmphasisMark");
|
|
1924
|
+
replace(node, marks);
|
|
1925
|
+
break;
|
|
1926
|
+
}
|
|
1927
|
+
case "Strikethrough": {
|
|
1928
|
+
const marks = node.node.getChildren("StrikethroughMark");
|
|
1929
|
+
replace(node, marks);
|
|
1930
|
+
break;
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
},
|
|
1934
|
+
from,
|
|
1935
|
+
to
|
|
1936
|
+
});
|
|
1937
|
+
}
|
|
1938
|
+
return builder.finish();
|
|
1939
|
+
};
|
|
1940
|
+
return [
|
|
1941
|
+
ViewPlugin4.fromClass(class {
|
|
1942
|
+
constructor(view) {
|
|
1943
|
+
this.decorations = buildDecorations7(view);
|
|
1944
|
+
}
|
|
1945
|
+
update(update2) {
|
|
1946
|
+
this.decorations = buildDecorations7(update2.view);
|
|
1947
|
+
}
|
|
1948
|
+
}, {
|
|
1949
|
+
decorations: (value) => value.decorations
|
|
1950
|
+
})
|
|
1951
|
+
];
|
|
1952
|
+
};
|
|
1953
|
+
|
|
1954
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
1955
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1956
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
1957
|
+
import { Decoration as Decoration5, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
1958
|
+
var buildDecorations2 = (view) => {
|
|
1959
|
+
const builder = new RangeSetBuilder3();
|
|
1960
|
+
const { state } = view;
|
|
1961
|
+
const cursor = state.selection.main.head;
|
|
1962
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1963
|
+
syntaxTree3(state).iterate({
|
|
1964
|
+
enter: (node) => {
|
|
1965
|
+
switch (node.name) {
|
|
1966
|
+
case "ATXHeading1":
|
|
1967
|
+
case "ATXHeading2":
|
|
1968
|
+
case "ATXHeading3":
|
|
1969
|
+
case "ATXHeading4":
|
|
1970
|
+
case "ATXHeading5":
|
|
1971
|
+
case "ATXHeading6": {
|
|
1972
|
+
const mark2 = node.node.getChild("HeaderMark");
|
|
1973
|
+
if (mark2) {
|
|
1974
|
+
if (!view.hasFocus || view.state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1975
|
+
builder.add(mark2.from, mark2.to + 1, Decoration5.replace({}));
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
},
|
|
1981
|
+
from,
|
|
1982
|
+
to
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
return builder.finish();
|
|
1986
|
+
};
|
|
1987
|
+
var heading2 = () => {
|
|
1988
|
+
return [
|
|
1989
|
+
ViewPlugin5.fromClass(class {
|
|
1990
|
+
constructor(view) {
|
|
1991
|
+
this.decorations = buildDecorations2(view);
|
|
1992
|
+
}
|
|
1993
|
+
update(update2) {
|
|
1994
|
+
this.decorations = buildDecorations2(update2.view);
|
|
1995
|
+
}
|
|
1996
|
+
}, {
|
|
1997
|
+
decorations: (value) => value.decorations
|
|
1998
|
+
})
|
|
1999
|
+
];
|
|
2000
|
+
};
|
|
2001
|
+
|
|
2002
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
2003
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2004
|
+
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
2005
|
+
import { Decoration as Decoration6, EditorView as EditorView9, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
2006
|
+
var styles4 = EditorView9.baseTheme({
|
|
2007
|
+
"& .cm-hr": {
|
|
2008
|
+
// Note that block-level decorations should not have vertical margins,
|
|
2009
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
2010
|
+
}
|
|
2011
|
+
});
|
|
2012
|
+
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
2013
|
+
toDOM() {
|
|
2014
|
+
const el = document.createElement("div");
|
|
2015
|
+
el.className = "cm-hr";
|
|
2016
|
+
return el;
|
|
2017
|
+
}
|
|
2018
|
+
};
|
|
2019
|
+
var decoration = Decoration6.replace({
|
|
2020
|
+
widget: new HorizontalRuleWidget()
|
|
2021
|
+
});
|
|
2022
|
+
var buildDecorations3 = (view) => {
|
|
2023
|
+
const builder = new RangeSetBuilder4();
|
|
2024
|
+
const { state } = view;
|
|
2025
|
+
const cursor = state.selection.main.head;
|
|
2026
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2027
|
+
syntaxTree4(state).iterate({
|
|
2028
|
+
enter: (node) => {
|
|
2029
|
+
if (node.name === "HorizontalRule") {
|
|
2030
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
2031
|
+
builder.add(node.from, node.to, decoration);
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
},
|
|
2035
|
+
from,
|
|
2036
|
+
to
|
|
2037
|
+
});
|
|
2038
|
+
}
|
|
2039
|
+
return builder.finish();
|
|
2040
|
+
};
|
|
2041
|
+
var hr = () => {
|
|
2042
|
+
return [
|
|
2043
|
+
ViewPlugin6.fromClass(class {
|
|
2044
|
+
constructor(view) {
|
|
2045
|
+
this.decorations = buildDecorations3(view);
|
|
2046
|
+
}
|
|
2047
|
+
update(update2) {
|
|
2048
|
+
this.decorations = buildDecorations3(update2.view);
|
|
2049
|
+
}
|
|
2050
|
+
}, {
|
|
2051
|
+
decorations: (value) => value.decorations
|
|
2052
|
+
}),
|
|
2053
|
+
styles4
|
|
2054
|
+
];
|
|
2055
|
+
};
|
|
2056
|
+
|
|
2057
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
2058
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
2059
|
+
import { StateField as StateField3 } from "@codemirror/state";
|
|
2060
|
+
import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
2061
|
+
var image = (options = {}) => {
|
|
2062
|
+
return StateField3.define({
|
|
2063
|
+
create: (state) => {
|
|
2064
|
+
return Decoration7.set(buildDecorations4(0, state.doc.length, state));
|
|
2065
|
+
},
|
|
2066
|
+
update: (value, tr) => {
|
|
2067
|
+
if (!tr.docChanged && !tr.selection) {
|
|
2068
|
+
return value;
|
|
2069
|
+
}
|
|
2070
|
+
const cursor = tr.state.selection.main.head;
|
|
2071
|
+
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
2072
|
+
let from = Math.min(cursor, oldCursor);
|
|
2073
|
+
let to = Math.max(cursor, oldCursor);
|
|
2074
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
2075
|
+
from = Math.min(from, fromB);
|
|
2076
|
+
to = Math.max(to, toB);
|
|
2077
|
+
});
|
|
2078
|
+
from = tr.state.doc.lineAt(from).from;
|
|
2079
|
+
to = tr.state.doc.lineAt(to).to;
|
|
2080
|
+
return value.map(tr.changes).update({
|
|
2081
|
+
filterFrom: from,
|
|
2082
|
+
filterTo: to,
|
|
2083
|
+
filter: () => false,
|
|
2084
|
+
add: buildDecorations4(from, to, tr.state)
|
|
2085
|
+
});
|
|
2086
|
+
},
|
|
2087
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
2088
|
+
});
|
|
2089
|
+
};
|
|
2090
|
+
var buildDecorations4 = (from, to, state) => {
|
|
2091
|
+
const decorations = [];
|
|
2092
|
+
const cursor = state.selection.main.head;
|
|
2093
|
+
syntaxTree5(state).iterate({
|
|
2094
|
+
enter: (node) => {
|
|
2095
|
+
if (node.name === "Image") {
|
|
2096
|
+
const urlNode = node.node.getChild("URL");
|
|
2097
|
+
if (urlNode) {
|
|
2098
|
+
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
2099
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
2100
|
+
decorations.push(Decoration7.replace({
|
|
2101
|
+
block: true,
|
|
2102
|
+
widget: new ImageWidget(url)
|
|
2103
|
+
}).range(hide ? node.from : node.to, node.to));
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
},
|
|
2107
|
+
from,
|
|
2108
|
+
to
|
|
2109
|
+
});
|
|
2110
|
+
return decorations;
|
|
2111
|
+
};
|
|
2112
|
+
var ImageWidget = class extends WidgetType4 {
|
|
2113
|
+
constructor(_url) {
|
|
2114
|
+
super();
|
|
2115
|
+
this._url = _url;
|
|
2116
|
+
}
|
|
2117
|
+
eq(other) {
|
|
2118
|
+
return this._url === other._url;
|
|
2119
|
+
}
|
|
2120
|
+
toDOM(view) {
|
|
2121
|
+
const img = document.createElement("img");
|
|
2122
|
+
img.setAttribute("src", this._url);
|
|
2123
|
+
img.setAttribute("class", "cm-image");
|
|
2124
|
+
img.onload = () => img.classList.add("cm-loaded-image");
|
|
2125
|
+
return img;
|
|
2126
|
+
}
|
|
2127
|
+
};
|
|
2128
|
+
|
|
2129
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
2130
|
+
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
|
2131
|
+
import { RangeSetBuilder as RangeSetBuilder5 } from "@codemirror/state";
|
|
2132
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration8, ViewPlugin as ViewPlugin7, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
2133
|
+
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
2134
|
+
var link = (options = {}) => {
|
|
2135
|
+
const extensions = [
|
|
2136
|
+
ViewPlugin7.fromClass(class {
|
|
2137
|
+
constructor(view) {
|
|
2138
|
+
this.decorations = buildDecorations5(view, options);
|
|
2139
|
+
}
|
|
2140
|
+
update(update2) {
|
|
2141
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2142
|
+
this.decorations = buildDecorations5(update2.view, options);
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
}, {
|
|
2146
|
+
decorations: (value) => value.decorations
|
|
2147
|
+
})
|
|
2148
|
+
];
|
|
2149
|
+
if (options.onHover) {
|
|
2150
|
+
extensions.push(
|
|
2151
|
+
// https://codemirror.net/examples/tooltip
|
|
2152
|
+
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
2153
|
+
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
2154
|
+
hoverTooltip2((view, pos, side) => {
|
|
2155
|
+
const syntax = syntaxTree6(view.state).resolveInner(pos, side);
|
|
2156
|
+
let link2 = null;
|
|
2157
|
+
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
2158
|
+
link2 = node.name === "Link" ? node : null;
|
|
2159
|
+
}
|
|
2160
|
+
const url = link2 && link2.getChild("URL");
|
|
2161
|
+
if (!url || !link2) {
|
|
2162
|
+
return null;
|
|
2163
|
+
}
|
|
2164
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
2165
|
+
return {
|
|
2166
|
+
pos: link2.from,
|
|
2167
|
+
end: link2.to,
|
|
2168
|
+
above: true,
|
|
2169
|
+
create: () => {
|
|
2170
|
+
const el = document.createElement("div");
|
|
2171
|
+
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
2172
|
+
options.onHover(el, urlText);
|
|
2173
|
+
return {
|
|
2174
|
+
dom: el,
|
|
2175
|
+
offset: {
|
|
2176
|
+
x: 0,
|
|
2177
|
+
y: 4
|
|
2178
|
+
}
|
|
2179
|
+
};
|
|
2180
|
+
}
|
|
2181
|
+
};
|
|
2182
|
+
})
|
|
2183
|
+
);
|
|
2184
|
+
}
|
|
2185
|
+
return extensions;
|
|
2186
|
+
};
|
|
2187
|
+
var LinkButton = class extends WidgetType5 {
|
|
2188
|
+
constructor(_url, _onAttach) {
|
|
2189
|
+
super();
|
|
2190
|
+
this._url = _url;
|
|
2191
|
+
this._onAttach = _onAttach;
|
|
2192
|
+
}
|
|
2193
|
+
eq(other) {
|
|
2194
|
+
return this._url === other._url;
|
|
2195
|
+
}
|
|
2196
|
+
toDOM(view) {
|
|
2197
|
+
const el = document.createElement("span");
|
|
2198
|
+
this._onAttach(el, this._url);
|
|
2199
|
+
return el;
|
|
2200
|
+
}
|
|
2201
|
+
};
|
|
2202
|
+
var LinkText = class extends WidgetType5 {
|
|
2203
|
+
constructor(_text, _url) {
|
|
2204
|
+
super();
|
|
2205
|
+
this._text = _text;
|
|
2206
|
+
this._url = _url;
|
|
2207
|
+
}
|
|
2208
|
+
eq(other) {
|
|
2209
|
+
return this._url === other._url;
|
|
2210
|
+
}
|
|
2211
|
+
toDOM(view) {
|
|
2212
|
+
const link2 = document.createElement("a");
|
|
2213
|
+
link2.setAttribute("class", "cm-link");
|
|
2214
|
+
link2.textContent = this._text;
|
|
2215
|
+
if (this._url) {
|
|
2216
|
+
link2.setAttribute("rel", "noreferrer");
|
|
2217
|
+
link2.setAttribute("target", "_blank");
|
|
2218
|
+
link2.href = this._url;
|
|
2219
|
+
} else {
|
|
2220
|
+
link2.onclick = () => {
|
|
2221
|
+
view.dispatch({
|
|
2222
|
+
selection: {
|
|
2223
|
+
anchor: view.posAtDOM(link2)
|
|
2224
|
+
}
|
|
2225
|
+
});
|
|
2226
|
+
};
|
|
2227
|
+
}
|
|
2228
|
+
return link2;
|
|
2229
|
+
}
|
|
2230
|
+
};
|
|
2231
|
+
var buildDecorations5 = (view, options) => {
|
|
2232
|
+
const builder = new RangeSetBuilder5();
|
|
2233
|
+
const { state } = view;
|
|
2234
|
+
const cursor = state.selection.main.head;
|
|
2235
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2236
|
+
syntaxTree6(state).iterate({
|
|
2237
|
+
enter: (node) => {
|
|
2238
|
+
if (node.name === "Link") {
|
|
2239
|
+
const marks = node.node.getChildren("LinkMark");
|
|
2240
|
+
const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
|
|
2241
|
+
const urlNode = node.node.getChild("URL");
|
|
2242
|
+
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
2243
|
+
if (!url) {
|
|
2244
|
+
return false;
|
|
2245
|
+
}
|
|
2246
|
+
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
2247
|
+
builder.add(node.from, node.to, Decoration8.replace({
|
|
2248
|
+
widget: new LinkText(text, options.link ? url : void 0)
|
|
2249
|
+
}));
|
|
2250
|
+
}
|
|
2251
|
+
if (options.onRender) {
|
|
2252
|
+
builder.add(node.to, node.to, Decoration8.replace({
|
|
2253
|
+
widget: new LinkButton(url, options.onRender)
|
|
2254
|
+
}));
|
|
2255
|
+
}
|
|
2256
|
+
return false;
|
|
2257
|
+
}
|
|
2258
|
+
},
|
|
2259
|
+
from,
|
|
2260
|
+
to
|
|
2261
|
+
});
|
|
2262
|
+
}
|
|
2263
|
+
return builder.finish();
|
|
2264
|
+
};
|
|
2265
|
+
|
|
2266
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
2267
|
+
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
|
2268
|
+
import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField4 } from "@codemirror/state";
|
|
2269
|
+
import { Decoration as Decoration9, EditorView as EditorView11, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
2270
|
+
var table = (options = {}) => {
|
|
2271
|
+
return StateField4.define({
|
|
2272
|
+
create: (state) => update(state, options),
|
|
2273
|
+
update: (_, tr) => update(tr.state, options),
|
|
2274
|
+
provide: (field) => EditorView11.decorations.from(field)
|
|
2275
|
+
});
|
|
2276
|
+
};
|
|
2277
|
+
var update = (state, options) => {
|
|
2278
|
+
const builder = new RangeSetBuilder6();
|
|
2279
|
+
const cursor = state.selection.main.head;
|
|
2280
|
+
const tables = [];
|
|
2281
|
+
const getTable = () => tables[tables.length - 1];
|
|
2282
|
+
const getRow = () => {
|
|
2283
|
+
const table2 = getTable();
|
|
2284
|
+
return table2.rows?.[table2.rows.length - 1];
|
|
2285
|
+
};
|
|
2286
|
+
syntaxTree7(state).iterate({
|
|
2287
|
+
enter: (node) => {
|
|
2288
|
+
switch (node.name) {
|
|
2289
|
+
case "Table": {
|
|
2290
|
+
tables.push({
|
|
2291
|
+
from: node.from,
|
|
2292
|
+
to: node.to
|
|
2293
|
+
});
|
|
2294
|
+
break;
|
|
2295
|
+
}
|
|
2296
|
+
case "TableHeader": {
|
|
2004
2297
|
getTable().header = [];
|
|
2005
2298
|
break;
|
|
2006
2299
|
}
|
|
@@ -2022,11 +2315,10 @@ var update3 = (state, options) => {
|
|
|
2022
2315
|
});
|
|
2023
2316
|
tables.forEach((table2) => {
|
|
2024
2317
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2025
|
-
hide && builder.add(table2.from, table2.to,
|
|
2026
|
-
block: true,
|
|
2318
|
+
hide && builder.add(table2.from, table2.to, Decoration9.replace({
|
|
2027
2319
|
widget: new TableWidget(table2)
|
|
2028
2320
|
}));
|
|
2029
|
-
builder.add(table2.from, table2.to,
|
|
2321
|
+
builder.add(table2.from, table2.to, Decoration9.mark({
|
|
2030
2322
|
class: "cm-table"
|
|
2031
2323
|
}));
|
|
2032
2324
|
});
|
|
@@ -2038,7 +2330,7 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2038
2330
|
this._table = _table;
|
|
2039
2331
|
}
|
|
2040
2332
|
eq(other) {
|
|
2041
|
-
return this._table.
|
|
2333
|
+
return this._table.header?.join() === other._table.header?.join() && this._table.rows?.join() === other._table.rows?.join();
|
|
2042
2334
|
}
|
|
2043
2335
|
toDOM(view) {
|
|
2044
2336
|
const table2 = document.createElement("table");
|
|
@@ -2064,95 +2356,144 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2064
2356
|
}
|
|
2065
2357
|
return table2;
|
|
2066
2358
|
}
|
|
2359
|
+
ignoreEvent(e) {
|
|
2360
|
+
return !/^mouse/.test(e.type);
|
|
2361
|
+
}
|
|
2067
2362
|
};
|
|
2068
2363
|
|
|
2069
|
-
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2070
|
-
import {
|
|
2364
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
2365
|
+
import { syntaxTree as syntaxTree8 } from "@codemirror/language";
|
|
2366
|
+
import { RangeSetBuilder as RangeSetBuilder7 } from "@codemirror/state";
|
|
2367
|
+
import { EditorView as EditorView12, Decoration as Decoration10, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
|
|
2071
2368
|
var styles5 = EditorView12.baseTheme({
|
|
2072
|
-
"& .cm-task
|
|
2073
|
-
|
|
2074
|
-
|
|
2369
|
+
"& .cm-task": {
|
|
2370
|
+
color: getToken("extend.colors.blue.500")
|
|
2371
|
+
},
|
|
2372
|
+
"& .cm-task-checkbox": {
|
|
2373
|
+
marginLeft: "4px",
|
|
2374
|
+
marginRight: "4px"
|
|
2075
2375
|
}
|
|
2076
2376
|
});
|
|
2077
2377
|
var CheckboxWidget = class extends WidgetType7 {
|
|
2078
|
-
constructor(
|
|
2378
|
+
constructor(_checked) {
|
|
2079
2379
|
super();
|
|
2080
|
-
this._pos = _pos;
|
|
2081
2380
|
this._checked = _checked;
|
|
2082
|
-
this._indent = _indent;
|
|
2083
|
-
this._onCheck = _onCheck;
|
|
2084
2381
|
}
|
|
2085
2382
|
eq(other) {
|
|
2086
|
-
return this.
|
|
2383
|
+
return this._checked === other._checked;
|
|
2087
2384
|
}
|
|
2088
2385
|
toDOM(view) {
|
|
2089
|
-
const
|
|
2090
|
-
|
|
2091
|
-
wrap.setAttribute("aria-hidden", "true");
|
|
2092
|
-
wrap.style.setProperty("margin-left", this._indent * 24 + "px");
|
|
2093
|
-
const input = wrap.appendChild(document.createElement("input"));
|
|
2386
|
+
const input = document.createElement("input");
|
|
2387
|
+
input.className = "cm-task-checkbox";
|
|
2094
2388
|
input.type = "checkbox";
|
|
2095
2389
|
input.checked = this._checked;
|
|
2096
|
-
if (
|
|
2390
|
+
if (view.state.readOnly) {
|
|
2097
2391
|
input.setAttribute("disabled", "true");
|
|
2098
|
-
}
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2392
|
+
} else {
|
|
2393
|
+
input.onmousedown = (event) => {
|
|
2394
|
+
const pos = view.posAtDOM(input);
|
|
2395
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
2396
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
2397
|
+
view.dispatch({
|
|
2398
|
+
changes: {
|
|
2399
|
+
from: pos + 1,
|
|
2400
|
+
to: pos + 2,
|
|
2401
|
+
insert: this._checked ? " " : "x"
|
|
2402
|
+
}
|
|
2403
|
+
});
|
|
2404
|
+
event.preventDefault();
|
|
2405
|
+
}
|
|
2103
2406
|
};
|
|
2104
2407
|
}
|
|
2105
|
-
return
|
|
2408
|
+
return input;
|
|
2106
2409
|
}
|
|
2107
2410
|
ignoreEvent() {
|
|
2108
2411
|
return false;
|
|
2109
2412
|
}
|
|
2110
2413
|
};
|
|
2111
|
-
var
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
}
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
}
|
|
2142
|
-
}, {
|
|
2143
|
-
decorations: (value) => value.tasks,
|
|
2144
|
-
provide: (plugin) => EditorView12.atomicRanges.of((view) => {
|
|
2145
|
-
return view.plugin(plugin)?.tasks || Decoration8.none;
|
|
2146
|
-
})
|
|
2147
|
-
});
|
|
2414
|
+
var checkedDecoration = Decoration10.replace({
|
|
2415
|
+
widget: new CheckboxWidget(true)
|
|
2416
|
+
});
|
|
2417
|
+
var uncheckedDecoration = Decoration10.replace({
|
|
2418
|
+
widget: new CheckboxWidget(false)
|
|
2419
|
+
});
|
|
2420
|
+
var buildDecorations6 = (view) => {
|
|
2421
|
+
const builder = new RangeSetBuilder7();
|
|
2422
|
+
const { state } = view;
|
|
2423
|
+
const cursor = state.selection.main.head;
|
|
2424
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2425
|
+
syntaxTree8(state).iterate({
|
|
2426
|
+
enter: (node) => {
|
|
2427
|
+
if (node.name === "TaskMarker") {
|
|
2428
|
+
if (cursor < node.from || cursor > node.to) {
|
|
2429
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2430
|
+
builder.add(node.from - 2, node.from - 1, Decoration10.mark({
|
|
2431
|
+
class: "cm-task"
|
|
2432
|
+
}));
|
|
2433
|
+
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
},
|
|
2437
|
+
from,
|
|
2438
|
+
to
|
|
2439
|
+
});
|
|
2440
|
+
}
|
|
2441
|
+
return builder.finish();
|
|
2442
|
+
};
|
|
2443
|
+
var tasklist = (options = {}) => {
|
|
2148
2444
|
return [
|
|
2149
|
-
|
|
2445
|
+
ViewPlugin8.fromClass(class {
|
|
2446
|
+
constructor(view) {
|
|
2447
|
+
this.decorations = buildDecorations6(view);
|
|
2448
|
+
}
|
|
2449
|
+
update(update2) {
|
|
2450
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2451
|
+
this.decorations = buildDecorations6(update2.view);
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
}, {
|
|
2455
|
+
decorations: (value) => value.decorations
|
|
2456
|
+
}),
|
|
2150
2457
|
styles5
|
|
2151
2458
|
];
|
|
2152
2459
|
};
|
|
2153
2460
|
|
|
2461
|
+
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
2462
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
2463
|
+
var mention = ({ onSearch }) => {
|
|
2464
|
+
return autocompletion2({
|
|
2465
|
+
// TODO(burdon): Not working.
|
|
2466
|
+
activateOnTyping: true,
|
|
2467
|
+
// activateOnTypingDelay: 100,
|
|
2468
|
+
// selectOnOpen: true,
|
|
2469
|
+
closeOnBlur: false,
|
|
2470
|
+
// defaultKeymap: false,
|
|
2471
|
+
icons: false,
|
|
2472
|
+
override: [
|
|
2473
|
+
(context) => {
|
|
2474
|
+
console.log(context);
|
|
2475
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
2476
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
2477
|
+
return null;
|
|
2478
|
+
}
|
|
2479
|
+
return {
|
|
2480
|
+
from: match.from,
|
|
2481
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
2482
|
+
label: `@${value}`
|
|
2483
|
+
}))
|
|
2484
|
+
};
|
|
2485
|
+
}
|
|
2486
|
+
]
|
|
2487
|
+
});
|
|
2488
|
+
};
|
|
2489
|
+
|
|
2490
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
2491
|
+
var outliner = (options = {}) => {
|
|
2492
|
+
return [];
|
|
2493
|
+
};
|
|
2494
|
+
|
|
2154
2495
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2155
|
-
import { keymap as
|
|
2496
|
+
import { keymap as keymap6 } from "@codemirror/view";
|
|
2156
2497
|
var defaultItems = [
|
|
2157
2498
|
"hello world!",
|
|
2158
2499
|
"this is a test.",
|
|
@@ -2162,7 +2503,7 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2162
2503
|
let t;
|
|
2163
2504
|
let idx = 0;
|
|
2164
2505
|
return [
|
|
2165
|
-
|
|
2506
|
+
keymap6.of([
|
|
2166
2507
|
{
|
|
2167
2508
|
// Reset.
|
|
2168
2509
|
key: "alt-meta-'",
|
|
@@ -2208,29 +2549,8 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2208
2549
|
];
|
|
2209
2550
|
};
|
|
2210
2551
|
|
|
2211
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2212
|
-
import { yCollab } from "y-codemirror.next";
|
|
2213
|
-
|
|
2214
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/cursor.ts
|
|
2215
|
-
import * as Y from "yjs";
|
|
2216
|
-
import { arrayToString, stringToArray } from "@dxos/util";
|
|
2217
|
-
var cursorConverter2 = (text) => ({
|
|
2218
|
-
toCursor: (index, assoc) => {
|
|
2219
|
-
return arrayToString(Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text, index, assoc)));
|
|
2220
|
-
},
|
|
2221
|
-
fromCursor: (cursor) => {
|
|
2222
|
-
return Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(cursor)), text.doc)?.index ?? 0;
|
|
2223
|
-
}
|
|
2224
|
-
});
|
|
2225
|
-
|
|
2226
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2227
|
-
var yjs = (content, awareness2) => [
|
|
2228
|
-
CursorConverter.of(cursorConverter2(content)),
|
|
2229
|
-
yCollab(content, awareness2)
|
|
2230
|
-
];
|
|
2231
|
-
|
|
2232
2552
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2233
|
-
import
|
|
2553
|
+
import get3 from "lodash.get";
|
|
2234
2554
|
var defaultTheme = {
|
|
2235
2555
|
//
|
|
2236
2556
|
// Main layout:
|
|
@@ -2259,21 +2579,22 @@ var defaultTheme = {
|
|
|
2259
2579
|
"&.cm-focused": {
|
|
2260
2580
|
outline: "none"
|
|
2261
2581
|
},
|
|
2262
|
-
"
|
|
2263
|
-
overflow:
|
|
2264
|
-
fontFamily:
|
|
2582
|
+
".cm-scroller": {
|
|
2583
|
+
// overflow: 'visible',
|
|
2584
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(","),
|
|
2585
|
+
lineHeight: 1.4
|
|
2265
2586
|
},
|
|
2266
|
-
"
|
|
2587
|
+
".cm-content": {
|
|
2267
2588
|
padding: 0,
|
|
2268
2589
|
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
|
2269
2590
|
fontSize: "16px"
|
|
2270
2591
|
},
|
|
2271
2592
|
"&light .cm-content": {
|
|
2272
|
-
color:
|
|
2593
|
+
color: get3(tokens, "extend.colors.neutral.900", "black"),
|
|
2273
2594
|
caretColor: "black"
|
|
2274
2595
|
},
|
|
2275
2596
|
"&dark .cm-content": {
|
|
2276
|
-
color:
|
|
2597
|
+
color: get3(tokens, "extend.colors.neutral.100", "white"),
|
|
2277
2598
|
caretColor: "white"
|
|
2278
2599
|
},
|
|
2279
2600
|
//
|
|
@@ -2285,158 +2606,120 @@ var defaultTheme = {
|
|
|
2285
2606
|
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
2286
2607
|
borderLeft: "2px solid white"
|
|
2287
2608
|
},
|
|
2288
|
-
"
|
|
2609
|
+
".cm-placeholder": {
|
|
2289
2610
|
fontWeight: 100
|
|
2290
2611
|
},
|
|
2291
2612
|
//
|
|
2292
2613
|
// line
|
|
2293
2614
|
//
|
|
2294
|
-
"
|
|
2615
|
+
".cm-line": {
|
|
2295
2616
|
paddingInline: 0
|
|
2296
2617
|
},
|
|
2297
|
-
"
|
|
2298
|
-
background: "
|
|
2618
|
+
".cm-activeLine": {
|
|
2619
|
+
background: "transparent"
|
|
2299
2620
|
},
|
|
2300
2621
|
//
|
|
2301
2622
|
// Selection
|
|
2302
2623
|
//
|
|
2303
2624
|
"&light .cm-selectionBackground": {
|
|
2304
|
-
background:
|
|
2625
|
+
background: get3(tokens, "extend.colors.primary.100")
|
|
2305
2626
|
},
|
|
2306
2627
|
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2307
|
-
background:
|
|
2628
|
+
background: get3(tokens, "extend.colors.primary.200")
|
|
2308
2629
|
},
|
|
2309
2630
|
"&dark .cm-selectionBackground": {
|
|
2310
|
-
background:
|
|
2631
|
+
background: get3(tokens, "extend.colors.primary.700")
|
|
2311
2632
|
},
|
|
2312
2633
|
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2313
|
-
background:
|
|
2634
|
+
background: get3(tokens, "extend.colors.primary.600")
|
|
2314
2635
|
},
|
|
2315
2636
|
//
|
|
2316
2637
|
// Search
|
|
2317
2638
|
//
|
|
2318
2639
|
"&light .cm-searchMatch": {
|
|
2319
|
-
backgroundColor:
|
|
2640
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.100")
|
|
2320
2641
|
},
|
|
2321
2642
|
"&dark .cm-searchMatch": {
|
|
2322
|
-
backgroundColor:
|
|
2323
|
-
},
|
|
2324
|
-
//
|
|
2325
|
-
// collaboration
|
|
2326
|
-
// TODO(burdon): Review classnames (YJS dependent?) Note: e2e tests depend on this class.
|
|
2327
|
-
//
|
|
2328
|
-
"&light .cm-ySelection, &light .cm-yLineSelection": {
|
|
2329
|
-
mixBlendMode: "multiply"
|
|
2330
|
-
},
|
|
2331
|
-
"&dark .cm-ySelection, &dark .cm-yLineSelection": {
|
|
2332
|
-
mixBlendMode: "screen"
|
|
2333
|
-
},
|
|
2334
|
-
"& .cm-ySelectionInfo": {
|
|
2335
|
-
padding: "2px 4px",
|
|
2336
|
-
marginBlockStart: "-4px"
|
|
2337
|
-
},
|
|
2338
|
-
"& .cm-ySelection, & .cm-selectionMatch": {
|
|
2339
|
-
paddingBlockStart: ".15em",
|
|
2340
|
-
paddingBlockEnd: ".15em"
|
|
2341
|
-
},
|
|
2342
|
-
"& .cm-ySelectionCaret": {
|
|
2343
|
-
display: "inline-block",
|
|
2344
|
-
insetBlockStart: ".1em",
|
|
2345
|
-
blockSize: "1.4em",
|
|
2346
|
-
verticalAlign: "top"
|
|
2347
|
-
},
|
|
2348
|
-
"& .cm-yLineSelection": {
|
|
2349
|
-
margin: 0
|
|
2643
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.700")
|
|
2350
2644
|
},
|
|
2351
2645
|
//
|
|
2352
2646
|
// link
|
|
2353
2647
|
//
|
|
2354
|
-
"
|
|
2355
|
-
color:
|
|
2648
|
+
".cm-link": {
|
|
2649
|
+
color: get3(tokens, "extend.colors.primary.500"),
|
|
2356
2650
|
textDecorationLine: "underline",
|
|
2357
2651
|
textDecorationThickness: "1px",
|
|
2358
2652
|
textUnderlineOffset: "2px",
|
|
2359
2653
|
borderRadius: ".125rem",
|
|
2360
|
-
fontFamily:
|
|
2654
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2361
2655
|
},
|
|
2362
2656
|
//
|
|
2363
2657
|
// tooltip
|
|
2364
2658
|
//
|
|
2365
|
-
"
|
|
2659
|
+
".cm-tooltip": {
|
|
2366
2660
|
border: "none"
|
|
2367
2661
|
},
|
|
2368
|
-
"
|
|
2662
|
+
".cm-tooltip-below": {},
|
|
2369
2663
|
//
|
|
2370
2664
|
// autocomplete
|
|
2371
2665
|
//
|
|
2372
|
-
"
|
|
2666
|
+
".cm-tooltip-autocomplete": {
|
|
2373
2667
|
marginTop: "4px",
|
|
2374
2668
|
marginLeft: "-3px"
|
|
2375
2669
|
},
|
|
2376
|
-
"
|
|
2377
|
-
"
|
|
2378
|
-
"
|
|
2670
|
+
".cm-tooltip-autocomplete ul li": {},
|
|
2671
|
+
".cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
2672
|
+
".cm-completionIcon": {
|
|
2379
2673
|
display: "none"
|
|
2380
2674
|
},
|
|
2381
|
-
"
|
|
2382
|
-
fontFamily:
|
|
2675
|
+
".cm-completionLabel": {
|
|
2676
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2383
2677
|
},
|
|
2384
|
-
"
|
|
2678
|
+
".cm-completionMatchedText": {
|
|
2385
2679
|
textDecoration: "none"
|
|
2386
2680
|
},
|
|
2387
2681
|
//
|
|
2388
|
-
// widgets
|
|
2389
|
-
//
|
|
2390
|
-
"& .cm-widgetBuffer": {
|
|
2391
|
-
display: "none",
|
|
2392
|
-
height: 0
|
|
2393
|
-
},
|
|
2394
|
-
//
|
|
2395
2682
|
// table
|
|
2396
2683
|
//
|
|
2397
|
-
"
|
|
2398
|
-
fontFamily: `${
|
|
2684
|
+
".cm-table *": {
|
|
2685
|
+
fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
2399
2686
|
textDecoration: "none !important"
|
|
2400
2687
|
},
|
|
2401
|
-
"
|
|
2688
|
+
".cm-table-head": {
|
|
2402
2689
|
padding: "2px 16px 2px 0px",
|
|
2403
|
-
borderBottom: `1px solid ${
|
|
2690
|
+
borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
|
|
2404
2691
|
fontWeight: 100,
|
|
2405
2692
|
textAlign: "left",
|
|
2406
|
-
color:
|
|
2693
|
+
color: get3(tokens, "extend.colors.neutral.500")
|
|
2407
2694
|
},
|
|
2408
|
-
"
|
|
2695
|
+
".cm-table-cell": {
|
|
2409
2696
|
padding: "2px 16px 2px 0px"
|
|
2410
2697
|
},
|
|
2411
2698
|
//
|
|
2412
2699
|
// image
|
|
2413
2700
|
//
|
|
2414
|
-
"
|
|
2415
|
-
|
|
2701
|
+
".cm-image": {
|
|
2702
|
+
display: "block",
|
|
2703
|
+
height: "0"
|
|
2704
|
+
},
|
|
2705
|
+
".cm-image.cm-loaded-image": {
|
|
2706
|
+
height: "auto",
|
|
2707
|
+
borderTop: "0.5rem solid transparent",
|
|
2708
|
+
borderBottom: "0.5rem solid transparent"
|
|
2416
2709
|
},
|
|
2417
2710
|
//
|
|
2418
2711
|
// font size
|
|
2419
|
-
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2712
|
+
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2713
|
+
// but it's far more verbose than it needs to be.
|
|
2420
2714
|
//
|
|
2421
|
-
...Object.keys(
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = {
|
|
2430
|
-
height
|
|
2431
|
-
};
|
|
2432
|
-
acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = {
|
|
2433
|
-
height
|
|
2434
|
-
};
|
|
2435
|
-
acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = {
|
|
2436
|
-
height
|
|
2437
|
-
};
|
|
2438
|
-
return acc;
|
|
2439
|
-
}, {}),
|
|
2715
|
+
// ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
|
|
2716
|
+
// const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
|
|
2717
|
+
//
|
|
2718
|
+
// acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
|
|
2719
|
+
// acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
|
|
2720
|
+
// acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
2721
|
+
// return acc;
|
|
2722
|
+
// }, {}),
|
|
2440
2723
|
/**
|
|
2441
2724
|
* Panels
|
|
2442
2725
|
* TODO(burdon): Needs styling attention (esp. dark mode).
|
|
@@ -2453,144 +2736,146 @@ var defaultTheme = {
|
|
|
2453
2736
|
* </div>
|
|
2454
2737
|
* </div
|
|
2455
2738
|
*/
|
|
2456
|
-
"
|
|
2457
|
-
border: `1px solid ${
|
|
2739
|
+
".cm-panels": {
|
|
2740
|
+
border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`
|
|
2458
2741
|
},
|
|
2459
|
-
"
|
|
2460
|
-
background:
|
|
2461
|
-
fontFamily:
|
|
2742
|
+
".cm-panel": {
|
|
2743
|
+
background: get3(tokens, "extend.colors.neutral.50"),
|
|
2744
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2462
2745
|
},
|
|
2463
|
-
"
|
|
2746
|
+
".cm-button": {
|
|
2464
2747
|
margin: "4px",
|
|
2465
|
-
fontFamily:
|
|
2466
|
-
background:
|
|
2748
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
2749
|
+
background: get3(tokens, "extend.colors.neutral.100"),
|
|
2467
2750
|
backgroundImage: "none",
|
|
2468
2751
|
border: "none",
|
|
2469
2752
|
"&:hover": {
|
|
2470
|
-
background:
|
|
2753
|
+
background: get3(tokens, "extend.colors.neutral.200")
|
|
2471
2754
|
},
|
|
2472
2755
|
"&:active": {
|
|
2473
|
-
background:
|
|
2756
|
+
background: get3(tokens, "extend.colors.neutral.300"),
|
|
2474
2757
|
backgroundImage: "none"
|
|
2475
2758
|
}
|
|
2476
2759
|
},
|
|
2477
|
-
"
|
|
2760
|
+
".cm-panel input[type=checkbox]": {
|
|
2478
2761
|
marginRight: "0.4rem !important"
|
|
2479
2762
|
}
|
|
2480
2763
|
};
|
|
2481
2764
|
var textTheme = {
|
|
2482
|
-
"
|
|
2483
|
-
fontFamily:
|
|
2765
|
+
".cm-scroller": {
|
|
2766
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2484
2767
|
},
|
|
2485
|
-
"
|
|
2486
|
-
fontFamily:
|
|
2768
|
+
".cm-placeholder": {
|
|
2769
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2487
2770
|
}
|
|
2488
2771
|
};
|
|
2489
2772
|
var markdownTheme = {
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2773
|
+
".cm-scroller": {
|
|
2774
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2775
|
+
},
|
|
2776
|
+
".cm-placeholder": {
|
|
2777
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2493
2778
|
}
|
|
2494
2779
|
};
|
|
2495
2780
|
var codeTheme = {
|
|
2496
|
-
"
|
|
2497
|
-
fontFamily:
|
|
2781
|
+
".cm-scroller": {
|
|
2782
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2498
2783
|
},
|
|
2499
|
-
"
|
|
2500
|
-
fontFamily:
|
|
2784
|
+
".cm-placeholder": {
|
|
2785
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2501
2786
|
}
|
|
2502
2787
|
};
|
|
2503
2788
|
|
|
2504
2789
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2790
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
2505
2791
|
var EditorModes = [
|
|
2506
2792
|
"default",
|
|
2507
2793
|
"vim"
|
|
2508
2794
|
];
|
|
2509
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly,
|
|
2795
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
2510
2796
|
const { themeMode } = useThemeContext();
|
|
2511
|
-
const
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
const [root, setRoot] = useState(null);
|
|
2515
|
-
const [{ state = void 0, view = void 0 } = {}, setEditor] = useState();
|
|
2516
|
-
useImperativeHandle(forwardedRef, () => ({
|
|
2517
|
-
root,
|
|
2518
|
-
state,
|
|
2797
|
+
const rootRef = useRef(null);
|
|
2798
|
+
const [view, setView] = useState(null);
|
|
2799
|
+
useImperativeHandle(forwardedRef, () => view, [
|
|
2519
2800
|
view
|
|
2520
|
-
}), [
|
|
2521
|
-
view,
|
|
2522
|
-
state,
|
|
2523
|
-
root
|
|
2524
|
-
]);
|
|
2525
|
-
const { awareness: awareness2, peer } = model;
|
|
2526
|
-
useEffect(() => {
|
|
2527
|
-
if (awareness2 && peer) {
|
|
2528
|
-
awareness2.setLocalStateField("user", {
|
|
2529
|
-
name: peer.name ?? generateName(peer.id),
|
|
2530
|
-
color: getColorForValue({
|
|
2531
|
-
value: peer.id,
|
|
2532
|
-
type: "color"
|
|
2533
|
-
}),
|
|
2534
|
-
colorLight: getColorForValue({
|
|
2535
|
-
value: peer.id,
|
|
2536
|
-
themeMode,
|
|
2537
|
-
type: "highlight"
|
|
2538
|
-
})
|
|
2539
|
-
});
|
|
2540
|
-
}
|
|
2541
|
-
}, [
|
|
2542
|
-
awareness2,
|
|
2543
|
-
peer,
|
|
2544
|
-
themeMode
|
|
2545
2801
|
]);
|
|
2546
|
-
|
|
2547
|
-
if (
|
|
2548
|
-
view.
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2802
|
+
useEffect2(() => {
|
|
2803
|
+
if (autoFocus && !view?.hasFocus) {
|
|
2804
|
+
if (view?.state.selection.main?.from === 0) {
|
|
2805
|
+
const { to } = view.state.doc.lineAt(0);
|
|
2806
|
+
view?.dispatch({
|
|
2807
|
+
selection: {
|
|
2808
|
+
anchor: to
|
|
2809
|
+
}
|
|
2810
|
+
});
|
|
2811
|
+
}
|
|
2812
|
+
view?.focus();
|
|
2554
2813
|
}
|
|
2555
2814
|
}, [
|
|
2556
2815
|
view,
|
|
2557
|
-
|
|
2816
|
+
autoFocus
|
|
2558
2817
|
]);
|
|
2559
|
-
|
|
2560
|
-
if (!
|
|
2818
|
+
useEffect2(() => {
|
|
2819
|
+
if (!model || !rootRef.current) {
|
|
2561
2820
|
return;
|
|
2562
2821
|
}
|
|
2563
|
-
const
|
|
2822
|
+
const state = EditorState2.create({
|
|
2564
2823
|
doc: model.text(),
|
|
2824
|
+
selection,
|
|
2565
2825
|
extensions: [
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2826
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2827
|
+
EditorView13.exceptionSink.of((err) => {
|
|
2828
|
+
log2.catch(err, void 0, {
|
|
2829
|
+
F: __dxlog_file3,
|
|
2830
|
+
L: 134,
|
|
2831
|
+
S: void 0,
|
|
2832
|
+
C: (f, a) => f(...a)
|
|
2833
|
+
});
|
|
2834
|
+
}),
|
|
2569
2835
|
// Theme.
|
|
2570
|
-
// TODO(burdon): Make
|
|
2836
|
+
// TODO(burdon): Make configurable.
|
|
2571
2837
|
EditorView13.baseTheme(defaultTheme),
|
|
2572
|
-
EditorView13.theme(
|
|
2838
|
+
EditorView13.theme(theme ?? {}),
|
|
2573
2839
|
EditorView13.darkTheme.of(themeMode === "dark"),
|
|
2840
|
+
EditorView13.editorAttributes.of({
|
|
2841
|
+
class: slots.editor?.className ?? ""
|
|
2842
|
+
}),
|
|
2843
|
+
EditorView13.contentAttributes.of({
|
|
2844
|
+
class: slots.content?.className ?? ""
|
|
2845
|
+
}),
|
|
2846
|
+
// State.
|
|
2847
|
+
EditorView13.editable.of(!readonly),
|
|
2848
|
+
EditorState2.readOnly.of(!!readonly),
|
|
2574
2849
|
// Storage and replication.
|
|
2850
|
+
// NOTE: This must come before user extensions.
|
|
2575
2851
|
model.extension,
|
|
2852
|
+
// TODO(burdon): Factor out? (Requires special handling for Escape/Enter below).
|
|
2853
|
+
editorMode === "vim" && vim(),
|
|
2576
2854
|
// Custom.
|
|
2577
2855
|
...extensions
|
|
2578
|
-
].filter(
|
|
2856
|
+
].filter(isNotFalsy3)
|
|
2579
2857
|
});
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2858
|
+
const newView = new EditorView13({
|
|
2859
|
+
state,
|
|
2860
|
+
parent: rootRef.current,
|
|
2861
|
+
scrollTo,
|
|
2862
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
2863
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
2864
|
+
dispatchTransactions: (trs, view2) => {
|
|
2865
|
+
if (debug) {
|
|
2866
|
+
logChanges(trs);
|
|
2867
|
+
}
|
|
2868
|
+
view2.update(trs);
|
|
2869
|
+
}
|
|
2587
2870
|
});
|
|
2871
|
+
view?.destroy();
|
|
2872
|
+
setView(newView);
|
|
2588
2873
|
return () => {
|
|
2589
|
-
|
|
2590
|
-
|
|
2874
|
+
newView?.destroy();
|
|
2875
|
+
setView(null);
|
|
2591
2876
|
};
|
|
2592
2877
|
}, [
|
|
2593
|
-
|
|
2878
|
+
rootRef,
|
|
2594
2879
|
model,
|
|
2595
2880
|
readonly,
|
|
2596
2881
|
editorMode,
|
|
@@ -2600,11 +2885,13 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2600
2885
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2601
2886
|
switch (key) {
|
|
2602
2887
|
case "Enter": {
|
|
2603
|
-
view?.
|
|
2888
|
+
view?.focus();
|
|
2604
2889
|
break;
|
|
2605
2890
|
}
|
|
2606
2891
|
case "Escape": {
|
|
2607
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)
|
|
2892
|
+
if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
2893
|
+
view?.focus();
|
|
2894
|
+
}
|
|
2608
2895
|
break;
|
|
2609
2896
|
}
|
|
2610
2897
|
}
|
|
@@ -2614,83 +2901,239 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2614
2901
|
]);
|
|
2615
2902
|
return /* @__PURE__ */ React.createElement("div", {
|
|
2616
2903
|
key: model.id,
|
|
2617
|
-
|
|
2904
|
+
role: "none",
|
|
2618
2905
|
tabIndex: 0,
|
|
2619
|
-
...slots
|
|
2620
|
-
...editorMode !==
|
|
2621
|
-
onKeyUp: handleKeyUp
|
|
2906
|
+
...slots.root,
|
|
2907
|
+
// {...(editorMode !== 'vim' && tabsterDOMAttribute)}
|
|
2908
|
+
onKeyUp: handleKeyUp,
|
|
2909
|
+
ref: rootRef
|
|
2622
2910
|
});
|
|
2623
2911
|
});
|
|
2624
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly,
|
|
2912
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2625
2913
|
const { themeMode } = useThemeContext();
|
|
2626
|
-
const
|
|
2914
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2627
2915
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2628
2916
|
ref: forwardedRef,
|
|
2629
2917
|
readonly,
|
|
2630
2918
|
extensions: [
|
|
2631
|
-
|
|
2632
|
-
readonly,
|
|
2919
|
+
createBasicBundle({
|
|
2633
2920
|
themeMode,
|
|
2634
|
-
placeholder:
|
|
2921
|
+
placeholder: placeholder3,
|
|
2922
|
+
lineWrapping
|
|
2635
2923
|
}),
|
|
2636
2924
|
...extensions
|
|
2637
2925
|
],
|
|
2638
|
-
|
|
2926
|
+
theme,
|
|
2927
|
+
slots: updatedSlots,
|
|
2639
2928
|
...props
|
|
2640
2929
|
});
|
|
2641
2930
|
});
|
|
2642
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly,
|
|
2931
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2643
2932
|
const { themeMode } = useThemeContext();
|
|
2644
|
-
const
|
|
2933
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2645
2934
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2646
2935
|
ref: forwardedRef,
|
|
2647
2936
|
readonly,
|
|
2648
2937
|
extensions: [
|
|
2649
|
-
|
|
2650
|
-
readonly,
|
|
2938
|
+
createMarkdownExtensions({
|
|
2651
2939
|
themeMode,
|
|
2652
|
-
placeholder:
|
|
2940
|
+
placeholder: placeholder3
|
|
2653
2941
|
}),
|
|
2654
2942
|
...extensions
|
|
2655
2943
|
],
|
|
2656
|
-
|
|
2944
|
+
theme,
|
|
2945
|
+
slots: updatedSlots,
|
|
2657
2946
|
...props
|
|
2658
2947
|
});
|
|
2659
2948
|
});
|
|
2660
2949
|
var defaultSlots = {
|
|
2661
2950
|
root: {
|
|
2662
|
-
|
|
2951
|
+
// TODO(burdon): Add focusRing by default/as property?
|
|
2952
|
+
className: mx3("flex flex-col grow overflow-y-auto", attentionSurface)
|
|
2953
|
+
},
|
|
2954
|
+
editor: {
|
|
2955
|
+
className: "h-full p-2"
|
|
2663
2956
|
}
|
|
2664
2957
|
};
|
|
2665
2958
|
var defaultTextSlots = {
|
|
2666
|
-
...defaultSlots
|
|
2667
|
-
editor: {
|
|
2668
|
-
theme: textTheme
|
|
2669
|
-
}
|
|
2959
|
+
...defaultSlots
|
|
2670
2960
|
};
|
|
2671
2961
|
var defaultMarkdownSlots = {
|
|
2672
|
-
...defaultSlots
|
|
2673
|
-
editor: {
|
|
2674
|
-
theme: markdownTheme
|
|
2675
|
-
}
|
|
2962
|
+
...defaultSlots
|
|
2676
2963
|
};
|
|
2677
2964
|
|
|
2678
|
-
// packages/ui/react-ui-editor/src/
|
|
2679
|
-
import
|
|
2680
|
-
import {
|
|
2681
|
-
import
|
|
2965
|
+
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
|
2966
|
+
import { At, CaretRight, ChatText, Code, Image, Link, ListBullets, ListChecks, ListNumbers, TextStrikethrough, Table as Table2, TextB, TextItalic } from "@phosphor-icons/react";
|
|
2967
|
+
import { createContext } from "@radix-ui/react-context";
|
|
2968
|
+
import React2 from "react";
|
|
2969
|
+
import { Button, DensityProvider, Select } from "@dxos/react-ui";
|
|
2970
|
+
import { getSize } from "@dxos/react-ui-theme";
|
|
2971
|
+
var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
|
|
2972
|
+
var ToolbarRoot = ({ children, onAction }) => {
|
|
2973
|
+
return /* @__PURE__ */ React2.createElement(ToolbarContextProvider, {
|
|
2974
|
+
onAction
|
|
2975
|
+
}, /* @__PURE__ */ React2.createElement(DensityProvider, {
|
|
2976
|
+
density: "fine"
|
|
2977
|
+
}, /* @__PURE__ */ React2.createElement("div", {
|
|
2978
|
+
role: "toolbar",
|
|
2979
|
+
className: "flex w-full shrink-0 p-2 gap-4 items-center whitespace-nowrap overflow-hidden"
|
|
2980
|
+
}, children)));
|
|
2981
|
+
};
|
|
2982
|
+
var ToolbarButton = ({ Icon, onClick, title }) => {
|
|
2983
|
+
const { onAction } = useToolbarContext("ToolbarButton");
|
|
2984
|
+
const handleClick = () => {
|
|
2985
|
+
const action = onClick();
|
|
2986
|
+
if (action) {
|
|
2987
|
+
onAction?.(action);
|
|
2988
|
+
}
|
|
2989
|
+
};
|
|
2990
|
+
return /* @__PURE__ */ React2.createElement(Button, {
|
|
2991
|
+
variant: "ghost",
|
|
2992
|
+
classNames: "p-2",
|
|
2993
|
+
onClick: handleClick,
|
|
2994
|
+
title
|
|
2995
|
+
}, /* @__PURE__ */ React2.createElement(Icon, {
|
|
2996
|
+
className: getSize(5)
|
|
2997
|
+
}));
|
|
2998
|
+
};
|
|
2999
|
+
var ToolbarSeparator = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3000
|
+
className: "grow"
|
|
3001
|
+
});
|
|
3002
|
+
var MarkdownHeading = () => {
|
|
3003
|
+
const { onAction } = useToolbarContext("MarkdownFormatting");
|
|
3004
|
+
return /* @__PURE__ */ React2.createElement(Select.Root, {
|
|
3005
|
+
defaultValue: "0",
|
|
3006
|
+
onValueChange: (value) => onAction?.({
|
|
3007
|
+
type: "heading",
|
|
3008
|
+
data: parseInt(value)
|
|
3009
|
+
})
|
|
3010
|
+
}, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
|
|
3011
|
+
classNames: "w-[8rem]"
|
|
3012
|
+
}), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
3013
|
+
value: "0"
|
|
3014
|
+
}, "Paragraph"), [
|
|
3015
|
+
1,
|
|
3016
|
+
2,
|
|
3017
|
+
3,
|
|
3018
|
+
4,
|
|
3019
|
+
5,
|
|
3020
|
+
6
|
|
3021
|
+
].map((level) => /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
3022
|
+
key: level,
|
|
3023
|
+
value: String(level)
|
|
3024
|
+
}, "Heading ", level))))));
|
|
3025
|
+
};
|
|
3026
|
+
var MarkdownStyles = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3027
|
+
role: "none"
|
|
3028
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3029
|
+
Icon: TextB,
|
|
3030
|
+
title: "Bold",
|
|
3031
|
+
onClick: () => ({
|
|
3032
|
+
type: "bold"
|
|
3033
|
+
})
|
|
3034
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3035
|
+
Icon: TextItalic,
|
|
3036
|
+
title: "Italic",
|
|
3037
|
+
onClick: () => ({
|
|
3038
|
+
type: "italic"
|
|
3039
|
+
})
|
|
3040
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3041
|
+
Icon: TextStrikethrough,
|
|
3042
|
+
title: "Strike-through",
|
|
3043
|
+
onClick: () => ({
|
|
3044
|
+
type: "strikethrough"
|
|
3045
|
+
})
|
|
3046
|
+
}));
|
|
3047
|
+
var MarkdownLists = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3048
|
+
role: "none"
|
|
3049
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3050
|
+
Icon: ListBullets,
|
|
3051
|
+
title: "Bullet list",
|
|
3052
|
+
onClick: () => ({
|
|
3053
|
+
type: "list"
|
|
3054
|
+
})
|
|
3055
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3056
|
+
Icon: ListNumbers,
|
|
3057
|
+
title: "Numbered list",
|
|
3058
|
+
onClick: () => ({
|
|
3059
|
+
type: "list-ordered"
|
|
3060
|
+
})
|
|
3061
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3062
|
+
Icon: ListChecks,
|
|
3063
|
+
title: "Task list",
|
|
3064
|
+
onClick: () => ({
|
|
3065
|
+
type: "list-tasks"
|
|
3066
|
+
})
|
|
3067
|
+
}));
|
|
3068
|
+
var MarkdownBlocks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3069
|
+
role: "none"
|
|
3070
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3071
|
+
Icon: CaretRight,
|
|
3072
|
+
title: "Block quite",
|
|
3073
|
+
onClick: () => ({
|
|
3074
|
+
type: "blockquote"
|
|
3075
|
+
})
|
|
3076
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3077
|
+
Icon: Code,
|
|
3078
|
+
title: "Code block",
|
|
3079
|
+
onClick: () => ({
|
|
3080
|
+
type: "codeblock"
|
|
3081
|
+
})
|
|
3082
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3083
|
+
Icon: Table2,
|
|
3084
|
+
title: "Table",
|
|
3085
|
+
onClick: () => ({
|
|
3086
|
+
type: "table"
|
|
3087
|
+
})
|
|
3088
|
+
}));
|
|
3089
|
+
var MarkdownLinks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3090
|
+
role: "none"
|
|
3091
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3092
|
+
Icon: Link,
|
|
3093
|
+
title: "Link",
|
|
3094
|
+
onClick: () => ({
|
|
3095
|
+
type: "link"
|
|
3096
|
+
})
|
|
3097
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3098
|
+
Icon: At,
|
|
3099
|
+
title: "Mention",
|
|
3100
|
+
onClick: () => ({
|
|
3101
|
+
type: "mention"
|
|
3102
|
+
})
|
|
3103
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3104
|
+
Icon: Image,
|
|
3105
|
+
title: "Image",
|
|
3106
|
+
onClick: () => ({
|
|
3107
|
+
type: "image"
|
|
3108
|
+
})
|
|
3109
|
+
}));
|
|
3110
|
+
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), /* @__PURE__ */ React2.createElement(MarkdownLinks, null));
|
|
3111
|
+
var MarkdownExtended = () => /* @__PURE__ */ React2.createElement(Toolbar.Button, {
|
|
3112
|
+
Icon: ChatText,
|
|
3113
|
+
title: "Create comment",
|
|
3114
|
+
onClick: () => ({
|
|
3115
|
+
type: "comment"
|
|
3116
|
+
})
|
|
3117
|
+
});
|
|
3118
|
+
var Toolbar = {
|
|
3119
|
+
Root: ToolbarRoot,
|
|
3120
|
+
Button: ToolbarButton,
|
|
3121
|
+
Separator: ToolbarSeparator,
|
|
3122
|
+
Markdown: MarkdownStandard,
|
|
3123
|
+
Extended: MarkdownExtended
|
|
3124
|
+
};
|
|
2682
3125
|
|
|
2683
3126
|
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2684
3127
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2685
3128
|
import { Context as Context2 } from "@dxos/context";
|
|
2686
|
-
import { invariant as
|
|
3129
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
2687
3130
|
import { log as log3 } from "@dxos/log";
|
|
2688
3131
|
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2689
3132
|
var DEBOUNCE_INTERVAL = 100;
|
|
2690
3133
|
var SpaceAwarenessProvider = class {
|
|
2691
3134
|
constructor(params) {
|
|
2692
|
-
this.remoteStateChange = new Event2();
|
|
2693
3135
|
this._remoteStates = /* @__PURE__ */ new Map();
|
|
3136
|
+
this.remoteStateChange = new Event2();
|
|
2694
3137
|
this._space = params.space;
|
|
2695
3138
|
this._channel = params.channel;
|
|
2696
3139
|
this._peerId = params.peerId;
|
|
@@ -2707,7 +3150,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2707
3150
|
await sleep(DEBOUNCE_INTERVAL);
|
|
2708
3151
|
}
|
|
2709
3152
|
});
|
|
2710
|
-
|
|
3153
|
+
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
2711
3154
|
switch (message.payload.kind) {
|
|
2712
3155
|
case "query": {
|
|
2713
3156
|
this._handleQueryMessage();
|
|
@@ -2718,8 +3161,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2718
3161
|
break;
|
|
2719
3162
|
}
|
|
2720
3163
|
}
|
|
2721
|
-
});
|
|
2722
|
-
this._ctx.onDispose(unsubscribe);
|
|
3164
|
+
}));
|
|
2723
3165
|
void this._space.postMessage(this._channel, {
|
|
2724
3166
|
kind: "query"
|
|
2725
3167
|
}).catch((err) => {
|
|
@@ -2727,7 +3169,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2727
3169
|
err
|
|
2728
3170
|
}, {
|
|
2729
3171
|
F: __dxlog_file4,
|
|
2730
|
-
L:
|
|
3172
|
+
L: 89,
|
|
2731
3173
|
S: this,
|
|
2732
3174
|
C: (f, a) => f(...a)
|
|
2733
3175
|
});
|
|
@@ -2738,10 +3180,13 @@ var SpaceAwarenessProvider = class {
|
|
|
2738
3180
|
this._ctx = void 0;
|
|
2739
3181
|
this._postTask = void 0;
|
|
2740
3182
|
}
|
|
3183
|
+
getRemoteStates() {
|
|
3184
|
+
return Array.from(this._remoteStates.values());
|
|
3185
|
+
}
|
|
2741
3186
|
update(position) {
|
|
2742
|
-
|
|
3187
|
+
invariant2(this._postTask, void 0, {
|
|
2743
3188
|
F: __dxlog_file4,
|
|
2744
|
-
L:
|
|
3189
|
+
L: 104,
|
|
2745
3190
|
S: this,
|
|
2746
3191
|
A: [
|
|
2747
3192
|
"this._postTask",
|
|
@@ -2755,13 +3200,10 @@ var SpaceAwarenessProvider = class {
|
|
|
2755
3200
|
};
|
|
2756
3201
|
this._postTask.schedule();
|
|
2757
3202
|
}
|
|
2758
|
-
getRemoteStates() {
|
|
2759
|
-
return Array.from(this._remoteStates.values());
|
|
2760
|
-
}
|
|
2761
3203
|
_handleQueryMessage() {
|
|
2762
|
-
|
|
3204
|
+
invariant2(this._postTask, void 0, {
|
|
2763
3205
|
F: __dxlog_file4,
|
|
2764
|
-
L:
|
|
3206
|
+
L: 115,
|
|
2765
3207
|
S: this,
|
|
2766
3208
|
A: [
|
|
2767
3209
|
"this._postTask",
|
|
@@ -2771,9 +3213,9 @@ var SpaceAwarenessProvider = class {
|
|
|
2771
3213
|
this._postTask.schedule();
|
|
2772
3214
|
}
|
|
2773
3215
|
_handlePostMessage(message) {
|
|
2774
|
-
|
|
3216
|
+
invariant2(message.kind === "post", void 0, {
|
|
2775
3217
|
F: __dxlog_file4,
|
|
2776
|
-
L:
|
|
3218
|
+
L: 120,
|
|
2777
3219
|
S: this,
|
|
2778
3220
|
A: [
|
|
2779
3221
|
"message.kind === 'post'",
|
|
@@ -2785,229 +3227,231 @@ var SpaceAwarenessProvider = class {
|
|
|
2785
3227
|
}
|
|
2786
3228
|
};
|
|
2787
3229
|
|
|
2788
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2789
|
-
import { StateField as
|
|
2790
|
-
|
|
2791
|
-
|
|
3230
|
+
// packages/ui/react-ui-editor/src/hooks/defs.ts
|
|
3231
|
+
import { StateField as StateField5 } from "@codemirror/state";
|
|
3232
|
+
var modelState = StateField5.define({
|
|
3233
|
+
create: () => void 0,
|
|
3234
|
+
update: (model) => model
|
|
3235
|
+
});
|
|
2792
3236
|
|
|
2793
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
arrayToString2(to)
|
|
2830
|
-
].join(":");
|
|
2831
|
-
},
|
|
2832
|
-
getRangeFromCursor: (cursor) => {
|
|
2833
|
-
invariant4(text.doc, void 0, {
|
|
2834
|
-
F: __dxlog_file5,
|
|
2835
|
-
L: 40,
|
|
2836
|
-
S: void 0,
|
|
2837
|
-
A: [
|
|
2838
|
-
"text.doc",
|
|
2839
|
-
""
|
|
2840
|
-
]
|
|
3237
|
+
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
3238
|
+
var useActionHandler = (view) => {
|
|
3239
|
+
return (action) => {
|
|
3240
|
+
if (!view) {
|
|
3241
|
+
return;
|
|
3242
|
+
}
|
|
3243
|
+
switch (action.type) {
|
|
3244
|
+
case "heading":
|
|
3245
|
+
setHeading(parseInt(action.data))(view);
|
|
3246
|
+
break;
|
|
3247
|
+
case "bold":
|
|
3248
|
+
toggleBold(view);
|
|
3249
|
+
break;
|
|
3250
|
+
case "italic":
|
|
3251
|
+
toggleItalic(view);
|
|
3252
|
+
break;
|
|
3253
|
+
case "strikethrough":
|
|
3254
|
+
toggleStrikethrough(view);
|
|
3255
|
+
break;
|
|
3256
|
+
case "list":
|
|
3257
|
+
toggleList(view);
|
|
3258
|
+
break;
|
|
3259
|
+
case "codeblock":
|
|
3260
|
+
insertCodeblock(view);
|
|
3261
|
+
break;
|
|
3262
|
+
case "table":
|
|
3263
|
+
insertTable(view);
|
|
3264
|
+
break;
|
|
3265
|
+
case "comment":
|
|
3266
|
+
createComment(view);
|
|
3267
|
+
break;
|
|
3268
|
+
}
|
|
3269
|
+
setTimeout(() => {
|
|
3270
|
+
view.focus();
|
|
3271
|
+
view.dispatch({
|
|
3272
|
+
selection: view.state.selection
|
|
2841
3273
|
});
|
|
2842
|
-
|
|
2843
|
-
const from = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[0])), text.doc);
|
|
2844
|
-
const to = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[1])), text.doc);
|
|
2845
|
-
return from && to ? {
|
|
2846
|
-
from: from.index,
|
|
2847
|
-
to: to.index
|
|
2848
|
-
} : void 0;
|
|
2849
|
-
},
|
|
2850
|
-
extension: [
|
|
2851
|
-
modelState.init(() => model),
|
|
2852
|
-
yjs(text.content, provider?.awareness)
|
|
2853
|
-
],
|
|
2854
|
-
awareness: provider?.awareness,
|
|
2855
|
-
peer: identity ? {
|
|
2856
|
-
id: identity.identityKey.toHex(),
|
|
2857
|
-
name: identity.profile?.displayName
|
|
2858
|
-
} : void 0
|
|
3274
|
+
});
|
|
2859
3275
|
};
|
|
2860
|
-
return model;
|
|
2861
3276
|
};
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
3277
|
+
|
|
3278
|
+
// packages/ui/react-ui-editor/src/hooks/useEditorView.ts
|
|
3279
|
+
import { useState as useState2 } from "react";
|
|
3280
|
+
var useEditorView = () => {
|
|
3281
|
+
const [view, setView] = useState2(null);
|
|
3282
|
+
return [
|
|
3283
|
+
(ref) => {
|
|
3284
|
+
setView(ref);
|
|
3285
|
+
},
|
|
3286
|
+
view
|
|
3287
|
+
];
|
|
3288
|
+
};
|
|
3289
|
+
|
|
3290
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
3291
|
+
import { EditorSelection, EditorState as EditorState3 } from "@codemirror/state";
|
|
3292
|
+
import { EditorView as EditorView14 } from "@codemirror/view";
|
|
3293
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
3294
|
+
import { log as log4 } from "@dxos/log";
|
|
3295
|
+
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
3296
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
3297
|
+
var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}) => {
|
|
3298
|
+
const onUpdate = useRef2();
|
|
3299
|
+
const [view, setView] = useState3();
|
|
3300
|
+
const parentRef = useRef2(null);
|
|
3301
|
+
useEffect3(() => {
|
|
3302
|
+
if (parentRef.current) {
|
|
3303
|
+
const state = EditorState3.create({
|
|
3304
|
+
doc,
|
|
3305
|
+
selection,
|
|
3306
|
+
extensions: [
|
|
3307
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
3308
|
+
EditorView14.exceptionSink.of((err) => {
|
|
3309
|
+
log4.catch(err, void 0, {
|
|
3310
|
+
F: __dxlog_file5,
|
|
3311
|
+
L: 57,
|
|
3312
|
+
S: void 0,
|
|
3313
|
+
C: (f, a) => f(...a)
|
|
3314
|
+
});
|
|
3315
|
+
}),
|
|
3316
|
+
extensions,
|
|
3317
|
+
EditorView14.updateListener.of(() => {
|
|
3318
|
+
onUpdate.current?.();
|
|
3319
|
+
})
|
|
3320
|
+
].filter(isNotFalsy4)
|
|
3321
|
+
});
|
|
3322
|
+
const view2 = new EditorView14({
|
|
3323
|
+
parent: parentRef.current,
|
|
3324
|
+
scrollTo,
|
|
3325
|
+
state,
|
|
3326
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
3327
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
3328
|
+
dispatchTransactions: (trs, view3) => {
|
|
3329
|
+
if (debug) {
|
|
3330
|
+
logChanges(trs);
|
|
3331
|
+
}
|
|
3332
|
+
view3.update(trs);
|
|
3333
|
+
}
|
|
3334
|
+
});
|
|
3335
|
+
setView(view2);
|
|
2920
3336
|
}
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
3337
|
+
return () => {
|
|
3338
|
+
view?.destroy();
|
|
3339
|
+
};
|
|
3340
|
+
}, [
|
|
3341
|
+
parentRef
|
|
3342
|
+
]);
|
|
3343
|
+
useEffect3(() => {
|
|
3344
|
+
if (view) {
|
|
3345
|
+
if (!selection && !view.state.selection.main.anchor) {
|
|
3346
|
+
selection = EditorSelection.single(view.state.doc.line(1).to);
|
|
2931
3347
|
}
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
3348
|
+
if (selection || scrollTo) {
|
|
3349
|
+
onUpdate.current = () => {
|
|
3350
|
+
onUpdate.current = void 0;
|
|
3351
|
+
view.dispatch({
|
|
3352
|
+
selection,
|
|
3353
|
+
effects: scrollTo && [
|
|
3354
|
+
scrollTo
|
|
3355
|
+
],
|
|
3356
|
+
scrollIntoView: !scrollTo
|
|
3357
|
+
});
|
|
3358
|
+
};
|
|
2937
3359
|
}
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
return encoder;
|
|
3360
|
+
if (autoFocus) {
|
|
3361
|
+
view.focus();
|
|
2941
3362
|
}
|
|
2942
3363
|
}
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
}
|
|
3364
|
+
}, [
|
|
3365
|
+
view,
|
|
3366
|
+
autoFocus,
|
|
3367
|
+
selection,
|
|
3368
|
+
scrollTo
|
|
3369
|
+
]);
|
|
3370
|
+
return {
|
|
3371
|
+
parentRef,
|
|
3372
|
+
view
|
|
3373
|
+
};
|
|
3374
|
+
};
|
|
3375
|
+
var createDataExtensions = ({ readonly = false } = {}) => {
|
|
3376
|
+
return [
|
|
3377
|
+
//
|
|
3378
|
+
EditorState3.readOnly.of(readonly),
|
|
3379
|
+
EditorView14.editable.of(!readonly)
|
|
3380
|
+
];
|
|
3381
|
+
};
|
|
3382
|
+
var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
3383
|
+
return [
|
|
3384
|
+
//
|
|
3385
|
+
EditorView14.baseTheme(defaultTheme),
|
|
3386
|
+
theme && EditorView14.theme(theme),
|
|
3387
|
+
EditorView14.darkTheme.of(themeMode === "dark"),
|
|
3388
|
+
EditorView14.editorAttributes.of({
|
|
3389
|
+
class: slots?.editor?.className ?? ""
|
|
3390
|
+
}),
|
|
3391
|
+
EditorView14.contentAttributes.of({
|
|
3392
|
+
class: slots?.content?.className ?? ""
|
|
3393
|
+
})
|
|
3394
|
+
].filter(isNotFalsy4);
|
|
2953
3395
|
};
|
|
2954
3396
|
|
|
2955
3397
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
}
|
|
3398
|
+
import get4 from "lodash.get";
|
|
3399
|
+
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
3400
|
+
import { generateName } from "@dxos/display-name";
|
|
3401
|
+
import { getRawDoc } from "@dxos/echo-schema";
|
|
3402
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
3403
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
3404
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
2960
3405
|
var useTextModel = (props) => {
|
|
2961
3406
|
const { identity, space, text } = props;
|
|
2962
|
-
const [model, setModel] =
|
|
2963
|
-
|
|
3407
|
+
const [model, setModel] = useState4();
|
|
3408
|
+
useEffect4(() => setModel(createModel(props)), [
|
|
2964
3409
|
identity,
|
|
2965
3410
|
space,
|
|
2966
3411
|
text
|
|
2967
3412
|
]);
|
|
2968
3413
|
return model;
|
|
2969
3414
|
};
|
|
2970
|
-
var createModel = (
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
};
|
|
2980
|
-
|
|
2981
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2982
|
-
var createAutomergeModel = ({ space, identity, text }) => {
|
|
3415
|
+
var createModel = ({ space, identity, text }) => {
|
|
3416
|
+
invariant3(isAutomergeObject(text), void 0, {
|
|
3417
|
+
F: __dxlog_file6,
|
|
3418
|
+
L: 34,
|
|
3419
|
+
S: void 0,
|
|
3420
|
+
A: [
|
|
3421
|
+
"isAutomergeObject(text)",
|
|
3422
|
+
""
|
|
3423
|
+
]
|
|
3424
|
+
});
|
|
2983
3425
|
const obj = text;
|
|
2984
3426
|
const doc = getRawDoc(obj, [
|
|
2985
3427
|
obj.field
|
|
2986
3428
|
]);
|
|
2987
|
-
const
|
|
3429
|
+
const awarenessProvider2 = space && new SpaceAwarenessProvider({
|
|
2988
3430
|
space,
|
|
2989
3431
|
channel: `automerge.awareness.${obj.id}`,
|
|
2990
3432
|
info: {
|
|
2991
|
-
displayName: identity
|
|
3433
|
+
displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
|
|
2992
3434
|
color: cursorColor.color,
|
|
2993
3435
|
lightColor: cursorColor.light
|
|
2994
3436
|
},
|
|
2995
3437
|
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2996
3438
|
});
|
|
3439
|
+
const extensions = [
|
|
3440
|
+
//
|
|
3441
|
+
modelState.init(() => model),
|
|
3442
|
+
automerge({
|
|
3443
|
+
handle: doc.handle,
|
|
3444
|
+
path: doc.path
|
|
3445
|
+
})
|
|
3446
|
+
];
|
|
3447
|
+
if (awarenessProvider2) {
|
|
3448
|
+
extensions.push(awareness(awarenessProvider2));
|
|
3449
|
+
}
|
|
2997
3450
|
const model = {
|
|
2998
3451
|
id: obj.id,
|
|
2999
3452
|
content: doc,
|
|
3000
|
-
text: () =>
|
|
3001
|
-
|
|
3002
|
-
extension: [
|
|
3003
|
-
modelState.init(() => model),
|
|
3004
|
-
automerge3({
|
|
3005
|
-
handle: doc.handle,
|
|
3006
|
-
path: doc.path
|
|
3007
|
-
}),
|
|
3008
|
-
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
3009
|
-
awareness()
|
|
3010
|
-
].filter(isNotNullOrUndefined),
|
|
3453
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
3454
|
+
extension: extensions,
|
|
3011
3455
|
peer: identity ? {
|
|
3012
3456
|
id: identity.identityKey.toHex(),
|
|
3013
3457
|
name: identity.profile?.displayName
|
|
@@ -3016,8 +3460,8 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
3016
3460
|
return model;
|
|
3017
3461
|
};
|
|
3018
3462
|
export {
|
|
3019
|
-
AwarenessProvider,
|
|
3020
3463
|
BaseTextEditor,
|
|
3464
|
+
Cursor,
|
|
3021
3465
|
Doc,
|
|
3022
3466
|
EditorModes,
|
|
3023
3467
|
MarkdownEditor,
|
|
@@ -3025,45 +3469,64 @@ export {
|
|
|
3025
3469
|
SpaceAwarenessProvider,
|
|
3026
3470
|
TextEditor,
|
|
3027
3471
|
TextKind,
|
|
3028
|
-
|
|
3472
|
+
Toolbar,
|
|
3029
3473
|
YText,
|
|
3030
3474
|
YXmlFragment,
|
|
3031
3475
|
autocomplete,
|
|
3032
|
-
|
|
3476
|
+
automerge,
|
|
3033
3477
|
awareness,
|
|
3034
|
-
|
|
3478
|
+
awarenessProvider,
|
|
3035
3479
|
blast,
|
|
3480
|
+
callbackWrapper,
|
|
3036
3481
|
code2 as code,
|
|
3037
3482
|
codeTheme,
|
|
3038
3483
|
comments,
|
|
3039
|
-
|
|
3040
|
-
|
|
3484
|
+
createBasicBundle,
|
|
3485
|
+
createComment,
|
|
3486
|
+
createDataExtensions,
|
|
3487
|
+
createMarkdownExtensions,
|
|
3488
|
+
createThemeExtensions,
|
|
3041
3489
|
defaultMarkdownSlots,
|
|
3042
3490
|
defaultOptions,
|
|
3043
3491
|
defaultSlots,
|
|
3044
3492
|
defaultTextSlots,
|
|
3045
3493
|
defaultTheme,
|
|
3494
|
+
focusComment,
|
|
3495
|
+
formatting,
|
|
3496
|
+
getToken,
|
|
3497
|
+
heading2 as heading,
|
|
3046
3498
|
hr,
|
|
3047
3499
|
image,
|
|
3500
|
+
insertCodeblock,
|
|
3501
|
+
insertTable,
|
|
3048
3502
|
link,
|
|
3049
3503
|
listener,
|
|
3050
|
-
|
|
3504
|
+
logChanges,
|
|
3051
3505
|
markdownHighlightStyle,
|
|
3052
3506
|
markdownTags,
|
|
3053
3507
|
markdownTagsExtensions,
|
|
3054
3508
|
markdownTheme,
|
|
3055
3509
|
mention,
|
|
3056
|
-
mermaid,
|
|
3057
3510
|
modelState,
|
|
3058
|
-
|
|
3059
|
-
|
|
3511
|
+
outliner,
|
|
3512
|
+
setComments,
|
|
3513
|
+
setHeading,
|
|
3060
3514
|
setSelection,
|
|
3061
3515
|
table,
|
|
3062
3516
|
tags2 as tags,
|
|
3063
3517
|
tasklist,
|
|
3064
3518
|
textTheme,
|
|
3519
|
+
toggleBold,
|
|
3520
|
+
toggleItalic,
|
|
3521
|
+
toggleList,
|
|
3522
|
+
toggleStrikethrough,
|
|
3523
|
+
toggleStyle,
|
|
3065
3524
|
typewriter,
|
|
3525
|
+
useActionHandler,
|
|
3526
|
+
useComments,
|
|
3527
|
+
useEditorView,
|
|
3528
|
+
useTextEditor,
|
|
3066
3529
|
useTextModel,
|
|
3067
|
-
|
|
3530
|
+
useToolbarContext
|
|
3068
3531
|
};
|
|
3069
3532
|
//# sourceMappingURL=index.mjs.map
|