@dxos/react-ui-editor 0.8.2-main.f11618f → 0.8.2-main.fbd8ed0
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 +1662 -1357
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +2175 -1872
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +1662 -1357
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts +1 -1
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -1
- package/dist/types/src/{stories/InputMode.stories.d.ts → components/EditorToolbar/EditorToolbar.stories.d.ts} +3 -7
- package/dist/types/src/components/EditorToolbar/EditorToolbar.stories.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/blocks.d.ts +4 -3
- package/dist/types/src/components/EditorToolbar/blocks.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/comment.d.ts +4 -3
- package/dist/types/src/components/EditorToolbar/comment.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/formatting.d.ts +4 -3
- package/dist/types/src/components/EditorToolbar/formatting.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/headings.d.ts +4 -3
- package/dist/types/src/components/EditorToolbar/headings.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/image.d.ts +16 -0
- package/dist/types/src/components/EditorToolbar/image.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/lists.d.ts +4 -3
- package/dist/types/src/components/EditorToolbar/lists.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/search.d.ts +17 -0
- package/dist/types/src/components/EditorToolbar/search.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/util.d.ts +11 -17
- package/dist/types/src/components/EditorToolbar/util.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts +4 -3
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts.map +1 -1
- package/dist/types/src/defaults.d.ts.map +1 -1
- package/dist/types/src/extensions/annotations.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.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/sync.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-codemirror.d.ts +1 -1
- package/dist/types/src/extensions/automerge/update-codemirror.d.ts.map +1 -1
- package/dist/types/src/extensions/awareness/awareness.d.ts.map +1 -1
- package/dist/types/src/extensions/blast.d.ts.map +1 -1
- package/dist/types/src/extensions/command/command.d.ts.map +1 -1
- package/dist/types/src/extensions/command/hint.d.ts.map +1 -1
- package/dist/types/src/extensions/command/menu.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/debug.d.ts.map +1 -1
- package/dist/types/src/extensions/dnd.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/folding.d.ts.map +1 -1
- package/dist/types/src/extensions/listener.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/changes.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/debug.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts +1 -0
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/index.d.ts +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/outliner.d.ts +12 -0
- package/dist/types/src/extensions/markdown/outliner.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -1
- package/dist/types/src/extensions/mention.d.ts.map +1 -1
- package/dist/types/src/extensions/modes.d.ts +5 -5
- package/dist/types/src/extensions/modes.d.ts.map +1 -1
- package/dist/types/src/extensions/preview/preview.d.ts.map +1 -1
- package/dist/types/src/extensions/selection.d.ts.map +1 -1
- package/dist/types/src/extensions/typewriter.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +0 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/stories/TextEditorBasic.stories.d.ts +3 -0
- package/dist/types/src/stories/TextEditorBasic.stories.d.ts.map +1 -1
- package/dist/types/src/stories/story-utils.d.ts.map +1 -1
- package/dist/types/src/styles/theme.d.ts.map +1 -1
- package/dist/types/src/util/cursor.d.ts.map +1 -1
- package/dist/types/src/util/debug.d.ts.map +1 -1
- package/dist/types/src/util/dom.d.ts.map +1 -1
- package/dist/types/src/util/facet.d.ts.map +1 -1
- package/dist/types/src/util/react.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +32 -28
- package/src/components/EditorToolbar/EditorToolbar.stories.tsx +90 -0
- package/src/components/EditorToolbar/EditorToolbar.tsx +31 -32
- package/src/components/EditorToolbar/blocks.ts +27 -6
- package/src/components/EditorToolbar/comment.ts +11 -4
- package/src/components/EditorToolbar/formatting.ts +34 -7
- package/src/components/EditorToolbar/headings.ts +9 -8
- package/src/components/EditorToolbar/image.ts +16 -0
- package/src/components/EditorToolbar/lists.ts +26 -7
- package/src/components/EditorToolbar/search.ts +19 -0
- package/src/components/EditorToolbar/util.ts +14 -14
- package/src/components/EditorToolbar/view-mode.ts +9 -8
- package/src/defaults.ts +1 -1
- package/src/extensions/automerge/automerge.stories.tsx +9 -7
- package/src/extensions/automerge/automerge.test.tsx +4 -4
- package/src/extensions/automerge/automerge.ts +2 -2
- package/src/extensions/automerge/defs.ts +1 -2
- package/src/extensions/automerge/sync.ts +4 -4
- package/src/extensions/automerge/update-automerge.ts +1 -1
- package/src/extensions/automerge/update-codemirror.ts +3 -4
- package/src/extensions/markdown/changes.ts +3 -2
- package/src/extensions/markdown/decorate.ts +8 -7
- package/src/extensions/markdown/formatting.ts +4 -4
- package/src/extensions/markdown/index.ts +1 -0
- package/src/extensions/markdown/outliner.ts +235 -0
- package/src/extensions/markdown/styles.ts +2 -2
- package/src/extensions/modes.ts +5 -6
- package/src/hooks/index.ts +0 -1
- package/src/stories/TextEditorBasic.stories.tsx +44 -0
- package/src/stories/story-utils.tsx +7 -9
- package/src/styles/theme.ts +3 -0
- package/dist/types/src/hooks/useActionHandler.d.ts +0 -4
- package/dist/types/src/hooks/useActionHandler.d.ts.map +0 -1
- package/dist/types/src/stories/InputMode.stories.d.ts.map +0 -1
- package/src/hooks/useActionHandler.ts +0 -12
- package/src/stories/InputMode.stories.tsx +0 -124
@@ -34,13 +34,13 @@ var translations_default = [
|
|
34
34
|
];
|
35
35
|
|
36
36
|
// packages/ui/react-ui-editor/src/index.ts
|
37
|
-
import { EditorState as
|
38
|
-
import { EditorView as
|
37
|
+
import { EditorState as EditorState4 } from "@codemirror/state";
|
38
|
+
import { EditorView as EditorView23, keymap as keymap11 } from "@codemirror/view";
|
39
39
|
import { tags as tags2 } from "@lezer/highlight";
|
40
40
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
41
41
|
|
42
42
|
// packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
|
43
|
-
import
|
43
|
+
import React3, { memo, useCallback } from "react";
|
44
44
|
import { ElevationProvider } from "@dxos/react-ui";
|
45
45
|
import { MenuProvider, ToolbarMenu, createGapSeparator, useMenuActions } from "@dxos/react-ui-menu";
|
46
46
|
import { textBlockWidth } from "@dxos/react-ui-theme";
|
@@ -52,692 +52,110 @@ import { createMenuAction, createMenuItemGroup } from "@dxos/react-ui-menu";
|
|
52
52
|
var useEditorToolbarState = (initialState = {}) => {
|
53
53
|
return useMemo(() => live(initialState), []);
|
54
54
|
};
|
55
|
-
var createEditorAction = (
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
55
|
+
var createEditorAction = (id, invoke, properties) => {
|
56
|
+
const { label = [
|
57
|
+
`${id} label`,
|
58
|
+
{
|
59
|
+
ns: translationKey
|
60
|
+
}
|
61
|
+
], ...rest } = properties;
|
62
|
+
return createMenuAction(id, invoke, {
|
63
|
+
label,
|
64
|
+
...rest
|
65
|
+
});
|
66
|
+
};
|
65
67
|
var createEditorActionGroup = (id, props, icon) => createMenuItemGroup(id, {
|
66
68
|
icon,
|
67
69
|
iconOnly: true,
|
68
70
|
...props
|
69
71
|
});
|
70
|
-
var editorToolbarSearch = createEditorAction({
|
71
|
-
type: "search"
|
72
|
-
}, "ph--magnifying-glass--regular");
|
73
72
|
|
74
|
-
// packages/ui/react-ui-editor/src/
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
value
|
79
|
-
});
|
80
|
-
var createBlockActions = (value, blankLine) => Object.entries({
|
81
|
-
blockquote: "ph--quotes--regular",
|
82
|
-
codeblock: "ph--code-block--regular",
|
83
|
-
table: "ph--table--regular"
|
84
|
-
}).map(([type, icon]) => {
|
85
|
-
return createEditorAction({
|
86
|
-
type,
|
87
|
-
checked: type === value,
|
88
|
-
...type === "table" && {
|
89
|
-
disabled: !!blankLine
|
90
|
-
}
|
91
|
-
}, icon);
|
92
|
-
});
|
93
|
-
var createBlocks = (state) => {
|
94
|
-
const value = state?.blockQuote ? "blockquote" : state.blockType ?? "";
|
95
|
-
const blockGroupAction = createBlockGroupAction(value);
|
96
|
-
const blockActions = createBlockActions(value, state.blankLine);
|
97
|
-
return {
|
98
|
-
nodes: [
|
99
|
-
blockGroupAction,
|
100
|
-
...blockActions
|
101
|
-
],
|
102
|
-
edges: [
|
103
|
-
{
|
104
|
-
source: "root",
|
105
|
-
target: "block"
|
106
|
-
},
|
107
|
-
...blockActions.map(({ id }) => ({
|
108
|
-
source: blockGroupAction.id,
|
109
|
-
target: id
|
110
|
-
}))
|
111
|
-
]
|
112
|
-
};
|
113
|
-
};
|
73
|
+
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
74
|
+
import { StateField } from "@codemirror/state";
|
75
|
+
import { Decoration, EditorView } from "@codemirror/view";
|
76
|
+
import { isNotFalsy } from "@dxos/util";
|
114
77
|
|
115
|
-
// packages/ui/react-ui-editor/src/
|
116
|
-
|
117
|
-
var
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
nodes: [
|
123
|
-
createCommentAction([
|
124
|
-
commentLabel(state.comment, state.selection),
|
125
|
-
{
|
126
|
-
ns: translationKey
|
127
|
-
}
|
128
|
-
])
|
129
|
-
],
|
130
|
-
edges: [
|
131
|
-
{
|
132
|
-
source: "root",
|
133
|
-
target: "comment"
|
134
|
-
}
|
135
|
-
]
|
78
|
+
// packages/ui/react-ui-editor/src/util/facet.ts
|
79
|
+
import { Facet } from "@codemirror/state";
|
80
|
+
var singleValueFacet = (defaultValue) => Facet.define({
|
81
|
+
// Called immediately.
|
82
|
+
combine: (providers) => {
|
83
|
+
return providers[0] ?? defaultValue;
|
84
|
+
}
|
136
85
|
});
|
137
86
|
|
138
|
-
// packages/ui/react-ui-editor/src/
|
139
|
-
var
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
code: "ph--code--regular",
|
144
|
-
link: "ph--link--regular"
|
87
|
+
// packages/ui/react-ui-editor/src/util/cursor.ts
|
88
|
+
var overlap = (a, b) => a.from <= b.to && a.to >= b.from;
|
89
|
+
var defaultCursorConverter = {
|
90
|
+
toCursor: (position) => position.toString(),
|
91
|
+
fromCursor: (cursor) => parseInt(cursor)
|
145
92
|
};
|
146
|
-
var
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
};
|
93
|
+
var Cursor = class _Cursor {
|
94
|
+
static {
|
95
|
+
this.converter = singleValueFacet(defaultCursorConverter);
|
96
|
+
}
|
97
|
+
static {
|
98
|
+
this.getCursorFromRange = (state, range) => {
|
99
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
100
|
+
const from = cursorConverter2.toCursor(range.from);
|
101
|
+
const to = cursorConverter2.toCursor(range.to, -1);
|
102
|
+
return [
|
103
|
+
from,
|
104
|
+
to
|
105
|
+
].join(":");
|
106
|
+
};
|
107
|
+
}
|
108
|
+
static {
|
109
|
+
this.getRangeFromCursor = (state, cursor) => {
|
110
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
111
|
+
const parts = cursor.split(":");
|
112
|
+
const from = cursorConverter2.fromCursor(parts[0]);
|
113
|
+
const to = cursorConverter2.fromCursor(parts[1]);
|
114
|
+
return from !== void 0 && to !== void 0 ? {
|
115
|
+
from,
|
116
|
+
to
|
117
|
+
} : void 0;
|
118
|
+
};
|
119
|
+
}
|
174
120
|
};
|
175
121
|
|
176
|
-
// packages/ui/react-ui-editor/src/
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
"6": "ph--text-h-six--regular"
|
191
|
-
}).map(([levelStr, icon]) => {
|
192
|
-
const level = parseInt(levelStr);
|
193
|
-
return createEditorAction({
|
194
|
-
type: "heading",
|
195
|
-
data: level,
|
196
|
-
checked: value === levelStr
|
197
|
-
}, icon, [
|
198
|
-
"heading level label",
|
199
|
-
{
|
200
|
-
count: level,
|
201
|
-
ns: translationKey
|
122
|
+
// packages/ui/react-ui-editor/src/util/debug.ts
|
123
|
+
import { log } from "@dxos/log";
|
124
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/debug.ts";
|
125
|
+
var wrapWithCatch = (fn) => {
|
126
|
+
return (...args) => {
|
127
|
+
try {
|
128
|
+
return fn(...args);
|
129
|
+
} catch (err) {
|
130
|
+
log.catch(err, void 0, {
|
131
|
+
F: __dxlog_file,
|
132
|
+
L: 15,
|
133
|
+
S: void 0,
|
134
|
+
C: (f, a) => f(...a)
|
135
|
+
});
|
202
136
|
}
|
203
|
-
], `heading--${levelStr}`);
|
204
|
-
});
|
205
|
-
var computeHeadingValue = (state) => {
|
206
|
-
const blockType = state ? state.blockType : "paragraph";
|
207
|
-
const header = blockType && /heading(\d)/.exec(blockType);
|
208
|
-
return header ? header[1] : blockType === "paragraph" || !blockType ? "0" : "";
|
209
|
-
};
|
210
|
-
var createHeadings = (state) => {
|
211
|
-
const headingValue = computeHeadingValue(state);
|
212
|
-
const headingGroupAction = createHeadingGroupAction(headingValue);
|
213
|
-
const headingActions = createHeadingActions(headingValue);
|
214
|
-
return {
|
215
|
-
nodes: [
|
216
|
-
headingGroupAction,
|
217
|
-
...headingActions
|
218
|
-
],
|
219
|
-
edges: [
|
220
|
-
{
|
221
|
-
source: "root",
|
222
|
-
target: "heading"
|
223
|
-
},
|
224
|
-
...headingActions.map(({ id }) => ({
|
225
|
-
source: headingGroupAction.id,
|
226
|
-
target: id
|
227
|
-
}))
|
228
|
-
]
|
229
137
|
};
|
230
138
|
};
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
139
|
+
var callbackWrapper = (fn) => (...args) => {
|
140
|
+
try {
|
141
|
+
return fn(...args);
|
142
|
+
} catch (err) {
|
143
|
+
log.catch(err, void 0, {
|
144
|
+
F: __dxlog_file,
|
145
|
+
L: 29,
|
146
|
+
S: void 0,
|
147
|
+
C: (f, a) => f(...a)
|
148
|
+
});
|
149
|
+
}
|
237
150
|
};
|
238
|
-
var
|
239
|
-
|
240
|
-
|
241
|
-
value
|
242
|
-
});
|
243
|
-
var createListActions = (value) => Object.entries(listStyles).map(([listStyle, icon]) => createEditorAction({
|
244
|
-
type: `list-${listStyle}`,
|
245
|
-
checked: value === listStyle
|
246
|
-
}, icon));
|
247
|
-
var createLists = (state) => {
|
248
|
-
const value = state.listStyle ?? "";
|
249
|
-
const listGroupAction = createListGroupAction(value);
|
250
|
-
const listActionsMap = createListActions(value);
|
251
|
-
return {
|
252
|
-
nodes: [
|
253
|
-
listGroupAction,
|
254
|
-
...listActionsMap
|
255
|
-
],
|
256
|
-
edges: [
|
257
|
-
{
|
258
|
-
source: "root",
|
259
|
-
target: "list"
|
260
|
-
},
|
261
|
-
...listActionsMap.map(({ id }) => ({
|
262
|
-
source: listGroupAction.id,
|
263
|
-
target: id
|
264
|
-
}))
|
265
|
-
]
|
266
|
-
};
|
151
|
+
var debugDispatcher = (trs, view) => {
|
152
|
+
logChanges(trs);
|
153
|
+
view.update(trs);
|
267
154
|
};
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
applyActive: true,
|
273
|
-
selectCardinality: "single",
|
274
|
-
value
|
275
|
-
}, "ph--eye--regular");
|
276
|
-
var createViewModeActions = (value) => Object.entries({
|
277
|
-
preview: "ph--eye--regular",
|
278
|
-
source: "ph--pencil-simple--regular",
|
279
|
-
readonly: "ph--pencil-slash--regular"
|
280
|
-
}).map(([viewMode, icon]) => {
|
281
|
-
return createEditorAction({
|
282
|
-
type: "view-mode",
|
283
|
-
data: viewMode,
|
284
|
-
checked: viewMode === value
|
285
|
-
}, icon, [
|
286
|
-
`${viewMode} mode label`,
|
287
|
-
{
|
288
|
-
ns: translationKey
|
289
|
-
}
|
290
|
-
], `view-mode--${viewMode}`);
|
291
|
-
});
|
292
|
-
var createViewMode = (state) => {
|
293
|
-
const value = state.viewMode ?? "source";
|
294
|
-
const viewModeGroupAction = createViewModeGroupAction(value);
|
295
|
-
const viewModeActions = createViewModeActions(value);
|
296
|
-
return {
|
297
|
-
nodes: [
|
298
|
-
viewModeGroupAction,
|
299
|
-
...viewModeActions
|
300
|
-
],
|
301
|
-
edges: [
|
302
|
-
{
|
303
|
-
source: "root",
|
304
|
-
target: "viewMode"
|
305
|
-
},
|
306
|
-
...viewModeActions.map(({ id }) => ({
|
307
|
-
source: viewModeGroupAction.id,
|
308
|
-
target: id
|
309
|
-
}))
|
310
|
-
]
|
311
|
-
};
|
312
|
-
};
|
313
|
-
|
314
|
-
// packages/ui/react-ui-editor/src/defaults.ts
|
315
|
-
import { EditorView } from "@codemirror/view";
|
316
|
-
import { mx as mx2 } from "@dxos/react-ui-theme";
|
317
|
-
|
318
|
-
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
319
|
-
import { mx } from "@dxos/react-ui-theme";
|
320
|
-
var headings = {
|
321
|
-
1: "text-4xl",
|
322
|
-
2: "text-3xl",
|
323
|
-
3: "text-2xl",
|
324
|
-
4: "text-xl",
|
325
|
-
5: "text-lg",
|
326
|
-
6: ""
|
327
|
-
};
|
328
|
-
var theme = {
|
329
|
-
code: "font-mono !no-underline text-neutral-700 dark:text-neutral-300",
|
330
|
-
codeMark: "font-mono text-primary-500",
|
331
|
-
mark: "opacity-50",
|
332
|
-
heading: (level) => {
|
333
|
-
return mx(headings[level], "dark:text-primary-400");
|
334
|
-
}
|
335
|
-
};
|
336
|
-
|
337
|
-
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
338
|
-
import get from "lodash.get";
|
339
|
-
import { tokens } from "@dxos/react-ui-theme";
|
340
|
-
var getToken = (path, defaultValue) => {
|
341
|
-
const value = get(tokens, path, defaultValue);
|
342
|
-
return value?.toString() ?? "";
|
343
|
-
};
|
344
|
-
var fontBody = getToken("fontFamily.body");
|
345
|
-
var fontMono = getToken("fontFamily.mono");
|
346
|
-
|
347
|
-
// packages/ui/react-ui-editor/src/styles/theme.ts
|
348
|
-
var defaultTheme = {
|
349
|
-
"&": {},
|
350
|
-
"&.cm-focused": {
|
351
|
-
outline: "none"
|
352
|
-
},
|
353
|
-
/**
|
354
|
-
* Scroller
|
355
|
-
*/
|
356
|
-
".cm-scroller": {
|
357
|
-
overflowY: "auto"
|
358
|
-
},
|
359
|
-
/**
|
360
|
-
* Content
|
361
|
-
* NOTE: Apply margins to content so that scrollbar is at the edge of the container.
|
362
|
-
*/
|
363
|
-
".cm-content": {
|
364
|
-
padding: "unset",
|
365
|
-
fontFamily: fontBody,
|
366
|
-
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
367
|
-
fontSize: "16px",
|
368
|
-
lineHeight: 1.5,
|
369
|
-
color: "unset"
|
370
|
-
},
|
371
|
-
/**
|
372
|
-
* Gutters
|
373
|
-
* NOTE: Gutters should have the same top margin as the content.
|
374
|
-
*/
|
375
|
-
".cm-gutters": {
|
376
|
-
borderRight: "none",
|
377
|
-
background: "transparent"
|
378
|
-
},
|
379
|
-
".cm-gutter": {},
|
380
|
-
".cm-gutter.cm-lineNumbers": {
|
381
|
-
paddingRight: "4px",
|
382
|
-
borderRight: "1px solid var(--dx-separator)"
|
383
|
-
},
|
384
|
-
".cm-gutter.cm-lineNumbers .cm-gutterElement": {
|
385
|
-
minWidth: "40px",
|
386
|
-
alignContent: "center"
|
387
|
-
},
|
388
|
-
/**
|
389
|
-
* Height is set to match the corresponding line.
|
390
|
-
*/
|
391
|
-
".cm-gutterElement": {
|
392
|
-
alignItems: "center",
|
393
|
-
fontSize: "12px"
|
394
|
-
},
|
395
|
-
/**
|
396
|
-
* Line.
|
397
|
-
*/
|
398
|
-
".cm-line": {
|
399
|
-
paddingInline: 0
|
400
|
-
},
|
401
|
-
".cm-activeLine": {
|
402
|
-
background: "var(--dx-cmActiveLine)"
|
403
|
-
},
|
404
|
-
/**
|
405
|
-
* Cursor (layer).
|
406
|
-
*/
|
407
|
-
".cm-cursor, .cm-dropCursor": {
|
408
|
-
borderLeft: "2px solid var(--dx-cmCursor)"
|
409
|
-
},
|
410
|
-
".cm-placeholder": {
|
411
|
-
color: "var(--dx-subdued)"
|
412
|
-
},
|
413
|
-
/**
|
414
|
-
* Selection (layer).
|
415
|
-
*/
|
416
|
-
".cm-selectionBackground": {
|
417
|
-
background: "var(--dx-cmSelection)"
|
418
|
-
},
|
419
|
-
/**
|
420
|
-
* Search.
|
421
|
-
* NOTE: Matches comment.
|
422
|
-
*/
|
423
|
-
".cm-searchMatch": {
|
424
|
-
margin: "0 -3px",
|
425
|
-
padding: "3px",
|
426
|
-
borderRadius: "3px",
|
427
|
-
background: "var(--dx-cmHighlightSurface)",
|
428
|
-
color: "var(--dx-cmHighlight)"
|
429
|
-
},
|
430
|
-
".cm-searchMatch-selected": {
|
431
|
-
textDecoration: "underline"
|
432
|
-
},
|
433
|
-
/**
|
434
|
-
* Link.
|
435
|
-
*/
|
436
|
-
".cm-link": {
|
437
|
-
textDecorationLine: "underline",
|
438
|
-
textDecorationThickness: "1px",
|
439
|
-
textDecorationColor: "var(--dx-separator)",
|
440
|
-
textUnderlineOffset: "2px",
|
441
|
-
borderRadius: ".125rem"
|
442
|
-
},
|
443
|
-
".cm-link > span": {
|
444
|
-
color: "var(--dx-accentText)"
|
445
|
-
},
|
446
|
-
/**
|
447
|
-
* Tooltip.
|
448
|
-
*/
|
449
|
-
".cm-tooltip": {
|
450
|
-
background: "var(--dx-baseSurface)"
|
451
|
-
},
|
452
|
-
".cm-tooltip-below": {},
|
453
|
-
/**
|
454
|
-
* Autocomplete.
|
455
|
-
* https://github.com/codemirror/autocomplete/blob/main/src/completion.ts
|
456
|
-
*/
|
457
|
-
".cm-tooltip.cm-tooltip-autocomplete": {
|
458
|
-
marginTop: "4px",
|
459
|
-
marginLeft: "-3px"
|
460
|
-
},
|
461
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul": {
|
462
|
-
maxHeight: "20em"
|
463
|
-
},
|
464
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > li": {},
|
465
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {},
|
466
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
|
467
|
-
paddingLeft: "4px !important",
|
468
|
-
borderBottom: "none !important",
|
469
|
-
color: "var(--dx-accentText)"
|
470
|
-
},
|
471
|
-
".cm-tooltip.cm-completionInfo": {
|
472
|
-
width: "360px !important",
|
473
|
-
margin: "-10px 1px 0 1px",
|
474
|
-
padding: "8px !important",
|
475
|
-
borderColor: "var(--dx-separator)"
|
476
|
-
},
|
477
|
-
".cm-completionIcon": {
|
478
|
-
display: "none"
|
479
|
-
},
|
480
|
-
".cm-completionLabel": {
|
481
|
-
fontFamily: fontBody
|
482
|
-
},
|
483
|
-
".cm-completionMatchedText": {
|
484
|
-
textDecoration: "none !important",
|
485
|
-
opacity: 0.5
|
486
|
-
},
|
487
|
-
/**
|
488
|
-
* Panels
|
489
|
-
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
490
|
-
*
|
491
|
-
* Find/replace panel.
|
492
|
-
* <div class="cm-announced">...</div>
|
493
|
-
* <div class="cm-scroller">...</div>
|
494
|
-
* <div class="cm-panels cm-panels-bottom">
|
495
|
-
* <div class="cm-search cm-panel">
|
496
|
-
* <input class="cm-textfield" />
|
497
|
-
* <button class="cm-button">...</button>
|
498
|
-
* <label><input type="checkbox" />...</label>
|
499
|
-
* </div>
|
500
|
-
* </div
|
501
|
-
*/
|
502
|
-
// TODO(burdon): Implement custom panel (with icon buttons).
|
503
|
-
".cm-panels": {},
|
504
|
-
".cm-panel": {
|
505
|
-
fontFamily: fontBody,
|
506
|
-
backgroundColor: "var(--surface-bg)"
|
507
|
-
},
|
508
|
-
".cm-panel input, .cm-panel button, .cm-panel label": {
|
509
|
-
color: "var(--dx-subdued)",
|
510
|
-
fontFamily: fontBody,
|
511
|
-
fontSize: "14px",
|
512
|
-
all: "unset",
|
513
|
-
margin: "3px !important",
|
514
|
-
padding: "2px 6px !important",
|
515
|
-
outline: "1px solid transparent"
|
516
|
-
},
|
517
|
-
".cm-panel input, .cm-panel button": {
|
518
|
-
backgroundColor: "var(--dx-input)"
|
519
|
-
},
|
520
|
-
".cm-panel input:focus, .cm-panel button:focus": {
|
521
|
-
outline: "1px solid var(--dx-accentFocusIndicator)"
|
522
|
-
},
|
523
|
-
".cm-panel label": {
|
524
|
-
display: "inline-flex",
|
525
|
-
alignItems: "center",
|
526
|
-
cursor: "pointer"
|
527
|
-
},
|
528
|
-
".cm-panel input.cm-textfield": {},
|
529
|
-
".cm-panel input[type=checkbox]": {
|
530
|
-
width: "8px",
|
531
|
-
height: "8px",
|
532
|
-
marginRight: "6px !important",
|
533
|
-
padding: "2px !important",
|
534
|
-
color: "var(--dx-accentFocusIndicator)"
|
535
|
-
},
|
536
|
-
".cm-panel button": {
|
537
|
-
"&:hover": {
|
538
|
-
backgroundColor: "var(--dx-accentSurfaceHover) !important"
|
539
|
-
},
|
540
|
-
"&:active": {
|
541
|
-
backgroundColor: "var(--dx-accentSurfaceHover)"
|
542
|
-
}
|
543
|
-
},
|
544
|
-
".cm-panel.cm-search": {
|
545
|
-
padding: "4px",
|
546
|
-
borderTop: "1px solid var(--dx-separator)"
|
547
|
-
}
|
548
|
-
};
|
549
|
-
|
550
|
-
// packages/ui/react-ui-editor/src/defaults.ts
|
551
|
-
var margin = "!mt-[1rem]";
|
552
|
-
var editorWidth = "!mli-auto is-full max-is-[min(50rem,100%-4rem)]";
|
553
|
-
var editorContent = mx2(margin, editorWidth);
|
554
|
-
var editorFullWidth = mx2(margin);
|
555
|
-
var editorGutter = EditorView.theme({
|
556
|
-
// Match margin from content.
|
557
|
-
// Gutter = 2rem + 1rem margin.
|
558
|
-
".cm-gutters": {
|
559
|
-
marginTop: "1rem",
|
560
|
-
paddingRight: "1rem"
|
561
|
-
}
|
562
|
-
});
|
563
|
-
var editorMonospace = EditorView.theme({
|
564
|
-
".cm-content": {
|
565
|
-
fontFamily: fontMono
|
566
|
-
}
|
567
|
-
});
|
568
|
-
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
569
|
-
var stackItemContentEditorClassNames = (role) => mx2("attention-surface dx-focus-ring-inset data-[toolbar=disabled]:pbs-2", role === "section" ? "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-bs-24" : "min-bs-0");
|
570
|
-
var stackItemContentToolbarClassNames = (role) => mx2("attention-surface is-full border-be !border-separator relative z-[1]", role === "section" && "sticky block-start-0 -mbe-px min-is-0");
|
571
|
-
|
572
|
-
// packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
|
573
|
-
var createToolbar = ({ state, customActions, ...features }) => {
|
574
|
-
const nodes = [];
|
575
|
-
const edges = [];
|
576
|
-
if (features.headings ?? true) {
|
577
|
-
const headings2 = createHeadings(state);
|
578
|
-
nodes.push(...headings2.nodes);
|
579
|
-
edges.push(...headings2.edges);
|
580
|
-
}
|
581
|
-
if (features.formatting ?? true) {
|
582
|
-
const formatting = createFormatting(state);
|
583
|
-
nodes.push(...formatting.nodes);
|
584
|
-
edges.push(...formatting.edges);
|
585
|
-
}
|
586
|
-
if (features.lists ?? true) {
|
587
|
-
const lists = createLists(state);
|
588
|
-
nodes.push(...lists.nodes);
|
589
|
-
edges.push(...lists.edges);
|
590
|
-
}
|
591
|
-
if (features.blocks ?? true) {
|
592
|
-
const blocks = createBlocks(state);
|
593
|
-
nodes.push(...blocks.nodes);
|
594
|
-
edges.push(...blocks.edges);
|
595
|
-
}
|
596
|
-
if (customActions) {
|
597
|
-
const custom = customActions();
|
598
|
-
nodes.push(...custom.nodes);
|
599
|
-
edges.push(...custom.edges);
|
600
|
-
}
|
601
|
-
const editorToolbarGap = createGapSeparator();
|
602
|
-
nodes.push(...editorToolbarGap.nodes);
|
603
|
-
edges.push(...editorToolbarGap.edges);
|
604
|
-
if (features.comment ?? true) {
|
605
|
-
const comment = createComment(state);
|
606
|
-
nodes.push(...comment.nodes);
|
607
|
-
edges.push(...comment.edges);
|
608
|
-
}
|
609
|
-
if (features.search ?? true) {
|
610
|
-
nodes.push(editorToolbarSearch);
|
611
|
-
edges.push({
|
612
|
-
source: "root",
|
613
|
-
target: editorToolbarSearch.id
|
614
|
-
});
|
615
|
-
}
|
616
|
-
if (features.viewMode ?? true) {
|
617
|
-
const viewMode = createViewMode(state);
|
618
|
-
nodes.push(...viewMode.nodes);
|
619
|
-
edges.push(...viewMode.edges);
|
620
|
-
}
|
621
|
-
return {
|
622
|
-
nodes,
|
623
|
-
edges
|
624
|
-
};
|
625
|
-
};
|
626
|
-
var useEditorToolbarActionGraph = ({ onAction, ...props }) => {
|
627
|
-
const menuCreator = useCallback(() => createToolbar(props), [
|
628
|
-
props
|
629
|
-
]);
|
630
|
-
const { resolveGroupItems } = useMenuActions(menuCreator);
|
631
|
-
return {
|
632
|
-
resolveGroupItems,
|
633
|
-
onAction
|
634
|
-
};
|
635
|
-
};
|
636
|
-
var EditorToolbar = ({ classNames, attendableId, role, ...props }) => {
|
637
|
-
const menuProps = useEditorToolbarActionGraph(props);
|
638
|
-
return /* @__PURE__ */ React.createElement("div", {
|
639
|
-
role: "none",
|
640
|
-
className: stackItemContentToolbarClassNames(role)
|
641
|
-
}, /* @__PURE__ */ React.createElement(ElevationProvider, {
|
642
|
-
elevation: role === "section" ? "positioned" : "base"
|
643
|
-
}, /* @__PURE__ */ React.createElement(MenuProvider, {
|
644
|
-
...menuProps,
|
645
|
-
attendableId
|
646
|
-
}, /* @__PURE__ */ React.createElement(ToolbarMenu, {
|
647
|
-
classNames: [
|
648
|
-
textBlockWidth,
|
649
|
-
"!bg-transparent",
|
650
|
-
classNames
|
651
|
-
]
|
652
|
-
}))));
|
653
|
-
};
|
654
|
-
|
655
|
-
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
656
|
-
import { StateField } from "@codemirror/state";
|
657
|
-
import { Decoration, EditorView as EditorView2 } from "@codemirror/view";
|
658
|
-
import { isNotFalsy } from "@dxos/util";
|
659
|
-
|
660
|
-
// packages/ui/react-ui-editor/src/util/facet.ts
|
661
|
-
import { Facet } from "@codemirror/state";
|
662
|
-
var singleValueFacet = (defaultValue) => Facet.define({
|
663
|
-
// Called immediately.
|
664
|
-
combine: (providers) => {
|
665
|
-
return providers[0] ?? defaultValue;
|
666
|
-
}
|
667
|
-
});
|
668
|
-
|
669
|
-
// packages/ui/react-ui-editor/src/util/cursor.ts
|
670
|
-
var overlap = (a, b) => a.from <= b.to && a.to >= b.from;
|
671
|
-
var defaultCursorConverter = {
|
672
|
-
toCursor: (position) => position.toString(),
|
673
|
-
fromCursor: (cursor) => parseInt(cursor)
|
674
|
-
};
|
675
|
-
var Cursor = class _Cursor {
|
676
|
-
static {
|
677
|
-
this.converter = singleValueFacet(defaultCursorConverter);
|
678
|
-
}
|
679
|
-
static {
|
680
|
-
this.getCursorFromRange = (state, range) => {
|
681
|
-
const cursorConverter2 = state.facet(_Cursor.converter);
|
682
|
-
const from = cursorConverter2.toCursor(range.from);
|
683
|
-
const to = cursorConverter2.toCursor(range.to, -1);
|
684
|
-
return [
|
685
|
-
from,
|
686
|
-
to
|
687
|
-
].join(":");
|
688
|
-
};
|
689
|
-
}
|
690
|
-
static {
|
691
|
-
this.getRangeFromCursor = (state, cursor) => {
|
692
|
-
const cursorConverter2 = state.facet(_Cursor.converter);
|
693
|
-
const parts = cursor.split(":");
|
694
|
-
const from = cursorConverter2.fromCursor(parts[0]);
|
695
|
-
const to = cursorConverter2.fromCursor(parts[1]);
|
696
|
-
return from !== void 0 && to !== void 0 ? {
|
697
|
-
from,
|
698
|
-
to
|
699
|
-
} : void 0;
|
700
|
-
};
|
701
|
-
}
|
702
|
-
};
|
703
|
-
|
704
|
-
// packages/ui/react-ui-editor/src/util/debug.ts
|
705
|
-
import { log } from "@dxos/log";
|
706
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/debug.ts";
|
707
|
-
var wrapWithCatch = (fn) => {
|
708
|
-
return (...args) => {
|
709
|
-
try {
|
710
|
-
return fn(...args);
|
711
|
-
} catch (err) {
|
712
|
-
log.catch(err, void 0, {
|
713
|
-
F: __dxlog_file,
|
714
|
-
L: 15,
|
715
|
-
S: void 0,
|
716
|
-
C: (f, a) => f(...a)
|
717
|
-
});
|
718
|
-
}
|
719
|
-
};
|
720
|
-
};
|
721
|
-
var callbackWrapper = (fn) => (...args) => {
|
722
|
-
try {
|
723
|
-
return fn(...args);
|
724
|
-
} catch (err) {
|
725
|
-
log.catch(err, void 0, {
|
726
|
-
F: __dxlog_file,
|
727
|
-
L: 29,
|
728
|
-
S: void 0,
|
729
|
-
C: (f, a) => f(...a)
|
730
|
-
});
|
731
|
-
}
|
732
|
-
};
|
733
|
-
var debugDispatcher = (trs, view) => {
|
734
|
-
logChanges(trs);
|
735
|
-
view.update(trs);
|
736
|
-
};
|
737
|
-
var logChanges = (trs) => {
|
738
|
-
const changes = trs.flatMap((tr) => {
|
739
|
-
if (tr.changes.empty) {
|
740
|
-
return void 0;
|
155
|
+
var logChanges = (trs) => {
|
156
|
+
const changes = trs.flatMap((tr) => {
|
157
|
+
if (tr.changes.empty) {
|
158
|
+
return void 0;
|
741
159
|
}
|
742
160
|
const changes2 = [];
|
743
161
|
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
@@ -789,7 +207,7 @@ var clientRectsFor = (dom) => {
|
|
789
207
|
};
|
790
208
|
|
791
209
|
// packages/ui/react-ui-editor/src/util/react.tsx
|
792
|
-
import
|
210
|
+
import React from "react";
|
793
211
|
import { createRoot } from "react-dom/client";
|
794
212
|
import { ThemeProvider, Tooltip } from "@dxos/react-ui";
|
795
213
|
import { defaultTx } from "@dxos/react-ui-theme";
|
@@ -806,15 +224,15 @@ var createElement = (tag, options, children) => {
|
|
806
224
|
return el;
|
807
225
|
};
|
808
226
|
var renderRoot = (root, node) => {
|
809
|
-
createRoot(root).render(/* @__PURE__ */
|
227
|
+
createRoot(root).render(/* @__PURE__ */ React.createElement(ThemeProvider, {
|
810
228
|
tx: defaultTx
|
811
229
|
}, node));
|
812
230
|
return root;
|
813
231
|
};
|
814
232
|
var createRenderer = (Component) => (el, props) => {
|
815
|
-
renderRoot(el, /* @__PURE__ */
|
233
|
+
renderRoot(el, /* @__PURE__ */ React.createElement(ThemeProvider, {
|
816
234
|
tx: defaultTx
|
817
|
-
}, /* @__PURE__ */
|
235
|
+
}, /* @__PURE__ */ React.createElement(Tooltip.Provider, null, /* @__PURE__ */ React.createElement(Component, props))));
|
818
236
|
};
|
819
237
|
|
820
238
|
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
@@ -854,7 +272,7 @@ var annotations = (options = {}) => {
|
|
854
272
|
});
|
855
273
|
return [
|
856
274
|
annotationsState,
|
857
|
-
|
275
|
+
EditorView.decorations.compute([
|
858
276
|
annotationsState
|
859
277
|
], (state) => {
|
860
278
|
const annotations2 = state.field(annotationsState);
|
@@ -867,7 +285,7 @@ var annotations = (options = {}) => {
|
|
867
285
|
styles
|
868
286
|
];
|
869
287
|
};
|
870
|
-
var styles =
|
288
|
+
var styles = EditorView.theme({
|
871
289
|
".cm-annotation": {
|
872
290
|
textDecoration: "underline",
|
873
291
|
textDecorationStyle: "wavy",
|
@@ -915,9 +333,9 @@ var autocomplete = ({ debug, activateOnTyping, override, onSearch } = {}) => {
|
|
915
333
|
};
|
916
334
|
|
917
335
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
336
|
+
import { next as A3 } from "@automerge/automerge";
|
918
337
|
import { StateField as StateField2 } from "@codemirror/state";
|
919
|
-
import { EditorView as
|
920
|
-
import { next as A3 } from "@dxos/automerge/automerge";
|
338
|
+
import { EditorView as EditorView2, ViewPlugin } from "@codemirror/view";
|
921
339
|
|
922
340
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
923
341
|
import { log as log2 } from "@dxos/log";
|
@@ -966,10 +384,10 @@ var isReconcile = (tr) => {
|
|
966
384
|
};
|
967
385
|
|
968
386
|
// packages/ui/react-ui-editor/src/extensions/automerge/sync.ts
|
969
|
-
import { next as A2 } from "@
|
387
|
+
import { next as A2 } from "@automerge/automerge";
|
970
388
|
|
971
389
|
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
972
|
-
import { next as A } from "@
|
390
|
+
import { next as A } from "@automerge/automerge";
|
973
391
|
var updateAutomerge = (field, handle, transactions, state) => {
|
974
392
|
const { lastHeads, path } = state.field(field);
|
975
393
|
let hasChanges = false;
|
@@ -1138,8 +556,8 @@ var Syncer = class {
|
|
1138
556
|
}
|
1139
557
|
onAutomergeChange(view) {
|
1140
558
|
const oldHeads = getLastHeads(view.state, this._state);
|
1141
|
-
const newHeads = A2.getHeads(this._handle.
|
1142
|
-
const diff = A2.equals(oldHeads, newHeads) ? [] : A2.diff(this._handle.
|
559
|
+
const newHeads = A2.getHeads(this._handle.doc());
|
560
|
+
const diff = A2.equals(oldHeads, newHeads) ? [] : A2.diff(this._handle.doc(), oldHeads, newHeads);
|
1143
561
|
const selection = view.state.selection;
|
1144
562
|
const path = getPath(view.state, this._state);
|
1145
563
|
updateCodeMirror(view, selection, path, diff);
|
@@ -1155,7 +573,7 @@ var automerge = (accessor) => {
|
|
1155
573
|
const syncState = StateField2.define({
|
1156
574
|
create: () => ({
|
1157
575
|
path: accessor.path.slice(),
|
1158
|
-
lastHeads: A3.getHeads(accessor.handle.
|
576
|
+
lastHeads: A3.getHeads(accessor.handle.doc()),
|
1159
577
|
unreconciledTransactions: []
|
1160
578
|
}),
|
1161
579
|
update: (value, tr) => {
|
@@ -1200,7 +618,7 @@ var automerge = (accessor) => {
|
|
1200
618
|
}
|
1201
619
|
}),
|
1202
620
|
// Reconcile local updates.
|
1203
|
-
|
621
|
+
EditorView2.updateListener.of(({ view, changes }) => {
|
1204
622
|
if (!changes.empty) {
|
1205
623
|
syncer.reconcile(view, true);
|
1206
624
|
}
|
@@ -1210,7 +628,7 @@ var automerge = (accessor) => {
|
|
1210
628
|
|
1211
629
|
// packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts
|
1212
630
|
import { Annotation as Annotation2, RangeSet } from "@codemirror/state";
|
1213
|
-
import { Decoration as Decoration2, EditorView as
|
631
|
+
import { Decoration as Decoration2, EditorView as EditorView3, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
1214
632
|
import { Event } from "@dxos/async";
|
1215
633
|
import { Context } from "@dxos/context";
|
1216
634
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts";
|
@@ -1384,7 +802,7 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
1384
802
|
return true;
|
1385
803
|
}
|
1386
804
|
};
|
1387
|
-
var styles2 =
|
805
|
+
var styles2 = EditorView3.theme({
|
1388
806
|
".cm-collab-selection": {},
|
1389
807
|
".cm-collab-selectionLine": {
|
1390
808
|
padding: 0,
|
@@ -1550,7 +968,7 @@ var SpaceAwarenessProvider = class {
|
|
1550
968
|
};
|
1551
969
|
|
1552
970
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
1553
|
-
import { EditorView as
|
971
|
+
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
1554
972
|
import defaultsDeep from "lodash.defaultsdeep";
|
1555
973
|
import { invariant as invariant2 } from "@dxos/invariant";
|
1556
974
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
@@ -1598,7 +1016,7 @@ var blast = (options = defaultOptions) => {
|
|
1598
1016
|
};
|
1599
1017
|
return [
|
1600
1018
|
// Cursor moved.
|
1601
|
-
|
1019
|
+
EditorView4.updateListener.of((update2) => {
|
1602
1020
|
if (blaster?.node !== update2.view.scrollDOM) {
|
1603
1021
|
if (blaster) {
|
1604
1022
|
blaster.destroy();
|
@@ -1972,11 +1390,11 @@ var commandKeyBindings = [
|
|
1972
1390
|
];
|
1973
1391
|
|
1974
1392
|
// packages/ui/react-ui-editor/src/extensions/command/command.ts
|
1975
|
-
import { EditorView as
|
1393
|
+
import { EditorView as EditorView6, keymap as keymap3 } from "@codemirror/view";
|
1976
1394
|
|
1977
1395
|
// packages/ui/react-ui-editor/src/extensions/command/hint.ts
|
1978
1396
|
import { RangeSetBuilder } from "@codemirror/state";
|
1979
|
-
import { Decoration as Decoration3, EditorView as
|
1397
|
+
import { Decoration as Decoration3, EditorView as EditorView5, ViewPlugin as ViewPlugin3, WidgetType as WidgetType2 } from "@codemirror/view";
|
1980
1398
|
var hintViewPlugin = ({ onHint }) => ViewPlugin3.fromClass(class {
|
1981
1399
|
constructor() {
|
1982
1400
|
this.deco = Decoration3.none;
|
@@ -2000,7 +1418,7 @@ var hintViewPlugin = ({ onHint }) => ViewPlugin3.fromClass(class {
|
|
2000
1418
|
}
|
2001
1419
|
}, {
|
2002
1420
|
provide: (plugin) => [
|
2003
|
-
|
1421
|
+
EditorView5.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration3.none)
|
2004
1422
|
]
|
2005
1423
|
});
|
2006
1424
|
var CommandHint = class extends WidgetType2 {
|
@@ -2119,10 +1537,10 @@ var command = (options = {}) => {
|
|
2119
1537
|
options.onHint ? hintViewPlugin({
|
2120
1538
|
onHint: options.onHint
|
2121
1539
|
}) : [],
|
2122
|
-
|
1540
|
+
EditorView6.focusChangeEffect.of((_, focusing) => {
|
2123
1541
|
return focusing ? closeEffect.of(null) : null;
|
2124
1542
|
}),
|
2125
|
-
|
1543
|
+
EditorView6.theme({
|
2126
1544
|
".cm-tooltip": {
|
2127
1545
|
background: "transparent"
|
2128
1546
|
}
|
@@ -2133,7 +1551,7 @@ var command = (options = {}) => {
|
|
2133
1551
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
2134
1552
|
import { invertedEffects } from "@codemirror/commands";
|
2135
1553
|
import { StateEffect as StateEffect3, StateField as StateField4 } from "@codemirror/state";
|
2136
|
-
import { hoverTooltip, keymap as keymap5, Decoration as Decoration4, EditorView as
|
1554
|
+
import { hoverTooltip, keymap as keymap5, Decoration as Decoration4, EditorView as EditorView8, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
2137
1555
|
import sortBy from "lodash.sortby";
|
2138
1556
|
import { useEffect, useMemo as useMemo2 } from "react";
|
2139
1557
|
import { debounce as debounce2 } from "@dxos/async";
|
@@ -2142,7 +1560,7 @@ import { isNonNullable } from "@dxos/util";
|
|
2142
1560
|
|
2143
1561
|
// packages/ui/react-ui-editor/src/extensions/selection.ts
|
2144
1562
|
import { Transaction } from "@codemirror/state";
|
2145
|
-
import { EditorView as
|
1563
|
+
import { EditorView as EditorView7, keymap as keymap4 } from "@codemirror/view";
|
2146
1564
|
import { debounce } from "@dxos/async";
|
2147
1565
|
import { invariant as invariant3 } from "@dxos/invariant";
|
2148
1566
|
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
@@ -2153,7 +1571,7 @@ var createEditorStateTransaction = ({ scrollTo, selection }) => {
|
|
2153
1571
|
return {
|
2154
1572
|
selection,
|
2155
1573
|
scrollIntoView: !scrollTo,
|
2156
|
-
effects: scrollTo ?
|
1574
|
+
effects: scrollTo ? EditorView7.scrollIntoView(scrollTo, {
|
2157
1575
|
yMargin: 96
|
2158
1576
|
}) : void 0,
|
2159
1577
|
annotations: Transaction.userEvent.of(stateRestoreAnnotation)
|
@@ -2195,7 +1613,7 @@ var selectionState = ({ getState, setState } = {}) => {
|
|
2195
1613
|
// setStateDebounced(id, {});
|
2196
1614
|
// },
|
2197
1615
|
// }),
|
2198
|
-
|
1616
|
+
EditorView7.updateListener.of(({ view, transactions }) => {
|
2199
1617
|
const id = view.state.facet(documentId);
|
2200
1618
|
if (!id || transactions.some((tr) => tr.isUserEvent(stateRestoreAnnotation))) {
|
2201
1619
|
return;
|
@@ -2276,7 +1694,7 @@ var commentsState = StateField4.define({
|
|
2276
1694
|
return value;
|
2277
1695
|
}
|
2278
1696
|
});
|
2279
|
-
var styles3 =
|
1697
|
+
var styles3 = EditorView8.theme({
|
2280
1698
|
".cm-comment, .cm-comment-current": {
|
2281
1699
|
margin: "0 -3px",
|
2282
1700
|
padding: "3px",
|
@@ -2296,7 +1714,7 @@ var createCommentMark = (id, isCurrent) => Decoration4.mark({
|
|
2296
1714
|
"data-comment-id": id
|
2297
1715
|
}
|
2298
1716
|
});
|
2299
|
-
var commentsDecorations =
|
1717
|
+
var commentsDecorations = EditorView8.decorations.compute([
|
2300
1718
|
commentsState
|
2301
1719
|
], (state) => {
|
2302
1720
|
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
@@ -2319,7 +1737,7 @@ var commentsDecorations = EditorView9.decorations.compute([
|
|
2319
1737
|
return Decoration4.set(decorations);
|
2320
1738
|
});
|
2321
1739
|
var commentClickedEffect = StateEffect3.define();
|
2322
|
-
var handleCommentClick =
|
1740
|
+
var handleCommentClick = EditorView8.domEventHandlers({
|
2323
1741
|
click: (event, view) => {
|
2324
1742
|
let target = event.target;
|
2325
1743
|
const editorRoot = view.dom;
|
@@ -2358,7 +1776,7 @@ var trackPastedComments = (onUpdate) => {
|
|
2358
1776
|
}
|
2359
1777
|
};
|
2360
1778
|
return [
|
2361
|
-
|
1779
|
+
EditorView8.domEventHandlers({
|
2362
1780
|
cut: handleTrack,
|
2363
1781
|
copy: handleTrack
|
2364
1782
|
}),
|
@@ -2380,7 +1798,7 @@ var trackPastedComments = (onUpdate) => {
|
|
2380
1798
|
return effects;
|
2381
1799
|
}),
|
2382
1800
|
// Handle paste or the undo of comment deletion.
|
2383
|
-
|
1801
|
+
EditorView8.updateListener.of((update2) => {
|
2384
1802
|
const restore = [];
|
2385
1803
|
for (let i = 0; i < update2.transactions.length; i++) {
|
2386
1804
|
const tr = update2.transactions[i];
|
@@ -2439,7 +1857,7 @@ var mapTrackedComment = (comment, changes) => ({
|
|
2439
1857
|
var restoreCommentEffect = StateEffect3.define({
|
2440
1858
|
map: mapTrackedComment
|
2441
1859
|
});
|
2442
|
-
var
|
1860
|
+
var createComment = (view) => {
|
2443
1861
|
const options = view.state.facet(optionsFacet);
|
2444
1862
|
const { from, to } = view.state.selection.main;
|
2445
1863
|
if (from === to) {
|
@@ -2484,7 +1902,7 @@ var comments = (options = {}) => {
|
|
2484
1902
|
options.onCreate && keymap5.of([
|
2485
1903
|
{
|
2486
1904
|
key: shortcut,
|
2487
|
-
run: callbackWrapper(
|
1905
|
+
run: callbackWrapper(createComment)
|
2488
1906
|
}
|
2489
1907
|
]),
|
2490
1908
|
//
|
@@ -2522,7 +1940,7 @@ var comments = (options = {}) => {
|
|
2522
1940
|
//
|
2523
1941
|
// Track deleted ranges and update ranges for decorations.
|
2524
1942
|
//
|
2525
|
-
|
1943
|
+
EditorView8.updateListener.of(({ view, state, changes }) => {
|
2526
1944
|
let mod = false;
|
2527
1945
|
const { comments: comments2, ...value } = state.field(commentsState);
|
2528
1946
|
changes.iterChanges((from, to, from2, to2) => {
|
@@ -2554,7 +1972,7 @@ var comments = (options = {}) => {
|
|
2554
1972
|
//
|
2555
1973
|
// Track selection/proximity.
|
2556
1974
|
//
|
2557
|
-
|
1975
|
+
EditorView8.updateListener.of(({ view, state }) => {
|
2558
1976
|
let min = Infinity;
|
2559
1977
|
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
2560
1978
|
const { head } = state.selection.main;
|
@@ -2608,7 +2026,7 @@ var scrollThreadIntoView = (view, id, center = true) => {
|
|
2608
2026
|
anchor: range.from
|
2609
2027
|
} : void 0,
|
2610
2028
|
effects: [
|
2611
|
-
needsScroll ?
|
2029
|
+
needsScroll ? EditorView8.scrollIntoView(range.from, center ? {
|
2612
2030
|
y: "center"
|
2613
2031
|
} : void 0) : [],
|
2614
2032
|
needsSelectionUpdate ? setSelection.of({
|
@@ -2660,7 +2078,7 @@ var createExternalCommentSync = (id, subscribe, getComments) => ViewPlugin5.from
|
|
2660
2078
|
}
|
2661
2079
|
});
|
2662
2080
|
var useCommentState = (state) => {
|
2663
|
-
return useMemo2(() =>
|
2081
|
+
return useMemo2(() => EditorView8.updateListener.of((update2) => {
|
2664
2082
|
if (update2.docChanged || update2.selectionSet) {
|
2665
2083
|
state.comment = selectionOverlapsComment(update2.state);
|
2666
2084
|
state.selection = hasActiveSelection(update2.state);
|
@@ -2684,7 +2102,7 @@ var useComments = (view, id, comments2) => {
|
|
2684
2102
|
});
|
2685
2103
|
};
|
2686
2104
|
var useCommentClickListener = (onCommentClick) => {
|
2687
|
-
return useMemo2(() =>
|
2105
|
+
return useMemo2(() => EditorView8.updateListener.of((update2) => {
|
2688
2106
|
update2.transactions.forEach((transaction) => {
|
2689
2107
|
transaction.effects.forEach((effect) => {
|
2690
2108
|
if (effect.is(commentClickedEffect)) {
|
@@ -2700,9 +2118,9 @@ var useCommentClickListener = (onCommentClick) => {
|
|
2700
2118
|
// packages/ui/react-ui-editor/src/extensions/debug.ts
|
2701
2119
|
import { syntaxTree } from "@codemirror/language";
|
2702
2120
|
import { StateField as StateField5 } from "@codemirror/state";
|
2703
|
-
var debugNodeLogger = (
|
2121
|
+
var debugNodeLogger = (log9 = console.log) => {
|
2704
2122
|
const logTokens = (state) => syntaxTree(state).iterate({
|
2705
|
-
enter: (node) =>
|
2123
|
+
enter: (node) => log9(node.type)
|
2706
2124
|
});
|
2707
2125
|
return StateField5.define({
|
2708
2126
|
create: (state) => logTokens(state),
|
@@ -2711,8 +2129,8 @@ var debugNodeLogger = (log8 = console.log) => {
|
|
2711
2129
|
};
|
2712
2130
|
|
2713
2131
|
// packages/ui/react-ui-editor/src/extensions/dnd.ts
|
2714
|
-
import { dropCursor, EditorView as
|
2715
|
-
var styles4 =
|
2132
|
+
import { dropCursor, EditorView as EditorView9 } from "@codemirror/view";
|
2133
|
+
var styles4 = EditorView9.theme({
|
2716
2134
|
".cm-dropCursor": {
|
2717
2135
|
borderLeft: "2px solid var(--dx-accentText)",
|
2718
2136
|
color: "var(--dx-accentText)",
|
@@ -2726,7 +2144,7 @@ var dropFile = (options = {}) => {
|
|
2726
2144
|
return [
|
2727
2145
|
styles4,
|
2728
2146
|
dropCursor(),
|
2729
|
-
|
2147
|
+
EditorView9.domEventHandlers({
|
2730
2148
|
drop: (event, view) => {
|
2731
2149
|
event.preventDefault();
|
2732
2150
|
const files = event.dataTransfer?.files;
|
@@ -2753,7 +2171,7 @@ import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@cod
|
|
2753
2171
|
import { searchKeymap } from "@codemirror/search";
|
2754
2172
|
import { EditorState } from "@codemirror/state";
|
2755
2173
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
2756
|
-
import { EditorView as
|
2174
|
+
import { EditorView as EditorView11, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap6, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
|
2757
2175
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
2758
2176
|
import merge from "lodash.merge";
|
2759
2177
|
import { generateName } from "@dxos/display-name";
|
@@ -2762,7 +2180,7 @@ import { hexToHue, isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
2762
2180
|
|
2763
2181
|
// packages/ui/react-ui-editor/src/extensions/focus.ts
|
2764
2182
|
import { StateEffect as StateEffect4, StateField as StateField6 } from "@codemirror/state";
|
2765
|
-
import { EditorView as
|
2183
|
+
import { EditorView as EditorView10 } from "@codemirror/view";
|
2766
2184
|
var focusEffect = StateEffect4.define();
|
2767
2185
|
var focusField = StateField6.define({
|
2768
2186
|
create: () => false,
|
@@ -2777,19 +2195,254 @@ var focusField = StateField6.define({
|
|
2777
2195
|
});
|
2778
2196
|
var focus = [
|
2779
2197
|
focusField,
|
2780
|
-
|
2198
|
+
EditorView10.domEventHandlers({
|
2781
2199
|
focus: (event, view) => {
|
2782
2200
|
setTimeout(() => view.dispatch({
|
2783
2201
|
effects: focusEffect.of(true)
|
2784
2202
|
}));
|
2785
2203
|
},
|
2786
|
-
blur: (event, view) => {
|
2787
|
-
setTimeout(() => view.dispatch({
|
2788
|
-
effects: focusEffect.of(false)
|
2789
|
-
}));
|
2204
|
+
blur: (event, view) => {
|
2205
|
+
setTimeout(() => view.dispatch({
|
2206
|
+
effects: focusEffect.of(false)
|
2207
|
+
}));
|
2208
|
+
}
|
2209
|
+
})
|
2210
|
+
];
|
2211
|
+
|
2212
|
+
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
2213
|
+
import { mx } from "@dxos/react-ui-theme";
|
2214
|
+
var headings = {
|
2215
|
+
1: "text-4xl",
|
2216
|
+
2: "text-3xl",
|
2217
|
+
3: "text-2xl",
|
2218
|
+
4: "text-xl",
|
2219
|
+
5: "text-lg",
|
2220
|
+
6: ""
|
2221
|
+
};
|
2222
|
+
var theme = {
|
2223
|
+
code: "font-mono !no-underline text-neutral-700 dark:text-neutral-300",
|
2224
|
+
codeMark: "font-mono text-primary-500",
|
2225
|
+
mark: "opacity-50",
|
2226
|
+
heading: (level) => {
|
2227
|
+
return mx(headings[level], "dark:text-primary-400");
|
2228
|
+
}
|
2229
|
+
};
|
2230
|
+
|
2231
|
+
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
2232
|
+
import get from "lodash.get";
|
2233
|
+
import { tokens } from "@dxos/react-ui-theme";
|
2234
|
+
var getToken = (path, defaultValue) => {
|
2235
|
+
const value = get(tokens, path, defaultValue);
|
2236
|
+
return value?.toString() ?? "";
|
2237
|
+
};
|
2238
|
+
var fontBody = getToken("fontFamily.body");
|
2239
|
+
var fontMono = getToken("fontFamily.mono");
|
2240
|
+
|
2241
|
+
// packages/ui/react-ui-editor/src/styles/theme.ts
|
2242
|
+
var defaultTheme = {
|
2243
|
+
"&": {},
|
2244
|
+
"&.cm-focused": {
|
2245
|
+
outline: "none"
|
2246
|
+
},
|
2247
|
+
/**
|
2248
|
+
* Scroller
|
2249
|
+
*/
|
2250
|
+
".cm-scroller": {
|
2251
|
+
overflowY: "auto"
|
2252
|
+
},
|
2253
|
+
/**
|
2254
|
+
* Content
|
2255
|
+
* NOTE: Apply margins to content so that scrollbar is at the edge of the container.
|
2256
|
+
*/
|
2257
|
+
".cm-content": {
|
2258
|
+
padding: "unset",
|
2259
|
+
fontFamily: fontBody,
|
2260
|
+
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
2261
|
+
fontSize: "16px",
|
2262
|
+
lineHeight: 1.5,
|
2263
|
+
color: "unset"
|
2264
|
+
},
|
2265
|
+
/**
|
2266
|
+
* Gutters
|
2267
|
+
* NOTE: Gutters should have the same top margin as the content.
|
2268
|
+
*/
|
2269
|
+
".cm-gutters": {
|
2270
|
+
borderRight: "none",
|
2271
|
+
background: "transparent"
|
2272
|
+
},
|
2273
|
+
".cm-gutter": {},
|
2274
|
+
".cm-gutter.cm-lineNumbers": {
|
2275
|
+
paddingRight: "4px",
|
2276
|
+
borderRight: "1px solid var(--dx-separator)"
|
2277
|
+
},
|
2278
|
+
".cm-gutter.cm-lineNumbers .cm-gutterElement": {
|
2279
|
+
minWidth: "40px",
|
2280
|
+
alignContent: "center"
|
2281
|
+
},
|
2282
|
+
/**
|
2283
|
+
* Height is set to match the corresponding line.
|
2284
|
+
*/
|
2285
|
+
".cm-gutterElement": {
|
2286
|
+
alignItems: "center",
|
2287
|
+
fontSize: "12px"
|
2288
|
+
},
|
2289
|
+
/**
|
2290
|
+
* Line.
|
2291
|
+
*/
|
2292
|
+
".cm-line": {
|
2293
|
+
paddingInline: 0
|
2294
|
+
},
|
2295
|
+
".cm-activeLine": {
|
2296
|
+
background: "var(--dx-cmActiveLine)"
|
2297
|
+
},
|
2298
|
+
/**
|
2299
|
+
* Cursor (layer).
|
2300
|
+
*/
|
2301
|
+
".cm-cursor, .cm-dropCursor": {
|
2302
|
+
borderLeft: "2px solid var(--dx-cmCursor)"
|
2303
|
+
},
|
2304
|
+
".cm-placeholder": {
|
2305
|
+
color: "var(--dx-subdued)"
|
2306
|
+
},
|
2307
|
+
/**
|
2308
|
+
* Selection (layer).
|
2309
|
+
*/
|
2310
|
+
".cm-selectionBackground": {
|
2311
|
+
background: "var(--dx-cmSelection)"
|
2312
|
+
},
|
2313
|
+
"&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
2314
|
+
background: "var(--dx-cmFocusedSelection)"
|
2315
|
+
},
|
2316
|
+
/**
|
2317
|
+
* Search.
|
2318
|
+
* NOTE: Matches comment.
|
2319
|
+
*/
|
2320
|
+
".cm-searchMatch": {
|
2321
|
+
margin: "0 -3px",
|
2322
|
+
padding: "3px",
|
2323
|
+
borderRadius: "3px",
|
2324
|
+
background: "var(--dx-cmHighlightSurface)",
|
2325
|
+
color: "var(--dx-cmHighlight)"
|
2326
|
+
},
|
2327
|
+
".cm-searchMatch-selected": {
|
2328
|
+
textDecoration: "underline"
|
2329
|
+
},
|
2330
|
+
/**
|
2331
|
+
* Link.
|
2332
|
+
*/
|
2333
|
+
".cm-link": {
|
2334
|
+
textDecorationLine: "underline",
|
2335
|
+
textDecorationThickness: "1px",
|
2336
|
+
textDecorationColor: "var(--dx-separator)",
|
2337
|
+
textUnderlineOffset: "2px",
|
2338
|
+
borderRadius: ".125rem"
|
2339
|
+
},
|
2340
|
+
".cm-link > span": {
|
2341
|
+
color: "var(--dx-accentText)"
|
2342
|
+
},
|
2343
|
+
/**
|
2344
|
+
* Tooltip.
|
2345
|
+
*/
|
2346
|
+
".cm-tooltip": {
|
2347
|
+
background: "var(--dx-baseSurface)"
|
2348
|
+
},
|
2349
|
+
".cm-tooltip-below": {},
|
2350
|
+
/**
|
2351
|
+
* Autocomplete.
|
2352
|
+
* https://github.com/codemirror/autocomplete/blob/main/src/completion.ts
|
2353
|
+
*/
|
2354
|
+
".cm-tooltip.cm-tooltip-autocomplete": {
|
2355
|
+
marginTop: "4px",
|
2356
|
+
marginLeft: "-3px"
|
2357
|
+
},
|
2358
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul": {
|
2359
|
+
maxHeight: "20em"
|
2360
|
+
},
|
2361
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > li": {},
|
2362
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {},
|
2363
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
|
2364
|
+
paddingLeft: "4px !important",
|
2365
|
+
borderBottom: "none !important",
|
2366
|
+
color: "var(--dx-accentText)"
|
2367
|
+
},
|
2368
|
+
".cm-tooltip.cm-completionInfo": {
|
2369
|
+
width: "360px !important",
|
2370
|
+
margin: "-10px 1px 0 1px",
|
2371
|
+
padding: "8px !important",
|
2372
|
+
borderColor: "var(--dx-separator)"
|
2373
|
+
},
|
2374
|
+
".cm-completionIcon": {
|
2375
|
+
display: "none"
|
2376
|
+
},
|
2377
|
+
".cm-completionLabel": {
|
2378
|
+
fontFamily: fontBody
|
2379
|
+
},
|
2380
|
+
".cm-completionMatchedText": {
|
2381
|
+
textDecoration: "none !important",
|
2382
|
+
opacity: 0.5
|
2383
|
+
},
|
2384
|
+
/**
|
2385
|
+
* Panels
|
2386
|
+
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
2387
|
+
*
|
2388
|
+
* Find/replace panel.
|
2389
|
+
* <div class="cm-announced">...</div>
|
2390
|
+
* <div class="cm-scroller">...</div>
|
2391
|
+
* <div class="cm-panels cm-panels-bottom">
|
2392
|
+
* <div class="cm-search cm-panel">
|
2393
|
+
* <input class="cm-textfield" />
|
2394
|
+
* <button class="cm-button">...</button>
|
2395
|
+
* <label><input type="checkbox" />...</label>
|
2396
|
+
* </div>
|
2397
|
+
* </div
|
2398
|
+
*/
|
2399
|
+
// TODO(burdon): Implement custom panel (with icon buttons).
|
2400
|
+
".cm-panels": {},
|
2401
|
+
".cm-panel": {
|
2402
|
+
fontFamily: fontBody,
|
2403
|
+
backgroundColor: "var(--surface-bg)"
|
2404
|
+
},
|
2405
|
+
".cm-panel input, .cm-panel button, .cm-panel label": {
|
2406
|
+
color: "var(--dx-subdued)",
|
2407
|
+
fontFamily: fontBody,
|
2408
|
+
fontSize: "14px",
|
2409
|
+
all: "unset",
|
2410
|
+
margin: "3px !important",
|
2411
|
+
padding: "2px 6px !important",
|
2412
|
+
outline: "1px solid transparent"
|
2413
|
+
},
|
2414
|
+
".cm-panel input, .cm-panel button": {
|
2415
|
+
backgroundColor: "var(--dx-input)"
|
2416
|
+
},
|
2417
|
+
".cm-panel input:focus, .cm-panel button:focus": {
|
2418
|
+
outline: "1px solid var(--dx-accentFocusIndicator)"
|
2419
|
+
},
|
2420
|
+
".cm-panel label": {
|
2421
|
+
display: "inline-flex",
|
2422
|
+
alignItems: "center",
|
2423
|
+
cursor: "pointer"
|
2424
|
+
},
|
2425
|
+
".cm-panel input.cm-textfield": {},
|
2426
|
+
".cm-panel input[type=checkbox]": {
|
2427
|
+
width: "8px",
|
2428
|
+
height: "8px",
|
2429
|
+
marginRight: "6px !important",
|
2430
|
+
padding: "2px !important",
|
2431
|
+
color: "var(--dx-accentFocusIndicator)"
|
2432
|
+
},
|
2433
|
+
".cm-panel button": {
|
2434
|
+
"&:hover": {
|
2435
|
+
backgroundColor: "var(--dx-accentSurfaceHover) !important"
|
2436
|
+
},
|
2437
|
+
"&:active": {
|
2438
|
+
backgroundColor: "var(--dx-accentSurfaceHover)"
|
2790
2439
|
}
|
2791
|
-
}
|
2792
|
-
|
2440
|
+
},
|
2441
|
+
".cm-panel.cm-search": {
|
2442
|
+
padding: "4px",
|
2443
|
+
borderTop: "1px solid var(--dx-separator)"
|
2444
|
+
}
|
2445
|
+
};
|
2793
2446
|
|
2794
2447
|
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2795
2448
|
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
|
@@ -2815,7 +2468,7 @@ var createBasicExtensions = (_props) => {
|
|
2815
2468
|
const props = defaultsDeep2({}, _props, defaultBasicOptions);
|
2816
2469
|
return [
|
2817
2470
|
// NOTE: Doesn't catch errors in keymap functions.
|
2818
|
-
|
2471
|
+
EditorView11.exceptionSink.of((err) => {
|
2819
2472
|
log5.catch(err, void 0, {
|
2820
2473
|
F: __dxlog_file8,
|
2821
2474
|
L: 96,
|
@@ -2830,12 +2483,12 @@ var createBasicExtensions = (_props) => {
|
|
2830
2483
|
props.drawSelection && drawSelection({
|
2831
2484
|
cursorBlinkRate: 1200
|
2832
2485
|
}),
|
2833
|
-
props.editable !== void 0 &&
|
2486
|
+
props.editable !== void 0 && EditorView11.editable.of(props.editable),
|
2834
2487
|
props.focus && focus,
|
2835
2488
|
props.highlightActiveLine && highlightActiveLine(),
|
2836
2489
|
props.history && history(),
|
2837
2490
|
props.lineNumbers && lineNumbers(),
|
2838
|
-
props.lineWrapping &&
|
2491
|
+
props.lineWrapping && EditorView11.lineWrapping,
|
2839
2492
|
props.placeholder && placeholder(props.placeholder),
|
2840
2493
|
props.readOnly !== void 0 && EditorState.readOnly.of(props.readOnly),
|
2841
2494
|
props.scrollPastEnd && scrollPastEnd(),
|
@@ -2872,14 +2525,14 @@ var defaultThemeSlots = {
|
|
2872
2525
|
var createThemeExtensions = ({ themeMode, styles: styles5, syntaxHighlighting: _syntaxHighlighting, slots: _slots } = {}) => {
|
2873
2526
|
const slots = defaultsDeep2({}, _slots, defaultThemeSlots);
|
2874
2527
|
return [
|
2875
|
-
|
2876
|
-
|
2528
|
+
EditorView11.darkTheme.of(themeMode === "dark"),
|
2529
|
+
EditorView11.baseTheme(styles5 ? merge({}, defaultTheme, styles5) : defaultTheme),
|
2877
2530
|
// https://github.com/codemirror/theme-one-dark
|
2878
2531
|
_syntaxHighlighting && (themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)),
|
2879
|
-
slots.editor?.className &&
|
2532
|
+
slots.editor?.className && EditorView11.editorAttributes.of({
|
2880
2533
|
class: slots.editor.className
|
2881
2534
|
}),
|
2882
|
-
slots.content?.className &&
|
2535
|
+
slots.content?.className && EditorView11.contentAttributes.of({
|
2883
2536
|
class: slots.content.className
|
2884
2537
|
})
|
2885
2538
|
].filter(isNotFalsy3);
|
@@ -2908,8 +2561,8 @@ var createDataExtensions = ({ id, text, space, identity }) => {
|
|
2908
2561
|
|
2909
2562
|
// packages/ui/react-ui-editor/src/extensions/folding.tsx
|
2910
2563
|
import { codeFolding, foldGutter } from "@codemirror/language";
|
2911
|
-
import { EditorView as
|
2912
|
-
import
|
2564
|
+
import { EditorView as EditorView12 } from "@codemirror/view";
|
2565
|
+
import React2 from "react";
|
2913
2566
|
import { Icon } from "@dxos/react-ui";
|
2914
2567
|
var folding = (_props = {}) => [
|
2915
2568
|
codeFolding({
|
@@ -2922,7 +2575,7 @@ var folding = (_props = {}) => [
|
|
2922
2575
|
const el = createElement("div", {
|
2923
2576
|
className: "flex h-full items-center"
|
2924
2577
|
});
|
2925
|
-
return renderRoot(el, /* @__PURE__ */
|
2578
|
+
return renderRoot(el, /* @__PURE__ */ React2.createElement(Icon, {
|
2926
2579
|
icon: "ph--caret-right--bold",
|
2927
2580
|
size: 3,
|
2928
2581
|
classNames: [
|
@@ -2932,7 +2585,7 @@ var folding = (_props = {}) => [
|
|
2932
2585
|
}));
|
2933
2586
|
}
|
2934
2587
|
}),
|
2935
|
-
|
2588
|
+
EditorView12.theme({
|
2936
2589
|
".cm-foldGutter": {
|
2937
2590
|
opacity: 0.3,
|
2938
2591
|
transition: "opacity 0.3s",
|
@@ -2945,14 +2598,14 @@ var folding = (_props = {}) => [
|
|
2945
2598
|
];
|
2946
2599
|
|
2947
2600
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
2948
|
-
import { EditorView as
|
2601
|
+
import { EditorView as EditorView13 } from "@codemirror/view";
|
2949
2602
|
var listener = ({ onFocus, onChange }) => {
|
2950
2603
|
const extensions = [];
|
2951
|
-
onFocus && extensions.push(
|
2604
|
+
onFocus && extensions.push(EditorView13.focusChangeEffect.of((_, focusing) => {
|
2952
2605
|
onFocus(focusing);
|
2953
2606
|
return null;
|
2954
2607
|
}));
|
2955
|
-
onChange && extensions.push(
|
2608
|
+
onChange && extensions.push(EditorView13.updateListener.of((update2) => {
|
2956
2609
|
onChange(update2.state.doc.toString(), update2.state.facet(documentId));
|
2957
2610
|
}));
|
2958
2611
|
return extensions;
|
@@ -2962,7 +2615,7 @@ var listener = ({ onFocus, onChange }) => {
|
|
2962
2615
|
import { snippet } from "@codemirror/autocomplete";
|
2963
2616
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
2964
2617
|
import { EditorSelection } from "@codemirror/state";
|
2965
|
-
import { EditorView as
|
2618
|
+
import { EditorView as EditorView14, keymap as keymap7 } from "@codemirror/view";
|
2966
2619
|
import { useMemo as useMemo3 } from "react";
|
2967
2620
|
var formattingEquals = (a, b) => a.blockType === b.blockType && a.strong === b.strong && a.emphasis === b.emphasis && a.strikethrough === b.strikethrough && a.code === b.code && a.link === b.link && a.listStyle === b.listStyle && a.blockQuote === b.blockQuote;
|
2968
2621
|
var Inline;
|
@@ -4051,7 +3704,7 @@ var getFormatting = (state) => {
|
|
4051
3704
|
};
|
4052
3705
|
};
|
4053
3706
|
var useFormattingState = (state) => {
|
4054
|
-
return useMemo3(() =>
|
3707
|
+
return useMemo3(() => EditorView14.updateListener.of((update2) => {
|
4055
3708
|
if (update2.docChanged || update2.selectionSet) {
|
4056
3709
|
Object.entries(getFormatting(update2.state)).forEach(([key, active]) => {
|
4057
3710
|
state[key] = active;
|
@@ -4099,7 +3752,7 @@ var processEditorPayload = (view, { type, data }) => {
|
|
4099
3752
|
})(view);
|
4100
3753
|
break;
|
4101
3754
|
case "comment":
|
4102
|
-
|
3755
|
+
createComment(view);
|
4103
3756
|
break;
|
4104
3757
|
}
|
4105
3758
|
requestAnimationFrame(() => {
|
@@ -4363,9 +4016,9 @@ var convertTreeToJson = (state) => {
|
|
4363
4016
|
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
4364
4017
|
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
4365
4018
|
import { RangeSetBuilder as RangeSetBuilder3, StateEffect as StateEffect5 } from "@codemirror/state";
|
4366
|
-
import { EditorView as
|
4019
|
+
import { EditorView as EditorView18, Decoration as Decoration7, WidgetType as WidgetType5, ViewPlugin as ViewPlugin7 } from "@codemirror/view";
|
4367
4020
|
import { invariant as invariant4 } from "@dxos/invariant";
|
4368
|
-
import { mx as
|
4021
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
4369
4022
|
|
4370
4023
|
// packages/ui/react-ui-editor/src/extensions/markdown/changes.ts
|
4371
4024
|
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
@@ -4415,11 +4068,11 @@ var adjustChanges = () => {
|
|
4415
4068
|
if (url) {
|
4416
4069
|
const node = tree.resolveInner(fromA, -1);
|
4417
4070
|
const invalidPositions = /* @__PURE__ */ new Set([
|
4418
|
-
"Link",
|
4419
|
-
"LinkMark",
|
4420
4071
|
"Code",
|
4421
4072
|
"CodeText",
|
4422
4073
|
"FencedCode",
|
4074
|
+
"Link",
|
4075
|
+
"LinkMark",
|
4423
4076
|
"URL"
|
4424
4077
|
]);
|
4425
4078
|
if (!invalidPositions.has(node?.name)) {
|
@@ -4514,7 +4167,7 @@ var getValidUrl = (str) => {
|
|
4514
4167
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
4515
4168
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
4516
4169
|
import { StateField as StateField8 } from "@codemirror/state";
|
4517
|
-
import { Decoration as Decoration5, EditorView as
|
4170
|
+
import { Decoration as Decoration5, EditorView as EditorView15, WidgetType as WidgetType3 } from "@codemirror/view";
|
4518
4171
|
var image = (_options = {}) => {
|
4519
4172
|
return [
|
4520
4173
|
StateField8.define({
|
@@ -4542,7 +4195,7 @@ var image = (_options = {}) => {
|
|
4542
4195
|
add: buildDecorations(from, to, tr.state)
|
4543
4196
|
});
|
4544
4197
|
},
|
4545
|
-
provide: (field) =>
|
4198
|
+
provide: (field) => EditorView15.decorations.from(field)
|
4546
4199
|
})
|
4547
4200
|
];
|
4548
4201
|
};
|
@@ -4602,10 +4255,10 @@ var ImageWidget = class extends WidgetType3 {
|
|
4602
4255
|
};
|
4603
4256
|
|
4604
4257
|
// packages/ui/react-ui-editor/src/extensions/markdown/styles.ts
|
4605
|
-
import { EditorView as
|
4258
|
+
import { EditorView as EditorView16 } from "@codemirror/view";
|
4606
4259
|
var bulletListIndentationWidth = 24;
|
4607
4260
|
var orderedListIndentationWidth = 36;
|
4608
|
-
var formattingStyles =
|
4261
|
+
var formattingStyles = EditorView16.theme({
|
4609
4262
|
/**
|
4610
4263
|
* Horizontal rule.
|
4611
4264
|
*/
|
@@ -4652,11 +4305,11 @@ var formattingStyles = EditorView17.theme({
|
|
4652
4305
|
background: "var(--dx-cmCodeblock)",
|
4653
4306
|
paddingInline: "1rem !important"
|
4654
4307
|
},
|
4655
|
-
"& .cm-codeblock-
|
4308
|
+
"& .cm-codeblock-start": {
|
4656
4309
|
borderTopLeftRadius: ".25rem",
|
4657
4310
|
borderTopRightRadius: ".25rem"
|
4658
4311
|
},
|
4659
|
-
"& .cm-codeblock-
|
4312
|
+
"& .cm-codeblock-end": {
|
4660
4313
|
borderBottomLeftRadius: ".25rem",
|
4661
4314
|
borderBottomRightRadius: ".25rem"
|
4662
4315
|
},
|
@@ -4726,12 +4379,12 @@ var formattingStyles = EditorView17.theme({
|
|
4726
4379
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
4727
4380
|
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
4728
4381
|
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField9 } from "@codemirror/state";
|
4729
|
-
import { Decoration as Decoration6, EditorView as
|
4382
|
+
import { Decoration as Decoration6, EditorView as EditorView17, WidgetType as WidgetType4 } from "@codemirror/view";
|
4730
4383
|
var table = (options = {}) => {
|
4731
4384
|
return StateField9.define({
|
4732
4385
|
create: (state) => update(state, options),
|
4733
4386
|
update: (_, tr) => update(tr.state, options),
|
4734
|
-
provide: (field) =>
|
4387
|
+
provide: (field) => EditorView17.decorations.from(field)
|
4735
4388
|
});
|
4736
4389
|
};
|
4737
4390
|
var update = (state, _options) => {
|
@@ -4917,16 +4570,16 @@ var TextWidget = class extends WidgetType5 {
|
|
4917
4570
|
};
|
4918
4571
|
var hide = Decoration7.replace({});
|
4919
4572
|
var blockQuote = Decoration7.line({
|
4920
|
-
class:
|
4573
|
+
class: "cm-blockquote"
|
4921
4574
|
});
|
4922
4575
|
var fencedCodeLine = Decoration7.line({
|
4923
|
-
class:
|
4576
|
+
class: "cm-code cm-codeblock-line"
|
4924
4577
|
});
|
4925
4578
|
var fencedCodeLineFirst = Decoration7.line({
|
4926
|
-
class:
|
4579
|
+
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-start")
|
4927
4580
|
});
|
4928
4581
|
var fencedCodeLineLast = Decoration7.line({
|
4929
|
-
class:
|
4582
|
+
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-end")
|
4930
4583
|
});
|
4931
4584
|
var commentBlockLine = fencedCodeLine;
|
4932
4585
|
var commentBlockLineFirst = fencedCodeLineFirst;
|
@@ -4993,653 +4646,1305 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
4993
4646
|
number: 0
|
4994
4647
|
});
|
4995
4648
|
};
|
4996
|
-
const leaveList = () => {
|
4997
|
-
listLevels.pop();
|
4998
|
-
};
|
4999
|
-
const getCurrentListLevel = () => {
|
5000
|
-
invariant4(listLevels.length, void 0, {
|
5001
|
-
F: __dxlog_file9,
|
5002
|
-
L: 201,
|
5003
|
-
S: void 0,
|
5004
|
-
A: [
|
5005
|
-
"listLevels.length",
|
5006
|
-
""
|
4649
|
+
const leaveList = () => {
|
4650
|
+
listLevels.pop();
|
4651
|
+
};
|
4652
|
+
const getCurrentListLevel = () => {
|
4653
|
+
invariant4(listLevels.length, void 0, {
|
4654
|
+
F: __dxlog_file9,
|
4655
|
+
L: 201,
|
4656
|
+
S: void 0,
|
4657
|
+
A: [
|
4658
|
+
"listLevels.length",
|
4659
|
+
""
|
4660
|
+
]
|
4661
|
+
});
|
4662
|
+
return listLevels[listLevels.length - 1];
|
4663
|
+
};
|
4664
|
+
const enterNode = (node) => {
|
4665
|
+
switch (node.name) {
|
4666
|
+
// ATXHeading > HeaderMark > Paragraph
|
4667
|
+
// NOTE: Numbering requires processing the entire document since otherwise only the visible range will be
|
4668
|
+
// processed and the numbering will be incorrect.
|
4669
|
+
case "ATXHeading1":
|
4670
|
+
case "ATXHeading2":
|
4671
|
+
case "ATXHeading3":
|
4672
|
+
case "ATXHeading4":
|
4673
|
+
case "ATXHeading5":
|
4674
|
+
case "ATXHeading6": {
|
4675
|
+
const level = parseInt(node.name["ATXHeading".length]);
|
4676
|
+
const headers = getHeaderLevels(node, level);
|
4677
|
+
if (options.numberedHeadings?.from !== void 0) {
|
4678
|
+
const header = headers[level - 1];
|
4679
|
+
if (header) {
|
4680
|
+
header.number++;
|
4681
|
+
}
|
4682
|
+
}
|
4683
|
+
const editing = editingRange(state, node, focus2);
|
4684
|
+
if (editing) {
|
4685
|
+
break;
|
4686
|
+
}
|
4687
|
+
const mark = node.node.firstChild;
|
4688
|
+
if (mark?.name === "HeaderMark") {
|
4689
|
+
const { from, to = 6 } = options.numberedHeadings ?? {};
|
4690
|
+
const text = view.state.sliceDoc(node.from, node.to);
|
4691
|
+
const len = text.match(/[#\s]+/)[0].length;
|
4692
|
+
if (!from || level < from || level > to) {
|
4693
|
+
atomicDeco.add(mark.from, mark.from + len, hide);
|
4694
|
+
} else {
|
4695
|
+
const num = headers.slice(from - 1).map((level2) => level2?.number ?? 0).join(".") + " ";
|
4696
|
+
if (num.length) {
|
4697
|
+
atomicDeco.add(mark.from, mark.from + len, Decoration7.replace({
|
4698
|
+
widget: new TextWidget(num, theme.heading(level))
|
4699
|
+
}));
|
4700
|
+
}
|
4701
|
+
}
|
4702
|
+
}
|
4703
|
+
return false;
|
4704
|
+
}
|
4705
|
+
//
|
4706
|
+
// Lists.
|
4707
|
+
// [BulletList | OrderedList] > (ListItem > ListMark) > (Task > TaskMarker)?
|
4708
|
+
//
|
4709
|
+
case "BulletList":
|
4710
|
+
case "OrderedList": {
|
4711
|
+
enterList(node);
|
4712
|
+
break;
|
4713
|
+
}
|
4714
|
+
case "ListItem": {
|
4715
|
+
const line = state.doc.lineAt(node.from);
|
4716
|
+
const list = getCurrentListLevel();
|
4717
|
+
const width = list.type === "OrderedList" ? orderedListIndentationWidth : bulletListIndentationWidth;
|
4718
|
+
const offset = (options?.listPaddingLeft ?? 0) + ((list.level ?? 0) + 1) * width;
|
4719
|
+
if (node.from === line.to - 1) {
|
4720
|
+
return false;
|
4721
|
+
}
|
4722
|
+
deco.add(line.from, line.from, Decoration7.line({
|
4723
|
+
class: "cm-list-item",
|
4724
|
+
attributes: {
|
4725
|
+
style: `padding-left: ${offset}px; text-indent: -${width}px;`
|
4726
|
+
}
|
4727
|
+
}));
|
4728
|
+
break;
|
4729
|
+
}
|
4730
|
+
case "ListMark": {
|
4731
|
+
const list = getCurrentListLevel();
|
4732
|
+
const next = tree.resolve(node.to + 1, 1);
|
4733
|
+
if (next?.name === "TaskMarker") {
|
4734
|
+
break;
|
4735
|
+
}
|
4736
|
+
const label = list.type === "OrderedList" ? `${++list.number}.` : Unicode.bulletSmall;
|
4737
|
+
const line = state.doc.lineAt(node.from);
|
4738
|
+
const to = state.doc.sliceString(node.to, node.to + 1) === " " ? node.to + 1 : node.to;
|
4739
|
+
atomicDeco.add(line.from, to, Decoration7.replace({
|
4740
|
+
widget: new TextWidget(label, list.type === "OrderedList" ? "cm-list-mark cm-list-mark-ordered" : "cm-list-mark cm-list-mark-bullet")
|
4741
|
+
}));
|
4742
|
+
break;
|
4743
|
+
}
|
4744
|
+
case "TaskMarker": {
|
4745
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
4746
|
+
const line = state.doc.lineAt(node.from);
|
4747
|
+
const to = state.doc.sliceString(node.to, node.to + 1) === " " ? node.to + 1 : node.to;
|
4748
|
+
atomicDeco.add(line.from, to, checked ? checkedTask : uncheckedTask);
|
4749
|
+
break;
|
4750
|
+
}
|
4751
|
+
//
|
4752
|
+
// Blockquote > QuoteMark > Paragraph
|
4753
|
+
//
|
4754
|
+
case "Blockquote": {
|
4755
|
+
const editing = editingRange(state, node, focus2);
|
4756
|
+
const quoteMark = node.node.getChild("QuoteMark");
|
4757
|
+
const paragraph = node.node.getChild("Paragraph");
|
4758
|
+
if (!editing && quoteMark && paragraph) {
|
4759
|
+
atomicDeco.add(quoteMark.from, paragraph.from, hide);
|
4760
|
+
}
|
4761
|
+
for (const block of view.viewportLineBlocks) {
|
4762
|
+
if (block.to < node.from) {
|
4763
|
+
continue;
|
4764
|
+
}
|
4765
|
+
if (block.from > node.to) {
|
4766
|
+
break;
|
4767
|
+
}
|
4768
|
+
deco.add(block.from, block.from, blockQuote);
|
4769
|
+
}
|
4770
|
+
break;
|
4771
|
+
}
|
4772
|
+
//
|
4773
|
+
// CommentBlock
|
4774
|
+
//
|
4775
|
+
case "CommentBlock": {
|
4776
|
+
const editing = editingRange(state, node, focus2);
|
4777
|
+
for (const block of view.viewportLineBlocks) {
|
4778
|
+
if (block.to < node.from) {
|
4779
|
+
continue;
|
4780
|
+
}
|
4781
|
+
if (block.from > node.to) {
|
4782
|
+
break;
|
4783
|
+
}
|
4784
|
+
const isFirst = block.from <= node.from;
|
4785
|
+
const isLast = block.to >= node.to && /^(\s>)*-->$/.test(state.doc.sliceString(block.from, block.to));
|
4786
|
+
deco.add(block.from, block.from, isFirst ? commentBlockLineFirst : isLast ? commentBlockLineLast : commentBlockLine);
|
4787
|
+
if (!editing && (isFirst || isLast)) {
|
4788
|
+
atomicDeco.add(block.from, block.to, hide);
|
4789
|
+
}
|
4790
|
+
}
|
4791
|
+
break;
|
4792
|
+
}
|
4793
|
+
//
|
4794
|
+
// FencedCode > CodeMark > [CodeInfo] > CodeText > CodeMark
|
4795
|
+
//
|
4796
|
+
case "FencedCode": {
|
4797
|
+
for (const block of view.viewportLineBlocks) {
|
4798
|
+
if (block.to < node.from) {
|
4799
|
+
continue;
|
4800
|
+
}
|
4801
|
+
if (block.from > node.to) {
|
4802
|
+
break;
|
4803
|
+
}
|
4804
|
+
const first = block.from <= node.from;
|
4805
|
+
const last = block.to >= node.to && /```$/.test(state.doc.sliceString(block.from, block.to));
|
4806
|
+
deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
|
4807
|
+
const editing = editingRange(state, node, focus2);
|
4808
|
+
if (!editing && (first || last)) {
|
4809
|
+
atomicDeco.add(block.from, block.to, hide);
|
4810
|
+
}
|
4811
|
+
}
|
4812
|
+
return false;
|
4813
|
+
}
|
4814
|
+
//
|
4815
|
+
// Link > [LinkMark, URL]
|
4816
|
+
//
|
4817
|
+
case "Link": {
|
4818
|
+
const marks = node.node.getChildren("LinkMark");
|
4819
|
+
const urlNode = node.node.getChild("URL");
|
4820
|
+
const editing = editingRange(state, node, focus2);
|
4821
|
+
if (urlNode && marks.length >= 2) {
|
4822
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
4823
|
+
if (!editing) {
|
4824
|
+
atomicDeco.add(node.from, marks[0].to, hide);
|
4825
|
+
}
|
4826
|
+
deco.add(marks[0].to, marks[1].from, Decoration7.mark({
|
4827
|
+
tagName: "a",
|
4828
|
+
attributes: {
|
4829
|
+
class: "cm-link",
|
4830
|
+
href: url,
|
4831
|
+
rel: "noreferrer",
|
4832
|
+
target: "_blank"
|
4833
|
+
}
|
4834
|
+
}));
|
4835
|
+
if (!editing) {
|
4836
|
+
atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration7.replace({
|
4837
|
+
widget: new LinkButton(url, options.renderLinkButton)
|
4838
|
+
}) : hide);
|
4839
|
+
}
|
4840
|
+
}
|
4841
|
+
break;
|
4842
|
+
}
|
4843
|
+
//
|
4844
|
+
// HR
|
4845
|
+
//
|
4846
|
+
case "HorizontalRule": {
|
4847
|
+
if (!editingRange(state, node, focus2)) {
|
4848
|
+
deco.add(node.from, node.to, horizontalRule);
|
4849
|
+
}
|
4850
|
+
break;
|
4851
|
+
}
|
4852
|
+
default: {
|
4853
|
+
if (autoHideTags.has(node.name)) {
|
4854
|
+
if (!editingRange(state, node.node.parent, focus2)) {
|
4855
|
+
atomicDeco.add(node.from, node.to, hide);
|
4856
|
+
}
|
4857
|
+
}
|
4858
|
+
}
|
4859
|
+
}
|
4860
|
+
};
|
4861
|
+
const leaveNode = (node) => {
|
4862
|
+
switch (node.name) {
|
4863
|
+
case "BulletList":
|
4864
|
+
case "OrderedList": {
|
4865
|
+
leaveList();
|
4866
|
+
break;
|
4867
|
+
}
|
4868
|
+
}
|
4869
|
+
};
|
4870
|
+
const tree = syntaxTree7(state);
|
4871
|
+
if (options.numberedHeadings?.from === void 0) {
|
4872
|
+
for (const { from, to } of view.visibleRanges) {
|
4873
|
+
tree.iterate({
|
4874
|
+
from,
|
4875
|
+
to,
|
4876
|
+
enter: wrapWithCatch(enterNode),
|
4877
|
+
leave: wrapWithCatch(leaveNode)
|
4878
|
+
});
|
4879
|
+
}
|
4880
|
+
} else {
|
4881
|
+
tree.iterate({
|
4882
|
+
enter: wrapWithCatch(enterNode),
|
4883
|
+
leave: wrapWithCatch(leaveNode)
|
4884
|
+
});
|
4885
|
+
}
|
4886
|
+
return {
|
4887
|
+
deco: deco.finish(),
|
4888
|
+
atomicDeco: atomicDeco.finish()
|
4889
|
+
};
|
4890
|
+
};
|
4891
|
+
var forceUpdate = StateEffect5.define();
|
4892
|
+
var decorateMarkdown = (options = {}) => {
|
4893
|
+
return [
|
4894
|
+
ViewPlugin7.fromClass(class {
|
4895
|
+
constructor(view) {
|
4896
|
+
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations2(view, options, view.hasFocus));
|
4897
|
+
}
|
4898
|
+
update(update2) {
|
4899
|
+
if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((effect) => effect.is(forceUpdate))) || update2.selectionSet && !options.selectionChangeDelay) {
|
4900
|
+
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations2(update2.view, options, update2.view.hasFocus));
|
4901
|
+
this.clearUpdate();
|
4902
|
+
} else if (update2.selectionSet) {
|
4903
|
+
this.scheduleUpdate(update2.view);
|
4904
|
+
}
|
4905
|
+
}
|
4906
|
+
// Defer update in case moving through the document.
|
4907
|
+
scheduleUpdate(view) {
|
4908
|
+
this.clearUpdate();
|
4909
|
+
this.pendingUpdate = setTimeout(() => {
|
4910
|
+
view.dispatch({
|
4911
|
+
effects: forceUpdate.of(null)
|
4912
|
+
});
|
4913
|
+
}, options.selectionChangeDelay);
|
4914
|
+
}
|
4915
|
+
clearUpdate() {
|
4916
|
+
if (this.pendingUpdate) {
|
4917
|
+
clearTimeout(this.pendingUpdate);
|
4918
|
+
this.pendingUpdate = void 0;
|
4919
|
+
}
|
4920
|
+
}
|
4921
|
+
destroy() {
|
4922
|
+
this.clearUpdate();
|
4923
|
+
}
|
4924
|
+
}, {
|
4925
|
+
provide: (plugin) => [
|
4926
|
+
EditorView18.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
4927
|
+
EditorView18.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
4928
|
+
EditorView18.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration7.none)
|
5007
4929
|
]
|
5008
|
-
})
|
5009
|
-
|
4930
|
+
}),
|
4931
|
+
image(),
|
4932
|
+
table(),
|
4933
|
+
adjustChanges(),
|
4934
|
+
formattingStyles
|
4935
|
+
];
|
4936
|
+
};
|
4937
|
+
|
4938
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
4939
|
+
import { syntaxTree as syntaxTree8 } from "@codemirror/language";
|
4940
|
+
import { hoverTooltip as hoverTooltip2 } from "@codemirror/view";
|
4941
|
+
import { tooltipContent } from "@dxos/react-ui-theme";
|
4942
|
+
var linkTooltip = (renderTooltip) => {
|
4943
|
+
return hoverTooltip2((view, pos, side) => {
|
4944
|
+
const syntax = syntaxTree8(view.state).resolveInner(pos, side);
|
4945
|
+
let link = null;
|
4946
|
+
for (let i = 0, node = syntax; !link && node && i < 5; node = node.parent, i++) {
|
4947
|
+
link = node.name === "Link" ? node : null;
|
4948
|
+
}
|
4949
|
+
const url = link && link.getChild("URL");
|
4950
|
+
if (!url || !link) {
|
4951
|
+
return null;
|
4952
|
+
}
|
4953
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
4954
|
+
return {
|
4955
|
+
pos: link.from,
|
4956
|
+
end: link.to,
|
4957
|
+
// NOTE: Forcing above causes the tooltip to flicker.
|
4958
|
+
// above: true,
|
4959
|
+
create: () => {
|
4960
|
+
const el = document.createElement("div");
|
4961
|
+
el.className = tooltipContent({});
|
4962
|
+
renderTooltip(el, {
|
4963
|
+
url: urlText
|
4964
|
+
}, view);
|
4965
|
+
return {
|
4966
|
+
dom: el,
|
4967
|
+
offset: {
|
4968
|
+
x: 0,
|
4969
|
+
y: 4
|
4970
|
+
}
|
4971
|
+
};
|
4972
|
+
}
|
4973
|
+
};
|
4974
|
+
}, {
|
4975
|
+
// NOTE: 0 = default of 300ms.
|
4976
|
+
hoverTime: 1
|
4977
|
+
});
|
4978
|
+
};
|
4979
|
+
|
4980
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/outliner.ts
|
4981
|
+
import { syntaxTree as syntaxTree9 } from "@codemirror/language";
|
4982
|
+
import { StateField as StateField10, EditorState as EditorState2 } from "@codemirror/state";
|
4983
|
+
import { Decoration as Decoration8, EditorView as EditorView19 } from "@codemirror/view";
|
4984
|
+
import { log as log6 } from "@dxos/log";
|
4985
|
+
import { mx as mx3 } from "@dxos/react-ui-theme";
|
4986
|
+
var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/markdown/outliner.ts";
|
4987
|
+
var indentLevel = 2;
|
4988
|
+
var matchTaskMarker = /^\s*- (\[ \]|\[x\])? /;
|
4989
|
+
var getLineInfo = (line) => {
|
4990
|
+
const match = line.text.match(matchTaskMarker);
|
4991
|
+
const start = line.from + (match?.[0]?.length ?? 0);
|
4992
|
+
return {
|
4993
|
+
match,
|
4994
|
+
start
|
5010
4995
|
};
|
5011
|
-
|
5012
|
-
|
5013
|
-
|
5014
|
-
|
5015
|
-
|
5016
|
-
|
5017
|
-
|
5018
|
-
|
5019
|
-
|
5020
|
-
|
5021
|
-
|
5022
|
-
|
5023
|
-
|
5024
|
-
|
5025
|
-
|
5026
|
-
|
5027
|
-
|
4996
|
+
};
|
4997
|
+
var outliner = () => [
|
4998
|
+
EditorState2.transactionFilter.of((tr) => {
|
4999
|
+
if (!tr.docChanged) {
|
5000
|
+
const pos = tr.selection?.ranges[tr.selection?.mainIndex]?.from;
|
5001
|
+
if (pos != null) {
|
5002
|
+
const { match, start } = getLineInfo(tr.startState.doc.lineAt(pos));
|
5003
|
+
if (match) {
|
5004
|
+
if (pos < start) {
|
5005
|
+
return [
|
5006
|
+
{
|
5007
|
+
selection: {
|
5008
|
+
anchor: start,
|
5009
|
+
head: start
|
5010
|
+
}
|
5011
|
+
}
|
5012
|
+
];
|
5028
5013
|
}
|
5029
5014
|
}
|
5030
|
-
|
5031
|
-
|
5032
|
-
|
5015
|
+
}
|
5016
|
+
return tr;
|
5017
|
+
}
|
5018
|
+
const changes = [];
|
5019
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, insert) => {
|
5020
|
+
const line = tr.startState.doc.lineAt(fromA);
|
5021
|
+
const isTaskMarker = line.text.match(matchTaskMarker);
|
5022
|
+
if (isTaskMarker) {
|
5023
|
+
const { start } = getLineInfo(line);
|
5024
|
+
const replace = start === toA && toA - fromA === insert.length;
|
5025
|
+
if (replace) {
|
5026
|
+
log6.info("delete line", void 0, {
|
5027
|
+
F: __dxlog_file10,
|
5028
|
+
L: 82,
|
5029
|
+
S: void 0,
|
5030
|
+
C: (f, a) => f(...a)
|
5031
|
+
});
|
5032
|
+
changes.push({
|
5033
|
+
from: line.from - 1,
|
5034
|
+
to: toA
|
5035
|
+
});
|
5036
|
+
return;
|
5033
5037
|
}
|
5034
|
-
|
5035
|
-
|
5036
|
-
|
5037
|
-
|
5038
|
-
|
5039
|
-
|
5040
|
-
|
5038
|
+
if (fromB === toB) {
|
5039
|
+
if (toA === line.to) {
|
5040
|
+
const line2 = tr.state.doc.lineAt(fromA);
|
5041
|
+
if (line2.text.match(/^\s*$/)) {
|
5042
|
+
if (line2.from === 0) {
|
5043
|
+
log6.info("skip", void 0, {
|
5044
|
+
F: __dxlog_file10,
|
5045
|
+
L: 94,
|
5046
|
+
S: void 0,
|
5047
|
+
C: (f, a) => f(...a)
|
5048
|
+
});
|
5049
|
+
changes.push({
|
5050
|
+
from: 0,
|
5051
|
+
to: 0
|
5052
|
+
});
|
5053
|
+
return;
|
5054
|
+
} else {
|
5055
|
+
log6.info("delete line", void 0, {
|
5056
|
+
F: __dxlog_file10,
|
5057
|
+
L: 99,
|
5058
|
+
S: void 0,
|
5059
|
+
C: (f, a) => f(...a)
|
5060
|
+
});
|
5061
|
+
changes.push({
|
5062
|
+
from: line2.from - 1,
|
5063
|
+
to: toA
|
5064
|
+
});
|
5065
|
+
return;
|
5066
|
+
}
|
5067
|
+
}
|
5068
|
+
}
|
5069
|
+
return;
|
5070
|
+
}
|
5071
|
+
if (insert.length === indentLevel) {
|
5072
|
+
if (line.number === 1) {
|
5073
|
+
log6.info("skip", void 0, {
|
5074
|
+
F: __dxlog_file10,
|
5075
|
+
L: 111,
|
5076
|
+
S: void 0,
|
5077
|
+
C: (f, a) => f(...a)
|
5078
|
+
});
|
5079
|
+
changes.push({
|
5080
|
+
from: 0,
|
5081
|
+
to: 0
|
5082
|
+
});
|
5083
|
+
return;
|
5041
5084
|
} else {
|
5042
|
-
const
|
5043
|
-
|
5044
|
-
|
5045
|
-
|
5046
|
-
|
5085
|
+
const getIndent = (text) => (text.match(/^\s*/)?.[0]?.length ?? 0) / indentLevel;
|
5086
|
+
const currentIndent = getIndent(line.text);
|
5087
|
+
const indentPrevious = getIndent(tr.state.doc.lineAt(fromA - 1).text);
|
5088
|
+
if (currentIndent > indentPrevious) {
|
5089
|
+
log6.info("skip", void 0, {
|
5090
|
+
F: __dxlog_file10,
|
5091
|
+
L: 119,
|
5092
|
+
S: void 0,
|
5093
|
+
C: (f, a) => f(...a)
|
5094
|
+
});
|
5095
|
+
changes.push({
|
5096
|
+
from: 0,
|
5097
|
+
to: 0
|
5098
|
+
});
|
5099
|
+
return;
|
5047
5100
|
}
|
5048
5101
|
}
|
5049
5102
|
}
|
5050
|
-
|
5103
|
+
log6.info("change", {
|
5104
|
+
line: {
|
5105
|
+
from: line.from,
|
5106
|
+
to: line.to
|
5107
|
+
},
|
5108
|
+
start,
|
5109
|
+
a: [
|
5110
|
+
fromA,
|
5111
|
+
toA
|
5112
|
+
],
|
5113
|
+
b: [
|
5114
|
+
fromB,
|
5115
|
+
toB
|
5116
|
+
],
|
5117
|
+
insert: {
|
5118
|
+
text: insert.toString(),
|
5119
|
+
length: insert.length
|
5120
|
+
}
|
5121
|
+
}, {
|
5122
|
+
F: __dxlog_file10,
|
5123
|
+
L: 134,
|
5124
|
+
S: void 0,
|
5125
|
+
C: (f, a) => f(...a)
|
5126
|
+
});
|
5051
5127
|
}
|
5052
|
-
|
5053
|
-
|
5054
|
-
|
5055
|
-
|
5056
|
-
|
5057
|
-
|
5058
|
-
|
5059
|
-
|
5128
|
+
});
|
5129
|
+
if (changes.length > 0) {
|
5130
|
+
return [
|
5131
|
+
{
|
5132
|
+
changes
|
5133
|
+
}
|
5134
|
+
];
|
5135
|
+
}
|
5136
|
+
return tr;
|
5137
|
+
}),
|
5138
|
+
StateField10.define({
|
5139
|
+
create: (state) => {
|
5140
|
+
return Decoration8.set(buildDecorations3(0, state.doc.length, state));
|
5141
|
+
},
|
5142
|
+
update: (value, tr) => {
|
5143
|
+
const from = 0;
|
5144
|
+
const to = tr.state.doc.length;
|
5145
|
+
return value.map(tr.changes).update({
|
5146
|
+
filterFrom: 0,
|
5147
|
+
filterTo: tr.state.doc.length,
|
5148
|
+
filter: () => false,
|
5149
|
+
add: buildDecorations3(from, to, tr.state)
|
5150
|
+
});
|
5151
|
+
},
|
5152
|
+
provide: (field) => EditorView19.decorations.from(field)
|
5153
|
+
}),
|
5154
|
+
// TODO(burdon): Increase indent padding by configuring decorate extension.
|
5155
|
+
// TODO(burdon): Hover to select entire group.
|
5156
|
+
EditorView19.theme({
|
5157
|
+
".cm-list-item-start": {
|
5158
|
+
borderTop: "1px solid var(--dx-separator)",
|
5159
|
+
borderLeft: "1px solid var(--dx-separator)",
|
5160
|
+
borderRight: "1px solid var(--dx-separator)",
|
5161
|
+
borderTopLeftRadius: "4px",
|
5162
|
+
borderTopRightRadius: "4px",
|
5163
|
+
paddingTop: "4px",
|
5164
|
+
marginTop: "8px"
|
5165
|
+
},
|
5166
|
+
".cm-list-item-end": {
|
5167
|
+
borderLeft: "1px solid var(--dx-separator)",
|
5168
|
+
borderRight: "1px solid var(--dx-separator)",
|
5169
|
+
borderBottom: "1px solid var(--dx-separator)",
|
5170
|
+
borderBottomLeftRadius: "4px",
|
5171
|
+
borderBottomRightRadius: "4px",
|
5172
|
+
paddingBottom: "4px",
|
5173
|
+
marginBottom: "8px"
|
5174
|
+
},
|
5175
|
+
".cm-list-item-continuation": {
|
5176
|
+
borderLeft: "1px solid var(--dx-separator)",
|
5177
|
+
borderRight: "1px solid var(--dx-separator)",
|
5178
|
+
// TODO(burdon): Should match parent indentation.
|
5179
|
+
paddingLeft: "24px"
|
5180
|
+
},
|
5181
|
+
// TODO(burdon): Set via options to decorate extension.
|
5182
|
+
".cm-list-item-continuation.cm-codeblock-start": {
|
5183
|
+
borderRadius: "0"
|
5184
|
+
}
|
5185
|
+
})
|
5186
|
+
];
|
5187
|
+
var buildDecorations3 = (from, to, state) => {
|
5188
|
+
const decorations = [];
|
5189
|
+
syntaxTree9(state).iterate({
|
5190
|
+
enter: (node) => {
|
5191
|
+
if (node.name === "ListItem") {
|
5192
|
+
const sub = node.node.getChild("BulletList");
|
5193
|
+
const lineStart = state.doc.lineAt(node.from);
|
5194
|
+
const lineEnd = sub ? state.doc.lineAt(state.doc.lineAt(sub.from).from - 1) : state.doc.lineAt(node.to);
|
5195
|
+
decorations.push(Decoration8.line({
|
5196
|
+
class: mx3("cm-list-item-start", lineStart.number === lineEnd.number && "cm-list-item-end")
|
5197
|
+
}).range(lineStart.from, lineStart.from));
|
5198
|
+
for (let i = lineStart.from + 1; i < lineEnd.from; i++) {
|
5199
|
+
decorations.push(Decoration8.line({
|
5200
|
+
class: mx3("cm-list-item-continuation")
|
5201
|
+
}).range(i, i));
|
5202
|
+
}
|
5203
|
+
if (lineStart.number !== lineEnd.number) {
|
5204
|
+
decorations.push(Decoration8.line({
|
5205
|
+
class: mx3("cm-list-item-end")
|
5206
|
+
}).range(lineEnd.from, lineEnd.from));
|
5207
|
+
}
|
5060
5208
|
}
|
5061
|
-
|
5062
|
-
|
5063
|
-
|
5064
|
-
|
5065
|
-
|
5066
|
-
|
5067
|
-
|
5209
|
+
}
|
5210
|
+
});
|
5211
|
+
return decorations;
|
5212
|
+
};
|
5213
|
+
|
5214
|
+
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
5215
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
5216
|
+
import { log as log7 } from "@dxos/log";
|
5217
|
+
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/mention.ts";
|
5218
|
+
var mention = ({ debug, onSearch }) => {
|
5219
|
+
return autocompletion2({
|
5220
|
+
// TODO(burdon): Not working.
|
5221
|
+
activateOnTyping: true,
|
5222
|
+
// activateOnTypingDelay: 100,
|
5223
|
+
// selectOnOpen: true,
|
5224
|
+
closeOnBlur: !debug,
|
5225
|
+
// defaultKeymap: false,
|
5226
|
+
icons: false,
|
5227
|
+
override: [
|
5228
|
+
(context) => {
|
5229
|
+
log7.info("completion context", {
|
5230
|
+
context
|
5231
|
+
}, {
|
5232
|
+
F: __dxlog_file11,
|
5233
|
+
L: 27,
|
5234
|
+
S: void 0,
|
5235
|
+
C: (f, a) => f(...a)
|
5236
|
+
});
|
5237
|
+
const match = context.matchBefore(/@(\w+)?/);
|
5238
|
+
if (!match || match.from === match.to && !context.explicit) {
|
5239
|
+
return null;
|
5068
5240
|
}
|
5069
|
-
|
5070
|
-
|
5071
|
-
|
5072
|
-
|
5073
|
-
}
|
5074
|
-
}
|
5075
|
-
break;
|
5241
|
+
return {
|
5242
|
+
from: match.from,
|
5243
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
5244
|
+
label: `@${value}`
|
5245
|
+
}))
|
5246
|
+
};
|
5076
5247
|
}
|
5077
|
-
|
5078
|
-
|
5079
|
-
|
5080
|
-
|
5081
|
-
|
5248
|
+
]
|
5249
|
+
});
|
5250
|
+
};
|
5251
|
+
|
5252
|
+
// packages/ui/react-ui-editor/src/extensions/modes.ts
|
5253
|
+
import { keymap as keymap9 } from "@codemirror/view";
|
5254
|
+
import { vim } from "@replit/codemirror-vim";
|
5255
|
+
import { vscodeKeymap } from "@replit/codemirror-vscode-keymap";
|
5256
|
+
import { Schema } from "effect";
|
5257
|
+
var EditorViewModes = [
|
5258
|
+
"preview",
|
5259
|
+
"readonly",
|
5260
|
+
"source"
|
5261
|
+
];
|
5262
|
+
var EditorViewMode = Schema.Union(...EditorViewModes.map((mode) => Schema.Literal(mode)));
|
5263
|
+
var EditorInputModes = [
|
5264
|
+
"default",
|
5265
|
+
"vim",
|
5266
|
+
"vscode"
|
5267
|
+
];
|
5268
|
+
var EditorInputMode = Schema.Union(...EditorInputModes.map((mode) => Schema.Literal(mode)));
|
5269
|
+
var editorInputMode = singleValueFacet({});
|
5270
|
+
var InputModeExtensions = {
|
5271
|
+
default: [],
|
5272
|
+
vscode: [
|
5273
|
+
// https://github.com/replit/codemirror-vscode-keymap
|
5274
|
+
editorInputMode.of({
|
5275
|
+
type: "vscode"
|
5276
|
+
}),
|
5277
|
+
keymap9.of(vscodeKeymap)
|
5278
|
+
],
|
5279
|
+
vim: [
|
5280
|
+
// https://github.com/replit/codemirror-vim
|
5281
|
+
vim(),
|
5282
|
+
editorInputMode.of({
|
5283
|
+
type: "vim",
|
5284
|
+
noTabster: true
|
5285
|
+
}),
|
5286
|
+
keymap9.of([
|
5287
|
+
{
|
5288
|
+
key: "Alt-Escape",
|
5289
|
+
run: (view) => {
|
5290
|
+
view.dom.parentElement?.focus();
|
5291
|
+
return true;
|
5082
5292
|
}
|
5083
|
-
const label = list.type === "OrderedList" ? `${++list.number}.` : Unicode.bulletSmall;
|
5084
|
-
const line = state.doc.lineAt(node.from);
|
5085
|
-
const to = state.doc.sliceString(node.to, node.to + 1) === " " ? node.to + 1 : node.to;
|
5086
|
-
atomicDeco.add(line.from, to, Decoration7.replace({
|
5087
|
-
widget: new TextWidget(label, list.type === "OrderedList" ? "cm-list-mark cm-list-mark-ordered" : "cm-list-mark cm-list-mark-bullet")
|
5088
|
-
}));
|
5089
|
-
break;
|
5090
|
-
}
|
5091
|
-
case "TaskMarker": {
|
5092
|
-
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
5093
|
-
const line = state.doc.lineAt(node.from);
|
5094
|
-
const to = state.doc.sliceString(node.to, node.to + 1) === " " ? node.to + 1 : node.to;
|
5095
|
-
atomicDeco.add(line.from, to, checked ? checkedTask : uncheckedTask);
|
5096
|
-
break;
|
5097
5293
|
}
|
5098
|
-
|
5099
|
-
|
5100
|
-
|
5101
|
-
|
5102
|
-
|
5103
|
-
|
5104
|
-
|
5105
|
-
|
5106
|
-
|
5107
|
-
|
5108
|
-
|
5109
|
-
|
5110
|
-
|
5111
|
-
|
5112
|
-
|
5113
|
-
|
5114
|
-
|
5115
|
-
|
5116
|
-
|
5117
|
-
|
5294
|
+
])
|
5295
|
+
]
|
5296
|
+
};
|
5297
|
+
|
5298
|
+
// packages/ui/react-ui-editor/src/extensions/preview/preview.ts
|
5299
|
+
import "@dxos/lit-ui/dx-ref-tag.pcss";
|
5300
|
+
import { syntaxTree as syntaxTree10 } from "@codemirror/language";
|
5301
|
+
import { RangeSetBuilder as RangeSetBuilder4, StateField as StateField11 } from "@codemirror/state";
|
5302
|
+
import { Decoration as Decoration9, EditorView as EditorView20, WidgetType as WidgetType6 } from "@codemirror/view";
|
5303
|
+
var preview = (options = {}) => {
|
5304
|
+
return [
|
5305
|
+
// NOTE: Atomic block decorations must be created from a state field, now a widget, otherwise it results in the following error:
|
5306
|
+
// "Block decorations may not be specified via plugins"
|
5307
|
+
StateField11.define({
|
5308
|
+
create: (state) => buildDecorations4(state, options),
|
5309
|
+
update: (_, tr) => buildDecorations4(tr.state, options),
|
5310
|
+
provide: (field) => [
|
5311
|
+
EditorView20.decorations.from(field),
|
5312
|
+
EditorView20.atomicRanges.of((view) => view.state.field(field))
|
5313
|
+
]
|
5314
|
+
}),
|
5315
|
+
EditorView20.theme({
|
5316
|
+
".cm-preview-block": {
|
5317
|
+
marginLeft: "-1rem",
|
5318
|
+
marginRight: "-1rem",
|
5319
|
+
padding: "1rem",
|
5320
|
+
borderRadius: "0.5rem",
|
5321
|
+
background: "var(--dx-modalSurface)",
|
5322
|
+
border: "1px solid var(--dx-separator)"
|
5118
5323
|
}
|
5119
|
-
|
5120
|
-
|
5121
|
-
|
5122
|
-
|
5123
|
-
|
5124
|
-
|
5125
|
-
|
5126
|
-
|
5127
|
-
|
5128
|
-
|
5129
|
-
|
5130
|
-
|
5131
|
-
|
5132
|
-
|
5133
|
-
|
5134
|
-
|
5135
|
-
|
5324
|
+
})
|
5325
|
+
];
|
5326
|
+
};
|
5327
|
+
var getLinkRef = (state, node) => {
|
5328
|
+
const mark = node.getChild("LinkMark");
|
5329
|
+
const label = node.getChild("LinkLabel");
|
5330
|
+
if (mark && label) {
|
5331
|
+
const ref = state.sliceDoc(label.from + 1, label.to - 1);
|
5332
|
+
return {
|
5333
|
+
suggest: ref.startsWith("?"),
|
5334
|
+
block: state.sliceDoc(mark.from, mark.from + 1) === "!",
|
5335
|
+
label: state.sliceDoc(mark.to, label.from - 1),
|
5336
|
+
ref: ref.startsWith("?") ? ref.slice(1) : ref
|
5337
|
+
};
|
5338
|
+
}
|
5339
|
+
};
|
5340
|
+
var buildDecorations4 = (state, options) => {
|
5341
|
+
const builder = new RangeSetBuilder4();
|
5342
|
+
syntaxTree10(state).iterate({
|
5343
|
+
enter: (node) => {
|
5344
|
+
switch (node.name) {
|
5345
|
+
//
|
5346
|
+
// Decoration.
|
5347
|
+
// [Label][dxn:echo:123]
|
5348
|
+
//
|
5349
|
+
case "Link": {
|
5350
|
+
const link = getLinkRef(state, node.node);
|
5351
|
+
if (link) {
|
5352
|
+
builder.add(node.from, node.to, Decoration9.replace({
|
5353
|
+
widget: new PreviewInlineWidget(options, link)
|
5354
|
+
}));
|
5136
5355
|
}
|
5356
|
+
break;
|
5137
5357
|
}
|
5138
|
-
|
5139
|
-
|
5140
|
-
|
5141
|
-
|
5142
|
-
|
5143
|
-
|
5144
|
-
|
5145
|
-
|
5146
|
-
|
5147
|
-
|
5148
|
-
|
5149
|
-
|
5150
|
-
}
|
5151
|
-
const first = block.from <= node.from;
|
5152
|
-
const last = block.to >= node.to && /^(\s>)*```$/.test(state.doc.sliceString(block.from, block.to));
|
5153
|
-
deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
|
5154
|
-
const editing = editingRange(state, node, focus2);
|
5155
|
-
if (!editing && (first || last)) {
|
5156
|
-
atomicDeco.add(block.from, block.to, hide);
|
5358
|
+
//
|
5359
|
+
// Block widget.
|
5360
|
+
// ![Label][dxn:echo:123]
|
5361
|
+
//
|
5362
|
+
case "Image": {
|
5363
|
+
const link = getLinkRef(state, node.node);
|
5364
|
+
if (options.renderBlock && link) {
|
5365
|
+
builder.add(node.from, node.to, Decoration9.replace({
|
5366
|
+
block: true,
|
5367
|
+
// atomic: true,
|
5368
|
+
widget: new PreviewBlockWidget(options, link)
|
5369
|
+
}));
|
5157
5370
|
}
|
5371
|
+
break;
|
5158
5372
|
}
|
5159
|
-
return false;
|
5160
5373
|
}
|
5161
|
-
|
5162
|
-
|
5163
|
-
|
5164
|
-
|
5165
|
-
|
5166
|
-
|
5167
|
-
|
5168
|
-
|
5169
|
-
|
5170
|
-
|
5171
|
-
|
5172
|
-
|
5173
|
-
|
5174
|
-
|
5175
|
-
|
5176
|
-
|
5177
|
-
|
5178
|
-
|
5179
|
-
|
5374
|
+
}
|
5375
|
+
});
|
5376
|
+
return builder.finish();
|
5377
|
+
};
|
5378
|
+
var PreviewInlineWidget = class extends WidgetType6 {
|
5379
|
+
constructor(_options, _link) {
|
5380
|
+
super();
|
5381
|
+
this._options = _options;
|
5382
|
+
this._link = _link;
|
5383
|
+
}
|
5384
|
+
// override ignoreEvent() {
|
5385
|
+
// return false;
|
5386
|
+
// }
|
5387
|
+
eq(other) {
|
5388
|
+
return this._link.ref === other._link.ref && this._link.label === other._link.label;
|
5389
|
+
}
|
5390
|
+
toDOM(view) {
|
5391
|
+
const root = document.createElement("dx-ref-tag");
|
5392
|
+
root.textContent = this._link.label;
|
5393
|
+
root.setAttribute("ref", this._link.ref);
|
5394
|
+
return root;
|
5395
|
+
}
|
5396
|
+
};
|
5397
|
+
var PreviewBlockWidget = class extends WidgetType6 {
|
5398
|
+
constructor(_options, _link) {
|
5399
|
+
super();
|
5400
|
+
this._options = _options;
|
5401
|
+
this._link = _link;
|
5402
|
+
}
|
5403
|
+
// override ignoreEvent() {
|
5404
|
+
// return true;
|
5405
|
+
// }
|
5406
|
+
eq(other) {
|
5407
|
+
return this._link.ref === other._link.ref;
|
5408
|
+
}
|
5409
|
+
toDOM(view) {
|
5410
|
+
const root = document.createElement("div");
|
5411
|
+
root.classList.add("cm-preview-block");
|
5412
|
+
const handleAction = (action) => {
|
5413
|
+
const pos = view.posAtDOM(root);
|
5414
|
+
const node = syntaxTree10(view.state).resolve(pos + 1).node.parent;
|
5415
|
+
if (!node) {
|
5416
|
+
return;
|
5417
|
+
}
|
5418
|
+
const link = getLinkRef(view.state, node);
|
5419
|
+
if (link?.ref !== action.link.ref) {
|
5420
|
+
return;
|
5421
|
+
}
|
5422
|
+
switch (action.type) {
|
5423
|
+
// TODO(burdon): Should we dispatch to the view or mutate the document? (i.e., handle externally?)
|
5424
|
+
// Insert ref text.
|
5425
|
+
case "insert": {
|
5426
|
+
view.dispatch({
|
5427
|
+
changes: {
|
5428
|
+
from: node.from,
|
5429
|
+
to: node.to,
|
5430
|
+
insert: action.target.text
|
5180
5431
|
}
|
5181
|
-
})
|
5182
|
-
|
5183
|
-
atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration7.replace({
|
5184
|
-
widget: new LinkButton(url, options.renderLinkButton)
|
5185
|
-
}) : hide);
|
5186
|
-
}
|
5432
|
+
});
|
5433
|
+
break;
|
5187
5434
|
}
|
5188
|
-
|
5189
|
-
|
5190
|
-
|
5191
|
-
|
5192
|
-
|
5193
|
-
|
5194
|
-
|
5195
|
-
|
5435
|
+
// Remove ref.
|
5436
|
+
case "delete": {
|
5437
|
+
view.dispatch({
|
5438
|
+
changes: {
|
5439
|
+
from: node.from,
|
5440
|
+
to: node.to
|
5441
|
+
}
|
5442
|
+
});
|
5443
|
+
break;
|
5196
5444
|
}
|
5197
|
-
break;
|
5198
5445
|
}
|
5199
|
-
|
5200
|
-
|
5201
|
-
|
5202
|
-
|
5446
|
+
};
|
5447
|
+
this._options.renderBlock(root, {
|
5448
|
+
readonly: view.state.readOnly,
|
5449
|
+
link: this._link,
|
5450
|
+
onAction: handleAction,
|
5451
|
+
onLookup: this._options.onLookup
|
5452
|
+
}, view);
|
5453
|
+
return root;
|
5454
|
+
}
|
5455
|
+
};
|
5456
|
+
|
5457
|
+
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
5458
|
+
import { keymap as keymap10 } from "@codemirror/view";
|
5459
|
+
var defaultItems = [
|
5460
|
+
"hello world!",
|
5461
|
+
"this is a test.",
|
5462
|
+
"this is [DXOS](https://dxos.org)"
|
5463
|
+
];
|
5464
|
+
var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
5465
|
+
let t;
|
5466
|
+
let idx = 0;
|
5467
|
+
return [
|
5468
|
+
keymap10.of([
|
5469
|
+
{
|
5470
|
+
// Reset.
|
5471
|
+
key: "alt-meta-'",
|
5472
|
+
run: (view) => {
|
5473
|
+
clearTimeout(t);
|
5474
|
+
idx = 0;
|
5475
|
+
return true;
|
5476
|
+
}
|
5477
|
+
},
|
5478
|
+
{
|
5479
|
+
// Next prompt.
|
5480
|
+
// TODO(burdon): Press 1-9 to select prompt?
|
5481
|
+
key: "shift-meta-'",
|
5482
|
+
run: (view) => {
|
5483
|
+
clearTimeout(t);
|
5484
|
+
const text = items[idx++];
|
5485
|
+
if (idx === items?.length) {
|
5486
|
+
idx = 0;
|
5203
5487
|
}
|
5488
|
+
let i = 0;
|
5489
|
+
const insert = (d = 0) => {
|
5490
|
+
t = setTimeout(() => {
|
5491
|
+
const pos = view.state.selection.main.head;
|
5492
|
+
view.dispatch({
|
5493
|
+
changes: {
|
5494
|
+
from: pos,
|
5495
|
+
insert: text[i++]
|
5496
|
+
},
|
5497
|
+
selection: {
|
5498
|
+
anchor: pos + 1
|
5499
|
+
}
|
5500
|
+
});
|
5501
|
+
if (i < text.length) {
|
5502
|
+
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
5503
|
+
}
|
5504
|
+
}, d);
|
5505
|
+
};
|
5506
|
+
insert();
|
5507
|
+
return true;
|
5204
5508
|
}
|
5205
5509
|
}
|
5510
|
+
])
|
5511
|
+
];
|
5512
|
+
};
|
5513
|
+
|
5514
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/blocks.ts
|
5515
|
+
var createBlockGroupAction = (value) => createEditorActionGroup("block", {
|
5516
|
+
variant: "toggleGroup",
|
5517
|
+
selectCardinality: "single",
|
5518
|
+
value
|
5519
|
+
});
|
5520
|
+
var createBlockActions = (value, getView, blankLine) => Object.entries({
|
5521
|
+
blockquote: "ph--quotes--regular",
|
5522
|
+
codeblock: "ph--code-block--regular",
|
5523
|
+
table: "ph--table--regular"
|
5524
|
+
}).map(([type, icon]) => {
|
5525
|
+
const checked = type === value;
|
5526
|
+
return createEditorAction(type, () => {
|
5527
|
+
const view = getView();
|
5528
|
+
if (!view) {
|
5529
|
+
return;
|
5206
5530
|
}
|
5207
|
-
|
5208
|
-
|
5209
|
-
|
5210
|
-
|
5211
|
-
case "
|
5212
|
-
|
5531
|
+
switch (type) {
|
5532
|
+
case "blockquote":
|
5533
|
+
checked ? removeBlockquote(view) : addBlockquote(view);
|
5534
|
+
break;
|
5535
|
+
case "codeblock":
|
5536
|
+
checked ? removeCodeblock(view) : addCodeblock(view);
|
5537
|
+
break;
|
5538
|
+
case "table":
|
5539
|
+
insertTable(view);
|
5213
5540
|
break;
|
5214
|
-
}
|
5215
|
-
}
|
5216
|
-
};
|
5217
|
-
const tree = syntaxTree7(state);
|
5218
|
-
if (options.numberedHeadings?.from === void 0) {
|
5219
|
-
for (const { from, to } of view.visibleRanges) {
|
5220
|
-
tree.iterate({
|
5221
|
-
from,
|
5222
|
-
to,
|
5223
|
-
enter: wrapWithCatch(enterNode),
|
5224
|
-
leave: wrapWithCatch(leaveNode)
|
5225
|
-
});
|
5226
5541
|
}
|
5227
|
-
}
|
5228
|
-
|
5229
|
-
|
5230
|
-
|
5231
|
-
}
|
5232
|
-
|
5542
|
+
}, {
|
5543
|
+
checked,
|
5544
|
+
...type === "table" && {
|
5545
|
+
disabled: !!blankLine
|
5546
|
+
},
|
5547
|
+
icon
|
5548
|
+
});
|
5549
|
+
});
|
5550
|
+
var createBlocks = (state, getView) => {
|
5551
|
+
const value = state?.blockQuote ? "blockquote" : state.blockType ?? "";
|
5552
|
+
const blockGroupAction = createBlockGroupAction(value);
|
5553
|
+
const blockActions = createBlockActions(value, getView, state.blankLine);
|
5233
5554
|
return {
|
5234
|
-
|
5235
|
-
|
5555
|
+
nodes: [
|
5556
|
+
blockGroupAction,
|
5557
|
+
...blockActions
|
5558
|
+
],
|
5559
|
+
edges: [
|
5560
|
+
{
|
5561
|
+
source: "root",
|
5562
|
+
target: "block"
|
5563
|
+
},
|
5564
|
+
...blockActions.map(({ id }) => ({
|
5565
|
+
source: blockGroupAction.id,
|
5566
|
+
target: id
|
5567
|
+
}))
|
5568
|
+
]
|
5236
5569
|
};
|
5237
5570
|
};
|
5238
|
-
var forceUpdate = StateEffect5.define();
|
5239
|
-
var decorateMarkdown = (options = {}) => {
|
5240
|
-
return [
|
5241
|
-
ViewPlugin7.fromClass(class {
|
5242
|
-
constructor(view) {
|
5243
|
-
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations2(view, options, view.hasFocus));
|
5244
|
-
}
|
5245
|
-
update(update2) {
|
5246
|
-
if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((effect) => effect.is(forceUpdate))) || update2.selectionSet && !options.selectionChangeDelay) {
|
5247
|
-
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations2(update2.view, options, update2.view.hasFocus));
|
5248
|
-
this.clearUpdate();
|
5249
|
-
} else if (update2.selectionSet) {
|
5250
|
-
this.scheduleUpdate(update2.view);
|
5251
|
-
}
|
5252
|
-
}
|
5253
|
-
// Defer update in case moving through the document.
|
5254
|
-
scheduleUpdate(view) {
|
5255
|
-
this.clearUpdate();
|
5256
|
-
this.pendingUpdate = setTimeout(() => {
|
5257
|
-
view.dispatch({
|
5258
|
-
effects: forceUpdate.of(null)
|
5259
|
-
});
|
5260
|
-
}, options.selectionChangeDelay);
|
5261
|
-
}
|
5262
|
-
clearUpdate() {
|
5263
|
-
if (this.pendingUpdate) {
|
5264
|
-
clearTimeout(this.pendingUpdate);
|
5265
|
-
this.pendingUpdate = void 0;
|
5266
|
-
}
|
5267
|
-
}
|
5268
|
-
destroy() {
|
5269
|
-
this.clearUpdate();
|
5270
|
-
}
|
5271
|
-
}, {
|
5272
|
-
provide: (plugin) => [
|
5273
|
-
EditorView19.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
5274
|
-
EditorView19.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
5275
|
-
EditorView19.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration7.none)
|
5276
|
-
]
|
5277
|
-
}),
|
5278
|
-
image(),
|
5279
|
-
table(),
|
5280
|
-
adjustChanges(),
|
5281
|
-
formattingStyles
|
5282
|
-
];
|
5283
|
-
};
|
5284
5571
|
|
5285
|
-
// packages/ui/react-ui-editor/src/
|
5286
|
-
|
5287
|
-
|
5288
|
-
|
5289
|
-
|
5290
|
-
|
5291
|
-
|
5292
|
-
|
5293
|
-
|
5294
|
-
|
5572
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/comment.ts
|
5573
|
+
var commentLabel = (comment, selection) => comment ? "selection overlaps existing comment label" : selection === false ? "select text to comment label" : "comment label";
|
5574
|
+
var createCommentAction = (label, getView) => createEditorAction("comment", () => createComment(getView()), {
|
5575
|
+
testId: "editor.toolbar.comment",
|
5576
|
+
icon: "ph--chat-text--regular",
|
5577
|
+
label
|
5578
|
+
});
|
5579
|
+
var createComment2 = (state, getView) => ({
|
5580
|
+
nodes: [
|
5581
|
+
createCommentAction([
|
5582
|
+
commentLabel(state.comment, state.selection),
|
5583
|
+
{
|
5584
|
+
ns: translationKey
|
5585
|
+
}
|
5586
|
+
], getView)
|
5587
|
+
],
|
5588
|
+
edges: [
|
5589
|
+
{
|
5590
|
+
source: "root",
|
5591
|
+
target: "comment"
|
5295
5592
|
}
|
5296
|
-
|
5297
|
-
|
5298
|
-
|
5593
|
+
]
|
5594
|
+
});
|
5595
|
+
|
5596
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/formatting.ts
|
5597
|
+
var formats = {
|
5598
|
+
strong: "ph--text-b--regular",
|
5599
|
+
emphasis: "ph--text-italic--regular",
|
5600
|
+
strikethrough: "ph--text-strikethrough--regular",
|
5601
|
+
code: "ph--code--regular",
|
5602
|
+
link: "ph--link--regular"
|
5603
|
+
};
|
5604
|
+
var createFormattingGroup = (formatting) => createEditorActionGroup("formatting", {
|
5605
|
+
variant: "toggleGroup",
|
5606
|
+
selectCardinality: "multiple",
|
5607
|
+
value: Object.keys(formats).filter((key) => !!formatting[key])
|
5608
|
+
});
|
5609
|
+
var createFormattingActions = (formatting, getView) => Object.entries(formats).map(([type, icon]) => {
|
5610
|
+
const checked = !!formatting[type];
|
5611
|
+
return createEditorAction(type, () => {
|
5612
|
+
const view = getView();
|
5613
|
+
if (!view) {
|
5614
|
+
return;
|
5299
5615
|
}
|
5300
|
-
|
5301
|
-
|
5302
|
-
|
5303
|
-
|
5304
|
-
|
5305
|
-
|
5306
|
-
create: () => {
|
5307
|
-
const el = document.createElement("div");
|
5308
|
-
el.className = tooltipContent({});
|
5309
|
-
renderTooltip(el, {
|
5310
|
-
url: urlText
|
5311
|
-
}, view);
|
5312
|
-
return {
|
5313
|
-
dom: el,
|
5314
|
-
offset: {
|
5315
|
-
x: 0,
|
5316
|
-
y: 4
|
5317
|
-
}
|
5318
|
-
};
|
5319
|
-
}
|
5320
|
-
};
|
5616
|
+
if (type === "link") {
|
5617
|
+
checked ? removeLink(view) : addLink()(view);
|
5618
|
+
return;
|
5619
|
+
}
|
5620
|
+
const inlineType = type === "strong" ? Inline.Strong : type === "emphasis" ? Inline.Emphasis : type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
5621
|
+
setStyle(inlineType, !checked)(view);
|
5321
5622
|
}, {
|
5322
|
-
|
5323
|
-
|
5623
|
+
checked,
|
5624
|
+
icon
|
5324
5625
|
});
|
5626
|
+
});
|
5627
|
+
var createFormatting = (state, getView) => {
|
5628
|
+
const formattingGroupAction = createFormattingGroup(state);
|
5629
|
+
const formattingActions = createFormattingActions(state, getView);
|
5630
|
+
return {
|
5631
|
+
nodes: [
|
5632
|
+
formattingGroupAction,
|
5633
|
+
...formattingActions
|
5634
|
+
],
|
5635
|
+
edges: [
|
5636
|
+
{
|
5637
|
+
source: "root",
|
5638
|
+
target: "formatting"
|
5639
|
+
},
|
5640
|
+
...formattingActions.map(({ id }) => ({
|
5641
|
+
source: formattingGroupAction.id,
|
5642
|
+
target: id
|
5643
|
+
}))
|
5644
|
+
]
|
5645
|
+
};
|
5325
5646
|
};
|
5326
5647
|
|
5327
|
-
// packages/ui/react-ui-editor/src/
|
5328
|
-
|
5329
|
-
|
5330
|
-
|
5331
|
-
|
5332
|
-
|
5333
|
-
|
5334
|
-
|
5335
|
-
|
5336
|
-
|
5337
|
-
|
5338
|
-
|
5339
|
-
|
5340
|
-
|
5341
|
-
|
5342
|
-
|
5343
|
-
|
5344
|
-
|
5345
|
-
|
5346
|
-
|
5347
|
-
|
5348
|
-
|
5349
|
-
|
5350
|
-
const match = context.matchBefore(/@(\w+)?/);
|
5351
|
-
if (!match || match.from === match.to && !context.explicit) {
|
5352
|
-
return null;
|
5353
|
-
}
|
5354
|
-
return {
|
5355
|
-
from: match.from,
|
5356
|
-
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
5357
|
-
label: `@${value}`
|
5358
|
-
}))
|
5359
|
-
};
|
5648
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/headings.ts
|
5649
|
+
var createHeadingGroupAction = (value) => createEditorActionGroup("heading", {
|
5650
|
+
variant: "dropdownMenu",
|
5651
|
+
applyActive: true,
|
5652
|
+
selectCardinality: "single",
|
5653
|
+
value
|
5654
|
+
}, "ph--text-h--regular");
|
5655
|
+
var createHeadingActions = (getView) => Object.entries({
|
5656
|
+
"0": "ph--paragraph--regular",
|
5657
|
+
"1": "ph--text-h-one--regular",
|
5658
|
+
"2": "ph--text-h-two--regular",
|
5659
|
+
"3": "ph--text-h-three--regular",
|
5660
|
+
"4": "ph--text-h-four--regular",
|
5661
|
+
"5": "ph--text-h-five--regular",
|
5662
|
+
"6": "ph--text-h-six--regular"
|
5663
|
+
}).map(([levelStr, icon]) => {
|
5664
|
+
const level = parseInt(levelStr);
|
5665
|
+
return createEditorAction(`heading--${levelStr}`, () => setHeading(level)(getView()), {
|
5666
|
+
label: [
|
5667
|
+
"heading level label",
|
5668
|
+
{
|
5669
|
+
count: level,
|
5670
|
+
ns: translationKey
|
5360
5671
|
}
|
5361
|
-
]
|
5672
|
+
],
|
5673
|
+
icon
|
5362
5674
|
});
|
5675
|
+
});
|
5676
|
+
var computeHeadingValue = (state) => {
|
5677
|
+
const blockType = state ? state.blockType : "paragraph";
|
5678
|
+
const header = blockType && /heading(\d)/.exec(blockType);
|
5679
|
+
return header ? header[1] : blockType === "paragraph" || !blockType ? "0" : "";
|
5680
|
+
};
|
5681
|
+
var createHeadings = (state, getView) => {
|
5682
|
+
const headingValue = computeHeadingValue(state);
|
5683
|
+
const headingGroupAction = createHeadingGroupAction(headingValue);
|
5684
|
+
const headingActions = createHeadingActions(getView);
|
5685
|
+
return {
|
5686
|
+
nodes: [
|
5687
|
+
headingGroupAction,
|
5688
|
+
...headingActions
|
5689
|
+
],
|
5690
|
+
edges: [
|
5691
|
+
{
|
5692
|
+
source: "root",
|
5693
|
+
target: "heading"
|
5694
|
+
},
|
5695
|
+
...headingActions.map(({ id }) => ({
|
5696
|
+
source: headingGroupAction.id,
|
5697
|
+
target: id
|
5698
|
+
}))
|
5699
|
+
]
|
5700
|
+
};
|
5363
5701
|
};
|
5364
5702
|
|
5365
|
-
// packages/ui/react-ui-editor/src/
|
5366
|
-
|
5367
|
-
|
5368
|
-
|
5369
|
-
|
5370
|
-
var
|
5371
|
-
|
5372
|
-
|
5373
|
-
"source"
|
5374
|
-
];
|
5375
|
-
var EditorViewMode = S.Union(...EditorViewModes.map((mode) => S.Literal(mode)));
|
5376
|
-
var EditorInputModes = [
|
5377
|
-
"default",
|
5378
|
-
"vim",
|
5379
|
-
"vscode"
|
5380
|
-
];
|
5381
|
-
var EditorInputMode = S.Union(...EditorInputModes.map((mode) => S.Literal(mode)));
|
5382
|
-
var editorInputMode = singleValueFacet({});
|
5383
|
-
var InputModeExtensions = {
|
5384
|
-
default: [],
|
5385
|
-
vscode: [
|
5386
|
-
// https://github.com/replit/codemirror-vscode-keymap
|
5387
|
-
editorInputMode.of({
|
5388
|
-
type: "vscode"
|
5389
|
-
}),
|
5390
|
-
keymap9.of(vscodeKeymap)
|
5703
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/image.ts
|
5704
|
+
var createImageUploadAction = (onImageUpload) => createEditorAction("image", onImageUpload, {
|
5705
|
+
testId: "editor.toolbar.image",
|
5706
|
+
icon: "ph--image-square--regular"
|
5707
|
+
});
|
5708
|
+
var createImageUpload = (onImageUpload) => ({
|
5709
|
+
nodes: [
|
5710
|
+
createImageUploadAction(onImageUpload)
|
5391
5711
|
],
|
5392
|
-
|
5393
|
-
|
5394
|
-
|
5395
|
-
|
5396
|
-
|
5397
|
-
noTabster: true
|
5398
|
-
}),
|
5399
|
-
keymap9.of([
|
5400
|
-
{
|
5401
|
-
key: "Alt-Escape",
|
5402
|
-
run: (view) => {
|
5403
|
-
view.dom.parentElement?.focus();
|
5404
|
-
return true;
|
5405
|
-
}
|
5406
|
-
}
|
5407
|
-
])
|
5712
|
+
edges: [
|
5713
|
+
{
|
5714
|
+
source: "root",
|
5715
|
+
target: "image"
|
5716
|
+
}
|
5408
5717
|
]
|
5409
|
-
};
|
5718
|
+
});
|
5410
5719
|
|
5411
|
-
// packages/ui/react-ui-editor/src/
|
5412
|
-
|
5413
|
-
|
5414
|
-
|
5415
|
-
|
5416
|
-
var preview = (options = {}) => {
|
5417
|
-
return [
|
5418
|
-
// NOTE: Atomic block decorations must be created from a state field, now a widget, otherwise it results in the following error:
|
5419
|
-
// "Block decorations may not be specified via plugins"
|
5420
|
-
StateField10.define({
|
5421
|
-
create: (state) => buildDecorations3(state, options),
|
5422
|
-
update: (_, tr) => buildDecorations3(tr.state, options),
|
5423
|
-
provide: (field) => [
|
5424
|
-
EditorView20.decorations.from(field),
|
5425
|
-
EditorView20.atomicRanges.of((view) => view.state.field(field))
|
5426
|
-
]
|
5427
|
-
}),
|
5428
|
-
EditorView20.theme({
|
5429
|
-
".cm-preview-block": {
|
5430
|
-
marginLeft: "-1rem",
|
5431
|
-
marginRight: "-1rem",
|
5432
|
-
padding: "1rem",
|
5433
|
-
borderRadius: "0.5rem",
|
5434
|
-
background: "var(--dx-modalSurface)",
|
5435
|
-
border: "1px solid var(--dx-separator)"
|
5436
|
-
}
|
5437
|
-
})
|
5438
|
-
];
|
5439
|
-
};
|
5440
|
-
var getLinkRef = (state, node) => {
|
5441
|
-
const mark = node.getChild("LinkMark");
|
5442
|
-
const label = node.getChild("LinkLabel");
|
5443
|
-
if (mark && label) {
|
5444
|
-
const ref = state.sliceDoc(label.from + 1, label.to - 1);
|
5445
|
-
return {
|
5446
|
-
suggest: ref.startsWith("?"),
|
5447
|
-
block: state.sliceDoc(mark.from, mark.from + 1) === "!",
|
5448
|
-
label: state.sliceDoc(mark.to, label.from - 1),
|
5449
|
-
ref: ref.startsWith("?") ? ref.slice(1) : ref
|
5450
|
-
};
|
5451
|
-
}
|
5720
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/lists.ts
|
5721
|
+
var listStyles = {
|
5722
|
+
bullet: "ph--list-bullets--regular",
|
5723
|
+
ordered: "ph--list-numbers--regular",
|
5724
|
+
task: "ph--list-checks--regular"
|
5452
5725
|
};
|
5453
|
-
var
|
5454
|
-
|
5455
|
-
|
5456
|
-
|
5457
|
-
|
5458
|
-
|
5459
|
-
|
5460
|
-
|
5461
|
-
|
5462
|
-
|
5463
|
-
|
5464
|
-
|
5465
|
-
|
5466
|
-
|
5467
|
-
|
5468
|
-
|
5469
|
-
|
5470
|
-
|
5471
|
-
|
5472
|
-
|
5473
|
-
|
5474
|
-
|
5475
|
-
|
5476
|
-
|
5477
|
-
|
5478
|
-
|
5479
|
-
|
5480
|
-
|
5481
|
-
|
5482
|
-
|
5483
|
-
|
5484
|
-
|
5485
|
-
|
5486
|
-
|
5726
|
+
var createListGroupAction = (value) => createEditorActionGroup("list", {
|
5727
|
+
variant: "toggleGroup",
|
5728
|
+
selectCardinality: "single",
|
5729
|
+
value
|
5730
|
+
});
|
5731
|
+
var createListActions = (value, getView) => Object.entries(listStyles).map(([listStyle, icon]) => {
|
5732
|
+
const checked = value === listStyle;
|
5733
|
+
return createEditorAction(`list-${listStyle}`, () => {
|
5734
|
+
const view = getView();
|
5735
|
+
if (!view) {
|
5736
|
+
return;
|
5737
|
+
}
|
5738
|
+
const listType = listStyle === "ordered" ? List.Ordered : listStyle === "bullet" ? List.Bullet : List.Task;
|
5739
|
+
if (checked) {
|
5740
|
+
removeList(listType)(view);
|
5741
|
+
} else {
|
5742
|
+
addList(listType)(view);
|
5743
|
+
}
|
5744
|
+
}, {
|
5745
|
+
checked,
|
5746
|
+
icon
|
5747
|
+
});
|
5748
|
+
});
|
5749
|
+
var createLists = (state, getView) => {
|
5750
|
+
const value = state.listStyle ?? "";
|
5751
|
+
const listGroupAction = createListGroupAction(value);
|
5752
|
+
const listActionsMap = createListActions(value, getView);
|
5753
|
+
return {
|
5754
|
+
nodes: [
|
5755
|
+
listGroupAction,
|
5756
|
+
...listActionsMap
|
5757
|
+
],
|
5758
|
+
edges: [
|
5759
|
+
{
|
5760
|
+
source: "root",
|
5761
|
+
target: "list"
|
5762
|
+
},
|
5763
|
+
...listActionsMap.map(({ id }) => ({
|
5764
|
+
source: listGroupAction.id,
|
5765
|
+
target: id
|
5766
|
+
}))
|
5767
|
+
]
|
5768
|
+
};
|
5769
|
+
};
|
5770
|
+
|
5771
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/search.ts
|
5772
|
+
import { openSearchPanel } from "@codemirror/search";
|
5773
|
+
var createSearchAction = (getView) => createEditorAction("search", () => openSearchPanel(getView()), {
|
5774
|
+
testId: "editor.toolbar.search",
|
5775
|
+
icon: "ph--magnifying-glass--regular"
|
5776
|
+
});
|
5777
|
+
var createSearch = (getView) => ({
|
5778
|
+
nodes: [
|
5779
|
+
createSearchAction(getView)
|
5780
|
+
],
|
5781
|
+
edges: [
|
5782
|
+
{
|
5783
|
+
source: "root",
|
5784
|
+
target: "search"
|
5487
5785
|
}
|
5786
|
+
]
|
5787
|
+
});
|
5788
|
+
|
5789
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/view-mode.ts
|
5790
|
+
var createViewModeGroupAction = (value) => createEditorActionGroup("viewMode", {
|
5791
|
+
variant: "dropdownMenu",
|
5792
|
+
applyActive: true,
|
5793
|
+
selectCardinality: "single",
|
5794
|
+
value
|
5795
|
+
}, "ph--eye--regular");
|
5796
|
+
var createViewModeActions = (value, onViewModeChange) => Object.entries({
|
5797
|
+
preview: "ph--eye--regular",
|
5798
|
+
source: "ph--pencil-simple--regular",
|
5799
|
+
readonly: "ph--pencil-slash--regular"
|
5800
|
+
}).map(([viewMode, icon]) => {
|
5801
|
+
const checked = viewMode === value;
|
5802
|
+
return createEditorAction(`view-mode--${viewMode}`, () => onViewModeChange(viewMode), {
|
5803
|
+
label: [
|
5804
|
+
`${viewMode} mode label`,
|
5805
|
+
{
|
5806
|
+
ns: translationKey
|
5807
|
+
}
|
5808
|
+
],
|
5809
|
+
checked,
|
5810
|
+
icon
|
5488
5811
|
});
|
5489
|
-
|
5812
|
+
});
|
5813
|
+
var createViewMode = (state, onViewModeChange) => {
|
5814
|
+
const value = state.viewMode ?? "source";
|
5815
|
+
const viewModeGroupAction = createViewModeGroupAction(value);
|
5816
|
+
const viewModeActions = createViewModeActions(value, onViewModeChange);
|
5817
|
+
return {
|
5818
|
+
nodes: [
|
5819
|
+
viewModeGroupAction,
|
5820
|
+
...viewModeActions
|
5821
|
+
],
|
5822
|
+
edges: [
|
5823
|
+
{
|
5824
|
+
source: "root",
|
5825
|
+
target: "viewMode"
|
5826
|
+
},
|
5827
|
+
...viewModeActions.map(({ id }) => ({
|
5828
|
+
source: viewModeGroupAction.id,
|
5829
|
+
target: id
|
5830
|
+
}))
|
5831
|
+
]
|
5832
|
+
};
|
5490
5833
|
};
|
5491
|
-
|
5492
|
-
|
5493
|
-
|
5494
|
-
|
5495
|
-
|
5834
|
+
|
5835
|
+
// packages/ui/react-ui-editor/src/defaults.ts
|
5836
|
+
import { EditorView as EditorView21 } from "@codemirror/view";
|
5837
|
+
import { mx as mx4 } from "@dxos/react-ui-theme";
|
5838
|
+
var margin = "!mt-[1rem]";
|
5839
|
+
var editorWidth = "!mli-auto is-full max-is-[min(50rem,100%-4rem)]";
|
5840
|
+
var editorContent = mx4(margin, editorWidth);
|
5841
|
+
var editorFullWidth = mx4(margin);
|
5842
|
+
var editorGutter = EditorView21.theme({
|
5843
|
+
// Match margin from content.
|
5844
|
+
// Gutter = 2rem + 1rem margin.
|
5845
|
+
".cm-gutters": {
|
5846
|
+
marginTop: "1rem",
|
5847
|
+
paddingRight: "1rem"
|
5496
5848
|
}
|
5497
|
-
|
5498
|
-
|
5499
|
-
|
5500
|
-
|
5501
|
-
return this._link.ref === other._link.ref && this._link.label === other._link.label;
|
5849
|
+
});
|
5850
|
+
var editorMonospace = EditorView21.theme({
|
5851
|
+
".cm-content": {
|
5852
|
+
fontFamily: fontMono
|
5502
5853
|
}
|
5503
|
-
|
5504
|
-
|
5505
|
-
|
5506
|
-
|
5507
|
-
|
5854
|
+
});
|
5855
|
+
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
5856
|
+
var stackItemContentEditorClassNames = (role) => mx4("attention-surface dx-focus-ring-inset data-[toolbar=disabled]:pbs-2", role === "section" ? "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-bs-24" : "min-bs-0");
|
5857
|
+
var stackItemContentToolbarClassNames = (role) => mx4("relative z-[1] flex is-full bg-toolbarSurface border-be border-separator", role === "section" && "sticky block-start-0 -mbe-px min-is-0");
|
5858
|
+
|
5859
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
|
5860
|
+
var createToolbar = ({ getView, state, customActions, ...features }) => {
|
5861
|
+
const nodes = [];
|
5862
|
+
const edges = [];
|
5863
|
+
if (features.headings ?? true) {
|
5864
|
+
const headings2 = createHeadings(state, getView);
|
5865
|
+
nodes.push(...headings2.nodes);
|
5866
|
+
edges.push(...headings2.edges);
|
5508
5867
|
}
|
5509
|
-
|
5510
|
-
|
5511
|
-
|
5512
|
-
|
5513
|
-
this._options = _options;
|
5514
|
-
this._link = _link;
|
5868
|
+
if (features.formatting ?? true) {
|
5869
|
+
const formatting = createFormatting(state, getView);
|
5870
|
+
nodes.push(...formatting.nodes);
|
5871
|
+
edges.push(...formatting.edges);
|
5515
5872
|
}
|
5516
|
-
|
5517
|
-
|
5518
|
-
|
5519
|
-
|
5520
|
-
return this._link.ref === other._link.ref;
|
5873
|
+
if (features.lists ?? true) {
|
5874
|
+
const lists = createLists(state, getView);
|
5875
|
+
nodes.push(...lists.nodes);
|
5876
|
+
edges.push(...lists.edges);
|
5521
5877
|
}
|
5522
|
-
|
5523
|
-
const
|
5524
|
-
|
5525
|
-
|
5526
|
-
const pos = view.posAtDOM(root);
|
5527
|
-
const node = syntaxTree9(view.state).resolve(pos + 1).node.parent;
|
5528
|
-
if (!node) {
|
5529
|
-
return;
|
5530
|
-
}
|
5531
|
-
const link = getLinkRef(view.state, node);
|
5532
|
-
if (link?.ref !== action.link.ref) {
|
5533
|
-
return;
|
5534
|
-
}
|
5535
|
-
switch (action.type) {
|
5536
|
-
// TODO(burdon): Should we dispatch to the view or mutate the document? (i.e., handle externally?)
|
5537
|
-
// Insert ref text.
|
5538
|
-
case "insert": {
|
5539
|
-
view.dispatch({
|
5540
|
-
changes: {
|
5541
|
-
from: node.from,
|
5542
|
-
to: node.to,
|
5543
|
-
insert: action.target.text
|
5544
|
-
}
|
5545
|
-
});
|
5546
|
-
break;
|
5547
|
-
}
|
5548
|
-
// Remove ref.
|
5549
|
-
case "delete": {
|
5550
|
-
view.dispatch({
|
5551
|
-
changes: {
|
5552
|
-
from: node.from,
|
5553
|
-
to: node.to
|
5554
|
-
}
|
5555
|
-
});
|
5556
|
-
break;
|
5557
|
-
}
|
5558
|
-
}
|
5559
|
-
};
|
5560
|
-
this._options.renderBlock(root, {
|
5561
|
-
readonly: view.state.readOnly,
|
5562
|
-
link: this._link,
|
5563
|
-
onAction: handleAction,
|
5564
|
-
onLookup: this._options.onLookup
|
5565
|
-
}, view);
|
5566
|
-
return root;
|
5878
|
+
if (features.blocks ?? true) {
|
5879
|
+
const blocks = createBlocks(state, getView);
|
5880
|
+
nodes.push(...blocks.nodes);
|
5881
|
+
edges.push(...blocks.edges);
|
5567
5882
|
}
|
5883
|
+
if (features.image) {
|
5884
|
+
const image2 = createImageUpload(features.image);
|
5885
|
+
nodes.push(...image2.nodes);
|
5886
|
+
edges.push(...image2.edges);
|
5887
|
+
}
|
5888
|
+
if (customActions) {
|
5889
|
+
const custom = customActions();
|
5890
|
+
nodes.push(...custom.nodes);
|
5891
|
+
edges.push(...custom.edges);
|
5892
|
+
}
|
5893
|
+
const editorToolbarGap = createGapSeparator();
|
5894
|
+
nodes.push(...editorToolbarGap.nodes);
|
5895
|
+
edges.push(...editorToolbarGap.edges);
|
5896
|
+
if (features.comment) {
|
5897
|
+
const comment = createComment2(state, getView);
|
5898
|
+
nodes.push(...comment.nodes);
|
5899
|
+
edges.push(...comment.edges);
|
5900
|
+
}
|
5901
|
+
if (features.search ?? true) {
|
5902
|
+
const search = createSearch(getView);
|
5903
|
+
nodes.push(...search.nodes);
|
5904
|
+
edges.push(...search.edges);
|
5905
|
+
}
|
5906
|
+
if (features.viewMode) {
|
5907
|
+
const viewMode = createViewMode(state, features.viewMode);
|
5908
|
+
nodes.push(...viewMode.nodes);
|
5909
|
+
edges.push(...viewMode.edges);
|
5910
|
+
}
|
5911
|
+
return {
|
5912
|
+
nodes,
|
5913
|
+
edges
|
5914
|
+
};
|
5568
5915
|
};
|
5569
|
-
|
5570
|
-
|
5571
|
-
|
5572
|
-
var defaultItems = [
|
5573
|
-
"hello world!",
|
5574
|
-
"this is a test.",
|
5575
|
-
"this is [DXOS](https://dxos.org)"
|
5576
|
-
];
|
5577
|
-
var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
5578
|
-
let t;
|
5579
|
-
let idx = 0;
|
5580
|
-
return [
|
5581
|
-
keymap10.of([
|
5582
|
-
{
|
5583
|
-
// Reset.
|
5584
|
-
key: "alt-meta-'",
|
5585
|
-
run: (view) => {
|
5586
|
-
clearTimeout(t);
|
5587
|
-
idx = 0;
|
5588
|
-
return true;
|
5589
|
-
}
|
5590
|
-
},
|
5591
|
-
{
|
5592
|
-
// Next prompt.
|
5593
|
-
// TODO(burdon): Press 1-9 to select prompt?
|
5594
|
-
key: "shift-meta-'",
|
5595
|
-
run: (view) => {
|
5596
|
-
clearTimeout(t);
|
5597
|
-
const text = items[idx++];
|
5598
|
-
if (idx === items?.length) {
|
5599
|
-
idx = 0;
|
5600
|
-
}
|
5601
|
-
let i = 0;
|
5602
|
-
const insert = (d = 0) => {
|
5603
|
-
t = setTimeout(() => {
|
5604
|
-
const pos = view.state.selection.main.head;
|
5605
|
-
view.dispatch({
|
5606
|
-
changes: {
|
5607
|
-
from: pos,
|
5608
|
-
insert: text[i++]
|
5609
|
-
},
|
5610
|
-
selection: {
|
5611
|
-
anchor: pos + 1
|
5612
|
-
}
|
5613
|
-
});
|
5614
|
-
if (i < text.length) {
|
5615
|
-
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
5616
|
-
}
|
5617
|
-
}, d);
|
5618
|
-
};
|
5619
|
-
insert();
|
5620
|
-
return true;
|
5621
|
-
}
|
5622
|
-
}
|
5623
|
-
])
|
5624
|
-
];
|
5625
|
-
};
|
5626
|
-
|
5627
|
-
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
5628
|
-
import { useCallback as useCallback2 } from "react";
|
5629
|
-
var useActionHandler = (view) => {
|
5630
|
-
return useCallback2((action) => view && processEditorPayload(view, action.properties), [
|
5631
|
-
view
|
5916
|
+
var useEditorToolbarActionGraph = (props) => {
|
5917
|
+
const menuCreator = useCallback(() => createToolbar(props), [
|
5918
|
+
props
|
5632
5919
|
]);
|
5920
|
+
return useMenuActions(menuCreator);
|
5633
5921
|
};
|
5922
|
+
var EditorToolbar = /* @__PURE__ */ memo(({ classNames, attendableId, role, ...props }) => {
|
5923
|
+
const menuProps = useEditorToolbarActionGraph(props);
|
5924
|
+
return /* @__PURE__ */ React3.createElement("div", {
|
5925
|
+
role: "none",
|
5926
|
+
className: stackItemContentToolbarClassNames(role)
|
5927
|
+
}, /* @__PURE__ */ React3.createElement(ElevationProvider, {
|
5928
|
+
elevation: role === "section" ? "positioned" : "base"
|
5929
|
+
}, /* @__PURE__ */ React3.createElement(MenuProvider, {
|
5930
|
+
...menuProps,
|
5931
|
+
attendableId
|
5932
|
+
}, /* @__PURE__ */ React3.createElement(ToolbarMenu, {
|
5933
|
+
classNames: [
|
5934
|
+
textBlockWidth,
|
5935
|
+
classNames
|
5936
|
+
]
|
5937
|
+
}))));
|
5938
|
+
});
|
5634
5939
|
|
5635
5940
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
5636
|
-
import { EditorState as
|
5637
|
-
import { EditorView as
|
5941
|
+
import { EditorState as EditorState3 } from "@codemirror/state";
|
5942
|
+
import { EditorView as EditorView22 } from "@codemirror/view";
|
5638
5943
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
5639
|
-
import { useCallback as
|
5640
|
-
import { log as
|
5944
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo4, useRef, useState } from "react";
|
5945
|
+
import { log as log8 } from "@dxos/log";
|
5641
5946
|
import { getProviderValue, isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
5642
|
-
var
|
5947
|
+
var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
5643
5948
|
var instanceCount = 0;
|
5644
5949
|
var useTextEditor = (props = {}, deps = []) => {
|
5645
5950
|
const { id, doc, initialValue, extensions, autoFocus, scrollTo, selection, moveToEndOfLine, debug } = useMemo4(() => getProviderValue(props), deps ?? []);
|
@@ -5649,12 +5954,12 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5649
5954
|
useEffect2(() => {
|
5650
5955
|
let view2;
|
5651
5956
|
if (parentRef.current) {
|
5652
|
-
|
5957
|
+
log8("create", {
|
5653
5958
|
id,
|
5654
5959
|
instanceId,
|
5655
5960
|
doc: initialValue?.length ?? 0
|
5656
5961
|
}, {
|
5657
|
-
F:
|
5962
|
+
F: __dxlog_file12,
|
5658
5963
|
L: 76,
|
5659
5964
|
S: void 0,
|
5660
5965
|
C: (f, a) => f(...a)
|
@@ -5671,16 +5976,16 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5671
5976
|
anchor
|
5672
5977
|
};
|
5673
5978
|
}
|
5674
|
-
const state =
|
5979
|
+
const state = EditorState3.create({
|
5675
5980
|
doc: doc ?? initialValue,
|
5676
5981
|
// selection: initialSelection,
|
5677
5982
|
extensions: [
|
5678
5983
|
id && documentId.of(id),
|
5679
5984
|
extensions,
|
5680
5985
|
// NOTE: This doesn't catch errors in keymap functions.
|
5681
|
-
|
5682
|
-
|
5683
|
-
F:
|
5986
|
+
EditorView22.exceptionSink.of((err) => {
|
5987
|
+
log8.catch(err, void 0, {
|
5988
|
+
F: __dxlog_file12,
|
5684
5989
|
L: 98,
|
5685
5990
|
S: void 0,
|
5686
5991
|
C: (f, a) => f(...a)
|
@@ -5688,10 +5993,10 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5688
5993
|
})
|
5689
5994
|
].filter(isNotFalsy4)
|
5690
5995
|
});
|
5691
|
-
view2 = new
|
5996
|
+
view2 = new EditorView22({
|
5692
5997
|
parent: parentRef.current,
|
5693
5998
|
state,
|
5694
|
-
scrollTo: scrollTo ?
|
5999
|
+
scrollTo: scrollTo ? EditorView22.scrollIntoView(scrollTo, {
|
5695
6000
|
yMargin: 96
|
5696
6001
|
}) : void 0,
|
5697
6002
|
dispatchTransactions: debug ? debugDispatcher : void 0
|
@@ -5709,10 +6014,10 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5709
6014
|
setView(view2);
|
5710
6015
|
}
|
5711
6016
|
return () => {
|
5712
|
-
|
6017
|
+
log8("destroy", {
|
5713
6018
|
id
|
5714
6019
|
}, {
|
5715
|
-
F:
|
6020
|
+
F: __dxlog_file12,
|
5716
6021
|
L: 135,
|
5717
6022
|
S: void 0,
|
5718
6023
|
C: (f, a) => f(...a)
|
@@ -5724,12 +6029,12 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5724
6029
|
if (view) {
|
5725
6030
|
if (scrollTo || selection) {
|
5726
6031
|
if (selection && selection.anchor > view.state.doc.length) {
|
5727
|
-
|
6032
|
+
log8.warn("invalid selection", {
|
5728
6033
|
length: view.state.doc.length,
|
5729
6034
|
scrollTo,
|
5730
6035
|
selection
|
5731
6036
|
}, {
|
5732
|
-
F:
|
6037
|
+
F: __dxlog_file12,
|
5733
6038
|
L: 144,
|
5734
6039
|
S: void 0,
|
5735
6040
|
C: (f, a) => f(...a)
|
@@ -5761,7 +6066,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5761
6066
|
Escape: view?.state.facet(editorInputMode).noTabster
|
5762
6067
|
}
|
5763
6068
|
});
|
5764
|
-
const handleKeyUp =
|
6069
|
+
const handleKeyUp = useCallback2((event) => {
|
5765
6070
|
const { key, target, currentTarget } = event;
|
5766
6071
|
if (target === currentTarget) {
|
5767
6072
|
switch (key) {
|
@@ -5788,9 +6093,9 @@ export {
|
|
5788
6093
|
Cursor,
|
5789
6094
|
EditorInputMode,
|
5790
6095
|
EditorInputModes,
|
5791
|
-
|
6096
|
+
EditorState4 as EditorState,
|
5792
6097
|
EditorToolbar,
|
5793
|
-
|
6098
|
+
EditorView23 as EditorView,
|
5794
6099
|
EditorViewMode,
|
5795
6100
|
EditorViewModes,
|
5796
6101
|
Inline,
|
@@ -5820,7 +6125,7 @@ export {
|
|
5820
6125
|
commentsState,
|
5821
6126
|
convertTreeToJson,
|
5822
6127
|
createBasicExtensions,
|
5823
|
-
|
6128
|
+
createComment,
|
5824
6129
|
createDataExtensions,
|
5825
6130
|
createEditorAction,
|
5826
6131
|
createEditorActionGroup,
|
@@ -5864,6 +6169,7 @@ export {
|
|
5864
6169
|
mention,
|
5865
6170
|
openCommand,
|
5866
6171
|
openEffect,
|
6172
|
+
outliner,
|
5867
6173
|
overlap,
|
5868
6174
|
preventNewline,
|
5869
6175
|
preview,
|
@@ -5898,7 +6204,6 @@ export {
|
|
5898
6204
|
toggleStyle,
|
5899
6205
|
translations_default as translations,
|
5900
6206
|
typewriter,
|
5901
|
-
useActionHandler,
|
5902
6207
|
useCommentClickListener,
|
5903
6208
|
useCommentState,
|
5904
6209
|
useComments,
|