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