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