@dxos/react-ui-editor 0.7.5-main.9d26e3a → 0.7.5-main.e9bb01b
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 +1110 -1127
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +1133 -1164
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +1110 -1127
- 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/hooks/useActionHandler.d.ts +2 -2
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/stack-item-content-class-names.d.ts +3 -0
- package/dist/types/src/styles/stack-item-content-class-names.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- 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/hooks/useActionHandler.ts +4 -4
- package/src/index.ts +4 -0
- package/src/styles/markdown.ts +1 -1
- package/src/styles/stack-item-content-class-names.ts +17 -0
- package/src/styles/theme.ts +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
@@ -41,258 +41,860 @@ import { EditorView as EditorView21, keymap as keymap11 } from "@codemirror/view
|
|
41
41
|
import { tags as tags2 } from "@lezer/highlight";
|
42
42
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
43
43
|
|
44
|
-
// packages/ui/react-ui-editor/src/components/
|
45
|
-
import
|
46
|
-
import {
|
47
|
-
import
|
48
|
-
import {
|
49
|
-
import { Button, DropdownMenu, ElevationProvider, Toolbar as NaturalToolbar, Tooltip, useTranslation } from "@dxos/react-ui";
|
50
|
-
import { getSize } from "@dxos/react-ui-theme";
|
44
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
|
45
|
+
import React, { useCallback } from "react";
|
46
|
+
import { ElevationProvider } from "@dxos/react-ui";
|
47
|
+
import { ToolbarMenu, MenuProvider, useMenuActions, createGapSeparator } from "@dxos/react-ui-menu";
|
48
|
+
import { textBlockWidth } from "@dxos/react-ui-theme";
|
51
49
|
|
52
|
-
// packages/ui/react-ui-editor/src/
|
53
|
-
import {
|
54
|
-
import {
|
55
|
-
import {
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
var
|
60
|
-
|
61
|
-
|
62
|
-
|
50
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/util.ts
|
51
|
+
import { useMemo } from "react";
|
52
|
+
import { create } from "@dxos/live-object";
|
53
|
+
import { createMenuAction, createMenuItemGroup } from "@dxos/react-ui-menu";
|
54
|
+
var useEditorToolbarState = (initialState = {}) => {
|
55
|
+
return useMemo(() => create(initialState), []);
|
56
|
+
};
|
57
|
+
var createEditorAction = (payload, icon, label = [
|
58
|
+
`${payload.type} label`,
|
59
|
+
{
|
60
|
+
ns: translationKey
|
63
61
|
}
|
62
|
+
], id = payload.type) => createMenuAction(id, {
|
63
|
+
icon,
|
64
|
+
label,
|
65
|
+
...payload
|
66
|
+
});
|
67
|
+
var createEditorActionGroup = (id, props, icon) => createMenuItemGroup(id, {
|
68
|
+
icon,
|
69
|
+
iconOnly: true,
|
70
|
+
...props
|
64
71
|
});
|
72
|
+
var editorToolbarSearch = createEditorAction({
|
73
|
+
type: "search"
|
74
|
+
}, "ph--magnifying-glass--regular");
|
65
75
|
|
66
|
-
// packages/ui/react-ui-editor/src/
|
67
|
-
var
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
};
|
72
|
-
var
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
76
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/blocks.ts
|
77
|
+
var createBlockGroupAction = (value) => createEditorActionGroup("block", {
|
78
|
+
variant: "toggleGroup",
|
79
|
+
selectCardinality: "single",
|
80
|
+
value
|
81
|
+
});
|
82
|
+
var createBlockActions = (value, blankLine) => Object.entries({
|
83
|
+
blockquote: "ph--quotes--regular",
|
84
|
+
codeblock: "ph--code-block--regular",
|
85
|
+
table: "ph--table--regular"
|
86
|
+
}).map(([type, icon]) => {
|
87
|
+
return createEditorAction({
|
88
|
+
type,
|
89
|
+
checked: type === value,
|
90
|
+
...type === "table" && {
|
91
|
+
disabled: !!blankLine
|
92
|
+
}
|
93
|
+
}, icon);
|
94
|
+
});
|
95
|
+
var createBlocks = (state) => {
|
96
|
+
const value = state?.blockQuote ? "blockquote" : state.blockType ?? "";
|
97
|
+
const blockGroupAction = createBlockGroupAction(value);
|
98
|
+
const blockActions = createBlockActions(value, state.blankLine);
|
99
|
+
return {
|
100
|
+
nodes: [
|
101
|
+
blockGroupAction,
|
102
|
+
...blockActions
|
103
|
+
],
|
104
|
+
edges: [
|
105
|
+
{
|
106
|
+
source: "root",
|
107
|
+
target: "block"
|
108
|
+
},
|
109
|
+
...blockActions.map(({ id }) => ({
|
110
|
+
source: blockGroupAction.id,
|
111
|
+
target: id
|
112
|
+
}))
|
113
|
+
]
|
114
|
+
};
|
99
115
|
};
|
100
116
|
|
101
|
-
// packages/ui/react-ui-editor/src/
|
102
|
-
|
103
|
-
var
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
117
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/comment.ts
|
118
|
+
var commentLabel = (comment, selection) => comment ? "selection overlaps existing comment label" : selection === false ? "select text to comment label" : "comment label";
|
119
|
+
var createCommentAction = (label) => createEditorAction({
|
120
|
+
type: "comment",
|
121
|
+
testId: "editor.toolbar.comment"
|
122
|
+
}, "ph--chat-text--regular", label);
|
123
|
+
var createComment = (state) => ({
|
124
|
+
nodes: [
|
125
|
+
createCommentAction([
|
126
|
+
commentLabel(state.comment, state.selection),
|
127
|
+
{
|
128
|
+
ns: translationKey
|
129
|
+
}
|
130
|
+
])
|
131
|
+
],
|
132
|
+
edges: [
|
133
|
+
{
|
134
|
+
source: "root",
|
135
|
+
target: "comment"
|
115
136
|
}
|
137
|
+
]
|
138
|
+
});
|
139
|
+
|
140
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/formatting.ts
|
141
|
+
var formats = {
|
142
|
+
strong: "ph--text-b--regular",
|
143
|
+
emphasis: "ph--text-italic--regular",
|
144
|
+
strikethrough: "ph--text-strikethrough--regular",
|
145
|
+
code: "ph--code--regular",
|
146
|
+
link: "ph--link--regular"
|
147
|
+
};
|
148
|
+
var createFormattingGroup = (formatting) => createEditorActionGroup("formatting", {
|
149
|
+
variant: "toggleGroup",
|
150
|
+
selectCardinality: "multiple",
|
151
|
+
value: Object.keys(formats).filter((key) => !!formatting[key])
|
152
|
+
});
|
153
|
+
var createFormattingActions = (formatting) => Object.entries(formats).map(([type, icon]) => createEditorAction({
|
154
|
+
type,
|
155
|
+
checked: !!formatting[type]
|
156
|
+
}, icon));
|
157
|
+
var createFormatting = (state) => {
|
158
|
+
const formattingGroupAction = createFormattingGroup(state);
|
159
|
+
const formattingActions = createFormattingActions(state);
|
160
|
+
return {
|
161
|
+
nodes: [
|
162
|
+
formattingGroupAction,
|
163
|
+
...formattingActions
|
164
|
+
],
|
165
|
+
edges: [
|
166
|
+
{
|
167
|
+
source: "root",
|
168
|
+
target: "formatting"
|
169
|
+
},
|
170
|
+
...formattingActions.map(({ id }) => ({
|
171
|
+
source: formattingGroupAction.id,
|
172
|
+
target: id
|
173
|
+
}))
|
174
|
+
]
|
116
175
|
};
|
117
176
|
};
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
177
|
+
|
178
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/headings.ts
|
179
|
+
var createHeadingGroupAction = (value) => createEditorActionGroup("heading", {
|
180
|
+
variant: "dropdownMenu",
|
181
|
+
applyActive: true,
|
182
|
+
selectCardinality: "single",
|
183
|
+
value
|
184
|
+
}, "ph--text-h--regular");
|
185
|
+
var createHeadingActions = (value) => Object.entries({
|
186
|
+
"0": "ph--paragraph--regular",
|
187
|
+
"1": "ph--text-h-one--regular",
|
188
|
+
"2": "ph--text-h-two--regular",
|
189
|
+
"3": "ph--text-h-three--regular",
|
190
|
+
"4": "ph--text-h-four--regular",
|
191
|
+
"5": "ph--text-h-five--regular",
|
192
|
+
"6": "ph--text-h-six--regular"
|
193
|
+
}).map(([levelStr, icon]) => {
|
194
|
+
const level = parseInt(levelStr);
|
195
|
+
return createEditorAction({
|
196
|
+
type: "heading",
|
197
|
+
data: level,
|
198
|
+
checked: value === levelStr
|
199
|
+
}, icon, [
|
200
|
+
"heading level label",
|
201
|
+
{
|
202
|
+
count: level,
|
203
|
+
ns: translationKey
|
204
|
+
}
|
205
|
+
], `heading--${levelStr}`);
|
206
|
+
});
|
207
|
+
var computeHeadingValue = (state) => {
|
208
|
+
const blockType = state ? state.blockType : "paragraph";
|
209
|
+
const header = blockType && /heading(\d)/.exec(blockType);
|
210
|
+
return header ? header[1] : blockType === "paragraph" || !blockType ? "0" : "";
|
129
211
|
};
|
130
|
-
var
|
131
|
-
|
132
|
-
|
212
|
+
var createHeadings = (state) => {
|
213
|
+
const headingValue = computeHeadingValue(state);
|
214
|
+
const headingGroupAction = createHeadingGroupAction(headingValue);
|
215
|
+
const headingActions = createHeadingActions(headingValue);
|
216
|
+
return {
|
217
|
+
nodes: [
|
218
|
+
headingGroupAction,
|
219
|
+
...headingActions
|
220
|
+
],
|
221
|
+
edges: [
|
222
|
+
{
|
223
|
+
source: "root",
|
224
|
+
target: "heading"
|
225
|
+
},
|
226
|
+
...headingActions.map(({ id }) => ({
|
227
|
+
source: headingGroupAction.id,
|
228
|
+
target: id
|
229
|
+
}))
|
230
|
+
]
|
231
|
+
};
|
133
232
|
};
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
233
|
+
|
234
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/lists.ts
|
235
|
+
var listStyles = {
|
236
|
+
bullet: "ph--list-bullets--regular",
|
237
|
+
ordered: "ph--list-numbers--regular",
|
238
|
+
task: "ph--list-checks--regular"
|
239
|
+
};
|
240
|
+
var createListGroupAction = (value) => createEditorActionGroup("list", {
|
241
|
+
variant: "toggleGroup",
|
242
|
+
selectCardinality: "single",
|
243
|
+
value
|
244
|
+
});
|
245
|
+
var createListActions = (value) => Object.entries(listStyles).map(([listStyle, icon]) => createEditorAction({
|
246
|
+
type: `list-${listStyle}`,
|
247
|
+
checked: value === listStyle
|
248
|
+
}, icon));
|
249
|
+
var createLists = (state) => {
|
250
|
+
const value = state.listStyle ?? "";
|
251
|
+
const listGroupAction = createListGroupAction(value);
|
252
|
+
const listActionsMap = createListActions(value);
|
253
|
+
return {
|
254
|
+
nodes: [
|
255
|
+
listGroupAction,
|
256
|
+
...listActionsMap
|
257
|
+
],
|
258
|
+
edges: [
|
259
|
+
{
|
260
|
+
source: "root",
|
261
|
+
target: "list"
|
262
|
+
},
|
263
|
+
...listActionsMap.map(({ id }) => ({
|
264
|
+
source: listGroupAction.id,
|
265
|
+
target: id
|
266
|
+
}))
|
267
|
+
]
|
268
|
+
};
|
269
|
+
};
|
270
|
+
|
271
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/viewMode.ts
|
272
|
+
var createViewModeGroupAction = (value) => createEditorActionGroup("viewMode", {
|
273
|
+
variant: "dropdownMenu",
|
274
|
+
applyActive: true,
|
275
|
+
selectCardinality: "single",
|
276
|
+
value
|
277
|
+
}, "ph--eye--regular");
|
278
|
+
var createViewModeActions = (value) => Object.entries({
|
279
|
+
preview: "ph--eye--regular",
|
280
|
+
source: "ph--pencil-simple--regular",
|
281
|
+
readonly: "ph--pencil-slash--regular"
|
282
|
+
}).map(([viewMode, icon]) => {
|
283
|
+
return createEditorAction({
|
284
|
+
type: "view-mode",
|
285
|
+
data: viewMode,
|
286
|
+
checked: viewMode === value
|
287
|
+
}, icon, [
|
288
|
+
`${viewMode} mode label`,
|
289
|
+
{
|
290
|
+
ns: translationKey
|
138
291
|
}
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
292
|
+
], `view-mode--${viewMode}`);
|
293
|
+
});
|
294
|
+
var createViewMode = (state) => {
|
295
|
+
const value = state.viewMode ?? "source";
|
296
|
+
const viewModeGroupAction = createViewModeGroupAction(value);
|
297
|
+
const viewModeActions = createViewModeActions(value);
|
298
|
+
return {
|
299
|
+
nodes: [
|
300
|
+
viewModeGroupAction,
|
301
|
+
...viewModeActions
|
302
|
+
],
|
303
|
+
edges: [
|
304
|
+
{
|
305
|
+
source: "root",
|
306
|
+
target: "viewMode"
|
307
|
+
},
|
308
|
+
...viewModeActions.map(({ id }) => ({
|
309
|
+
source: viewModeGroupAction.id,
|
310
|
+
target: id
|
311
|
+
}))
|
312
|
+
]
|
313
|
+
};
|
159
314
|
};
|
160
315
|
|
161
|
-
// packages/ui/react-ui-editor/src/
|
162
|
-
|
163
|
-
|
316
|
+
// packages/ui/react-ui-editor/src/styles/stack-item-content-class-names.ts
|
317
|
+
import { mx } from "@dxos/react-ui-theme";
|
318
|
+
var stackItemContentEditorClassNames = (role) => mx("dx-focus-ring-inset data-[toolbar=disabled]:pbs-2 attention-surface", role === "article" ? "min-bs-0" : "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-bs-24");
|
319
|
+
var stackItemContentToolbarClassNames = (role) => mx("attention-surface is-full border-be !border-separator", role === "section" && "sticky block-start-0 z-[1] -mbe-px min-is-0");
|
320
|
+
|
321
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
|
322
|
+
var createToolbar = ({ state, customActions, ...features }) => {
|
323
|
+
const nodes = [];
|
324
|
+
const edges = [];
|
325
|
+
if (features.headings ?? true) {
|
326
|
+
const headings2 = createHeadings(state);
|
327
|
+
nodes.push(...headings2.nodes);
|
328
|
+
edges.push(...headings2.edges);
|
329
|
+
}
|
330
|
+
if (features.formatting ?? true) {
|
331
|
+
const formatting = createFormatting(state);
|
332
|
+
nodes.push(...formatting.nodes);
|
333
|
+
edges.push(...formatting.edges);
|
334
|
+
}
|
335
|
+
if (features.lists ?? true) {
|
336
|
+
const lists = createLists(state);
|
337
|
+
nodes.push(...lists.nodes);
|
338
|
+
edges.push(...lists.edges);
|
339
|
+
}
|
340
|
+
if (features.blocks ?? true) {
|
341
|
+
const blocks = createBlocks(state);
|
342
|
+
nodes.push(...blocks.nodes);
|
343
|
+
edges.push(...blocks.edges);
|
344
|
+
}
|
345
|
+
if (customActions) {
|
346
|
+
const custom = customActions();
|
347
|
+
nodes.push(...custom.nodes);
|
348
|
+
edges.push(...custom.edges);
|
349
|
+
}
|
350
|
+
const editorToolbarGap = createGapSeparator();
|
351
|
+
nodes.push(...editorToolbarGap.nodes);
|
352
|
+
edges.push(...editorToolbarGap.edges);
|
353
|
+
if (features.comment ?? true) {
|
354
|
+
const comment = createComment(state);
|
355
|
+
nodes.push(...comment.nodes);
|
356
|
+
edges.push(...comment.edges);
|
357
|
+
}
|
358
|
+
if (features.search ?? true) {
|
359
|
+
nodes.push(editorToolbarSearch);
|
360
|
+
edges.push({
|
361
|
+
source: "root",
|
362
|
+
target: editorToolbarSearch.id
|
363
|
+
});
|
364
|
+
}
|
365
|
+
if (features.viewMode ?? true) {
|
366
|
+
const viewMode = createViewMode(state);
|
367
|
+
nodes.push(...viewMode.nodes);
|
368
|
+
edges.push(...viewMode.edges);
|
369
|
+
}
|
164
370
|
return {
|
165
|
-
|
166
|
-
|
167
|
-
top: rect.top,
|
168
|
-
bottom: rect.bottom
|
371
|
+
nodes,
|
372
|
+
edges
|
169
373
|
};
|
170
374
|
};
|
171
|
-
var
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
return
|
375
|
+
var useEditorToolbarActionGraph = ({ onAction, ...props }) => {
|
376
|
+
const menuCreator = useCallback(() => createToolbar(props), [
|
377
|
+
props
|
378
|
+
]);
|
379
|
+
const { resolveGroupItems } = useMenuActions(menuCreator);
|
380
|
+
return {
|
381
|
+
resolveGroupItems,
|
382
|
+
onAction
|
383
|
+
};
|
177
384
|
};
|
178
|
-
var
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
}
|
184
|
-
|
185
|
-
}
|
385
|
+
var EditorToolbar = ({ classNames, attendableId, role, ...props }) => {
|
386
|
+
const menuProps = useEditorToolbarActionGraph(props);
|
387
|
+
return /* @__PURE__ */ React.createElement("div", {
|
388
|
+
role: "none",
|
389
|
+
className: stackItemContentToolbarClassNames(role)
|
390
|
+
}, /* @__PURE__ */ React.createElement(ElevationProvider, {
|
391
|
+
elevation: role === "section" ? "positioned" : "base"
|
392
|
+
}, /* @__PURE__ */ React.createElement(MenuProvider, {
|
393
|
+
...menuProps,
|
394
|
+
attendableId
|
395
|
+
}, /* @__PURE__ */ React.createElement(ToolbarMenu, {
|
396
|
+
classNames: [
|
397
|
+
textBlockWidth,
|
398
|
+
"!bg-transparent",
|
399
|
+
classNames
|
400
|
+
]
|
401
|
+
}))));
|
186
402
|
};
|
187
403
|
|
188
|
-
// packages/ui/react-ui-editor/src/
|
189
|
-
import
|
190
|
-
import {
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
404
|
+
// packages/ui/react-ui-editor/src/defaults.ts
|
405
|
+
import { EditorView } from "@codemirror/view";
|
406
|
+
import { mx as mx3 } from "@dxos/react-ui-theme";
|
407
|
+
|
408
|
+
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
409
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
410
|
+
var headings = {
|
411
|
+
1: "text-4xl",
|
412
|
+
2: "text-3xl",
|
413
|
+
3: "text-2xl",
|
414
|
+
4: "text-xl",
|
415
|
+
5: "text-lg",
|
416
|
+
6: ""
|
417
|
+
};
|
418
|
+
var theme = {
|
419
|
+
code: "font-mono !no-underline text-neutral-700 dark:text-neutral-300",
|
420
|
+
codeMark: "font-mono text-primary-500",
|
421
|
+
mark: "opacity-50",
|
422
|
+
heading: (level) => {
|
423
|
+
return mx2(headings[level], "dark:text-primary-400");
|
202
424
|
}
|
203
|
-
return el;
|
204
425
|
};
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
426
|
+
|
427
|
+
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
428
|
+
import get from "lodash.get";
|
429
|
+
import { tokens } from "@dxos/react-ui-theme";
|
430
|
+
var getToken = (path, defaultValue) => {
|
431
|
+
const value = get(tokens, path, defaultValue);
|
432
|
+
return value?.toString() ?? "";
|
210
433
|
};
|
434
|
+
var fontBody = getToken("fontFamily.body");
|
435
|
+
var fontMono = getToken("fontFamily.mono");
|
211
436
|
|
212
|
-
// packages/ui/react-ui-editor/src/
|
213
|
-
var
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
}
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
437
|
+
// packages/ui/react-ui-editor/src/styles/theme.ts
|
438
|
+
var defaultTheme = {
|
439
|
+
"&": {},
|
440
|
+
"&.cm-focused": {
|
441
|
+
outline: "none"
|
442
|
+
},
|
443
|
+
/**
|
444
|
+
* Scroller
|
445
|
+
*/
|
446
|
+
".cm-scroller": {
|
447
|
+
overflowY: "auto"
|
448
|
+
},
|
449
|
+
/**
|
450
|
+
* Content
|
451
|
+
* NOTE: Apply margins to content so that scrollbar is at the edge of the container.
|
452
|
+
*/
|
453
|
+
".cm-content": {
|
454
|
+
padding: "unset",
|
455
|
+
fontFamily: fontBody,
|
456
|
+
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
457
|
+
fontSize: "16px",
|
458
|
+
lineHeight: 1.5,
|
459
|
+
color: "unset"
|
460
|
+
},
|
461
|
+
/**
|
462
|
+
* Gutters
|
463
|
+
* NOTE: Gutters should have the same top margin as the content.
|
464
|
+
* 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)"
|
245
628
|
}
|
246
|
-
}
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
], (state) => {
|
252
|
-
const annotations2 = state.field(annotationsState);
|
253
|
-
const decorations = annotations2.map((annotation) => {
|
254
|
-
const range = Cursor.getRangeFromCursor(state, annotation.cursor);
|
255
|
-
return range && annotationMark.range(range.from, range.to);
|
256
|
-
}).filter(isNotFalsy);
|
257
|
-
return Decoration.set(decorations);
|
258
|
-
}),
|
259
|
-
styles
|
260
|
-
];
|
629
|
+
},
|
630
|
+
".cm-panel.cm-search": {
|
631
|
+
padding: "4px",
|
632
|
+
borderTop: "1px solid var(--dx-separator)"
|
633
|
+
}
|
261
634
|
};
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
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
|
267
651
|
}
|
268
652
|
});
|
269
653
|
|
270
|
-
// packages/ui/react-ui-editor/src/extensions/
|
271
|
-
import {
|
272
|
-
import {
|
273
|
-
import {
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
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) {
|
296
898
|
return null;
|
297
899
|
}
|
298
900
|
return {
|
@@ -308,7 +910,7 @@ var autocomplete = ({ debug, activateOnTyping, override, onSearch } = {}) => {
|
|
308
910
|
|
309
911
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
310
912
|
import { StateField as StateField2 } from "@codemirror/state";
|
311
|
-
import { EditorView as
|
913
|
+
import { EditorView as EditorView3, ViewPlugin } from "@codemirror/view";
|
312
914
|
import { next as A3 } from "@dxos/automerge/automerge";
|
313
915
|
|
314
916
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
@@ -592,7 +1194,7 @@ var automerge = (accessor) => {
|
|
592
1194
|
}
|
593
1195
|
}),
|
594
1196
|
// Reconcile local updates.
|
595
|
-
|
1197
|
+
EditorView3.updateListener.of(({ view, changes }) => {
|
596
1198
|
if (!changes.empty) {
|
597
1199
|
syncer.reconcile(view, true);
|
598
1200
|
}
|
@@ -602,7 +1204,7 @@ var automerge = (accessor) => {
|
|
602
1204
|
|
603
1205
|
// packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts
|
604
1206
|
import { Annotation as Annotation2, RangeSet } from "@codemirror/state";
|
605
|
-
import { Decoration as Decoration2, EditorView as
|
1207
|
+
import { Decoration as Decoration2, EditorView as EditorView4, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
606
1208
|
import { Event } from "@dxos/async";
|
607
1209
|
import { Context } from "@dxos/context";
|
608
1210
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts";
|
@@ -776,7 +1378,7 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
776
1378
|
return true;
|
777
1379
|
}
|
778
1380
|
};
|
779
|
-
var styles2 =
|
1381
|
+
var styles2 = EditorView4.theme({
|
780
1382
|
".cm-collab-selection": {},
|
781
1383
|
".cm-collab-selectionLine": {
|
782
1384
|
padding: 0,
|
@@ -942,7 +1544,7 @@ var SpaceAwarenessProvider = class {
|
|
942
1544
|
};
|
943
1545
|
|
944
1546
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
945
|
-
import { EditorView as
|
1547
|
+
import { EditorView as EditorView5, keymap as keymap2 } from "@codemirror/view";
|
946
1548
|
import defaultsDeep from "lodash.defaultsdeep";
|
947
1549
|
import { invariant as invariant2 } from "@dxos/invariant";
|
948
1550
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
@@ -990,7 +1592,7 @@ var blast = (options = defaultOptions) => {
|
|
990
1592
|
};
|
991
1593
|
return [
|
992
1594
|
// Cursor moved.
|
993
|
-
|
1595
|
+
EditorView5.updateListener.of((update2) => {
|
994
1596
|
if (blaster?.node !== update2.view.scrollDOM) {
|
995
1597
|
if (blaster) {
|
996
1598
|
blaster.destroy();
|
@@ -1252,11 +1854,11 @@ var random = (min, max) => {
|
|
1252
1854
|
};
|
1253
1855
|
|
1254
1856
|
// packages/ui/react-ui-editor/src/extensions/command/command.ts
|
1255
|
-
import { EditorView as
|
1857
|
+
import { EditorView as EditorView7, keymap as keymap3 } from "@codemirror/view";
|
1256
1858
|
|
1257
1859
|
// packages/ui/react-ui-editor/src/extensions/command/hint.ts
|
1258
1860
|
import { RangeSetBuilder } from "@codemirror/state";
|
1259
|
-
import { Decoration as Decoration3, EditorView as
|
1861
|
+
import { Decoration as Decoration3, EditorView as EditorView6, ViewPlugin as ViewPlugin3, WidgetType as WidgetType2 } from "@codemirror/view";
|
1260
1862
|
|
1261
1863
|
// packages/ui/react-ui-editor/src/extensions/command/state.ts
|
1262
1864
|
import { StateEffect as StateEffect2, StateField as StateField3 } from "@codemirror/state";
|
@@ -1422,7 +2024,7 @@ var hintViewPlugin = ({ onHint }) => ViewPlugin3.fromClass(class {
|
|
1422
2024
|
}
|
1423
2025
|
}, {
|
1424
2026
|
provide: (plugin) => [
|
1425
|
-
|
2027
|
+
EditorView6.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration3.none)
|
1426
2028
|
]
|
1427
2029
|
});
|
1428
2030
|
|
@@ -1433,7 +2035,7 @@ var command = (options) => {
|
|
1433
2035
|
commandState,
|
1434
2036
|
keymap3.of(commandKeyBindings),
|
1435
2037
|
hintViewPlugin(options),
|
1436
|
-
|
2038
|
+
EditorView7.focusChangeEffect.of((_, focusing) => {
|
1437
2039
|
return focusing ? closeEffect.of(null) : null;
|
1438
2040
|
})
|
1439
2041
|
];
|
@@ -1442,16 +2044,16 @@ var command = (options) => {
|
|
1442
2044
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
1443
2045
|
import { invertedEffects } from "@codemirror/commands";
|
1444
2046
|
import { StateEffect as StateEffect3, StateField as StateField4 } from "@codemirror/state";
|
1445
|
-
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";
|
1446
2048
|
import sortBy from "lodash.sortby";
|
1447
|
-
import { useEffect, useMemo
|
2049
|
+
import { useEffect, useMemo as useMemo2 } from "react";
|
1448
2050
|
import { debounce as debounce2 } from "@dxos/async";
|
1449
2051
|
import { log as log4 } from "@dxos/log";
|
1450
2052
|
import { nonNullable } from "@dxos/util";
|
1451
2053
|
|
1452
2054
|
// packages/ui/react-ui-editor/src/extensions/selection.ts
|
1453
2055
|
import { Transaction } from "@codemirror/state";
|
1454
|
-
import { EditorView as
|
2056
|
+
import { EditorView as EditorView8, keymap as keymap4 } from "@codemirror/view";
|
1455
2057
|
import { debounce } from "@dxos/async";
|
1456
2058
|
import { invariant as invariant3 } from "@dxos/invariant";
|
1457
2059
|
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
@@ -1462,7 +2064,7 @@ var createEditorStateTransaction = ({ scrollTo, selection }) => {
|
|
1462
2064
|
return {
|
1463
2065
|
selection,
|
1464
2066
|
scrollIntoView: !scrollTo,
|
1465
|
-
effects: scrollTo ?
|
2067
|
+
effects: scrollTo ? EditorView8.scrollIntoView(scrollTo, {
|
1466
2068
|
yMargin: 96
|
1467
2069
|
}) : void 0,
|
1468
2070
|
annotations: Transaction.userEvent.of(stateRestoreAnnotation)
|
@@ -1504,7 +2106,7 @@ var selectionState = ({ getState, setState } = {}) => {
|
|
1504
2106
|
// setStateDebounced(id, {});
|
1505
2107
|
// },
|
1506
2108
|
// }),
|
1507
|
-
|
2109
|
+
EditorView8.updateListener.of(({ view, transactions }) => {
|
1508
2110
|
const id = view.state.facet(documentId);
|
1509
2111
|
if (!id || transactions.some((tr) => tr.isUserEvent(stateRestoreAnnotation))) {
|
1510
2112
|
return;
|
@@ -1585,7 +2187,7 @@ var commentsState = StateField4.define({
|
|
1585
2187
|
return value;
|
1586
2188
|
}
|
1587
2189
|
});
|
1588
|
-
var styles3 =
|
2190
|
+
var styles3 = EditorView9.theme({
|
1589
2191
|
".cm-comment, .cm-comment-current": {
|
1590
2192
|
margin: "0 -3px",
|
1591
2193
|
padding: "3px",
|
@@ -1605,7 +2207,7 @@ var createCommentMark = (id, isCurrent) => Decoration4.mark({
|
|
1605
2207
|
"data-comment-id": id
|
1606
2208
|
}
|
1607
2209
|
});
|
1608
|
-
var commentsDecorations =
|
2210
|
+
var commentsDecorations = EditorView9.decorations.compute([
|
1609
2211
|
commentsState
|
1610
2212
|
], (state) => {
|
1611
2213
|
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
@@ -1614,7 +2216,7 @@ var commentsDecorations = EditorView8.decorations.compute([
|
|
1614
2216
|
if (!range) {
|
1615
2217
|
log4.warn("Invalid range:", range, {
|
1616
2218
|
F: __dxlog_file7,
|
1617
|
-
L:
|
2219
|
+
L: 144,
|
1618
2220
|
S: void 0,
|
1619
2221
|
C: (f, a) => f(...a)
|
1620
2222
|
});
|
@@ -1628,7 +2230,7 @@ var commentsDecorations = EditorView8.decorations.compute([
|
|
1628
2230
|
return Decoration4.set(decorations);
|
1629
2231
|
});
|
1630
2232
|
var commentClickedEffect = StateEffect3.define();
|
1631
|
-
var handleCommentClick =
|
2233
|
+
var handleCommentClick = EditorView9.domEventHandlers({
|
1632
2234
|
click: (event, view) => {
|
1633
2235
|
let target = event.target;
|
1634
2236
|
const editorRoot = view.dom;
|
@@ -1667,7 +2269,7 @@ var trackPastedComments = (onUpdate) => {
|
|
1667
2269
|
}
|
1668
2270
|
};
|
1669
2271
|
return [
|
1670
|
-
|
2272
|
+
EditorView9.domEventHandlers({
|
1671
2273
|
cut: handleTrack,
|
1672
2274
|
copy: handleTrack
|
1673
2275
|
}),
|
@@ -1689,7 +2291,7 @@ var trackPastedComments = (onUpdate) => {
|
|
1689
2291
|
return effects;
|
1690
2292
|
}),
|
1691
2293
|
// Handle paste or the undo of comment deletion.
|
1692
|
-
|
2294
|
+
EditorView9.updateListener.of((update2) => {
|
1693
2295
|
const restore = [];
|
1694
2296
|
for (let i = 0; i < update2.transactions.length; i++) {
|
1695
2297
|
const tr = update2.transactions[i];
|
@@ -1748,7 +2350,7 @@ var mapTrackedComment = (comment, changes) => ({
|
|
1748
2350
|
var restoreCommentEffect = StateEffect3.define({
|
1749
2351
|
map: mapTrackedComment
|
1750
2352
|
});
|
1751
|
-
var
|
2353
|
+
var createComment2 = (view) => {
|
1752
2354
|
const options = view.state.facet(optionsFacet);
|
1753
2355
|
const { from, to } = view.state.selection.main;
|
1754
2356
|
if (from === to) {
|
@@ -1793,7 +2395,7 @@ var comments = (options = {}) => {
|
|
1793
2395
|
options.onCreate && keymap5.of([
|
1794
2396
|
{
|
1795
2397
|
key: shortcut,
|
1796
|
-
run: callbackWrapper(
|
2398
|
+
run: callbackWrapper(createComment2)
|
1797
2399
|
}
|
1798
2400
|
]),
|
1799
2401
|
//
|
@@ -1829,7 +2431,7 @@ var comments = (options = {}) => {
|
|
1829
2431
|
//
|
1830
2432
|
// Track deleted ranges and update ranges for decorations.
|
1831
2433
|
//
|
1832
|
-
|
2434
|
+
EditorView9.updateListener.of(({ view, state, changes }) => {
|
1833
2435
|
let mod = false;
|
1834
2436
|
const { comments: comments2, ...value } = state.field(commentsState);
|
1835
2437
|
changes.iterChanges((from, to, from2, to2) => {
|
@@ -1861,7 +2463,7 @@ var comments = (options = {}) => {
|
|
1861
2463
|
//
|
1862
2464
|
// Track selection/proximity.
|
1863
2465
|
//
|
1864
|
-
|
2466
|
+
EditorView9.updateListener.of(({ view, state }) => {
|
1865
2467
|
let min = Infinity;
|
1866
2468
|
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
1867
2469
|
const { head } = state.selection.main;
|
@@ -1915,7 +2517,7 @@ var scrollThreadIntoView = (view, id, center = true) => {
|
|
1915
2517
|
anchor: range.from
|
1916
2518
|
} : void 0,
|
1917
2519
|
effects: [
|
1918
|
-
needsScroll ?
|
2520
|
+
needsScroll ? EditorView9.scrollIntoView(range.from, center ? {
|
1919
2521
|
y: "center"
|
1920
2522
|
} : void 0) : [],
|
1921
2523
|
needsSelectionUpdate ? setSelection.of({
|
@@ -1926,415 +2528,179 @@ var scrollThreadIntoView = (view, id, center = true) => {
|
|
1926
2528
|
}
|
1927
2529
|
}
|
1928
2530
|
};
|
1929
|
-
var selectionOverlapsComment = (state) => {
|
1930
|
-
const commentState = state.field(commentsState, false);
|
1931
|
-
if (commentState === void 0) {
|
1932
|
-
return false;
|
1933
|
-
}
|
1934
|
-
const { selection } = state;
|
1935
|
-
for (const range of selection.ranges) {
|
1936
|
-
if (commentState.comments.some(({ range: commentRange }) => overlap(commentRange, range))) {
|
1937
|
-
return true;
|
1938
|
-
}
|
1939
|
-
}
|
1940
|
-
return false;
|
1941
|
-
};
|
1942
|
-
var hasActiveSelection = (state) => {
|
1943
|
-
return state.selection.ranges.some((range) => !range.empty);
|
1944
|
-
};
|
1945
|
-
var ExternalCommentSync = class {
|
1946
|
-
constructor(view, id, subscribe, getComments) {
|
1947
|
-
this.destroy = () => {
|
1948
|
-
this.unsubscribe();
|
1949
|
-
};
|
1950
|
-
const updateComments = () => {
|
1951
|
-
const comments2 = getComments();
|
1952
|
-
if (id === view.state.facet(documentId)) {
|
1953
|
-
queueMicrotask(() => view.dispatch({
|
1954
|
-
effects: setComments.of({
|
1955
|
-
id,
|
1956
|
-
comments: comments2
|
1957
|
-
})
|
1958
|
-
}));
|
1959
|
-
}
|
1960
|
-
};
|
1961
|
-
this.unsubscribe = subscribe(updateComments);
|
1962
|
-
}
|
1963
|
-
};
|
1964
|
-
var createExternalCommentSync = (id, subscribe, getComments) => ViewPlugin4.fromClass(class {
|
1965
|
-
constructor(view) {
|
1966
|
-
return new ExternalCommentSync(view, id, subscribe, getComments);
|
1967
|
-
}
|
1968
|
-
});
|
1969
|
-
var useCommentState = () => {
|
1970
|
-
|
1971
|
-
|
1972
|
-
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1981
|
-
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
1987
|
-
|
1988
|
-
|
1989
|
-
|
1990
|
-
if (id === view.state.facet(documentId)) {
|
1991
|
-
view.dispatch({
|
1992
|
-
effects: setComments.of({
|
1993
|
-
id,
|
1994
|
-
comments: comments2 ?? []
|
1995
|
-
})
|
1996
|
-
});
|
1997
|
-
}
|
1998
|
-
}
|
1999
|
-
});
|
2000
|
-
};
|
2001
|
-
var useCommentClickListener = (onCommentClick) => {
|
2002
|
-
return useMemo(() => EditorView8.updateListener.of((update2) => {
|
2003
|
-
update2.transactions.forEach((transaction) => {
|
2004
|
-
transaction.effects.forEach((effect) => {
|
2005
|
-
if (effect.is(commentClickedEffect)) {
|
2006
|
-
onCommentClick(effect.value);
|
2007
|
-
}
|
2008
|
-
});
|
2009
|
-
});
|
2010
|
-
}), [
|
2011
|
-
onCommentClick
|
2012
|
-
]);
|
2013
|
-
};
|
2014
|
-
|
2015
|
-
// packages/ui/react-ui-editor/src/extensions/debug.ts
|
2016
|
-
import { syntaxTree } from "@codemirror/language";
|
2017
|
-
import { StateField as StateField5 } from "@codemirror/state";
|
2018
|
-
var debugNodeLogger = (log8 = console.log) => {
|
2019
|
-
const logTokens = (state) => syntaxTree(state).iterate({
|
2020
|
-
enter: (node) => log8(node.type)
|
2021
|
-
});
|
2022
|
-
return StateField5.define({
|
2023
|
-
create: (state) => logTokens(state),
|
2024
|
-
update: (_, tr) => logTokens(tr.state)
|
2025
|
-
});
|
2026
|
-
};
|
2027
|
-
|
2028
|
-
// packages/ui/react-ui-editor/src/extensions/dnd.ts
|
2029
|
-
import { dropCursor, EditorView as EditorView9 } from "@codemirror/view";
|
2030
|
-
var styles4 = EditorView9.theme({
|
2031
|
-
".cm-dropCursor": {
|
2032
|
-
borderLeft: "2px solid var(--dx-accentText)",
|
2033
|
-
color: "var(--dx-accentText)",
|
2034
|
-
padding: "0 4px"
|
2035
|
-
},
|
2036
|
-
".cm-dropCursor:after": {
|
2037
|
-
content: '"\u2190"'
|
2038
|
-
}
|
2039
|
-
});
|
2040
|
-
var dropFile = (options = {}) => {
|
2041
|
-
return [
|
2042
|
-
styles4,
|
2043
|
-
dropCursor(),
|
2044
|
-
EditorView9.domEventHandlers({
|
2045
|
-
drop: (event, view) => {
|
2046
|
-
event.preventDefault();
|
2047
|
-
const files = event.dataTransfer?.files;
|
2048
|
-
const pos = view.posAtCoords(event);
|
2049
|
-
if (files?.length && pos !== null) {
|
2050
|
-
view.dispatch({
|
2051
|
-
selection: {
|
2052
|
-
anchor: pos
|
2053
|
-
}
|
2054
|
-
});
|
2055
|
-
options.onDrop?.(view, {
|
2056
|
-
files
|
2057
|
-
});
|
2058
|
-
}
|
2059
|
-
}
|
2060
|
-
})
|
2061
|
-
];
|
2062
|
-
};
|
2063
|
-
|
2064
|
-
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2065
|
-
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
2066
|
-
import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
2067
|
-
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
2068
|
-
import { searchKeymap } from "@codemirror/search";
|
2069
|
-
import { EditorState } from "@codemirror/state";
|
2070
|
-
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
2071
|
-
import { EditorView as EditorView11, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap6, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
|
2072
|
-
import defaultsDeep2 from "lodash.defaultsdeep";
|
2073
|
-
import merge from "lodash.merge";
|
2074
|
-
import { generateName } from "@dxos/display-name";
|
2075
|
-
import { log as log5 } from "@dxos/log";
|
2076
|
-
import { hueTokens } from "@dxos/react-ui-theme";
|
2077
|
-
import { hexToHue, isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
2078
|
-
|
2079
|
-
// packages/ui/react-ui-editor/src/extensions/focus.ts
|
2080
|
-
import { StateEffect as StateEffect4, StateField as StateField6 } from "@codemirror/state";
|
2081
|
-
import { EditorView as EditorView10 } from "@codemirror/view";
|
2082
|
-
var focusEffect = StateEffect4.define();
|
2083
|
-
var focusField = StateField6.define({
|
2084
|
-
create: () => false,
|
2085
|
-
update: (value, tr) => {
|
2086
|
-
for (const effect of tr.effects) {
|
2087
|
-
if (effect.is(focusEffect)) {
|
2088
|
-
return effect.value;
|
2089
|
-
}
|
2090
|
-
}
|
2091
|
-
return value;
|
2092
|
-
}
|
2093
|
-
});
|
2094
|
-
var focus = [
|
2095
|
-
focusField,
|
2096
|
-
EditorView10.domEventHandlers({
|
2097
|
-
focus: (event, view) => {
|
2098
|
-
setTimeout(() => view.dispatch({
|
2099
|
-
effects: focusEffect.of(true)
|
2100
|
-
}));
|
2101
|
-
},
|
2102
|
-
blur: (event, view) => {
|
2103
|
-
setTimeout(() => view.dispatch({
|
2104
|
-
effects: focusEffect.of(false)
|
2105
|
-
}));
|
2106
|
-
}
|
2107
|
-
})
|
2108
|
-
];
|
2109
|
-
|
2110
|
-
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
2111
|
-
import { mx } from "@dxos/react-ui-theme";
|
2112
|
-
var headings = {
|
2113
|
-
1: "text-4xl",
|
2114
|
-
2: "text-3xl",
|
2115
|
-
3: "text-2xl",
|
2116
|
-
4: "text-xl",
|
2117
|
-
5: "text-lg",
|
2118
|
-
6: "text-md"
|
2119
|
-
};
|
2120
|
-
var theme = {
|
2121
|
-
code: "font-mono !no-underline text-neutral-700 dark:text-neutral-300",
|
2122
|
-
codeMark: "font-mono text-primary-500",
|
2123
|
-
mark: "opacity-50",
|
2124
|
-
heading: (level) => {
|
2125
|
-
return mx(headings[level], "dark:text-primary-400");
|
2126
|
-
}
|
2127
|
-
};
|
2128
|
-
|
2129
|
-
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
2130
|
-
import get from "lodash.get";
|
2131
|
-
import { tokens } from "@dxos/react-ui-theme";
|
2132
|
-
var getToken = (path, defaultValue) => {
|
2133
|
-
const value = get(tokens, path, defaultValue);
|
2134
|
-
return value?.toString() ?? "";
|
2135
|
-
};
|
2136
|
-
var fontBody = getToken("fontFamily.body");
|
2137
|
-
var fontMono = getToken("fontFamily.mono");
|
2138
|
-
|
2139
|
-
// packages/ui/react-ui-editor/src/styles/theme.ts
|
2140
|
-
var defaultTheme = {
|
2141
|
-
"&": {},
|
2142
|
-
"&.cm-focused": {
|
2143
|
-
outline: "none"
|
2144
|
-
},
|
2145
|
-
/**
|
2146
|
-
* Scroller
|
2147
|
-
*/
|
2148
|
-
".cm-scroller": {
|
2149
|
-
overflowY: "auto"
|
2150
|
-
},
|
2151
|
-
/**
|
2152
|
-
* Content
|
2153
|
-
* NOTE: Apply margins to content so that scrollbar is at the edge of the container.
|
2154
|
-
*/
|
2155
|
-
".cm-content": {
|
2156
|
-
padding: "unset",
|
2157
|
-
fontFamily: fontBody,
|
2158
|
-
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
2159
|
-
fontSize: "16px",
|
2160
|
-
lineHeight: 1.5,
|
2161
|
-
color: "unset"
|
2162
|
-
},
|
2163
|
-
/**
|
2164
|
-
* Gutters
|
2165
|
-
* NOTE: Gutters should have the same top margin as the content.
|
2166
|
-
* NOTE: They can't be transparent since the content needs to scroll below.
|
2167
|
-
*/
|
2168
|
-
".cm-gutters": {
|
2169
|
-
background: "var(--surface-bg)",
|
2170
|
-
borderRight: "none"
|
2171
|
-
},
|
2172
|
-
".cm-gutter": {},
|
2173
|
-
".cm-gutter.cm-lineNumbers .cm-gutterElement": {
|
2174
|
-
minWidth: "40px",
|
2175
|
-
alignContent: "center"
|
2176
|
-
},
|
2177
|
-
/**
|
2178
|
-
* Height is set to match the corresponding line.
|
2179
|
-
*/
|
2180
|
-
".cm-gutterElement": {
|
2181
|
-
alignItems: "center",
|
2182
|
-
fontSize: "16px"
|
2183
|
-
},
|
2184
|
-
/**
|
2185
|
-
* Line.
|
2186
|
-
*/
|
2187
|
-
".cm-line": {
|
2188
|
-
paddingInline: 0
|
2189
|
-
},
|
2190
|
-
".cm-activeLine": {
|
2191
|
-
background: "var(--dx-cmActiveLine)"
|
2192
|
-
},
|
2193
|
-
/**
|
2194
|
-
* Cursor (layer).
|
2195
|
-
*/
|
2196
|
-
".cm-cursor, .cm-dropCursor": {
|
2197
|
-
borderLeft: "2px solid var(--dx-cmCursor)"
|
2198
|
-
},
|
2199
|
-
".cm-placeholder": {
|
2200
|
-
color: "var(--dx-subdued)"
|
2201
|
-
},
|
2202
|
-
/**
|
2203
|
-
* Selection (layer).
|
2204
|
-
*/
|
2205
|
-
".cm-selectionBackground": {
|
2206
|
-
background: "var(--dx-cmSelection)"
|
2207
|
-
},
|
2208
|
-
/**
|
2209
|
-
* Search.
|
2210
|
-
* NOTE: Matches comment.
|
2211
|
-
*/
|
2212
|
-
".cm-searchMatch": {
|
2213
|
-
margin: "0 -3px",
|
2214
|
-
padding: "3px",
|
2215
|
-
borderRadius: "3px",
|
2216
|
-
background: "var(--dx-cmHighlightSurface)",
|
2217
|
-
color: "var(--dx-cmHighlight)"
|
2218
|
-
},
|
2219
|
-
".cm-searchMatch-selected": {
|
2220
|
-
textDecoration: "underline"
|
2221
|
-
},
|
2222
|
-
/**
|
2223
|
-
* Link.
|
2224
|
-
*/
|
2225
|
-
".cm-link": {
|
2226
|
-
textDecorationLine: "underline",
|
2227
|
-
textDecorationThickness: "1px",
|
2228
|
-
textUnderlineOffset: "2px",
|
2229
|
-
borderRadius: ".125rem"
|
2230
|
-
},
|
2231
|
-
".cm-link > span": {
|
2232
|
-
color: "var(--dx-accentText)"
|
2233
|
-
},
|
2234
|
-
/**
|
2235
|
-
* Tooltip.
|
2236
|
-
*/
|
2237
|
-
".cm-tooltip": {
|
2238
|
-
background: "var(--dx-base)"
|
2239
|
-
},
|
2240
|
-
".cm-tooltip-below": {},
|
2241
|
-
/**
|
2242
|
-
* Autocomplete.
|
2243
|
-
* https://github.com/codemirror/autocomplete/blob/main/src/completion.ts
|
2244
|
-
*/
|
2245
|
-
".cm-tooltip.cm-tooltip-autocomplete": {
|
2246
|
-
marginTop: "4px",
|
2247
|
-
marginLeft: "-3px"
|
2248
|
-
},
|
2249
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul": {
|
2250
|
-
maxHeight: "20em"
|
2251
|
-
},
|
2252
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > li": {},
|
2253
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {},
|
2254
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
|
2255
|
-
paddingLeft: "4px !important",
|
2256
|
-
borderBottom: "none !important",
|
2257
|
-
color: "var(--dx-accentText)"
|
2258
|
-
},
|
2259
|
-
".cm-tooltip.cm-completionInfo": {
|
2260
|
-
width: "360px !important",
|
2261
|
-
margin: "-10px 1px 0 1px",
|
2262
|
-
padding: "8px !important",
|
2263
|
-
borderColor: "var(--dx-separator)"
|
2264
|
-
},
|
2265
|
-
".cm-completionIcon": {
|
2266
|
-
display: "none"
|
2267
|
-
},
|
2268
|
-
".cm-completionLabel": {
|
2269
|
-
fontFamily: fontBody
|
2270
|
-
},
|
2271
|
-
".cm-completionMatchedText": {
|
2272
|
-
textDecoration: "none !important",
|
2273
|
-
opacity: 0.5
|
2274
|
-
},
|
2275
|
-
/**
|
2276
|
-
* Panels
|
2277
|
-
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
2278
|
-
*
|
2279
|
-
* Find/replace panel.
|
2280
|
-
* <div class="cm-announced">...</div>
|
2281
|
-
* <div class="cm-scroller">...</div>
|
2282
|
-
* <div class="cm-panels cm-panels-bottom">
|
2283
|
-
* <div class="cm-search cm-panel">
|
2284
|
-
* <input class="cm-textfield" />
|
2285
|
-
* <button class="cm-button">...</button>
|
2286
|
-
* <label><input type="checkbox" />...</label>
|
2287
|
-
* </div>
|
2288
|
-
* </div
|
2289
|
-
*/
|
2290
|
-
// TODO(burdon): Implement custom panel (with icon buttons).
|
2291
|
-
".cm-panels": {},
|
2292
|
-
".cm-panel": {
|
2293
|
-
fontFamily: fontBody,
|
2294
|
-
backgroundColor: "var(--surface-bg)"
|
2295
|
-
},
|
2296
|
-
".cm-panel input, .cm-panel button, .cm-panel label": {
|
2297
|
-
color: "var(--dx-subdued)",
|
2298
|
-
fontFamily: fontBody,
|
2299
|
-
fontSize: "14px",
|
2300
|
-
all: "unset",
|
2301
|
-
margin: "3px !important",
|
2302
|
-
padding: "2px 6px !important",
|
2303
|
-
outline: "1px solid transparent"
|
2304
|
-
},
|
2305
|
-
".cm-panel input, .cm-panel button": {
|
2306
|
-
backgroundColor: "var(--dx-input)"
|
2307
|
-
},
|
2308
|
-
".cm-panel input:focus, .cm-panel button:focus": {
|
2309
|
-
outline: "1px solid var(--dx-accentFocusIndicator)"
|
2310
|
-
},
|
2311
|
-
".cm-panel label": {
|
2312
|
-
display: "inline-flex",
|
2313
|
-
alignItems: "center",
|
2314
|
-
cursor: "pointer"
|
2315
|
-
},
|
2316
|
-
".cm-panel input.cm-textfield": {},
|
2317
|
-
".cm-panel input[type=checkbox]": {
|
2318
|
-
width: "8px",
|
2319
|
-
height: "8px",
|
2320
|
-
marginRight: "6px !important",
|
2321
|
-
padding: "2px !important",
|
2322
|
-
color: "var(--dx-accentFocusIndicator)"
|
2323
|
-
},
|
2324
|
-
".cm-panel button": {
|
2325
|
-
"&:hover": {
|
2326
|
-
backgroundColor: "var(--dx-accentSurfaceHover) !important"
|
2327
|
-
},
|
2328
|
-
"&:active": {
|
2329
|
-
backgroundColor: "var(--dx-accentSurfaceHover)"
|
2531
|
+
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
|
+
}
|
2330
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"
|
2331
2629
|
},
|
2332
|
-
".cm-
|
2333
|
-
|
2334
|
-
borderTop: "1px solid var(--dx-separator)"
|
2630
|
+
".cm-dropCursor:after": {
|
2631
|
+
content: '"\u2190"'
|
2335
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
|
+
];
|
2336
2656
|
};
|
2337
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
|
+
|
2338
2704
|
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2339
2705
|
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
|
2340
2706
|
var preventNewline = EditorState.transactionFilter.of((tr) => tr.newDoc.lines > 1 ? [] : tr);
|
@@ -2360,7 +2726,7 @@ var createBasicExtensions = (_props) => {
|
|
2360
2726
|
const props = defaultsDeep2({}, _props, defaultBasicOptions);
|
2361
2727
|
return [
|
2362
2728
|
// NOTE: Doesn't catch errors in keymap functions.
|
2363
|
-
|
2729
|
+
EditorView12.exceptionSink.of((err) => {
|
2364
2730
|
log5.catch(err, void 0, {
|
2365
2731
|
F: __dxlog_file8,
|
2366
2732
|
L: 96,
|
@@ -2379,11 +2745,11 @@ var createBasicExtensions = (_props) => {
|
|
2379
2745
|
props.highlightActiveLine && highlightActiveLine(),
|
2380
2746
|
props.history && history(),
|
2381
2747
|
props.lineNumbers && lineNumbers(),
|
2382
|
-
props.lineWrapping &&
|
2748
|
+
props.lineWrapping && EditorView12.lineWrapping,
|
2383
2749
|
props.placeholder && placeholder(props.placeholder),
|
2384
2750
|
props.readonly && [
|
2385
2751
|
EditorState.readOnly.of(true),
|
2386
|
-
|
2752
|
+
EditorView12.editable.of(false)
|
2387
2753
|
],
|
2388
2754
|
props.scrollPastEnd && scrollPastEnd(),
|
2389
2755
|
props.tabSize && EditorState.tabSize.of(props.tabSize),
|
@@ -2412,14 +2778,14 @@ var defaultThemeSlots = {
|
|
2412
2778
|
var createThemeExtensions = ({ themeMode, styles: styles5, syntaxHighlighting: _syntaxHighlighting, slots: _slots } = {}) => {
|
2413
2779
|
const slots = defaultsDeep2({}, _slots, defaultThemeSlots);
|
2414
2780
|
return [
|
2415
|
-
|
2416
|
-
|
2781
|
+
EditorView12.darkTheme.of(themeMode === "dark"),
|
2782
|
+
EditorView12.baseTheme(styles5 ? merge({}, defaultTheme, styles5) : defaultTheme),
|
2417
2783
|
// https://github.com/codemirror/theme-one-dark
|
2418
2784
|
_syntaxHighlighting && (themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)),
|
2419
|
-
slots.editor?.className &&
|
2785
|
+
slots.editor?.className && EditorView12.editorAttributes.of({
|
2420
2786
|
class: slots.editor.className
|
2421
2787
|
}),
|
2422
|
-
slots.content?.className &&
|
2788
|
+
slots.content?.className && EditorView12.contentAttributes.of({
|
2423
2789
|
class: slots.content.className
|
2424
2790
|
})
|
2425
2791
|
].filter(isNotFalsy3);
|
@@ -2448,8 +2814,8 @@ var createDataExtensions = ({ id, text, space, identity }) => {
|
|
2448
2814
|
|
2449
2815
|
// packages/ui/react-ui-editor/src/extensions/folding.tsx
|
2450
2816
|
import { codeFolding, foldGutter } from "@codemirror/language";
|
2451
|
-
import { EditorView as
|
2452
|
-
import
|
2817
|
+
import { EditorView as EditorView13 } from "@codemirror/view";
|
2818
|
+
import React3 from "react";
|
2453
2819
|
import { Icon } from "@dxos/react-ui";
|
2454
2820
|
var folding = (_props = {}) => [
|
2455
2821
|
codeFolding({
|
@@ -2462,7 +2828,7 @@ var folding = (_props = {}) => [
|
|
2462
2828
|
const el = createElement("div", {
|
2463
2829
|
className: "flex h-full items-center"
|
2464
2830
|
});
|
2465
|
-
return renderRoot(el, /* @__PURE__ */
|
2831
|
+
return renderRoot(el, /* @__PURE__ */ React3.createElement(Icon, {
|
2466
2832
|
icon: "ph--caret-right--regular",
|
2467
2833
|
size: 3,
|
2468
2834
|
classNames: [
|
@@ -2472,7 +2838,7 @@ var folding = (_props = {}) => [
|
|
2472
2838
|
}));
|
2473
2839
|
}
|
2474
2840
|
}),
|
2475
|
-
|
2841
|
+
EditorView13.theme({
|
2476
2842
|
".cm-foldGutter": {
|
2477
2843
|
opacity: 0.3,
|
2478
2844
|
transition: "opacity 0.3s",
|
@@ -2485,14 +2851,14 @@ var folding = (_props = {}) => [
|
|
2485
2851
|
];
|
2486
2852
|
|
2487
2853
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
2488
|
-
import { EditorView as
|
2854
|
+
import { EditorView as EditorView14 } from "@codemirror/view";
|
2489
2855
|
var listener = ({ onFocus, onChange }) => {
|
2490
2856
|
const extensions = [];
|
2491
|
-
onFocus && extensions.push(
|
2857
|
+
onFocus && extensions.push(EditorView14.focusChangeEffect.of((_, focusing) => {
|
2492
2858
|
onFocus(focusing);
|
2493
2859
|
return null;
|
2494
2860
|
}));
|
2495
|
-
onChange && extensions.push(
|
2861
|
+
onChange && extensions.push(EditorView14.updateListener.of((update2) => {
|
2496
2862
|
onChange(update2.state.doc.toString(), update2.state.facet(documentId));
|
2497
2863
|
}));
|
2498
2864
|
return extensions;
|
@@ -2502,8 +2868,8 @@ var listener = ({ onFocus, onChange }) => {
|
|
2502
2868
|
import { snippet } from "@codemirror/autocomplete";
|
2503
2869
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
2504
2870
|
import { EditorSelection } from "@codemirror/state";
|
2505
|
-
import { EditorView as
|
2506
|
-
import { useMemo as
|
2871
|
+
import { EditorView as EditorView15, keymap as keymap7 } from "@codemirror/view";
|
2872
|
+
import { useMemo as useMemo3 } from "react";
|
2507
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;
|
2508
2874
|
var Inline;
|
2509
2875
|
(function(Inline2) {
|
@@ -3590,65 +3956,56 @@ var getFormatting = (state) => {
|
|
3590
3956
|
listStyle: listStyle || null
|
3591
3957
|
};
|
3592
3958
|
};
|
3593
|
-
var useFormattingState = () => {
|
3594
|
-
|
3595
|
-
const observer = useMemo2(() => EditorView14.updateListener.of((update2) => {
|
3959
|
+
var useFormattingState = (state) => {
|
3960
|
+
return useMemo3(() => EditorView15.updateListener.of((update2) => {
|
3596
3961
|
if (update2.docChanged || update2.selectionSet) {
|
3597
|
-
|
3598
|
-
|
3599
|
-
if (!prevState || !formattingEquals(prevState, newState)) {
|
3600
|
-
return newState;
|
3601
|
-
}
|
3602
|
-
return prevState;
|
3962
|
+
Object.entries(getFormatting(update2.state)).forEach(([key, active]) => {
|
3963
|
+
state[key] = active;
|
3603
3964
|
});
|
3604
3965
|
}
|
3605
3966
|
}), []);
|
3606
|
-
return [
|
3607
|
-
state,
|
3608
|
-
observer
|
3609
|
-
];
|
3610
3967
|
};
|
3611
3968
|
|
3612
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/
|
3613
|
-
var
|
3969
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/editorAction.ts
|
3970
|
+
var processEditorPayload = (view, { type, data }) => {
|
3614
3971
|
let inlineType, listType;
|
3615
|
-
switch (
|
3972
|
+
switch (type) {
|
3616
3973
|
case "heading":
|
3617
|
-
setHeading(parseInt(
|
3974
|
+
setHeading(parseInt(data))(view);
|
3618
3975
|
break;
|
3619
3976
|
case "strong":
|
3620
3977
|
case "emphasis":
|
3621
3978
|
case "strikethrough":
|
3622
3979
|
case "code":
|
3623
|
-
inlineType =
|
3624
|
-
(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);
|
3625
3982
|
break;
|
3626
3983
|
case "list-ordered":
|
3627
3984
|
case "list-bullet":
|
3628
3985
|
case "list-task":
|
3629
|
-
listType =
|
3630
|
-
(
|
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);
|
3631
3988
|
break;
|
3632
3989
|
case "blockquote":
|
3633
|
-
(
|
3990
|
+
(data === false ? removeBlockquote : data === true ? addBlockquote : toggleBlockquote)(view);
|
3634
3991
|
break;
|
3635
3992
|
case "codeblock":
|
3636
|
-
(
|
3993
|
+
(data === false ? removeCodeblock : addCodeblock)(view);
|
3637
3994
|
break;
|
3638
3995
|
case "table":
|
3639
3996
|
insertTable(view);
|
3640
3997
|
break;
|
3641
3998
|
case "link":
|
3642
|
-
(
|
3999
|
+
(data === false ? removeLink : addLink())(view);
|
3643
4000
|
break;
|
3644
4001
|
case "image":
|
3645
4002
|
addLink({
|
3646
|
-
url:
|
4003
|
+
url: data,
|
3647
4004
|
image: true
|
3648
4005
|
})(view);
|
3649
4006
|
break;
|
3650
4007
|
case "comment":
|
3651
|
-
|
4008
|
+
createComment2(view);
|
3652
4009
|
break;
|
3653
4010
|
}
|
3654
4011
|
requestAnimationFrame(() => {
|
@@ -3912,9 +4269,9 @@ var convertTreeToJson = (state) => {
|
|
3912
4269
|
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
3913
4270
|
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
3914
4271
|
import { RangeSetBuilder as RangeSetBuilder3, StateEffect as StateEffect5 } from "@codemirror/state";
|
3915
|
-
import { EditorView as
|
4272
|
+
import { EditorView as EditorView19, Decoration as Decoration7, WidgetType as WidgetType5, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
3916
4273
|
import { invariant as invariant4 } from "@dxos/invariant";
|
3917
|
-
import { mx as
|
4274
|
+
import { mx as mx4 } from "@dxos/react-ui-theme";
|
3918
4275
|
|
3919
4276
|
// packages/ui/react-ui-editor/src/extensions/markdown/changes.ts
|
3920
4277
|
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
@@ -4063,7 +4420,7 @@ var getValidUrl = (str) => {
|
|
4063
4420
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
4064
4421
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
4065
4422
|
import { StateField as StateField8 } from "@codemirror/state";
|
4066
|
-
import { Decoration as Decoration5, EditorView as
|
4423
|
+
import { Decoration as Decoration5, EditorView as EditorView16, WidgetType as WidgetType3 } from "@codemirror/view";
|
4067
4424
|
var image = (_options = {}) => {
|
4068
4425
|
return [
|
4069
4426
|
StateField8.define({
|
@@ -4091,7 +4448,7 @@ var image = (_options = {}) => {
|
|
4091
4448
|
add: buildDecorations(from, to, tr.state)
|
4092
4449
|
});
|
4093
4450
|
},
|
4094
|
-
provide: (field) =>
|
4451
|
+
provide: (field) => EditorView16.decorations.from(field)
|
4095
4452
|
})
|
4096
4453
|
];
|
4097
4454
|
};
|
@@ -4151,10 +4508,10 @@ var ImageWidget = class extends WidgetType3 {
|
|
4151
4508
|
};
|
4152
4509
|
|
4153
4510
|
// packages/ui/react-ui-editor/src/extensions/markdown/styles.ts
|
4154
|
-
import { EditorView as
|
4511
|
+
import { EditorView as EditorView17 } from "@codemirror/view";
|
4155
4512
|
var bulletListIndentationWidth = 24;
|
4156
4513
|
var orderedListIndentationWidth = 36;
|
4157
|
-
var formattingStyles =
|
4514
|
+
var formattingStyles = EditorView17.theme({
|
4158
4515
|
/**
|
4159
4516
|
* Horizontal rule.
|
4160
4517
|
*/
|
@@ -4248,18 +4605,39 @@ var formattingStyles = EditorView16.theme({
|
|
4248
4605
|
height: "auto",
|
4249
4606
|
borderTop: "0.5rem solid transparent",
|
4250
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
|
+
}
|
4251
4629
|
}
|
4252
4630
|
});
|
4253
4631
|
|
4254
4632
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
4255
4633
|
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
4256
4634
|
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField9 } from "@codemirror/state";
|
4257
|
-
import { Decoration as Decoration6, EditorView as
|
4635
|
+
import { Decoration as Decoration6, EditorView as EditorView18, WidgetType as WidgetType4 } from "@codemirror/view";
|
4258
4636
|
var table = (options = {}) => {
|
4259
4637
|
return StateField9.define({
|
4260
4638
|
create: (state) => update(state, options),
|
4261
4639
|
update: (_, tr) => update(tr.state, options),
|
4262
|
-
provide: (field) =>
|
4640
|
+
provide: (field) => EditorView18.decorations.from(field)
|
4263
4641
|
});
|
4264
4642
|
};
|
4265
4643
|
var update = (state, _options) => {
|
@@ -4391,7 +4769,7 @@ var CheckboxWidget = class extends WidgetType5 {
|
|
4391
4769
|
}
|
4392
4770
|
toDOM(view) {
|
4393
4771
|
const input = document.createElement("input");
|
4394
|
-
input.className = "cm-task-checkbox
|
4772
|
+
input.className = "cm-task-checkbox dx-checkbox";
|
4395
4773
|
input.type = "checkbox";
|
4396
4774
|
input.tabIndex = -1;
|
4397
4775
|
input.checked = this._checked;
|
@@ -4443,16 +4821,16 @@ var TextWidget = class extends WidgetType5 {
|
|
4443
4821
|
};
|
4444
4822
|
var hide = Decoration7.replace({});
|
4445
4823
|
var blockQuote = Decoration7.line({
|
4446
|
-
class:
|
4824
|
+
class: mx4("cm-blockquote")
|
4447
4825
|
});
|
4448
4826
|
var fencedCodeLine = Decoration7.line({
|
4449
|
-
class:
|
4827
|
+
class: mx4("cm-code cm-codeblock-line")
|
4450
4828
|
});
|
4451
4829
|
var fencedCodeLineFirst = Decoration7.line({
|
4452
|
-
class:
|
4830
|
+
class: mx4("cm-code cm-codeblock-line", "cm-codeblock-first")
|
4453
4831
|
});
|
4454
4832
|
var fencedCodeLineLast = Decoration7.line({
|
4455
|
-
class:
|
4833
|
+
class: mx4("cm-code cm-codeblock-line", "cm-codeblock-last")
|
4456
4834
|
});
|
4457
4835
|
var commentBlockLine = fencedCodeLine;
|
4458
4836
|
var commentBlockLineFirst = fencedCodeLineFirst;
|
@@ -4793,9 +5171,9 @@ var decorateMarkdown = (options = {}) => {
|
|
4793
5171
|
}
|
4794
5172
|
}, {
|
4795
5173
|
provide: (plugin) => [
|
4796
|
-
|
4797
|
-
|
4798
|
-
|
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)
|
4799
5177
|
]
|
4800
5178
|
}),
|
4801
5179
|
image(),
|
@@ -4982,428 +5360,29 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
4982
5360
|
];
|
4983
5361
|
};
|
4984
5362
|
|
4985
|
-
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
4986
|
-
var iconStyles = getSize(5);
|
4987
|
-
var buttonStyles = "min-bs-0 p-1";
|
4988
|
-
var tooltipProps = {
|
4989
|
-
side: "top",
|
4990
|
-
classNames: "z-10"
|
4991
|
-
};
|
4992
|
-
var ToolbarSeparator = () => /* @__PURE__ */ React3.createElement("div", {
|
4993
|
-
role: "separator",
|
4994
|
-
className: "grow"
|
4995
|
-
});
|
4996
|
-
var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
|
4997
|
-
var ToolbarRoot = ({ children, onAction, classNames, state }) => {
|
4998
|
-
return /* @__PURE__ */ React3.createElement(ToolbarContextProvider, {
|
4999
|
-
onAction,
|
5000
|
-
state
|
5001
|
-
}, /* @__PURE__ */ React3.createElement(ElevationProvider, {
|
5002
|
-
elevation: "positioned"
|
5003
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.Root, {
|
5004
|
-
classNames: [
|
5005
|
-
"p-1 is-full shrink-0 overflow-x-auto overflow-y-hidden",
|
5006
|
-
classNames
|
5007
|
-
],
|
5008
|
-
style: {
|
5009
|
-
contain: "layout"
|
5010
|
-
}
|
5011
|
-
}, children)));
|
5012
|
-
};
|
5013
|
-
var ToolbarToggleButton = ({ Icon: Icon2, children, ...props }) => {
|
5014
|
-
return /* @__PURE__ */ React3.createElement(Tooltip.Root, null, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
|
5015
|
-
asChild: true
|
5016
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroupItem, {
|
5017
|
-
variant: "ghost",
|
5018
|
-
...props,
|
5019
|
-
classNames: buttonStyles
|
5020
|
-
}, /* @__PURE__ */ React3.createElement(Icon2, {
|
5021
|
-
className: iconStyles
|
5022
|
-
}), /* @__PURE__ */ React3.createElement("span", {
|
5023
|
-
className: "sr-only"
|
5024
|
-
}, children))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
|
5025
|
-
};
|
5026
|
-
var ToolbarButton = ({ Icon: Icon2, children, ...props }) => {
|
5027
|
-
return /* @__PURE__ */ React3.createElement(Tooltip.Root, null, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
|
5028
|
-
asChild: true
|
5029
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
|
5030
|
-
variant: "ghost",
|
5031
|
-
...props,
|
5032
|
-
classNames: buttonStyles
|
5033
|
-
}, /* @__PURE__ */ React3.createElement(Icon2, {
|
5034
|
-
className: iconStyles
|
5035
|
-
}), /* @__PURE__ */ React3.createElement("span", {
|
5036
|
-
className: "sr-only"
|
5037
|
-
}, children))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
|
5038
|
-
};
|
5039
|
-
var HeadingIcons = {
|
5040
|
-
"0": Paragraph,
|
5041
|
-
"1": TextHOne,
|
5042
|
-
"2": TextHTwo,
|
5043
|
-
"3": TextHThree,
|
5044
|
-
"4": TextHFour,
|
5045
|
-
"5": TextHFive,
|
5046
|
-
"6": TextHSix
|
5047
|
-
};
|
5048
|
-
var MarkdownHeading = () => {
|
5049
|
-
const { t } = useTranslation(translationKey);
|
5050
|
-
const { onAction, state } = useToolbarContext("MarkdownFormatting");
|
5051
|
-
const blockType = state ? state.blockType : "paragraph";
|
5052
|
-
const header = blockType && /heading(\d)/.exec(blockType);
|
5053
|
-
const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : void 0;
|
5054
|
-
const HeadingIcon = HeadingIcons[value ?? "0"];
|
5055
|
-
const suppressNextTooltip = useRef(false);
|
5056
|
-
const [tooltipOpen, setTooltipOpen] = useState3(false);
|
5057
|
-
const [selectOpen, setSelectOpen] = useState3(false);
|
5058
|
-
return /* @__PURE__ */ React3.createElement(Tooltip.Root, {
|
5059
|
-
open: tooltipOpen,
|
5060
|
-
onOpenChange: (nextOpen) => {
|
5061
|
-
if (nextOpen && suppressNextTooltip.current) {
|
5062
|
-
suppressNextTooltip.current = false;
|
5063
|
-
return setTooltipOpen(false);
|
5064
|
-
} else {
|
5065
|
-
return setTooltipOpen(nextOpen);
|
5066
|
-
}
|
5067
|
-
}
|
5068
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
|
5069
|
-
open: selectOpen,
|
5070
|
-
onOpenChange: (nextOpen) => {
|
5071
|
-
if (!nextOpen) {
|
5072
|
-
suppressNextTooltip.current = true;
|
5073
|
-
}
|
5074
|
-
return setSelectOpen(nextOpen);
|
5075
|
-
}
|
5076
|
-
}, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
|
5077
|
-
asChild: true
|
5078
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
|
5079
|
-
asChild: true
|
5080
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
|
5081
|
-
asChild: true
|
5082
|
-
}, /* @__PURE__ */ React3.createElement(Button, {
|
5083
|
-
variant: "ghost",
|
5084
|
-
classNames: buttonStyles,
|
5085
|
-
disabled: value === null
|
5086
|
-
}, /* @__PURE__ */ React3.createElement("span", {
|
5087
|
-
className: "sr-only"
|
5088
|
-
}, t("heading label")), /* @__PURE__ */ React3.createElement(HeadingIcon, {
|
5089
|
-
className: iconStyles
|
5090
|
-
}), /* @__PURE__ */ React3.createElement(CaretDown, null))))), /* @__PURE__ */ React3.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
|
5091
|
-
classNames: "is-min md:is-min",
|
5092
|
-
onCloseAutoFocus: (e) => e.preventDefault()
|
5093
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Viewport, null, Object.keys(HeadingIcons).map((level) => {
|
5094
|
-
const Icon2 = HeadingIcons[level];
|
5095
|
-
return /* @__PURE__ */ React3.createElement(DropdownMenu.CheckboxItem, {
|
5096
|
-
key: level,
|
5097
|
-
checked: value === level,
|
5098
|
-
onClick: () => onAction?.({
|
5099
|
-
type: "heading",
|
5100
|
-
data: level
|
5101
|
-
})
|
5102
|
-
}, /* @__PURE__ */ React3.createElement("span", {
|
5103
|
-
className: "sr-only"
|
5104
|
-
}, t("heading level label", {
|
5105
|
-
count: parseInt(level)
|
5106
|
-
})), /* @__PURE__ */ React3.createElement(Icon2, {
|
5107
|
-
className: iconStyles
|
5108
|
-
}), /* @__PURE__ */ React3.createElement(DropdownMenu.ItemIndicator, null, /* @__PURE__ */ React3.createElement(Check, null)));
|
5109
|
-
})), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null)))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, t("heading label"), /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
|
5110
|
-
};
|
5111
|
-
var markdownStyles = [
|
5112
|
-
{
|
5113
|
-
type: "strong",
|
5114
|
-
Icon: TextB,
|
5115
|
-
getState: (state) => !!state?.strong
|
5116
|
-
},
|
5117
|
-
{
|
5118
|
-
type: "emphasis",
|
5119
|
-
Icon: TextItalic,
|
5120
|
-
getState: (state) => !!state?.emphasis
|
5121
|
-
},
|
5122
|
-
{
|
5123
|
-
type: "strikethrough",
|
5124
|
-
Icon: TextStrikethrough,
|
5125
|
-
getState: (state) => !!state?.strikethrough
|
5126
|
-
},
|
5127
|
-
{
|
5128
|
-
type: "code",
|
5129
|
-
Icon: Code,
|
5130
|
-
getState: (state) => !!state?.code
|
5131
|
-
},
|
5132
|
-
{
|
5133
|
-
type: "link",
|
5134
|
-
Icon: Link,
|
5135
|
-
getState: (state) => !!state?.link
|
5136
|
-
}
|
5137
|
-
];
|
5138
|
-
var MarkdownStyles = () => {
|
5139
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
5140
|
-
const { t } = useTranslation(translationKey);
|
5141
|
-
return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
|
5142
|
-
type: "multiple",
|
5143
|
-
value: markdownStyles.filter(({ getState }) => state && getState(state)).map(({ type }) => type)
|
5144
|
-
}, markdownStyles.map(({ type, getState, Icon: Icon2 }) => /* @__PURE__ */ React3.createElement(ToolbarToggleButton, {
|
5145
|
-
key: type,
|
5146
|
-
value: type,
|
5147
|
-
Icon: Icon2,
|
5148
|
-
disabled: state?.blockType === "codeblock",
|
5149
|
-
onClick: state ? () => onAction?.({
|
5150
|
-
type,
|
5151
|
-
data: !getState(state)
|
5152
|
-
}) : void 0
|
5153
|
-
}, t(`${type} label`))));
|
5154
|
-
};
|
5155
|
-
var markdownLists = [
|
5156
|
-
{
|
5157
|
-
type: "list-bullet",
|
5158
|
-
Icon: ListBullets,
|
5159
|
-
getState: (state) => state.listStyle === "bullet"
|
5160
|
-
},
|
5161
|
-
{
|
5162
|
-
type: "list-ordered",
|
5163
|
-
Icon: ListNumbers,
|
5164
|
-
getState: (state) => state.listStyle === "ordered"
|
5165
|
-
},
|
5166
|
-
{
|
5167
|
-
type: "list-task",
|
5168
|
-
Icon: ListChecks,
|
5169
|
-
getState: (state) => state.listStyle === "task"
|
5170
|
-
}
|
5171
|
-
];
|
5172
|
-
var MarkdownLists = () => {
|
5173
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
5174
|
-
const { t } = useTranslation(translationKey);
|
5175
|
-
return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
|
5176
|
-
type: "single",
|
5177
|
-
value: state?.listStyle ? `list-${state.listStyle}` : ""
|
5178
|
-
}, markdownLists.map(({ type, getState, Icon: Icon2 }) => /* @__PURE__ */ React3.createElement(ToolbarToggleButton, {
|
5179
|
-
key: type,
|
5180
|
-
value: type,
|
5181
|
-
Icon: Icon2,
|
5182
|
-
onClick: state ? () => onAction?.({
|
5183
|
-
type,
|
5184
|
-
data: !getState(state)
|
5185
|
-
}) : void 0
|
5186
|
-
}, t(`${type} label`))));
|
5187
|
-
};
|
5188
|
-
var markdownBlocks = [
|
5189
|
-
{
|
5190
|
-
type: "blockquote",
|
5191
|
-
Icon: Quotes,
|
5192
|
-
getState: (state) => !!state?.blockQuote
|
5193
|
-
},
|
5194
|
-
{
|
5195
|
-
type: "codeblock",
|
5196
|
-
Icon: CodeBlock,
|
5197
|
-
getState: (state) => state.blockType === "codeblock"
|
5198
|
-
},
|
5199
|
-
{
|
5200
|
-
type: "table",
|
5201
|
-
Icon: Table2,
|
5202
|
-
getState: (state) => state.blockType === "tablecell",
|
5203
|
-
disabled: (state) => !state.blankLine
|
5204
|
-
}
|
5205
|
-
];
|
5206
|
-
var MarkdownBlocks = () => {
|
5207
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
5208
|
-
const { t } = useTranslation(translationKey);
|
5209
|
-
const value = markdownBlocks.find(({ getState }) => state && getState(state));
|
5210
|
-
return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
|
5211
|
-
type: "single",
|
5212
|
-
value: value?.type ?? ""
|
5213
|
-
}, markdownBlocks.map(({ type, disabled, getState, Icon: Icon2 }) => /* @__PURE__ */ React3.createElement(ToolbarToggleButton, {
|
5214
|
-
key: type,
|
5215
|
-
value: type,
|
5216
|
-
Icon: Icon2,
|
5217
|
-
disabled: !state || disabled?.(state),
|
5218
|
-
onClick: state ? () => onAction?.({
|
5219
|
-
type,
|
5220
|
-
data: !getState(state)
|
5221
|
-
}) : void 0
|
5222
|
-
}, t(`${type} label`))));
|
5223
|
-
};
|
5224
|
-
var MarkdownStandard = () => /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(MarkdownHeading, null), /* @__PURE__ */ React3.createElement(MarkdownStyles, null), /* @__PURE__ */ React3.createElement(MarkdownLists, null), /* @__PURE__ */ React3.createElement(MarkdownBlocks, null));
|
5225
|
-
var MarkdownCustom = ({ onUpload } = {}) => {
|
5226
|
-
const { onAction } = useToolbarContext("MarkdownStyles");
|
5227
|
-
const { t } = useTranslation(translationKey);
|
5228
|
-
const { acceptedFiles, getInputProps, open } = useDropzone({
|
5229
|
-
multiple: false,
|
5230
|
-
noDrag: true,
|
5231
|
-
accept: {
|
5232
|
-
"image/*": [
|
5233
|
-
".jpg",
|
5234
|
-
".jpeg",
|
5235
|
-
".png",
|
5236
|
-
".gif"
|
5237
|
-
]
|
5238
|
-
}
|
5239
|
-
});
|
5240
|
-
useEffect2(() => {
|
5241
|
-
if (onUpload && acceptedFiles.length) {
|
5242
|
-
requestAnimationFrame(async () => {
|
5243
|
-
const f = acceptedFiles[0];
|
5244
|
-
const file = new File([
|
5245
|
-
f
|
5246
|
-
], f.name, {
|
5247
|
-
type: f.type,
|
5248
|
-
lastModified: f.lastModified
|
5249
|
-
});
|
5250
|
-
const info = await onUpload(file);
|
5251
|
-
if (info) {
|
5252
|
-
onAction?.({
|
5253
|
-
type: "image",
|
5254
|
-
data: info.url
|
5255
|
-
});
|
5256
|
-
}
|
5257
|
-
});
|
5258
|
-
}
|
5259
|
-
}, [
|
5260
|
-
acceptedFiles
|
5261
|
-
]);
|
5262
|
-
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("input", getInputProps()), /* @__PURE__ */ React3.createElement(ToolbarButton, {
|
5263
|
-
value: "image",
|
5264
|
-
Icon: Image,
|
5265
|
-
onClick: () => open()
|
5266
|
-
}, t("image label")));
|
5267
|
-
};
|
5268
|
-
var ViewModeIcons = {
|
5269
|
-
preview: PencilSimple,
|
5270
|
-
readonly: PencilSimpleSlash,
|
5271
|
-
source: MarkdownLogo
|
5272
|
-
};
|
5273
|
-
var MarkdownView = ({ mode }) => {
|
5274
|
-
const { t } = useTranslation(translationKey);
|
5275
|
-
const { onAction } = useToolbarContext("ViewMode");
|
5276
|
-
const ModeIcon = ViewModeIcons[mode ?? "preview"];
|
5277
|
-
const suppressNextTooltip = useRef(false);
|
5278
|
-
const [tooltipOpen, setTooltipOpen] = useState3(false);
|
5279
|
-
const [selectOpen, setSelectOpen] = useState3(false);
|
5280
|
-
return /* @__PURE__ */ React3.createElement(Tooltip.Root, {
|
5281
|
-
open: tooltipOpen,
|
5282
|
-
onOpenChange: (nextOpen) => {
|
5283
|
-
if (nextOpen && suppressNextTooltip.current) {
|
5284
|
-
suppressNextTooltip.current = false;
|
5285
|
-
return setTooltipOpen(false);
|
5286
|
-
} else {
|
5287
|
-
return setTooltipOpen(nextOpen);
|
5288
|
-
}
|
5289
|
-
}
|
5290
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
|
5291
|
-
open: selectOpen,
|
5292
|
-
onOpenChange: (nextOpen) => {
|
5293
|
-
if (!nextOpen) {
|
5294
|
-
suppressNextTooltip.current = true;
|
5295
|
-
}
|
5296
|
-
return setSelectOpen(nextOpen);
|
5297
|
-
}
|
5298
|
-
}, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
|
5299
|
-
asChild: true
|
5300
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
|
5301
|
-
asChild: true
|
5302
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
|
5303
|
-
asChild: true
|
5304
|
-
}, /* @__PURE__ */ React3.createElement(Button, {
|
5305
|
-
variant: "ghost",
|
5306
|
-
classNames: buttonStyles
|
5307
|
-
}, /* @__PURE__ */ React3.createElement("span", {
|
5308
|
-
className: "sr-only"
|
5309
|
-
}, t("mode label")), /* @__PURE__ */ React3.createElement(ModeIcon, {
|
5310
|
-
className: iconStyles
|
5311
|
-
}), /* @__PURE__ */ React3.createElement(CaretDown, null))))), /* @__PURE__ */ React3.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
|
5312
|
-
classNames: "is-min md:is-min",
|
5313
|
-
onCloseAutoFocus: (e) => e.preventDefault()
|
5314
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Viewport, null, EditorViewModes.map((value) => {
|
5315
|
-
const Icon2 = ViewModeIcons[value];
|
5316
|
-
return /* @__PURE__ */ React3.createElement(DropdownMenu.CheckboxItem, {
|
5317
|
-
key: value,
|
5318
|
-
checked: value === mode,
|
5319
|
-
onClick: () => onAction?.({
|
5320
|
-
type: "view-mode",
|
5321
|
-
data: value
|
5322
|
-
})
|
5323
|
-
}, /* @__PURE__ */ React3.createElement(Icon2, {
|
5324
|
-
className: iconStyles
|
5325
|
-
}), /* @__PURE__ */ React3.createElement("span", {
|
5326
|
-
className: "whitespace-nowrap grow"
|
5327
|
-
}, t(`${value} mode label`)), /* @__PURE__ */ React3.createElement(Check, {
|
5328
|
-
className: value === mode ? "visible" : "invisible"
|
5329
|
-
}));
|
5330
|
-
})), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null)))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, t("view mode label"), /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
|
5331
|
-
};
|
5332
|
-
var MarkdownActions = () => {
|
5333
|
-
const { onAction, state } = useToolbarContext("MarkdownActions");
|
5334
|
-
const { t } = useTranslation(translationKey);
|
5335
|
-
let commentToolTipKey = "comment label";
|
5336
|
-
if (state?.comment) {
|
5337
|
-
commentToolTipKey = "selection overlaps existing comment label";
|
5338
|
-
} else if (state?.selection === false) {
|
5339
|
-
commentToolTipKey = "select text to comment label";
|
5340
|
-
}
|
5341
|
-
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(ToolbarButton, {
|
5342
|
-
value: "search",
|
5343
|
-
Icon: MagnifyingGlass,
|
5344
|
-
onClick: () => onAction?.({
|
5345
|
-
type: "search"
|
5346
|
-
})
|
5347
|
-
}, t("search label")), /* @__PURE__ */ React3.createElement(ToolbarButton, {
|
5348
|
-
value: "comment",
|
5349
|
-
Icon: ChatText,
|
5350
|
-
"data-testid": "editor.toolbar.comment",
|
5351
|
-
onClick: () => onAction?.({
|
5352
|
-
type: "comment"
|
5353
|
-
}),
|
5354
|
-
disabled: !state || state.comment || !state.selection
|
5355
|
-
}, t(commentToolTipKey)));
|
5356
|
-
};
|
5357
|
-
var Toolbar = {
|
5358
|
-
Root: ToolbarRoot,
|
5359
|
-
Button: ToolbarToggleButton,
|
5360
|
-
Separator: ToolbarSeparator,
|
5361
|
-
View: MarkdownView,
|
5362
|
-
Markdown: MarkdownStandard,
|
5363
|
-
Custom: MarkdownCustom,
|
5364
|
-
Actions: MarkdownActions
|
5365
|
-
};
|
5366
|
-
|
5367
|
-
// packages/ui/react-ui-editor/src/defaults.ts
|
5368
|
-
import { EditorView as EditorView19 } from "@codemirror/view";
|
5369
|
-
import { mx as mx3 } from "@dxos/react-ui-theme";
|
5370
|
-
var margin = "!mt-[1rem]";
|
5371
|
-
var editorContent = mx3(margin, "!mli-auto w-full max-w-[min(50rem,100%-2rem)]");
|
5372
|
-
var editorFullWidth = mx3(margin);
|
5373
|
-
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
5374
|
-
var editorGutter = EditorView19.theme({
|
5375
|
-
// Match margin from content.
|
5376
|
-
".cm-gutters": {
|
5377
|
-
marginTop: "16px",
|
5378
|
-
paddingRight: "1rem"
|
5379
|
-
}
|
5380
|
-
});
|
5381
|
-
var editorMonospace = EditorView19.theme({
|
5382
|
-
".cm-content": {
|
5383
|
-
fontFamily: fontMono
|
5384
|
-
}
|
5385
|
-
});
|
5386
|
-
|
5387
5363
|
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
5364
|
+
import { useCallback as useCallback2 } from "react";
|
5388
5365
|
var useActionHandler = (view) => {
|
5389
|
-
return (action) => view &&
|
5366
|
+
return useCallback2((action) => view && processEditorPayload(view, action.properties), [
|
5367
|
+
view
|
5368
|
+
]);
|
5390
5369
|
};
|
5391
5370
|
|
5392
5371
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
5393
5372
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
5394
5373
|
import { EditorView as EditorView20 } from "@codemirror/view";
|
5395
5374
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
5396
|
-
import { useCallback, useEffect as
|
5375
|
+
import { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo4, useRef, useState } from "react";
|
5397
5376
|
import { log as log7 } from "@dxos/log";
|
5398
5377
|
import { getProviderValue, isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
5399
5378
|
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
5400
5379
|
var instanceCount = 0;
|
5401
5380
|
var useTextEditor = (props = {}, deps = []) => {
|
5402
|
-
const { id, initialValue, extensions, autoFocus, scrollTo, selection, moveToEndOfLine, debug } =
|
5403
|
-
const [instanceId] =
|
5404
|
-
const [view, setView] =
|
5405
|
-
const parentRef =
|
5406
|
-
|
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(() => {
|
5407
5386
|
let view2;
|
5408
5387
|
if (parentRef.current) {
|
5409
5388
|
log7("create", {
|
@@ -5477,7 +5456,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5477
5456
|
view2?.destroy();
|
5478
5457
|
};
|
5479
5458
|
}, deps);
|
5480
|
-
|
5459
|
+
useEffect2(() => {
|
5481
5460
|
if (view) {
|
5482
5461
|
if (scrollTo || selection) {
|
5483
5462
|
if (selection && selection.anchor > view.state.doc.length) {
|
@@ -5504,7 +5483,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5504
5483
|
scrollTo,
|
5505
5484
|
selection
|
5506
5485
|
]);
|
5507
|
-
|
5486
|
+
useEffect2(() => {
|
5508
5487
|
if (view && autoFocus) {
|
5509
5488
|
view.focus();
|
5510
5489
|
}
|
@@ -5518,7 +5497,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5518
5497
|
Escape: view?.state.facet(editorInputMode).noTabster
|
5519
5498
|
}
|
5520
5499
|
});
|
5521
|
-
const handleKeyUp =
|
5500
|
+
const handleKeyUp = useCallback3((event) => {
|
5522
5501
|
const { key, target, currentTarget } = event;
|
5523
5502
|
if (target === currentTarget) {
|
5524
5503
|
switch (key) {
|
@@ -5547,6 +5526,7 @@ export {
|
|
5547
5526
|
EditorInputMode,
|
5548
5527
|
EditorInputModes,
|
5549
5528
|
EditorState3 as EditorState,
|
5529
|
+
EditorToolbar,
|
5550
5530
|
EditorView21 as EditorView,
|
5551
5531
|
EditorViewMode,
|
5552
5532
|
EditorViewModes,
|
@@ -5556,7 +5536,6 @@ export {
|
|
5556
5536
|
RemoteSelectionsDecorator,
|
5557
5537
|
SpaceAwarenessProvider,
|
5558
5538
|
TextKind,
|
5559
|
-
Toolbar,
|
5560
5539
|
addBlockquote,
|
5561
5540
|
addCodeblock,
|
5562
5541
|
addLink,
|
@@ -5575,8 +5554,10 @@ export {
|
|
5575
5554
|
commentsState,
|
5576
5555
|
convertTreeToJson,
|
5577
5556
|
createBasicExtensions,
|
5578
|
-
createComment,
|
5557
|
+
createComment2 as createComment,
|
5579
5558
|
createDataExtensions,
|
5559
|
+
createEditorAction,
|
5560
|
+
createEditorActionGroup,
|
5580
5561
|
createEditorStateStore,
|
5581
5562
|
createEditorStateTransaction,
|
5582
5563
|
createElement,
|
@@ -5615,7 +5596,7 @@ export {
|
|
5615
5596
|
mention,
|
5616
5597
|
overlap,
|
5617
5598
|
preventNewline,
|
5618
|
-
|
5599
|
+
processEditorPayload,
|
5619
5600
|
removeBlockquote,
|
5620
5601
|
removeCodeblock,
|
5621
5602
|
removeLink,
|
@@ -5631,6 +5612,8 @@ export {
|
|
5631
5612
|
setSelection,
|
5632
5613
|
setStyle,
|
5633
5614
|
singleValueFacet,
|
5615
|
+
stackItemContentEditorClassNames,
|
5616
|
+
stackItemContentToolbarClassNames,
|
5634
5617
|
table,
|
5635
5618
|
tags2 as tags,
|
5636
5619
|
textRange,
|
@@ -5648,9 +5631,9 @@ export {
|
|
5648
5631
|
useCommentClickListener,
|
5649
5632
|
useCommentState,
|
5650
5633
|
useComments,
|
5634
|
+
useEditorToolbarState,
|
5651
5635
|
useFormattingState,
|
5652
5636
|
useTextEditor,
|
5653
|
-
useToolbarContext,
|
5654
5637
|
wrapWithCatch
|
5655
5638
|
};
|
5656
5639
|
//# sourceMappingURL=index.mjs.map
|