@dxos/react-ui-editor 0.7.5-main.9d26e3a → 0.7.5-main.b19bfc8

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