@dxos/react-ui-editor 0.8.2-main.5885341 → 0.8.2-main.600d381
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 +1874 -1806
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +1386 -1319
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +1874 -1806
- 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/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts.map +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.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.map +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/link.d.ts.map +1 -1
- 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/story-utils.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 +30 -28
- package/src/components/EditorToolbar/EditorToolbar.stories.tsx +90 -0
- package/src/components/EditorToolbar/EditorToolbar.tsx +30 -31
- 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/extensions/modes.ts +5 -6
- package/src/hooks/index.ts +0 -1
- 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
@@ -42,7 +42,7 @@ import { tags as tags2 } from "@lezer/highlight";
|
|
42
42
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
43
43
|
|
44
44
|
// packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
|
45
|
-
import
|
45
|
+
import React3, { memo, useCallback } from "react";
|
46
46
|
import { ElevationProvider } from "@dxos/react-ui";
|
47
47
|
import { MenuProvider, ToolbarMenu, createGapSeparator, useMenuActions } from "@dxos/react-ui-menu";
|
48
48
|
import { textBlockWidth } from "@dxos/react-ui-theme";
|
@@ -54,1176 +54,594 @@ import { createMenuAction, createMenuItemGroup } from "@dxos/react-ui-menu";
|
|
54
54
|
var useEditorToolbarState = (initialState = {}) => {
|
55
55
|
return useMemo(() => live(initialState), []);
|
56
56
|
};
|
57
|
-
var createEditorAction = (
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
57
|
+
var createEditorAction = (id, invoke, properties) => {
|
58
|
+
const { label = [
|
59
|
+
`${id} label`,
|
60
|
+
{
|
61
|
+
ns: translationKey
|
62
|
+
}
|
63
|
+
], ...rest } = properties;
|
64
|
+
return createMenuAction(id, invoke, {
|
65
|
+
label,
|
66
|
+
...rest
|
67
|
+
});
|
68
|
+
};
|
67
69
|
var createEditorActionGroup = (id, props, icon) => createMenuItemGroup(id, {
|
68
70
|
icon,
|
69
71
|
iconOnly: true,
|
70
72
|
...props
|
71
73
|
});
|
72
|
-
var editorToolbarSearch = createEditorAction({
|
73
|
-
type: "search"
|
74
|
-
}, "ph--magnifying-glass--regular");
|
75
74
|
|
76
|
-
// packages/ui/react-ui-editor/src/
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
value
|
81
|
-
});
|
82
|
-
var createBlockActions = (value, blankLine) => Object.entries({
|
83
|
-
blockquote: "ph--quotes--regular",
|
84
|
-
codeblock: "ph--code-block--regular",
|
85
|
-
table: "ph--table--regular"
|
86
|
-
}).map(([type, icon]) => {
|
87
|
-
return createEditorAction({
|
88
|
-
type,
|
89
|
-
checked: type === value,
|
90
|
-
...type === "table" && {
|
91
|
-
disabled: !!blankLine
|
92
|
-
}
|
93
|
-
}, icon);
|
94
|
-
});
|
95
|
-
var createBlocks = (state) => {
|
96
|
-
const value = state?.blockQuote ? "blockquote" : state.blockType ?? "";
|
97
|
-
const blockGroupAction = createBlockGroupAction(value);
|
98
|
-
const blockActions = createBlockActions(value, state.blankLine);
|
99
|
-
return {
|
100
|
-
nodes: [
|
101
|
-
blockGroupAction,
|
102
|
-
...blockActions
|
103
|
-
],
|
104
|
-
edges: [
|
105
|
-
{
|
106
|
-
source: "root",
|
107
|
-
target: "block"
|
108
|
-
},
|
109
|
-
...blockActions.map(({ id }) => ({
|
110
|
-
source: blockGroupAction.id,
|
111
|
-
target: id
|
112
|
-
}))
|
113
|
-
]
|
114
|
-
};
|
115
|
-
};
|
75
|
+
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
76
|
+
import { StateField } from "@codemirror/state";
|
77
|
+
import { Decoration, EditorView } from "@codemirror/view";
|
78
|
+
import { isNotFalsy } from "@dxos/util";
|
116
79
|
|
117
|
-
// packages/ui/react-ui-editor/src/
|
118
|
-
|
119
|
-
var
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
nodes: [
|
125
|
-
createCommentAction([
|
126
|
-
commentLabel(state.comment, state.selection),
|
127
|
-
{
|
128
|
-
ns: translationKey
|
129
|
-
}
|
130
|
-
])
|
131
|
-
],
|
132
|
-
edges: [
|
133
|
-
{
|
134
|
-
source: "root",
|
135
|
-
target: "comment"
|
136
|
-
}
|
137
|
-
]
|
80
|
+
// packages/ui/react-ui-editor/src/util/facet.ts
|
81
|
+
import { Facet } from "@codemirror/state";
|
82
|
+
var singleValueFacet = (defaultValue) => Facet.define({
|
83
|
+
// Called immediately.
|
84
|
+
combine: (providers) => {
|
85
|
+
return providers[0] ?? defaultValue;
|
86
|
+
}
|
138
87
|
});
|
139
88
|
|
140
|
-
// packages/ui/react-ui-editor/src/
|
141
|
-
var
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
code: "ph--code--regular",
|
146
|
-
link: "ph--link--regular"
|
89
|
+
// packages/ui/react-ui-editor/src/util/cursor.ts
|
90
|
+
var overlap = (a, b) => a.from <= b.to && a.to >= b.from;
|
91
|
+
var defaultCursorConverter = {
|
92
|
+
toCursor: (position) => position.toString(),
|
93
|
+
fromCursor: (cursor) => parseInt(cursor)
|
147
94
|
};
|
148
|
-
var
|
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
|
-
|
174
|
-
|
175
|
-
};
|
95
|
+
var Cursor = class _Cursor {
|
96
|
+
static {
|
97
|
+
this.converter = singleValueFacet(defaultCursorConverter);
|
98
|
+
}
|
99
|
+
static {
|
100
|
+
this.getCursorFromRange = (state, range) => {
|
101
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
102
|
+
const from = cursorConverter2.toCursor(range.from);
|
103
|
+
const to = cursorConverter2.toCursor(range.to, -1);
|
104
|
+
return [
|
105
|
+
from,
|
106
|
+
to
|
107
|
+
].join(":");
|
108
|
+
};
|
109
|
+
}
|
110
|
+
static {
|
111
|
+
this.getRangeFromCursor = (state, cursor) => {
|
112
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
113
|
+
const parts = cursor.split(":");
|
114
|
+
const from = cursorConverter2.fromCursor(parts[0]);
|
115
|
+
const to = cursorConverter2.fromCursor(parts[1]);
|
116
|
+
return from !== void 0 && to !== void 0 ? {
|
117
|
+
from,
|
118
|
+
to
|
119
|
+
} : void 0;
|
120
|
+
};
|
121
|
+
}
|
176
122
|
};
|
177
123
|
|
178
|
-
// packages/ui/react-ui-editor/src/
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
"6": "ph--text-h-six--regular"
|
193
|
-
}).map(([levelStr, icon]) => {
|
194
|
-
const level = parseInt(levelStr);
|
195
|
-
return createEditorAction({
|
196
|
-
type: "heading",
|
197
|
-
data: level,
|
198
|
-
checked: value === levelStr
|
199
|
-
}, icon, [
|
200
|
-
"heading level label",
|
201
|
-
{
|
202
|
-
count: level,
|
203
|
-
ns: translationKey
|
124
|
+
// packages/ui/react-ui-editor/src/util/debug.ts
|
125
|
+
import { log } from "@dxos/log";
|
126
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/debug.ts";
|
127
|
+
var wrapWithCatch = (fn) => {
|
128
|
+
return (...args) => {
|
129
|
+
try {
|
130
|
+
return fn(...args);
|
131
|
+
} catch (err) {
|
132
|
+
log.catch(err, void 0, {
|
133
|
+
F: __dxlog_file,
|
134
|
+
L: 15,
|
135
|
+
S: void 0,
|
136
|
+
C: (f, a) => f(...a)
|
137
|
+
});
|
204
138
|
}
|
205
|
-
], `heading--${levelStr}`);
|
206
|
-
});
|
207
|
-
var computeHeadingValue = (state) => {
|
208
|
-
const blockType = state ? state.blockType : "paragraph";
|
209
|
-
const header = blockType && /heading(\d)/.exec(blockType);
|
210
|
-
return header ? header[1] : blockType === "paragraph" || !blockType ? "0" : "";
|
211
|
-
};
|
212
|
-
var createHeadings = (state) => {
|
213
|
-
const headingValue = computeHeadingValue(state);
|
214
|
-
const headingGroupAction = createHeadingGroupAction(headingValue);
|
215
|
-
const headingActions = createHeadingActions(headingValue);
|
216
|
-
return {
|
217
|
-
nodes: [
|
218
|
-
headingGroupAction,
|
219
|
-
...headingActions
|
220
|
-
],
|
221
|
-
edges: [
|
222
|
-
{
|
223
|
-
source: "root",
|
224
|
-
target: "heading"
|
225
|
-
},
|
226
|
-
...headingActions.map(({ id }) => ({
|
227
|
-
source: headingGroupAction.id,
|
228
|
-
target: id
|
229
|
-
}))
|
230
|
-
]
|
231
139
|
};
|
232
140
|
};
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
141
|
+
var callbackWrapper = (fn) => (...args) => {
|
142
|
+
try {
|
143
|
+
return fn(...args);
|
144
|
+
} catch (err) {
|
145
|
+
log.catch(err, void 0, {
|
146
|
+
F: __dxlog_file,
|
147
|
+
L: 29,
|
148
|
+
S: void 0,
|
149
|
+
C: (f, a) => f(...a)
|
150
|
+
});
|
151
|
+
}
|
239
152
|
};
|
240
|
-
var
|
241
|
-
|
242
|
-
|
243
|
-
value
|
244
|
-
});
|
245
|
-
var createListActions = (value) => Object.entries(listStyles).map(([listStyle, icon]) => createEditorAction({
|
246
|
-
type: `list-${listStyle}`,
|
247
|
-
checked: value === listStyle
|
248
|
-
}, icon));
|
249
|
-
var createLists = (state) => {
|
250
|
-
const value = state.listStyle ?? "";
|
251
|
-
const listGroupAction = createListGroupAction(value);
|
252
|
-
const listActionsMap = createListActions(value);
|
253
|
-
return {
|
254
|
-
nodes: [
|
255
|
-
listGroupAction,
|
256
|
-
...listActionsMap
|
257
|
-
],
|
258
|
-
edges: [
|
259
|
-
{
|
260
|
-
source: "root",
|
261
|
-
target: "list"
|
262
|
-
},
|
263
|
-
...listActionsMap.map(({ id }) => ({
|
264
|
-
source: listGroupAction.id,
|
265
|
-
target: id
|
266
|
-
}))
|
267
|
-
]
|
268
|
-
};
|
153
|
+
var debugDispatcher = (trs, view) => {
|
154
|
+
logChanges(trs);
|
155
|
+
view.update(trs);
|
269
156
|
};
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
applyActive: true,
|
275
|
-
selectCardinality: "single",
|
276
|
-
value
|
277
|
-
}, "ph--eye--regular");
|
278
|
-
var createViewModeActions = (value) => Object.entries({
|
279
|
-
preview: "ph--eye--regular",
|
280
|
-
source: "ph--pencil-simple--regular",
|
281
|
-
readonly: "ph--pencil-slash--regular"
|
282
|
-
}).map(([viewMode, icon]) => {
|
283
|
-
return createEditorAction({
|
284
|
-
type: "view-mode",
|
285
|
-
data: viewMode,
|
286
|
-
checked: viewMode === value
|
287
|
-
}, icon, [
|
288
|
-
`${viewMode} mode label`,
|
289
|
-
{
|
290
|
-
ns: translationKey
|
157
|
+
var logChanges = (trs) => {
|
158
|
+
const changes = trs.flatMap((tr) => {
|
159
|
+
if (tr.changes.empty) {
|
160
|
+
return void 0;
|
291
161
|
}
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
162
|
+
const changes2 = [];
|
163
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
164
|
+
fromA,
|
165
|
+
toA,
|
166
|
+
fromB,
|
167
|
+
toB,
|
168
|
+
inserted: inserted.toString()
|
169
|
+
})));
|
170
|
+
return changes2;
|
171
|
+
}).filter(Boolean);
|
172
|
+
if (changes.length) {
|
173
|
+
log("changes", {
|
174
|
+
changes
|
175
|
+
}, {
|
176
|
+
F: __dxlog_file,
|
177
|
+
L: 62,
|
178
|
+
S: void 0,
|
179
|
+
C: (f, a) => f(...a)
|
180
|
+
});
|
181
|
+
}
|
182
|
+
};
|
183
|
+
|
184
|
+
// packages/ui/react-ui-editor/src/util/dom.ts
|
185
|
+
var flattenRect = (rect, left) => {
|
186
|
+
const x = left ? rect.left : rect.right;
|
187
|
+
return {
|
188
|
+
left: x,
|
189
|
+
right: x,
|
190
|
+
top: rect.top,
|
191
|
+
bottom: rect.bottom
|
313
192
|
};
|
314
193
|
};
|
194
|
+
var scratchRange;
|
195
|
+
var textRange = (node, from, to = from) => {
|
196
|
+
const range = scratchRange || (scratchRange = document.createRange());
|
197
|
+
range.setEnd(node, to);
|
198
|
+
range.setStart(node, from);
|
199
|
+
return range;
|
200
|
+
};
|
201
|
+
var clientRectsFor = (dom) => {
|
202
|
+
if (dom.nodeType === 3) {
|
203
|
+
return textRange(dom, 0, dom.nodeValue.length).getClientRects();
|
204
|
+
} else if (dom.nodeType === 1) {
|
205
|
+
return dom.getClientRects();
|
206
|
+
} else {
|
207
|
+
return [];
|
208
|
+
}
|
209
|
+
};
|
315
210
|
|
316
|
-
// packages/ui/react-ui-editor/src/
|
317
|
-
import
|
318
|
-
import {
|
211
|
+
// packages/ui/react-ui-editor/src/util/react.tsx
|
212
|
+
import React from "react";
|
213
|
+
import { createRoot } from "react-dom/client";
|
214
|
+
import { ThemeProvider, Tooltip } from "@dxos/react-ui";
|
215
|
+
import { defaultTx } from "@dxos/react-ui-theme";
|
216
|
+
var createElement = (tag, options, children) => {
|
217
|
+
const el = document.createElement(tag);
|
218
|
+
if (options?.className) {
|
219
|
+
el.className = options.className;
|
220
|
+
}
|
221
|
+
if (children) {
|
222
|
+
el.append(...Array.isArray(children) ? children : [
|
223
|
+
children
|
224
|
+
]);
|
225
|
+
}
|
226
|
+
return el;
|
227
|
+
};
|
228
|
+
var renderRoot = (root, node) => {
|
229
|
+
createRoot(root).render(/* @__PURE__ */ React.createElement(ThemeProvider, {
|
230
|
+
tx: defaultTx
|
231
|
+
}, node));
|
232
|
+
return root;
|
233
|
+
};
|
234
|
+
var createRenderer = (Component) => (el, props) => {
|
235
|
+
renderRoot(el, /* @__PURE__ */ React.createElement(ThemeProvider, {
|
236
|
+
tx: defaultTx
|
237
|
+
}, /* @__PURE__ */ React.createElement(Tooltip.Provider, null, /* @__PURE__ */ React.createElement(Component, props))));
|
238
|
+
};
|
319
239
|
|
320
|
-
// packages/ui/react-ui-editor/src/
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
240
|
+
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
241
|
+
var annotationMark = Decoration.mark({
|
242
|
+
class: "cm-annotation"
|
243
|
+
});
|
244
|
+
var annotations = (options = {}) => {
|
245
|
+
const match = (state) => {
|
246
|
+
const annotations2 = [];
|
247
|
+
const text = state.doc.toString();
|
248
|
+
if (options.match) {
|
249
|
+
const matches = text.matchAll(options.match);
|
250
|
+
for (const match2 of matches) {
|
251
|
+
const from = match2.index;
|
252
|
+
const to = from + match2[0].length;
|
253
|
+
const cursor = Cursor.getCursorFromRange(state, {
|
254
|
+
from,
|
255
|
+
to
|
256
|
+
});
|
257
|
+
annotations2.push({
|
258
|
+
cursor
|
259
|
+
});
|
260
|
+
}
|
261
|
+
}
|
262
|
+
return annotations2;
|
263
|
+
};
|
264
|
+
const annotationsState = StateField.define({
|
265
|
+
create: (state) => {
|
266
|
+
return match(state);
|
267
|
+
},
|
268
|
+
update: (value, tr) => {
|
269
|
+
if (!tr.changes.empty) {
|
270
|
+
return match(tr.state);
|
271
|
+
}
|
272
|
+
return value;
|
273
|
+
}
|
274
|
+
});
|
275
|
+
return [
|
276
|
+
annotationsState,
|
277
|
+
EditorView.decorations.compute([
|
278
|
+
annotationsState
|
279
|
+
], (state) => {
|
280
|
+
const annotations2 = state.field(annotationsState);
|
281
|
+
const decorations = annotations2.map((annotation) => {
|
282
|
+
const range = Cursor.getRangeFromCursor(state, annotation.cursor);
|
283
|
+
return range && annotationMark.range(range.from, range.to);
|
284
|
+
}).filter(isNotFalsy);
|
285
|
+
return Decoration.set(decorations);
|
286
|
+
}),
|
287
|
+
styles
|
288
|
+
];
|
329
289
|
};
|
330
|
-
var
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
return mx(headings[level], "dark:text-primary-400");
|
290
|
+
var styles = EditorView.theme({
|
291
|
+
".cm-annotation": {
|
292
|
+
textDecoration: "underline",
|
293
|
+
textDecorationStyle: "wavy",
|
294
|
+
textDecorationColor: "var(--dx-error)"
|
336
295
|
}
|
337
|
-
};
|
296
|
+
});
|
338
297
|
|
339
|
-
// packages/ui/react-ui-editor/src/
|
340
|
-
import
|
341
|
-
import {
|
342
|
-
|
343
|
-
|
344
|
-
|
298
|
+
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
299
|
+
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
300
|
+
import { markdownLanguage } from "@codemirror/lang-markdown";
|
301
|
+
import { keymap } from "@codemirror/view";
|
302
|
+
var autocomplete = ({ debug, activateOnTyping, override, onSearch } = {}) => {
|
303
|
+
const extensions = [
|
304
|
+
// https://codemirror.net/docs/ref/#view.keymap
|
305
|
+
// https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
|
306
|
+
// TODO(burdon): Set custom keymap.
|
307
|
+
keymap.of(completionKeymap),
|
308
|
+
// https://codemirror.net/examples/autocompletion
|
309
|
+
// https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
310
|
+
autocompletion({
|
311
|
+
activateOnTyping,
|
312
|
+
override,
|
313
|
+
closeOnBlur: !debug,
|
314
|
+
tooltipClass: () => "shadow rounded"
|
315
|
+
})
|
316
|
+
];
|
317
|
+
if (onSearch) {
|
318
|
+
extensions.push(
|
319
|
+
// TODO(burdon): Optional decoration via addToOptions
|
320
|
+
markdownLanguage.data.of({
|
321
|
+
autocomplete: (context) => {
|
322
|
+
const match = context.matchBefore(/\w*/);
|
323
|
+
if (!match || match.from === match.to && !context.explicit) {
|
324
|
+
return null;
|
325
|
+
}
|
326
|
+
return {
|
327
|
+
from: match.from,
|
328
|
+
options: onSearch(match.text.toLowerCase())
|
329
|
+
};
|
330
|
+
}
|
331
|
+
})
|
332
|
+
);
|
333
|
+
}
|
334
|
+
return extensions;
|
345
335
|
};
|
346
|
-
var fontBody = getToken("fontFamily.body");
|
347
|
-
var fontMono = getToken("fontFamily.mono");
|
348
336
|
|
349
|
-
// packages/ui/react-ui-editor/src/
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
color: "unset"
|
372
|
-
},
|
373
|
-
/**
|
374
|
-
* Gutters
|
375
|
-
* NOTE: Gutters should have the same top margin as the content.
|
376
|
-
*/
|
377
|
-
".cm-gutters": {
|
378
|
-
borderRight: "none",
|
379
|
-
background: "transparent"
|
380
|
-
},
|
381
|
-
".cm-gutter": {},
|
382
|
-
".cm-gutter.cm-lineNumbers": {
|
383
|
-
paddingRight: "4px",
|
384
|
-
borderRight: "1px solid var(--dx-separator)"
|
385
|
-
},
|
386
|
-
".cm-gutter.cm-lineNumbers .cm-gutterElement": {
|
387
|
-
minWidth: "40px",
|
388
|
-
alignContent: "center"
|
337
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
338
|
+
import { StateField as StateField2 } from "@codemirror/state";
|
339
|
+
import { EditorView as EditorView2, ViewPlugin } from "@codemirror/view";
|
340
|
+
import { next as A3 } from "@dxos/automerge/automerge";
|
341
|
+
|
342
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
343
|
+
import { log as log2 } from "@dxos/log";
|
344
|
+
import { fromCursor, toCursor } from "@dxos/react-client/echo";
|
345
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts";
|
346
|
+
var cursorConverter = (accessor) => ({
|
347
|
+
toCursor: (pos, assoc) => {
|
348
|
+
try {
|
349
|
+
return toCursor(accessor, pos, assoc);
|
350
|
+
} catch (err) {
|
351
|
+
log2.catch(err, void 0, {
|
352
|
+
F: __dxlog_file2,
|
353
|
+
L: 15,
|
354
|
+
S: void 0,
|
355
|
+
C: (f, a) => f(...a)
|
356
|
+
});
|
357
|
+
return "";
|
358
|
+
}
|
389
359
|
},
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
paddingInline: 0
|
402
|
-
},
|
403
|
-
".cm-activeLine": {
|
404
|
-
background: "var(--dx-cmActiveLine)"
|
405
|
-
},
|
406
|
-
/**
|
407
|
-
* Cursor (layer).
|
408
|
-
*/
|
409
|
-
".cm-cursor, .cm-dropCursor": {
|
410
|
-
borderLeft: "2px solid var(--dx-cmCursor)"
|
411
|
-
},
|
412
|
-
".cm-placeholder": {
|
413
|
-
color: "var(--dx-subdued)"
|
414
|
-
},
|
415
|
-
/**
|
416
|
-
* Selection (layer).
|
417
|
-
*/
|
418
|
-
".cm-selectionBackground": {
|
419
|
-
background: "var(--dx-cmSelection)"
|
420
|
-
},
|
421
|
-
/**
|
422
|
-
* Search.
|
423
|
-
* NOTE: Matches comment.
|
424
|
-
*/
|
425
|
-
".cm-searchMatch": {
|
426
|
-
margin: "0 -3px",
|
427
|
-
padding: "3px",
|
428
|
-
borderRadius: "3px",
|
429
|
-
background: "var(--dx-cmHighlightSurface)",
|
430
|
-
color: "var(--dx-cmHighlight)"
|
431
|
-
},
|
432
|
-
".cm-searchMatch-selected": {
|
433
|
-
textDecoration: "underline"
|
434
|
-
},
|
435
|
-
/**
|
436
|
-
* Link.
|
437
|
-
*/
|
438
|
-
".cm-link": {
|
439
|
-
textDecorationLine: "underline",
|
440
|
-
textDecorationThickness: "1px",
|
441
|
-
textDecorationColor: "var(--dx-separator)",
|
442
|
-
textUnderlineOffset: "2px",
|
443
|
-
borderRadius: ".125rem"
|
444
|
-
},
|
445
|
-
".cm-link > span": {
|
446
|
-
color: "var(--dx-accentText)"
|
447
|
-
},
|
448
|
-
/**
|
449
|
-
* Tooltip.
|
450
|
-
*/
|
451
|
-
".cm-tooltip": {
|
452
|
-
background: "var(--dx-baseSurface)"
|
453
|
-
},
|
454
|
-
".cm-tooltip-below": {},
|
455
|
-
/**
|
456
|
-
* Autocomplete.
|
457
|
-
* https://github.com/codemirror/autocomplete/blob/main/src/completion.ts
|
458
|
-
*/
|
459
|
-
".cm-tooltip.cm-tooltip-autocomplete": {
|
460
|
-
marginTop: "4px",
|
461
|
-
marginLeft: "-3px"
|
462
|
-
},
|
463
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul": {
|
464
|
-
maxHeight: "20em"
|
465
|
-
},
|
466
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > li": {},
|
467
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {},
|
468
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
|
469
|
-
paddingLeft: "4px !important",
|
470
|
-
borderBottom: "none !important",
|
471
|
-
color: "var(--dx-accentText)"
|
472
|
-
},
|
473
|
-
".cm-tooltip.cm-completionInfo": {
|
474
|
-
width: "360px !important",
|
475
|
-
margin: "-10px 1px 0 1px",
|
476
|
-
padding: "8px !important",
|
477
|
-
borderColor: "var(--dx-separator)"
|
478
|
-
},
|
479
|
-
".cm-completionIcon": {
|
480
|
-
display: "none"
|
481
|
-
},
|
482
|
-
".cm-completionLabel": {
|
483
|
-
fontFamily: fontBody
|
484
|
-
},
|
485
|
-
".cm-completionMatchedText": {
|
486
|
-
textDecoration: "none !important",
|
487
|
-
opacity: 0.5
|
488
|
-
},
|
489
|
-
/**
|
490
|
-
* Panels
|
491
|
-
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
492
|
-
*
|
493
|
-
* Find/replace panel.
|
494
|
-
* <div class="cm-announced">...</div>
|
495
|
-
* <div class="cm-scroller">...</div>
|
496
|
-
* <div class="cm-panels cm-panels-bottom">
|
497
|
-
* <div class="cm-search cm-panel">
|
498
|
-
* <input class="cm-textfield" />
|
499
|
-
* <button class="cm-button">...</button>
|
500
|
-
* <label><input type="checkbox" />...</label>
|
501
|
-
* </div>
|
502
|
-
* </div
|
503
|
-
*/
|
504
|
-
// TODO(burdon): Implement custom panel (with icon buttons).
|
505
|
-
".cm-panels": {},
|
506
|
-
".cm-panel": {
|
507
|
-
fontFamily: fontBody,
|
508
|
-
backgroundColor: "var(--surface-bg)"
|
509
|
-
},
|
510
|
-
".cm-panel input, .cm-panel button, .cm-panel label": {
|
511
|
-
color: "var(--dx-subdued)",
|
512
|
-
fontFamily: fontBody,
|
513
|
-
fontSize: "14px",
|
514
|
-
all: "unset",
|
515
|
-
margin: "3px !important",
|
516
|
-
padding: "2px 6px !important",
|
517
|
-
outline: "1px solid transparent"
|
518
|
-
},
|
519
|
-
".cm-panel input, .cm-panel button": {
|
520
|
-
backgroundColor: "var(--dx-input)"
|
521
|
-
},
|
522
|
-
".cm-panel input:focus, .cm-panel button:focus": {
|
523
|
-
outline: "1px solid var(--dx-accentFocusIndicator)"
|
524
|
-
},
|
525
|
-
".cm-panel label": {
|
526
|
-
display: "inline-flex",
|
527
|
-
alignItems: "center",
|
528
|
-
cursor: "pointer"
|
529
|
-
},
|
530
|
-
".cm-panel input.cm-textfield": {},
|
531
|
-
".cm-panel input[type=checkbox]": {
|
532
|
-
width: "8px",
|
533
|
-
height: "8px",
|
534
|
-
marginRight: "6px !important",
|
535
|
-
padding: "2px !important",
|
536
|
-
color: "var(--dx-accentFocusIndicator)"
|
537
|
-
},
|
538
|
-
".cm-panel button": {
|
539
|
-
"&:hover": {
|
540
|
-
backgroundColor: "var(--dx-accentSurfaceHover) !important"
|
541
|
-
},
|
542
|
-
"&:active": {
|
543
|
-
backgroundColor: "var(--dx-accentSurfaceHover)"
|
360
|
+
fromCursor: (cursor) => {
|
361
|
+
try {
|
362
|
+
return fromCursor(accessor, cursor);
|
363
|
+
} catch (err) {
|
364
|
+
log2.catch(err, void 0, {
|
365
|
+
F: __dxlog_file2,
|
366
|
+
L: 24,
|
367
|
+
S: void 0,
|
368
|
+
C: (f, a) => f(...a)
|
369
|
+
});
|
370
|
+
return 0;
|
544
371
|
}
|
545
|
-
},
|
546
|
-
".cm-panel.cm-search": {
|
547
|
-
padding: "4px",
|
548
|
-
borderTop: "1px solid var(--dx-separator)"
|
549
|
-
}
|
550
|
-
};
|
551
|
-
|
552
|
-
// packages/ui/react-ui-editor/src/defaults.ts
|
553
|
-
var margin = "!mt-[1rem]";
|
554
|
-
var editorWidth = "!mli-auto is-full max-is-[min(50rem,100%-4rem)]";
|
555
|
-
var editorContent = mx2(margin, editorWidth);
|
556
|
-
var editorFullWidth = mx2(margin);
|
557
|
-
var editorGutter = EditorView.theme({
|
558
|
-
// Match margin from content.
|
559
|
-
// Gutter = 2rem + 1rem margin.
|
560
|
-
".cm-gutters": {
|
561
|
-
marginTop: "1rem",
|
562
|
-
paddingRight: "1rem"
|
563
372
|
}
|
564
373
|
});
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
374
|
+
|
375
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
376
|
+
import { Annotation, StateEffect } from "@codemirror/state";
|
377
|
+
var getPath = (state, field) => state.field(field).path;
|
378
|
+
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
379
|
+
var updateHeadsEffect = StateEffect.define({});
|
380
|
+
var updateHeads = (newHeads) => updateHeadsEffect.of({
|
381
|
+
newHeads
|
569
382
|
});
|
570
|
-
var
|
571
|
-
var
|
572
|
-
|
383
|
+
var reconcileAnnotation = Annotation.define();
|
384
|
+
var isReconcile = (tr) => {
|
385
|
+
return !!tr.annotation(reconcileAnnotation);
|
386
|
+
};
|
573
387
|
|
574
|
-
// packages/ui/react-ui-editor/src/
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
nodes.push(...formatting.nodes);
|
586
|
-
edges.push(...formatting.edges);
|
587
|
-
}
|
588
|
-
if (features.lists ?? true) {
|
589
|
-
const lists = createLists(state);
|
590
|
-
nodes.push(...lists.nodes);
|
591
|
-
edges.push(...lists.edges);
|
592
|
-
}
|
593
|
-
if (features.blocks ?? true) {
|
594
|
-
const blocks = createBlocks(state);
|
595
|
-
nodes.push(...blocks.nodes);
|
596
|
-
edges.push(...blocks.edges);
|
597
|
-
}
|
598
|
-
if (customActions) {
|
599
|
-
const custom = customActions();
|
600
|
-
nodes.push(...custom.nodes);
|
601
|
-
edges.push(...custom.edges);
|
602
|
-
}
|
603
|
-
const editorToolbarGap = createGapSeparator();
|
604
|
-
nodes.push(...editorToolbarGap.nodes);
|
605
|
-
edges.push(...editorToolbarGap.edges);
|
606
|
-
if (features.comment ?? true) {
|
607
|
-
const comment = createComment(state);
|
608
|
-
nodes.push(...comment.nodes);
|
609
|
-
edges.push(...comment.edges);
|
610
|
-
}
|
611
|
-
if (features.search ?? true) {
|
612
|
-
nodes.push(editorToolbarSearch);
|
613
|
-
edges.push({
|
614
|
-
source: "root",
|
615
|
-
target: editorToolbarSearch.id
|
388
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/sync.ts
|
389
|
+
import { next as A2 } from "@dxos/automerge/automerge";
|
390
|
+
|
391
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
392
|
+
import { next as A } from "@dxos/automerge/automerge";
|
393
|
+
var updateAutomerge = (field, handle, transactions, state) => {
|
394
|
+
const { lastHeads, path } = state.field(field);
|
395
|
+
let hasChanges = false;
|
396
|
+
for (const tr of transactions) {
|
397
|
+
tr.changes.iterChanges(() => {
|
398
|
+
hasChanges = true;
|
616
399
|
});
|
617
400
|
}
|
618
|
-
if (
|
619
|
-
|
620
|
-
nodes.push(...viewMode.nodes);
|
621
|
-
edges.push(...viewMode.edges);
|
401
|
+
if (!hasChanges) {
|
402
|
+
return void 0;
|
622
403
|
}
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
};
|
638
|
-
|
639
|
-
const menuProps = useEditorToolbarActionGraph(props);
|
640
|
-
return /* @__PURE__ */ React.createElement("div", {
|
641
|
-
role: "none",
|
642
|
-
className: stackItemContentToolbarClassNames(role)
|
643
|
-
}, /* @__PURE__ */ React.createElement(ElevationProvider, {
|
644
|
-
elevation: role === "section" ? "positioned" : "base"
|
645
|
-
}, /* @__PURE__ */ React.createElement(MenuProvider, {
|
646
|
-
...menuProps,
|
647
|
-
attendableId
|
648
|
-
}, /* @__PURE__ */ React.createElement(ToolbarMenu, {
|
649
|
-
classNames: [
|
650
|
-
textBlockWidth,
|
651
|
-
"!bg-transparent",
|
652
|
-
classNames
|
653
|
-
]
|
654
|
-
}))));
|
404
|
+
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
405
|
+
const invertedTransactions = [];
|
406
|
+
for (const tr of transactions) {
|
407
|
+
tr.changes.iterChanges((fromA, toA, _fromB, _toB, insert) => {
|
408
|
+
invertedTransactions.push({
|
409
|
+
from: fromA,
|
410
|
+
del: toA - fromA,
|
411
|
+
insert
|
412
|
+
});
|
413
|
+
});
|
414
|
+
}
|
415
|
+
invertedTransactions.reverse().forEach(({ from, del, insert }) => {
|
416
|
+
A.splice(doc, path.slice(), from, del, insert.toString());
|
417
|
+
});
|
418
|
+
});
|
419
|
+
return newHeads ?? void 0;
|
655
420
|
};
|
656
421
|
|
657
|
-
// packages/ui/react-ui-editor/src/extensions/
|
658
|
-
import {
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
422
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/update-codemirror.ts
|
423
|
+
import { ChangeSet } from "@codemirror/state";
|
424
|
+
var updateCodeMirror = (view, selection, target, patches) => {
|
425
|
+
for (const patch of patches) {
|
426
|
+
const changeSpec = handlePatch(patch, target, view.state);
|
427
|
+
if (changeSpec != null) {
|
428
|
+
const changeSet = ChangeSet.of(changeSpec, view.state.doc.length, "\n");
|
429
|
+
selection = selection.map(changeSet, 1);
|
430
|
+
view.dispatch({
|
431
|
+
changes: changeSet,
|
432
|
+
annotations: reconcileAnnotation.of(false)
|
433
|
+
});
|
434
|
+
}
|
668
435
|
}
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
var defaultCursorConverter = {
|
674
|
-
toCursor: (position) => position.toString(),
|
675
|
-
fromCursor: (cursor) => parseInt(cursor)
|
436
|
+
view.dispatch({
|
437
|
+
selection,
|
438
|
+
annotations: reconcileAnnotation.of(false)
|
439
|
+
});
|
676
440
|
};
|
677
|
-
var
|
678
|
-
|
679
|
-
|
680
|
-
}
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
to
|
689
|
-
].join(":");
|
690
|
-
};
|
691
|
-
}
|
692
|
-
static {
|
693
|
-
this.getRangeFromCursor = (state, cursor) => {
|
694
|
-
const cursorConverter2 = state.facet(_Cursor.converter);
|
695
|
-
const parts = cursor.split(":");
|
696
|
-
const from = cursorConverter2.fromCursor(parts[0]);
|
697
|
-
const to = cursorConverter2.fromCursor(parts[1]);
|
698
|
-
return from !== void 0 && to !== void 0 ? {
|
699
|
-
from,
|
700
|
-
to
|
701
|
-
} : void 0;
|
702
|
-
};
|
441
|
+
var handlePatch = (patch, target, state) => {
|
442
|
+
if (patch.action === "insert") {
|
443
|
+
return handleInsert(target, patch);
|
444
|
+
} else if (patch.action === "splice") {
|
445
|
+
return handleSplice(target, patch);
|
446
|
+
} else if (patch.action === "del") {
|
447
|
+
return handleDel(target, patch);
|
448
|
+
} else if (patch.action === "put") {
|
449
|
+
return handlePut(target, patch, state);
|
450
|
+
} else {
|
451
|
+
return null;
|
703
452
|
}
|
704
453
|
};
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
L: 15,
|
717
|
-
S: void 0,
|
718
|
-
C: (f, a) => f(...a)
|
719
|
-
});
|
454
|
+
var handleInsert = (target, patch) => {
|
455
|
+
const index = charPath(target, patch.path);
|
456
|
+
if (index == null) {
|
457
|
+
return [];
|
458
|
+
}
|
459
|
+
const text = patch.values.map((value) => value ? value.toString() : "").join("");
|
460
|
+
return [
|
461
|
+
{
|
462
|
+
from: index,
|
463
|
+
to: index,
|
464
|
+
insert: text
|
720
465
|
}
|
721
|
-
|
466
|
+
];
|
722
467
|
};
|
723
|
-
var
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
log.catch(err, void 0, {
|
728
|
-
F: __dxlog_file,
|
729
|
-
L: 29,
|
730
|
-
S: void 0,
|
731
|
-
C: (f, a) => f(...a)
|
732
|
-
});
|
468
|
+
var handleSplice = (target, patch) => {
|
469
|
+
const index = charPath(target, patch.path);
|
470
|
+
if (index == null) {
|
471
|
+
return [];
|
733
472
|
}
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
};
|
739
|
-
var logChanges = (trs) => {
|
740
|
-
const changes = trs.flatMap((tr) => {
|
741
|
-
if (tr.changes.empty) {
|
742
|
-
return void 0;
|
473
|
+
return [
|
474
|
+
{
|
475
|
+
from: index,
|
476
|
+
insert: patch.value
|
743
477
|
}
|
744
|
-
|
745
|
-
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
746
|
-
fromA,
|
747
|
-
toA,
|
748
|
-
fromB,
|
749
|
-
toB,
|
750
|
-
inserted: inserted.toString()
|
751
|
-
})));
|
752
|
-
return changes2;
|
753
|
-
}).filter(Boolean);
|
754
|
-
if (changes.length) {
|
755
|
-
log("changes", {
|
756
|
-
changes
|
757
|
-
}, {
|
758
|
-
F: __dxlog_file,
|
759
|
-
L: 62,
|
760
|
-
S: void 0,
|
761
|
-
C: (f, a) => f(...a)
|
762
|
-
});
|
763
|
-
}
|
764
|
-
};
|
765
|
-
|
766
|
-
// packages/ui/react-ui-editor/src/util/dom.ts
|
767
|
-
var flattenRect = (rect, left) => {
|
768
|
-
const x = left ? rect.left : rect.right;
|
769
|
-
return {
|
770
|
-
left: x,
|
771
|
-
right: x,
|
772
|
-
top: rect.top,
|
773
|
-
bottom: rect.bottom
|
774
|
-
};
|
775
|
-
};
|
776
|
-
var scratchRange;
|
777
|
-
var textRange = (node, from, to = from) => {
|
778
|
-
const range = scratchRange || (scratchRange = document.createRange());
|
779
|
-
range.setEnd(node, to);
|
780
|
-
range.setStart(node, from);
|
781
|
-
return range;
|
478
|
+
];
|
782
479
|
};
|
783
|
-
var
|
784
|
-
|
785
|
-
|
786
|
-
} else if (dom.nodeType === 1) {
|
787
|
-
return dom.getClientRects();
|
788
|
-
} else {
|
480
|
+
var handleDel = (target, patch) => {
|
481
|
+
const index = charPath(target, patch.path);
|
482
|
+
if (index == null) {
|
789
483
|
return [];
|
790
484
|
}
|
485
|
+
const length = patch.length || 1;
|
486
|
+
return [
|
487
|
+
{
|
488
|
+
from: index,
|
489
|
+
to: index + length
|
490
|
+
}
|
491
|
+
];
|
791
492
|
};
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
const el = document.createElement(tag);
|
800
|
-
if (options?.className) {
|
801
|
-
el.className = options.className;
|
493
|
+
var handlePut = (target, patch, state) => {
|
494
|
+
const index = charPath(target, [
|
495
|
+
...patch.path,
|
496
|
+
0
|
497
|
+
]);
|
498
|
+
if (index == null) {
|
499
|
+
return [];
|
802
500
|
}
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
]);
|
501
|
+
const length = state.doc.length;
|
502
|
+
if (typeof patch.value !== "string") {
|
503
|
+
return [];
|
807
504
|
}
|
808
|
-
return
|
505
|
+
return [
|
506
|
+
{
|
507
|
+
from: 0,
|
508
|
+
to: length,
|
509
|
+
insert: patch.value
|
510
|
+
}
|
511
|
+
];
|
809
512
|
};
|
810
|
-
var
|
811
|
-
|
812
|
-
|
813
|
-
}
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
513
|
+
var charPath = (textPath, candidatePath) => {
|
514
|
+
if (candidatePath.length !== textPath.length + 1) {
|
515
|
+
return null;
|
516
|
+
}
|
517
|
+
for (let i = 0; i < textPath.length; i++) {
|
518
|
+
if (textPath[i] !== candidatePath[i]) {
|
519
|
+
return null;
|
520
|
+
}
|
521
|
+
}
|
522
|
+
const index = candidatePath[candidatePath.length - 1];
|
523
|
+
if (typeof index === "number") {
|
524
|
+
return index;
|
525
|
+
}
|
526
|
+
return null;
|
820
527
|
};
|
821
528
|
|
822
|
-
// packages/ui/react-ui-editor/src/extensions/
|
823
|
-
var
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
const from = match2.index;
|
834
|
-
const to = from + match2[0].length;
|
835
|
-
const cursor = Cursor.getCursorFromRange(state, {
|
836
|
-
from,
|
837
|
-
to
|
838
|
-
});
|
839
|
-
annotations2.push({
|
840
|
-
cursor
|
841
|
-
});
|
842
|
-
}
|
529
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/sync.ts
|
530
|
+
var Syncer = class {
|
531
|
+
// prettier-ignore
|
532
|
+
constructor(_handle, _state) {
|
533
|
+
this._handle = _handle;
|
534
|
+
this._state = _state;
|
535
|
+
this._pending = false;
|
536
|
+
}
|
537
|
+
reconcile(view, editor) {
|
538
|
+
if (this._pending) {
|
539
|
+
return;
|
843
540
|
}
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
}
|
541
|
+
this._pending = true;
|
542
|
+
if (editor) {
|
543
|
+
this.onEditorChange(view);
|
544
|
+
} else {
|
545
|
+
this.onAutomergeChange(view);
|
546
|
+
}
|
547
|
+
this._pending = false;
|
548
|
+
}
|
549
|
+
onEditorChange(view) {
|
550
|
+
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcile(tx));
|
551
|
+
const newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
|
552
|
+
if (newHeads) {
|
553
|
+
view.dispatch({
|
554
|
+
effects: updateHeads(newHeads),
|
555
|
+
annotations: reconcileAnnotation.of(false)
|
556
|
+
});
|
557
|
+
}
|
558
|
+
}
|
559
|
+
onAutomergeChange(view) {
|
560
|
+
const oldHeads = getLastHeads(view.state, this._state);
|
561
|
+
const newHeads = A2.getHeads(this._handle.docSync());
|
562
|
+
const diff = A2.equals(oldHeads, newHeads) ? [] : A2.diff(this._handle.docSync(), oldHeads, newHeads);
|
563
|
+
const selection = view.state.selection;
|
564
|
+
const path = getPath(view.state, this._state);
|
565
|
+
updateCodeMirror(view, selection, path, diff);
|
566
|
+
view.dispatch({
|
567
|
+
effects: updateHeads(newHeads),
|
568
|
+
annotations: reconcileAnnotation.of(false)
|
569
|
+
});
|
570
|
+
}
|
571
|
+
};
|
572
|
+
|
573
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
574
|
+
var automerge = (accessor) => {
|
575
|
+
const syncState = StateField2.define({
|
576
|
+
create: () => ({
|
577
|
+
path: accessor.path.slice(),
|
578
|
+
lastHeads: A3.getHeads(accessor.handle.docSync()),
|
579
|
+
unreconciledTransactions: []
|
580
|
+
}),
|
850
581
|
update: (value, tr) => {
|
851
|
-
|
852
|
-
|
582
|
+
const result = {
|
583
|
+
path: accessor.path.slice(),
|
584
|
+
lastHeads: value.lastHeads,
|
585
|
+
unreconciledTransactions: value.unreconciledTransactions.slice()
|
586
|
+
};
|
587
|
+
let clearUnreconciled = false;
|
588
|
+
for (const effect of tr.effects) {
|
589
|
+
if (effect.is(updateHeadsEffect)) {
|
590
|
+
result.lastHeads = effect.value.newHeads;
|
591
|
+
clearUnreconciled = true;
|
592
|
+
}
|
853
593
|
}
|
854
|
-
|
594
|
+
if (clearUnreconciled) {
|
595
|
+
result.unreconciledTransactions = [];
|
596
|
+
} else {
|
597
|
+
if (!isReconcile(tr)) {
|
598
|
+
result.unreconciledTransactions.push(tr);
|
599
|
+
}
|
600
|
+
}
|
601
|
+
return result;
|
855
602
|
}
|
856
603
|
});
|
604
|
+
const syncer = new Syncer(accessor.handle, syncState);
|
857
605
|
return [
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
606
|
+
Cursor.converter.of(cursorConverter(accessor)),
|
607
|
+
// Track heads.
|
608
|
+
syncState,
|
609
|
+
// Reconcile external updates.
|
610
|
+
ViewPlugin.fromClass(class {
|
611
|
+
constructor(_view) {
|
612
|
+
this._view = _view;
|
613
|
+
this._handleChange = () => {
|
614
|
+
syncer.reconcile(this._view, false);
|
615
|
+
};
|
616
|
+
accessor.handle.addListener("change", this._handleChange);
|
617
|
+
}
|
618
|
+
destroy() {
|
619
|
+
accessor.handle.removeListener("change", this._handleChange);
|
620
|
+
}
|
868
621
|
}),
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
textDecoration: "underline",
|
875
|
-
textDecorationStyle: "wavy",
|
876
|
-
textDecorationColor: "var(--dx-error)"
|
877
|
-
}
|
878
|
-
});
|
879
|
-
|
880
|
-
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
881
|
-
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
882
|
-
import { markdownLanguage } from "@codemirror/lang-markdown";
|
883
|
-
import { keymap } from "@codemirror/view";
|
884
|
-
var autocomplete = ({ debug, activateOnTyping, override, onSearch } = {}) => {
|
885
|
-
const extensions = [
|
886
|
-
// https://codemirror.net/docs/ref/#view.keymap
|
887
|
-
// https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
|
888
|
-
// TODO(burdon): Set custom keymap.
|
889
|
-
keymap.of(completionKeymap),
|
890
|
-
// https://codemirror.net/examples/autocompletion
|
891
|
-
// https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
892
|
-
autocompletion({
|
893
|
-
activateOnTyping,
|
894
|
-
override,
|
895
|
-
closeOnBlur: !debug,
|
896
|
-
tooltipClass: () => "shadow rounded"
|
622
|
+
// Reconcile local updates.
|
623
|
+
EditorView2.updateListener.of(({ view, changes }) => {
|
624
|
+
if (!changes.empty) {
|
625
|
+
syncer.reconcile(view, true);
|
626
|
+
}
|
897
627
|
})
|
898
628
|
];
|
899
|
-
if (onSearch) {
|
900
|
-
extensions.push(
|
901
|
-
// TODO(burdon): Optional decoration via addToOptions
|
902
|
-
markdownLanguage.data.of({
|
903
|
-
autocomplete: (context) => {
|
904
|
-
const match = context.matchBefore(/\w*/);
|
905
|
-
if (!match || match.from === match.to && !context.explicit) {
|
906
|
-
return null;
|
907
|
-
}
|
908
|
-
return {
|
909
|
-
from: match.from,
|
910
|
-
options: onSearch(match.text.toLowerCase())
|
911
|
-
};
|
912
|
-
}
|
913
|
-
})
|
914
|
-
);
|
915
|
-
}
|
916
|
-
return extensions;
|
917
629
|
};
|
918
630
|
|
919
|
-
// packages/ui/react-ui-editor/src/extensions/
|
920
|
-
import {
|
921
|
-
import { EditorView as EditorView3, ViewPlugin } from "@codemirror/view";
|
922
|
-
import {
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
var cursorConverter = (accessor) => ({
|
929
|
-
toCursor: (pos, assoc) => {
|
930
|
-
try {
|
931
|
-
return toCursor(accessor, pos, assoc);
|
932
|
-
} catch (err) {
|
933
|
-
log2.catch(err, void 0, {
|
934
|
-
F: __dxlog_file2,
|
935
|
-
L: 15,
|
936
|
-
S: void 0,
|
937
|
-
C: (f, a) => f(...a)
|
938
|
-
});
|
939
|
-
return "";
|
940
|
-
}
|
631
|
+
// packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts
|
632
|
+
import { Annotation as Annotation2, RangeSet } from "@codemirror/state";
|
633
|
+
import { Decoration as Decoration2, EditorView as EditorView3, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
634
|
+
import { Event } from "@dxos/async";
|
635
|
+
import { Context } from "@dxos/context";
|
636
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts";
|
637
|
+
var dummyProvider = {
|
638
|
+
remoteStateChange: new Event(),
|
639
|
+
open: () => {
|
941
640
|
},
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
log2.catch(err, void 0, {
|
947
|
-
F: __dxlog_file2,
|
948
|
-
L: 24,
|
949
|
-
S: void 0,
|
950
|
-
C: (f, a) => f(...a)
|
951
|
-
});
|
952
|
-
return 0;
|
953
|
-
}
|
954
|
-
}
|
955
|
-
});
|
956
|
-
|
957
|
-
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
958
|
-
import { Annotation, StateEffect } from "@codemirror/state";
|
959
|
-
var getPath = (state, field) => state.field(field).path;
|
960
|
-
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
961
|
-
var updateHeadsEffect = StateEffect.define({});
|
962
|
-
var updateHeads = (newHeads) => updateHeadsEffect.of({
|
963
|
-
newHeads
|
964
|
-
});
|
965
|
-
var reconcileAnnotation = Annotation.define();
|
966
|
-
var isReconcile = (tr) => {
|
967
|
-
return !!tr.annotation(reconcileAnnotation);
|
968
|
-
};
|
969
|
-
|
970
|
-
// packages/ui/react-ui-editor/src/extensions/automerge/sync.ts
|
971
|
-
import { next as A2 } from "@dxos/automerge/automerge";
|
972
|
-
|
973
|
-
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
974
|
-
import { next as A } from "@dxos/automerge/automerge";
|
975
|
-
var updateAutomerge = (field, handle, transactions, state) => {
|
976
|
-
const { lastHeads, path } = state.field(field);
|
977
|
-
let hasChanges = false;
|
978
|
-
for (const tr of transactions) {
|
979
|
-
tr.changes.iterChanges(() => {
|
980
|
-
hasChanges = true;
|
981
|
-
});
|
982
|
-
}
|
983
|
-
if (!hasChanges) {
|
984
|
-
return void 0;
|
985
|
-
}
|
986
|
-
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
987
|
-
const invertedTransactions = [];
|
988
|
-
for (const tr of transactions) {
|
989
|
-
tr.changes.iterChanges((fromA, toA, _fromB, _toB, insert) => {
|
990
|
-
invertedTransactions.push({
|
991
|
-
from: fromA,
|
992
|
-
del: toA - fromA,
|
993
|
-
insert
|
994
|
-
});
|
995
|
-
});
|
996
|
-
}
|
997
|
-
invertedTransactions.reverse().forEach(({ from, del, insert }) => {
|
998
|
-
A.splice(doc, path.slice(), from, del, insert.toString());
|
999
|
-
});
|
1000
|
-
});
|
1001
|
-
return newHeads ?? void 0;
|
1002
|
-
};
|
1003
|
-
|
1004
|
-
// packages/ui/react-ui-editor/src/extensions/automerge/update-codemirror.ts
|
1005
|
-
import { ChangeSet } from "@codemirror/state";
|
1006
|
-
var updateCodeMirror = (view, selection, target, patches) => {
|
1007
|
-
for (const patch of patches) {
|
1008
|
-
const changeSpec = handlePatch(patch, target, view.state);
|
1009
|
-
if (changeSpec != null) {
|
1010
|
-
const changeSet = ChangeSet.of(changeSpec, view.state.doc.length, "\n");
|
1011
|
-
selection = selection.map(changeSet, 1);
|
1012
|
-
view.dispatch({
|
1013
|
-
changes: changeSet,
|
1014
|
-
annotations: reconcileAnnotation.of(false)
|
1015
|
-
});
|
1016
|
-
}
|
1017
|
-
}
|
1018
|
-
view.dispatch({
|
1019
|
-
selection,
|
1020
|
-
annotations: reconcileAnnotation.of(false)
|
1021
|
-
});
|
1022
|
-
};
|
1023
|
-
var handlePatch = (patch, target, state) => {
|
1024
|
-
if (patch.action === "insert") {
|
1025
|
-
return handleInsert(target, patch);
|
1026
|
-
} else if (patch.action === "splice") {
|
1027
|
-
return handleSplice(target, patch);
|
1028
|
-
} else if (patch.action === "del") {
|
1029
|
-
return handleDel(target, patch);
|
1030
|
-
} else if (patch.action === "put") {
|
1031
|
-
return handlePut(target, patch, state);
|
1032
|
-
} else {
|
1033
|
-
return null;
|
1034
|
-
}
|
1035
|
-
};
|
1036
|
-
var handleInsert = (target, patch) => {
|
1037
|
-
const index = charPath(target, patch.path);
|
1038
|
-
if (index == null) {
|
1039
|
-
return [];
|
1040
|
-
}
|
1041
|
-
const text = patch.values.map((value) => value ? value.toString() : "").join("");
|
1042
|
-
return [
|
1043
|
-
{
|
1044
|
-
from: index,
|
1045
|
-
to: index,
|
1046
|
-
insert: text
|
1047
|
-
}
|
1048
|
-
];
|
1049
|
-
};
|
1050
|
-
var handleSplice = (target, patch) => {
|
1051
|
-
const index = charPath(target, patch.path);
|
1052
|
-
if (index == null) {
|
1053
|
-
return [];
|
1054
|
-
}
|
1055
|
-
return [
|
1056
|
-
{
|
1057
|
-
from: index,
|
1058
|
-
insert: patch.value
|
1059
|
-
}
|
1060
|
-
];
|
1061
|
-
};
|
1062
|
-
var handleDel = (target, patch) => {
|
1063
|
-
const index = charPath(target, patch.path);
|
1064
|
-
if (index == null) {
|
1065
|
-
return [];
|
1066
|
-
}
|
1067
|
-
const length = patch.length || 1;
|
1068
|
-
return [
|
1069
|
-
{
|
1070
|
-
from: index,
|
1071
|
-
to: index + length
|
1072
|
-
}
|
1073
|
-
];
|
1074
|
-
};
|
1075
|
-
var handlePut = (target, patch, state) => {
|
1076
|
-
const index = charPath(target, [
|
1077
|
-
...patch.path,
|
1078
|
-
0
|
1079
|
-
]);
|
1080
|
-
if (index == null) {
|
1081
|
-
return [];
|
1082
|
-
}
|
1083
|
-
const length = state.doc.length;
|
1084
|
-
if (typeof patch.value !== "string") {
|
1085
|
-
return [];
|
1086
|
-
}
|
1087
|
-
return [
|
1088
|
-
{
|
1089
|
-
from: 0,
|
1090
|
-
to: length,
|
1091
|
-
insert: patch.value
|
1092
|
-
}
|
1093
|
-
];
|
1094
|
-
};
|
1095
|
-
var charPath = (textPath, candidatePath) => {
|
1096
|
-
if (candidatePath.length !== textPath.length + 1) {
|
1097
|
-
return null;
|
1098
|
-
}
|
1099
|
-
for (let i = 0; i < textPath.length; i++) {
|
1100
|
-
if (textPath[i] !== candidatePath[i]) {
|
1101
|
-
return null;
|
1102
|
-
}
|
1103
|
-
}
|
1104
|
-
const index = candidatePath[candidatePath.length - 1];
|
1105
|
-
if (typeof index === "number") {
|
1106
|
-
return index;
|
1107
|
-
}
|
1108
|
-
return null;
|
1109
|
-
};
|
1110
|
-
|
1111
|
-
// packages/ui/react-ui-editor/src/extensions/automerge/sync.ts
|
1112
|
-
var Syncer = class {
|
1113
|
-
// prettier-ignore
|
1114
|
-
constructor(_handle, _state) {
|
1115
|
-
this._handle = _handle;
|
1116
|
-
this._state = _state;
|
1117
|
-
this._pending = false;
|
1118
|
-
}
|
1119
|
-
reconcile(view, editor) {
|
1120
|
-
if (this._pending) {
|
1121
|
-
return;
|
1122
|
-
}
|
1123
|
-
this._pending = true;
|
1124
|
-
if (editor) {
|
1125
|
-
this.onEditorChange(view);
|
1126
|
-
} else {
|
1127
|
-
this.onAutomergeChange(view);
|
1128
|
-
}
|
1129
|
-
this._pending = false;
|
1130
|
-
}
|
1131
|
-
onEditorChange(view) {
|
1132
|
-
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcile(tx));
|
1133
|
-
const newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
|
1134
|
-
if (newHeads) {
|
1135
|
-
view.dispatch({
|
1136
|
-
effects: updateHeads(newHeads),
|
1137
|
-
annotations: reconcileAnnotation.of(false)
|
1138
|
-
});
|
1139
|
-
}
|
1140
|
-
}
|
1141
|
-
onAutomergeChange(view) {
|
1142
|
-
const oldHeads = getLastHeads(view.state, this._state);
|
1143
|
-
const newHeads = A2.getHeads(this._handle.docSync());
|
1144
|
-
const diff = A2.equals(oldHeads, newHeads) ? [] : A2.diff(this._handle.docSync(), oldHeads, newHeads);
|
1145
|
-
const selection = view.state.selection;
|
1146
|
-
const path = getPath(view.state, this._state);
|
1147
|
-
updateCodeMirror(view, selection, path, diff);
|
1148
|
-
view.dispatch({
|
1149
|
-
effects: updateHeads(newHeads),
|
1150
|
-
annotations: reconcileAnnotation.of(false)
|
1151
|
-
});
|
1152
|
-
}
|
1153
|
-
};
|
1154
|
-
|
1155
|
-
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
1156
|
-
var automerge = (accessor) => {
|
1157
|
-
const syncState = StateField2.define({
|
1158
|
-
create: () => ({
|
1159
|
-
path: accessor.path.slice(),
|
1160
|
-
lastHeads: A3.getHeads(accessor.handle.docSync()),
|
1161
|
-
unreconciledTransactions: []
|
1162
|
-
}),
|
1163
|
-
update: (value, tr) => {
|
1164
|
-
const result = {
|
1165
|
-
path: accessor.path.slice(),
|
1166
|
-
lastHeads: value.lastHeads,
|
1167
|
-
unreconciledTransactions: value.unreconciledTransactions.slice()
|
1168
|
-
};
|
1169
|
-
let clearUnreconciled = false;
|
1170
|
-
for (const effect of tr.effects) {
|
1171
|
-
if (effect.is(updateHeadsEffect)) {
|
1172
|
-
result.lastHeads = effect.value.newHeads;
|
1173
|
-
clearUnreconciled = true;
|
1174
|
-
}
|
1175
|
-
}
|
1176
|
-
if (clearUnreconciled) {
|
1177
|
-
result.unreconciledTransactions = [];
|
1178
|
-
} else {
|
1179
|
-
if (!isReconcile(tr)) {
|
1180
|
-
result.unreconciledTransactions.push(tr);
|
1181
|
-
}
|
1182
|
-
}
|
1183
|
-
return result;
|
1184
|
-
}
|
1185
|
-
});
|
1186
|
-
const syncer = new Syncer(accessor.handle, syncState);
|
1187
|
-
return [
|
1188
|
-
Cursor.converter.of(cursorConverter(accessor)),
|
1189
|
-
// Track heads.
|
1190
|
-
syncState,
|
1191
|
-
// Reconcile external updates.
|
1192
|
-
ViewPlugin.fromClass(class {
|
1193
|
-
constructor(_view) {
|
1194
|
-
this._view = _view;
|
1195
|
-
this._handleChange = () => {
|
1196
|
-
syncer.reconcile(this._view, false);
|
1197
|
-
};
|
1198
|
-
accessor.handle.addListener("change", this._handleChange);
|
1199
|
-
}
|
1200
|
-
destroy() {
|
1201
|
-
accessor.handle.removeListener("change", this._handleChange);
|
1202
|
-
}
|
1203
|
-
}),
|
1204
|
-
// Reconcile local updates.
|
1205
|
-
EditorView3.updateListener.of(({ view, changes }) => {
|
1206
|
-
if (!changes.empty) {
|
1207
|
-
syncer.reconcile(view, true);
|
1208
|
-
}
|
1209
|
-
})
|
1210
|
-
];
|
1211
|
-
};
|
1212
|
-
|
1213
|
-
// packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts
|
1214
|
-
import { Annotation as Annotation2, RangeSet } from "@codemirror/state";
|
1215
|
-
import { Decoration as Decoration2, EditorView as EditorView4, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
1216
|
-
import { Event } from "@dxos/async";
|
1217
|
-
import { Context } from "@dxos/context";
|
1218
|
-
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts";
|
1219
|
-
var dummyProvider = {
|
1220
|
-
remoteStateChange: new Event(),
|
1221
|
-
open: () => {
|
1222
|
-
},
|
1223
|
-
close: () => {
|
1224
|
-
},
|
1225
|
-
getRemoteStates: () => [],
|
1226
|
-
update: () => {
|
641
|
+
close: () => {
|
642
|
+
},
|
643
|
+
getRemoteStates: () => [],
|
644
|
+
update: () => {
|
1227
645
|
}
|
1228
646
|
};
|
1229
647
|
var awarenessProvider = singleValueFacet(dummyProvider);
|
@@ -1386,7 +804,7 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
1386
804
|
return true;
|
1387
805
|
}
|
1388
806
|
};
|
1389
|
-
var styles2 =
|
807
|
+
var styles2 = EditorView3.theme({
|
1390
808
|
".cm-collab-selection": {},
|
1391
809
|
".cm-collab-selectionLine": {
|
1392
810
|
padding: 0,
|
@@ -1552,7 +970,7 @@ var SpaceAwarenessProvider = class {
|
|
1552
970
|
};
|
1553
971
|
|
1554
972
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
1555
|
-
import { EditorView as
|
973
|
+
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
1556
974
|
import defaultsDeep from "lodash.defaultsdeep";
|
1557
975
|
import { invariant as invariant2 } from "@dxos/invariant";
|
1558
976
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
@@ -1600,7 +1018,7 @@ var blast = (options = defaultOptions) => {
|
|
1600
1018
|
};
|
1601
1019
|
return [
|
1602
1020
|
// Cursor moved.
|
1603
|
-
|
1021
|
+
EditorView4.updateListener.of((update2) => {
|
1604
1022
|
if (blaster?.node !== update2.view.scrollDOM) {
|
1605
1023
|
if (blaster) {
|
1606
1024
|
blaster.destroy();
|
@@ -1974,11 +1392,11 @@ var commandKeyBindings = [
|
|
1974
1392
|
];
|
1975
1393
|
|
1976
1394
|
// packages/ui/react-ui-editor/src/extensions/command/command.ts
|
1977
|
-
import { EditorView as
|
1395
|
+
import { EditorView as EditorView6, keymap as keymap3 } from "@codemirror/view";
|
1978
1396
|
|
1979
1397
|
// packages/ui/react-ui-editor/src/extensions/command/hint.ts
|
1980
1398
|
import { RangeSetBuilder } from "@codemirror/state";
|
1981
|
-
import { Decoration as Decoration3, EditorView as
|
1399
|
+
import { Decoration as Decoration3, EditorView as EditorView5, ViewPlugin as ViewPlugin3, WidgetType as WidgetType2 } from "@codemirror/view";
|
1982
1400
|
var hintViewPlugin = ({ onHint }) => ViewPlugin3.fromClass(class {
|
1983
1401
|
constructor() {
|
1984
1402
|
this.deco = Decoration3.none;
|
@@ -2002,7 +1420,7 @@ var hintViewPlugin = ({ onHint }) => ViewPlugin3.fromClass(class {
|
|
2002
1420
|
}
|
2003
1421
|
}, {
|
2004
1422
|
provide: (plugin) => [
|
2005
|
-
|
1423
|
+
EditorView5.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration3.none)
|
2006
1424
|
]
|
2007
1425
|
});
|
2008
1426
|
var CommandHint = class extends WidgetType2 {
|
@@ -2121,10 +1539,10 @@ var command = (options = {}) => {
|
|
2121
1539
|
options.onHint ? hintViewPlugin({
|
2122
1540
|
onHint: options.onHint
|
2123
1541
|
}) : [],
|
2124
|
-
|
1542
|
+
EditorView6.focusChangeEffect.of((_, focusing) => {
|
2125
1543
|
return focusing ? closeEffect.of(null) : null;
|
2126
1544
|
}),
|
2127
|
-
|
1545
|
+
EditorView6.theme({
|
2128
1546
|
".cm-tooltip": {
|
2129
1547
|
background: "transparent"
|
2130
1548
|
}
|
@@ -2135,7 +1553,7 @@ var command = (options = {}) => {
|
|
2135
1553
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
2136
1554
|
import { invertedEffects } from "@codemirror/commands";
|
2137
1555
|
import { StateEffect as StateEffect3, StateField as StateField4 } from "@codemirror/state";
|
2138
|
-
import { hoverTooltip, keymap as keymap5, Decoration as Decoration4, EditorView as
|
1556
|
+
import { hoverTooltip, keymap as keymap5, Decoration as Decoration4, EditorView as EditorView8, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
2139
1557
|
import sortBy from "lodash.sortby";
|
2140
1558
|
import { useEffect, useMemo as useMemo2 } from "react";
|
2141
1559
|
import { debounce as debounce2 } from "@dxos/async";
|
@@ -2144,7 +1562,7 @@ import { isNonNullable } from "@dxos/util";
|
|
2144
1562
|
|
2145
1563
|
// packages/ui/react-ui-editor/src/extensions/selection.ts
|
2146
1564
|
import { Transaction } from "@codemirror/state";
|
2147
|
-
import { EditorView as
|
1565
|
+
import { EditorView as EditorView7, keymap as keymap4 } from "@codemirror/view";
|
2148
1566
|
import { debounce } from "@dxos/async";
|
2149
1567
|
import { invariant as invariant3 } from "@dxos/invariant";
|
2150
1568
|
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
@@ -2155,7 +1573,7 @@ var createEditorStateTransaction = ({ scrollTo, selection }) => {
|
|
2155
1573
|
return {
|
2156
1574
|
selection,
|
2157
1575
|
scrollIntoView: !scrollTo,
|
2158
|
-
effects: scrollTo ?
|
1576
|
+
effects: scrollTo ? EditorView7.scrollIntoView(scrollTo, {
|
2159
1577
|
yMargin: 96
|
2160
1578
|
}) : void 0,
|
2161
1579
|
annotations: Transaction.userEvent.of(stateRestoreAnnotation)
|
@@ -2197,7 +1615,7 @@ var selectionState = ({ getState, setState } = {}) => {
|
|
2197
1615
|
// setStateDebounced(id, {});
|
2198
1616
|
// },
|
2199
1617
|
// }),
|
2200
|
-
|
1618
|
+
EditorView7.updateListener.of(({ view, transactions }) => {
|
2201
1619
|
const id = view.state.facet(documentId);
|
2202
1620
|
if (!id || transactions.some((tr) => tr.isUserEvent(stateRestoreAnnotation))) {
|
2203
1621
|
return;
|
@@ -2278,7 +1696,7 @@ var commentsState = StateField4.define({
|
|
2278
1696
|
return value;
|
2279
1697
|
}
|
2280
1698
|
});
|
2281
|
-
var styles3 =
|
1699
|
+
var styles3 = EditorView8.theme({
|
2282
1700
|
".cm-comment, .cm-comment-current": {
|
2283
1701
|
margin: "0 -3px",
|
2284
1702
|
padding: "3px",
|
@@ -2298,7 +1716,7 @@ var createCommentMark = (id, isCurrent) => Decoration4.mark({
|
|
2298
1716
|
"data-comment-id": id
|
2299
1717
|
}
|
2300
1718
|
});
|
2301
|
-
var commentsDecorations =
|
1719
|
+
var commentsDecorations = EditorView8.decorations.compute([
|
2302
1720
|
commentsState
|
2303
1721
|
], (state) => {
|
2304
1722
|
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
@@ -2321,7 +1739,7 @@ var commentsDecorations = EditorView9.decorations.compute([
|
|
2321
1739
|
return Decoration4.set(decorations);
|
2322
1740
|
});
|
2323
1741
|
var commentClickedEffect = StateEffect3.define();
|
2324
|
-
var handleCommentClick =
|
1742
|
+
var handleCommentClick = EditorView8.domEventHandlers({
|
2325
1743
|
click: (event, view) => {
|
2326
1744
|
let target = event.target;
|
2327
1745
|
const editorRoot = view.dom;
|
@@ -2360,7 +1778,7 @@ var trackPastedComments = (onUpdate) => {
|
|
2360
1778
|
}
|
2361
1779
|
};
|
2362
1780
|
return [
|
2363
|
-
|
1781
|
+
EditorView8.domEventHandlers({
|
2364
1782
|
cut: handleTrack,
|
2365
1783
|
copy: handleTrack
|
2366
1784
|
}),
|
@@ -2382,7 +1800,7 @@ var trackPastedComments = (onUpdate) => {
|
|
2382
1800
|
return effects;
|
2383
1801
|
}),
|
2384
1802
|
// Handle paste or the undo of comment deletion.
|
2385
|
-
|
1803
|
+
EditorView8.updateListener.of((update2) => {
|
2386
1804
|
const restore = [];
|
2387
1805
|
for (let i = 0; i < update2.transactions.length; i++) {
|
2388
1806
|
const tr = update2.transactions[i];
|
@@ -2441,7 +1859,7 @@ var mapTrackedComment = (comment, changes) => ({
|
|
2441
1859
|
var restoreCommentEffect = StateEffect3.define({
|
2442
1860
|
map: mapTrackedComment
|
2443
1861
|
});
|
2444
|
-
var
|
1862
|
+
var createComment = (view) => {
|
2445
1863
|
const options = view.state.facet(optionsFacet);
|
2446
1864
|
const { from, to } = view.state.selection.main;
|
2447
1865
|
if (from === to) {
|
@@ -2486,7 +1904,7 @@ var comments = (options = {}) => {
|
|
2486
1904
|
options.onCreate && keymap5.of([
|
2487
1905
|
{
|
2488
1906
|
key: shortcut,
|
2489
|
-
run: callbackWrapper(
|
1907
|
+
run: callbackWrapper(createComment)
|
2490
1908
|
}
|
2491
1909
|
]),
|
2492
1910
|
//
|
@@ -2524,7 +1942,7 @@ var comments = (options = {}) => {
|
|
2524
1942
|
//
|
2525
1943
|
// Track deleted ranges and update ranges for decorations.
|
2526
1944
|
//
|
2527
|
-
|
1945
|
+
EditorView8.updateListener.of(({ view, state, changes }) => {
|
2528
1946
|
let mod = false;
|
2529
1947
|
const { comments: comments2, ...value } = state.field(commentsState);
|
2530
1948
|
changes.iterChanges((from, to, from2, to2) => {
|
@@ -2556,7 +1974,7 @@ var comments = (options = {}) => {
|
|
2556
1974
|
//
|
2557
1975
|
// Track selection/proximity.
|
2558
1976
|
//
|
2559
|
-
|
1977
|
+
EditorView8.updateListener.of(({ view, state }) => {
|
2560
1978
|
let min = Infinity;
|
2561
1979
|
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
2562
1980
|
const { head } = state.selection.main;
|
@@ -2610,7 +2028,7 @@ var scrollThreadIntoView = (view, id, center = true) => {
|
|
2610
2028
|
anchor: range.from
|
2611
2029
|
} : void 0,
|
2612
2030
|
effects: [
|
2613
|
-
needsScroll ?
|
2031
|
+
needsScroll ? EditorView8.scrollIntoView(range.from, center ? {
|
2614
2032
|
y: "center"
|
2615
2033
|
} : void 0) : [],
|
2616
2034
|
needsSelectionUpdate ? setSelection.of({
|
@@ -2662,7 +2080,7 @@ var createExternalCommentSync = (id, subscribe, getComments) => ViewPlugin5.from
|
|
2662
2080
|
}
|
2663
2081
|
});
|
2664
2082
|
var useCommentState = (state) => {
|
2665
|
-
return useMemo2(() =>
|
2083
|
+
return useMemo2(() => EditorView8.updateListener.of((update2) => {
|
2666
2084
|
if (update2.docChanged || update2.selectionSet) {
|
2667
2085
|
state.comment = selectionOverlapsComment(update2.state);
|
2668
2086
|
state.selection = hasActiveSelection(update2.state);
|
@@ -2683,116 +2101,348 @@ var useComments = (view, id, comments2) => {
|
|
2683
2101
|
});
|
2684
2102
|
}
|
2685
2103
|
}
|
2686
|
-
});
|
2687
|
-
};
|
2688
|
-
var useCommentClickListener = (onCommentClick) => {
|
2689
|
-
return useMemo2(() =>
|
2690
|
-
update2.transactions.forEach((transaction) => {
|
2691
|
-
transaction.effects.forEach((effect) => {
|
2692
|
-
if (effect.is(commentClickedEffect)) {
|
2693
|
-
onCommentClick(effect.value);
|
2694
|
-
}
|
2695
|
-
});
|
2696
|
-
});
|
2697
|
-
}), [
|
2698
|
-
onCommentClick
|
2699
|
-
]);
|
2700
|
-
};
|
2701
|
-
|
2702
|
-
// packages/ui/react-ui-editor/src/extensions/debug.ts
|
2703
|
-
import { syntaxTree } from "@codemirror/language";
|
2704
|
-
import { StateField as StateField5 } from "@codemirror/state";
|
2705
|
-
var debugNodeLogger = (log8 = console.log) => {
|
2706
|
-
const logTokens = (state) => syntaxTree(state).iterate({
|
2707
|
-
enter: (node) => log8(node.type)
|
2708
|
-
});
|
2709
|
-
return StateField5.define({
|
2710
|
-
create: (state) => logTokens(state),
|
2711
|
-
update: (_, tr) => logTokens(tr.state)
|
2712
|
-
});
|
2713
|
-
};
|
2714
|
-
|
2715
|
-
// packages/ui/react-ui-editor/src/extensions/dnd.ts
|
2716
|
-
import { dropCursor, EditorView as
|
2717
|
-
var styles4 =
|
2718
|
-
".cm-dropCursor": {
|
2719
|
-
borderLeft: "2px solid var(--dx-accentText)",
|
2720
|
-
color: "var(--dx-accentText)",
|
2721
|
-
padding: "0 4px"
|
2104
|
+
});
|
2105
|
+
};
|
2106
|
+
var useCommentClickListener = (onCommentClick) => {
|
2107
|
+
return useMemo2(() => EditorView8.updateListener.of((update2) => {
|
2108
|
+
update2.transactions.forEach((transaction) => {
|
2109
|
+
transaction.effects.forEach((effect) => {
|
2110
|
+
if (effect.is(commentClickedEffect)) {
|
2111
|
+
onCommentClick(effect.value);
|
2112
|
+
}
|
2113
|
+
});
|
2114
|
+
});
|
2115
|
+
}), [
|
2116
|
+
onCommentClick
|
2117
|
+
]);
|
2118
|
+
};
|
2119
|
+
|
2120
|
+
// packages/ui/react-ui-editor/src/extensions/debug.ts
|
2121
|
+
import { syntaxTree } from "@codemirror/language";
|
2122
|
+
import { StateField as StateField5 } from "@codemirror/state";
|
2123
|
+
var debugNodeLogger = (log8 = console.log) => {
|
2124
|
+
const logTokens = (state) => syntaxTree(state).iterate({
|
2125
|
+
enter: (node) => log8(node.type)
|
2126
|
+
});
|
2127
|
+
return StateField5.define({
|
2128
|
+
create: (state) => logTokens(state),
|
2129
|
+
update: (_, tr) => logTokens(tr.state)
|
2130
|
+
});
|
2131
|
+
};
|
2132
|
+
|
2133
|
+
// packages/ui/react-ui-editor/src/extensions/dnd.ts
|
2134
|
+
import { dropCursor, EditorView as EditorView9 } from "@codemirror/view";
|
2135
|
+
var styles4 = EditorView9.theme({
|
2136
|
+
".cm-dropCursor": {
|
2137
|
+
borderLeft: "2px solid var(--dx-accentText)",
|
2138
|
+
color: "var(--dx-accentText)",
|
2139
|
+
padding: "0 4px"
|
2140
|
+
},
|
2141
|
+
".cm-dropCursor:after": {
|
2142
|
+
content: '"\u2190"'
|
2143
|
+
}
|
2144
|
+
});
|
2145
|
+
var dropFile = (options = {}) => {
|
2146
|
+
return [
|
2147
|
+
styles4,
|
2148
|
+
dropCursor(),
|
2149
|
+
EditorView9.domEventHandlers({
|
2150
|
+
drop: (event, view) => {
|
2151
|
+
event.preventDefault();
|
2152
|
+
const files = event.dataTransfer?.files;
|
2153
|
+
const pos = view.posAtCoords(event);
|
2154
|
+
if (files?.length && pos !== null) {
|
2155
|
+
view.dispatch({
|
2156
|
+
selection: {
|
2157
|
+
anchor: pos
|
2158
|
+
}
|
2159
|
+
});
|
2160
|
+
options.onDrop?.(view, {
|
2161
|
+
files
|
2162
|
+
});
|
2163
|
+
}
|
2164
|
+
}
|
2165
|
+
})
|
2166
|
+
];
|
2167
|
+
};
|
2168
|
+
|
2169
|
+
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2170
|
+
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
2171
|
+
import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
2172
|
+
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
2173
|
+
import { searchKeymap } from "@codemirror/search";
|
2174
|
+
import { EditorState } from "@codemirror/state";
|
2175
|
+
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
2176
|
+
import { EditorView as EditorView11, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap6, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
|
2177
|
+
import defaultsDeep2 from "lodash.defaultsdeep";
|
2178
|
+
import merge from "lodash.merge";
|
2179
|
+
import { generateName } from "@dxos/display-name";
|
2180
|
+
import { log as log5 } from "@dxos/log";
|
2181
|
+
import { hexToHue, isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
2182
|
+
|
2183
|
+
// packages/ui/react-ui-editor/src/extensions/focus.ts
|
2184
|
+
import { StateEffect as StateEffect4, StateField as StateField6 } from "@codemirror/state";
|
2185
|
+
import { EditorView as EditorView10 } from "@codemirror/view";
|
2186
|
+
var focusEffect = StateEffect4.define();
|
2187
|
+
var focusField = StateField6.define({
|
2188
|
+
create: () => false,
|
2189
|
+
update: (value, tr) => {
|
2190
|
+
for (const effect of tr.effects) {
|
2191
|
+
if (effect.is(focusEffect)) {
|
2192
|
+
return effect.value;
|
2193
|
+
}
|
2194
|
+
}
|
2195
|
+
return value;
|
2196
|
+
}
|
2197
|
+
});
|
2198
|
+
var focus = [
|
2199
|
+
focusField,
|
2200
|
+
EditorView10.domEventHandlers({
|
2201
|
+
focus: (event, view) => {
|
2202
|
+
setTimeout(() => view.dispatch({
|
2203
|
+
effects: focusEffect.of(true)
|
2204
|
+
}));
|
2205
|
+
},
|
2206
|
+
blur: (event, view) => {
|
2207
|
+
setTimeout(() => view.dispatch({
|
2208
|
+
effects: focusEffect.of(false)
|
2209
|
+
}));
|
2210
|
+
}
|
2211
|
+
})
|
2212
|
+
];
|
2213
|
+
|
2214
|
+
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
2215
|
+
import { mx } from "@dxos/react-ui-theme";
|
2216
|
+
var headings = {
|
2217
|
+
1: "text-4xl",
|
2218
|
+
2: "text-3xl",
|
2219
|
+
3: "text-2xl",
|
2220
|
+
4: "text-xl",
|
2221
|
+
5: "text-lg",
|
2222
|
+
6: ""
|
2223
|
+
};
|
2224
|
+
var theme = {
|
2225
|
+
code: "font-mono !no-underline text-neutral-700 dark:text-neutral-300",
|
2226
|
+
codeMark: "font-mono text-primary-500",
|
2227
|
+
mark: "opacity-50",
|
2228
|
+
heading: (level) => {
|
2229
|
+
return mx(headings[level], "dark:text-primary-400");
|
2230
|
+
}
|
2231
|
+
};
|
2232
|
+
|
2233
|
+
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
2234
|
+
import get from "lodash.get";
|
2235
|
+
import { tokens } from "@dxos/react-ui-theme";
|
2236
|
+
var getToken = (path, defaultValue) => {
|
2237
|
+
const value = get(tokens, path, defaultValue);
|
2238
|
+
return value?.toString() ?? "";
|
2239
|
+
};
|
2240
|
+
var fontBody = getToken("fontFamily.body");
|
2241
|
+
var fontMono = getToken("fontFamily.mono");
|
2242
|
+
|
2243
|
+
// packages/ui/react-ui-editor/src/styles/theme.ts
|
2244
|
+
var defaultTheme = {
|
2245
|
+
"&": {},
|
2246
|
+
"&.cm-focused": {
|
2247
|
+
outline: "none"
|
2248
|
+
},
|
2249
|
+
/**
|
2250
|
+
* Scroller
|
2251
|
+
*/
|
2252
|
+
".cm-scroller": {
|
2253
|
+
overflowY: "auto"
|
2254
|
+
},
|
2255
|
+
/**
|
2256
|
+
* Content
|
2257
|
+
* NOTE: Apply margins to content so that scrollbar is at the edge of the container.
|
2258
|
+
*/
|
2259
|
+
".cm-content": {
|
2260
|
+
padding: "unset",
|
2261
|
+
fontFamily: fontBody,
|
2262
|
+
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
2263
|
+
fontSize: "16px",
|
2264
|
+
lineHeight: 1.5,
|
2265
|
+
color: "unset"
|
2266
|
+
},
|
2267
|
+
/**
|
2268
|
+
* Gutters
|
2269
|
+
* NOTE: Gutters should have the same top margin as the content.
|
2270
|
+
*/
|
2271
|
+
".cm-gutters": {
|
2272
|
+
borderRight: "none",
|
2273
|
+
background: "transparent"
|
2274
|
+
},
|
2275
|
+
".cm-gutter": {},
|
2276
|
+
".cm-gutter.cm-lineNumbers": {
|
2277
|
+
paddingRight: "4px",
|
2278
|
+
borderRight: "1px solid var(--dx-separator)"
|
2279
|
+
},
|
2280
|
+
".cm-gutter.cm-lineNumbers .cm-gutterElement": {
|
2281
|
+
minWidth: "40px",
|
2282
|
+
alignContent: "center"
|
2283
|
+
},
|
2284
|
+
/**
|
2285
|
+
* Height is set to match the corresponding line.
|
2286
|
+
*/
|
2287
|
+
".cm-gutterElement": {
|
2288
|
+
alignItems: "center",
|
2289
|
+
fontSize: "12px"
|
2290
|
+
},
|
2291
|
+
/**
|
2292
|
+
* Line.
|
2293
|
+
*/
|
2294
|
+
".cm-line": {
|
2295
|
+
paddingInline: 0
|
2296
|
+
},
|
2297
|
+
".cm-activeLine": {
|
2298
|
+
background: "var(--dx-cmActiveLine)"
|
2299
|
+
},
|
2300
|
+
/**
|
2301
|
+
* Cursor (layer).
|
2302
|
+
*/
|
2303
|
+
".cm-cursor, .cm-dropCursor": {
|
2304
|
+
borderLeft: "2px solid var(--dx-cmCursor)"
|
2305
|
+
},
|
2306
|
+
".cm-placeholder": {
|
2307
|
+
color: "var(--dx-subdued)"
|
2308
|
+
},
|
2309
|
+
/**
|
2310
|
+
* Selection (layer).
|
2311
|
+
*/
|
2312
|
+
".cm-selectionBackground": {
|
2313
|
+
background: "var(--dx-cmSelection)"
|
2314
|
+
},
|
2315
|
+
/**
|
2316
|
+
* Search.
|
2317
|
+
* NOTE: Matches comment.
|
2318
|
+
*/
|
2319
|
+
".cm-searchMatch": {
|
2320
|
+
margin: "0 -3px",
|
2321
|
+
padding: "3px",
|
2322
|
+
borderRadius: "3px",
|
2323
|
+
background: "var(--dx-cmHighlightSurface)",
|
2324
|
+
color: "var(--dx-cmHighlight)"
|
2325
|
+
},
|
2326
|
+
".cm-searchMatch-selected": {
|
2327
|
+
textDecoration: "underline"
|
2328
|
+
},
|
2329
|
+
/**
|
2330
|
+
* Link.
|
2331
|
+
*/
|
2332
|
+
".cm-link": {
|
2333
|
+
textDecorationLine: "underline",
|
2334
|
+
textDecorationThickness: "1px",
|
2335
|
+
textDecorationColor: "var(--dx-separator)",
|
2336
|
+
textUnderlineOffset: "2px",
|
2337
|
+
borderRadius: ".125rem"
|
2338
|
+
},
|
2339
|
+
".cm-link > span": {
|
2340
|
+
color: "var(--dx-accentText)"
|
2341
|
+
},
|
2342
|
+
/**
|
2343
|
+
* Tooltip.
|
2344
|
+
*/
|
2345
|
+
".cm-tooltip": {
|
2346
|
+
background: "var(--dx-baseSurface)"
|
2347
|
+
},
|
2348
|
+
".cm-tooltip-below": {},
|
2349
|
+
/**
|
2350
|
+
* Autocomplete.
|
2351
|
+
* https://github.com/codemirror/autocomplete/blob/main/src/completion.ts
|
2352
|
+
*/
|
2353
|
+
".cm-tooltip.cm-tooltip-autocomplete": {
|
2354
|
+
marginTop: "4px",
|
2355
|
+
marginLeft: "-3px"
|
2356
|
+
},
|
2357
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul": {
|
2358
|
+
maxHeight: "20em"
|
2359
|
+
},
|
2360
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > li": {},
|
2361
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {},
|
2362
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
|
2363
|
+
paddingLeft: "4px !important",
|
2364
|
+
borderBottom: "none !important",
|
2365
|
+
color: "var(--dx-accentText)"
|
2366
|
+
},
|
2367
|
+
".cm-tooltip.cm-completionInfo": {
|
2368
|
+
width: "360px !important",
|
2369
|
+
margin: "-10px 1px 0 1px",
|
2370
|
+
padding: "8px !important",
|
2371
|
+
borderColor: "var(--dx-separator)"
|
2372
|
+
},
|
2373
|
+
".cm-completionIcon": {
|
2374
|
+
display: "none"
|
2375
|
+
},
|
2376
|
+
".cm-completionLabel": {
|
2377
|
+
fontFamily: fontBody
|
2378
|
+
},
|
2379
|
+
".cm-completionMatchedText": {
|
2380
|
+
textDecoration: "none !important",
|
2381
|
+
opacity: 0.5
|
2382
|
+
},
|
2383
|
+
/**
|
2384
|
+
* Panels
|
2385
|
+
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
2386
|
+
*
|
2387
|
+
* Find/replace panel.
|
2388
|
+
* <div class="cm-announced">...</div>
|
2389
|
+
* <div class="cm-scroller">...</div>
|
2390
|
+
* <div class="cm-panels cm-panels-bottom">
|
2391
|
+
* <div class="cm-search cm-panel">
|
2392
|
+
* <input class="cm-textfield" />
|
2393
|
+
* <button class="cm-button">...</button>
|
2394
|
+
* <label><input type="checkbox" />...</label>
|
2395
|
+
* </div>
|
2396
|
+
* </div
|
2397
|
+
*/
|
2398
|
+
// TODO(burdon): Implement custom panel (with icon buttons).
|
2399
|
+
".cm-panels": {},
|
2400
|
+
".cm-panel": {
|
2401
|
+
fontFamily: fontBody,
|
2402
|
+
backgroundColor: "var(--surface-bg)"
|
2403
|
+
},
|
2404
|
+
".cm-panel input, .cm-panel button, .cm-panel label": {
|
2405
|
+
color: "var(--dx-subdued)",
|
2406
|
+
fontFamily: fontBody,
|
2407
|
+
fontSize: "14px",
|
2408
|
+
all: "unset",
|
2409
|
+
margin: "3px !important",
|
2410
|
+
padding: "2px 6px !important",
|
2411
|
+
outline: "1px solid transparent"
|
2412
|
+
},
|
2413
|
+
".cm-panel input, .cm-panel button": {
|
2414
|
+
backgroundColor: "var(--dx-input)"
|
2415
|
+
},
|
2416
|
+
".cm-panel input:focus, .cm-panel button:focus": {
|
2417
|
+
outline: "1px solid var(--dx-accentFocusIndicator)"
|
2418
|
+
},
|
2419
|
+
".cm-panel label": {
|
2420
|
+
display: "inline-flex",
|
2421
|
+
alignItems: "center",
|
2422
|
+
cursor: "pointer"
|
2423
|
+
},
|
2424
|
+
".cm-panel input.cm-textfield": {},
|
2425
|
+
".cm-panel input[type=checkbox]": {
|
2426
|
+
width: "8px",
|
2427
|
+
height: "8px",
|
2428
|
+
marginRight: "6px !important",
|
2429
|
+
padding: "2px !important",
|
2430
|
+
color: "var(--dx-accentFocusIndicator)"
|
2431
|
+
},
|
2432
|
+
".cm-panel button": {
|
2433
|
+
"&:hover": {
|
2434
|
+
backgroundColor: "var(--dx-accentSurfaceHover) !important"
|
2435
|
+
},
|
2436
|
+
"&:active": {
|
2437
|
+
backgroundColor: "var(--dx-accentSurfaceHover)"
|
2438
|
+
}
|
2722
2439
|
},
|
2723
|
-
".cm-
|
2724
|
-
|
2440
|
+
".cm-panel.cm-search": {
|
2441
|
+
padding: "4px",
|
2442
|
+
borderTop: "1px solid var(--dx-separator)"
|
2725
2443
|
}
|
2726
|
-
});
|
2727
|
-
var dropFile = (options = {}) => {
|
2728
|
-
return [
|
2729
|
-
styles4,
|
2730
|
-
dropCursor(),
|
2731
|
-
EditorView10.domEventHandlers({
|
2732
|
-
drop: (event, view) => {
|
2733
|
-
event.preventDefault();
|
2734
|
-
const files = event.dataTransfer?.files;
|
2735
|
-
const pos = view.posAtCoords(event);
|
2736
|
-
if (files?.length && pos !== null) {
|
2737
|
-
view.dispatch({
|
2738
|
-
selection: {
|
2739
|
-
anchor: pos
|
2740
|
-
}
|
2741
|
-
});
|
2742
|
-
options.onDrop?.(view, {
|
2743
|
-
files
|
2744
|
-
});
|
2745
|
-
}
|
2746
|
-
}
|
2747
|
-
})
|
2748
|
-
];
|
2749
2444
|
};
|
2750
2445
|
|
2751
|
-
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2752
|
-
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
2753
|
-
import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
2754
|
-
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
2755
|
-
import { searchKeymap } from "@codemirror/search";
|
2756
|
-
import { EditorState } from "@codemirror/state";
|
2757
|
-
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
2758
|
-
import { EditorView as EditorView12, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap6, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
|
2759
|
-
import defaultsDeep2 from "lodash.defaultsdeep";
|
2760
|
-
import merge from "lodash.merge";
|
2761
|
-
import { generateName } from "@dxos/display-name";
|
2762
|
-
import { log as log5 } from "@dxos/log";
|
2763
|
-
import { hexToHue, isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
2764
|
-
|
2765
|
-
// packages/ui/react-ui-editor/src/extensions/focus.ts
|
2766
|
-
import { StateEffect as StateEffect4, StateField as StateField6 } from "@codemirror/state";
|
2767
|
-
import { EditorView as EditorView11 } from "@codemirror/view";
|
2768
|
-
var focusEffect = StateEffect4.define();
|
2769
|
-
var focusField = StateField6.define({
|
2770
|
-
create: () => false,
|
2771
|
-
update: (value, tr) => {
|
2772
|
-
for (const effect of tr.effects) {
|
2773
|
-
if (effect.is(focusEffect)) {
|
2774
|
-
return effect.value;
|
2775
|
-
}
|
2776
|
-
}
|
2777
|
-
return value;
|
2778
|
-
}
|
2779
|
-
});
|
2780
|
-
var focus = [
|
2781
|
-
focusField,
|
2782
|
-
EditorView11.domEventHandlers({
|
2783
|
-
focus: (event, view) => {
|
2784
|
-
setTimeout(() => view.dispatch({
|
2785
|
-
effects: focusEffect.of(true)
|
2786
|
-
}));
|
2787
|
-
},
|
2788
|
-
blur: (event, view) => {
|
2789
|
-
setTimeout(() => view.dispatch({
|
2790
|
-
effects: focusEffect.of(false)
|
2791
|
-
}));
|
2792
|
-
}
|
2793
|
-
})
|
2794
|
-
];
|
2795
|
-
|
2796
2446
|
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2797
2447
|
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
|
2798
2448
|
var preventNewline = EditorState.transactionFilter.of((tr) => tr.newDoc.lines > 1 ? [] : tr);
|
@@ -2817,7 +2467,7 @@ var createBasicExtensions = (_props) => {
|
|
2817
2467
|
const props = defaultsDeep2({}, _props, defaultBasicOptions);
|
2818
2468
|
return [
|
2819
2469
|
// NOTE: Doesn't catch errors in keymap functions.
|
2820
|
-
|
2470
|
+
EditorView11.exceptionSink.of((err) => {
|
2821
2471
|
log5.catch(err, void 0, {
|
2822
2472
|
F: __dxlog_file8,
|
2823
2473
|
L: 96,
|
@@ -2832,12 +2482,12 @@ var createBasicExtensions = (_props) => {
|
|
2832
2482
|
props.drawSelection && drawSelection({
|
2833
2483
|
cursorBlinkRate: 1200
|
2834
2484
|
}),
|
2835
|
-
props.editable !== void 0 &&
|
2485
|
+
props.editable !== void 0 && EditorView11.editable.of(props.editable),
|
2836
2486
|
props.focus && focus,
|
2837
2487
|
props.highlightActiveLine && highlightActiveLine(),
|
2838
2488
|
props.history && history(),
|
2839
2489
|
props.lineNumbers && lineNumbers(),
|
2840
|
-
props.lineWrapping &&
|
2490
|
+
props.lineWrapping && EditorView11.lineWrapping,
|
2841
2491
|
props.placeholder && placeholder(props.placeholder),
|
2842
2492
|
props.readOnly !== void 0 && EditorState.readOnly.of(props.readOnly),
|
2843
2493
|
props.scrollPastEnd && scrollPastEnd(),
|
@@ -2874,14 +2524,14 @@ var defaultThemeSlots = {
|
|
2874
2524
|
var createThemeExtensions = ({ themeMode, styles: styles5, syntaxHighlighting: _syntaxHighlighting, slots: _slots } = {}) => {
|
2875
2525
|
const slots = defaultsDeep2({}, _slots, defaultThemeSlots);
|
2876
2526
|
return [
|
2877
|
-
|
2878
|
-
|
2527
|
+
EditorView11.darkTheme.of(themeMode === "dark"),
|
2528
|
+
EditorView11.baseTheme(styles5 ? merge({}, defaultTheme, styles5) : defaultTheme),
|
2879
2529
|
// https://github.com/codemirror/theme-one-dark
|
2880
2530
|
_syntaxHighlighting && (themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)),
|
2881
|
-
slots.editor?.className &&
|
2531
|
+
slots.editor?.className && EditorView11.editorAttributes.of({
|
2882
2532
|
class: slots.editor.className
|
2883
2533
|
}),
|
2884
|
-
slots.content?.className &&
|
2534
|
+
slots.content?.className && EditorView11.contentAttributes.of({
|
2885
2535
|
class: slots.content.className
|
2886
2536
|
})
|
2887
2537
|
].filter(isNotFalsy3);
|
@@ -2910,8 +2560,8 @@ var createDataExtensions = ({ id, text, space, identity }) => {
|
|
2910
2560
|
|
2911
2561
|
// packages/ui/react-ui-editor/src/extensions/folding.tsx
|
2912
2562
|
import { codeFolding, foldGutter } from "@codemirror/language";
|
2913
|
-
import { EditorView as
|
2914
|
-
import
|
2563
|
+
import { EditorView as EditorView12 } from "@codemirror/view";
|
2564
|
+
import React2 from "react";
|
2915
2565
|
import { Icon } from "@dxos/react-ui";
|
2916
2566
|
var folding = (_props = {}) => [
|
2917
2567
|
codeFolding({
|
@@ -2924,7 +2574,7 @@ var folding = (_props = {}) => [
|
|
2924
2574
|
const el = createElement("div", {
|
2925
2575
|
className: "flex h-full items-center"
|
2926
2576
|
});
|
2927
|
-
return renderRoot(el, /* @__PURE__ */
|
2577
|
+
return renderRoot(el, /* @__PURE__ */ React2.createElement(Icon, {
|
2928
2578
|
icon: "ph--caret-right--bold",
|
2929
2579
|
size: 3,
|
2930
2580
|
classNames: [
|
@@ -2934,7 +2584,7 @@ var folding = (_props = {}) => [
|
|
2934
2584
|
}));
|
2935
2585
|
}
|
2936
2586
|
}),
|
2937
|
-
|
2587
|
+
EditorView12.theme({
|
2938
2588
|
".cm-foldGutter": {
|
2939
2589
|
opacity: 0.3,
|
2940
2590
|
transition: "opacity 0.3s",
|
@@ -2947,14 +2597,14 @@ var folding = (_props = {}) => [
|
|
2947
2597
|
];
|
2948
2598
|
|
2949
2599
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
2950
|
-
import { EditorView as
|
2600
|
+
import { EditorView as EditorView13 } from "@codemirror/view";
|
2951
2601
|
var listener = ({ onFocus, onChange }) => {
|
2952
2602
|
const extensions = [];
|
2953
|
-
onFocus && extensions.push(
|
2603
|
+
onFocus && extensions.push(EditorView13.focusChangeEffect.of((_, focusing) => {
|
2954
2604
|
onFocus(focusing);
|
2955
2605
|
return null;
|
2956
2606
|
}));
|
2957
|
-
onChange && extensions.push(
|
2607
|
+
onChange && extensions.push(EditorView13.updateListener.of((update2) => {
|
2958
2608
|
onChange(update2.state.doc.toString(), update2.state.facet(documentId));
|
2959
2609
|
}));
|
2960
2610
|
return extensions;
|
@@ -2964,7 +2614,7 @@ var listener = ({ onFocus, onChange }) => {
|
|
2964
2614
|
import { snippet } from "@codemirror/autocomplete";
|
2965
2615
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
2966
2616
|
import { EditorSelection } from "@codemirror/state";
|
2967
|
-
import { EditorView as
|
2617
|
+
import { EditorView as EditorView14, keymap as keymap7 } from "@codemirror/view";
|
2968
2618
|
import { useMemo as useMemo3 } from "react";
|
2969
2619
|
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;
|
2970
2620
|
var Inline;
|
@@ -4053,7 +3703,7 @@ var getFormatting = (state) => {
|
|
4053
3703
|
};
|
4054
3704
|
};
|
4055
3705
|
var useFormattingState = (state) => {
|
4056
|
-
return useMemo3(() =>
|
3706
|
+
return useMemo3(() => EditorView14.updateListener.of((update2) => {
|
4057
3707
|
if (update2.docChanged || update2.selectionSet) {
|
4058
3708
|
Object.entries(getFormatting(update2.state)).forEach(([key, active]) => {
|
4059
3709
|
state[key] = active;
|
@@ -4101,7 +3751,7 @@ var processEditorPayload = (view, { type, data }) => {
|
|
4101
3751
|
})(view);
|
4102
3752
|
break;
|
4103
3753
|
case "comment":
|
4104
|
-
|
3754
|
+
createComment(view);
|
4105
3755
|
break;
|
4106
3756
|
}
|
4107
3757
|
requestAnimationFrame(() => {
|
@@ -4365,9 +4015,9 @@ var convertTreeToJson = (state) => {
|
|
4365
4015
|
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
4366
4016
|
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
4367
4017
|
import { RangeSetBuilder as RangeSetBuilder3, StateEffect as StateEffect5 } from "@codemirror/state";
|
4368
|
-
import { EditorView as
|
4018
|
+
import { EditorView as EditorView18, Decoration as Decoration7, WidgetType as WidgetType5, ViewPlugin as ViewPlugin7 } from "@codemirror/view";
|
4369
4019
|
import { invariant as invariant4 } from "@dxos/invariant";
|
4370
|
-
import { mx as
|
4020
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
4371
4021
|
|
4372
4022
|
// packages/ui/react-ui-editor/src/extensions/markdown/changes.ts
|
4373
4023
|
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
@@ -4516,7 +4166,7 @@ var getValidUrl = (str) => {
|
|
4516
4166
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
4517
4167
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
4518
4168
|
import { StateField as StateField8 } from "@codemirror/state";
|
4519
|
-
import { Decoration as Decoration5, EditorView as
|
4169
|
+
import { Decoration as Decoration5, EditorView as EditorView15, WidgetType as WidgetType3 } from "@codemirror/view";
|
4520
4170
|
var image = (_options = {}) => {
|
4521
4171
|
return [
|
4522
4172
|
StateField8.define({
|
@@ -4544,7 +4194,7 @@ var image = (_options = {}) => {
|
|
4544
4194
|
add: buildDecorations(from, to, tr.state)
|
4545
4195
|
});
|
4546
4196
|
},
|
4547
|
-
provide: (field) =>
|
4197
|
+
provide: (field) => EditorView15.decorations.from(field)
|
4548
4198
|
})
|
4549
4199
|
];
|
4550
4200
|
};
|
@@ -4604,10 +4254,10 @@ var ImageWidget = class extends WidgetType3 {
|
|
4604
4254
|
};
|
4605
4255
|
|
4606
4256
|
// packages/ui/react-ui-editor/src/extensions/markdown/styles.ts
|
4607
|
-
import { EditorView as
|
4257
|
+
import { EditorView as EditorView16 } from "@codemirror/view";
|
4608
4258
|
var bulletListIndentationWidth = 24;
|
4609
4259
|
var orderedListIndentationWidth = 36;
|
4610
|
-
var formattingStyles =
|
4260
|
+
var formattingStyles = EditorView16.theme({
|
4611
4261
|
/**
|
4612
4262
|
* Horizontal rule.
|
4613
4263
|
*/
|
@@ -4728,12 +4378,12 @@ var formattingStyles = EditorView17.theme({
|
|
4728
4378
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
4729
4379
|
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
4730
4380
|
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField9 } from "@codemirror/state";
|
4731
|
-
import { Decoration as Decoration6, EditorView as
|
4381
|
+
import { Decoration as Decoration6, EditorView as EditorView17, WidgetType as WidgetType4 } from "@codemirror/view";
|
4732
4382
|
var table = (options = {}) => {
|
4733
4383
|
return StateField9.define({
|
4734
4384
|
create: (state) => update(state, options),
|
4735
4385
|
update: (_, tr) => update(tr.state, options),
|
4736
|
-
provide: (field) =>
|
4386
|
+
provide: (field) => EditorView17.decorations.from(field)
|
4737
4387
|
});
|
4738
4388
|
};
|
4739
4389
|
var update = (state, _options) => {
|
@@ -4919,16 +4569,16 @@ var TextWidget = class extends WidgetType5 {
|
|
4919
4569
|
};
|
4920
4570
|
var hide = Decoration7.replace({});
|
4921
4571
|
var blockQuote = Decoration7.line({
|
4922
|
-
class:
|
4572
|
+
class: mx2("cm-blockquote")
|
4923
4573
|
});
|
4924
4574
|
var fencedCodeLine = Decoration7.line({
|
4925
|
-
class:
|
4575
|
+
class: mx2("cm-code cm-codeblock-line")
|
4926
4576
|
});
|
4927
4577
|
var fencedCodeLineFirst = Decoration7.line({
|
4928
|
-
class:
|
4578
|
+
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-first")
|
4929
4579
|
});
|
4930
4580
|
var fencedCodeLineLast = Decoration7.line({
|
4931
|
-
class:
|
4581
|
+
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-last")
|
4932
4582
|
});
|
4933
4583
|
var commentBlockLine = fencedCodeLine;
|
4934
4584
|
var commentBlockLineFirst = fencedCodeLineFirst;
|
@@ -5030,615 +4680,1034 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
5030
4680
|
}
|
5031
4681
|
}
|
5032
4682
|
const editing = editingRange(state, node, focus2);
|
5033
|
-
if (editing) {
|
5034
|
-
break;
|
4683
|
+
if (editing) {
|
4684
|
+
break;
|
4685
|
+
}
|
4686
|
+
const mark = node.node.firstChild;
|
4687
|
+
if (mark?.name === "HeaderMark") {
|
4688
|
+
const { from, to = 6 } = options.numberedHeadings ?? {};
|
4689
|
+
const text = view.state.sliceDoc(node.from, node.to);
|
4690
|
+
const len = text.match(/[#\s]+/)[0].length;
|
4691
|
+
if (!from || level < from || level > to) {
|
4692
|
+
atomicDeco.add(mark.from, mark.from + len, hide);
|
4693
|
+
} else {
|
4694
|
+
const num = headers.slice(from - 1).map((level2) => level2?.number ?? 0).join(".") + " ";
|
4695
|
+
if (num.length) {
|
4696
|
+
atomicDeco.add(mark.from, mark.from + len, Decoration7.replace({
|
4697
|
+
widget: new TextWidget(num, theme.heading(level))
|
4698
|
+
}));
|
4699
|
+
}
|
4700
|
+
}
|
4701
|
+
}
|
4702
|
+
return false;
|
4703
|
+
}
|
4704
|
+
//
|
4705
|
+
// Lists.
|
4706
|
+
// [BulletList | OrderedList] > (ListItem > ListMark) > (Task > TaskMarker)?
|
4707
|
+
//
|
4708
|
+
case "BulletList":
|
4709
|
+
case "OrderedList": {
|
4710
|
+
enterList(node);
|
4711
|
+
break;
|
4712
|
+
}
|
4713
|
+
case "ListItem": {
|
4714
|
+
const line = state.doc.lineAt(node.from);
|
4715
|
+
const list = getCurrentListLevel();
|
4716
|
+
const width = list.type === "OrderedList" ? orderedListIndentationWidth : bulletListIndentationWidth;
|
4717
|
+
const offset = ((list.level ?? 0) + 1) * width;
|
4718
|
+
if (node.from === line.to - 1) {
|
4719
|
+
return false;
|
4720
|
+
}
|
4721
|
+
deco.add(line.from, line.from, Decoration7.line({
|
4722
|
+
class: "cm-list-item",
|
4723
|
+
attributes: {
|
4724
|
+
style: `padding-left: ${offset}px; text-indent: -${width}px;`
|
4725
|
+
}
|
4726
|
+
}));
|
4727
|
+
break;
|
4728
|
+
}
|
4729
|
+
case "ListMark": {
|
4730
|
+
const list = getCurrentListLevel();
|
4731
|
+
const next = tree.resolve(node.to + 1, 1);
|
4732
|
+
if (next?.name === "TaskMarker") {
|
4733
|
+
break;
|
4734
|
+
}
|
4735
|
+
const label = list.type === "OrderedList" ? `${++list.number}.` : Unicode.bulletSmall;
|
4736
|
+
const line = state.doc.lineAt(node.from);
|
4737
|
+
const to = state.doc.sliceString(node.to, node.to + 1) === " " ? node.to + 1 : node.to;
|
4738
|
+
atomicDeco.add(line.from, to, Decoration7.replace({
|
4739
|
+
widget: new TextWidget(label, list.type === "OrderedList" ? "cm-list-mark cm-list-mark-ordered" : "cm-list-mark cm-list-mark-bullet")
|
4740
|
+
}));
|
4741
|
+
break;
|
4742
|
+
}
|
4743
|
+
case "TaskMarker": {
|
4744
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
4745
|
+
const line = state.doc.lineAt(node.from);
|
4746
|
+
const to = state.doc.sliceString(node.to, node.to + 1) === " " ? node.to + 1 : node.to;
|
4747
|
+
atomicDeco.add(line.from, to, checked ? checkedTask : uncheckedTask);
|
4748
|
+
break;
|
4749
|
+
}
|
4750
|
+
//
|
4751
|
+
// Blockquote > QuoteMark > Paragraph
|
4752
|
+
//
|
4753
|
+
case "Blockquote": {
|
4754
|
+
const editing = editingRange(state, node, focus2);
|
4755
|
+
const quoteMark = node.node.getChild("QuoteMark");
|
4756
|
+
const paragraph = node.node.getChild("Paragraph");
|
4757
|
+
if (!editing && quoteMark && paragraph) {
|
4758
|
+
atomicDeco.add(quoteMark.from, paragraph.from, hide);
|
4759
|
+
}
|
4760
|
+
for (const block of view.viewportLineBlocks) {
|
4761
|
+
if (block.to < node.from) {
|
4762
|
+
continue;
|
4763
|
+
}
|
4764
|
+
if (block.from > node.to) {
|
4765
|
+
break;
|
4766
|
+
}
|
4767
|
+
deco.add(block.from, block.from, blockQuote);
|
4768
|
+
}
|
4769
|
+
break;
|
4770
|
+
}
|
4771
|
+
//
|
4772
|
+
// CommentBlock
|
4773
|
+
//
|
4774
|
+
case "CommentBlock": {
|
4775
|
+
const editing = editingRange(state, node, focus2);
|
4776
|
+
for (const block of view.viewportLineBlocks) {
|
4777
|
+
if (block.to < node.from) {
|
4778
|
+
continue;
|
4779
|
+
}
|
4780
|
+
if (block.from > node.to) {
|
4781
|
+
break;
|
4782
|
+
}
|
4783
|
+
const isFirst = block.from <= node.from;
|
4784
|
+
const isLast = block.to >= node.to && /^(\s>)*-->$/.test(state.doc.sliceString(block.from, block.to));
|
4785
|
+
deco.add(block.from, block.from, isFirst ? commentBlockLineFirst : isLast ? commentBlockLineLast : commentBlockLine);
|
4786
|
+
if (!editing && (isFirst || isLast)) {
|
4787
|
+
atomicDeco.add(block.from, block.to, hide);
|
4788
|
+
}
|
5035
4789
|
}
|
5036
|
-
|
5037
|
-
|
5038
|
-
|
5039
|
-
|
5040
|
-
|
5041
|
-
|
5042
|
-
|
5043
|
-
|
5044
|
-
|
5045
|
-
|
5046
|
-
|
5047
|
-
|
5048
|
-
|
5049
|
-
|
4790
|
+
break;
|
4791
|
+
}
|
4792
|
+
//
|
4793
|
+
// FencedCode > CodeMark > [CodeInfo] > CodeText > CodeMark
|
4794
|
+
//
|
4795
|
+
case "FencedCode": {
|
4796
|
+
for (const block of view.viewportLineBlocks) {
|
4797
|
+
if (block.to < node.from) {
|
4798
|
+
continue;
|
4799
|
+
}
|
4800
|
+
if (block.from > node.to) {
|
4801
|
+
break;
|
4802
|
+
}
|
4803
|
+
const first = block.from <= node.from;
|
4804
|
+
const last = block.to >= node.to && /^(\s>)*```$/.test(state.doc.sliceString(block.from, block.to));
|
4805
|
+
deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
|
4806
|
+
const editing = editingRange(state, node, focus2);
|
4807
|
+
if (!editing && (first || last)) {
|
4808
|
+
atomicDeco.add(block.from, block.to, hide);
|
5050
4809
|
}
|
5051
4810
|
}
|
5052
4811
|
return false;
|
5053
4812
|
}
|
5054
4813
|
//
|
5055
|
-
//
|
5056
|
-
//
|
4814
|
+
// Link > [LinkMark, URL]
|
4815
|
+
//
|
4816
|
+
case "Link": {
|
4817
|
+
const marks = node.node.getChildren("LinkMark");
|
4818
|
+
const urlNode = node.node.getChild("URL");
|
4819
|
+
const editing = editingRange(state, node, focus2);
|
4820
|
+
if (urlNode && marks.length >= 2) {
|
4821
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
4822
|
+
if (!editing) {
|
4823
|
+
atomicDeco.add(node.from, marks[0].to, hide);
|
4824
|
+
}
|
4825
|
+
deco.add(marks[0].to, marks[1].from, Decoration7.mark({
|
4826
|
+
tagName: "a",
|
4827
|
+
attributes: {
|
4828
|
+
class: "cm-link",
|
4829
|
+
href: url,
|
4830
|
+
rel: "noreferrer",
|
4831
|
+
target: "_blank"
|
4832
|
+
}
|
4833
|
+
}));
|
4834
|
+
if (!editing) {
|
4835
|
+
atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration7.replace({
|
4836
|
+
widget: new LinkButton(url, options.renderLinkButton)
|
4837
|
+
}) : hide);
|
4838
|
+
}
|
4839
|
+
}
|
4840
|
+
break;
|
4841
|
+
}
|
4842
|
+
//
|
4843
|
+
// HR
|
5057
4844
|
//
|
4845
|
+
case "HorizontalRule": {
|
4846
|
+
if (!editingRange(state, node, focus2)) {
|
4847
|
+
deco.add(node.from, node.to, horizontalRule);
|
4848
|
+
}
|
4849
|
+
break;
|
4850
|
+
}
|
4851
|
+
default: {
|
4852
|
+
if (autoHideTags.has(node.name)) {
|
4853
|
+
if (!editingRange(state, node.node.parent, focus2)) {
|
4854
|
+
atomicDeco.add(node.from, node.to, hide);
|
4855
|
+
}
|
4856
|
+
}
|
4857
|
+
}
|
4858
|
+
}
|
4859
|
+
};
|
4860
|
+
const leaveNode = (node) => {
|
4861
|
+
switch (node.name) {
|
5058
4862
|
case "BulletList":
|
5059
4863
|
case "OrderedList": {
|
5060
|
-
|
4864
|
+
leaveList();
|
5061
4865
|
break;
|
5062
4866
|
}
|
5063
|
-
|
5064
|
-
|
5065
|
-
|
5066
|
-
|
5067
|
-
|
5068
|
-
|
5069
|
-
|
4867
|
+
}
|
4868
|
+
};
|
4869
|
+
const tree = syntaxTree7(state);
|
4870
|
+
if (options.numberedHeadings?.from === void 0) {
|
4871
|
+
for (const { from, to } of view.visibleRanges) {
|
4872
|
+
tree.iterate({
|
4873
|
+
from,
|
4874
|
+
to,
|
4875
|
+
enter: wrapWithCatch(enterNode),
|
4876
|
+
leave: wrapWithCatch(leaveNode)
|
4877
|
+
});
|
4878
|
+
}
|
4879
|
+
} else {
|
4880
|
+
tree.iterate({
|
4881
|
+
enter: wrapWithCatch(enterNode),
|
4882
|
+
leave: wrapWithCatch(leaveNode)
|
4883
|
+
});
|
4884
|
+
}
|
4885
|
+
return {
|
4886
|
+
deco: deco.finish(),
|
4887
|
+
atomicDeco: atomicDeco.finish()
|
4888
|
+
};
|
4889
|
+
};
|
4890
|
+
var forceUpdate = StateEffect5.define();
|
4891
|
+
var decorateMarkdown = (options = {}) => {
|
4892
|
+
return [
|
4893
|
+
ViewPlugin7.fromClass(class {
|
4894
|
+
constructor(view) {
|
4895
|
+
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations2(view, options, view.hasFocus));
|
4896
|
+
}
|
4897
|
+
update(update2) {
|
4898
|
+
if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((effect) => effect.is(forceUpdate))) || update2.selectionSet && !options.selectionChangeDelay) {
|
4899
|
+
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations2(update2.view, options, update2.view.hasFocus));
|
4900
|
+
this.clearUpdate();
|
4901
|
+
} else if (update2.selectionSet) {
|
4902
|
+
this.scheduleUpdate(update2.view);
|
5070
4903
|
}
|
5071
|
-
|
5072
|
-
|
5073
|
-
|
5074
|
-
|
4904
|
+
}
|
4905
|
+
// Defer update in case moving through the document.
|
4906
|
+
scheduleUpdate(view) {
|
4907
|
+
this.clearUpdate();
|
4908
|
+
this.pendingUpdate = setTimeout(() => {
|
4909
|
+
view.dispatch({
|
4910
|
+
effects: forceUpdate.of(null)
|
4911
|
+
});
|
4912
|
+
}, options.selectionChangeDelay);
|
4913
|
+
}
|
4914
|
+
clearUpdate() {
|
4915
|
+
if (this.pendingUpdate) {
|
4916
|
+
clearTimeout(this.pendingUpdate);
|
4917
|
+
this.pendingUpdate = void 0;
|
4918
|
+
}
|
4919
|
+
}
|
4920
|
+
destroy() {
|
4921
|
+
this.clearUpdate();
|
4922
|
+
}
|
4923
|
+
}, {
|
4924
|
+
provide: (plugin) => [
|
4925
|
+
EditorView18.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
4926
|
+
EditorView18.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
4927
|
+
EditorView18.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration7.none)
|
4928
|
+
]
|
4929
|
+
}),
|
4930
|
+
image(),
|
4931
|
+
table(),
|
4932
|
+
adjustChanges(),
|
4933
|
+
formattingStyles
|
4934
|
+
];
|
4935
|
+
};
|
4936
|
+
|
4937
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
4938
|
+
import { syntaxTree as syntaxTree8 } from "@codemirror/language";
|
4939
|
+
import { hoverTooltip as hoverTooltip2 } from "@codemirror/view";
|
4940
|
+
import { tooltipContent } from "@dxos/react-ui-theme";
|
4941
|
+
var linkTooltip = (renderTooltip) => {
|
4942
|
+
return hoverTooltip2((view, pos, side) => {
|
4943
|
+
const syntax = syntaxTree8(view.state).resolveInner(pos, side);
|
4944
|
+
let link = null;
|
4945
|
+
for (let i = 0, node = syntax; !link && node && i < 5; node = node.parent, i++) {
|
4946
|
+
link = node.name === "Link" ? node : null;
|
4947
|
+
}
|
4948
|
+
const url = link && link.getChild("URL");
|
4949
|
+
if (!url || !link) {
|
4950
|
+
return null;
|
4951
|
+
}
|
4952
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
4953
|
+
return {
|
4954
|
+
pos: link.from,
|
4955
|
+
end: link.to,
|
4956
|
+
// NOTE: Forcing above causes the tooltip to flicker.
|
4957
|
+
// above: true,
|
4958
|
+
create: () => {
|
4959
|
+
const el = document.createElement("div");
|
4960
|
+
el.className = tooltipContent({});
|
4961
|
+
renderTooltip(el, {
|
4962
|
+
url: urlText
|
4963
|
+
}, view);
|
4964
|
+
return {
|
4965
|
+
dom: el,
|
4966
|
+
offset: {
|
4967
|
+
x: 0,
|
4968
|
+
y: 4
|
5075
4969
|
}
|
5076
|
-
}
|
5077
|
-
break;
|
4970
|
+
};
|
5078
4971
|
}
|
5079
|
-
|
5080
|
-
|
5081
|
-
|
5082
|
-
|
5083
|
-
|
4972
|
+
};
|
4973
|
+
}, {
|
4974
|
+
// NOTE: 0 = default of 300ms.
|
4975
|
+
hoverTime: 1
|
4976
|
+
});
|
4977
|
+
};
|
4978
|
+
|
4979
|
+
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
4980
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
4981
|
+
import { log as log6 } from "@dxos/log";
|
4982
|
+
var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/mention.ts";
|
4983
|
+
var mention = ({ debug, onSearch }) => {
|
4984
|
+
return autocompletion2({
|
4985
|
+
// TODO(burdon): Not working.
|
4986
|
+
activateOnTyping: true,
|
4987
|
+
// activateOnTypingDelay: 100,
|
4988
|
+
// selectOnOpen: true,
|
4989
|
+
closeOnBlur: !debug,
|
4990
|
+
// defaultKeymap: false,
|
4991
|
+
icons: false,
|
4992
|
+
override: [
|
4993
|
+
(context) => {
|
4994
|
+
log6.info("completion context", {
|
4995
|
+
context
|
4996
|
+
}, {
|
4997
|
+
F: __dxlog_file10,
|
4998
|
+
L: 27,
|
4999
|
+
S: void 0,
|
5000
|
+
C: (f, a) => f(...a)
|
5001
|
+
});
|
5002
|
+
const match = context.matchBefore(/@(\w+)?/);
|
5003
|
+
if (!match || match.from === match.to && !context.explicit) {
|
5004
|
+
return null;
|
5084
5005
|
}
|
5085
|
-
|
5086
|
-
|
5087
|
-
|
5088
|
-
|
5089
|
-
|
5090
|
-
}
|
5091
|
-
break;
|
5092
|
-
}
|
5093
|
-
case "TaskMarker": {
|
5094
|
-
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
5095
|
-
const line = state.doc.lineAt(node.from);
|
5096
|
-
const to = state.doc.sliceString(node.to, node.to + 1) === " " ? node.to + 1 : node.to;
|
5097
|
-
atomicDeco.add(line.from, to, checked ? checkedTask : uncheckedTask);
|
5098
|
-
break;
|
5006
|
+
return {
|
5007
|
+
from: match.from,
|
5008
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
5009
|
+
label: `@${value}`
|
5010
|
+
}))
|
5011
|
+
};
|
5099
5012
|
}
|
5100
|
-
|
5101
|
-
|
5102
|
-
|
5103
|
-
|
5104
|
-
|
5105
|
-
|
5106
|
-
|
5107
|
-
|
5108
|
-
|
5109
|
-
|
5110
|
-
|
5111
|
-
|
5112
|
-
|
5113
|
-
|
5114
|
-
|
5115
|
-
|
5116
|
-
|
5117
|
-
|
5013
|
+
]
|
5014
|
+
});
|
5015
|
+
};
|
5016
|
+
|
5017
|
+
// packages/ui/react-ui-editor/src/extensions/modes.ts
|
5018
|
+
import { keymap as keymap9 } from "@codemirror/view";
|
5019
|
+
import { vim } from "@replit/codemirror-vim";
|
5020
|
+
import { vscodeKeymap } from "@replit/codemirror-vscode-keymap";
|
5021
|
+
import { Schema } from "effect";
|
5022
|
+
var EditorViewModes = [
|
5023
|
+
"preview",
|
5024
|
+
"readonly",
|
5025
|
+
"source"
|
5026
|
+
];
|
5027
|
+
var EditorViewMode = Schema.Union(...EditorViewModes.map((mode) => Schema.Literal(mode)));
|
5028
|
+
var EditorInputModes = [
|
5029
|
+
"default",
|
5030
|
+
"vim",
|
5031
|
+
"vscode"
|
5032
|
+
];
|
5033
|
+
var EditorInputMode = Schema.Union(...EditorInputModes.map((mode) => Schema.Literal(mode)));
|
5034
|
+
var editorInputMode = singleValueFacet({});
|
5035
|
+
var InputModeExtensions = {
|
5036
|
+
default: [],
|
5037
|
+
vscode: [
|
5038
|
+
// https://github.com/replit/codemirror-vscode-keymap
|
5039
|
+
editorInputMode.of({
|
5040
|
+
type: "vscode"
|
5041
|
+
}),
|
5042
|
+
keymap9.of(vscodeKeymap)
|
5043
|
+
],
|
5044
|
+
vim: [
|
5045
|
+
// https://github.com/replit/codemirror-vim
|
5046
|
+
vim(),
|
5047
|
+
editorInputMode.of({
|
5048
|
+
type: "vim",
|
5049
|
+
noTabster: true
|
5050
|
+
}),
|
5051
|
+
keymap9.of([
|
5052
|
+
{
|
5053
|
+
key: "Alt-Escape",
|
5054
|
+
run: (view) => {
|
5055
|
+
view.dom.parentElement?.focus();
|
5056
|
+
return true;
|
5118
5057
|
}
|
5119
|
-
break;
|
5120
5058
|
}
|
5121
|
-
|
5122
|
-
|
5123
|
-
|
5124
|
-
|
5125
|
-
|
5126
|
-
|
5127
|
-
|
5128
|
-
|
5129
|
-
|
5130
|
-
|
5131
|
-
|
5132
|
-
|
5133
|
-
|
5134
|
-
|
5135
|
-
|
5136
|
-
|
5137
|
-
|
5138
|
-
|
5139
|
-
|
5140
|
-
|
5059
|
+
])
|
5060
|
+
]
|
5061
|
+
};
|
5062
|
+
|
5063
|
+
// packages/ui/react-ui-editor/src/extensions/preview/preview.ts
|
5064
|
+
import "@dxos/lit-ui/dx-ref-tag.pcss";
|
5065
|
+
import { syntaxTree as syntaxTree9 } from "@codemirror/language";
|
5066
|
+
import { RangeSetBuilder as RangeSetBuilder4, StateField as StateField10 } from "@codemirror/state";
|
5067
|
+
import { Decoration as Decoration8, EditorView as EditorView19, WidgetType as WidgetType6 } from "@codemirror/view";
|
5068
|
+
var preview = (options = {}) => {
|
5069
|
+
return [
|
5070
|
+
// NOTE: Atomic block decorations must be created from a state field, now a widget, otherwise it results in the following error:
|
5071
|
+
// "Block decorations may not be specified via plugins"
|
5072
|
+
StateField10.define({
|
5073
|
+
create: (state) => buildDecorations3(state, options),
|
5074
|
+
update: (_, tr) => buildDecorations3(tr.state, options),
|
5075
|
+
provide: (field) => [
|
5076
|
+
EditorView19.decorations.from(field),
|
5077
|
+
EditorView19.atomicRanges.of((view) => view.state.field(field))
|
5078
|
+
]
|
5079
|
+
}),
|
5080
|
+
EditorView19.theme({
|
5081
|
+
".cm-preview-block": {
|
5082
|
+
marginLeft: "-1rem",
|
5083
|
+
marginRight: "-1rem",
|
5084
|
+
padding: "1rem",
|
5085
|
+
borderRadius: "0.5rem",
|
5086
|
+
background: "var(--dx-modalSurface)",
|
5087
|
+
border: "1px solid var(--dx-separator)"
|
5141
5088
|
}
|
5142
|
-
|
5143
|
-
|
5144
|
-
|
5145
|
-
|
5146
|
-
|
5147
|
-
|
5148
|
-
|
5149
|
-
|
5150
|
-
|
5151
|
-
|
5152
|
-
|
5153
|
-
|
5154
|
-
|
5155
|
-
|
5156
|
-
|
5157
|
-
|
5158
|
-
|
5089
|
+
})
|
5090
|
+
];
|
5091
|
+
};
|
5092
|
+
var getLinkRef = (state, node) => {
|
5093
|
+
const mark = node.getChild("LinkMark");
|
5094
|
+
const label = node.getChild("LinkLabel");
|
5095
|
+
if (mark && label) {
|
5096
|
+
const ref = state.sliceDoc(label.from + 1, label.to - 1);
|
5097
|
+
return {
|
5098
|
+
suggest: ref.startsWith("?"),
|
5099
|
+
block: state.sliceDoc(mark.from, mark.from + 1) === "!",
|
5100
|
+
label: state.sliceDoc(mark.to, label.from - 1),
|
5101
|
+
ref: ref.startsWith("?") ? ref.slice(1) : ref
|
5102
|
+
};
|
5103
|
+
}
|
5104
|
+
};
|
5105
|
+
var buildDecorations3 = (state, options) => {
|
5106
|
+
const builder = new RangeSetBuilder4();
|
5107
|
+
syntaxTree9(state).iterate({
|
5108
|
+
enter: (node) => {
|
5109
|
+
switch (node.name) {
|
5110
|
+
//
|
5111
|
+
// Decoration.
|
5112
|
+
// [Label][dxn:echo:123]
|
5113
|
+
//
|
5114
|
+
case "Link": {
|
5115
|
+
const link = getLinkRef(state, node.node);
|
5116
|
+
if (link) {
|
5117
|
+
builder.add(node.from, node.to, Decoration8.replace({
|
5118
|
+
widget: new PreviewInlineWidget(options, link)
|
5119
|
+
}));
|
5159
5120
|
}
|
5121
|
+
break;
|
5160
5122
|
}
|
5161
|
-
|
5162
|
-
|
5163
|
-
|
5164
|
-
|
5165
|
-
|
5166
|
-
|
5167
|
-
|
5168
|
-
|
5169
|
-
|
5170
|
-
|
5171
|
-
|
5172
|
-
|
5173
|
-
atomicDeco.add(node.from, marks[0].to, hide);
|
5174
|
-
}
|
5175
|
-
deco.add(marks[0].to, marks[1].from, Decoration7.mark({
|
5176
|
-
tagName: "a",
|
5177
|
-
attributes: {
|
5178
|
-
class: "cm-link",
|
5179
|
-
href: url,
|
5180
|
-
rel: "noreferrer",
|
5181
|
-
target: "_blank"
|
5182
|
-
}
|
5183
|
-
}));
|
5184
|
-
if (!editing) {
|
5185
|
-
atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration7.replace({
|
5186
|
-
widget: new LinkButton(url, options.renderLinkButton)
|
5187
|
-
}) : hide);
|
5123
|
+
//
|
5124
|
+
// Block widget.
|
5125
|
+
// ![Label][dxn:echo:123]
|
5126
|
+
//
|
5127
|
+
case "Image": {
|
5128
|
+
const link = getLinkRef(state, node.node);
|
5129
|
+
if (options.renderBlock && link) {
|
5130
|
+
builder.add(node.from, node.to, Decoration8.replace({
|
5131
|
+
block: true,
|
5132
|
+
// atomic: true,
|
5133
|
+
widget: new PreviewBlockWidget(options, link)
|
5134
|
+
}));
|
5188
5135
|
}
|
5136
|
+
break;
|
5189
5137
|
}
|
5190
|
-
break;
|
5191
5138
|
}
|
5192
|
-
|
5193
|
-
|
5194
|
-
|
5195
|
-
|
5196
|
-
|
5197
|
-
|
5198
|
-
|
5199
|
-
|
5139
|
+
}
|
5140
|
+
});
|
5141
|
+
return builder.finish();
|
5142
|
+
};
|
5143
|
+
var PreviewInlineWidget = class extends WidgetType6 {
|
5144
|
+
constructor(_options, _link) {
|
5145
|
+
super();
|
5146
|
+
this._options = _options;
|
5147
|
+
this._link = _link;
|
5148
|
+
}
|
5149
|
+
// override ignoreEvent() {
|
5150
|
+
// return false;
|
5151
|
+
// }
|
5152
|
+
eq(other) {
|
5153
|
+
return this._link.ref === other._link.ref && this._link.label === other._link.label;
|
5154
|
+
}
|
5155
|
+
toDOM(view) {
|
5156
|
+
const root = document.createElement("dx-ref-tag");
|
5157
|
+
root.textContent = this._link.label;
|
5158
|
+
root.setAttribute("ref", this._link.ref);
|
5159
|
+
return root;
|
5160
|
+
}
|
5161
|
+
};
|
5162
|
+
var PreviewBlockWidget = class extends WidgetType6 {
|
5163
|
+
constructor(_options, _link) {
|
5164
|
+
super();
|
5165
|
+
this._options = _options;
|
5166
|
+
this._link = _link;
|
5167
|
+
}
|
5168
|
+
// override ignoreEvent() {
|
5169
|
+
// return true;
|
5170
|
+
// }
|
5171
|
+
eq(other) {
|
5172
|
+
return this._link.ref === other._link.ref;
|
5173
|
+
}
|
5174
|
+
toDOM(view) {
|
5175
|
+
const root = document.createElement("div");
|
5176
|
+
root.classList.add("cm-preview-block");
|
5177
|
+
const handleAction = (action) => {
|
5178
|
+
const pos = view.posAtDOM(root);
|
5179
|
+
const node = syntaxTree9(view.state).resolve(pos + 1).node.parent;
|
5180
|
+
if (!node) {
|
5181
|
+
return;
|
5182
|
+
}
|
5183
|
+
const link = getLinkRef(view.state, node);
|
5184
|
+
if (link?.ref !== action.link.ref) {
|
5185
|
+
return;
|
5200
5186
|
}
|
5201
|
-
|
5202
|
-
|
5203
|
-
|
5204
|
-
|
5205
|
-
|
5187
|
+
switch (action.type) {
|
5188
|
+
// TODO(burdon): Should we dispatch to the view or mutate the document? (i.e., handle externally?)
|
5189
|
+
// Insert ref text.
|
5190
|
+
case "insert": {
|
5191
|
+
view.dispatch({
|
5192
|
+
changes: {
|
5193
|
+
from: node.from,
|
5194
|
+
to: node.to,
|
5195
|
+
insert: action.target.text
|
5196
|
+
}
|
5197
|
+
});
|
5198
|
+
break;
|
5199
|
+
}
|
5200
|
+
// Remove ref.
|
5201
|
+
case "delete": {
|
5202
|
+
view.dispatch({
|
5203
|
+
changes: {
|
5204
|
+
from: node.from,
|
5205
|
+
to: node.to
|
5206
|
+
}
|
5207
|
+
});
|
5208
|
+
break;
|
5206
5209
|
}
|
5207
5210
|
}
|
5208
|
-
}
|
5209
|
-
|
5210
|
-
|
5211
|
-
|
5212
|
-
|
5213
|
-
|
5214
|
-
|
5215
|
-
|
5216
|
-
}
|
5217
|
-
}
|
5218
|
-
};
|
5219
|
-
const tree = syntaxTree7(state);
|
5220
|
-
if (options.numberedHeadings?.from === void 0) {
|
5221
|
-
for (const { from, to } of view.visibleRanges) {
|
5222
|
-
tree.iterate({
|
5223
|
-
from,
|
5224
|
-
to,
|
5225
|
-
enter: wrapWithCatch(enterNode),
|
5226
|
-
leave: wrapWithCatch(leaveNode)
|
5227
|
-
});
|
5228
|
-
}
|
5229
|
-
} else {
|
5230
|
-
tree.iterate({
|
5231
|
-
enter: wrapWithCatch(enterNode),
|
5232
|
-
leave: wrapWithCatch(leaveNode)
|
5233
|
-
});
|
5211
|
+
};
|
5212
|
+
this._options.renderBlock(root, {
|
5213
|
+
readonly: view.state.readOnly,
|
5214
|
+
link: this._link,
|
5215
|
+
onAction: handleAction,
|
5216
|
+
onLookup: this._options.onLookup
|
5217
|
+
}, view);
|
5218
|
+
return root;
|
5234
5219
|
}
|
5235
|
-
return {
|
5236
|
-
deco: deco.finish(),
|
5237
|
-
atomicDeco: atomicDeco.finish()
|
5238
|
-
};
|
5239
5220
|
};
|
5240
|
-
|
5241
|
-
|
5221
|
+
|
5222
|
+
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
5223
|
+
import { keymap as keymap10 } from "@codemirror/view";
|
5224
|
+
var defaultItems = [
|
5225
|
+
"hello world!",
|
5226
|
+
"this is a test.",
|
5227
|
+
"this is [DXOS](https://dxos.org)"
|
5228
|
+
];
|
5229
|
+
var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
5230
|
+
let t;
|
5231
|
+
let idx = 0;
|
5242
5232
|
return [
|
5243
|
-
|
5244
|
-
|
5245
|
-
|
5246
|
-
|
5247
|
-
|
5248
|
-
|
5249
|
-
|
5250
|
-
|
5251
|
-
} else if (update2.selectionSet) {
|
5252
|
-
this.scheduleUpdate(update2.view);
|
5233
|
+
keymap10.of([
|
5234
|
+
{
|
5235
|
+
// Reset.
|
5236
|
+
key: "alt-meta-'",
|
5237
|
+
run: (view) => {
|
5238
|
+
clearTimeout(t);
|
5239
|
+
idx = 0;
|
5240
|
+
return true;
|
5253
5241
|
}
|
5254
|
-
}
|
5255
|
-
|
5256
|
-
|
5257
|
-
|
5258
|
-
|
5259
|
-
|
5260
|
-
|
5261
|
-
|
5262
|
-
|
5263
|
-
|
5264
|
-
|
5265
|
-
|
5266
|
-
|
5267
|
-
|
5242
|
+
},
|
5243
|
+
{
|
5244
|
+
// Next prompt.
|
5245
|
+
// TODO(burdon): Press 1-9 to select prompt?
|
5246
|
+
key: "shift-meta-'",
|
5247
|
+
run: (view) => {
|
5248
|
+
clearTimeout(t);
|
5249
|
+
const text = items[idx++];
|
5250
|
+
if (idx === items?.length) {
|
5251
|
+
idx = 0;
|
5252
|
+
}
|
5253
|
+
let i = 0;
|
5254
|
+
const insert = (d = 0) => {
|
5255
|
+
t = setTimeout(() => {
|
5256
|
+
const pos = view.state.selection.main.head;
|
5257
|
+
view.dispatch({
|
5258
|
+
changes: {
|
5259
|
+
from: pos,
|
5260
|
+
insert: text[i++]
|
5261
|
+
},
|
5262
|
+
selection: {
|
5263
|
+
anchor: pos + 1
|
5264
|
+
}
|
5265
|
+
});
|
5266
|
+
if (i < text.length) {
|
5267
|
+
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
5268
|
+
}
|
5269
|
+
}, d);
|
5270
|
+
};
|
5271
|
+
insert();
|
5272
|
+
return true;
|
5268
5273
|
}
|
5269
5274
|
}
|
5270
|
-
|
5271
|
-
this.clearUpdate();
|
5272
|
-
}
|
5273
|
-
}, {
|
5274
|
-
provide: (plugin) => [
|
5275
|
-
EditorView19.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
5276
|
-
EditorView19.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
5277
|
-
EditorView19.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration7.none)
|
5278
|
-
]
|
5279
|
-
}),
|
5280
|
-
image(),
|
5281
|
-
table(),
|
5282
|
-
adjustChanges(),
|
5283
|
-
formattingStyles
|
5275
|
+
])
|
5284
5276
|
];
|
5285
5277
|
};
|
5286
5278
|
|
5287
|
-
// packages/ui/react-ui-editor/src/
|
5288
|
-
|
5289
|
-
|
5290
|
-
|
5291
|
-
|
5292
|
-
|
5293
|
-
|
5294
|
-
|
5295
|
-
|
5296
|
-
|
5279
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/blocks.ts
|
5280
|
+
var createBlockGroupAction = (value) => createEditorActionGroup("block", {
|
5281
|
+
variant: "toggleGroup",
|
5282
|
+
selectCardinality: "single",
|
5283
|
+
value
|
5284
|
+
});
|
5285
|
+
var createBlockActions = (value, getView, blankLine) => Object.entries({
|
5286
|
+
blockquote: "ph--quotes--regular",
|
5287
|
+
codeblock: "ph--code-block--regular",
|
5288
|
+
table: "ph--table--regular"
|
5289
|
+
}).map(([type, icon]) => {
|
5290
|
+
const checked = type === value;
|
5291
|
+
return createEditorAction(type, () => {
|
5292
|
+
const view = getView();
|
5293
|
+
if (!view) {
|
5294
|
+
return;
|
5297
5295
|
}
|
5298
|
-
|
5299
|
-
|
5300
|
-
|
5296
|
+
switch (type) {
|
5297
|
+
case "blockquote":
|
5298
|
+
checked ? removeBlockquote(view) : addBlockquote(view);
|
5299
|
+
break;
|
5300
|
+
case "codeblock":
|
5301
|
+
checked ? removeCodeblock(view) : addCodeblock(view);
|
5302
|
+
break;
|
5303
|
+
case "table":
|
5304
|
+
insertTable(view);
|
5305
|
+
break;
|
5301
5306
|
}
|
5302
|
-
|
5303
|
-
|
5304
|
-
|
5305
|
-
|
5306
|
-
|
5307
|
-
|
5308
|
-
|
5309
|
-
|
5310
|
-
|
5311
|
-
|
5312
|
-
|
5313
|
-
|
5314
|
-
|
5315
|
-
|
5316
|
-
|
5317
|
-
|
5318
|
-
|
5319
|
-
|
5320
|
-
|
5307
|
+
}, {
|
5308
|
+
checked,
|
5309
|
+
...type === "table" && {
|
5310
|
+
disabled: !!blankLine
|
5311
|
+
},
|
5312
|
+
icon
|
5313
|
+
});
|
5314
|
+
});
|
5315
|
+
var createBlocks = (state, getView) => {
|
5316
|
+
const value = state?.blockQuote ? "blockquote" : state.blockType ?? "";
|
5317
|
+
const blockGroupAction = createBlockGroupAction(value);
|
5318
|
+
const blockActions = createBlockActions(value, getView, state.blankLine);
|
5319
|
+
return {
|
5320
|
+
nodes: [
|
5321
|
+
blockGroupAction,
|
5322
|
+
...blockActions
|
5323
|
+
],
|
5324
|
+
edges: [
|
5325
|
+
{
|
5326
|
+
source: "root",
|
5327
|
+
target: "block"
|
5328
|
+
},
|
5329
|
+
...blockActions.map(({ id }) => ({
|
5330
|
+
source: blockGroupAction.id,
|
5331
|
+
target: id
|
5332
|
+
}))
|
5333
|
+
]
|
5334
|
+
};
|
5335
|
+
};
|
5336
|
+
|
5337
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/comment.ts
|
5338
|
+
var commentLabel = (comment, selection) => comment ? "selection overlaps existing comment label" : selection === false ? "select text to comment label" : "comment label";
|
5339
|
+
var createCommentAction = (label, getView) => createEditorAction("comment", () => createComment(getView()), {
|
5340
|
+
testId: "editor.toolbar.comment",
|
5341
|
+
icon: "ph--chat-text--regular",
|
5342
|
+
label
|
5343
|
+
});
|
5344
|
+
var createComment2 = (state, getView) => ({
|
5345
|
+
nodes: [
|
5346
|
+
createCommentAction([
|
5347
|
+
commentLabel(state.comment, state.selection),
|
5348
|
+
{
|
5349
|
+
ns: translationKey
|
5321
5350
|
}
|
5322
|
-
|
5351
|
+
], getView)
|
5352
|
+
],
|
5353
|
+
edges: [
|
5354
|
+
{
|
5355
|
+
source: "root",
|
5356
|
+
target: "comment"
|
5357
|
+
}
|
5358
|
+
]
|
5359
|
+
});
|
5360
|
+
|
5361
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/formatting.ts
|
5362
|
+
var formats = {
|
5363
|
+
strong: "ph--text-b--regular",
|
5364
|
+
emphasis: "ph--text-italic--regular",
|
5365
|
+
strikethrough: "ph--text-strikethrough--regular",
|
5366
|
+
code: "ph--code--regular",
|
5367
|
+
link: "ph--link--regular"
|
5368
|
+
};
|
5369
|
+
var createFormattingGroup = (formatting) => createEditorActionGroup("formatting", {
|
5370
|
+
variant: "toggleGroup",
|
5371
|
+
selectCardinality: "multiple",
|
5372
|
+
value: Object.keys(formats).filter((key) => !!formatting[key])
|
5373
|
+
});
|
5374
|
+
var createFormattingActions = (formatting, getView) => Object.entries(formats).map(([type, icon]) => {
|
5375
|
+
const checked = !!formatting[type];
|
5376
|
+
return createEditorAction(type, () => {
|
5377
|
+
const view = getView();
|
5378
|
+
if (!view) {
|
5379
|
+
return;
|
5380
|
+
}
|
5381
|
+
if (type === "link") {
|
5382
|
+
checked ? removeLink(view) : addLink()(view);
|
5383
|
+
return;
|
5384
|
+
}
|
5385
|
+
const inlineType = type === "strong" ? Inline.Strong : type === "emphasis" ? Inline.Emphasis : type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
5386
|
+
setStyle(inlineType, !checked)(view);
|
5323
5387
|
}, {
|
5324
|
-
|
5325
|
-
|
5388
|
+
checked,
|
5389
|
+
icon
|
5326
5390
|
});
|
5391
|
+
});
|
5392
|
+
var createFormatting = (state, getView) => {
|
5393
|
+
const formattingGroupAction = createFormattingGroup(state);
|
5394
|
+
const formattingActions = createFormattingActions(state, getView);
|
5395
|
+
return {
|
5396
|
+
nodes: [
|
5397
|
+
formattingGroupAction,
|
5398
|
+
...formattingActions
|
5399
|
+
],
|
5400
|
+
edges: [
|
5401
|
+
{
|
5402
|
+
source: "root",
|
5403
|
+
target: "formatting"
|
5404
|
+
},
|
5405
|
+
...formattingActions.map(({ id }) => ({
|
5406
|
+
source: formattingGroupAction.id,
|
5407
|
+
target: id
|
5408
|
+
}))
|
5409
|
+
]
|
5410
|
+
};
|
5327
5411
|
};
|
5328
5412
|
|
5329
|
-
// packages/ui/react-ui-editor/src/
|
5330
|
-
|
5331
|
-
|
5332
|
-
|
5333
|
-
|
5334
|
-
|
5335
|
-
|
5336
|
-
|
5337
|
-
|
5338
|
-
|
5339
|
-
|
5340
|
-
|
5341
|
-
|
5342
|
-
|
5343
|
-
|
5344
|
-
|
5345
|
-
|
5346
|
-
|
5347
|
-
|
5348
|
-
|
5349
|
-
|
5350
|
-
|
5351
|
-
|
5352
|
-
const match = context.matchBefore(/@(\w+)?/);
|
5353
|
-
if (!match || match.from === match.to && !context.explicit) {
|
5354
|
-
return null;
|
5355
|
-
}
|
5356
|
-
return {
|
5357
|
-
from: match.from,
|
5358
|
-
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
5359
|
-
label: `@${value}`
|
5360
|
-
}))
|
5361
|
-
};
|
5413
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/headings.ts
|
5414
|
+
var createHeadingGroupAction = (value) => createEditorActionGroup("heading", {
|
5415
|
+
variant: "dropdownMenu",
|
5416
|
+
applyActive: true,
|
5417
|
+
selectCardinality: "single",
|
5418
|
+
value
|
5419
|
+
}, "ph--text-h--regular");
|
5420
|
+
var createHeadingActions = (getView) => Object.entries({
|
5421
|
+
"0": "ph--paragraph--regular",
|
5422
|
+
"1": "ph--text-h-one--regular",
|
5423
|
+
"2": "ph--text-h-two--regular",
|
5424
|
+
"3": "ph--text-h-three--regular",
|
5425
|
+
"4": "ph--text-h-four--regular",
|
5426
|
+
"5": "ph--text-h-five--regular",
|
5427
|
+
"6": "ph--text-h-six--regular"
|
5428
|
+
}).map(([levelStr, icon]) => {
|
5429
|
+
const level = parseInt(levelStr);
|
5430
|
+
return createEditorAction(`heading--${levelStr}`, () => setHeading(level)(getView()), {
|
5431
|
+
label: [
|
5432
|
+
"heading level label",
|
5433
|
+
{
|
5434
|
+
count: level,
|
5435
|
+
ns: translationKey
|
5362
5436
|
}
|
5363
|
-
]
|
5437
|
+
],
|
5438
|
+
icon
|
5364
5439
|
});
|
5440
|
+
});
|
5441
|
+
var computeHeadingValue = (state) => {
|
5442
|
+
const blockType = state ? state.blockType : "paragraph";
|
5443
|
+
const header = blockType && /heading(\d)/.exec(blockType);
|
5444
|
+
return header ? header[1] : blockType === "paragraph" || !blockType ? "0" : "";
|
5445
|
+
};
|
5446
|
+
var createHeadings = (state, getView) => {
|
5447
|
+
const headingValue = computeHeadingValue(state);
|
5448
|
+
const headingGroupAction = createHeadingGroupAction(headingValue);
|
5449
|
+
const headingActions = createHeadingActions(getView);
|
5450
|
+
return {
|
5451
|
+
nodes: [
|
5452
|
+
headingGroupAction,
|
5453
|
+
...headingActions
|
5454
|
+
],
|
5455
|
+
edges: [
|
5456
|
+
{
|
5457
|
+
source: "root",
|
5458
|
+
target: "heading"
|
5459
|
+
},
|
5460
|
+
...headingActions.map(({ id }) => ({
|
5461
|
+
source: headingGroupAction.id,
|
5462
|
+
target: id
|
5463
|
+
}))
|
5464
|
+
]
|
5465
|
+
};
|
5365
5466
|
};
|
5366
5467
|
|
5367
|
-
// packages/ui/react-ui-editor/src/
|
5368
|
-
|
5369
|
-
|
5370
|
-
|
5371
|
-
|
5372
|
-
var
|
5373
|
-
|
5374
|
-
|
5375
|
-
"source"
|
5376
|
-
];
|
5377
|
-
var EditorViewMode = S.Union(...EditorViewModes.map((mode) => S.Literal(mode)));
|
5378
|
-
var EditorInputModes = [
|
5379
|
-
"default",
|
5380
|
-
"vim",
|
5381
|
-
"vscode"
|
5382
|
-
];
|
5383
|
-
var EditorInputMode = S.Union(...EditorInputModes.map((mode) => S.Literal(mode)));
|
5384
|
-
var editorInputMode = singleValueFacet({});
|
5385
|
-
var InputModeExtensions = {
|
5386
|
-
default: [],
|
5387
|
-
vscode: [
|
5388
|
-
// https://github.com/replit/codemirror-vscode-keymap
|
5389
|
-
editorInputMode.of({
|
5390
|
-
type: "vscode"
|
5391
|
-
}),
|
5392
|
-
keymap9.of(vscodeKeymap)
|
5468
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/image.ts
|
5469
|
+
var createImageUploadAction = (onImageUpload) => createEditorAction("image", onImageUpload, {
|
5470
|
+
testId: "editor.toolbar.image",
|
5471
|
+
icon: "ph--image-square--regular"
|
5472
|
+
});
|
5473
|
+
var createImageUpload = (onImageUpload) => ({
|
5474
|
+
nodes: [
|
5475
|
+
createImageUploadAction(onImageUpload)
|
5393
5476
|
],
|
5394
|
-
|
5395
|
-
|
5396
|
-
|
5397
|
-
|
5398
|
-
|
5399
|
-
noTabster: true
|
5400
|
-
}),
|
5401
|
-
keymap9.of([
|
5402
|
-
{
|
5403
|
-
key: "Alt-Escape",
|
5404
|
-
run: (view) => {
|
5405
|
-
view.dom.parentElement?.focus();
|
5406
|
-
return true;
|
5407
|
-
}
|
5408
|
-
}
|
5409
|
-
])
|
5477
|
+
edges: [
|
5478
|
+
{
|
5479
|
+
source: "root",
|
5480
|
+
target: "image"
|
5481
|
+
}
|
5410
5482
|
]
|
5411
|
-
};
|
5483
|
+
});
|
5412
5484
|
|
5413
|
-
// packages/ui/react-ui-editor/src/
|
5414
|
-
|
5415
|
-
|
5416
|
-
|
5417
|
-
|
5418
|
-
var preview = (options = {}) => {
|
5419
|
-
return [
|
5420
|
-
// NOTE: Atomic block decorations must be created from a state field, now a widget, otherwise it results in the following error:
|
5421
|
-
// "Block decorations may not be specified via plugins"
|
5422
|
-
StateField10.define({
|
5423
|
-
create: (state) => buildDecorations3(state, options),
|
5424
|
-
update: (_, tr) => buildDecorations3(tr.state, options),
|
5425
|
-
provide: (field) => [
|
5426
|
-
EditorView20.decorations.from(field),
|
5427
|
-
EditorView20.atomicRanges.of((view) => view.state.field(field))
|
5428
|
-
]
|
5429
|
-
}),
|
5430
|
-
EditorView20.theme({
|
5431
|
-
".cm-preview-block": {
|
5432
|
-
marginLeft: "-1rem",
|
5433
|
-
marginRight: "-1rem",
|
5434
|
-
padding: "1rem",
|
5435
|
-
borderRadius: "0.5rem",
|
5436
|
-
background: "var(--dx-modalSurface)",
|
5437
|
-
border: "1px solid var(--dx-separator)"
|
5438
|
-
}
|
5439
|
-
})
|
5440
|
-
];
|
5441
|
-
};
|
5442
|
-
var getLinkRef = (state, node) => {
|
5443
|
-
const mark = node.getChild("LinkMark");
|
5444
|
-
const label = node.getChild("LinkLabel");
|
5445
|
-
if (mark && label) {
|
5446
|
-
const ref = state.sliceDoc(label.from + 1, label.to - 1);
|
5447
|
-
return {
|
5448
|
-
suggest: ref.startsWith("?"),
|
5449
|
-
block: state.sliceDoc(mark.from, mark.from + 1) === "!",
|
5450
|
-
label: state.sliceDoc(mark.to, label.from - 1),
|
5451
|
-
ref: ref.startsWith("?") ? ref.slice(1) : ref
|
5452
|
-
};
|
5453
|
-
}
|
5485
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/lists.ts
|
5486
|
+
var listStyles = {
|
5487
|
+
bullet: "ph--list-bullets--regular",
|
5488
|
+
ordered: "ph--list-numbers--regular",
|
5489
|
+
task: "ph--list-checks--regular"
|
5454
5490
|
};
|
5455
|
-
var
|
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
|
-
|
5487
|
-
|
5488
|
-
|
5491
|
+
var createListGroupAction = (value) => createEditorActionGroup("list", {
|
5492
|
+
variant: "toggleGroup",
|
5493
|
+
selectCardinality: "single",
|
5494
|
+
value
|
5495
|
+
});
|
5496
|
+
var createListActions = (value, getView) => Object.entries(listStyles).map(([listStyle, icon]) => {
|
5497
|
+
const checked = value === listStyle;
|
5498
|
+
return createEditorAction(`list-${listStyle}`, () => {
|
5499
|
+
const view = getView();
|
5500
|
+
if (!view) {
|
5501
|
+
return;
|
5502
|
+
}
|
5503
|
+
const listType = listStyle === "ordered" ? List.Ordered : listStyle === "bullet" ? List.Bullet : List.Task;
|
5504
|
+
if (checked) {
|
5505
|
+
removeList(listType)(view);
|
5506
|
+
} else {
|
5507
|
+
addList(listType)(view);
|
5508
|
+
}
|
5509
|
+
}, {
|
5510
|
+
checked,
|
5511
|
+
icon
|
5512
|
+
});
|
5513
|
+
});
|
5514
|
+
var createLists = (state, getView) => {
|
5515
|
+
const value = state.listStyle ?? "";
|
5516
|
+
const listGroupAction = createListGroupAction(value);
|
5517
|
+
const listActionsMap = createListActions(value, getView);
|
5518
|
+
return {
|
5519
|
+
nodes: [
|
5520
|
+
listGroupAction,
|
5521
|
+
...listActionsMap
|
5522
|
+
],
|
5523
|
+
edges: [
|
5524
|
+
{
|
5525
|
+
source: "root",
|
5526
|
+
target: "list"
|
5527
|
+
},
|
5528
|
+
...listActionsMap.map(({ id }) => ({
|
5529
|
+
source: listGroupAction.id,
|
5530
|
+
target: id
|
5531
|
+
}))
|
5532
|
+
]
|
5533
|
+
};
|
5534
|
+
};
|
5535
|
+
|
5536
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/search.ts
|
5537
|
+
import { openSearchPanel } from "@codemirror/search";
|
5538
|
+
var createSearchAction = (getView) => createEditorAction("search", () => openSearchPanel(getView()), {
|
5539
|
+
testId: "editor.toolbar.search",
|
5540
|
+
icon: "ph--magnifying-glass--regular"
|
5541
|
+
});
|
5542
|
+
var createSearch = (getView) => ({
|
5543
|
+
nodes: [
|
5544
|
+
createSearchAction(getView)
|
5545
|
+
],
|
5546
|
+
edges: [
|
5547
|
+
{
|
5548
|
+
source: "root",
|
5549
|
+
target: "search"
|
5489
5550
|
}
|
5551
|
+
]
|
5552
|
+
});
|
5553
|
+
|
5554
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/view-mode.ts
|
5555
|
+
var createViewModeGroupAction = (value) => createEditorActionGroup("viewMode", {
|
5556
|
+
variant: "dropdownMenu",
|
5557
|
+
applyActive: true,
|
5558
|
+
selectCardinality: "single",
|
5559
|
+
value
|
5560
|
+
}, "ph--eye--regular");
|
5561
|
+
var createViewModeActions = (value, onViewModeChange) => Object.entries({
|
5562
|
+
preview: "ph--eye--regular",
|
5563
|
+
source: "ph--pencil-simple--regular",
|
5564
|
+
readonly: "ph--pencil-slash--regular"
|
5565
|
+
}).map(([viewMode, icon]) => {
|
5566
|
+
const checked = viewMode === value;
|
5567
|
+
return createEditorAction(`view-mode--${viewMode}`, () => onViewModeChange(viewMode), {
|
5568
|
+
label: [
|
5569
|
+
`${viewMode} mode label`,
|
5570
|
+
{
|
5571
|
+
ns: translationKey
|
5572
|
+
}
|
5573
|
+
],
|
5574
|
+
checked,
|
5575
|
+
icon
|
5490
5576
|
});
|
5491
|
-
|
5577
|
+
});
|
5578
|
+
var createViewMode = (state, onViewModeChange) => {
|
5579
|
+
const value = state.viewMode ?? "source";
|
5580
|
+
const viewModeGroupAction = createViewModeGroupAction(value);
|
5581
|
+
const viewModeActions = createViewModeActions(value, onViewModeChange);
|
5582
|
+
return {
|
5583
|
+
nodes: [
|
5584
|
+
viewModeGroupAction,
|
5585
|
+
...viewModeActions
|
5586
|
+
],
|
5587
|
+
edges: [
|
5588
|
+
{
|
5589
|
+
source: "root",
|
5590
|
+
target: "viewMode"
|
5591
|
+
},
|
5592
|
+
...viewModeActions.map(({ id }) => ({
|
5593
|
+
source: viewModeGroupAction.id,
|
5594
|
+
target: id
|
5595
|
+
}))
|
5596
|
+
]
|
5597
|
+
};
|
5492
5598
|
};
|
5493
|
-
|
5494
|
-
|
5495
|
-
|
5496
|
-
|
5497
|
-
|
5599
|
+
|
5600
|
+
// packages/ui/react-ui-editor/src/defaults.ts
|
5601
|
+
import { EditorView as EditorView20 } from "@codemirror/view";
|
5602
|
+
import { mx as mx3 } from "@dxos/react-ui-theme";
|
5603
|
+
var margin = "!mt-[1rem]";
|
5604
|
+
var editorWidth = "!mli-auto is-full max-is-[min(50rem,100%-4rem)]";
|
5605
|
+
var editorContent = mx3(margin, editorWidth);
|
5606
|
+
var editorFullWidth = mx3(margin);
|
5607
|
+
var editorGutter = EditorView20.theme({
|
5608
|
+
// Match margin from content.
|
5609
|
+
// Gutter = 2rem + 1rem margin.
|
5610
|
+
".cm-gutters": {
|
5611
|
+
marginTop: "1rem",
|
5612
|
+
paddingRight: "1rem"
|
5498
5613
|
}
|
5499
|
-
|
5500
|
-
|
5501
|
-
|
5502
|
-
|
5503
|
-
return this._link.ref === other._link.ref && this._link.label === other._link.label;
|
5614
|
+
});
|
5615
|
+
var editorMonospace = EditorView20.theme({
|
5616
|
+
".cm-content": {
|
5617
|
+
fontFamily: fontMono
|
5504
5618
|
}
|
5505
|
-
|
5506
|
-
|
5507
|
-
|
5508
|
-
|
5509
|
-
|
5619
|
+
});
|
5620
|
+
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
5621
|
+
var stackItemContentEditorClassNames = (role) => mx3("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");
|
5622
|
+
var stackItemContentToolbarClassNames = (role) => mx3("attention-surface is-full border-be !border-separator relative z-[1]", role === "section" && "sticky block-start-0 -mbe-px min-is-0");
|
5623
|
+
|
5624
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
|
5625
|
+
var createToolbar = ({ getView, state, customActions, ...features }) => {
|
5626
|
+
const nodes = [];
|
5627
|
+
const edges = [];
|
5628
|
+
if (features.headings ?? true) {
|
5629
|
+
const headings2 = createHeadings(state, getView);
|
5630
|
+
nodes.push(...headings2.nodes);
|
5631
|
+
edges.push(...headings2.edges);
|
5510
5632
|
}
|
5511
|
-
|
5512
|
-
|
5513
|
-
|
5514
|
-
|
5515
|
-
this._options = _options;
|
5516
|
-
this._link = _link;
|
5633
|
+
if (features.formatting ?? true) {
|
5634
|
+
const formatting = createFormatting(state, getView);
|
5635
|
+
nodes.push(...formatting.nodes);
|
5636
|
+
edges.push(...formatting.edges);
|
5517
5637
|
}
|
5518
|
-
|
5519
|
-
|
5520
|
-
|
5521
|
-
|
5522
|
-
return this._link.ref === other._link.ref;
|
5638
|
+
if (features.lists ?? true) {
|
5639
|
+
const lists = createLists(state, getView);
|
5640
|
+
nodes.push(...lists.nodes);
|
5641
|
+
edges.push(...lists.edges);
|
5523
5642
|
}
|
5524
|
-
|
5525
|
-
const
|
5526
|
-
|
5527
|
-
|
5528
|
-
const pos = view.posAtDOM(root);
|
5529
|
-
const node = syntaxTree9(view.state).resolve(pos + 1).node.parent;
|
5530
|
-
if (!node) {
|
5531
|
-
return;
|
5532
|
-
}
|
5533
|
-
const link = getLinkRef(view.state, node);
|
5534
|
-
if (link?.ref !== action.link.ref) {
|
5535
|
-
return;
|
5536
|
-
}
|
5537
|
-
switch (action.type) {
|
5538
|
-
// TODO(burdon): Should we dispatch to the view or mutate the document? (i.e., handle externally?)
|
5539
|
-
// Insert ref text.
|
5540
|
-
case "insert": {
|
5541
|
-
view.dispatch({
|
5542
|
-
changes: {
|
5543
|
-
from: node.from,
|
5544
|
-
to: node.to,
|
5545
|
-
insert: action.target.text
|
5546
|
-
}
|
5547
|
-
});
|
5548
|
-
break;
|
5549
|
-
}
|
5550
|
-
// Remove ref.
|
5551
|
-
case "delete": {
|
5552
|
-
view.dispatch({
|
5553
|
-
changes: {
|
5554
|
-
from: node.from,
|
5555
|
-
to: node.to
|
5556
|
-
}
|
5557
|
-
});
|
5558
|
-
break;
|
5559
|
-
}
|
5560
|
-
}
|
5561
|
-
};
|
5562
|
-
this._options.renderBlock(root, {
|
5563
|
-
readonly: view.state.readOnly,
|
5564
|
-
link: this._link,
|
5565
|
-
onAction: handleAction,
|
5566
|
-
onLookup: this._options.onLookup
|
5567
|
-
}, view);
|
5568
|
-
return root;
|
5643
|
+
if (features.blocks ?? true) {
|
5644
|
+
const blocks = createBlocks(state, getView);
|
5645
|
+
nodes.push(...blocks.nodes);
|
5646
|
+
edges.push(...blocks.edges);
|
5569
5647
|
}
|
5648
|
+
if (features.image) {
|
5649
|
+
const image2 = createImageUpload(features.image);
|
5650
|
+
nodes.push(...image2.nodes);
|
5651
|
+
edges.push(...image2.edges);
|
5652
|
+
}
|
5653
|
+
if (customActions) {
|
5654
|
+
const custom = customActions();
|
5655
|
+
nodes.push(...custom.nodes);
|
5656
|
+
edges.push(...custom.edges);
|
5657
|
+
}
|
5658
|
+
const editorToolbarGap = createGapSeparator();
|
5659
|
+
nodes.push(...editorToolbarGap.nodes);
|
5660
|
+
edges.push(...editorToolbarGap.edges);
|
5661
|
+
if (features.comment) {
|
5662
|
+
const comment = createComment2(state, getView);
|
5663
|
+
nodes.push(...comment.nodes);
|
5664
|
+
edges.push(...comment.edges);
|
5665
|
+
}
|
5666
|
+
if (features.search ?? true) {
|
5667
|
+
const search = createSearch(getView);
|
5668
|
+
nodes.push(...search.nodes);
|
5669
|
+
edges.push(...search.edges);
|
5670
|
+
}
|
5671
|
+
if (features.viewMode) {
|
5672
|
+
const viewMode = createViewMode(state, features.viewMode);
|
5673
|
+
nodes.push(...viewMode.nodes);
|
5674
|
+
edges.push(...viewMode.edges);
|
5675
|
+
}
|
5676
|
+
return {
|
5677
|
+
nodes,
|
5678
|
+
edges
|
5679
|
+
};
|
5570
5680
|
};
|
5571
|
-
|
5572
|
-
|
5573
|
-
|
5574
|
-
var defaultItems = [
|
5575
|
-
"hello world!",
|
5576
|
-
"this is a test.",
|
5577
|
-
"this is [DXOS](https://dxos.org)"
|
5578
|
-
];
|
5579
|
-
var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
5580
|
-
let t;
|
5581
|
-
let idx = 0;
|
5582
|
-
return [
|
5583
|
-
keymap10.of([
|
5584
|
-
{
|
5585
|
-
// Reset.
|
5586
|
-
key: "alt-meta-'",
|
5587
|
-
run: (view) => {
|
5588
|
-
clearTimeout(t);
|
5589
|
-
idx = 0;
|
5590
|
-
return true;
|
5591
|
-
}
|
5592
|
-
},
|
5593
|
-
{
|
5594
|
-
// Next prompt.
|
5595
|
-
// TODO(burdon): Press 1-9 to select prompt?
|
5596
|
-
key: "shift-meta-'",
|
5597
|
-
run: (view) => {
|
5598
|
-
clearTimeout(t);
|
5599
|
-
const text = items[idx++];
|
5600
|
-
if (idx === items?.length) {
|
5601
|
-
idx = 0;
|
5602
|
-
}
|
5603
|
-
let i = 0;
|
5604
|
-
const insert = (d = 0) => {
|
5605
|
-
t = setTimeout(() => {
|
5606
|
-
const pos = view.state.selection.main.head;
|
5607
|
-
view.dispatch({
|
5608
|
-
changes: {
|
5609
|
-
from: pos,
|
5610
|
-
insert: text[i++]
|
5611
|
-
},
|
5612
|
-
selection: {
|
5613
|
-
anchor: pos + 1
|
5614
|
-
}
|
5615
|
-
});
|
5616
|
-
if (i < text.length) {
|
5617
|
-
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
5618
|
-
}
|
5619
|
-
}, d);
|
5620
|
-
};
|
5621
|
-
insert();
|
5622
|
-
return true;
|
5623
|
-
}
|
5624
|
-
}
|
5625
|
-
])
|
5626
|
-
];
|
5627
|
-
};
|
5628
|
-
|
5629
|
-
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
5630
|
-
import { useCallback as useCallback2 } from "react";
|
5631
|
-
var useActionHandler = (view) => {
|
5632
|
-
return useCallback2((action) => view && processEditorPayload(view, action.properties), [
|
5633
|
-
view
|
5681
|
+
var useEditorToolbarActionGraph = (props) => {
|
5682
|
+
const menuCreator = useCallback(() => createToolbar(props), [
|
5683
|
+
props
|
5634
5684
|
]);
|
5685
|
+
return useMenuActions(menuCreator);
|
5635
5686
|
};
|
5687
|
+
var EditorToolbar = /* @__PURE__ */ memo(({ classNames, attendableId, role, ...props }) => {
|
5688
|
+
const menuProps = useEditorToolbarActionGraph(props);
|
5689
|
+
return /* @__PURE__ */ React3.createElement("div", {
|
5690
|
+
role: "none",
|
5691
|
+
className: stackItemContentToolbarClassNames(role)
|
5692
|
+
}, /* @__PURE__ */ React3.createElement(ElevationProvider, {
|
5693
|
+
elevation: role === "section" ? "positioned" : "base"
|
5694
|
+
}, /* @__PURE__ */ React3.createElement(MenuProvider, {
|
5695
|
+
...menuProps,
|
5696
|
+
attendableId
|
5697
|
+
}, /* @__PURE__ */ React3.createElement(ToolbarMenu, {
|
5698
|
+
classNames: [
|
5699
|
+
textBlockWidth,
|
5700
|
+
"!bg-transparent",
|
5701
|
+
classNames
|
5702
|
+
]
|
5703
|
+
}))));
|
5704
|
+
});
|
5636
5705
|
|
5637
5706
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
5638
5707
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
5639
5708
|
import { EditorView as EditorView21 } from "@codemirror/view";
|
5640
5709
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
5641
|
-
import { useCallback as
|
5710
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo4, useRef, useState } from "react";
|
5642
5711
|
import { log as log7 } from "@dxos/log";
|
5643
5712
|
import { getProviderValue, isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
5644
5713
|
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
@@ -5763,7 +5832,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5763
5832
|
Escape: view?.state.facet(editorInputMode).noTabster
|
5764
5833
|
}
|
5765
5834
|
});
|
5766
|
-
const handleKeyUp =
|
5835
|
+
const handleKeyUp = useCallback2((event) => {
|
5767
5836
|
const { key, target, currentTarget } = event;
|
5768
5837
|
if (target === currentTarget) {
|
5769
5838
|
switch (key) {
|
@@ -5822,7 +5891,7 @@ export {
|
|
5822
5891
|
commentsState,
|
5823
5892
|
convertTreeToJson,
|
5824
5893
|
createBasicExtensions,
|
5825
|
-
|
5894
|
+
createComment,
|
5826
5895
|
createDataExtensions,
|
5827
5896
|
createEditorAction,
|
5828
5897
|
createEditorActionGroup,
|
@@ -5900,7 +5969,6 @@ export {
|
|
5900
5969
|
toggleStyle,
|
5901
5970
|
translations_default as translations,
|
5902
5971
|
typewriter,
|
5903
|
-
useActionHandler,
|
5904
5972
|
useCommentClickListener,
|
5905
5973
|
useCommentState,
|
5906
5974
|
useComments,
|