@dxos/react-ui-editor 0.7.5-main.9cb18ac → 0.7.5-main.9d2a38b
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 +1105 -1127
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +1128 -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 +1105 -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 +28 -27
- 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 +20 -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/{action.ts → editorAction.ts} +22 -20
- 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/stack-item-content-class-names.ts +17 -0
- 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,259 +41,856 @@ 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(commentLabel(state.comment, state.selection))
|
126
|
+
],
|
127
|
+
edges: [
|
128
|
+
{
|
129
|
+
source: "root",
|
130
|
+
target: "comment"
|
115
131
|
}
|
132
|
+
]
|
133
|
+
});
|
134
|
+
|
135
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/formatting.ts
|
136
|
+
var formats = {
|
137
|
+
strong: "ph--text-b--regular",
|
138
|
+
emphasis: "ph--text-italic--regular",
|
139
|
+
strikethrough: "ph--text-strikethrough--regular",
|
140
|
+
code: "ph--code--regular",
|
141
|
+
link: "ph--link--regular"
|
142
|
+
};
|
143
|
+
var createFormattingGroup = (formatting) => createEditorActionGroup("formatting", {
|
144
|
+
variant: "toggleGroup",
|
145
|
+
selectCardinality: "multiple",
|
146
|
+
value: Object.keys(formats).filter((key) => !!formatting[key])
|
147
|
+
});
|
148
|
+
var createFormattingActions = (formatting) => Object.entries(formats).map(([type, icon]) => createEditorAction({
|
149
|
+
type,
|
150
|
+
checked: !!formatting[type]
|
151
|
+
}, icon));
|
152
|
+
var createFormatting = (state) => {
|
153
|
+
const formattingGroupAction = createFormattingGroup(state);
|
154
|
+
const formattingActions = createFormattingActions(state);
|
155
|
+
return {
|
156
|
+
nodes: [
|
157
|
+
formattingGroupAction,
|
158
|
+
...formattingActions
|
159
|
+
],
|
160
|
+
edges: [
|
161
|
+
{
|
162
|
+
source: "root",
|
163
|
+
target: "formatting"
|
164
|
+
},
|
165
|
+
...formattingActions.map(({ id }) => ({
|
166
|
+
source: formattingGroupAction.id,
|
167
|
+
target: id
|
168
|
+
}))
|
169
|
+
]
|
116
170
|
};
|
117
171
|
};
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
172
|
+
|
173
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/headings.ts
|
174
|
+
var createHeadingGroupAction = (value) => createEditorActionGroup("heading", {
|
175
|
+
variant: "dropdownMenu",
|
176
|
+
applyActive: true,
|
177
|
+
selectCardinality: "single",
|
178
|
+
value
|
179
|
+
}, "ph--text-h--regular");
|
180
|
+
var createHeadingActions = (value) => Object.entries({
|
181
|
+
"0": "ph--paragraph--regular",
|
182
|
+
"1": "ph--text-h-one--regular",
|
183
|
+
"2": "ph--text-h-two--regular",
|
184
|
+
"3": "ph--text-h-three--regular",
|
185
|
+
"4": "ph--text-h-four--regular",
|
186
|
+
"5": "ph--text-h-five--regular",
|
187
|
+
"6": "ph--text-h-six--regular"
|
188
|
+
}).map(([levelStr, icon]) => {
|
189
|
+
const level = parseInt(levelStr);
|
190
|
+
return createEditorAction({
|
191
|
+
type: "heading",
|
192
|
+
data: level,
|
193
|
+
checked: value === levelStr
|
194
|
+
}, icon, [
|
195
|
+
"heading level label",
|
196
|
+
{
|
197
|
+
count: level,
|
198
|
+
ns: translationKey
|
199
|
+
}
|
200
|
+
], `heading--${levelStr}`);
|
201
|
+
});
|
202
|
+
var computeHeadingValue = (state) => {
|
203
|
+
const blockType = state ? state.blockType : "paragraph";
|
204
|
+
const header = blockType && /heading(\d)/.exec(blockType);
|
205
|
+
return header ? header[1] : blockType === "paragraph" || !blockType ? "0" : "";
|
129
206
|
};
|
130
|
-
var
|
131
|
-
|
132
|
-
|
207
|
+
var createHeadings = (state) => {
|
208
|
+
const headingValue = computeHeadingValue(state);
|
209
|
+
const headingGroupAction = createHeadingGroupAction(headingValue);
|
210
|
+
const headingActions = createHeadingActions(headingValue);
|
211
|
+
return {
|
212
|
+
nodes: [
|
213
|
+
headingGroupAction,
|
214
|
+
...headingActions
|
215
|
+
],
|
216
|
+
edges: [
|
217
|
+
{
|
218
|
+
source: "root",
|
219
|
+
target: "heading"
|
220
|
+
},
|
221
|
+
...headingActions.map(({ id }) => ({
|
222
|
+
source: headingGroupAction.id,
|
223
|
+
target: id
|
224
|
+
}))
|
225
|
+
]
|
226
|
+
};
|
133
227
|
};
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
228
|
+
|
229
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/lists.ts
|
230
|
+
var listStyles = {
|
231
|
+
bullet: "ph--list-bullets--regular",
|
232
|
+
ordered: "ph--list-numbers--regular",
|
233
|
+
task: "ph--list-checks--regular"
|
234
|
+
};
|
235
|
+
var createListGroupAction = (value) => createEditorActionGroup("list", {
|
236
|
+
variant: "toggleGroup",
|
237
|
+
selectCardinality: "single",
|
238
|
+
value
|
239
|
+
});
|
240
|
+
var createListActions = (value) => Object.entries(listStyles).map(([listStyle, icon]) => createEditorAction({
|
241
|
+
type: `list-${listStyle}`,
|
242
|
+
checked: value === listStyle
|
243
|
+
}, icon));
|
244
|
+
var createLists = (state) => {
|
245
|
+
const value = state.listStyle ?? "";
|
246
|
+
const listGroupAction = createListGroupAction(value);
|
247
|
+
const listActionsMap = createListActions(value);
|
248
|
+
return {
|
249
|
+
nodes: [
|
250
|
+
listGroupAction,
|
251
|
+
...listActionsMap
|
252
|
+
],
|
253
|
+
edges: [
|
254
|
+
{
|
255
|
+
source: "root",
|
256
|
+
target: "list"
|
257
|
+
},
|
258
|
+
...listActionsMap.map(({ id }) => ({
|
259
|
+
source: listGroupAction.id,
|
260
|
+
target: id
|
261
|
+
}))
|
262
|
+
]
|
263
|
+
};
|
264
|
+
};
|
265
|
+
|
266
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/viewMode.ts
|
267
|
+
var createViewModeGroupAction = (value) => createEditorActionGroup("viewMode", {
|
268
|
+
variant: "dropdownMenu",
|
269
|
+
applyActive: true,
|
270
|
+
selectCardinality: "single",
|
271
|
+
value
|
272
|
+
}, "ph--eye--regular");
|
273
|
+
var createViewModeActions = (value) => Object.entries({
|
274
|
+
preview: "ph--eye--regular",
|
275
|
+
source: "ph--pencil-simple--regular",
|
276
|
+
readonly: "ph--pencil-slash--regular"
|
277
|
+
}).map(([viewMode, icon]) => {
|
278
|
+
return createEditorAction({
|
279
|
+
type: "view-mode",
|
280
|
+
data: viewMode,
|
281
|
+
checked: viewMode === value
|
282
|
+
}, icon, [
|
283
|
+
`${viewMode} mode label`,
|
284
|
+
{
|
285
|
+
ns: translationKey
|
138
286
|
}
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
287
|
+
], `view-mode--${viewMode}`);
|
288
|
+
});
|
289
|
+
var createViewMode = (state) => {
|
290
|
+
const value = state.viewMode ?? "source";
|
291
|
+
const viewModeGroupAction = createViewModeGroupAction(value);
|
292
|
+
const viewModeActions = createViewModeActions(value);
|
293
|
+
return {
|
294
|
+
nodes: [
|
295
|
+
viewModeGroupAction,
|
296
|
+
...viewModeActions
|
297
|
+
],
|
298
|
+
edges: [
|
299
|
+
{
|
300
|
+
source: "root",
|
301
|
+
target: "viewMode"
|
302
|
+
},
|
303
|
+
...viewModeActions.map(({ id }) => ({
|
304
|
+
source: viewModeGroupAction.id,
|
305
|
+
target: id
|
306
|
+
}))
|
307
|
+
]
|
308
|
+
};
|
159
309
|
};
|
160
310
|
|
161
|
-
// packages/ui/react-ui-editor/src/
|
162
|
-
|
163
|
-
|
311
|
+
// packages/ui/react-ui-editor/src/styles/stack-item-content-class-names.ts
|
312
|
+
import { mx } from "@dxos/react-ui-theme";
|
313
|
+
var stackItemContentEditorClassNames = (role) => mx("ch-focus-ring-inset data-[toolbar=disabled]:pbs-2 attention-surface", role === "article" ? "min-bs-0" : "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-bs-24");
|
314
|
+
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");
|
315
|
+
|
316
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
|
317
|
+
var createToolbar = ({ state, customActions, ...features }) => {
|
318
|
+
const nodes = [];
|
319
|
+
const edges = [];
|
320
|
+
if (features.headings ?? true) {
|
321
|
+
const headings2 = createHeadings(state);
|
322
|
+
nodes.push(...headings2.nodes);
|
323
|
+
edges.push(...headings2.edges);
|
324
|
+
}
|
325
|
+
if (features.formatting ?? true) {
|
326
|
+
const formatting = createFormatting(state);
|
327
|
+
nodes.push(...formatting.nodes);
|
328
|
+
edges.push(...formatting.edges);
|
329
|
+
}
|
330
|
+
if (features.lists ?? true) {
|
331
|
+
const lists = createLists(state);
|
332
|
+
nodes.push(...lists.nodes);
|
333
|
+
edges.push(...lists.edges);
|
334
|
+
}
|
335
|
+
if (features.blocks ?? true) {
|
336
|
+
const blocks = createBlocks(state);
|
337
|
+
nodes.push(...blocks.nodes);
|
338
|
+
edges.push(...blocks.edges);
|
339
|
+
}
|
340
|
+
if (customActions) {
|
341
|
+
const custom = customActions();
|
342
|
+
nodes.push(...custom.nodes);
|
343
|
+
edges.push(...custom.edges);
|
344
|
+
}
|
345
|
+
const editorToolbarGap = createGapSeparator();
|
346
|
+
nodes.push(...editorToolbarGap.nodes);
|
347
|
+
edges.push(...editorToolbarGap.edges);
|
348
|
+
if (features.comment ?? true) {
|
349
|
+
const comment = createComment(state);
|
350
|
+
nodes.push(...comment.nodes);
|
351
|
+
edges.push(...comment.edges);
|
352
|
+
}
|
353
|
+
if (features.search ?? true) {
|
354
|
+
nodes.push(editorToolbarSearch);
|
355
|
+
edges.push({
|
356
|
+
source: "root",
|
357
|
+
target: editorToolbarSearch.id
|
358
|
+
});
|
359
|
+
}
|
360
|
+
if (features.viewMode ?? true) {
|
361
|
+
const viewMode = createViewMode(state);
|
362
|
+
nodes.push(...viewMode.nodes);
|
363
|
+
edges.push(...viewMode.edges);
|
364
|
+
}
|
164
365
|
return {
|
165
|
-
|
166
|
-
|
167
|
-
top: rect.top,
|
168
|
-
bottom: rect.bottom
|
366
|
+
nodes,
|
367
|
+
edges
|
169
368
|
};
|
170
369
|
};
|
171
|
-
var
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
return
|
370
|
+
var useEditorToolbarActionGraph = ({ onAction, ...props }) => {
|
371
|
+
const menuCreator = useCallback(() => createToolbar(props), [
|
372
|
+
props
|
373
|
+
]);
|
374
|
+
const { resolveGroupItems } = useMenuActions(menuCreator);
|
375
|
+
return {
|
376
|
+
resolveGroupItems,
|
377
|
+
onAction
|
378
|
+
};
|
177
379
|
};
|
178
|
-
var
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
}
|
184
|
-
|
185
|
-
}
|
380
|
+
var EditorToolbar = ({ classNames, attendableId, role, ...props }) => {
|
381
|
+
const menuProps = useEditorToolbarActionGraph(props);
|
382
|
+
return /* @__PURE__ */ React.createElement("div", {
|
383
|
+
role: "none",
|
384
|
+
className: stackItemContentToolbarClassNames(role)
|
385
|
+
}, /* @__PURE__ */ React.createElement(ElevationProvider, {
|
386
|
+
elevation: role === "section" ? "positioned" : "base"
|
387
|
+
}, /* @__PURE__ */ React.createElement(MenuProvider, {
|
388
|
+
...menuProps,
|
389
|
+
attendableId
|
390
|
+
}, /* @__PURE__ */ React.createElement(ToolbarMenu, {
|
391
|
+
classNames: [
|
392
|
+
textBlockWidth,
|
393
|
+
"!bg-transparent",
|
394
|
+
classNames
|
395
|
+
]
|
396
|
+
}))));
|
186
397
|
};
|
187
398
|
|
188
|
-
// packages/ui/react-ui-editor/src/
|
189
|
-
import
|
190
|
-
import {
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
399
|
+
// packages/ui/react-ui-editor/src/defaults.ts
|
400
|
+
import { EditorView } from "@codemirror/view";
|
401
|
+
import { mx as mx3 } from "@dxos/react-ui-theme";
|
402
|
+
|
403
|
+
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
404
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
405
|
+
var headings = {
|
406
|
+
1: "text-4xl",
|
407
|
+
2: "text-3xl",
|
408
|
+
3: "text-2xl",
|
409
|
+
4: "text-xl",
|
410
|
+
5: "text-lg",
|
411
|
+
6: "text-md"
|
412
|
+
};
|
413
|
+
var theme = {
|
414
|
+
code: "font-mono !no-underline text-neutral-700 dark:text-neutral-300",
|
415
|
+
codeMark: "font-mono text-primary-500",
|
416
|
+
mark: "opacity-50",
|
417
|
+
heading: (level) => {
|
418
|
+
return mx2(headings[level], "dark:text-primary-400");
|
202
419
|
}
|
203
|
-
return el;
|
204
420
|
};
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
421
|
+
|
422
|
+
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
423
|
+
import get from "lodash.get";
|
424
|
+
import { tokens } from "@dxos/react-ui-theme";
|
425
|
+
var getToken = (path, defaultValue) => {
|
426
|
+
const value = get(tokens, path, defaultValue);
|
427
|
+
return value?.toString() ?? "";
|
210
428
|
};
|
429
|
+
var fontBody = getToken("fontFamily.body");
|
430
|
+
var fontMono = getToken("fontFamily.mono");
|
211
431
|
|
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
|
-
|
432
|
+
// packages/ui/react-ui-editor/src/styles/theme.ts
|
433
|
+
var defaultTheme = {
|
434
|
+
"&": {},
|
435
|
+
"&.cm-focused": {
|
436
|
+
outline: "none"
|
437
|
+
},
|
438
|
+
/**
|
439
|
+
* Scroller
|
440
|
+
*/
|
441
|
+
".cm-scroller": {
|
442
|
+
overflowY: "auto"
|
443
|
+
},
|
444
|
+
/**
|
445
|
+
* Content
|
446
|
+
* NOTE: Apply margins to content so that scrollbar is at the edge of the container.
|
447
|
+
*/
|
448
|
+
".cm-content": {
|
449
|
+
padding: "unset",
|
450
|
+
fontFamily: fontBody,
|
451
|
+
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
452
|
+
fontSize: "16px",
|
453
|
+
lineHeight: 1.5,
|
454
|
+
color: "unset"
|
455
|
+
},
|
456
|
+
/**
|
457
|
+
* Gutters
|
458
|
+
* NOTE: Gutters should have the same top margin as the content.
|
459
|
+
* NOTE: They can't be transparent since the content needs to scroll below.
|
460
|
+
*/
|
461
|
+
".cm-gutters": {
|
462
|
+
background: "var(--surface-bg)",
|
463
|
+
borderRight: "none"
|
464
|
+
},
|
465
|
+
".cm-gutter": {},
|
466
|
+
".cm-gutter.cm-lineNumbers .cm-gutterElement": {
|
467
|
+
minWidth: "40px",
|
468
|
+
alignContent: "center"
|
469
|
+
},
|
470
|
+
/**
|
471
|
+
* Height is set to match the corresponding line.
|
472
|
+
*/
|
473
|
+
".cm-gutterElement": {
|
474
|
+
alignItems: "center",
|
475
|
+
fontSize: "16px"
|
476
|
+
},
|
477
|
+
/**
|
478
|
+
* Line.
|
479
|
+
*/
|
480
|
+
".cm-line": {
|
481
|
+
paddingInline: 0
|
482
|
+
},
|
483
|
+
".cm-activeLine": {
|
484
|
+
background: "var(--dx-cmActiveLine)"
|
485
|
+
},
|
486
|
+
/**
|
487
|
+
* Cursor (layer).
|
488
|
+
*/
|
489
|
+
".cm-cursor, .cm-dropCursor": {
|
490
|
+
borderLeft: "2px solid var(--dx-cmCursor)"
|
491
|
+
},
|
492
|
+
".cm-placeholder": {
|
493
|
+
color: "var(--dx-subdued)"
|
494
|
+
},
|
495
|
+
/**
|
496
|
+
* Selection (layer).
|
497
|
+
*/
|
498
|
+
".cm-selectionBackground": {
|
499
|
+
background: "var(--dx-cmSelection)"
|
500
|
+
},
|
501
|
+
/**
|
502
|
+
* Search.
|
503
|
+
* NOTE: Matches comment.
|
504
|
+
*/
|
505
|
+
".cm-searchMatch": {
|
506
|
+
margin: "0 -3px",
|
507
|
+
padding: "3px",
|
508
|
+
borderRadius: "3px",
|
509
|
+
background: "var(--dx-cmHighlightSurface)",
|
510
|
+
color: "var(--dx-cmHighlight)"
|
511
|
+
},
|
512
|
+
".cm-searchMatch-selected": {
|
513
|
+
textDecoration: "underline"
|
514
|
+
},
|
515
|
+
/**
|
516
|
+
* Link.
|
517
|
+
*/
|
518
|
+
".cm-link": {
|
519
|
+
textDecorationLine: "underline",
|
520
|
+
textDecorationThickness: "1px",
|
521
|
+
textUnderlineOffset: "2px",
|
522
|
+
borderRadius: ".125rem"
|
523
|
+
},
|
524
|
+
".cm-link > span": {
|
525
|
+
color: "var(--dx-accentText)"
|
526
|
+
},
|
527
|
+
/**
|
528
|
+
* Tooltip.
|
529
|
+
*/
|
530
|
+
".cm-tooltip": {
|
531
|
+
background: "var(--dx-base)"
|
532
|
+
},
|
533
|
+
".cm-tooltip-below": {},
|
534
|
+
/**
|
535
|
+
* Autocomplete.
|
536
|
+
* https://github.com/codemirror/autocomplete/blob/main/src/completion.ts
|
537
|
+
*/
|
538
|
+
".cm-tooltip.cm-tooltip-autocomplete": {
|
539
|
+
marginTop: "4px",
|
540
|
+
marginLeft: "-3px"
|
541
|
+
},
|
542
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul": {
|
543
|
+
maxHeight: "20em"
|
544
|
+
},
|
545
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > li": {},
|
546
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {},
|
547
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
|
548
|
+
paddingLeft: "4px !important",
|
549
|
+
borderBottom: "none !important",
|
550
|
+
color: "var(--dx-accentText)"
|
551
|
+
},
|
552
|
+
".cm-tooltip.cm-completionInfo": {
|
553
|
+
width: "360px !important",
|
554
|
+
margin: "-10px 1px 0 1px",
|
555
|
+
padding: "8px !important",
|
556
|
+
borderColor: "var(--dx-separator)"
|
557
|
+
},
|
558
|
+
".cm-completionIcon": {
|
559
|
+
display: "none"
|
560
|
+
},
|
561
|
+
".cm-completionLabel": {
|
562
|
+
fontFamily: fontBody
|
563
|
+
},
|
564
|
+
".cm-completionMatchedText": {
|
565
|
+
textDecoration: "none !important",
|
566
|
+
opacity: 0.5
|
567
|
+
},
|
568
|
+
/**
|
569
|
+
* Panels
|
570
|
+
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
571
|
+
*
|
572
|
+
* Find/replace panel.
|
573
|
+
* <div class="cm-announced">...</div>
|
574
|
+
* <div class="cm-scroller">...</div>
|
575
|
+
* <div class="cm-panels cm-panels-bottom">
|
576
|
+
* <div class="cm-search cm-panel">
|
577
|
+
* <input class="cm-textfield" />
|
578
|
+
* <button class="cm-button">...</button>
|
579
|
+
* <label><input type="checkbox" />...</label>
|
580
|
+
* </div>
|
581
|
+
* </div
|
582
|
+
*/
|
583
|
+
// TODO(burdon): Implement custom panel (with icon buttons).
|
584
|
+
".cm-panels": {},
|
585
|
+
".cm-panel": {
|
586
|
+
fontFamily: fontBody,
|
587
|
+
backgroundColor: "var(--surface-bg)"
|
588
|
+
},
|
589
|
+
".cm-panel input, .cm-panel button, .cm-panel label": {
|
590
|
+
color: "var(--dx-subdued)",
|
591
|
+
fontFamily: fontBody,
|
592
|
+
fontSize: "14px",
|
593
|
+
all: "unset",
|
594
|
+
margin: "3px !important",
|
595
|
+
padding: "2px 6px !important",
|
596
|
+
outline: "1px solid transparent"
|
597
|
+
},
|
598
|
+
".cm-panel input, .cm-panel button": {
|
599
|
+
backgroundColor: "var(--dx-input)"
|
600
|
+
},
|
601
|
+
".cm-panel input:focus, .cm-panel button:focus": {
|
602
|
+
outline: "1px solid var(--dx-accentFocusIndicator)"
|
603
|
+
},
|
604
|
+
".cm-panel label": {
|
605
|
+
display: "inline-flex",
|
606
|
+
alignItems: "center",
|
607
|
+
cursor: "pointer"
|
608
|
+
},
|
609
|
+
".cm-panel input.cm-textfield": {},
|
610
|
+
".cm-panel input[type=checkbox]": {
|
611
|
+
width: "8px",
|
612
|
+
height: "8px",
|
613
|
+
marginRight: "6px !important",
|
614
|
+
padding: "2px !important",
|
615
|
+
color: "var(--dx-accentFocusIndicator)"
|
616
|
+
},
|
617
|
+
".cm-panel button": {
|
618
|
+
"&:hover": {
|
619
|
+
backgroundColor: "var(--dx-accentSurfaceHover) !important"
|
620
|
+
},
|
621
|
+
"&:active": {
|
622
|
+
backgroundColor: "var(--dx-accentSurfaceHover)"
|
245
623
|
}
|
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
|
-
];
|
624
|
+
},
|
625
|
+
".cm-panel.cm-search": {
|
626
|
+
padding: "4px",
|
627
|
+
borderTop: "1px solid var(--dx-separator)"
|
628
|
+
}
|
261
629
|
};
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
630
|
+
|
631
|
+
// packages/ui/react-ui-editor/src/defaults.ts
|
632
|
+
var margin = "!mt-[1rem]";
|
633
|
+
var editorContent = mx3(margin, "!mli-auto w-full max-w-[min(50rem,100%-2rem)]");
|
634
|
+
var editorFullWidth = mx3(margin);
|
635
|
+
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
636
|
+
var editorGutter = EditorView.theme({
|
637
|
+
// Match margin from content.
|
638
|
+
".cm-gutters": {
|
639
|
+
marginTop: "16px",
|
640
|
+
paddingRight: "1rem"
|
641
|
+
}
|
642
|
+
});
|
643
|
+
var editorMonospace = EditorView.theme({
|
644
|
+
".cm-content": {
|
645
|
+
fontFamily: fontMono
|
267
646
|
}
|
268
647
|
});
|
269
648
|
|
270
|
-
// packages/ui/react-ui-editor/src/extensions/
|
271
|
-
import {
|
272
|
-
import {
|
273
|
-
import {
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
649
|
+
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
650
|
+
import { StateField } from "@codemirror/state";
|
651
|
+
import { Decoration, EditorView as EditorView2 } from "@codemirror/view";
|
652
|
+
import { isNotFalsy } from "@dxos/util";
|
653
|
+
|
654
|
+
// packages/ui/react-ui-editor/src/util/facet.ts
|
655
|
+
import { Facet } from "@codemirror/state";
|
656
|
+
var singleValueFacet = (defaultValue) => Facet.define({
|
657
|
+
// Called immediately.
|
658
|
+
combine: (providers) => {
|
659
|
+
return providers[0] ?? defaultValue;
|
660
|
+
}
|
661
|
+
});
|
662
|
+
|
663
|
+
// packages/ui/react-ui-editor/src/util/cursor.ts
|
664
|
+
var overlap = (a, b) => a.from <= b.to && a.to >= b.from;
|
665
|
+
var defaultCursorConverter = {
|
666
|
+
toCursor: (position) => position.toString(),
|
667
|
+
fromCursor: (cursor) => parseInt(cursor)
|
668
|
+
};
|
669
|
+
var Cursor = class _Cursor {
|
670
|
+
static {
|
671
|
+
this.converter = singleValueFacet(defaultCursorConverter);
|
672
|
+
}
|
673
|
+
static {
|
674
|
+
this.getCursorFromRange = (state, range) => {
|
675
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
676
|
+
const from = cursorConverter2.toCursor(range.from);
|
677
|
+
const to = cursorConverter2.toCursor(range.to, -1);
|
678
|
+
return [
|
679
|
+
from,
|
680
|
+
to
|
681
|
+
].join(":");
|
682
|
+
};
|
683
|
+
}
|
684
|
+
static {
|
685
|
+
this.getRangeFromCursor = (state, cursor) => {
|
686
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
687
|
+
const parts = cursor.split(":");
|
688
|
+
const from = cursorConverter2.fromCursor(parts[0]);
|
689
|
+
const to = cursorConverter2.fromCursor(parts[1]);
|
690
|
+
return from !== void 0 && to !== void 0 ? {
|
691
|
+
from,
|
692
|
+
to
|
693
|
+
} : void 0;
|
694
|
+
};
|
695
|
+
}
|
696
|
+
};
|
697
|
+
|
698
|
+
// packages/ui/react-ui-editor/src/util/debug.ts
|
699
|
+
import { log } from "@dxos/log";
|
700
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/debug.ts";
|
701
|
+
var wrapWithCatch = (fn) => {
|
702
|
+
return (...args) => {
|
703
|
+
try {
|
704
|
+
return fn(...args);
|
705
|
+
} catch (err) {
|
706
|
+
log.catch(err, void 0, {
|
707
|
+
F: __dxlog_file,
|
708
|
+
L: 15,
|
709
|
+
S: void 0,
|
710
|
+
C: (f, a) => f(...a)
|
711
|
+
});
|
712
|
+
}
|
713
|
+
};
|
714
|
+
};
|
715
|
+
var callbackWrapper = (fn) => (...args) => {
|
716
|
+
try {
|
717
|
+
return fn(...args);
|
718
|
+
} catch (err) {
|
719
|
+
log.catch(err, void 0, {
|
720
|
+
F: __dxlog_file,
|
721
|
+
L: 29,
|
722
|
+
S: void 0,
|
723
|
+
C: (f, a) => f(...a)
|
724
|
+
});
|
725
|
+
}
|
726
|
+
};
|
727
|
+
var debugDispatcher = (trs, view) => {
|
728
|
+
logChanges(trs);
|
729
|
+
view.update(trs);
|
730
|
+
};
|
731
|
+
var logChanges = (trs) => {
|
732
|
+
const changes = trs.flatMap((tr) => {
|
733
|
+
if (tr.changes.empty) {
|
734
|
+
return void 0;
|
735
|
+
}
|
736
|
+
const changes2 = [];
|
737
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
738
|
+
fromA,
|
739
|
+
toA,
|
740
|
+
fromB,
|
741
|
+
toB,
|
742
|
+
inserted: inserted.toString()
|
743
|
+
})));
|
744
|
+
return changes2;
|
745
|
+
}).filter(Boolean);
|
746
|
+
if (changes.length) {
|
747
|
+
log.info("changes", {
|
748
|
+
changes
|
749
|
+
}, {
|
750
|
+
F: __dxlog_file,
|
751
|
+
L: 62,
|
752
|
+
S: void 0,
|
753
|
+
C: (f, a) => f(...a)
|
754
|
+
});
|
755
|
+
}
|
756
|
+
};
|
757
|
+
|
758
|
+
// packages/ui/react-ui-editor/src/util/dom.ts
|
759
|
+
var flattenRect = (rect, left) => {
|
760
|
+
const x = left ? rect.left : rect.right;
|
761
|
+
return {
|
762
|
+
left: x,
|
763
|
+
right: x,
|
764
|
+
top: rect.top,
|
765
|
+
bottom: rect.bottom
|
766
|
+
};
|
767
|
+
};
|
768
|
+
var scratchRange;
|
769
|
+
var textRange = (node, from, to = from) => {
|
770
|
+
const range = scratchRange || (scratchRange = document.createRange());
|
771
|
+
range.setEnd(node, to);
|
772
|
+
range.setStart(node, from);
|
773
|
+
return range;
|
774
|
+
};
|
775
|
+
var clientRectsFor = (dom) => {
|
776
|
+
if (dom.nodeType === 3) {
|
777
|
+
return textRange(dom, 0, dom.nodeValue.length).getClientRects();
|
778
|
+
} else if (dom.nodeType === 1) {
|
779
|
+
return dom.getClientRects();
|
780
|
+
} else {
|
781
|
+
return [];
|
782
|
+
}
|
783
|
+
};
|
784
|
+
|
785
|
+
// packages/ui/react-ui-editor/src/util/react.tsx
|
786
|
+
import React2 from "react";
|
787
|
+
import { createRoot } from "react-dom/client";
|
788
|
+
import { ThemeProvider } from "@dxos/react-ui";
|
789
|
+
import { defaultTx } from "@dxos/react-ui-theme";
|
790
|
+
var createElement = (tag, options, children) => {
|
791
|
+
const el = document.createElement(tag);
|
792
|
+
if (options?.className) {
|
793
|
+
el.className = options.className;
|
794
|
+
}
|
795
|
+
if (children) {
|
796
|
+
el.append(...Array.isArray(children) ? children : [
|
797
|
+
children
|
798
|
+
]);
|
799
|
+
}
|
800
|
+
return el;
|
801
|
+
};
|
802
|
+
var renderRoot = (root, node) => {
|
803
|
+
createRoot(root).render(/* @__PURE__ */ React2.createElement(ThemeProvider, {
|
804
|
+
tx: defaultTx
|
805
|
+
}, node));
|
806
|
+
return root;
|
807
|
+
};
|
808
|
+
|
809
|
+
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
810
|
+
var annotationMark = Decoration.mark({
|
811
|
+
class: "cm-annotation"
|
812
|
+
});
|
813
|
+
var annotations = (options = {}) => {
|
814
|
+
const match = (state) => {
|
815
|
+
const annotations2 = [];
|
816
|
+
const text = state.doc.toString();
|
817
|
+
if (options.match) {
|
818
|
+
const matches = text.matchAll(options.match);
|
819
|
+
for (const match2 of matches) {
|
820
|
+
const from = match2.index;
|
821
|
+
const to = from + match2[0].length;
|
822
|
+
const cursor = Cursor.getCursorFromRange(state, {
|
823
|
+
from,
|
824
|
+
to
|
825
|
+
});
|
826
|
+
annotations2.push({
|
827
|
+
cursor
|
828
|
+
});
|
829
|
+
}
|
830
|
+
}
|
831
|
+
return annotations2;
|
832
|
+
};
|
833
|
+
const annotationsState = StateField.define({
|
834
|
+
create: (state) => {
|
835
|
+
return match(state);
|
836
|
+
},
|
837
|
+
update: (value, tr) => {
|
838
|
+
if (!tr.changes.empty) {
|
839
|
+
return match(tr.state);
|
840
|
+
}
|
841
|
+
return value;
|
842
|
+
}
|
843
|
+
});
|
844
|
+
return [
|
845
|
+
annotationsState,
|
846
|
+
EditorView2.decorations.compute([
|
847
|
+
annotationsState
|
848
|
+
], (state) => {
|
849
|
+
const annotations2 = state.field(annotationsState);
|
850
|
+
const decorations = annotations2.map((annotation) => {
|
851
|
+
const range = Cursor.getRangeFromCursor(state, annotation.cursor);
|
852
|
+
return range && annotationMark.range(range.from, range.to);
|
853
|
+
}).filter(isNotFalsy);
|
854
|
+
return Decoration.set(decorations);
|
855
|
+
}),
|
856
|
+
styles
|
857
|
+
];
|
858
|
+
};
|
859
|
+
var styles = EditorView2.theme({
|
860
|
+
".cm-annotation": {
|
861
|
+
textDecoration: "underline",
|
862
|
+
textDecorationStyle: "wavy",
|
863
|
+
textDecorationColor: "var(--dx-error)"
|
864
|
+
}
|
865
|
+
});
|
866
|
+
|
867
|
+
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
868
|
+
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
869
|
+
import { markdownLanguage } from "@codemirror/lang-markdown";
|
870
|
+
import { keymap } from "@codemirror/view";
|
871
|
+
var autocomplete = ({ debug, activateOnTyping, override, onSearch } = {}) => {
|
872
|
+
const extensions = [
|
873
|
+
// https://codemirror.net/docs/ref/#view.keymap
|
874
|
+
// https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
|
875
|
+
// TODO(burdon): Set custom keymap.
|
876
|
+
keymap.of(completionKeymap),
|
877
|
+
// https://codemirror.net/examples/autocompletion
|
878
|
+
// https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
879
|
+
autocompletion({
|
880
|
+
activateOnTyping,
|
881
|
+
override,
|
882
|
+
closeOnBlur: !debug,
|
883
|
+
tooltipClass: () => "shadow rounded"
|
884
|
+
})
|
885
|
+
];
|
886
|
+
if (onSearch) {
|
887
|
+
extensions.push(
|
888
|
+
// TODO(burdon): Optional decoration via addToOptions
|
889
|
+
markdownLanguage.data.of({
|
890
|
+
autocomplete: (context) => {
|
891
|
+
const match = context.matchBefore(/\w*/);
|
892
|
+
if (!match || match.from === match.to && !context.explicit) {
|
893
|
+
return null;
|
297
894
|
}
|
298
895
|
return {
|
299
896
|
from: match.from,
|
@@ -308,7 +905,7 @@ var autocomplete = ({ debug, activateOnTyping, override, onSearch } = {}) => {
|
|
308
905
|
|
309
906
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
310
907
|
import { StateField as StateField2 } from "@codemirror/state";
|
311
|
-
import { EditorView as
|
908
|
+
import { EditorView as EditorView3, ViewPlugin } from "@codemirror/view";
|
312
909
|
import { next as A3 } from "@dxos/automerge/automerge";
|
313
910
|
|
314
911
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
@@ -592,7 +1189,7 @@ var automerge = (accessor) => {
|
|
592
1189
|
}
|
593
1190
|
}),
|
594
1191
|
// Reconcile local updates.
|
595
|
-
|
1192
|
+
EditorView3.updateListener.of(({ view, changes }) => {
|
596
1193
|
if (!changes.empty) {
|
597
1194
|
syncer.reconcile(view, true);
|
598
1195
|
}
|
@@ -602,7 +1199,7 @@ var automerge = (accessor) => {
|
|
602
1199
|
|
603
1200
|
// packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts
|
604
1201
|
import { Annotation as Annotation2, RangeSet } from "@codemirror/state";
|
605
|
-
import { Decoration as Decoration2, EditorView as
|
1202
|
+
import { Decoration as Decoration2, EditorView as EditorView4, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
606
1203
|
import { Event } from "@dxos/async";
|
607
1204
|
import { Context } from "@dxos/context";
|
608
1205
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts";
|
@@ -776,7 +1373,7 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
776
1373
|
return true;
|
777
1374
|
}
|
778
1375
|
};
|
779
|
-
var styles2 =
|
1376
|
+
var styles2 = EditorView4.theme({
|
780
1377
|
".cm-collab-selection": {},
|
781
1378
|
".cm-collab-selectionLine": {
|
782
1379
|
padding: 0,
|
@@ -942,7 +1539,7 @@ var SpaceAwarenessProvider = class {
|
|
942
1539
|
};
|
943
1540
|
|
944
1541
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
945
|
-
import { EditorView as
|
1542
|
+
import { EditorView as EditorView5, keymap as keymap2 } from "@codemirror/view";
|
946
1543
|
import defaultsDeep from "lodash.defaultsdeep";
|
947
1544
|
import { invariant as invariant2 } from "@dxos/invariant";
|
948
1545
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
@@ -990,7 +1587,7 @@ var blast = (options = defaultOptions) => {
|
|
990
1587
|
};
|
991
1588
|
return [
|
992
1589
|
// Cursor moved.
|
993
|
-
|
1590
|
+
EditorView5.updateListener.of((update2) => {
|
994
1591
|
if (blaster?.node !== update2.view.scrollDOM) {
|
995
1592
|
if (blaster) {
|
996
1593
|
blaster.destroy();
|
@@ -1252,11 +1849,11 @@ var random = (min, max) => {
|
|
1252
1849
|
};
|
1253
1850
|
|
1254
1851
|
// packages/ui/react-ui-editor/src/extensions/command/command.ts
|
1255
|
-
import { EditorView as
|
1852
|
+
import { EditorView as EditorView7, keymap as keymap3 } from "@codemirror/view";
|
1256
1853
|
|
1257
1854
|
// packages/ui/react-ui-editor/src/extensions/command/hint.ts
|
1258
1855
|
import { RangeSetBuilder } from "@codemirror/state";
|
1259
|
-
import { Decoration as Decoration3, EditorView as
|
1856
|
+
import { Decoration as Decoration3, EditorView as EditorView6, ViewPlugin as ViewPlugin3, WidgetType as WidgetType2 } from "@codemirror/view";
|
1260
1857
|
|
1261
1858
|
// packages/ui/react-ui-editor/src/extensions/command/state.ts
|
1262
1859
|
import { StateEffect as StateEffect2, StateField as StateField3 } from "@codemirror/state";
|
@@ -1422,7 +2019,7 @@ var hintViewPlugin = ({ onHint }) => ViewPlugin3.fromClass(class {
|
|
1422
2019
|
}
|
1423
2020
|
}, {
|
1424
2021
|
provide: (plugin) => [
|
1425
|
-
|
2022
|
+
EditorView6.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration3.none)
|
1426
2023
|
]
|
1427
2024
|
});
|
1428
2025
|
|
@@ -1433,7 +2030,7 @@ var command = (options) => {
|
|
1433
2030
|
commandState,
|
1434
2031
|
keymap3.of(commandKeyBindings),
|
1435
2032
|
hintViewPlugin(options),
|
1436
|
-
|
2033
|
+
EditorView7.focusChangeEffect.of((_, focusing) => {
|
1437
2034
|
return focusing ? closeEffect.of(null) : null;
|
1438
2035
|
})
|
1439
2036
|
];
|
@@ -1442,16 +2039,16 @@ var command = (options) => {
|
|
1442
2039
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
1443
2040
|
import { invertedEffects } from "@codemirror/commands";
|
1444
2041
|
import { StateEffect as StateEffect3, StateField as StateField4 } from "@codemirror/state";
|
1445
|
-
import { hoverTooltip, keymap as keymap5, Decoration as Decoration4, EditorView as
|
2042
|
+
import { hoverTooltip, keymap as keymap5, Decoration as Decoration4, EditorView as EditorView9, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
1446
2043
|
import sortBy from "lodash.sortby";
|
1447
|
-
import { useEffect, useMemo
|
2044
|
+
import { useEffect, useMemo as useMemo2 } from "react";
|
1448
2045
|
import { debounce as debounce2 } from "@dxos/async";
|
1449
2046
|
import { log as log4 } from "@dxos/log";
|
1450
2047
|
import { nonNullable } from "@dxos/util";
|
1451
2048
|
|
1452
2049
|
// packages/ui/react-ui-editor/src/extensions/selection.ts
|
1453
2050
|
import { Transaction } from "@codemirror/state";
|
1454
|
-
import { EditorView as
|
2051
|
+
import { EditorView as EditorView8, keymap as keymap4 } from "@codemirror/view";
|
1455
2052
|
import { debounce } from "@dxos/async";
|
1456
2053
|
import { invariant as invariant3 } from "@dxos/invariant";
|
1457
2054
|
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
@@ -1462,7 +2059,7 @@ var createEditorStateTransaction = ({ scrollTo, selection }) => {
|
|
1462
2059
|
return {
|
1463
2060
|
selection,
|
1464
2061
|
scrollIntoView: !scrollTo,
|
1465
|
-
effects: scrollTo ?
|
2062
|
+
effects: scrollTo ? EditorView8.scrollIntoView(scrollTo, {
|
1466
2063
|
yMargin: 96
|
1467
2064
|
}) : void 0,
|
1468
2065
|
annotations: Transaction.userEvent.of(stateRestoreAnnotation)
|
@@ -1504,7 +2101,7 @@ var selectionState = ({ getState, setState } = {}) => {
|
|
1504
2101
|
// setStateDebounced(id, {});
|
1505
2102
|
// },
|
1506
2103
|
// }),
|
1507
|
-
|
2104
|
+
EditorView8.updateListener.of(({ view, transactions }) => {
|
1508
2105
|
const id = view.state.facet(documentId);
|
1509
2106
|
if (!id || transactions.some((tr) => tr.isUserEvent(stateRestoreAnnotation))) {
|
1510
2107
|
return;
|
@@ -1585,7 +2182,7 @@ var commentsState = StateField4.define({
|
|
1585
2182
|
return value;
|
1586
2183
|
}
|
1587
2184
|
});
|
1588
|
-
var styles3 =
|
2185
|
+
var styles3 = EditorView9.theme({
|
1589
2186
|
".cm-comment, .cm-comment-current": {
|
1590
2187
|
margin: "0 -3px",
|
1591
2188
|
padding: "3px",
|
@@ -1605,7 +2202,7 @@ var createCommentMark = (id, isCurrent) => Decoration4.mark({
|
|
1605
2202
|
"data-comment-id": id
|
1606
2203
|
}
|
1607
2204
|
});
|
1608
|
-
var commentsDecorations =
|
2205
|
+
var commentsDecorations = EditorView9.decorations.compute([
|
1609
2206
|
commentsState
|
1610
2207
|
], (state) => {
|
1611
2208
|
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
@@ -1614,7 +2211,7 @@ var commentsDecorations = EditorView8.decorations.compute([
|
|
1614
2211
|
if (!range) {
|
1615
2212
|
log4.warn("Invalid range:", range, {
|
1616
2213
|
F: __dxlog_file7,
|
1617
|
-
L:
|
2214
|
+
L: 144,
|
1618
2215
|
S: void 0,
|
1619
2216
|
C: (f, a) => f(...a)
|
1620
2217
|
});
|
@@ -1628,7 +2225,7 @@ var commentsDecorations = EditorView8.decorations.compute([
|
|
1628
2225
|
return Decoration4.set(decorations);
|
1629
2226
|
});
|
1630
2227
|
var commentClickedEffect = StateEffect3.define();
|
1631
|
-
var handleCommentClick =
|
2228
|
+
var handleCommentClick = EditorView9.domEventHandlers({
|
1632
2229
|
click: (event, view) => {
|
1633
2230
|
let target = event.target;
|
1634
2231
|
const editorRoot = view.dom;
|
@@ -1667,7 +2264,7 @@ var trackPastedComments = (onUpdate) => {
|
|
1667
2264
|
}
|
1668
2265
|
};
|
1669
2266
|
return [
|
1670
|
-
|
2267
|
+
EditorView9.domEventHandlers({
|
1671
2268
|
cut: handleTrack,
|
1672
2269
|
copy: handleTrack
|
1673
2270
|
}),
|
@@ -1689,7 +2286,7 @@ var trackPastedComments = (onUpdate) => {
|
|
1689
2286
|
return effects;
|
1690
2287
|
}),
|
1691
2288
|
// Handle paste or the undo of comment deletion.
|
1692
|
-
|
2289
|
+
EditorView9.updateListener.of((update2) => {
|
1693
2290
|
const restore = [];
|
1694
2291
|
for (let i = 0; i < update2.transactions.length; i++) {
|
1695
2292
|
const tr = update2.transactions[i];
|
@@ -1748,7 +2345,7 @@ var mapTrackedComment = (comment, changes) => ({
|
|
1748
2345
|
var restoreCommentEffect = StateEffect3.define({
|
1749
2346
|
map: mapTrackedComment
|
1750
2347
|
});
|
1751
|
-
var
|
2348
|
+
var createComment2 = (view) => {
|
1752
2349
|
const options = view.state.facet(optionsFacet);
|
1753
2350
|
const { from, to } = view.state.selection.main;
|
1754
2351
|
if (from === to) {
|
@@ -1793,7 +2390,7 @@ var comments = (options = {}) => {
|
|
1793
2390
|
options.onCreate && keymap5.of([
|
1794
2391
|
{
|
1795
2392
|
key: shortcut,
|
1796
|
-
run: callbackWrapper(
|
2393
|
+
run: callbackWrapper(createComment2)
|
1797
2394
|
}
|
1798
2395
|
]),
|
1799
2396
|
//
|
@@ -1829,7 +2426,7 @@ var comments = (options = {}) => {
|
|
1829
2426
|
//
|
1830
2427
|
// Track deleted ranges and update ranges for decorations.
|
1831
2428
|
//
|
1832
|
-
|
2429
|
+
EditorView9.updateListener.of(({ view, state, changes }) => {
|
1833
2430
|
let mod = false;
|
1834
2431
|
const { comments: comments2, ...value } = state.field(commentsState);
|
1835
2432
|
changes.iterChanges((from, to, from2, to2) => {
|
@@ -1861,7 +2458,7 @@ var comments = (options = {}) => {
|
|
1861
2458
|
//
|
1862
2459
|
// Track selection/proximity.
|
1863
2460
|
//
|
1864
|
-
|
2461
|
+
EditorView9.updateListener.of(({ view, state }) => {
|
1865
2462
|
let min = Infinity;
|
1866
2463
|
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
1867
2464
|
const { head } = state.selection.main;
|
@@ -1915,7 +2512,7 @@ var scrollThreadIntoView = (view, id, center = true) => {
|
|
1915
2512
|
anchor: range.from
|
1916
2513
|
} : void 0,
|
1917
2514
|
effects: [
|
1918
|
-
needsScroll ?
|
2515
|
+
needsScroll ? EditorView9.scrollIntoView(range.from, center ? {
|
1919
2516
|
y: "center"
|
1920
2517
|
} : void 0) : [],
|
1921
2518
|
needsSelectionUpdate ? setSelection.of({
|
@@ -1926,415 +2523,179 @@ var scrollThreadIntoView = (view, id, center = true) => {
|
|
1926
2523
|
}
|
1927
2524
|
}
|
1928
2525
|
};
|
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)"
|
2526
|
+
var selectionOverlapsComment = (state) => {
|
2527
|
+
const commentState = state.field(commentsState, false);
|
2528
|
+
if (commentState === void 0) {
|
2529
|
+
return false;
|
2530
|
+
}
|
2531
|
+
const { selection } = state;
|
2532
|
+
for (const range of selection.ranges) {
|
2533
|
+
if (commentState.comments.some(({ range: commentRange }) => overlap(commentRange, range))) {
|
2534
|
+
return true;
|
2535
|
+
}
|
2536
|
+
}
|
2537
|
+
return false;
|
2538
|
+
};
|
2539
|
+
var hasActiveSelection = (state) => {
|
2540
|
+
return state.selection.ranges.some((range) => !range.empty);
|
2541
|
+
};
|
2542
|
+
var ExternalCommentSync = class {
|
2543
|
+
constructor(view, id, subscribe, getComments) {
|
2544
|
+
this.destroy = () => {
|
2545
|
+
this.unsubscribe();
|
2546
|
+
};
|
2547
|
+
const updateComments = () => {
|
2548
|
+
const comments2 = getComments();
|
2549
|
+
if (id === view.state.facet(documentId)) {
|
2550
|
+
queueMicrotask(() => view.dispatch({
|
2551
|
+
effects: setComments.of({
|
2552
|
+
id,
|
2553
|
+
comments: comments2
|
2554
|
+
})
|
2555
|
+
}));
|
2556
|
+
}
|
2557
|
+
};
|
2558
|
+
this.unsubscribe = subscribe(updateComments);
|
2559
|
+
}
|
2560
|
+
};
|
2561
|
+
var createExternalCommentSync = (id, subscribe, getComments) => ViewPlugin4.fromClass(class {
|
2562
|
+
constructor(view) {
|
2563
|
+
return new ExternalCommentSync(view, id, subscribe, getComments);
|
2564
|
+
}
|
2565
|
+
});
|
2566
|
+
var useCommentState = (state) => {
|
2567
|
+
return useMemo2(() => EditorView9.updateListener.of((update2) => {
|
2568
|
+
if (update2.docChanged || update2.selectionSet) {
|
2569
|
+
state.comment = selectionOverlapsComment(update2.state);
|
2570
|
+
state.selection = hasActiveSelection(update2.state);
|
2571
|
+
}
|
2572
|
+
}), [
|
2573
|
+
state
|
2574
|
+
]);
|
2575
|
+
};
|
2576
|
+
var useComments = (view, id, comments2) => {
|
2577
|
+
useEffect(() => {
|
2578
|
+
if (view) {
|
2579
|
+
if (id === view.state.facet(documentId)) {
|
2580
|
+
view.dispatch({
|
2581
|
+
effects: setComments.of({
|
2582
|
+
id,
|
2583
|
+
comments: comments2 ?? []
|
2584
|
+
})
|
2585
|
+
});
|
2586
|
+
}
|
2330
2587
|
}
|
2588
|
+
});
|
2589
|
+
};
|
2590
|
+
var useCommentClickListener = (onCommentClick) => {
|
2591
|
+
return useMemo2(() => EditorView9.updateListener.of((update2) => {
|
2592
|
+
update2.transactions.forEach((transaction) => {
|
2593
|
+
transaction.effects.forEach((effect) => {
|
2594
|
+
if (effect.is(commentClickedEffect)) {
|
2595
|
+
onCommentClick(effect.value);
|
2596
|
+
}
|
2597
|
+
});
|
2598
|
+
});
|
2599
|
+
}), [
|
2600
|
+
onCommentClick
|
2601
|
+
]);
|
2602
|
+
};
|
2603
|
+
|
2604
|
+
// packages/ui/react-ui-editor/src/extensions/debug.ts
|
2605
|
+
import { syntaxTree } from "@codemirror/language";
|
2606
|
+
import { StateField as StateField5 } from "@codemirror/state";
|
2607
|
+
var debugNodeLogger = (log8 = console.log) => {
|
2608
|
+
const logTokens = (state) => syntaxTree(state).iterate({
|
2609
|
+
enter: (node) => log8(node.type)
|
2610
|
+
});
|
2611
|
+
return StateField5.define({
|
2612
|
+
create: (state) => logTokens(state),
|
2613
|
+
update: (_, tr) => logTokens(tr.state)
|
2614
|
+
});
|
2615
|
+
};
|
2616
|
+
|
2617
|
+
// packages/ui/react-ui-editor/src/extensions/dnd.ts
|
2618
|
+
import { dropCursor, EditorView as EditorView10 } from "@codemirror/view";
|
2619
|
+
var styles4 = EditorView10.theme({
|
2620
|
+
".cm-dropCursor": {
|
2621
|
+
borderLeft: "2px solid var(--dx-accentText)",
|
2622
|
+
color: "var(--dx-accentText)",
|
2623
|
+
padding: "0 4px"
|
2331
2624
|
},
|
2332
|
-
".cm-
|
2333
|
-
|
2334
|
-
borderTop: "1px solid var(--dx-separator)"
|
2625
|
+
".cm-dropCursor:after": {
|
2626
|
+
content: '"\u2190"'
|
2335
2627
|
}
|
2628
|
+
});
|
2629
|
+
var dropFile = (options = {}) => {
|
2630
|
+
return [
|
2631
|
+
styles4,
|
2632
|
+
dropCursor(),
|
2633
|
+
EditorView10.domEventHandlers({
|
2634
|
+
drop: (event, view) => {
|
2635
|
+
event.preventDefault();
|
2636
|
+
const files = event.dataTransfer?.files;
|
2637
|
+
const pos = view.posAtCoords(event);
|
2638
|
+
if (files?.length && pos !== null) {
|
2639
|
+
view.dispatch({
|
2640
|
+
selection: {
|
2641
|
+
anchor: pos
|
2642
|
+
}
|
2643
|
+
});
|
2644
|
+
options.onDrop?.(view, {
|
2645
|
+
files
|
2646
|
+
});
|
2647
|
+
}
|
2648
|
+
}
|
2649
|
+
})
|
2650
|
+
];
|
2336
2651
|
};
|
2337
2652
|
|
2653
|
+
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2654
|
+
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
2655
|
+
import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
2656
|
+
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
2657
|
+
import { searchKeymap } from "@codemirror/search";
|
2658
|
+
import { EditorState } from "@codemirror/state";
|
2659
|
+
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
2660
|
+
import { EditorView as EditorView12, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap6, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
|
2661
|
+
import defaultsDeep2 from "lodash.defaultsdeep";
|
2662
|
+
import merge from "lodash.merge";
|
2663
|
+
import { generateName } from "@dxos/display-name";
|
2664
|
+
import { log as log5 } from "@dxos/log";
|
2665
|
+
import { hueTokens } from "@dxos/react-ui-theme";
|
2666
|
+
import { hexToHue, isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
2667
|
+
|
2668
|
+
// packages/ui/react-ui-editor/src/extensions/focus.ts
|
2669
|
+
import { StateEffect as StateEffect4, StateField as StateField6 } from "@codemirror/state";
|
2670
|
+
import { EditorView as EditorView11 } from "@codemirror/view";
|
2671
|
+
var focusEffect = StateEffect4.define();
|
2672
|
+
var focusField = StateField6.define({
|
2673
|
+
create: () => false,
|
2674
|
+
update: (value, tr) => {
|
2675
|
+
for (const effect of tr.effects) {
|
2676
|
+
if (effect.is(focusEffect)) {
|
2677
|
+
return effect.value;
|
2678
|
+
}
|
2679
|
+
}
|
2680
|
+
return value;
|
2681
|
+
}
|
2682
|
+
});
|
2683
|
+
var focus = [
|
2684
|
+
focusField,
|
2685
|
+
EditorView11.domEventHandlers({
|
2686
|
+
focus: (event, view) => {
|
2687
|
+
setTimeout(() => view.dispatch({
|
2688
|
+
effects: focusEffect.of(true)
|
2689
|
+
}));
|
2690
|
+
},
|
2691
|
+
blur: (event, view) => {
|
2692
|
+
setTimeout(() => view.dispatch({
|
2693
|
+
effects: focusEffect.of(false)
|
2694
|
+
}));
|
2695
|
+
}
|
2696
|
+
})
|
2697
|
+
];
|
2698
|
+
|
2338
2699
|
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2339
2700
|
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
|
2340
2701
|
var preventNewline = EditorState.transactionFilter.of((tr) => tr.newDoc.lines > 1 ? [] : tr);
|
@@ -2360,7 +2721,7 @@ var createBasicExtensions = (_props) => {
|
|
2360
2721
|
const props = defaultsDeep2({}, _props, defaultBasicOptions);
|
2361
2722
|
return [
|
2362
2723
|
// NOTE: Doesn't catch errors in keymap functions.
|
2363
|
-
|
2724
|
+
EditorView12.exceptionSink.of((err) => {
|
2364
2725
|
log5.catch(err, void 0, {
|
2365
2726
|
F: __dxlog_file8,
|
2366
2727
|
L: 96,
|
@@ -2379,11 +2740,11 @@ var createBasicExtensions = (_props) => {
|
|
2379
2740
|
props.highlightActiveLine && highlightActiveLine(),
|
2380
2741
|
props.history && history(),
|
2381
2742
|
props.lineNumbers && lineNumbers(),
|
2382
|
-
props.lineWrapping &&
|
2743
|
+
props.lineWrapping && EditorView12.lineWrapping,
|
2383
2744
|
props.placeholder && placeholder(props.placeholder),
|
2384
2745
|
props.readonly && [
|
2385
2746
|
EditorState.readOnly.of(true),
|
2386
|
-
|
2747
|
+
EditorView12.editable.of(false)
|
2387
2748
|
],
|
2388
2749
|
props.scrollPastEnd && scrollPastEnd(),
|
2389
2750
|
props.tabSize && EditorState.tabSize.of(props.tabSize),
|
@@ -2412,14 +2773,14 @@ var defaultThemeSlots = {
|
|
2412
2773
|
var createThemeExtensions = ({ themeMode, styles: styles5, syntaxHighlighting: _syntaxHighlighting, slots: _slots } = {}) => {
|
2413
2774
|
const slots = defaultsDeep2({}, _slots, defaultThemeSlots);
|
2414
2775
|
return [
|
2415
|
-
|
2416
|
-
|
2776
|
+
EditorView12.darkTheme.of(themeMode === "dark"),
|
2777
|
+
EditorView12.baseTheme(styles5 ? merge({}, defaultTheme, styles5) : defaultTheme),
|
2417
2778
|
// https://github.com/codemirror/theme-one-dark
|
2418
2779
|
_syntaxHighlighting && (themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)),
|
2419
|
-
slots.editor?.className &&
|
2780
|
+
slots.editor?.className && EditorView12.editorAttributes.of({
|
2420
2781
|
class: slots.editor.className
|
2421
2782
|
}),
|
2422
|
-
slots.content?.className &&
|
2783
|
+
slots.content?.className && EditorView12.contentAttributes.of({
|
2423
2784
|
class: slots.content.className
|
2424
2785
|
})
|
2425
2786
|
].filter(isNotFalsy3);
|
@@ -2448,8 +2809,8 @@ var createDataExtensions = ({ id, text, space, identity }) => {
|
|
2448
2809
|
|
2449
2810
|
// packages/ui/react-ui-editor/src/extensions/folding.tsx
|
2450
2811
|
import { codeFolding, foldGutter } from "@codemirror/language";
|
2451
|
-
import { EditorView as
|
2452
|
-
import
|
2812
|
+
import { EditorView as EditorView13 } from "@codemirror/view";
|
2813
|
+
import React3 from "react";
|
2453
2814
|
import { Icon } from "@dxos/react-ui";
|
2454
2815
|
var folding = (_props = {}) => [
|
2455
2816
|
codeFolding({
|
@@ -2462,7 +2823,7 @@ var folding = (_props = {}) => [
|
|
2462
2823
|
const el = createElement("div", {
|
2463
2824
|
className: "flex h-full items-center"
|
2464
2825
|
});
|
2465
|
-
return renderRoot(el, /* @__PURE__ */
|
2826
|
+
return renderRoot(el, /* @__PURE__ */ React3.createElement(Icon, {
|
2466
2827
|
icon: "ph--caret-right--regular",
|
2467
2828
|
size: 3,
|
2468
2829
|
classNames: [
|
@@ -2472,7 +2833,7 @@ var folding = (_props = {}) => [
|
|
2472
2833
|
}));
|
2473
2834
|
}
|
2474
2835
|
}),
|
2475
|
-
|
2836
|
+
EditorView13.theme({
|
2476
2837
|
".cm-foldGutter": {
|
2477
2838
|
opacity: 0.3,
|
2478
2839
|
transition: "opacity 0.3s",
|
@@ -2485,14 +2846,14 @@ var folding = (_props = {}) => [
|
|
2485
2846
|
];
|
2486
2847
|
|
2487
2848
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
2488
|
-
import { EditorView as
|
2849
|
+
import { EditorView as EditorView14 } from "@codemirror/view";
|
2489
2850
|
var listener = ({ onFocus, onChange }) => {
|
2490
2851
|
const extensions = [];
|
2491
|
-
onFocus && extensions.push(
|
2852
|
+
onFocus && extensions.push(EditorView14.focusChangeEffect.of((_, focusing) => {
|
2492
2853
|
onFocus(focusing);
|
2493
2854
|
return null;
|
2494
2855
|
}));
|
2495
|
-
onChange && extensions.push(
|
2856
|
+
onChange && extensions.push(EditorView14.updateListener.of((update2) => {
|
2496
2857
|
onChange(update2.state.doc.toString(), update2.state.facet(documentId));
|
2497
2858
|
}));
|
2498
2859
|
return extensions;
|
@@ -2502,8 +2863,8 @@ var listener = ({ onFocus, onChange }) => {
|
|
2502
2863
|
import { snippet } from "@codemirror/autocomplete";
|
2503
2864
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
2504
2865
|
import { EditorSelection } from "@codemirror/state";
|
2505
|
-
import { EditorView as
|
2506
|
-
import { useMemo as
|
2866
|
+
import { EditorView as EditorView15, keymap as keymap7 } from "@codemirror/view";
|
2867
|
+
import { useMemo as useMemo3 } from "react";
|
2507
2868
|
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
2869
|
var Inline;
|
2509
2870
|
(function(Inline2) {
|
@@ -3590,65 +3951,56 @@ var getFormatting = (state) => {
|
|
3590
3951
|
listStyle: listStyle || null
|
3591
3952
|
};
|
3592
3953
|
};
|
3593
|
-
var useFormattingState = () => {
|
3594
|
-
|
3595
|
-
const observer = useMemo2(() => EditorView14.updateListener.of((update2) => {
|
3954
|
+
var useFormattingState = (state) => {
|
3955
|
+
return useMemo3(() => EditorView15.updateListener.of((update2) => {
|
3596
3956
|
if (update2.docChanged || update2.selectionSet) {
|
3597
|
-
|
3598
|
-
|
3599
|
-
if (!prevState || !formattingEquals(prevState, newState)) {
|
3600
|
-
return newState;
|
3601
|
-
}
|
3602
|
-
return prevState;
|
3957
|
+
Object.entries(getFormatting(update2.state)).forEach(([key, active]) => {
|
3958
|
+
state[key] = active;
|
3603
3959
|
});
|
3604
3960
|
}
|
3605
3961
|
}), []);
|
3606
|
-
return [
|
3607
|
-
state,
|
3608
|
-
observer
|
3609
|
-
];
|
3610
3962
|
};
|
3611
3963
|
|
3612
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/
|
3613
|
-
var
|
3964
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/editorAction.ts
|
3965
|
+
var processEditorPayload = (view, { type, data }) => {
|
3614
3966
|
let inlineType, listType;
|
3615
|
-
switch (
|
3967
|
+
switch (type) {
|
3616
3968
|
case "heading":
|
3617
|
-
setHeading(parseInt(
|
3969
|
+
setHeading(parseInt(data))(view);
|
3618
3970
|
break;
|
3619
3971
|
case "strong":
|
3620
3972
|
case "emphasis":
|
3621
3973
|
case "strikethrough":
|
3622
3974
|
case "code":
|
3623
|
-
inlineType =
|
3624
|
-
(typeof
|
3975
|
+
inlineType = type === "strong" ? Inline.Strong : type === "emphasis" ? Inline.Emphasis : type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
3976
|
+
(typeof data === "boolean" ? setStyle(inlineType, data) : toggleStyle(inlineType))(view);
|
3625
3977
|
break;
|
3626
3978
|
case "list-ordered":
|
3627
3979
|
case "list-bullet":
|
3628
3980
|
case "list-task":
|
3629
|
-
listType =
|
3630
|
-
(
|
3981
|
+
listType = type === "list-ordered" ? List.Ordered : type === "list-bullet" ? List.Bullet : List.Task;
|
3982
|
+
(data === false ? removeList(listType) : data === true ? addList(listType) : toggleList(listType))(view);
|
3631
3983
|
break;
|
3632
3984
|
case "blockquote":
|
3633
|
-
(
|
3985
|
+
(data === false ? removeBlockquote : data === true ? addBlockquote : toggleBlockquote)(view);
|
3634
3986
|
break;
|
3635
3987
|
case "codeblock":
|
3636
|
-
(
|
3988
|
+
(data === false ? removeCodeblock : addCodeblock)(view);
|
3637
3989
|
break;
|
3638
3990
|
case "table":
|
3639
3991
|
insertTable(view);
|
3640
3992
|
break;
|
3641
3993
|
case "link":
|
3642
|
-
(
|
3994
|
+
(data === false ? removeLink : addLink())(view);
|
3643
3995
|
break;
|
3644
3996
|
case "image":
|
3645
3997
|
addLink({
|
3646
|
-
url:
|
3998
|
+
url: data,
|
3647
3999
|
image: true
|
3648
4000
|
})(view);
|
3649
4001
|
break;
|
3650
4002
|
case "comment":
|
3651
|
-
|
4003
|
+
createComment2(view);
|
3652
4004
|
break;
|
3653
4005
|
}
|
3654
4006
|
requestAnimationFrame(() => {
|
@@ -3912,9 +4264,9 @@ var convertTreeToJson = (state) => {
|
|
3912
4264
|
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
3913
4265
|
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
3914
4266
|
import { RangeSetBuilder as RangeSetBuilder3, StateEffect as StateEffect5 } from "@codemirror/state";
|
3915
|
-
import { EditorView as
|
4267
|
+
import { EditorView as EditorView19, Decoration as Decoration7, WidgetType as WidgetType5, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
3916
4268
|
import { invariant as invariant4 } from "@dxos/invariant";
|
3917
|
-
import { mx as
|
4269
|
+
import { mx as mx4 } from "@dxos/react-ui-theme";
|
3918
4270
|
|
3919
4271
|
// packages/ui/react-ui-editor/src/extensions/markdown/changes.ts
|
3920
4272
|
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
@@ -4063,7 +4415,7 @@ var getValidUrl = (str) => {
|
|
4063
4415
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
4064
4416
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
4065
4417
|
import { StateField as StateField8 } from "@codemirror/state";
|
4066
|
-
import { Decoration as Decoration5, EditorView as
|
4418
|
+
import { Decoration as Decoration5, EditorView as EditorView16, WidgetType as WidgetType3 } from "@codemirror/view";
|
4067
4419
|
var image = (_options = {}) => {
|
4068
4420
|
return [
|
4069
4421
|
StateField8.define({
|
@@ -4091,7 +4443,7 @@ var image = (_options = {}) => {
|
|
4091
4443
|
add: buildDecorations(from, to, tr.state)
|
4092
4444
|
});
|
4093
4445
|
},
|
4094
|
-
provide: (field) =>
|
4446
|
+
provide: (field) => EditorView16.decorations.from(field)
|
4095
4447
|
})
|
4096
4448
|
];
|
4097
4449
|
};
|
@@ -4151,10 +4503,10 @@ var ImageWidget = class extends WidgetType3 {
|
|
4151
4503
|
};
|
4152
4504
|
|
4153
4505
|
// packages/ui/react-ui-editor/src/extensions/markdown/styles.ts
|
4154
|
-
import { EditorView as
|
4506
|
+
import { EditorView as EditorView17 } from "@codemirror/view";
|
4155
4507
|
var bulletListIndentationWidth = 24;
|
4156
4508
|
var orderedListIndentationWidth = 36;
|
4157
|
-
var formattingStyles =
|
4509
|
+
var formattingStyles = EditorView17.theme({
|
4158
4510
|
/**
|
4159
4511
|
* Horizontal rule.
|
4160
4512
|
*/
|
@@ -4248,18 +4600,39 @@ var formattingStyles = EditorView16.theme({
|
|
4248
4600
|
height: "auto",
|
4249
4601
|
borderTop: "0.5rem solid transparent",
|
4250
4602
|
borderBottom: "0.5rem solid transparent"
|
4603
|
+
},
|
4604
|
+
".cm-image-with-loader": {
|
4605
|
+
display: "block",
|
4606
|
+
opacity: "0",
|
4607
|
+
transitionDuration: "350ms",
|
4608
|
+
transitionProperty: "opacity"
|
4609
|
+
},
|
4610
|
+
".cm-image-with-loader.cm-loaded-image": {
|
4611
|
+
opacity: "1"
|
4612
|
+
},
|
4613
|
+
".cm-image-wrapper": {
|
4614
|
+
"grid-template-columns": "1fr",
|
4615
|
+
display: "grid",
|
4616
|
+
margin: "0.5rem 0",
|
4617
|
+
overflow: "hidden",
|
4618
|
+
transitionDuration: "350ms",
|
4619
|
+
transitionProperty: "height",
|
4620
|
+
"& > *": {
|
4621
|
+
"grid-row-start": 1,
|
4622
|
+
"grid-column-start": 1
|
4623
|
+
}
|
4251
4624
|
}
|
4252
4625
|
});
|
4253
4626
|
|
4254
4627
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
4255
4628
|
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
4256
4629
|
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField9 } from "@codemirror/state";
|
4257
|
-
import { Decoration as Decoration6, EditorView as
|
4630
|
+
import { Decoration as Decoration6, EditorView as EditorView18, WidgetType as WidgetType4 } from "@codemirror/view";
|
4258
4631
|
var table = (options = {}) => {
|
4259
4632
|
return StateField9.define({
|
4260
4633
|
create: (state) => update(state, options),
|
4261
4634
|
update: (_, tr) => update(tr.state, options),
|
4262
|
-
provide: (field) =>
|
4635
|
+
provide: (field) => EditorView18.decorations.from(field)
|
4263
4636
|
});
|
4264
4637
|
};
|
4265
4638
|
var update = (state, _options) => {
|
@@ -4443,16 +4816,16 @@ var TextWidget = class extends WidgetType5 {
|
|
4443
4816
|
};
|
4444
4817
|
var hide = Decoration7.replace({});
|
4445
4818
|
var blockQuote = Decoration7.line({
|
4446
|
-
class:
|
4819
|
+
class: mx4("cm-blockquote")
|
4447
4820
|
});
|
4448
4821
|
var fencedCodeLine = Decoration7.line({
|
4449
|
-
class:
|
4822
|
+
class: mx4("cm-code cm-codeblock-line")
|
4450
4823
|
});
|
4451
4824
|
var fencedCodeLineFirst = Decoration7.line({
|
4452
|
-
class:
|
4825
|
+
class: mx4("cm-code cm-codeblock-line", "cm-codeblock-first")
|
4453
4826
|
});
|
4454
4827
|
var fencedCodeLineLast = Decoration7.line({
|
4455
|
-
class:
|
4828
|
+
class: mx4("cm-code cm-codeblock-line", "cm-codeblock-last")
|
4456
4829
|
});
|
4457
4830
|
var commentBlockLine = fencedCodeLine;
|
4458
4831
|
var commentBlockLineFirst = fencedCodeLineFirst;
|
@@ -4793,9 +5166,9 @@ var decorateMarkdown = (options = {}) => {
|
|
4793
5166
|
}
|
4794
5167
|
}, {
|
4795
5168
|
provide: (plugin) => [
|
4796
|
-
|
4797
|
-
|
4798
|
-
|
5169
|
+
EditorView19.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
5170
|
+
EditorView19.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
5171
|
+
EditorView19.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration7.none)
|
4799
5172
|
]
|
4800
5173
|
}),
|
4801
5174
|
image(),
|
@@ -4982,428 +5355,29 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
4982
5355
|
];
|
4983
5356
|
};
|
4984
5357
|
|
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
5358
|
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
5359
|
+
import { useCallback as useCallback2 } from "react";
|
5388
5360
|
var useActionHandler = (view) => {
|
5389
|
-
return (action) => view &&
|
5361
|
+
return useCallback2((action) => view && processEditorPayload(view, action.properties), [
|
5362
|
+
view
|
5363
|
+
]);
|
5390
5364
|
};
|
5391
5365
|
|
5392
5366
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
5393
5367
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
5394
5368
|
import { EditorView as EditorView20 } from "@codemirror/view";
|
5395
5369
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
5396
|
-
import { useCallback, useEffect as
|
5370
|
+
import { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo4, useRef, useState } from "react";
|
5397
5371
|
import { log as log7 } from "@dxos/log";
|
5398
5372
|
import { getProviderValue, isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
5399
5373
|
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
5400
5374
|
var instanceCount = 0;
|
5401
5375
|
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
|
-
|
5376
|
+
const { id, initialValue, extensions, autoFocus, scrollTo, selection, moveToEndOfLine, debug } = useMemo4(() => getProviderValue(props), deps ?? []);
|
5377
|
+
const [instanceId] = useState(() => `text-editor-${++instanceCount}`);
|
5378
|
+
const [view, setView] = useState();
|
5379
|
+
const parentRef = useRef(null);
|
5380
|
+
useEffect2(() => {
|
5407
5381
|
let view2;
|
5408
5382
|
if (parentRef.current) {
|
5409
5383
|
log7("create", {
|
@@ -5477,7 +5451,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5477
5451
|
view2?.destroy();
|
5478
5452
|
};
|
5479
5453
|
}, deps);
|
5480
|
-
|
5454
|
+
useEffect2(() => {
|
5481
5455
|
if (view) {
|
5482
5456
|
if (scrollTo || selection) {
|
5483
5457
|
if (selection && selection.anchor > view.state.doc.length) {
|
@@ -5504,7 +5478,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5504
5478
|
scrollTo,
|
5505
5479
|
selection
|
5506
5480
|
]);
|
5507
|
-
|
5481
|
+
useEffect2(() => {
|
5508
5482
|
if (view && autoFocus) {
|
5509
5483
|
view.focus();
|
5510
5484
|
}
|
@@ -5518,7 +5492,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5518
5492
|
Escape: view?.state.facet(editorInputMode).noTabster
|
5519
5493
|
}
|
5520
5494
|
});
|
5521
|
-
const handleKeyUp =
|
5495
|
+
const handleKeyUp = useCallback3((event) => {
|
5522
5496
|
const { key, target, currentTarget } = event;
|
5523
5497
|
if (target === currentTarget) {
|
5524
5498
|
switch (key) {
|
@@ -5547,6 +5521,7 @@ export {
|
|
5547
5521
|
EditorInputMode,
|
5548
5522
|
EditorInputModes,
|
5549
5523
|
EditorState3 as EditorState,
|
5524
|
+
EditorToolbar,
|
5550
5525
|
EditorView21 as EditorView,
|
5551
5526
|
EditorViewMode,
|
5552
5527
|
EditorViewModes,
|
@@ -5556,7 +5531,6 @@ export {
|
|
5556
5531
|
RemoteSelectionsDecorator,
|
5557
5532
|
SpaceAwarenessProvider,
|
5558
5533
|
TextKind,
|
5559
|
-
Toolbar,
|
5560
5534
|
addBlockquote,
|
5561
5535
|
addCodeblock,
|
5562
5536
|
addLink,
|
@@ -5575,8 +5549,10 @@ export {
|
|
5575
5549
|
commentsState,
|
5576
5550
|
convertTreeToJson,
|
5577
5551
|
createBasicExtensions,
|
5578
|
-
createComment,
|
5552
|
+
createComment2 as createComment,
|
5579
5553
|
createDataExtensions,
|
5554
|
+
createEditorAction,
|
5555
|
+
createEditorActionGroup,
|
5580
5556
|
createEditorStateStore,
|
5581
5557
|
createEditorStateTransaction,
|
5582
5558
|
createElement,
|
@@ -5615,7 +5591,7 @@ export {
|
|
5615
5591
|
mention,
|
5616
5592
|
overlap,
|
5617
5593
|
preventNewline,
|
5618
|
-
|
5594
|
+
processEditorPayload,
|
5619
5595
|
removeBlockquote,
|
5620
5596
|
removeCodeblock,
|
5621
5597
|
removeLink,
|
@@ -5631,6 +5607,8 @@ export {
|
|
5631
5607
|
setSelection,
|
5632
5608
|
setStyle,
|
5633
5609
|
singleValueFacet,
|
5610
|
+
stackItemContentEditorClassNames,
|
5611
|
+
stackItemContentToolbarClassNames,
|
5634
5612
|
table,
|
5635
5613
|
tags2 as tags,
|
5636
5614
|
textRange,
|
@@ -5648,9 +5626,9 @@ export {
|
|
5648
5626
|
useCommentClickListener,
|
5649
5627
|
useCommentState,
|
5650
5628
|
useComments,
|
5629
|
+
useEditorToolbarState,
|
5651
5630
|
useFormattingState,
|
5652
5631
|
useTextEditor,
|
5653
|
-
useToolbarContext,
|
5654
5632
|
wrapWithCatch
|
5655
5633
|
};
|
5656
5634
|
//# sourceMappingURL=index.mjs.map
|