@dxos/react-ui-editor 0.7.5-main.499c70c → 0.7.5-main.5ae2ba8
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 +1125 -1137
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +1145 -1171
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +1125 -1137
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/InputMode.stories.d.ts +3 -4
- package/dist/types/src/InputMode.stories.d.ts.map +1 -1
- package/dist/types/src/TextEditor.stories.d.ts +34 -35
- package/dist/types/src/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts +3 -0
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/blocks.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/blocks.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/comment.d.ts +17 -0
- package/dist/types/src/components/EditorToolbar/comment.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/formatting.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/formatting.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/headings.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/headings.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/index.d.ts +3 -0
- package/dist/types/src/components/EditorToolbar/index.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/lists.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/lists.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/util.d.ts +58 -0
- package/dist/types/src/components/EditorToolbar/util.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/viewMode.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/viewMode.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts +5 -6
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +3 -4
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/editorAction.d.ts +12 -0
- package/dist/types/src/extensions/markdown/editorAction.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts +14 -12
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/index.d.ts +1 -1
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/styles.d.ts.map +1 -1
- package/dist/types/src/hooks/useActionHandler.d.ts +2 -2
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/stack-item-content-class-names.d.ts +3 -0
- package/dist/types/src/styles/stack-item-content-class-names.d.ts.map +1 -0
- package/dist/types/src/styles/theme.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +31 -29
- package/src/InputMode.stories.tsx +7 -10
- package/src/components/EditorToolbar/EditorToolbar.tsx +106 -0
- package/src/components/EditorToolbar/blocks.ts +41 -0
- package/src/components/EditorToolbar/comment.ts +23 -0
- package/src/components/EditorToolbar/formatting.ts +41 -0
- package/src/components/EditorToolbar/headings.ts +59 -0
- package/src/components/EditorToolbar/index.ts +6 -0
- package/src/components/EditorToolbar/lists.ts +40 -0
- package/src/components/EditorToolbar/util.ts +65 -0
- package/src/components/EditorToolbar/viewMode.ts +48 -0
- package/src/components/index.ts +1 -1
- package/src/extensions/automerge/automerge.stories.tsx +2 -2
- package/src/extensions/comments.ts +12 -19
- package/src/extensions/factories.ts +11 -5
- package/src/extensions/markdown/decorate.ts +1 -1
- package/src/extensions/markdown/{action.ts → editorAction.ts} +22 -20
- package/src/extensions/markdown/formatting.test.ts +7 -6
- package/src/extensions/markdown/formatting.ts +20 -24
- package/src/extensions/markdown/index.ts +1 -1
- package/src/extensions/markdown/styles.ts +21 -0
- package/src/hooks/useActionHandler.ts +4 -4
- package/src/index.ts +4 -0
- package/src/styles/markdown.ts +1 -1
- package/src/styles/stack-item-content-class-names.ts +17 -0
- package/src/styles/theme.ts +2 -3
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +0 -34
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +0 -1
- package/dist/types/src/components/Toolbar/index.d.ts +0 -2
- package/dist/types/src/components/Toolbar/index.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/action.d.ts +0 -9
- package/dist/types/src/extensions/markdown/action.d.ts.map +0 -1
- package/src/components/Toolbar/Toolbar.tsx +0 -522
- package/src/components/Toolbar/index.ts +0 -5
@@ -39,261 +39,862 @@ import { EditorView as EditorView21, keymap as keymap11 } from "@codemirror/view
|
|
39
39
|
import { tags as tags2 } from "@lezer/highlight";
|
40
40
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
41
41
|
|
42
|
-
// packages/ui/react-ui-editor/src/components/
|
43
|
-
import
|
44
|
-
import {
|
45
|
-
import
|
46
|
-
import {
|
47
|
-
import { Button, DropdownMenu, ElevationProvider, Toolbar as NaturalToolbar, Tooltip, useTranslation } from "@dxos/react-ui";
|
48
|
-
import { getSize } from "@dxos/react-ui-theme";
|
42
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
|
43
|
+
import React, { useCallback } from "react";
|
44
|
+
import { ElevationProvider } from "@dxos/react-ui";
|
45
|
+
import { ToolbarMenu, MenuProvider, useMenuActions, createGapSeparator } from "@dxos/react-ui-menu";
|
46
|
+
import { textBlockWidth } from "@dxos/react-ui-theme";
|
49
47
|
|
50
|
-
// packages/ui/react-ui-editor/src/
|
51
|
-
import {
|
52
|
-
import {
|
53
|
-
import {
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
var
|
58
|
-
|
59
|
-
|
60
|
-
|
48
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/util.ts
|
49
|
+
import { useMemo } from "react";
|
50
|
+
import { create } from "@dxos/live-object";
|
51
|
+
import { createMenuAction, createMenuItemGroup } from "@dxos/react-ui-menu";
|
52
|
+
var useEditorToolbarState = (initialState = {}) => {
|
53
|
+
return useMemo(() => create(initialState), []);
|
54
|
+
};
|
55
|
+
var createEditorAction = (payload, icon, label = [
|
56
|
+
`${payload.type} label`,
|
57
|
+
{
|
58
|
+
ns: translationKey
|
61
59
|
}
|
60
|
+
], id = payload.type) => createMenuAction(id, {
|
61
|
+
icon,
|
62
|
+
label,
|
63
|
+
...payload
|
64
|
+
});
|
65
|
+
var createEditorActionGroup = (id, props, icon) => createMenuItemGroup(id, {
|
66
|
+
icon,
|
67
|
+
iconOnly: true,
|
68
|
+
...props
|
62
69
|
});
|
70
|
+
var editorToolbarSearch = createEditorAction({
|
71
|
+
type: "search"
|
72
|
+
}, "ph--magnifying-glass--regular");
|
63
73
|
|
64
|
-
// packages/ui/react-ui-editor/src/
|
65
|
-
var
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
};
|
70
|
-
var
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
74
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/blocks.ts
|
75
|
+
var createBlockGroupAction = (value) => createEditorActionGroup("block", {
|
76
|
+
variant: "toggleGroup",
|
77
|
+
selectCardinality: "single",
|
78
|
+
value
|
79
|
+
});
|
80
|
+
var createBlockActions = (value, blankLine) => Object.entries({
|
81
|
+
blockquote: "ph--quotes--regular",
|
82
|
+
codeblock: "ph--code-block--regular",
|
83
|
+
table: "ph--table--regular"
|
84
|
+
}).map(([type, icon]) => {
|
85
|
+
return createEditorAction({
|
86
|
+
type,
|
87
|
+
checked: type === value,
|
88
|
+
...type === "table" && {
|
89
|
+
disabled: !!blankLine
|
90
|
+
}
|
91
|
+
}, icon);
|
92
|
+
});
|
93
|
+
var createBlocks = (state) => {
|
94
|
+
const value = state?.blockQuote ? "blockquote" : state.blockType ?? "";
|
95
|
+
const blockGroupAction = createBlockGroupAction(value);
|
96
|
+
const blockActions = createBlockActions(value, state.blankLine);
|
97
|
+
return {
|
98
|
+
nodes: [
|
99
|
+
blockGroupAction,
|
100
|
+
...blockActions
|
101
|
+
],
|
102
|
+
edges: [
|
103
|
+
{
|
104
|
+
source: "root",
|
105
|
+
target: "block"
|
106
|
+
},
|
107
|
+
...blockActions.map(({ id }) => ({
|
108
|
+
source: blockGroupAction.id,
|
109
|
+
target: id
|
110
|
+
}))
|
111
|
+
]
|
112
|
+
};
|
97
113
|
};
|
98
114
|
|
99
|
-
// packages/ui/react-ui-editor/src/
|
100
|
-
|
101
|
-
var
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
115
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/comment.ts
|
116
|
+
var commentLabel = (comment, selection) => comment ? "selection overlaps existing comment label" : selection === false ? "select text to comment label" : "comment label";
|
117
|
+
var createCommentAction = (label) => createEditorAction({
|
118
|
+
type: "comment",
|
119
|
+
testId: "editor.toolbar.comment"
|
120
|
+
}, "ph--chat-text--regular", label);
|
121
|
+
var createComment = (state) => ({
|
122
|
+
nodes: [
|
123
|
+
createCommentAction([
|
124
|
+
commentLabel(state.comment, state.selection),
|
125
|
+
{
|
126
|
+
ns: translationKey
|
127
|
+
}
|
128
|
+
])
|
129
|
+
],
|
130
|
+
edges: [
|
131
|
+
{
|
132
|
+
source: "root",
|
133
|
+
target: "comment"
|
113
134
|
}
|
135
|
+
]
|
136
|
+
});
|
137
|
+
|
138
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/formatting.ts
|
139
|
+
var formats = {
|
140
|
+
strong: "ph--text-b--regular",
|
141
|
+
emphasis: "ph--text-italic--regular",
|
142
|
+
strikethrough: "ph--text-strikethrough--regular",
|
143
|
+
code: "ph--code--regular",
|
144
|
+
link: "ph--link--regular"
|
145
|
+
};
|
146
|
+
var createFormattingGroup = (formatting) => createEditorActionGroup("formatting", {
|
147
|
+
variant: "toggleGroup",
|
148
|
+
selectCardinality: "multiple",
|
149
|
+
value: Object.keys(formats).filter((key) => !!formatting[key])
|
150
|
+
});
|
151
|
+
var createFormattingActions = (formatting) => Object.entries(formats).map(([type, icon]) => createEditorAction({
|
152
|
+
type,
|
153
|
+
checked: !!formatting[type]
|
154
|
+
}, icon));
|
155
|
+
var createFormatting = (state) => {
|
156
|
+
const formattingGroupAction = createFormattingGroup(state);
|
157
|
+
const formattingActions = createFormattingActions(state);
|
158
|
+
return {
|
159
|
+
nodes: [
|
160
|
+
formattingGroupAction,
|
161
|
+
...formattingActions
|
162
|
+
],
|
163
|
+
edges: [
|
164
|
+
{
|
165
|
+
source: "root",
|
166
|
+
target: "formatting"
|
167
|
+
},
|
168
|
+
...formattingActions.map(({ id }) => ({
|
169
|
+
source: formattingGroupAction.id,
|
170
|
+
target: id
|
171
|
+
}))
|
172
|
+
]
|
114
173
|
};
|
115
174
|
};
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
175
|
+
|
176
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/headings.ts
|
177
|
+
var createHeadingGroupAction = (value) => createEditorActionGroup("heading", {
|
178
|
+
variant: "dropdownMenu",
|
179
|
+
applyActive: true,
|
180
|
+
selectCardinality: "single",
|
181
|
+
value
|
182
|
+
}, "ph--text-h--regular");
|
183
|
+
var createHeadingActions = (value) => Object.entries({
|
184
|
+
"0": "ph--paragraph--regular",
|
185
|
+
"1": "ph--text-h-one--regular",
|
186
|
+
"2": "ph--text-h-two--regular",
|
187
|
+
"3": "ph--text-h-three--regular",
|
188
|
+
"4": "ph--text-h-four--regular",
|
189
|
+
"5": "ph--text-h-five--regular",
|
190
|
+
"6": "ph--text-h-six--regular"
|
191
|
+
}).map(([levelStr, icon]) => {
|
192
|
+
const level = parseInt(levelStr);
|
193
|
+
return createEditorAction({
|
194
|
+
type: "heading",
|
195
|
+
data: level,
|
196
|
+
checked: value === levelStr
|
197
|
+
}, icon, [
|
198
|
+
"heading level label",
|
199
|
+
{
|
200
|
+
count: level,
|
201
|
+
ns: translationKey
|
202
|
+
}
|
203
|
+
], `heading--${levelStr}`);
|
204
|
+
});
|
205
|
+
var computeHeadingValue = (state) => {
|
206
|
+
const blockType = state ? state.blockType : "paragraph";
|
207
|
+
const header = blockType && /heading(\d)/.exec(blockType);
|
208
|
+
return header ? header[1] : blockType === "paragraph" || !blockType ? "0" : "";
|
127
209
|
};
|
128
|
-
var
|
129
|
-
|
130
|
-
|
210
|
+
var createHeadings = (state) => {
|
211
|
+
const headingValue = computeHeadingValue(state);
|
212
|
+
const headingGroupAction = createHeadingGroupAction(headingValue);
|
213
|
+
const headingActions = createHeadingActions(headingValue);
|
214
|
+
return {
|
215
|
+
nodes: [
|
216
|
+
headingGroupAction,
|
217
|
+
...headingActions
|
218
|
+
],
|
219
|
+
edges: [
|
220
|
+
{
|
221
|
+
source: "root",
|
222
|
+
target: "heading"
|
223
|
+
},
|
224
|
+
...headingActions.map(({ id }) => ({
|
225
|
+
source: headingGroupAction.id,
|
226
|
+
target: id
|
227
|
+
}))
|
228
|
+
]
|
229
|
+
};
|
131
230
|
};
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
231
|
+
|
232
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/lists.ts
|
233
|
+
var listStyles = {
|
234
|
+
bullet: "ph--list-bullets--regular",
|
235
|
+
ordered: "ph--list-numbers--regular",
|
236
|
+
task: "ph--list-checks--regular"
|
237
|
+
};
|
238
|
+
var createListGroupAction = (value) => createEditorActionGroup("list", {
|
239
|
+
variant: "toggleGroup",
|
240
|
+
selectCardinality: "single",
|
241
|
+
value
|
242
|
+
});
|
243
|
+
var createListActions = (value) => Object.entries(listStyles).map(([listStyle, icon]) => createEditorAction({
|
244
|
+
type: `list-${listStyle}`,
|
245
|
+
checked: value === listStyle
|
246
|
+
}, icon));
|
247
|
+
var createLists = (state) => {
|
248
|
+
const value = state.listStyle ?? "";
|
249
|
+
const listGroupAction = createListGroupAction(value);
|
250
|
+
const listActionsMap = createListActions(value);
|
251
|
+
return {
|
252
|
+
nodes: [
|
253
|
+
listGroupAction,
|
254
|
+
...listActionsMap
|
255
|
+
],
|
256
|
+
edges: [
|
257
|
+
{
|
258
|
+
source: "root",
|
259
|
+
target: "list"
|
260
|
+
},
|
261
|
+
...listActionsMap.map(({ id }) => ({
|
262
|
+
source: listGroupAction.id,
|
263
|
+
target: id
|
264
|
+
}))
|
265
|
+
]
|
266
|
+
};
|
267
|
+
};
|
268
|
+
|
269
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/viewMode.ts
|
270
|
+
var createViewModeGroupAction = (value) => createEditorActionGroup("viewMode", {
|
271
|
+
variant: "dropdownMenu",
|
272
|
+
applyActive: true,
|
273
|
+
selectCardinality: "single",
|
274
|
+
value
|
275
|
+
}, "ph--eye--regular");
|
276
|
+
var createViewModeActions = (value) => Object.entries({
|
277
|
+
preview: "ph--eye--regular",
|
278
|
+
source: "ph--pencil-simple--regular",
|
279
|
+
readonly: "ph--pencil-slash--regular"
|
280
|
+
}).map(([viewMode, icon]) => {
|
281
|
+
return createEditorAction({
|
282
|
+
type: "view-mode",
|
283
|
+
data: viewMode,
|
284
|
+
checked: viewMode === value
|
285
|
+
}, icon, [
|
286
|
+
`${viewMode} mode label`,
|
287
|
+
{
|
288
|
+
ns: translationKey
|
136
289
|
}
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
290
|
+
], `view-mode--${viewMode}`);
|
291
|
+
});
|
292
|
+
var createViewMode = (state) => {
|
293
|
+
const value = state.viewMode ?? "source";
|
294
|
+
const viewModeGroupAction = createViewModeGroupAction(value);
|
295
|
+
const viewModeActions = createViewModeActions(value);
|
296
|
+
return {
|
297
|
+
nodes: [
|
298
|
+
viewModeGroupAction,
|
299
|
+
...viewModeActions
|
300
|
+
],
|
301
|
+
edges: [
|
302
|
+
{
|
303
|
+
source: "root",
|
304
|
+
target: "viewMode"
|
305
|
+
},
|
306
|
+
...viewModeActions.map(({ id }) => ({
|
307
|
+
source: viewModeGroupAction.id,
|
308
|
+
target: id
|
309
|
+
}))
|
310
|
+
]
|
311
|
+
};
|
157
312
|
};
|
158
313
|
|
159
|
-
// packages/ui/react-ui-editor/src/
|
160
|
-
|
161
|
-
|
314
|
+
// packages/ui/react-ui-editor/src/styles/stack-item-content-class-names.ts
|
315
|
+
import { mx } from "@dxos/react-ui-theme";
|
316
|
+
var stackItemContentEditorClassNames = (role) => mx("dx-focus-ring-inset data-[toolbar=disabled]:pbs-2 attention-surface", role === "article" ? "min-bs-0" : "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-bs-24");
|
317
|
+
var stackItemContentToolbarClassNames = (role) => mx("attention-surface is-full border-be !border-separator", role === "section" && "sticky block-start-0 z-[1] -mbe-px min-is-0");
|
318
|
+
|
319
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
|
320
|
+
var createToolbar = ({ state, customActions, ...features }) => {
|
321
|
+
const nodes = [];
|
322
|
+
const edges = [];
|
323
|
+
if (features.headings ?? true) {
|
324
|
+
const headings2 = createHeadings(state);
|
325
|
+
nodes.push(...headings2.nodes);
|
326
|
+
edges.push(...headings2.edges);
|
327
|
+
}
|
328
|
+
if (features.formatting ?? true) {
|
329
|
+
const formatting = createFormatting(state);
|
330
|
+
nodes.push(...formatting.nodes);
|
331
|
+
edges.push(...formatting.edges);
|
332
|
+
}
|
333
|
+
if (features.lists ?? true) {
|
334
|
+
const lists = createLists(state);
|
335
|
+
nodes.push(...lists.nodes);
|
336
|
+
edges.push(...lists.edges);
|
337
|
+
}
|
338
|
+
if (features.blocks ?? true) {
|
339
|
+
const blocks = createBlocks(state);
|
340
|
+
nodes.push(...blocks.nodes);
|
341
|
+
edges.push(...blocks.edges);
|
342
|
+
}
|
343
|
+
if (customActions) {
|
344
|
+
const custom = customActions();
|
345
|
+
nodes.push(...custom.nodes);
|
346
|
+
edges.push(...custom.edges);
|
347
|
+
}
|
348
|
+
const editorToolbarGap = createGapSeparator();
|
349
|
+
nodes.push(...editorToolbarGap.nodes);
|
350
|
+
edges.push(...editorToolbarGap.edges);
|
351
|
+
if (features.comment ?? true) {
|
352
|
+
const comment = createComment(state);
|
353
|
+
nodes.push(...comment.nodes);
|
354
|
+
edges.push(...comment.edges);
|
355
|
+
}
|
356
|
+
if (features.search ?? true) {
|
357
|
+
nodes.push(editorToolbarSearch);
|
358
|
+
edges.push({
|
359
|
+
source: "root",
|
360
|
+
target: editorToolbarSearch.id
|
361
|
+
});
|
362
|
+
}
|
363
|
+
if (features.viewMode ?? true) {
|
364
|
+
const viewMode = createViewMode(state);
|
365
|
+
nodes.push(...viewMode.nodes);
|
366
|
+
edges.push(...viewMode.edges);
|
367
|
+
}
|
162
368
|
return {
|
163
|
-
|
164
|
-
|
165
|
-
top: rect.top,
|
166
|
-
bottom: rect.bottom
|
369
|
+
nodes,
|
370
|
+
edges
|
167
371
|
};
|
168
372
|
};
|
169
|
-
var
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
return
|
373
|
+
var useEditorToolbarActionGraph = ({ onAction, ...props }) => {
|
374
|
+
const menuCreator = useCallback(() => createToolbar(props), [
|
375
|
+
props
|
376
|
+
]);
|
377
|
+
const { resolveGroupItems } = useMenuActions(menuCreator);
|
378
|
+
return {
|
379
|
+
resolveGroupItems,
|
380
|
+
onAction
|
381
|
+
};
|
175
382
|
};
|
176
|
-
var
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
}
|
182
|
-
|
183
|
-
}
|
383
|
+
var EditorToolbar = ({ classNames, attendableId, role, ...props }) => {
|
384
|
+
const menuProps = useEditorToolbarActionGraph(props);
|
385
|
+
return /* @__PURE__ */ React.createElement("div", {
|
386
|
+
role: "none",
|
387
|
+
className: stackItemContentToolbarClassNames(role)
|
388
|
+
}, /* @__PURE__ */ React.createElement(ElevationProvider, {
|
389
|
+
elevation: role === "section" ? "positioned" : "base"
|
390
|
+
}, /* @__PURE__ */ React.createElement(MenuProvider, {
|
391
|
+
...menuProps,
|
392
|
+
attendableId
|
393
|
+
}, /* @__PURE__ */ React.createElement(ToolbarMenu, {
|
394
|
+
classNames: [
|
395
|
+
textBlockWidth,
|
396
|
+
"!bg-transparent",
|
397
|
+
classNames
|
398
|
+
]
|
399
|
+
}))));
|
184
400
|
};
|
185
401
|
|
186
|
-
// packages/ui/react-ui-editor/src/
|
187
|
-
import
|
188
|
-
import {
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
402
|
+
// packages/ui/react-ui-editor/src/defaults.ts
|
403
|
+
import { EditorView } from "@codemirror/view";
|
404
|
+
import { mx as mx3 } from "@dxos/react-ui-theme";
|
405
|
+
|
406
|
+
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
407
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
408
|
+
var headings = {
|
409
|
+
1: "text-4xl",
|
410
|
+
2: "text-3xl",
|
411
|
+
3: "text-2xl",
|
412
|
+
4: "text-xl",
|
413
|
+
5: "text-lg",
|
414
|
+
6: ""
|
415
|
+
};
|
416
|
+
var theme = {
|
417
|
+
code: "font-mono !no-underline text-neutral-700 dark:text-neutral-300",
|
418
|
+
codeMark: "font-mono text-primary-500",
|
419
|
+
mark: "opacity-50",
|
420
|
+
heading: (level) => {
|
421
|
+
return mx2(headings[level], "dark:text-primary-400");
|
200
422
|
}
|
201
|
-
return el;
|
202
423
|
};
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
424
|
+
|
425
|
+
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
426
|
+
import get from "lodash.get";
|
427
|
+
import { tokens } from "@dxos/react-ui-theme";
|
428
|
+
var getToken = (path, defaultValue) => {
|
429
|
+
const value = get(tokens, path, defaultValue);
|
430
|
+
return value?.toString() ?? "";
|
208
431
|
};
|
432
|
+
var fontBody = getToken("fontFamily.body");
|
433
|
+
var fontMono = getToken("fontFamily.mono");
|
209
434
|
|
210
|
-
// packages/ui/react-ui-editor/src/
|
211
|
-
var
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
}
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
435
|
+
// packages/ui/react-ui-editor/src/styles/theme.ts
|
436
|
+
var defaultTheme = {
|
437
|
+
"&": {},
|
438
|
+
"&.cm-focused": {
|
439
|
+
outline: "none"
|
440
|
+
},
|
441
|
+
/**
|
442
|
+
* Scroller
|
443
|
+
*/
|
444
|
+
".cm-scroller": {
|
445
|
+
overflowY: "auto"
|
446
|
+
},
|
447
|
+
/**
|
448
|
+
* Content
|
449
|
+
* NOTE: Apply margins to content so that scrollbar is at the edge of the container.
|
450
|
+
*/
|
451
|
+
".cm-content": {
|
452
|
+
padding: "unset",
|
453
|
+
fontFamily: fontBody,
|
454
|
+
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
455
|
+
fontSize: "16px",
|
456
|
+
lineHeight: 1.5,
|
457
|
+
color: "unset"
|
458
|
+
},
|
459
|
+
/**
|
460
|
+
* Gutters
|
461
|
+
* NOTE: Gutters should have the same top margin as the content.
|
462
|
+
*/
|
463
|
+
".cm-gutters": {
|
464
|
+
borderRight: "none",
|
465
|
+
background: "transparent"
|
466
|
+
},
|
467
|
+
".cm-gutter": {},
|
468
|
+
".cm-gutter.cm-lineNumbers .cm-gutterElement": {
|
469
|
+
minWidth: "40px",
|
470
|
+
alignContent: "center"
|
471
|
+
},
|
472
|
+
/**
|
473
|
+
* Height is set to match the corresponding line.
|
474
|
+
*/
|
475
|
+
".cm-gutterElement": {
|
476
|
+
alignItems: "center",
|
477
|
+
fontSize: "16px"
|
478
|
+
},
|
479
|
+
/**
|
480
|
+
* Line.
|
481
|
+
*/
|
482
|
+
".cm-line": {
|
483
|
+
paddingInline: 0
|
484
|
+
},
|
485
|
+
".cm-activeLine": {
|
486
|
+
background: "var(--dx-cmActiveLine)"
|
487
|
+
},
|
488
|
+
/**
|
489
|
+
* Cursor (layer).
|
490
|
+
*/
|
491
|
+
".cm-cursor, .cm-dropCursor": {
|
492
|
+
borderLeft: "2px solid var(--dx-cmCursor)"
|
493
|
+
},
|
494
|
+
".cm-placeholder": {
|
495
|
+
color: "var(--dx-subdued)"
|
496
|
+
},
|
497
|
+
/**
|
498
|
+
* Selection (layer).
|
499
|
+
*/
|
500
|
+
".cm-selectionBackground": {
|
501
|
+
background: "var(--dx-cmSelection)"
|
502
|
+
},
|
503
|
+
/**
|
504
|
+
* Search.
|
505
|
+
* NOTE: Matches comment.
|
506
|
+
*/
|
507
|
+
".cm-searchMatch": {
|
508
|
+
margin: "0 -3px",
|
509
|
+
padding: "3px",
|
510
|
+
borderRadius: "3px",
|
511
|
+
background: "var(--dx-cmHighlightSurface)",
|
512
|
+
color: "var(--dx-cmHighlight)"
|
513
|
+
},
|
514
|
+
".cm-searchMatch-selected": {
|
515
|
+
textDecoration: "underline"
|
516
|
+
},
|
517
|
+
/**
|
518
|
+
* Link.
|
519
|
+
*/
|
520
|
+
".cm-link": {
|
521
|
+
textDecorationLine: "underline",
|
522
|
+
textDecorationThickness: "1px",
|
523
|
+
textUnderlineOffset: "2px",
|
524
|
+
borderRadius: ".125rem"
|
525
|
+
},
|
526
|
+
".cm-link > span": {
|
527
|
+
color: "var(--dx-accentText)"
|
528
|
+
},
|
529
|
+
/**
|
530
|
+
* Tooltip.
|
531
|
+
*/
|
532
|
+
".cm-tooltip": {
|
533
|
+
background: "var(--dx-baseSurface)"
|
534
|
+
},
|
535
|
+
".cm-tooltip-below": {},
|
536
|
+
/**
|
537
|
+
* Autocomplete.
|
538
|
+
* https://github.com/codemirror/autocomplete/blob/main/src/completion.ts
|
539
|
+
*/
|
540
|
+
".cm-tooltip.cm-tooltip-autocomplete": {
|
541
|
+
marginTop: "4px",
|
542
|
+
marginLeft: "-3px"
|
543
|
+
},
|
544
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul": {
|
545
|
+
maxHeight: "20em"
|
546
|
+
},
|
547
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > li": {},
|
548
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {},
|
549
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
|
550
|
+
paddingLeft: "4px !important",
|
551
|
+
borderBottom: "none !important",
|
552
|
+
color: "var(--dx-accentText)"
|
553
|
+
},
|
554
|
+
".cm-tooltip.cm-completionInfo": {
|
555
|
+
width: "360px !important",
|
556
|
+
margin: "-10px 1px 0 1px",
|
557
|
+
padding: "8px !important",
|
558
|
+
borderColor: "var(--dx-separator)"
|
559
|
+
},
|
560
|
+
".cm-completionIcon": {
|
561
|
+
display: "none"
|
562
|
+
},
|
563
|
+
".cm-completionLabel": {
|
564
|
+
fontFamily: fontBody
|
565
|
+
},
|
566
|
+
".cm-completionMatchedText": {
|
567
|
+
textDecoration: "none !important",
|
568
|
+
opacity: 0.5
|
569
|
+
},
|
570
|
+
/**
|
571
|
+
* Panels
|
572
|
+
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
573
|
+
*
|
574
|
+
* Find/replace panel.
|
575
|
+
* <div class="cm-announced">...</div>
|
576
|
+
* <div class="cm-scroller">...</div>
|
577
|
+
* <div class="cm-panels cm-panels-bottom">
|
578
|
+
* <div class="cm-search cm-panel">
|
579
|
+
* <input class="cm-textfield" />
|
580
|
+
* <button class="cm-button">...</button>
|
581
|
+
* <label><input type="checkbox" />...</label>
|
582
|
+
* </div>
|
583
|
+
* </div
|
584
|
+
*/
|
585
|
+
// TODO(burdon): Implement custom panel (with icon buttons).
|
586
|
+
".cm-panels": {},
|
587
|
+
".cm-panel": {
|
588
|
+
fontFamily: fontBody,
|
589
|
+
backgroundColor: "var(--surface-bg)"
|
590
|
+
},
|
591
|
+
".cm-panel input, .cm-panel button, .cm-panel label": {
|
592
|
+
color: "var(--dx-subdued)",
|
593
|
+
fontFamily: fontBody,
|
594
|
+
fontSize: "14px",
|
595
|
+
all: "unset",
|
596
|
+
margin: "3px !important",
|
597
|
+
padding: "2px 6px !important",
|
598
|
+
outline: "1px solid transparent"
|
599
|
+
},
|
600
|
+
".cm-panel input, .cm-panel button": {
|
601
|
+
backgroundColor: "var(--dx-input)"
|
602
|
+
},
|
603
|
+
".cm-panel input:focus, .cm-panel button:focus": {
|
604
|
+
outline: "1px solid var(--dx-accentFocusIndicator)"
|
605
|
+
},
|
606
|
+
".cm-panel label": {
|
607
|
+
display: "inline-flex",
|
608
|
+
alignItems: "center",
|
609
|
+
cursor: "pointer"
|
610
|
+
},
|
611
|
+
".cm-panel input.cm-textfield": {},
|
612
|
+
".cm-panel input[type=checkbox]": {
|
613
|
+
width: "8px",
|
614
|
+
height: "8px",
|
615
|
+
marginRight: "6px !important",
|
616
|
+
padding: "2px !important",
|
617
|
+
color: "var(--dx-accentFocusIndicator)"
|
618
|
+
},
|
619
|
+
".cm-panel button": {
|
620
|
+
"&:hover": {
|
621
|
+
backgroundColor: "var(--dx-accentSurfaceHover) !important"
|
622
|
+
},
|
623
|
+
"&:active": {
|
624
|
+
backgroundColor: "var(--dx-accentSurfaceHover)"
|
243
625
|
}
|
244
|
-
}
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
], (state) => {
|
250
|
-
const annotations2 = state.field(annotationsState);
|
251
|
-
const decorations = annotations2.map((annotation) => {
|
252
|
-
const range = Cursor.getRangeFromCursor(state, annotation.cursor);
|
253
|
-
return range && annotationMark.range(range.from, range.to);
|
254
|
-
}).filter(isNotFalsy);
|
255
|
-
return Decoration.set(decorations);
|
256
|
-
}),
|
257
|
-
styles
|
258
|
-
];
|
626
|
+
},
|
627
|
+
".cm-panel.cm-search": {
|
628
|
+
padding: "4px",
|
629
|
+
borderTop: "1px solid var(--dx-separator)"
|
630
|
+
}
|
259
631
|
};
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
632
|
+
|
633
|
+
// packages/ui/react-ui-editor/src/defaults.ts
|
634
|
+
var margin = "!mt-[1rem]";
|
635
|
+
var editorContent = mx3(margin, "!mli-auto w-full max-w-[min(50rem,100%-2rem)]");
|
636
|
+
var editorFullWidth = mx3(margin);
|
637
|
+
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
638
|
+
var editorGutter = EditorView.theme({
|
639
|
+
// Match margin from content.
|
640
|
+
".cm-gutters": {
|
641
|
+
marginTop: "16px",
|
642
|
+
paddingRight: "1rem"
|
643
|
+
}
|
644
|
+
});
|
645
|
+
var editorMonospace = EditorView.theme({
|
646
|
+
".cm-content": {
|
647
|
+
fontFamily: fontMono
|
265
648
|
}
|
266
649
|
});
|
267
650
|
|
268
|
-
// packages/ui/react-ui-editor/src/extensions/
|
269
|
-
import {
|
270
|
-
import {
|
271
|
-
import {
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
651
|
+
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
652
|
+
import { StateField } from "@codemirror/state";
|
653
|
+
import { Decoration, EditorView as EditorView2 } from "@codemirror/view";
|
654
|
+
import { isNotFalsy } from "@dxos/util";
|
655
|
+
|
656
|
+
// packages/ui/react-ui-editor/src/util/facet.ts
|
657
|
+
import { Facet } from "@codemirror/state";
|
658
|
+
var singleValueFacet = (defaultValue) => Facet.define({
|
659
|
+
// Called immediately.
|
660
|
+
combine: (providers) => {
|
661
|
+
return providers[0] ?? defaultValue;
|
662
|
+
}
|
663
|
+
});
|
664
|
+
|
665
|
+
// packages/ui/react-ui-editor/src/util/cursor.ts
|
666
|
+
var overlap = (a, b) => a.from <= b.to && a.to >= b.from;
|
667
|
+
var defaultCursorConverter = {
|
668
|
+
toCursor: (position) => position.toString(),
|
669
|
+
fromCursor: (cursor) => parseInt(cursor)
|
670
|
+
};
|
671
|
+
var Cursor = class _Cursor {
|
672
|
+
static {
|
673
|
+
this.converter = singleValueFacet(defaultCursorConverter);
|
674
|
+
}
|
675
|
+
static {
|
676
|
+
this.getCursorFromRange = (state, range) => {
|
677
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
678
|
+
const from = cursorConverter2.toCursor(range.from);
|
679
|
+
const to = cursorConverter2.toCursor(range.to, -1);
|
680
|
+
return [
|
681
|
+
from,
|
682
|
+
to
|
683
|
+
].join(":");
|
684
|
+
};
|
685
|
+
}
|
686
|
+
static {
|
687
|
+
this.getRangeFromCursor = (state, cursor) => {
|
688
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
689
|
+
const parts = cursor.split(":");
|
690
|
+
const from = cursorConverter2.fromCursor(parts[0]);
|
691
|
+
const to = cursorConverter2.fromCursor(parts[1]);
|
692
|
+
return from !== void 0 && to !== void 0 ? {
|
693
|
+
from,
|
694
|
+
to
|
695
|
+
} : void 0;
|
696
|
+
};
|
697
|
+
}
|
698
|
+
};
|
699
|
+
|
700
|
+
// packages/ui/react-ui-editor/src/util/debug.ts
|
701
|
+
import { log } from "@dxos/log";
|
702
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/debug.ts";
|
703
|
+
var wrapWithCatch = (fn) => {
|
704
|
+
return (...args) => {
|
705
|
+
try {
|
706
|
+
return fn(...args);
|
707
|
+
} catch (err) {
|
708
|
+
log.catch(err, void 0, {
|
709
|
+
F: __dxlog_file,
|
710
|
+
L: 15,
|
711
|
+
S: void 0,
|
712
|
+
C: (f, a) => f(...a)
|
713
|
+
});
|
714
|
+
}
|
715
|
+
};
|
716
|
+
};
|
717
|
+
var callbackWrapper = (fn) => (...args) => {
|
718
|
+
try {
|
719
|
+
return fn(...args);
|
720
|
+
} catch (err) {
|
721
|
+
log.catch(err, void 0, {
|
722
|
+
F: __dxlog_file,
|
723
|
+
L: 29,
|
724
|
+
S: void 0,
|
725
|
+
C: (f, a) => f(...a)
|
726
|
+
});
|
727
|
+
}
|
728
|
+
};
|
729
|
+
var debugDispatcher = (trs, view) => {
|
730
|
+
logChanges(trs);
|
731
|
+
view.update(trs);
|
732
|
+
};
|
733
|
+
var logChanges = (trs) => {
|
734
|
+
const changes = trs.flatMap((tr) => {
|
735
|
+
if (tr.changes.empty) {
|
736
|
+
return void 0;
|
737
|
+
}
|
738
|
+
const changes2 = [];
|
739
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
740
|
+
fromA,
|
741
|
+
toA,
|
742
|
+
fromB,
|
743
|
+
toB,
|
744
|
+
inserted: inserted.toString()
|
745
|
+
})));
|
746
|
+
return changes2;
|
747
|
+
}).filter(Boolean);
|
748
|
+
if (changes.length) {
|
749
|
+
log.info("changes", {
|
750
|
+
changes
|
751
|
+
}, {
|
752
|
+
F: __dxlog_file,
|
753
|
+
L: 62,
|
754
|
+
S: void 0,
|
755
|
+
C: (f, a) => f(...a)
|
756
|
+
});
|
757
|
+
}
|
758
|
+
};
|
759
|
+
|
760
|
+
// packages/ui/react-ui-editor/src/util/dom.ts
|
761
|
+
var flattenRect = (rect, left) => {
|
762
|
+
const x = left ? rect.left : rect.right;
|
763
|
+
return {
|
764
|
+
left: x,
|
765
|
+
right: x,
|
766
|
+
top: rect.top,
|
767
|
+
bottom: rect.bottom
|
768
|
+
};
|
769
|
+
};
|
770
|
+
var scratchRange;
|
771
|
+
var textRange = (node, from, to = from) => {
|
772
|
+
const range = scratchRange || (scratchRange = document.createRange());
|
773
|
+
range.setEnd(node, to);
|
774
|
+
range.setStart(node, from);
|
775
|
+
return range;
|
776
|
+
};
|
777
|
+
var clientRectsFor = (dom) => {
|
778
|
+
if (dom.nodeType === 3) {
|
779
|
+
return textRange(dom, 0, dom.nodeValue.length).getClientRects();
|
780
|
+
} else if (dom.nodeType === 1) {
|
781
|
+
return dom.getClientRects();
|
782
|
+
} else {
|
783
|
+
return [];
|
784
|
+
}
|
785
|
+
};
|
786
|
+
|
787
|
+
// packages/ui/react-ui-editor/src/util/react.tsx
|
788
|
+
import React2 from "react";
|
789
|
+
import { createRoot } from "react-dom/client";
|
790
|
+
import { ThemeProvider } from "@dxos/react-ui";
|
791
|
+
import { defaultTx } from "@dxos/react-ui-theme";
|
792
|
+
var createElement = (tag, options, children) => {
|
793
|
+
const el = document.createElement(tag);
|
794
|
+
if (options?.className) {
|
795
|
+
el.className = options.className;
|
796
|
+
}
|
797
|
+
if (children) {
|
798
|
+
el.append(...Array.isArray(children) ? children : [
|
799
|
+
children
|
800
|
+
]);
|
801
|
+
}
|
802
|
+
return el;
|
803
|
+
};
|
804
|
+
var renderRoot = (root, node) => {
|
805
|
+
createRoot(root).render(/* @__PURE__ */ React2.createElement(ThemeProvider, {
|
806
|
+
tx: defaultTx
|
807
|
+
}, node));
|
808
|
+
return root;
|
809
|
+
};
|
810
|
+
|
811
|
+
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
812
|
+
var annotationMark = Decoration.mark({
|
813
|
+
class: "cm-annotation"
|
814
|
+
});
|
815
|
+
var annotations = (options = {}) => {
|
816
|
+
const match = (state) => {
|
817
|
+
const annotations2 = [];
|
818
|
+
const text = state.doc.toString();
|
819
|
+
if (options.match) {
|
820
|
+
const matches = text.matchAll(options.match);
|
821
|
+
for (const match2 of matches) {
|
822
|
+
const from = match2.index;
|
823
|
+
const to = from + match2[0].length;
|
824
|
+
const cursor = Cursor.getCursorFromRange(state, {
|
825
|
+
from,
|
826
|
+
to
|
827
|
+
});
|
828
|
+
annotations2.push({
|
829
|
+
cursor
|
830
|
+
});
|
831
|
+
}
|
832
|
+
}
|
833
|
+
return annotations2;
|
834
|
+
};
|
835
|
+
const annotationsState = StateField.define({
|
836
|
+
create: (state) => {
|
837
|
+
return match(state);
|
838
|
+
},
|
839
|
+
update: (value, tr) => {
|
840
|
+
if (!tr.changes.empty) {
|
841
|
+
return match(tr.state);
|
842
|
+
}
|
843
|
+
return value;
|
844
|
+
}
|
845
|
+
});
|
846
|
+
return [
|
847
|
+
annotationsState,
|
848
|
+
EditorView2.decorations.compute([
|
849
|
+
annotationsState
|
850
|
+
], (state) => {
|
851
|
+
const annotations2 = state.field(annotationsState);
|
852
|
+
const decorations = annotations2.map((annotation) => {
|
853
|
+
const range = Cursor.getRangeFromCursor(state, annotation.cursor);
|
854
|
+
return range && annotationMark.range(range.from, range.to);
|
855
|
+
}).filter(isNotFalsy);
|
856
|
+
return Decoration.set(decorations);
|
857
|
+
}),
|
858
|
+
styles
|
859
|
+
];
|
860
|
+
};
|
861
|
+
var styles = EditorView2.theme({
|
862
|
+
".cm-annotation": {
|
863
|
+
textDecoration: "underline",
|
864
|
+
textDecorationStyle: "wavy",
|
865
|
+
textDecorationColor: "var(--dx-error)"
|
866
|
+
}
|
867
|
+
});
|
868
|
+
|
869
|
+
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
870
|
+
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
871
|
+
import { markdownLanguage } from "@codemirror/lang-markdown";
|
872
|
+
import { keymap } from "@codemirror/view";
|
873
|
+
var autocomplete = ({ debug, activateOnTyping, override, onSearch } = {}) => {
|
874
|
+
const extensions = [
|
875
|
+
// https://codemirror.net/docs/ref/#view.keymap
|
876
|
+
// https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
|
877
|
+
// TODO(burdon): Set custom keymap.
|
878
|
+
keymap.of(completionKeymap),
|
879
|
+
// https://codemirror.net/examples/autocompletion
|
880
|
+
// https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
881
|
+
autocompletion({
|
882
|
+
activateOnTyping,
|
883
|
+
override,
|
884
|
+
closeOnBlur: !debug,
|
885
|
+
tooltipClass: () => "shadow rounded"
|
886
|
+
})
|
887
|
+
];
|
888
|
+
if (onSearch) {
|
889
|
+
extensions.push(
|
890
|
+
// TODO(burdon): Optional decoration via addToOptions
|
891
|
+
markdownLanguage.data.of({
|
892
|
+
autocomplete: (context) => {
|
893
|
+
const match = context.matchBefore(/\w*/);
|
894
|
+
if (!match || match.from === match.to && !context.explicit) {
|
895
|
+
return null;
|
896
|
+
}
|
897
|
+
return {
|
297
898
|
from: match.from,
|
298
899
|
options: onSearch(match.text.toLowerCase())
|
299
900
|
};
|
@@ -306,7 +907,7 @@ var autocomplete = ({ debug, activateOnTyping, override, onSearch } = {}) => {
|
|
306
907
|
|
307
908
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
308
909
|
import { StateField as StateField2 } from "@codemirror/state";
|
309
|
-
import { EditorView as
|
910
|
+
import { EditorView as EditorView3, ViewPlugin } from "@codemirror/view";
|
310
911
|
import { next as A3 } from "@dxos/automerge/automerge";
|
311
912
|
|
312
913
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
@@ -590,7 +1191,7 @@ var automerge = (accessor) => {
|
|
590
1191
|
}
|
591
1192
|
}),
|
592
1193
|
// Reconcile local updates.
|
593
|
-
|
1194
|
+
EditorView3.updateListener.of(({ view, changes }) => {
|
594
1195
|
if (!changes.empty) {
|
595
1196
|
syncer.reconcile(view, true);
|
596
1197
|
}
|
@@ -600,7 +1201,7 @@ var automerge = (accessor) => {
|
|
600
1201
|
|
601
1202
|
// packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts
|
602
1203
|
import { Annotation as Annotation2, RangeSet } from "@codemirror/state";
|
603
|
-
import { Decoration as Decoration2, EditorView as
|
1204
|
+
import { Decoration as Decoration2, EditorView as EditorView4, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
604
1205
|
import { Event } from "@dxos/async";
|
605
1206
|
import { Context } from "@dxos/context";
|
606
1207
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts";
|
@@ -774,7 +1375,7 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
774
1375
|
return true;
|
775
1376
|
}
|
776
1377
|
};
|
777
|
-
var styles2 =
|
1378
|
+
var styles2 = EditorView4.theme({
|
778
1379
|
".cm-collab-selection": {},
|
779
1380
|
".cm-collab-selectionLine": {
|
780
1381
|
padding: 0,
|
@@ -940,7 +1541,7 @@ var SpaceAwarenessProvider = class {
|
|
940
1541
|
};
|
941
1542
|
|
942
1543
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
943
|
-
import { EditorView as
|
1544
|
+
import { EditorView as EditorView5, keymap as keymap2 } from "@codemirror/view";
|
944
1545
|
import defaultsDeep from "lodash.defaultsdeep";
|
945
1546
|
import { invariant as invariant2 } from "@dxos/invariant";
|
946
1547
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
@@ -988,7 +1589,7 @@ var blast = (options = defaultOptions) => {
|
|
988
1589
|
};
|
989
1590
|
return [
|
990
1591
|
// Cursor moved.
|
991
|
-
|
1592
|
+
EditorView5.updateListener.of((update2) => {
|
992
1593
|
if (blaster?.node !== update2.view.scrollDOM) {
|
993
1594
|
if (blaster) {
|
994
1595
|
blaster.destroy();
|
@@ -1250,11 +1851,11 @@ var random = (min, max) => {
|
|
1250
1851
|
};
|
1251
1852
|
|
1252
1853
|
// packages/ui/react-ui-editor/src/extensions/command/command.ts
|
1253
|
-
import { EditorView as
|
1854
|
+
import { EditorView as EditorView7, keymap as keymap3 } from "@codemirror/view";
|
1254
1855
|
|
1255
1856
|
// packages/ui/react-ui-editor/src/extensions/command/hint.ts
|
1256
1857
|
import { RangeSetBuilder } from "@codemirror/state";
|
1257
|
-
import { Decoration as Decoration3, EditorView as
|
1858
|
+
import { Decoration as Decoration3, EditorView as EditorView6, ViewPlugin as ViewPlugin3, WidgetType as WidgetType2 } from "@codemirror/view";
|
1258
1859
|
|
1259
1860
|
// packages/ui/react-ui-editor/src/extensions/command/state.ts
|
1260
1861
|
import { StateEffect as StateEffect2, StateField as StateField3 } from "@codemirror/state";
|
@@ -1420,7 +2021,7 @@ var hintViewPlugin = ({ onHint }) => ViewPlugin3.fromClass(class {
|
|
1420
2021
|
}
|
1421
2022
|
}, {
|
1422
2023
|
provide: (plugin) => [
|
1423
|
-
|
2024
|
+
EditorView6.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration3.none)
|
1424
2025
|
]
|
1425
2026
|
});
|
1426
2027
|
|
@@ -1431,7 +2032,7 @@ var command = (options) => {
|
|
1431
2032
|
commandState,
|
1432
2033
|
keymap3.of(commandKeyBindings),
|
1433
2034
|
hintViewPlugin(options),
|
1434
|
-
|
2035
|
+
EditorView7.focusChangeEffect.of((_, focusing) => {
|
1435
2036
|
return focusing ? closeEffect.of(null) : null;
|
1436
2037
|
})
|
1437
2038
|
];
|
@@ -1440,16 +2041,16 @@ var command = (options) => {
|
|
1440
2041
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
1441
2042
|
import { invertedEffects } from "@codemirror/commands";
|
1442
2043
|
import { StateEffect as StateEffect3, StateField as StateField4 } from "@codemirror/state";
|
1443
|
-
import { hoverTooltip, keymap as keymap5, Decoration as Decoration4, EditorView as
|
2044
|
+
import { hoverTooltip, keymap as keymap5, Decoration as Decoration4, EditorView as EditorView9, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
1444
2045
|
import sortBy from "lodash.sortby";
|
1445
|
-
import { useEffect, useMemo
|
2046
|
+
import { useEffect, useMemo as useMemo2 } from "react";
|
1446
2047
|
import { debounce as debounce2 } from "@dxos/async";
|
1447
2048
|
import { log as log4 } from "@dxos/log";
|
1448
|
-
import {
|
2049
|
+
import { isNonNullable } from "@dxos/util";
|
1449
2050
|
|
1450
2051
|
// packages/ui/react-ui-editor/src/extensions/selection.ts
|
1451
2052
|
import { Transaction } from "@codemirror/state";
|
1452
|
-
import { EditorView as
|
2053
|
+
import { EditorView as EditorView8, keymap as keymap4 } from "@codemirror/view";
|
1453
2054
|
import { debounce } from "@dxos/async";
|
1454
2055
|
import { invariant as invariant3 } from "@dxos/invariant";
|
1455
2056
|
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
@@ -1460,7 +2061,7 @@ var createEditorStateTransaction = ({ scrollTo, selection }) => {
|
|
1460
2061
|
return {
|
1461
2062
|
selection,
|
1462
2063
|
scrollIntoView: !scrollTo,
|
1463
|
-
effects: scrollTo ?
|
2064
|
+
effects: scrollTo ? EditorView8.scrollIntoView(scrollTo, {
|
1464
2065
|
yMargin: 96
|
1465
2066
|
}) : void 0,
|
1466
2067
|
annotations: Transaction.userEvent.of(stateRestoreAnnotation)
|
@@ -1502,7 +2103,7 @@ var selectionState = ({ getState, setState } = {}) => {
|
|
1502
2103
|
// setStateDebounced(id, {});
|
1503
2104
|
// },
|
1504
2105
|
// }),
|
1505
|
-
|
2106
|
+
EditorView8.updateListener.of(({ view, transactions }) => {
|
1506
2107
|
const id = view.state.facet(documentId);
|
1507
2108
|
if (!id || transactions.some((tr) => tr.isUserEvent(stateRestoreAnnotation))) {
|
1508
2109
|
return;
|
@@ -1570,7 +2171,7 @@ var commentsState = StateField4.define({
|
|
1570
2171
|
comment,
|
1571
2172
|
range
|
1572
2173
|
};
|
1573
|
-
}).filter(
|
2174
|
+
}).filter(isNonNullable);
|
1574
2175
|
return {
|
1575
2176
|
...value,
|
1576
2177
|
comments: commentStates
|
@@ -1583,7 +2184,7 @@ var commentsState = StateField4.define({
|
|
1583
2184
|
return value;
|
1584
2185
|
}
|
1585
2186
|
});
|
1586
|
-
var styles3 =
|
2187
|
+
var styles3 = EditorView9.theme({
|
1587
2188
|
".cm-comment, .cm-comment-current": {
|
1588
2189
|
margin: "0 -3px",
|
1589
2190
|
padding: "3px",
|
@@ -1603,7 +2204,7 @@ var createCommentMark = (id, isCurrent) => Decoration4.mark({
|
|
1603
2204
|
"data-comment-id": id
|
1604
2205
|
}
|
1605
2206
|
});
|
1606
|
-
var commentsDecorations =
|
2207
|
+
var commentsDecorations = EditorView9.decorations.compute([
|
1607
2208
|
commentsState
|
1608
2209
|
], (state) => {
|
1609
2210
|
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
@@ -1612,7 +2213,7 @@ var commentsDecorations = EditorView8.decorations.compute([
|
|
1612
2213
|
if (!range) {
|
1613
2214
|
log4.warn("Invalid range:", range, {
|
1614
2215
|
F: __dxlog_file7,
|
1615
|
-
L:
|
2216
|
+
L: 144,
|
1616
2217
|
S: void 0,
|
1617
2218
|
C: (f, a) => f(...a)
|
1618
2219
|
});
|
@@ -1622,11 +2223,11 @@ var commentsDecorations = EditorView8.decorations.compute([
|
|
1622
2223
|
}
|
1623
2224
|
const mark = createCommentMark(comment.comment.id, comment.comment.id === current);
|
1624
2225
|
return mark.range(range.from, range.to);
|
1625
|
-
}).filter(
|
2226
|
+
}).filter(isNonNullable);
|
1626
2227
|
return Decoration4.set(decorations);
|
1627
2228
|
});
|
1628
2229
|
var commentClickedEffect = StateEffect3.define();
|
1629
|
-
var handleCommentClick =
|
2230
|
+
var handleCommentClick = EditorView9.domEventHandlers({
|
1630
2231
|
click: (event, view) => {
|
1631
2232
|
let target = event.target;
|
1632
2233
|
const editorRoot = view.dom;
|
@@ -1665,7 +2266,7 @@ var trackPastedComments = (onUpdate) => {
|
|
1665
2266
|
}
|
1666
2267
|
};
|
1667
2268
|
return [
|
1668
|
-
|
2269
|
+
EditorView9.domEventHandlers({
|
1669
2270
|
cut: handleTrack,
|
1670
2271
|
copy: handleTrack
|
1671
2272
|
}),
|
@@ -1687,7 +2288,7 @@ var trackPastedComments = (onUpdate) => {
|
|
1687
2288
|
return effects;
|
1688
2289
|
}),
|
1689
2290
|
// Handle paste or the undo of comment deletion.
|
1690
|
-
|
2291
|
+
EditorView9.updateListener.of((update2) => {
|
1691
2292
|
const restore = [];
|
1692
2293
|
for (let i = 0; i < update2.transactions.length; i++) {
|
1693
2294
|
const tr = update2.transactions[i];
|
@@ -1746,7 +2347,7 @@ var mapTrackedComment = (comment, changes) => ({
|
|
1746
2347
|
var restoreCommentEffect = StateEffect3.define({
|
1747
2348
|
map: mapTrackedComment
|
1748
2349
|
});
|
1749
|
-
var
|
2350
|
+
var createComment2 = (view) => {
|
1750
2351
|
const options = view.state.facet(optionsFacet);
|
1751
2352
|
const { from, to } = view.state.selection.main;
|
1752
2353
|
if (from === to) {
|
@@ -1791,7 +2392,7 @@ var comments = (options = {}) => {
|
|
1791
2392
|
options.onCreate && keymap5.of([
|
1792
2393
|
{
|
1793
2394
|
key: shortcut,
|
1794
|
-
run: callbackWrapper(
|
2395
|
+
run: callbackWrapper(createComment2)
|
1795
2396
|
}
|
1796
2397
|
]),
|
1797
2398
|
//
|
@@ -1827,7 +2428,7 @@ var comments = (options = {}) => {
|
|
1827
2428
|
//
|
1828
2429
|
// Track deleted ranges and update ranges for decorations.
|
1829
2430
|
//
|
1830
|
-
|
2431
|
+
EditorView9.updateListener.of(({ view, state, changes }) => {
|
1831
2432
|
let mod = false;
|
1832
2433
|
const { comments: comments2, ...value } = state.field(commentsState);
|
1833
2434
|
changes.iterChanges((from, to, from2, to2) => {
|
@@ -1859,7 +2460,7 @@ var comments = (options = {}) => {
|
|
1859
2460
|
//
|
1860
2461
|
// Track selection/proximity.
|
1861
2462
|
//
|
1862
|
-
|
2463
|
+
EditorView9.updateListener.of(({ view, state }) => {
|
1863
2464
|
let min = Infinity;
|
1864
2465
|
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
1865
2466
|
const { head } = state.selection.main;
|
@@ -1893,7 +2494,7 @@ var comments = (options = {}) => {
|
|
1893
2494
|
}
|
1894
2495
|
}),
|
1895
2496
|
options.onUpdate && trackPastedComments(options.onUpdate)
|
1896
|
-
].filter(
|
2497
|
+
].filter(isNonNullable);
|
1897
2498
|
};
|
1898
2499
|
var scrollThreadIntoView = (view, id, center = true) => {
|
1899
2500
|
const comment = view.state.field(commentsState).comments.find((range2) => range2.comment.id === id);
|
@@ -1913,7 +2514,7 @@ var scrollThreadIntoView = (view, id, center = true) => {
|
|
1913
2514
|
anchor: range.from
|
1914
2515
|
} : void 0,
|
1915
2516
|
effects: [
|
1916
|
-
needsScroll ?
|
2517
|
+
needsScroll ? EditorView9.scrollIntoView(range.from, center ? {
|
1917
2518
|
y: "center"
|
1918
2519
|
} : void 0) : [],
|
1919
2520
|
needsSelectionUpdate ? setSelection.of({
|
@@ -1925,414 +2526,177 @@ var scrollThreadIntoView = (view, id, center = true) => {
|
|
1925
2526
|
}
|
1926
2527
|
};
|
1927
2528
|
var selectionOverlapsComment = (state) => {
|
1928
|
-
const commentState = state.field(commentsState, false);
|
1929
|
-
if (commentState === void 0) {
|
1930
|
-
return false;
|
1931
|
-
}
|
1932
|
-
const { selection } = state;
|
1933
|
-
for (const range of selection.ranges) {
|
1934
|
-
if (commentState.comments.some(({ range: commentRange }) => overlap(commentRange, range))) {
|
1935
|
-
return true;
|
1936
|
-
}
|
1937
|
-
}
|
1938
|
-
return false;
|
1939
|
-
};
|
1940
|
-
var hasActiveSelection = (state) => {
|
1941
|
-
return state.selection.ranges.some((range) => !range.empty);
|
1942
|
-
};
|
1943
|
-
var ExternalCommentSync = class {
|
1944
|
-
constructor(view, id, subscribe, getComments) {
|
1945
|
-
this.destroy = () => {
|
1946
|
-
this.unsubscribe();
|
1947
|
-
};
|
1948
|
-
const updateComments = () => {
|
1949
|
-
const comments2 = getComments();
|
1950
|
-
if (id === view.state.facet(documentId)) {
|
1951
|
-
queueMicrotask(() => view.dispatch({
|
1952
|
-
effects: setComments.of({
|
1953
|
-
id,
|
1954
|
-
comments: comments2
|
1955
|
-
})
|
1956
|
-
}));
|
1957
|
-
}
|
1958
|
-
};
|
1959
|
-
this.unsubscribe = subscribe(updateComments);
|
1960
|
-
}
|
1961
|
-
};
|
1962
|
-
var createExternalCommentSync = (id, subscribe, getComments) => ViewPlugin4.fromClass(class {
|
1963
|
-
constructor(view) {
|
1964
|
-
return new ExternalCommentSync(view, id, subscribe, getComments);
|
1965
|
-
}
|
1966
|
-
});
|
1967
|
-
var useCommentState = () => {
|
1968
|
-
|
1969
|
-
|
1970
|
-
|
1971
|
-
|
1972
|
-
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1981
|
-
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
1987
|
-
|
1988
|
-
if (id === view.state.facet(documentId)) {
|
1989
|
-
view.dispatch({
|
1990
|
-
effects: setComments.of({
|
1991
|
-
id,
|
1992
|
-
comments: comments2 ?? []
|
1993
|
-
})
|
1994
|
-
});
|
1995
|
-
}
|
1996
|
-
}
|
1997
|
-
});
|
1998
|
-
};
|
1999
|
-
var useCommentClickListener = (onCommentClick) => {
|
2000
|
-
return useMemo(() => EditorView8.updateListener.of((update2) => {
|
2001
|
-
update2.transactions.forEach((transaction) => {
|
2002
|
-
transaction.effects.forEach((effect) => {
|
2003
|
-
if (effect.is(commentClickedEffect)) {
|
2004
|
-
onCommentClick(effect.value);
|
2005
|
-
}
|
2006
|
-
});
|
2007
|
-
});
|
2008
|
-
}), [
|
2009
|
-
onCommentClick
|
2010
|
-
]);
|
2011
|
-
};
|
2012
|
-
|
2013
|
-
// packages/ui/react-ui-editor/src/extensions/debug.ts
|
2014
|
-
import { syntaxTree } from "@codemirror/language";
|
2015
|
-
import { StateField as StateField5 } from "@codemirror/state";
|
2016
|
-
var debugNodeLogger = (log8 = console.log) => {
|
2017
|
-
const logTokens = (state) => syntaxTree(state).iterate({
|
2018
|
-
enter: (node) => log8(node.type)
|
2019
|
-
});
|
2020
|
-
return StateField5.define({
|
2021
|
-
create: (state) => logTokens(state),
|
2022
|
-
update: (_, tr) => logTokens(tr.state)
|
2023
|
-
});
|
2024
|
-
};
|
2025
|
-
|
2026
|
-
// packages/ui/react-ui-editor/src/extensions/dnd.ts
|
2027
|
-
import { dropCursor, EditorView as EditorView9 } from "@codemirror/view";
|
2028
|
-
var styles4 = EditorView9.theme({
|
2029
|
-
".cm-dropCursor": {
|
2030
|
-
borderLeft: "2px solid var(--dx-accentText)",
|
2031
|
-
color: "var(--dx-accentText)",
|
2032
|
-
padding: "0 4px"
|
2033
|
-
},
|
2034
|
-
".cm-dropCursor:after": {
|
2035
|
-
content: '"\u2190"'
|
2036
|
-
}
|
2037
|
-
});
|
2038
|
-
var dropFile = (options = {}) => {
|
2039
|
-
return [
|
2040
|
-
styles4,
|
2041
|
-
dropCursor(),
|
2042
|
-
EditorView9.domEventHandlers({
|
2043
|
-
drop: (event, view) => {
|
2044
|
-
event.preventDefault();
|
2045
|
-
const files = event.dataTransfer?.files;
|
2046
|
-
const pos = view.posAtCoords(event);
|
2047
|
-
if (files?.length && pos !== null) {
|
2048
|
-
view.dispatch({
|
2049
|
-
selection: {
|
2050
|
-
anchor: pos
|
2051
|
-
}
|
2052
|
-
});
|
2053
|
-
options.onDrop?.(view, {
|
2054
|
-
files
|
2055
|
-
});
|
2056
|
-
}
|
2057
|
-
}
|
2058
|
-
})
|
2059
|
-
];
|
2060
|
-
};
|
2061
|
-
|
2062
|
-
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2063
|
-
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
2064
|
-
import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
2065
|
-
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
2066
|
-
import { searchKeymap } from "@codemirror/search";
|
2067
|
-
import { EditorState } from "@codemirror/state";
|
2068
|
-
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
2069
|
-
import { EditorView as EditorView11, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap6, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
|
2070
|
-
import defaultsDeep2 from "lodash.defaultsdeep";
|
2071
|
-
import merge from "lodash.merge";
|
2072
|
-
import { generateName } from "@dxos/display-name";
|
2073
|
-
import { log as log5 } from "@dxos/log";
|
2074
|
-
import { hueTokens } from "@dxos/react-ui-theme";
|
2075
|
-
import { hexToHue, isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
2076
|
-
|
2077
|
-
// packages/ui/react-ui-editor/src/extensions/focus.ts
|
2078
|
-
import { StateEffect as StateEffect4, StateField as StateField6 } from "@codemirror/state";
|
2079
|
-
import { EditorView as EditorView10 } from "@codemirror/view";
|
2080
|
-
var focusEffect = StateEffect4.define();
|
2081
|
-
var focusField = StateField6.define({
|
2082
|
-
create: () => false,
|
2083
|
-
update: (value, tr) => {
|
2084
|
-
for (const effect of tr.effects) {
|
2085
|
-
if (effect.is(focusEffect)) {
|
2086
|
-
return effect.value;
|
2087
|
-
}
|
2088
|
-
}
|
2089
|
-
return value;
|
2090
|
-
}
|
2091
|
-
});
|
2092
|
-
var focus = [
|
2093
|
-
focusField,
|
2094
|
-
EditorView10.domEventHandlers({
|
2095
|
-
focus: (event, view) => {
|
2096
|
-
setTimeout(() => view.dispatch({
|
2097
|
-
effects: focusEffect.of(true)
|
2098
|
-
}));
|
2099
|
-
},
|
2100
|
-
blur: (event, view) => {
|
2101
|
-
setTimeout(() => view.dispatch({
|
2102
|
-
effects: focusEffect.of(false)
|
2103
|
-
}));
|
2104
|
-
}
|
2105
|
-
})
|
2106
|
-
];
|
2107
|
-
|
2108
|
-
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
2109
|
-
import { mx } from "@dxos/react-ui-theme";
|
2110
|
-
var headings = {
|
2111
|
-
1: "text-4xl",
|
2112
|
-
2: "text-3xl",
|
2113
|
-
3: "text-2xl",
|
2114
|
-
4: "text-xl",
|
2115
|
-
5: "text-lg",
|
2116
|
-
6: "text-md"
|
2117
|
-
};
|
2118
|
-
var theme = {
|
2119
|
-
code: "font-mono !no-underline text-neutral-700 dark:text-neutral-300",
|
2120
|
-
codeMark: "font-mono text-primary-500",
|
2121
|
-
mark: "opacity-50",
|
2122
|
-
heading: (level) => {
|
2123
|
-
return mx(headings[level], "dark:text-primary-400");
|
2124
|
-
}
|
2125
|
-
};
|
2126
|
-
|
2127
|
-
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
2128
|
-
import get from "lodash.get";
|
2129
|
-
import { tokens } from "@dxos/react-ui-theme";
|
2130
|
-
var getToken = (path, defaultValue) => {
|
2131
|
-
const value = get(tokens, path, defaultValue);
|
2132
|
-
return value?.toString() ?? "";
|
2133
|
-
};
|
2134
|
-
var fontBody = getToken("fontFamily.body");
|
2135
|
-
var fontMono = getToken("fontFamily.mono");
|
2136
|
-
|
2137
|
-
// packages/ui/react-ui-editor/src/styles/theme.ts
|
2138
|
-
var defaultTheme = {
|
2139
|
-
"&": {},
|
2140
|
-
"&.cm-focused": {
|
2141
|
-
outline: "none"
|
2142
|
-
},
|
2143
|
-
/**
|
2144
|
-
* Scroller
|
2145
|
-
*/
|
2146
|
-
".cm-scroller": {
|
2147
|
-
overflowY: "auto"
|
2148
|
-
},
|
2149
|
-
/**
|
2150
|
-
* Content
|
2151
|
-
* NOTE: Apply margins to content so that scrollbar is at the edge of the container.
|
2152
|
-
*/
|
2153
|
-
".cm-content": {
|
2154
|
-
padding: "unset",
|
2155
|
-
fontFamily: fontBody,
|
2156
|
-
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
2157
|
-
fontSize: "16px",
|
2158
|
-
lineHeight: 1.5,
|
2159
|
-
color: "unset"
|
2160
|
-
},
|
2161
|
-
/**
|
2162
|
-
* Gutters
|
2163
|
-
* NOTE: Gutters should have the same top margin as the content.
|
2164
|
-
* NOTE: They can't be transparent since the content needs to scroll below.
|
2165
|
-
*/
|
2166
|
-
".cm-gutters": {
|
2167
|
-
background: "var(--surface-bg)",
|
2168
|
-
borderRight: "none"
|
2169
|
-
},
|
2170
|
-
".cm-gutter": {},
|
2171
|
-
".cm-gutter.cm-lineNumbers .cm-gutterElement": {
|
2172
|
-
minWidth: "40px",
|
2173
|
-
alignContent: "center"
|
2174
|
-
},
|
2175
|
-
/**
|
2176
|
-
* Height is set to match the corresponding line.
|
2177
|
-
*/
|
2178
|
-
".cm-gutterElement": {
|
2179
|
-
alignItems: "center",
|
2180
|
-
fontSize: "16px"
|
2181
|
-
},
|
2182
|
-
/**
|
2183
|
-
* Line.
|
2184
|
-
*/
|
2185
|
-
".cm-line": {
|
2186
|
-
paddingInline: 0
|
2187
|
-
},
|
2188
|
-
".cm-activeLine": {
|
2189
|
-
background: "var(--dx-cmActiveLine)"
|
2190
|
-
},
|
2191
|
-
/**
|
2192
|
-
* Cursor (layer).
|
2193
|
-
*/
|
2194
|
-
".cm-cursor, .cm-dropCursor": {
|
2195
|
-
borderLeft: "2px solid var(--dx-cmCursor)"
|
2196
|
-
},
|
2197
|
-
".cm-placeholder": {
|
2198
|
-
color: "var(--dx-subdued)"
|
2199
|
-
},
|
2200
|
-
/**
|
2201
|
-
* Selection (layer).
|
2202
|
-
*/
|
2203
|
-
".cm-selectionBackground": {
|
2204
|
-
background: "var(--dx-cmSelection)"
|
2205
|
-
},
|
2206
|
-
/**
|
2207
|
-
* Search.
|
2208
|
-
* NOTE: Matches comment.
|
2209
|
-
*/
|
2210
|
-
".cm-searchMatch": {
|
2211
|
-
margin: "0 -3px",
|
2212
|
-
padding: "3px",
|
2213
|
-
borderRadius: "3px",
|
2214
|
-
background: "var(--dx-cmHighlightSurface)",
|
2215
|
-
color: "var(--dx-cmHighlight)"
|
2216
|
-
},
|
2217
|
-
".cm-searchMatch-selected": {
|
2218
|
-
textDecoration: "underline"
|
2219
|
-
},
|
2220
|
-
/**
|
2221
|
-
* Link.
|
2222
|
-
*/
|
2223
|
-
".cm-link": {
|
2224
|
-
textDecorationLine: "underline",
|
2225
|
-
textDecorationThickness: "1px",
|
2226
|
-
textUnderlineOffset: "2px",
|
2227
|
-
borderRadius: ".125rem"
|
2228
|
-
},
|
2229
|
-
".cm-link > span": {
|
2230
|
-
color: "var(--dx-accentText)"
|
2231
|
-
},
|
2232
|
-
/**
|
2233
|
-
* Tooltip.
|
2234
|
-
*/
|
2235
|
-
".cm-tooltip": {
|
2236
|
-
background: "var(--dx-base)"
|
2237
|
-
},
|
2238
|
-
".cm-tooltip-below": {},
|
2239
|
-
/**
|
2240
|
-
* Autocomplete.
|
2241
|
-
* https://github.com/codemirror/autocomplete/blob/main/src/completion.ts
|
2242
|
-
*/
|
2243
|
-
".cm-tooltip.cm-tooltip-autocomplete": {
|
2244
|
-
marginTop: "4px",
|
2245
|
-
marginLeft: "-3px"
|
2246
|
-
},
|
2247
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul": {
|
2248
|
-
maxHeight: "20em"
|
2249
|
-
},
|
2250
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > li": {},
|
2251
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {},
|
2252
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
|
2253
|
-
paddingLeft: "4px !important",
|
2254
|
-
borderBottom: "none !important",
|
2255
|
-
color: "var(--dx-accentText)"
|
2256
|
-
},
|
2257
|
-
".cm-tooltip.cm-completionInfo": {
|
2258
|
-
width: "360px !important",
|
2259
|
-
margin: "-10px 1px 0 1px",
|
2260
|
-
padding: "8px !important",
|
2261
|
-
borderColor: "var(--dx-separator)"
|
2262
|
-
},
|
2263
|
-
".cm-completionIcon": {
|
2264
|
-
display: "none"
|
2265
|
-
},
|
2266
|
-
".cm-completionLabel": {
|
2267
|
-
fontFamily: fontBody
|
2268
|
-
},
|
2269
|
-
".cm-completionMatchedText": {
|
2270
|
-
textDecoration: "none !important",
|
2271
|
-
opacity: 0.5
|
2272
|
-
},
|
2273
|
-
/**
|
2274
|
-
* Panels
|
2275
|
-
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
2276
|
-
*
|
2277
|
-
* Find/replace panel.
|
2278
|
-
* <div class="cm-announced">...</div>
|
2279
|
-
* <div class="cm-scroller">...</div>
|
2280
|
-
* <div class="cm-panels cm-panels-bottom">
|
2281
|
-
* <div class="cm-search cm-panel">
|
2282
|
-
* <input class="cm-textfield" />
|
2283
|
-
* <button class="cm-button">...</button>
|
2284
|
-
* <label><input type="checkbox" />...</label>
|
2285
|
-
* </div>
|
2286
|
-
* </div
|
2287
|
-
*/
|
2288
|
-
// TODO(burdon): Implement custom panel (with icon buttons).
|
2289
|
-
".cm-panels": {},
|
2290
|
-
".cm-panel": {
|
2291
|
-
fontFamily: fontBody,
|
2292
|
-
backgroundColor: "var(--surface-bg)"
|
2293
|
-
},
|
2294
|
-
".cm-panel input, .cm-panel button, .cm-panel label": {
|
2295
|
-
color: "var(--dx-subdued)",
|
2296
|
-
fontFamily: fontBody,
|
2297
|
-
fontSize: "14px",
|
2298
|
-
all: "unset",
|
2299
|
-
margin: "3px !important",
|
2300
|
-
padding: "2px 6px !important",
|
2301
|
-
outline: "1px solid transparent"
|
2302
|
-
},
|
2303
|
-
".cm-panel input, .cm-panel button": {
|
2304
|
-
backgroundColor: "var(--dx-input)"
|
2305
|
-
},
|
2306
|
-
".cm-panel input:focus, .cm-panel button:focus": {
|
2307
|
-
outline: "1px solid var(--dx-accentFocusIndicator)"
|
2308
|
-
},
|
2309
|
-
".cm-panel label": {
|
2310
|
-
display: "inline-flex",
|
2311
|
-
alignItems: "center",
|
2312
|
-
cursor: "pointer"
|
2313
|
-
},
|
2314
|
-
".cm-panel input.cm-textfield": {},
|
2315
|
-
".cm-panel input[type=checkbox]": {
|
2316
|
-
width: "8px",
|
2317
|
-
height: "8px",
|
2318
|
-
marginRight: "6px !important",
|
2319
|
-
padding: "2px !important",
|
2320
|
-
color: "var(--dx-accentFocusIndicator)"
|
2321
|
-
},
|
2322
|
-
".cm-panel button": {
|
2323
|
-
"&:hover": {
|
2324
|
-
backgroundColor: "var(--dx-accentSurfaceHover) !important"
|
2325
|
-
},
|
2326
|
-
"&:active": {
|
2327
|
-
backgroundColor: "var(--dx-accentSurfaceHover)"
|
2529
|
+
const commentState = state.field(commentsState, false);
|
2530
|
+
if (commentState === void 0) {
|
2531
|
+
return false;
|
2532
|
+
}
|
2533
|
+
const { selection } = state;
|
2534
|
+
for (const range of selection.ranges) {
|
2535
|
+
if (commentState.comments.some(({ range: commentRange }) => overlap(commentRange, range))) {
|
2536
|
+
return true;
|
2537
|
+
}
|
2538
|
+
}
|
2539
|
+
return false;
|
2540
|
+
};
|
2541
|
+
var hasActiveSelection = (state) => {
|
2542
|
+
return state.selection.ranges.some((range) => !range.empty);
|
2543
|
+
};
|
2544
|
+
var ExternalCommentSync = class {
|
2545
|
+
constructor(view, id, subscribe, getComments) {
|
2546
|
+
this.destroy = () => {
|
2547
|
+
this.unsubscribe();
|
2548
|
+
};
|
2549
|
+
const updateComments = () => {
|
2550
|
+
const comments2 = getComments();
|
2551
|
+
if (id === view.state.facet(documentId)) {
|
2552
|
+
queueMicrotask(() => view.dispatch({
|
2553
|
+
effects: setComments.of({
|
2554
|
+
id,
|
2555
|
+
comments: comments2
|
2556
|
+
})
|
2557
|
+
}));
|
2558
|
+
}
|
2559
|
+
};
|
2560
|
+
this.unsubscribe = subscribe(updateComments);
|
2561
|
+
}
|
2562
|
+
};
|
2563
|
+
var createExternalCommentSync = (id, subscribe, getComments) => ViewPlugin4.fromClass(class {
|
2564
|
+
constructor(view) {
|
2565
|
+
return new ExternalCommentSync(view, id, subscribe, getComments);
|
2566
|
+
}
|
2567
|
+
});
|
2568
|
+
var useCommentState = (state) => {
|
2569
|
+
return useMemo2(() => EditorView9.updateListener.of((update2) => {
|
2570
|
+
if (update2.docChanged || update2.selectionSet) {
|
2571
|
+
state.comment = selectionOverlapsComment(update2.state);
|
2572
|
+
state.selection = hasActiveSelection(update2.state);
|
2573
|
+
}
|
2574
|
+
}), [
|
2575
|
+
state
|
2576
|
+
]);
|
2577
|
+
};
|
2578
|
+
var useComments = (view, id, comments2) => {
|
2579
|
+
useEffect(() => {
|
2580
|
+
if (view) {
|
2581
|
+
if (id === view.state.facet(documentId)) {
|
2582
|
+
view.dispatch({
|
2583
|
+
effects: setComments.of({
|
2584
|
+
id,
|
2585
|
+
comments: comments2 ?? []
|
2586
|
+
})
|
2587
|
+
});
|
2588
|
+
}
|
2328
2589
|
}
|
2590
|
+
});
|
2591
|
+
};
|
2592
|
+
var useCommentClickListener = (onCommentClick) => {
|
2593
|
+
return useMemo2(() => EditorView9.updateListener.of((update2) => {
|
2594
|
+
update2.transactions.forEach((transaction) => {
|
2595
|
+
transaction.effects.forEach((effect) => {
|
2596
|
+
if (effect.is(commentClickedEffect)) {
|
2597
|
+
onCommentClick(effect.value);
|
2598
|
+
}
|
2599
|
+
});
|
2600
|
+
});
|
2601
|
+
}), [
|
2602
|
+
onCommentClick
|
2603
|
+
]);
|
2604
|
+
};
|
2605
|
+
|
2606
|
+
// packages/ui/react-ui-editor/src/extensions/debug.ts
|
2607
|
+
import { syntaxTree } from "@codemirror/language";
|
2608
|
+
import { StateField as StateField5 } from "@codemirror/state";
|
2609
|
+
var debugNodeLogger = (log8 = console.log) => {
|
2610
|
+
const logTokens = (state) => syntaxTree(state).iterate({
|
2611
|
+
enter: (node) => log8(node.type)
|
2612
|
+
});
|
2613
|
+
return StateField5.define({
|
2614
|
+
create: (state) => logTokens(state),
|
2615
|
+
update: (_, tr) => logTokens(tr.state)
|
2616
|
+
});
|
2617
|
+
};
|
2618
|
+
|
2619
|
+
// packages/ui/react-ui-editor/src/extensions/dnd.ts
|
2620
|
+
import { dropCursor, EditorView as EditorView10 } from "@codemirror/view";
|
2621
|
+
var styles4 = EditorView10.theme({
|
2622
|
+
".cm-dropCursor": {
|
2623
|
+
borderLeft: "2px solid var(--dx-accentText)",
|
2624
|
+
color: "var(--dx-accentText)",
|
2625
|
+
padding: "0 4px"
|
2329
2626
|
},
|
2330
|
-
".cm-
|
2331
|
-
|
2332
|
-
borderTop: "1px solid var(--dx-separator)"
|
2627
|
+
".cm-dropCursor:after": {
|
2628
|
+
content: '"\u2190"'
|
2333
2629
|
}
|
2630
|
+
});
|
2631
|
+
var dropFile = (options = {}) => {
|
2632
|
+
return [
|
2633
|
+
styles4,
|
2634
|
+
dropCursor(),
|
2635
|
+
EditorView10.domEventHandlers({
|
2636
|
+
drop: (event, view) => {
|
2637
|
+
event.preventDefault();
|
2638
|
+
const files = event.dataTransfer?.files;
|
2639
|
+
const pos = view.posAtCoords(event);
|
2640
|
+
if (files?.length && pos !== null) {
|
2641
|
+
view.dispatch({
|
2642
|
+
selection: {
|
2643
|
+
anchor: pos
|
2644
|
+
}
|
2645
|
+
});
|
2646
|
+
options.onDrop?.(view, {
|
2647
|
+
files
|
2648
|
+
});
|
2649
|
+
}
|
2650
|
+
}
|
2651
|
+
})
|
2652
|
+
];
|
2334
2653
|
};
|
2335
2654
|
|
2655
|
+
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2656
|
+
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
2657
|
+
import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
2658
|
+
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
2659
|
+
import { searchKeymap } from "@codemirror/search";
|
2660
|
+
import { EditorState } from "@codemirror/state";
|
2661
|
+
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
2662
|
+
import { EditorView as EditorView12, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap6, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
|
2663
|
+
import defaultsDeep2 from "lodash.defaultsdeep";
|
2664
|
+
import merge from "lodash.merge";
|
2665
|
+
import { generateName } from "@dxos/display-name";
|
2666
|
+
import { log as log5 } from "@dxos/log";
|
2667
|
+
import { hexToHue, isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
2668
|
+
|
2669
|
+
// packages/ui/react-ui-editor/src/extensions/focus.ts
|
2670
|
+
import { StateEffect as StateEffect4, StateField as StateField6 } from "@codemirror/state";
|
2671
|
+
import { EditorView as EditorView11 } from "@codemirror/view";
|
2672
|
+
var focusEffect = StateEffect4.define();
|
2673
|
+
var focusField = StateField6.define({
|
2674
|
+
create: () => false,
|
2675
|
+
update: (value, tr) => {
|
2676
|
+
for (const effect of tr.effects) {
|
2677
|
+
if (effect.is(focusEffect)) {
|
2678
|
+
return effect.value;
|
2679
|
+
}
|
2680
|
+
}
|
2681
|
+
return value;
|
2682
|
+
}
|
2683
|
+
});
|
2684
|
+
var focus = [
|
2685
|
+
focusField,
|
2686
|
+
EditorView11.domEventHandlers({
|
2687
|
+
focus: (event, view) => {
|
2688
|
+
setTimeout(() => view.dispatch({
|
2689
|
+
effects: focusEffect.of(true)
|
2690
|
+
}));
|
2691
|
+
},
|
2692
|
+
blur: (event, view) => {
|
2693
|
+
setTimeout(() => view.dispatch({
|
2694
|
+
effects: focusEffect.of(false)
|
2695
|
+
}));
|
2696
|
+
}
|
2697
|
+
})
|
2698
|
+
];
|
2699
|
+
|
2336
2700
|
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2337
2701
|
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
|
2338
2702
|
var preventNewline = EditorState.transactionFilter.of((tr) => tr.newDoc.lines > 1 ? [] : tr);
|
@@ -2358,7 +2722,7 @@ var createBasicExtensions = (_props) => {
|
|
2358
2722
|
const props = defaultsDeep2({}, _props, defaultBasicOptions);
|
2359
2723
|
return [
|
2360
2724
|
// NOTE: Doesn't catch errors in keymap functions.
|
2361
|
-
|
2725
|
+
EditorView12.exceptionSink.of((err) => {
|
2362
2726
|
log5.catch(err, void 0, {
|
2363
2727
|
F: __dxlog_file8,
|
2364
2728
|
L: 96,
|
@@ -2377,11 +2741,11 @@ var createBasicExtensions = (_props) => {
|
|
2377
2741
|
props.highlightActiveLine && highlightActiveLine(),
|
2378
2742
|
props.history && history(),
|
2379
2743
|
props.lineNumbers && lineNumbers(),
|
2380
|
-
props.lineWrapping &&
|
2744
|
+
props.lineWrapping && EditorView12.lineWrapping,
|
2381
2745
|
props.placeholder && placeholder(props.placeholder),
|
2382
2746
|
props.readonly && [
|
2383
2747
|
EditorState.readOnly.of(true),
|
2384
|
-
|
2748
|
+
EditorView12.editable.of(false)
|
2385
2749
|
],
|
2386
2750
|
props.scrollPastEnd && scrollPastEnd(),
|
2387
2751
|
props.tabSize && EditorState.tabSize.of(props.tabSize),
|
@@ -2398,7 +2762,14 @@ var createBasicExtensions = (_props) => {
|
|
2398
2762
|
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
2399
2763
|
...props.history ? historyKeymap : [],
|
2400
2764
|
// https://codemirror.net/docs/ref/#search.searchKeymap
|
2401
|
-
...props.search ? searchKeymap : []
|
2765
|
+
...props.search ? searchKeymap : [],
|
2766
|
+
// Disable bindings that conflict with system shortcuts.
|
2767
|
+
// TODO(burdon): Catalog global shortcuts.
|
2768
|
+
{
|
2769
|
+
key: "Mod-Shift-k",
|
2770
|
+
preventDefault: true,
|
2771
|
+
run: () => true
|
2772
|
+
}
|
2402
2773
|
].filter(isNotFalsy3))
|
2403
2774
|
].filter(isNotFalsy3);
|
2404
2775
|
};
|
@@ -2410,14 +2781,14 @@ var defaultThemeSlots = {
|
|
2410
2781
|
var createThemeExtensions = ({ themeMode, styles: styles5, syntaxHighlighting: _syntaxHighlighting, slots: _slots } = {}) => {
|
2411
2782
|
const slots = defaultsDeep2({}, _slots, defaultThemeSlots);
|
2412
2783
|
return [
|
2413
|
-
|
2414
|
-
|
2784
|
+
EditorView12.darkTheme.of(themeMode === "dark"),
|
2785
|
+
EditorView12.baseTheme(styles5 ? merge({}, defaultTheme, styles5) : defaultTheme),
|
2415
2786
|
// https://github.com/codemirror/theme-one-dark
|
2416
2787
|
_syntaxHighlighting && (themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)),
|
2417
|
-
slots.editor?.className &&
|
2788
|
+
slots.editor?.className && EditorView12.editorAttributes.of({
|
2418
2789
|
class: slots.editor.className
|
2419
2790
|
}),
|
2420
|
-
slots.content?.className &&
|
2791
|
+
slots.content?.className && EditorView12.contentAttributes.of({
|
2421
2792
|
class: slots.content.className
|
2422
2793
|
})
|
2423
2794
|
].filter(isNotFalsy3);
|
@@ -2429,15 +2800,15 @@ var createDataExtensions = ({ id, text, space, identity }) => {
|
|
2429
2800
|
}
|
2430
2801
|
if (space && identity) {
|
2431
2802
|
const peerId = identity?.identityKey.toHex();
|
2432
|
-
const
|
2803
|
+
const hue = identity?.profile?.data?.hue ?? hexToHue(peerId ?? "0");
|
2433
2804
|
extensions.push(awareness(new SpaceAwarenessProvider({
|
2434
2805
|
space,
|
2435
2806
|
channel: `awareness.${id}`,
|
2436
2807
|
peerId: identity.identityKey.toHex(),
|
2437
2808
|
info: {
|
2438
2809
|
displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
|
2439
|
-
darkColor:
|
2440
|
-
lightColor:
|
2810
|
+
darkColor: `var(--dx-${hue}Cursor)`,
|
2811
|
+
lightColor: `var(--dx-${hue}Cursor)`
|
2441
2812
|
}
|
2442
2813
|
})));
|
2443
2814
|
}
|
@@ -2446,8 +2817,8 @@ var createDataExtensions = ({ id, text, space, identity }) => {
|
|
2446
2817
|
|
2447
2818
|
// packages/ui/react-ui-editor/src/extensions/folding.tsx
|
2448
2819
|
import { codeFolding, foldGutter } from "@codemirror/language";
|
2449
|
-
import { EditorView as
|
2450
|
-
import
|
2820
|
+
import { EditorView as EditorView13 } from "@codemirror/view";
|
2821
|
+
import React3 from "react";
|
2451
2822
|
import { Icon } from "@dxos/react-ui";
|
2452
2823
|
var folding = (_props = {}) => [
|
2453
2824
|
codeFolding({
|
@@ -2460,7 +2831,7 @@ var folding = (_props = {}) => [
|
|
2460
2831
|
const el = createElement("div", {
|
2461
2832
|
className: "flex h-full items-center"
|
2462
2833
|
});
|
2463
|
-
return renderRoot(el, /* @__PURE__ */
|
2834
|
+
return renderRoot(el, /* @__PURE__ */ React3.createElement(Icon, {
|
2464
2835
|
icon: "ph--caret-right--regular",
|
2465
2836
|
size: 3,
|
2466
2837
|
classNames: [
|
@@ -2470,7 +2841,7 @@ var folding = (_props = {}) => [
|
|
2470
2841
|
}));
|
2471
2842
|
}
|
2472
2843
|
}),
|
2473
|
-
|
2844
|
+
EditorView13.theme({
|
2474
2845
|
".cm-foldGutter": {
|
2475
2846
|
opacity: 0.3,
|
2476
2847
|
transition: "opacity 0.3s",
|
@@ -2483,14 +2854,14 @@ var folding = (_props = {}) => [
|
|
2483
2854
|
];
|
2484
2855
|
|
2485
2856
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
2486
|
-
import { EditorView as
|
2857
|
+
import { EditorView as EditorView14 } from "@codemirror/view";
|
2487
2858
|
var listener = ({ onFocus, onChange }) => {
|
2488
2859
|
const extensions = [];
|
2489
|
-
onFocus && extensions.push(
|
2860
|
+
onFocus && extensions.push(EditorView14.focusChangeEffect.of((_, focusing) => {
|
2490
2861
|
onFocus(focusing);
|
2491
2862
|
return null;
|
2492
2863
|
}));
|
2493
|
-
onChange && extensions.push(
|
2864
|
+
onChange && extensions.push(EditorView14.updateListener.of((update2) => {
|
2494
2865
|
onChange(update2.state.doc.toString(), update2.state.facet(documentId));
|
2495
2866
|
}));
|
2496
2867
|
return extensions;
|
@@ -2500,8 +2871,8 @@ var listener = ({ onFocus, onChange }) => {
|
|
2500
2871
|
import { snippet } from "@codemirror/autocomplete";
|
2501
2872
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
2502
2873
|
import { EditorSelection } from "@codemirror/state";
|
2503
|
-
import { EditorView as
|
2504
|
-
import { useMemo as
|
2874
|
+
import { EditorView as EditorView15, keymap as keymap7 } from "@codemirror/view";
|
2875
|
+
import { useMemo as useMemo3 } from "react";
|
2505
2876
|
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;
|
2506
2877
|
var Inline;
|
2507
2878
|
(function(Inline2) {
|
@@ -3588,65 +3959,56 @@ var getFormatting = (state) => {
|
|
3588
3959
|
listStyle: listStyle || null
|
3589
3960
|
};
|
3590
3961
|
};
|
3591
|
-
var useFormattingState = () => {
|
3592
|
-
|
3593
|
-
const observer = useMemo2(() => EditorView14.updateListener.of((update2) => {
|
3962
|
+
var useFormattingState = (state) => {
|
3963
|
+
return useMemo3(() => EditorView15.updateListener.of((update2) => {
|
3594
3964
|
if (update2.docChanged || update2.selectionSet) {
|
3595
|
-
|
3596
|
-
|
3597
|
-
if (!prevState || !formattingEquals(prevState, newState)) {
|
3598
|
-
return newState;
|
3599
|
-
}
|
3600
|
-
return prevState;
|
3965
|
+
Object.entries(getFormatting(update2.state)).forEach(([key, active]) => {
|
3966
|
+
state[key] = active;
|
3601
3967
|
});
|
3602
3968
|
}
|
3603
3969
|
}), []);
|
3604
|
-
return [
|
3605
|
-
state,
|
3606
|
-
observer
|
3607
|
-
];
|
3608
3970
|
};
|
3609
3971
|
|
3610
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/
|
3611
|
-
var
|
3972
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/editorAction.ts
|
3973
|
+
var processEditorPayload = (view, { type, data }) => {
|
3612
3974
|
let inlineType, listType;
|
3613
|
-
switch (
|
3975
|
+
switch (type) {
|
3614
3976
|
case "heading":
|
3615
|
-
setHeading(parseInt(
|
3977
|
+
setHeading(parseInt(data))(view);
|
3616
3978
|
break;
|
3617
3979
|
case "strong":
|
3618
3980
|
case "emphasis":
|
3619
3981
|
case "strikethrough":
|
3620
3982
|
case "code":
|
3621
|
-
inlineType =
|
3622
|
-
(typeof
|
3983
|
+
inlineType = type === "strong" ? Inline.Strong : type === "emphasis" ? Inline.Emphasis : type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
3984
|
+
(typeof data === "boolean" ? setStyle(inlineType, data) : toggleStyle(inlineType))(view);
|
3623
3985
|
break;
|
3624
3986
|
case "list-ordered":
|
3625
3987
|
case "list-bullet":
|
3626
3988
|
case "list-task":
|
3627
|
-
listType =
|
3628
|
-
(
|
3989
|
+
listType = type === "list-ordered" ? List.Ordered : type === "list-bullet" ? List.Bullet : List.Task;
|
3990
|
+
(data === false ? removeList(listType) : data === true ? addList(listType) : toggleList(listType))(view);
|
3629
3991
|
break;
|
3630
3992
|
case "blockquote":
|
3631
|
-
(
|
3993
|
+
(data === false ? removeBlockquote : data === true ? addBlockquote : toggleBlockquote)(view);
|
3632
3994
|
break;
|
3633
3995
|
case "codeblock":
|
3634
|
-
(
|
3996
|
+
(data === false ? removeCodeblock : addCodeblock)(view);
|
3635
3997
|
break;
|
3636
3998
|
case "table":
|
3637
3999
|
insertTable(view);
|
3638
4000
|
break;
|
3639
4001
|
case "link":
|
3640
|
-
(
|
4002
|
+
(data === false ? removeLink : addLink())(view);
|
3641
4003
|
break;
|
3642
4004
|
case "image":
|
3643
4005
|
addLink({
|
3644
|
-
url:
|
4006
|
+
url: data,
|
3645
4007
|
image: true
|
3646
4008
|
})(view);
|
3647
4009
|
break;
|
3648
4010
|
case "comment":
|
3649
|
-
|
4011
|
+
createComment2(view);
|
3650
4012
|
break;
|
3651
4013
|
}
|
3652
4014
|
requestAnimationFrame(() => {
|
@@ -3910,9 +4272,9 @@ var convertTreeToJson = (state) => {
|
|
3910
4272
|
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
3911
4273
|
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
3912
4274
|
import { RangeSetBuilder as RangeSetBuilder3, StateEffect as StateEffect5 } from "@codemirror/state";
|
3913
|
-
import { EditorView as
|
4275
|
+
import { EditorView as EditorView19, Decoration as Decoration7, WidgetType as WidgetType5, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
3914
4276
|
import { invariant as invariant4 } from "@dxos/invariant";
|
3915
|
-
import { mx as
|
4277
|
+
import { mx as mx4 } from "@dxos/react-ui-theme";
|
3916
4278
|
|
3917
4279
|
// packages/ui/react-ui-editor/src/extensions/markdown/changes.ts
|
3918
4280
|
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
@@ -4061,7 +4423,7 @@ var getValidUrl = (str) => {
|
|
4061
4423
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
4062
4424
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
4063
4425
|
import { StateField as StateField8 } from "@codemirror/state";
|
4064
|
-
import { Decoration as Decoration5, EditorView as
|
4426
|
+
import { Decoration as Decoration5, EditorView as EditorView16, WidgetType as WidgetType3 } from "@codemirror/view";
|
4065
4427
|
var image = (_options = {}) => {
|
4066
4428
|
return [
|
4067
4429
|
StateField8.define({
|
@@ -4089,7 +4451,7 @@ var image = (_options = {}) => {
|
|
4089
4451
|
add: buildDecorations(from, to, tr.state)
|
4090
4452
|
});
|
4091
4453
|
},
|
4092
|
-
provide: (field) =>
|
4454
|
+
provide: (field) => EditorView16.decorations.from(field)
|
4093
4455
|
})
|
4094
4456
|
];
|
4095
4457
|
};
|
@@ -4149,10 +4511,10 @@ var ImageWidget = class extends WidgetType3 {
|
|
4149
4511
|
};
|
4150
4512
|
|
4151
4513
|
// packages/ui/react-ui-editor/src/extensions/markdown/styles.ts
|
4152
|
-
import { EditorView as
|
4514
|
+
import { EditorView as EditorView17 } from "@codemirror/view";
|
4153
4515
|
var bulletListIndentationWidth = 24;
|
4154
4516
|
var orderedListIndentationWidth = 36;
|
4155
|
-
var formattingStyles =
|
4517
|
+
var formattingStyles = EditorView17.theme({
|
4156
4518
|
/**
|
4157
4519
|
* Horizontal rule.
|
4158
4520
|
*/
|
@@ -4246,18 +4608,39 @@ var formattingStyles = EditorView16.theme({
|
|
4246
4608
|
height: "auto",
|
4247
4609
|
borderTop: "0.5rem solid transparent",
|
4248
4610
|
borderBottom: "0.5rem solid transparent"
|
4611
|
+
},
|
4612
|
+
".cm-image-with-loader": {
|
4613
|
+
display: "block",
|
4614
|
+
opacity: "0",
|
4615
|
+
transitionDuration: "350ms",
|
4616
|
+
transitionProperty: "opacity"
|
4617
|
+
},
|
4618
|
+
".cm-image-with-loader.cm-loaded-image": {
|
4619
|
+
opacity: "1"
|
4620
|
+
},
|
4621
|
+
".cm-image-wrapper": {
|
4622
|
+
"grid-template-columns": "1fr",
|
4623
|
+
display: "grid",
|
4624
|
+
margin: "0.5rem 0",
|
4625
|
+
overflow: "hidden",
|
4626
|
+
transitionDuration: "350ms",
|
4627
|
+
transitionProperty: "height",
|
4628
|
+
"& > *": {
|
4629
|
+
"grid-row-start": 1,
|
4630
|
+
"grid-column-start": 1
|
4631
|
+
}
|
4249
4632
|
}
|
4250
4633
|
});
|
4251
4634
|
|
4252
4635
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
4253
4636
|
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
4254
4637
|
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField9 } from "@codemirror/state";
|
4255
|
-
import { Decoration as Decoration6, EditorView as
|
4638
|
+
import { Decoration as Decoration6, EditorView as EditorView18, WidgetType as WidgetType4 } from "@codemirror/view";
|
4256
4639
|
var table = (options = {}) => {
|
4257
4640
|
return StateField9.define({
|
4258
4641
|
create: (state) => update(state, options),
|
4259
4642
|
update: (_, tr) => update(tr.state, options),
|
4260
|
-
provide: (field) =>
|
4643
|
+
provide: (field) => EditorView18.decorations.from(field)
|
4261
4644
|
});
|
4262
4645
|
};
|
4263
4646
|
var update = (state, _options) => {
|
@@ -4389,7 +4772,7 @@ var CheckboxWidget = class extends WidgetType5 {
|
|
4389
4772
|
}
|
4390
4773
|
toDOM(view) {
|
4391
4774
|
const input = document.createElement("input");
|
4392
|
-
input.className = "cm-task-checkbox
|
4775
|
+
input.className = "cm-task-checkbox dx-checkbox";
|
4393
4776
|
input.type = "checkbox";
|
4394
4777
|
input.tabIndex = -1;
|
4395
4778
|
input.checked = this._checked;
|
@@ -4441,16 +4824,16 @@ var TextWidget = class extends WidgetType5 {
|
|
4441
4824
|
};
|
4442
4825
|
var hide = Decoration7.replace({});
|
4443
4826
|
var blockQuote = Decoration7.line({
|
4444
|
-
class:
|
4827
|
+
class: mx4("cm-blockquote")
|
4445
4828
|
});
|
4446
4829
|
var fencedCodeLine = Decoration7.line({
|
4447
|
-
class:
|
4830
|
+
class: mx4("cm-code cm-codeblock-line")
|
4448
4831
|
});
|
4449
4832
|
var fencedCodeLineFirst = Decoration7.line({
|
4450
|
-
class:
|
4833
|
+
class: mx4("cm-code cm-codeblock-line", "cm-codeblock-first")
|
4451
4834
|
});
|
4452
4835
|
var fencedCodeLineLast = Decoration7.line({
|
4453
|
-
class:
|
4836
|
+
class: mx4("cm-code cm-codeblock-line", "cm-codeblock-last")
|
4454
4837
|
});
|
4455
4838
|
var commentBlockLine = fencedCodeLine;
|
4456
4839
|
var commentBlockLineFirst = fencedCodeLineFirst;
|
@@ -4791,9 +5174,9 @@ var decorateMarkdown = (options = {}) => {
|
|
4791
5174
|
}
|
4792
5175
|
}, {
|
4793
5176
|
provide: (plugin) => [
|
4794
|
-
|
4795
|
-
|
4796
|
-
|
5177
|
+
EditorView19.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
5178
|
+
EditorView19.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
5179
|
+
EditorView19.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration7.none)
|
4797
5180
|
]
|
4798
5181
|
}),
|
4799
5182
|
image(),
|
@@ -4980,428 +5363,29 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
4980
5363
|
];
|
4981
5364
|
};
|
4982
5365
|
|
4983
|
-
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
4984
|
-
var iconStyles = getSize(5);
|
4985
|
-
var buttonStyles = "min-bs-0 p-1";
|
4986
|
-
var tooltipProps = {
|
4987
|
-
side: "top",
|
4988
|
-
classNames: "z-10"
|
4989
|
-
};
|
4990
|
-
var ToolbarSeparator = () => /* @__PURE__ */ React3.createElement("div", {
|
4991
|
-
role: "separator",
|
4992
|
-
className: "grow"
|
4993
|
-
});
|
4994
|
-
var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
|
4995
|
-
var ToolbarRoot = ({ children, onAction, classNames, state }) => {
|
4996
|
-
return /* @__PURE__ */ React3.createElement(ToolbarContextProvider, {
|
4997
|
-
onAction,
|
4998
|
-
state
|
4999
|
-
}, /* @__PURE__ */ React3.createElement(ElevationProvider, {
|
5000
|
-
elevation: "positioned"
|
5001
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.Root, {
|
5002
|
-
classNames: [
|
5003
|
-
"p-1 is-full shrink-0 overflow-x-auto overflow-y-hidden",
|
5004
|
-
classNames
|
5005
|
-
],
|
5006
|
-
style: {
|
5007
|
-
contain: "layout"
|
5008
|
-
}
|
5009
|
-
}, children)));
|
5010
|
-
};
|
5011
|
-
var ToolbarToggleButton = ({ Icon: Icon2, children, ...props }) => {
|
5012
|
-
return /* @__PURE__ */ React3.createElement(Tooltip.Root, null, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
|
5013
|
-
asChild: true
|
5014
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroupItem, {
|
5015
|
-
variant: "ghost",
|
5016
|
-
...props,
|
5017
|
-
classNames: buttonStyles
|
5018
|
-
}, /* @__PURE__ */ React3.createElement(Icon2, {
|
5019
|
-
className: iconStyles
|
5020
|
-
}), /* @__PURE__ */ React3.createElement("span", {
|
5021
|
-
className: "sr-only"
|
5022
|
-
}, children))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
|
5023
|
-
};
|
5024
|
-
var ToolbarButton = ({ Icon: Icon2, children, ...props }) => {
|
5025
|
-
return /* @__PURE__ */ React3.createElement(Tooltip.Root, null, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
|
5026
|
-
asChild: true
|
5027
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
|
5028
|
-
variant: "ghost",
|
5029
|
-
...props,
|
5030
|
-
classNames: buttonStyles
|
5031
|
-
}, /* @__PURE__ */ React3.createElement(Icon2, {
|
5032
|
-
className: iconStyles
|
5033
|
-
}), /* @__PURE__ */ React3.createElement("span", {
|
5034
|
-
className: "sr-only"
|
5035
|
-
}, children))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
|
5036
|
-
};
|
5037
|
-
var HeadingIcons = {
|
5038
|
-
"0": Paragraph,
|
5039
|
-
"1": TextHOne,
|
5040
|
-
"2": TextHTwo,
|
5041
|
-
"3": TextHThree,
|
5042
|
-
"4": TextHFour,
|
5043
|
-
"5": TextHFive,
|
5044
|
-
"6": TextHSix
|
5045
|
-
};
|
5046
|
-
var MarkdownHeading = () => {
|
5047
|
-
const { t } = useTranslation(translationKey);
|
5048
|
-
const { onAction, state } = useToolbarContext("MarkdownFormatting");
|
5049
|
-
const blockType = state ? state.blockType : "paragraph";
|
5050
|
-
const header = blockType && /heading(\d)/.exec(blockType);
|
5051
|
-
const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : void 0;
|
5052
|
-
const HeadingIcon = HeadingIcons[value ?? "0"];
|
5053
|
-
const suppressNextTooltip = useRef(false);
|
5054
|
-
const [tooltipOpen, setTooltipOpen] = useState3(false);
|
5055
|
-
const [selectOpen, setSelectOpen] = useState3(false);
|
5056
|
-
return /* @__PURE__ */ React3.createElement(Tooltip.Root, {
|
5057
|
-
open: tooltipOpen,
|
5058
|
-
onOpenChange: (nextOpen) => {
|
5059
|
-
if (nextOpen && suppressNextTooltip.current) {
|
5060
|
-
suppressNextTooltip.current = false;
|
5061
|
-
return setTooltipOpen(false);
|
5062
|
-
} else {
|
5063
|
-
return setTooltipOpen(nextOpen);
|
5064
|
-
}
|
5065
|
-
}
|
5066
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
|
5067
|
-
open: selectOpen,
|
5068
|
-
onOpenChange: (nextOpen) => {
|
5069
|
-
if (!nextOpen) {
|
5070
|
-
suppressNextTooltip.current = true;
|
5071
|
-
}
|
5072
|
-
return setSelectOpen(nextOpen);
|
5073
|
-
}
|
5074
|
-
}, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
|
5075
|
-
asChild: true
|
5076
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
|
5077
|
-
asChild: true
|
5078
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
|
5079
|
-
asChild: true
|
5080
|
-
}, /* @__PURE__ */ React3.createElement(Button, {
|
5081
|
-
variant: "ghost",
|
5082
|
-
classNames: buttonStyles,
|
5083
|
-
disabled: value === null
|
5084
|
-
}, /* @__PURE__ */ React3.createElement("span", {
|
5085
|
-
className: "sr-only"
|
5086
|
-
}, t("heading label")), /* @__PURE__ */ React3.createElement(HeadingIcon, {
|
5087
|
-
className: iconStyles
|
5088
|
-
}), /* @__PURE__ */ React3.createElement(CaretDown, null))))), /* @__PURE__ */ React3.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
|
5089
|
-
classNames: "is-min md:is-min",
|
5090
|
-
onCloseAutoFocus: (e) => e.preventDefault()
|
5091
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Viewport, null, Object.keys(HeadingIcons).map((level) => {
|
5092
|
-
const Icon2 = HeadingIcons[level];
|
5093
|
-
return /* @__PURE__ */ React3.createElement(DropdownMenu.CheckboxItem, {
|
5094
|
-
key: level,
|
5095
|
-
checked: value === level,
|
5096
|
-
onClick: () => onAction?.({
|
5097
|
-
type: "heading",
|
5098
|
-
data: level
|
5099
|
-
})
|
5100
|
-
}, /* @__PURE__ */ React3.createElement("span", {
|
5101
|
-
className: "sr-only"
|
5102
|
-
}, t("heading level label", {
|
5103
|
-
count: parseInt(level)
|
5104
|
-
})), /* @__PURE__ */ React3.createElement(Icon2, {
|
5105
|
-
className: iconStyles
|
5106
|
-
}), /* @__PURE__ */ React3.createElement(DropdownMenu.ItemIndicator, null, /* @__PURE__ */ React3.createElement(Check, null)));
|
5107
|
-
})), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null)))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, t("heading label"), /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
|
5108
|
-
};
|
5109
|
-
var markdownStyles = [
|
5110
|
-
{
|
5111
|
-
type: "strong",
|
5112
|
-
Icon: TextB,
|
5113
|
-
getState: (state) => !!state?.strong
|
5114
|
-
},
|
5115
|
-
{
|
5116
|
-
type: "emphasis",
|
5117
|
-
Icon: TextItalic,
|
5118
|
-
getState: (state) => !!state?.emphasis
|
5119
|
-
},
|
5120
|
-
{
|
5121
|
-
type: "strikethrough",
|
5122
|
-
Icon: TextStrikethrough,
|
5123
|
-
getState: (state) => !!state?.strikethrough
|
5124
|
-
},
|
5125
|
-
{
|
5126
|
-
type: "code",
|
5127
|
-
Icon: Code,
|
5128
|
-
getState: (state) => !!state?.code
|
5129
|
-
},
|
5130
|
-
{
|
5131
|
-
type: "link",
|
5132
|
-
Icon: Link,
|
5133
|
-
getState: (state) => !!state?.link
|
5134
|
-
}
|
5135
|
-
];
|
5136
|
-
var MarkdownStyles = () => {
|
5137
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
5138
|
-
const { t } = useTranslation(translationKey);
|
5139
|
-
return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
|
5140
|
-
type: "multiple",
|
5141
|
-
value: markdownStyles.filter(({ getState }) => state && getState(state)).map(({ type }) => type)
|
5142
|
-
}, markdownStyles.map(({ type, getState, Icon: Icon2 }) => /* @__PURE__ */ React3.createElement(ToolbarToggleButton, {
|
5143
|
-
key: type,
|
5144
|
-
value: type,
|
5145
|
-
Icon: Icon2,
|
5146
|
-
disabled: state?.blockType === "codeblock",
|
5147
|
-
onClick: state ? () => onAction?.({
|
5148
|
-
type,
|
5149
|
-
data: !getState(state)
|
5150
|
-
}) : void 0
|
5151
|
-
}, t(`${type} label`))));
|
5152
|
-
};
|
5153
|
-
var markdownLists = [
|
5154
|
-
{
|
5155
|
-
type: "list-bullet",
|
5156
|
-
Icon: ListBullets,
|
5157
|
-
getState: (state) => state.listStyle === "bullet"
|
5158
|
-
},
|
5159
|
-
{
|
5160
|
-
type: "list-ordered",
|
5161
|
-
Icon: ListNumbers,
|
5162
|
-
getState: (state) => state.listStyle === "ordered"
|
5163
|
-
},
|
5164
|
-
{
|
5165
|
-
type: "list-task",
|
5166
|
-
Icon: ListChecks,
|
5167
|
-
getState: (state) => state.listStyle === "task"
|
5168
|
-
}
|
5169
|
-
];
|
5170
|
-
var MarkdownLists = () => {
|
5171
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
5172
|
-
const { t } = useTranslation(translationKey);
|
5173
|
-
return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
|
5174
|
-
type: "single",
|
5175
|
-
value: state?.listStyle ? `list-${state.listStyle}` : ""
|
5176
|
-
}, markdownLists.map(({ type, getState, Icon: Icon2 }) => /* @__PURE__ */ React3.createElement(ToolbarToggleButton, {
|
5177
|
-
key: type,
|
5178
|
-
value: type,
|
5179
|
-
Icon: Icon2,
|
5180
|
-
onClick: state ? () => onAction?.({
|
5181
|
-
type,
|
5182
|
-
data: !getState(state)
|
5183
|
-
}) : void 0
|
5184
|
-
}, t(`${type} label`))));
|
5185
|
-
};
|
5186
|
-
var markdownBlocks = [
|
5187
|
-
{
|
5188
|
-
type: "blockquote",
|
5189
|
-
Icon: Quotes,
|
5190
|
-
getState: (state) => !!state?.blockQuote
|
5191
|
-
},
|
5192
|
-
{
|
5193
|
-
type: "codeblock",
|
5194
|
-
Icon: CodeBlock,
|
5195
|
-
getState: (state) => state.blockType === "codeblock"
|
5196
|
-
},
|
5197
|
-
{
|
5198
|
-
type: "table",
|
5199
|
-
Icon: Table2,
|
5200
|
-
getState: (state) => state.blockType === "tablecell",
|
5201
|
-
disabled: (state) => !state.blankLine
|
5202
|
-
}
|
5203
|
-
];
|
5204
|
-
var MarkdownBlocks = () => {
|
5205
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
5206
|
-
const { t } = useTranslation(translationKey);
|
5207
|
-
const value = markdownBlocks.find(({ getState }) => state && getState(state));
|
5208
|
-
return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
|
5209
|
-
type: "single",
|
5210
|
-
value: value?.type ?? ""
|
5211
|
-
}, markdownBlocks.map(({ type, disabled, getState, Icon: Icon2 }) => /* @__PURE__ */ React3.createElement(ToolbarToggleButton, {
|
5212
|
-
key: type,
|
5213
|
-
value: type,
|
5214
|
-
Icon: Icon2,
|
5215
|
-
disabled: !state || disabled?.(state),
|
5216
|
-
onClick: state ? () => onAction?.({
|
5217
|
-
type,
|
5218
|
-
data: !getState(state)
|
5219
|
-
}) : void 0
|
5220
|
-
}, t(`${type} label`))));
|
5221
|
-
};
|
5222
|
-
var MarkdownStandard = () => /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(MarkdownHeading, null), /* @__PURE__ */ React3.createElement(MarkdownStyles, null), /* @__PURE__ */ React3.createElement(MarkdownLists, null), /* @__PURE__ */ React3.createElement(MarkdownBlocks, null));
|
5223
|
-
var MarkdownCustom = ({ onUpload } = {}) => {
|
5224
|
-
const { onAction } = useToolbarContext("MarkdownStyles");
|
5225
|
-
const { t } = useTranslation(translationKey);
|
5226
|
-
const { acceptedFiles, getInputProps, open } = useDropzone({
|
5227
|
-
multiple: false,
|
5228
|
-
noDrag: true,
|
5229
|
-
accept: {
|
5230
|
-
"image/*": [
|
5231
|
-
".jpg",
|
5232
|
-
".jpeg",
|
5233
|
-
".png",
|
5234
|
-
".gif"
|
5235
|
-
]
|
5236
|
-
}
|
5237
|
-
});
|
5238
|
-
useEffect2(() => {
|
5239
|
-
if (onUpload && acceptedFiles.length) {
|
5240
|
-
requestAnimationFrame(async () => {
|
5241
|
-
const f = acceptedFiles[0];
|
5242
|
-
const file = new File([
|
5243
|
-
f
|
5244
|
-
], f.name, {
|
5245
|
-
type: f.type,
|
5246
|
-
lastModified: f.lastModified
|
5247
|
-
});
|
5248
|
-
const info = await onUpload(file);
|
5249
|
-
if (info) {
|
5250
|
-
onAction?.({
|
5251
|
-
type: "image",
|
5252
|
-
data: info.url
|
5253
|
-
});
|
5254
|
-
}
|
5255
|
-
});
|
5256
|
-
}
|
5257
|
-
}, [
|
5258
|
-
acceptedFiles
|
5259
|
-
]);
|
5260
|
-
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("input", getInputProps()), /* @__PURE__ */ React3.createElement(ToolbarButton, {
|
5261
|
-
value: "image",
|
5262
|
-
Icon: Image,
|
5263
|
-
onClick: () => open()
|
5264
|
-
}, t("image label")));
|
5265
|
-
};
|
5266
|
-
var ViewModeIcons = {
|
5267
|
-
preview: PencilSimple,
|
5268
|
-
readonly: PencilSimpleSlash,
|
5269
|
-
source: MarkdownLogo
|
5270
|
-
};
|
5271
|
-
var MarkdownView = ({ mode }) => {
|
5272
|
-
const { t } = useTranslation(translationKey);
|
5273
|
-
const { onAction } = useToolbarContext("ViewMode");
|
5274
|
-
const ModeIcon = ViewModeIcons[mode ?? "preview"];
|
5275
|
-
const suppressNextTooltip = useRef(false);
|
5276
|
-
const [tooltipOpen, setTooltipOpen] = useState3(false);
|
5277
|
-
const [selectOpen, setSelectOpen] = useState3(false);
|
5278
|
-
return /* @__PURE__ */ React3.createElement(Tooltip.Root, {
|
5279
|
-
open: tooltipOpen,
|
5280
|
-
onOpenChange: (nextOpen) => {
|
5281
|
-
if (nextOpen && suppressNextTooltip.current) {
|
5282
|
-
suppressNextTooltip.current = false;
|
5283
|
-
return setTooltipOpen(false);
|
5284
|
-
} else {
|
5285
|
-
return setTooltipOpen(nextOpen);
|
5286
|
-
}
|
5287
|
-
}
|
5288
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
|
5289
|
-
open: selectOpen,
|
5290
|
-
onOpenChange: (nextOpen) => {
|
5291
|
-
if (!nextOpen) {
|
5292
|
-
suppressNextTooltip.current = true;
|
5293
|
-
}
|
5294
|
-
return setSelectOpen(nextOpen);
|
5295
|
-
}
|
5296
|
-
}, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
|
5297
|
-
asChild: true
|
5298
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
|
5299
|
-
asChild: true
|
5300
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
|
5301
|
-
asChild: true
|
5302
|
-
}, /* @__PURE__ */ React3.createElement(Button, {
|
5303
|
-
variant: "ghost",
|
5304
|
-
classNames: buttonStyles
|
5305
|
-
}, /* @__PURE__ */ React3.createElement("span", {
|
5306
|
-
className: "sr-only"
|
5307
|
-
}, t("mode label")), /* @__PURE__ */ React3.createElement(ModeIcon, {
|
5308
|
-
className: iconStyles
|
5309
|
-
}), /* @__PURE__ */ React3.createElement(CaretDown, null))))), /* @__PURE__ */ React3.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
|
5310
|
-
classNames: "is-min md:is-min",
|
5311
|
-
onCloseAutoFocus: (e) => e.preventDefault()
|
5312
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Viewport, null, EditorViewModes.map((value) => {
|
5313
|
-
const Icon2 = ViewModeIcons[value];
|
5314
|
-
return /* @__PURE__ */ React3.createElement(DropdownMenu.CheckboxItem, {
|
5315
|
-
key: value,
|
5316
|
-
checked: value === mode,
|
5317
|
-
onClick: () => onAction?.({
|
5318
|
-
type: "view-mode",
|
5319
|
-
data: value
|
5320
|
-
})
|
5321
|
-
}, /* @__PURE__ */ React3.createElement(Icon2, {
|
5322
|
-
className: iconStyles
|
5323
|
-
}), /* @__PURE__ */ React3.createElement("span", {
|
5324
|
-
className: "whitespace-nowrap grow"
|
5325
|
-
}, t(`${value} mode label`)), /* @__PURE__ */ React3.createElement(Check, {
|
5326
|
-
className: value === mode ? "visible" : "invisible"
|
5327
|
-
}));
|
5328
|
-
})), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null)))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, t("view mode label"), /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
|
5329
|
-
};
|
5330
|
-
var MarkdownActions = () => {
|
5331
|
-
const { onAction, state } = useToolbarContext("MarkdownActions");
|
5332
|
-
const { t } = useTranslation(translationKey);
|
5333
|
-
let commentToolTipKey = "comment label";
|
5334
|
-
if (state?.comment) {
|
5335
|
-
commentToolTipKey = "selection overlaps existing comment label";
|
5336
|
-
} else if (state?.selection === false) {
|
5337
|
-
commentToolTipKey = "select text to comment label";
|
5338
|
-
}
|
5339
|
-
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(ToolbarButton, {
|
5340
|
-
value: "search",
|
5341
|
-
Icon: MagnifyingGlass,
|
5342
|
-
onClick: () => onAction?.({
|
5343
|
-
type: "search"
|
5344
|
-
})
|
5345
|
-
}, t("search label")), /* @__PURE__ */ React3.createElement(ToolbarButton, {
|
5346
|
-
value: "comment",
|
5347
|
-
Icon: ChatText,
|
5348
|
-
"data-testid": "editor.toolbar.comment",
|
5349
|
-
onClick: () => onAction?.({
|
5350
|
-
type: "comment"
|
5351
|
-
}),
|
5352
|
-
disabled: !state || state.comment || !state.selection
|
5353
|
-
}, t(commentToolTipKey)));
|
5354
|
-
};
|
5355
|
-
var Toolbar = {
|
5356
|
-
Root: ToolbarRoot,
|
5357
|
-
Button: ToolbarToggleButton,
|
5358
|
-
Separator: ToolbarSeparator,
|
5359
|
-
View: MarkdownView,
|
5360
|
-
Markdown: MarkdownStandard,
|
5361
|
-
Custom: MarkdownCustom,
|
5362
|
-
Actions: MarkdownActions
|
5363
|
-
};
|
5364
|
-
|
5365
|
-
// packages/ui/react-ui-editor/src/defaults.ts
|
5366
|
-
import { EditorView as EditorView19 } from "@codemirror/view";
|
5367
|
-
import { mx as mx3 } from "@dxos/react-ui-theme";
|
5368
|
-
var margin = "!mt-[1rem]";
|
5369
|
-
var editorContent = mx3(margin, "!mli-auto w-full max-w-[min(50rem,100%-2rem)]");
|
5370
|
-
var editorFullWidth = mx3(margin);
|
5371
|
-
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
5372
|
-
var editorGutter = EditorView19.theme({
|
5373
|
-
// Match margin from content.
|
5374
|
-
".cm-gutters": {
|
5375
|
-
marginTop: "16px",
|
5376
|
-
paddingRight: "1rem"
|
5377
|
-
}
|
5378
|
-
});
|
5379
|
-
var editorMonospace = EditorView19.theme({
|
5380
|
-
".cm-content": {
|
5381
|
-
fontFamily: fontMono
|
5382
|
-
}
|
5383
|
-
});
|
5384
|
-
|
5385
5366
|
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
5367
|
+
import { useCallback as useCallback2 } from "react";
|
5386
5368
|
var useActionHandler = (view) => {
|
5387
|
-
return (action) => view &&
|
5369
|
+
return useCallback2((action) => view && processEditorPayload(view, action.properties), [
|
5370
|
+
view
|
5371
|
+
]);
|
5388
5372
|
};
|
5389
5373
|
|
5390
5374
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
5391
5375
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
5392
5376
|
import { EditorView as EditorView20 } from "@codemirror/view";
|
5393
5377
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
5394
|
-
import { useCallback, useEffect as
|
5378
|
+
import { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo4, useRef, useState } from "react";
|
5395
5379
|
import { log as log7 } from "@dxos/log";
|
5396
5380
|
import { getProviderValue, isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
5397
5381
|
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
5398
5382
|
var instanceCount = 0;
|
5399
5383
|
var useTextEditor = (props = {}, deps = []) => {
|
5400
|
-
const { id, initialValue, extensions, autoFocus, scrollTo, selection, moveToEndOfLine, debug } =
|
5401
|
-
const [instanceId] =
|
5402
|
-
const [view, setView] =
|
5403
|
-
const parentRef =
|
5404
|
-
|
5384
|
+
const { id, initialValue, extensions, autoFocus, scrollTo, selection, moveToEndOfLine, debug } = useMemo4(() => getProviderValue(props), deps ?? []);
|
5385
|
+
const [instanceId] = useState(() => `text-editor-${++instanceCount}`);
|
5386
|
+
const [view, setView] = useState();
|
5387
|
+
const parentRef = useRef(null);
|
5388
|
+
useEffect2(() => {
|
5405
5389
|
let view2;
|
5406
5390
|
if (parentRef.current) {
|
5407
5391
|
log7("create", {
|
@@ -5475,7 +5459,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5475
5459
|
view2?.destroy();
|
5476
5460
|
};
|
5477
5461
|
}, deps);
|
5478
|
-
|
5462
|
+
useEffect2(() => {
|
5479
5463
|
if (view) {
|
5480
5464
|
if (scrollTo || selection) {
|
5481
5465
|
if (selection && selection.anchor > view.state.doc.length) {
|
@@ -5502,7 +5486,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5502
5486
|
scrollTo,
|
5503
5487
|
selection
|
5504
5488
|
]);
|
5505
|
-
|
5489
|
+
useEffect2(() => {
|
5506
5490
|
if (view && autoFocus) {
|
5507
5491
|
view.focus();
|
5508
5492
|
}
|
@@ -5516,7 +5500,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5516
5500
|
Escape: view?.state.facet(editorInputMode).noTabster
|
5517
5501
|
}
|
5518
5502
|
});
|
5519
|
-
const handleKeyUp =
|
5503
|
+
const handleKeyUp = useCallback3((event) => {
|
5520
5504
|
const { key, target, currentTarget } = event;
|
5521
5505
|
if (target === currentTarget) {
|
5522
5506
|
switch (key) {
|
@@ -5545,6 +5529,7 @@ export {
|
|
5545
5529
|
EditorInputMode,
|
5546
5530
|
EditorInputModes,
|
5547
5531
|
EditorState3 as EditorState,
|
5532
|
+
EditorToolbar,
|
5548
5533
|
EditorView21 as EditorView,
|
5549
5534
|
EditorViewMode,
|
5550
5535
|
EditorViewModes,
|
@@ -5554,7 +5539,6 @@ export {
|
|
5554
5539
|
RemoteSelectionsDecorator,
|
5555
5540
|
SpaceAwarenessProvider,
|
5556
5541
|
TextKind,
|
5557
|
-
Toolbar,
|
5558
5542
|
addBlockquote,
|
5559
5543
|
addCodeblock,
|
5560
5544
|
addLink,
|
@@ -5573,8 +5557,10 @@ export {
|
|
5573
5557
|
commentsState,
|
5574
5558
|
convertTreeToJson,
|
5575
5559
|
createBasicExtensions,
|
5576
|
-
createComment,
|
5560
|
+
createComment2 as createComment,
|
5577
5561
|
createDataExtensions,
|
5562
|
+
createEditorAction,
|
5563
|
+
createEditorActionGroup,
|
5578
5564
|
createEditorStateStore,
|
5579
5565
|
createEditorStateTransaction,
|
5580
5566
|
createElement,
|
@@ -5613,7 +5599,7 @@ export {
|
|
5613
5599
|
mention,
|
5614
5600
|
overlap,
|
5615
5601
|
preventNewline,
|
5616
|
-
|
5602
|
+
processEditorPayload,
|
5617
5603
|
removeBlockquote,
|
5618
5604
|
removeCodeblock,
|
5619
5605
|
removeLink,
|
@@ -5629,6 +5615,8 @@ export {
|
|
5629
5615
|
setSelection,
|
5630
5616
|
setStyle,
|
5631
5617
|
singleValueFacet,
|
5618
|
+
stackItemContentEditorClassNames,
|
5619
|
+
stackItemContentToolbarClassNames,
|
5632
5620
|
table,
|
5633
5621
|
tags2 as tags,
|
5634
5622
|
textRange,
|
@@ -5646,9 +5634,9 @@ export {
|
|
5646
5634
|
useCommentClickListener,
|
5647
5635
|
useCommentState,
|
5648
5636
|
useComments,
|
5637
|
+
useEditorToolbarState,
|
5649
5638
|
useFormattingState,
|
5650
5639
|
useTextEditor,
|
5651
|
-
useToolbarContext,
|
5652
5640
|
wrapWithCatch
|
5653
5641
|
};
|
5654
5642
|
//# sourceMappingURL=index.mjs.map
|