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